Gigabeat S: Make it a removable mass-storage device. Windows will assign a drive to only the main data partition by default. To access the bootloader partition instead, press 'Vol -' while it connects (in bootloader and firmware). Hopefully doesn't break anything for anyone.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28972 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
f97b9f11e4
commit
89a7a8138e
5 changed files with 97 additions and 42 deletions
|
@ -71,11 +71,15 @@ static bool pause_if_button_pressed(bool pre_usb)
|
|||
if (pre_usb && !usb_plugged())
|
||||
return false;
|
||||
|
||||
/* Exit if no button or only the menu (settings reset) button */
|
||||
/* Exit if no button or only select buttons that have other
|
||||
* functions */
|
||||
switch (button)
|
||||
{
|
||||
case BUTTON_MENU:
|
||||
case BUTTON_NONE:
|
||||
case USB_BL_INSTALL_MODE_BTN:
|
||||
if (!pre_usb)
|
||||
break; /* Only before USB detect */
|
||||
case BUTTON_MENU: /* Settings reset */
|
||||
case BUTTON_NONE: /* Nothing pressed */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,8 +190,17 @@
|
|||
|
||||
/* define this if the unit can be powered or charged via USB */
|
||||
#define HAVE_USB_POWER
|
||||
#define USBPOWER_BUTTON BUTTON_MENU
|
||||
#define USBPOWER_BTN_IGNORE BUTTON_POWER
|
||||
#define USBPOWER_BUTTON BUTTON_MENU
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
#define USBPOWER_BTN_IGNORE BUTTON_POWER
|
||||
#else
|
||||
/* Disable charging-only mode detection in bootloader */
|
||||
#define USBPOWER_BTN_IGNORE (BUTTON_MAIN | BUTTON_REMOTE)
|
||||
#endif
|
||||
|
||||
/* Button that exposures boot partition rather than data during session */
|
||||
#define USB_BL_INSTALL_MODE_BTN BUTTON_VOL_DOWN
|
||||
|
||||
/* define this if the unit has a battery switch or battery can be removed
|
||||
* when running */
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "ata.h"
|
||||
|
@ -31,8 +30,10 @@
|
|||
#include "ccm-imx31.h"
|
||||
#include "avic-imx31.h"
|
||||
#include "power-gigabeat-s.h"
|
||||
#include <string.h>
|
||||
|
||||
static int usb_status = USB_EXTRACTED;
|
||||
static bool bootloader_install_mode = false;
|
||||
|
||||
static void enable_transceiver(bool enable)
|
||||
{
|
||||
|
@ -106,6 +107,16 @@ void usb_enable(bool on)
|
|||
|
||||
void usb_attach(void)
|
||||
{
|
||||
bootloader_install_mode = false;
|
||||
|
||||
if (usb_core_driver_enabled(USB_DRIVER_MASS_STORAGE))
|
||||
{
|
||||
/* Check if this will be bootloader install mode, exposing the
|
||||
* boot partition instead of the data partition */
|
||||
bootloader_install_mode =
|
||||
(button_status() & USB_BL_INSTALL_MODE_BTN) != 0;
|
||||
}
|
||||
|
||||
usb_drv_attach();
|
||||
}
|
||||
|
||||
|
@ -133,3 +144,34 @@ void usb_drv_usb_detect_event(void)
|
|||
if (usb_drv_powered())
|
||||
usb_status_event(USB_INSERTED);
|
||||
}
|
||||
|
||||
/* Called when reading the MBR */
|
||||
void usb_fix_mbr(unsigned char *mbr)
|
||||
{
|
||||
unsigned char* p = mbr + 0x1be;
|
||||
char tmp[16];
|
||||
|
||||
/* The Gigabeat S factory partition table contains invalid values for the
|
||||
"active" flag in the MBR. This prevents at least the Linux kernel
|
||||
from accepting the partition table, so we fix it on-the-fly. */
|
||||
p[0x00] &= 0x80;
|
||||
p[0x10] &= 0x80;
|
||||
p[0x20] &= 0x80;
|
||||
p[0x30] &= 0x80;
|
||||
|
||||
if (bootloader_install_mode)
|
||||
return;
|
||||
|
||||
/* Windows ignores the partition flags and mounts the first partition it
|
||||
sees when the device reports itself as removable. Swap the partitions
|
||||
so the data partition appears to be partition 0. Mark the boot
|
||||
partition 0 as hidden and make it partition 1. */
|
||||
|
||||
/* Mark the first partition as hidden */
|
||||
p[0x04] |= 0x10;
|
||||
|
||||
/* Swap first and second partitions */
|
||||
memcpy(tmp, &p[0x00], 16);
|
||||
memcpy(&p[0x00], &p[0x10], 16);
|
||||
memcpy(&p[0x10], tmp, 16);
|
||||
}
|
||||
|
|
|
@ -30,4 +30,17 @@ void usb_init_device(void);
|
|||
/* Read the immediate state of the cable from the PMIC */
|
||||
bool usb_plugged(void);
|
||||
|
||||
/** Sector read/write filters **/
|
||||
|
||||
/* Filter some things in the MBR - see usb-gigabeat-s.c */
|
||||
void usb_fix_mbr(unsigned char *mbr);
|
||||
#define USBSTOR_READ_SECTORS_FILTER() \
|
||||
({ if (cur_cmd.sector == 0) \
|
||||
usb_fix_mbr(cur_cmd.data[cur_cmd.data_select]); \
|
||||
0; })
|
||||
|
||||
/* Disallow MBR writes entirely since it was "fixed" in usb_fix_mbr */
|
||||
#define USBSTOR_WRITE_SECTORS_FILTER() \
|
||||
({ cur_cmd.sector != 0 ? 0 : -1; })
|
||||
|
||||
#endif /* USB_TARGET */
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "usb_storage.h"
|
||||
#include "timefuncs.h"
|
||||
|
||||
/* For sector filter macro definitions */
|
||||
#include "usb-target.h"
|
||||
|
||||
/* Enable the following define to export only the SD card slot. This
|
||||
* is useful for USBCV MSC tests, as those are destructive.
|
||||
|
@ -47,6 +49,15 @@
|
|||
#define SECTOR_SIZE 512
|
||||
#endif
|
||||
|
||||
/* These defaults allow the operation */
|
||||
#ifndef USBSTOR_READ_SECTORS_FILTER
|
||||
#define USBSTOR_READ_SECTORS_FILTER() ({ 0; })
|
||||
#endif
|
||||
|
||||
#ifndef USBSTOR_WRITE_SECTORS_FILTER
|
||||
#define USBSTOR_WRITE_SECTORS_FILTER() ({ 0; })
|
||||
#endif
|
||||
|
||||
/* the ARC driver currently supports up to 64k USB transfers. This is
|
||||
* enough for efficient mass storage support, as commonly host OSes
|
||||
* don't do larger SCSI transfers anyway, so larger USB transfers
|
||||
|
@ -342,23 +353,6 @@ static void yearday_to_daymonth(int yd, int y, int *d, int *m)
|
|||
*m = i;
|
||||
}
|
||||
|
||||
#ifdef TOSHIBA_GIGABEAT_S
|
||||
|
||||
/* The Gigabeat S factory partition table contains invalid values for the
|
||||
"active" flag in the MBR. This prevents at least the Linux kernel from
|
||||
accepting the partition table, so we fix it on-the-fly. */
|
||||
|
||||
static void fix_mbr(unsigned char* mbr)
|
||||
{
|
||||
unsigned char* p = mbr + 0x1be;
|
||||
|
||||
p[0x00] &= 0x80;
|
||||
p[0x10] &= 0x80;
|
||||
p[0x20] &= 0x80;
|
||||
p[0x30] &= 0x80;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool check_disk_present(IF_MD_NONVOID(int volume))
|
||||
{
|
||||
#ifdef USB_USE_RAMDISK
|
||||
|
@ -491,14 +485,7 @@ void usb_storage_init_connection(void)
|
|||
|
||||
int i;
|
||||
for(i=0;i<storage_num_drives();i++) {
|
||||
#ifdef TOSHIBA_GIGABEAT_S
|
||||
/* As long as the Gigabeat S is a non-removable device, we need
|
||||
to mark the device as locked to avoid usb_storage_try_release_ata()
|
||||
to leave MSC mode while the device is in use */
|
||||
locked[i] = true;
|
||||
#else
|
||||
locked[i] = false;
|
||||
#endif
|
||||
ejected[i] = !check_disk_present(IF_MD(i));
|
||||
queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0);
|
||||
}
|
||||
|
@ -549,10 +536,15 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
|
|||
cur_cmd.data[cur_cmd.data_select],
|
||||
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
||||
#else
|
||||
int result = storage_write_sectors(IF_MD2(cur_cmd.lun,)
|
||||
int result = USBSTOR_WRITE_SECTORS_FILTER();
|
||||
|
||||
if (result == 0) {
|
||||
result = storage_write_sectors(IF_MD2(cur_cmd.lun,)
|
||||
cur_cmd.sector,
|
||||
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||
cur_cmd.data[cur_cmd.data_select]);
|
||||
}
|
||||
|
||||
if(result != 0) {
|
||||
send_csw(UMS_STATUS_FAIL);
|
||||
cur_sense_data.sense_key=SENSE_MEDIUM_ERROR;
|
||||
|
@ -725,6 +717,11 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* des
|
|||
|
||||
static void send_and_read_next(void)
|
||||
{
|
||||
int result = USBSTOR_READ_SECTORS_FILTER();
|
||||
|
||||
if(result != 0 && cur_cmd.last_result == 0)
|
||||
cur_cmd.last_result = result;
|
||||
|
||||
send_block_data(cur_cmd.data[cur_cmd.data_select],
|
||||
MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE));
|
||||
|
||||
|
@ -742,7 +739,7 @@ static void send_and_read_next(void)
|
|||
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
|
||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
||||
#else
|
||||
int result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
|
||||
result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
|
||||
cur_cmd.sector,
|
||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||
cur_cmd.data[cur_cmd.data_select]);
|
||||
|
@ -1104,12 +1101,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
|||
cur_cmd.sector,
|
||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||
cur_cmd.data[cur_cmd.data_select]);
|
||||
|
||||
#ifdef TOSHIBA_GIGABEAT_S
|
||||
if(cur_cmd.sector == 0) {
|
||||
fix_mbr(cur_cmd.data[cur_cmd.data_select]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
send_and_read_next();
|
||||
}
|
||||
|
@ -1262,9 +1253,5 @@ static void fill_inquiry(IF_MD_NONVOID(int lun))
|
|||
tb.inquiry->Versions = 4; /* SPC-2 */
|
||||
tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
|
||||
|
||||
#ifdef TOSHIBA_GIGABEAT_S
|
||||
tb.inquiry->DeviceTypeModifier = 0;
|
||||
#else
|
||||
tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue