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