1 /*
2 ********************************************************************************************************************
3 * usb host driver
4 *
5 * (c) Copyright 2007-2010, javen.China
6 * All Rights Reserved
7 *
8 * File Name : Scsi2.c
9 *
10 * Author : javen
11 *
12 * Version : 2.0
13 *
14 * Date : 2010.03.02
15 *
16 * Description : scsi command
17 *
18 * History :
19 *
20 ********************************************************************************************************************
21 */
22 #include "usb_os_platform.h"
23 #include "error.h"
24 #include "usb_msc_i.h"
25 #include "Scsi2.h"
26
27 static int ScsiGetSenseData(__mscLun_t *mscLun);
28
Scsi2_show_command(__ScsiCmnd_t * ScsiCmnd)29 void Scsi2_show_command(__ScsiCmnd_t *ScsiCmnd)
30 {
31 #if 0
32 char *what = NULL;
33 int i;
34 unsigned char *CB = NULL;
35 CB = (unsigned char *)ScsiCmnd->cmnd.CommandBlock;
36
37 switch (CB[0])
38 {
39 case SCSI_TEST_UNIT_READY:
40 what = "TEST_UNIT_READY";
41 break;
42
43 case SCSI_REQUEST_SENSE:
44 what = "REQUEST_SENSE";
45 break;
46
47 case SCSI_READ6:
48 what = "READ_6";
49 break;
50
51 case SCSI_WRITE6:
52 what = "WRITE_6";
53 break;
54
55 case SCSI_INQUIRY:
56 what = "INQUIRY";
57 break;
58
59 case SCSI_MODE_SELECT6:
60 what = "MODE_SELECT";
61 break;
62
63 case SCSI_MODE_SELECT10:
64 what = "MODE_SELECT";
65 break;
66
67 case SCSI_MODE_SENSE6:
68 what = "MODE_SENSE";
69 break;
70
71 case SCSI_MODE_SENSE10:
72 what = "MODE_SENSE";
73 break;
74
75 case SCSI_START_STOP:
76 what = "START_STOP";
77 break;
78
79 case SCSI_READ_CAPACITY:
80 what = "READ_CAPACITY";
81 break;
82
83 case SCSI_READ10:
84 what = "READ_10";
85 break;
86
87 case SCSI_WRITE10:
88 what = "WRITE_10";
89 break;
90
91 case SCSI_SYNCHRONIZE_CACHE:
92 what = "SYNCHRONIZE_CACHE";
93 break;
94
95 /* CD */
96 case SCSI_CD_READ_TOC:
97 what = "READ HEADER";
98 break;
99
100 // case SCSI_CD_PLAY10:
101 // what = "PLAY AUDIO (10)";
102 // break;
103
104 // case SCSI_CD_PLAY_MSF:
105 // what = "PLAY AUDIO MSF";
106 // break;
107
108 case SCSI_CD_PAUSE_RESUME:
109 what = "GET EVENT/STATUS NOTIFICATION";
110 break;
111
112 default:
113 what = "(unknown command)";
114 break;
115 }
116
117 hal_log_info("");
118 hal_log_info("Command name = %s (%d bytes)", what, ScsiCmnd->cmnd.CBLen);
119
120 for (i = 0; i < ScsiCmnd->cmnd.CBLen && i < MAX_CDB; i++)
121 {
122 hal_log_info(" %x ", CB[i]);
123 }
124
125 hal_log_info("allowed = %d", ScsiCmnd->allowed);
126 hal_log_info("TransLen = %d", ScsiCmnd->DataTransferLength);
127 hal_log_info("direction = %s", (ScsiCmnd->cmnd.data_direction == DATA_FROM_DEVICE)
128 ? "DATA_FROM_DEVICE" : "DATA_TO_DEVICE");
129 hal_log_info("Tag = %x", ScsiCmnd->cmnd.Tag);
130 hal_log_info("Timeout = %d", ScsiCmnd->cmnd.Timeout);
131 hal_log_info("dwLun = %d", ScsiCmnd->cmnd.dwLun);
132 hal_log_info("CB_ADDR = %x", ScsiCmnd->cmnd.CommandBlock);
133 hal_log_info("");
134 #endif
135 }
136
ScsiCmndDone(__ScsiCmnd_t * ScsiCmnd)137 static void ScsiCmndDone(__ScsiCmnd_t *ScsiCmnd)
138 {
139 hal_sem_post(ScsiCmnd->complete);
140 }
141
142 /*
143 *******************************************************************************
144 * ScsiDoCommand
145 *
146 * Description:
147 *
148 *
149 * Parameters:
150 *
151 *
152 * Return value:
153 *
154 *
155 * note:
156 *
157 *
158 *******************************************************************************
159 */
ScsiDoCommand(__mscLun_t * mscLun,__ScsiCmnd_t * ScsiCmnd)160 static int ScsiDoCommand(__mscLun_t *mscLun, __ScsiCmnd_t *ScsiCmnd)
161 {
162 unsigned int ret = 0;
163
164 if (mscLun == NULL || ScsiCmnd == NULL)
165 {
166 hal_log_err("ERR: ScsiDoCommand: input error, mscLun = %x, ScsiCmd == %x", mscLun, ScsiCmnd);
167 return USB_STATUS_BAD_ARGUMENTS;
168 }
169
170 ScsiCmnd->complete = hal_sem_create(0);
171
172 if (ScsiCmnd->complete == NULL)
173 {
174 hal_log_err("ERR: ScsiDoCommand: hal_sem_createfailed");
175 return USB_STATUS_UNKOWN_ERROR;
176 }
177
178 Scsi2_show_command(ScsiCmnd);
179 /* do scsi command */
180 ret = mscDevQueueCmnd(mscLun, ScsiCmnd);
181
182 if (ret != USB_ERR_SUCCESS)
183 {
184 hal_log_err("ERR: mscDevQueueCmnd failed");
185 goto Next;
186 }
187
188 scsidone:
189 /* wait for complete */
190 ret = hal_sem_wait(ScsiCmnd->complete);
191 if (ret != 0)
192 {
193 hal_log_err("wait scsi done again!");
194 goto scsidone;
195 }
196
197 Next:
198 hal_sem_delete(ScsiCmnd->complete);
199 ScsiCmnd->complete = NULL;
200
201 switch (ScsiCmnd->Result)
202 {
203 case USB_STOR_TRANSPORT_GOOD:
204 ret = USB_STATUS_SUCCESS;
205 break;
206
207 case USB_STOR_TRANSPORT_FAILED:
208 ret = ScsiGetSenseData(mscLun);
209 break;
210
211 case USB_STOR_TRANSPORT_ERROR:
212 ret = USB_STATUS_COMMAND_FAILED;
213 break;
214
215 default:
216 hal_log_err("ERR: ScsiDoCommand: unkown command result %d", ScsiCmnd->Result);
217 ret = USB_STATUS_COMMAND_FAILED;
218 }
219
220 return ret;
221 }
222
223
224 /*
225 *******************************************************************************
226 * ScsiInquery
227 *
228 * Description:
229 *
230 *
231 * Parameters:
232 *
233 *
234 * Return value:
235 *
236 *
237 * note:
238 *
239 *
240 *******************************************************************************
241 */
ScsiInquery(__mscLun_t * mscLun,void * buffer,unsigned int buffer_len)242 int ScsiInquery(__mscLun_t *mscLun, void *buffer, unsigned int buffer_len)
243 {
244 __ScsiCmnd_t ScsiCmnd;
245 unsigned char CB[MAX_CDB];
246
247 if (mscLun == NULL || buffer == NULL)
248 {
249 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x, buffer = %x", mscLun, buffer);
250 return USB_STATUS_BAD_ARGUMENTS;
251 }
252
253 if (buffer_len == 0)
254 {
255 hal_log_err("ERR: ScsiInquery: input error, buffer_len == %d", buffer_len);
256 return USB_STATUS_BUFFER_TOO_SMALL;
257 }
258
259 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
260 memset(CB, 0, MAX_CDB);
261 /* create command block */
262 CB[0] = SCSI_INQUIRY; /* scsi command */
263 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
264 CB[4] = buffer_len; /* Allocation Length */
265 /* initialize transport command */
266 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
267 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
268 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
269 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
270 ScsiCmnd.cmnd.CommandBlock = CB;
271 /* initialize scsi_cnmd */
272 ScsiCmnd.sc_lun = mscLun;
273 ScsiCmnd.allowed = SCSI_CMD_RETRY;
274 ScsiCmnd.DataTransferLength = buffer_len;
275 ScsiCmnd.buffer = buffer;
276 ScsiCmnd.Done = ScsiCmndDone;
277 return ScsiDoCommand(mscLun, &ScsiCmnd);
278 }
279
280 /*
281 *******************************************************************************
282 * ScsiReadCapacity
283 *
284 * Description:
285 *
286 *
287 * Parameters:
288 *
289 *
290 * Return value:
291 *
292 *
293 * note:
294 *
295 *
296 *******************************************************************************
297 */
ScsiReadCapacity(__mscLun_t * mscLun)298 int ScsiReadCapacity(__mscLun_t *mscLun)
299 {
300 __ScsiCmnd_t ScsiCmnd;
301 unsigned char CB[MAX_CDB];
302 unsigned char buffer[8];
303 int ret = 0;
304
305 if (mscLun == NULL)
306 {
307 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
308 return USB_STATUS_BAD_ARGUMENTS;
309 }
310
311 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
312 memset(CB, 0, MAX_CDB);
313 /* create command block */
314 CB[0] = SCSI_READ_CAPACITY; /* scsi command */
315 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
316 /* initialize transport command */
317 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
318 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
319 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
320 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
321 ScsiCmnd.cmnd.CommandBlock = CB;
322 /* initialize scsi_cnmd */
323 ScsiCmnd.sc_lun = mscLun;
324 ScsiCmnd.allowed = SCSI_CMD_RETRY;
325 ScsiCmnd.DataTransferLength = 8;
326 ScsiCmnd.buffer = buffer;
327 ScsiCmnd.Done = ScsiCmndDone;
328 /* parse read capacity data */
329 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
330
331 if (ret == USB_STATUS_SUCCESS)
332 {
333 mscLun->disk_info.capacity = get_be32(buffer) + 1;
334 mscLun->disk_info.sector_size = get_be32(buffer + 4);
335 }
336 else
337 {
338 mscLun->disk_info.capacity = 0;
339 mscLun->disk_info.sector_size = 512;
340 }
341
342 return ret;
343 }
344
345 /*
346 *******************************************************************************
347 * ScsiModeSense6
348 *
349 * Description:
350 *
351 *
352 * Parameters:
353 *
354 *
355 * Return value:
356 *
357 *
358 * note:
359 *
360 *
361 *******************************************************************************
362 */
ScsiModeSense6(__mscLun_t * mscLun,unsigned int PageCode,unsigned int DBD,void * buffer,unsigned int buffer_len,unsigned int * ActLen)363 int ScsiModeSense6(__mscLun_t *mscLun,
364 unsigned int PageCode,
365 unsigned int DBD,
366 void *buffer,
367 unsigned int buffer_len,
368 unsigned int *ActLen)
369 {
370 __ScsiCmnd_t ScsiCmnd;
371 unsigned char CB[MAX_CDB];
372 int ret = 0;
373
374 if (mscLun == NULL || buffer == NULL)
375 {
376 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x, buffer = %x", mscLun, buffer);
377 return USB_STATUS_BAD_ARGUMENTS;
378 }
379
380 if (buffer_len == 0)
381 {
382 hal_log_err("ERR: ScsiInquery: input error, buffer_len == %d", buffer_len);
383 return USB_STATUS_BUFFER_TOO_SMALL;
384 }
385
386 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
387 memset(CB, 0, MAX_CDB);
388 /* create command block */
389 CB[0] = SCSI_MODE_SENSE6; /* scsi command */
390 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
391 CB[1] = CB[1] | (DBD << 3); /* dbd */
392 CB[2] = PageCode; /* Page Code */
393 CB[4] = buffer_len; /* Allocation Length */
394 /* initialize transport command */
395 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
396 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
397 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
398 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
399 ScsiCmnd.cmnd.CommandBlock = CB;
400 /* initialize scsi_cnmd */
401 ScsiCmnd.sc_lun = mscLun;
402 ScsiCmnd.allowed = SCSI_CMD_RETRY;
403 ScsiCmnd.DataTransferLength = buffer_len;
404 ScsiCmnd.buffer = buffer;
405 ScsiCmnd.Done = ScsiCmndDone;
406 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
407
408 if (ret == USB_ERR_SUCCESS)
409 {
410 *ActLen = ScsiCmnd.ActualLength;
411 }
412 else
413 {
414 *ActLen = 0;
415 }
416
417 return ret;
418 }
419
420 /*
421 *******************************************************************************
422 * ScsiModeSense10
423 *
424 * Description:
425 *
426 *
427 * Parameters:
428 *
429 *
430 * Return value:
431 *
432 *
433 * note:
434 *
435 *
436 *******************************************************************************
437 */
ScsiModeSense10(__mscLun_t * mscLun,unsigned int PageCode,unsigned int DBD,void * buffer,unsigned int buffer_len,unsigned int * ActLen)438 int ScsiModeSense10(__mscLun_t *mscLun,
439 unsigned int PageCode,
440 unsigned int DBD,
441 void *buffer,
442 unsigned int buffer_len,
443 unsigned int *ActLen)
444 {
445 __ScsiCmnd_t ScsiCmnd;
446 unsigned char CB[MAX_CDB];
447 int ret = 0;
448
449 if (mscLun == NULL || buffer == NULL)
450 {
451 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x, buffer = %x", mscLun, buffer);
452 return USB_STATUS_BAD_ARGUMENTS;
453 }
454
455 if (buffer_len == 0)
456 {
457 hal_log_err("ERR: ScsiInquery: input error, buffer_len == %d", buffer_len);
458 return USB_STATUS_BUFFER_TOO_SMALL;
459 }
460
461 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
462 memset(CB, 0, MAX_CDB);
463 /* create command block */
464 CB[0] = SCSI_MODE_SENSE10; /* scsi command */
465 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
466 CB[1] = CB[1] | (DBD << 3); /* dbd */
467 CB[2] = PageCode; /* Page Code */
468 put_be16(&CB[7], buffer_len); /* Allocation Length */
469 /* initialize transport command */
470 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
471 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
472 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
473 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
474 ScsiCmnd.cmnd.CommandBlock = CB;
475 /* initialize scsi_cnmd */
476 ScsiCmnd.sc_lun = mscLun;
477 ScsiCmnd.allowed = SCSI_CMD_RETRY;
478 ScsiCmnd.DataTransferLength = buffer_len;
479 ScsiCmnd.buffer = buffer;
480 ScsiCmnd.Done = ScsiCmndDone;
481 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
482
483 if (ret == USB_ERR_SUCCESS)
484 {
485 *ActLen = ScsiCmnd.ActualLength;
486 }
487 else
488 {
489 *ActLen = 0;
490 }
491
492 return ret;
493 }
494
495 /*
496 *******************************************************************************
497 * ScsiTestUnitReady
498 *
499 * Description:
500 *
501 *
502 * Parameters:
503 *
504 *
505 * Return value:
506 *
507 *
508 * note:
509 *
510 *
511 *******************************************************************************
512 */
ScsiTestUnitReady(__mscLun_t * mscLun)513 int ScsiTestUnitReady(__mscLun_t *mscLun)
514 {
515 __ScsiCmnd_t ScsiCmnd;
516 unsigned char CB[MAX_CDB];
517 int ret = 0;
518
519 if (mscLun == NULL)
520 {
521 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
522 return USB_STATUS_BAD_ARGUMENTS;
523 }
524
525 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
526 memset(CB, 0, MAX_CDB);
527 /* create command block */
528 CB[0] = SCSI_TEST_UNIT_READY; /* scsi command */
529 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
530 /* initialize transport command */
531 ScsiCmnd.cmnd.data_direction = DATA_NONE;
532 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
533 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
534 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
535 ScsiCmnd.cmnd.CommandBlock = CB;
536 /* initialize scsi_cnmd */
537 ScsiCmnd.sc_lun = mscLun;
538 ScsiCmnd.allowed = SCSI_CMD_RETRY;
539 ScsiCmnd.DataTransferLength = 0;
540 ScsiCmnd.buffer = NULL;
541 ScsiCmnd.Done = ScsiCmndDone;
542 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
543 /*
544 if((ret == USB_STATUS_SUCCESS && !(mscLun->MediaPresent))){
545 DMSG_INFO("mscLun Media not Present, but test unit ready command is successful");
546 mscLun->MediaPresent = 1;
547 }else if((ret == USB_STATUS_MEDIA_NOT_PRESENT)
548 && (ret == USB_STATUS_UNIT_NOT_READY)
549 && (ret == USB_STATUS_UNRECOGNIZED_MEDIA)
550 && (ret == USB_STATUS_MEDIA_CHANGE)){
551 mscLun->MediaPresent = 0;
552 }
553 */
554 return ret;
555 }
556
557 /*
558 *******************************************************************************
559 * ScsiRequestSense
560 *
561 * Description:
562 *
563 *
564 * Parameters:
565 *
566 *
567 * Return value:
568 *
569 *
570 * note:
571 *
572 *
573 *******************************************************************************
574 */
ScsiRequestSense(__mscLun_t * mscLun,void * buffer,unsigned int buffer_len)575 int ScsiRequestSense(__mscLun_t *mscLun, void *buffer, unsigned int buffer_len)
576 {
577 __ScsiCmnd_t ScsiCmnd;
578 unsigned char CB[MAX_CDB];
579 unsigned char err = 0;
580 unsigned int ret = 0;
581
582 if (mscLun == NULL || buffer == NULL)
583 {
584 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x, buffer = %x", mscLun, buffer);
585 return USB_STATUS_BAD_ARGUMENTS;
586 }
587
588 if (buffer_len == 0)
589 {
590 hal_log_err("ERR: ScsiInquery: input error, buffer_len == %d", buffer_len);
591 return USB_STATUS_BUFFER_TOO_SMALL;
592 }
593
594 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
595 memset(CB, 0, MAX_CDB);
596 /* create command block */
597 CB[0] = SCSI_REQUEST_SENSE; /* scsi command */
598 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
599 CB[4] = buffer_len; /* Allocation Length */
600 /* initialize transport command */
601 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
602 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
603 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
604 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
605 ScsiCmnd.cmnd.CommandBlock = CB;
606 /* initialize scsi_cnmd */
607 ScsiCmnd.sc_lun = mscLun;
608 ScsiCmnd.allowed = SCSI_CMD_RETRY;
609 ScsiCmnd.DataTransferLength = buffer_len;
610 ScsiCmnd.buffer = buffer;
611 ScsiCmnd.Done = ScsiCmndDone;
612 /* do command */
613 ScsiCmnd.complete = hal_sem_create(0);
614
615 if (ScsiCmnd.complete == NULL)
616 {
617 hal_log_err("ERR: ScsiDoCommand: hal_sem_createfailed");
618 return USB_STATUS_UNKOWN_ERROR;
619 }
620
621 ret = mscDevQueueCmnd(mscLun, &ScsiCmnd);
622
623 if (ret != USB_ERR_SUCCESS)
624 {
625 hal_log_err("ERR: mscDevQueueCmnd failed");
626 goto Next;
627 }
628
629 /* wait for complete */
630 hal_sem_wait(ScsiCmnd.complete);
631 Next:
632 hal_sem_delete(ScsiCmnd.complete);
633 ScsiCmnd.complete = NULL;
634
635 switch (ScsiCmnd.Result)
636 {
637 case USB_STOR_TRANSPORT_GOOD:
638 ret = USB_STATUS_SUCCESS;
639 break;
640
641 case USB_STOR_TRANSPORT_FAILED:
642 ret = USB_STATUS_UNKOWN_ERROR;
643 break;
644
645 case USB_STOR_TRANSPORT_ERROR:
646 ret = USB_STATUS_COMMAND_FAILED;
647 break;
648
649 default:
650 hal_log_err("ERR: ScsiDoCommand: unkown command result %d", ScsiCmnd.Result);
651 ret = USB_STATUS_COMMAND_FAILED;
652 }
653
654 return ret;
655 }
656
657 /*
658 *******************************************************************************
659 * ScsiGetSenseData
660 *
661 * Description:
662 *
663 *
664 * Parameters:
665 *
666 *
667 * Return value:
668 *
669 *
670 * note:
671 *
672 *
673 *******************************************************************************
674 */
ScsiGetSenseData(__mscLun_t * mscLun)675 static int ScsiGetSenseData(__mscLun_t *mscLun)
676 {
677 __SenseData_t SenseData;
678 int ret = 0;
679 memset(&SenseData, 0, sizeof(__SenseData_t));
680 ret = ScsiRequestSense(mscLun, (void *)&SenseData, sizeof(__SenseData_t));
681
682 if (ret != USB_STATUS_SUCCESS)
683 {
684 hal_log_err("ERR: ScsiRequestSense failed");
685 return USB_STATUS_UNKOWN_ERROR;
686 }
687
688 hal_log_info("SenseKey = %x, AdditionalSenseCode = %x", SenseData.SenseKey, SenseData.AdditionalSenseCode);
689
690 switch (SenseData.SenseKey)
691 {
692 case SENSE_NONE :
693 ret = USB_STATUS_SUCCESS;
694 break;
695
696 case SENSE_NOT_READY :
697 switch (SenseData.AdditionalSenseCode)
698 {
699 case ASC_LUN:
700 if (0x02 == SenseData.AdditionalSenseCodeQualifier) // Initialization Required
701 {
702 ScsiStartStopUnit(mscLun, 0, 1);
703 }
704
705 if (0x01 == SenseData.AdditionalSenseCodeQualifier) /* not ready to ready */
706 {
707 ret = USB_STATUS_NOT_READY_TO_READY_TRANSITION;
708 }
709 else
710 {
711 ret = USB_STATUS_UNIT_NOT_READY;
712 }
713
714 break;
715
716 case ASC_MEDIUM_NOT_PRESENT :
717 hal_log_info("ERR: media is not present");
718 mscLun->MediaPresent = 0;
719 ret = USB_STATUS_MEDIA_NOT_PRESENT;
720 break;
721
722 default:
723 hal_log_info("ERR: unkown ASC(%d)", SenseData.AdditionalSenseCode);
724 ret = USB_STATUS_UNIT_NOT_READY;
725 break;
726 }
727
728 break;
729
730 case SENSE_MEDIUM_ERROR :
731 ret = USB_STATUS_UNRECOGNIZED_MEDIA;
732 break;
733
734 case SENSE_HARDWARE_ERROR :
735 ret = USB_STATUS_UNRECOGNIZED_MEDIA;
736 break;
737
738 case SENSE_ILLEGAL_REQUEST :
739 ret = USB_STATUS_INVALID_FIELD_IN_COMMAND;
740 break;
741
742 case SENSE_UNIT_ATTENTION :
743 switch (SenseData.AdditionalSenseCode)
744 {
745 case ASC_MEDIA_CHANGED :
746 hal_log_info("ERR: media not ready to ready transition");
747 ret = USB_STATUS_NOT_READY_TO_READY_TRANSITION;
748 break;
749
750 /* 见到sandisk的U盘,竟然在SENSE_UNIT_ATTENTION时, 说ASC_MEDIUM_NOT_PRESENT。
751 为了处理这样的U盘, 这里也检查ASC_MEDIUM_NOT_PRESENT */
752 case ASC_MEDIUM_NOT_PRESENT :
753 hal_log_info("ERR: media is not present");
754 mscLun->MediaPresent = 0;
755 ret = USB_STATUS_MEDIA_NOT_PRESENT;
756 break;
757
758 default:
759 hal_log_info("ERR: unkown ASC(%d)", SenseData.AdditionalSenseCode);
760 ret = USB_STATUS_UNKOWN_SENSE;
761 }
762
763 break;
764
765 default:
766 ret = USB_STATUS_UNKOWN_SENSE;
767 }
768
769 return ret;
770 }
771
772 /*
773 *******************************************************************************
774 * ScsiStartStopUnit
775 *
776 * Description:
777 * 开始 / 停止 设备工作
778 *
779 * Parameters:
780 * mscLun : input. 命令发向的设备
781 * LoEj : input. 加载/弹出 媒体介质
782 * Start : input. 开始 / 停止 设备工作
783 *
784 * Return value:
785 *
786 *
787 * note:
788 *
789 *
790 *******************************************************************************
791 */
ScsiStartStopUnit(__mscLun_t * mscLun,unsigned int LoEj,unsigned int Start)792 int ScsiStartStopUnit(__mscLun_t *mscLun, unsigned int LoEj, unsigned int Start)
793 {
794 __ScsiCmnd_t ScsiCmnd;
795 unsigned char CB[MAX_CDB];
796
797 if (mscLun == NULL)
798 {
799 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
800 return USB_STATUS_BAD_ARGUMENTS;
801 }
802
803 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
804 memset(CB, 0, MAX_CDB);
805 /* create command block */
806 CB[0] = SCSI_START_STOP; /* scsi command */
807 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
808 CB[4] = Start;
809 CB[4] = CB[4] | (LoEj << 1);
810 /* initialize transport command */
811 ScsiCmnd.cmnd.data_direction = DATA_NONE;
812 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
813 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
814 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
815 ScsiCmnd.cmnd.CommandBlock = CB;
816 /* initialize scsi_cnmd */
817 ScsiCmnd.sc_lun = mscLun;
818 ScsiCmnd.allowed = SCSI_CMD_RETRY;
819 ScsiCmnd.DataTransferLength = 0;
820 ScsiCmnd.buffer = NULL;
821 ScsiCmnd.Done = ScsiCmndDone;
822 return ScsiDoCommand(mscLun, &ScsiCmnd);
823 }
824
825 /*
826 *******************************************************************************
827 * SynchronizeCache
828 *
829 * Description:
830 *
831 *
832 * Parameters:
833 *
834 *
835 * Return value:
836 *
837 *
838 * note:
839 *
840 *
841 *******************************************************************************
842 */
ScsiSynchronizeCache(__mscLun_t * mscLun)843 int ScsiSynchronizeCache(__mscLun_t *mscLun)
844 {
845 __ScsiCmnd_t ScsiCmnd;
846 unsigned char CB[MAX_CDB];
847
848 if (mscLun == NULL)
849 {
850 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
851 return USB_STATUS_BAD_ARGUMENTS;
852 }
853
854 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
855 memset(CB, 0, MAX_CDB);
856 /* create command block */
857 CB[0] = SCSI_SYNCHRONIZE_CACHE; /* scsi command */
858 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
859 /* initialize transport command */
860 ScsiCmnd.cmnd.data_direction = DATA_NONE;
861 ScsiCmnd.cmnd.Timeout = SCSI_MEDIA_OP_TIMEOUT;
862 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
863 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
864 ScsiCmnd.cmnd.CommandBlock = CB;
865 /* initialize scsi_cnmd */
866 ScsiCmnd.sc_lun = mscLun;
867 ScsiCmnd.allowed = SCSI_CMD_RETRY;
868 ScsiCmnd.DataTransferLength = 0;
869 ScsiCmnd.buffer = NULL;
870 ScsiCmnd.Done = ScsiCmndDone;
871 return ScsiDoCommand(mscLun, &ScsiCmnd);
872 }
873
874 /*
875 *******************************************************************************
876 * ScsiRead
877 *
878 * Description:
879 *
880 *
881 * Parameters:
882 *
883 *
884 * Return value:
885 *
886 *
887 * note:
888 *
889 *
890 *******************************************************************************
891 */
ScsiRead(__mscLun_t * mscLun,unsigned int Version,unsigned int StartSector,unsigned int NumSectors,void * buffer,unsigned int buffer_len)892 int ScsiRead(__mscLun_t *mscLun,
893 unsigned int Version,
894 unsigned int StartSector,
895 unsigned int NumSectors,
896 void *buffer,
897 unsigned int buffer_len)
898 {
899 __ScsiCmnd_t ScsiCmnd;
900 unsigned char CB[MAX_CDB];
901
902 if (mscLun == NULL)
903 {
904 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
905 return USB_STATUS_BAD_ARGUMENTS;
906 }
907
908 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
909 memset(CB, 0, MAX_CDB);
910
911 /* create command block */
912 if (Version == 16)
913 {
914 hal_log_err("ERR: read16 not support");
915 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_16 : UFI_CDB;
916 return USB_STATUS_INVALID_COMMAND;
917 }
918 else if (Version == 10)
919 {
920 CB[0] = SCSI_READ10; /* scsi command */
921 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
922 put_be32(&CB[2], StartSector); /* LOGICAL BLOCK ADDRESS */
923 put_be16(&CB[7], NumSectors); /* TRANSFER LENGTH */
924 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
925 }
926 else
927 {
928 CB[0] = SCSI_READ6; /* scsi command */
929 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
930 CB[1] = (unsigned char)(StartSector >> 16) & 0x1f; /* LOGICAL BLOCK ADDRESS */
931 put_be16(&CB[2], (__u16)StartSector);
932 CB[4] = NumSectors; /* TRANSFER LENGTH */
933 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
934 }
935
936 /* initialize transport command */
937 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
938 ScsiCmnd.cmnd.Timeout = SCSI_MEDIA_OP_TIMEOUT;
939 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
940 ScsiCmnd.cmnd.CommandBlock = CB;
941 /* initialize scsi_cnmd */
942 ScsiCmnd.sc_lun = mscLun;
943 ScsiCmnd.allowed = SCSI_CMD_RETRY;
944 ScsiCmnd.DataTransferLength = buffer_len;
945 ScsiCmnd.buffer = buffer;
946 ScsiCmnd.Done = ScsiCmndDone;
947 return ScsiDoCommand(mscLun, &ScsiCmnd);
948 }
949
950 /*
951 *******************************************************************************
952 * ScsiWrite
953 *
954 * Description:
955 *
956 *
957 * Parameters:
958 *
959 *
960 * Return value:
961 *
962 *
963 * note:
964 *
965 *
966 *******************************************************************************
967 */
ScsiWrite(__mscLun_t * mscLun,unsigned int Version,unsigned int StartSector,unsigned int NumSectors,void * buffer,unsigned int buffer_len)968 int ScsiWrite(__mscLun_t *mscLun,
969 unsigned int Version,
970 unsigned int StartSector,
971 unsigned int NumSectors,
972 void *buffer,
973 unsigned int buffer_len)
974 {
975 __ScsiCmnd_t ScsiCmnd;
976 unsigned char CB[MAX_CDB];
977
978 if (mscLun == NULL)
979 {
980 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
981 return USB_STATUS_BAD_ARGUMENTS;
982 }
983
984 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
985 memset(CB, 0, MAX_CDB);
986
987 /* create command block */
988 if (Version == 16)
989 {
990 hal_log_err("ERR: read16 not support");
991 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_16 : UFI_CDB;
992 return USB_STATUS_INVALID_COMMAND;
993 }
994 else if (Version == 10)
995 {
996 CB[0] = SCSI_WRITE10; /* scsi command */
997 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
998 put_be32(&CB[2], StartSector); /* LOGICAL BLOCK ADDRESS */
999 put_be16(&CB[7], NumSectors); /* TRANSFER LENGTH */
1000 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
1001 }
1002 else
1003 {
1004 CB[0] = SCSI_WRITE6; /* scsi command */
1005 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
1006 CB[1] = (unsigned char)(StartSector >> 16) & 0x1f; /* LOGICAL BLOCK ADDRESS */
1007 put_be16(&CB[2], (__u16)StartSector);
1008 CB[4] = NumSectors; /* TRANSFER LENGTH */
1009 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
1010 }
1011
1012 /* initialize transport command */
1013 ScsiCmnd.cmnd.data_direction = DATA_TO_DEVICE;
1014 ScsiCmnd.cmnd.Timeout = SCSI_MEDIA_OP_TIMEOUT;
1015 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1016 ScsiCmnd.cmnd.CommandBlock = CB;
1017 /* initialize scsi_cnmd */
1018 ScsiCmnd.sc_lun = mscLun;
1019 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1020 ScsiCmnd.DataTransferLength = buffer_len;
1021 ScsiCmnd.buffer = buffer;
1022 ScsiCmnd.Done = ScsiCmndDone;
1023 return ScsiDoCommand(mscLun, &ScsiCmnd);
1024 }
1025
1026 /*
1027 *******************************************************************************
1028 * ScsiPreventAllowMedium
1029 *
1030 * Description:
1031 * 禁止/允许介质移动
1032 *
1033 * Parameters:
1034 * mscLun : input. 目标设备
1035 * Persistent : input. 禁止介质数据传输
1036 * Prevent : input. 禁止介质移动
1037 *
1038 *
1039 * Return value:
1040 * 返回命令的执行结果
1041 *
1042 * note:
1043 * Persistent只能在设备枚举的时候设置, 在设备操作阶段不要使用。
1044 *
1045 *******************************************************************************
1046 */
ScsiPreventAllowMedium(__mscLun_t * mscLun,unsigned int Persistent,unsigned int Prevent)1047 int ScsiPreventAllowMedium(__mscLun_t *mscLun, unsigned int Persistent, unsigned int Prevent)
1048 {
1049 __ScsiCmnd_t ScsiCmnd;
1050 unsigned char CB[MAX_CDB];
1051
1052 if (mscLun == NULL)
1053 {
1054 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1055 return USB_STATUS_BAD_ARGUMENTS;
1056 }
1057
1058 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1059 memset(CB, 0, MAX_CDB);
1060 /* create command block */
1061 CB[0] = SCSI_DVD_PREVENT_ALLOW_MEDIUM_REMOVAL; /* scsi command */
1062 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1063 CB[4] = CB[4] | (Persistent << 1); /* persistent */
1064 CB[4] = CB[4] | (Prevent << 0); /* prevent */
1065 /* initialize transport command */
1066 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1067 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1068 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1069 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : UFI_CDB;
1070 ScsiCmnd.cmnd.CommandBlock = CB;
1071 /* initialize scsi_cnmd */
1072 ScsiCmnd.sc_lun = mscLun;
1073 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1074 ScsiCmnd.DataTransferLength = 0;
1075 ScsiCmnd.buffer = NULL;
1076 ScsiCmnd.Done = ScsiCmndDone;
1077 return ScsiDoCommand(mscLun, &ScsiCmnd);
1078 }
1079
1080 /*
1081 *******************************************************************************
1082 * ScsiCDPauseResume
1083 *
1084 * Description:
1085 * 停止/恢复播放CD media
1086 *
1087 * Parameters:
1088 *
1089 *
1090 * Return value:
1091 *
1092 *
1093 * note:
1094 *
1095 *
1096 *******************************************************************************
1097 */
ScsiCDPauseResume(__mscLun_t * mscLun,unsigned int Resume)1098 int ScsiCDPauseResume(__mscLun_t *mscLun, unsigned int Resume)
1099 {
1100 __ScsiCmnd_t ScsiCmnd;
1101 unsigned char CB[MAX_CDB];
1102
1103 if (mscLun == NULL)
1104 {
1105 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1106 return USB_STATUS_BAD_ARGUMENTS;
1107 }
1108
1109 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1110 memset(CB, 0, MAX_CDB);
1111 /* create command block */
1112 CB[0] = SCSI_CD_PAUSE_RESUME; /* scsi command */
1113 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1114 CB[8] = Resume & 0x01; /* Resume bit */
1115 /* initialize transport command */
1116 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1117 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1118 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1119 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1120 ScsiCmnd.cmnd.CommandBlock = CB;
1121 /* initialize scsi_cnmd */
1122 ScsiCmnd.sc_lun = mscLun;
1123 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1124 ScsiCmnd.DataTransferLength = 0;
1125 ScsiCmnd.buffer = NULL;
1126 ScsiCmnd.Done = ScsiCmndDone;
1127 return ScsiDoCommand(mscLun, &ScsiCmnd);
1128 }
1129
1130 /*
1131 *******************************************************************************
1132 * ScsiCDPlayAudio10
1133 *
1134 * Description:
1135 *
1136 *
1137 * Parameters:
1138 *
1139 *
1140 * Return value:
1141 *
1142 *
1143 * note:
1144 *
1145 *
1146 *******************************************************************************
1147 */
ScsiCDPlayAudio10(__mscLun_t * mscLun,unsigned int Lba,unsigned int Lenght)1148 int ScsiCDPlayAudio10(__mscLun_t *mscLun, unsigned int Lba, unsigned int Lenght)
1149 {
1150 __ScsiCmnd_t ScsiCmnd;
1151 unsigned char CB[MAX_CDB];
1152
1153 if (mscLun == NULL)
1154 {
1155 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1156 return USB_STATUS_BAD_ARGUMENTS;
1157 }
1158
1159 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1160 memset(CB, 0, MAX_CDB);
1161 /* create command block */
1162 CB[0] = SCSI_CD_PLAY_AUDIO10; /* scsi command */
1163 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1164 put_be32(&CB[2], Lba); /* Start LOGICAL BLOCK ADDRESS */
1165 put_be16(&CB[7], Lenght); /* TRANSFER LENGTH */
1166 /* initialize transport command */
1167 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1168 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1169 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1170 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1171 ScsiCmnd.cmnd.CommandBlock = CB;
1172 /* initialize scsi_cnmd */
1173 ScsiCmnd.sc_lun = mscLun;
1174 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1175 ScsiCmnd.DataTransferLength = 0;
1176 ScsiCmnd.buffer = NULL;
1177 ScsiCmnd.Done = ScsiCmndDone;
1178 return ScsiDoCommand(mscLun, &ScsiCmnd);
1179 }
1180
1181 /*
1182 *******************************************************************************
1183 * ScsiCDPlayAudioMSF
1184 *
1185 * Description:
1186 * 播放指定mfs的音乐光碟
1187 *
1188 * Parameters:
1189 * mscLun : input. Logic unit
1190 * MSF : input. 多扇区
1191 *
1192 * Return value:
1193 * 返回命令的执行情况
1194 *
1195 * note:
1196 *
1197 *
1198 *******************************************************************************
1199 */
ScsiCDPlayAudioMSF(__mscLun_t * mscLun,CDROM_PlayAudioMsf_t * MSF)1200 int ScsiCDPlayAudioMSF(__mscLun_t *mscLun, CDROM_PlayAudioMsf_t *MSF)
1201 {
1202 __ScsiCmnd_t ScsiCmnd;
1203 unsigned char CB[MAX_CDB];
1204
1205 if (mscLun == NULL)
1206 {
1207 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1208 return USB_STATUS_BAD_ARGUMENTS;
1209 }
1210
1211 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1212 memset(CB, 0, MAX_CDB);
1213 /* create command block */
1214 CB[0] = SCSI_CD_PLAY_AUDIO_MSF; /* scsi command */
1215 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1216 CB[3] = MSF->StartingM;
1217 CB[4] = MSF->StartingS;
1218 CB[5] = MSF->StartingF;
1219 CB[6] = MSF->EndingM;
1220 CB[7] = MSF->EndingS;
1221 CB[8] = MSF->EndingF;
1222 /* initialize transport command */
1223 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1224 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1225 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1226 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1227 ScsiCmnd.cmnd.CommandBlock = CB;
1228 /* initialize scsi_cnmd */
1229 ScsiCmnd.sc_lun = mscLun;
1230 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1231 ScsiCmnd.DataTransferLength = 0;
1232 ScsiCmnd.buffer = NULL;
1233 ScsiCmnd.Done = ScsiCmndDone;
1234 return ScsiDoCommand(mscLun, &ScsiCmnd);
1235 }
1236
1237 /*
1238 *******************************************************************************
1239 * ScsiCDReadToc
1240 *
1241 * Description:
1242 * 读取介质内容的分配表信息
1243 *
1244 * Parameters:
1245 * mscLun : input. Logic unit
1246 * MSF : input. 多扇区
1247 * Format : input. 数据格式化模式
1248 * StartingNumber : input. 起始扇区
1249 * Buffer : input. 缓冲区。存放命令执行的结果
1250 * BufferLen : input. 缓冲区大小
1251 *
1252 * Return value:
1253 * 返回命令的执行情况
1254 *
1255 * note:
1256 *
1257 *
1258 *******************************************************************************
1259 */
ScsiCDReadToc(__mscLun_t * mscLun,unsigned int MSF,unsigned int Format,unsigned int StartingNumber,void * Buffer,unsigned int BufferLen)1260 int ScsiCDReadToc(__mscLun_t *mscLun,
1261 unsigned int MSF,
1262 unsigned int Format,
1263 unsigned int StartingNumber,
1264 void *Buffer,
1265 unsigned int BufferLen)
1266 {
1267 __ScsiCmnd_t ScsiCmnd;
1268 unsigned char CB[MAX_CDB];
1269
1270 if (mscLun == NULL)
1271 {
1272 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1273 return USB_STATUS_BAD_ARGUMENTS;
1274 }
1275
1276 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1277 memset(CB, 0, MAX_CDB);
1278 /* create command block */
1279 CB[0] = SCSI_CD_READ_TOC; /* scsi command */
1280 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1281 CB[1] = CB[1] | ((MSF ? 0 : 1) << 1); /* is Msf? */
1282 CB[2] = CB[2] | (Format & 0x07); /* Read TOC Data Format */
1283 CB[6] = StartingNumber; /* Starting Track/Session Number */
1284 put_be16(&CB[7], BufferLen); /* TRANSFER LENGTH */
1285 /* initialize transport command */
1286 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1287 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1288 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1289 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1290 ScsiCmnd.cmnd.CommandBlock = CB;
1291 /* initialize scsi_cnmd */
1292 ScsiCmnd.sc_lun = mscLun;
1293 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1294 ScsiCmnd.DataTransferLength = BufferLen;
1295 ScsiCmnd.buffer = Buffer;
1296 ScsiCmnd.Done = ScsiCmndDone;
1297 return ScsiDoCommand(mscLun, &ScsiCmnd);
1298 }
1299
1300 /*
1301 *******************************************************************************
1302 * ScsiCDStopPlayScan
1303 *
1304 * Description:
1305 * 中止扫描或是播放
1306 *
1307 * Parameters:
1308 * mscLun : input. Logic unit
1309 *
1310 * Return value:
1311 * 返回命令的执行情况
1312 *
1313 * note:
1314 *
1315 *
1316 *******************************************************************************
1317 */
ScsiCDStopPlayScan(__mscLun_t * mscLun)1318 int ScsiCDStopPlayScan(__mscLun_t *mscLun)
1319 {
1320 __ScsiCmnd_t ScsiCmnd;
1321 unsigned char CB[MAX_CDB];
1322
1323 if (mscLun == NULL)
1324 {
1325 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1326 return USB_STATUS_BAD_ARGUMENTS;
1327 }
1328
1329 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1330 memset(CB, 0, MAX_CDB);
1331 /* create command block */
1332 CB[0] = SCSI_CD_STOP_PLAY_SCAN; /* scsi command */
1333 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1334 /* initialize transport command */
1335 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1336 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1337 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1338 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1339 ScsiCmnd.cmnd.CommandBlock = CB;
1340 /* initialize scsi_cnmd */
1341 ScsiCmnd.sc_lun = mscLun;
1342 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1343 ScsiCmnd.DataTransferLength = 0;
1344 ScsiCmnd.buffer = NULL;
1345 ScsiCmnd.Done = ScsiCmndDone;
1346 return ScsiDoCommand(mscLun, &ScsiCmnd);
1347 }
1348
1349 /*
1350 *******************************************************************************
1351 * ScsiCDReadDiskInfo
1352 *
1353 * Description:
1354 * 读取光碟的信息
1355 *
1356 * Parameters:
1357 * mscLun : input. Logic unit
1358 * Buffer : input. 缓冲区。存放disk的信息
1359 * BufferLen : input. 本次打算获得数据的长度
1360 *
1361 * Return value:
1362 * 返回命令的执行情况
1363 *
1364 * note:
1365 *
1366 *
1367 *******************************************************************************
1368 */
ScsiCDReadDiscInfo(__mscLun_t * mscLun,unsigned int DataType,void * Buffer,unsigned int BufferLen,unsigned int * ActLen)1369 int ScsiCDReadDiscInfo(__mscLun_t *mscLun,
1370 unsigned int DataType,
1371 void *Buffer,
1372 unsigned int BufferLen,
1373 unsigned int *ActLen)
1374 {
1375 __ScsiCmnd_t ScsiCmnd;
1376 unsigned char CB[MAX_CDB];
1377 int ret = 0;
1378
1379 if (mscLun == NULL)
1380 {
1381 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1382 return USB_STATUS_BAD_ARGUMENTS;
1383 }
1384
1385 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1386 memset(CB, 0, MAX_CDB);
1387 /* create command block */
1388 CB[0] = SCSI_DVD_READ_DISC_INFORMATION; /* scsi command */
1389 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1390 CB[1] = CB[1] | (DataType & 0x07);
1391 put_be16(&CB[7], BufferLen); /* TRANSFER LENGTH */
1392 /* initialize transport command */
1393 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1394 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1395 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1396 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1397 ScsiCmnd.cmnd.CommandBlock = CB;
1398 /* initialize scsi_cnmd */
1399 ScsiCmnd.sc_lun = mscLun;
1400 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1401 ScsiCmnd.DataTransferLength = BufferLen;
1402 ScsiCmnd.buffer = Buffer;
1403 ScsiCmnd.Done = ScsiCmndDone;
1404 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
1405
1406 if (ret == USB_ERR_SUCCESS)
1407 {
1408 *ActLen = ScsiCmnd.ActualLength;
1409 }
1410 else
1411 {
1412 *ActLen = 0;
1413 }
1414
1415 return ret;
1416 }
1417
1418 /*
1419 *******************************************************************************
1420 * ScsiCDReadTrackInfo
1421 *
1422 * Description:
1423 * 读取光碟轨道的信息
1424 *
1425 * Parameters:
1426 * mscLun : input. Logic unit
1427 * Open : input.
1428 * Address_or_Number : input.
1429 * LogicalBlockAddress: input.
1430 * Buffer : input. 缓冲区。存放disk的信息
1431 * BufferLen : input. 本次打算获得数据的长度
1432 * ActLen : input. 实际取得的长度
1433 *
1434 * Return value:
1435 * 返回命令的执行情况
1436 *
1437 * note:
1438 *
1439 *
1440 *******************************************************************************
1441 */
ScsiCDReadTrackInfo(__mscLun_t * mscLun,unsigned int Open,unsigned int Address_or_Number,unsigned int LogicalBlockAddress,void * Buffer,unsigned int BufferLen,unsigned int * ActLen)1442 int ScsiCDReadTrackInfo(__mscLun_t *mscLun,
1443 unsigned int Open,
1444 unsigned int Address_or_Number,
1445 unsigned int LogicalBlockAddress,
1446 void *Buffer,
1447 unsigned int BufferLen,
1448 unsigned int *ActLen)
1449 {
1450 __ScsiCmnd_t ScsiCmnd;
1451 unsigned char CB[MAX_CDB];
1452 int ret = 0;
1453
1454 if (mscLun == NULL)
1455 {
1456 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1457 return USB_STATUS_BAD_ARGUMENTS;
1458 }
1459
1460 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1461 memset(CB, 0, MAX_CDB);
1462 /* create command block */
1463 CB[0] = SCSI_DVD_READ_TRACK_INFORMATION; /* scsi command */
1464 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1465 CB[1] = CB[1] | (Open ? 1 : 0);
1466 CB[1] = CB[1] | (Address_or_Number & 0x03);
1467 put_be16(&CB[7], BufferLen); /* TRANSFER LENGTH */
1468 /* initialize transport command */
1469 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1470 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1471 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1472 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1473 ScsiCmnd.cmnd.CommandBlock = CB;
1474 /* initialize scsi_cnmd */
1475 ScsiCmnd.sc_lun = mscLun;
1476 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1477 ScsiCmnd.DataTransferLength = BufferLen;
1478 ScsiCmnd.buffer = Buffer;
1479 ScsiCmnd.Done = ScsiCmndDone;
1480 ret = ScsiDoCommand(mscLun, &ScsiCmnd);
1481
1482 if (ret == USB_ERR_SUCCESS)
1483 {
1484 *ActLen = ScsiCmnd.ActualLength;
1485 }
1486 else
1487 {
1488 *ActLen = 0;
1489 }
1490
1491 return ret;
1492 }
1493
1494 /*
1495 *******************************************************************************
1496 * ScsiDvdGetEventStatus
1497 *
1498 * Description:
1499 * 获得DVD的事件状态。
1500 *
1501 * Parameters:
1502 * mscLun : input. Logic unit
1503 * Immed : input. 是否立即返回命令的执行结果
1504 * ClassRequest : input. 类请求
1505 * Buffer : input. 存放DVD的事件结果
1506 * BufferLen : input. 本次打算获得数据的长度
1507 *
1508 * Return value:
1509 * 返回命令的执行情况
1510 *
1511 * note:
1512 *
1513 *
1514 *******************************************************************************
1515 */
ScsiDvdGetEventStatus(__mscLun_t * mscLun,unsigned int Immed,unsigned int ClassRequest,void * Buffer,unsigned int BufferLen)1516 int ScsiDvdGetEventStatus(__mscLun_t *mscLun,
1517 unsigned int Immed,
1518 unsigned int ClassRequest,
1519 void *Buffer,
1520 unsigned int BufferLen)
1521 {
1522 __ScsiCmnd_t ScsiCmnd;
1523 unsigned char CB[MAX_CDB];
1524
1525 if (mscLun == NULL)
1526 {
1527 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1528 return USB_STATUS_BAD_ARGUMENTS;
1529 }
1530
1531 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1532 memset(CB, 0, MAX_CDB);
1533 /* create command block */
1534 CB[0] = SCSI_DVD_GET_EVENT_STATUS_NOTIFICATION; /* scsi command */
1535 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1536 CB[1] = CB[1] | (Immed ? 1 : 0);
1537 CB[4] = ClassRequest; /* Notification Class Request */
1538 put_be16(&CB[7], BufferLen); /* TRANSFER LENGTH */
1539 /* initialize transport command */
1540 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1541 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1542 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1543 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1544 ScsiCmnd.cmnd.CommandBlock = CB;
1545 /* initialize scsi_cnmd */
1546 ScsiCmnd.sc_lun = mscLun;
1547 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1548 ScsiCmnd.DataTransferLength = BufferLen;
1549 ScsiCmnd.buffer = Buffer;
1550 ScsiCmnd.Done = ScsiCmndDone;
1551 return ScsiDoCommand(mscLun, &ScsiCmnd);
1552 }
1553
1554 /*
1555 *******************************************************************************
1556 * ScsiDvdGetEventStatus
1557 *
1558 * Description:
1559 * 装载或是卸载光碟
1560 *
1561 * Parameters:
1562 * mscLun : input. Logic unit
1563 * Immed : input. 是否立即返回命令的执行结果
1564 * Start : input. media就绪或者停止
1565 * LoUnlo : input. 装载或是卸载
1566 * Slot : input.
1567 *
1568 * Return value:
1569 * 返回命令的执行情况
1570 *
1571 * note:
1572 *
1573 *
1574 *******************************************************************************
1575 */
ScsiDvdLoad(__mscLun_t * mscLun,unsigned int Immed,unsigned int Start,unsigned int LoUnlo,unsigned int Slot)1576 int ScsiDvdLoad(__mscLun_t *mscLun,
1577 unsigned int Immed,
1578 unsigned int Start,
1579 unsigned int LoUnlo,
1580 unsigned int Slot)
1581 {
1582 __ScsiCmnd_t ScsiCmnd;
1583 unsigned char CB[MAX_CDB];
1584
1585 if (mscLun == NULL)
1586 {
1587 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1588 return USB_STATUS_BAD_ARGUMENTS;
1589 }
1590
1591 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1592 memset(CB, 0, MAX_CDB);
1593 /* create command block */
1594 CB[0] = SCSI_DVD_LOAD_UNLOAD; /* scsi command */
1595 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1596 CB[1] = CB[1] | (Immed ? 1 : 0);
1597 CB[4] = CB[4] | (Start ? 1 : 0);
1598 CB[4] = CB[4] | ((LoUnlo ? 1 : 0) << 1);
1599 CB[8] = Slot;
1600 /* initialize transport command */
1601 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1602 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1603 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1604 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1605 ScsiCmnd.cmnd.CommandBlock = CB;
1606 /* initialize scsi_cnmd */
1607 ScsiCmnd.sc_lun = mscLun;
1608 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1609 ScsiCmnd.DataTransferLength = 0;
1610 ScsiCmnd.buffer = NULL;
1611 ScsiCmnd.Done = ScsiCmndDone;
1612 return ScsiDoCommand(mscLun, &ScsiCmnd);
1613 }
1614
1615 /*
1616 *******************************************************************************
1617 * ScsiSetSpeed
1618 *
1619 * Description:
1620 * 设置光驱的读写速度
1621 *
1622 * Parameters:
1623 * mscLun : input. Logic unit
1624 * ReadSpeed : input. 读速度. Kbytes/second
1625 * WriteSpeed : input. 写速度. Kbytes/second
1626 *
1627 * Return value:
1628 * 返回命令的执行情况
1629 *
1630 * note:
1631 *
1632 *
1633 *******************************************************************************
1634 */
ScsiCDSetSpeed(__mscLun_t * mscLun,unsigned int ReadSpeed,unsigned int WriteSpeed)1635 int ScsiCDSetSpeed(__mscLun_t *mscLun, unsigned int ReadSpeed, unsigned int WriteSpeed)
1636 {
1637 __ScsiCmnd_t ScsiCmnd;
1638 unsigned char CB[MAX_CDB];
1639
1640 if (mscLun == NULL)
1641 {
1642 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1643 return USB_STATUS_BAD_ARGUMENTS;
1644 }
1645
1646 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1647 memset(CB, 0, MAX_CDB);
1648 /* create command block */
1649 CB[0] = SCSI_CD_SET_SPEED; /* scsi command */
1650 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1651 put_be16(&CB[2], ReadSpeed);
1652 put_be16(&CB[4], WriteSpeed);
1653 /* initialize transport command */
1654 ScsiCmnd.cmnd.data_direction = DATA_NONE;
1655 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1656 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1657 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1658 ScsiCmnd.cmnd.CommandBlock = CB;
1659 /* initialize scsi_cnmd */
1660 ScsiCmnd.sc_lun = mscLun;
1661 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1662 ScsiCmnd.DataTransferLength = 0;
1663 ScsiCmnd.buffer = NULL;
1664 ScsiCmnd.Done = ScsiCmndDone;
1665 return ScsiDoCommand(mscLun, &ScsiCmnd);
1666 }
1667
1668 /*
1669 *******************************************************************************
1670 * ScsiGetConfiguration
1671 *
1672 * Description:
1673 * 设置光驱的读写速度
1674 *
1675 * Parameters:
1676 * mscLun : input. Logic unit
1677 * ReadSpeed : input. 读速度. Kbytes/second
1678 * WriteSpeed : input. 写速度. Kbytes/second
1679 *
1680 * Return value:
1681 * 返回命令的执行情况
1682 *
1683 * note:
1684 *
1685 *
1686 *******************************************************************************
1687 */
ScsiDVDGetConfiguration(__mscLun_t * mscLun,unsigned int RT,unsigned int StartingFeatureNumber,void * Buffer,unsigned int BufferLen)1688 int ScsiDVDGetConfiguration(__mscLun_t *mscLun,
1689 unsigned int RT,
1690 unsigned int StartingFeatureNumber,
1691 void *Buffer,
1692 unsigned int BufferLen)
1693 {
1694 __ScsiCmnd_t ScsiCmnd;
1695 unsigned char CB[MAX_CDB];
1696
1697 if (mscLun == NULL)
1698 {
1699 hal_log_err("ERR: ScsiInquery: input error, mscLun = %x", mscLun);
1700 return USB_STATUS_BAD_ARGUMENTS;
1701 }
1702
1703 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
1704 memset(CB, 0, MAX_CDB);
1705 /* create command block */
1706 CB[0] = SCSI_DVD_GET_EVENT_STATUS_NOTIFICATION; /* scsi command */
1707 CB[1] = CB[1] | ((mscLun->LunNo & 0x7) << 5); /* lun */
1708 CB[1] = CB[1] | (RT & 0x03); /* Request type */
1709 put_be16(&CB[2], StartingFeatureNumber); /* Starting Feature Number */
1710 put_be16(&CB[7], BufferLen); /* TRANSFER LENGTH */
1711 /* initialize transport command */
1712 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
1713 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
1714 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
1715 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_10 : ATAPI_CDB;
1716 ScsiCmnd.cmnd.CommandBlock = CB;
1717 /* initialize scsi_cnmd */
1718 ScsiCmnd.sc_lun = mscLun;
1719 ScsiCmnd.allowed = SCSI_CMD_RETRY;
1720 ScsiCmnd.DataTransferLength = BufferLen;
1721 ScsiCmnd.buffer = Buffer;
1722 ScsiCmnd.Done = ScsiCmndDone;
1723 return ScsiDoCommand(mscLun, &ScsiCmnd);
1724 }
1725
1726
1727
1728