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