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