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())
|
if (pre_usb && !usb_plugged())
|
||||||
return false;
|
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)
|
switch (button)
|
||||||
{
|
{
|
||||||
case BUTTON_MENU:
|
case USB_BL_INSTALL_MODE_BTN:
|
||||||
case BUTTON_NONE:
|
if (!pre_usb)
|
||||||
|
break; /* Only before USB detect */
|
||||||
|
case BUTTON_MENU: /* Settings reset */
|
||||||
|
case BUTTON_NONE: /* Nothing pressed */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,17 @@
|
||||||
|
|
||||||
/* define this if the unit can be powered or charged via USB */
|
/* define this if the unit can be powered or charged via USB */
|
||||||
#define HAVE_USB_POWER
|
#define HAVE_USB_POWER
|
||||||
#define USBPOWER_BUTTON BUTTON_MENU
|
#define USBPOWER_BUTTON BUTTON_MENU
|
||||||
#define USBPOWER_BTN_IGNORE BUTTON_POWER
|
|
||||||
|
#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
|
/* define this if the unit has a battery switch or battery can be removed
|
||||||
* when running */
|
* when running */
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "cpu.h"
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
|
@ -31,8 +30,10 @@
|
||||||
#include "ccm-imx31.h"
|
#include "ccm-imx31.h"
|
||||||
#include "avic-imx31.h"
|
#include "avic-imx31.h"
|
||||||
#include "power-gigabeat-s.h"
|
#include "power-gigabeat-s.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static int usb_status = USB_EXTRACTED;
|
static int usb_status = USB_EXTRACTED;
|
||||||
|
static bool bootloader_install_mode = false;
|
||||||
|
|
||||||
static void enable_transceiver(bool enable)
|
static void enable_transceiver(bool enable)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +107,16 @@ void usb_enable(bool on)
|
||||||
|
|
||||||
void usb_attach(void)
|
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();
|
usb_drv_attach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,3 +144,34 @@ void usb_drv_usb_detect_event(void)
|
||||||
if (usb_drv_powered())
|
if (usb_drv_powered())
|
||||||
usb_status_event(USB_INSERTED);
|
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 */
|
/* Read the immediate state of the cable from the PMIC */
|
||||||
bool usb_plugged(void);
|
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 */
|
#endif /* USB_TARGET */
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "usb_storage.h"
|
#include "usb_storage.h"
|
||||||
#include "timefuncs.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
|
/* Enable the following define to export only the SD card slot. This
|
||||||
* is useful for USBCV MSC tests, as those are destructive.
|
* is useful for USBCV MSC tests, as those are destructive.
|
||||||
|
@ -47,6 +49,15 @@
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
#endif
|
#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
|
/* the ARC driver currently supports up to 64k USB transfers. This is
|
||||||
* enough for efficient mass storage support, as commonly host OSes
|
* enough for efficient mass storage support, as commonly host OSes
|
||||||
* don't do larger SCSI transfers anyway, so larger USB transfers
|
* 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;
|
*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))
|
static bool check_disk_present(IF_MD_NONVOID(int volume))
|
||||||
{
|
{
|
||||||
#ifdef USB_USE_RAMDISK
|
#ifdef USB_USE_RAMDISK
|
||||||
|
@ -491,14 +485,7 @@ void usb_storage_init_connection(void)
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i=0;i<storage_num_drives();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;
|
locked[i] = false;
|
||||||
#endif
|
|
||||||
ejected[i] = !check_disk_present(IF_MD(i));
|
ejected[i] = !check_disk_present(IF_MD(i));
|
||||||
queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0);
|
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],
|
cur_cmd.data[cur_cmd.data_select],
|
||||||
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
||||||
#else
|
#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,
|
cur_cmd.sector,
|
||||||
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||||
cur_cmd.data[cur_cmd.data_select]);
|
cur_cmd.data[cur_cmd.data_select]);
|
||||||
|
}
|
||||||
|
|
||||||
if(result != 0) {
|
if(result != 0) {
|
||||||
send_csw(UMS_STATUS_FAIL);
|
send_csw(UMS_STATUS_FAIL);
|
||||||
cur_sense_data.sense_key=SENSE_MEDIUM_ERROR;
|
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)
|
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],
|
send_block_data(cur_cmd.data[cur_cmd.data_select],
|
||||||
MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE));
|
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,
|
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
|
||||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
|
||||||
#else
|
#else
|
||||||
int result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
|
result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
|
||||||
cur_cmd.sector,
|
cur_cmd.sector,
|
||||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||||
cur_cmd.data[cur_cmd.data_select]);
|
cur_cmd.data[cur_cmd.data_select]);
|
||||||
|
@ -1104,12 +1101,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
||||||
cur_cmd.sector,
|
cur_cmd.sector,
|
||||||
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
|
||||||
cur_cmd.data[cur_cmd.data_select]);
|
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
|
#endif
|
||||||
send_and_read_next();
|
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->Versions = 4; /* SPC-2 */
|
||||||
tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
|
tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
|
||||||
|
|
||||||
#ifdef TOSHIBA_GIGABEAT_S
|
|
||||||
tb.inquiry->DeviceTypeModifier = 0;
|
|
||||||
#else
|
|
||||||
tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
|
tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue