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