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