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.
20 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
21 update - ATAIdentity() func
22 update - AtaBlockIoReadBlocks() func
23 update - AtaBlockIoWriteBlocks() func
24 add - AtaAtapi6Identify() func
25 add - AtaReadSectorsExt() func
26 add - AtaWriteSectorsExt() func
27 add - AtaPioDataInExt() func
28 add - AtaPioDataOutExt() func
37 IN IDE_BLK_IO_DEV
*IdeDev
,
38 IN OUT VOID
*DataBuffer
,
40 IN UINTN NumberOfBlocks
45 IN IDE_BLK_IO_DEV
*IdeDev
,
48 IN UINTN NumberOfBlocks
53 IN IDE_BLK_IO_DEV
*IdeDev
,
63 IN IDE_BLK_IO_DEV
*IdeDev
,
73 IN IDE_BLK_IO_DEV
*IdeDev
81 This function is called by DiscoverIdeDevice() during its device
82 identification. It sends out the ATA Identify Command to the
83 specified device. Only ATA device responses to this command. If
84 the command succeeds, it returns the Identify data structure which
85 contains information about the device. This function extracts the
86 information it needs to fill the IDE_BLK_IO_DEV data structure,
87 including device type, media block size, media capacity, and etc.
91 IDE_BLK_IO_DEV IN *IdeDev
92 pointer pointing to IDE_BLK_IO_DEV data structure,used
93 to record all the information of the IDE device.
98 Identify ATA device successfully.
101 ATA Identify Device Command failed or device is not
106 parameter IdeDev will be updated in this function.
108 // TODO: function comment is missing 'Routine Description:'
109 // TODO: function comment is missing 'Arguments:'
110 // TODO: IdeDev - add argument and description to function comment
113 EFI_IDENTIFY_DATA
*AtaIdentifyPointer
;
118 // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of
119 // the ATA Identify command
121 AtaIdentifyPointer
= (EFI_IDENTIFY_DATA
*) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA
));
124 // use ATA PIO Data In protocol to send ATA Identify command
125 // and receive data from device
128 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
129 Status
= AtaPioDataIn (
131 (VOID
*) AtaIdentifyPointer
,
132 sizeof (EFI_IDENTIFY_DATA
),
141 // If ATA Identify command succeeds, then according to the received
143 // identify the device type ( ATA or not ).
144 // If ATA device, fill the information in IdeDev.
145 // If not ATA device, return IDE_DEVICE_ERROR
147 if (!EFI_ERROR (Status
)) {
149 IdeDev
->pIdData
= AtaIdentifyPointer
;
152 // Print ATA Module Name
154 PrintAtaModuleName (IdeDev
);
157 // bit 15 of pAtaIdentify->config is used to identify whether device is
158 // ATA device or ATAPI device.
159 // if 0, means ATA device; if 1, means ATAPI device.
161 if ((AtaIdentifyPointer
->AtaData
.config
& 0x8000) == 0x00) {
163 // Detect if support S.M.A.R.T. If yes, enable it as default
165 AtaSMARTSupport (IdeDev
);
168 // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)
170 Status
= AtaAtapi6Identify (IdeDev
);
171 if (!EFI_ERROR (Status
)) {
173 // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()
178 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
180 IdeDev
->Type
= IdeHardDisk
;
183 // Block Media Information:
184 // Media->LogicalPartition , Media->WriteCaching will be filled
185 // in the DiscoverIdeDevcie() function.
187 IdeDev
->BlkIo
.Media
->IoAlign
= 4;
188 IdeDev
->BlkIo
.Media
->MediaId
= 1;
189 IdeDev
->BlkIo
.Media
->RemovableMedia
= FALSE
;
190 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
191 IdeDev
->BlkIo
.Media
->ReadOnly
= FALSE
;
192 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
195 // Calculate device capacity
197 Capacity
= ((UINT32
)AtaIdentifyPointer
->AtaData
.user_addressable_sectors_hi
<< 16) |
198 AtaIdentifyPointer
->AtaData
.user_addressable_sectors_lo
;
199 IdeDev
->BlkIo
.Media
->LastBlock
= Capacity
- 1;
206 gBS
->FreePool (AtaIdentifyPointer
);
208 // Make sure the pIdData will not be freed again.
210 IdeDev
->pIdData
= NULL
;
212 return EFI_DEVICE_ERROR
;
218 IN IDE_BLK_IO_DEV
*IdeDev
227 This function is called by ATAIdentify() to identity whether this disk
228 supports ATA/ATAPI6 48bit addressing, ie support >120G capacity
231 IDE_BLK_IO_DEV IN *IdeDev
232 pointer pointing to IDE_BLK_IO_DEV data structure, used
233 to record all the information of the IDE device.
237 EFI_SUCCESS - The disk specified by IdeDev is a Atapi6 supported one
238 and 48-bit addressing must be used
240 EFI_UNSUPPORTED - The disk dosn't not support Atapi6 or it supports but
241 the capacity is below 120G, 48bit addressing is not
246 This function must be called after DEVICE_IDENTITY command has been
247 successfully returned
249 // TODO: function comment is missing 'Routine Description:'
250 // TODO: function comment is missing 'Arguments:'
251 // TODO: IdeDev - add argument and description to function comment
256 EFI_IDENTIFY_DATA
*Atapi6IdentifyStruct
;
258 if (IdeDev
->pIdData
== NULL
) {
259 return EFI_UNSUPPORTED
;
262 Atapi6IdentifyStruct
= IdeDev
->pIdData
;
264 if ((Atapi6IdentifyStruct
->AtapiData
.cmd_set_support_83
& bit10
) == 0) {
266 // The device dosn't support 48 bit addressing
268 return EFI_UNSUPPORTED
;
272 // 48 bit address feature set is supported, get maximum capacity
274 Capacity
= Atapi6IdentifyStruct
->AtapiData
.max_user_lba_for_48bit_addr
[0];
275 for (Index
= 1; Index
< 4; Index
++) {
277 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
279 TmpLba
= Atapi6IdentifyStruct
->AtapiData
.max_user_lba_for_48bit_addr
[Index
];
280 Capacity
|= LShiftU64 (TmpLba
, 16 * Index
);
283 if (Capacity
> MAX_28BIT_ADDRESSING_CAPACITY
) {
285 // Capacity exceeds 120GB. 48-bit addressing is really needed
287 IdeDev
->Type
= Ide48bitAddressingHardDisk
;
290 // Fill block media information:Media->LogicalPartition ,
291 // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.
293 IdeDev
->BlkIo
.Media
->IoAlign
= 4;
294 IdeDev
->BlkIo
.Media
->MediaId
= 1;
295 IdeDev
->BlkIo
.Media
->RemovableMedia
= FALSE
;
296 IdeDev
->BlkIo
.Media
->MediaPresent
= TRUE
;
297 IdeDev
->BlkIo
.Media
->ReadOnly
= FALSE
;
298 IdeDev
->BlkIo
.Media
->BlockSize
= 0x200;
299 IdeDev
->BlkIo
.Media
->LastBlock
= Capacity
- 1;
304 return EFI_UNSUPPORTED
;
309 IN IDE_BLK_IO_DEV
*IdeDev
317 This function is called by ATAIdentify() or ATAPIIdentify()
318 to print device's module name.
322 IDE_BLK_IO_DEV IN *IdeDev
323 pointer pointing to IDE_BLK_IO_DEV data structure, used
324 to record all the information of the IDE device.
331 // TODO: function comment is missing 'Routine Description:'
332 // TODO: function comment is missing 'Arguments:'
333 // TODO: IdeDev - add argument and description to function comment
335 if (IdeDev
->pIdData
== NULL
) {
339 SwapStringChars (IdeDev
->ModelName
, IdeDev
->pIdData
->AtaData
.ModelName
, 40);
340 IdeDev
->ModelName
[40] = 0x00;
345 IN IDE_BLK_IO_DEV
*IdeDev
,
350 IN UINT8 SectorCount
,
351 IN UINT8 SectorNumber
,
352 IN UINT8 CylinderLsb
,
361 This function is used to send out ATA commands conforms to the
362 PIO Data In Protocol.
366 IDE_BLK_IO_DEV IN *IdeDev
367 pointer pointing to IDE_BLK_IO_DEV data structure, used
368 to record all the information of the IDE device.
371 buffer contained data transferred from device to host.
374 data size in byte unit of the buffer.
377 value of the Command Register
380 value of the Head/Device Register
383 value of the Sector Count Register
385 UINT8 IN SectorNumber
386 value of the Sector Number Register
389 value of the low byte of the Cylinder Register
392 value of the high byte of the Cylinder Register
397 send out the ATA command and device send required
404 // TODO: function comment is missing 'Routine Description:'
405 // TODO: function comment is missing 'Arguments:'
406 // TODO: IdeDev - add argument and description to function comment
407 // TODO: Buffer - add argument and description to function comment
408 // TODO: ByteCount - add argument and description to function comment
409 // TODO: AtaCommand - add argument and description to function comment
410 // TODO: Head - add argument and description to function comment
411 // TODO: SectorCount - add argument and description to function comment
412 // TODO: SectorNumber - add argument and description to function comment
413 // TODO: CylinderLsb - add argument and description to function comment
414 // TODO: CylinderMsb - add argument and description to function comment
421 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
422 if (EFI_ERROR (Status
)) {
423 return EFI_DEVICE_ERROR
;
427 // e0:1110,0000-- bit7 and bit5 are reserved bits.
428 // bit6 set means LBA mode
432 IdeDev
->IoPort
->Head
,
433 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0 | Head
)
437 // All ATAPI device's ATA commands can be issued regardless of the
440 if (IdeDev
->Type
== IdeHardDisk
) {
442 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
443 if (EFI_ERROR (Status
)) {
444 return EFI_DEVICE_ERROR
;
448 // set all the command parameters
449 // Before write to all the following registers, BSY and DRQ must be 0.
451 Status
= DRQClear2 (IdeDev
, ATATIMEOUT
);
452 if (EFI_ERROR (Status
)) {
453 return EFI_DEVICE_ERROR
;
456 if (AtaCommand
== SET_FEATURES_CMD
) {
457 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x03);
460 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount
);
461 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, SectorNumber
);
462 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, CylinderLsb
);
463 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, CylinderMsb
);
466 // send command via Command Register
468 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
470 Buffer16
= (UINT16
*) Buffer
;
473 // According to PIO data in protocol, host can perform a series of reads to
474 // the data register after each time device set DRQ ready;
475 // The data size of "a series of read" is command specific.
476 // For most ATA command, data size received from device will not exceed
477 // 1 sector, hence the data size for "a series of read" can be the whole data
478 // size of one command request.
479 // For ATA command such as Read Sector command, the data size of one ATA
480 // command request is often larger than 1 sector, according to the
481 // Read Sector command, the data size of "a series of read" is exactly 1
483 // Here for simplification reason, we specify the data size for
484 // "a series of read" to 1 sector (256 words) if data size of one ATA command
485 // request is larger than 256 words.
490 // used to record bytes of currently transfered data
494 while (WordCount
< ByteCount
/ 2) {
496 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
498 Status
= DRQReady2 (IdeDev
, ATATIMEOUT
);
499 if (EFI_ERROR (Status
)) {
500 return EFI_DEVICE_ERROR
;
503 Status
= CheckErrorStatus (IdeDev
);
504 if (EFI_ERROR (Status
)) {
505 return EFI_DEVICE_ERROR
;
509 // Get the byte count for one series of read
511 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
512 Increment
= ByteCount
/ 2 - WordCount
;
515 IDEReadPortWMultiple (
517 IdeDev
->IoPort
->Data
,
522 WordCount
+= Increment
;
523 Buffer16
+= Increment
;
527 DRQClear (IdeDev
, ATATIMEOUT
);
529 return CheckErrorStatus (IdeDev
);
534 IN IDE_BLK_IO_DEV
*IdeDev
,
539 IN UINT8 SectorCount
,
540 IN UINT8 SectorNumber
,
541 IN UINT8 CylinderLsb
,
550 This function is used to send out ATA commands conforms to the
551 PIO Data Out Protocol.
555 IDE_BLK_IO_DEV IN *IdeDev
556 pointer pointing to IDE_BLK_IO_DEV data structure, used
557 to record all the information of the IDE device.
560 buffer contained data transferred from host to device.
563 data size in byte unit of the buffer.
566 value of the Command Register
569 value of the Head/Device Register
572 value of the Sector Count Register
574 UINT8 IN SectorNumber
575 value of the Sector Number Register
578 value of the low byte of the Cylinder Register
581 value of the high byte of the Cylinder Register
586 send out the ATA command and device received required
594 // TODO: function comment is missing 'Routine Description:'
595 // TODO: function comment is missing 'Arguments:'
596 // TODO: IdeDev - add argument and description to function comment
597 // TODO: Buffer - add argument and description to function comment
598 // TODO: ByteCount - add argument and description to function comment
599 // TODO: AtaCommand - add argument and description to function comment
600 // TODO: Head - add argument and description to function comment
601 // TODO: SectorCount - add argument and description to function comment
602 // TODO: SectorNumber - add argument and description to function comment
603 // TODO: CylinderLsb - add argument and description to function comment
604 // TODO: CylinderMsb - add argument and description to function comment
611 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
612 if (EFI_ERROR (Status
)) {
613 return EFI_DEVICE_ERROR
;
617 // select device via Head/Device register.
618 // Before write Head/Device register, BSY and DRQ must be 0.
620 Status
= DRQClear2 (IdeDev
, ATATIMEOUT
);
621 if (EFI_ERROR (Status
)) {
622 return EFI_DEVICE_ERROR
;
626 // e0:1110,0000-- bit7 and bit5 are reserved bits.
627 // bit6 set means LBA mode
631 IdeDev
->IoPort
->Head
,
632 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0 | Head
)
635 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
636 if (EFI_ERROR (Status
)) {
637 return EFI_DEVICE_ERROR
;
641 // set all the command parameters
642 // Before write to all the following registers, BSY and DRQ must be 0.
644 Status
= DRQClear2 (IdeDev
, ATATIMEOUT
);
645 if (EFI_ERROR (Status
)) {
646 return EFI_DEVICE_ERROR
;
649 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount
);
650 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, SectorNumber
);
651 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, CylinderLsb
);
652 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, CylinderMsb
);
655 // send command via Command Register
657 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
659 Buffer16
= (UINT16
*) Buffer
;
662 // According to PIO data out protocol, host can perform a series of
663 // writes to the data register after each time device set DRQ ready;
664 // The data size of "a series of read" is command specific.
665 // For most ATA command, data size written to device will not exceed 1 sector,
666 // hence the data size for "a series of write" can be the data size of one
668 // For ATA command such as Write Sector command, the data size of one
669 // ATA command request is often larger than 1 sector, according to the
670 // Write Sector command, the data size of "a series of read" is exactly
672 // Here for simplification reason, we specify the data size for
673 // "a series of write" to 1 sector (256 words) if data size of one ATA command
674 // request is larger than 256 words.
679 while (WordCount
< ByteCount
/ 2) {
682 // DRQReady2-- read Alternate Status Register to determine the DRQ bit
683 // data transfer can be performed only when DRQ is ready.
685 Status
= DRQReady2 (IdeDev
, ATATIMEOUT
);
686 if (EFI_ERROR (Status
)) {
687 return EFI_DEVICE_ERROR
;
690 Status
= CheckErrorStatus (IdeDev
);
691 if (EFI_ERROR (Status
)) {
692 return EFI_DEVICE_ERROR
;
696 // Check the remaining byte count is less than 512 bytes
698 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
699 Increment
= ByteCount
/ 2 - WordCount
;
702 // perform a series of write without check DRQ ready
705 IDEWritePortWMultiple (
707 IdeDev
->IoPort
->Data
,
711 WordCount
+= Increment
;
712 Buffer16
+= Increment
;
716 DRQClear (IdeDev
, ATATIMEOUT
);
718 return CheckErrorStatus (IdeDev
);
723 IN IDE_BLK_IO_DEV
*IdeDev
731 This function is used to analyze the Status Register and print out
732 some debug information and if there is ERR bit set in the Status
733 Register, the Error Register's value is also be parsed and print out.
737 IDE_BLK_IO_DEV IN *IdeDev
738 pointer pointing to IDE_BLK_IO_DEV data structure, used
739 to record all the information of the IDE device.
743 No err information in the Status Register.
746 Any err information in the Status Register.
750 // TODO: function comment is missing 'Routine Description:'
751 // TODO: function comment is missing 'Arguments:'
752 // TODO: IdeDev - add argument and description to function comment
754 UINT8 StatusRegister
;
762 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
766 if (StatusRegister
& DWF
) {
769 "CheckErrorStatus()-- %02x : Error : Write Fault\n",
774 if (StatusRegister
& CORR
) {
777 "CheckErrorStatus()-- %02x : Error : Corrected Data\n",
782 if (StatusRegister
& ERR
) {
783 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
785 if (ErrorRegister
& BBK_ERR
) {
788 "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",
793 if (ErrorRegister
& UNC_ERR
) {
796 "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",
801 if (ErrorRegister
& MC_ERR
) {
804 "CheckErrorStatus()-- %02x : Error : Media Change\n",
809 if (ErrorRegister
& ABRT_ERR
) {
812 "CheckErrorStatus()-- %02x : Error : Abort\n",
817 if (ErrorRegister
& TK0NF_ERR
) {
820 "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",
825 if (ErrorRegister
& AMNF_ERR
) {
828 "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",
836 if ((StatusRegister
& (ERR
| DWF
| CORR
)) == 0) {
840 return EFI_DEVICE_ERROR
;
846 IN IDE_BLK_IO_DEV
*IdeDev
,
849 IN UINTN NumberOfBlocks
857 This function is called by the AtaBlkIoReadBlocks() to perform
858 reading from media in block unit.
862 IDE_BLK_IO_DEV IN *IdeDev
863 pointer pointing to IDE_BLK_IO_DEV data structure, used
864 to record all the information of the IDE device.
867 A pointer to the destination buffer for the data.
870 The starting logical block address to read from
873 UINTN IN NumberOfBlocks
874 The number of transfer data blocks.
877 return status is fully dependent on the return status
878 of AtaPioDataIn() function.
882 // TODO: function comment is missing 'Routine Description:'
883 // TODO: function comment is missing 'Arguments:'
884 // TODO: IdeDev - add argument and description to function comment
885 // TODO: DataBuffer - add argument and description to function comment
886 // TODO: Lba - add argument and description to function comment
887 // TODO: NumberOfBlocks - add argument and description to function comment
890 UINTN BlocksRemaining
;
905 // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol
907 AtaCommand
= READ_SECTORS_CMD
;
910 BlocksRemaining
= NumberOfBlocks
;
912 Lba32
= (UINT32
) Lba
;
914 Status
= EFI_SUCCESS
;
916 while (BlocksRemaining
> 0) {
919 // in ATA-3 spec, LBA is in 28 bit width
921 Lba0
= (UINT8
) Lba32
;
922 Lba1
= (UINT8
) (Lba32
>> 8);
923 Lba2
= (UINT8
) (Lba32
>> 16);
925 // low 4 bit of Lba3 stands for LBA bit24~bit27.
927 Lba3
= (UINT8
) ((Lba32
>> 24) & 0x0f);
929 if (BlocksRemaining
>= 0x100) {
932 // SectorCount8 is sent to Sector Count register, 0x00 means 256
933 // sectors to be read
937 // SectorCount is used to record the number of sectors to be read
942 SectorCount8
= (UINT8
) BlocksRemaining
;
943 SectorCount
= (UINT16
) BlocksRemaining
;
947 // ByteCount is the number of bytes that will be read
949 ByteCount
= SectorCount
* (IdeDev
->BlkIo
.Media
->BlockSize
);
952 // call AtaPioDataIn() to send Read Sector Command and receive data read
954 Status
= AtaPioDataIn (
965 if (EFI_ERROR (Status
)) {
969 Lba32
+= SectorCount
;
970 Buffer
= ((UINT8
*) Buffer
+ ByteCount
);
971 BlocksRemaining
-= SectorCount
;
979 IN IDE_BLK_IO_DEV
*IdeDev
,
982 IN UINTN NumberOfBlocks
990 This function is called by the AtaBlkIoWriteBlocks() to perform
991 writing onto media in block unit.
995 IDE_BLK_IO_DEV IN *IdeDev
996 pointer pointing to IDE_BLK_IO_DEV data structure,used
997 to record all the information of the IDE device.
1000 A pointer to the source buffer for the data.
1003 The starting logical block address to write onto
1006 UINTN IN NumberOfBlocks
1007 The number of transfer data blocks.
1011 return status is fully dependent on the return status
1012 of AtaPioDataOut() function.
1016 // TODO: function comment is missing 'Routine Description:'
1017 // TODO: function comment is missing 'Arguments:'
1018 // TODO: IdeDev - add argument and description to function comment
1019 // TODO: BufferData - add argument and description to function comment
1020 // TODO: Lba - add argument and description to function comment
1021 // TODO: NumberOfBlocks - add argument and description to function comment
1024 UINTN BlocksRemaining
;
1036 Buffer
= BufferData
;
1039 // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol
1041 AtaCommand
= WRITE_SECTORS_CMD
;
1043 BlocksRemaining
= NumberOfBlocks
;
1045 Lba32
= (UINT32
) Lba
;
1047 Status
= EFI_SUCCESS
;
1049 while (BlocksRemaining
> 0) {
1051 Lba0
= (UINT8
) Lba32
;
1052 Lba1
= (UINT8
) (Lba32
>> 8);
1053 Lba2
= (UINT8
) (Lba32
>> 16);
1054 Lba3
= (UINT8
) ((Lba32
>> 24) & 0x0f);
1056 if (BlocksRemaining
>= 0x100) {
1059 // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors
1062 SectorCount8
= 0x00;
1064 // SectorCount is used to record the number of sectors to be written
1069 SectorCount8
= (UINT8
) BlocksRemaining
;
1070 SectorCount
= (UINT16
) BlocksRemaining
;
1073 ByteCount
= SectorCount
* (IdeDev
->BlkIo
.Media
->BlockSize
);
1075 Status
= AtaPioDataOut (
1086 if (EFI_ERROR (Status
)) {
1090 Lba32
+= SectorCount
;
1091 Buffer
= ((UINT8
*) Buffer
+ ByteCount
);
1092 BlocksRemaining
-= SectorCount
;
1100 IN IDE_BLK_IO_DEV
*IdeDev
1107 This function is used to implement the Soft Reset on the specified
1108 device. But, the ATA Soft Reset mechanism is so strong a reset method
1109 that it will force resetting on both devices connected to the
1111 It is called by IdeBlkIoReset(), a interface function of Block
1113 This function can also be used by the ATAPI device to perform reset when
1114 ATAPI Reset command is failed.
1117 IDE_BLK_IO_DEV IN *IdeDev
1118 pointer pointing to IDE_BLK_IO_DEV data structure, used
1119 to record all the information of the IDE device.
1122 Soft reset completes successfully.
1125 Any step during the reset process is failed.
1127 The registers initial values after ATA soft reset are different
1128 to the ATA device and ATAPI device.
1130 // TODO: function comment is missing 'Routine Description:'
1131 // TODO: function comment is missing 'Arguments:'
1132 // TODO: IdeDev - add argument and description to function comment
1135 UINT8 DeviceControl
;
1139 // set SRST bit to initiate soft reset
1141 DeviceControl
|= SRST
;
1144 // disable Interrupt
1146 DeviceControl
|= bit1
;
1148 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
1153 // Enable interrupt to support UDMA, and clear SRST bit
1156 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
1159 // slave device needs at most 31s to clear BSY
1161 if (WaitForBSYClear (IdeDev
, 31000) == EFI_TIMEOUT
) {
1162 return EFI_DEVICE_ERROR
;
1169 AtaBlkIoReadBlocks (
1170 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
1173 IN UINTN BufferSize
,
1182 This function is the ATA implementation for ReadBlocks in the
1183 Block I/O Protocol interface.
1187 IDE_BLK_IO_DEV IN *IdeBlkIoDevice
1188 Indicates the calling context.
1191 The media id that the read request is for.
1194 The starting logical block address to read from
1198 The size of the Buffer in bytes. This must be a
1199 multiple of the intrinsic block size of the device.
1202 A pointer to the destination buffer for the data.
1203 The caller is responsible for either having implicit
1204 or explicit ownership of the memory that data is read into.
1208 Read Blocks successfully.
1214 There is no media in the device.
1217 The MediaId is not for the current media.
1220 The BufferSize parameter is not a multiple of the
1221 intrinsic block size of the device.
1223 EFI_INVALID_PARAMETER
1224 The read request contains LBAs that are not valid,
1225 or the data buffer is not valid.
1228 If Read Block error because of device error, this function will call
1229 AtaSoftReset() function to reset device.
1231 // TODO: function comment is missing 'Routine Description:'
1232 // TODO: function comment is missing 'Arguments:'
1233 // TODO: IdeBlkIoDevice - add argument and description to function comment
1234 // TODO: MediaId - add argument and description to function comment
1235 // TODO: LBA - add argument and description to function comment
1236 // TODO: BufferSize - add argument and description to function comment
1237 // TODO: Buffer - add argument and description to function comment
1238 // TODO: EFI_MEDIA_CHANGED - add return value to function comment
1240 EFI_BLOCK_IO_MEDIA
*Media
;
1242 UINTN NumberOfBlocks
;
1245 if (Buffer
== NULL
) {
1246 return EFI_INVALID_PARAMETER
;
1249 if (BufferSize
== 0) {
1253 Status
= EFI_SUCCESS
;
1256 // Get the intrinsic block size
1258 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
1259 BlockSize
= Media
->BlockSize
;
1261 NumberOfBlocks
= BufferSize
/ BlockSize
;
1263 if (MediaId
!= Media
->MediaId
) {
1264 return EFI_MEDIA_CHANGED
;
1267 if (BufferSize
% BlockSize
!= 0) {
1268 return EFI_BAD_BUFFER_SIZE
;
1271 if (!(Media
->MediaPresent
)) {
1272 return EFI_NO_MEDIA
;
1275 if (LBA
> Media
->LastBlock
) {
1276 return EFI_INVALID_PARAMETER
;
1279 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1280 return EFI_INVALID_PARAMETER
;
1283 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
1284 return EFI_INVALID_PARAMETER
;
1287 if (IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1289 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism
1291 Status
= AtaUdmaReadExt (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1292 if (EFI_ERROR (Status
)) {
1293 Status
= AtaReadSectorsExt (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1297 // For ATA-3 compatible device, use ATA-3 read block mechanism
1298 // Notice DMA operation can only handle 32bit address
1300 if ((UINTN
) Buffer
<= 0xFFFFFFFF) {
1301 Status
= AtaUdmaRead (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1304 if (EFI_ERROR (Status
) || ((UINTN
) Buffer
> 0xFFFFFFFF)) {
1305 Status
= AtaReadSectors (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1309 if (EFI_ERROR (Status
)) {
1310 AtaSoftReset (IdeBlkIoDevice
);
1311 return EFI_DEVICE_ERROR
;
1319 AtaBlkIoWriteBlocks (
1320 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
,
1323 IN UINTN BufferSize
,
1332 This function is the ATA implementation for WriteBlocks in the
1333 Block I/O Protocol interface.
1336 IDE_BLK_IO_DEV IN *IdeBlkIoDevice
1337 Indicates the calling context.
1340 The media id that the write request is for.
1343 The starting logical block address to write onto
1347 The size of the Buffer in bytes. This must be a
1348 multiple of the intrinsic block size of the device.
1351 A pointer to the source buffer for the data.
1352 The caller is responsible for either having implicit
1353 or explicit ownership of the memory that data is
1359 Write Blocks successfully.
1362 Write Blocks failed.
1365 There is no media in the device.
1368 The MediaId is not for the current media.
1371 The BufferSize parameter is not a multiple of the
1372 intrinsic block size of the device.
1374 EFI_INVALID_PARAMETER
1375 The write request contains LBAs that are not valid,
1376 or the data buffer is not valid.
1379 If Write Block error because of device error, this function will call
1380 AtaSoftReset() function to reset device.
1382 // TODO: function comment is missing 'Routine Description:'
1383 // TODO: function comment is missing 'Arguments:'
1384 // TODO: IdeBlkIoDevice - add argument and description to function comment
1385 // TODO: MediaId - add argument and description to function comment
1386 // TODO: LBA - add argument and description to function comment
1387 // TODO: BufferSize - add argument and description to function comment
1388 // TODO: Buffer - add argument and description to function comment
1389 // TODO: EFI_MEDIA_CHANGED - add return value to function comment
1392 EFI_BLOCK_IO_MEDIA
*Media
;
1394 UINTN NumberOfBlocks
;
1397 if (Buffer
== NULL
) {
1398 return EFI_INVALID_PARAMETER
;
1401 if (BufferSize
== 0) {
1405 Status
= EFI_SUCCESS
;
1408 // Get the intrinsic block size
1410 Media
= IdeBlkIoDevice
->BlkIo
.Media
;
1411 BlockSize
= Media
->BlockSize
;
1412 NumberOfBlocks
= BufferSize
/ BlockSize
;
1414 if (MediaId
!= Media
->MediaId
) {
1415 return EFI_MEDIA_CHANGED
;
1418 if (BufferSize
% BlockSize
!= 0) {
1419 return EFI_BAD_BUFFER_SIZE
;
1422 if (LBA
> Media
->LastBlock
) {
1423 return EFI_INVALID_PARAMETER
;
1426 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1427 return EFI_INVALID_PARAMETER
;
1430 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
1431 return EFI_INVALID_PARAMETER
;
1434 if (IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1436 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism
1438 Status
= AtaUdmaWriteExt (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1439 if (EFI_ERROR (Status
)) {
1440 Status
= AtaWriteSectorsExt (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1444 // For ATA-3 compatible device, use ATA-3 write block mechanism
1446 Status
= AtaUdmaWrite (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1447 if (EFI_ERROR (Status
) || ((UINTN
) Buffer
> 0xFFFFFFFF)) {
1448 Status
= AtaWriteSectors (IdeBlkIoDevice
, Buffer
, LBA
, NumberOfBlocks
);
1452 if (EFI_ERROR (Status
)) {
1453 AtaSoftReset (IdeBlkIoDevice
);
1454 return EFI_DEVICE_ERROR
;
1462 IN IDE_BLK_IO_DEV
*IdeDev
,
1463 IN VOID
*DataBuffer
,
1464 IN EFI_LBA StartLba
,
1465 IN UINTN NumberOfBlocks
1474 This function is called by the AtaBlkIoReadBlocks() to perform
1475 reading from media in block unit. The function has been enhanced to
1476 support >120GB access and transfer at most 65536 blocks per command
1480 IDE_BLK_IO_DEV IN *IdeDev
1481 pointer pointing to IDE_BLK_IO_DEV data structure, used
1482 to record all the information of the IDE device.
1485 A pointer to the destination buffer for the data.
1488 The starting logical block address to read from
1489 on the device media.
1491 UINTN IN NumberOfBlocks
1492 The number of transfer data blocks.
1496 return status is fully dependent on the return status
1497 of AtaPioDataInExt() function.
1501 // TODO: function comment is missing 'Routine Description:'
1502 // TODO: function comment is missing 'Arguments:'
1503 // TODO: IdeDev - add argument and description to function comment
1504 // TODO: DataBuffer - add argument and description to function comment
1505 // TODO: StartLba - add argument and description to function comment
1506 // TODO: NumberOfBlocks - add argument and description to function comment
1509 UINTN BlocksRemaining
;
1517 // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol
1519 AtaCommand
= READ_SECTORS_EXT_CMD
;
1520 Buffer
= DataBuffer
;
1521 BlocksRemaining
= NumberOfBlocks
;
1523 Status
= EFI_SUCCESS
;
1525 while (BlocksRemaining
> 0) {
1527 if (BlocksRemaining
>= 0x10000) {
1529 // SectorCount is used to record the number of sectors to be read
1530 // Max 65536 sectors can be transfered at a time.
1532 SectorCount
= 0xffff;
1534 SectorCount
= (UINT16
) BlocksRemaining
;
1538 // ByteCount is the number of bytes that will be read
1540 ByteCount
= SectorCount
* (IdeDev
->BlkIo
.Media
->BlockSize
);
1543 // call AtaPioDataInExt() to send Read Sector Command and receive data read
1545 Status
= AtaPioDataInExt (
1553 if (EFI_ERROR (Status
)) {
1557 Lba64
+= SectorCount
;
1558 Buffer
= ((UINT8
*) Buffer
+ ByteCount
);
1559 BlocksRemaining
-= SectorCount
;
1566 AtaWriteSectorsExt (
1567 IN IDE_BLK_IO_DEV
*IdeDev
,
1568 IN VOID
*DataBuffer
,
1569 IN EFI_LBA StartLba
,
1570 IN UINTN NumberOfBlocks
1579 This function is called by the AtaBlkIoWriteBlocks() to perform
1580 writing onto media in block unit. The function has been enhanced to
1581 support >120GB access and transfer at most 65536 blocks per command
1585 IDE_BLK_IO_DEV IN *IdeDev
1586 pointer pointing to IDE_BLK_IO_DEV data structure,used
1587 to record all the information of the IDE device.
1590 A pointer to the source buffer for the data.
1593 The starting logical block address to write onto
1596 UINTN IN NumberOfBlocks
1597 The number of transfer data blocks.
1601 return status is fully dependent on the return status
1602 of AtaPioDataOutExt() function.
1606 // TODO: function comment is missing 'Routine Description:'
1607 // TODO: function comment is missing 'Arguments:'
1608 // TODO: IdeDev - add argument and description to function comment
1609 // TODO: DataBuffer - add argument and description to function comment
1610 // TODO: StartLba - add argument and description to function comment
1611 // TODO: NumberOfBlocks - add argument and description to function comment
1615 UINTN BlocksRemaining
;
1622 // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol
1624 AtaCommand
= WRITE_SECTORS_EXT_CMD
;
1626 Buffer
= DataBuffer
;
1627 BlocksRemaining
= NumberOfBlocks
;
1629 Status
= EFI_SUCCESS
;
1631 while (BlocksRemaining
> 0) {
1633 if (BlocksRemaining
>= 0x10000) {
1635 // SectorCount is used to record the number of sectors to be written.
1636 // Max 65536 sectors can be transfered at a time.
1638 SectorCount
= 0xffff;
1640 SectorCount
= (UINT16
) BlocksRemaining
;
1644 // ByteCount is the number of bytes that will be written
1646 ByteCount
= SectorCount
* (IdeDev
->BlkIo
.Media
->BlockSize
);
1649 // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command
1651 Status
= AtaPioDataOutExt (
1659 if (EFI_ERROR (Status
)) {
1663 Lba64
+= SectorCount
;
1664 Buffer
= ((UINT8
*) Buffer
+ ByteCount
);
1665 BlocksRemaining
-= SectorCount
;
1673 IN IDE_BLK_IO_DEV
*IdeDev
,
1674 IN OUT VOID
*Buffer
,
1675 IN UINT32 ByteCount
,
1676 IN UINT8 AtaCommand
,
1677 IN EFI_LBA StartLba
,
1678 IN UINT16 SectorCount
1687 This function is used to send out ATA commands conforms to the
1688 PIO Data In Protocol, supporting ATA/ATAPI-6 standard
1690 Comparing with ATA-3 data in protocol, we have two differents here:
1691 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
1692 wait will frequently fail... cause writing function return error)
1694 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
1695 slow down writing performance by 100 times!)
1700 IDE_BLK_IO_DEV IN *IdeDev
1701 pointer pointing to IDE_BLK_IO_DEV data structure, used
1702 to record all the information of the IDE device.
1705 buffer contained data transferred from device to host.
1708 data size in byte unit of the buffer.
1711 value of the Command Register
1714 the start LBA of this transaction
1716 UINT16 IN SectorCount
1717 the count of sectors to be transfered
1722 send out the ATA command and device send required
1726 command sent failed.
1729 // TODO: function comment is missing 'Routine Description:'
1730 // TODO: function comment is missing 'Arguments:'
1731 // TODO: IdeDev - add argument and description to function comment
1732 // TODO: Buffer - add argument and description to function comment
1733 // TODO: ByteCount - add argument and description to function comment
1734 // TODO: AtaCommand - add argument and description to function comment
1735 // TODO: StartLba - add argument and description to function comment
1736 // TODO: SectorCount - add argument and description to function comment
1748 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1749 if (EFI_ERROR (Status
)) {
1750 return EFI_DEVICE_ERROR
;
1754 // Select device, set bit6 as 1 to indicate LBA mode is used
1756 DevSel
= (UINT8
) (IdeDev
->Device
<< 4);
1760 IdeDev
->IoPort
->Head
,
1765 // Wait for DRDY singnal asserting. ATAPI device needn't wait
1767 if ( (IdeDev
->Type
== IdeHardDisk
) ||
1768 (IdeDev
->Type
== Ide48bitAddressingHardDisk
)) {
1770 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
1771 if (EFI_ERROR (Status
)) {
1772 return EFI_DEVICE_ERROR
;
1777 // Fill feature register if needed
1779 if (AtaCommand
== SET_FEATURES_CMD
) {
1780 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x03);
1784 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
1786 SectorCount8
= (UINT8
) (SectorCount
>> 8);
1787 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1789 SectorCount8
= (UINT8
) SectorCount
;
1790 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1793 // Fill the start LBA registers, which are also two-byte FIFO
1795 LbaLow
= (UINT8
) RShiftU64 (StartLba
, 24);
1796 LbaMid
= (UINT8
) RShiftU64 (StartLba
, 32);
1797 LbaHigh
= (UINT8
) RShiftU64 (StartLba
, 40);
1798 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1799 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1800 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1802 LbaLow
= (UINT8
) StartLba
;
1803 LbaMid
= (UINT8
) RShiftU64 (StartLba
, 8);
1804 LbaHigh
= (UINT8
) RShiftU64 (StartLba
, 16);
1805 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1806 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1807 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1810 // Send command via Command Register, invoking the processing of this command
1812 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
1814 Buffer16
= (UINT16
*) Buffer
;
1817 // According to PIO data in protocol, host can perform a series of reads to
1818 // the data register after each time device set DRQ ready;
1827 // used to record bytes of currently transfered data
1831 while (WordCount
< ByteCount
/ 2) {
1833 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
1835 Status
= DRQReady2 (IdeDev
, ATATIMEOUT
);
1836 if (EFI_ERROR (Status
)) {
1837 return EFI_DEVICE_ERROR
;
1840 Status
= CheckErrorStatus (IdeDev
);
1841 if (EFI_ERROR (Status
)) {
1842 return EFI_DEVICE_ERROR
;
1846 // Get the byte count for one series of read
1848 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
1849 Increment
= ByteCount
/ 2 - WordCount
;
1852 IDEReadPortWMultiple (
1854 IdeDev
->IoPort
->Data
,
1859 WordCount
+= Increment
;
1860 Buffer16
+= Increment
;
1864 return CheckErrorStatus (IdeDev
);
1869 IN IDE_BLK_IO_DEV
*IdeDev
,
1871 IN UINT32 ByteCount
,
1872 IN UINT8 AtaCommand
,
1873 IN EFI_LBA StartLba
,
1874 IN UINT16 SectorCount
1883 This function is used to send out ATA commands conforms to the
1884 PIO Data Out Protocol, supporting ATA/ATAPI-6 standard
1886 Comparing with ATA-3 data out protocol, we have two differents here:
1887 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
1888 wait will frequently fail... cause writing function return error)
1890 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
1891 slow down writing performance by 100 times!)
1895 IDE_BLK_IO_DEV IN *IdeDev
1896 pointer pointing to IDE_BLK_IO_DEV data structure, used
1897 to record all the information of the IDE device.
1900 buffer contained data transferred from host to device.
1903 data size in byte unit of the buffer.
1906 value of the Command Register
1909 the start LBA of this transaction
1911 UINT16 IN SectorCount
1912 the count of sectors to be transfered
1917 send out the ATA command and device receive required
1921 command sent failed.
1924 // TODO: function comment is missing 'Routine Description:'
1925 // TODO: function comment is missing 'Arguments:'
1926 // TODO: IdeDev - add argument and description to function comment
1927 // TODO: Buffer - add argument and description to function comment
1928 // TODO: ByteCount - add argument and description to function comment
1929 // TODO: AtaCommand - add argument and description to function comment
1930 // TODO: StartLba - add argument and description to function comment
1931 // TODO: SectorCount - add argument and description to function comment
1943 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1944 if (EFI_ERROR (Status
)) {
1945 return EFI_DEVICE_ERROR
;
1949 // Select device. Set bit6 as 1 to indicate LBA mode is used
1951 DevSel
= (UINT8
) (IdeDev
->Device
<< 4);
1955 IdeDev
->IoPort
->Head
,
1960 // Wait for DRDY singnal asserting.
1962 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
1963 if (EFI_ERROR (Status
)) {
1964 return EFI_DEVICE_ERROR
;
1968 // Fill feature register if needed
1970 if (AtaCommand
== SET_FEATURES_CMD
) {
1971 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, 0x03);
1975 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
1977 SectorCount8
= (UINT8
) (SectorCount
>> 8);
1978 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1980 SectorCount8
= (UINT8
) SectorCount
;
1981 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1984 // Fill the start LBA registers, which are also two-byte FIFO
1986 LbaLow
= (UINT8
) RShiftU64 (StartLba
, 24);
1987 LbaMid
= (UINT8
) RShiftU64 (StartLba
, 32);
1988 LbaHigh
= (UINT8
) RShiftU64 (StartLba
, 40);
1989 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1990 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1991 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1993 LbaLow
= (UINT8
) StartLba
;
1994 LbaMid
= (UINT8
) RShiftU64 (StartLba
, 8);
1995 LbaHigh
= (UINT8
) RShiftU64 (StartLba
, 16);
1996 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1997 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1998 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
2001 // Send command via Command Register, invoking the processing of this command
2003 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
2005 Buffer16
= (UINT16
*) Buffer
;
2008 // According to PIO Data Out protocol, host can perform a series of writes to
2009 // the data register after each time device set DRQ ready;
2014 // used to record bytes of currently transfered data
2018 while (WordCount
< ByteCount
/ 2) {
2020 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
2022 Status
= DRQReady2 (IdeDev
, ATATIMEOUT
);
2023 if (EFI_ERROR (Status
)) {
2024 return EFI_DEVICE_ERROR
;
2027 Status
= CheckErrorStatus (IdeDev
);
2028 if (EFI_ERROR (Status
)) {
2029 return EFI_DEVICE_ERROR
;
2033 // Write data into device by one series of writing to data register
2035 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
2036 Increment
= ByteCount
/ 2 - WordCount
;
2039 IDEWritePortWMultiple (
2041 IdeDev
->IoPort
->Data
,
2046 WordCount
+= Increment
;
2047 Buffer16
+= Increment
;
2054 return CheckErrorStatus (IdeDev
);
2060 IN IDE_BLK_IO_DEV
*IdeDev
2068 Enable SMART of the disk if supported
2072 IDE_BLK_IO_DEV IN *IdeDev
2073 pointer pointing to IDE_BLK_IO_DEV data structure,used
2074 to record all the information of the IDE device.
2080 // TODO: function comment is missing 'Routine Description:'
2081 // TODO: function comment is missing 'Arguments:'
2082 // TODO: IdeDev - add argument and description to function comment
2085 BOOLEAN SMARTSupported
;
2087 EFI_IDENTIFY_DATA
*TmpAtaIdentifyPointer
;
2093 // Detect if the device supports S.M.A.R.T.
2095 if ((IdeDev
->pIdData
->AtaData
.command_set_supported_83
& 0xc000) != 0x4000) {
2097 // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)
2101 if ((IdeDev
->pIdData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
2103 // S.M.A.R.T is not supported by the device
2105 SMARTSupported
= FALSE
;
2107 SMARTSupported
= TRUE
;
2111 if (!SMARTSupported
) {
2113 // Report nonsupport status code
2115 REPORT_STATUS_CODE (
2116 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
2117 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
2121 // Enable this feature
2123 REPORT_STATUS_CODE (
2125 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
2128 Device
= (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0);
2129 Status
= AtaNonDataCommandIn (
2133 ATA_SMART_ENABLE_OPERATION
,
2140 // Detect if this feature is enabled
2142 TmpAtaIdentifyPointer
= (EFI_IDENTIFY_DATA
*) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA
));
2144 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
2145 Status
= AtaPioDataIn (
2147 (VOID
*) TmpAtaIdentifyPointer
,
2148 sizeof (EFI_IDENTIFY_DATA
),
2156 if (EFI_ERROR (Status
)) {
2157 gBS
->FreePool (TmpAtaIdentifyPointer
);
2162 // Check if the feature is enabled
2164 if ((TmpAtaIdentifyPointer
->AtaData
.command_set_feature_enb_85
& 0x0001) == 0x0001) {
2168 AtaNonDataCommandIn (
2172 ATA_SMART_RETURN_STATUS
,
2178 LBAMid
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
);
2179 LBAHigh
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
);
2181 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
2183 // The threshold exceeded condition is not detected by the device
2185 REPORT_STATUS_CODE (
2187 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
2190 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
2192 // The threshold exceeded condition is detected by the device
2194 REPORT_STATUS_CODE (
2196 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
2202 // Report disabled status code
2204 REPORT_STATUS_CODE (
2205 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
2206 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
2210 gBS
->FreePool (TmpAtaIdentifyPointer
);
2217 AtaCommandIssueExt (
2218 IN IDE_BLK_IO_DEV
*IdeDev
,
2219 IN UINT8 AtaCommand
,
2222 IN UINT16 SectorCount
,
2223 IN EFI_LBA LbaAddress
2227 Routine Description:
2229 Send ATA Ext command into device with NON_DATA protocol
2233 IdeDev - Standard IDE device private data structure
2234 AtaCommand - The ATA command to be sent
2235 Device - The value in Device register
2236 Feature - The value in Feature register
2237 SectorCount - The value in SectorCount register
2238 LbaAddress - The LBA address in 48-bit mode
2242 EFI_SUCCESS - Reading succeed
2243 EFI_DEVICE_ERROR - Error executing commands on this device
2254 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
2255 if (EFI_ERROR (Status
)) {
2256 return EFI_DEVICE_ERROR
;
2260 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
2264 IdeDev
->IoPort
->Head
,
2265 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0)
2269 // ATA commands for ATA device must be issued when DRDY is set
2271 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
2272 if (EFI_ERROR (Status
)) {
2273 return EFI_DEVICE_ERROR
;
2277 // Pass parameter into device register block
2279 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
2282 // Fill the feature register, which is a two-byte FIFO. Need write twice.
2284 Feature8
= (UINT8
) (Feature
>> 8);
2285 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature8
);
2287 Feature8
= (UINT8
) Feature
;
2288 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature8
);
2291 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
2293 SectorCount8
= (UINT8
) (SectorCount
>> 8);
2294 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
2296 SectorCount8
= (UINT8
) SectorCount
;
2297 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
2300 // Fill the start LBA registers, which are also two-byte FIFO
2302 LbaLow
= (UINT8
) RShiftU64 (LbaAddress
, 24);
2303 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
2304 LbaLow
= (UINT8
) LbaAddress
;
2305 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
2307 LbaMid
= (UINT8
) RShiftU64 (LbaAddress
, 32);
2308 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
2309 LbaMid
= (UINT8
) RShiftU64 (LbaAddress
, 8);
2310 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
2312 LbaHigh
= (UINT8
) RShiftU64 (LbaAddress
, 40);
2313 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
2314 LbaHigh
= (UINT8
) RShiftU64 (LbaAddress
, 16);
2315 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
2318 // Work around for Segate 160G disk writing
2323 // Send command via Command Register
2325 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
2328 // Stall at least 400ns
2337 IN IDE_BLK_IO_DEV
*IdeDev
,
2338 IN UINT8 AtaCommand
,
2341 IN UINT16 SectorCount
,
2342 IN EFI_LBA LbaAddress
2346 Routine Description:
2348 Send ATA Ext command into device with NON_DATA protocol
2352 IdeDev - Standard IDE device private data structure
2353 AtaCommand - The ATA command to be sent
2354 Device - The value in Device register
2355 Feature - The value in Feature register
2356 SectorCount - The value in SectorCount register
2357 LbaAddress - The LBA address in 48-bit mode
2361 EFI_SUCCESS - Reading succeed
2362 EFI_DEVICE_ERROR - Error executing commands on this device
2374 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
2375 if (EFI_ERROR (Status
)) {
2376 return EFI_DEVICE_ERROR
;
2380 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
2384 IdeDev
->IoPort
->Head
,
2385 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0)
2389 // ATA commands for ATA device must be issued when DRDY is set
2391 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
2392 if (EFI_ERROR (Status
)) {
2393 return EFI_DEVICE_ERROR
;
2396 Lba0
= (UINT8
) LbaAddress
;
2397 Lba1
= (UINT8
) RShiftU64 (LbaAddress
, 8);
2398 Lba2
= (UINT8
) RShiftU64 (LbaAddress
, 16);
2399 Lba3
= (UINT8
) RShiftU64 (LbaAddress
, 24);
2403 // Pass parameter into device register block
2405 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
2408 // Fill the feature register, which is a two-byte FIFO. Need write twice.
2410 Feature8
= (UINT8
) Feature
;
2411 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature8
);
2414 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
2416 SectorCount8
= (UINT8
) SectorCount
;
2417 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
2420 // Fill the start LBA registers, which are also two-byte FIFO
2423 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, Lba0
);
2424 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, Lba1
);
2425 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, Lba2
);
2428 // Send command via Command Register
2430 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
2433 // Stall at least 400ns
2442 IN IDE_BLK_IO_DEV
*IdeDev
,
2443 IN VOID
*DataBuffer
,
2444 IN EFI_LBA StartLba
,
2445 IN UINTN NumberOfBlocks
2454 This function is called by the AtaBlkIoReadBlocks() to perform
2455 reading from media in block unit. The function has been enhanced to
2456 support >120GB access and transfer at most 65536 blocks per command
2460 IDE_BLK_IO_DEV IN *IdeDev
2461 pointer pointing to IDE_BLK_IO_DEV data structure, used
2462 to record all the information of the IDE device.
2465 A pointer to the destination buffer for the data.
2468 The starting logical block address to read from
2469 on the device media.
2471 UINTN IN NumberOfBlocks
2472 The number of transfer data blocks.
2476 The device status of UDMA operation. If the operation is
2477 successful, return EFI_SUCCESS.
2480 // TODO: function comment is missing 'Routine Description:'
2481 // TODO: function comment is missing 'Arguments:'
2482 // TODO: IdeDev - add argument and description to function comment
2483 // TODO: DataBuffer - add argument and description to function comment
2484 // TODO: StartLba - add argument and description to function comment
2485 // TODO: NumberOfBlocks - add argument and description to function comment
2486 // TODO: EFI_UNSUPPORTED - add return value to function comment
2487 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2488 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2489 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2491 IDE_DMA_PRD
*PrdAddr
;
2492 IDE_DMA_PRD
*UsedPrdAddr
;
2493 IDE_DMA_PRD
*TempPrdAddr
;
2494 UINT8 RegisterValue
;
2496 UINT64 IoPortForBmic
;
2497 UINT64 IoPortForBmis
;
2498 UINT64 IoPortForBmid
;
2502 UINTN ByteAvailable
;
2504 UINTN RemainBlockNum
;
2505 UINT8 DeviceControl
;
2508 // Channel and device differential. Select device.
2510 Device
= (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0);
2513 // Enable interrupt to support UDMA and Select device
2516 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
2518 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
2520 if (IdePrimary
== IdeDev
->Channel
) {
2521 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICP_OFFSET
;
2522 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
2523 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDP_OFFSET
;
2525 if (IdeSecondary
== IdeDev
->Channel
) {
2526 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICS_OFFSET
;
2527 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
2528 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDS_OFFSET
;
2530 return EFI_UNSUPPORTED
;
2534 RemainBlockNum
= NumberOfBlocks
;
2535 while (RemainBlockNum
> 0) {
2537 if (RemainBlockNum
>= MAX_DMA_EXT_COMMAND_SECTORS
) {
2539 // SectorCount is used to record the number of sectors to be read
2540 // Max 65536 sectors can be transfered at a time.
2542 NumberOfBlocks
= MAX_DMA_EXT_COMMAND_SECTORS
;
2543 RemainBlockNum
-= MAX_DMA_EXT_COMMAND_SECTORS
;
2545 NumberOfBlocks
= (UINT16
) RemainBlockNum
;
2550 // Calculate the number of PRD table to make sure the memory region
2551 // not cross 64K boundary
2553 ByteCount
= NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
2554 PrdTableNum
= ((ByteCount
>> 16) + 1) + 1;
2559 PrdAddr
= (IDE_DMA_PRD
*) AllocateZeroPool ((2 * PrdTableNum
* sizeof (IDE_DMA_PRD
)));
2562 // To make sure PRD is allocated in one 64K page
2564 if (((UINTN
) PrdAddr
& 0x0FFFF) > (((UINTN
) PrdAddr
+ PrdTableNum
* sizeof (IDE_DMA_PRD
) - 1) & 0x0FFFF)) {
2565 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x10000) & 0xFFFF0000);
2567 if ((UINTN
) PrdAddr
& 0x03) {
2568 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x04) & 0xFFFFFFFC);
2570 UsedPrdAddr
= PrdAddr
;
2575 // Build the PRD table
2577 PrdBuffer
= DataBuffer
;
2578 TempPrdAddr
= UsedPrdAddr
;
2581 ByteAvailable
= 0x10000 - ((UINTN
) PrdBuffer
& 0xFFFF);
2583 if (ByteCount
<= ByteAvailable
) {
2584 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
2585 TempPrdAddr
->ByteCount
= (UINT16
) ByteCount
;
2586 TempPrdAddr
->EndOfTable
= 0x8000;
2590 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
2591 TempPrdAddr
->ByteCount
= (UINT16
) ByteAvailable
;
2593 ByteCount
-= ByteAvailable
;
2594 PrdBuffer
+= ByteAvailable
;
2599 // Set the base address to BMID register
2601 IdeDev
->PciIo
->Io
.Write (
2603 EfiPciIoWidthUint32
,
2604 EFI_PCI_IO_PASS_THROUGH_BAR
,
2611 // Set BMIC register to identify the operation direction
2613 IdeDev
->PciIo
->Io
.Read (
2616 EFI_PCI_IO_PASS_THROUGH_BAR
,
2622 RegisterValue
|= BMIC_nREAD
;
2624 IdeDev
->PciIo
->Io
.Write (
2627 EFI_PCI_IO_PASS_THROUGH_BAR
,
2634 // Read BMIS register and clear ERROR and INTR bit
2636 IdeDev
->PciIo
->Io
.Read (
2639 EFI_PCI_IO_PASS_THROUGH_BAR
,
2645 RegisterValue
|= BMIS_INTERRUPT
| BMIS_ERROR
;
2647 IdeDev
->PciIo
->Io
.Write (
2650 EFI_PCI_IO_PASS_THROUGH_BAR
,
2657 // Issue READ DMA EXT command
2659 Status
= AtaCommandIssueExt (
2664 (UINT16
) NumberOfBlocks
,
2667 if (EFI_ERROR (Status
)) {
2668 gBS
->FreePool (PrdAddr
);
2669 return EFI_DEVICE_ERROR
;
2673 // Set START bit of BMIC register
2675 IdeDev
->PciIo
->Io
.Read (
2678 EFI_PCI_IO_PASS_THROUGH_BAR
,
2684 RegisterValue
|= BMIC_START
;
2686 IdeDev
->PciIo
->Io
.Write (
2689 EFI_PCI_IO_PASS_THROUGH_BAR
,
2696 // Check the INTERRUPT and ERROR bit of BMIS
2700 IdeDev
->PciIo
->Io
.Read (
2703 EFI_PCI_IO_PASS_THROUGH_BAR
,
2708 if (RegisterValue
& (BMIS_INTERRUPT
| BMIS_ERROR
)) {
2709 if (RegisterValue
& BMIS_ERROR
) {
2710 gBS
->FreePool (PrdAddr
);
2711 return EFI_DEVICE_ERROR
;
2719 gBS
->FreePool (PrdAddr
);
2722 // Set START bit of BMIC register
2724 IdeDev
->PciIo
->Io
.Read (
2727 EFI_PCI_IO_PASS_THROUGH_BAR
,
2733 RegisterValue
&= ~((UINT8
) BMIC_START
);
2735 IdeDev
->PciIo
->Io
.Write (
2738 EFI_PCI_IO_PASS_THROUGH_BAR
,
2744 if (RegisterValue
& BMIS_ERROR
) {
2745 return EFI_DEVICE_ERROR
;
2748 DataBuffer
= (UINT8
*) DataBuffer
+ NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
2749 StartLba
+= NumberOfBlocks
;
2757 IN IDE_BLK_IO_DEV
*IdeDev
,
2758 IN VOID
*DataBuffer
,
2759 IN EFI_LBA StartLba
,
2760 IN UINTN NumberOfBlocks
2769 This function is called by the AtaBlkIoReadBlocks() to perform
2770 reading from media in block unit. The function has been enhanced to
2771 support >120GB access and transfer at most 65536 blocks per command
2775 IDE_BLK_IO_DEV IN *IdeDev
2776 pointer pointing to IDE_BLK_IO_DEV data structure, used
2777 to record all the information of the IDE device.
2780 A pointer to the destination buffer for the data.
2783 The starting logical block address to read from
2784 on the device media.
2786 UINTN IN NumberOfBlocks
2787 The number of transfer data blocks.
2791 The device status of UDMA operation. If the operation is
2792 successful, return EFI_SUCCESS.
2795 // TODO: function comment is missing 'Routine Description:'
2796 // TODO: function comment is missing 'Arguments:'
2797 // TODO: IdeDev - add argument and description to function comment
2798 // TODO: DataBuffer - add argument and description to function comment
2799 // TODO: StartLba - add argument and description to function comment
2800 // TODO: NumberOfBlocks - add argument and description to function comment
2801 // TODO: EFI_UNSUPPORTED - add return value to function comment
2802 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2803 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2804 // TODO: EFI_DEVICE_ERROR - add return value to function comment
2806 IDE_DMA_PRD
*PrdAddr
;
2807 IDE_DMA_PRD
*UsedPrdAddr
;
2808 IDE_DMA_PRD
*TempPrdAddr
;
2809 UINT8 RegisterValue
;
2811 UINT64 IoPortForBmic
;
2812 UINT64 IoPortForBmis
;
2813 UINT64 IoPortForBmid
;
2817 UINTN ByteAvailable
;
2819 UINTN RemainBlockNum
;
2820 UINT8 DeviceControl
;
2823 // Channel and device differential
2825 Device
= (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0);
2828 // Enable interrupt to support UDMA and Select device
2831 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
2833 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
2835 if (IdePrimary
== IdeDev
->Channel
) {
2836 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICP_OFFSET
;
2837 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
2838 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDP_OFFSET
;
2840 if (IdeSecondary
== IdeDev
->Channel
) {
2841 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICS_OFFSET
;
2842 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
2843 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDS_OFFSET
;
2845 return EFI_UNSUPPORTED
;
2849 RemainBlockNum
= NumberOfBlocks
;
2850 while (RemainBlockNum
> 0) {
2852 if (RemainBlockNum
>= MAX_DMA_COMMAND_SECTORS
) {
2854 // SectorCount is used to record the number of sectors to be read
2855 // Max 256 sectors can be transfered at a time.
2857 NumberOfBlocks
= MAX_DMA_COMMAND_SECTORS
;
2858 RemainBlockNum
-= MAX_DMA_COMMAND_SECTORS
;
2860 NumberOfBlocks
= (UINT16
) RemainBlockNum
;
2865 // Calculate the number of PRD table to make sure the memory region
2866 // not cross 64K boundary
2868 ByteCount
= NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
2869 PrdTableNum
= ((ByteCount
>> 16) + 1) + 1;
2874 PrdAddr
= (IDE_DMA_PRD
*) AllocateZeroPool ((2 * PrdTableNum
* sizeof (IDE_DMA_PRD
)));
2876 // To make sure PRD is allocated in one 64K page
2878 if (((UINTN
) PrdAddr
& 0x0FFFF) > (((UINTN
) PrdAddr
+ PrdTableNum
* sizeof (IDE_DMA_PRD
) - 1) & 0x0FFFF)) {
2879 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x10000) & 0xFFFF0000);
2881 if ((UINTN
) PrdAddr
& 0x03) {
2882 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x04) & 0xFFFFFFFC);
2884 UsedPrdAddr
= PrdAddr
;
2889 // Build the PRD table
2891 PrdBuffer
= DataBuffer
;
2892 TempPrdAddr
= UsedPrdAddr
;
2895 ByteAvailable
= 0x10000 - ((UINTN
) PrdBuffer
& 0xFFFF);
2897 if (ByteCount
<= ByteAvailable
) {
2898 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
2899 TempPrdAddr
->ByteCount
= (UINT16
) ByteCount
;
2900 TempPrdAddr
->EndOfTable
= 0x8000;
2904 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
2905 TempPrdAddr
->ByteCount
= (UINT16
) ByteAvailable
;
2907 ByteCount
-= ByteAvailable
;
2908 PrdBuffer
+= ByteAvailable
;
2913 // Set the base address to BMID register
2915 IdeDev
->PciIo
->Io
.Write (
2917 EfiPciIoWidthUint32
,
2918 EFI_PCI_IO_PASS_THROUGH_BAR
,
2925 // Set BMIC register to identify the operation direction
2927 IdeDev
->PciIo
->Io
.Read (
2930 EFI_PCI_IO_PASS_THROUGH_BAR
,
2936 RegisterValue
|= BMIC_nREAD
;
2938 IdeDev
->PciIo
->Io
.Write (
2941 EFI_PCI_IO_PASS_THROUGH_BAR
,
2948 // Read BMIS register and clear ERROR and INTR bit
2950 IdeDev
->PciIo
->Io
.Read (
2953 EFI_PCI_IO_PASS_THROUGH_BAR
,
2959 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
2961 IdeDev
->PciIo
->Io
.Write (
2964 EFI_PCI_IO_PASS_THROUGH_BAR
,
2971 // Issue READ DMA command
2973 Status
= AtaCommandIssue (
2978 (UINT16
) NumberOfBlocks
,
2981 if (EFI_ERROR (Status
)) {
2982 gBS
->FreePool (PrdAddr
);
2983 return EFI_DEVICE_ERROR
;
2987 // Set START bit of BMIC register
2989 IdeDev
->PciIo
->Io
.Read (
2992 EFI_PCI_IO_PASS_THROUGH_BAR
,
2998 RegisterValue
|= BMIC_START
;
3000 IdeDev
->PciIo
->Io
.Write (
3003 EFI_PCI_IO_PASS_THROUGH_BAR
,
3010 // Check the INTERRUPT and ERROR bit of BMIS
3014 IdeDev
->PciIo
->Io
.Read (
3017 EFI_PCI_IO_PASS_THROUGH_BAR
,
3022 if (RegisterValue
& (BMIS_INTERRUPT
| BMIS_ERROR
)) {
3023 if (RegisterValue
& BMIS_ERROR
) {
3024 gBS
->FreePool (PrdAddr
);
3025 return EFI_DEVICE_ERROR
;
3033 gBS
->FreePool (PrdAddr
);
3036 // Set START bit of BMIC register
3038 IdeDev
->PciIo
->Io
.Read (
3041 EFI_PCI_IO_PASS_THROUGH_BAR
,
3047 RegisterValue
&= ~((UINT8
) BMIC_START
);
3049 IdeDev
->PciIo
->Io
.Write (
3052 EFI_PCI_IO_PASS_THROUGH_BAR
,
3058 if (RegisterValue
& BMIS_ERROR
) {
3059 return EFI_DEVICE_ERROR
;
3062 DataBuffer
= (UINT8
*) DataBuffer
+ NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
3063 StartLba
+= NumberOfBlocks
;
3071 IN IDE_BLK_IO_DEV
*IdeDev
,
3072 IN VOID
*DataBuffer
,
3073 IN EFI_LBA StartLba
,
3074 IN UINTN NumberOfBlocks
3083 This function is called by the AtaBlkIoWriteBlocks() to perform
3084 writing to media in block unit. The function has been enhanced to
3085 support >120GB access and transfer at most 65536 blocks per command
3089 IDE_BLK_IO_DEV IN *IdeDev
3090 pointer pointing to IDE_BLK_IO_DEV data structure, used
3091 to record all the information of the IDE device.
3094 A pointer to the source buffer for the data.
3097 The starting logical block address to write to
3098 on the device media.
3100 UINTN IN NumberOfBlocks
3101 The number of transfer data blocks.
3105 The device status of UDMA operation. If the operation is
3106 successful, return EFI_SUCCESS.
3109 // TODO: function comment is missing 'Routine Description:'
3110 // TODO: function comment is missing 'Arguments:'
3111 // TODO: IdeDev - add argument and description to function comment
3112 // TODO: DataBuffer - add argument and description to function comment
3113 // TODO: StartLba - add argument and description to function comment
3114 // TODO: NumberOfBlocks - add argument and description to function comment
3115 // TODO: EFI_UNSUPPORTED - add return value to function comment
3116 // TODO: EFI_DEVICE_ERROR - add return value to function comment
3117 // TODO: EFI_DEVICE_ERROR - add return value to function comment
3119 IDE_DMA_PRD
*PrdAddr
;
3120 IDE_DMA_PRD
*UsedPrdAddr
;
3121 IDE_DMA_PRD
*TempPrdAddr
;
3122 UINT8 RegisterValue
;
3124 UINT64 IoPortForBmic
;
3125 UINT64 IoPortForBmis
;
3126 UINT64 IoPortForBmid
;
3130 UINTN ByteAvailable
;
3132 UINTN RemainBlockNum
;
3133 UINT8 DeviceControl
;
3136 // Channel and device differential
3138 Device
= (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0);
3141 // Enable interrupt to support UDMA and Select device
3144 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
3146 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
3148 if (IdePrimary
== IdeDev
->Channel
) {
3149 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICP_OFFSET
;
3150 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
3151 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDP_OFFSET
;
3153 if (IdeSecondary
== IdeDev
->Channel
) {
3154 IoPortForBmic
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMICS_OFFSET
;
3155 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
3156 IoPortForBmid
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMIDS_OFFSET
;
3158 return EFI_UNSUPPORTED
;
3162 RemainBlockNum
= NumberOfBlocks
;
3163 while (RemainBlockNum
> 0) {
3165 if (RemainBlockNum
>= MAX_DMA_EXT_COMMAND_SECTORS
) {
3167 // SectorCount is used to record the number of sectors to be read
3168 // Max 65536 sectors can be transfered at a time.
3170 NumberOfBlocks
= MAX_DMA_EXT_COMMAND_SECTORS
;
3171 RemainBlockNum
-= MAX_DMA_EXT_COMMAND_SECTORS
;
3173 NumberOfBlocks
= (UINT16
) RemainBlockNum
;
3178 // Calculate the number of PRD table to make sure the memory region
3179 // not cross 64K boundary
3181 ByteCount
= NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
3182 PrdTableNum
= ((ByteCount
>> 16) + 1) + 1;
3187 PrdAddr
= (IDE_DMA_PRD
*) AllocateZeroPool ((2 * PrdTableNum
* sizeof (IDE_DMA_PRD
)));
3189 // To make sure PRD is allocated in one 64K page
3191 if (((UINTN
) PrdAddr
& 0x0FFFF) > (((UINTN
) PrdAddr
+ PrdTableNum
* sizeof (IDE_DMA_PRD
) - 1) & 0x0FFFF)) {
3192 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x10000) & 0xFFFF0000);
3194 if ((UINTN
) PrdAddr
& 0x03) {
3195 UsedPrdAddr
= (IDE_DMA_PRD
*) ((UINTN
) ((UINT8
*) PrdAddr
+ 0x04) & 0xFFFFFFFC);
3197 UsedPrdAddr
= PrdAddr
;
3202 // Build the PRD table
3204 PrdBuffer
= DataBuffer
;
3205 TempPrdAddr
= UsedPrdAddr
;
3208 ByteAvailable
= 0x10000 - ((UINTN
) PrdBuffer
& 0xFFFF);
3210 if (ByteCount
<= ByteAvailable
) {
3211 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
3212 TempPrdAddr
->ByteCount
= (UINT16
) ByteCount
;
3213 TempPrdAddr
->EndOfTable
= 0x8000;
3217 TempPrdAddr
->RegionBaseAddr
= (UINT32
) ((UINTN
) PrdBuffer
);
3218 TempPrdAddr
->ByteCount
= (UINT16
) ByteAvailable
;
3220 ByteCount
-= ByteAvailable
;
3221 PrdBuffer
+= ByteAvailable
;
3226 // Set the base address to BMID register
3228 IdeDev
->PciIo
->Io
.Write (
3230 EfiPciIoWidthUint32
,
3231 EFI_PCI_IO_PASS_THROUGH_BAR
,
3238 // Set BMIC register to identify the operation direction
3240 IdeDev
->PciIo
->Io
.Read (
3243 EFI_PCI_IO_PASS_THROUGH_BAR
,
3251 RegisterValue
&= ~((UINT8
) BMIC_nREAD
);
3253 IdeDev
->PciIo
->Io
.Write (
3256 EFI_PCI_IO_PASS_THROUGH_BAR
,
3263 // Read BMIS register and clear ERROR and INTR bit
3265 IdeDev
->PciIo
->Io
.Read (
3268 EFI_PCI_IO_PASS_THROUGH_BAR
,
3274 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
3276 IdeDev
->PciIo
->Io
.Write (
3279 EFI_PCI_IO_PASS_THROUGH_BAR
,
3286 // Issue WRITE DMA EXT command
3288 Status
= AtaCommandIssueExt (
3293 (UINT16
) NumberOfBlocks
,
3296 if (EFI_ERROR (Status
)) {
3297 gBS
->FreePool (PrdAddr
);
3298 return EFI_DEVICE_ERROR
;
3302 // Set START bit of BMIC register
3304 IdeDev
->PciIo
->Io
.Read (
3307 EFI_PCI_IO_PASS_THROUGH_BAR
,
3313 RegisterValue
|= BMIC_START
;
3315 IdeDev
->PciIo
->Io
.Write (
3318 EFI_PCI_IO_PASS_THROUGH_BAR
,
3325 // Check the INTERRUPT and ERROR bit of BMIS
3329 IdeDev
->PciIo
->Io
.Read (
3332 EFI_PCI_IO_PASS_THROUGH_BAR
,
3337 if (RegisterValue
& (BMIS_INTERRUPT
| BMIS_ERROR
)) {
3338 if (RegisterValue
& BMIS_ERROR
) {
3339 gBS
->FreePool (PrdAddr
);
3340 return EFI_DEVICE_ERROR
;
3348 gBS
->FreePool (PrdAddr
);
3351 // Set START bit of BMIC register
3353 IdeDev
->PciIo
->Io
.Read (
3356 EFI_PCI_IO_PASS_THROUGH_BAR
,
3362 RegisterValue
&= ~((UINT8
) BMIC_START
);
3364 IdeDev
->PciIo
->Io
.Write (
3367 EFI_PCI_IO_PASS_THROUGH_BAR
,
3373 DataBuffer
= (UINT8
*) DataBuffer
+ NumberOfBlocks
* IdeDev
->BlkIo
.Media
->BlockSize
;
3374 StartLba
+= NumberOfBlocks
;
3382 IN IDE_BLK_IO_DEV
*IdeDev
,
3383 IN VOID
*DataBuffer
,
3384 IN EFI_LBA StartLba
,
3385 IN UINTN NumberOfBlocks
3394 This function is called by the AtaBlkIoWriteBlocks() to perform
3395 writing to media in block unit. The function has been enhanced to
3396 support >120GB access and transfer at most 65536 blocks per command
3400 IDE_BLK_IO_DEV IN *IdeDev
3401 pointer pointing to IDE_BLK_IO_DEV data structure, used
3402 to record all the information of the IDE device.
3405 A pointer to the source buffer for the data.
3408 The starting logical block address to write to
3409 on the device media.
3411 UINTN IN NumberOfBlocks
3412 The number of transfer data blocks.
3416 The device status of UDMA operation. If the operation is
3417 successful, return EFI_SUCCESS.
3420 // TODO: function comment is missing 'Routine Description:'
3421 // TODO: function comment is missing 'Arguments:'
3422 // TODO: IdeDev - add argument and description to function comment
3423 // TODO: DataBuffer - add argument and description to function comment
3424 // TODO: StartLba - add argument and description to function comment
3425 // TODO: NumberOfBlocks - add argument and description to function comment
3426 // TODO: EFI_UNSUPPORTED - add return value to function comment
3427 // TODO: EFI_DEVICE_ERROR - add return value to function comment
3428 // TODO: EFI_DEVICE_ERROR - add return value to function comment
3430 IDE_DMA_PRD
*PrdAddr
;
3431 IDE_DMA_PRD
*UsedPrdAddr
;
3432 IDE_DMA_PRD
*TempPrdAddr
;
3433 UINT8 RegisterValue
;
3435 UINT64 IoPortForBmic
;
3436 UINT64 IoPortForBmis
;
3437 UINT64 IoPortForBmid
;
3441 UINTN ByteAvailable
;
3443 UINTN RemainBlockNum
;
3444 UINT8 DeviceControl
;