3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 IN IDE_BLK_IO_DEV
*IdeDev
34 This function is used to get the current status of the media residing
35 in the LS-120 drive or ZIP drive. The media status is returned in the
39 IDE_BLK_IO_DEV IN *IdeDev
40 pointer pointing to IDE_BLK_IO_DEV data structure, used
41 to record all the information of the IDE device.
45 The media status is achieved successfully and the media
49 Get Media Status Command is failed.
52 There is no media in the drive.
55 The media is writing protected.
58 This function must be called after the LS120EnableMediaStatus()
59 with second parameter set to TRUE
60 (means enable media status notification) is called.
62 // TODO: function comment is missing 'Routine Description:'
63 // TODO: function comment is missing 'Arguments:'
64 // TODO: IdeDev - add argument and description to function comment
70 // Poll Alternate Register for BSY clear within timeout.
72 EfiStatus
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
73 if (EFI_ERROR (EfiStatus
)) {
74 return EFI_DEVICE_ERROR
;
78 // Select device via Device/Head Register.
80 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4 | 0xe0);
81 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
84 // Poll Alternate Register for DRDY set within timeout.
85 // After device is selected, DRDY set indicates the device is ready to
88 EfiStatus
= DRDYReady2 (IdeDev
, ATATIMEOUT
);
89 if (EFI_ERROR (EfiStatus
)) {
90 return EFI_DEVICE_ERROR
;
94 // Get Media Status Command is sent
96 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, 0xDA);
99 // BSY bit will clear after command is complete.
101 EfiStatus
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
102 if (EFI_ERROR (EfiStatus
)) {
103 return EFI_DEVICE_ERROR
;
107 // the media status is returned by the command in the ERROR register
109 StatusValue
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
111 if (StatusValue
& bit1
) {
115 if (StatusValue
& bit6
) {
116 return EFI_WRITE_PROTECTED
;
124 LS120EnableMediaStatus (
125 IN IDE_BLK_IO_DEV
*IdeDev
,
130 LS120EnableMediaStatus
133 This function is used to send Enable Media Status Notification Command
134 or Disable Media Status Notification Command.
137 IDE_BLK_IO_DEV IN *IdeDev
138 pointer pointing to IDE_BLK_IO_DEV data structure, used
139 to record all the information of the IDE device.
142 a flag that indicates whether enable or disable media
147 If command completes successfully.
155 // TODO: function comment is missing 'Routine Description:'
156 // TODO: function comment is missing 'Arguments:'
157 // TODO: IdeDev - add argument and description to function comment
158 // TODO: Enable - add argument and description to function comment
164 // Poll Alternate Register for BSY clear within timeout.
166 Status
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
167 if (EFI_ERROR (Status
)) {
168 return EFI_DEVICE_ERROR
;
172 // Select device via Device/Head Register.
174 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4 | 0xe0);
175 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
178 // Poll Alternate Register for DRDY set within timeout.
179 // After device is selected, DRDY set indicates the device is ready to
182 Status
= DRDYReady2 (IdeDev
, ATATIMEOUT
);
183 if (EFI_ERROR (Status
)) {
184 return EFI_DEVICE_ERROR
;
189 // 0x95: Enable media status notification
191 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x95);
194 // 0x31: Disable media status notification
196 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x31);
199 // Set Feature Command is sent
201 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, 0xEF);
204 // BSY bit will clear after command is complete.
206 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
207 if (EFI_ERROR (Status
)) {
208 return EFI_DEVICE_ERROR
;
216 IN IDE_BLK_IO_DEV
*IdeDev
224 This function is called by DiscoverIdeDevice() during its device
227 Its main purpose is to get enough information for the device media
228 to fill in the Media data structure of the Block I/O Protocol interface.
230 There are 5 steps to reach such objective:
232 1. Sends out the ATAPI Identify Command to the specified device.
233 Only ATAPI device responses to this command. If the command succeeds,
234 it returns the Identify data structure which filled with information
235 about the device. Since the ATAPI device contains removable media,
236 the only meaningful information is the device module name.
238 2. Sends out ATAPI Inquiry Packet Command to the specified device.
239 This command will return inquiry data of the device, which contains
240 the device type information.
242 3. Allocate sense data space for future use. We don't detect the media
243 presence here to improvement boot performance, especially when CD
244 media is present. The media detection will be performed just before
245 each BLK_IO read/write
248 IDE_BLK_IO_DEV IN *IdeDev
249 pointer pointing to IDE_BLK_IO_DEV data structure, used
250 to record all the information of the IDE device.
254 Identify ATAPI device successfully.
257 ATAPI Identify Device Command failed or device type
258 is not supported by this IDE driver.
261 Parameter "IdeDev" will be updated in this function.
263 // TODO: function comment is missing 'Routine Description:'
264 // TODO: function comment is missing 'Arguments:'
265 // TODO: IdeDev - add argument and description to function comment
266 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
267 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
269 EFI_IDENTIFY_DATA
*AtapiIdentifyPointer
;
277 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
279 AtapiIdentifyPointer
= AllocatePool (sizeof (EFI_IDENTIFY_DATA
));
280 if (AtapiIdentifyPointer
== NULL
) {
281 return EFI_OUT_OF_RESOURCES
;
284 // Send ATAPI Identify Command to get IDENTIFY data.
286 Status
= AtaPioDataIn (
288 (VOID
*) AtapiIdentifyPointer
,
289 sizeof (EFI_IDENTIFY_DATA
),
290 ATAPI_IDENTIFY_DEVICE_CMD
,
298 if (EFI_ERROR (Status
)) {
299 gBS
->FreePool (AtapiIdentifyPointer
);
300 return EFI_DEVICE_ERROR
;
303 IdeDev
->pIdData
= AtapiIdentifyPointer
;
304 PrintAtaModuleName (IdeDev
);
307 // Send ATAPI Inquiry Packet Command to get INQUIRY data.
309 Status
= AtapiInquiry (IdeDev
);
310 if (EFI_ERROR (Status
)) {
311 gBS
->FreePool (IdeDev
->pIdData
);
313 // Make sure the pIdData will not be freed again.
315 IdeDev
->pIdData
= NULL
;
316 return EFI_DEVICE_ERROR
;
319 // Get media removable info from INQUIRY data.
321 IdeDev
->BlkIo
.Media
->RemovableMedia
= (UINT8
) ((IdeDev
->pInquiryData
->RMB
& 0x80) == 0x80);
324 // Identify device type via INQUIRY data.
326 switch (IdeDev
->pInquiryData
->peripheral_type
& 0x1f) {
334 // device is LS120 or ZIP drive.
336 IdeDev
->Type
= IdeMagnetic
;
338 IdeDev
->BlkIo
.Media
->MediaId
= 0;
340 // Give initial value
342 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
344 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
345 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
353 IdeDev
->Type
= IdeCdRom
;
354 IdeDev
->BlkIo
.Media
->MediaId
= 0;
356 // Give initial value
358 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
360 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
361 IdeDev
->BlkIo
.Media
->BlockSize
= 0x800;
362 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
381 IdeDev
->Type
= IdeUnknown
;
382 gBS
->FreePool (IdeDev
->pIdData
);
383 gBS
->FreePool (IdeDev
->pInquiryData
);
385 // Make sure the pIdData and pInquiryData will not be freed again.
387 IdeDev
->pIdData
= NULL
;
388 IdeDev
->pInquiryData
= NULL
;
389 return EFI_DEVICE_ERROR
;
393 // original sense data numbers
395 IdeDev
->SenseDataNumber
= 20;
397 IdeDev
->SenseData
= AllocatePool (IdeDev
->SenseDataNumber
* sizeof (REQUEST_SENSE_DATA
));
398 if (IdeDev
->SenseData
== NULL
) {
399 gBS
->FreePool (IdeDev
->pIdData
);
400 gBS
->FreePool (IdeDev
->pInquiryData
);
402 // Make sure the pIdData and pInquiryData will not be freed again.
404 IdeDev
->pIdData
= NULL
;
405 IdeDev
->pInquiryData
= NULL
;
406 return EFI_OUT_OF_RESOURCES
;
414 IN IDE_BLK_IO_DEV
*IdeDev
421 Sends out ATAPI Inquiry Packet Command to the specified device.
422 This command will return INQUIRY data of the device.
425 IDE_BLK_IO_DEV IN *IdeDev
426 pointer pointing to IDE_BLK_IO_DEV data structure, used
427 to record all the information of the IDE device.
431 Inquiry command completes successfully.
434 Inquiry command failed.
436 Parameter "IdeDev" will be updated in this function.
438 // TODO: function comment is missing 'Routine Description:'
439 // TODO: function comment is missing 'Arguments:'
440 // TODO: IdeDev - add argument and description to function comment
442 ATAPI_PACKET_COMMAND Packet
;
444 INQUIRY_DATA
*InquiryData
;
447 // prepare command packet for the ATAPI Inquiry Packet Command.
449 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
450 Packet
.Inquiry
.opcode
= INQUIRY
;
451 Packet
.Inquiry
.page_code
= 0;
452 Packet
.Inquiry
.allocation_length
= sizeof (INQUIRY_DATA
);
454 InquiryData
= AllocatePool (sizeof (INQUIRY_DATA
));
455 if (InquiryData
== NULL
) {
456 return EFI_DEVICE_ERROR
;
460 // Send command packet and get requested Inquiry data.
462 Status
= AtapiPacketCommandIn (
465 (UINT16
*) InquiryData
,
466 sizeof (INQUIRY_DATA
),
469 if (EFI_ERROR (Status
)) {
470 gBS
->FreePool (InquiryData
);
471 return EFI_DEVICE_ERROR
;
474 IdeDev
->pInquiryData
= InquiryData
;
480 AtapiPacketCommandIn (
481 IN IDE_BLK_IO_DEV
*IdeDev
,
482 IN ATAPI_PACKET_COMMAND
*Packet
,
492 This function is used to send out ATAPI commands conforms to the
493 Packet Command with PIO Data In Protocol.
496 IDE_BLK_IO_DEV IN *IdeDev
497 pointer pointing to IDE_BLK_IO_DEV data structure, used
498 to record all the information of the IDE device.
500 ATAPI_PACKET_COMMAND IN *Packet
501 pointer pointing to ATAPI_PACKET_COMMAND data structure
502 which contains the contents of the command.
505 buffer contained data transferred from device to host.
508 data size in byte unit of the buffer.
511 this parameter is used to specify the timeout
512 value for the PioReadWriteData() function.
516 send out the ATAPI packet command successfully
517 and device sends data successfully.
520 the device failed to send data.
524 // TODO: function comment is missing 'Routine Description:'
525 // TODO: function comment is missing 'Arguments:'
526 // TODO: IdeDev - add argument and description to function comment
527 // TODO: Packet - add argument and description to function comment
528 // TODO: Buffer - add argument and description to function comment
529 // TODO: ByteCount - add argument and description to function comment
530 // TODO: TimeOut - add argument and description to function comment
532 UINT16
*CommandIndex
;
537 // Set all the command parameters by fill related registers.
538 // Before write to all the following registers, BSY and DRQ must be 0.
540 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
541 if (EFI_ERROR (Status
)) {
546 // Select device via Device/Head Register.
550 IdeDev
->IoPort
->Head
,
551 (UINT8
) ((IdeDev
->Device
<< 4) | DEFAULT_CMD
) // DEFAULT_CMD: 0xa0 (1010,0000)
557 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x00);
560 // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
561 // determine how many data should be transferred.
565 IdeDev
->IoPort
->CylinderLsb
,
566 (UINT8
) (MAX_ATAPI_BYTE_COUNT
& 0x00ff)
570 IdeDev
->IoPort
->CylinderMsb
,
571 (UINT8
) (MAX_ATAPI_BYTE_COUNT
>> 8)
575 // DEFAULT_CTL:0x0a (0000,1010)
578 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DEFAULT_CTL
);
581 // Send Packet command to inform device
582 // that the following data bytes are command packet.
584 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, PACKET_CMD
);
586 Status
= DRQReady (IdeDev
, ATAPITIMEOUT
);
587 if (EFI_ERROR (Status
)) {
592 // Send out command packet
594 CommandIndex
= Packet
->Data16
;
595 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
597 IDEWritePortW (IdeDev
->PciIo
, IdeDev
->IoPort
->Data
, *CommandIndex
);
602 // call PioReadWriteData() function to get
603 // requested transfer data form device.
605 return PioReadWriteData (IdeDev
, Buffer
, ByteCount
, 1, TimeOut
);
609 AtapiPacketCommandOut (
610 IN IDE_BLK_IO_DEV
*IdeDev
,
611 IN ATAPI_PACKET_COMMAND
*Packet
,
618 AtapiPacketCommandOut
621 This function is used to send out ATAPI commands conforms to the
622 Packet Command with PIO Data Out Protocol.
625 IDE_BLK_IO_DEV IN *IdeDev
626 pointer pointing to IDE_BLK_IO_DEV data structure, used
627 to record all the information of the IDE device.
629 ATAPI_PACKET_COMMAND IN *Packet
630 pointer pointing to ATAPI_PACKET_COMMAND data structure
631 which contains the contents of the command.
634 buffer contained data transferred from host to device.
637 data size in byte unit of the buffer.
640 this parameter is used to specify the timeout
641 value for the PioReadWriteData() function.
645 send out the ATAPI packet command successfully
646 and device received data successfully.
649 the device failed to send data.
654 // TODO: function comment is missing 'Routine Description:'
655 // TODO: function comment is missing 'Arguments:'
656 // TODO: IdeDev - add argument and description to function comment
657 // TODO: Packet - add argument and description to function comment
658 // TODO: Buffer - add argument and description to function comment
659 // TODO: ByteCount - add argument and description to function comment
660 // TODO: TimeOut - add argument and description to function comment
662 UINT16
*CommandIndex
;
667 // set all the command parameters
668 // Before write to all the following registers, BSY and DRQ must be 0.
670 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
671 if (EFI_ERROR (Status
)) {
676 // Select device via Device/Head Register.
680 IdeDev
->IoPort
->Head
,
681 (UINT8
) ((IdeDev
->Device
<< 4) | DEFAULT_CMD
) // DEFAULT_CMD: 0xa0 (1010,0000)
687 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x00);
690 // set the transfersize to MAX_ATAPI_BYTE_COUNT to
691 // let the device determine how many data should be transferred.
695 IdeDev
->IoPort
->CylinderLsb
,
696 (UINT8
) (MAX_ATAPI_BYTE_COUNT
& 0x00ff)
700 IdeDev
->IoPort
->CylinderMsb
,
701 (UINT8
) (MAX_ATAPI_BYTE_COUNT
>> 8)
705 // DEFAULT_CTL:0x0a (0000,1010)
708 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DEFAULT_CTL
);
711 // Send Packet command to inform device
712 // that the following data bytes are command packet.
714 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, PACKET_CMD
);
716 Status
= DRQReady2 (IdeDev
, ATAPITIMEOUT
);
717 if (EFI_ERROR (Status
)) {
722 // Send out command packet
724 CommandIndex
= Packet
->Data16
;
725 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
726 IDEWritePortW (IdeDev
->PciIo
, IdeDev
->IoPort
->Data
, *CommandIndex
);
731 // call PioReadWriteData() function to send requested transfer data to device.
733 return PioReadWriteData (IdeDev
, Buffer
, ByteCount
, 0, TimeOut
);
738 IN IDE_BLK_IO_DEV
*IdeDev
,
749 This function is called by either AtapiPacketCommandIn() or
750 AtapiPacketCommandOut(). It is used to transfer data between
751 host and device. The data direction is specified by the fourth
756 IDE_BLK_IO_DEV IN *IdeDev
757 pointer pointing to IDE_BLK_IO_DEV data structure, used
758 to record all the information of the IDE device.
761 buffer contained data transferred between host and device.
764 data size in byte unit of the buffer.
767 flag used to determine the data transfer direction.
768 Read equals 1, means data transferred from device to host;
769 Read equals 0, means data transferred from host to device.
772 timeout value for wait DRQ ready before each data
777 data is transferred successfully.
780 the device failed to transfer data.
785 // TODO: function comment is missing 'Routine Description:'
786 // TODO: function comment is missing 'Arguments:'
787 // TODO: IdeDev - add argument and description to function comment
788 // TODO: Buffer - add argument and description to function comment
789 // TODO: ByteCount - add argument and description to function comment
790 // TODO: Read - add argument and description to function comment
791 // TODO: TimeOut - add argument and description to function comment
794 // required transfer data in word unit.
796 UINT32 RequiredWordCount
;
799 // actual transfer data in word unit.
801 UINT32 ActualWordCount
;
807 // containing status byte read from Status Register.
809 UINT8 StatusRegister
;
812 // No data transfer is premitted.
814 if (ByteCount
== 0) {
818 // for performance, we assert the ByteCount is an even number
819 // which is actually a resonable assumption
820 ASSERT((ByteCount
%2) == 0);
823 RequiredWordCount
= ByteCount
/ 2;
825 // ActuralWordCount means the word count of data really transferred.
829 while (ActualWordCount
< RequiredWordCount
) {
832 // before each data transfer stream, the host should poll DRQ bit ready,
833 // to see whether indicates device is ready to transfer data.
835 Status
= DRQReady2 (IdeDev
, TimeOut
);
836 if (EFI_ERROR (Status
)) {
837 return CheckErrorStatus (IdeDev
);
841 // read Status Register will clear interrupt
843 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
846 // get current data transfer size from Cylinder Registers.
850 (IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
) << 8) |
851 IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
)
855 WordCount
= EFI_MIN (WordCount
, (RequiredWordCount
- ActualWordCount
));
858 IDEReadPortWMultiple (
860 IdeDev
->IoPort
->Data
,
865 IDEWritePortWMultiple (
867 IdeDev
->IoPort
->Data
,
873 PtrBuffer
+= WordCount
;
874 ActualWordCount
+= WordCount
;
878 // After data transfer is completed, normally, DRQ bit should clear.
880 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
881 if (EFI_ERROR (Status
)) {
882 return EFI_DEVICE_ERROR
;
886 // read status register to check whether error happens.
888 return CheckErrorStatus (IdeDev
);
893 IN IDE_BLK_IO_DEV
*IdeDev
900 Sends out ATAPI Test Unit Ready Packet Command to the specified device
901 to find out whether device is accessible.
904 IDE_BLK_IO_DEV IN *IdeDev
905 pointer pointing to IDE_BLK_IO_DEV data structure, used
906 to record all the information of the IDE device.
910 device is accessible.
913 device is not accessible.
918 // TODO: function comment is missing 'Routine Description:'
919 // TODO: function comment is missing 'Arguments:'
920 // TODO: IdeDev - add argument and description to function comment
922 ATAPI_PACKET_COMMAND Packet
;
926 // fill command packet
928 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
929 Packet
.TestUnitReady
.opcode
= TEST_UNIT_READY
;
932 // send command packet
934 Status
= AtapiPacketCommandIn (IdeDev
, &Packet
, NULL
, 0, ATAPITIMEOUT
);
940 IN IDE_BLK_IO_DEV
*IdeDev
,
941 OUT UINTN
*SenseCounts
948 Sends out ATAPI Request Sense Packet Command to the specified device.
949 This command will return all the current Sense data in the device.
950 This function will pack all the Sense data in one single buffer.
953 IDE_BLK_IO_DEV IN *IdeDev
954 pointer pointing to IDE_BLK_IO_DEV data structure, used
955 to record all the information of the IDE device.
957 UINT16 OUT **SenseBuffers
958 allocated in this function, and freed by the calling function.
959 This buffer is used to accommodate all the sense data returned
963 record the unit size of the sense data block in the SenseBuffers,
965 UINTN OUT *BufNumbers
966 record the number of units in the SenseBuffers.
970 Request Sense command completes successfully.
973 Request Sense command failed.
978 // TODO: function comment is missing 'Routine Description:'
979 // TODO: function comment is missing 'Arguments:'
980 // TODO: IdeDev - add argument and description to function comment
981 // TODO: SenseCounts - add argument and description to function comment
984 REQUEST_SENSE_DATA
*Sense
;
986 BOOLEAN FetchSenseData
;
987 ATAPI_PACKET_COMMAND Packet
;
991 ZeroMem (IdeDev
->SenseData
, sizeof (REQUEST_SENSE_DATA
) * (IdeDev
->SenseDataNumber
));
993 // fill command packet for Request Sense Packet Command
995 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
996 Packet
.RequestSence
.opcode
= REQUEST_SENSE
;
997 Packet
.RequestSence
.allocation_length
= sizeof (REQUEST_SENSE_DATA
);
1000 // initialize pointer
1002 Ptr
= (UINT16
*) IdeDev
->SenseData
;
1004 // request sense data from device continuously until no sense data
1005 // exists in the device.
1007 for (FetchSenseData
= TRUE
; FetchSenseData
;) {
1009 Sense
= (REQUEST_SENSE_DATA
*) Ptr
;
1012 // send out Request Sense Packet Command and get one Sense data form device
1014 Status
= AtapiPacketCommandIn (
1018 sizeof (REQUEST_SENSE_DATA
),
1022 // failed to get Sense data
1024 if (EFI_ERROR (Status
)) {
1025 if (*SenseCounts
== 0) {
1026 return EFI_DEVICE_ERROR
;
1034 // We limit MAX sense data count to 20 in order to avoid dead loop. Some
1035 // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
1036 // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
1037 // supposed to be large enough for any ATAPI device.
1039 if ((Sense
->sense_key
!= SK_NO_SENSE
) && ((*SenseCounts
) < 20)) {
1041 // Ptr is word-based pointer
1043 Ptr
+= sizeof (REQUEST_SENSE_DATA
) / 2;
1047 // when no sense key, skip out the loop
1049 FetchSenseData
= FALSE
;
1058 IN IDE_BLK_IO_DEV
*IdeDev
1065 Sends out ATAPI Read Capacity Packet Command to the specified device.
1066 This command will return the information regarding the capacity of the
1067 media in the device.
1069 Current device status will impact device's response to the Read Capacity
1070 Command. For example, if the device once reset, the Read Capacity
1071 Command will fail. The Sense data record the current device status, so
1072 if the Read Capacity Command failed, the Sense data must be requested
1073 and be analyzed to determine if the Read Capacity Command should retry.
1077 IDE_BLK_IO_DEV IN *IdeDev
1078 pointer pointing to IDE_BLK_IO_DEV data structure, used
1079 to record all the information of the IDE device.
1083 Read Capacity Command finally completes successfully.
1086 Read Capacity Command failed because of device error.
1089 parameter "IdeDev" will be updated in this function.
1091 // TODO: function comment is missing 'Routine Description:'
1092 // TODO: function comment is missing 'Arguments:'
1093 // TODO: IdeDev - add argument and description to function comment
1094 // TODO: EFI_NOT_READY - add return value to function comment
1097 // status returned by Read Capacity Packet Command
1100 ATAPI_PACKET_COMMAND Packet
;
1103 // used for capacity data returned from ATAPI device
1105 READ_CAPACITY_DATA Data
;
1106 READ_FORMAT_CAPACITY_DATA FormatData
;
1108 ZeroMem (&Data
, sizeof (Data
));
1109 ZeroMem (&FormatData
, sizeof (FormatData
));
1111 if (IdeDev
->Type
== IdeCdRom
) {
1113 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1114 Packet
.Inquiry
.opcode
= READ_CAPACITY
;
1115 Status
= AtapiPacketCommandIn (
1119 sizeof (READ_CAPACITY_DATA
),
1125 // Type == IdeMagnetic
1127 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1128 Packet
.ReadFormatCapacity
.opcode
= READ_FORMAT_CAPACITY
;
1129 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
1130 Status
= AtapiPacketCommandIn (
1133 (UINT16
*) &FormatData
,
1134 sizeof (READ_FORMAT_CAPACITY_DATA
),
1139 if (!EFI_ERROR (Status
)) {
1141 if (IdeDev
->Type
== IdeCdRom
) {
1143 IdeDev
->BlkIo
.Media
->LastBlock
= (Data
.LastLba3
<< 24) |
1144 (Data
.LastLba2
<< 16) |
1145 (Data
.LastLba1
<< 8) |
1148 if (IdeDev
->BlkIo
.Media
->LastBlock
!= 0) {
1150 IdeDev
->BlkIo
.Media
->BlockSize
= (Data
.BlockSize3
<< 24) |
1151 (Data
.BlockSize2
<< 16) |
1152 (Data
.BlockSize1
<< 8) |
1155 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
1157 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1158 return EFI_DEVICE_ERROR
;
1161 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
1164 // Because the user data portion in the sector of the Data CD supported
1167 IdeDev
->BlkIo
.Media
->BlockSize
= 0x800;
1170 if (IdeDev
->Type
== IdeMagnetic
) {
1172 if (FormatData
.DesCode
== 3) {
1173 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1174 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1177 IdeDev
->BlkIo
.Media
->LastBlock
= (FormatData
.LastLba3
<< 24) |
1178 (FormatData
.LastLba2
<< 16) |
1179 (FormatData
.LastLba1
<< 8) |
1180 FormatData
.LastLba0
;
1181 if (IdeDev
->BlkIo
.Media
->LastBlock
!= 0) {
1182 IdeDev
->BlkIo
.Media
->LastBlock
--;
1184 IdeDev
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
1185 (FormatData
.BlockSize1
<< 8) |
1186 FormatData
.BlockSize0
;
1188 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
1190 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1192 // Return EFI_NOT_READY operation succeeds but returned capacity is 0
1194 return EFI_NOT_READY
;
1197 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
1206 return EFI_DEVICE_ERROR
;
1212 IN IDE_BLK_IO_DEV
*IdeDev
,
1213 OUT BOOLEAN
*MediaChange
1220 Used before read/write blocks from/to ATAPI device media.
1221 Since ATAPI device media is removable, it is necessary to detect
1222 whether media is present and get current present media's
1223 information, and if media has been changed, Block I/O Protocol
1224 need to be reinstalled.
1227 IDE_BLK_IO_DEV IN *IdeDev
1228 pointer pointing to IDE_BLK_IO_DEV data structure, used
1229 to record all the information of the IDE device.
1231 BOOLEAN OUT *MediaChange
1232 return value that indicates if the media of the device has been
1237 media found successfully.
1240 any error encounters during media detection.
1246 parameter IdeDev may be updated in this function.
1248 // TODO: function comment is missing 'Routine Description:'
1249 // TODO: function comment is missing 'Arguments:'
1250 // TODO: IdeDev - add argument and description to function comment
1251 // TODO: MediaChange - add argument and description to function comment
1254 EFI_STATUS ReadCapacityStatus
;
1255 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
1259 UINTN MaximumRetryTimes
;
1260 UINTN ReadyWaitFactor
;
1263 // a flag used to determine whether need to perform Read Capacity command.
1265 BOOLEAN NeedReadCapacity
;
1266 BOOLEAN WriteProtected
;
1271 CopyMem (&OldMediaInfo
, IdeDev
->BlkIo
.Media
, sizeof (OldMediaInfo
));
1272 // OldMediaInfo = *(IdeDev->BlkIo.Media);
1273 *MediaChange
= FALSE
;
1274 ReadCapacityStatus
= EFI_DEVICE_ERROR
;
1277 // if there is no media, or media is not changed,
1278 // the request sense command will detect faster than read capacity command.
1279 // read capacity command can be bypassed, thus improve performance.
1283 // Test Unit Ready command is used to detect whether device is accessible,
1284 // the device will produce corresponding Sense data.
1286 for (RetryIndex
= 0; RetryIndex
< 2; RetryIndex
++) {
1288 Status
= AtapiTestUnitReady (IdeDev
);
1289 if (!EFI_ERROR (Status
)) {
1291 // skip the loop if test unit command succeeds.
1296 Status
= AtapiSoftReset (IdeDev
);
1298 if (EFI_ERROR (Status
)) {
1299 AtaSoftReset (IdeDev
);
1304 NeedReadCapacity
= TRUE
;
1307 // at most retry 5 times
1309 MaximumRetryTimes
= 5;
1312 for (RetryIndex
= 0;
1313 (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
);
1316 Status
= AtapiRequestSense (IdeDev
, &SenseCounts
);
1318 if (!EFI_ERROR (Status
)) {
1320 // if first time there is no Sense Key, no need to read capacity any more
1322 if (!HaveSenseKey (IdeDev
->SenseData
, SenseCounts
) &&
1323 (IdeDev
->BlkIo
.Media
->MediaPresent
)) {
1325 if (RetryIndex
== 0) {
1326 NeedReadCapacity
= FALSE
;
1333 if (IsNoMedia (IdeDev
->SenseData
, SenseCounts
)) {
1334 NeedReadCapacity
= FALSE
;
1335 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1336 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1341 if (IsMediaChange (IdeDev
->SenseData
, SenseCounts
)) {
1342 NeedReadCapacity
= TRUE
;
1343 IdeDev
->BlkIo
.Media
->MediaId
++;
1348 if (IsMediaError (IdeDev
->SenseData
, SenseCounts
)) {
1349 return EFI_DEVICE_ERROR
;
1355 // retry once more, if request sense command met errors.
1361 if (NeedReadCapacity
) {
1363 // at most retry 5 times
1365 MaximumRetryTimes
= 5;
1367 // initial retry twice
1370 ReadyWaitFactor
= 2;
1372 for (RetryIndex
= 0;
1373 (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
);
1376 ReadCapacityStatus
= AtapiReadCapacity (IdeDev
);
1380 if (!EFI_ERROR (ReadCapacityStatus
)) {
1382 // Read Capacity succeeded
1388 if (ReadCapacityStatus
== EFI_NOT_READY
) {
1390 // If device not ready, wait here... waiting time increases by retry
1393 gBS
->Stall (ReadyWaitFactor
* 2000 * STALL_1_MILLI_SECOND
);
1403 // Other errors returned, requery sense data
1405 Status
= AtapiRequestSense (IdeDev
, &SenseCounts
);
1408 // If Request Sense data failed, reset the device and retry.
1410 if (EFI_ERROR (Status
)) {
1412 Status
= AtapiSoftReset (IdeDev
);
1415 // if ATAPI soft reset fail,
1416 // use stronger reset mechanism -- ATA soft reset.
1418 if (EFI_ERROR (Status
)) {
1419 AtaSoftReset (IdeDev
);
1431 if (IsNoMedia (IdeDev
->SenseData
, SenseCounts
)) {
1433 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1434 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1435 return EFI_NO_MEDIA
;
1438 if (IsMediaError (IdeDev
->SenseData
, SenseCounts
)) {
1439 return EFI_DEVICE_ERROR
;
1445 if (IsMediaChange (IdeDev
->SenseData
, SenseCounts
)) {
1446 IdeDev
->BlkIo
.Media
->MediaId
++;
1449 if (!IsDriveReady (IdeDev
->SenseData
, SenseCounts
, &NeedRetry
)) {
1452 // Drive not ready: if NeedRetry, then retry once more;
1453 // else return error
1457 // Stall 1 second to wait for drive becoming ready
1459 gBS
->Stall (1000 * STALL_1_MILLI_SECOND
);
1461 // reset retry variable to zero,
1462 // to make it retry for "drive in progress of becoming ready".
1467 AtapiSoftReset (IdeDev
);
1468 return EFI_DEVICE_ERROR
;
1472 // if read capacity fail not for above reasons, retry once more
1480 // tell whether the readcapacity process is successful or not in the end
1482 if (EFI_ERROR (ReadCapacityStatus
)) {
1483 return EFI_DEVICE_ERROR
;
1488 // the following code is to check the write-protected for LS120 media
1490 if ((IdeDev
->BlkIo
.Media
->MediaPresent
) && (IdeDev
->Type
== IdeMagnetic
)) {
1492 Status
= IsLS120orZipWriteProtected (IdeDev
, &WriteProtected
);
1493 if (!EFI_ERROR (Status
)) {
1495 if (WriteProtected
) {
1497 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
1500 IdeDev
->BlkIo
.Media
->ReadOnly
= FALSE
;
1506 if (IdeDev
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1508 // Media change information got from the device
1510 *MediaChange
= TRUE
;
1513 if (IdeDev
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1514 *MediaChange
= TRUE
;
1515 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1518 if (IdeDev
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1519 *MediaChange
= TRUE
;
1520 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1523 if (IdeDev
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1524 *MediaChange
= TRUE
;
1525 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1528 if (IdeDev
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1529 if (IdeDev
->BlkIo
.Media
->MediaPresent
) {
1531 // when change from no media to media present, reset the MediaId to 1.
1533 IdeDev
->BlkIo
.Media
->MediaId
= 1;
1536 // when no media, reset the MediaId to zero.
1538 IdeDev
->BlkIo
.Media
->MediaId
= 0;
1541 *MediaChange
= TRUE
;
1545 // if any change on current existing media,
1546 // the Block I/O protocol need to be reinstalled.
1549 gBS
->ReinstallProtocolInterface (
1551 &gEfiBlockIoProtocolGuid
,
1563 IN IDE_BLK_IO_DEV
*IdeDev
,
1566 IN UINTN NumberOfBlocks
1573 This function is called by the AtapiBlkIoReadBlocks() to perform
1574 read from media in block unit.
1576 The main command used to access media here is READ(10) Command.
1577 READ(10) Command requests that the ATAPI device media transfer
1578 specified data to the host. Data is transferred in block(sector)
1579 unit. The maximum number of blocks that can be transferred once is
1580 65536. This is the main difference between READ(10) and READ(12)
1581 Command. The maximum number of blocks in READ(12) is 2 power 32.
1584 IDE_BLK_IO_DEV IN *IdeDev
1585 pointer pointing to IDE_BLK_IO_DEV data structure, used
1586 to record all the information of the IDE device.
1589 A pointer to the destination buffer for the data.
1592 The starting logical block address to read from
1593 on the device media.
1595 UINTN IN NumberOfBlocks
1596 The number of transfer data blocks.
1599 return status is fully dependent on the return status
1600 of AtapiPacketCommandIn() function.
1605 // TODO: function comment is missing 'Routine Description:'
1606 // TODO: function comment is missing 'Arguments:'
1607 // TODO: IdeDev - add argument and description to function comment
1608 // TODO: Buffer - add argument and description to function comment
1609 // TODO: Lba - add argument and description to function comment
1610 // TODO: NumberOfBlocks - add argument and description to function comment
1613 ATAPI_PACKET_COMMAND Packet
;
1614 READ10_CMD
*Read10Packet
;
1616 UINTN BlocksRemaining
;
1626 // fill command packet for Read(10) command
1628 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1629 Read10Packet
= &Packet
.Read10
;
1630 Lba32
= (UINT32
) Lba
;
1633 BlockSize
= IdeDev
->BlkIo
.Media
->BlockSize
;
1636 // limit the data bytes that can be transferred by one Read(10) Command
1638 MaxBlock
= (UINT16
) (65536 / BlockSize
);
1640 BlocksRemaining
= NumberOfBlocks
;
1642 Status
= EFI_SUCCESS
;
1643 while (BlocksRemaining
> 0) {
1645 if (BlocksRemaining
<= MaxBlock
) {
1647 SectorCount
= (UINT16
) BlocksRemaining
;
1650 SectorCount
= MaxBlock
;
1654 // fill the Packet data structure
1657 Read10Packet
->opcode
= READ_10
;
1660 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1661 // Lba0 is MSB, Lba3 is LSB
1663 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
1664 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
1665 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
1666 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
1669 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1670 // TranLen0 is MSB, TranLen is LSB
1672 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
1673 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
1675 ByteCount
= SectorCount
* BlockSize
;
1677 if (IdeDev
->Type
== IdeCdRom
) {
1678 TimeOut
= CDROMLONGTIMEOUT
;
1680 TimeOut
= ATAPILONGTIMEOUT
;
1683 Status
= AtapiPacketCommandIn (
1686 (UINT16
*) PtrBuffer
,
1690 if (EFI_ERROR (Status
)) {
1694 Lba32
+= SectorCount
;
1695 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
1696 BlocksRemaining
-= SectorCount
;
1704 IN IDE_BLK_IO_DEV
*IdeDev
,
1707 IN UINTN NumberOfBlocks
1714 This function is called by the AtapiBlkIoWriteBlocks() to perform
1715 write onto media in block unit.
1716 The main command used to access media here is Write(10) Command.
1717 Write(10) Command requests that the ATAPI device media transfer
1718 specified data to the host. Data is transferred in block (sector)
1719 unit. The maximum number of blocks that can be transferred once is
1723 IDE_BLK_IO_DEV IN *IdeDev
1724 pointer pointing to IDE_BLK_IO_DEV data structure, used
1725 to record all the information of the IDE device.
1728 A pointer to the source buffer for the data.
1731 The starting logical block address to write onto
1734 UINTN IN NumberOfBlocks
1735 The number of transfer data blocks.
1738 return status is fully dependent on the return status
1739 of AtapiPacketCommandOut() function.
1744 // TODO: function comment is missing 'Routine Description:'
1745 // TODO: function comment is missing 'Arguments:'
1746 // TODO: IdeDev - add argument and description to function comment
1747 // TODO: Buffer - add argument and description to function comment
1748 // TODO: Lba - add argument and description to function comment
1749 // TODO: NumberOfBlocks - add argument and description to function comment
1752 ATAPI_PACKET_COMMAND Packet
;
1753 READ10_CMD
*Read10Packet
;
1756 UINTN BlocksRemaining
;
1765 // fill command packet for Write(10) command
1766 // Write(10) command packet has the same data structure as
1767 // Read(10) command packet,
1768 // so here use the Read10Packet data structure
1769 // for the Write(10) command packet.
1771 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1772 Read10Packet
= &Packet
.Read10
;
1774 Lba32
= (UINT32
) Lba
;
1777 BlockSize
= IdeDev
->BlkIo
.Media
->BlockSize
;
1780 // limit the data bytes that can be transferred by one Read(10) Command
1782 MaxBlock
= (UINT16
) (65536 / BlockSize
);
1784 BlocksRemaining
= NumberOfBlocks
;
1786 Status
= EFI_SUCCESS
;
1787 while (BlocksRemaining
> 0) {
1789 if (BlocksRemaining
>= MaxBlock
) {
1790 SectorCount
= MaxBlock
;
1792 SectorCount
= (UINT16
) BlocksRemaining
;
1796 // Command code is WRITE_10.
1798 Read10Packet
->opcode
= WRITE_10
;
1801 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1802 // Lba0 is MSB, Lba3 is LSB
1804 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
1805 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
1806 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
1807 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
1810 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1811 // TranLen0 is MSB, TranLen is LSB
1813 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
1814 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
1816 ByteCount
= SectorCount
* BlockSize
;
1818 Status
= AtapiPacketCommandOut (
1821 (UINT16
*) PtrBuffer
,
1825 if (EFI_ERROR (Status
)) {
1829 Lba32
+= SectorCount
;
1830 PtrBuffer
= ((UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
);
1831 BlocksRemaining
-= SectorCount
;
1839 IN IDE_BLK_IO_DEV
*IdeDev
1846 This function is used to implement the Soft Reset on the specified
1847 ATAPI device. Different from the AtaSoftReset(), here reset is a ATA
1848 Soft Reset Command special for ATAPI device, and it only take effects
1849 on the specified ATAPI device, not on the whole IDE bus.
1850 Since the ATAPI soft reset is needed when device is in exceptional
1851 condition (such as BSY bit is always set ), I think the Soft Reset
1852 command should be sent without waiting for the BSY clear and DRDY
1854 This function is called by IdeBlkIoReset(),
1855 a interface function of Block I/O protocol.
1859 IDE_BLK_IO_DEV IN *IdeDev
1860 pointer pointing to IDE_BLK_IO_DEV data structure, used
1861 to record all the information of the IDE device.
1865 Soft reset completes successfully.
1868 Any step during the reset process is failed.
1873 // TODO: function comment is missing 'Routine Description:'
1874 // TODO: function comment is missing 'Arguments:'
1875 // TODO: IdeDev - add argument and description to function comment
1882 // for ATAPI device, no need to wait DRDY ready after device selecting.
1883 // (bit7 and bit5 are both set to 1 for backward compatibility)
1885 DeviceSelect
= (UINT8
) (((bit7
| bit5
) | (IdeDev
->Device
<< 4)));
1886 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
1888 Command
= ATAPI_SOFT_RESET_CMD
;
1889 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, Command
);
1892 // BSY cleared is the only status return to the host by the device
1893 // when reset is completed.
1894 // slave device needs at most 31s to clear BSY
1896 Status
= WaitForBSYClear (IdeDev
, 31000);
1897 if (EFI_ERROR (Status
)) {
1898 return EFI_DEVICE_ERROR
;
1902 // stall 5 seconds to make the device status stable
1904 gBS
->Stall (5000000);
1910 AtapiBlkIoReadBlocks (
1911 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
1914 IN UINTN BufferSize
,
1919 AtapiBlkIoReadBlocks
1922 This function is the ATAPI implementation for ReadBlocks in the
1923 Block I/O Protocol interface.
1926 IDE_BLK_IO_DEV IN *IdeBlkIoDev
1927 Indicates the calling context.
1930 The media id that the read request is for.
1933 The starting logical block address to read from
1937 The size of the Buffer in bytes. This must be a
1938 multiple of the intrinsic block size of the device.
1941 A pointer to the destination buffer for the data.
1942 The caller is responsible for either having implicit
1943 or explicit ownership of the memory that data is read into.
1947 Read Blocks successfully.
1953 There is no media in the device.
1956 The MediaId is not for the current media.
1959 The BufferSize parameter is not a multiple of the
1960 intrinsic block size of the device.
1962 EFI_INVALID_PARAMETER
1963 The read request contains LBAs that are not valid,
1964 or the data buffer is not valid.
1969 // TODO: function comment is missing 'Routine Description:'
1970 // TODO: function comment is missing 'Arguments:'
1971 // TODO: IdeBlkIoDevice - add argument and description to function comment
1972 // TODO: MediaId - add argument and description to function comment
1973 // TODO: LBA - add argument and description to function comment
1974 // TODO: BufferSize - add argument and description to function comment
1975 // TODO: Buffer - add argument and description to function comment
1977 EFI_BLOCK_IO_MEDIA
*Media
;
1979 UINTN NumberOfBlocks
;
1982 BOOLEAN MediaChange
;
1984 if (Buffer
== NULL
) {
1985 return EFI_INVALID_PARAMETER
;
1988 if (BufferSize
== 0) {
1993 // ATAPI device media is removable, so it is a must
1994 // to detect media first before read operation
1996 MediaChange
= FALSE
;
1997 Status
= AtapiDetectMedia (IdeBlkIoDevice
, &MediaChange
);
1998 if (EFI_ERROR (Status
)) {
2000 if (IdeBlkIoDevice
->Cache
!= NULL
) {
2001 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2002 IdeBlkIoDevice
->Cache
= NULL
;
2008 // Get the intrinsic block size
2010 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
2011 BlockSize
= Media
->BlockSize
;
2013 NumberOfBlocks
= BufferSize
/ BlockSize
;
2015 if (!(Media
->MediaPresent
)) {
2017 if (IdeBlkIoDevice
->Cache
!= NULL
) {
2018 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2019 IdeBlkIoDevice
->Cache
= NULL
;
2021 return EFI_NO_MEDIA
;
2025 if ((MediaId
!= Media
->MediaId
) || MediaChange
) {
2027 if (IdeBlkIoDevice
->Cache
!= NULL
) {
2028 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2029 IdeBlkIoDevice
->Cache
= NULL
;
2031 return EFI_MEDIA_CHANGED
;
2034 if (BufferSize
% BlockSize
!= 0) {
2035 return EFI_BAD_BUFFER_SIZE
;
2038 if (LBA
> Media
->LastBlock
) {
2039 return EFI_INVALID_PARAMETER
;
2042 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
2043 return EFI_INVALID_PARAMETER
;
2046 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
2047 return EFI_INVALID_PARAMETER
;
2051 // if all the parameters are valid, then perform read sectors command
2052 // to transfer data from device to host.
2054 Status
= AtapiReadSectors (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
2055 if (EFI_ERROR (Status
)) {
2056 return EFI_DEVICE_ERROR
;
2060 // Read blocks succeeded
2064 // save the first block to the cache for performance
2066 if (LBA
== 0 && !IdeBlkIoDevice
->Cache
) {
2067 IdeBlkIoDevice
->Cache
= AllocatePool (BlockSize
);
2068 if (IdeBlkIoDevice
!= NULL
) {
2069 CopyMem ((UINT8
*) IdeBlkIoDevice
->Cache
, (UINT8
*) Buffer
, BlockSize
);
2078 AtapiBlkIoWriteBlocks (
2079 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
2082 IN UINTN BufferSize
,
2087 AtapiBlkIoWriteBlocks
2090 This function is the ATAPI implementation for WriteBlocks in the
2091 Block I/O Protocol interface.
2094 EFI_BLOCK_IO IN *This
2095 Indicates the calling context.
2098 The media id that the write request is for.
2101 The starting logical block address to write onto
2105 The size of the Buffer in bytes. This must be a
2106 multiple of the intrinsic block size of the device.
2109 A pointer to the source buffer for the data.
2110 The caller is responsible for either having implicit
2111 or explicit ownership of the memory that data is
2116 Write Blocks successfully.
2119 Write Blocks failed.
2122 There is no media in the device.
2125 The MediaId is not for the current media.
2128 The BufferSize parameter is not a multiple of the
2129 intrinsic block size of the device.
2131 EFI_INVALID_PARAMETER
2132 The write request contains LBAs that are not valid,
2133 or the data buffer is not valid.
2138 // TODO: function comment is missing 'Routine Description:'
2139 // TODO: function comment is missing 'Arguments:'
2140 // TODO: IdeBlkIoDevice - add argument and description to function comment
2141 // TODO: MediaId - add argument and description to function comment
2142 // TODO: LBA - add argument and description to function comment
2143 // TODO: BufferSize - add argument and description to function comment
2144 // TODO: Buffer - add argument and description to function comment
2145 // TODO: EFI_MEDIA_CHANGED - add return value to function comment
2146 // TODO: EFI_WRITE_PROTECTED - add return value to function comment
2149 EFI_BLOCK_IO_MEDIA
*Media
;
2151 UINTN NumberOfBlocks
;
2153 BOOLEAN MediaChange
;
2155 if (LBA
== 0 && IdeBlkIoDevice
->Cache
) {
2156 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2157 IdeBlkIoDevice
->Cache
= NULL
;
2160 if (Buffer
== NULL
) {
2161 return EFI_INVALID_PARAMETER
;
2164 if (BufferSize
== 0) {
2169 // ATAPI device media is removable,
2170 // so it is a must to detect media first before write operation
2172 MediaChange
= FALSE
;
2173 Status
= AtapiDetectMedia (IdeBlkIoDevice
, &MediaChange
);
2174 if (EFI_ERROR (Status
)) {
2176 if (LBA
== 0 && IdeBlkIoDevice
->Cache
) {
2177 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2178 IdeBlkIoDevice
->Cache
= NULL
;
2184 // Get the intrinsic block size
2186 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
2187 BlockSize
= Media
->BlockSize
;
2188 NumberOfBlocks
= BufferSize
/ BlockSize
;
2190 if (!(Media
->MediaPresent
)) {
2192 if (LBA
== 0 && IdeBlkIoDevice
->Cache
) {
2193 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2194 IdeBlkIoDevice
->Cache
= NULL
;
2196 return EFI_NO_MEDIA
;
2199 if ((MediaId
!= Media
->MediaId
) || MediaChange
) {
2201 if (LBA
== 0 && IdeBlkIoDevice
->Cache
) {
2202 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
2203 IdeBlkIoDevice
->Cache
= NULL
;
2205 return EFI_MEDIA_CHANGED
;
2208 if (Media
->ReadOnly
) {
2209 return EFI_WRITE_PROTECTED
;
2212 if (BufferSize
% BlockSize
!= 0) {
2213 return EFI_BAD_BUFFER_SIZE
;
2216 if (LBA
> Media
->LastBlock
) {
2217 return EFI_INVALID_PARAMETER
;
2220 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
2221 return EFI_INVALID_PARAMETER
;
2224 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
2225 return EFI_INVALID_PARAMETER
;
2229 // if all the parameters are valid,
2230 // then perform write sectors command to transfer data from host to device.
2232 Status
= AtapiWriteSectors (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
2233 if (EFI_ERROR (Status
)) {
2234 return EFI_DEVICE_ERROR
;
2242 // The following functions are a set of helper functions,
2243 // which are used to parse sense key returned by the device.
2248 IN REQUEST_SENSE_DATA
*SenseData
,
2249 IN UINTN SenseCounts
2253 Routine Description:
2255 TODO: Add function description
2259 SenseData - TODO: add argument description
2260 SenseCounts - TODO: add argument description
2264 TODO: add return values
2268 REQUEST_SENSE_DATA
*SensePointer
;
2273 SensePointer
= SenseData
;
2275 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2277 // Sense Key is SK_NOT_READY (0x2),
2278 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
2280 if ((SensePointer
->sense_key
== SK_NOT_READY
) &&
2281 (SensePointer
->addnl_sense_code
== ASC_NO_MEDIA
)) {
2294 IN REQUEST_SENSE_DATA
*SenseData
,
2295 IN UINTN SenseCounts
2302 Test if the device meets a media error after media changed
2305 EQUEST_SENSE_DATA IN *SenseData
2306 pointer pointing to ATAPI device sense data list.
2307 UINTN IN SenseCounts
2308 sense data number of the list
2312 Device meets a media error
2317 // TODO: function comment is missing 'Routine Description:'
2318 // TODO: function comment is missing 'Arguments:'
2319 // TODO: SenseData - add argument and description to function comment
2320 // TODO: SenseCounts - add argument and description to function comment
2322 REQUEST_SENSE_DATA
*SensePointer
;
2327 SensePointer
= SenseData
;
2329 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2331 switch (SensePointer
->sense_key
) {
2333 case SK_MEDIUM_ERROR
:
2335 // Sense Key is SK_MEDIUM_ERROR (0x3)
2337 switch (SensePointer
->addnl_sense_code
) {
2338 case ASC_MEDIA_ERR1
:
2339 case ASC_MEDIA_ERR2
:
2340 case ASC_MEDIA_ERR3
:
2341 case ASC_MEDIA_ERR4
:
2353 // Sense Key is SK_NOT_READY (0x2)
2355 switch (SensePointer
->addnl_sense_code
) {
2357 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2359 case ASC_MEDIA_UPSIDE_DOWN
:
2380 IN REQUEST_SENSE_DATA
*SenseData
,
2381 IN UINTN SenseCounts
2385 Routine Description:
2387 TODO: Add function description
2391 SenseData - TODO: add argument description
2392 SenseCounts - TODO: add argument description
2396 TODO: add return values
2400 REQUEST_SENSE_DATA
*SensePointer
;
2402 BOOLEAN IsMediaChange
;
2404 IsMediaChange
= FALSE
;
2405 SensePointer
= SenseData
;
2407 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2409 // Sense Key is SK_UNIT_ATTENTION (0x6)
2411 if ((SensePointer
->sense_key
== SK_UNIT_ATTENTION
) &&
2412 (SensePointer
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
2414 IsMediaChange
= TRUE
;
2420 return IsMediaChange
;
2425 IN REQUEST_SENSE_DATA
*SenseData
,
2426 IN UINTN SenseCounts
,
2427 OUT BOOLEAN
*NeedRetry
2431 Routine Description:
2433 TODO: Add function description
2437 SenseData - TODO: add argument description
2438 SenseCounts - TODO: add argument description
2439 NeedRetry - TODO: add argument description
2443 TODO: add return values
2447 REQUEST_SENSE_DATA
*SensePointer
;
2453 SensePointer
= SenseData
;
2455 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2457 switch (SensePointer
->sense_key
) {
2461 // Sense Key is SK_NOT_READY (0x2)
2463 switch (SensePointer
->addnl_sense_code
) {
2466 // Additional Sense Code is ASC_NOT_READY (0x4)
2468 switch (SensePointer
->addnl_sense_code_qualifier
) {
2469 case ASCQ_IN_PROGRESS
:
2471 // Additional Sense Code Qualifier is ASCQ_IN_PROGRESS (0x1)
2501 IN REQUEST_SENSE_DATA
*SenseData
,
2502 IN UINTN SenseCounts
2506 Routine Description:
2508 TODO: Add function description
2512 SenseData - TODO: add argument description
2513 SenseCounts - TODO: add argument description
2517 TODO: add return values
2526 // if first sense key in the Sense Data Array is SK_NO_SENSE,
2527 // it indicates there is no more sense key in the Sense Data Array.
2529 if (SenseData
->sense_key
== SK_NO_SENSE
) {
2537 IsLS120orZipWriteProtected (
2538 IN IDE_BLK_IO_DEV
*IdeDev
,
2539 OUT BOOLEAN
*WriteProtected
2543 Routine Description:
2545 TODO: Add function description
2549 IdeDev - TODO: add argument description
2550 WriteProtected - TODO: add argument description
2554 EFI_DEVICE_ERROR - TODO: Add description for return value
2555 EFI_DEVICE_ERROR - TODO: Add description for return value
2556 EFI_SUCCESS - TODO: Add description for return value
2562 *WriteProtected
= FALSE
;
2564 Status
= LS120EnableMediaStatus (IdeDev
, TRUE
);
2565 if (EFI_ERROR (Status
)) {
2566 return EFI_DEVICE_ERROR
;
2570 // the Get Media Status Command is only valid
2571 // if a Set Features/Enable Media Status Command has been priviously issued.
2573 if (LS120GetMediaStatus (IdeDev
) == EFI_WRITE_PROTECTED
) {
2575 *WriteProtected
= TRUE
;
2578 *WriteProtected
= FALSE
;
2582 // After Get Media Status Command completes,
2583 // Set Features/Disable Media Command should be sent.
2585 Status
= LS120EnableMediaStatus (IdeDev
, FALSE
);
2586 if (EFI_ERROR (Status
)) {
2587 return EFI_DEVICE_ERROR
;