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