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