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