]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
In IdeBus driver block I/O read/write interface, it will always try to use UDMA mode...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / ata.c
CommitLineData
ed72955c 1/** @file\r
a98f11c5 2 Copyright (c) 2006, Intel Corporation\r
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
597\r
598//#ifdef EFI_DEBUG\r
599\r
600 UINT8 ErrorRegister;\r
601\r
602//#endif\r
603\r
604 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
605\r
2ce31132 606 DEBUG_CODE_BEGIN ();\r
878ddf1f 607\r
608 if (StatusRegister & DWF) {\r
2ce31132 609 DEBUG (\r
610 (EFI_D_BLKIO,\r
611 "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
612 StatusRegister)\r
613 );\r
614 }\r
878ddf1f 615\r
2ce31132 616 if (StatusRegister & CORR) {\r
617 DEBUG (\r
618 (EFI_D_BLKIO,\r
619 "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
620 StatusRegister)\r
621 );\r
622 }\r
878ddf1f 623\r
2ce31132 624 if (StatusRegister & ERR) {\r
625 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
878ddf1f 626\r
2ce31132 627 if (ErrorRegister & BBK_ERR) {\r
628 DEBUG (\r
629 (EFI_D_BLKIO,\r
630 "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
631 ErrorRegister)\r
632 );\r
633 }\r
878ddf1f 634\r
2ce31132 635 if (ErrorRegister & UNC_ERR) {\r
636 DEBUG (\r
637 (EFI_D_BLKIO,\r
638 "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
639 ErrorRegister)\r
640 );\r
641 }\r
878ddf1f 642\r
2ce31132 643 if (ErrorRegister & MC_ERR) {\r
644 DEBUG (\r
645 (EFI_D_BLKIO,\r
646 "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
647 ErrorRegister)\r
648 );\r
649 }\r
878ddf1f 650\r
2ce31132 651 if (ErrorRegister & ABRT_ERR) {\r
652 DEBUG (\r
653 (EFI_D_BLKIO,\r
654 "CheckErrorStatus()-- %02x : Error : Abort\n",\r
655 ErrorRegister)\r
656 );\r
657 }\r
878ddf1f 658\r
2ce31132 659 if (ErrorRegister & TK0NF_ERR) {\r
660 DEBUG (\r
661 (EFI_D_BLKIO,\r
662 "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
663 ErrorRegister)\r
664 );\r
665 }\r
878ddf1f 666\r
2ce31132 667 if (ErrorRegister & AMNF_ERR) {\r
668 DEBUG (\r
669 (EFI_D_BLKIO,\r
670 "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
671 ErrorRegister)\r
672 );\r
673 }\r
674 }\r
878ddf1f 675\r
2ce31132 676 DEBUG_CODE_END ();\r
878ddf1f 677\r
678 if ((StatusRegister & (ERR | DWF | CORR)) == 0) {\r
679 return EFI_SUCCESS;\r
680 }\r
681\r
682 return EFI_DEVICE_ERROR;\r
683\r
684}\r
685\r
ed72955c 686/**\r
687 This function is called by the AtaBlkIoReadBlocks() to perform\r
688 reading from media in block unit.\r
689\r
690 @param[in] *IdeDev\r
691 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
692 to record all the information of the IDE device.\r
693\r
694 @param[in] *DataBuffer\r
a98f11c5 695 A pointer to the destination buffer for the data.\r
ed72955c 696\r
697 @param[in] Lba\r
a98f11c5 698 The starting logical block address to read from\r
ed72955c 699 on the device media.\r
700\r
701 @param[in] NumberOfBlocks\r
702 The number of transfer data blocks.\r
703\r
704 @return return status is fully dependent on the return status\r
705 of AtaPioDataIn() function.\r
706\r
707**/\r
878ddf1f 708EFI_STATUS\r
709AtaReadSectors (\r
710 IN IDE_BLK_IO_DEV *IdeDev,\r
711 IN VOID *DataBuffer,\r
712 IN EFI_LBA Lba,\r
713 IN UINTN NumberOfBlocks\r
714 )\r
878ddf1f 715{\r
716 EFI_STATUS Status;\r
717 UINTN BlocksRemaining;\r
718 UINT32 Lba32;\r
719 UINT8 Lba0;\r
720 UINT8 Lba1;\r
721 UINT8 Lba2;\r
722 UINT8 Lba3;\r
723 UINT8 AtaCommand;\r
724 UINT8 SectorCount8;\r
725 UINT16 SectorCount;\r
726 UINTN ByteCount;\r
727 VOID *Buffer;\r
728\r
729 Buffer = DataBuffer;\r
730\r
731 //\r
732 // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol\r
733 //\r
734 AtaCommand = READ_SECTORS_CMD;\r
735\r
a98f11c5 736\r
878ddf1f 737 BlocksRemaining = NumberOfBlocks;\r
738\r
739 Lba32 = (UINT32) Lba;\r
740\r
741 Status = EFI_SUCCESS;\r
742\r
743 while (BlocksRemaining > 0) {\r
a98f11c5 744\r
878ddf1f 745 //\r
746 // in ATA-3 spec, LBA is in 28 bit width\r
747 //\r
748 Lba0 = (UINT8) Lba32;\r
749 Lba1 = (UINT8) (Lba32 >> 8);\r
750 Lba2 = (UINT8) (Lba32 >> 16);\r
751 //\r
752 // low 4 bit of Lba3 stands for LBA bit24~bit27.\r
753 //\r
754 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
755\r
756 if (BlocksRemaining >= 0x100) {\r
a98f11c5 757\r
878ddf1f 758 //\r
759 // SectorCount8 is sent to Sector Count register, 0x00 means 256\r
760 // sectors to be read\r
761 //\r
762 SectorCount8 = 0x00;\r
763 //\r
764 // SectorCount is used to record the number of sectors to be read\r
765 //\r
766 SectorCount = 256;\r
767 } else {\r
768\r
769 SectorCount8 = (UINT8) BlocksRemaining;\r
770 SectorCount = (UINT16) BlocksRemaining;\r
771 }\r
772\r
773 //\r
774 // ByteCount is the number of bytes that will be read\r
775 //\r
776 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
777\r
778 //\r
779 // call AtaPioDataIn() to send Read Sector Command and receive data read\r
780 //\r
781 Status = AtaPioDataIn (\r
782 IdeDev,\r
783 Buffer,\r
784 (UINT32) ByteCount,\r
785 AtaCommand,\r
786 Lba3,\r
787 SectorCount8,\r
788 Lba0,\r
789 Lba1,\r
790 Lba2\r
791 );\r
792 if (EFI_ERROR (Status)) {\r
793 return Status;\r
794 }\r
795\r
796 Lba32 += SectorCount;\r
797 Buffer = ((UINT8 *) Buffer + ByteCount);\r
798 BlocksRemaining -= SectorCount;\r
799 }\r
800\r
801 return Status;\r
802}\r
803\r
ed72955c 804/**\r
805 This function is called by the AtaBlkIoWriteBlocks() to perform\r
806 writing onto media in block unit.\r
807\r
808 @param[in] *IdeDev\r
809 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
810 to record all the information of the IDE device.\r
811\r
812 @param[in] *BufferData\r
a98f11c5 813 A pointer to the source buffer for the data.\r
ed72955c 814\r
815 @param[in] Lba\r
a98f11c5 816 The starting logical block address to write onto\r
ed72955c 817 the device media.\r
818\r
819 @param[in] NumberOfBlocks\r
820 The number of transfer data blocks.\r
821\r
822 @return return status is fully dependent on the return status\r
823 of AtaPioDataOut() function.\r
824\r
825**/\r
878ddf1f 826EFI_STATUS\r
827AtaWriteSectors (\r
828 IN IDE_BLK_IO_DEV *IdeDev,\r
829 IN VOID *BufferData,\r
830 IN EFI_LBA Lba,\r
831 IN UINTN NumberOfBlocks\r
832 )\r
878ddf1f 833{\r
834 EFI_STATUS Status;\r
835 UINTN BlocksRemaining;\r
836 UINT32 Lba32;\r
837 UINT8 Lba0;\r
838 UINT8 Lba1;\r
839 UINT8 Lba2;\r
840 UINT8 Lba3;\r
841 UINT8 AtaCommand;\r
842 UINT8 SectorCount8;\r
843 UINT16 SectorCount;\r
844 UINTN ByteCount;\r
845 VOID *Buffer;\r
846\r
847 Buffer = BufferData;\r
848\r
849 //\r
850 // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol\r
851 //\r
852 AtaCommand = WRITE_SECTORS_CMD;\r
853\r
854 BlocksRemaining = NumberOfBlocks;\r
855\r
856 Lba32 = (UINT32) Lba;\r
857\r
858 Status = EFI_SUCCESS;\r
859\r
860 while (BlocksRemaining > 0) {\r
861\r
862 Lba0 = (UINT8) Lba32;\r
863 Lba1 = (UINT8) (Lba32 >> 8);\r
864 Lba2 = (UINT8) (Lba32 >> 16);\r
865 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
866\r
867 if (BlocksRemaining >= 0x100) {\r
a98f11c5 868\r
878ddf1f 869 //\r
870 // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors\r
871 // to be written\r
872 //\r
873 SectorCount8 = 0x00;\r
874 //\r
875 // SectorCount is used to record the number of sectors to be written\r
876 //\r
877 SectorCount = 256;\r
878 } else {\r
879\r
880 SectorCount8 = (UINT8) BlocksRemaining;\r
881 SectorCount = (UINT16) BlocksRemaining;\r
882 }\r
883\r
884 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
885\r
886 Status = AtaPioDataOut (\r
887 IdeDev,\r
888 Buffer,\r
889 (UINT32) ByteCount,\r
890 AtaCommand,\r
891 Lba3,\r
892 SectorCount8,\r
893 Lba0,\r
894 Lba1,\r
895 Lba2\r
896 );\r
897 if (EFI_ERROR (Status)) {\r
898 return Status;\r
899 }\r
900\r
901 Lba32 += SectorCount;\r
902 Buffer = ((UINT8 *) Buffer + ByteCount);\r
903 BlocksRemaining -= SectorCount;\r
904 }\r
905\r
906 return Status;\r
907}\r
908\r
ed72955c 909/**\r
910 This function is used to implement the Soft Reset on the specified\r
a98f11c5 911 device. But, the ATA Soft Reset mechanism is so strong a reset method\r
912 that it will force resetting on both devices connected to the\r
ed72955c 913 same cable.\r
914\r
915 It is called by IdeBlkIoReset(), a interface function of Block\r
916 I/O protocol.\r
917\r
918 This function can also be used by the ATAPI device to perform reset when\r
919 ATAPI Reset command is failed.\r
920\r
921 @param[in] *IdeDev\r
922 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
923 to record all the information of the IDE device.\r
924\r
925 @retval EFI_SUCCESS Soft reset completes successfully.\r
926 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
927\r
928 @note\r
929 The registers initial values after ATA soft reset are different\r
930 to the ATA device and ATAPI device.\r
931\r
932**/\r
878ddf1f 933EFI_STATUS\r
934AtaSoftReset (\r
935 IN IDE_BLK_IO_DEV *IdeDev\r
936 )\r
878ddf1f 937{\r
938\r
939 UINT8 DeviceControl;\r
940\r
941 DeviceControl = 0;\r
942 //\r
943 // set SRST bit to initiate soft reset\r
944 //\r
945 DeviceControl |= SRST;\r
946\r
947 //\r
948 // disable Interrupt\r
949 //\r
950 DeviceControl |= bit1;\r
951\r
952 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
953\r
a98f11c5 954 //\r
955 // SRST should assert for at least 5 us, we use 10 us for\r
956 // better compatibility\r
957 //\r
878ddf1f 958 gBS->Stall (10);\r
959\r
960 //\r
961 // Enable interrupt to support UDMA, and clear SRST bit\r
962 //\r
963 DeviceControl = 0;\r
964 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
965\r
a98f11c5 966 //\r
967 // Wait for at least 2 ms to check BSY status, we use 10 ms\r
968 // for better compatibility\r
969 //\r
970 gBS->Stall(10000);\r
878ddf1f 971 //\r
972 // slave device needs at most 31s to clear BSY\r
973 //\r
974 if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {\r
975 return EFI_DEVICE_ERROR;\r
976 }\r
977\r
978 return EFI_SUCCESS;\r
979}\r
980\r
ed72955c 981/**\r
982 This function is the ATA implementation for ReadBlocks in the\r
983 Block I/O Protocol interface.\r
878ddf1f 984\r
ed72955c 985 @param[in] *IdeBlkIoDevice\r
986 Indicates the calling context.\r
878ddf1f 987\r
ed72955c 988 @param[in] MediaId\r
989 The media id that the read request is for.\r
878ddf1f 990\r
ed72955c 991 @param[in] LBA\r
a98f11c5 992 The starting logical block address to read from\r
ed72955c 993 on the device.\r
878ddf1f 994\r
ed72955c 995 @param[in] BufferSize\r
996 The size of the Buffer in bytes. This must be a\r
997 multiple of the intrinsic block size of the device.\r
878ddf1f 998\r
ed72955c 999 @param[out] *Buffer\r
a98f11c5 1000 A pointer to the destination buffer for the data.\r
ed72955c 1001 The caller is responsible for either having implicit\r
1002 or explicit ownership of the memory that data is read into.\r
878ddf1f 1003\r
ed72955c 1004 @retval EFI_SUCCESS Read Blocks successfully.\r
1005 @retval EFI_DEVICE_ERROR Read Blocks failed.\r
1006 @retval EFI_NO_MEDIA There is no media in the device.\r
1007 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
a98f11c5 1008\r
ed72955c 1009 @retval EFI_BAD_BUFFER_SIZE\r
1010 The BufferSize parameter is not a multiple of the\r
1011 intrinsic block size of the device.\r
a98f11c5 1012\r
ed72955c 1013 @retval EFI_INVALID_PARAMETER\r
1014 The read request contains LBAs that are not valid,\r
1015 or the data buffer is not valid.\r
878ddf1f 1016\r
ed72955c 1017 @note\r
1018 If Read Block error because of device error, this function will call\r
1019 AtaSoftReset() function to reset device.\r
878ddf1f 1020\r
ed72955c 1021**/\r
1022EFI_STATUS\r
1023AtaBlkIoReadBlocks (\r
1024 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
1025 IN UINT32 MediaId,\r
1026 IN EFI_LBA LBA,\r
1027 IN UINTN BufferSize,\r
1028 OUT VOID *Buffer\r
1029 )\r
878ddf1f 1030{\r
1031 EFI_BLOCK_IO_MEDIA *Media;\r
1032 UINTN BlockSize;\r
1033 UINTN NumberOfBlocks;\r
1034 EFI_STATUS Status;\r
1035\r
1036 if (Buffer == NULL) {\r
1037 return EFI_INVALID_PARAMETER;\r
1038 }\r
1039\r
1040 if (BufferSize == 0) {\r
1041 return EFI_SUCCESS;\r
1042 }\r
1043\r
1044 Status = EFI_SUCCESS;\r
1045\r
1046 //\r
1047 // Get the intrinsic block size\r
1048 //\r
1049 Media = IdeBlkIoDevice->BlkIo.Media;\r
1050 BlockSize = Media->BlockSize;\r
1051\r
1052 NumberOfBlocks = BufferSize / BlockSize;\r
1053\r
1054 if (MediaId != Media->MediaId) {\r
1055 return EFI_MEDIA_CHANGED;\r
1056 }\r
1057\r
1058 if (BufferSize % BlockSize != 0) {\r
1059 return EFI_BAD_BUFFER_SIZE;\r
1060 }\r
1061\r
1062 if (!(Media->MediaPresent)) {\r
1063 return EFI_NO_MEDIA;\r
1064 }\r
1065\r
1066 if (LBA > Media->LastBlock) {\r
1067 return EFI_INVALID_PARAMETER;\r
1068 }\r
1069\r
1070 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
1071 return EFI_INVALID_PARAMETER;\r
1072 }\r
1073\r
1074 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
1075 return EFI_INVALID_PARAMETER;\r
1076 }\r
1077\r
bc4e770c 1078 Status = EFI_SUCCESS;\r
878ddf1f 1079 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1080 //\r
1081 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism\r
1082 //\r
bc4e770c 1083 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
1084 Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1085 } else {\r
878ddf1f 1086 Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1087 }\r
1088 } else {\r
1089 //\r
1090 // For ATA-3 compatible device, use ATA-3 read block mechanism\r
878ddf1f 1091 //\r
bc4e770c 1092 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
1093 Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1094 } else {\r
878ddf1f 1095 Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1096 }\r
1097 }\r
1098\r
1099 if (EFI_ERROR (Status)) {\r
1100 AtaSoftReset (IdeBlkIoDevice);\r
1101 return EFI_DEVICE_ERROR;\r
1102 }\r
1103\r
1104 return EFI_SUCCESS;\r
1105\r
1106}\r
1107\r
ed72955c 1108/**\r
1109 This function is the ATA implementation for WriteBlocks in the\r
1110 Block I/O Protocol interface.\r
1111\r
1112 @param[in] *IdeBlkIoDevice\r
1113 Indicates the calling context.\r
1114\r
1115 @param[in] MediaId\r
1116 The media id that the write request is for.\r
1117\r
1118 @param[in] LBA\r
a98f11c5 1119 The starting logical block address to write onto\r
ed72955c 1120 the device.\r
1121\r
1122 @param[in] BufferSize\r
1123 The size of the Buffer in bytes. This must be a\r
1124 multiple of the intrinsic block size of the device.\r
1125\r
1126 @param[out] *Buffer\r
a98f11c5 1127 A pointer to the source buffer for the data.\r
ed72955c 1128 The caller is responsible for either having implicit\r
a98f11c5 1129 or explicit ownership of the memory that data is\r
ed72955c 1130 written from.\r
1131\r
1132 @retval EFI_SUCCESS Write Blocks successfully.\r
1133 @retval EFI_DEVICE_ERROR Write Blocks failed.\r
1134 @retval EFI_NO_MEDIA There is no media in the device.\r
1135 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
a98f11c5 1136\r
ed72955c 1137 @retval EFI_BAD_BUFFER_SIZE\r
1138 The BufferSize parameter is not a multiple of the\r
1139 intrinsic block size of the device.\r
a98f11c5 1140\r
ed72955c 1141 @retval EFI_INVALID_PARAMETER\r
1142 The write request contains LBAs that are not valid,\r
1143 or the data buffer is not valid.\r
1144\r
1145 @note\r
1146 If Write Block error because of device error, this function will call\r
1147 AtaSoftReset() function to reset device.\r
1148\r
1149**/\r
878ddf1f 1150EFI_STATUS\r
1151AtaBlkIoWriteBlocks (\r
1152 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
1153 IN UINT32 MediaId,\r
1154 IN EFI_LBA LBA,\r
1155 IN UINTN BufferSize,\r
1156 OUT VOID *Buffer\r
1157 )\r
878ddf1f 1158{\r
1159\r
1160 EFI_BLOCK_IO_MEDIA *Media;\r
1161 UINTN BlockSize;\r
1162 UINTN NumberOfBlocks;\r
1163 EFI_STATUS Status;\r
1164\r
1165 if (Buffer == NULL) {\r
1166 return EFI_INVALID_PARAMETER;\r
1167 }\r
1168\r
1169 if (BufferSize == 0) {\r
1170 return EFI_SUCCESS;\r
1171 }\r
1172\r
1173 Status = EFI_SUCCESS;\r
1174\r
1175 //\r
1176 // Get the intrinsic block size\r
1177 //\r
1178 Media = IdeBlkIoDevice->BlkIo.Media;\r
1179 BlockSize = Media->BlockSize;\r
1180 NumberOfBlocks = BufferSize / BlockSize;\r
1181\r
1182 if (MediaId != Media->MediaId) {\r
1183 return EFI_MEDIA_CHANGED;\r
1184 }\r
1185\r
1186 if (BufferSize % BlockSize != 0) {\r
1187 return EFI_BAD_BUFFER_SIZE;\r
1188 }\r
1189\r
1190 if (LBA > Media->LastBlock) {\r
1191 return EFI_INVALID_PARAMETER;\r
1192 }\r
1193\r
1194 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
1195 return EFI_INVALID_PARAMETER;\r
1196 }\r
1197\r
1198 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
1199 return EFI_INVALID_PARAMETER;\r
1200 }\r
1201\r
bc4e770c 1202 Status = EFI_SUCCESS;\r
878ddf1f 1203 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1204 //\r
1205 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism\r
1206 //\r
bc4e770c 1207 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
1208 Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1209 } else {\r
878ddf1f 1210 Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1211 }\r
1212 } else {\r
1213 //\r
1214 // For ATA-3 compatible device, use ATA-3 write block mechanism\r
1215 //\r
bc4e770c 1216 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
1217 Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1218 } else {\r
878ddf1f 1219 Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1220 }\r
1221 }\r
1222\r
1223 if (EFI_ERROR (Status)) {\r
1224 AtaSoftReset (IdeBlkIoDevice);\r
1225 return EFI_DEVICE_ERROR;\r
1226 }\r
1227\r
1228 return EFI_SUCCESS;\r
1229}\r
1230\r
ed72955c 1231/**\r
1232 This function is called by the AtaBlkIoReadBlocks() to perform\r
a98f11c5 1233 reading from media in block unit. The function has been enhanced to\r
ed72955c 1234 support >120GB access and transfer at most 65536 blocks per command\r
1235\r
1236 @param[in] *IdeDev\r
1237 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1238 to record all the information of the IDE device.\r
1239\r
a98f11c5 1240 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
1241 @param[in] StartLba The starting logical block address to read from\r
ed72955c 1242 on the device media.\r
1243 @param[in] NumberOfBlocks The number of transfer data blocks.\r
1244\r
1245 @return return status is fully dependent on the return status\r
1246 of AtaPioDataInExt() function.\r
1247\r
1248**/\r
878ddf1f 1249EFI_STATUS\r
1250AtaReadSectorsExt (\r
1251 IN IDE_BLK_IO_DEV *IdeDev,\r
1252 IN VOID *DataBuffer,\r
1253 IN EFI_LBA StartLba,\r
1254 IN UINTN NumberOfBlocks\r
1255 )\r
878ddf1f 1256{\r
1257 EFI_STATUS Status;\r
1258 UINTN BlocksRemaining;\r
1259 EFI_LBA Lba64;\r
1260 UINT8 AtaCommand;\r
1261 UINT16 SectorCount;\r
1262 UINT32 ByteCount;\r
1263 VOID *Buffer;\r
1264\r
1265 //\r
1266 // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol\r
1267 //\r
1268 AtaCommand = READ_SECTORS_EXT_CMD;\r
1269 Buffer = DataBuffer;\r
1270 BlocksRemaining = NumberOfBlocks;\r
1271 Lba64 = StartLba;\r
1272 Status = EFI_SUCCESS;\r
1273\r
1274 while (BlocksRemaining > 0) {\r
1275\r
1276 if (BlocksRemaining >= 0x10000) {\r
1277 //\r
1278 // SectorCount is used to record the number of sectors to be read\r
1279 // Max 65536 sectors can be transfered at a time.\r
1280 //\r
1281 SectorCount = 0xffff;\r
1282 } else {\r
1283 SectorCount = (UINT16) BlocksRemaining;\r
1284 }\r
1285\r
1286 //\r
1287 // ByteCount is the number of bytes that will be read\r
1288 //\r
1289 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1290\r
1291 //\r
1292 // call AtaPioDataInExt() to send Read Sector Command and receive data read\r
1293 //\r
1294 Status = AtaPioDataInExt (\r
1295 IdeDev,\r
1296 Buffer,\r
1297 ByteCount,\r
1298 AtaCommand,\r
1299 Lba64,\r
1300 SectorCount\r
1301 );\r
1302 if (EFI_ERROR (Status)) {\r
1303 return Status;\r
1304 }\r
1305\r
1306 Lba64 += SectorCount;\r
1307 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1308 BlocksRemaining -= SectorCount;\r
1309 }\r
1310\r
1311 return Status;\r
1312}\r
1313\r
ed72955c 1314/**\r
1315 This function is called by the AtaBlkIoWriteBlocks() to perform\r
a98f11c5 1316 writing onto media in block unit. The function has been enhanced to\r
ed72955c 1317 support >120GB access and transfer at most 65536 blocks per command\r
1318\r
1319 @param[in] *IdeDev\r
1320 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
1321 to record all the information of the IDE device.\r
1322\r
1323 @param[in] *DataBuffer\r
a98f11c5 1324 A pointer to the source buffer for the data.\r
ed72955c 1325\r
1326 @param[in] Lba\r
a98f11c5 1327 The starting logical block address to write onto\r
ed72955c 1328 the device media.\r
1329\r
1330 @param[in] NumberOfBlocks\r
1331 The number of transfer data blocks.\r
1332\r
1333 @return status is fully dependent on the return status\r
1334 of AtaPioDataOutExt() function.\r
1335\r
1336**/\r
878ddf1f 1337EFI_STATUS\r
1338AtaWriteSectorsExt (\r
1339 IN IDE_BLK_IO_DEV *IdeDev,\r
1340 IN VOID *DataBuffer,\r
1341 IN EFI_LBA StartLba,\r
1342 IN UINTN NumberOfBlocks\r
1343 )\r
878ddf1f 1344{\r
1345 EFI_STATUS Status;\r
1346 EFI_LBA Lba64;\r
1347 UINTN BlocksRemaining;\r
1348 UINT8 AtaCommand;\r
1349 UINT16 SectorCount;\r
1350 UINT32 ByteCount;\r
1351 VOID *Buffer;\r
1352\r
1353 //\r
1354 // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol\r
1355 //\r
1356 AtaCommand = WRITE_SECTORS_EXT_CMD;\r
1357 Lba64 = StartLba;\r
1358 Buffer = DataBuffer;\r
1359 BlocksRemaining = NumberOfBlocks;\r
1360\r
1361 Status = EFI_SUCCESS;\r
1362\r
1363 while (BlocksRemaining > 0) {\r
1364\r
1365 if (BlocksRemaining >= 0x10000) {\r
1366 //\r
1367 // SectorCount is used to record the number of sectors to be written.\r
1368 // Max 65536 sectors can be transfered at a time.\r
1369 //\r
1370 SectorCount = 0xffff;\r
1371 } else {\r
1372 SectorCount = (UINT16) BlocksRemaining;\r
1373 }\r
1374\r
1375 //\r
1376 // ByteCount is the number of bytes that will be written\r
1377 //\r
1378 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1379\r
1380 //\r
1381 // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command\r
1382 //\r
1383 Status = AtaPioDataOutExt (\r
1384 IdeDev,\r
1385 Buffer,\r
1386 ByteCount,\r
1387 AtaCommand,\r
1388 Lba64,\r
1389 SectorCount\r
1390 );\r
1391 if (EFI_ERROR (Status)) {\r
1392 return Status;\r
1393 }\r
1394\r
1395 Lba64 += SectorCount;\r
1396 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1397 BlocksRemaining -= SectorCount;\r
1398 }\r
1399\r
1400 return Status;\r
1401}\r
1402\r
ed72955c 1403/**\r
a98f11c5 1404 This function is used to send out ATA commands conforms to the\r
ed72955c 1405 PIO Data In Protocol, supporting ATA/ATAPI-6 standard\r
1406\r
1407 Comparing with ATA-3 data in protocol, we have two differents here:<BR>\r
1408 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1409 wait will frequently fail... cause writing function return error)\r
1410\r
a98f11c5 1411 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
ed72955c 1412 slow down writing performance by 100 times!)\r
1413\r
1414 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1415 to record all the information of the IDE device.\r
1416\r
1417 @param[in,out] *Buffer buffer contained data transferred from device to host.\r
1418 @param[in] ByteCount data size in byte unit of the buffer.\r
1419 @param[in] AtaCommand value of the Command Register\r
1420 @param[in] StartLba the start LBA of this transaction\r
1421 @param[in] SectorCount the count of sectors to be transfered\r
1422\r
1423 @retval EFI_SUCCESS send out the ATA command and device send required\r
1424 data successfully.\r
a98f11c5 1425\r
ed72955c 1426 @retval EFI_DEVICE_ERROR command sent failed.\r
1427\r
1428**/\r
878ddf1f 1429EFI_STATUS\r
1430AtaPioDataInExt (\r
1431 IN IDE_BLK_IO_DEV *IdeDev,\r
1432 IN OUT VOID *Buffer,\r
1433 IN UINT32 ByteCount,\r
1434 IN UINT8 AtaCommand,\r
1435 IN EFI_LBA StartLba,\r
1436 IN UINT16 SectorCount\r
1437 )\r
878ddf1f 1438{\r
1439 UINT8 DevSel;\r
1440 UINT8 SectorCount8;\r
1441 UINT8 LbaLow;\r
1442 UINT8 LbaMid;\r
1443 UINT8 LbaHigh;\r
1444 UINTN WordCount;\r
1445 UINTN Increment;\r
1446 UINT16 *Buffer16;\r
1447 EFI_STATUS Status;\r
1448\r
1449 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1450 if (EFI_ERROR (Status)) {\r
1451 return EFI_DEVICE_ERROR;\r
1452 }\r
1453\r
1454 //\r
1455 // Select device, set bit6 as 1 to indicate LBA mode is used\r
1456 //\r
1457 DevSel = (UINT8) (IdeDev->Device << 4);\r
1458 DevSel |= 0x40;\r
1459 IDEWritePortB (\r
1460 IdeDev->PciIo,\r
1461 IdeDev->IoPort->Head,\r
1462 DevSel\r
1463 );\r
1464\r
1465 //\r
1466 // Wait for DRDY singnal asserting. ATAPI device needn't wait\r
1467 //\r
1468 if ( (IdeDev->Type == IdeHardDisk) ||\r
1469 (IdeDev->Type == Ide48bitAddressingHardDisk)) {\r
1470\r
1471 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1472 if (EFI_ERROR (Status)) {\r
1473 return EFI_DEVICE_ERROR;\r
1474 }\r
1475 }\r
1476\r
1477 //\r
1478 // Fill feature register if needed\r
1479 //\r
1480 if (AtaCommand == SET_FEATURES_CMD) {\r
1481 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1482 }\r
1483\r
1484 //\r
1485 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1486 //\r
1487 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1488 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1489\r
1490 SectorCount8 = (UINT8) SectorCount;\r
1491 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1492\r
1493 //\r
1494 // Fill the start LBA registers, which are also two-byte FIFO\r
1495 //\r
1496 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1497 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1498 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1499 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1500 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1501 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1502\r
1503 LbaLow = (UINT8) StartLba;\r
1504 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1505 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1506 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1507 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1508 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1509\r
1510 //\r
1511 // Send command via Command Register, invoking the processing of this command\r
1512 //\r
1513 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1514\r
1515 Buffer16 = (UINT16 *) Buffer;\r
1516\r
1517 //\r
1518 // According to PIO data in protocol, host can perform a series of reads to\r
1519 // the data register after each time device set DRQ ready;\r
1520 //\r
a98f11c5 1521\r
878ddf1f 1522 //\r
1523 // 256 words\r
1524 //\r
1525 Increment = 256;\r
1526\r
1527 //\r
1528 // used to record bytes of currently transfered data\r
1529 //\r
1530 WordCount = 0;\r
1531\r
1532 while (WordCount < ByteCount / 2) {\r
1533 //\r
1534 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
1535 //\r
1536 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1537 if (EFI_ERROR (Status)) {\r
1538 return EFI_DEVICE_ERROR;\r
1539 }\r
1540\r
1541 Status = CheckErrorStatus (IdeDev);\r
1542 if (EFI_ERROR (Status)) {\r
1543 return EFI_DEVICE_ERROR;\r
1544 }\r
1545\r
1546 //\r
1547 // Get the byte count for one series of read\r
1548 //\r
1549 if ((WordCount + Increment) > ByteCount / 2) {\r
1550 Increment = ByteCount / 2 - WordCount;\r
1551 }\r
1552\r
1553 IDEReadPortWMultiple (\r
1554 IdeDev->PciIo,\r
1555 IdeDev->IoPort->Data,\r
1556 Increment,\r
1557 Buffer16\r
1558 );\r
1559\r
1560 WordCount += Increment;\r
1561 Buffer16 += Increment;\r
1562\r
1563 }\r
1564\r
1565 return CheckErrorStatus (IdeDev);\r
1566}\r
1567\r
ed72955c 1568/**\r
a98f11c5 1569 This function is used to send out ATA commands conforms to the\r
ed72955c 1570 PIO Data Out Protocol, supporting ATA/ATAPI-6 standard\r
1571\r
1572 Comparing with ATA-3 data out protocol, we have two differents here:<BR>\r
1573 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1574 wait will frequently fail... cause writing function return error)\r
1575\r
a98f11c5 1576 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
ed72955c 1577 slow down writing performance by 100 times!)\r
1578\r
1579 @param[in] *IdeDev\r
1580 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1581 to record all the information of the IDE device.\r
1582\r
1583 @param[in] *Buffer buffer contained data transferred from host to device.\r
1584 @param[in] ByteCount data size in byte unit of the buffer.\r
1585 @param[in] AtaCommand value of the Command Register\r
1586 @param[in] StartLba the start LBA of this transaction\r
1587 @param[in] SectorCount the count of sectors to be transfered\r
1588\r
1589 @retval EFI_SUCCESS send out the ATA command and device receive required\r
1590 data successfully.\r
a98f11c5 1591\r
ed72955c 1592 @retval EFI_DEVICE_ERROR command sent failed.\r
1593\r
1594**/\r
878ddf1f 1595EFI_STATUS\r
1596AtaPioDataOutExt (\r
1597 IN IDE_BLK_IO_DEV *IdeDev,\r
1598 IN VOID *Buffer,\r
1599 IN UINT32 ByteCount,\r
1600 IN UINT8 AtaCommand,\r
1601 IN EFI_LBA StartLba,\r
1602 IN UINT16 SectorCount\r
1603 )\r
878ddf1f 1604{\r
1605 UINT8 DevSel;\r
1606 UINT8 SectorCount8;\r
1607 UINT8 LbaLow;\r
1608 UINT8 LbaMid;\r
1609 UINT8 LbaHigh;\r
1610 UINTN WordCount;\r
1611 UINTN Increment;\r
1612 UINT16 *Buffer16;\r
1613 EFI_STATUS Status;\r
1614\r
1615 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1616 if (EFI_ERROR (Status)) {\r
1617 return EFI_DEVICE_ERROR;\r
1618 }\r
1619\r
1620 //\r
1621 // Select device. Set bit6 as 1 to indicate LBA mode is used\r
1622 //\r
1623 DevSel = (UINT8) (IdeDev->Device << 4);\r
1624 DevSel |= 0x40;\r
1625 IDEWritePortB (\r
1626 IdeDev->PciIo,\r
1627 IdeDev->IoPort->Head,\r
1628 DevSel\r
1629 );\r
1630\r
1631 //\r
1632 // Wait for DRDY singnal asserting.\r
1633 //\r
1634 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1635 if (EFI_ERROR (Status)) {\r
1636 return EFI_DEVICE_ERROR;\r
1637 }\r
a98f11c5 1638\r
878ddf1f 1639 //\r
1640 // Fill feature register if needed\r
1641 //\r
1642 if (AtaCommand == SET_FEATURES_CMD) {\r
1643 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1644 }\r
1645\r
1646 //\r
1647 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1648 //\r
1649 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1650 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1651\r
1652 SectorCount8 = (UINT8) SectorCount;\r
1653 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1654\r
1655 //\r
1656 // Fill the start LBA registers, which are also two-byte FIFO\r
1657 //\r
1658 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1659 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1660 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1661 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1662 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1663 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1664\r
1665 LbaLow = (UINT8) StartLba;\r
1666 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1667 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1668 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1669 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1670 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1671\r
1672 //\r
1673 // Send command via Command Register, invoking the processing of this command\r
1674 //\r
1675 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1676\r
1677 Buffer16 = (UINT16 *) Buffer;\r
1678\r
1679 //\r
1680 // According to PIO Data Out protocol, host can perform a series of writes to\r
1681 // the data register after each time device set DRQ ready;\r
1682 //\r
1683 Increment = 256;\r
1684\r
1685 //\r
1686 // used to record bytes of currently transfered data\r
1687 //\r
1688 WordCount = 0;\r
1689\r
1690 while (WordCount < ByteCount / 2) {\r
1691 //\r
1692 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
1693 //\r
1694 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1695 if (EFI_ERROR (Status)) {\r
1696 return EFI_DEVICE_ERROR;\r
1697 }\r
1698\r
1699 Status = CheckErrorStatus (IdeDev);\r
1700 if (EFI_ERROR (Status)) {\r
1701 return EFI_DEVICE_ERROR;\r
1702 }\r
1703\r
1704 //\r
1705 // Write data into device by one series of writing to data register\r
1706 //\r
1707 if ((WordCount + Increment) > ByteCount / 2) {\r
1708 Increment = ByteCount / 2 - WordCount;\r
1709 }\r
1710\r
1711 IDEWritePortWMultiple (\r
1712 IdeDev->PciIo,\r
1713 IdeDev->IoPort->Data,\r
1714 Increment,\r
1715 Buffer16\r
1716 );\r
1717\r
1718 WordCount += Increment;\r
1719 Buffer16 += Increment;\r
1720\r
1721 }\r
1722 //\r
1723 // while\r
1724 //\r
1725\r
1726 return CheckErrorStatus (IdeDev);\r
1727}\r
1728\r
1729\r
ed72955c 1730/**\r
1731 Enable SMART of the disk if supported\r
1732\r
1733 @param[in] *IdeDev\r
1734 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
1735 to record all the information of the IDE device.\r
1736\r
1737**/\r
878ddf1f 1738VOID\r
1739AtaSMARTSupport (\r
1740 IN IDE_BLK_IO_DEV *IdeDev\r
1741 )\r
878ddf1f 1742{\r
1743 EFI_STATUS Status;\r
1744 BOOLEAN SMARTSupported;\r
1745 UINT8 Device;\r
1746 EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;\r
1747 UINT8 DeviceSelect;\r
1748 UINT8 LBAMid;\r
1749 UINT8 LBAHigh;\r
1750\r
1751 //\r
1752 // Detect if the device supports S.M.A.R.T.\r
1753 //\r
1754 if ((IdeDev->pIdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {\r
1755 //\r
1756 // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)\r
1757 //\r
1758 return ;\r
1759 } else {\r
1760 if ((IdeDev->pIdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
1761 //\r
1762 // S.M.A.R.T is not supported by the device\r
1763 //\r
1764 SMARTSupported = FALSE;\r
1765 } else {\r
1766 SMARTSupported = TRUE;\r
1767 }\r
1768 }\r
1769\r
1770 if (!SMARTSupported) {\r
1771 //\r
1772 // Report nonsupport status code\r
1773 //\r
1774 REPORT_STATUS_CODE (\r
1775 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1776 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
1777 );\r
1778 } else {\r
1779 //\r
1780 // Enable this feature\r
1781 //\r
1782 REPORT_STATUS_CODE (\r
1783 EFI_PROGRESS_CODE,\r
1784 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
1785 );\r
1786\r
1787 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
1788 Status = AtaNonDataCommandIn (\r
1789 IdeDev,\r
1790 ATA_SMART_CMD,\r
1791 Device,\r
1792 ATA_SMART_ENABLE_OPERATION,\r
1793 0,\r
1794 0,\r
1795 ATA_CONSTANT_4F,\r
1796 ATA_CONSTANT_C2\r
1797 );\r
1798 //\r
1799 // Detect if this feature is enabled\r
1800 //\r
1801 TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
1802\r
1803 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
1804 Status = AtaPioDataIn (\r
1805 IdeDev,\r
1806 (VOID *) TmpAtaIdentifyPointer,\r
1807 sizeof (EFI_IDENTIFY_DATA),\r
1808 IDENTIFY_DRIVE_CMD,\r
1809 DeviceSelect,\r
1810 0,\r
1811 0,\r
1812 0,\r
1813 0\r
1814 );\r
1815 if (EFI_ERROR (Status)) {\r
1816 gBS->FreePool (TmpAtaIdentifyPointer);\r
1817 return ;\r
1818 }\r
1819\r
1820 //\r
1821 // Check if the feature is enabled\r
1822 //\r
1823 if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {\r
1824 //\r
1825 // Read status data\r
1826 //\r
1827 AtaNonDataCommandIn (\r
1828 IdeDev,\r
1829 ATA_SMART_CMD,\r
1830 Device,\r
1831 ATA_SMART_RETURN_STATUS,\r
1832 0,\r
1833 0,\r
1834 ATA_CONSTANT_4F,\r
1835 ATA_CONSTANT_C2\r
1836 );\r
1837 LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);\r
1838 LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);\r
1839\r
1840 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
1841 //\r
1842 // The threshold exceeded condition is not detected by the device\r
1843 //\r
1844 REPORT_STATUS_CODE (\r
1845 EFI_PROGRESS_CODE,\r
1846 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
1847 );\r
1848\r
1849 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
1850 //\r
1851 // The threshold exceeded condition is detected by the device\r
1852 //\r
1853 REPORT_STATUS_CODE (\r
1854 EFI_PROGRESS_CODE,\r
1855 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
1856 );\r
1857 }\r
1858\r
1859 } else {\r
1860 //\r
1861 // Report disabled status code\r
1862 //\r
1863 REPORT_STATUS_CODE (\r
1864 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1865 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
1866 );\r
1867 }\r
1868\r
1869 gBS->FreePool (TmpAtaIdentifyPointer);\r
1870 }\r
1871\r
1872 return ;\r
1873}\r
1874\r
ed72955c 1875/**\r
1876 Send ATA Ext command into device with NON_DATA protocol\r
1877\r
1878 @param IdeDev Standard IDE device private data structure\r
1879 @param AtaCommand The ATA command to be sent\r
1880 @param Device The value in Device register\r
1881 @param Feature The value in Feature register\r
1882 @param SectorCount The value in SectorCount register\r
1883 @param LbaAddress The LBA address in 48-bit mode\r
1884\r
1885 @retval EFI_SUCCESS Reading succeed\r
1886 @retval EFI_DEVICE_ERROR Error executing commands on this device\r
1887\r
1888**/\r
878ddf1f 1889EFI_STATUS\r
1890AtaCommandIssueExt (\r
1891 IN IDE_BLK_IO_DEV *IdeDev,\r
1892 IN UINT8 AtaCommand,\r
1893 IN UINT8 Device,\r
1894 IN UINT16 Feature,\r
1895 IN UINT16 SectorCount,\r
1896 IN EFI_LBA LbaAddress\r
1897 )\r
878ddf1f 1898{\r
1899 EFI_STATUS Status;\r
1900 UINT8 SectorCount8;\r
1901 UINT8 Feature8;\r
1902 UINT8 LbaLow;\r
1903 UINT8 LbaMid;\r
1904 UINT8 LbaHigh;\r
1905\r
1906 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1907 if (EFI_ERROR (Status)) {\r
1908 return EFI_DEVICE_ERROR;\r
1909 }\r
1910\r
1911 //\r
1912 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1913 //\r
1914 IDEWritePortB (\r
1915 IdeDev->PciIo,\r
1916 IdeDev->IoPort->Head,\r
1917 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1918 );\r
1919\r
1920 //\r
1921 // ATA commands for ATA device must be issued when DRDY is set\r
1922 //\r
1923 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1924 if (EFI_ERROR (Status)) {\r
1925 return EFI_DEVICE_ERROR;\r
1926 }\r
1927\r
1928 //\r
1929 // Pass parameter into device register block\r
1930 //\r
1931 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
1932\r
1933 //\r
1934 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1935 //\r
1936 Feature8 = (UINT8) (Feature >> 8);\r
1937 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1938\r
1939 Feature8 = (UINT8) Feature;\r
1940 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1941\r
1942 //\r
1943 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1944 //\r
1945 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1946 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1947\r
1948 SectorCount8 = (UINT8) SectorCount;\r
1949 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1950\r
1951 //\r
1952 // Fill the start LBA registers, which are also two-byte FIFO\r
1953 //\r
1954 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);\r
1955 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1956 LbaLow = (UINT8) LbaAddress;\r
1957 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1958\r
1959 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);\r
1960 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1961 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);\r
1962 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1963\r
1964 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
1965 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1966 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
1967 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1968\r
1969 //\r
1970 // Work around for Segate 160G disk writing\r
1971 //\r
1972 gBS->Stall (1800);\r
1973\r
1974 //\r
1975 // Send command via Command Register\r
1976 //\r
1977 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1978\r
1979 //\r
1980 // Stall at least 400ns\r
1981 //\r
1982 gBS->Stall (100);\r
1983\r
1984 return EFI_SUCCESS;\r
1985}\r
1986\r
ed72955c 1987/**\r
1988 Send ATA Ext command into device with NON_DATA protocol\r
1989\r
1990 @param IdeDev Standard IDE device private data structure\r
1991 @param AtaCommand The ATA command to be sent\r
1992 @param Device The value in Device register\r
1993 @param Feature The value in Feature register\r
1994 @param SectorCount The value in SectorCount register\r
1995 @param LbaAddress The LBA address in 48-bit mode\r
1996\r
1997 @retval EFI_SUCCESS Reading succeed\r
1998 @retval EFI_DEVICE_ERROR Error executing commands on this device\r
1999\r
2000**/\r
878ddf1f 2001EFI_STATUS\r
2002AtaCommandIssue (\r
2003 IN IDE_BLK_IO_DEV *IdeDev,\r
2004 IN UINT8 AtaCommand,\r
2005 IN UINT8 Device,\r
2006 IN UINT16 Feature,\r
2007 IN UINT16 SectorCount,\r
2008 IN EFI_LBA LbaAddress\r
2009 )\r
878ddf1f 2010{\r
2011 EFI_STATUS Status;\r
2012 UINT8 SectorCount8;\r
2013 UINT8 Feature8;\r
2014 UINT8 Lba0;\r
2015 UINT8 Lba1;\r
2016 UINT8 Lba2;\r
2017 UINT8 Lba3;\r
2018\r
2019 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2020 if (EFI_ERROR (Status)) {\r
2021 return EFI_DEVICE_ERROR;\r
2022 }\r
2023\r
2024 //\r
2025 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
2026 //\r
2027 IDEWritePortB (\r
2028 IdeDev->PciIo,\r
2029 IdeDev->IoPort->Head,\r
2030 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
2031 );\r
2032\r
2033 //\r
2034 // ATA commands for ATA device must be issued when DRDY is set\r
2035 //\r
2036 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2037 if (EFI_ERROR (Status)) {\r
2038 return EFI_DEVICE_ERROR;\r
2039 }\r
2040\r
2041 Lba0 = (UINT8) LbaAddress;\r
2042 Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);\r
2043 Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);\r
2044 Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);\r
1cc8ee78 2045 Device = (UINT8) (Device | Lba3);\r
878ddf1f 2046\r
2047 //\r
2048 // Pass parameter into device register block\r
2049 //\r
2050 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2051\r
2052 //\r
2053 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
2054 //\r
2055 Feature8 = (UINT8) Feature;\r
2056 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
2057\r
2058 //\r
2059 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
2060 //\r
2061 SectorCount8 = (UINT8) SectorCount;\r
2062 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2063\r
2064 //\r
2065 // Fill the start LBA registers, which are also two-byte FIFO\r
2066 //\r
a98f11c5 2067\r
878ddf1f 2068 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);\r
2069 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);\r
2070 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);\r
2071\r
2072 //\r
2073 // Send command via Command Register\r
2074 //\r
2075 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2076\r
2077 //\r
2078 // Stall at least 400ns\r
2079 //\r
2080 gBS->Stall (100);\r
2081\r
2082 return EFI_SUCCESS;\r
2083}\r
2084\r
ed72955c 2085/**\r
2086 This function is called by the AtaBlkIoReadBlocks() to perform\r
a98f11c5 2087 reading from media in block unit. The function has been enhanced to\r
ed72955c 2088 support >120GB access and transfer at most 65536 blocks per command\r
2089\r
2090 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2091 to record all the information of the IDE device.\r
2092\r
a98f11c5 2093 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
ed72955c 2094\r
a98f11c5 2095 @param[in] StartLba The starting logical block address to read from\r
ed72955c 2096 on the device media.\r
2097\r
2098 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2099\r
2100 @return The device status of UDMA operation. If the operation is\r
2101 successful, return EFI_SUCCESS.\r
2102\r
2103 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2104 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2105 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2106 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2107**/\r
878ddf1f 2108EFI_STATUS\r
2109AtaUdmaReadExt (\r
2110 IN IDE_BLK_IO_DEV *IdeDev,\r
2111 IN VOID *DataBuffer,\r
2112 IN EFI_LBA StartLba,\r
2113 IN UINTN NumberOfBlocks\r
2114 )\r
878ddf1f 2115{\r
bc4e770c 2116 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);\r
2117}\r
2118\r
2119/**\r
2120 This function is called by the AtaBlkIoReadBlocks() to perform\r
2121 reading from media in block unit. The function has been enhanced to\r
2122 support >120GB access and transfer at most 65536 blocks per command\r
2123\r
2124 @param[in] *IdeDev\r
2125 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2126 to record all the information of the IDE device.\r
2127\r
2128 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
2129 @param[in] StartLba The starting logical block address to read from\r
2130 on the device media.\r
2131 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2132\r
2133 @return The device status of UDMA operation. If the operation is\r
2134 successful, return EFI_SUCCESS.\r
2135\r
2136 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2137 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2138 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2139 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2140**/\r
2141EFI_STATUS\r
2142AtaUdmaRead (\r
2143 IN IDE_BLK_IO_DEV *IdeDev,\r
2144 IN VOID *DataBuffer,\r
2145 IN EFI_LBA StartLba,\r
2146 IN UINTN NumberOfBlocks\r
2147 )\r
2148{\r
2149 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);\r
2150}\r
2151\r
2152/**\r
2153 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2154 writing to media in block unit. The function has been enhanced to\r
2155 support >120GB access and transfer at most 65536 blocks per command\r
2156\r
2157 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2158 to record all the information of the IDE device.\r
2159\r
2160 @param[in] *DataBuffer A pointer to the source buffer for the data.\r
2161\r
2162 @param[in] StartLba The starting logical block address to write to\r
2163 on the device media.\r
2164\r
2165 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2166\r
2167 @return The device status of UDMA operation. If the operation is\r
2168 successful, return EFI_SUCCESS.\r
2169\r
2170 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2171 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2172 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2173**/\r
2174EFI_STATUS\r
2175AtaUdmaWriteExt (\r
2176 IN IDE_BLK_IO_DEV *IdeDev,\r
2177 IN VOID *DataBuffer,\r
2178 IN EFI_LBA StartLba,\r
2179 IN UINTN NumberOfBlocks\r
2180 )\r
2181{\r
2182 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);\r
2183}\r
2184\r
2185/**\r
2186 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2187 writing to media in block unit. The function has been enhanced to\r
2188 support >120GB access and transfer at most 65536 blocks per command\r
2189\r
2190 @param[in] *IdeDev\r
2191 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2192 to record all the information of the IDE device.\r
2193\r
2194 @param[in] *DataBuffer\r
2195 A pointer to the source buffer for the data.\r
2196\r
2197 @param[in] StartLba\r
2198 The starting logical block address to write to\r
2199 on the device media.\r
2200\r
2201 @param[in] NumberOfBlocks\r
2202 The number of transfer data blocks.\r
2203\r
2204 @return The device status of UDMA operation. If the operation is\r
2205 successful, return EFI_SUCCESS.\r
2206\r
2207 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2208 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2209 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2210**/\r
2211EFI_STATUS\r
2212AtaUdmaWrite (\r
2213 IN IDE_BLK_IO_DEV *IdeDev,\r
2214 IN VOID *DataBuffer,\r
2215 IN EFI_LBA StartLba,\r
2216 IN UINTN NumberOfBlocks\r
2217 )\r
2218{\r
2219 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);\r
2220}\r
2221\r
2222/**\r
2223 Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
2224 \r
2225 @param[in] *IdeDev\r
2226 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2227 to record all the information of the IDE device.\r
2228\r
2229 @param[in] *DataBuffer\r
2230 A pointer to the source buffer for the data.\r
2231\r
2232 @param[in] StartLba\r
2233 The starting logical block address to write to\r
2234 on the device media.\r
2235\r
2236 @param[in] NumberOfBlocks\r
2237 The number of transfer data blocks.\r
2238 \r
2239 @param[in] UdmaOp\r
2240 The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,\r
2241 AtaUdmaWriteOp, AtaUdmaWriteExOp\r
2242\r
2243 @return The device status of UDMA operation. If the operation is\r
2244 successful, return EFI_SUCCESS.\r
2245\r
2246**/\r
2247EFI_STATUS\r
2248DoAtaUdma (\r
2249 IN IDE_BLK_IO_DEV *IdeDev,\r
2250 IN VOID *DataBuffer,\r
2251 IN EFI_LBA StartLba,\r
2252 IN UINTN NumberOfBlocks,\r
2253 IN ATA_UDMA_OPERATION UdmaOp\r
2254 )\r
2255{\r
2256 IDE_DMA_PRD *PrdAddr;\r
2257 IDE_DMA_PRD *UsedPrdAddr;\r
2258 IDE_DMA_PRD *TempPrdAddr;\r
2259 UINT8 RegisterValue;\r
2260 UINT8 Device;\r
2261 UINT64 IoPortForBmic;\r
2262 UINT64 IoPortForBmis;\r
2263 UINT64 IoPortForBmid;\r
2264 EFI_STATUS Status;\r
2265 UINTN PrdTableNum;\r
2266 UINTN ByteCount;\r
2267 UINTN ByteAvailable;\r
2268 UINT8 *PrdBuffer;\r
2269 UINTN RemainBlockNum;\r
2270 UINT8 DeviceControl;\r
2271 UINT32 Count;\r
2272 UINTN PageCount;\r
2273 VOID *Map;\r
2274 VOID *MemPage;\r
2275 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
2276 UINTN MaxDmaCommandSectors;\r
2277 EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;\r
2278 UINT8 AtaCommand;\r
2279\r
2280 switch (UdmaOp) {\r
2281 case AtaUdmaReadOp:\r
2282 MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;\r
2283 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
2284 AtaCommand = READ_DMA_CMD;\r
2285 break;\r
2286 case AtaUdmaReadExtOp:\r
2287 MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;\r
2288 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
2289 AtaCommand = READ_DMA_EXT_CMD;\r
2290 break;\r
2291 case AtaUdmaWriteOp:\r
2292 MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;\r
2293 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
2294 AtaCommand = WRITE_DMA_CMD;\r
2295 break;\r
2296 case AtaUdmaWriteExtOp:\r
2297 MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;\r
2298 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
2299 AtaCommand = WRITE_DMA_EXT_CMD;\r
2300 break;\r
2301 default:\r
2302 return EFI_UNSUPPORTED;\r
2303 break;\r
2304 }\r
2305\r
2306 //\r
2307 // Channel and device differential\r
878ddf1f 2308 //\r
2309 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
2310\r
2311 //\r
2312 // Enable interrupt to support UDMA and Select device\r
2313 //\r
2314 DeviceControl = 0;\r
2315 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2316\r
2317 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2318\r
2319 if (IdePrimary == IdeDev->Channel) {\r
2320 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
2321 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
2322 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
2323 } else {\r
2324 if (IdeSecondary == IdeDev->Channel) {\r
2325 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
2326 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
2327 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
2328 } else {\r
2329 return EFI_UNSUPPORTED;\r
2330 }\r
2331 }\r
2332\r
2333 RemainBlockNum = NumberOfBlocks;\r
2334 while (RemainBlockNum > 0) {\r
2335\r
bc4e770c 2336 if (RemainBlockNum >= MaxDmaCommandSectors) {\r
878ddf1f 2337 //\r
2338 // SectorCount is used to record the number of sectors to be read\r
2339 // Max 65536 sectors can be transfered at a time.\r
2340 //\r
bc4e770c 2341 NumberOfBlocks = MaxDmaCommandSectors;\r
2342 RemainBlockNum -= MaxDmaCommandSectors;\r
878ddf1f 2343 } else {\r
2344 NumberOfBlocks = (UINT16) RemainBlockNum;\r
2345 RemainBlockNum = 0;\r
2346 }\r
2347\r
2348 //\r
2349 // Calculate the number of PRD table to make sure the memory region\r
2350 // not cross 64K boundary\r
2351 //\r
2352 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2353 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
2354\r
2355 //\r
2356 // Build PRD table\r
2357 //\r
a98f11c5 2358 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
aa23173f 2359 Status = IdeDev->PciIo->AllocateBuffer (\r
bc4e770c 2360 IdeDev->PciIo,\r
2361 AllocateAnyPages,\r
2362 EfiBootServicesData,\r
2363 PageCount,\r
2364 &MemPage,\r
2365 0\r
2366 );\r
a98f11c5 2367 if (EFI_ERROR (Status)) {\r
2368 return EFI_OUT_OF_RESOURCES;\r
2369 }\r
2370 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
bc4e770c 2371 \r
a98f11c5 2372 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
878ddf1f 2373 //\r
2374 // To make sure PRD is allocated in one 64K page\r
2375 //\r
2376 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
2377 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
2378 } else {\r
2379 if ((UINTN) PrdAddr & 0x03) {\r
2380 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
2381 } else {\r
2382 UsedPrdAddr = PrdAddr;\r
2383 }\r
2384 }\r
2385\r
2386 //\r
2387 // Build the PRD table\r
2388 //\r
a98f11c5 2389 Status = IdeDev->PciIo->Map (\r
bc4e770c 2390 IdeDev->PciIo, \r
2391 PciIoProtocolOp, \r
2392 DataBuffer, \r
2393 &ByteCount, \r
a98f11c5 2394 &DeviceAddress,\r
2395 &Map\r
2396 );\r
2397 if (EFI_ERROR (Status)) {\r
aa23173f 2398 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2399 return EFI_OUT_OF_RESOURCES;\r
bc4e770c 2400 } \r
a98f11c5 2401 PrdBuffer = (VOID *) ((UINTN) DeviceAddress);\r
878ddf1f 2402 TempPrdAddr = UsedPrdAddr;\r
2403 while (TRUE) {\r
2404\r
2405 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
2406\r
2407 if (ByteCount <= ByteAvailable) {\r
2408 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2409 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
2410 TempPrdAddr->EndOfTable = 0x8000;\r
2411 break;\r
2412 }\r
2413\r
2414 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2415 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
2416\r
2417 ByteCount -= ByteAvailable;\r
2418 PrdBuffer += ByteAvailable;\r
2419 TempPrdAddr++;\r
2420 }\r
a98f11c5 2421\r
878ddf1f 2422 //\r
2423 // Set the base address to BMID register\r
2424 //\r
2425 IdeDev->PciIo->Io.Write (\r
2426 IdeDev->PciIo,\r
2427 EfiPciIoWidthUint32,\r
2428 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2429 IoPortForBmid,\r
2430 1,\r
2431 &UsedPrdAddr\r
2432 );\r
2433\r
2434 //\r
2435 // Set BMIC register to identify the operation direction\r
2436 //\r
2437 IdeDev->PciIo->Io.Read (\r
2438 IdeDev->PciIo,\r
2439 EfiPciIoWidthUint8,\r
2440 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2441 IoPortForBmic,\r
2442 1,\r
2443 &RegisterValue\r
2444 );\r
2445\r
bc4e770c 2446 if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {\r
2447 RegisterValue |= BMIC_nREAD;\r
2448 } else {\r
2449 RegisterValue &= ~((UINT8) BMIC_nREAD);\r
2450 }\r
878ddf1f 2451\r
2452 IdeDev->PciIo->Io.Write (\r
2453 IdeDev->PciIo,\r
2454 EfiPciIoWidthUint8,\r
2455 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2456 IoPortForBmic,\r
2457 1,\r
2458 &RegisterValue\r
2459 );\r
2460\r
2461 //\r
2462 // Read BMIS register and clear ERROR and INTR bit\r
2463 //\r
2464 IdeDev->PciIo->Io.Read (\r
2465 IdeDev->PciIo,\r
2466 EfiPciIoWidthUint8,\r
2467 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2468 IoPortForBmis,\r
2469 1,\r
2470 &RegisterValue\r
2471 );\r
2472\r
bc4e770c 2473 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
878ddf1f 2474\r
2475 IdeDev->PciIo->Io.Write (\r
2476 IdeDev->PciIo,\r
2477 EfiPciIoWidthUint8,\r
2478 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2479 IoPortForBmis,\r
2480 1,\r
2481 &RegisterValue\r
2482 );\r
2483\r
bc4e770c 2484 if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {\r
2485 Status = AtaCommandIssueExt (\r
2486 IdeDev,\r
2487 AtaCommand,\r
2488 Device,\r
2489 0,\r
2490 (UINT16) NumberOfBlocks,\r
2491 StartLba\r
2492 );\r
2493 } else {\r
2494 Status = AtaCommandIssue (\r
2495 IdeDev,\r
2496 AtaCommand,\r
2497 Device,\r
2498 0,\r
2499 (UINT16) NumberOfBlocks,\r
2500 StartLba\r
2501 );\r
2502 }\r
2503\r
878ddf1f 2504 if (EFI_ERROR (Status)) {\r
aa23173f 2505 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2506 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2507 return EFI_DEVICE_ERROR;\r
2508 }\r
2509\r
2510 //\r
2511 // Set START bit of BMIC register\r
2512 //\r
2513 IdeDev->PciIo->Io.Read (\r
2514 IdeDev->PciIo,\r
2515 EfiPciIoWidthUint8,\r
2516 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2517 IoPortForBmic,\r
2518 1,\r
2519 &RegisterValue\r
2520 );\r
2521\r
2522 RegisterValue |= BMIC_START;\r
2523\r
2524 IdeDev->PciIo->Io.Write (\r
2525 IdeDev->PciIo,\r
2526 EfiPciIoWidthUint8,\r
2527 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2528 IoPortForBmic,\r
2529 1,\r
2530 &RegisterValue\r
2531 );\r
2532\r
2533 //\r
2534 // Check the INTERRUPT and ERROR bit of BMIS\r
a98f11c5 2535 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
2536 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
2537 // So set the variable Count to 2000, for about 2 second timeout time.\r
878ddf1f 2538 //\r
a98f11c5 2539 Count = 2000;\r
878ddf1f 2540 while (TRUE) {\r
2541\r
2542 IdeDev->PciIo->Io.Read (\r
2543 IdeDev->PciIo,\r
2544 EfiPciIoWidthUint8,\r
2545 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2546 IoPortForBmis,\r
2547 1,\r
2548 &RegisterValue\r
2549 );\r
a98f11c5 2550 if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
2551 if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
2552 //\r
2553 // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
2554 //\r
2555 IdeDev->PciIo->Io.Read (\r
2556 IdeDev->PciIo,\r
2557 EfiPciIoWidthUint8,\r
2558 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2559 IoPortForBmic,\r
2560 1,\r
2561 &RegisterValue\r
2562 );\r
2563\r
2564 RegisterValue &= ~((UINT8)BMIC_START);\r
2565\r
2566 IdeDev->PciIo->Io.Write (\r
2567 IdeDev->PciIo,\r
2568 EfiPciIoWidthUint8,\r
2569 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2570 IoPortForBmic,\r
2571 1,\r
2572 &RegisterValue\r
2573 );\r
aa23173f 2574 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2575 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2576 return EFI_DEVICE_ERROR;\r
2577 }\r
2578 break;\r
2579 }\r
2580\r
2581 gBS->Stall (1000);\r
a98f11c5 2582 Count --;\r
878ddf1f 2583 }\r
2584\r
aa23173f 2585 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2586 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2587 //\r
a98f11c5 2588 // Read Status Register of IDE device to clear interrupt\r
2589 //\r
2590 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
2591 //\r
2592 // Clear START bit of BMIC register\r
878ddf1f 2593 //\r
2594 IdeDev->PciIo->Io.Read (\r
2595 IdeDev->PciIo,\r
2596 EfiPciIoWidthUint8,\r
2597 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2598 IoPortForBmic,\r
2599 1,\r
2600 &RegisterValue\r
2601 );\r
2602\r
2603 RegisterValue &= ~((UINT8) BMIC_START);\r
2604\r
2605 IdeDev->PciIo->Io.Write (\r
2606 IdeDev->PciIo,\r
2607 EfiPciIoWidthUint8,\r
2608 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2609 IoPortForBmic,\r
2610 1,\r
2611 &RegisterValue\r
2612 );\r
2613\r
2614 if (RegisterValue & BMIS_ERROR) {\r
2615 return EFI_DEVICE_ERROR;\r
2616 }\r
2617\r
2618 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2619 StartLba += NumberOfBlocks;\r
2620 }\r
2621\r
a98f11c5 2622 //\r
2623 // Disable interrupt of Select device\r
2624 //\r
2625 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
2626 DeviceControl |= IEN_L;\r
2627 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2628\r
878ddf1f 2629 return EFI_SUCCESS;\r
bc4e770c 2630}