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