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