]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c
fix ia32 build error.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / Ata.c
CommitLineData
ead42efc 1/** @file\r
630d580d 2 This file contains all helper functions on the ATA command \r
3 \r
a7ddec11 4 Copyright (c) 2006 - 2010, Intel Corporation.<BR>\r
ead42efc 5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 @par Revision Reference:\r
14 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including\r
15 update - ATAIdentity() func\r
16 update - AtaBlockIoReadBlocks() func\r
17 update - AtaBlockIoWriteBlocks() func\r
18 add - AtaAtapi6Identify() func\r
19 add - AtaReadSectorsExt() func\r
20 add - AtaWriteSectorsExt() func\r
21 add - AtaPioDataInExt() func\r
22 add - AtaPioDataOutExt() func\r
23\r
24**/\r
25\r
03417d8d 26#include "IdeBus.h"\r
630d580d 27/**\r
28 This function is called by ATAIdentify() to identity whether this disk\r
29 supports ATA/ATAPI6 48bit addressing, ie support >120G capacity\r
30\r
31 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
32 all the information of the IDE device.\r
33\r
34 @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one and \r
35 48-bit addressing must be used\r
36 @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but the \r
37 capacity is below 120G, 48bit addressing is not needed\r
38 @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect\r
39 @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL.\r
40\r
41 @note This function must be called after DEVICE_IDENTITY command has been\r
42 successfully returned\r
43\r
44**/\r
45EFI_STATUS\r
46AtaAtapi6Identify (\r
47 IN IDE_BLK_IO_DEV *IdeDev\r
48 )\r
49{\r
50 UINT8 Index;\r
51 EFI_LBA TmpLba;\r
52 EFI_LBA Capacity;\r
53 EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;\r
54\r
55 if (IdeDev->IdData == NULL) {\r
56 return EFI_INVALID_PARAMETER;\r
57 }\r
58\r
59 Atapi6IdentifyStruct = IdeDev->IdData;\r
60\r
61 if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) {\r
62 //\r
63 // Per ATA-6 spec, word83: bit15 is zero and bit14 is one\r
64 //\r
65 return EFI_DEVICE_ERROR;\r
66 }\r
67\r
68 if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) {\r
69 //\r
70 // The device dosn't support 48 bit addressing\r
71 //\r
72 return EFI_UNSUPPORTED;\r
73 }\r
74\r
75 //\r
76 // 48 bit address feature set is supported, get maximum capacity\r
77 //\r
a7ddec11 78 Capacity = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[0];\r
630d580d 79 for (Index = 1; Index < 4; Index++) {\r
80 //\r
81 // Lower byte goes first: word[100] is the lowest word, word[103] is highest\r
82 //\r
a7ddec11 83 TmpLba = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[Index];\r
630d580d 84 Capacity |= LShiftU64 (TmpLba, 16 * Index);\r
85 }\r
86\r
87 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {\r
88 //\r
89 // Capacity exceeds 120GB. 48-bit addressing is really needed\r
90 //\r
91 IdeDev->Type = Ide48bitAddressingHardDisk;\r
92\r
93 //\r
94 // Fill block media information:Media->LogicalPartition ,\r
95 // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.\r
96 //\r
97 IdeDev->BlkIo.Media->IoAlign = 4;\r
98 IdeDev->BlkIo.Media->MediaId = 1;\r
99 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
100 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
101 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
102 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
103 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
104\r
105 return EFI_SUCCESS;\r
106 }\r
107\r
108 return EFI_UNSUPPORTED;\r
109}\r
110/**\r
111 Enable SMART of the disk if supported\r
112\r
113 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record \r
114 all the information of the IDE device.\r
115**/\r
116VOID\r
117AtaSMARTSupport (\r
118 IN IDE_BLK_IO_DEV *IdeDev\r
119 )\r
120{\r
121 EFI_STATUS Status;\r
122 BOOLEAN SMARTSupported;\r
123 UINT8 Device;\r
124 EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;\r
125 UINT8 DeviceSelect;\r
126 UINT8 LBAMid;\r
127 UINT8 LBAHigh;\r
128\r
129 //\r
130 // Detect if the device supports S.M.A.R.T.\r
131 //\r
132 if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {\r
133 //\r
134 // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)\r
135 //\r
136 return ;\r
137 } else {\r
138 if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
139 //\r
140 // S.M.A.R.T is not supported by the device\r
141 //\r
142 SMARTSupported = FALSE;\r
143 } else {\r
144 SMARTSupported = TRUE;\r
145 }\r
146 }\r
147\r
148 if (!SMARTSupported) {\r
149 //\r
150 // Report nonsupport status code\r
151 //\r
152 REPORT_STATUS_CODE (\r
153 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
154 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
155 );\r
156 } else {\r
157 //\r
158 // Enable this feature\r
159 //\r
160 REPORT_STATUS_CODE (\r
161 EFI_PROGRESS_CODE,\r
162 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
163 );\r
164\r
165 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
166 Status = AtaNonDataCommandIn (\r
167 IdeDev,\r
168 ATA_CMD_SMART,\r
169 Device,\r
170 ATA_SMART_ENABLE_OPERATION,\r
171 0,\r
172 0,\r
173 ATA_CONSTANT_4F,\r
174 ATA_CONSTANT_C2\r
175 );\r
176 //\r
177 // Detect if this feature is enabled\r
178 //\r
179 TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
180 if (TmpAtaIdentifyPointer == NULL) {\r
181 return;\r
182 }\r
183\r
184 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
185 Status = AtaPioDataIn (\r
186 IdeDev,\r
187 (VOID *) TmpAtaIdentifyPointer,\r
188 sizeof (EFI_IDENTIFY_DATA),\r
189 ATA_CMD_IDENTIFY_DRIVE,\r
190 DeviceSelect,\r
191 0,\r
192 0,\r
193 0,\r
194 0\r
195 );\r
196 if (EFI_ERROR (Status)) {\r
197 gBS->FreePool (TmpAtaIdentifyPointer);\r
198 return ;\r
199 }\r
200\r
201 //\r
202 // Check if the feature is enabled\r
203 //\r
204 if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {\r
205 //\r
206 // Read status data\r
207 //\r
208 AtaNonDataCommandIn (\r
209 IdeDev,\r
210 ATA_CMD_SMART,\r
211 Device,\r
212 ATA_SMART_RETURN_STATUS,\r
213 0,\r
214 0,\r
215 ATA_CONSTANT_4F,\r
216 ATA_CONSTANT_C2\r
217 );\r
218 LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);\r
219 LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);\r
220\r
221 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
222 //\r
223 // The threshold exceeded condition is not detected by the device\r
224 //\r
225 REPORT_STATUS_CODE (\r
226 EFI_PROGRESS_CODE,\r
227 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
228 );\r
ead42efc 229\r
630d580d 230 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
231 //\r
232 // The threshold exceeded condition is detected by the device\r
233 //\r
234 REPORT_STATUS_CODE (\r
235 EFI_PROGRESS_CODE,\r
236 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
237 );\r
238 }\r
239\r
240 } else {\r
241 //\r
242 // Report disabled status code\r
243 //\r
244 REPORT_STATUS_CODE (\r
245 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
246 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
247 );\r
248 }\r
249\r
250 gBS->FreePool (TmpAtaIdentifyPointer);\r
251 }\r
252\r
253 return ;\r
254}\r
ead42efc 255/**\r
256 Sends out an ATA Identify Command to the specified device.\r
257\r
258 This function is called by DiscoverIdeDevice() during its device\r
259 identification. It sends out the ATA Identify Command to the\r
260 specified device. Only ATA device responses to this command. If\r
261 the command succeeds, it returns the Identify data structure which\r
262 contains information about the device. This function extracts the\r
263 information it needs to fill the IDE_BLK_IO_DEV data structure,\r
264 including device type, media block size, media capacity, and etc.\r
265\r
630d580d 266 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record \r
267 all the information of the IDE device.\r
ead42efc 268\r
630d580d 269 @retval EFI_SUCCESS Identify ATA device successfully.\r
270 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.\r
271 @note parameter IdeDev will be updated in this function.\r
ead42efc 272\r
273**/\r
274EFI_STATUS\r
275ATAIdentify (\r
276 IN IDE_BLK_IO_DEV *IdeDev\r
277 )\r
278{\r
279 EFI_STATUS Status;\r
280 EFI_IDENTIFY_DATA *AtaIdentifyPointer;\r
281 UINT32 Capacity;\r
282 UINT8 DeviceSelect;\r
6979fd93 283 UINTN Retry;\r
ead42efc 284\r
285 //\r
286 // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of\r
287 // the ATA Identify command\r
288 //\r
289 AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
261136bc 290 if (AtaIdentifyPointer == NULL) {\r
291 return EFI_OUT_OF_RESOURCES;\r
292 }\r
ead42efc 293\r
294 //\r
295 // use ATA PIO Data In protocol to send ATA Identify command\r
296 // and receive data from device\r
297 //\r
298 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
ead42efc 299\r
6979fd93 300 \r
301 Retry = 3;\r
302 while (Retry > 0) { \r
303 Status = AtaPioDataIn (\r
304 IdeDev,\r
305 (VOID *) AtaIdentifyPointer,\r
306 sizeof (EFI_IDENTIFY_DATA),\r
307 ATA_CMD_IDENTIFY_DRIVE,\r
308 DeviceSelect,\r
309 0,\r
310 0,\r
311 0,\r
312 0\r
313 );\r
ead42efc 314 //\r
6979fd93 315 // If ATA Identify command succeeds, then according to the received\r
316 // IDENTIFY data,\r
317 // identify the device type ( ATA or not ).\r
318 // If ATA device, fill the information in IdeDev.\r
319 // If not ATA device, return IDE_DEVICE_ERROR\r
ead42efc 320 //\r
6979fd93 321 if (!EFI_ERROR (Status)) {\r
322\r
e72ca438 323 IdeDev->IdData = AtaIdentifyPointer;\r
ead42efc 324\r
ead42efc 325 //\r
6979fd93 326 // Print ATA Module Name\r
ead42efc 327 //\r
6979fd93 328 PrintAtaModuleName (IdeDev);\r
ead42efc 329\r
330 //\r
6979fd93 331 // bit 15 of pAtaIdentify->config is used to identify whether device is\r
332 // ATA device or ATAPI device.\r
333 // if 0, means ATA device; if 1, means ATAPI device.\r
ead42efc 334 //\r
6979fd93 335 if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {\r
ead42efc 336 //\r
6979fd93 337 // Detect if support S.M.A.R.T. If yes, enable it as default\r
ead42efc 338 //\r
6979fd93 339 AtaSMARTSupport (IdeDev);\r
ead42efc 340\r
6979fd93 341 //\r
342 // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)\r
343 //\r
344 Status = AtaAtapi6Identify (IdeDev);\r
345 if (!EFI_ERROR (Status)) {\r
346 //\r
347 // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()\r
348 //\r
349 return EFI_SUCCESS;\r
350 } else if (Status == EFI_DEVICE_ERROR) {\r
351 //\r
352 // Some disk with big capacity (>200GB) is slow when being identified\r
353 // and will return all zero for word83.\r
354 // We try twice at first. If it fails, we do a SoftRest and try again.\r
355 //\r
356 Retry--;\r
357 if (Retry == 1) {\r
358 //\r
359 // Do a SoftRest before the third attempt.\r
360 //\r
361 AtaSoftReset (IdeDev);\r
362 }\r
363 continue;\r
364 }\r
365 //\r
366 // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
367 //\r
368 IdeDev->Type = IdeHardDisk;\r
ead42efc 369\r
6979fd93 370 //\r
371 // Block Media Information:\r
372 // Media->LogicalPartition , Media->WriteCaching will be filled\r
373 // in the DiscoverIdeDevcie() function.\r
374 //\r
375 IdeDev->BlkIo.Media->IoAlign = 4;\r
376 IdeDev->BlkIo.Media->MediaId = 1;\r
377 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
378 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
379 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
380 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
381\r
382 //\r
383 // Calculate device capacity\r
384 //\r
385 Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |\r
ead42efc 386 AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;\r
6979fd93 387 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
ead42efc 388\r
6979fd93 389 return EFI_SUCCESS;\r
390 }\r
ead42efc 391\r
392 }\r
6979fd93 393 break;\r
ead42efc 394 }\r
395\r
396 gBS->FreePool (AtaIdentifyPointer);\r
397 //\r
398 // Make sure the pIdData will not be freed again.\r
399 //\r
e72ca438 400 IdeDev->IdData = NULL;\r
ead42efc 401\r
402 return EFI_DEVICE_ERROR;\r
403}\r
404\r
ead42efc 405/**\r
630d580d 406 This function is a helper function used to change the char order in a string. It\r
407 is designed specially for the PrintAtaModuleName() function. After the IDE device \r
408 is detected, the IDE driver gets the device module name by sending ATA command \r
409 called ATA Identify Command or ATAPI Identify Command to the specified IDE device.\r
410 The module name returned is a string of ASCII characters: the first character is bit8--bit15\r
411 of the first word, the second character is BIT0--bit7 of the first word and so on. Thus\r
412 the string can not be print directly before it is preprocessed by this func to change \r
413 the order of characters in each word in the string.\r
414\r
415 @param Destination Indicates the destination string.\r
416 @param Source Indicates the source string.\r
417 @param Size the length of the string\r
418**/\r
419VOID\r
420SwapStringChars (\r
421 IN CHAR8 *Destination,\r
422 IN CHAR8 *Source,\r
423 IN UINT32 Size\r
424 )\r
425{\r
426 UINT32 Index;\r
427 CHAR8 Temp;\r
6979fd93 428\r
630d580d 429 for (Index = 0; Index < Size; Index += 2) {\r
ead42efc 430\r
630d580d 431 Temp = Source[Index + 1];\r
432 Destination[Index + 1] = Source[Index];\r
433 Destination[Index] = Temp;\r
434 }\r
435}\r
436/**\r
437 This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name.\r
ead42efc 438\r
630d580d 439 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
440 all the information of the IDE device.\r
ead42efc 441**/\r
630d580d 442VOID\r
443PrintAtaModuleName (\r
ead42efc 444 IN IDE_BLK_IO_DEV *IdeDev\r
445 )\r
446{\r
e72ca438 447 if (IdeDev->IdData == NULL) {\r
630d580d 448 return ;\r
ead42efc 449 }\r
450\r
630d580d 451 SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40);\r
452 IdeDev->ModelName[40] = 0x00;\r
453}\r
ead42efc 454\r
630d580d 455/**\r
456 This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
ead42efc 457\r
630d580d 458 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record \r
459 all the information of the IDE device.\r
460 @param Buffer buffer contained data transferred from device to host.\r
461 @param ByteCount data size in byte unit of the buffer.\r
462 @param AtaCommand value of the Command Register\r
463 @param Head value of the Head/Device Register\r
464 @param SectorCount value of the Sector Count Register\r
465 @param SectorNumber value of the Sector Number Register\r
466 @param CylinderLsb value of the low byte of the Cylinder Register\r
467 @param CylinderMsb value of the high byte of the Cylinder Register\r
468 \r
469 @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
ead42efc 470 @retval EFI_DEVICE_ERROR command sent failed.\r
471\r
472**/\r
473EFI_STATUS\r
474AtaPioDataIn (\r
475 IN IDE_BLK_IO_DEV *IdeDev,\r
476 IN VOID *Buffer,\r
477 IN UINT32 ByteCount,\r
478 IN UINT8 AtaCommand,\r
479 IN UINT8 Head,\r
480 IN UINT8 SectorCount,\r
481 IN UINT8 SectorNumber,\r
482 IN UINT8 CylinderLsb,\r
483 IN UINT8 CylinderMsb\r
484 )\r
485{\r
486 UINTN WordCount;\r
487 UINTN Increment;\r
488 UINT16 *Buffer16;\r
489 EFI_STATUS Status;\r
490\r
491 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
492 if (EFI_ERROR (Status)) {\r
493 return EFI_DEVICE_ERROR;\r
494 }\r
495\r
496 //\r
497 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
498 // bit6 set means LBA mode\r
499 //\r
500 IDEWritePortB (\r
501 IdeDev->PciIo,\r
502 IdeDev->IoPort->Head,\r
503 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
504 );\r
505\r
506 //\r
507 // All ATAPI device's ATA commands can be issued regardless of the\r
508 // state of the DRDY\r
509 //\r
510 if (IdeDev->Type == IdeHardDisk) {\r
511\r
512 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
513 if (EFI_ERROR (Status)) {\r
514 return EFI_DEVICE_ERROR;\r
515 }\r
516 }\r
517 //\r
518 // set all the command parameters\r
519 // Before write to all the following registers, BSY and DRQ must be 0.\r
520 //\r
521 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
522 if (EFI_ERROR (Status)) {\r
523 return EFI_DEVICE_ERROR;\r
524 }\r
525\r
1e23bd8d 526 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
ead42efc 527 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
528 }\r
529\r
530 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
531 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
532 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
533 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
534\r
535 //\r
536 // send command via Command Register\r
537 //\r
538 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
539\r
540 Buffer16 = (UINT16 *) Buffer;\r
541\r
542 //\r
543 // According to PIO data in protocol, host can perform a series of reads to\r
544 // the data register after each time device set DRQ ready;\r
545 // The data size of "a series of read" is command specific.\r
546 // For most ATA command, data size received from device will not exceed\r
547 // 1 sector, hence the data size for "a series of read" can be the whole data\r
548 // size of one command request.\r
549 // For ATA command such as Read Sector command, the data size of one ATA\r
550 // command request is often larger than 1 sector, according to the\r
551 // Read Sector command, the data size of "a series of read" is exactly 1\r
552 // sector.\r
553 // Here for simplification reason, we specify the data size for\r
554 // "a series of read" to 1 sector (256 words) if data size of one ATA command\r
555 // request is larger than 256 words.\r
556 //\r
557 Increment = 256;\r
558\r
559 //\r
560 // used to record bytes of currently transfered data\r
561 //\r
562 WordCount = 0;\r
563\r
564 while (WordCount < ByteCount / 2) {\r
565 //\r
566 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
567 //\r
568 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
569 if (EFI_ERROR (Status)) {\r
570 return EFI_DEVICE_ERROR;\r
571 }\r
572\r
573 Status = CheckErrorStatus (IdeDev);\r
574 if (EFI_ERROR (Status)) {\r
575 return EFI_DEVICE_ERROR;\r
576 }\r
577\r
578 //\r
579 // Get the byte count for one series of read\r
580 //\r
581 if ((WordCount + Increment) > ByteCount / 2) {\r
582 Increment = ByteCount / 2 - WordCount;\r
583 }\r
584\r
585 IDEReadPortWMultiple (\r
586 IdeDev->PciIo,\r
587 IdeDev->IoPort->Data,\r
588 Increment,\r
589 Buffer16\r
590 );\r
591\r
592 WordCount += Increment;\r
593 Buffer16 += Increment;\r
594\r
595 }\r
596\r
597 DRQClear (IdeDev, ATATIMEOUT);\r
598\r
599 return CheckErrorStatus (IdeDev);\r
600}\r
601\r
602/**\r
603 This function is used to send out ATA commands conforms to the\r
604 PIO Data Out Protocol.\r
605\r
630d580d 606 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
607 to record all the information of the IDE device.\r
ead42efc 608 @param *Buffer buffer contained data transferred from host to device.\r
609 @param ByteCount data size in byte unit of the buffer.\r
610 @param AtaCommand value of the Command Register\r
611 @param Head value of the Head/Device Register\r
612 @param SectorCount value of the Sector Count Register\r
613 @param SectorNumber value of the Sector Number Register\r
614 @param CylinderLsb value of the low byte of the Cylinder Register\r
615 @param CylinderMsb value of the high byte of the Cylinder Register\r
616\r
630d580d 617 @retval EFI_SUCCESS send out the ATA command and device received required\r
618 data successfully.\r
ead42efc 619 @retval EFI_DEVICE_ERROR command sent failed.\r
620\r
621**/\r
622EFI_STATUS\r
623AtaPioDataOut (\r
624 IN IDE_BLK_IO_DEV *IdeDev,\r
625 IN VOID *Buffer,\r
626 IN UINT32 ByteCount,\r
627 IN UINT8 AtaCommand,\r
628 IN UINT8 Head,\r
629 IN UINT8 SectorCount,\r
630 IN UINT8 SectorNumber,\r
631 IN UINT8 CylinderLsb,\r
632 IN UINT8 CylinderMsb\r
633 )\r
634{\r
635 UINTN WordCount;\r
636 UINTN Increment;\r
637 UINT16 *Buffer16;\r
638 EFI_STATUS Status;\r
639\r
640 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
641 if (EFI_ERROR (Status)) {\r
642 return EFI_DEVICE_ERROR;\r
643 }\r
644\r
645 //\r
646 // select device via Head/Device register.\r
647 // Before write Head/Device register, BSY and DRQ must be 0.\r
648 //\r
649 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
650 if (EFI_ERROR (Status)) {\r
651 return EFI_DEVICE_ERROR;\r
652 }\r
653\r
654 //\r
655 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
656 // bit6 set means LBA mode\r
657 //\r
658 IDEWritePortB (\r
659 IdeDev->PciIo,\r
660 IdeDev->IoPort->Head,\r
661 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
662 );\r
663\r
664 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
665 if (EFI_ERROR (Status)) {\r
666 return EFI_DEVICE_ERROR;\r
667 }\r
668\r
669 //\r
670 // set all the command parameters\r
671 // Before write to all the following registers, BSY and DRQ must be 0.\r
672 //\r
673 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
674 if (EFI_ERROR (Status)) {\r
675 return EFI_DEVICE_ERROR;\r
676 }\r
677\r
678 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
679 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
680 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
681 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
682\r
683 //\r
684 // send command via Command Register\r
685 //\r
686 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
687\r
688 Buffer16 = (UINT16 *) Buffer;\r
689\r
690 //\r
691 // According to PIO data out protocol, host can perform a series of\r
692 // writes to the data register after each time device set DRQ ready;\r
693 // The data size of "a series of read" is command specific.\r
694 // For most ATA command, data size written to device will not exceed 1 sector,\r
695 // hence the data size for "a series of write" can be the data size of one\r
696 // command request.\r
697 // For ATA command such as Write Sector command, the data size of one\r
698 // ATA command request is often larger than 1 sector, according to the\r
699 // Write Sector command, the data size of "a series of read" is exactly\r
700 // 1 sector.\r
701 // Here for simplification reason, we specify the data size for\r
702 // "a series of write" to 1 sector (256 words) if data size of one ATA command\r
703 // request is larger than 256 words.\r
704 //\r
705 Increment = 256;\r
706 WordCount = 0;\r
707\r
708 while (WordCount < ByteCount / 2) {\r
709\r
710 //\r
711 // DRQReady2-- read Alternate Status Register to determine the DRQ bit\r
712 // data transfer can be performed only when DRQ is ready.\r
713 //\r
714 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
715 if (EFI_ERROR (Status)) {\r
716 return EFI_DEVICE_ERROR;\r
717 }\r
718\r
719 Status = CheckErrorStatus (IdeDev);\r
720 if (EFI_ERROR (Status)) {\r
721 return EFI_DEVICE_ERROR;\r
722 }\r
723\r
724 //\r
725 // Check the remaining byte count is less than 512 bytes\r
726 //\r
727 if ((WordCount + Increment) > ByteCount / 2) {\r
728 Increment = ByteCount / 2 - WordCount;\r
729 }\r
730 //\r
731 // perform a series of write without check DRQ ready\r
732 //\r
733\r
734 IDEWritePortWMultiple (\r
735 IdeDev->PciIo,\r
736 IdeDev->IoPort->Data,\r
737 Increment,\r
738 Buffer16\r
739 );\r
740 WordCount += Increment;\r
741 Buffer16 += Increment;\r
742\r
743 }\r
744\r
745 DRQClear (IdeDev, ATATIMEOUT);\r
746\r
747 return CheckErrorStatus (IdeDev);\r
748}\r
749\r
750/**\r
751 This function is used to analyze the Status Register and print out\r
752 some debug information and if there is ERR bit set in the Status\r
753 Register, the Error Register's value is also be parsed and print out.\r
754\r
630d580d 755 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to \r
756 record all the information of the IDE device.\r
ead42efc 757\r
758 @retval EFI_SUCCESS No err information in the Status Register.\r
759 @retval EFI_DEVICE_ERROR Any err information in the Status Register.\r
760\r
761**/\r
762EFI_STATUS\r
763CheckErrorStatus (\r
764 IN IDE_BLK_IO_DEV *IdeDev\r
765 )\r
766{\r
767 UINT8 StatusRegister;\r
768 UINT8 ErrorRegister;\r
769\r
770 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
771\r
772 DEBUG_CODE_BEGIN ();\r
773\r
630d580d 774 if ((StatusRegister & ATA_STSREG_DWF) != 0) {\r
775 DEBUG (\r
776 (EFI_D_BLKIO,\r
777 "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
778 StatusRegister)\r
779 );\r
780 }\r
ead42efc 781\r
630d580d 782 if ((StatusRegister & ATA_STSREG_CORR) != 0) {\r
783 DEBUG (\r
784 (EFI_D_BLKIO,\r
785 "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
786 StatusRegister)\r
787 );\r
788 }\r
ead42efc 789\r
630d580d 790 if ((StatusRegister & ATA_STSREG_ERR) != 0) {\r
791 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
ead42efc 792\r
630d580d 793 if ((ErrorRegister & ATA_ERRREG_BBK) != 0) {\r
ead42efc 794 DEBUG (\r
795 (EFI_D_BLKIO,\r
796 "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
797 ErrorRegister)\r
798 );\r
799 }\r
800\r
97404058 801 if ((ErrorRegister & ATA_ERRREG_UNC) != 0) {\r
ead42efc 802 DEBUG (\r
803 (EFI_D_BLKIO,\r
804 "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
805 ErrorRegister)\r
806 );\r
807 }\r
808\r
97404058 809 if ((ErrorRegister & ATA_ERRREG_MC) != 0) {\r
ead42efc 810 DEBUG (\r
811 (EFI_D_BLKIO,\r
812 "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
813 ErrorRegister)\r
814 );\r
815 }\r
816\r
97404058 817 if ((ErrorRegister & ATA_ERRREG_ABRT) != 0) {\r
ead42efc 818 DEBUG (\r
819 (EFI_D_BLKIO,\r
820 "CheckErrorStatus()-- %02x : Error : Abort\n",\r
821 ErrorRegister)\r
822 );\r
823 }\r
824\r
97404058 825 if ((ErrorRegister & ATA_ERRREG_TK0NF) != 0) {\r
ead42efc 826 DEBUG (\r
827 (EFI_D_BLKIO,\r
828 "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
829 ErrorRegister)\r
830 );\r
831 }\r
832\r
97404058 833 if ((ErrorRegister & ATA_ERRREG_AMNF) != 0) {\r
ead42efc 834 DEBUG (\r
835 (EFI_D_BLKIO,\r
836 "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
837 ErrorRegister)\r
838 );\r
839 }\r
840 }\r
841\r
842 DEBUG_CODE_END ();\r
843\r
1e23bd8d 844 if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {\r
ead42efc 845 return EFI_SUCCESS;\r
846 }\r
847\r
848 return EFI_DEVICE_ERROR;\r
849\r
850}\r
851\r
852/**\r
630d580d 853 This function is called by the AtaBlkIoReadBlocks() to perform reading from \r
854 media in block unit.\r
855\r
856 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record \r
857 all the information of the IDE device.\r
858 @param DataBuffer A pointer to the destination buffer for the data.\r
859 @param Lba The starting logical block address to read from on the device media.\r
860 @param NumberOfBlocks The number of transfer data blocks.\r
861 \r
862 @return status is fully dependent on the return status of AtaPioDataIn() function.\r
ead42efc 863\r
864**/\r
865EFI_STATUS\r
866AtaReadSectors (\r
867 IN IDE_BLK_IO_DEV *IdeDev,\r
868 IN VOID *DataBuffer,\r
869 IN EFI_LBA Lba,\r
870 IN UINTN NumberOfBlocks\r
871 )\r
872{\r
873 EFI_STATUS Status;\r
874 UINTN BlocksRemaining;\r
875 UINT32 Lba32;\r
876 UINT8 Lba0;\r
877 UINT8 Lba1;\r
878 UINT8 Lba2;\r
879 UINT8 Lba3;\r
880 UINT8 AtaCommand;\r
881 UINT8 SectorCount8;\r
882 UINT16 SectorCount;\r
883 UINTN ByteCount;\r
884 VOID *Buffer;\r
885\r
886 Buffer = DataBuffer;\r
887\r
888 //\r
889 // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol\r
890 //\r
1e23bd8d 891 AtaCommand = ATA_CMD_READ_SECTORS;\r
ead42efc 892\r
893\r
894 BlocksRemaining = NumberOfBlocks;\r
895\r
896 Lba32 = (UINT32) Lba;\r
897\r
898 Status = EFI_SUCCESS;\r
899\r
900 while (BlocksRemaining > 0) {\r
901\r
902 //\r
903 // in ATA-3 spec, LBA is in 28 bit width\r
904 //\r
905 Lba0 = (UINT8) Lba32;\r
906 Lba1 = (UINT8) (Lba32 >> 8);\r
907 Lba2 = (UINT8) (Lba32 >> 16);\r
908 //\r
909 // low 4 bit of Lba3 stands for LBA bit24~bit27.\r
910 //\r
911 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
912\r
913 if (BlocksRemaining >= 0x100) {\r
914\r
915 //\r
916 // SectorCount8 is sent to Sector Count register, 0x00 means 256\r
917 // sectors to be read\r
918 //\r
919 SectorCount8 = 0x00;\r
920 //\r
921 // SectorCount is used to record the number of sectors to be read\r
922 //\r
923 SectorCount = 256;\r
924 } else {\r
925\r
926 SectorCount8 = (UINT8) BlocksRemaining;\r
927 SectorCount = (UINT16) BlocksRemaining;\r
928 }\r
929\r
930 //\r
931 // ByteCount is the number of bytes that will be read\r
932 //\r
933 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
934\r
935 //\r
936 // call AtaPioDataIn() to send Read Sector Command and receive data read\r
937 //\r
938 Status = AtaPioDataIn (\r
939 IdeDev,\r
940 Buffer,\r
941 (UINT32) ByteCount,\r
942 AtaCommand,\r
943 Lba3,\r
944 SectorCount8,\r
945 Lba0,\r
946 Lba1,\r
947 Lba2\r
948 );\r
949 if (EFI_ERROR (Status)) {\r
950 return Status;\r
951 }\r
952\r
953 Lba32 += SectorCount;\r
954 Buffer = ((UINT8 *) Buffer + ByteCount);\r
955 BlocksRemaining -= SectorCount;\r
956 }\r
957\r
958 return Status;\r
959}\r
960\r
961/**\r
630d580d 962 This function is called by the AtaBlkIoWriteBlocks() to perform writing onto \r
963 media in block unit.\r
964\r
965 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record\r
966 all the information of the IDE device.\r
967 @param BufferData A pointer to the source buffer for the data.\r
968 @param Lba The starting logical block address to write onto the device media.\r
969 @param NumberOfBlocks The number of transfer data blocks.\r
970 \r
971 @return status is fully dependent on the return status of AtaPioDataIn() function.\r
ead42efc 972\r
973**/\r
974EFI_STATUS\r
975AtaWriteSectors (\r
976 IN IDE_BLK_IO_DEV *IdeDev,\r
977 IN VOID *BufferData,\r
978 IN EFI_LBA Lba,\r
979 IN UINTN NumberOfBlocks\r
980 )\r
981{\r
982 EFI_STATUS Status;\r
983 UINTN BlocksRemaining;\r
984 UINT32 Lba32;\r
985 UINT8 Lba0;\r
986 UINT8 Lba1;\r
987 UINT8 Lba2;\r
988 UINT8 Lba3;\r
989 UINT8 AtaCommand;\r
990 UINT8 SectorCount8;\r
991 UINT16 SectorCount;\r
992 UINTN ByteCount;\r
993 VOID *Buffer;\r
994\r
995 Buffer = BufferData;\r
996\r
997 //\r
998 // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol\r
999 //\r
1e23bd8d 1000 AtaCommand = ATA_CMD_WRITE_SECTORS;\r
ead42efc 1001\r
1002 BlocksRemaining = NumberOfBlocks;\r
1003\r
1004 Lba32 = (UINT32) Lba;\r
1005\r
1006 Status = EFI_SUCCESS;\r
1007\r
1008 while (BlocksRemaining > 0) {\r
1009\r
1010 Lba0 = (UINT8) Lba32;\r
1011 Lba1 = (UINT8) (Lba32 >> 8);\r
1012 Lba2 = (UINT8) (Lba32 >> 16);\r
1013 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
1014\r
1015 if (BlocksRemaining >= 0x100) {\r
1016\r
1017 //\r
1018 // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors\r
1019 // to be written\r
1020 //\r
1021 SectorCount8 = 0x00;\r
1022 //\r
1023 // SectorCount is used to record the number of sectors to be written\r
1024 //\r
1025 SectorCount = 256;\r
1026 } else {\r
1027\r
1028 SectorCount8 = (UINT8) BlocksRemaining;\r
1029 SectorCount = (UINT16) BlocksRemaining;\r
1030 }\r
1031\r
1032 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1033\r
1034 Status = AtaPioDataOut (\r
1035 IdeDev,\r
1036 Buffer,\r
1037 (UINT32) ByteCount,\r
1038 AtaCommand,\r
1039 Lba3,\r
1040 SectorCount8,\r
1041 Lba0,\r
1042 Lba1,\r
1043 Lba2\r
1044 );\r
1045 if (EFI_ERROR (Status)) {\r
1046 return Status;\r
1047 }\r
1048\r
1049 Lba32 += SectorCount;\r
1050 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1051 BlocksRemaining -= SectorCount;\r
1052 }\r
1053\r
1054 return Status;\r
1055}\r
ead42efc 1056/**\r
630d580d 1057 This function is used to implement the Soft Reset on the specified device. But,\r
1058 the ATA Soft Reset mechanism is so strong a reset method that it will force \r
1059 resetting on both devices connected to the same cable.\r
ead42efc 1060\r
1061 It is called by IdeBlkIoReset(), a interface function of Block\r
1062 I/O protocol.\r
1063\r
1064 This function can also be used by the ATAPI device to perform reset when\r
1065 ATAPI Reset command is failed.\r
1066\r
630d580d 1067 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1068 all the information of the IDE device.\r
ead42efc 1069 @retval EFI_SUCCESS Soft reset completes successfully.\r
1070 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
1071\r
630d580d 1072 @note The registers initial values after ATA soft reset are different\r
1073 to the ATA device and ATAPI device.\r
ead42efc 1074**/\r
1075EFI_STATUS\r
1076AtaSoftReset (\r
1077 IN IDE_BLK_IO_DEV *IdeDev\r
1078 )\r
1079{\r
1080\r
1081 UINT8 DeviceControl;\r
1082\r
1083 DeviceControl = 0;\r
1084 //\r
1085 // set SRST bit to initiate soft reset\r
1086 //\r
1e23bd8d 1087 DeviceControl |= ATA_CTLREG_SRST;\r
ead42efc 1088\r
1089 //\r
1090 // disable Interrupt\r
1091 //\r
1e23bd8d 1092 DeviceControl |= BIT1;\r
ead42efc 1093\r
1094 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1095\r
1096 //\r
1097 // SRST should assert for at least 5 us, we use 10 us for\r
1098 // better compatibility\r
1099 //\r
1100 gBS->Stall (10);\r
1101\r
1102 //\r
1103 // Enable interrupt to support UDMA, and clear SRST bit\r
1104 //\r
1105 DeviceControl = 0;\r
1106 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1107\r
1108 //\r
1109 // Wait for at least 2 ms to check BSY status, we use 10 ms\r
1110 // for better compatibility\r
1111 //\r
1112 gBS->Stall(10000);\r
1113 //\r
1114 // slave device needs at most 31s to clear BSY\r
1115 //\r
1116 if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {\r
1117 return EFI_DEVICE_ERROR;\r
1118 }\r
1119\r
1120 return EFI_SUCCESS;\r
1121}\r
ead42efc 1122/**\r
630d580d 1123 This function is used to send out ATA commands conforms to the PIO Data In \r
1124 Protocol, supporting ATA/ATAPI-6 standard\r
ead42efc 1125\r
630d580d 1126 Comparing with ATA-3 data in protocol, we have two differents here:\r
1127 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1128 wait will frequently fail... cause writing function return error)\r
ead42efc 1129\r
630d580d 1130 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
1131 slow down writing performance by 100 times!)\r
ead42efc 1132\r
630d580d 1133 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1134 to record all the information of the IDE device.\r
1135 @param Buffer buffer contained data transferred from device to host.\r
1136 @param ByteCount data size in byte unit of the buffer.\r
1137 @param AtaCommand value of the Command Register\r
1138 @param StartLba the start LBA of this transaction\r
1139 @param SectorCount the count of sectors to be transfered\r
ead42efc 1140\r
630d580d 1141 @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
1142 @retval EFI_DEVICE_ERROR command sent failed.\r
ead42efc 1143\r
1144**/\r
1145EFI_STATUS\r
630d580d 1146AtaPioDataInExt (\r
1147 IN IDE_BLK_IO_DEV *IdeDev,\r
1148 IN OUT VOID *Buffer,\r
1149 IN UINT32 ByteCount,\r
1150 IN UINT8 AtaCommand,\r
1151 IN EFI_LBA StartLba,\r
1152 IN UINT16 SectorCount\r
ead42efc 1153 )\r
1154{\r
630d580d 1155 UINT8 DevSel;\r
1156 UINT8 SectorCount8;\r
1157 UINT8 LbaLow;\r
1158 UINT8 LbaMid;\r
1159 UINT8 LbaHigh;\r
1160 UINTN WordCount;\r
1161 UINTN Increment;\r
1162 UINT16 *Buffer16;\r
1163 EFI_STATUS Status;\r
ead42efc 1164\r
630d580d 1165 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1166 if (EFI_ERROR (Status)) {\r
1167 return EFI_DEVICE_ERROR;\r
ead42efc 1168 }\r
1169\r
630d580d 1170 //\r
1171 // Select device, set bit6 as 1 to indicate LBA mode is used\r
1172 //\r
1173 DevSel = (UINT8) (IdeDev->Device << 4);\r
1174 DevSel |= 0x40;\r
1175 IDEWritePortB (\r
1176 IdeDev->PciIo,\r
1177 IdeDev->IoPort->Head,\r
1178 DevSel\r
1179 );\r
1180\r
1181 //\r
1182 // Wait for DRDY singnal asserting. ATAPI device needn't wait\r
1183 //\r
1184 if ( (IdeDev->Type == IdeHardDisk) ||\r
1185 (IdeDev->Type == Ide48bitAddressingHardDisk)) {\r
1186\r
1187 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1188 if (EFI_ERROR (Status)) {\r
1189 return EFI_DEVICE_ERROR;\r
1190 }\r
ead42efc 1191 }\r
1192\r
630d580d 1193 //\r
1194 // Fill feature register if needed\r
1195 //\r
1196 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
1197 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1198 }\r
ead42efc 1199\r
1200 //\r
630d580d 1201 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
ead42efc 1202 //\r
630d580d 1203 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1204 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
ead42efc 1205\r
630d580d 1206 SectorCount8 = (UINT8) SectorCount;\r
1207 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
ead42efc 1208\r
630d580d 1209 //\r
1210 // Fill the start LBA registers, which are also two-byte FIFO\r
1211 //\r
1212 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1213 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1214 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1215 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1216 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1217 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
ead42efc 1218\r
630d580d 1219 LbaLow = (UINT8) StartLba;\r
1220 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1221 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1222 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1223 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1224 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
ead42efc 1225\r
630d580d 1226 //\r
1227 // Send command via Command Register, invoking the processing of this command\r
1228 //\r
1229 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
ead42efc 1230\r
630d580d 1231 Buffer16 = (UINT16 *) Buffer;\r
ead42efc 1232\r
630d580d 1233 //\r
1234 // According to PIO data in protocol, host can perform a series of reads to\r
1235 // the data register after each time device set DRQ ready;\r
1236 //\r
ead42efc 1237\r
630d580d 1238 //\r
1239 // 256 words\r
1240 //\r
1241 Increment = 256;\r
ead42efc 1242\r
630d580d 1243 //\r
1244 // used to record bytes of currently transfered data\r
1245 //\r
1246 WordCount = 0;\r
1247\r
1248 while (WordCount < ByteCount / 2) {\r
ead42efc 1249 //\r
630d580d 1250 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
ead42efc 1251 //\r
630d580d 1252 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1253 if (EFI_ERROR (Status)) {\r
1254 return EFI_DEVICE_ERROR;\r
ead42efc 1255 }\r
630d580d 1256\r
1257 Status = CheckErrorStatus (IdeDev);\r
1258 if (EFI_ERROR (Status)) {\r
1259 return EFI_DEVICE_ERROR;\r
1260 }\r
1261\r
ead42efc 1262 //\r
630d580d 1263 // Get the byte count for one series of read\r
ead42efc 1264 //\r
630d580d 1265 if ((WordCount + Increment) > ByteCount / 2) {\r
1266 Increment = ByteCount / 2 - WordCount;\r
ead42efc 1267 }\r
ead42efc 1268\r
630d580d 1269 IDEReadPortWMultiple (\r
1270 IdeDev->PciIo,\r
1271 IdeDev->IoPort->Data,\r
1272 Increment,\r
1273 Buffer16\r
1274 );\r
ead42efc 1275\r
630d580d 1276 WordCount += Increment;\r
1277 Buffer16 += Increment;\r
ead42efc 1278\r
630d580d 1279 }\r
ead42efc 1280\r
630d580d 1281 return CheckErrorStatus (IdeDev);\r
1282}\r
ead42efc 1283/**\r
cd57e888 1284 Send ATA Ext command into device with NON_DATA protocol.\r
ead42efc 1285\r
630d580d 1286 @param IdeDev Standard IDE device private data structure\r
1287 @param AtaCommand The ATA command to be sent\r
1288 @param Device The value in Device register\r
1289 @param Feature The value in Feature register\r
1290 @param SectorCount The value in SectorCount register\r
1291 @param LbaAddress The LBA address in 48-bit mode\r
ead42efc 1292\r
630d580d 1293 @retval EFI_SUCCESS Reading succeed\r
1294 @retval EFI_DEVICE_ERROR Error executing commands on this device.\r
ead42efc 1295\r
1296**/\r
1297EFI_STATUS\r
630d580d 1298AtaCommandIssueExt (\r
1299 IN IDE_BLK_IO_DEV *IdeDev,\r
1300 IN UINT8 AtaCommand,\r
1301 IN UINT8 Device,\r
1302 IN UINT16 Feature,\r
1303 IN UINT16 SectorCount,\r
1304 IN EFI_LBA LbaAddress\r
ead42efc 1305 )\r
1306{\r
630d580d 1307 EFI_STATUS Status;\r
1308 UINT8 SectorCount8;\r
1309 UINT8 Feature8;\r
1310 UINT8 LbaLow;\r
1311 UINT8 LbaMid;\r
1312 UINT8 LbaHigh;\r
ead42efc 1313\r
630d580d 1314 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1315 if (EFI_ERROR (Status)) {\r
1316 return EFI_DEVICE_ERROR;\r
ead42efc 1317 }\r
1318\r
630d580d 1319 //\r
1320 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1321 //\r
1322 IDEWritePortB (\r
1323 IdeDev->PciIo,\r
1324 IdeDev->IoPort->Head,\r
1325 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1326 );\r
1327\r
1328 //\r
1329 // ATA commands for ATA device must be issued when DRDY is set\r
1330 //\r
1331 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1332 if (EFI_ERROR (Status)) {\r
1333 return EFI_DEVICE_ERROR;\r
ead42efc 1334 }\r
1335\r
630d580d 1336 //\r
1337 // Pass parameter into device register block\r
1338 //\r
1339 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
ead42efc 1340\r
1341 //\r
630d580d 1342 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
ead42efc 1343 //\r
630d580d 1344 Feature8 = (UINT8) (Feature >> 8);\r
1345 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
ead42efc 1346\r
630d580d 1347 Feature8 = (UINT8) Feature;\r
1348 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
ead42efc 1349\r
630d580d 1350 //\r
1351 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1352 //\r
1353 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1354 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
ead42efc 1355\r
630d580d 1356 SectorCount8 = (UINT8) SectorCount;\r
1357 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
ead42efc 1358\r
630d580d 1359 //\r
1360 // Fill the start LBA registers, which are also two-byte FIFO\r
1361 //\r
1362 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);\r
1363 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1364 LbaLow = (UINT8) LbaAddress;\r
1365 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
ead42efc 1366\r
630d580d 1367 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);\r
1368 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1369 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);\r
1370 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
ead42efc 1371\r
630d580d 1372 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
1373 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1374 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
1375 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
ead42efc 1376\r
630d580d 1377 //\r
1378 // Work around for Segate 160G disk writing\r
1379 //\r
1380 gBS->Stall (1800);\r
1381\r
1382 //\r
1383 // Send command via Command Register\r
1384 //\r
1385 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1386\r
1387 //\r
1388 // Stall at least 400ns\r
1389 //\r
1390 gBS->Stall (100);\r
ead42efc 1391\r
1392 return EFI_SUCCESS;\r
1393}\r
ead42efc 1394/**\r
630d580d 1395 Send ATA Ext command into device with NON_DATA protocol\r
ead42efc 1396\r
630d580d 1397 @param IdeDev Standard IDE device private data structure\r
1398 @param AtaCommand The ATA command to be sent\r
1399 @param Device The value in Device register\r
1400 @param Feature The value in Feature register\r
1401 @param SectorCount The value in SectorCount register\r
1402 @param LbaAddress The LBA address in 48-bit mode\r
ead42efc 1403\r
630d580d 1404 @retval EFI_SUCCESS Reading succeed\r
1405 @retval EFI_DEVICE_ERROR Error executing commands on this device.\r
ead42efc 1406\r
1407**/\r
1408EFI_STATUS\r
630d580d 1409AtaCommandIssue (\r
ead42efc 1410 IN IDE_BLK_IO_DEV *IdeDev,\r
630d580d 1411 IN UINT8 AtaCommand,\r
1412 IN UINT8 Device,\r
1413 IN UINT16 Feature,\r
1414 IN UINT16 SectorCount,\r
1415 IN EFI_LBA LbaAddress\r
ead42efc 1416 )\r
1417{\r
1418 EFI_STATUS Status;\r
630d580d 1419 UINT8 SectorCount8;\r
1420 UINT8 Feature8;\r
1421 UINT8 Lba0;\r
1422 UINT8 Lba1;\r
1423 UINT8 Lba2;\r
1424 UINT8 Lba3;\r
1425\r
1426 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1427 if (EFI_ERROR (Status)) {\r
1428 return EFI_DEVICE_ERROR;\r
1429 }\r
ead42efc 1430\r
1431 //\r
630d580d 1432 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
ead42efc 1433 //\r
630d580d 1434 IDEWritePortB (\r
1435 IdeDev->PciIo,\r
1436 IdeDev->IoPort->Head,\r
1437 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1438 );\r
ead42efc 1439\r
630d580d 1440 //\r
1441 // ATA commands for ATA device must be issued when DRDY is set\r
1442 //\r
1443 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1444 if (EFI_ERROR (Status)) {\r
1445 return EFI_DEVICE_ERROR;\r
1446 }\r
ead42efc 1447\r
630d580d 1448 Lba0 = (UINT8) LbaAddress;\r
1449 Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);\r
1450 Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);\r
1451 Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);\r
1452 Device = (UINT8) (Device | Lba3);\r
ead42efc 1453\r
630d580d 1454 //\r
1455 // Pass parameter into device register block\r
1456 //\r
1457 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
ead42efc 1458\r
630d580d 1459 //\r
1460 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1461 //\r
1462 Feature8 = (UINT8) Feature;\r
1463 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
ead42efc 1464\r
630d580d 1465 //\r
1466 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1467 //\r
1468 SectorCount8 = (UINT8) SectorCount;\r
1469 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
ead42efc 1470\r
630d580d 1471 //\r
1472 // Fill the start LBA registers, which are also two-byte FIFO\r
1473 //\r
ead42efc 1474\r
630d580d 1475 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);\r
1476 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);\r
1477 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);\r
ead42efc 1478\r
630d580d 1479 //\r
1480 // Send command via Command Register\r
1481 //\r
1482 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
ead42efc 1483\r
630d580d 1484 //\r
1485 // Stall at least 400ns\r
1486 //\r
1487 gBS->Stall (100);\r
ead42efc 1488\r
630d580d 1489 return EFI_SUCCESS;\r
1490}\r
1491/**\r
1492 Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
ead42efc 1493\r
630d580d 1494 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1495 to record all the information of the IDE device.\r
1496 @param DataBuffer A pointer to the source buffer for the data.\r
1497 @param StartLba The starting logical block address to write to\r
1498 on the device media.\r
1499 @param NumberOfBlocks The number of transfer data blocks.\r
1500 @param UdmaOp The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,\r
1501 AtaUdmaWriteOp, AtaUdmaWriteExOp\r
ead42efc 1502\r
630d580d 1503 @retval EFI_SUCCESS the operation is successful.\r
1504 @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
1505 @retval EFI_UNSUPPORTED Unknown channel or operations command\r
1506 @retval EFI_DEVICE_ERROR Ata command execute failed\r
ead42efc 1507\r
1508**/\r
1509EFI_STATUS\r
630d580d 1510DoAtaUdma (\r
1511 IN IDE_BLK_IO_DEV *IdeDev,\r
1512 IN VOID *DataBuffer,\r
1513 IN EFI_LBA StartLba,\r
1514 IN UINTN NumberOfBlocks,\r
1515 IN ATA_UDMA_OPERATION UdmaOp\r
ead42efc 1516 )\r
1517{\r
630d580d 1518 IDE_DMA_PRD *PrdAddr;\r
1519 IDE_DMA_PRD *UsedPrdAddr;\r
1520 IDE_DMA_PRD *TempPrdAddr;\r
1521 UINT8 RegisterValue;\r
1522 UINT8 Device;\r
1523 UINT64 IoPortForBmic;\r
1524 UINT64 IoPortForBmis;\r
1525 UINT64 IoPortForBmid;\r
1526 EFI_STATUS Status;\r
1527 UINTN PrdTableNum;\r
1528 UINTN ByteCount;\r
1529 UINTN ByteAvailable;\r
1530 UINT8 *PrdBuffer;\r
1531 UINTN RemainBlockNum;\r
1532 UINT8 DeviceControl;\r
1533 UINT32 Count;\r
1534 UINTN PageCount;\r
1535 VOID *Map;\r
1536 VOID *MemPage;\r
1537 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
1538 UINTN MaxDmaCommandSectors;\r
1539 EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;\r
1540 UINT8 AtaCommand;\r
1541\r
1542 switch (UdmaOp) {\r
1543 case AtaUdmaReadOp:\r
1544 MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS;\r
1545 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
1546 AtaCommand = ATA_CMD_READ_DMA;\r
1547 break;\r
1548 case AtaUdmaReadExtOp:\r
1549 MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS;\r
1550 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
1551 AtaCommand = ATA_CMD_READ_DMA_EXT;\r
1552 break;\r
1553 case AtaUdmaWriteOp:\r
1554 MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS;\r
1555 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
1556 AtaCommand = ATA_CMD_WRITE_DMA;\r
1557 break;\r
1558 case AtaUdmaWriteExtOp:\r
1559 MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS;\r
1560 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
1561 AtaCommand = ATA_CMD_WRITE_DMA_EXT;\r
1562 break;\r
1563 default:\r
1564 return EFI_UNSUPPORTED;\r
1565 break;\r
1566 }\r
ead42efc 1567\r
1568 //\r
630d580d 1569 // Select device\r
ead42efc 1570 //\r
630d580d 1571 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
1572 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
ead42efc 1573\r
630d580d 1574 //\r
1575 // Enable interrupt to support UDMA\r
1576 //\r
1577 DeviceControl = 0;\r
1578 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
ead42efc 1579\r
630d580d 1580 if (IdePrimary == IdeDev->Channel) {\r
1581 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
1582 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
1583 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
1584 } else {\r
1585 if (IdeSecondary == IdeDev->Channel) {\r
1586 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
1587 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
1588 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
1589 } else {\r
1590 return EFI_UNSUPPORTED;\r
1591 }\r
1592 }\r
ead42efc 1593\r
630d580d 1594 //\r
1595 // Read BMIS register and clear ERROR and INTR bit\r
1596 //\r
1597 IdeDev->PciIo->Io.Read (\r
1598 IdeDev->PciIo,\r
1599 EfiPciIoWidthUint8,\r
1600 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1601 IoPortForBmis,\r
1602 1,\r
1603 &RegisterValue\r
1604 );\r
1605 \r
1606 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
1607 \r
1608 IdeDev->PciIo->Io.Write (\r
1609 IdeDev->PciIo,\r
1610 EfiPciIoWidthUint8,\r
1611 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1612 IoPortForBmis,\r
1613 1,\r
1614 &RegisterValue\r
1615 );\r
1616\r
1617 Status = EFI_SUCCESS;\r
1618 \r
1619 RemainBlockNum = NumberOfBlocks;\r
1620 while (RemainBlockNum > 0) {\r
1621\r
1622 if (RemainBlockNum >= MaxDmaCommandSectors) {\r
ead42efc 1623 //\r
630d580d 1624 // SectorCount is used to record the number of sectors to be read\r
ead42efc 1625 // Max 65536 sectors can be transfered at a time.\r
1626 //\r
630d580d 1627 NumberOfBlocks = MaxDmaCommandSectors;\r
1628 RemainBlockNum -= MaxDmaCommandSectors;\r
ead42efc 1629 } else {\r
630d580d 1630 NumberOfBlocks = (UINT16) RemainBlockNum;\r
1631 RemainBlockNum = 0;\r
ead42efc 1632 }\r
1633\r
1634 //\r
630d580d 1635 // Calculate the number of PRD table to make sure the memory region\r
1636 // not cross 64K boundary\r
ead42efc 1637 //\r
630d580d 1638 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
1639 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
ead42efc 1640\r
1641 //\r
630d580d 1642 // Build PRD table\r
ead42efc 1643 //\r
630d580d 1644 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
1645 Status = IdeDev->PciIo->AllocateBuffer (\r
1646 IdeDev->PciIo,\r
1647 AllocateAnyPages,\r
1648 EfiBootServicesData,\r
1649 PageCount,\r
1650 &MemPage,\r
1651 0\r
1652 );\r
ead42efc 1653 if (EFI_ERROR (Status)) {\r
630d580d 1654 return EFI_OUT_OF_RESOURCES;\r
ead42efc 1655 }\r
630d580d 1656 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
ead42efc 1657\r
630d580d 1658 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
1659 //\r
1660 // To make sure PRD is allocated in one 64K page\r
1661 //\r
1662 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
1663 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
1664 } else {\r
1665 if ((UINTN) PrdAddr & 0x03) {\r
1666 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
1667 } else {\r
1668 UsedPrdAddr = PrdAddr;\r
1669 }\r
1670 }\r
ead42efc 1671\r
630d580d 1672 //\r
1673 // Build the PRD table\r
1674 //\r
1675 Status = IdeDev->PciIo->Map (\r
1676 IdeDev->PciIo,\r
1677 PciIoProtocolOp,\r
1678 DataBuffer,\r
1679 &ByteCount,\r
1680 &DeviceAddress,\r
1681 &Map\r
1682 );\r
1683 if (EFI_ERROR (Status)) {\r
1684 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1685 return EFI_OUT_OF_RESOURCES;\r
1686 }\r
1687 PrdBuffer = (VOID *) ((UINTN) DeviceAddress);\r
1688 TempPrdAddr = UsedPrdAddr;\r
1689 while (TRUE) {\r
ead42efc 1690\r
630d580d 1691 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
ead42efc 1692\r
630d580d 1693 if (ByteCount <= ByteAvailable) {\r
1694 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
1695 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
1696 TempPrdAddr->EndOfTable = 0x8000;\r
1697 break;\r
1698 }\r
ead42efc 1699\r
630d580d 1700 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
1701 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
ead42efc 1702\r
630d580d 1703 ByteCount -= ByteAvailable;\r
1704 PrdBuffer += ByteAvailable;\r
1705 TempPrdAddr++;\r
1706 }\r
ead42efc 1707\r
630d580d 1708 //\r
1709 // Set the base address to BMID register\r
1710 //\r
1711 IdeDev->PciIo->Io.Write (\r
1712 IdeDev->PciIo,\r
1713 EfiPciIoWidthUint32,\r
1714 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1715 IoPortForBmid,\r
1716 1,\r
1717 &UsedPrdAddr\r
1718 );\r
ead42efc 1719\r
630d580d 1720 //\r
1721 // Set BMIC register to identify the operation direction\r
1722 //\r
1723 IdeDev->PciIo->Io.Read (\r
1724 IdeDev->PciIo,\r
1725 EfiPciIoWidthUint8,\r
1726 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1727 IoPortForBmic,\r
1728 1,\r
1729 &RegisterValue\r
1730 );\r
ead42efc 1731\r
630d580d 1732 if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {\r
1733 RegisterValue |= BMIC_NREAD;\r
1734 } else {\r
1735 RegisterValue &= ~((UINT8) BMIC_NREAD);\r
1736 }\r
ead42efc 1737\r
630d580d 1738 IdeDev->PciIo->Io.Write (\r
1739 IdeDev->PciIo,\r
1740 EfiPciIoWidthUint8,\r
1741 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1742 IoPortForBmic,\r
1743 1,\r
1744 &RegisterValue\r
1745 );\r
ead42efc 1746\r
630d580d 1747 if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {\r
1748 Status = AtaCommandIssueExt (\r
1749 IdeDev,\r
1750 AtaCommand,\r
1751 Device,\r
1752 0,\r
1753 (UINT16) NumberOfBlocks,\r
1754 StartLba\r
1755 );\r
1756 } else {\r
1757 Status = AtaCommandIssue (\r
1758 IdeDev,\r
1759 AtaCommand,\r
1760 Device,\r
1761 0,\r
1762 (UINT16) NumberOfBlocks,\r
1763 StartLba\r
1764 );\r
1765 }\r
ead42efc 1766\r
ead42efc 1767 if (EFI_ERROR (Status)) {\r
630d580d 1768 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1769 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
ead42efc 1770 return EFI_DEVICE_ERROR;\r
1771 }\r
ead42efc 1772\r
630d580d 1773 //\r
1774 // Set START bit of BMIC register\r
1775 //\r
1776 IdeDev->PciIo->Io.Read (\r
1777 IdeDev->PciIo,\r
1778 EfiPciIoWidthUint8,\r
1779 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1780 IoPortForBmic,\r
1781 1,\r
1782 &RegisterValue\r
1783 );\r
ead42efc 1784\r
630d580d 1785 RegisterValue |= BMIC_START;\r
ead42efc 1786\r
630d580d 1787 IdeDev->PciIo->Io.Write (\r
1788 IdeDev->PciIo,\r
1789 EfiPciIoWidthUint8,\r
1790 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1791 IoPortForBmic,\r
1792 1,\r
1793 &RegisterValue\r
1794 );\r
ead42efc 1795\r
ead42efc 1796 //\r
630d580d 1797 // Check the INTERRUPT and ERROR bit of BMIS\r
1798 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
1799 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
1800 // So set the variable Count to 2000, for about 2 second timeout time.\r
ead42efc 1801 //\r
630d580d 1802 Status = EFI_SUCCESS;\r
1803 Count = 2000;\r
1804 while (TRUE) {\r
ead42efc 1805\r
630d580d 1806 IdeDev->PciIo->Io.Read (\r
1807 IdeDev->PciIo,\r
1808 EfiPciIoWidthUint8,\r
1809 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1810 IoPortForBmis,\r
1811 1,\r
1812 &RegisterValue\r
1813 );\r
1814 if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) {\r
1815 if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) {\r
1816 Status = EFI_DEVICE_ERROR;\r
1817 break;\r
1818 }\r
1819 break;\r
1820 }\r
1821\r
1822 gBS->Stall (1000);\r
1823 Count --;\r
ead42efc 1824 }\r
1825\r
630d580d 1826 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1827 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
ead42efc 1828 //\r
630d580d 1829 // Read BMIS register and clear ERROR and INTR bit\r
ead42efc 1830 //\r
630d580d 1831 IdeDev->PciIo->Io.Read (\r
1832 IdeDev->PciIo,\r
1833 EfiPciIoWidthUint8,\r
1834 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1835 IoPortForBmis,\r
1836 1,\r
1837 &RegisterValue\r
1838 );\r
ead42efc 1839\r
630d580d 1840 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
ead42efc 1841\r
630d580d 1842 IdeDev->PciIo->Io.Write (\r
1843 IdeDev->PciIo,\r
1844 EfiPciIoWidthUint8,\r
1845 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1846 IoPortForBmis,\r
1847 1,\r
1848 &RegisterValue\r
1849 );\r
1850 //\r
1851 // Read Status Register of IDE device to clear interrupt\r
1852 //\r
1853 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
1854 //\r
1855 // Clear START bit of BMIC register\r
1856 //\r
1857 IdeDev->PciIo->Io.Read (\r
1858 IdeDev->PciIo,\r
1859 EfiPciIoWidthUint8,\r
1860 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1861 IoPortForBmic,\r
1862 1,\r
1863 &RegisterValue\r
1864 );\r
ead42efc 1865\r
630d580d 1866 RegisterValue &= ~((UINT8) BMIC_START);\r
ead42efc 1867\r
630d580d 1868 IdeDev->PciIo->Io.Write (\r
1869 IdeDev->PciIo,\r
1870 EfiPciIoWidthUint8,\r
1871 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1872 IoPortForBmic,\r
1873 1,\r
1874 &RegisterValue\r
1875 );\r
ead42efc 1876\r
630d580d 1877 if ((RegisterValue & BMIS_ERROR) != 0) {\r
1878 return EFI_DEVICE_ERROR;\r
1879 }\r
ead42efc 1880\r
630d580d 1881 if (EFI_ERROR (Status)) {\r
1882 break;\r
1883 }\r
1884 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
1885 StartLba += NumberOfBlocks;\r
1886 }\r
ead42efc 1887\r
630d580d 1888 //\r
1889 // Disable interrupt of Select device\r
1890 //\r
1891 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
1892 DeviceControl |= ATA_CTLREG_IEN_L;\r
1893 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
ead42efc 1894\r
630d580d 1895 return Status;\r
1896}\r
ead42efc 1897\r
ead42efc 1898\r
630d580d 1899/**\r
1900 This function is called by the AtaBlkIoReadBlocks() to perform reading from\r
1901 media in block unit. The function has been enhanced to support >120GB access \r
1902 and transfer at most 65536 blocks per command\r
ead42efc 1903\r
630d580d 1904 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record \r
1905 all the information of the IDE device.\r
1906 @param DataBuffer A pointer to the destination buffer for the data.\r
1907 @param StartLba The starting logical block address to read from on the device media.\r
1908 @param NumberOfBlocks The number of transfer data blocks.\r
ead42efc 1909\r
630d580d 1910 @return status depends on the function DoAtaUdma() returns.\r
ead42efc 1911**/\r
1912EFI_STATUS\r
630d580d 1913AtaUdmaReadExt (\r
ead42efc 1914 IN IDE_BLK_IO_DEV *IdeDev,\r
630d580d 1915 IN VOID *DataBuffer,\r
ead42efc 1916 IN EFI_LBA StartLba,\r
630d580d 1917 IN UINTN NumberOfBlocks\r
ead42efc 1918 )\r
1919{\r
630d580d 1920 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);\r
1921}\r
1922/**\r
1923 This function is called by the AtaBlkIoReadBlocks() to perform\r
1924 reading from media in block unit. The function has been enhanced to\r
1925 support >120GB access and transfer at most 65536 blocks per command\r
ead42efc 1926\r
630d580d 1927 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1928 all the information of the IDE device.\r
1929 @param DataBuffer A pointer to the destination buffer for the data.\r
1930 @param StartLba The starting logical block address to read from\r
1931 on the device media.\r
1932 @param NumberOfBlocks The number of transfer data blocks.\r
1933 \r
1934 @return status depends on the function DoAtaUdma() returns.\r
1935**/\r
1936EFI_STATUS\r
1937AtaUdmaRead (\r
1938 IN IDE_BLK_IO_DEV *IdeDev,\r
1939 IN VOID *DataBuffer,\r
1940 IN EFI_LBA StartLba,\r
1941 IN UINTN NumberOfBlocks\r
1942 )\r
1943{\r
1944 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);\r
1945}\r
ead42efc 1946\r
630d580d 1947/**\r
1948 This function is called by the AtaBlkIoReadBlocks() to perform\r
1949 reading from media in block unit. The function has been enhanced to\r
1950 support >120GB access and transfer at most 65536 blocks per command\r
ead42efc 1951\r
630d580d 1952 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1953 all the information of the IDE device.\r
1954 @param DataBuffer A pointer to the destination buffer for the data.\r
1955 @param StartLba The starting logical block address to read from on the device media.\r
1956 @param NumberOfBlocks The number of transfer data blocks.\r
ead42efc 1957\r
630d580d 1958 @return status is fully dependent on the return status of AtaPioDataInExt() function.\r
1959**/\r
1960EFI_STATUS\r
1961AtaReadSectorsExt (\r
1962 IN IDE_BLK_IO_DEV *IdeDev,\r
1963 IN VOID *DataBuffer,\r
1964 IN EFI_LBA StartLba,\r
1965 IN UINTN NumberOfBlocks\r
1966 )\r
1967{\r
1968 EFI_STATUS Status;\r
1969 UINTN BlocksRemaining;\r
1970 EFI_LBA Lba64;\r
1971 UINT8 AtaCommand;\r
1972 UINT16 SectorCount;\r
1973 UINT32 ByteCount;\r
1974 VOID *Buffer;\r
ead42efc 1975\r
1976 //\r
630d580d 1977 // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol\r
ead42efc 1978 //\r
630d580d 1979 AtaCommand = ATA_CMD_READ_SECTORS_EXT;\r
1980 Buffer = DataBuffer;\r
1981 BlocksRemaining = NumberOfBlocks;\r
1982 Lba64 = StartLba;\r
1983 Status = EFI_SUCCESS;\r
ead42efc 1984\r
630d580d 1985 while (BlocksRemaining > 0) {\r
ead42efc 1986\r
630d580d 1987 if (BlocksRemaining >= 0x10000) {\r
1988 //\r
1989 // SectorCount is used to record the number of sectors to be read\r
1990 // Max 65536 sectors can be transfered at a time.\r
1991 //\r
1992 SectorCount = 0xffff;\r
1993 } else {\r
1994 SectorCount = (UINT16) BlocksRemaining;\r
1995 }\r
ead42efc 1996\r
ead42efc 1997 //\r
630d580d 1998 // ByteCount is the number of bytes that will be read\r
ead42efc 1999 //\r
630d580d 2000 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
ead42efc 2001\r
2002 //\r
630d580d 2003 // call AtaPioDataInExt() to send Read Sector Command and receive data read\r
ead42efc 2004 //\r
630d580d 2005 Status = AtaPioDataInExt (\r
2006 IdeDev,\r
2007 Buffer,\r
2008 ByteCount,\r
2009 AtaCommand,\r
2010 Lba64,\r
2011 SectorCount\r
2012 );\r
2013 if (EFI_ERROR (Status)) {\r
2014 return Status;\r
ead42efc 2015 }\r
2016\r
630d580d 2017 Lba64 += SectorCount;\r
2018 Buffer = ((UINT8 *) Buffer + ByteCount);\r
2019 BlocksRemaining -= SectorCount;\r
ead42efc 2020 }\r
ead42efc 2021\r
630d580d 2022 return Status;\r
ead42efc 2023}\r
630d580d 2024/**\r
2025 This function is the ATA implementation for ReadBlocks in the\r
2026 Block I/O Protocol interface.\r
ead42efc 2027\r
630d580d 2028 @param IdeBlkIoDevice Indicates the calling context.\r
2029 @param MediaId The media id that the read request is for.\r
cd57e888 2030 @param Lba The starting logical block address to read from on the device.\r
630d580d 2031 @param BufferSize The size of the Buffer in bytes. This must be a multiple\r
2032 of the intrinsic block size of the device.\r
ead42efc 2033\r
630d580d 2034 @param Buffer A pointer to the destination buffer for the data. The caller\r
2035 is responsible for either having implicit or explicit ownership\r
2036 of the memory that data is read into.\r
2037\r
2038 @retval EFI_SUCCESS Read Blocks successfully.\r
2039 @retval EFI_DEVICE_ERROR Read Blocks failed.\r
2040 @retval EFI_NO_MEDIA There is no media in the device.\r
2041 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
2042 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
2043 intrinsic block size of the device.\r
2044 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
2045 or the data buffer is not valid.\r
ead42efc 2046\r
630d580d 2047 @note If Read Block error because of device error, this function will call\r
2048 AtaSoftReset() function to reset device.\r
ead42efc 2049\r
2050**/\r
630d580d 2051EFI_STATUS\r
2052AtaBlkIoReadBlocks (\r
2053 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
2054 IN UINT32 MediaId,\r
cd57e888 2055 IN EFI_LBA Lba,\r
630d580d 2056 IN UINTN BufferSize,\r
2057 OUT VOID *Buffer\r
ead42efc 2058 )\r
2059{\r
630d580d 2060 EFI_BLOCK_IO_MEDIA *Media;\r
2061 UINTN BlockSize;\r
2062 UINTN NumberOfBlocks;\r
2063 EFI_STATUS Status;\r
2064\r
2065 if (Buffer == NULL) {\r
2066 return EFI_INVALID_PARAMETER;\r
2067 }\r
2068\r
2069 if (BufferSize == 0) {\r
2070 return EFI_SUCCESS;\r
2071 }\r
2072\r
2073 Status = EFI_SUCCESS;\r
ead42efc 2074\r
2075 //\r
630d580d 2076 // Get the intrinsic block size\r
ead42efc 2077 //\r
630d580d 2078 Media = IdeBlkIoDevice->BlkIo.Media;\r
2079 BlockSize = Media->BlockSize;\r
2080\r
2081 NumberOfBlocks = BufferSize / BlockSize;\r
2082\r
2083 if (MediaId != Media->MediaId) {\r
2084 return EFI_MEDIA_CHANGED;\r
ead42efc 2085 }\r
2086\r
630d580d 2087 if (BufferSize % BlockSize != 0) {\r
2088 return EFI_BAD_BUFFER_SIZE;\r
2089 }\r
ead42efc 2090\r
630d580d 2091 if (!(Media->MediaPresent)) {\r
2092 return EFI_NO_MEDIA;\r
2093 }\r
2094\r
cd57e888 2095 if (Lba > Media->LastBlock) {\r
630d580d 2096 return EFI_INVALID_PARAMETER;\r
2097 }\r
2098\r
cd57e888 2099 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
630d580d 2100 return EFI_INVALID_PARAMETER;\r
2101 }\r
2102\r
2103 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
2104 return EFI_INVALID_PARAMETER;\r
2105 }\r
2106\r
2107 Status = EFI_SUCCESS;\r
2108 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
ead42efc 2109 //\r
630d580d 2110 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism\r
ead42efc 2111 //\r
630d580d 2112 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
cd57e888 2113 Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
630d580d 2114 } else {\r
cd57e888 2115 Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2116 }\r
630d580d 2117 } else {\r
ead42efc 2118 //\r
630d580d 2119 // For ATA-3 compatible device, use ATA-3 read block mechanism\r
ead42efc 2120 //\r
630d580d 2121 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
cd57e888 2122 Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2123 } else {\r
cd57e888 2124 Status = AtaReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2125 }\r
630d580d 2126 }\r
ead42efc 2127\r
630d580d 2128 if (EFI_ERROR (Status)) {\r
2129 AtaSoftReset (IdeBlkIoDevice);\r
2130 return EFI_DEVICE_ERROR;\r
ead42efc 2131 }\r
2132\r
630d580d 2133 return EFI_SUCCESS;\r
ead42efc 2134\r
630d580d 2135}\r
75eccf9d 2136/**\r
630d580d 2137 This function is used to send out ATA commands conforms to the\r
2138 PIO Data Out Protocol, supporting ATA/ATAPI-6 standard\r
75eccf9d 2139\r
630d580d 2140 Comparing with ATA-3 data out protocol, we have two differents here:<BR>\r
2141 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
2142 wait will frequently fail... cause writing function return error)\r
2143\r
2144 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
2145 slow down writing performance by 100 times!)\r
2146\r
2147 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2148 to record all the information of the IDE device.\r
2149 @param Buffer buffer contained data transferred from host to device.\r
2150 @param ByteCount data size in byte unit of the buffer.\r
2151 @param AtaCommand value of the Command Register\r
2152 @param StartLba the start LBA of this transaction\r
2153 @param SectorCount the count of sectors to be transfered\r
2154\r
2155 @retval EFI_SUCCESS send out the ATA command and device receive required\r
2156 data successfully.\r
2157 @retval EFI_DEVICE_ERROR command sent failed.\r
75eccf9d 2158\r
75eccf9d 2159**/\r
2160EFI_STATUS\r
630d580d 2161AtaPioDataOutExt (\r
2162 IN IDE_BLK_IO_DEV *IdeDev,\r
2163 IN VOID *Buffer,\r
2164 IN UINT32 ByteCount,\r
2165 IN UINT8 AtaCommand,\r
2166 IN EFI_LBA StartLba,\r
2167 IN UINT16 SectorCount\r
75eccf9d 2168 )\r
2169{\r
630d580d 2170 UINT8 DevSel;\r
2171 UINT8 SectorCount8;\r
2172 UINT8 LbaLow;\r
2173 UINT8 LbaMid;\r
2174 UINT8 LbaHigh;\r
2175 UINTN WordCount;\r
2176 UINTN Increment;\r
2177 UINT16 *Buffer16;\r
2178 EFI_STATUS Status;\r
2179\r
2180 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2181 if (EFI_ERROR (Status)) {\r
2182 return EFI_DEVICE_ERROR;\r
2183 }\r
75eccf9d 2184\r
75eccf9d 2185 //\r
630d580d 2186 // Select device. Set bit6 as 1 to indicate LBA mode is used\r
75eccf9d 2187 //\r
630d580d 2188 DevSel = (UINT8) (IdeDev->Device << 4);\r
2189 DevSel |= 0x40;\r
2190 IDEWritePortB (\r
2191 IdeDev->PciIo,\r
2192 IdeDev->IoPort->Head,\r
2193 DevSel\r
2194 );\r
2195\r
75eccf9d 2196 //\r
630d580d 2197 // Wait for DRDY singnal asserting.\r
ead42efc 2198 //\r
2199 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2200 if (EFI_ERROR (Status)) {\r
2201 return EFI_DEVICE_ERROR;\r
2202 }\r
2203\r
2204 //\r
630d580d 2205 // Fill feature register if needed\r
ead42efc 2206 //\r
630d580d 2207 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
2208 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
2209 }\r
ead42efc 2210\r
2211 //\r
2212 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
2213 //\r
2214 SectorCount8 = (UINT8) (SectorCount >> 8);\r
2215 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2216\r
2217 SectorCount8 = (UINT8) SectorCount;\r
2218 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2219\r
2220 //\r
2221 // Fill the start LBA registers, which are also two-byte FIFO\r
2222 //\r
630d580d 2223 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
2224 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
2225 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
ead42efc 2226 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
ead42efc 2227 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
ead42efc 2228 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2229\r
630d580d 2230 LbaLow = (UINT8) StartLba;\r
2231 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
2232 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
2233 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2234 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
2235 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
ead42efc 2236\r
2237 //\r
630d580d 2238 // Send command via Command Register, invoking the processing of this command\r
ead42efc 2239 //\r
2240 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2241\r
630d580d 2242 Buffer16 = (UINT16 *) Buffer;\r
ead42efc 2243\r
2244 //\r
630d580d 2245 // According to PIO Data Out protocol, host can perform a series of writes to\r
2246 // the data register after each time device set DRQ ready;\r
ead42efc 2247 //\r
630d580d 2248 Increment = 256;\r
ead42efc 2249\r
2250 //\r
630d580d 2251 // used to record bytes of currently transfered data\r
ead42efc 2252 //\r
630d580d 2253 WordCount = 0;\r
ead42efc 2254\r
630d580d 2255 while (WordCount < ByteCount / 2) {\r
2256 //\r
2257 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
2258 //\r
2259 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
2260 if (EFI_ERROR (Status)) {\r
2261 return EFI_DEVICE_ERROR;\r
2262 }\r
ead42efc 2263\r
630d580d 2264 Status = CheckErrorStatus (IdeDev);\r
2265 if (EFI_ERROR (Status)) {\r
2266 return EFI_DEVICE_ERROR;\r
2267 }\r
ead42efc 2268\r
630d580d 2269 //\r
2270 // Write data into device by one series of writing to data register\r
2271 //\r
2272 if ((WordCount + Increment) > ByteCount / 2) {\r
2273 Increment = ByteCount / 2 - WordCount;\r
2274 }\r
ead42efc 2275\r
630d580d 2276 IDEWritePortWMultiple (\r
2277 IdeDev->PciIo,\r
2278 IdeDev->IoPort->Data,\r
2279 Increment,\r
2280 Buffer16\r
2281 );\r
ead42efc 2282\r
630d580d 2283 WordCount += Increment;\r
2284 Buffer16 += Increment;\r
ead42efc 2285\r
630d580d 2286 }\r
2287 return CheckErrorStatus (IdeDev);\r
ead42efc 2288}\r
ead42efc 2289/**\r
630d580d 2290 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2291 writing to media in block unit. The function has been enhanced to\r
ead42efc 2292 support >120GB access and transfer at most 65536 blocks per command\r
2293\r
630d580d 2294 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2295 to record all the information of the IDE device.\r
2296 @param DataBuffer A pointer to the source buffer for the data.\r
2297 @param StartLba The starting logical block address to write to\r
2298 on the device media.\r
2299 @param NumberOfBlocks The number of transfer data blocks.\r
ead42efc 2300\r
630d580d 2301 @return status depends on the function DoAtaUdma() returns.\r
ead42efc 2302**/\r
2303EFI_STATUS\r
630d580d 2304AtaUdmaWriteExt (\r
ead42efc 2305 IN IDE_BLK_IO_DEV *IdeDev,\r
2306 IN VOID *DataBuffer,\r
2307 IN EFI_LBA StartLba,\r
2308 IN UINTN NumberOfBlocks\r
2309 )\r
2310{\r
630d580d 2311 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);\r
ead42efc 2312}\r
2313\r
2314/**\r
630d580d 2315 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2316 writing to media in block unit. \r
2317\r
2318 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2319 to record all the information of the IDE device.\r
2320 @param DataBuffer A pointer to the source buffer for the data.\r
2321 @param StartLba The starting logical block address to write to\r
2322 on the device media.\r
2323 @param NumberOfBlocks The number of transfer data blocks.\r
2324 \r
2325 @return status depends on the function DoAtaUdma() returns.\r
ead42efc 2326**/\r
2327EFI_STATUS\r
630d580d 2328AtaUdmaWrite (\r
ead42efc 2329 IN IDE_BLK_IO_DEV *IdeDev,\r
2330 IN VOID *DataBuffer,\r
2331 IN EFI_LBA StartLba,\r
2332 IN UINTN NumberOfBlocks\r
2333 )\r
2334{\r
630d580d 2335 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);\r
ead42efc 2336}\r
ead42efc 2337/**\r
2338 This function is called by the AtaBlkIoWriteBlocks() to perform\r
630d580d 2339 writing onto media in block unit. The function has been enhanced to\r
ead42efc 2340 support >120GB access and transfer at most 65536 blocks per command\r
2341\r
630d580d 2342 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used\r
2343 to record all the information of the IDE device.\r
2344 @param DataBuffer A pointer to the source buffer for the data.\r
2345 @param StartLba The starting logical block address to write onto the device \r
2346 media.\r
2347 @param NumberOfBlocks The number of transfer data blocks.\r
ead42efc 2348\r
630d580d 2349 @return status is fully dependent on the return status of AtaPioDataOutExt() function.\r
ead42efc 2350**/\r
2351EFI_STATUS\r
630d580d 2352AtaWriteSectorsExt (\r
ead42efc 2353 IN IDE_BLK_IO_DEV *IdeDev,\r
2354 IN VOID *DataBuffer,\r
2355 IN EFI_LBA StartLba,\r
2356 IN UINTN NumberOfBlocks\r
2357 )\r
2358{\r
630d580d 2359 EFI_STATUS Status;\r
2360 EFI_LBA Lba64;\r
2361 UINTN BlocksRemaining;\r
2362 UINT8 AtaCommand;\r
2363 UINT16 SectorCount;\r
2364 UINT32 ByteCount;\r
2365 VOID *Buffer;\r
ead42efc 2366\r
630d580d 2367 //\r
2368 // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol\r
2369 //\r
2370 AtaCommand = ATA_CMD_WRITE_SECTORS_EXT;\r
2371 Lba64 = StartLba;\r
2372 Buffer = DataBuffer;\r
2373 BlocksRemaining = NumberOfBlocks;\r
2374\r
2375 Status = EFI_SUCCESS;\r
ead42efc 2376\r
630d580d 2377 while (BlocksRemaining > 0) {\r
ead42efc 2378\r
630d580d 2379 if (BlocksRemaining >= 0x10000) {\r
2380 //\r
2381 // SectorCount is used to record the number of sectors to be written.\r
2382 // Max 65536 sectors can be transfered at a time.\r
2383 //\r
2384 SectorCount = 0xffff;\r
2385 } else {\r
2386 SectorCount = (UINT16) BlocksRemaining;\r
2387 }\r
ead42efc 2388\r
630d580d 2389 //\r
2390 // ByteCount is the number of bytes that will be written\r
2391 //\r
2392 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
ead42efc 2393\r
630d580d 2394 //\r
2395 // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command\r
2396 //\r
2397 Status = AtaPioDataOutExt (\r
2398 IdeDev,\r
2399 Buffer,\r
2400 ByteCount,\r
2401 AtaCommand,\r
2402 Lba64,\r
2403 SectorCount\r
2404 );\r
2405 if (EFI_ERROR (Status)) {\r
2406 return Status;\r
2407 }\r
ead42efc 2408\r
630d580d 2409 Lba64 += SectorCount;\r
2410 Buffer = ((UINT8 *) Buffer + ByteCount);\r
2411 BlocksRemaining -= SectorCount;\r
2412 }\r
ead42efc 2413\r
630d580d 2414 return Status;\r
ead42efc 2415}\r
ead42efc 2416/**\r
630d580d 2417 This function is the ATA implementation for WriteBlocks in the\r
2418 Block I/O Protocol interface.\r
ead42efc 2419\r
630d580d 2420 @param IdeBlkIoDevice Indicates the calling context.\r
2421 @param MediaId The media id that the write request is for.\r
cd57e888 2422 @param Lba The starting logical block address to write onto the device.\r
630d580d 2423 @param BufferSize The size of the Buffer in bytes. This must be a multiple\r
2424 of the intrinsic block size of the device.\r
2425 @param Buffer A pointer to the source buffer for the data.The caller\r
2426 is responsible for either having implicit or explicit \r
2427 ownership of the memory that data is written from.\r
ead42efc 2428\r
630d580d 2429 @retval EFI_SUCCESS Write Blocks successfully.\r
2430 @retval EFI_DEVICE_ERROR Write Blocks failed.\r
2431 @retval EFI_NO_MEDIA There is no media in the device.\r
2432 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
ead42efc 2433\r
630d580d 2434 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
2435 intrinsic block size of the device.\r
2436 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
2437 or the data buffer is not valid.\r
ead42efc 2438\r
630d580d 2439 @note If Write Block error because of device error, this function will call\r
2440 AtaSoftReset() function to reset device.\r
ead42efc 2441**/\r
2442EFI_STATUS\r
630d580d 2443AtaBlkIoWriteBlocks (\r
2444 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
2445 IN UINT32 MediaId,\r
cd57e888 2446 IN EFI_LBA Lba,\r
630d580d 2447 IN UINTN BufferSize,\r
2448 OUT VOID *Buffer\r
ead42efc 2449 )\r
2450{\r
ead42efc 2451\r
630d580d 2452 EFI_BLOCK_IO_MEDIA *Media;\r
2453 UINTN BlockSize;\r
2454 UINTN NumberOfBlocks;\r
2455 EFI_STATUS Status;\r
2456\r
2457 if (Buffer == NULL) {\r
2458 return EFI_INVALID_PARAMETER;\r
ead42efc 2459 }\r
2460\r
630d580d 2461 if (BufferSize == 0) {\r
2462 return EFI_SUCCESS;\r
2463 }\r
2464\r
2465 Status = EFI_SUCCESS;\r
ead42efc 2466\r
2467 //\r
630d580d 2468 // Get the intrinsic block size\r
ead42efc 2469 //\r
630d580d 2470 Media = IdeBlkIoDevice->BlkIo.Media;\r
2471 BlockSize = Media->BlockSize;\r
2472 NumberOfBlocks = BufferSize / BlockSize;\r
ead42efc 2473\r
630d580d 2474 if (MediaId != Media->MediaId) {\r
2475 return EFI_MEDIA_CHANGED;\r
ead42efc 2476 }\r
2477\r
630d580d 2478 if (BufferSize % BlockSize != 0) {\r
2479 return EFI_BAD_BUFFER_SIZE;\r
2480 }\r
6979fd93 2481\r
cd57e888 2482 if (Lba > Media->LastBlock) {\r
630d580d 2483 return EFI_INVALID_PARAMETER;\r
2484 }\r
ead42efc 2485\r
cd57e888 2486 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
630d580d 2487 return EFI_INVALID_PARAMETER;\r
2488 }\r
ead42efc 2489\r
630d580d 2490 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
2491 return EFI_INVALID_PARAMETER;\r
2492 }\r
ead42efc 2493\r
630d580d 2494 Status = EFI_SUCCESS;\r
2495 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
ead42efc 2496 //\r
630d580d 2497 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism\r
ead42efc 2498 //\r
630d580d 2499 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
cd57e888 2500 Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2501 } else {\r
cd57e888 2502 Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2503 }\r
630d580d 2504 } else {\r
ead42efc 2505 //\r
630d580d 2506 // For ATA-3 compatible device, use ATA-3 write block mechanism\r
ead42efc 2507 //\r
630d580d 2508 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
cd57e888 2509 Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
630d580d 2510 } else {\r
cd57e888 2511 Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
ead42efc 2512 }\r
630d580d 2513 }\r
ead42efc 2514\r
630d580d 2515 if (EFI_ERROR (Status)) {\r
2516 AtaSoftReset (IdeBlkIoDevice);\r
2517 return EFI_DEVICE_ERROR;\r
2518 }\r
ead42efc 2519\r
630d580d 2520 return EFI_SUCCESS;\r
2521}\r
2522/**\r
2523 Enable Long Physical Sector Feature for ATA device.\r
ead42efc 2524\r
630d580d 2525 @param IdeDev The IDE device data\r
ead42efc 2526\r
630d580d 2527 @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature\r
2528 and corresponding fields in BlockIo structure is updated.\r
2529 @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector\r
2530 feature is not supported.\r
2531**/\r
2532EFI_STATUS\r
2533AtaEnableLongPhysicalSector (\r
2534 IN IDE_BLK_IO_DEV *IdeDev\r
2535 )\r
2536{\r
2537 EFI_ATA_IDENTIFY_DATA *AtaIdentifyData;\r
2538 UINT16 PhyLogicSectorSupport;\r
ead42efc 2539\r
630d580d 2540 ASSERT (IdeDev->IdData != NULL);\r
2541 //\r
2542 // Only valid for ATA device\r
2543 //\r
2544 AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData;\r
2545 if ((AtaIdentifyData->config & 0x8000) != 0) {\r
2546 return EFI_UNSUPPORTED;\r
2547 }\r
2548 PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support;\r
2549 //\r
2550 // Check whether Long Physical Sector Feature is supported\r
2551 //\r
2552 if ((PhyLogicSectorSupport & 0xc000) == 0x4000) {\r
2553 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1;\r
2554 IdeDev->BlkIo.Media->LowestAlignedLba = 0;\r
ead42efc 2555 //\r
630d580d 2556 // Check whether one physical block contains multiple physical blocks\r
ead42efc 2557 //\r
630d580d 2558 if ((PhyLogicSectorSupport & 0x2000) != 0) {\r
2559 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock =\r
2560 (UINT32) (1 << (PhyLogicSectorSupport & 0x000f));\r
2561 //\r
2562 // Check lowest alignment of logical blocks within physical block\r
2563 //\r
2564 if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) {\r
2565 IdeDev->BlkIo.Media->LowestAlignedLba =\r
d96d37d8 2566 (EFI_LBA) ((IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock - ((UINT32)AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %\r
2567 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock);\r
630d580d 2568 }\r
2569 }\r
ead42efc 2570 //\r
630d580d 2571 // Check logical block size\r
ead42efc 2572 //\r
630d580d 2573 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
2574 if ((PhyLogicSectorSupport & 0x1000) != 0) {\r
2575 IdeDev->BlkIo.Media->BlockSize = (UINT32) (\r
2576 ((AtaIdentifyData->logic_sector_size_hi << 16) |\r
2577 AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16)\r
2578 );\r
ead42efc 2579 }\r
630d580d 2580 return EFI_SUCCESS;\r
2581 } else {\r
2582 return EFI_UNSUPPORTED;\r
2583 }\r
2584}\r
2585/**\r
2586 Send ATA command into device with NON_DATA protocol\r
ead42efc 2587\r
630d580d 2588 @param IdeDev Standard IDE device private data structure\r
2589 @param AtaCommand The ATA command to be sent\r
2590 @param Device The value in Device register\r
2591 @param Feature The value in Feature register\r
2592 @param SectorCount The value in SectorCount register\r
2593 @param LbaLow The value in LBA_LOW register\r
2594 @param LbaMiddle The value in LBA_MIDDLE register\r
2595 @param LbaHigh The value in LBA_HIGH register\r
ead42efc 2596\r
630d580d 2597 @retval EFI_SUCCESS Reading succeed\r
2598 @retval EFI_ABORTED Command failed\r
2599 @retval EFI_DEVICE_ERROR Device status error.\r
ead42efc 2600\r
630d580d 2601**/\r
2602EFI_STATUS\r
2603AtaNonDataCommandIn (\r
2604 IN IDE_BLK_IO_DEV *IdeDev,\r
2605 IN UINT8 AtaCommand,\r
2606 IN UINT8 Device,\r
2607 IN UINT8 Feature,\r
2608 IN UINT8 SectorCount,\r
2609 IN UINT8 LbaLow,\r
2610 IN UINT8 LbaMiddle,\r
2611 IN UINT8 LbaHigh\r
2612 )\r
2613{\r
2614 EFI_STATUS Status;\r
2615 UINT8 StatusRegister;\r
ead42efc 2616\r
630d580d 2617 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2618 if (EFI_ERROR (Status)) {\r
2619 return EFI_DEVICE_ERROR;\r
2620 }\r
ead42efc 2621\r
630d580d 2622 //\r
cd57e888 2623 // Select device (bit4), set Lba mode(bit6) (use 0xe0 for compatibility)\r
630d580d 2624 //\r
2625 IDEWritePortB (\r
2626 IdeDev->PciIo,\r
2627 IdeDev->IoPort->Head,\r
2628 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
2629 );\r
ead42efc 2630\r
630d580d 2631 //\r
2632 // ATA commands for ATA device must be issued when DRDY is set\r
2633 //\r
2634 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2635 if (EFI_ERROR (Status)) {\r
2636 return EFI_DEVICE_ERROR;\r
2637 }\r
ead42efc 2638\r
630d580d 2639 //\r
2640 // Pass parameter into device register block\r
2641 //\r
2642 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2643 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);\r
2644 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
2645 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2646 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);\r
2647 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
ead42efc 2648\r
630d580d 2649 //\r
2650 // Send command via Command Register\r
2651 //\r
2652 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
ead42efc 2653\r
630d580d 2654 //\r
2655 // Wait for command completion\r
2656 // For ATAPI_SMART_CMD, we may need more timeout to let device\r
2657 // adjust internal states.\r
2658 //\r
2659 if (AtaCommand == ATA_CMD_SMART) {\r
2660 Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);\r
2661 } else {\r
2662 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2663 }\r
2664 if (EFI_ERROR (Status)) {\r
2665 return EFI_DEVICE_ERROR;\r
2666 }\r
ead42efc 2667\r
630d580d 2668 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
2669 if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
ead42efc 2670 //\r
630d580d 2671 // Failed to execute command, abort operation\r
6979fd93 2672 //\r
630d580d 2673 return EFI_ABORTED;\r
2674 }\r
6979fd93 2675\r
630d580d 2676 return EFI_SUCCESS;\r
2677}\r
6979fd93 2678\r
630d580d 2679/**\r
2680 Send ATA Ext command into device with NON_DATA protocol\r
ead42efc 2681\r
630d580d 2682 @param IdeDev Standard IDE device private data structure\r
2683 @param AtaCommand The ATA command to be sent\r
2684 @param Device The value in Device register\r
2685 @param Feature The value in Feature register\r
2686 @param SectorCount The value in SectorCount register\r
2687 @param LbaAddress The LBA address in 48-bit mode\r
ead42efc 2688\r
630d580d 2689 @retval EFI_SUCCESS Reading succeed\r
2690 @retval EFI_ABORTED Command failed\r
2691 @retval EFI_DEVICE_ERROR Device status error.\r
ead42efc 2692\r
630d580d 2693**/\r
2694EFI_STATUS\r
2695AtaNonDataCommandInExt (\r
2696 IN IDE_BLK_IO_DEV *IdeDev,\r
2697 IN UINT8 AtaCommand,\r
2698 IN UINT8 Device,\r
2699 IN UINT16 Feature,\r
2700 IN UINT16 SectorCount,\r
2701 IN EFI_LBA LbaAddress\r
2702 )\r
2703{\r
2704 EFI_STATUS Status;\r
2705 UINT8 StatusRegister;\r
2706 UINT8 SectorCount8;\r
2707 UINT8 Feature8;\r
2708 UINT8 LbaLow;\r
2709 UINT8 LbaMid;\r
2710 UINT8 LbaHigh;\r
ead42efc 2711\r
630d580d 2712 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2713 if (EFI_ERROR (Status)) {\r
2714 return EFI_DEVICE_ERROR;\r
ead42efc 2715 }\r
2716\r
2717 //\r
630d580d 2718 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
ead42efc 2719 //\r
630d580d 2720 IDEWritePortB (\r
2721 IdeDev->PciIo,\r
2722 IdeDev->IoPort->Head,\r
2723 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
2724 );\r
ead42efc 2725\r
630d580d 2726 //\r
2727 // ATA commands for ATA device must be issued when DRDY is set\r
2728 //\r
2729 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2730 if (EFI_ERROR (Status)) {\r
2731 return EFI_DEVICE_ERROR;\r
2732 }\r
2733\r
2734 //\r
2735 // Pass parameter into device register block\r
2736 //\r
2737 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2738\r
2739 //\r
2740 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
2741 //\r
2742 Feature8 = (UINT8) (Feature >> 8);\r
2743 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
2744\r
2745 Feature8 = (UINT8) Feature;\r
2746 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
2747\r
2748 //\r
2749 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
2750 //\r
2751 SectorCount8 = (UINT8) (SectorCount >> 8);\r
2752 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2753\r
2754 SectorCount8 = (UINT8) SectorCount;\r
2755 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2756\r
2757 //\r
2758 // Fill the start LBA registers, which are also two-byte FIFO\r
2759 //\r
2760 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);\r
2761 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);\r
2762 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
2763 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2764 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
2765 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2766\r
2767 LbaLow = (UINT8) LbaAddress;\r
2768 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);\r
2769 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
2770 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2771 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
2772 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2773\r
2774 //\r
2775 // Send command via Command Register\r
2776 //\r
2777 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2778\r
2779 //\r
2780 // Wait for command completion\r
2781 //\r
2782 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2783 if (EFI_ERROR (Status)) {\r
2784 return EFI_DEVICE_ERROR;\r
2785 }\r
2786\r
2787 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
2788 if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
2789 //\r
2790 // Failed to execute command, abort operation\r
2791 //\r
2792 return EFI_ABORTED;\r
2793 }\r
2794\r
2795 return EFI_SUCCESS;\r
ead42efc 2796}\r
6979fd93 2797\r
630d580d 2798\r
2799\r