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