]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
1. Add NULL QH to set as QH header;
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMassStorage / Dxe / UsbMassStorageHelper.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UsbMassStorageHelper.c
15
16 Abstract:
17
18 Helper functions for USB Mass Storage Driver
19
20 Revision History
21
22 --*/
23
24 #include "UsbMassStorageHelper.h"
25
26 STATIC
27 BOOLEAN
28 IsNoMedia (
29 IN REQUEST_SENSE_DATA *SenseData,
30 IN UINTN SenseCounts
31 );
32
33 STATIC
34 BOOLEAN
35 IsMediaError (
36 IN REQUEST_SENSE_DATA *SenseData,
37 IN UINTN SenseCounts
38 );
39
40 STATIC
41 BOOLEAN
42 IsMediaChange (
43 IN REQUEST_SENSE_DATA *SenseData,
44 IN UINTN SenseCounts
45 );
46
47 STATIC
48 BOOLEAN
49 IsDriveReady (
50 IN REQUEST_SENSE_DATA *SenseData,
51 IN UINTN SenseCounts,
52 OUT BOOLEAN *NeedRetry
53 );
54
55 STATIC
56 BOOLEAN
57 IsMediaWriteProtected (
58 IN REQUEST_SENSE_DATA *SenseData,
59 IN UINTN SenseCounts
60 );
61
62 STATIC
63 BOOLEAN
64 IsLogicalUnitCommunicationOverRun (
65 IN REQUEST_SENSE_DATA *SenseData,
66 IN UINTN SenseCounts
67 );
68
69 EFI_STATUS
70 USBFloppyPacketCommand (
71 USB_FLOPPY_DEV *UsbFloppyDevice,
72 VOID *Command,
73 UINT8 CommandSize,
74 VOID *DataBuffer,
75 UINT32 BufferLength,
76 EFI_USB_DATA_DIRECTION Direction,
77 UINT16 TimeOutInMilliSeconds
78 )
79 /*++
80
81 Routine Description:
82 Sends Packet Command to USB Floppy Drive.
83
84 Arguments:
85 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
86 Command - A pointer to the command packet.
87 CommandSize - Indicates the size of the command packet.
88 DataBuffer - A pointer to the buffer for the data transfer
89 after the command packet.
90 BufferLength - Indicates the size of the Data Buffer.
91 Direction - Transfer Direction
92 TimeOutInMilliSeconds - Timeout Value
93 Returns:
94 EFI_SUCCESS - Success
95 --*/
96 {
97 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
98 EFI_STATUS Status;
99
100 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
101 //
102 // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
103 // to perform the command request.
104 //
105 Status = UsbAtapiInterface->UsbAtapiPacketCmd (
106 UsbAtapiInterface,
107 Command,
108 CommandSize,
109 DataBuffer,
110 BufferLength,
111 Direction,
112 TimeOutInMilliSeconds
113 );
114
115 return Status;
116 }
117
118 EFI_STATUS
119 USBFloppyIdentify (
120 IN USB_FLOPPY_DEV *UsbFloppyDevice
121 )
122 /*++
123
124 Routine Description:
125 Retrieves device information to tell the device type.
126
127 Arguments:
128 UsbFloppyDevice The USB_FLOPPY_DEV instance.
129
130 Returns:
131 EFI_DEVICE_ERROR - Hardware error
132 EFI_SUCCESS - Success
133 --*/
134 {
135
136 EFI_STATUS Status;
137 USB_INQUIRY_DATA *Idata;
138 BOOLEAN MediaChange;
139
140 //
141 // Send Inquiry Packet Command to get INQUIRY data.
142 //
143 Status = USBFloppyInquiry (UsbFloppyDevice, &Idata);
144 if (EFI_ERROR (Status)) {
145 return EFI_DEVICE_ERROR;
146 }
147
148 //
149 // Get media removable info from INQUIRY data.
150 //
151 UsbFloppyDevice->BlkIo.Media->RemovableMedia = (UINT8) ((Idata->RMB & 0x80) == 0x80);
152
153 //
154 // Identify device type via INQUIRY data.
155 //
156 switch ((Idata->peripheral_type) & 0x1f) {
157 //
158 // Floppy
159 //
160 case 0x00:
161 UsbFloppyDevice->DeviceType = USBFLOPPY;
162 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
163 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
164 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
165 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
166 break;
167
168 //
169 // CD-ROM
170 //
171 case 0x05:
172 UsbFloppyDevice->DeviceType = USBCDROM;
173 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
174 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
175 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
176 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
177 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
178 break;
179
180 default:
181 gBS->FreePool (Idata);
182 return EFI_DEVICE_ERROR;
183 };
184
185 //
186 // Initialize some device specific data.
187 //
188 //
189 // original sense data numbers
190 //
191 UsbFloppyDevice->SenseDataNumber = 6;
192
193 if (UsbFloppyDevice->SenseData != NULL) {
194 gBS->FreePool (UsbFloppyDevice->SenseData);
195 UsbFloppyDevice->SenseData = NULL;
196 }
197
198 UsbFloppyDevice->SenseData = AllocatePool (UsbFloppyDevice->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
199
200 if (UsbFloppyDevice->SenseData == NULL) {
201 gBS->FreePool (Idata);
202 return EFI_DEVICE_ERROR;
203 }
204
205 //
206 // Get media information.
207 //
208 UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
209
210 gBS->FreePool (Idata);
211
212 return EFI_SUCCESS;
213 }
214
215 EFI_STATUS
216 USBFloppyInquiry (
217 IN USB_FLOPPY_DEV *UsbFloppyDevice,
218 OUT USB_INQUIRY_DATA **Idata
219 )
220 /*++
221
222 Routine Description:
223 Send Inquiry Packet Command to device and retrieve Inquiry Data.
224
225 Arguments:
226 UsbFloppyDevice The USB_FLOPPY_DEV instance.
227 Idata A pointer pointing to the address of
228 Inquiry Data.
229
230 Returns:
231 EFI_DEVICE_ERROR - Hardware error
232 EFI_SUCCESS - Success
233 --*/
234 {
235 ATAPI_PACKET_COMMAND Packet;
236 EFI_STATUS Status;
237 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
238
239 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
240
241 //
242 // prepare command packet for the Inquiry Packet Command.
243 //
244 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
245 Packet.Inquiry.opcode = INQUIRY;
246 Packet.Inquiry.page_code = 0;
247 Packet.Inquiry.allocation_length = sizeof (USB_INQUIRY_DATA);
248
249 *Idata = AllocateZeroPool (sizeof (USB_INQUIRY_DATA));
250 if (*Idata == NULL) {
251 return EFI_DEVICE_ERROR;
252 }
253 //
254 // Send command packet and retrieve requested Inquiry Data.
255 //
256 Status = USBFloppyPacketCommand (
257 UsbFloppyDevice,
258 &Packet,
259 sizeof (ATAPI_PACKET_COMMAND),
260 (VOID *) (*Idata),
261 sizeof (USB_INQUIRY_DATA),
262 EfiUsbDataIn,
263 USBFLPTIMEOUT * 3
264 );
265 if (EFI_ERROR (Status)) {
266 gBS->FreePool (*Idata);
267 return EFI_DEVICE_ERROR;
268 }
269
270 return EFI_SUCCESS;
271 }
272
273 EFI_STATUS
274 USBFloppyRead10 (
275 IN USB_FLOPPY_DEV *UsbFloppyDevice,
276 IN VOID *Buffer,
277 IN EFI_LBA Lba,
278 IN UINTN NumberOfBlocks
279 )
280 /*++
281
282 Routine Description:
283 Sends Read10 Packet Command to device to perform data transfer
284 from device to host.
285
286 Arguments:
287 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
288 Buffer - A pointer to the destination buffer for the data.
289 The caller is responsible for either having implicit
290 or explicit ownership of the buffer.
291 Lba - The starting logical block address to read from
292 on the device.
293 NumberOfBlocks - Indicates the number of blocks that the read
294 operation requests.
295
296 Returns:
297 EFI_DEVICE_ERROR - Hardware error
298 EFI_SUCCESS - Success
299 --*/
300 {
301 ATAPI_PACKET_COMMAND Packet;
302 READ10_CMD *Read10Packet;
303 UINT16 MaxBlock;
304 UINT16 BlocksRemaining;
305 UINT16 SectorCount;
306 UINT32 Lba32;
307 UINT32 BlockSize;
308 UINT32 ByteCount;
309 VOID *ptrBuffer;
310 EFI_STATUS Status;
311 UINT16 TimeOut;
312 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
313 UINT8 Index;
314
315 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
316
317 //
318 // prepare command packet for the Inquiry Packet Command.
319 //
320 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
321 Read10Packet = &Packet.Read10;
322 Lba32 = (UINT32) Lba;
323 ptrBuffer = Buffer;
324 BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
325
326 MaxBlock = (UINT16) (65536 / BlockSize);
327 BlocksRemaining = (UINT16) NumberOfBlocks;
328
329 Status = EFI_SUCCESS;
330 while (BlocksRemaining > 0) {
331 if (BlocksRemaining <= MaxBlock) {
332 SectorCount = BlocksRemaining;
333 } else {
334 SectorCount = MaxBlock;
335 }
336
337 for (Index = 0; Index < 3; Index ++) {
338
339 //
340 // fill the Packet data structure
341 //
342 Read10Packet->opcode = READ_10;
343 //
344 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
345 // Lba0 is MSB, Lba3 is LSB
346 //
347 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
348 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
349 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
350 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
351
352 //
353 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
354 // TranLen0 is MSB, TranLen is LSB
355 //
356 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
357 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
358
359 ByteCount = SectorCount * BlockSize;
360
361 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
362
363
364 Status = USBFloppyPacketCommand (
365 UsbFloppyDevice,
366 &Packet,
367 sizeof (ATAPI_PACKET_COMMAND),
368 (VOID *) ptrBuffer,
369 ByteCount,
370 EfiUsbDataIn,
371 TimeOut
372 );
373 if (!EFI_ERROR (Status)) {
374 break;
375 }
376 }
377
378 if (Index == 3) {
379 return EFI_DEVICE_ERROR;
380 }
381
382 Lba32 += SectorCount;
383 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
384 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
385 }
386
387 return Status;
388 }
389
390 EFI_STATUS
391 USBFloppyReadCapacity (
392 IN USB_FLOPPY_DEV *UsbFloppyDevice
393 )
394 /*++
395
396 Routine Description:
397 Retrieves media capacity information via
398 sending Read Capacity Packet Command.
399
400 Arguments:
401 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
402
403 Returns:
404 EFI_DEVICE_ERROR - Hardware error
405 EFI_SUCCESS - Success
406 --*/
407 {
408 //
409 // status returned by Read Capacity Packet Command
410 //
411 EFI_STATUS Status;
412 ATAPI_PACKET_COMMAND Packet;
413 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
414
415 //
416 // used for capacity data returned from Usb Floppy
417 //
418 READ_CAPACITY_DATA Data;
419
420 ZeroMem (&Data, sizeof (Data));
421
422 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
423
424 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
425 Packet.Inquiry.opcode = READ_CAPACITY;
426 Status = USBFloppyPacketCommand (
427 UsbFloppyDevice,
428 &Packet,
429 sizeof (ATAPI_PACKET_COMMAND),
430 (VOID *) &Data,
431 sizeof (READ_CAPACITY_DATA),
432 EfiUsbDataIn,
433 USBFLPTIMEOUT
434 );
435
436 if (EFI_ERROR (Status)) {
437 return EFI_DEVICE_ERROR;
438 }
439
440 UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
441 (Data.LastLba2 << 16) |
442 (Data.LastLba1 << 8) |
443 Data.LastLba0;
444
445 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
446
447 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
448
449 return EFI_SUCCESS;
450
451 }
452
453 EFI_STATUS
454 USBFloppyReadFormatCapacity (
455 IN USB_FLOPPY_DEV *UsbFloppyDevice
456 )
457 /*++
458
459 Routine Description:
460 Retrieves media capacity information via sending Read Format
461 Capacity Packet Command.
462
463 Arguments:
464 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
465
466 Returns:
467 EFI_DEVICE_ERROR - Hardware error
468 EFI_SUCCESS - Success
469 --*/
470 {
471 //
472 // status returned by Read Capacity Packet Command
473 //
474 EFI_STATUS Status;
475 ATAPI_PACKET_COMMAND Packet;
476 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
477
478 //
479 // used for capacity data returned from Usb Floppy
480 //
481 READ_FORMAT_CAPACITY_DATA FormatData;
482
483 ZeroMem (&FormatData, sizeof (FormatData));
484
485 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
486
487 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
488 Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
489 Packet.ReadFormatCapacity.allocation_length_lo = 12;
490 Status = USBFloppyPacketCommand (
491 UsbFloppyDevice,
492 &Packet,
493 sizeof (ATAPI_PACKET_COMMAND),
494 (VOID *) &FormatData,
495 sizeof (READ_FORMAT_CAPACITY_DATA),
496 EfiUsbDataIn,
497 USBFLPTIMEOUT
498 );
499
500 if (EFI_ERROR (Status)) {
501 return EFI_DEVICE_ERROR;
502 }
503
504 if (FormatData.DesCode == 3) {
505 //
506 // Media is not present
507 //
508 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
509 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
510 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
511 } else {
512
513 UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
514 (FormatData.LastLba2 << 16) |
515 (FormatData.LastLba1 << 8) |
516 FormatData.LastLba0;
517
518 UsbFloppyDevice->BlkIo.Media->LastBlock--;
519
520 UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
521 (FormatData.BlockSize1 << 8) |
522 FormatData.BlockSize0;
523
524 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
525
526 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
527
528 }
529
530 return EFI_SUCCESS;
531
532 }
533
534 EFI_STATUS
535 UsbFloppyRequestSense (
536 IN USB_FLOPPY_DEV *UsbFloppyDevice,
537 OUT UINTN *SenseCounts
538 )
539 /*++
540
541 Routine Description:
542 Retrieves Sense Data from device via
543 sending Request Sense Packet Command.
544
545 Arguments:
546 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
547 SenseCounts - A pointer to the number of Sense Data returned.
548
549 Returns:
550 EFI_DEVICE_ERROR - Hardware error
551 EFI_SUCCESS - Success
552 --*/
553 {
554 EFI_STATUS Status;
555 REQUEST_SENSE_DATA *Sense;
556 UINT8 *Ptr;
557 BOOLEAN SenseReq;
558 ATAPI_PACKET_COMMAND Packet;
559 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
560
561 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
562
563 *SenseCounts = 0;
564
565 ZeroMem (
566 UsbFloppyDevice->SenseData,
567 sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber)
568 );
569 //
570 // fill command packet for Request Sense Packet Command
571 //
572 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
573 Packet.RequestSense.opcode = REQUEST_SENSE;
574 Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA);
575
576 //
577 // initialize pointer
578 //
579 Ptr = (UINT8 *) (UsbFloppyDevice->SenseData);
580
581 //
582 // request sense data from device continuously
583 // until no sense data exists in the device.
584 //
585 for (SenseReq = TRUE; SenseReq;) {
586
587 Sense = (REQUEST_SENSE_DATA *) Ptr;
588
589 //
590 // send out Request Sense Packet Command and get one Sense
591 // data from device.
592 //
593 Status = USBFloppyPacketCommand (
594 UsbFloppyDevice,
595 &Packet,
596 sizeof (ATAPI_PACKET_COMMAND),
597 (VOID *) Ptr,
598 sizeof (REQUEST_SENSE_DATA),
599 EfiUsbDataIn,
600 USBFLPTIMEOUT
601 );
602 //
603 // failed to get Sense data
604 //
605 if (EFI_ERROR (Status)) {
606 //
607 // Recovery the device back to normal state.
608 //
609 UsbFloppyDevice->AtapiProtocol->UsbAtapiReset (
610 UsbFloppyDevice->AtapiProtocol,
611 TRUE
612 );
613
614 if (*SenseCounts == 0) {
615 //
616 // never retrieved any sense data from device,
617 // just return error.
618 //
619 return EFI_DEVICE_ERROR;
620 } else {
621 //
622 // has retrieved some sense data from device,
623 // so return success.
624 //
625 return EFI_SUCCESS;
626 }
627 }
628
629 if (Sense->sense_key != SK_NO_SENSE) {
630 //
631 // Ptr is byte based pointer
632 //
633 Ptr += sizeof (REQUEST_SENSE_DATA);
634
635 (*SenseCounts)++;
636
637 } else {
638 //
639 // when no sense key, skip out the loop
640 //
641 SenseReq = FALSE;
642 }
643
644 //
645 // If the sense key numbers exceed Sense Data Buffer size,
646 // just skip the loop and do not fetch the sense key in this function.
647 //
648 if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) {
649 SenseReq = FALSE;
650 }
651 }
652
653 return EFI_SUCCESS;
654 }
655
656 EFI_STATUS
657 UsbFloppyTestUnitReady (
658 IN USB_FLOPPY_DEV *UsbFloppyDevice
659 )
660 /*++
661
662 Routine Description:
663 Sends Test Unit ReadyPacket Command to the device.
664
665 Arguments:
666 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
667
668 Returns:
669 EFI_DEVICE_ERROR - Hardware error
670 EFI_SUCCESS - Success
671 --*/
672 {
673 ATAPI_PACKET_COMMAND Packet;
674 EFI_STATUS Status;
675 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
676 UINT32 RetryIndex;
677 UINT32 MaximumRetryTimes;
678
679 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
680 MaximumRetryTimes = 2;
681 //
682 // fill command packet
683 //
684 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
685 Packet.TestUnitReady.opcode = TEST_UNIT_READY;
686
687 //
688 // send command packet
689 //
690 Status = EFI_DEVICE_ERROR;
691
692 for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) {
693
694 Status = USBFloppyPacketCommand (
695 UsbFloppyDevice,
696 &Packet,
697 sizeof (ATAPI_PACKET_COMMAND),
698 NULL,
699 0,
700 EfiUsbNoData,
701 USBFLPTIMEOUT
702 );
703
704 if (EFI_ERROR (Status)) {
705 gBS->Stall (100 * STALL_1_MILLI_SECOND);
706 }
707 }
708
709 return Status;
710 }
711
712 EFI_STATUS
713 USBFloppyWrite10 (
714 IN USB_FLOPPY_DEV *UsbFloppyDevice,
715 IN VOID *Buffer,
716 IN EFI_LBA Lba,
717 IN UINTN NumberOfBlocks
718 )
719 /*++
720
721 Routine Description:
722 Sends Write10 Packet Command to device to perform data transfer
723 from host to device.
724
725 Arguments:
726 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
727 Buffer - A pointer to the source buffer for the data.
728 The caller is responsible for either having implicit
729 or explicit ownership of the buffer.
730 Lba - The starting logical block address to written to
731 the device.
732 NumberOfBlocks - Indicates the number of blocks that the write
733 operation requests.
734
735 Returns:
736 EFI_DEVICE_ERROR - Hardware error
737 EFI_SUCCESS - Success
738 --*/
739 {
740 ATAPI_PACKET_COMMAND Packet;
741 READ10_CMD *Write10Packet;
742 UINT16 MaxBlock;
743 UINT16 BlocksRemaining;
744 UINT16 SectorCount;
745 UINT32 Lba32;
746 UINT32 BlockSize;
747 UINT32 ByteCount;
748 VOID *ptrBuffer;
749 EFI_STATUS Status;
750 UINT16 TimeOut;
751 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
752 UINT8 Index;
753
754 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
755
756 //
757 // prepare command packet for the Write10 Packet Command.
758 //
759 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
760 Write10Packet = &Packet.Read10;
761 Lba32 = (UINT32) Lba;
762 ptrBuffer = Buffer;
763 BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
764
765 MaxBlock = (UINT16) (65536 / BlockSize);
766 BlocksRemaining = (UINT16) NumberOfBlocks;
767
768 Status = EFI_SUCCESS;
769 while (BlocksRemaining > 0) {
770
771 if (BlocksRemaining <= MaxBlock) {
772 SectorCount = BlocksRemaining;
773 } else {
774 SectorCount = MaxBlock;
775 }
776
777 for (Index = 0; Index < 3; Index ++) {
778 //
779 // fill the Packet data structure
780 //
781 Write10Packet->opcode = WRITE_10;
782
783 //
784 // Lba0 ~ Lba3 specify the start logical block address
785 // of the data transfer.
786 // Lba0 is MSB, Lba3 is LSB
787 //
788 Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
789 Write10Packet->Lba2 = (UINT8) (Lba32 >> 8);
790 Write10Packet->Lba1 = (UINT8) (Lba32 >> 16);
791 Write10Packet->Lba0 = (UINT8) (Lba32 >> 24);
792
793 //
794 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
795 // TranLen0 is MSB, TranLen is LSB
796 //
797 Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
798 Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
799
800 ByteCount = SectorCount * BlockSize;
801
802 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
803
804 Status = USBFloppyPacketCommand (
805 UsbFloppyDevice,
806 &Packet,
807 sizeof (ATAPI_PACKET_COMMAND),
808 (VOID *) ptrBuffer,
809 ByteCount,
810 EfiUsbDataOut,
811 TimeOut
812 );
813 if (!EFI_ERROR (Status)) {
814 break;
815 }
816 }
817
818 if (Index == 3) {
819 return EFI_DEVICE_ERROR;
820 }
821
822 Lba32 += SectorCount;
823 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
824 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
825 }
826
827 return Status;
828 }
829
830 EFI_STATUS
831 UsbFloppyDetectMedia (
832 IN USB_FLOPPY_DEV *UsbFloppyDevice,
833 OUT BOOLEAN *MediaChange
834 )
835 /*++
836
837 Routine Description:
838 Retrieves media information.
839
840 Arguments:
841 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
842 MediaChange - Indicates whether media was changed.
843
844 Returns:
845 EFI_DEVICE_ERROR - Hardware error
846 EFI_SUCCESS - Success
847 EFI_INVALID_PARAMETER - Parameter is error
848 --*/
849 {
850 EFI_STATUS Status;
851 EFI_STATUS FloppyStatus;
852 //
853 // the following variables are used to record previous media information
854 //
855 EFI_BLOCK_IO_MEDIA OldMediaInfo;
856 UINTN SenseCounts;
857 UINTN RetryIndex;
858 UINTN RetryTimes;
859 UINTN MaximumRetryTimes;
860 BOOLEAN NeedRetry;
861 BOOLEAN NeedReadCapacity;
862 //
863 // a flag used to determine whether need to perform Read Capacity command.
864 //
865
866 REQUEST_SENSE_DATA *SensePtr;
867
868 //
869 // init
870 //
871 Status = EFI_SUCCESS;
872 FloppyStatus = EFI_SUCCESS;
873 CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo));
874 *MediaChange = FALSE;
875 NeedReadCapacity = TRUE;
876
877 //
878 // if there is no media present,or media not changed,
879 // the request sense command will detect faster than read capacity command.
880 // read capacity command can be bypassed, thus improve performance.
881 //
882 SenseCounts = 0;
883 Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
884
885 if (!EFI_ERROR (Status)) {
886
887 SensePtr = UsbFloppyDevice->SenseData;
888
889 //
890 // No Media
891 //
892 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
893
894 NeedReadCapacity = FALSE;
895 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
896 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
897 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
898 } else {
899 //
900 // Media Changed
901 //
902 if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) {
903 UsbFloppyDevice->BlkIo.Media->MediaId++;
904 }
905
906 //
907 // Media Write-protected
908 //
909 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
910 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
911 }
912
913 //
914 // Media Error
915 //
916 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
917 //
918 // if media error encountered, make it look like no media present.
919 //
920 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
921 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
922 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
923 }
924
925 }
926
927 }
928
929 if (NeedReadCapacity) {
930 //
931 // at most retry 5 times
932 //
933 MaximumRetryTimes = 5;
934 //
935 // initial retry twice
936 //
937 RetryTimes = 2;
938
939 for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) {
940 //
941 // Using different command to retrieve media capacity.
942 //
943 switch (UsbFloppyDevice->DeviceType) {
944
945 case USBCDROM:
946 Status = USBFloppyReadCapacity (UsbFloppyDevice);
947 break;
948
949 case USBFLOPPY2:
950 UsbMassStorageModeSense (UsbFloppyDevice);
951 Status = USBFloppyReadFormatCapacity (UsbFloppyDevice);
952 if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) {
953 //
954 // retry the ReadCapacity command
955 //
956 UsbFloppyDevice->DeviceType = USBFLOPPY;
957 Status = EFI_DEVICE_ERROR;
958 }
959 break;
960
961 case USBFLOPPY:
962 UsbMassStorageModeSense (UsbFloppyDevice);
963 Status = USBFloppyReadCapacity (UsbFloppyDevice);
964 if (EFI_ERROR (Status)) {
965 //
966 // retry the ReadFormatCapacity command
967 //
968 UsbFloppyDevice->DeviceType = USBFLOPPY2;
969 }
970 //
971 // force the BlockSize to be 0x200.
972 //
973 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
974 break;
975
976 default:
977 return EFI_INVALID_PARAMETER;
978 }
979
980 if (!EFI_ERROR (Status)) {
981 //
982 // skip the loop when read capacity succeeds.
983 //
984 break;
985 }
986
987 SenseCounts = 0;
988
989 FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
990
991 //
992 // If Request Sense data failed,retry.
993 //
994 if (EFI_ERROR (FloppyStatus)) {
995 //
996 // retry once more
997 //
998 RetryTimes++;
999 continue;
1000 }
1001 //
1002 // No Media
1003 //
1004 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
1005
1006 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
1007 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
1008 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
1009 break;
1010 }
1011
1012 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
1013 //
1014 // if media error encountered, make it look like no media present.
1015 //
1016 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
1017 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
1018 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
1019 break;
1020 }
1021
1022 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
1023 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
1024 continue;
1025 }
1026
1027 if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) {
1028
1029 //
1030 // Drive not ready: if NeedRetry, then retry once more;
1031 // else return error
1032 //
1033 if (NeedRetry) {
1034 //
1035 // Stall 0.1 second to wait for drive becoming ready
1036 //
1037 gBS->Stall (100 * STALL_1_MILLI_SECOND);
1038 //
1039 // reset retry variable to zero,
1040 // to make it retry for "drive in progress of becoming ready".
1041 //
1042 RetryIndex = 0;
1043 continue;
1044 } else {
1045 return EFI_DEVICE_ERROR;
1046 }
1047 }
1048 //
1049 // if read capacity fail not for above reasons, retry once more
1050 //
1051 RetryTimes++;
1052
1053 }
1054 //
1055 // ENDFOR
1056 //
1057
1058 //
1059 // tell whether the readcapacity process is successful or not
1060 // ("Status" variable record the latest status returned
1061 // by ReadCapacity AND "FloppyStatus" record the latest status
1062 // returned by RequestSense)
1063 //
1064 if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) {
1065 return EFI_DEVICE_ERROR;
1066 }
1067
1068 }
1069
1070 if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
1071
1072 if (UsbFloppyDevice->BlkIo.Media->MediaPresent) {
1073 UsbFloppyDevice->BlkIo.Media->MediaId = 1;
1074 }
1075
1076 *MediaChange = TRUE;
1077 }
1078
1079 if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
1080 *MediaChange = TRUE;
1081 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1082 }
1083
1084 if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
1085 *MediaChange = TRUE;
1086 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1087 }
1088
1089 if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
1090 *MediaChange = TRUE;
1091 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1092 }
1093
1094 if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
1095 *MediaChange = TRUE;
1096 }
1097
1098 return EFI_SUCCESS;
1099 }
1100
1101
1102
1103 EFI_STATUS
1104 UsbFloppyModeSense5APage5 (
1105 IN USB_FLOPPY_DEV *UsbFloppyDevice
1106 )
1107 /*++
1108
1109 Routine Description:
1110 Retrieves media capacity information via sending Read Format
1111 Capacity Packet Command.
1112
1113 Arguments:
1114 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1115
1116 Returns:
1117 EFI_DEVICE_ERROR - Hardware error
1118 EFI_SUCCESS - Success
1119
1120 --*/
1121 {
1122 //
1123 // status returned by Read Capacity Packet Command
1124 //
1125 EFI_STATUS Status;
1126 ATAPI_PACKET_COMMAND Packet;
1127 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1128 UFI_MODE_PARAMETER_PAGE_5 ModePage5;
1129 EFI_LBA LastBlock;
1130 UINT32 SectorsPerTrack;
1131 UINT32 NumberOfCylinders;
1132 UINT32 NumberOfHeads;
1133 UINT32 DataBytesPerSector;
1134
1135 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1136
1137 ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5));
1138
1139 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1140 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1141 //
1142 // Flexible Disk Page
1143 //
1144 Packet.ModeSenseUFI.page_code = 5;
1145 //
1146 // current values
1147 //
1148 Packet.ModeSenseUFI.page_control = 0;
1149 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1150 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5);
1151 Status = USBFloppyPacketCommand (
1152 UsbFloppyDevice,
1153 &Packet,
1154 sizeof (ATAPI_PACKET_COMMAND),
1155 (VOID *) &ModePage5,
1156 sizeof (UFI_MODE_PARAMETER_PAGE_5),
1157 EfiUsbDataIn,
1158 USBFLPTIMEOUT
1159 );
1160
1161 if (EFI_ERROR (Status)) {
1162 return EFI_DEVICE_ERROR;
1163 }
1164
1165 NumberOfHeads = ModePage5.flex_disk_page.number_of_heads;
1166 SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track;
1167 NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 |
1168 ModePage5.flex_disk_page.number_of_cylinders_lsb;
1169
1170 LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders;
1171 DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 |
1172 ModePage5.flex_disk_page.databytes_per_sector_lsb;
1173
1174 UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock;
1175
1176 UsbFloppyDevice->BlkIo.Media->LastBlock--;
1177
1178 UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector;
1179
1180 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
1181
1182 UsbFloppyDevice->BlkIo.Media->ReadOnly =
1183 ModePage5.mode_param_header.write_protected;
1184
1185 return EFI_SUCCESS;
1186
1187 }
1188
1189 EFI_STATUS
1190 UsbFloppyModeSense5APage1C (
1191 IN USB_FLOPPY_DEV *UsbFloppyDevice
1192 )
1193 /*++
1194
1195 Routine Description:
1196 Retrieves media capacity information via sending Read Format
1197 Capacity Packet Command.
1198
1199 Arguments:
1200 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1201
1202 Returns:
1203 EFI_DEVICE_ERROR - Hardware error
1204 EFI_SUCCESS - Success
1205
1206 --*/
1207 {
1208 //
1209 // status returned by Read Capacity Packet Command
1210 //
1211 EFI_STATUS Status;
1212 ATAPI_PACKET_COMMAND Packet;
1213 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1214 UFI_MODE_PARAMETER_PAGE_1C ModePage1C;
1215
1216 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1217
1218 ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C));
1219
1220 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1221 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1222 //
1223 // Flexible Disk Page
1224 //
1225 Packet.ModeSenseUFI.page_code = 0x1C;
1226 //
1227 // current values
1228 //
1229 Packet.ModeSenseUFI.page_control = 0;
1230 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1231 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C);
1232 Status = USBFloppyPacketCommand (
1233 UsbFloppyDevice,
1234 &Packet,
1235 sizeof (ATAPI_PACKET_COMMAND),
1236 (VOID *) &ModePage1C,
1237 sizeof (UFI_MODE_PARAMETER_PAGE_1C),
1238 EfiUsbDataIn,
1239 USBFLPTIMEOUT
1240 );
1241
1242 if (EFI_ERROR (Status)) {
1243 return EFI_DEVICE_ERROR;
1244 }
1245
1246 UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected;
1247
1248 return EFI_SUCCESS;
1249
1250 }
1251
1252 EFI_STATUS
1253 UsbMassStorageModeSense (
1254 IN USB_FLOPPY_DEV *UsbFloppyDevice
1255 )
1256 {
1257 if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) {
1258 return UsbSCSIModeSense1APage3F (UsbFloppyDevice);
1259 } else {
1260 return UsbFloppyModeSense5APage3F (UsbFloppyDevice);
1261 }
1262 }
1263
1264 EFI_STATUS
1265 UsbFloppyModeSense5APage3F (
1266 IN USB_FLOPPY_DEV *UsbFloppyDevice
1267 )
1268 /*++
1269
1270 Routine Description:
1271 Retrieves mode sense information via sending Mode Sense
1272 Packet Command.
1273
1274 Arguments:
1275 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1276
1277 Returns:
1278 EFI_DEVICE_ERROR - Hardware error
1279 EFI_SUCCESS - Success
1280
1281 --*/
1282 {
1283 //
1284 // status returned by Read Capacity Packet Command
1285 //
1286 EFI_STATUS Status;
1287 ATAPI_PACKET_COMMAND Packet;
1288 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1289 UFI_MODE_PARAMETER_HEADER Header;
1290 UINT32 Size;
1291
1292 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1293
1294 Size = sizeof (UFI_MODE_PARAMETER_HEADER);
1295
1296 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1297 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1298 Packet.ModeSenseUFI.page_code = 0x3F;
1299 Packet.ModeSenseUFI.page_control = 0;
1300 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1301 Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size;
1302 Status = USBFloppyPacketCommand (
1303 UsbFloppyDevice,
1304 &Packet,
1305 sizeof (ATAPI_PACKET_COMMAND),
1306 &Header,
1307 Size,
1308 EfiUsbDataIn,
1309 USBFLPTIMEOUT
1310 );
1311
1312 if (EFI_ERROR (Status)) {
1313 return EFI_DEVICE_ERROR;
1314 }
1315
1316 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1317
1318 return EFI_SUCCESS;
1319
1320 }
1321
1322 EFI_STATUS
1323 UsbSCSIModeSense1APage3F (
1324 IN USB_FLOPPY_DEV *UsbFloppyDevice
1325 )
1326 /*++
1327
1328 Routine Description:
1329 Retrieves mode sense information via sending Mode Sense
1330 Packet Command.
1331
1332 Arguments:
1333 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1334
1335 Returns:
1336 EFI_DEVICE_ERROR - Hardware error
1337 EFI_SUCCESS - Success
1338
1339 --*/
1340 {
1341 //
1342 // status returned by Read Capacity Packet Command
1343 //
1344 EFI_STATUS Status;
1345 ATAPI_PACKET_COMMAND Packet;
1346 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1347 SCSI_MODE_PARAMETER_HEADER6 Header;
1348 UINT32 Size;
1349
1350 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1351
1352 Size = sizeof (SCSI_MODE_PARAMETER_HEADER6);
1353
1354 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1355 Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A;
1356 Packet.ModeSenseSCSI.page_code = 0x3F;
1357 Packet.ModeSenseSCSI.page_control = 0;
1358 Packet.ModeSenseSCSI.allocation_length = (UINT8) Size;
1359 Status = USBFloppyPacketCommand (
1360 UsbFloppyDevice,
1361 &Packet,
1362 sizeof (MODE_SENSE_CMD_SCSI),
1363 &Header,
1364 Size,
1365 EfiUsbDataIn,
1366 USBFLPTIMEOUT
1367 );
1368
1369 if (EFI_ERROR (Status)) {
1370 return EFI_DEVICE_ERROR;
1371 }
1372
1373 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1374 return EFI_SUCCESS;
1375
1376 }
1377
1378 /*++
1379
1380 The following functions are a set of helper functions,
1381 which are used to parse sense key returned by the device.
1382
1383 --*/
1384 BOOLEAN
1385 IsNoMedia (
1386 IN REQUEST_SENSE_DATA *SenseData,
1387 IN UINTN SenseCounts
1388 )
1389 {
1390 REQUEST_SENSE_DATA *SensePtr;
1391 UINTN Index;
1392 BOOLEAN NoMedia;
1393
1394 NoMedia = FALSE;
1395
1396 SensePtr = SenseData;
1397
1398 for (Index = 0; Index < SenseCounts; Index++) {
1399
1400 if ((SensePtr->sense_key == SK_NOT_READY) &&
1401 (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) {
1402
1403 NoMedia = TRUE;
1404 }
1405
1406 SensePtr++;
1407 }
1408
1409 return NoMedia;
1410 }
1411
1412
1413 BOOLEAN
1414 IsMediaError (
1415 IN REQUEST_SENSE_DATA *SenseData,
1416 IN UINTN SenseCounts
1417 )
1418 {
1419 REQUEST_SENSE_DATA *SensePtr;
1420 UINTN Index;
1421 BOOLEAN IsError;
1422
1423 IsError = FALSE;
1424 SensePtr = SenseData;
1425
1426 for (Index = 0; Index < SenseCounts; Index++) {
1427
1428 switch (SensePtr->sense_key) {
1429
1430 //
1431 // Medium error case
1432 //
1433 case SK_MEDIUM_ERROR:
1434 switch (SensePtr->addnl_sense_code) {
1435
1436 case ASC_MEDIA_ERR1:
1437 case ASC_MEDIA_ERR2:
1438 case ASC_MEDIA_ERR3:
1439 case ASC_MEDIA_ERR4:
1440 IsError = TRUE;
1441 break;
1442
1443 default:
1444 break;
1445 }
1446
1447 break;
1448
1449 //
1450 // Medium upside-down case
1451 //
1452 case SK_NOT_READY:
1453 switch (SensePtr->addnl_sense_code) {
1454 case ASC_MEDIA_UPSIDE_DOWN:
1455 IsError = TRUE;
1456 break;
1457
1458 default:
1459 break;
1460 }
1461 break;
1462
1463 default:
1464 break;
1465 }
1466
1467 SensePtr++;
1468 }
1469
1470 return IsError;
1471 }
1472
1473 BOOLEAN
1474 IsMediaChange (
1475 IN REQUEST_SENSE_DATA *SenseData,
1476 IN UINTN SenseCounts
1477 )
1478 {
1479 REQUEST_SENSE_DATA *SensePtr;
1480 UINTN Index;
1481 BOOLEAN MediaChanged;
1482
1483 MediaChanged = FALSE;
1484 SensePtr = SenseData;
1485
1486 for (Index = 0; Index < SenseCounts; Index++) {
1487
1488 if ((SensePtr->sense_key == SK_UNIT_ATTENTION) &&
1489 (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) {
1490
1491 MediaChanged = TRUE;
1492 }
1493
1494 SensePtr++;
1495 }
1496
1497 return MediaChanged;
1498 }
1499
1500 BOOLEAN
1501 IsDriveReady (
1502 IN REQUEST_SENSE_DATA *SenseData,
1503 IN UINTN SenseCounts,
1504 OUT BOOLEAN *NeedRetry
1505 )
1506 {
1507 REQUEST_SENSE_DATA *SensePtr;
1508 UINTN Index;
1509 BOOLEAN IsReady;
1510
1511 IsReady = TRUE;
1512 *NeedRetry = FALSE;
1513 SensePtr = SenseData;
1514
1515 for (Index = 0; Index < SenseCounts; Index++) {
1516
1517 if ((SensePtr->sense_key == SK_NOT_READY) &&
1518 (SensePtr->addnl_sense_code == ASC_NOT_READY)) {
1519
1520 switch (SensePtr->addnl_sense_code_qualifier) {
1521
1522 case ASCQ_IN_PROGRESS:
1523 case ASCQ_DEVICE_BUSY:
1524 IsReady = FALSE;
1525 *NeedRetry = TRUE;
1526 break;
1527
1528 default:
1529 //
1530 // Drive is in error condition,
1531 // no need to retry.
1532 //
1533 IsReady = FALSE;
1534 *NeedRetry = FALSE;
1535 break;
1536 }
1537 }
1538
1539 SensePtr++;
1540 }
1541
1542 return IsReady;
1543 }
1544
1545 BOOLEAN
1546 IsMediaWriteProtected (
1547 IN REQUEST_SENSE_DATA *SenseData,
1548 IN UINTN SenseCounts
1549 )
1550 {
1551 REQUEST_SENSE_DATA *SensePtr;
1552 UINTN Index;
1553 BOOLEAN IsWriteProtected;
1554
1555 IsWriteProtected = FALSE;
1556 SensePtr = SenseData;
1557
1558 for (Index = 0; Index < SenseCounts; Index++) {
1559 //
1560 // catch media write-protected condition.
1561 //
1562 if ((SensePtr->sense_key == SK_DATA_PROTECT) &&
1563 (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) {
1564
1565 IsWriteProtected = TRUE;
1566 }
1567
1568 SensePtr++;
1569 }
1570
1571 return IsWriteProtected;
1572 }
1573
1574 BOOLEAN
1575 IsLogicalUnitCommunicationOverRun (
1576 IN REQUEST_SENSE_DATA *SenseData,
1577 IN UINTN SenseCounts
1578 )
1579 {
1580 REQUEST_SENSE_DATA *SensePtr;
1581 UINTN Index;
1582 BOOLEAN IsOverRun;
1583
1584 IsOverRun = FALSE;
1585 SensePtr = SenseData;
1586
1587 for (Index = 0; Index < SenseCounts; Index++) {
1588
1589 if ((SensePtr->sense_key == SK_NOT_READY) &&
1590 (SensePtr->addnl_sense_code == ASC_LOGICAL_UNIT_STATUS) &&
1591 (SensePtr->addnl_sense_code_qualifier == ASCQ_LOGICAL_UNIT_OVERRUN)) {
1592 IsOverRun = TRUE;
1593 }
1594
1595 SensePtr++;
1596 }
1597
1598 return IsOverRun;
1599 }