Add the following Pcds declaration in EdkModulePkg.spd file. EdkModulePkg PeiVariable...
[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 UINTN SenseCounts;
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 // fill the Packet data structure
338 //
339 Read10Packet->opcode = READ_10;
340
341 //
342 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
343 // Lba0 is MSB, Lba3 is LSB
344 //
345 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
346 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
347 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
348 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
349
350 //
351 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
352 // TranLen0 is MSB, TranLen is LSB
353 //
354 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
355 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
356
357 ByteCount = SectorCount * BlockSize;
358
359 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
360
361 Status = USBFloppyPacketCommand (
362 UsbFloppyDevice,
363 &Packet,
364 sizeof (ATAPI_PACKET_COMMAND),
365 (VOID *) ptrBuffer,
366 ByteCount,
367 EfiUsbDataIn,
368 TimeOut
369 );
370 if (EFI_ERROR (Status)) {
371
372 Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
373 if (!EFI_ERROR (Status)) {
374 if (IsLogicalUnitCommunicationOverRun (
375 UsbFloppyDevice->SenseData,
376 SenseCounts
377 )) {
378 Lba32 = (UINT32) Lba;
379 ptrBuffer = Buffer;
380 BlocksRemaining = (UINT16) NumberOfBlocks;
381 MaxBlock = (UINT16) (MaxBlock / 4);
382 if (MaxBlock < 1) {
383 MaxBlock = 1;
384 }
385
386 continue;
387 }
388 } else {
389 return EFI_DEVICE_ERROR;
390 }
391 //
392 // retry read10 command
393 //
394 Status = USBFloppyPacketCommand (
395 UsbFloppyDevice,
396 &Packet,
397 sizeof (ATAPI_PACKET_COMMAND),
398 (VOID *) ptrBuffer,
399 ByteCount,
400 EfiUsbDataIn,
401 TimeOut
402 );
403 if (EFI_ERROR (Status)) {
404 return EFI_DEVICE_ERROR;
405 }
406 }
407
408 Lba32 += SectorCount;
409 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
410 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
411 }
412
413 return Status;
414 }
415
416 EFI_STATUS
417 USBFloppyReadCapacity (
418 IN USB_FLOPPY_DEV *UsbFloppyDevice
419 )
420 /*++
421
422 Routine Description:
423 Retrieves media capacity information via
424 sending Read Capacity Packet Command.
425
426 Arguments:
427 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
428
429 Returns:
430 EFI_DEVICE_ERROR - Hardware error
431 EFI_SUCCESS - Success
432 --*/
433 {
434 //
435 // status returned by Read Capacity Packet Command
436 //
437 EFI_STATUS Status;
438 ATAPI_PACKET_COMMAND Packet;
439 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
440
441 //
442 // used for capacity data returned from Usb Floppy
443 //
444 READ_CAPACITY_DATA Data;
445
446 ZeroMem (&Data, sizeof (Data));
447
448 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
449
450 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
451 Packet.Inquiry.opcode = READ_CAPACITY;
452 Status = USBFloppyPacketCommand (
453 UsbFloppyDevice,
454 &Packet,
455 sizeof (ATAPI_PACKET_COMMAND),
456 (VOID *) &Data,
457 sizeof (READ_CAPACITY_DATA),
458 EfiUsbDataIn,
459 USBFLPTIMEOUT
460 );
461
462 if (EFI_ERROR (Status)) {
463 return EFI_DEVICE_ERROR;
464 }
465
466 UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
467 (Data.LastLba2 << 16) |
468 (Data.LastLba1 << 8) |
469 Data.LastLba0;
470
471 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
472
473 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
474
475 return EFI_SUCCESS;
476
477 }
478
479 EFI_STATUS
480 USBFloppyReadFormatCapacity (
481 IN USB_FLOPPY_DEV *UsbFloppyDevice
482 )
483 /*++
484
485 Routine Description:
486 Retrieves media capacity information via sending Read Format
487 Capacity Packet Command.
488
489 Arguments:
490 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
491
492 Returns:
493 EFI_DEVICE_ERROR - Hardware error
494 EFI_SUCCESS - Success
495 --*/
496 {
497 //
498 // status returned by Read Capacity Packet Command
499 //
500 EFI_STATUS Status;
501 ATAPI_PACKET_COMMAND Packet;
502 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
503
504 //
505 // used for capacity data returned from Usb Floppy
506 //
507 READ_FORMAT_CAPACITY_DATA FormatData;
508
509 ZeroMem (&FormatData, sizeof (FormatData));
510
511 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
512
513 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
514 Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
515 Packet.ReadFormatCapacity.allocation_length_lo = 12;
516 Status = USBFloppyPacketCommand (
517 UsbFloppyDevice,
518 &Packet,
519 sizeof (ATAPI_PACKET_COMMAND),
520 (VOID *) &FormatData,
521 sizeof (READ_FORMAT_CAPACITY_DATA),
522 EfiUsbDataIn,
523 USBFLPTIMEOUT
524 );
525
526 if (EFI_ERROR (Status)) {
527 return EFI_DEVICE_ERROR;
528 }
529
530 if (FormatData.DesCode == 3) {
531 //
532 // Media is not present
533 //
534 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
535 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
536 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
537 } else {
538
539 UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
540 (FormatData.LastLba2 << 16) |
541 (FormatData.LastLba1 << 8) |
542 FormatData.LastLba0;
543
544 UsbFloppyDevice->BlkIo.Media->LastBlock--;
545
546 UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
547 (FormatData.BlockSize1 << 8) |
548 FormatData.BlockSize0;
549
550 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
551
552 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
553
554 }
555
556 return EFI_SUCCESS;
557
558 }
559
560 EFI_STATUS
561 UsbFloppyRequestSense (
562 IN USB_FLOPPY_DEV *UsbFloppyDevice,
563 OUT UINTN *SenseCounts
564 )
565 /*++
566
567 Routine Description:
568 Retrieves Sense Data from device via
569 sending Request Sense Packet Command.
570
571 Arguments:
572 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
573 SenseCounts - A pointer to the number of Sense Data returned.
574
575 Returns:
576 EFI_DEVICE_ERROR - Hardware error
577 EFI_SUCCESS - Success
578 --*/
579 {
580 EFI_STATUS Status;
581 REQUEST_SENSE_DATA *Sense;
582 UINT8 *Ptr;
583 BOOLEAN SenseReq;
584 ATAPI_PACKET_COMMAND Packet;
585 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
586
587 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
588
589 *SenseCounts = 0;
590
591 ZeroMem (
592 UsbFloppyDevice->SenseData,
593 sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber)
594 );
595 //
596 // fill command packet for Request Sense Packet Command
597 //
598 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
599 Packet.RequestSense.opcode = REQUEST_SENSE;
600 Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA);
601
602 //
603 // initialize pointer
604 //
605 Ptr = (UINT8 *) (UsbFloppyDevice->SenseData);
606
607 //
608 // request sense data from device continuously
609 // until no sense data exists in the device.
610 //
611 for (SenseReq = TRUE; SenseReq;) {
612
613 Sense = (REQUEST_SENSE_DATA *) Ptr;
614
615 //
616 // send out Request Sense Packet Command and get one Sense
617 // data from device.
618 //
619 Status = USBFloppyPacketCommand (
620 UsbFloppyDevice,
621 &Packet,
622 sizeof (ATAPI_PACKET_COMMAND),
623 (VOID *) Ptr,
624 sizeof (REQUEST_SENSE_DATA),
625 EfiUsbDataIn,
626 USBFLPTIMEOUT
627 );
628 //
629 // failed to get Sense data
630 //
631 if (EFI_ERROR (Status)) {
632 //
633 // Recovery the device back to normal state.
634 //
635 UsbFloppyDevice->AtapiProtocol->UsbAtapiReset (
636 UsbFloppyDevice->AtapiProtocol,
637 TRUE
638 );
639
640 if (*SenseCounts == 0) {
641 //
642 // never retrieved any sense data from device,
643 // just return error.
644 //
645 return EFI_DEVICE_ERROR;
646 } else {
647 //
648 // has retrieved some sense data from device,
649 // so return success.
650 //
651 return EFI_SUCCESS;
652 }
653 }
654
655 if (Sense->sense_key != SK_NO_SENSE) {
656 //
657 // Ptr is byte based pointer
658 //
659 Ptr += sizeof (REQUEST_SENSE_DATA);
660
661 (*SenseCounts)++;
662
663 } else {
664 //
665 // when no sense key, skip out the loop
666 //
667 SenseReq = FALSE;
668 }
669
670 //
671 // If the sense key numbers exceed Sense Data Buffer size,
672 // just skip the loop and do not fetch the sense key in this function.
673 //
674 if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) {
675 SenseReq = FALSE;
676 }
677 }
678
679 return EFI_SUCCESS;
680 }
681
682 EFI_STATUS
683 UsbFloppyTestUnitReady (
684 IN USB_FLOPPY_DEV *UsbFloppyDevice
685 )
686 /*++
687
688 Routine Description:
689 Sends Test Unit ReadyPacket Command to the device.
690
691 Arguments:
692 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
693
694 Returns:
695 EFI_DEVICE_ERROR - Hardware error
696 EFI_SUCCESS - Success
697 --*/
698 {
699 ATAPI_PACKET_COMMAND Packet;
700 EFI_STATUS Status;
701 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
702 UINT32 RetryIndex;
703 UINT32 MaximumRetryTimes;
704
705 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
706 MaximumRetryTimes = 2;
707 //
708 // fill command packet
709 //
710 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
711 Packet.TestUnitReady.opcode = TEST_UNIT_READY;
712
713 //
714 // send command packet
715 //
716 Status = EFI_DEVICE_ERROR;
717
718 for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) {
719
720 Status = USBFloppyPacketCommand (
721 UsbFloppyDevice,
722 &Packet,
723 sizeof (ATAPI_PACKET_COMMAND),
724 NULL,
725 0,
726 EfiUsbNoData,
727 USBFLPTIMEOUT
728 );
729
730 if (EFI_ERROR (Status)) {
731 gBS->Stall (100 * STALL_1_MILLI_SECOND);
732 }
733 }
734
735 return Status;
736 }
737
738 EFI_STATUS
739 USBFloppyWrite10 (
740 IN USB_FLOPPY_DEV *UsbFloppyDevice,
741 IN VOID *Buffer,
742 IN EFI_LBA Lba,
743 IN UINTN NumberOfBlocks
744 )
745 /*++
746
747 Routine Description:
748 Sends Write10 Packet Command to device to perform data transfer
749 from host to device.
750
751 Arguments:
752 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
753 Buffer - A pointer to the source buffer for the data.
754 The caller is responsible for either having implicit
755 or explicit ownership of the buffer.
756 Lba - The starting logical block address to written to
757 the device.
758 NumberOfBlocks - Indicates the number of blocks that the write
759 operation requests.
760
761 Returns:
762 EFI_DEVICE_ERROR - Hardware error
763 EFI_SUCCESS - Success
764 --*/
765 {
766 ATAPI_PACKET_COMMAND Packet;
767 READ10_CMD *Write10Packet;
768 UINT16 MaxBlock;
769 UINT16 BlocksRemaining;
770 UINT16 SectorCount;
771 UINT32 Lba32;
772 UINT32 BlockSize;
773 UINT32 ByteCount;
774 VOID *ptrBuffer;
775 EFI_STATUS Status;
776 UINT16 TimeOut;
777 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
778 UINTN SenseCounts;
779
780 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
781
782 //
783 // prepare command packet for the Write10 Packet Command.
784 //
785 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
786 Write10Packet = &Packet.Read10;
787 Lba32 = (UINT32) Lba;
788 ptrBuffer = Buffer;
789 BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
790
791 MaxBlock = (UINT16) (65536 / BlockSize);
792 BlocksRemaining = (UINT16) NumberOfBlocks;
793
794 Status = EFI_SUCCESS;
795 while (BlocksRemaining > 0) {
796
797 if (BlocksRemaining <= MaxBlock) {
798
799 SectorCount = BlocksRemaining;
800 } else {
801
802 SectorCount = MaxBlock;
803 }
804 //
805 // fill the Packet data structure
806 //
807 Write10Packet->opcode = WRITE_10;
808
809 //
810 // Lba0 ~ Lba3 specify the start logical block address
811 // of the data transfer.
812 // Lba0 is MSB, Lba3 is LSB
813 //
814 Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
815 Write10Packet->Lba2 = (UINT8) (Lba32 >> 8);
816 Write10Packet->Lba1 = (UINT8) (Lba32 >> 16);
817 Write10Packet->Lba0 = (UINT8) (Lba32 >> 24);
818
819 //
820 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
821 // TranLen0 is MSB, TranLen is LSB
822 //
823 Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
824 Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
825
826 ByteCount = SectorCount * BlockSize;
827
828 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
829
830 Status = USBFloppyPacketCommand (
831 UsbFloppyDevice,
832 &Packet,
833 sizeof (ATAPI_PACKET_COMMAND),
834 (VOID *) ptrBuffer,
835 ByteCount,
836 EfiUsbDataOut,
837 TimeOut
838 );
839 if (EFI_ERROR (Status)) {
840 Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
841 if (!EFI_ERROR (Status)) {
842 if (IsLogicalUnitCommunicationOverRun (
843 UsbFloppyDevice->SenseData,
844 SenseCounts
845 )) {
846 Lba32 = (UINT32) Lba;
847 ptrBuffer = Buffer;
848 BlocksRemaining = (UINT16) NumberOfBlocks;
849 MaxBlock = (UINT16) (MaxBlock / 4);
850 if (MaxBlock < 1) {
851 MaxBlock = 1;
852 }
853
854 continue;
855 }
856 }
857 //
858 // retry write10 command
859 //
860 Status = USBFloppyPacketCommand (
861 UsbFloppyDevice,
862 &Packet,
863 sizeof (ATAPI_PACKET_COMMAND),
864 (VOID *) ptrBuffer,
865 ByteCount,
866 EfiUsbDataOut,
867 TimeOut
868 );
869 if (EFI_ERROR (Status)) {
870 return EFI_DEVICE_ERROR;
871 }
872 }
873
874 Lba32 += SectorCount;
875 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
876 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
877 }
878
879 return Status;
880 }
881
882 EFI_STATUS
883 UsbFloppyDetectMedia (
884 IN USB_FLOPPY_DEV *UsbFloppyDevice,
885 OUT BOOLEAN *MediaChange
886 )
887 /*++
888
889 Routine Description:
890 Retrieves media information.
891
892 Arguments:
893 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
894 MediaChange - Indicates whether media was changed.
895
896 Returns:
897 EFI_DEVICE_ERROR - Hardware error
898 EFI_SUCCESS - Success
899 EFI_INVALID_PARAMETER - Parameter is error
900 --*/
901 {
902 EFI_STATUS Status;
903 EFI_STATUS FloppyStatus;
904 //
905 // the following variables are used to record previous media information
906 //
907 EFI_BLOCK_IO_MEDIA OldMediaInfo;
908 UINTN SenseCounts;
909 UINTN RetryIndex;
910 UINTN RetryTimes;
911 UINTN MaximumRetryTimes;
912 BOOLEAN NeedRetry;
913
914 //
915 // a flag used to determine whether need to perform Read Capacity command.
916 //
917 BOOLEAN NeedReadCapacity;
918
919 REQUEST_SENSE_DATA *SensePtr;
920
921 //
922 // init
923 //
924 Status = EFI_SUCCESS;
925 FloppyStatus = EFI_SUCCESS;
926 CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo));
927 //OldMediaInfo = *UsbFloppyDevice->BlkIo.Media;
928 *MediaChange = FALSE;
929 NeedReadCapacity = TRUE;
930
931 //
932 // if there is no media present,or media not changed,
933 // the request sense command will detect faster than read capacity command.
934 // read capacity command can be bypassed, thus improve performance.
935 //
936 SenseCounts = 0;
937 Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
938
939 if (!EFI_ERROR (Status)) {
940
941 SensePtr = UsbFloppyDevice->SenseData;
942
943 //
944 // No Media
945 //
946 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
947
948 NeedReadCapacity = FALSE;
949 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
950 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
951 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
952 } else {
953 //
954 // Media Changed
955 //
956 if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) {
957 UsbFloppyDevice->BlkIo.Media->MediaId++;
958 }
959
960 //
961 // Media Write-protected
962 //
963 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
964 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
965 }
966
967 //
968 // Media Error
969 //
970 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
971 //
972 // if media error encountered, make it look like no media present.
973 //
974 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
975 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
976 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
977 }
978
979 }
980
981 }
982
983 if (NeedReadCapacity) {
984 //
985 // at most retry 5 times
986 //
987 MaximumRetryTimes = 5;
988 //
989 // initial retry twice
990 //
991 RetryTimes = 2;
992
993 for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) {
994 //
995 // Using different command to retrieve media capacity.
996 //
997 switch (UsbFloppyDevice->DeviceType) {
998
999 case USBCDROM:
1000 Status = USBFloppyReadCapacity (UsbFloppyDevice);
1001 break;
1002
1003 case USBFLOPPY:
1004 UsbMassStorageModeSense (UsbFloppyDevice);
1005 Status = USBFloppyReadFormatCapacity (UsbFloppyDevice);
1006 if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) {
1007 //
1008 // retry the ReadCapacity command
1009 //
1010 UsbFloppyDevice->DeviceType = USBFLOPPY2;
1011 Status = EFI_DEVICE_ERROR;
1012 }
1013 break;
1014
1015 case USBFLOPPY2:
1016 UsbMassStorageModeSense (UsbFloppyDevice);
1017 Status = USBFloppyReadCapacity (UsbFloppyDevice);
1018 if (EFI_ERROR (Status)) {
1019 //
1020 // retry the ReadFormatCapacity command
1021 //
1022 UsbFloppyDevice->DeviceType = USBFLOPPY;
1023 }
1024 //
1025 // force the BlockSize to be 0x200.
1026 //
1027 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
1028 break;
1029
1030 default:
1031 return EFI_INVALID_PARAMETER;
1032 }
1033
1034 if (!EFI_ERROR (Status)) {
1035 //
1036 // skip the loop when read capacity succeeds.
1037 //
1038 break;
1039 }
1040
1041 SenseCounts = 0;
1042
1043 FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
1044
1045 //
1046 // If Request Sense data failed,retry.
1047 //
1048 if (EFI_ERROR (FloppyStatus)) {
1049 //
1050 // retry once more
1051 //
1052 RetryTimes++;
1053 continue;
1054 }
1055 //
1056 // No Media
1057 //
1058 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
1059
1060 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
1061 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
1062 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
1063 break;
1064 }
1065
1066 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
1067 //
1068 // if media error encountered, make it look like no media present.
1069 //
1070 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
1071 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
1072 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
1073 break;
1074 }
1075
1076 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
1077 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
1078 continue;
1079 }
1080
1081 if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) {
1082
1083 //
1084 // Drive not ready: if NeedRetry, then retry once more;
1085 // else return error
1086 //
1087 if (NeedRetry) {
1088 //
1089 // Stall 0.1 second to wait for drive becoming ready
1090 //
1091 gBS->Stall (100 * STALL_1_MILLI_SECOND);
1092 //
1093 // reset retry variable to zero,
1094 // to make it retry for "drive in progress of becoming ready".
1095 //
1096 RetryIndex = 0;
1097 continue;
1098 } else {
1099 return EFI_DEVICE_ERROR;
1100 }
1101 }
1102 //
1103 // if read capacity fail not for above reasons, retry once more
1104 //
1105 RetryTimes++;
1106
1107 }
1108 //
1109 // ENDFOR
1110 //
1111
1112 //
1113 // tell whether the readcapacity process is successful or not
1114 // ("Status" variable record the latest status returned
1115 // by ReadCapacity AND "FloppyStatus" record the latest status
1116 // returned by RequestSense)
1117 //
1118 if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) {
1119 return EFI_DEVICE_ERROR;
1120 }
1121
1122 }
1123
1124 if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
1125
1126 if (UsbFloppyDevice->BlkIo.Media->MediaPresent) {
1127 UsbFloppyDevice->BlkIo.Media->MediaId = 1;
1128 }
1129
1130 *MediaChange = TRUE;
1131 }
1132
1133 if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
1134 *MediaChange = TRUE;
1135 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1136 }
1137
1138 if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
1139 *MediaChange = TRUE;
1140 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1141 }
1142
1143 if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
1144 *MediaChange = TRUE;
1145 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1146 }
1147
1148 if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
1149 *MediaChange = TRUE;
1150 }
1151
1152 return EFI_SUCCESS;
1153 }
1154
1155
1156
1157 EFI_STATUS
1158 UsbFloppyModeSense5APage5 (
1159 IN USB_FLOPPY_DEV *UsbFloppyDevice
1160 )
1161 /*++
1162
1163 Routine Description:
1164 Retrieves media capacity information via sending Read Format
1165 Capacity Packet Command.
1166
1167 Arguments:
1168 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1169
1170 Returns:
1171 EFI_DEVICE_ERROR - Hardware error
1172 EFI_SUCCESS - Success
1173
1174 --*/
1175 {
1176 //
1177 // status returned by Read Capacity Packet Command
1178 //
1179 EFI_STATUS Status;
1180 ATAPI_PACKET_COMMAND Packet;
1181 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1182 UFI_MODE_PARAMETER_PAGE_5 ModePage5;
1183 EFI_LBA LastBlock;
1184 UINT32 SectorsPerTrack;
1185 UINT32 NumberOfCylinders;
1186 UINT32 NumberOfHeads;
1187 UINT32 DataBytesPerSector;
1188
1189 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1190
1191 ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5));
1192
1193 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1194 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1195 //
1196 // Flexible Disk Page
1197 //
1198 Packet.ModeSenseUFI.page_code = 5;
1199 //
1200 // current values
1201 //
1202 Packet.ModeSenseUFI.page_control = 0;
1203 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1204 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5);
1205 Status = USBFloppyPacketCommand (
1206 UsbFloppyDevice,
1207 &Packet,
1208 sizeof (ATAPI_PACKET_COMMAND),
1209 (VOID *) &ModePage5,
1210 sizeof (UFI_MODE_PARAMETER_PAGE_5),
1211 EfiUsbDataIn,
1212 USBFLPTIMEOUT
1213 );
1214
1215 if (EFI_ERROR (Status)) {
1216 return EFI_DEVICE_ERROR;
1217 }
1218
1219 NumberOfHeads = ModePage5.flex_disk_page.number_of_heads;
1220 SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track;
1221 NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 |
1222 ModePage5.flex_disk_page.number_of_cylinders_lsb;
1223
1224 LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders;
1225 DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 |
1226 ModePage5.flex_disk_page.databytes_per_sector_lsb;
1227
1228 UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock;
1229
1230 UsbFloppyDevice->BlkIo.Media->LastBlock--;
1231
1232 UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector;
1233
1234 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
1235
1236 UsbFloppyDevice->BlkIo.Media->ReadOnly =
1237 ModePage5.mode_param_header.write_protected;
1238
1239 return EFI_SUCCESS;
1240
1241 }
1242
1243 EFI_STATUS
1244 UsbFloppyModeSense5APage1C (
1245 IN USB_FLOPPY_DEV *UsbFloppyDevice
1246 )
1247 /*++
1248
1249 Routine Description:
1250 Retrieves media capacity information via sending Read Format
1251 Capacity Packet Command.
1252
1253 Arguments:
1254 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1255
1256 Returns:
1257 EFI_DEVICE_ERROR - Hardware error
1258 EFI_SUCCESS - Success
1259
1260 --*/
1261 {
1262 //
1263 // status returned by Read Capacity Packet Command
1264 //
1265 EFI_STATUS Status;
1266 ATAPI_PACKET_COMMAND Packet;
1267 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1268 UFI_MODE_PARAMETER_PAGE_1C ModePage1C;
1269
1270 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1271
1272 ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C));
1273
1274 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1275 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1276 //
1277 // Flexible Disk Page
1278 //
1279 Packet.ModeSenseUFI.page_code = 0x1C;
1280 //
1281 // current values
1282 //
1283 Packet.ModeSenseUFI.page_control = 0;
1284 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1285 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C);
1286 Status = USBFloppyPacketCommand (
1287 UsbFloppyDevice,
1288 &Packet,
1289 sizeof (ATAPI_PACKET_COMMAND),
1290 (VOID *) &ModePage1C,
1291 sizeof (UFI_MODE_PARAMETER_PAGE_1C),
1292 EfiUsbDataIn,
1293 USBFLPTIMEOUT
1294 );
1295
1296 if (EFI_ERROR (Status)) {
1297 return EFI_DEVICE_ERROR;
1298 }
1299
1300 UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected;
1301
1302 return EFI_SUCCESS;
1303
1304 }
1305
1306 EFI_STATUS
1307 UsbMassStorageModeSense (
1308 IN USB_FLOPPY_DEV *UsbFloppyDevice
1309 )
1310 {
1311 if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) {
1312 return UsbSCSIModeSense1APage3F (UsbFloppyDevice);
1313 } else {
1314 return UsbFloppyModeSense5APage3F (UsbFloppyDevice);
1315 }
1316 }
1317
1318 EFI_STATUS
1319 UsbFloppyModeSense5APage3F (
1320 IN USB_FLOPPY_DEV *UsbFloppyDevice
1321 )
1322 /*++
1323
1324 Routine Description:
1325 Retrieves mode sense information via sending Mode Sense
1326 Packet Command.
1327
1328 Arguments:
1329 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1330
1331 Returns:
1332 EFI_DEVICE_ERROR - Hardware error
1333 EFI_SUCCESS - Success
1334
1335 --*/
1336 {
1337 //
1338 // status returned by Read Capacity Packet Command
1339 //
1340 EFI_STATUS Status;
1341 ATAPI_PACKET_COMMAND Packet;
1342 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1343 UFI_MODE_PARAMETER_HEADER Header;
1344 UINT32 Size;
1345
1346 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1347
1348 Size = sizeof (UFI_MODE_PARAMETER_HEADER);
1349
1350 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1351 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1352 Packet.ModeSenseUFI.page_code = 0x3F;
1353 Packet.ModeSenseUFI.page_control = 0;
1354 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1355 Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size;
1356 Status = USBFloppyPacketCommand (
1357 UsbFloppyDevice,
1358 &Packet,
1359 sizeof (ATAPI_PACKET_COMMAND),
1360 &Header,
1361 Size,
1362 EfiUsbDataIn,
1363 USBFLPTIMEOUT
1364 );
1365
1366 if (EFI_ERROR (Status)) {
1367 return EFI_DEVICE_ERROR;
1368 }
1369
1370 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1371
1372 return EFI_SUCCESS;
1373
1374 }
1375
1376 EFI_STATUS
1377 UsbSCSIModeSense1APage3F (
1378 IN USB_FLOPPY_DEV *UsbFloppyDevice
1379 )
1380 /*++
1381
1382 Routine Description:
1383 Retrieves mode sense information via sending Mode Sense
1384 Packet Command.
1385
1386 Arguments:
1387 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1388
1389 Returns:
1390 EFI_DEVICE_ERROR - Hardware error
1391 EFI_SUCCESS - Success
1392
1393 --*/
1394 {
1395 //
1396 // status returned by Read Capacity Packet Command
1397 //
1398 EFI_STATUS Status;
1399 ATAPI_PACKET_COMMAND Packet;
1400 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
1401 SCSI_MODE_PARAMETER_HEADER6 Header;
1402 UINT32 Size;
1403
1404 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
1405
1406 Size = sizeof (SCSI_MODE_PARAMETER_HEADER6);
1407
1408 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1409 Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A;
1410 Packet.ModeSenseSCSI.page_code = 0x3F;
1411 Packet.ModeSenseSCSI.page_control = 0;
1412 Packet.ModeSenseSCSI.allocation_length = (UINT8) Size;
1413 Status = USBFloppyPacketCommand (
1414 UsbFloppyDevice,
1415 &Packet,
1416 sizeof (MODE_SENSE_CMD_SCSI),
1417 &Header,
1418 Size,
1419 EfiUsbDataIn,
1420 USBFLPTIMEOUT
1421 );
1422
1423 if (EFI_ERROR (Status)) {
1424 return EFI_DEVICE_ERROR;
1425 }
1426
1427 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1428 return EFI_SUCCESS;
1429
1430 }
1431
1432 /*++
1433
1434 The following functions are a set of helper functions,
1435 which are used to parse sense key returned by the device.
1436
1437 --*/
1438 BOOLEAN
1439 IsNoMedia (
1440 IN REQUEST_SENSE_DATA *SenseData,
1441 IN UINTN SenseCounts
1442 )
1443 {
1444 REQUEST_SENSE_DATA *SensePtr;
1445 UINTN Index;
1446 BOOLEAN NoMedia;
1447
1448 NoMedia = FALSE;
1449
1450 SensePtr = SenseData;
1451
1452 for (Index = 0; Index < SenseCounts; Index++) {
1453
1454 if ((SensePtr->sense_key == SK_NOT_READY) &&
1455 (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) {
1456
1457 NoMedia = TRUE;
1458 }
1459
1460 SensePtr++;
1461 }
1462
1463 return NoMedia;
1464 }
1465
1466
1467 BOOLEAN
1468 IsMediaError (
1469 IN REQUEST_SENSE_DATA *SenseData,
1470 IN UINTN SenseCounts
1471 )
1472 {
1473 REQUEST_SENSE_DATA *SensePtr;
1474 UINTN Index;
1475 BOOLEAN IsError;
1476
1477 IsError = FALSE;
1478 SensePtr = SenseData;
1479
1480 for (Index = 0; Index < SenseCounts; Index++) {
1481
1482 switch (SensePtr->sense_key) {
1483
1484 //
1485 // Medium error case
1486 //
1487 case SK_MEDIUM_ERROR:
1488 switch (SensePtr->addnl_sense_code) {
1489
1490 case ASC_MEDIA_ERR1:
1491 case ASC_MEDIA_ERR2:
1492 case ASC_MEDIA_ERR3:
1493 case ASC_MEDIA_ERR4:
1494 IsError = TRUE;
1495 break;
1496
1497 default:
1498 break;
1499 }
1500
1501 break;
1502
1503 //
1504 // Medium upside-down case
1505 //
1506 case SK_NOT_READY:
1507 switch (SensePtr->addnl_sense_code) {
1508 case ASC_MEDIA_UPSIDE_DOWN:
1509 IsError = TRUE;
1510 break;
1511
1512 default:
1513 break;
1514 }
1515 break;
1516
1517 default:
1518 break;
1519 }
1520
1521 SensePtr++;
1522 }
1523
1524 return IsError;
1525 }
1526
1527 BOOLEAN
1528 IsMediaChange (
1529 IN REQUEST_SENSE_DATA *SenseData,
1530 IN UINTN SenseCounts
1531 )
1532 {
1533 REQUEST_SENSE_DATA *SensePtr;
1534 UINTN Index;
1535 BOOLEAN MediaChanged;
1536
1537 MediaChanged = FALSE;
1538 SensePtr = SenseData;
1539
1540 for (Index = 0; Index < SenseCounts; Index++) {
1541
1542 if ((SensePtr->sense_key == SK_UNIT_ATTENTION) &&
1543 (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) {
1544
1545 MediaChanged = TRUE;
1546 }
1547
1548 SensePtr++;
1549 }
1550
1551 return MediaChanged;
1552 }
1553
1554 BOOLEAN
1555 IsDriveReady (
1556 IN REQUEST_SENSE_DATA *SenseData,
1557 IN UINTN SenseCounts,
1558 OUT BOOLEAN *NeedRetry
1559 )
1560 {
1561 REQUEST_SENSE_DATA *SensePtr;
1562 UINTN Index;
1563 BOOLEAN IsReady;
1564
1565 IsReady = TRUE;
1566 *NeedRetry = FALSE;
1567 SensePtr = SenseData;
1568
1569 for (Index = 0; Index < SenseCounts; Index++) {
1570
1571 if ((SensePtr->sense_key == SK_NOT_READY) &&
1572 (SensePtr->addnl_sense_code == ASC_NOT_READY)) {
1573
1574 switch (SensePtr->addnl_sense_code_qualifier) {
1575
1576 case ASCQ_IN_PROGRESS:
1577 case ASCQ_DEVICE_BUSY:
1578 IsReady = FALSE;
1579 *NeedRetry = TRUE;
1580 break;
1581
1582 default:
1583 //
1584 // Drive is in error condition,
1585 // no need to retry.
1586 //
1587 IsReady = FALSE;
1588 *NeedRetry = FALSE;
1589 break;
1590 }
1591 }
1592
1593 SensePtr++;
1594 }
1595
1596 return IsReady;
1597 }
1598
1599 BOOLEAN
1600 IsMediaWriteProtected (
1601 IN REQUEST_SENSE_DATA *SenseData,
1602 IN UINTN SenseCounts
1603 )
1604 {
1605 REQUEST_SENSE_DATA *SensePtr;
1606 UINTN Index;
1607 BOOLEAN IsWriteProtected;
1608
1609 IsWriteProtected = FALSE;
1610 SensePtr = SenseData;
1611
1612 for (Index = 0; Index < SenseCounts; Index++) {
1613 //
1614 // catch media write-protected condition.
1615 //
1616 if ((SensePtr->sense_key == SK_DATA_PROTECT) &&
1617 (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) {
1618
1619 IsWriteProtected = TRUE;
1620 }
1621
1622 SensePtr++;
1623 }
1624
1625 return IsWriteProtected;
1626 }
1627
1628 BOOLEAN
1629 IsLogicalUnitCommunicationOverRun (
1630 IN REQUEST_SENSE_DATA *SenseData,
1631 IN UINTN SenseCounts
1632 )
1633 {
1634 REQUEST_SENSE_DATA *SensePtr;
1635 UINTN Index;
1636 BOOLEAN IsOverRun;
1637
1638 IsOverRun = FALSE;
1639 SensePtr = SenseData;
1640
1641 for (Index = 0; Index < SenseCounts; Index++) {
1642
1643 if ((SensePtr->sense_key == SK_NOT_READY) &&
1644 (SensePtr->addnl_sense_code == ASC_LOGICAL_UNIT_STATUS) &&
1645 (SensePtr->addnl_sense_code_qualifier == ASCQ_LOGICAL_UNIT_OVERRUN)) {
1646 IsOverRun = TRUE;
1647 }
1648
1649 SensePtr++;
1650 }
1651
1652 return IsOverRun;
1653 }