summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-01-05 19:35:51 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-01-05 19:35:51 +0000
commit89a7a8138ec97a038200ab3080710bd101a9ff0e (patch)
tree0d407ed964975d8eb3f13eafd85a3abe18918184
parentf97b9f11e4f95cf87b09f5184e2016d247f72d09 (diff)
downloadrockbox-89a7a8138ec97a038200ab3080710bd101a9ff0e.tar.gz
rockbox-89a7a8138ec97a038200ab3080710bd101a9ff0e.zip
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
-rw-r--r--bootloader/gigabeat-s.c10
-rw-r--r--firmware/export/config/gigabeats.h13
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c44
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-target.h13
-rw-r--r--firmware/usbstack/usb_storage.c59
5 files changed, 97 insertions, 42 deletions
diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c
index 9c5ad93d1f..c29265ddad 100644
--- a/bootloader/gigabeat-s.c
+++ b/bootloader/gigabeat-s.c
@@ -71,11 +71,15 @@ static bool pause_if_button_pressed(bool pre_usb)
71 if (pre_usb && !usb_plugged()) 71 if (pre_usb && !usb_plugged())
72 return false; 72 return false;
73 73
74 /* Exit if no button or only the menu (settings reset) button */ 74 /* Exit if no button or only select buttons that have other
75 * functions */
75 switch (button) 76 switch (button)
76 { 77 {
77 case BUTTON_MENU: 78 case USB_BL_INSTALL_MODE_BTN:
78 case BUTTON_NONE: 79 if (!pre_usb)
80 break; /* Only before USB detect */
81 case BUTTON_MENU: /* Settings reset */
82 case BUTTON_NONE: /* Nothing pressed */
79 return true; 83 return true;
80 } 84 }
81 85
diff --git a/firmware/export/config/gigabeats.h b/firmware/export/config/gigabeats.h
index fcfa274314..cf560aa35f 100644
--- a/firmware/export/config/gigabeats.h
+++ b/firmware/export/config/gigabeats.h
@@ -190,8 +190,17 @@
190 190
191/* define this if the unit can be powered or charged via USB */ 191/* define this if the unit can be powered or charged via USB */
192#define HAVE_USB_POWER 192#define HAVE_USB_POWER
193#define USBPOWER_BUTTON BUTTON_MENU 193#define USBPOWER_BUTTON BUTTON_MENU
194#define USBPOWER_BTN_IGNORE BUTTON_POWER 194
195#ifndef BOOTLOADER
196#define USBPOWER_BTN_IGNORE BUTTON_POWER
197#else
198/* Disable charging-only mode detection in bootloader */
199#define USBPOWER_BTN_IGNORE (BUTTON_MAIN | BUTTON_REMOTE)
200#endif
201
202/* Button that exposures boot partition rather than data during session */
203#define USB_BL_INSTALL_MODE_BTN BUTTON_VOL_DOWN
195 204
196/* define this if the unit has a battery switch or battery can be removed 205/* define this if the unit has a battery switch or battery can be removed
197 * when running */ 206 * when running */
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
index 016f24fc48..c52a9a6dec 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
@@ -19,7 +19,6 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "config.h" 21#include "config.h"
22#include "cpu.h"
23#include "system.h" 22#include "system.h"
24#include "kernel.h" 23#include "kernel.h"
25#include "ata.h" 24#include "ata.h"
@@ -31,8 +30,10 @@
31#include "ccm-imx31.h" 30#include "ccm-imx31.h"
32#include "avic-imx31.h" 31#include "avic-imx31.h"
33#include "power-gigabeat-s.h" 32#include "power-gigabeat-s.h"
33#include <string.h>
34 34
35static int usb_status = USB_EXTRACTED; 35static int usb_status = USB_EXTRACTED;
36static bool bootloader_install_mode = false;
36 37
37static void enable_transceiver(bool enable) 38static void enable_transceiver(bool enable)
38{ 39{
@@ -106,6 +107,16 @@ void usb_enable(bool on)
106 107
107void usb_attach(void) 108void usb_attach(void)
108{ 109{
110 bootloader_install_mode = false;
111
112 if (usb_core_driver_enabled(USB_DRIVER_MASS_STORAGE))
113 {
114 /* Check if this will be bootloader install mode, exposing the
115 * boot partition instead of the data partition */
116 bootloader_install_mode =
117 (button_status() & USB_BL_INSTALL_MODE_BTN) != 0;
118 }
119
109 usb_drv_attach(); 120 usb_drv_attach();
110} 121}
111 122
@@ -133,3 +144,34 @@ void usb_drv_usb_detect_event(void)
133 if (usb_drv_powered()) 144 if (usb_drv_powered())
134 usb_status_event(USB_INSERTED); 145 usb_status_event(USB_INSERTED);
135} 146}
147
148/* Called when reading the MBR */
149void usb_fix_mbr(unsigned char *mbr)
150{
151 unsigned char* p = mbr + 0x1be;
152 char tmp[16];
153
154 /* The Gigabeat S factory partition table contains invalid values for the
155 "active" flag in the MBR. This prevents at least the Linux kernel
156 from accepting the partition table, so we fix it on-the-fly. */
157 p[0x00] &= 0x80;
158 p[0x10] &= 0x80;
159 p[0x20] &= 0x80;
160 p[0x30] &= 0x80;
161
162 if (bootloader_install_mode)
163 return;
164
165 /* Windows ignores the partition flags and mounts the first partition it
166 sees when the device reports itself as removable. Swap the partitions
167 so the data partition appears to be partition 0. Mark the boot
168 partition 0 as hidden and make it partition 1. */
169
170 /* Mark the first partition as hidden */
171 p[0x04] |= 0x10;
172
173 /* Swap first and second partitions */
174 memcpy(tmp, &p[0x00], 16);
175 memcpy(&p[0x00], &p[0x10], 16);
176 memcpy(&p[0x10], tmp, 16);
177}
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-target.h b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
index c93400ca0b..7931058241 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
@@ -30,4 +30,17 @@ void usb_init_device(void);
30/* Read the immediate state of the cable from the PMIC */ 30/* Read the immediate state of the cable from the PMIC */
31bool usb_plugged(void); 31bool usb_plugged(void);
32 32
33/** Sector read/write filters **/
34
35/* Filter some things in the MBR - see usb-gigabeat-s.c */
36void usb_fix_mbr(unsigned char *mbr);
37#define USBSTOR_READ_SECTORS_FILTER() \
38 ({ if (cur_cmd.sector == 0) \
39 usb_fix_mbr(cur_cmd.data[cur_cmd.data_select]); \
40 0; })
41
42/* Disallow MBR writes entirely since it was "fixed" in usb_fix_mbr */
43#define USBSTOR_WRITE_SECTORS_FILTER() \
44 ({ cur_cmd.sector != 0 ? 0 : -1; })
45
33#endif /* USB_TARGET */ 46#endif /* USB_TARGET */
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 005697f6fa..1ff3b1ec4c 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -32,6 +32,8 @@
32#include "usb_storage.h" 32#include "usb_storage.h"
33#include "timefuncs.h" 33#include "timefuncs.h"
34 34
35/* For sector filter macro definitions */
36#include "usb-target.h"
35 37
36/* Enable the following define to export only the SD card slot. This 38/* Enable the following define to export only the SD card slot. This
37 * is useful for USBCV MSC tests, as those are destructive. 39 * is useful for USBCV MSC tests, as those are destructive.
@@ -47,6 +49,15 @@
47#define SECTOR_SIZE 512 49#define SECTOR_SIZE 512
48#endif 50#endif
49 51
52/* These defaults allow the operation */
53#ifndef USBSTOR_READ_SECTORS_FILTER
54#define USBSTOR_READ_SECTORS_FILTER() ({ 0; })
55#endif
56
57#ifndef USBSTOR_WRITE_SECTORS_FILTER
58#define USBSTOR_WRITE_SECTORS_FILTER() ({ 0; })
59#endif
60
50/* the ARC driver currently supports up to 64k USB transfers. This is 61/* the ARC driver currently supports up to 64k USB transfers. This is
51 * enough for efficient mass storage support, as commonly host OSes 62 * enough for efficient mass storage support, as commonly host OSes
52 * don't do larger SCSI transfers anyway, so larger USB transfers 63 * 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)
342 *m = i; 353 *m = i;
343} 354}
344 355
345#ifdef TOSHIBA_GIGABEAT_S
346
347/* The Gigabeat S factory partition table contains invalid values for the
348 "active" flag in the MBR. This prevents at least the Linux kernel from
349 accepting the partition table, so we fix it on-the-fly. */
350
351static void fix_mbr(unsigned char* mbr)
352{
353 unsigned char* p = mbr + 0x1be;
354
355 p[0x00] &= 0x80;
356 p[0x10] &= 0x80;
357 p[0x20] &= 0x80;
358 p[0x30] &= 0x80;
359}
360#endif
361
362static bool check_disk_present(IF_MD_NONVOID(int volume)) 356static bool check_disk_present(IF_MD_NONVOID(int volume))
363{ 357{
364#ifdef USB_USE_RAMDISK 358#ifdef USB_USE_RAMDISK
@@ -491,14 +485,7 @@ void usb_storage_init_connection(void)
491 485
492 int i; 486 int i;
493 for(i=0;i<storage_num_drives();i++) { 487 for(i=0;i<storage_num_drives();i++) {
494#ifdef TOSHIBA_GIGABEAT_S
495 /* As long as the Gigabeat S is a non-removable device, we need
496 to mark the device as locked to avoid usb_storage_try_release_ata()
497 to leave MSC mode while the device is in use */
498 locked[i] = true;
499#else
500 locked[i] = false; 488 locked[i] = false;
501#endif
502 ejected[i] = !check_disk_present(IF_MD(i)); 489 ejected[i] = !check_disk_present(IF_MD(i));
503 queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); 490 queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0);
504 } 491 }
@@ -549,10 +536,15 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
549 cur_cmd.data[cur_cmd.data_select], 536 cur_cmd.data[cur_cmd.data_select],
550 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 537 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
551#else 538#else
552 int result = storage_write_sectors(IF_MD2(cur_cmd.lun,) 539 int result = USBSTOR_WRITE_SECTORS_FILTER();
540
541 if (result == 0) {
542 result = storage_write_sectors(IF_MD2(cur_cmd.lun,)
553 cur_cmd.sector, 543 cur_cmd.sector,
554 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 544 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
555 cur_cmd.data[cur_cmd.data_select]); 545 cur_cmd.data[cur_cmd.data_select]);
546 }
547
556 if(result != 0) { 548 if(result != 0) {
557 send_csw(UMS_STATUS_FAIL); 549 send_csw(UMS_STATUS_FAIL);
558 cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; 550 cur_sense_data.sense_key=SENSE_MEDIUM_ERROR;
@@ -725,6 +717,11 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* des
725 717
726static void send_and_read_next(void) 718static void send_and_read_next(void)
727{ 719{
720 int result = USBSTOR_READ_SECTORS_FILTER();
721
722 if(result != 0 && cur_cmd.last_result == 0)
723 cur_cmd.last_result = result;
724
728 send_block_data(cur_cmd.data[cur_cmd.data_select], 725 send_block_data(cur_cmd.data[cur_cmd.data_select],
729 MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); 726 MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE));
730 727
@@ -742,7 +739,7 @@ static void send_and_read_next(void)
742 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 739 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
743 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 740 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
744#else 741#else
745 int result = storage_read_sectors(IF_MD2(cur_cmd.lun,) 742 result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
746 cur_cmd.sector, 743 cur_cmd.sector,
747 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 744 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
748 cur_cmd.data[cur_cmd.data_select]); 745 cur_cmd.data[cur_cmd.data_select]);
@@ -1104,12 +1101,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1104 cur_cmd.sector, 1101 cur_cmd.sector,
1105 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 1102 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
1106 cur_cmd.data[cur_cmd.data_select]); 1103 cur_cmd.data[cur_cmd.data_select]);
1107
1108#ifdef TOSHIBA_GIGABEAT_S
1109 if(cur_cmd.sector == 0) {
1110 fix_mbr(cur_cmd.data[cur_cmd.data_select]);
1111 }
1112#endif
1113#endif 1104#endif
1114 send_and_read_next(); 1105 send_and_read_next();
1115 } 1106 }
@@ -1262,9 +1253,5 @@ static void fill_inquiry(IF_MD_NONVOID(int lun))
1262 tb.inquiry->Versions = 4; /* SPC-2 */ 1253 tb.inquiry->Versions = 4; /* SPC-2 */
1263 tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ 1254 tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
1264 1255
1265#ifdef TOSHIBA_GIGABEAT_S
1266 tb.inquiry->DeviceTypeModifier = 0;
1267#else
1268 tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; 1256 tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
1269#endif
1270} 1257}