]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
Fix the build break by removing an unreferenced static function.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMassStorage / Dxe / UsbMassStorageHelper.c
... / ...
CommitLineData
1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 UsbMassStorageHelper.c\r
15\r
16Abstract:\r
17\r
18 Helper functions for USB Mass Storage Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "UsbMassStorageHelper.h"\r
25\r
26STATIC\r
27BOOLEAN\r
28IsNoMedia (\r
29 IN REQUEST_SENSE_DATA *SenseData,\r
30 IN UINTN SenseCounts\r
31 );\r
32\r
33STATIC\r
34BOOLEAN\r
35IsMediaError (\r
36 IN REQUEST_SENSE_DATA *SenseData,\r
37 IN UINTN SenseCounts\r
38 );\r
39\r
40STATIC\r
41BOOLEAN\r
42IsMediaChange (\r
43 IN REQUEST_SENSE_DATA *SenseData,\r
44 IN UINTN SenseCounts\r
45 );\r
46\r
47STATIC\r
48BOOLEAN\r
49IsDriveReady (\r
50 IN REQUEST_SENSE_DATA *SenseData,\r
51 IN UINTN SenseCounts,\r
52 OUT BOOLEAN *NeedRetry\r
53 );\r
54\r
55STATIC\r
56BOOLEAN\r
57IsMediaWriteProtected (\r
58 IN REQUEST_SENSE_DATA *SenseData,\r
59 IN UINTN SenseCounts\r
60 );\r
61\r
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
77\r
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
83 after the command packet.\r
84 BufferLength - Indicates the size of the Data Buffer.\r
85 Direction - Transfer Direction\r
86 TimeOutInMilliSeconds - Timeout Value\r
87 Returns:\r
88 EFI_SUCCESS - Success\r
89--*/\r
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
120\r
121 Arguments:\r
122 UsbFloppyDevice The USB_FLOPPY_DEV instance.\r
123\r
124 Returns:\r
125 EFI_DEVICE_ERROR - Hardware error\r
126 EFI_SUCCESS - Success\r
127--*/\r
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
141\r
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
198\r
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
218\r
219 Arguments:\r
220 UsbFloppyDevice The USB_FLOPPY_DEV instance.\r
221 Idata A pointer pointing to the address of\r
222 Inquiry Data.\r
223\r
224 Returns:\r
225 EFI_DEVICE_ERROR - Hardware error\r
226 EFI_SUCCESS - Success\r
227--*/\r
228{\r
229 ATAPI_PACKET_COMMAND Packet;\r
230 EFI_STATUS Status;\r
231\r
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
267 IN USB_FLOPPY_DEV *UsbFloppyDevice,\r
268 IN VOID *Buffer,\r
269 IN EFI_LBA Lba,\r
270 IN UINTN NumberOfBlocks\r
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
277\r
278 Arguments:\r
279 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
280 Buffer - A pointer to the destination buffer for the data.\r
281 The caller is responsible for either having implicit\r
282 or explicit ownership of the buffer.\r
283 Lba - The starting logical block address to read from\r
284 on the device.\r
285 NumberOfBlocks - Indicates the number of blocks that the read\r
286 operation requests.\r
287\r
288 Returns:\r
289 EFI_DEVICE_ERROR - Hardware error\r
290 EFI_SUCCESS - Success\r
291--*/\r
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
304 UINT8 Index;\r
305\r
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
326\r
327 for (Index = 0; Index < 3; Index ++) {\r
328\r
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
341\r
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
348\r
349 ByteCount = SectorCount * BlockSize;\r
350\r
351 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);\r
352\r
353\r
354 Status = USBFloppyPacketCommand (\r
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
365 }\r
366 }\r
367\r
368 if (Index == 3) {\r
369 return EFI_DEVICE_ERROR;\r
370 }\r
371\r
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
380STATIC\r
381EFI_STATUS\r
382USBFloppyReadCapacity (\r
383 IN USB_FLOPPY_DEV *UsbFloppyDevice\r
384 )\r
385/*++\r
386\r
387 Routine Description:\r
388 Retrieves media capacity information via\r
389 sending Read Capacity Packet Command.\r
390\r
391 Arguments:\r
392 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
393\r
394 Returns:\r
395 EFI_DEVICE_ERROR - Hardware error\r
396 EFI_SUCCESS - Success\r
397--*/\r
398{\r
399 //\r
400 // status returned by Read Capacity Packet Command\r
401 //\r
402 EFI_STATUS Status;\r
403 ATAPI_PACKET_COMMAND Packet;\r
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
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
449 Retrieves media capacity information via sending Read Format\r
450 Capacity Packet Command.\r
451\r
452 Arguments:\r
453 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
454\r
455 Returns:\r
456 EFI_DEVICE_ERROR - Hardware error\r
457 EFI_SUCCESS - Success\r
458--*/\r
459{\r
460 //\r
461 // status returned by Read Capacity Packet Command\r
462 //\r
463 EFI_STATUS Status;\r
464 ATAPI_PACKET_COMMAND Packet;\r
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
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
501 (FormatData.LastLba2 << 16) |\r
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
529 Retrieves Sense Data from device via\r
530 sending Request Sense Packet Command.\r
531\r
532 Arguments:\r
533 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
534 SenseCounts - A pointer to the number of Sense Data returned.\r
535\r
536 Returns:\r
537 EFI_DEVICE_ERROR - Hardware error\r
538 EFI_SUCCESS - Success\r
539--*/\r
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
546\r
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
560\r
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
628\r
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
649\r
650 Arguments:\r
651 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
652\r
653 Returns:\r
654 EFI_DEVICE_ERROR - Hardware error\r
655 EFI_SUCCESS - Success\r
656--*/\r
657{\r
658 ATAPI_PACKET_COMMAND Packet;\r
659 EFI_STATUS Status;\r
660 UINT32 RetryIndex;\r
661 UINT32 MaximumRetryTimes;\r
662\r
663 MaximumRetryTimes = 2;\r
664 //\r
665 // fill command packet\r
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
697 IN USB_FLOPPY_DEV *UsbFloppyDevice,\r
698 IN VOID *Buffer,\r
699 IN EFI_LBA Lba,\r
700 IN UINTN NumberOfBlocks\r
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
707\r
708 Arguments:\r
709 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
710 Buffer - A pointer to the source buffer for the data.\r
711 The caller is responsible for either having implicit\r
712 or explicit ownership of the buffer.\r
713 Lba - The starting logical block address to written to\r
714 the device.\r
715 NumberOfBlocks - Indicates the number of blocks that the write\r
716 operation requests.\r
717\r
718 Returns:\r
719 EFI_DEVICE_ERROR - Hardware error\r
720 EFI_SUCCESS - Success\r
721--*/\r
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
734 UINT8 Index;\r
735\r
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
753 SectorCount = BlocksRemaining;\r
754 } else {\r
755 SectorCount = MaxBlock;\r
756 }\r
757\r
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
763\r
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
773\r
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
780\r
781 ByteCount = SectorCount * BlockSize;\r
782\r
783 TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);\r
784\r
785 Status = USBFloppyPacketCommand (\r
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
796 }\r
797 }\r
798\r
799 if (Index == 3) {\r
800 return EFI_DEVICE_ERROR;\r
801 }\r
802\r
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
820\r
821 Arguments:\r
822 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
823 MediaChange - Indicates whether media was changed.\r
824\r
825 Returns:\r
826 EFI_DEVICE_ERROR - Hardware error\r
827 EFI_SUCCESS - Success\r
828 EFI_INVALID_PARAMETER - Parameter is error\r
829--*/\r
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
842 BOOLEAN NeedReadCapacity;\r
843 //\r
844 // a flag used to determine whether need to perform Read Capacity command.\r
845 //\r
846\r
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
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
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
882\r
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
889\r
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
926 case USBFLOPPY2:\r
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
933 UsbFloppyDevice->DeviceType = USBFLOPPY;\r
934 Status = EFI_DEVICE_ERROR;\r
935 }\r
936 break;\r
937\r
938 case USBFLOPPY:\r
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
945 UsbFloppyDevice->DeviceType = USBFLOPPY2;\r
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
1005\r
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
1087 Retrieves media capacity information via sending Read Format\r
1088 Capacity Packet Command.\r
1089\r
1090 Arguments:\r
1091 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
1092\r
1093 Returns:\r
1094 EFI_DEVICE_ERROR - Hardware error\r
1095 EFI_SUCCESS - Success\r
1096\r
1097--*/\r
1098{\r
1099 //\r
1100 // status returned by Read Capacity Packet Command\r
1101 //\r
1102 EFI_STATUS Status;\r
1103 ATAPI_PACKET_COMMAND Packet;\r
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
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
1171 Retrieves media capacity information via sending Read Format\r
1172 Capacity Packet Command.\r
1173\r
1174 Arguments:\r
1175 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
1176\r
1177 Returns:\r
1178 EFI_DEVICE_ERROR - Hardware error\r
1179 EFI_SUCCESS - Success\r
1180\r
1181--*/\r
1182{\r
1183 //\r
1184 // status returned by Read Capacity Packet Command\r
1185 //\r
1186 EFI_STATUS Status;\r
1187 ATAPI_PACKET_COMMAND Packet;\r
1188 UFI_MODE_PARAMETER_PAGE_1C ModePage1C;\r
1189\r
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
1246\r
1247 Arguments:\r
1248 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
1249\r
1250 Returns:\r
1251 EFI_DEVICE_ERROR - Hardware error\r
1252 EFI_SUCCESS - Success\r
1253\r
1254--*/\r
1255{\r
1256 //\r
1257 // status returned by Read Capacity Packet Command\r
1258 //\r
1259 EFI_STATUS Status;\r
1260 ATAPI_PACKET_COMMAND Packet;\r
1261 UFI_MODE_PARAMETER_HEADER Header;\r
1262 UINT32 Size;\r
1263\r
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
1302\r
1303 Arguments:\r
1304 UsbFloppyDevice - The USB_FLOPPY_DEV instance.\r
1305\r
1306 Returns:\r
1307 EFI_DEVICE_ERROR - Hardware error\r
1308 EFI_SUCCESS - Success\r
1309\r
1310--*/\r
1311{\r
1312 //\r
1313 // status returned by Read Capacity Packet Command\r
1314 //\r
1315 EFI_STATUS Status;\r
1316 ATAPI_PACKET_COMMAND Packet;\r
1317 SCSI_MODE_PARAMETER_HEADER6 Header;\r
1318 UINT32 Size;\r
1319\r
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
1369 if ((SensePtr->sense_key == SK_NOT_READY) &&\r
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
1398\r
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