summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r--firmware/usbstack/usb_storage.c316
1 files changed, 250 insertions, 66 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index b852475663..1fbfe5296d 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -24,6 +24,7 @@
24#include "logf.h" 24#include "logf.h"
25#include "ata.h" 25#include "ata.h"
26#include "hotswap.h" 26#include "hotswap.h"
27#include "disk.h"
27 28
28#define SECTOR_SIZE 512 29#define SECTOR_SIZE 512
29 30
@@ -40,14 +41,20 @@
40#define SCSI_TEST_UNIT_READY 0x00 41#define SCSI_TEST_UNIT_READY 0x00
41#define SCSI_INQUIRY 0x12 42#define SCSI_INQUIRY 0x12
42#define SCSI_MODE_SENSE 0x1a 43#define SCSI_MODE_SENSE 0x1a
44#define SCSI_REQUEST_SENSE 0x03
43#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e 45#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
44#define SCSI_READ_CAPACITY 0x25 46#define SCSI_READ_CAPACITY 0x25
47#define SCSI_READ_FORMAT_CAPACITY 0x23
45#define SCSI_READ_10 0x28 48#define SCSI_READ_10 0x28
46#define SCSI_WRITE_10 0x2a 49#define SCSI_WRITE_10 0x2a
50#define SCSI_START_STOP_UNIT 0x1b
47 51
48#define SCSI_STATUS_GOOD 0x00 52#define SCSI_STATUS_GOOD 0x00
53#define SCSI_STATUS_FAIL 0x01
49#define SCSI_STATUS_CHECK_CONDITION 0x02 54#define SCSI_STATUS_CHECK_CONDITION 0x02
50 55
56#define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000
57
51 58
52struct inquiry_data { 59struct inquiry_data {
53 unsigned char DeviceType; 60 unsigned char DeviceType;
@@ -62,6 +69,20 @@ struct inquiry_data {
62 unsigned char ProductRevisionLevel[4]; 69 unsigned char ProductRevisionLevel[4];
63} __attribute__ ((packed)); 70} __attribute__ ((packed));
64 71
72struct sense_data {
73 unsigned char ResponseCode;
74 unsigned char Obsolete;
75 unsigned char filemark_eom_ili_sensekey;
76 unsigned int Information;
77 unsigned char AdditionalSenseLength;
78 unsigned int CommandSpecificInformation;
79 unsigned char AdditionalSenseCode;
80 unsigned char AdditionalSenseCodeQualifier;
81 unsigned char FieldReplaceableUnitCode;
82 unsigned char SKSV;
83 unsigned short SenseKeySpecific;
84} __attribute__ ((packed));
85
65struct command_block_wrapper { 86struct command_block_wrapper {
66 unsigned int signature; 87 unsigned int signature;
67 unsigned int tag; 88 unsigned int tag;
@@ -84,26 +105,34 @@ struct capacity {
84 unsigned int block_size; 105 unsigned int block_size;
85} __attribute__ ((packed)); 106} __attribute__ ((packed));
86 107
108struct format_capacity {
109 unsigned int following_length;
110 unsigned int block_count;
111 unsigned int block_size;
112} __attribute__ ((packed));
113
87/* the ARC USB controller can at most buffer 16KB unaligned data */ 114/* the ARC USB controller can at most buffer 16KB unaligned data */
88static unsigned char _transfer_buffer[16384]; 115static unsigned char _transfer_buffer[16384*8] __attribute((aligned (4096)));
89static unsigned char* transfer_buffer; 116static unsigned char* transfer_buffer;
90static struct inquiry_data _inquiry; 117static struct inquiry_data _inquiry CACHEALIGN_ATTR;
91static struct inquiry_data* inquiry; 118static struct inquiry_data* inquiry;
92static struct capacity _capacity_data; 119static struct capacity _capacity_data CACHEALIGN_ATTR;
93static struct capacity* capacity_data; 120static struct capacity* capacity_data;
94 121static struct format_capacity _format_capacity_data CACHEALIGN_ATTR;
95//static unsigned char partial_sector[SECTOR_SIZE]; 122static struct format_capacity* format_capacity_data;
123static struct sense_data _sense_data CACHEALIGN_ATTR;
124static struct sense_data *sense_data;
96 125
97static struct { 126static struct {
98 unsigned int sector; 127 unsigned int sector;
99 unsigned int offset; /* if partial sector */
100 unsigned int count; 128 unsigned int count;
101 unsigned int tag; 129 unsigned int tag;
130 unsigned int lun;
102} current_cmd; 131} current_cmd;
103 132
104 void handle_scsi(struct command_block_wrapper* cbw); 133static void handle_scsi(struct command_block_wrapper* cbw);
105 void send_csw(unsigned int tag, int status); 134static void send_csw(unsigned int tag, int status);
106static void identify2inquiry(void); 135static void identify2inquiry(int lun);
107 136
108static enum { 137static enum {
109 IDLE, 138 IDLE,
@@ -117,7 +146,10 @@ void usb_storage_init(void)
117 inquiry = (void*)UNCACHED_ADDR(&_inquiry); 146 inquiry = (void*)UNCACHED_ADDR(&_inquiry);
118 transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); 147 transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer);
119 capacity_data = (void*)UNCACHED_ADDR(&_capacity_data); 148 capacity_data = (void*)UNCACHED_ADDR(&_capacity_data);
120 identify2inquiry(); 149 format_capacity_data = (void*)UNCACHED_ADDR(&_format_capacity_data);
150 sense_data = (void*)UNCACHED_ADDR(&_sense_data);
151 state = IDLE;
152 logf("usb_storage_init done");
121} 153}
122 154
123/* called by usb_core_transfer_complete() */ 155/* called by usb_core_transfer_complete() */
@@ -128,21 +160,44 @@ void usb_storage_transfer_complete(int endpoint)
128 switch (endpoint) { 160 switch (endpoint) {
129 case EP_RX: 161 case EP_RX:
130 //logf("ums: %d bytes in", length); 162 //logf("ums: %d bytes in", length);
131 switch (state) { 163 if(state == RECEIVING)
132 case IDLE: 164 {
133 handle_scsi(cbw); 165 int receive_count=usb_drv_get_last_transfer_length();
134 break; 166 logf("scsi write %d %d", current_cmd.sector, current_cmd.count);
135 167 if(usb_drv_get_last_transfer_status()==0)
136 default: 168 {
137 break; 169 if((unsigned int)receive_count!=(SECTOR_SIZE*current_cmd.count))
170 {
171 logf("%d >= %d",SECTOR_SIZE*current_cmd.count,receive_count);
172 }
173 ata_write_sectors(IF_MV2(current_cmd.lun,)
174 current_cmd.sector, current_cmd.count,
175 transfer_buffer);
176 send_csw(current_cmd.tag, SCSI_STATUS_GOOD);
177 }
178 else
179 {
180 logf("Transfer failed %X",usb_drv_get_last_transfer_status());
181 send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION);
182 }
138 } 183 }
139 184 else
140 /* re-prime endpoint */ 185 {
141 usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); 186 state = SENDING;
187 handle_scsi(cbw);
188 }
189
142 break; 190 break;
143 191
144 case EP_TX: 192 case EP_TX:
145 //logf("ums: %d bytes out", length); 193 //logf("ums: out complete");
194 if(state != IDLE)
195 {
196 /* re-prime endpoint. We only need room for commands */
197 state = IDLE;
198 usb_drv_recv(EP_RX, transfer_buffer, 1024);
199 }
200
146 break; 201 break;
147 } 202 }
148} 203}
@@ -156,7 +211,7 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req)
156 211
157 switch (req->bRequest) { 212 switch (req->bRequest) {
158 case USB_BULK_GET_MAX_LUN: { 213 case USB_BULK_GET_MAX_LUN: {
159 static char maxlun = 0; 214 static char maxlun = NUM_VOLUMES - 1;
160 logf("ums: getmaxlun"); 215 logf("ums: getmaxlun");
161 usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1); 216 usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1);
162 usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ 217 usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
@@ -174,8 +229,9 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req)
174 229
175 case USB_REQ_SET_CONFIGURATION: 230 case USB_REQ_SET_CONFIGURATION:
176 logf("ums: set config"); 231 logf("ums: set config");
177 /* prime rx endpoint */ 232 /* prime rx endpoint. We only need room for commands */
178 usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); 233 state = IDLE;
234 usb_drv_recv(EP_RX, transfer_buffer, 1024);
179 handled = true; 235 handled = true;
180 break; 236 break;
181 } 237 }
@@ -185,50 +241,138 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req)
185 241
186/****************************************************************************/ 242/****************************************************************************/
187 243
188void handle_scsi(struct command_block_wrapper* cbw) 244static void handle_scsi(struct command_block_wrapper* cbw)
189{ 245{
190 /* USB Mass Storage assumes LBA capability. 246 /* USB Mass Storage assumes LBA capability.
191 TODO: support 48-bit LBA */ 247 TODO: support 48-bit LBA */
192 248
249 unsigned int sectors_per_transfer=0;
193 unsigned int length = cbw->data_transfer_length; 250 unsigned int length = cbw->data_transfer_length;
251 unsigned int block_size;
252 unsigned char lun = cbw->lun;
253 unsigned int block_size_mult = 1;
254#ifdef HAVE_HOTSWAP
255 tCardInfo* cinfo = card_get_info(lun);
256 block_size = cinfo->blocksize;
257 if(cinfo->initialized==1)
258 {
259 sectors_per_transfer=(sizeof _transfer_buffer/ block_size);
260 }
261#else
262 block_size = SECTOR_SIZE;
263 sectors_per_transfer=(sizeof _transfer_buffer/ block_size);
264#endif
265
266#ifdef MAX_LOG_SECTOR_SIZE
267 block_size_mult = disk_sector_multiplier;
268#endif
194 269
195 switch (cbw->command_block[0]) { 270 switch (cbw->command_block[0]) {
196 case SCSI_TEST_UNIT_READY: 271 case SCSI_TEST_UNIT_READY:
197 logf("scsi test_unit_ready"); 272 logf("scsi test_unit_ready %d",lun);
273#ifdef HAVE_HOTSWAP
274 if(cinfo->initialized==1)
275 send_csw(cbw->tag, SCSI_STATUS_GOOD);
276 else
277 send_csw(cbw->tag, SCSI_STATUS_FAIL);
278#else
198 send_csw(cbw->tag, SCSI_STATUS_GOOD); 279 send_csw(cbw->tag, SCSI_STATUS_GOOD);
280#endif
199 break; 281 break;
200 282
201 case SCSI_INQUIRY: 283 case SCSI_INQUIRY:
202 logf("scsi inquiry"); 284 logf("scsi inquiry %d",lun);
285 identify2inquiry(lun);
203 length = MIN(length, cbw->command_block[4]); 286 length = MIN(length, cbw->command_block[4]);
204 usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length)); 287 usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length));
205 send_csw(cbw->tag, SCSI_STATUS_GOOD); 288 send_csw(cbw->tag, SCSI_STATUS_GOOD);
206 break; 289 break;
207 290
291 case SCSI_REQUEST_SENSE: {
292 sense_data->ResponseCode=0x70;
293 sense_data->filemark_eom_ili_sensekey=2;
294 sense_data->Information=2;
295 sense_data->AdditionalSenseLength=10;
296 sense_data->CommandSpecificInformation=0;
297 sense_data->AdditionalSenseCode=0x3a;
298 sense_data->AdditionalSenseCodeQualifier=0;
299 sense_data->FieldReplaceableUnitCode=0;
300 sense_data->SKSV=0;
301 sense_data->SenseKeySpecific=0;
302 logf("scsi request_sense %d",lun);
303 usb_drv_send(EP_TX, sense_data,
304 sizeof(_sense_data));
305 send_csw(cbw->tag, SCSI_STATUS_GOOD);
306 break;
307 }
308
208 case SCSI_MODE_SENSE: { 309 case SCSI_MODE_SENSE: {
209 static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 310 static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
210 logf("scsi mode_sense"); 311 logf("scsi mode_sense %d",lun);
211 usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data), 312 usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data),
212 MIN(sizeof sense_data, length)); 313 MIN(sizeof sense_data, length));
213 send_csw(cbw->tag, SCSI_STATUS_GOOD); 314 send_csw(cbw->tag, SCSI_STATUS_GOOD);
214 break; 315 break;
215 } 316 }
216 317
318 case SCSI_START_STOP_UNIT:
319 logf("scsi start_stop unit %d",lun);
320 send_csw(cbw->tag, SCSI_STATUS_GOOD);
321 break;
322
217 case SCSI_ALLOW_MEDIUM_REMOVAL: 323 case SCSI_ALLOW_MEDIUM_REMOVAL:
218 logf("scsi allow_medium_removal"); 324 logf("scsi allow_medium_removal %d",lun);
325 send_csw(cbw->tag, SCSI_STATUS_GOOD);
326 break;
327
328 case SCSI_READ_FORMAT_CAPACITY: {
329 logf("scsi read_format_capacity %d",lun);
330 format_capacity_data->following_length=htobe32(8);
331#ifdef HAVE_HOTSWAP
332 /* Careful: "block count" actually means "number of last block" */
333 if(cinfo->initialized==1)
334 {
335 format_capacity_data->block_count = htobe32(cinfo->numblocks - 1);
336 format_capacity_data->block_size = htobe32(cinfo->blocksize);
337 }
338 else
339 {
340 format_capacity_data->block_count = htobe32(0);
341 format_capacity_data->block_size = htobe32(0);
342 }
343#else
344 unsigned short* identify = ata_get_identify();
345 /* Careful: "block count" actually means "number of last block" */
346 format_capacity_data->block_count = htobe32((identify[61] << 16 | identify[60]) / block_size_mult - 1);
347 format_capacity_data->block_size = htobe32(block_size * block_size_mult);
348#endif
349 format_capacity_data->block_size |= SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA;
350
351 usb_drv_send(EP_TX, format_capacity_data,
352 MIN(sizeof _format_capacity_data, length));
219 send_csw(cbw->tag, SCSI_STATUS_GOOD); 353 send_csw(cbw->tag, SCSI_STATUS_GOOD);
220 break; 354 break;
355 }
221 356
222 case SCSI_READ_CAPACITY: { 357 case SCSI_READ_CAPACITY: {
223 logf("scsi read_capacity"); 358 logf("scsi read_capacity %d",lun);
224#ifdef HAVE_FLASH_STORAGE 359#ifdef HAVE_HOTSWAP
225 tCardInfo* cinfo = card_get_info(0); 360 /* Careful: "block count" actually means "number of last block" */
226 capacity_data->block_count = htobe32(cinfo->numblocks); 361 if(cinfo->initialized==1)
227 capacity_data->block_size = htobe32(cinfo->blocksize); 362 {
363 capacity_data->block_count = htobe32(cinfo->numblocks - 1);
364 capacity_data->block_size = htobe32(cinfo->blocksize);
365 }
366 else
367 {
368 capacity_data->block_count = htobe32(0);
369 capacity_data->block_size = htobe32(0);
370 }
228#else 371#else
229 unsigned short* identify = ata_get_identify(); 372 unsigned short* identify = ata_get_identify();
230 capacity_data->block_count = htobe32(identify[60] << 16 | identify[61]); 373 /* Careful : "block count" actually means the number of the last block */
231 capacity_data->block_size = htobe32(SECTOR_SIZE); 374 capacity_data->block_count = htobe32((identify[61] << 16 | identify[60]) / block_size_mult - 1);
375 capacity_data->block_size = htobe32(block_size * block_size_mult);
232#endif 376#endif
233 usb_drv_send(EP_TX, capacity_data, 377 usb_drv_send(EP_TX, capacity_data,
234 MIN(sizeof _capacity_data, length)); 378 MIN(sizeof _capacity_data, length));
@@ -237,43 +381,71 @@ void handle_scsi(struct command_block_wrapper* cbw)
237 } 381 }
238 382
239 case SCSI_READ_10: 383 case SCSI_READ_10:
240 current_cmd.sector = 384 current_cmd.sector = block_size_mult *
241 cbw->command_block[2] << 24 | 385 (cbw->command_block[2] << 24 |
242 cbw->command_block[3] << 16 | 386 cbw->command_block[3] << 16 |
243 cbw->command_block[4] << 8 | 387 cbw->command_block[4] << 8 |
244 cbw->command_block[5] ; 388 cbw->command_block[5] );
245 current_cmd.count = 389 current_cmd.count = block_size_mult *
246 cbw->command_block[7] << 16 | 390 (cbw->command_block[7] << 16 |
247 cbw->command_block[8]; 391 cbw->command_block[8]);
248 current_cmd.offset = 0;
249 current_cmd.tag = cbw->tag; 392 current_cmd.tag = cbw->tag;
393 current_cmd.lun = cbw->lun;
250 394
251 logf("scsi read %d %d", current_cmd.sector, current_cmd.count); 395 //logf("scsi read %d %d", current_cmd.sector, current_cmd.count);
252 396
253 /* too much? */ 397 //logf("Asked for %d sectors",current_cmd.count);
254 if (current_cmd.count > (sizeof _transfer_buffer / SECTOR_SIZE)) { 398 if(current_cmd.count > sectors_per_transfer)
255 send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); 399 {
256 break; 400 current_cmd.count = sectors_per_transfer;
257 } 401 }
402 //logf("Sending %d sectors",current_cmd.count);
258 403
259 ata_read_sectors(IF_MV2(0,) current_cmd.sector, current_cmd.count, 404 if(current_cmd.count*block_size > sizeof(_transfer_buffer)) {
260 transfer_buffer); 405 send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION);
261 state = SENDING; 406 }
262 usb_drv_send(EP_TX, transfer_buffer, 407 else {
263 MIN(current_cmd.count * SECTOR_SIZE, length)); 408 ata_read_sectors(IF_MV2(lun,) current_cmd.sector,
409 current_cmd.count, transfer_buffer);
410 usb_drv_send(EP_TX, transfer_buffer,
411 current_cmd.count*block_size);
412 send_csw(current_cmd.tag, SCSI_STATUS_GOOD);
413 }
264 break; 414 break;
265 415
266 case SCSI_WRITE_10: 416 case SCSI_WRITE_10:
267 logf("scsi write10"); 417 //logf("scsi write10");
418 current_cmd.sector = block_size_mult *
419 (cbw->command_block[2] << 24 |
420 cbw->command_block[3] << 16 |
421 cbw->command_block[4] << 8 |
422 cbw->command_block[5] );
423 current_cmd.count = block_size_mult *
424 (cbw->command_block[7] << 16 |
425 cbw->command_block[8]);
426 current_cmd.tag = cbw->tag;
427 current_cmd.lun = cbw->lun;
428 /* expect data */
429 if(current_cmd.count*block_size > sizeof(_transfer_buffer)) {
430 send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION);
431 }
432 else {
433 usb_drv_recv(EP_RX, transfer_buffer,
434 current_cmd.count*block_size);
435 state = RECEIVING;
436 }
437
268 break; 438 break;
269 439
270 default: 440 default:
271 logf("scsi unknown cmd %x", cbw->command_block[0]); 441 logf("scsi unknown cmd %x",cbw->command_block[0x0]);
442 usb_drv_stall(EP_TX, true);
443 send_csw(current_cmd.tag, SCSI_STATUS_GOOD);
272 break; 444 break;
273 } 445 }
274} 446}
275 447
276void send_csw(unsigned int tag, int status) 448static void send_csw(unsigned int tag, int status)
277{ 449{
278 static struct command_status_wrapper _csw; 450 static struct command_status_wrapper _csw;
279 struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw); 451 struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw);
@@ -287,16 +459,23 @@ void send_csw(unsigned int tag, int status)
287} 459}
288 460
289/* convert ATA IDENTIFY to SCSI INQUIRY */ 461/* convert ATA IDENTIFY to SCSI INQUIRY */
290static void identify2inquiry(void) 462static void identify2inquiry(int lun)
291{ 463{
292 unsigned int i;
293#ifdef HAVE_FLASH_STORAGE 464#ifdef HAVE_FLASH_STORAGE
294 for (i=0; i<8; i++) 465 if(lun==0)
295 inquiry->VendorId[i] = i + 'A'; 466 {
296 467 memcpy(&inquiry->VendorId,"Rockbox ",8);
297 for (i=0; i<8; i++) 468 memcpy(&inquiry->ProductId,"Internal Storage",16);
298 inquiry->ProductId[i] = i + 'm'; 469 memcpy(&inquiry->ProductRevisionLevel,"0.00",4);
470 }
471 else
472 {
473 memcpy(&inquiry->VendorId,"Rockbox ",8);
474 memcpy(&inquiry->ProductId,"SD Card Slot ",16);
475 memcpy(&inquiry->ProductRevisionLevel,"0.00",4);
476 }
299#else 477#else
478 unsigned int i;
300 unsigned short* dest; 479 unsigned short* dest;
301 unsigned short* src; 480 unsigned short* src;
302 unsigned short* identify = ata_get_identify(); 481 unsigned short* identify = ata_get_identify();
@@ -310,22 +489,27 @@ static void identify2inquiry(void)
310 src = (unsigned short*)&identify[27]; 489 src = (unsigned short*)&identify[27];
311 dest = (unsigned short*)&inquiry->VendorId; 490 dest = (unsigned short*)&inquiry->VendorId;
312 for (i=0;i<4;i++) 491 for (i=0;i<4;i++)
313 dest[i] = src[i]; 492 dest[i] = htobe16(src[i]);
314 493
315 src = (unsigned short*)&identify[27+8]; 494 src = (unsigned short*)&identify[27+8];
316 dest = (unsigned short*)&inquiry->ProductId; 495 dest = (unsigned short*)&inquiry->ProductId;
317 for (i=0;i<8;i++) 496 for (i=0;i<8;i++)
318 dest[i] = src[i]; 497 dest[i] = htobe16(src[i]);
319 498
320 src = (unsigned short*)&identify[23]; 499 src = (unsigned short*)&identify[23];
321 dest = (unsigned short*)&inquiry->ProductRevisionLevel; 500 dest = (unsigned short*)&inquiry->ProductRevisionLevel;
322 for (i=0;i<2;i++) 501 for (i=0;i<2;i++)
323 dest[i] = src[i]; 502 dest[i] = htobe16(src[i]);
324#endif 503#endif
325 504
326 inquiry->DeviceType = DIRECT_ACCESS_DEVICE; 505 inquiry->DeviceType = DIRECT_ACCESS_DEVICE;
327 inquiry->AdditionalLength = 0x1f; 506 inquiry->AdditionalLength = 0x1f;
328 inquiry->Versions = 3; /* ANSI SCSI level 2 */ 507 inquiry->Versions = 3; /* ANSI SCSI level 2 */
329 inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */ 508 inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */
509
510#ifdef HAVE_HOTSWAP
511 inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
512#endif
513
330} 514}
331 515