2 This file contains all helper functions on the ATAPI command
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 This function is used to get the current status of the media residing
13 in the LS-120 drive or ZIP drive. The media status is returned in the
16 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
17 to record all the information of the IDE device.
19 @retval EFI_SUCCESS The media status is achieved successfully and the media
21 @retval EFI_DEVICE_ERROR Get Media Status Command is failed.
22 @retval EFI_NO_MEDIA There is no media in the drive.
23 @retval EFI_WRITE_PROTECTED The media is writing protected.
25 @note This function must be called after the LS120EnableMediaStatus()
26 with second parameter set to TRUE
27 (means enable media status notification) is called.
31 IN IDE_BLK_IO_DEV
*IdeDev
38 // Poll Alternate Register for BSY clear within timeout.
40 EfiStatus
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
41 if (EFI_ERROR (EfiStatus
)) {
42 return EFI_DEVICE_ERROR
;
46 // Select device via Device/Head Register.
48 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4 | 0xe0);
49 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
52 // Poll Alternate Register for DRDY set within timeout.
53 // After device is selected, DRDY set indicates the device is ready to
56 EfiStatus
= DRDYReady2 (IdeDev
, ATATIMEOUT
);
57 if (EFI_ERROR (EfiStatus
)) {
58 return EFI_DEVICE_ERROR
;
62 // Get Media Status Command is sent
64 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, 0xDA);
67 // BSY bit will clear after command is complete.
69 EfiStatus
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
70 if (EFI_ERROR (EfiStatus
)) {
71 return EFI_DEVICE_ERROR
;
75 // the media status is returned by the command in the ERROR register
77 StatusValue
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
79 if ((StatusValue
& BIT1
) != 0) {
83 if ((StatusValue
& BIT6
) != 0) {
84 return EFI_WRITE_PROTECTED
;
90 This function is used to send Enable Media Status Notification Command
91 or Disable Media Status Notification Command.
93 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
94 to record all the information of the IDE device.
96 @param Enable a flag that indicates whether enable or disable media
98 @retval EFI_SUCCESS If command completes successfully.
99 @retval EFI_DEVICE_ERROR If command failed.
102 LS120EnableMediaStatus (
103 IN IDE_BLK_IO_DEV
*IdeDev
,
111 // Poll Alternate Register for BSY clear within timeout.
113 Status
= WaitForBSYClear2 (IdeDev
, ATATIMEOUT
);
114 if (EFI_ERROR (Status
)) {
115 return EFI_DEVICE_ERROR
;
119 // Select device via Device/Head Register.
121 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4 | 0xe0);
122 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
125 // Poll Alternate Register for DRDY set within timeout.
126 // After device is selected, DRDY set indicates the device is ready to
129 Status
= DRDYReady2 (IdeDev
, ATATIMEOUT
);
130 if (EFI_ERROR (Status
)) {
131 return EFI_DEVICE_ERROR
;
136 // 0x95: Enable media status notification
138 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x95);
141 // 0x31: Disable media status notification
143 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x31);
146 // Set Feature Command is sent
148 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, 0xEF);
151 // BSY bit will clear after command is complete.
153 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
154 if (EFI_ERROR (Status
)) {
155 return EFI_DEVICE_ERROR
;
161 This function reads the pending data in the device.
163 @param IdeDev Indicates the calling context.
165 @retval EFI_SUCCESS Successfully read.
166 @retval EFI_NOT_READY The BSY is set avoiding reading.
170 AtapiReadPendingData (
171 IN IDE_BLK_IO_DEV
*IdeDev
175 UINT16 TempWordBuffer
;
177 AltRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.AltStatus
);
178 if ((AltRegister
& ATA_STSREG_BSY
) == ATA_STSREG_BSY
) {
179 return EFI_NOT_READY
;
181 if ((AltRegister
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
182 TempWordBuffer
= IDEReadPortB (IdeDev
->PciIo
,IdeDev
->IoPort
->Alt
.AltStatus
);
183 while ((TempWordBuffer
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
184 IDEReadPortWMultiple (
186 IdeDev
->IoPort
->Data
,
190 TempWordBuffer
= IDEReadPortB (IdeDev
->PciIo
,IdeDev
->IoPort
->Alt
.AltStatus
);
197 This function is called by either AtapiPacketCommandIn() or AtapiPacketCommandOut().
198 It is used to transfer data between host and device. The data direction is specified
199 by the fourth parameter.
201 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record
202 all the information of the IDE device.
203 @param Buffer buffer contained data transferred between host and device.
204 @param ByteCount data size in byte unit of the buffer.
205 @param Read flag used to determine the data transfer direction.
206 Read equals 1, means data transferred from device to host;
207 Read equals 0, means data transferred from host to device.
208 @param TimeOut timeout value for wait DRQ ready before each data stream's transfer.
210 @retval EFI_SUCCESS data is transferred successfully.
211 @retval EFI_DEVICE_ERROR the device failed to transfer data.
215 IN IDE_BLK_IO_DEV
*IdeDev
,
223 // required transfer data in word unit.
225 UINT32 RequiredWordCount
;
228 // actual transfer data in word unit.
230 UINT32 ActualWordCount
;
236 // No data transfer is premitted.
238 if (ByteCount
== 0) {
242 // for performance, we assert the ByteCount is an even number
243 // which is actually a resonable assumption
244 ASSERT((ByteCount
%2) == 0);
247 RequiredWordCount
= ByteCount
/ 2;
249 // ActuralWordCount means the word count of data really transferred.
253 while (ActualWordCount
< RequiredWordCount
) {
256 // before each data transfer stream, the host should poll DRQ bit ready,
257 // to see whether indicates device is ready to transfer data.
259 Status
= DRQReady2 (IdeDev
, TimeOut
);
260 if (EFI_ERROR (Status
)) {
261 return CheckErrorStatus (IdeDev
);
265 // read Status Register will clear interrupt
267 IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
270 // get current data transfer size from Cylinder Registers.
272 WordCount
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
) << 8;
273 WordCount
= WordCount
| IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
);
274 WordCount
= WordCount
& 0xffff;
277 WordCount
= MIN (WordCount
, (RequiredWordCount
- ActualWordCount
));
280 IDEReadPortWMultiple (
282 IdeDev
->IoPort
->Data
,
287 IDEWritePortWMultiple (
289 IdeDev
->IoPort
->Data
,
295 PtrBuffer
+= WordCount
;
296 ActualWordCount
+= WordCount
;
301 // In the case where the drive wants to send more data than we need to read,
302 // the DRQ bit will be set and cause delays from DRQClear2().
303 // We need to read data from the drive until it clears DRQ so we can move on.
305 AtapiReadPendingData (IdeDev
);
309 // After data transfer is completed, normally, DRQ bit should clear.
311 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
312 if (EFI_ERROR (Status
)) {
313 return EFI_DEVICE_ERROR
;
317 // read status register to check whether error happens.
319 return CheckErrorStatus (IdeDev
);
323 This function is used to send out ATAPI commands conforms to the Packet Command
324 with PIO Data In Protocol.
326 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
327 to record all the information of the IDE device.
328 @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure
329 which contains the contents of the command.
330 @param Buffer buffer contained data transferred from device to host.
331 @param ByteCount data size in byte unit of the buffer.
332 @param TimeOut this parameter is used to specify the timeout value for the
333 PioReadWriteData() function.
335 @retval EFI_SUCCESS send out the ATAPI packet command successfully
336 and device sends data successfully.
337 @retval EFI_DEVICE_ERROR the device failed to send data.
341 AtapiPacketCommandIn (
342 IN IDE_BLK_IO_DEV
*IdeDev
,
343 IN ATAPI_PACKET_COMMAND
*Packet
,
349 UINT16
*CommandIndex
;
354 // Set all the command parameters by fill related registers.
355 // Before write to all the following registers, BSY and DRQ must be 0.
357 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
358 if (EFI_ERROR (Status
)) {
363 // Select device via Device/Head Register.
367 IdeDev
->IoPort
->Head
,
368 (UINT8
) ((IdeDev
->Device
<< 4) | ATA_DEFAULT_CMD
) // DEFAULT_CMD: 0xa0 (1010,0000)
374 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x00);
377 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
378 // determine how many data should be transferred.
382 IdeDev
->IoPort
->CylinderLsb
,
383 (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff)
387 IdeDev
->IoPort
->CylinderMsb
,
388 (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8)
392 // ATA_DEFAULT_CTL:0x0a (0000,1010)
395 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, ATA_DEFAULT_CTL
);
398 // Send Packet command to inform device
399 // that the following data bytes are command packet.
401 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, ATA_CMD_PACKET
);
403 Status
= DRQReady (IdeDev
, ATAPITIMEOUT
);
404 if (EFI_ERROR (Status
)) {
409 // Send out command packet
411 CommandIndex
= Packet
->Data16
;
412 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
414 IDEWritePortW (IdeDev
->PciIo
, IdeDev
->IoPort
->Data
, *CommandIndex
);
419 // call PioReadWriteData() function to get
420 // requested transfer data form device.
422 return PioReadWriteData (IdeDev
, Buffer
, ByteCount
, 1, TimeOut
);
425 This function is used to send out ATAPI commands conforms to the Packet Command
426 with PIO Data Out Protocol.
428 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
429 to record all the information of the IDE device.
430 @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure
431 which contains the contents of the command.
432 @param Buffer buffer contained data transferred from host to device.
433 @param ByteCount data size in byte unit of the buffer.
434 @param TimeOut this parameter is used to specify the timeout value
435 for the PioReadWriteData() function.
436 @retval EFI_SUCCESS send out the ATAPI packet command successfully
437 and device received data successfully.
438 @retval EFI_DEVICE_ERROR the device failed to send data.
442 AtapiPacketCommandOut (
443 IN IDE_BLK_IO_DEV
*IdeDev
,
444 IN ATAPI_PACKET_COMMAND
*Packet
,
450 UINT16
*CommandIndex
;
455 // set all the command parameters
456 // Before write to all the following registers, BSY and DRQ must be 0.
458 Status
= DRQClear2 (IdeDev
, ATAPITIMEOUT
);
459 if (EFI_ERROR (Status
)) {
464 // Select device via Device/Head Register.
468 IdeDev
->IoPort
->Head
,
469 (UINT8
) ((IdeDev
->Device
<< 4) | ATA_DEFAULT_CMD
) // ATA_DEFAULT_CMD: 0xa0 (1010,0000)
475 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x00);
478 // set the transfersize to ATAPI_MAX_BYTE_COUNT to
479 // let the device determine how many data should be transferred.
483 IdeDev
->IoPort
->CylinderLsb
,
484 (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff)
488 IdeDev
->IoPort
->CylinderMsb
,
489 (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8)
493 // DEFAULT_CTL:0x0a (0000,1010)
496 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, ATA_DEFAULT_CTL
);
499 // Send Packet command to inform device
500 // that the following data bytes are command packet.
502 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, ATA_CMD_PACKET
);
504 Status
= DRQReady2 (IdeDev
, ATAPITIMEOUT
);
505 if (EFI_ERROR (Status
)) {
510 // Send out command packet
512 CommandIndex
= Packet
->Data16
;
513 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
514 IDEWritePortW (IdeDev
->PciIo
, IdeDev
->IoPort
->Data
, *CommandIndex
);
519 // call PioReadWriteData() function to send requested transfer data to device.
521 return PioReadWriteData (IdeDev
, Buffer
, ByteCount
, 0, TimeOut
);
524 Sends out ATAPI Inquiry Packet Command to the specified device. This command will
525 return INQUIRY data of the device.
527 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
528 to record all the information of the IDE device.
530 @retval EFI_SUCCESS Inquiry command completes successfully.
531 @retval EFI_DEVICE_ERROR Inquiry command failed.
533 @note Parameter "IdeDev" will be updated in this function.
538 IN IDE_BLK_IO_DEV
*IdeDev
541 ATAPI_PACKET_COMMAND Packet
;
543 ATAPI_INQUIRY_DATA
*InquiryData
;
546 // prepare command packet for the ATAPI Inquiry Packet Command.
548 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
549 Packet
.Inquiry
.opcode
= ATA_CMD_INQUIRY
;
550 Packet
.Inquiry
.page_code
= 0;
551 Packet
.Inquiry
.allocation_length
= (UINT8
) sizeof (ATAPI_INQUIRY_DATA
);
553 InquiryData
= AllocatePool (sizeof (ATAPI_INQUIRY_DATA
));
554 if (InquiryData
== NULL
) {
555 return EFI_DEVICE_ERROR
;
559 // Send command packet and get requested Inquiry data.
561 Status
= AtapiPacketCommandIn (
564 (UINT16
*) InquiryData
,
565 sizeof (ATAPI_INQUIRY_DATA
),
568 if (EFI_ERROR (Status
)) {
569 gBS
->FreePool (InquiryData
);
570 return EFI_DEVICE_ERROR
;
573 IdeDev
->InquiryData
= InquiryData
;
578 This function is called by DiscoverIdeDevice() during its device
580 Its main purpose is to get enough information for the device media
581 to fill in the Media data structure of the Block I/O Protocol interface.
583 There are 5 steps to reach such objective:
584 1. Sends out the ATAPI Identify Command to the specified device.
585 Only ATAPI device responses to this command. If the command succeeds,
586 it returns the Identify data structure which filled with information
587 about the device. Since the ATAPI device contains removable media,
588 the only meaningful information is the device module name.
589 2. Sends out ATAPI Inquiry Packet Command to the specified device.
590 This command will return inquiry data of the device, which contains
591 the device type information.
592 3. Allocate sense data space for future use. We don't detect the media
593 presence here to improvement boot performance, especially when CD
594 media is present. The media detection will be performed just before
595 each BLK_IO read/write
597 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
598 to record all the information of the IDE device.
600 @retval EFI_SUCCESS Identify ATAPI device successfully.
601 @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type
602 is not supported by this IDE driver.
603 @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed
605 @note Parameter "IdeDev" will be updated in this function.
609 IN IDE_BLK_IO_DEV
*IdeDev
612 EFI_IDENTIFY_DATA
*AtapiIdentifyPointer
;
619 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
621 AtapiIdentifyPointer
= AllocatePool (sizeof (EFI_IDENTIFY_DATA
));
622 if (AtapiIdentifyPointer
== NULL
) {
623 return EFI_OUT_OF_RESOURCES
;
626 // Send ATAPI Identify Command to get IDENTIFY data.
628 Status
= AtaPioDataIn (
630 (VOID
*) AtapiIdentifyPointer
,
631 sizeof (EFI_IDENTIFY_DATA
),
632 ATA_CMD_IDENTIFY_DEVICE
,
640 if (EFI_ERROR (Status
)) {
641 gBS
->FreePool (AtapiIdentifyPointer
);
642 return EFI_DEVICE_ERROR
;
645 IdeDev
->IdData
= AtapiIdentifyPointer
;
646 PrintAtaModuleName (IdeDev
);
649 // Send ATAPI Inquiry Packet Command to get INQUIRY data.
651 Status
= AtapiInquiry (IdeDev
);
652 if (EFI_ERROR (Status
)) {
653 gBS
->FreePool (IdeDev
->IdData
);
655 // Make sure the pIdData will not be freed again.
657 IdeDev
->IdData
= NULL
;
658 return EFI_DEVICE_ERROR
;
661 // Get media removable info from INQUIRY data.
663 IdeDev
->BlkIo
.Media
->RemovableMedia
= (UINT8
) ((IdeDev
->InquiryData
->RMB
& 0x80) == 0x80);
666 // Identify device type via INQUIRY data.
668 switch (IdeDev
->InquiryData
->peripheral_type
& 0x1f) {
676 // device is LS120 or ZIP drive.
678 IdeDev
->Type
= IdeMagnetic
;
680 IdeDev
->BlkIo
.Media
->MediaId
= 0;
682 // Give initial value
684 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
686 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
687 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
695 IdeDev
->Type
= IdeCdRom
;
696 IdeDev
->BlkIo
.Media
->MediaId
= 0;
698 // Give initial value
700 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
702 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
703 IdeDev
->BlkIo
.Media
->BlockSize
= 0x800;
704 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
723 IdeDev
->Type
= IdeUnknown
;
724 gBS
->FreePool (IdeDev
->IdData
);
725 gBS
->FreePool (IdeDev
->InquiryData
);
727 // Make sure the pIdData and pInquiryData will not be freed again.
729 IdeDev
->IdData
= NULL
;
730 IdeDev
->InquiryData
= NULL
;
731 return EFI_DEVICE_ERROR
;
735 // original sense data numbers
737 IdeDev
->SenseDataNumber
= 20;
739 IdeDev
->SenseData
= AllocatePool (IdeDev
->SenseDataNumber
* sizeof (ATAPI_REQUEST_SENSE_DATA
));
740 if (IdeDev
->SenseData
== NULL
) {
741 gBS
->FreePool (IdeDev
->IdData
);
742 gBS
->FreePool (IdeDev
->InquiryData
);
744 // Make sure the pIdData and pInquiryData will not be freed again.
746 IdeDev
->IdData
= NULL
;
747 IdeDev
->InquiryData
= NULL
;
748 return EFI_OUT_OF_RESOURCES
;
754 Sends out ATAPI Request Sense Packet Command to the specified device. This command
755 will return all the current Sense data in the device. This function will pack
756 all the Sense data in one single buffer.
758 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
759 to record all the information of the IDE device.
760 @param SenseCounts allocated in this function, and freed by the calling function.
761 This buffer is used to accommodate all the sense data returned
764 @retval EFI_SUCCESS Request Sense command completes successfully.
765 @retval EFI_DEVICE_ERROR Request Sense command failed.
769 IN IDE_BLK_IO_DEV
*IdeDev
,
770 OUT UINTN
*SenseCounts
774 ATAPI_REQUEST_SENSE_DATA
*Sense
;
776 BOOLEAN FetchSenseData
;
777 ATAPI_PACKET_COMMAND Packet
;
781 ZeroMem (IdeDev
->SenseData
, sizeof (ATAPI_REQUEST_SENSE_DATA
) * (IdeDev
->SenseDataNumber
));
783 // fill command packet for Request Sense Packet Command
785 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
786 Packet
.RequestSence
.opcode
= ATA_CMD_REQUEST_SENSE
;
787 Packet
.RequestSence
.allocation_length
= (UINT8
) sizeof (ATAPI_REQUEST_SENSE_DATA
);
790 // initialize pointer
792 Ptr
= (UINT16
*) IdeDev
->SenseData
;
794 // request sense data from device continuously until no sense data
795 // exists in the device.
797 for (FetchSenseData
= TRUE
; FetchSenseData
;) {
799 Sense
= (ATAPI_REQUEST_SENSE_DATA
*) Ptr
;
802 // send out Request Sense Packet Command and get one Sense data form device
804 Status
= AtapiPacketCommandIn (
808 sizeof (ATAPI_REQUEST_SENSE_DATA
),
812 // failed to get Sense data
814 if (EFI_ERROR (Status
)) {
815 if (*SenseCounts
== 0) {
816 return EFI_DEVICE_ERROR
;
824 // We limit MAX sense data count to 20 in order to avoid dead loop. Some
825 // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
826 // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
827 // supposed to be large enough for any ATAPI device.
829 if ((Sense
->sense_key
!= ATA_SK_NO_SENSE
) && ((*SenseCounts
) < 20)) {
831 // Ptr is word-based pointer
833 Ptr
+= (sizeof (ATAPI_REQUEST_SENSE_DATA
) + 1) >> 1;
837 // when no sense key, skip out the loop
839 FetchSenseData
= FALSE
;
846 This function is used to parse sense data. Only the first sense data is honoured
848 @param IdeDev Indicates the calling context.
849 @param SenseCount Count of sense data.
850 @param Result The parsed result.
852 @retval EFI_SUCCESS Successfully parsed.
853 @retval EFI_INVALID_PARAMETER Count of sense data is zero.
858 IN IDE_BLK_IO_DEV
*IdeDev
,
860 OUT SENSE_RESULT
*Result
863 ATAPI_REQUEST_SENSE_DATA
*SenseData
;
865 if (SenseCount
== 0) {
866 return EFI_INVALID_PARAMETER
;
870 // Only use the first sense data
872 SenseData
= IdeDev
->SenseData
;
873 *Result
= SenseOtherSense
;
875 switch (SenseData
->sense_key
) {
876 case ATA_SK_NO_SENSE
:
877 *Result
= SenseNoSenseKey
;
879 case ATA_SK_NOT_READY
:
880 switch (SenseData
->addnl_sense_code
) {
881 case ATA_ASC_NO_MEDIA
:
882 *Result
= SenseNoMedia
;
884 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
885 *Result
= SenseMediaError
;
887 case ATA_ASC_NOT_READY
:
888 if (SenseData
->addnl_sense_code_qualifier
== ATA_ASCQ_IN_PROGRESS
) {
889 *Result
= SenseDeviceNotReadyNeedRetry
;
891 *Result
= SenseDeviceNotReadyNoRetry
;
896 case ATA_SK_UNIT_ATTENTION
:
897 if (SenseData
->addnl_sense_code
== ATA_ASC_MEDIA_CHANGE
) {
898 *Result
= SenseMediaChange
;
901 case ATA_SK_MEDIUM_ERROR
:
902 switch (SenseData
->addnl_sense_code
) {
903 case ATA_ASC_MEDIA_ERR1
:
904 case ATA_ASC_MEDIA_ERR2
:
905 case ATA_ASC_MEDIA_ERR3
:
906 case ATA_ASC_MEDIA_ERR4
:
907 *Result
= SenseMediaError
;
919 Sends out ATAPI Test Unit Ready Packet Command to the specified device
920 to find out whether device is accessible.
922 @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
923 to record all the information of the IDE device.
924 @param SResult Sense result for this packet command.
926 @retval EFI_SUCCESS Device is accessible.
927 @retval EFI_DEVICE_ERROR Device is not accessible.
932 IN IDE_BLK_IO_DEV
*IdeDev
,
933 OUT SENSE_RESULT
*SResult
936 ATAPI_PACKET_COMMAND Packet
;
941 // fill command packet
943 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
944 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
947 // send command packet
949 Status
= AtapiPacketCommandIn (IdeDev
, &Packet
, NULL
, 0, ATAPITIMEOUT
);
950 if (EFI_ERROR (Status
)) {
954 Status
= AtapiRequestSense (IdeDev
, &SenseCount
);
955 if (EFI_ERROR (Status
)) {
959 ParseSenseData (IdeDev
, SenseCount
, SResult
);
965 Sends out ATAPI Read Capacity Packet Command to the specified device.
966 This command will return the information regarding the capacity of the
969 Current device status will impact device's response to the Read Capacity
970 Command. For example, if the device once reset, the Read Capacity
971 Command will fail. The Sense data record the current device status, so
972 if the Read Capacity Command failed, the Sense data must be requested
973 and be analyzed to determine if the Read Capacity Command should retry.
975 @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
976 to record all the information of the IDE device.
977 @param SResult Sense result for this packet command
979 @retval EFI_SUCCESS Read Capacity Command finally completes successfully.
980 @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.
981 @retval EFI_NOT_READY Operation succeeds but returned capacity is 0
983 @note Parameter "IdeDev" will be updated in this function.
989 IN IDE_BLK_IO_DEV
*IdeDev
,
990 OUT SENSE_RESULT
*SResult
994 // status returned by Read Capacity Packet Command
997 EFI_STATUS SenseStatus
;
998 ATAPI_PACKET_COMMAND Packet
;
1002 // used for capacity data returned from ATAPI device
1004 ATAPI_READ_CAPACITY_DATA Data
;
1005 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
1007 ZeroMem (&Data
, sizeof (Data
));
1008 ZeroMem (&FormatData
, sizeof (FormatData
));
1010 if (IdeDev
->Type
== IdeCdRom
) {
1012 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1013 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
1014 Status
= AtapiPacketCommandIn (
1018 sizeof (ATAPI_READ_CAPACITY_DATA
),
1024 // Type == IdeMagnetic
1026 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1027 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
1028 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
1029 Status
= AtapiPacketCommandIn (
1032 (UINT16
*) &FormatData
,
1033 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
1038 if (Status
== EFI_TIMEOUT
) {
1042 SenseStatus
= AtapiRequestSense (IdeDev
, &SenseCount
);
1044 if (!EFI_ERROR (SenseStatus
)) {
1045 ParseSenseData (IdeDev
, SenseCount
, SResult
);
1047 if (!EFI_ERROR (Status
) && *SResult
== SenseNoSenseKey
) {
1048 if (IdeDev
->Type
== IdeCdRom
) {
1050 IdeDev
->BlkIo
.Media
->LastBlock
= ((UINT32
) Data
.LastLba3
<< 24) |
1051 (Data
.LastLba2
<< 16) |
1052 (Data
.LastLba1
<< 8) |
1055 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
1057 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
1060 // Because the user data portion in the sector of the Data CD supported
1063 IdeDev
->BlkIo
.Media
->BlockSize
= 0x800;
1066 if (IdeDev
->Type
== IdeMagnetic
) {
1068 if (FormatData
.DesCode
== 3) {
1069 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1070 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1073 IdeDev
->BlkIo
.Media
->LastBlock
= ((UINT32
) FormatData
.LastLba3
<< 24) |
1074 (FormatData
.LastLba2
<< 16) |
1075 (FormatData
.LastLba1
<< 8) |
1076 FormatData
.LastLba0
;
1077 if (IdeDev
->BlkIo
.Media
->LastBlock
!= 0) {
1078 IdeDev
->BlkIo
.Media
->LastBlock
--;
1080 IdeDev
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
1081 (FormatData
.BlockSize1
<< 8) |
1082 FormatData
.BlockSize0
;
1084 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
1086 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1088 // Return EFI_NOT_READY operation succeeds but returned capacity is 0
1090 return EFI_NOT_READY
;
1093 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
1102 return EFI_DEVICE_ERROR
;
1106 This function is used to test the current media write-protected or not residing
1107 in the LS-120 drive or ZIP drive.
1108 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1109 to record all the information of the IDE device.
1110 @param WriteProtected if True, current media is write protected.
1111 if FALSE, current media is writable
1113 @retval EFI_SUCCESS The media write-protected status is achieved successfully
1114 @retval EFI_DEVICE_ERROR Get Media Status Command is failed.
1117 IsLS120orZipWriteProtected (
1118 IN IDE_BLK_IO_DEV
*IdeDev
,
1119 OUT BOOLEAN
*WriteProtected
1124 *WriteProtected
= FALSE
;
1126 Status
= LS120EnableMediaStatus (IdeDev
, TRUE
);
1127 if (EFI_ERROR (Status
)) {
1128 return EFI_DEVICE_ERROR
;
1132 // the Get Media Status Command is only valid
1133 // if a Set Features/Enable Media Status Command has been priviously issued.
1135 if (LS120GetMediaStatus (IdeDev
) == EFI_WRITE_PROTECTED
) {
1137 *WriteProtected
= TRUE
;
1140 *WriteProtected
= FALSE
;
1144 // After Get Media Status Command completes,
1145 // Set Features/Disable Media Command should be sent.
1147 Status
= LS120EnableMediaStatus (IdeDev
, FALSE
);
1148 if (EFI_ERROR (Status
)) {
1149 return EFI_DEVICE_ERROR
;
1156 Used before read/write blocks from/to ATAPI device media. Since ATAPI device
1157 media is removable, it is necessary to detect whether media is present and
1158 get current present media's information, and if media has been changed, Block
1159 I/O Protocol need to be reinstalled.
1161 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1162 to record all the information of the IDE device.
1163 @param MediaChange return value that indicates if the media of the device has been
1166 @retval EFI_SUCCESS media found successfully.
1167 @retval EFI_DEVICE_ERROR any error encounters during media detection.
1168 @retval EFI_NO_MEDIA media not found.
1171 parameter IdeDev may be updated in this function.
1176 IN IDE_BLK_IO_DEV
*IdeDev
,
1177 OUT BOOLEAN
*MediaChange
1181 EFI_STATUS CleanStateStatus
;
1182 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
1184 UINTN RetryNotReady
;
1185 SENSE_RESULT SResult
;
1186 BOOLEAN WriteProtected
;
1188 CopyMem (&OldMediaInfo
, IdeDev
->BlkIo
.Media
, sizeof (EFI_BLOCK_IO_MEDIA
));
1189 *MediaChange
= FALSE
;
1191 // Retry for SenseDeviceNotReadyNeedRetry.
1192 // Each retry takes 1s and we limit the upper boundary to
1193 // 120 times about 2 min.
1195 RetryNotReady
= 120;
1198 // Do Test Unit Ready
1205 while (RetryTimes
!= 0) {
1207 Status
= AtapiTestUnitReady (IdeDev
, &SResult
);
1209 if (EFI_ERROR (Status
)) {
1211 // Test Unit Ready error without sense data.
1212 // For some devices, this means there's extra data
1213 // that has not been read, so we read these extra
1214 // data out before going on.
1216 CleanStateStatus
= AtapiReadPendingData (IdeDev
);
1217 if (EFI_ERROR (CleanStateStatus
)) {
1219 // Busy wait failed, try again
1224 // Try again without counting down RetryTimes
1229 case SenseNoSenseKey
:
1230 if (IdeDev
->BlkIo
.Media
->MediaPresent
) {
1234 // Media present but the internal structure need refreshed.
1235 // Try Read Capacity
1241 case SenseDeviceNotReadyNeedRetry
:
1242 if (--RetryNotReady
== 0) {
1243 return EFI_DEVICE_ERROR
;
1245 gBS
->Stall (1000 * STALL_1_MILLI_SECOND
);
1250 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1251 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1255 case SenseDeviceNotReadyNoRetry
:
1256 case SenseMediaError
:
1257 return EFI_DEVICE_ERROR
;
1259 case SenseMediaChange
:
1260 IdeDev
->BlkIo
.Media
->MediaId
++;
1271 return EFI_DEVICE_ERROR
;
1279 while (RetryTimes
!= 0) {
1281 Status
= AtapiReadCapacity (IdeDev
, &SResult
);
1283 if (EFI_ERROR (Status
)) {
1288 case SenseNoSenseKey
:
1292 case SenseDeviceNotReadyNeedRetry
:
1294 // We use Test Unit Ready to retry which
1301 IdeDev
->BlkIo
.Media
->MediaPresent
= FALSE
;
1302 IdeDev
->BlkIo
.Media
->LastBlock
= 0;
1306 case SenseDeviceNotReadyNoRetry
:
1307 case SenseMediaError
:
1308 return EFI_DEVICE_ERROR
;
1310 case SenseMediaChange
:
1311 IdeDev
->BlkIo
.Media
->MediaId
++;
1322 return EFI_DEVICE_ERROR
;
1326 // the following code is to check the write-protected for LS120 media
1328 if ((IdeDev
->BlkIo
.Media
->MediaPresent
) && (IdeDev
->Type
== IdeMagnetic
)) {
1330 Status
= IsLS120orZipWriteProtected (IdeDev
, &WriteProtected
);
1331 if (!EFI_ERROR (Status
)) {
1333 if (WriteProtected
) {
1335 IdeDev
->BlkIo
.Media
->ReadOnly
= TRUE
;
1338 IdeDev
->BlkIo
.Media
->ReadOnly
= FALSE
;
1344 if (IdeDev
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1346 // Media change information got from the device
1348 *MediaChange
= TRUE
;
1351 if (IdeDev
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1352 *MediaChange
= TRUE
;
1353 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1356 if (IdeDev
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1357 *MediaChange
= TRUE
;
1358 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1361 if (IdeDev
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1362 *MediaChange
= TRUE
;
1363 IdeDev
->BlkIo
.Media
->MediaId
+= 1;
1366 if (IdeDev
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1367 if (IdeDev
->BlkIo
.Media
->MediaPresent
) {
1369 // when change from no media to media present, reset the MediaId to 1.
1371 IdeDev
->BlkIo
.Media
->MediaId
= 1;
1374 // when no media, reset the MediaId to zero.
1376 IdeDev
->BlkIo
.Media
->MediaId
= 0;
1379 *MediaChange
= TRUE
;
1383 // if any change on current existing media,
1384 // the Block I/O protocol need to be reinstalled.
1387 gBS
->ReinstallProtocolInterface (
1389 &gEfiBlockIoProtocolGuid
,
1395 if (IdeDev
->BlkIo
.Media
->MediaPresent
) {
1398 return EFI_NO_MEDIA
;
1403 This function is called by the AtapiBlkIoReadBlocks() to perform
1404 read from media in block unit.
1406 The main command used to access media here is READ(10) Command.
1407 READ(10) Command requests that the ATAPI device media transfer
1408 specified data to the host. Data is transferred in block(sector)
1409 unit. The maximum number of blocks that can be transferred once is
1410 65536. This is the main difference between READ(10) and READ(12)
1411 Command. The maximum number of blocks in READ(12) is 2 power 32.
1413 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1414 to record all the information of the IDE device.
1415 @param Buffer A pointer to the destination buffer for the data.
1416 @param Lba The starting logical block address to read from on the
1418 @param NumberOfBlocks The number of transfer data blocks.
1420 @return status is fully dependent on the return status of AtapiPacketCommandIn() function.
1425 IN IDE_BLK_IO_DEV
*IdeDev
,
1428 IN UINTN NumberOfBlocks
1432 ATAPI_PACKET_COMMAND Packet
;
1433 ATAPI_READ10_CMD
*Read10Packet
;
1435 UINTN BlocksRemaining
;
1445 // fill command packet for Read(10) command
1447 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1448 Read10Packet
= &Packet
.Read10
;
1449 Lba32
= (UINT32
) Lba
;
1452 BlockSize
= IdeDev
->BlkIo
.Media
->BlockSize
;
1455 // limit the data bytes that can be transferred by one Read(10) Command
1459 BlocksRemaining
= NumberOfBlocks
;
1461 Status
= EFI_SUCCESS
;
1462 while (BlocksRemaining
> 0) {
1464 if (BlocksRemaining
<= MaxBlock
) {
1466 SectorCount
= (UINT16
) BlocksRemaining
;
1469 SectorCount
= MaxBlock
;
1473 // fill the Packet data structure
1476 Read10Packet
->opcode
= ATA_CMD_READ_10
;
1479 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1480 // Lba0 is MSB, Lba3 is LSB
1482 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
1483 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
1484 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
1485 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
1488 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1489 // TranLen0 is MSB, TranLen is LSB
1491 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
1492 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
1494 ByteCount
= SectorCount
* BlockSize
;
1496 if (IdeDev
->Type
== IdeCdRom
) {
1497 TimeOut
= CDROMLONGTIMEOUT
;
1499 TimeOut
= ATAPILONGTIMEOUT
;
1502 Status
= AtapiPacketCommandIn (
1505 (UINT16
*) PtrBuffer
,
1509 if (EFI_ERROR (Status
)) {
1513 Lba32
+= SectorCount
;
1514 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
1515 BlocksRemaining
-= SectorCount
;
1522 This function is called by the AtapiBlkIoWriteBlocks() to perform
1523 write onto media in block unit.
1524 The main command used to access media here is Write(10) Command.
1525 Write(10) Command requests that the ATAPI device media transfer
1526 specified data to the host. Data is transferred in block (sector)
1527 unit. The maximum number of blocks that can be transferred once is
1530 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1531 to record all the information of the IDE device.
1532 @param Buffer A pointer to the source buffer for the data.
1533 @param Lba The starting logical block address to write onto
1535 @param NumberOfBlocks The number of transfer data blocks.
1537 @return status is fully dependent on the return status of AtapiPacketCommandOut() function.
1542 IN IDE_BLK_IO_DEV
*IdeDev
,
1545 IN UINTN NumberOfBlocks
1549 ATAPI_PACKET_COMMAND Packet
;
1550 ATAPI_READ10_CMD
*Read10Packet
;
1553 UINTN BlocksRemaining
;
1562 // fill command packet for Write(10) command
1563 // Write(10) command packet has the same data structure as
1564 // Read(10) command packet,
1565 // so here use the Read10Packet data structure
1566 // for the Write(10) command packet.
1568 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1569 Read10Packet
= &Packet
.Read10
;
1571 Lba32
= (UINT32
) Lba
;
1574 BlockSize
= IdeDev
->BlkIo
.Media
->BlockSize
;
1577 // limit the data bytes that can be transferred by one Read(10) Command
1579 MaxBlock
= (UINT16
) (65536 / BlockSize
);
1581 BlocksRemaining
= NumberOfBlocks
;
1583 Status
= EFI_SUCCESS
;
1584 while (BlocksRemaining
> 0) {
1586 if (BlocksRemaining
>= MaxBlock
) {
1587 SectorCount
= MaxBlock
;
1589 SectorCount
= (UINT16
) BlocksRemaining
;
1593 // Command code is WRITE_10.
1595 Read10Packet
->opcode
= ATA_CMD_WRITE_10
;
1598 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1599 // Lba0 is MSB, Lba3 is LSB
1601 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
1602 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
1603 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
1604 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
1607 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1608 // TranLen0 is MSB, TranLen is LSB
1610 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
1611 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
1613 ByteCount
= SectorCount
* BlockSize
;
1615 Status
= AtapiPacketCommandOut (
1618 (UINT16
*) PtrBuffer
,
1622 if (EFI_ERROR (Status
)) {
1626 Lba32
+= SectorCount
;
1627 PtrBuffer
= ((UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
);
1628 BlocksRemaining
-= SectorCount
;
1634 This function is used to implement the Soft Reset on the specified
1635 ATAPI device. Different from the AtaSoftReset(), here reset is a ATA
1636 Soft Reset Command special for ATAPI device, and it only take effects
1637 on the specified ATAPI device, not on the whole IDE bus.
1638 Since the ATAPI soft reset is needed when device is in exceptional
1639 condition (such as BSY bit is always set ), I think the Soft Reset
1640 command should be sent without waiting for the BSY clear and DRDY
1642 This function is called by IdeBlkIoReset(),
1643 a interface function of Block I/O protocol.
1645 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1646 to record all the information of the IDE device.
1648 @retval EFI_SUCCESS Soft reset completes successfully.
1649 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.
1654 IN IDE_BLK_IO_DEV
*IdeDev
1662 // for ATAPI device, no need to wait DRDY ready after device selecting.
1663 // (bit7 and bit5 are both set to 1 for backward compatibility)
1665 DeviceSelect
= (UINT8
) (((BIT7
| BIT5
) | (IdeDev
->Device
<< 4)));
1666 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, DeviceSelect
);
1668 Command
= ATA_CMD_SOFT_RESET
;
1669 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, Command
);
1672 // BSY cleared is the only status return to the host by the device
1673 // when reset is completed.
1674 // slave device needs at most 31s to clear BSY
1676 Status
= WaitForBSYClear (IdeDev
, 31000);
1677 if (EFI_ERROR (Status
)) {
1678 return EFI_DEVICE_ERROR
;
1682 // stall 5 seconds to make the device status stable
1684 gBS
->Stall (5000000);
1690 This function is the ATAPI implementation for ReadBlocks in the
1691 Block I/O Protocol interface.
1693 @param IdeBlkIoDevice Indicates the calling context.
1694 @param MediaId The media id that the read request is for.
1695 @param Lba The starting logical block address to read from on the device.
1696 @param BufferSize The size of the Buffer in bytes. This must be a multiple
1697 of the intrinsic block size of the device.
1698 @param Buffer A pointer to the destination buffer for the data. The caller
1699 is responsible for either having implicit or explicit
1700 ownership of the memory that data is read into.
1702 @retval EFI_SUCCESS Read Blocks successfully.
1703 @retval EFI_DEVICE_ERROR Read Blocks failed.
1704 @retval EFI_NO_MEDIA There is no media in the device.
1705 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1706 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
1707 intrinsic block size of the device.
1708 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
1709 or the data buffer is not valid.
1712 AtapiBlkIoReadBlocks (
1713 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
1716 IN UINTN BufferSize
,
1720 EFI_BLOCK_IO_MEDIA
*Media
;
1722 UINTN NumberOfBlocks
;
1725 BOOLEAN MediaChange
;
1727 if (Buffer
== NULL
) {
1728 return EFI_INVALID_PARAMETER
;
1731 if (BufferSize
== 0) {
1736 // ATAPI device media is removable, so it is a must
1737 // to detect media first before read operation
1739 MediaChange
= FALSE
;
1740 Status
= AtapiDetectMedia (IdeBlkIoDevice
, &MediaChange
);
1741 if (EFI_ERROR (Status
)) {
1743 if (IdeBlkIoDevice
->Cache
!= NULL
) {
1744 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1745 IdeBlkIoDevice
->Cache
= NULL
;
1751 // Get the intrinsic block size
1753 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
1754 BlockSize
= Media
->BlockSize
;
1756 NumberOfBlocks
= BufferSize
/ BlockSize
;
1758 if (!(Media
->MediaPresent
)) {
1760 if (IdeBlkIoDevice
->Cache
!= NULL
) {
1761 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1762 IdeBlkIoDevice
->Cache
= NULL
;
1764 return EFI_NO_MEDIA
;
1768 if ((MediaId
!= Media
->MediaId
) || MediaChange
) {
1770 if (IdeBlkIoDevice
->Cache
!= NULL
) {
1771 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1772 IdeBlkIoDevice
->Cache
= NULL
;
1774 return EFI_MEDIA_CHANGED
;
1777 if (BufferSize
% BlockSize
!= 0) {
1778 return EFI_BAD_BUFFER_SIZE
;
1781 if (Lba
> Media
->LastBlock
) {
1782 return EFI_INVALID_PARAMETER
;
1785 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1786 return EFI_INVALID_PARAMETER
;
1789 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
1790 return EFI_INVALID_PARAMETER
;
1794 // if all the parameters are valid, then perform read sectors command
1795 // to transfer data from device to host.
1797 Status
= AtapiReadSectors (IdeBlkIoDevice
, Buffer
, Lba
, NumberOfBlocks
);
1798 if (EFI_ERROR (Status
)) {
1799 return EFI_DEVICE_ERROR
;
1803 // Read blocks succeeded
1807 // save the first block to the cache for performance
1809 if (Lba
== 0 && (IdeBlkIoDevice
->Cache
== NULL
)) {
1810 IdeBlkIoDevice
->Cache
= AllocatePool (BlockSize
);
1811 if (IdeBlkIoDevice
->Cache
!= NULL
) {
1812 CopyMem ((UINT8
*) IdeBlkIoDevice
->Cache
, (UINT8
*) Buffer
, BlockSize
);
1820 This function is the ATAPI implementation for WriteBlocks in the
1821 Block I/O Protocol interface.
1823 @param IdeBlkIoDevice Indicates the calling context.
1824 @param MediaId The media id that the write request is for.
1825 @param Lba The starting logical block address to write onto the device.
1826 @param BufferSize The size of the Buffer in bytes. This must be a multiple
1827 of the intrinsic block size of the device.
1828 @param Buffer A pointer to the source buffer for the data. The caller
1829 is responsible for either having implicit or explicit ownership
1830 of the memory that data is written from.
1832 @retval EFI_SUCCESS Write Blocks successfully.
1833 @retval EFI_DEVICE_ERROR Write Blocks failed.
1834 @retval EFI_NO_MEDIA There is no media in the device.
1835 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.
1836 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
1837 intrinsic block size of the device.
1838 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1839 or the data buffer is not valid.
1841 @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write
1844 AtapiBlkIoWriteBlocks (
1845 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
1848 IN UINTN BufferSize
,
1853 EFI_BLOCK_IO_MEDIA
*Media
;
1855 UINTN NumberOfBlocks
;
1857 BOOLEAN MediaChange
;
1859 if (Lba
== 0 && IdeBlkIoDevice
->Cache
!= NULL
) {
1860 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1861 IdeBlkIoDevice
->Cache
= NULL
;
1864 if (Buffer
== NULL
) {
1865 return EFI_INVALID_PARAMETER
;
1868 if (BufferSize
== 0) {
1873 // ATAPI device media is removable,
1874 // so it is a must to detect media first before write operation
1876 MediaChange
= FALSE
;
1877 Status
= AtapiDetectMedia (IdeBlkIoDevice
, &MediaChange
);
1878 if (EFI_ERROR (Status
)) {
1880 if (Lba
== 0 && IdeBlkIoDevice
->Cache
!= NULL
) {
1881 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1882 IdeBlkIoDevice
->Cache
= NULL
;
1888 // Get the intrinsic block size
1890 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
1891 BlockSize
= Media
->BlockSize
;
1892 NumberOfBlocks
= BufferSize
/ BlockSize
;
1894 if (!(Media
->MediaPresent
)) {
1896 if (Lba
== 0 && IdeBlkIoDevice
->Cache
!= NULL
) {
1897 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1898 IdeBlkIoDevice
->Cache
= NULL
;
1900 return EFI_NO_MEDIA
;
1903 if ((MediaId
!= Media
->MediaId
) || MediaChange
) {
1905 if (Lba
== 0 && IdeBlkIoDevice
->Cache
!= NULL
) {
1906 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1907 IdeBlkIoDevice
->Cache
= NULL
;
1909 return EFI_MEDIA_CHANGED
;
1912 if (Media
->ReadOnly
) {
1913 return EFI_WRITE_PROTECTED
;
1916 if (BufferSize
% BlockSize
!= 0) {
1917 return EFI_BAD_BUFFER_SIZE
;
1920 if (Lba
> Media
->LastBlock
) {
1921 return EFI_INVALID_PARAMETER
;
1924 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1925 return EFI_INVALID_PARAMETER
;
1928 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
1929 return EFI_INVALID_PARAMETER
;
1933 // if all the parameters are valid,
1934 // then perform write sectors command to transfer data from host to device.
1936 Status
= AtapiWriteSectors (IdeBlkIoDevice
, Buffer
, Lba
, NumberOfBlocks
);
1937 if (EFI_ERROR (Status
)) {
1938 return EFI_DEVICE_ERROR
;