]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
Make EdkModulePkg pass Intel IPF compiler with /W4 /WX switches, solving warning...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / ata.c
CommitLineData
ed72955c 1/** @file\r
a98f11c5 2 Copyright (c) 2006, Intel Corporation\r
3 All rights reserved. This program and the accompanying materials\r
4 are licensed and made available under the terms and conditions of the BSD License\r
5 which accompanies this distribution. The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.php\r
ed72955c 7\r
a98f11c5 8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
ed72955c 10\r
11 @par Revision Reference:\r
12 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including\r
13 update - ATAIdentity() func\r
14 update - AtaBlockIoReadBlocks() func\r
15 update - AtaBlockIoWriteBlocks() func\r
16 add - AtaAtapi6Identify() func\r
17 add - AtaReadSectorsExt() func\r
18 add - AtaWriteSectorsExt() func\r
19 add - AtaPioDataInExt() func\r
20 add - AtaPioDataOutExt() func\r
21\r
22**/\r
878ddf1f 23\r
24#include "idebus.h"\r
25\r
ed72955c 26/**\r
27 Sends out an ATA Identify Command to the specified device.\r
878ddf1f 28\r
ed72955c 29 This function is called by DiscoverIdeDevice() during its device\r
a98f11c5 30 identification. It sends out the ATA Identify Command to the\r
31 specified device. Only ATA device responses to this command. If\r
32 the command succeeds, it returns the Identify data structure which\r
33 contains information about the device. This function extracts the\r
34 information it needs to fill the IDE_BLK_IO_DEV data structure,\r
ed72955c 35 including device type, media block size, media capacity, and etc.\r
878ddf1f 36\r
ed72955c 37 @param[in] *IdeDev\r
38 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
39 to record all the information of the IDE device.\r
878ddf1f 40\r
ed72955c 41 @retval EFI_SUCCESS Identify ATA device successfully.\r
a98f11c5 42\r
ed72955c 43 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or\r
44 device is not ATA device.\r
878ddf1f 45\r
ed72955c 46 @note\r
47 parameter IdeDev will be updated in this function.\r
878ddf1f 48\r
ed72955c 49**/\r
50EFI_STATUS\r
51ATAIdentify (\r
52 IN IDE_BLK_IO_DEV *IdeDev\r
53 )\r
878ddf1f 54{\r
55 EFI_STATUS Status;\r
56 EFI_IDENTIFY_DATA *AtaIdentifyPointer;\r
57 UINT32 Capacity;\r
58 UINT8 DeviceSelect;\r
59\r
60 //\r
61 // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of\r
62 // the ATA Identify command\r
63 //\r
64 AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
65\r
66 //\r
67 // use ATA PIO Data In protocol to send ATA Identify command\r
68 // and receive data from device\r
69 //\r
70 DeviceSelect = 0;\r
71 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
72 Status = AtaPioDataIn (\r
73 IdeDev,\r
74 (VOID *) AtaIdentifyPointer,\r
75 sizeof (EFI_IDENTIFY_DATA),\r
76 IDENTIFY_DRIVE_CMD,\r
77 DeviceSelect,\r
78 0,\r
79 0,\r
80 0,\r
81 0\r
82 );\r
83 //\r
84 // If ATA Identify command succeeds, then according to the received\r
85 // IDENTIFY data,\r
86 // identify the device type ( ATA or not ).\r
87 // If ATA device, fill the information in IdeDev.\r
88 // If not ATA device, return IDE_DEVICE_ERROR\r
89 //\r
90 if (!EFI_ERROR (Status)) {\r
91\r
92 IdeDev->pIdData = AtaIdentifyPointer;\r
93\r
94 //\r
95 // Print ATA Module Name\r
96 //\r
97 PrintAtaModuleName (IdeDev);\r
98\r
99 //\r
100 // bit 15 of pAtaIdentify->config is used to identify whether device is\r
101 // ATA device or ATAPI device.\r
102 // if 0, means ATA device; if 1, means ATAPI device.\r
103 //\r
104 if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {\r
105 //\r
106 // Detect if support S.M.A.R.T. If yes, enable it as default\r
107 //\r
108 AtaSMARTSupport (IdeDev);\r
109\r
110 //\r
111 // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)\r
112 //\r
113 Status = AtaAtapi6Identify (IdeDev);\r
114 if (!EFI_ERROR (Status)) {\r
115 //\r
116 // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()\r
117 //\r
118 return EFI_SUCCESS;\r
119 }\r
120 //\r
121 // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
122 //\r
123 IdeDev->Type = IdeHardDisk;\r
124\r
125 //\r
126 // Block Media Information:\r
127 // Media->LogicalPartition , Media->WriteCaching will be filled\r
128 // in the DiscoverIdeDevcie() function.\r
129 //\r
130 IdeDev->BlkIo.Media->IoAlign = 4;\r
131 IdeDev->BlkIo.Media->MediaId = 1;\r
132 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
133 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
134 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
135 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
136\r
137 //\r
138 // Calculate device capacity\r
139 //\r
140 Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |\r
141 AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;\r
142 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
143\r
144 return EFI_SUCCESS;\r
145\r
146 }\r
147 }\r
148\r
149 gBS->FreePool (AtaIdentifyPointer);\r
150 //\r
151 // Make sure the pIdData will not be freed again.\r
152 //\r
153 IdeDev->pIdData = NULL;\r
154\r
155 return EFI_DEVICE_ERROR;\r
156}\r
157\r
158\r
ed72955c 159/**\r
160 This function is called by ATAIdentify() to identity whether this disk\r
161 supports ATA/ATAPI6 48bit addressing, ie support >120G capacity\r
878ddf1f 162\r
ed72955c 163 @param[in] *IdeDev\r
164 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
165 to record all the information of the IDE device.\r
166\r
167 @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one\r
168 and 48-bit addressing must be used\r
a98f11c5 169\r
ed72955c 170 @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but\r
171 the capacity is below 120G, 48bit addressing is not\r
172 needed\r
878ddf1f 173\r
ed72955c 174 @note\r
a98f11c5 175 This function must be called after DEVICE_IDENTITY command has been\r
ed72955c 176 successfully returned\r
878ddf1f 177\r
ed72955c 178**/\r
179EFI_STATUS\r
180AtaAtapi6Identify (\r
181 IN IDE_BLK_IO_DEV *IdeDev\r
182 )\r
878ddf1f 183{\r
184 UINT8 Index;\r
185 EFI_LBA TmpLba;\r
186 EFI_LBA Capacity;\r
187 EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;\r
188\r
189 if (IdeDev->pIdData == NULL) {\r
190 return EFI_UNSUPPORTED;\r
191 }\r
192\r
193 Atapi6IdentifyStruct = IdeDev->pIdData;\r
194\r
195 if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & bit10) == 0) {\r
196 //\r
197 // The device dosn't support 48 bit addressing\r
198 //\r
199 return EFI_UNSUPPORTED;\r
200 }\r
201\r
202 //\r
203 // 48 bit address feature set is supported, get maximum capacity\r
204 //\r
205 Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0];\r
206 for (Index = 1; Index < 4; Index++) {\r
207 //\r
208 // Lower byte goes first: word[100] is the lowest word, word[103] is highest\r
209 //\r
210 TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index];\r
211 Capacity |= LShiftU64 (TmpLba, 16 * Index);\r
212 }\r
213\r
214 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {\r
215 //\r
216 // Capacity exceeds 120GB. 48-bit addressing is really needed\r
217 //\r
218 IdeDev->Type = Ide48bitAddressingHardDisk;\r
219\r
220 //\r
221 // Fill block media information:Media->LogicalPartition ,\r
222 // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.\r
223 //\r
224 IdeDev->BlkIo.Media->IoAlign = 4;\r
225 IdeDev->BlkIo.Media->MediaId = 1;\r
226 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
227 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
228 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
229 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
230 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
231\r
232 return EFI_SUCCESS;\r
233 }\r
234\r
235 return EFI_UNSUPPORTED;\r
236}\r
237\r
ed72955c 238/**\r
239 This function is called by ATAIdentify() or ATAPIIdentify()\r
a98f11c5 240 to print device's module name.\r
ed72955c 241\r
242 @param[in] *IdeDev\r
243 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
244 to record all the information of the IDE device.\r
245\r
246**/\r
878ddf1f 247VOID\r
248PrintAtaModuleName (\r
249 IN IDE_BLK_IO_DEV *IdeDev\r
250 )\r
878ddf1f 251{\r
252 if (IdeDev->pIdData == NULL) {\r
253 return ;\r
254 }\r
255\r
256 SwapStringChars (IdeDev->ModelName, IdeDev->pIdData->AtaData.ModelName, 40);\r
257 IdeDev->ModelName[40] = 0x00;\r
258}\r
259\r
ed72955c 260/**\r
a98f11c5 261 This function is used to send out ATA commands conforms to the\r
ed72955c 262 PIO Data In Protocol.\r
263\r
264 @param[in] *IdeDev\r
265 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
266 to record all the information of the IDE device.\r
267\r
268 @param[in] *Buffer\r
269 buffer contained data transferred from device to host.\r
270\r
271 @param[in] ByteCount\r
272 data size in byte unit of the buffer.\r
273\r
274 @param[in] AtaCommand\r
275 value of the Command Register\r
276\r
277 @param[in] Head\r
278 value of the Head/Device Register\r
279\r
280 @param[in] SectorCount\r
281 value of the Sector Count Register\r
282\r
283 @param[in] SectorNumber\r
284 value of the Sector Number Register\r
285\r
286 @param[in] CylinderLsb\r
287 value of the low byte of the Cylinder Register\r
288\r
289 @param[in] CylinderMsb\r
290 value of the high byte of the Cylinder Register\r
291\r
292 @retval EFI_SUCCESS send out the ATA command and device send required\r
293 data successfully.\r
a98f11c5 294\r
ed72955c 295 @retval EFI_DEVICE_ERROR command sent failed.\r
296\r
297**/\r
878ddf1f 298EFI_STATUS\r
299AtaPioDataIn (\r
300 IN IDE_BLK_IO_DEV *IdeDev,\r
301 IN VOID *Buffer,\r
302 IN UINT32 ByteCount,\r
303 IN UINT8 AtaCommand,\r
304 IN UINT8 Head,\r
305 IN UINT8 SectorCount,\r
306 IN UINT8 SectorNumber,\r
307 IN UINT8 CylinderLsb,\r
308 IN UINT8 CylinderMsb\r
309 )\r
878ddf1f 310{\r
311 UINTN WordCount;\r
312 UINTN Increment;\r
313 UINT16 *Buffer16;\r
314 EFI_STATUS Status;\r
315\r
316 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
317 if (EFI_ERROR (Status)) {\r
318 return EFI_DEVICE_ERROR;\r
319 }\r
320\r
321 //\r
322 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
323 // bit6 set means LBA mode\r
324 //\r
325 IDEWritePortB (\r
326 IdeDev->PciIo,\r
327 IdeDev->IoPort->Head,\r
328 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
329 );\r
330\r
331 //\r
332 // All ATAPI device's ATA commands can be issued regardless of the\r
333 // state of the DRDY\r
334 //\r
335 if (IdeDev->Type == IdeHardDisk) {\r
336\r
337 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
338 if (EFI_ERROR (Status)) {\r
339 return EFI_DEVICE_ERROR;\r
340 }\r
341 }\r
342 //\r
343 // set all the command parameters\r
344 // Before write to all the following registers, BSY and DRQ must be 0.\r
345 //\r
346 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
347 if (EFI_ERROR (Status)) {\r
348 return EFI_DEVICE_ERROR;\r
349 }\r
350\r
351 if (AtaCommand == SET_FEATURES_CMD) {\r
352 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
353 }\r
354\r
355 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
356 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
357 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
358 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
359\r
360 //\r
361 // send command via Command Register\r
362 //\r
363 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
364\r
365 Buffer16 = (UINT16 *) Buffer;\r
366\r
367 //\r
368 // According to PIO data in protocol, host can perform a series of reads to\r
369 // the data register after each time device set DRQ ready;\r
370 // The data size of "a series of read" is command specific.\r
371 // For most ATA command, data size received from device will not exceed\r
372 // 1 sector, hence the data size for "a series of read" can be the whole data\r
373 // size of one command request.\r
374 // For ATA command such as Read Sector command, the data size of one ATA\r
375 // command request is often larger than 1 sector, according to the\r
376 // Read Sector command, the data size of "a series of read" is exactly 1\r
377 // sector.\r
378 // Here for simplification reason, we specify the data size for\r
379 // "a series of read" to 1 sector (256 words) if data size of one ATA command\r
380 // request is larger than 256 words.\r
381 //\r
382 Increment = 256;\r
383\r
384 //\r
385 // used to record bytes of currently transfered data\r
386 //\r
387 WordCount = 0;\r
388\r
389 while (WordCount < ByteCount / 2) {\r
390 //\r
391 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
392 //\r
393 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
394 if (EFI_ERROR (Status)) {\r
395 return EFI_DEVICE_ERROR;\r
396 }\r
397\r
398 Status = CheckErrorStatus (IdeDev);\r
399 if (EFI_ERROR (Status)) {\r
400 return EFI_DEVICE_ERROR;\r
401 }\r
402\r
403 //\r
404 // Get the byte count for one series of read\r
405 //\r
406 if ((WordCount + Increment) > ByteCount / 2) {\r
407 Increment = ByteCount / 2 - WordCount;\r
408 }\r
409\r
410 IDEReadPortWMultiple (\r
411 IdeDev->PciIo,\r
412 IdeDev->IoPort->Data,\r
413 Increment,\r
414 Buffer16\r
415 );\r
416\r
417 WordCount += Increment;\r
418 Buffer16 += Increment;\r
419\r
420 }\r
421\r
422 DRQClear (IdeDev, ATATIMEOUT);\r
423\r
424 return CheckErrorStatus (IdeDev);\r
425}\r
426\r
ed72955c 427/**\r
a98f11c5 428 This function is used to send out ATA commands conforms to the\r
ed72955c 429 PIO Data Out Protocol.\r
430\r
431 @param *IdeDev\r
432 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
433 to record all the information of the IDE device.\r
434\r
435 @param *Buffer buffer contained data transferred from host to device.\r
436 @param ByteCount data size in byte unit of the buffer.\r
437 @param AtaCommand value of the Command Register\r
438 @param Head value of the Head/Device Register\r
439 @param SectorCount value of the Sector Count Register\r
440 @param SectorNumber value of the Sector Number Register\r
441 @param CylinderLsb value of the low byte of the Cylinder Register\r
442 @param CylinderMsb value of the high byte of the Cylinder Register\r
443\r
444 @retval EFI_SUCCESS send out the ATA command and device received required\r
445 data successfully.\r
a98f11c5 446\r
ed72955c 447 @retval EFI_DEVICE_ERROR command sent failed.\r
448\r
449**/\r
878ddf1f 450EFI_STATUS\r
451AtaPioDataOut (\r
452 IN IDE_BLK_IO_DEV *IdeDev,\r
453 IN VOID *Buffer,\r
454 IN UINT32 ByteCount,\r
455 IN UINT8 AtaCommand,\r
456 IN UINT8 Head,\r
457 IN UINT8 SectorCount,\r
458 IN UINT8 SectorNumber,\r
459 IN UINT8 CylinderLsb,\r
460 IN UINT8 CylinderMsb\r
461 )\r
878ddf1f 462{\r
463 UINTN WordCount;\r
464 UINTN Increment;\r
465 UINT16 *Buffer16;\r
466 EFI_STATUS Status;\r
467\r
468 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
469 if (EFI_ERROR (Status)) {\r
470 return EFI_DEVICE_ERROR;\r
471 }\r
472\r
473 //\r
474 // select device via Head/Device register.\r
475 // Before write Head/Device register, BSY and DRQ must be 0.\r
476 //\r
477 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
478 if (EFI_ERROR (Status)) {\r
479 return EFI_DEVICE_ERROR;\r
480 }\r
481\r
482 //\r
483 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
484 // bit6 set means LBA mode\r
485 //\r
486 IDEWritePortB (\r
487 IdeDev->PciIo,\r
488 IdeDev->IoPort->Head,\r
489 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
490 );\r
491\r
492 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
493 if (EFI_ERROR (Status)) {\r
494 return EFI_DEVICE_ERROR;\r
495 }\r
496\r
497 //\r
498 // set all the command parameters\r
499 // Before write to all the following registers, BSY and DRQ must be 0.\r
500 //\r
501 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
502 if (EFI_ERROR (Status)) {\r
503 return EFI_DEVICE_ERROR;\r
504 }\r
505\r
506 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
507 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
508 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
509 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
510\r
511 //\r
512 // send command via Command Register\r
513 //\r
514 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
515\r
516 Buffer16 = (UINT16 *) Buffer;\r
517\r
518 //\r
519 // According to PIO data out protocol, host can perform a series of\r
520 // writes to the data register after each time device set DRQ ready;\r
521 // The data size of "a series of read" is command specific.\r
522 // For most ATA command, data size written to device will not exceed 1 sector,\r
523 // hence the data size for "a series of write" can be the data size of one\r
524 // command request.\r
525 // For ATA command such as Write Sector command, the data size of one\r
526 // ATA command request is often larger than 1 sector, according to the\r
527 // Write Sector command, the data size of "a series of read" is exactly\r
528 // 1 sector.\r
529 // Here for simplification reason, we specify the data size for\r
530 // "a series of write" to 1 sector (256 words) if data size of one ATA command\r
531 // request is larger than 256 words.\r
532 //\r
533 Increment = 256;\r
534 WordCount = 0;\r
535\r
536 while (WordCount < ByteCount / 2) {\r
a98f11c5 537\r
878ddf1f 538 //\r
539 // DRQReady2-- read Alternate Status Register to determine the DRQ bit\r
540 // data transfer can be performed only when DRQ is ready.\r
541 //\r
542 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
543 if (EFI_ERROR (Status)) {\r
544 return EFI_DEVICE_ERROR;\r
545 }\r
546\r
547 Status = CheckErrorStatus (IdeDev);\r
548 if (EFI_ERROR (Status)) {\r
549 return EFI_DEVICE_ERROR;\r
550 }\r
551\r
552 //\r
553 // Check the remaining byte count is less than 512 bytes\r
554 //\r
555 if ((WordCount + Increment) > ByteCount / 2) {\r
556 Increment = ByteCount / 2 - WordCount;\r
557 }\r
558 //\r
559 // perform a series of write without check DRQ ready\r
560 //\r
a98f11c5 561\r
878ddf1f 562 IDEWritePortWMultiple (\r
563 IdeDev->PciIo,\r
564 IdeDev->IoPort->Data,\r
565 Increment,\r
566 Buffer16\r
567 );\r
568 WordCount += Increment;\r
569 Buffer16 += Increment;\r
570\r
571 }\r
572\r
573 DRQClear (IdeDev, ATATIMEOUT);\r
574\r
575 return CheckErrorStatus (IdeDev);\r
576}\r
577\r
ed72955c 578/**\r
a98f11c5 579 This function is used to analyze the Status Register and print out\r
ed72955c 580 some debug information and if there is ERR bit set in the Status\r
581 Register, the Error Register's value is also be parsed and print out.\r
582\r
583 @param[in] *IdeDev\r
584 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
585 to record all the information of the IDE device.\r
586\r
587 @retval EFI_SUCCESS No err information in the Status Register.\r
588 @retval EFI_DEVICE_ERROR Any err information in the Status Register.\r
589\r
590**/\r
878ddf1f 591EFI_STATUS\r
592CheckErrorStatus (\r
593 IN IDE_BLK_IO_DEV *IdeDev\r
594 )\r
878ddf1f 595{\r
596 UINT8 StatusRegister;\r
597\r
598//#ifdef EFI_DEBUG\r
599\r
600 UINT8 ErrorRegister;\r
601\r
602//#endif\r
603\r
604 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
605\r
2ce31132 606 DEBUG_CODE_BEGIN ();\r
878ddf1f 607\r
608 if (StatusRegister & DWF) {\r
2ce31132 609 DEBUG (\r
610 (EFI_D_BLKIO,\r
611 "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
612 StatusRegister)\r
613 );\r
614 }\r
878ddf1f 615\r
2ce31132 616 if (StatusRegister & CORR) {\r
617 DEBUG (\r
618 (EFI_D_BLKIO,\r
619 "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
620 StatusRegister)\r
621 );\r
622 }\r
878ddf1f 623\r
2ce31132 624 if (StatusRegister & ERR) {\r
625 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
878ddf1f 626\r
2ce31132 627 if (ErrorRegister & BBK_ERR) {\r
628 DEBUG (\r
629 (EFI_D_BLKIO,\r
630 "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
631 ErrorRegister)\r
632 );\r
633 }\r
878ddf1f 634\r
2ce31132 635 if (ErrorRegister & UNC_ERR) {\r
636 DEBUG (\r
637 (EFI_D_BLKIO,\r
638 "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
639 ErrorRegister)\r
640 );\r
641 }\r
878ddf1f 642\r
2ce31132 643 if (ErrorRegister & MC_ERR) {\r
644 DEBUG (\r
645 (EFI_D_BLKIO,\r
646 "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
647 ErrorRegister)\r
648 );\r
649 }\r
878ddf1f 650\r
2ce31132 651 if (ErrorRegister & ABRT_ERR) {\r
652 DEBUG (\r
653 (EFI_D_BLKIO,\r
654 "CheckErrorStatus()-- %02x : Error : Abort\n",\r
655 ErrorRegister)\r
656 );\r
657 }\r
878ddf1f 658\r
2ce31132 659 if (ErrorRegister & TK0NF_ERR) {\r
660 DEBUG (\r
661 (EFI_D_BLKIO,\r
662 "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
663 ErrorRegister)\r
664 );\r
665 }\r
878ddf1f 666\r
2ce31132 667 if (ErrorRegister & AMNF_ERR) {\r
668 DEBUG (\r
669 (EFI_D_BLKIO,\r
670 "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
671 ErrorRegister)\r
672 );\r
673 }\r
674 }\r
878ddf1f 675\r
2ce31132 676 DEBUG_CODE_END ();\r
878ddf1f 677\r
678 if ((StatusRegister & (ERR | DWF | CORR)) == 0) {\r
679 return EFI_SUCCESS;\r
680 }\r
681\r
682 return EFI_DEVICE_ERROR;\r
683\r
684}\r
685\r
ed72955c 686/**\r
687 This function is called by the AtaBlkIoReadBlocks() to perform\r
688 reading from media in block unit.\r
689\r
690 @param[in] *IdeDev\r
691 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
692 to record all the information of the IDE device.\r
693\r
694 @param[in] *DataBuffer\r
a98f11c5 695 A pointer to the destination buffer for the data.\r
ed72955c 696\r
697 @param[in] Lba\r
a98f11c5 698 The starting logical block address to read from\r
ed72955c 699 on the device media.\r
700\r
701 @param[in] NumberOfBlocks\r
702 The number of transfer data blocks.\r
703\r
704 @return return status is fully dependent on the return status\r
705 of AtaPioDataIn() function.\r
706\r
707**/\r
878ddf1f 708EFI_STATUS\r
709AtaReadSectors (\r
710 IN IDE_BLK_IO_DEV *IdeDev,\r
711 IN VOID *DataBuffer,\r
712 IN EFI_LBA Lba,\r
713 IN UINTN NumberOfBlocks\r
714 )\r
878ddf1f 715{\r
716 EFI_STATUS Status;\r
717 UINTN BlocksRemaining;\r
718 UINT32 Lba32;\r
719 UINT8 Lba0;\r
720 UINT8 Lba1;\r
721 UINT8 Lba2;\r
722 UINT8 Lba3;\r
723 UINT8 AtaCommand;\r
724 UINT8 SectorCount8;\r
725 UINT16 SectorCount;\r
726 UINTN ByteCount;\r
727 VOID *Buffer;\r
728\r
729 Buffer = DataBuffer;\r
730\r
731 //\r
732 // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol\r
733 //\r
734 AtaCommand = READ_SECTORS_CMD;\r
735\r
a98f11c5 736\r
878ddf1f 737 BlocksRemaining = NumberOfBlocks;\r
738\r
739 Lba32 = (UINT32) Lba;\r
740\r
741 Status = EFI_SUCCESS;\r
742\r
743 while (BlocksRemaining > 0) {\r
a98f11c5 744\r
878ddf1f 745 //\r
746 // in ATA-3 spec, LBA is in 28 bit width\r
747 //\r
748 Lba0 = (UINT8) Lba32;\r
749 Lba1 = (UINT8) (Lba32 >> 8);\r
750 Lba2 = (UINT8) (Lba32 >> 16);\r
751 //\r
752 // low 4 bit of Lba3 stands for LBA bit24~bit27.\r
753 //\r
754 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
755\r
756 if (BlocksRemaining >= 0x100) {\r
a98f11c5 757\r
878ddf1f 758 //\r
759 // SectorCount8 is sent to Sector Count register, 0x00 means 256\r
760 // sectors to be read\r
761 //\r
762 SectorCount8 = 0x00;\r
763 //\r
764 // SectorCount is used to record the number of sectors to be read\r
765 //\r
766 SectorCount = 256;\r
767 } else {\r
768\r
769 SectorCount8 = (UINT8) BlocksRemaining;\r
770 SectorCount = (UINT16) BlocksRemaining;\r
771 }\r
772\r
773 //\r
774 // ByteCount is the number of bytes that will be read\r
775 //\r
776 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
777\r
778 //\r
779 // call AtaPioDataIn() to send Read Sector Command and receive data read\r
780 //\r
781 Status = AtaPioDataIn (\r
782 IdeDev,\r
783 Buffer,\r
784 (UINT32) ByteCount,\r
785 AtaCommand,\r
786 Lba3,\r
787 SectorCount8,\r
788 Lba0,\r
789 Lba1,\r
790 Lba2\r
791 );\r
792 if (EFI_ERROR (Status)) {\r
793 return Status;\r
794 }\r
795\r
796 Lba32 += SectorCount;\r
797 Buffer = ((UINT8 *) Buffer + ByteCount);\r
798 BlocksRemaining -= SectorCount;\r
799 }\r
800\r
801 return Status;\r
802}\r
803\r
ed72955c 804/**\r
805 This function is called by the AtaBlkIoWriteBlocks() to perform\r
806 writing onto media in block unit.\r
807\r
808 @param[in] *IdeDev\r
809 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
810 to record all the information of the IDE device.\r
811\r
812 @param[in] *BufferData\r
a98f11c5 813 A pointer to the source buffer for the data.\r
ed72955c 814\r
815 @param[in] Lba\r
a98f11c5 816 The starting logical block address to write onto\r
ed72955c 817 the device media.\r
818\r
819 @param[in] NumberOfBlocks\r
820 The number of transfer data blocks.\r
821\r
822 @return return status is fully dependent on the return status\r
823 of AtaPioDataOut() function.\r
824\r
825**/\r
878ddf1f 826EFI_STATUS\r
827AtaWriteSectors (\r
828 IN IDE_BLK_IO_DEV *IdeDev,\r
829 IN VOID *BufferData,\r
830 IN EFI_LBA Lba,\r
831 IN UINTN NumberOfBlocks\r
832 )\r
878ddf1f 833{\r
834 EFI_STATUS Status;\r
835 UINTN BlocksRemaining;\r
836 UINT32 Lba32;\r
837 UINT8 Lba0;\r
838 UINT8 Lba1;\r
839 UINT8 Lba2;\r
840 UINT8 Lba3;\r
841 UINT8 AtaCommand;\r
842 UINT8 SectorCount8;\r
843 UINT16 SectorCount;\r
844 UINTN ByteCount;\r
845 VOID *Buffer;\r
846\r
847 Buffer = BufferData;\r
848\r
849 //\r
850 // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol\r
851 //\r
852 AtaCommand = WRITE_SECTORS_CMD;\r
853\r
854 BlocksRemaining = NumberOfBlocks;\r
855\r
856 Lba32 = (UINT32) Lba;\r
857\r
858 Status = EFI_SUCCESS;\r
859\r
860 while (BlocksRemaining > 0) {\r
861\r
862 Lba0 = (UINT8) Lba32;\r
863 Lba1 = (UINT8) (Lba32 >> 8);\r
864 Lba2 = (UINT8) (Lba32 >> 16);\r
865 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
866\r
867 if (BlocksRemaining >= 0x100) {\r
a98f11c5 868\r
878ddf1f 869 //\r
870 // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors\r
871 // to be written\r
872 //\r
873 SectorCount8 = 0x00;\r
874 //\r
875 // SectorCount is used to record the number of sectors to be written\r
876 //\r
877 SectorCount = 256;\r
878 } else {\r
879\r
880 SectorCount8 = (UINT8) BlocksRemaining;\r
881 SectorCount = (UINT16) BlocksRemaining;\r
882 }\r
883\r
884 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
885\r
886 Status = AtaPioDataOut (\r
887 IdeDev,\r
888 Buffer,\r
889 (UINT32) ByteCount,\r
890 AtaCommand,\r
891 Lba3,\r
892 SectorCount8,\r
893 Lba0,\r
894 Lba1,\r
895 Lba2\r
896 );\r
897 if (EFI_ERROR (Status)) {\r
898 return Status;\r
899 }\r
900\r
901 Lba32 += SectorCount;\r
902 Buffer = ((UINT8 *) Buffer + ByteCount);\r
903 BlocksRemaining -= SectorCount;\r
904 }\r
905\r
906 return Status;\r
907}\r
908\r
ed72955c 909/**\r
910 This function is used to implement the Soft Reset on the specified\r
a98f11c5 911 device. But, the ATA Soft Reset mechanism is so strong a reset method\r
912 that it will force resetting on both devices connected to the\r
ed72955c 913 same cable.\r
914\r
915 It is called by IdeBlkIoReset(), a interface function of Block\r
916 I/O protocol.\r
917\r
918 This function can also be used by the ATAPI device to perform reset when\r
919 ATAPI Reset command is failed.\r
920\r
921 @param[in] *IdeDev\r
922 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
923 to record all the information of the IDE device.\r
924\r
925 @retval EFI_SUCCESS Soft reset completes successfully.\r
926 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
927\r
928 @note\r
929 The registers initial values after ATA soft reset are different\r
930 to the ATA device and ATAPI device.\r
931\r
932**/\r
878ddf1f 933EFI_STATUS\r
934AtaSoftReset (\r
935 IN IDE_BLK_IO_DEV *IdeDev\r
936 )\r
878ddf1f 937{\r
938\r
939 UINT8 DeviceControl;\r
940\r
941 DeviceControl = 0;\r
942 //\r
943 // set SRST bit to initiate soft reset\r
944 //\r
945 DeviceControl |= SRST;\r
946\r
947 //\r
948 // disable Interrupt\r
949 //\r
950 DeviceControl |= bit1;\r
951\r
952 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
953\r
a98f11c5 954 //\r
955 // SRST should assert for at least 5 us, we use 10 us for\r
956 // better compatibility\r
957 //\r
878ddf1f 958 gBS->Stall (10);\r
959\r
960 //\r
961 // Enable interrupt to support UDMA, and clear SRST bit\r
962 //\r
963 DeviceControl = 0;\r
964 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
965\r
a98f11c5 966 //\r
967 // Wait for at least 2 ms to check BSY status, we use 10 ms\r
968 // for better compatibility\r
969 //\r
970 gBS->Stall(10000);\r
878ddf1f 971 //\r
972 // slave device needs at most 31s to clear BSY\r
973 //\r
974 if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {\r
975 return EFI_DEVICE_ERROR;\r
976 }\r
977\r
978 return EFI_SUCCESS;\r
979}\r
980\r
ed72955c 981/**\r
982 This function is the ATA implementation for ReadBlocks in the\r
983 Block I/O Protocol interface.\r
878ddf1f 984\r
ed72955c 985 @param[in] *IdeBlkIoDevice\r
986 Indicates the calling context.\r
878ddf1f 987\r
ed72955c 988 @param[in] MediaId\r
989 The media id that the read request is for.\r
878ddf1f 990\r
ed72955c 991 @param[in] LBA\r
a98f11c5 992 The starting logical block address to read from\r
ed72955c 993 on the device.\r
878ddf1f 994\r
ed72955c 995 @param[in] BufferSize\r
996 The size of the Buffer in bytes. This must be a\r
997 multiple of the intrinsic block size of the device.\r
878ddf1f 998\r
ed72955c 999 @param[out] *Buffer\r
a98f11c5 1000 A pointer to the destination buffer for the data.\r
ed72955c 1001 The caller is responsible for either having implicit\r
1002 or explicit ownership of the memory that data is read into.\r
878ddf1f 1003\r
ed72955c 1004 @retval EFI_SUCCESS Read Blocks successfully.\r
1005 @retval EFI_DEVICE_ERROR Read Blocks failed.\r
1006 @retval EFI_NO_MEDIA There is no media in the device.\r
1007 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
a98f11c5 1008\r
ed72955c 1009 @retval EFI_BAD_BUFFER_SIZE\r
1010 The BufferSize parameter is not a multiple of the\r
1011 intrinsic block size of the device.\r
a98f11c5 1012\r
ed72955c 1013 @retval EFI_INVALID_PARAMETER\r
1014 The read request contains LBAs that are not valid,\r
1015 or the data buffer is not valid.\r
878ddf1f 1016\r
ed72955c 1017 @note\r
1018 If Read Block error because of device error, this function will call\r
1019 AtaSoftReset() function to reset device.\r
878ddf1f 1020\r
ed72955c 1021**/\r
1022EFI_STATUS\r
1023AtaBlkIoReadBlocks (\r
1024 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
1025 IN UINT32 MediaId,\r
1026 IN EFI_LBA LBA,\r
1027 IN UINTN BufferSize,\r
1028 OUT VOID *Buffer\r
1029 )\r
878ddf1f 1030{\r
1031 EFI_BLOCK_IO_MEDIA *Media;\r
1032 UINTN BlockSize;\r
1033 UINTN NumberOfBlocks;\r
1034 EFI_STATUS Status;\r
1035\r
1036 if (Buffer == NULL) {\r
1037 return EFI_INVALID_PARAMETER;\r
1038 }\r
1039\r
1040 if (BufferSize == 0) {\r
1041 return EFI_SUCCESS;\r
1042 }\r
1043\r
1044 Status = EFI_SUCCESS;\r
1045\r
1046 //\r
1047 // Get the intrinsic block size\r
1048 //\r
1049 Media = IdeBlkIoDevice->BlkIo.Media;\r
1050 BlockSize = Media->BlockSize;\r
1051\r
1052 NumberOfBlocks = BufferSize / BlockSize;\r
1053\r
1054 if (MediaId != Media->MediaId) {\r
1055 return EFI_MEDIA_CHANGED;\r
1056 }\r
1057\r
1058 if (BufferSize % BlockSize != 0) {\r
1059 return EFI_BAD_BUFFER_SIZE;\r
1060 }\r
1061\r
1062 if (!(Media->MediaPresent)) {\r
1063 return EFI_NO_MEDIA;\r
1064 }\r
1065\r
1066 if (LBA > Media->LastBlock) {\r
1067 return EFI_INVALID_PARAMETER;\r
1068 }\r
1069\r
1070 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
1071 return EFI_INVALID_PARAMETER;\r
1072 }\r
1073\r
1074 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
1075 return EFI_INVALID_PARAMETER;\r
1076 }\r
1077\r
1078 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1079 //\r
1080 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism\r
1081 //\r
1082 Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1083 if (EFI_ERROR (Status)) {\r
1084 Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1085 }\r
1086 } else {\r
1087 //\r
1088 // For ATA-3 compatible device, use ATA-3 read block mechanism\r
878ddf1f 1089 //\r
a98f11c5 1090 Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1091 if (EFI_ERROR (Status)) {\r
878ddf1f 1092 Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1093 }\r
1094 }\r
1095\r
1096 if (EFI_ERROR (Status)) {\r
1097 AtaSoftReset (IdeBlkIoDevice);\r
1098 return EFI_DEVICE_ERROR;\r
1099 }\r
1100\r
1101 return EFI_SUCCESS;\r
1102\r
1103}\r
1104\r
ed72955c 1105/**\r
1106 This function is the ATA implementation for WriteBlocks in the\r
1107 Block I/O Protocol interface.\r
1108\r
1109 @param[in] *IdeBlkIoDevice\r
1110 Indicates the calling context.\r
1111\r
1112 @param[in] MediaId\r
1113 The media id that the write request is for.\r
1114\r
1115 @param[in] LBA\r
a98f11c5 1116 The starting logical block address to write onto\r
ed72955c 1117 the device.\r
1118\r
1119 @param[in] BufferSize\r
1120 The size of the Buffer in bytes. This must be a\r
1121 multiple of the intrinsic block size of the device.\r
1122\r
1123 @param[out] *Buffer\r
a98f11c5 1124 A pointer to the source buffer for the data.\r
ed72955c 1125 The caller is responsible for either having implicit\r
a98f11c5 1126 or explicit ownership of the memory that data is\r
ed72955c 1127 written from.\r
1128\r
1129 @retval EFI_SUCCESS Write Blocks successfully.\r
1130 @retval EFI_DEVICE_ERROR Write Blocks failed.\r
1131 @retval EFI_NO_MEDIA There is no media in the device.\r
1132 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
a98f11c5 1133\r
ed72955c 1134 @retval EFI_BAD_BUFFER_SIZE\r
1135 The BufferSize parameter is not a multiple of the\r
1136 intrinsic block size of the device.\r
a98f11c5 1137\r
ed72955c 1138 @retval EFI_INVALID_PARAMETER\r
1139 The write request contains LBAs that are not valid,\r
1140 or the data buffer is not valid.\r
1141\r
1142 @note\r
1143 If Write Block error because of device error, this function will call\r
1144 AtaSoftReset() function to reset device.\r
1145\r
1146**/\r
878ddf1f 1147EFI_STATUS\r
1148AtaBlkIoWriteBlocks (\r
1149 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
1150 IN UINT32 MediaId,\r
1151 IN EFI_LBA LBA,\r
1152 IN UINTN BufferSize,\r
1153 OUT VOID *Buffer\r
1154 )\r
878ddf1f 1155{\r
1156\r
1157 EFI_BLOCK_IO_MEDIA *Media;\r
1158 UINTN BlockSize;\r
1159 UINTN NumberOfBlocks;\r
1160 EFI_STATUS Status;\r
1161\r
1162 if (Buffer == NULL) {\r
1163 return EFI_INVALID_PARAMETER;\r
1164 }\r
1165\r
1166 if (BufferSize == 0) {\r
1167 return EFI_SUCCESS;\r
1168 }\r
1169\r
1170 Status = EFI_SUCCESS;\r
1171\r
1172 //\r
1173 // Get the intrinsic block size\r
1174 //\r
1175 Media = IdeBlkIoDevice->BlkIo.Media;\r
1176 BlockSize = Media->BlockSize;\r
1177 NumberOfBlocks = BufferSize / BlockSize;\r
1178\r
1179 if (MediaId != Media->MediaId) {\r
1180 return EFI_MEDIA_CHANGED;\r
1181 }\r
1182\r
1183 if (BufferSize % BlockSize != 0) {\r
1184 return EFI_BAD_BUFFER_SIZE;\r
1185 }\r
1186\r
1187 if (LBA > Media->LastBlock) {\r
1188 return EFI_INVALID_PARAMETER;\r
1189 }\r
1190\r
1191 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
1192 return EFI_INVALID_PARAMETER;\r
1193 }\r
1194\r
1195 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
1196 return EFI_INVALID_PARAMETER;\r
1197 }\r
1198\r
1199 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
1200 //\r
1201 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism\r
1202 //\r
1203 Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1204 if (EFI_ERROR (Status)) {\r
1205 Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1206 }\r
1207 } else {\r
1208 //\r
1209 // For ATA-3 compatible device, use ATA-3 write block mechanism\r
1210 //\r
1211 Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
a98f11c5 1212 if (EFI_ERROR (Status)) {\r
878ddf1f 1213 Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
1214 }\r
1215 }\r
1216\r
1217 if (EFI_ERROR (Status)) {\r
1218 AtaSoftReset (IdeBlkIoDevice);\r
1219 return EFI_DEVICE_ERROR;\r
1220 }\r
1221\r
1222 return EFI_SUCCESS;\r
1223}\r
1224\r
ed72955c 1225/**\r
1226 This function is called by the AtaBlkIoReadBlocks() to perform\r
a98f11c5 1227 reading from media in block unit. The function has been enhanced to\r
ed72955c 1228 support >120GB access and transfer at most 65536 blocks per command\r
1229\r
1230 @param[in] *IdeDev\r
1231 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1232 to record all the information of the IDE device.\r
1233\r
a98f11c5 1234 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
1235 @param[in] StartLba The starting logical block address to read from\r
ed72955c 1236 on the device media.\r
1237 @param[in] NumberOfBlocks The number of transfer data blocks.\r
1238\r
1239 @return return status is fully dependent on the return status\r
1240 of AtaPioDataInExt() function.\r
1241\r
1242**/\r
878ddf1f 1243EFI_STATUS\r
1244AtaReadSectorsExt (\r
1245 IN IDE_BLK_IO_DEV *IdeDev,\r
1246 IN VOID *DataBuffer,\r
1247 IN EFI_LBA StartLba,\r
1248 IN UINTN NumberOfBlocks\r
1249 )\r
878ddf1f 1250{\r
1251 EFI_STATUS Status;\r
1252 UINTN BlocksRemaining;\r
1253 EFI_LBA Lba64;\r
1254 UINT8 AtaCommand;\r
1255 UINT16 SectorCount;\r
1256 UINT32 ByteCount;\r
1257 VOID *Buffer;\r
1258\r
1259 //\r
1260 // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol\r
1261 //\r
1262 AtaCommand = READ_SECTORS_EXT_CMD;\r
1263 Buffer = DataBuffer;\r
1264 BlocksRemaining = NumberOfBlocks;\r
1265 Lba64 = StartLba;\r
1266 Status = EFI_SUCCESS;\r
1267\r
1268 while (BlocksRemaining > 0) {\r
1269\r
1270 if (BlocksRemaining >= 0x10000) {\r
1271 //\r
1272 // SectorCount is used to record the number of sectors to be read\r
1273 // Max 65536 sectors can be transfered at a time.\r
1274 //\r
1275 SectorCount = 0xffff;\r
1276 } else {\r
1277 SectorCount = (UINT16) BlocksRemaining;\r
1278 }\r
1279\r
1280 //\r
1281 // ByteCount is the number of bytes that will be read\r
1282 //\r
1283 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1284\r
1285 //\r
1286 // call AtaPioDataInExt() to send Read Sector Command and receive data read\r
1287 //\r
1288 Status = AtaPioDataInExt (\r
1289 IdeDev,\r
1290 Buffer,\r
1291 ByteCount,\r
1292 AtaCommand,\r
1293 Lba64,\r
1294 SectorCount\r
1295 );\r
1296 if (EFI_ERROR (Status)) {\r
1297 return Status;\r
1298 }\r
1299\r
1300 Lba64 += SectorCount;\r
1301 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1302 BlocksRemaining -= SectorCount;\r
1303 }\r
1304\r
1305 return Status;\r
1306}\r
1307\r
ed72955c 1308/**\r
1309 This function is called by the AtaBlkIoWriteBlocks() to perform\r
a98f11c5 1310 writing onto media in block unit. The function has been enhanced to\r
ed72955c 1311 support >120GB access and transfer at most 65536 blocks per command\r
1312\r
1313 @param[in] *IdeDev\r
1314 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
1315 to record all the information of the IDE device.\r
1316\r
1317 @param[in] *DataBuffer\r
a98f11c5 1318 A pointer to the source buffer for the data.\r
ed72955c 1319\r
1320 @param[in] Lba\r
a98f11c5 1321 The starting logical block address to write onto\r
ed72955c 1322 the device media.\r
1323\r
1324 @param[in] NumberOfBlocks\r
1325 The number of transfer data blocks.\r
1326\r
1327 @return status is fully dependent on the return status\r
1328 of AtaPioDataOutExt() function.\r
1329\r
1330**/\r
878ddf1f 1331EFI_STATUS\r
1332AtaWriteSectorsExt (\r
1333 IN IDE_BLK_IO_DEV *IdeDev,\r
1334 IN VOID *DataBuffer,\r
1335 IN EFI_LBA StartLba,\r
1336 IN UINTN NumberOfBlocks\r
1337 )\r
878ddf1f 1338{\r
1339 EFI_STATUS Status;\r
1340 EFI_LBA Lba64;\r
1341 UINTN BlocksRemaining;\r
1342 UINT8 AtaCommand;\r
1343 UINT16 SectorCount;\r
1344 UINT32 ByteCount;\r
1345 VOID *Buffer;\r
1346\r
1347 //\r
1348 // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol\r
1349 //\r
1350 AtaCommand = WRITE_SECTORS_EXT_CMD;\r
1351 Lba64 = StartLba;\r
1352 Buffer = DataBuffer;\r
1353 BlocksRemaining = NumberOfBlocks;\r
1354\r
1355 Status = EFI_SUCCESS;\r
1356\r
1357 while (BlocksRemaining > 0) {\r
1358\r
1359 if (BlocksRemaining >= 0x10000) {\r
1360 //\r
1361 // SectorCount is used to record the number of sectors to be written.\r
1362 // Max 65536 sectors can be transfered at a time.\r
1363 //\r
1364 SectorCount = 0xffff;\r
1365 } else {\r
1366 SectorCount = (UINT16) BlocksRemaining;\r
1367 }\r
1368\r
1369 //\r
1370 // ByteCount is the number of bytes that will be written\r
1371 //\r
1372 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1373\r
1374 //\r
1375 // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command\r
1376 //\r
1377 Status = AtaPioDataOutExt (\r
1378 IdeDev,\r
1379 Buffer,\r
1380 ByteCount,\r
1381 AtaCommand,\r
1382 Lba64,\r
1383 SectorCount\r
1384 );\r
1385 if (EFI_ERROR (Status)) {\r
1386 return Status;\r
1387 }\r
1388\r
1389 Lba64 += SectorCount;\r
1390 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1391 BlocksRemaining -= SectorCount;\r
1392 }\r
1393\r
1394 return Status;\r
1395}\r
1396\r
ed72955c 1397/**\r
a98f11c5 1398 This function is used to send out ATA commands conforms to the\r
ed72955c 1399 PIO Data In Protocol, supporting ATA/ATAPI-6 standard\r
1400\r
1401 Comparing with ATA-3 data in protocol, we have two differents here:<BR>\r
1402 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1403 wait will frequently fail... cause writing function return error)\r
1404\r
a98f11c5 1405 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
ed72955c 1406 slow down writing performance by 100 times!)\r
1407\r
1408 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1409 to record all the information of the IDE device.\r
1410\r
1411 @param[in,out] *Buffer buffer contained data transferred from device to host.\r
1412 @param[in] ByteCount data size in byte unit of the buffer.\r
1413 @param[in] AtaCommand value of the Command Register\r
1414 @param[in] StartLba the start LBA of this transaction\r
1415 @param[in] SectorCount the count of sectors to be transfered\r
1416\r
1417 @retval EFI_SUCCESS send out the ATA command and device send required\r
1418 data successfully.\r
a98f11c5 1419\r
ed72955c 1420 @retval EFI_DEVICE_ERROR command sent failed.\r
1421\r
1422**/\r
878ddf1f 1423EFI_STATUS\r
1424AtaPioDataInExt (\r
1425 IN IDE_BLK_IO_DEV *IdeDev,\r
1426 IN OUT VOID *Buffer,\r
1427 IN UINT32 ByteCount,\r
1428 IN UINT8 AtaCommand,\r
1429 IN EFI_LBA StartLba,\r
1430 IN UINT16 SectorCount\r
1431 )\r
878ddf1f 1432{\r
1433 UINT8 DevSel;\r
1434 UINT8 SectorCount8;\r
1435 UINT8 LbaLow;\r
1436 UINT8 LbaMid;\r
1437 UINT8 LbaHigh;\r
1438 UINTN WordCount;\r
1439 UINTN Increment;\r
1440 UINT16 *Buffer16;\r
1441 EFI_STATUS Status;\r
1442\r
1443 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1444 if (EFI_ERROR (Status)) {\r
1445 return EFI_DEVICE_ERROR;\r
1446 }\r
1447\r
1448 //\r
1449 // Select device, set bit6 as 1 to indicate LBA mode is used\r
1450 //\r
1451 DevSel = (UINT8) (IdeDev->Device << 4);\r
1452 DevSel |= 0x40;\r
1453 IDEWritePortB (\r
1454 IdeDev->PciIo,\r
1455 IdeDev->IoPort->Head,\r
1456 DevSel\r
1457 );\r
1458\r
1459 //\r
1460 // Wait for DRDY singnal asserting. ATAPI device needn't wait\r
1461 //\r
1462 if ( (IdeDev->Type == IdeHardDisk) ||\r
1463 (IdeDev->Type == Ide48bitAddressingHardDisk)) {\r
1464\r
1465 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1466 if (EFI_ERROR (Status)) {\r
1467 return EFI_DEVICE_ERROR;\r
1468 }\r
1469 }\r
1470\r
1471 //\r
1472 // Fill feature register if needed\r
1473 //\r
1474 if (AtaCommand == SET_FEATURES_CMD) {\r
1475 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1476 }\r
1477\r
1478 //\r
1479 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1480 //\r
1481 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1482 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1483\r
1484 SectorCount8 = (UINT8) SectorCount;\r
1485 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1486\r
1487 //\r
1488 // Fill the start LBA registers, which are also two-byte FIFO\r
1489 //\r
1490 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1491 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1492 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1493 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1494 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1495 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1496\r
1497 LbaLow = (UINT8) StartLba;\r
1498 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1499 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1500 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1501 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1502 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1503\r
1504 //\r
1505 // Send command via Command Register, invoking the processing of this command\r
1506 //\r
1507 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1508\r
1509 Buffer16 = (UINT16 *) Buffer;\r
1510\r
1511 //\r
1512 // According to PIO data in protocol, host can perform a series of reads to\r
1513 // the data register after each time device set DRQ ready;\r
1514 //\r
a98f11c5 1515\r
878ddf1f 1516 //\r
1517 // 256 words\r
1518 //\r
1519 Increment = 256;\r
1520\r
1521 //\r
1522 // used to record bytes of currently transfered data\r
1523 //\r
1524 WordCount = 0;\r
1525\r
1526 while (WordCount < ByteCount / 2) {\r
1527 //\r
1528 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
1529 //\r
1530 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1531 if (EFI_ERROR (Status)) {\r
1532 return EFI_DEVICE_ERROR;\r
1533 }\r
1534\r
1535 Status = CheckErrorStatus (IdeDev);\r
1536 if (EFI_ERROR (Status)) {\r
1537 return EFI_DEVICE_ERROR;\r
1538 }\r
1539\r
1540 //\r
1541 // Get the byte count for one series of read\r
1542 //\r
1543 if ((WordCount + Increment) > ByteCount / 2) {\r
1544 Increment = ByteCount / 2 - WordCount;\r
1545 }\r
1546\r
1547 IDEReadPortWMultiple (\r
1548 IdeDev->PciIo,\r
1549 IdeDev->IoPort->Data,\r
1550 Increment,\r
1551 Buffer16\r
1552 );\r
1553\r
1554 WordCount += Increment;\r
1555 Buffer16 += Increment;\r
1556\r
1557 }\r
1558\r
1559 return CheckErrorStatus (IdeDev);\r
1560}\r
1561\r
ed72955c 1562/**\r
a98f11c5 1563 This function is used to send out ATA commands conforms to the\r
ed72955c 1564 PIO Data Out Protocol, supporting ATA/ATAPI-6 standard\r
1565\r
1566 Comparing with ATA-3 data out protocol, we have two differents here:<BR>\r
1567 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1568 wait will frequently fail... cause writing function return error)\r
1569\r
a98f11c5 1570 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
ed72955c 1571 slow down writing performance by 100 times!)\r
1572\r
1573 @param[in] *IdeDev\r
1574 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1575 to record all the information of the IDE device.\r
1576\r
1577 @param[in] *Buffer buffer contained data transferred from host to device.\r
1578 @param[in] ByteCount data size in byte unit of the buffer.\r
1579 @param[in] AtaCommand value of the Command Register\r
1580 @param[in] StartLba the start LBA of this transaction\r
1581 @param[in] SectorCount the count of sectors to be transfered\r
1582\r
1583 @retval EFI_SUCCESS send out the ATA command and device receive required\r
1584 data successfully.\r
a98f11c5 1585\r
ed72955c 1586 @retval EFI_DEVICE_ERROR command sent failed.\r
1587\r
1588**/\r
878ddf1f 1589EFI_STATUS\r
1590AtaPioDataOutExt (\r
1591 IN IDE_BLK_IO_DEV *IdeDev,\r
1592 IN VOID *Buffer,\r
1593 IN UINT32 ByteCount,\r
1594 IN UINT8 AtaCommand,\r
1595 IN EFI_LBA StartLba,\r
1596 IN UINT16 SectorCount\r
1597 )\r
878ddf1f 1598{\r
1599 UINT8 DevSel;\r
1600 UINT8 SectorCount8;\r
1601 UINT8 LbaLow;\r
1602 UINT8 LbaMid;\r
1603 UINT8 LbaHigh;\r
1604 UINTN WordCount;\r
1605 UINTN Increment;\r
1606 UINT16 *Buffer16;\r
1607 EFI_STATUS Status;\r
1608\r
1609 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1610 if (EFI_ERROR (Status)) {\r
1611 return EFI_DEVICE_ERROR;\r
1612 }\r
1613\r
1614 //\r
1615 // Select device. Set bit6 as 1 to indicate LBA mode is used\r
1616 //\r
1617 DevSel = (UINT8) (IdeDev->Device << 4);\r
1618 DevSel |= 0x40;\r
1619 IDEWritePortB (\r
1620 IdeDev->PciIo,\r
1621 IdeDev->IoPort->Head,\r
1622 DevSel\r
1623 );\r
1624\r
1625 //\r
1626 // Wait for DRDY singnal asserting.\r
1627 //\r
1628 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1629 if (EFI_ERROR (Status)) {\r
1630 return EFI_DEVICE_ERROR;\r
1631 }\r
a98f11c5 1632\r
878ddf1f 1633 //\r
1634 // Fill feature register if needed\r
1635 //\r
1636 if (AtaCommand == SET_FEATURES_CMD) {\r
1637 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1638 }\r
1639\r
1640 //\r
1641 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1642 //\r
1643 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1644 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1645\r
1646 SectorCount8 = (UINT8) SectorCount;\r
1647 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1648\r
1649 //\r
1650 // Fill the start LBA registers, which are also two-byte FIFO\r
1651 //\r
1652 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1653 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1654 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1655 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1656 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1657 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1658\r
1659 LbaLow = (UINT8) StartLba;\r
1660 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1661 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1662 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1663 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1664 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1665\r
1666 //\r
1667 // Send command via Command Register, invoking the processing of this command\r
1668 //\r
1669 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1670\r
1671 Buffer16 = (UINT16 *) Buffer;\r
1672\r
1673 //\r
1674 // According to PIO Data Out protocol, host can perform a series of writes to\r
1675 // the data register after each time device set DRQ ready;\r
1676 //\r
1677 Increment = 256;\r
1678\r
1679 //\r
1680 // used to record bytes of currently transfered data\r
1681 //\r
1682 WordCount = 0;\r
1683\r
1684 while (WordCount < ByteCount / 2) {\r
1685 //\r
1686 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
1687 //\r
1688 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1689 if (EFI_ERROR (Status)) {\r
1690 return EFI_DEVICE_ERROR;\r
1691 }\r
1692\r
1693 Status = CheckErrorStatus (IdeDev);\r
1694 if (EFI_ERROR (Status)) {\r
1695 return EFI_DEVICE_ERROR;\r
1696 }\r
1697\r
1698 //\r
1699 // Write data into device by one series of writing to data register\r
1700 //\r
1701 if ((WordCount + Increment) > ByteCount / 2) {\r
1702 Increment = ByteCount / 2 - WordCount;\r
1703 }\r
1704\r
1705 IDEWritePortWMultiple (\r
1706 IdeDev->PciIo,\r
1707 IdeDev->IoPort->Data,\r
1708 Increment,\r
1709 Buffer16\r
1710 );\r
1711\r
1712 WordCount += Increment;\r
1713 Buffer16 += Increment;\r
1714\r
1715 }\r
1716 //\r
1717 // while\r
1718 //\r
1719\r
1720 return CheckErrorStatus (IdeDev);\r
1721}\r
1722\r
1723\r
ed72955c 1724/**\r
1725 Enable SMART of the disk if supported\r
1726\r
1727 @param[in] *IdeDev\r
1728 pointer pointing to IDE_BLK_IO_DEV data structure,used\r
1729 to record all the information of the IDE device.\r
1730\r
1731**/\r
878ddf1f 1732VOID\r
1733AtaSMARTSupport (\r
1734 IN IDE_BLK_IO_DEV *IdeDev\r
1735 )\r
878ddf1f 1736{\r
1737 EFI_STATUS Status;\r
1738 BOOLEAN SMARTSupported;\r
1739 UINT8 Device;\r
1740 EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;\r
1741 UINT8 DeviceSelect;\r
1742 UINT8 LBAMid;\r
1743 UINT8 LBAHigh;\r
1744\r
1745 //\r
1746 // Detect if the device supports S.M.A.R.T.\r
1747 //\r
1748 if ((IdeDev->pIdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {\r
1749 //\r
1750 // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)\r
1751 //\r
1752 return ;\r
1753 } else {\r
1754 if ((IdeDev->pIdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
1755 //\r
1756 // S.M.A.R.T is not supported by the device\r
1757 //\r
1758 SMARTSupported = FALSE;\r
1759 } else {\r
1760 SMARTSupported = TRUE;\r
1761 }\r
1762 }\r
1763\r
1764 if (!SMARTSupported) {\r
1765 //\r
1766 // Report nonsupport status code\r
1767 //\r
1768 REPORT_STATUS_CODE (\r
1769 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1770 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
1771 );\r
1772 } else {\r
1773 //\r
1774 // Enable this feature\r
1775 //\r
1776 REPORT_STATUS_CODE (\r
1777 EFI_PROGRESS_CODE,\r
1778 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
1779 );\r
1780\r
1781 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
1782 Status = AtaNonDataCommandIn (\r
1783 IdeDev,\r
1784 ATA_SMART_CMD,\r
1785 Device,\r
1786 ATA_SMART_ENABLE_OPERATION,\r
1787 0,\r
1788 0,\r
1789 ATA_CONSTANT_4F,\r
1790 ATA_CONSTANT_C2\r
1791 );\r
1792 //\r
1793 // Detect if this feature is enabled\r
1794 //\r
1795 TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
1796\r
1797 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
1798 Status = AtaPioDataIn (\r
1799 IdeDev,\r
1800 (VOID *) TmpAtaIdentifyPointer,\r
1801 sizeof (EFI_IDENTIFY_DATA),\r
1802 IDENTIFY_DRIVE_CMD,\r
1803 DeviceSelect,\r
1804 0,\r
1805 0,\r
1806 0,\r
1807 0\r
1808 );\r
1809 if (EFI_ERROR (Status)) {\r
1810 gBS->FreePool (TmpAtaIdentifyPointer);\r
1811 return ;\r
1812 }\r
1813\r
1814 //\r
1815 // Check if the feature is enabled\r
1816 //\r
1817 if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {\r
1818 //\r
1819 // Read status data\r
1820 //\r
1821 AtaNonDataCommandIn (\r
1822 IdeDev,\r
1823 ATA_SMART_CMD,\r
1824 Device,\r
1825 ATA_SMART_RETURN_STATUS,\r
1826 0,\r
1827 0,\r
1828 ATA_CONSTANT_4F,\r
1829 ATA_CONSTANT_C2\r
1830 );\r
1831 LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);\r
1832 LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);\r
1833\r
1834 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
1835 //\r
1836 // The threshold exceeded condition is not detected by the device\r
1837 //\r
1838 REPORT_STATUS_CODE (\r
1839 EFI_PROGRESS_CODE,\r
1840 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
1841 );\r
1842\r
1843 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
1844 //\r
1845 // The threshold exceeded condition is detected by the device\r
1846 //\r
1847 REPORT_STATUS_CODE (\r
1848 EFI_PROGRESS_CODE,\r
1849 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
1850 );\r
1851 }\r
1852\r
1853 } else {\r
1854 //\r
1855 // Report disabled status code\r
1856 //\r
1857 REPORT_STATUS_CODE (\r
1858 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1859 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
1860 );\r
1861 }\r
1862\r
1863 gBS->FreePool (TmpAtaIdentifyPointer);\r
1864 }\r
1865\r
1866 return ;\r
1867}\r
1868\r
ed72955c 1869/**\r
1870 Send ATA Ext command into device with NON_DATA protocol\r
1871\r
1872 @param IdeDev Standard IDE device private data structure\r
1873 @param AtaCommand The ATA command to be sent\r
1874 @param Device The value in Device register\r
1875 @param Feature The value in Feature register\r
1876 @param SectorCount The value in SectorCount register\r
1877 @param LbaAddress The LBA address in 48-bit mode\r
1878\r
1879 @retval EFI_SUCCESS Reading succeed\r
1880 @retval EFI_DEVICE_ERROR Error executing commands on this device\r
1881\r
1882**/\r
878ddf1f 1883EFI_STATUS\r
1884AtaCommandIssueExt (\r
1885 IN IDE_BLK_IO_DEV *IdeDev,\r
1886 IN UINT8 AtaCommand,\r
1887 IN UINT8 Device,\r
1888 IN UINT16 Feature,\r
1889 IN UINT16 SectorCount,\r
1890 IN EFI_LBA LbaAddress\r
1891 )\r
878ddf1f 1892{\r
1893 EFI_STATUS Status;\r
1894 UINT8 SectorCount8;\r
1895 UINT8 Feature8;\r
1896 UINT8 LbaLow;\r
1897 UINT8 LbaMid;\r
1898 UINT8 LbaHigh;\r
1899\r
1900 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1901 if (EFI_ERROR (Status)) {\r
1902 return EFI_DEVICE_ERROR;\r
1903 }\r
1904\r
1905 //\r
1906 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1907 //\r
1908 IDEWritePortB (\r
1909 IdeDev->PciIo,\r
1910 IdeDev->IoPort->Head,\r
1911 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1912 );\r
1913\r
1914 //\r
1915 // ATA commands for ATA device must be issued when DRDY is set\r
1916 //\r
1917 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1918 if (EFI_ERROR (Status)) {\r
1919 return EFI_DEVICE_ERROR;\r
1920 }\r
1921\r
1922 //\r
1923 // Pass parameter into device register block\r
1924 //\r
1925 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
1926\r
1927 //\r
1928 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1929 //\r
1930 Feature8 = (UINT8) (Feature >> 8);\r
1931 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1932\r
1933 Feature8 = (UINT8) Feature;\r
1934 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1935\r
1936 //\r
1937 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1938 //\r
1939 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1940 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1941\r
1942 SectorCount8 = (UINT8) SectorCount;\r
1943 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1944\r
1945 //\r
1946 // Fill the start LBA registers, which are also two-byte FIFO\r
1947 //\r
1948 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);\r
1949 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1950 LbaLow = (UINT8) LbaAddress;\r
1951 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1952\r
1953 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);\r
1954 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1955 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);\r
1956 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1957\r
1958 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
1959 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1960 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
1961 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1962\r
1963 //\r
1964 // Work around for Segate 160G disk writing\r
1965 //\r
1966 gBS->Stall (1800);\r
1967\r
1968 //\r
1969 // Send command via Command Register\r
1970 //\r
1971 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1972\r
1973 //\r
1974 // Stall at least 400ns\r
1975 //\r
1976 gBS->Stall (100);\r
1977\r
1978 return EFI_SUCCESS;\r
1979}\r
1980\r
ed72955c 1981/**\r
1982 Send ATA Ext command into device with NON_DATA protocol\r
1983\r
1984 @param IdeDev Standard IDE device private data structure\r
1985 @param AtaCommand The ATA command to be sent\r
1986 @param Device The value in Device register\r
1987 @param Feature The value in Feature register\r
1988 @param SectorCount The value in SectorCount register\r
1989 @param LbaAddress The LBA address in 48-bit mode\r
1990\r
1991 @retval EFI_SUCCESS Reading succeed\r
1992 @retval EFI_DEVICE_ERROR Error executing commands on this device\r
1993\r
1994**/\r
878ddf1f 1995EFI_STATUS\r
1996AtaCommandIssue (\r
1997 IN IDE_BLK_IO_DEV *IdeDev,\r
1998 IN UINT8 AtaCommand,\r
1999 IN UINT8 Device,\r
2000 IN UINT16 Feature,\r
2001 IN UINT16 SectorCount,\r
2002 IN EFI_LBA LbaAddress\r
2003 )\r
878ddf1f 2004{\r
2005 EFI_STATUS Status;\r
2006 UINT8 SectorCount8;\r
2007 UINT8 Feature8;\r
2008 UINT8 Lba0;\r
2009 UINT8 Lba1;\r
2010 UINT8 Lba2;\r
2011 UINT8 Lba3;\r
2012\r
2013 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2014 if (EFI_ERROR (Status)) {\r
2015 return EFI_DEVICE_ERROR;\r
2016 }\r
2017\r
2018 //\r
2019 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
2020 //\r
2021 IDEWritePortB (\r
2022 IdeDev->PciIo,\r
2023 IdeDev->IoPort->Head,\r
2024 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
2025 );\r
2026\r
2027 //\r
2028 // ATA commands for ATA device must be issued when DRDY is set\r
2029 //\r
2030 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2031 if (EFI_ERROR (Status)) {\r
2032 return EFI_DEVICE_ERROR;\r
2033 }\r
2034\r
2035 Lba0 = (UINT8) LbaAddress;\r
2036 Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);\r
2037 Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);\r
2038 Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);\r
1cc8ee78 2039 Device = (UINT8) (Device | Lba3);\r
878ddf1f 2040\r
2041 //\r
2042 // Pass parameter into device register block\r
2043 //\r
2044 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2045\r
2046 //\r
2047 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
2048 //\r
2049 Feature8 = (UINT8) Feature;\r
2050 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
2051\r
2052 //\r
2053 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
2054 //\r
2055 SectorCount8 = (UINT8) SectorCount;\r
2056 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2057\r
2058 //\r
2059 // Fill the start LBA registers, which are also two-byte FIFO\r
2060 //\r
a98f11c5 2061\r
878ddf1f 2062 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);\r
2063 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);\r
2064 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);\r
2065\r
2066 //\r
2067 // Send command via Command Register\r
2068 //\r
2069 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2070\r
2071 //\r
2072 // Stall at least 400ns\r
2073 //\r
2074 gBS->Stall (100);\r
2075\r
2076 return EFI_SUCCESS;\r
2077}\r
2078\r
ed72955c 2079/**\r
2080 This function is called by the AtaBlkIoReadBlocks() to perform\r
a98f11c5 2081 reading from media in block unit. The function has been enhanced to\r
ed72955c 2082 support >120GB access and transfer at most 65536 blocks per command\r
2083\r
2084 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2085 to record all the information of the IDE device.\r
2086\r
a98f11c5 2087 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
ed72955c 2088\r
a98f11c5 2089 @param[in] StartLba The starting logical block address to read from\r
ed72955c 2090 on the device media.\r
2091\r
2092 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2093\r
2094 @return The device status of UDMA operation. If the operation is\r
2095 successful, return EFI_SUCCESS.\r
2096\r
2097 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2098 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2099 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2100 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2101**/\r
878ddf1f 2102EFI_STATUS\r
2103AtaUdmaReadExt (\r
2104 IN IDE_BLK_IO_DEV *IdeDev,\r
2105 IN VOID *DataBuffer,\r
2106 IN EFI_LBA StartLba,\r
2107 IN UINTN NumberOfBlocks\r
2108 )\r
878ddf1f 2109{\r
a98f11c5 2110 IDE_DMA_PRD *PrdAddr;\r
2111 IDE_DMA_PRD *UsedPrdAddr;\r
2112 IDE_DMA_PRD *TempPrdAddr;\r
2113 UINT8 RegisterValue;\r
2114 UINT8 Device;\r
2115 UINT64 IoPortForBmic;\r
2116 UINT64 IoPortForBmis;\r
2117 UINT64 IoPortForBmid;\r
2118 EFI_STATUS Status;\r
2119 UINTN PrdTableNum;\r
2120 UINTN ByteCount;\r
2121 UINTN ByteAvailable;\r
2122 UINT8 *PrdBuffer;\r
2123 UINTN RemainBlockNum;\r
2124 UINT8 DeviceControl;\r
2125 UINT32 Count;\r
2126 UINTN PageCount;\r
2127 VOID *Map;\r
aa23173f 2128 VOID *MemPage;\r
a98f11c5 2129 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
878ddf1f 2130\r
2131 //\r
2132 // Channel and device differential. Select device.\r
2133 //\r
2134 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
2135\r
2136 //\r
2137 // Enable interrupt to support UDMA and Select device\r
2138 //\r
2139 DeviceControl = 0;\r
2140 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2141\r
2142 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2143\r
2144 if (IdePrimary == IdeDev->Channel) {\r
2145 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
2146 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
2147 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
2148 } else {\r
2149 if (IdeSecondary == IdeDev->Channel) {\r
2150 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
2151 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
2152 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
2153 } else {\r
2154 return EFI_UNSUPPORTED;\r
2155 }\r
2156 }\r
2157\r
2158 RemainBlockNum = NumberOfBlocks;\r
2159 while (RemainBlockNum > 0) {\r
2160\r
2161 if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {\r
2162 //\r
2163 // SectorCount is used to record the number of sectors to be read\r
2164 // Max 65536 sectors can be transfered at a time.\r
2165 //\r
2166 NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;\r
2167 RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;\r
2168 } else {\r
2169 NumberOfBlocks = (UINT16) RemainBlockNum;\r
2170 RemainBlockNum = 0;\r
2171 }\r
2172\r
2173 //\r
2174 // Calculate the number of PRD table to make sure the memory region\r
2175 // not cross 64K boundary\r
2176 //\r
2177 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2178 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
2179\r
2180 //\r
2181 // Build PRD table\r
2182 //\r
a98f11c5 2183 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
aa23173f 2184 Status = IdeDev->PciIo->AllocateBuffer (\r
2185 IdeDev->PciIo,\r
2186 AllocateAnyPages,\r
2187 EfiBootServicesData,\r
2188 PageCount,\r
2189 &MemPage,\r
2190 0\r
2191 );\r
a98f11c5 2192 if (EFI_ERROR (Status)) {\r
2193 return EFI_OUT_OF_RESOURCES;\r
2194 }\r
2195 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
2196\r
2197 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
878ddf1f 2198\r
2199 //\r
2200 // To make sure PRD is allocated in one 64K page\r
2201 //\r
2202 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
2203 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
2204 } else {\r
2205 if ((UINTN) PrdAddr & 0x03) {\r
2206 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
2207 } else {\r
2208 UsedPrdAddr = PrdAddr;\r
2209 }\r
2210 }\r
2211\r
2212 //\r
2213 // Build the PRD table\r
2214 //\r
a98f11c5 2215 Status = IdeDev->PciIo->Map (\r
2216 IdeDev->PciIo,\r
2217 EfiPciIoOperationBusMasterWrite,\r
2218 DataBuffer,\r
2219 &ByteCount,\r
2220 &DeviceAddress,\r
2221 &Map\r
2222 );\r
2223 if (EFI_ERROR (Status)) {\r
aa23173f 2224 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2225 return EFI_OUT_OF_RESOURCES;\r
2226 }\r
2227 PrdBuffer = (VOID *) ((UINTN) DeviceAddress);\r
878ddf1f 2228 TempPrdAddr = UsedPrdAddr;\r
2229 while (TRUE) {\r
2230\r
2231 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
2232\r
2233 if (ByteCount <= ByteAvailable) {\r
2234 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2235 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
2236 TempPrdAddr->EndOfTable = 0x8000;\r
2237 break;\r
2238 }\r
2239\r
2240 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2241 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
2242\r
2243 ByteCount -= ByteAvailable;\r
2244 PrdBuffer += ByteAvailable;\r
2245 TempPrdAddr++;\r
2246 }\r
a98f11c5 2247\r
878ddf1f 2248 //\r
2249 // Set the base address to BMID register\r
2250 //\r
2251 IdeDev->PciIo->Io.Write (\r
2252 IdeDev->PciIo,\r
2253 EfiPciIoWidthUint32,\r
2254 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2255 IoPortForBmid,\r
2256 1,\r
2257 &UsedPrdAddr\r
2258 );\r
2259\r
2260 //\r
2261 // Set BMIC register to identify the operation direction\r
2262 //\r
2263 IdeDev->PciIo->Io.Read (\r
2264 IdeDev->PciIo,\r
2265 EfiPciIoWidthUint8,\r
2266 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2267 IoPortForBmic,\r
2268 1,\r
2269 &RegisterValue\r
2270 );\r
2271\r
2272 RegisterValue |= BMIC_nREAD;\r
2273\r
2274 IdeDev->PciIo->Io.Write (\r
2275 IdeDev->PciIo,\r
2276 EfiPciIoWidthUint8,\r
2277 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2278 IoPortForBmic,\r
2279 1,\r
2280 &RegisterValue\r
2281 );\r
2282\r
2283 //\r
2284 // Read BMIS register and clear ERROR and INTR bit\r
2285 //\r
2286 IdeDev->PciIo->Io.Read (\r
2287 IdeDev->PciIo,\r
2288 EfiPciIoWidthUint8,\r
2289 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2290 IoPortForBmis,\r
2291 1,\r
2292 &RegisterValue\r
2293 );\r
2294\r
2295 RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR;\r
2296\r
2297 IdeDev->PciIo->Io.Write (\r
2298 IdeDev->PciIo,\r
2299 EfiPciIoWidthUint8,\r
2300 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2301 IoPortForBmis,\r
2302 1,\r
2303 &RegisterValue\r
2304 );\r
2305\r
2306 //\r
2307 // Issue READ DMA EXT command\r
2308 //\r
2309 Status = AtaCommandIssueExt (\r
a98f11c5 2310 IdeDev,\r
2311 READ_DMA_EXT_CMD,\r
2312 Device,\r
2313 0,\r
2314 (UINT16) NumberOfBlocks,\r
2315 StartLba\r
2316 );\r
878ddf1f 2317 if (EFI_ERROR (Status)) {\r
aa23173f 2318 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2319 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2320 return EFI_DEVICE_ERROR;\r
2321 }\r
2322\r
2323 //\r
2324 // Set START bit of BMIC register\r
2325 //\r
2326 IdeDev->PciIo->Io.Read (\r
2327 IdeDev->PciIo,\r
2328 EfiPciIoWidthUint8,\r
2329 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2330 IoPortForBmic,\r
2331 1,\r
2332 &RegisterValue\r
2333 );\r
2334\r
2335 RegisterValue |= BMIC_START;\r
2336\r
2337 IdeDev->PciIo->Io.Write (\r
2338 IdeDev->PciIo,\r
2339 EfiPciIoWidthUint8,\r
2340 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2341 IoPortForBmic,\r
2342 1,\r
2343 &RegisterValue\r
2344 );\r
2345\r
2346 //\r
2347 // Check the INTERRUPT and ERROR bit of BMIS\r
a98f11c5 2348 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
2349 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
2350 // So set the variable Count to 2000, for about 2 second timeout time.\r
878ddf1f 2351 //\r
a98f11c5 2352 Count = 2000;\r
878ddf1f 2353 while (TRUE) {\r
2354\r
2355 IdeDev->PciIo->Io.Read (\r
2356 IdeDev->PciIo,\r
2357 EfiPciIoWidthUint8,\r
2358 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2359 IoPortForBmis,\r
2360 1,\r
2361 &RegisterValue\r
2362 );\r
a98f11c5 2363 if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
2364 if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
2365 //\r
2366 // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
2367 //\r
2368 IdeDev->PciIo->Io.Read (\r
2369 IdeDev->PciIo,\r
2370 EfiPciIoWidthUint8,\r
2371 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2372 IoPortForBmic,\r
2373 1,\r
2374 &RegisterValue\r
2375 );\r
2376\r
2377 RegisterValue &= ~((UINT8)BMIC_START);\r
2378\r
2379 IdeDev->PciIo->Io.Write (\r
2380 IdeDev->PciIo,\r
2381 EfiPciIoWidthUint8,\r
2382 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2383 IoPortForBmic,\r
2384 1,\r
2385 &RegisterValue\r
2386 );\r
aa23173f 2387 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2388 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2389 return EFI_DEVICE_ERROR;\r
2390 }\r
2391 break;\r
2392 }\r
2393\r
2394 gBS->Stall (1000);\r
a98f11c5 2395 Count --;\r
878ddf1f 2396 }\r
2397\r
aa23173f 2398 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2399 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2400 //\r
a98f11c5 2401 // Read Status Register of IDE device to clear interrupt\r
2402 //\r
2403 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
2404 //\r
2405 // Clear START bit of BMIC register\r
878ddf1f 2406 //\r
2407 IdeDev->PciIo->Io.Read (\r
2408 IdeDev->PciIo,\r
2409 EfiPciIoWidthUint8,\r
2410 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2411 IoPortForBmic,\r
2412 1,\r
2413 &RegisterValue\r
2414 );\r
2415\r
2416 RegisterValue &= ~((UINT8) BMIC_START);\r
2417\r
2418 IdeDev->PciIo->Io.Write (\r
2419 IdeDev->PciIo,\r
2420 EfiPciIoWidthUint8,\r
2421 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2422 IoPortForBmic,\r
2423 1,\r
2424 &RegisterValue\r
2425 );\r
2426\r
2427 if (RegisterValue & BMIS_ERROR) {\r
2428 return EFI_DEVICE_ERROR;\r
2429 }\r
2430\r
2431 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2432 StartLba += NumberOfBlocks;\r
2433 }\r
2434\r
a98f11c5 2435 //\r
2436 // Disable interrupt of Select device\r
2437 //\r
2438 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
2439 DeviceControl |= IEN_L;\r
2440 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2441\r
878ddf1f 2442 return EFI_SUCCESS;\r
2443}\r
2444\r
ed72955c 2445/**\r
2446 This function is called by the AtaBlkIoReadBlocks() to perform\r
a98f11c5 2447 reading from media in block unit. The function has been enhanced to\r
ed72955c 2448 support >120GB access and transfer at most 65536 blocks per command\r
2449\r
2450 @param[in] *IdeDev\r
2451 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2452 to record all the information of the IDE device.\r
2453\r
a98f11c5 2454 @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
2455 @param[in] StartLba The starting logical block address to read from\r
ed72955c 2456 on the device media.\r
2457 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2458\r
2459 @return The device status of UDMA operation. If the operation is\r
2460 successful, return EFI_SUCCESS.\r
2461\r
2462 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2463 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2464 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2465 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2466**/\r
878ddf1f 2467EFI_STATUS\r
2468AtaUdmaRead (\r
2469 IN IDE_BLK_IO_DEV *IdeDev,\r
2470 IN VOID *DataBuffer,\r
2471 IN EFI_LBA StartLba,\r
2472 IN UINTN NumberOfBlocks\r
2473 )\r
878ddf1f 2474{\r
a98f11c5 2475 IDE_DMA_PRD *PrdAddr;\r
2476 IDE_DMA_PRD *UsedPrdAddr;\r
2477 IDE_DMA_PRD *TempPrdAddr;\r
2478 UINT8 RegisterValue;\r
2479 UINT8 Device;\r
2480 UINT64 IoPortForBmic;\r
2481 UINT64 IoPortForBmis;\r
2482 UINT64 IoPortForBmid;\r
2483 EFI_STATUS Status;\r
2484 UINTN PrdTableNum;\r
2485 UINTN ByteCount;\r
2486 UINTN ByteAvailable;\r
2487 UINT8 *PrdBuffer;\r
2488 UINTN RemainBlockNum;\r
2489 UINT8 DeviceControl;\r
2490 UINT32 Count;\r
2491 UINTN PageCount;\r
2492 VOID *Map;\r
aa23173f 2493 VOID *MemPage;\r
a98f11c5 2494 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
878ddf1f 2495\r
2496 //\r
2497 // Channel and device differential\r
2498 //\r
2499 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
2500\r
2501 //\r
2502 // Enable interrupt to support UDMA and Select device\r
2503 //\r
2504 DeviceControl = 0;\r
2505 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2506\r
2507 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2508\r
2509 if (IdePrimary == IdeDev->Channel) {\r
2510 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
2511 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
2512 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
2513 } else {\r
2514 if (IdeSecondary == IdeDev->Channel) {\r
2515 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
2516 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
2517 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
2518 } else {\r
2519 return EFI_UNSUPPORTED;\r
2520 }\r
2521 }\r
2522\r
2523 RemainBlockNum = NumberOfBlocks;\r
2524 while (RemainBlockNum > 0) {\r
2525\r
2526 if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {\r
2527 //\r
2528 // SectorCount is used to record the number of sectors to be read\r
2529 // Max 256 sectors can be transfered at a time.\r
2530 //\r
2531 NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;\r
2532 RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;\r
2533 } else {\r
2534 NumberOfBlocks = (UINT16) RemainBlockNum;\r
2535 RemainBlockNum = 0;\r
2536 }\r
2537\r
2538 //\r
2539 // Calculate the number of PRD table to make sure the memory region\r
2540 // not cross 64K boundary\r
2541 //\r
2542 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2543 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
2544\r
2545 //\r
2546 // Build PRD table\r
2547 //\r
a98f11c5 2548 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
aa23173f 2549 Status = IdeDev->PciIo->AllocateBuffer (\r
2550 IdeDev->PciIo,\r
2551 AllocateAnyPages,\r
2552 EfiBootServicesData,\r
2553 PageCount,\r
2554 &MemPage,\r
2555 0\r
2556 );\r
a98f11c5 2557 if (EFI_ERROR (Status)) {\r
2558 return EFI_OUT_OF_RESOURCES;\r
2559 }\r
2560 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
2561\r
2562 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
878ddf1f 2563 //\r
2564 // To make sure PRD is allocated in one 64K page\r
2565 //\r
2566 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
2567 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
2568 } else {\r
2569 if ((UINTN) PrdAddr & 0x03) {\r
2570 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
2571 } else {\r
2572 UsedPrdAddr = PrdAddr;\r
2573 }\r
2574 }\r
2575\r
2576 //\r
2577 // Build the PRD table\r
2578 //\r
a98f11c5 2579 Status = IdeDev->PciIo->Map (\r
2580 IdeDev->PciIo,\r
2581 EfiPciIoOperationBusMasterWrite,\r
2582 DataBuffer,\r
2583 &ByteCount,\r
2584 &DeviceAddress,\r
2585 &Map\r
2586 );\r
2587 if (EFI_ERROR (Status)) {\r
aa23173f 2588 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2589 return EFI_OUT_OF_RESOURCES;\r
2590 }\r
2591 PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);\r
878ddf1f 2592 TempPrdAddr = UsedPrdAddr;\r
2593 while (TRUE) {\r
2594\r
2595 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
2596\r
2597 if (ByteCount <= ByteAvailable) {\r
2598 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2599 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
2600 TempPrdAddr->EndOfTable = 0x8000;\r
2601 break;\r
2602 }\r
2603\r
2604 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2605 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
2606\r
2607 ByteCount -= ByteAvailable;\r
2608 PrdBuffer += ByteAvailable;\r
2609 TempPrdAddr++;\r
2610 }\r
2611\r
2612 //\r
2613 // Set the base address to BMID register\r
2614 //\r
2615 IdeDev->PciIo->Io.Write (\r
2616 IdeDev->PciIo,\r
2617 EfiPciIoWidthUint32,\r
2618 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2619 IoPortForBmid,\r
2620 1,\r
2621 &UsedPrdAddr\r
2622 );\r
2623\r
2624 //\r
2625 // Set BMIC register to identify the operation direction\r
2626 //\r
2627 IdeDev->PciIo->Io.Read (\r
2628 IdeDev->PciIo,\r
2629 EfiPciIoWidthUint8,\r
2630 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2631 IoPortForBmic,\r
2632 1,\r
2633 &RegisterValue\r
2634 );\r
2635\r
2636 RegisterValue |= BMIC_nREAD;\r
2637\r
2638 IdeDev->PciIo->Io.Write (\r
2639 IdeDev->PciIo,\r
2640 EfiPciIoWidthUint8,\r
2641 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2642 IoPortForBmic,\r
2643 1,\r
2644 &RegisterValue\r
2645 );\r
2646\r
2647 //\r
2648 // Read BMIS register and clear ERROR and INTR bit\r
2649 //\r
2650 IdeDev->PciIo->Io.Read (\r
2651 IdeDev->PciIo,\r
2652 EfiPciIoWidthUint8,\r
2653 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2654 IoPortForBmis,\r
2655 1,\r
2656 &RegisterValue\r
2657 );\r
2658\r
2659 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
2660\r
2661 IdeDev->PciIo->Io.Write (\r
2662 IdeDev->PciIo,\r
2663 EfiPciIoWidthUint8,\r
2664 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2665 IoPortForBmis,\r
2666 1,\r
2667 &RegisterValue\r
2668 );\r
2669\r
2670 //\r
2671 // Issue READ DMA command\r
2672 //\r
2673 Status = AtaCommandIssue (\r
a98f11c5 2674 IdeDev,\r
2675 READ_DMA_CMD,\r
2676 Device,\r
2677 0,\r
2678 (UINT16) NumberOfBlocks,\r
2679 StartLba\r
2680 );\r
878ddf1f 2681 if (EFI_ERROR (Status)) {\r
aa23173f 2682 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2683 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2684 return EFI_DEVICE_ERROR;\r
2685 }\r
2686\r
2687 //\r
2688 // Set START bit of BMIC register\r
2689 //\r
2690 IdeDev->PciIo->Io.Read (\r
2691 IdeDev->PciIo,\r
2692 EfiPciIoWidthUint8,\r
2693 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2694 IoPortForBmic,\r
2695 1,\r
2696 &RegisterValue\r
2697 );\r
2698\r
2699 RegisterValue |= BMIC_START;\r
2700\r
2701 IdeDev->PciIo->Io.Write (\r
2702 IdeDev->PciIo,\r
2703 EfiPciIoWidthUint8,\r
2704 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2705 IoPortForBmic,\r
2706 1,\r
2707 &RegisterValue\r
2708 );\r
2709\r
2710 //\r
2711 // Check the INTERRUPT and ERROR bit of BMIS\r
a98f11c5 2712 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
2713 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
2714 // So set the variable Count to 2000, for about 2 second timeout time.\r
878ddf1f 2715 //\r
a98f11c5 2716 Count = 2000;\r
878ddf1f 2717 while (TRUE) {\r
2718\r
2719 IdeDev->PciIo->Io.Read (\r
2720 IdeDev->PciIo,\r
2721 EfiPciIoWidthUint8,\r
2722 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2723 IoPortForBmis,\r
2724 1,\r
2725 &RegisterValue\r
2726 );\r
a98f11c5 2727 if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
2728 if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
2729 //\r
2730 // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
2731 //\r
2732 IdeDev->PciIo->Io.Read (\r
2733 IdeDev->PciIo,\r
2734 EfiPciIoWidthUint8,\r
2735 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2736 IoPortForBmic,\r
2737 1,\r
2738 &RegisterValue\r
2739 );\r
2740\r
2741 RegisterValue &= ~((UINT8)BMIC_START);\r
2742\r
2743 IdeDev->PciIo->Io.Write (\r
2744 IdeDev->PciIo,\r
2745 EfiPciIoWidthUint8,\r
2746 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2747 IoPortForBmic,\r
2748 1,\r
2749 &RegisterValue\r
2750 );\r
aa23173f 2751 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2752 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2753 return EFI_DEVICE_ERROR;\r
2754 }\r
2755 break;\r
2756 }\r
2757\r
2758 gBS->Stall (1000);\r
a98f11c5 2759 Count --;\r
878ddf1f 2760 }\r
2761\r
aa23173f 2762 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2763 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 2764 //\r
a98f11c5 2765 // Read Status Register of IDE device to clear interrupt\r
2766 //\r
2767 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
2768 //\r
2769 // Clear START bit of BMIC register\r
878ddf1f 2770 //\r
2771 IdeDev->PciIo->Io.Read (\r
2772 IdeDev->PciIo,\r
2773 EfiPciIoWidthUint8,\r
2774 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2775 IoPortForBmic,\r
2776 1,\r
2777 &RegisterValue\r
2778 );\r
2779\r
2780 RegisterValue &= ~((UINT8) BMIC_START);\r
2781\r
2782 IdeDev->PciIo->Io.Write (\r
2783 IdeDev->PciIo,\r
2784 EfiPciIoWidthUint8,\r
2785 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2786 IoPortForBmic,\r
2787 1,\r
2788 &RegisterValue\r
2789 );\r
2790\r
2791 if (RegisterValue & BMIS_ERROR) {\r
2792 return EFI_DEVICE_ERROR;\r
2793 }\r
2794\r
2795 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2796 StartLba += NumberOfBlocks;\r
2797 }\r
2798\r
a98f11c5 2799 //\r
2800 // Disable interrupt of Select device\r
2801 //\r
2802 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
2803 DeviceControl |= IEN_L;\r
2804 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2805\r
878ddf1f 2806 return EFI_SUCCESS;\r
2807}\r
2808\r
ed72955c 2809/**\r
2810 This function is called by the AtaBlkIoWriteBlocks() to perform\r
a98f11c5 2811 writing to media in block unit. The function has been enhanced to\r
ed72955c 2812 support >120GB access and transfer at most 65536 blocks per command\r
2813\r
2814 @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2815 to record all the information of the IDE device.\r
2816\r
a98f11c5 2817 @param[in] *DataBuffer A pointer to the source buffer for the data.\r
ed72955c 2818\r
a98f11c5 2819 @param[in] StartLba The starting logical block address to write to\r
ed72955c 2820 on the device media.\r
2821\r
2822 @param[in] NumberOfBlocks The number of transfer data blocks.\r
2823\r
2824 @return The device status of UDMA operation. If the operation is\r
2825 successful, return EFI_SUCCESS.\r
2826\r
2827 TODO: EFI_UNSUPPORTED - add return value to function comment\r
2828 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2829 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2830**/\r
878ddf1f 2831EFI_STATUS\r
2832AtaUdmaWriteExt (\r
2833 IN IDE_BLK_IO_DEV *IdeDev,\r
2834 IN VOID *DataBuffer,\r
2835 IN EFI_LBA StartLba,\r
2836 IN UINTN NumberOfBlocks\r
2837 )\r
878ddf1f 2838{\r
a98f11c5 2839 IDE_DMA_PRD *PrdAddr;\r
2840 IDE_DMA_PRD *UsedPrdAddr;\r
2841 IDE_DMA_PRD *TempPrdAddr;\r
2842 UINT8 RegisterValue;\r
2843 UINT8 Device;\r
2844 UINT64 IoPortForBmic;\r
2845 UINT64 IoPortForBmis;\r
2846 UINT64 IoPortForBmid;\r
2847 EFI_STATUS Status;\r
2848 UINTN PrdTableNum;\r
2849 UINTN ByteCount;\r
2850 UINTN ByteAvailable;\r
2851 UINT8 *PrdBuffer;\r
2852 UINTN RemainBlockNum;\r
2853 UINT8 DeviceControl;\r
2854 UINT32 Count;\r
2855 UINTN PageCount;\r
2856 VOID *Map;\r
aa23173f 2857 VOID *MemPage;\r
a98f11c5 2858 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
878ddf1f 2859\r
2860 //\r
2861 // Channel and device differential\r
2862 //\r
2863 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
2864\r
2865 //\r
2866 // Enable interrupt to support UDMA and Select device\r
2867 //\r
2868 DeviceControl = 0;\r
2869 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
2870\r
2871 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2872\r
2873 if (IdePrimary == IdeDev->Channel) {\r
2874 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
2875 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
2876 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
2877 } else {\r
2878 if (IdeSecondary == IdeDev->Channel) {\r
2879 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
2880 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
2881 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
2882 } else {\r
2883 return EFI_UNSUPPORTED;\r
2884 }\r
2885 }\r
2886\r
2887 RemainBlockNum = NumberOfBlocks;\r
2888 while (RemainBlockNum > 0) {\r
2889\r
2890 if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {\r
2891 //\r
2892 // SectorCount is used to record the number of sectors to be read\r
2893 // Max 65536 sectors can be transfered at a time.\r
2894 //\r
2895 NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;\r
2896 RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;\r
2897 } else {\r
2898 NumberOfBlocks = (UINT16) RemainBlockNum;\r
2899 RemainBlockNum = 0;\r
2900 }\r
2901\r
2902 //\r
2903 // Calculate the number of PRD table to make sure the memory region\r
2904 // not cross 64K boundary\r
2905 //\r
2906 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
2907 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
2908\r
2909 //\r
2910 // Build PRD table\r
2911 //\r
a98f11c5 2912 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
aa23173f 2913 Status = IdeDev->PciIo->AllocateBuffer (\r
2914 IdeDev->PciIo,\r
2915 AllocateAnyPages,\r
2916 EfiBootServicesData,\r
2917 PageCount,\r
2918 &MemPage,\r
2919 0\r
2920 );\r
a98f11c5 2921 if (EFI_ERROR (Status)) {\r
2922 return EFI_OUT_OF_RESOURCES;\r
2923 }\r
2924 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
2925\r
2926 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
878ddf1f 2927 //\r
2928 // To make sure PRD is allocated in one 64K page\r
2929 //\r
2930 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
2931 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
2932 } else {\r
2933 if ((UINTN) PrdAddr & 0x03) {\r
2934 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
2935 } else {\r
2936 UsedPrdAddr = PrdAddr;\r
2937 }\r
2938 }\r
2939\r
2940 //\r
2941 // Build the PRD table\r
2942 //\r
a98f11c5 2943 Status = IdeDev->PciIo->Map (\r
2944 IdeDev->PciIo,\r
2945 EfiPciIoOperationBusMasterRead,\r
2946 DataBuffer,\r
2947 &ByteCount,\r
2948 &DeviceAddress,\r
2949 &Map\r
2950 );\r
2951 if (EFI_ERROR (Status)) {\r
aa23173f 2952 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 2953 return EFI_OUT_OF_RESOURCES;\r
2954 }\r
2955 PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);\r
878ddf1f 2956 TempPrdAddr = UsedPrdAddr;\r
2957 while (TRUE) {\r
2958\r
2959 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
2960\r
2961 if (ByteCount <= ByteAvailable) {\r
2962 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2963 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
2964 TempPrdAddr->EndOfTable = 0x8000;\r
2965 break;\r
2966 }\r
2967\r
2968 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
2969 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
2970\r
2971 ByteCount -= ByteAvailable;\r
2972 PrdBuffer += ByteAvailable;\r
2973 TempPrdAddr++;\r
2974 }\r
a98f11c5 2975\r
878ddf1f 2976 //\r
2977 // Set the base address to BMID register\r
2978 //\r
2979 IdeDev->PciIo->Io.Write (\r
2980 IdeDev->PciIo,\r
2981 EfiPciIoWidthUint32,\r
2982 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2983 IoPortForBmid,\r
2984 1,\r
2985 &UsedPrdAddr\r
2986 );\r
2987\r
2988 //\r
2989 // Set BMIC register to identify the operation direction\r
2990 //\r
2991 IdeDev->PciIo->Io.Read (\r
2992 IdeDev->PciIo,\r
2993 EfiPciIoWidthUint8,\r
2994 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2995 IoPortForBmic,\r
2996 1,\r
2997 &RegisterValue\r
2998 );\r
2999 //\r
3000 // 0000 1000\r
3001 //\r
3002 RegisterValue &= ~((UINT8) BMIC_nREAD);\r
3003\r
3004 IdeDev->PciIo->Io.Write (\r
3005 IdeDev->PciIo,\r
3006 EfiPciIoWidthUint8,\r
3007 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3008 IoPortForBmic,\r
3009 1,\r
3010 &RegisterValue\r
3011 );\r
3012\r
3013 //\r
3014 // Read BMIS register and clear ERROR and INTR bit\r
3015 //\r
3016 IdeDev->PciIo->Io.Read (\r
3017 IdeDev->PciIo,\r
3018 EfiPciIoWidthUint8,\r
3019 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3020 IoPortForBmis,\r
3021 1,\r
3022 &RegisterValue\r
3023 );\r
3024\r
3025 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
3026\r
3027 IdeDev->PciIo->Io.Write (\r
3028 IdeDev->PciIo,\r
3029 EfiPciIoWidthUint8,\r
3030 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3031 IoPortForBmis,\r
3032 1,\r
3033 &RegisterValue\r
3034 );\r
3035\r
3036 //\r
3037 // Issue WRITE DMA EXT command\r
3038 //\r
3039 Status = AtaCommandIssueExt (\r
a98f11c5 3040 IdeDev,\r
3041 WRITE_DMA_EXT_CMD,\r
3042 Device,\r
3043 0,\r
3044 (UINT16) NumberOfBlocks,\r
3045 StartLba\r
3046 );\r
878ddf1f 3047 if (EFI_ERROR (Status)) {\r
aa23173f 3048 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3049 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3050 return EFI_DEVICE_ERROR;\r
3051 }\r
3052\r
3053 //\r
3054 // Set START bit of BMIC register\r
3055 //\r
3056 IdeDev->PciIo->Io.Read (\r
3057 IdeDev->PciIo,\r
3058 EfiPciIoWidthUint8,\r
3059 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3060 IoPortForBmic,\r
3061 1,\r
3062 &RegisterValue\r
3063 );\r
3064\r
3065 RegisterValue |= BMIC_START;\r
3066\r
3067 IdeDev->PciIo->Io.Write (\r
3068 IdeDev->PciIo,\r
3069 EfiPciIoWidthUint8,\r
3070 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3071 IoPortForBmic,\r
3072 1,\r
3073 &RegisterValue\r
3074 );\r
3075\r
3076 //\r
3077 // Check the INTERRUPT and ERROR bit of BMIS\r
a98f11c5 3078 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
3079 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
3080 // So set the variable Count to 2000, for about 2 second timeout time.\r
878ddf1f 3081 //\r
a98f11c5 3082 Count = 2000;\r
878ddf1f 3083 while (TRUE) {\r
3084\r
3085 IdeDev->PciIo->Io.Read (\r
3086 IdeDev->PciIo,\r
3087 EfiPciIoWidthUint8,\r
3088 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3089 IoPortForBmis,\r
3090 1,\r
3091 &RegisterValue\r
3092 );\r
a98f11c5 3093 if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
3094 if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
3095 //\r
3096 // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
3097 //\r
3098 IdeDev->PciIo->Io.Read (\r
3099 IdeDev->PciIo,\r
3100 EfiPciIoWidthUint8,\r
3101 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3102 IoPortForBmic,\r
3103 1,\r
3104 &RegisterValue\r
3105 );\r
3106\r
3107 RegisterValue &= ~((UINT8)BMIC_START);\r
3108\r
3109 IdeDev->PciIo->Io.Write (\r
3110 IdeDev->PciIo,\r
3111 EfiPciIoWidthUint8,\r
3112 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3113 IoPortForBmic,\r
3114 1,\r
3115 &RegisterValue\r
3116 );\r
aa23173f 3117 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3118 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3119 return EFI_DEVICE_ERROR;\r
3120 }\r
3121 break;\r
3122 }\r
3123\r
3124 gBS->Stall (1000);\r
a98f11c5 3125 Count --;\r
878ddf1f 3126 }\r
3127\r
aa23173f 3128 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3129 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3130 //\r
a98f11c5 3131 // Read Status Register of IDE device to clear interrupt\r
3132 //\r
3133 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
3134 //\r
3135 // Clear START bit of BMIC register\r
878ddf1f 3136 //\r
3137 IdeDev->PciIo->Io.Read (\r
3138 IdeDev->PciIo,\r
3139 EfiPciIoWidthUint8,\r
3140 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3141 IoPortForBmic,\r
3142 1,\r
3143 &RegisterValue\r
3144 );\r
3145\r
3146 RegisterValue &= ~((UINT8) BMIC_START);\r
3147\r
3148 IdeDev->PciIo->Io.Write (\r
3149 IdeDev->PciIo,\r
3150 EfiPciIoWidthUint8,\r
3151 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3152 IoPortForBmic,\r
3153 1,\r
3154 &RegisterValue\r
3155 );\r
3156\r
3157 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
3158 StartLba += NumberOfBlocks;\r
3159 }\r
3160\r
a98f11c5 3161 //\r
3162 // Disable interrupt of Select device\r
3163 //\r
3164 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
3165 DeviceControl |= IEN_L;\r
3166 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
3167\r
878ddf1f 3168 return EFI_SUCCESS;\r
3169}\r
3170\r
ed72955c 3171/**\r
3172 This function is called by the AtaBlkIoWriteBlocks() to perform\r
a98f11c5 3173 writing to media in block unit. The function has been enhanced to\r
ed72955c 3174 support >120GB access and transfer at most 65536 blocks per command\r
3175\r
3176 @param[in] *IdeDev\r
3177 pointer pointing to IDE_BLK_IO_DEV data structure, used\r
3178 to record all the information of the IDE device.\r
3179\r
3180 @param[in] *DataBuffer\r
a98f11c5 3181 A pointer to the source buffer for the data.\r
ed72955c 3182\r
3183 @param[in] StartLba\r
a98f11c5 3184 The starting logical block address to write to\r
ed72955c 3185 on the device media.\r
3186\r
3187 @param[in] NumberOfBlocks\r
3188 The number of transfer data blocks.\r
3189\r
3190 @return The device status of UDMA operation. If the operation is\r
3191 successful, return EFI_SUCCESS.\r
3192\r
3193 TODO: EFI_UNSUPPORTED - add return value to function comment\r
3194 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
3195 TODO: EFI_DEVICE_ERROR - add return value to function comment\r
3196**/\r
878ddf1f 3197EFI_STATUS\r
3198AtaUdmaWrite (\r
3199 IN IDE_BLK_IO_DEV *IdeDev,\r
3200 IN VOID *DataBuffer,\r
3201 IN EFI_LBA StartLba,\r
3202 IN UINTN NumberOfBlocks\r
3203 )\r
878ddf1f 3204{\r
a98f11c5 3205 IDE_DMA_PRD *PrdAddr;\r
3206 IDE_DMA_PRD *UsedPrdAddr;\r
3207 IDE_DMA_PRD *TempPrdAddr;\r
3208 UINT8 RegisterValue;\r
3209 UINT8 Device;\r
3210 UINT64 IoPortForBmic;\r
3211 UINT64 IoPortForBmis;\r
3212 UINT64 IoPortForBmid;\r
3213 EFI_STATUS Status;\r
3214 UINTN PrdTableNum;\r
3215 UINTN ByteCount;\r
3216 UINTN ByteAvailable;\r
3217 UINT8 *PrdBuffer;\r
3218 UINTN RemainBlockNum;\r
3219 UINT8 DeviceControl;\r
3220 UINT32 Count;\r
3221 UINTN PageCount;\r
3222 VOID *Map;\r
aa23173f 3223 VOID *MemPage;\r
a98f11c5 3224 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
878ddf1f 3225\r
3226 //\r
3227 // Channel and device differential\r
3228 //\r
3229 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
3230\r
3231 //\r
3232 // Enable interrupt to support UDMA\r
3233 //\r
3234 DeviceControl = 0;\r
3235 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
3236\r
3237 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
3238\r
3239 if (IdePrimary == IdeDev->Channel) {\r
3240 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
3241 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
3242 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
3243 } else {\r
3244 if (IdeSecondary == IdeDev->Channel) {\r
3245 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
3246 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
3247 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
3248 } else {\r
3249 return EFI_UNSUPPORTED;\r
3250 }\r
3251 }\r
3252\r
3253 RemainBlockNum = NumberOfBlocks;\r
3254 while (RemainBlockNum > 0) {\r
3255\r
3256 if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {\r
3257 //\r
3258 // SectorCount is used to record the number of sectors to be read\r
3259 // Max 256 sectors can be transfered at a time.\r
3260 //\r
3261 NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;\r
3262 RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;\r
3263 } else {\r
3264 NumberOfBlocks = (UINT16) RemainBlockNum;\r
3265 RemainBlockNum = 0;\r
3266 }\r
3267\r
3268 //\r
3269 // Calculate the number of PRD table to make sure the memory region\r
3270 // not cross 64K boundary\r
3271 //\r
3272 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
3273 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
3274\r
3275 //\r
3276 // Build PRD table\r
3277 //\r
a98f11c5 3278 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
aa23173f 3279 Status = IdeDev->PciIo->AllocateBuffer (\r
3280 IdeDev->PciIo,\r
3281 AllocateAnyPages,\r
3282 EfiBootServicesData,\r
3283 PageCount,\r
3284 &MemPage,\r
3285 0\r
3286 );\r
a98f11c5 3287 if (EFI_ERROR (Status)) {\r
3288 return EFI_OUT_OF_RESOURCES;\r
3289 }\r
3290 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
3291\r
3292 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
878ddf1f 3293\r
3294 //\r
3295 // To make sure PRD is allocated in one 64K page\r
3296 //\r
3297 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
3298 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
3299 } else {\r
3300 if ((UINTN) PrdAddr & 0x03) {\r
3301 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
3302 } else {\r
3303 UsedPrdAddr = PrdAddr;\r
3304 }\r
3305 }\r
3306\r
3307 //\r
3308 // Build the PRD table\r
3309 //\r
a98f11c5 3310 Status = IdeDev->PciIo->Map (\r
3311 IdeDev->PciIo,\r
3312 EfiPciIoOperationBusMasterRead,\r
3313 DataBuffer,\r
3314 &ByteCount,\r
3315 &DeviceAddress,\r
3316 &Map\r
3317 );\r
3318 if (EFI_ERROR (Status)) {\r
aa23173f 3319 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3320 return EFI_OUT_OF_RESOURCES;\r
3321 }\r
3322 PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);\r
878ddf1f 3323 TempPrdAddr = UsedPrdAddr;\r
3324 while (TRUE) {\r
3325\r
3326 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
3327\r
3328 if (ByteCount <= ByteAvailable) {\r
3329 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
3330 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
3331 TempPrdAddr->EndOfTable = 0x8000;\r
3332 break;\r
3333 }\r
3334\r
3335 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
3336 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
3337\r
3338 ByteCount -= ByteAvailable;\r
3339 PrdBuffer += ByteAvailable;\r
3340 TempPrdAddr++;\r
3341 }\r
a98f11c5 3342\r
878ddf1f 3343 //\r
3344 // Set the base address to BMID register\r
3345 //\r
3346 IdeDev->PciIo->Io.Write (\r
3347 IdeDev->PciIo,\r
3348 EfiPciIoWidthUint32,\r
3349 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3350 IoPortForBmid,\r
3351 1,\r
3352 &UsedPrdAddr\r
3353 );\r
3354\r
3355 //\r
3356 // Set BMIC register to identify the operation direction\r
3357 //\r
3358 IdeDev->PciIo->Io.Read (\r
3359 IdeDev->PciIo,\r
3360 EfiPciIoWidthUint8,\r
3361 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3362 IoPortForBmic,\r
3363 1,\r
3364 &RegisterValue\r
3365 );\r
3366 //\r
3367 // 0000 1000\r
3368 //\r
3369 RegisterValue &= ~((UINT8) BMIC_nREAD);\r
3370\r
3371 IdeDev->PciIo->Io.Write (\r
3372 IdeDev->PciIo,\r
3373 EfiPciIoWidthUint8,\r
3374 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3375 IoPortForBmic,\r
3376 1,\r
3377 &RegisterValue\r
3378 );\r
3379\r
3380 //\r
3381 // Read BMIS register and clear ERROR and INTR bit\r
3382 //\r
3383 IdeDev->PciIo->Io.Read (\r
3384 IdeDev->PciIo,\r
3385 EfiPciIoWidthUint8,\r
3386 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3387 IoPortForBmis,\r
3388 1,\r
3389 &RegisterValue\r
3390 );\r
3391\r
3392 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
3393\r
3394 IdeDev->PciIo->Io.Write (\r
3395 IdeDev->PciIo,\r
3396 EfiPciIoWidthUint8,\r
3397 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3398 IoPortForBmis,\r
3399 1,\r
3400 &RegisterValue\r
3401 );\r
3402\r
3403 //\r
3404 // Issue WRITE DMA command\r
3405 //\r
3406 Status = AtaCommandIssue (\r
a98f11c5 3407 IdeDev,\r
3408 WRITE_DMA_CMD,\r
3409 Device,\r
3410 0,\r
3411 (UINT16) NumberOfBlocks,\r
3412 StartLba\r
3413 );\r
878ddf1f 3414 if (EFI_ERROR (Status)) {\r
aa23173f 3415 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3416 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3417 return EFI_DEVICE_ERROR;\r
3418 }\r
3419\r
3420 //\r
3421 // Set START bit of BMIC register\r
3422 //\r
3423 IdeDev->PciIo->Io.Read (\r
3424 IdeDev->PciIo,\r
3425 EfiPciIoWidthUint8,\r
3426 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3427 IoPortForBmic,\r
3428 1,\r
3429 &RegisterValue\r
3430 );\r
3431\r
3432 RegisterValue |= BMIC_START;\r
3433\r
3434 IdeDev->PciIo->Io.Write (\r
3435 IdeDev->PciIo,\r
3436 EfiPciIoWidthUint8,\r
3437 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3438 IoPortForBmic,\r
3439 1,\r
3440 &RegisterValue\r
3441 );\r
3442\r
3443 //\r
3444 // Check the INTERRUPT and ERROR bit of BMIS\r
a98f11c5 3445 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
3446 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
3447 // So set the variable Count to 2000, for about 2 second timeout time.\r
878ddf1f 3448 //\r
a98f11c5 3449 Count = 2000;\r
878ddf1f 3450 while (TRUE) {\r
3451\r
3452 IdeDev->PciIo->Io.Read (\r
3453 IdeDev->PciIo,\r
3454 EfiPciIoWidthUint8,\r
3455 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3456 IoPortForBmis,\r
3457 1,\r
3458 &RegisterValue\r
3459 );\r
a98f11c5 3460 if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
3461 if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
3462 //\r
3463 // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
3464 //\r
3465 IdeDev->PciIo->Io.Read (\r
3466 IdeDev->PciIo,\r
3467 EfiPciIoWidthUint8,\r
3468 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3469 IoPortForBmic,\r
3470 1,\r
3471 &RegisterValue\r
3472 );\r
3473\r
3474 RegisterValue &= ~((UINT8)BMIC_START);\r
3475\r
3476 IdeDev->PciIo->Io.Write (\r
3477 IdeDev->PciIo,\r
3478 EfiPciIoWidthUint8,\r
3479 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3480 IoPortForBmic,\r
3481 1,\r
3482 &RegisterValue\r
3483 );\r
aa23173f 3484 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3485 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3486 return EFI_DEVICE_ERROR;\r
3487 }\r
3488 break;\r
3489 }\r
3490\r
3491 gBS->Stall (1000);\r
a98f11c5 3492 Count --;\r
878ddf1f 3493 }\r
3494\r
aa23173f 3495 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
a98f11c5 3496 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
878ddf1f 3497\r
3498 //\r
a98f11c5 3499 // Read Status Register of IDE device to clear interrupt\r
3500 //\r
3501 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
3502 //\r
3503 // Clear START bit of BMIC register\r
878ddf1f 3504 //\r
3505 IdeDev->PciIo->Io.Read (\r
3506 IdeDev->PciIo,\r
3507 EfiPciIoWidthUint8,\r
3508 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3509 IoPortForBmic,\r
3510 1,\r
3511 &RegisterValue\r
3512 );\r
3513\r
3514 RegisterValue &= ~((UINT8) BMIC_START);\r
3515\r
3516 IdeDev->PciIo->Io.Write (\r
3517 IdeDev->PciIo,\r
3518 EfiPciIoWidthUint8,\r
3519 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3520 IoPortForBmic,\r
3521 1,\r
3522 &RegisterValue\r
3523 );\r
3524\r
3525 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
3526 StartLba += NumberOfBlocks;\r
3527 }\r
3528\r
a98f11c5 3529 //\r
3530 // Disable interrupt of Select device\r
3531 //\r
3532 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
3533 DeviceControl |= IEN_L;\r
3534 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
3535\r
878ddf1f 3536 return EFI_SUCCESS;\r
3537}\r