]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c
MdeModulePkg/ScsiDisk: Using back-off algorithm to dynamically adjust transfer length...
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaAtapiPassThru / IdeMode.c
CommitLineData
a41b5272 1/** @file\r
2 Header file for AHCI mode of ATA host controller.\r
1aff716a 3\r
73a9e822 4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
1aff716a 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
a41b5272 9\r
1aff716a 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
a41b5272 12\r
13**/\r
14\r
15#include "AtaAtapiPassThru.h"\r
16\r
17/**\r
18 read a one-byte data from a IDE port.\r
19\r
8536cc4b 20 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
1aff716a 21 @param Port The IDE Port number\r
a41b5272 22\r
23 @return the one-byte data read from IDE port\r
24**/\r
25UINT8\r
26EFIAPI\r
27IdeReadPortB (\r
28 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
29 IN UINT16 Port\r
30 )\r
31{\r
32 UINT8 Data;\r
33\r
34 ASSERT (PciIo != NULL);\r
35\r
36 Data = 0;\r
37 //\r
38 // perform 1-byte data read from register\r
39 //\r
40 PciIo->Io.Read (\r
41 PciIo,\r
42 EfiPciIoWidthUint8,\r
43 EFI_PCI_IO_PASS_THROUGH_BAR,\r
44 (UINT64) Port,\r
45 1,\r
46 &Data\r
47 );\r
48 return Data;\r
49}\r
50\r
51/**\r
52 write a 1-byte data to a specific IDE port.\r
53\r
8536cc4b 54 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
a41b5272 55 @param Port The IDE port to be writen\r
56 @param Data The data to write to the port\r
57**/\r
58VOID\r
59EFIAPI\r
60IdeWritePortB (\r
61 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
62 IN UINT16 Port,\r
63 IN UINT8 Data\r
64 )\r
65{\r
66 ASSERT (PciIo != NULL);\r
67\r
68 //\r
69 // perform 1-byte data write to register\r
70 //\r
71 PciIo->Io.Write (\r
72 PciIo,\r
73 EfiPciIoWidthUint8,\r
74 EFI_PCI_IO_PASS_THROUGH_BAR,\r
75 (UINT64) Port,\r
76 1,\r
77 &Data\r
78 );\r
79}\r
80\r
81/**\r
82 write a 1-word data to a specific IDE port.\r
83\r
8536cc4b 84 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
a41b5272 85 @param Port The IDE port to be writen\r
86 @param Data The data to write to the port\r
87**/\r
88VOID\r
89EFIAPI\r
90IdeWritePortW (\r
91 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
92 IN UINT16 Port,\r
93 IN UINT16 Data\r
94 )\r
95{\r
96 ASSERT (PciIo != NULL);\r
97\r
98 //\r
99 // perform 1-word data write to register\r
100 //\r
101 PciIo->Io.Write (\r
102 PciIo,\r
103 EfiPciIoWidthUint16,\r
104 EFI_PCI_IO_PASS_THROUGH_BAR,\r
105 (UINT64) Port,\r
106 1,\r
107 &Data\r
108 );\r
109}\r
110\r
111/**\r
112 write a 2-word data to a specific IDE port.\r
113\r
8536cc4b 114 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
a41b5272 115 @param Port The IDE port to be writen\r
116 @param Data The data to write to the port\r
117**/\r
118VOID\r
119EFIAPI\r
120IdeWritePortDW (\r
121 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
122 IN UINT16 Port,\r
123 IN UINT32 Data\r
124 )\r
125{\r
126 ASSERT (PciIo != NULL);\r
127\r
128 //\r
129 // perform 2-word data write to register\r
130 //\r
131 PciIo->Io.Write (\r
132 PciIo,\r
133 EfiPciIoWidthUint32,\r
134 EFI_PCI_IO_PASS_THROUGH_BAR,\r
135 (UINT64) Port,\r
136 1,\r
137 &Data\r
138 );\r
139}\r
140\r
141/**\r
142 Write multiple words of data to the IDE data port.\r
143 Call the IO abstraction once to do the complete read,\r
144 not one word at a time\r
145\r
8536cc4b 146 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
a41b5272 147 @param Port IO port to read\r
148 @param Count No. of UINT16's to read\r
149 @param Buffer Pointer to the data buffer for read\r
150\r
151**/\r
152VOID\r
153EFIAPI\r
154IdeWritePortWMultiple (\r
155 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
156 IN UINT16 Port,\r
157 IN UINTN Count,\r
158 IN VOID *Buffer\r
159 )\r
160{\r
161 ASSERT (PciIo != NULL);\r
162 ASSERT (Buffer != NULL);\r
163\r
164 //\r
165 // perform UINT16 data write to the FIFO\r
166 //\r
167 PciIo->Io.Write (\r
168 PciIo,\r
169 EfiPciIoWidthFifoUint16,\r
170 EFI_PCI_IO_PASS_THROUGH_BAR,\r
171 (UINT64) Port,\r
172 Count,\r
173 (UINT16 *) Buffer\r
174 );\r
175\r
176}\r
177\r
178/**\r
179 Reads multiple words of data from the IDE data port.\r
180 Call the IO abstraction once to do the complete read,\r
181 not one word at a time\r
182\r
8536cc4b 183 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
a41b5272 184 @param Port IO port to read\r
185 @param Count Number of UINT16's to read\r
186 @param Buffer Pointer to the data buffer for read\r
187\r
188**/\r
189VOID\r
190EFIAPI\r
191IdeReadPortWMultiple (\r
192 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
193 IN UINT16 Port,\r
194 IN UINTN Count,\r
195 IN VOID *Buffer\r
196 )\r
197{\r
198 ASSERT (PciIo != NULL);\r
199 ASSERT (Buffer != NULL);\r
200\r
201 //\r
202 // Perform UINT16 data read from FIFO\r
203 //\r
204 PciIo->Io.Read (\r
205 PciIo,\r
206 EfiPciIoWidthFifoUint16,\r
207 EFI_PCI_IO_PASS_THROUGH_BAR,\r
208 (UINT64) Port,\r
209 Count,\r
210 (UINT16 *) Buffer\r
211 );\r
212\r
213}\r
214\r
215/**\r
216 This function is used to analyze the Status Register and print out\r
217 some debug information and if there is ERR bit set in the Status\r
218 Register, the Error Register's value is also be parsed and print out.\r
219\r
8536cc4b 220 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 221 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
222 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
223\r
224**/\r
225VOID\r
226EFIAPI\r
227DumpAllIdeRegisters (\r
228 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
229 IN EFI_IDE_REGISTERS *IdeRegisters,\r
230 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
231 )\r
232{\r
233 EFI_ATA_STATUS_BLOCK StatusBlock;\r
234\r
235 ASSERT (PciIo != NULL);\r
236 ASSERT (IdeRegisters != NULL);\r
237\r
238 ZeroMem (&StatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
239\r
240 StatusBlock.AtaStatus = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
241 StatusBlock.AtaError = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
242 StatusBlock.AtaSectorCount = IdeReadPortB (PciIo, IdeRegisters->SectorCount);\r
243 StatusBlock.AtaSectorCountExp = IdeReadPortB (PciIo, IdeRegisters->SectorCount);\r
244 StatusBlock.AtaSectorNumber = IdeReadPortB (PciIo, IdeRegisters->SectorNumber);\r
245 StatusBlock.AtaSectorNumberExp = IdeReadPortB (PciIo, IdeRegisters->SectorNumber);\r
246 StatusBlock.AtaCylinderLow = IdeReadPortB (PciIo, IdeRegisters->CylinderLsb);\r
247 StatusBlock.AtaCylinderLowExp = IdeReadPortB (PciIo, IdeRegisters->CylinderLsb);\r
248 StatusBlock.AtaCylinderHigh = IdeReadPortB (PciIo, IdeRegisters->CylinderMsb);\r
249 StatusBlock.AtaCylinderHighExp = IdeReadPortB (PciIo, IdeRegisters->CylinderMsb);\r
250 StatusBlock.AtaDeviceHead = IdeReadPortB (PciIo, IdeRegisters->Head);\r
251\r
252 if (AtaStatusBlock != NULL) {\r
253 //\r
254 // Dump the content of all ATA registers.\r
255 //\r
256 CopyMem (AtaStatusBlock, &StatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
257 }\r
258\r
259 DEBUG_CODE_BEGIN ();\r
260 if ((StatusBlock.AtaStatus & ATA_STSREG_DWF) != 0) {\r
261 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Write Fault\n", StatusBlock.AtaStatus));\r
262 }\r
263\r
264 if ((StatusBlock.AtaStatus & ATA_STSREG_CORR) != 0) {\r
265 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Corrected Data\n", StatusBlock.AtaStatus));\r
266 }\r
267\r
268 if ((StatusBlock.AtaStatus & ATA_STSREG_ERR) != 0) {\r
269 if ((StatusBlock.AtaError & ATA_ERRREG_BBK) != 0) {\r
270 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Bad Block Detected\n", StatusBlock.AtaError));\r
271 }\r
272\r
273 if ((StatusBlock.AtaError & ATA_ERRREG_UNC) != 0) {\r
274 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Uncorrectable Data\n", StatusBlock.AtaError));\r
275 }\r
276\r
277 if ((StatusBlock.AtaError & ATA_ERRREG_MC) != 0) {\r
278 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Media Change\n", StatusBlock.AtaError));\r
279 }\r
280\r
281 if ((StatusBlock.AtaError & ATA_ERRREG_ABRT) != 0) {\r
282 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Abort\n", StatusBlock.AtaError));\r
283 }\r
284\r
285 if ((StatusBlock.AtaError & ATA_ERRREG_TK0NF) != 0) {\r
286 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Track 0 Not Found\n", StatusBlock.AtaError));\r
287 }\r
288\r
289 if ((StatusBlock.AtaError & ATA_ERRREG_AMNF) != 0) {\r
290 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Address Mark Not Found\n", StatusBlock.AtaError));\r
291 }\r
292 }\r
293 DEBUG_CODE_END ();\r
294}\r
295\r
296/**\r
8536cc4b 297 This function is used to analyze the Status Register at the condition that BSY is zero.\r
298 if there is ERR bit set in the Status Register, then return error.\r
a41b5272 299\r
8536cc4b 300 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 301 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
302\r
303 @retval EFI_SUCCESS No err information in the Status Register.\r
304 @retval EFI_DEVICE_ERROR Any err information in the Status Register.\r
305\r
306**/\r
307EFI_STATUS\r
308EFIAPI\r
309CheckStatusRegister (\r
310 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
311 IN EFI_IDE_REGISTERS *IdeRegisters\r
312 )\r
313{\r
a41b5272 314 UINT8 StatusRegister;\r
315\r
316 ASSERT (PciIo != NULL);\r
317 ASSERT (IdeRegisters != NULL);\r
318\r
319 StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
320\r
8536cc4b 321 if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
322 if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {\r
323 return EFI_SUCCESS;\r
324 } else {\r
325 return EFI_DEVICE_ERROR;\r
326 }\r
a41b5272 327 }\r
8536cc4b 328 return EFI_SUCCESS;\r
a41b5272 329}\r
330\r
331/**\r
332 This function is used to poll for the DRQ bit clear in the Status\r
333 Register. DRQ is cleared when the device is finished transferring data.\r
334 So this function is called after data transfer is finished.\r
335\r
8536cc4b 336 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 337 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 338 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 339\r
340 @retval EFI_SUCCESS DRQ bit clear within the time out.\r
341\r
342 @retval EFI_TIMEOUT DRQ bit not clear within the time out.\r
343\r
344 @note\r
345 Read Status Register will clear interrupt status.\r
346\r
347**/\r
348EFI_STATUS\r
349EFIAPI\r
350DRQClear (\r
351 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
352 IN EFI_IDE_REGISTERS *IdeRegisters,\r
353 IN UINT64 Timeout\r
354 )\r
355{\r
356 UINT32 Delay;\r
357 UINT8 StatusRegister;\r
a41b5272 358\r
359 ASSERT (PciIo != NULL);\r
360 ASSERT (IdeRegisters != NULL);\r
361\r
362 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
363 do {\r
364 StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
365\r
366 //\r
8536cc4b 367 // Wait for BSY == 0, then judge if DRQ is clear\r
a41b5272 368 //\r
8536cc4b 369 if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
370 if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
371 return EFI_DEVICE_ERROR;\r
372 } else {\r
373 return EFI_SUCCESS;\r
a41b5272 374 }\r
375 }\r
376\r
377 //\r
8536cc4b 378 // Stall for 100 microseconds.\r
a41b5272 379 //\r
380 MicroSecondDelay (100);\r
381\r
382 Delay--;\r
383\r
384 } while (Delay > 0);\r
385\r
8536cc4b 386 return EFI_TIMEOUT;\r
a41b5272 387}\r
388/**\r
389 This function is used to poll for the DRQ bit clear in the Alternate\r
390 Status Register. DRQ is cleared when the device is finished\r
391 transferring data. So this function is called after data transfer\r
392 is finished.\r
393\r
8536cc4b 394 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 395 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 396 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 397\r
398 @retval EFI_SUCCESS DRQ bit clear within the time out.\r
399\r
400 @retval EFI_TIMEOUT DRQ bit not clear within the time out.\r
401 @note Read Alternate Status Register will not clear interrupt status.\r
402\r
403**/\r
404EFI_STATUS\r
405EFIAPI\r
406DRQClear2 (\r
407 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
408 IN EFI_IDE_REGISTERS *IdeRegisters,\r
409 IN UINT64 Timeout\r
410 )\r
411{\r
412 UINT32 Delay;\r
413 UINT8 AltRegister;\r
a41b5272 414\r
415 ASSERT (PciIo != NULL);\r
416 ASSERT (IdeRegisters != NULL);\r
417\r
418 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
419 do {\r
420 AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
421\r
422 //\r
8536cc4b 423 // Wait for BSY == 0, then judge if DRQ is clear\r
a41b5272 424 //\r
8536cc4b 425 if ((AltRegister & ATA_STSREG_BSY) == 0) {\r
426 if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
427 return EFI_DEVICE_ERROR;\r
428 } else {\r
429 return EFI_SUCCESS;\r
a41b5272 430 }\r
431 }\r
432\r
433 //\r
434 // Stall for 100 microseconds.\r
435 //\r
436 MicroSecondDelay (100);\r
437\r
438 Delay--;\r
439\r
440 } while (Delay > 0);\r
441\r
8536cc4b 442 return EFI_TIMEOUT;\r
a41b5272 443}\r
444\r
445/**\r
446 This function is used to poll for the DRQ bit set in the\r
447 Status Register.\r
448 DRQ is set when the device is ready to transfer data. So this function\r
449 is called after the command is sent to the device and before required\r
450 data is transferred.\r
451\r
8536cc4b 452 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 453 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 454 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 455\r
456 @retval EFI_SUCCESS DRQ bit set within the time out.\r
457 @retval EFI_TIMEOUT DRQ bit not set within the time out.\r
458 @retval EFI_ABORTED DRQ bit not set caused by the command abort.\r
459\r
460 @note Read Status Register will clear interrupt status.\r
461\r
462**/\r
463EFI_STATUS\r
464EFIAPI\r
465DRQReady (\r
466 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
467 IN EFI_IDE_REGISTERS *IdeRegisters,\r
468 IN UINT64 Timeout\r
469 )\r
470{\r
471 UINT32 Delay;\r
472 UINT8 StatusRegister;\r
473 UINT8 ErrorRegister;\r
474\r
475 ASSERT (PciIo != NULL);\r
476 ASSERT (IdeRegisters != NULL);\r
477\r
478 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
479 do {\r
480 //\r
8536cc4b 481 // Read Status Register will clear interrupt\r
a41b5272 482 //\r
483 StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
484\r
485 //\r
8536cc4b 486 // Wait for BSY == 0, then judge if DRQ is clear or ERR is set\r
a41b5272 487 //\r
8536cc4b 488 if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
489 if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
490 ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
a41b5272 491\r
8536cc4b 492 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
493 return EFI_ABORTED;\r
494 }\r
495 return EFI_DEVICE_ERROR;\r
496 }\r
a41b5272 497\r
8536cc4b 498 if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
499 return EFI_SUCCESS;\r
500 } else {\r
501 return EFI_NOT_READY;\r
a41b5272 502 }\r
503 }\r
504\r
505 //\r
506 // Stall for 100 microseconds.\r
507 //\r
508 MicroSecondDelay (100);\r
509\r
510 Delay--;\r
511 } while (Delay > 0);\r
512\r
8536cc4b 513 return EFI_TIMEOUT;\r
a41b5272 514}\r
515/**\r
516 This function is used to poll for the DRQ bit set in the Alternate Status Register.\r
1aff716a 517 DRQ is set when the device is ready to transfer data. So this function is called after\r
a41b5272 518 the command is sent to the device and before required data is transferred.\r
519\r
8536cc4b 520 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 521 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 522 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 523\r
524 @retval EFI_SUCCESS DRQ bit set within the time out.\r
525 @retval EFI_TIMEOUT DRQ bit not set within the time out.\r
526 @retval EFI_ABORTED DRQ bit not set caused by the command abort.\r
527 @note Read Alternate Status Register will not clear interrupt status.\r
528\r
529**/\r
530EFI_STATUS\r
531EFIAPI\r
532DRQReady2 (\r
533 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
534 IN EFI_IDE_REGISTERS *IdeRegisters,\r
535 IN UINT64 Timeout\r
536 )\r
537{\r
538 UINT32 Delay;\r
539 UINT8 AltRegister;\r
540 UINT8 ErrorRegister;\r
541\r
542 ASSERT (PciIo != NULL);\r
543 ASSERT (IdeRegisters != NULL);\r
544\r
545 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
546\r
547 do {\r
548 //\r
8536cc4b 549 // Read Alternate Status Register will not clear interrupt status\r
a41b5272 550 //\r
551 AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
552 //\r
8536cc4b 553 // Wait for BSY == 0, then judge if DRQ is clear or ERR is set\r
a41b5272 554 //\r
8536cc4b 555 if ((AltRegister & ATA_STSREG_BSY) == 0) {\r
556 if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
557 ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
a41b5272 558\r
8536cc4b 559 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
560 return EFI_ABORTED;\r
561 }\r
562 return EFI_DEVICE_ERROR;\r
563 }\r
a41b5272 564\r
8536cc4b 565 if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
566 return EFI_SUCCESS;\r
567 } else {\r
568 return EFI_NOT_READY;\r
a41b5272 569 }\r
570 }\r
571\r
572 //\r
573 // Stall for 100 microseconds.\r
574 //\r
575 MicroSecondDelay (100);\r
576\r
577 Delay--;\r
578 } while (Delay > 0);\r
579\r
8536cc4b 580 return EFI_TIMEOUT;\r
a41b5272 581}\r
582\r
583/**\r
584 This function is used to poll for the DRDY bit set in the Status Register. DRDY\r
1aff716a 585 bit is set when the device is ready to accept command. Most ATA commands must be\r
a41b5272 586 sent after DRDY set except the ATAPI Packet Command.\r
587\r
8536cc4b 588 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 589 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 590 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 591\r
592 @retval EFI_SUCCESS DRDY bit set within the time out.\r
593 @retval EFI_TIMEOUT DRDY bit not set within the time out.\r
594\r
595 @note Read Status Register will clear interrupt status.\r
596**/\r
597EFI_STATUS\r
598EFIAPI\r
599DRDYReady (\r
600 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
601 IN EFI_IDE_REGISTERS *IdeRegisters,\r
602 IN UINT64 Timeout\r
603 )\r
604{\r
605 UINT32 Delay;\r
606 UINT8 StatusRegister;\r
607 UINT8 ErrorRegister;\r
608\r
609 ASSERT (PciIo != NULL);\r
610 ASSERT (IdeRegisters != NULL);\r
611\r
612 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
613 do {\r
614 StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
615 //\r
8536cc4b 616 // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
a41b5272 617 //\r
8536cc4b 618 if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
619 if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
620 ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
a41b5272 621\r
8536cc4b 622 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
623 return EFI_ABORTED;\r
624 }\r
625 return EFI_DEVICE_ERROR;\r
626 }\r
a41b5272 627\r
8536cc4b 628 if ((StatusRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
629 return EFI_SUCCESS;\r
630 } else {\r
631 return EFI_DEVICE_ERROR;\r
a41b5272 632 }\r
633 }\r
634\r
635 //\r
636 // Stall for 100 microseconds.\r
637 //\r
638 MicroSecondDelay (100);\r
639\r
640 Delay--;\r
641 } while (Delay > 0);\r
642\r
8536cc4b 643 return EFI_TIMEOUT;\r
a41b5272 644}\r
645\r
646/**\r
1aff716a 647 This function is used to poll for the DRDY bit set in the Alternate Status Register.\r
648 DRDY bit is set when the device is ready to accept command. Most ATA commands must\r
a41b5272 649 be sent after DRDY set except the ATAPI Packet Command.\r
650\r
8536cc4b 651 @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
a41b5272 652 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 653 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 654\r
655 @retval EFI_SUCCESS DRDY bit set within the time out.\r
656 @retval EFI_TIMEOUT DRDY bit not set within the time out.\r
657\r
658 @note Read Alternate Status Register will clear interrupt status.\r
659\r
660**/\r
661EFI_STATUS\r
662EFIAPI\r
663DRDYReady2 (\r
664 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
665 IN EFI_IDE_REGISTERS *IdeRegisters,\r
666 IN UINT64 Timeout\r
667 )\r
668{\r
669 UINT32 Delay;\r
670 UINT8 AltRegister;\r
671 UINT8 ErrorRegister;\r
672\r
673 ASSERT (PciIo != NULL);\r
674 ASSERT (IdeRegisters != NULL);\r
675\r
676 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
677 do {\r
678 AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
679 //\r
8536cc4b 680 // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
a41b5272 681 //\r
8536cc4b 682 if ((AltRegister & ATA_STSREG_BSY) == 0) {\r
683 if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
684 ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
a41b5272 685\r
8536cc4b 686 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
687 return EFI_ABORTED;\r
688 }\r
689 return EFI_DEVICE_ERROR;\r
690 }\r
a41b5272 691\r
8536cc4b 692 if ((AltRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
693 return EFI_SUCCESS;\r
694 } else {\r
695 return EFI_DEVICE_ERROR;\r
a41b5272 696 }\r
697 }\r
698\r
699 //\r
700 // Stall for 100 microseconds.\r
701 //\r
702 MicroSecondDelay (100);\r
703\r
704 Delay--;\r
705 } while (Delay > 0);\r
706\r
8536cc4b 707 return EFI_TIMEOUT;\r
a41b5272 708}\r
709\r
710/**\r
711 This function is used to poll for the BSY bit clear in the Status Register. BSY\r
712 is clear when the device is not busy. Every command must be sent after device is not busy.\r
713\r
714 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
715 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 716 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 717\r
718 @retval EFI_SUCCESS BSY bit clear within the time out.\r
719 @retval EFI_TIMEOUT BSY bit not clear within the time out.\r
720\r
721 @note Read Status Register will clear interrupt status.\r
722**/\r
723EFI_STATUS\r
724EFIAPI\r
725WaitForBSYClear (\r
726 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
727 IN EFI_IDE_REGISTERS *IdeRegisters,\r
728 IN UINT64 Timeout\r
729 )\r
730{\r
731 UINT32 Delay;\r
732 UINT8 StatusRegister;\r
733\r
734 ASSERT (PciIo != NULL);\r
735 ASSERT (IdeRegisters != NULL);\r
736\r
737 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
738 do {\r
739 StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
740\r
741 if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {\r
8536cc4b 742 return EFI_SUCCESS;\r
a41b5272 743 }\r
744\r
745 //\r
746 // Stall for 100 microseconds.\r
747 //\r
748 MicroSecondDelay (100);\r
749\r
750 Delay--;\r
751\r
752 } while (Delay > 0);\r
753\r
8536cc4b 754 return EFI_TIMEOUT;\r
a41b5272 755}\r
756\r
757/**\r
758 This function is used to poll for the BSY bit clear in the Status Register. BSY\r
759 is clear when the device is not busy. Every command must be sent after device is not busy.\r
760\r
761 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
762 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 763 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 764\r
765 @retval EFI_SUCCESS BSY bit clear within the time out.\r
766 @retval EFI_TIMEOUT BSY bit not clear within the time out.\r
767\r
768 @note Read Status Register will clear interrupt status.\r
769**/\r
770EFI_STATUS\r
771EFIAPI\r
772WaitForBSYClear2 (\r
773 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
774 IN EFI_IDE_REGISTERS *IdeRegisters,\r
775 IN UINT64 Timeout\r
776 )\r
777{\r
778 UINT32 Delay;\r
779 UINT8 AltStatusRegister;\r
780\r
781 ASSERT (PciIo != NULL);\r
782 ASSERT (IdeRegisters != NULL);\r
783\r
784 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
785 do {\r
786 AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
787\r
788 if ((AltStatusRegister & ATA_STSREG_BSY) == 0x00) {\r
8536cc4b 789 return EFI_SUCCESS;\r
a41b5272 790 }\r
791\r
792 //\r
793 // Stall for 100 microseconds.\r
794 //\r
795 MicroSecondDelay (100);\r
796\r
797 Delay--;\r
798\r
799 } while (Delay > 0);\r
800\r
8536cc4b 801 return EFI_TIMEOUT;\r
a41b5272 802}\r
803\r
804/**\r
1aff716a 805 Get IDE i/o port registers' base addresses by mode.\r
a41b5272 806\r
807 In 'Compatibility' mode, use fixed addresses.\r
808 In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's\r
809 Configuration Space.\r
810\r
811 The steps to get IDE i/o port registers' base addresses for each channel\r
812 as follows:\r
813\r
814 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE\r
815 controller's Configuration Space to determine the operating mode.\r
816\r
817 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.\r
818 ___________________________________________\r
819 | | Command Block | Control Block |\r
820 | Channel | Registers | Registers |\r
821 |___________|_______________|_______________|\r
822 | Primary | 1F0h - 1F7h | 3F6h - 3F7h |\r
823 |___________|_______________|_______________|\r
824 | Secondary | 170h - 177h | 376h - 377h |\r
825 |___________|_______________|_______________|\r
826\r
827 Table 1. Compatibility resource mappings\r
1aff716a 828\r
a41b5272 829 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs\r
830 in IDE controller's PCI Configuration Space, shown in the Table 2 below.\r
831 ___________________________________________________\r
832 | | Command Block | Control Block |\r
833 | Channel | Registers | Registers |\r
834 |___________|___________________|___________________|\r
835 | Primary | BAR at offset 0x10| BAR at offset 0x14|\r
836 |___________|___________________|___________________|\r
837 | Secondary | BAR at offset 0x18| BAR at offset 0x1C|\r
838 |___________|___________________|___________________|\r
839\r
840 Table 2. BARs for Register Mapping\r
841\r
842 @param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
843 @param[in, out] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to\r
844 store the IDE i/o port registers' base addresses\r
1aff716a 845\r
a41b5272 846 @retval EFI_UNSUPPORTED Return this value when the BARs is not IO type\r
847 @retval EFI_SUCCESS Get the Base address successfully\r
848 @retval Other Read the pci configureation data error\r
849\r
850**/\r
851EFI_STATUS\r
852EFIAPI\r
853GetIdeRegisterIoAddr (\r
854 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
855 IN OUT EFI_IDE_REGISTERS *IdeRegisters\r
856 )\r
857{\r
858 EFI_STATUS Status;\r
859 PCI_TYPE00 PciData;\r
860 UINT16 CommandBlockBaseAddr;\r
861 UINT16 ControlBlockBaseAddr;\r
862 UINT16 BusMasterBaseAddr;\r
863\r
864 if ((PciIo == NULL) || (IdeRegisters == NULL)) {\r
865 return EFI_INVALID_PARAMETER;\r
866 }\r
867\r
868 Status = PciIo->Pci.Read (\r
869 PciIo,\r
870 EfiPciIoWidthUint8,\r
871 0,\r
872 sizeof (PciData),\r
873 &PciData\r
874 );\r
875\r
876 if (EFI_ERROR (Status)) {\r
877 return Status;\r
878 }\r
879\r
880 BusMasterBaseAddr = (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
881\r
882 if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {\r
883 CommandBlockBaseAddr = 0x1f0;\r
884 ControlBlockBaseAddr = 0x3f6;\r
885 } else {\r
886 //\r
887 // The BARs should be of IO type\r
888 //\r
889 if ((PciData.Device.Bar[0] & BIT0) == 0 ||\r
890 (PciData.Device.Bar[1] & BIT0) == 0) {\r
891 return EFI_UNSUPPORTED;\r
892 }\r
893\r
894 CommandBlockBaseAddr = (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);\r
895 ControlBlockBaseAddr = (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);\r
896 }\r
897\r
898 //\r
899 // Calculate IDE primary channel I/O register base address.\r
900 //\r
901 IdeRegisters[EfiIdePrimary].Data = CommandBlockBaseAddr;\r
902 IdeRegisters[EfiIdePrimary].ErrOrFeature = (UINT16) (CommandBlockBaseAddr + 0x01);\r
903 IdeRegisters[EfiIdePrimary].SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
904 IdeRegisters[EfiIdePrimary].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
905 IdeRegisters[EfiIdePrimary].CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
906 IdeRegisters[EfiIdePrimary].CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
907 IdeRegisters[EfiIdePrimary].Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
908 IdeRegisters[EfiIdePrimary].CmdOrStatus = (UINT16) (CommandBlockBaseAddr + 0x07);\r
909 IdeRegisters[EfiIdePrimary].AltOrDev = ControlBlockBaseAddr;\r
910 IdeRegisters[EfiIdePrimary].BusMasterBaseAddr = BusMasterBaseAddr;\r
911\r
912 if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {\r
913 CommandBlockBaseAddr = 0x170;\r
914 ControlBlockBaseAddr = 0x376;\r
915 } else {\r
916 //\r
917 // The BARs should be of IO type\r
918 //\r
919 if ((PciData.Device.Bar[2] & BIT0) == 0 ||\r
920 (PciData.Device.Bar[3] & BIT0) == 0) {\r
921 return EFI_UNSUPPORTED;\r
922 }\r
923\r
924 CommandBlockBaseAddr = (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);\r
925 ControlBlockBaseAddr = (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);\r
926 }\r
927\r
928 //\r
929 // Calculate IDE secondary channel I/O register base address.\r
930 //\r
931 IdeRegisters[EfiIdeSecondary].Data = CommandBlockBaseAddr;\r
932 IdeRegisters[EfiIdeSecondary].ErrOrFeature = (UINT16) (CommandBlockBaseAddr + 0x01);\r
933 IdeRegisters[EfiIdeSecondary].SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
934 IdeRegisters[EfiIdeSecondary].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
935 IdeRegisters[EfiIdeSecondary].CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
936 IdeRegisters[EfiIdeSecondary].CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
937 IdeRegisters[EfiIdeSecondary].Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
938 IdeRegisters[EfiIdeSecondary].CmdOrStatus = (UINT16) (CommandBlockBaseAddr + 0x07);\r
939 IdeRegisters[EfiIdeSecondary].AltOrDev = ControlBlockBaseAddr;\r
aca84419 940 IdeRegisters[EfiIdeSecondary].BusMasterBaseAddr = (UINT16) (BusMasterBaseAddr + 0x8);\r
a41b5272 941\r
942 return EFI_SUCCESS;\r
943}\r
944\r
945/**\r
946 This function is used to implement the Soft Reset on the specified device. But,\r
1aff716a 947 the ATA Soft Reset mechanism is so strong a reset method that it will force\r
a41b5272 948 resetting on both devices connected to the same cable.\r
949\r
950 It is called by IdeBlkIoReset(), a interface function of Block\r
951 I/O protocol.\r
952\r
953 This function can also be used by the ATAPI device to perform reset when\r
954 ATAPI Reset command is failed.\r
955\r
956 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
957 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
8536cc4b 958 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 959\r
960 @retval EFI_SUCCESS Soft reset completes successfully.\r
961 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
962\r
963 @note The registers initial values after ATA soft reset are different\r
964 to the ATA device and ATAPI device.\r
965**/\r
966EFI_STATUS\r
967EFIAPI\r
968AtaSoftReset (\r
969 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
970 IN EFI_IDE_REGISTERS *IdeRegisters,\r
971 IN UINT64 Timeout\r
972 )\r
973{\r
974 UINT8 DeviceControl;\r
975\r
976 DeviceControl = 0;\r
977 //\r
978 // disable Interrupt and set SRST bit to initiate soft reset\r
979 //\r
980 DeviceControl = ATA_CTLREG_SRST | ATA_CTLREG_IEN_L;\r
981\r
982 IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
983\r
984 //\r
985 // SRST should assert for at least 5 us, we use 10 us for\r
986 // better compatibility\r
987 //\r
988 MicroSecondDelay (10);\r
989\r
990 //\r
991 // Enable interrupt to support UDMA, and clear SRST bit\r
992 //\r
993 DeviceControl = 0;\r
994 IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
995\r
996 //\r
997 // Wait for at least 10 ms to check BSY status, we use 10 ms\r
998 // for better compatibility\r
1aff716a 999 //\r
a41b5272 1000 MicroSecondDelay (10000);\r
1001\r
1002 //\r
1003 // slave device needs at most 31ms to clear BSY\r
1004 //\r
1005 if (WaitForBSYClear (PciIo, IdeRegisters, Timeout) == EFI_TIMEOUT) {\r
1006 return EFI_DEVICE_ERROR;\r
1007 }\r
1008\r
1009 return EFI_SUCCESS;\r
1010}\r
1011\r
1012/**\r
1013 Send ATA Ext command into device with NON_DATA protocol.\r
1014\r
1015 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
1016 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1017 @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
8536cc4b 1018 @param Timeout The time to complete the command, uses 100ns as a unit.\r
a41b5272 1019\r
1020 @retval EFI_SUCCESS Reading succeed\r
1021 @retval EFI_DEVICE_ERROR Error executing commands on this device.\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025EFIAPI\r
1026AtaIssueCommand (\r
1027 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1028 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1029 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
1030 IN UINT64 Timeout\r
1031 )\r
1032{\r
1033 EFI_STATUS Status;\r
1034 UINT8 DeviceHead;\r
1035 UINT8 AtaCommand;\r
1036\r
1037 ASSERT (PciIo != NULL);\r
1038 ASSERT (IdeRegisters != NULL);\r
1039 ASSERT (AtaCommandBlock != NULL);\r
1040\r
1041 DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
1042 AtaCommand = AtaCommandBlock->AtaCommand;\r
1043\r
1044 Status = WaitForBSYClear (PciIo, IdeRegisters, Timeout);\r
1045 if (EFI_ERROR (Status)) {\r
1046 return EFI_DEVICE_ERROR;\r
1047 }\r
1048\r
1049 //\r
1050 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1051 //\r
1052 IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8) (0xe0 | DeviceHead));\r
1053\r
1054 //\r
1055 // set all the command parameters\r
1056 // Before write to all the following registers, BSY and DRQ must be 0.\r
1057 //\r
1058 Status = DRQClear2 (PciIo, IdeRegisters, Timeout);\r
1059 if (EFI_ERROR (Status)) {\r
1060 return EFI_DEVICE_ERROR;\r
1061 }\r
1062\r
1063 //\r
1064 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1065 //\r
1066 IdeWritePortB (PciIo, IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeaturesExp);\r
1067 IdeWritePortB (PciIo, IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeatures);\r
1068\r
1069 //\r
1070 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1071 //\r
1072 IdeWritePortB (PciIo, IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCountExp);\r
1073 IdeWritePortB (PciIo, IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCount);\r
1074\r
1075 //\r
1076 // Fill the start LBA registers, which are also two-byte FIFO\r
1077 //\r
1078 IdeWritePortB (PciIo, IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumberExp);\r
1079 IdeWritePortB (PciIo, IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumber);\r
1080\r
1081 IdeWritePortB (PciIo, IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLowExp);\r
1082 IdeWritePortB (PciIo, IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLow);\r
1083\r
1084 IdeWritePortB (PciIo, IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHighExp);\r
1085 IdeWritePortB (PciIo, IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHigh);\r
1086\r
1087 //\r
1088 // Send command via Command Register\r
1089 //\r
1090 IdeWritePortB (PciIo, IdeRegisters->CmdOrStatus, AtaCommand);\r
1091\r
1092 //\r
1093 // Stall at least 400 microseconds.\r
1094 //\r
1095 MicroSecondDelay (400);\r
1096\r
1097 return EFI_SUCCESS;\r
1098}\r
1099\r
1100/**\r
1101 This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
1102\r
490b5ea1 1103 @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
1104 structure.\r
1105 @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1106 @param[in, out] Buffer A pointer to the source buffer for the data.\r
1107 @param[in] ByteCount The length of the data.\r
86d8e199 1108 @param[in] Read Flag used to determine the data transfer direction.\r
490b5ea1 1109 Read equals 1, means data transferred from device\r
1110 to host;Read equals 0, means data transferred\r
1111 from host to device.\r
1112 @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
86d8e199 1113 @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
8536cc4b 1114 @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
490b5ea1 1115 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
1116 used by non-blocking mode.\r
1aff716a 1117\r
a41b5272 1118 @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
1119 @retval EFI_DEVICE_ERROR command sent failed.\r
1120\r
1121**/\r
1122EFI_STATUS\r
1123EFIAPI\r
1aff716a 1124AtaPioDataInOut (\r
a41b5272 1125 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1126 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1127 IN OUT VOID *Buffer,\r
1128 IN UINT64 ByteCount,\r
1129 IN BOOLEAN Read,\r
1130 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
1131 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
490b5ea1 1132 IN UINT64 Timeout,\r
1133 IN ATA_NONBLOCK_TASK *Task\r
a41b5272 1134 )\r
1135{\r
1136 UINTN WordCount;\r
1137 UINTN Increment;\r
1138 UINT16 *Buffer16;\r
1139 EFI_STATUS Status;\r
1140\r
1141 if ((PciIo == NULL) || (IdeRegisters == NULL) || (Buffer == NULL) || (AtaCommandBlock == NULL)) {\r
1142 return EFI_INVALID_PARAMETER;\r
1143 }\r
1144\r
1145 //\r
1146 // Issue ATA command\r
1147 //\r
1148 Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
1149 if (EFI_ERROR (Status)) {\r
1150 Status = EFI_DEVICE_ERROR;\r
1151 goto Exit;\r
1152 }\r
1153\r
1154 Buffer16 = (UINT16 *) Buffer;\r
1155\r
1156 //\r
1157 // According to PIO data in protocol, host can perform a series of reads to\r
1158 // the data register after each time device set DRQ ready;\r
1159 // The data size of "a series of read" is command specific.\r
1160 // For most ATA command, data size received from device will not exceed\r
1161 // 1 sector, hence the data size for "a series of read" can be the whole data\r
1162 // size of one command request.\r
1163 // For ATA command such as Read Sector command, the data size of one ATA\r
1164 // command request is often larger than 1 sector, according to the\r
1165 // Read Sector command, the data size of "a series of read" is exactly 1\r
1166 // sector.\r
1167 // Here for simplification reason, we specify the data size for\r
1168 // "a series of read" to 1 sector (256 words) if data size of one ATA command\r
1169 // request is larger than 256 words.\r
1170 //\r
1171 Increment = 256;\r
1172\r
1173 //\r
1174 // used to record bytes of currently transfered data\r
1175 //\r
1176 WordCount = 0;\r
1177\r
1178 while (WordCount < RShiftU64(ByteCount, 1)) {\r
1179 //\r
1180 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready\r
1181 //\r
1182 Status = DRQReady2 (PciIo, IdeRegisters, Timeout);\r
1aff716a 1183 if (EFI_ERROR (Status)) {\r
a41b5272 1184 Status = EFI_DEVICE_ERROR;\r
1185 goto Exit;\r
1186 }\r
1187\r
1188 //\r
1189 // Get the byte count for one series of read\r
1190 //\r
1191 if ((WordCount + Increment) > RShiftU64(ByteCount, 1)) {\r
1192 Increment = (UINTN)(RShiftU64(ByteCount, 1) - WordCount);\r
1193 }\r
1194\r
1195 if (Read) {\r
1196 IdeReadPortWMultiple (\r
1197 PciIo,\r
1198 IdeRegisters->Data,\r
1199 Increment,\r
1200 Buffer16\r
1201 );\r
1202 } else {\r
1203 IdeWritePortWMultiple (\r
1204 PciIo,\r
1205 IdeRegisters->Data,\r
1206 Increment,\r
1207 Buffer16\r
1208 );\r
1209 }\r
1210\r
1211 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1212 if (EFI_ERROR (Status)) {\r
1213 Status = EFI_DEVICE_ERROR;\r
1214 goto Exit;\r
1215 }\r
1216\r
1217 WordCount += Increment;\r
1218 Buffer16 += Increment;\r
1219 }\r
1220\r
1221 Status = DRQClear (PciIo, IdeRegisters, Timeout);\r
1222 if (EFI_ERROR (Status)) {\r
1223 Status = EFI_DEVICE_ERROR;\r
1224 goto Exit;\r
1225 }\r
1226\r
1227Exit:\r
1228 //\r
1229 // Dump All Ide registers to ATA_STATUS_BLOCK\r
1230 //\r
1231 DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
1232\r
490b5ea1 1233 //\r
1234 // Not support the Non-blocking now,just do the blocking process.\r
1235 //\r
a41b5272 1236 return Status;\r
1237}\r
1238\r
1239/**\r
1240 Send ATA command into device with NON_DATA protocol\r
1241\r
490b5ea1 1242 @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE\r
1243 data structure.\r
1244 @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1245 @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data\r
1246 structure.\r
1247 @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
8536cc4b 1248 @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
490b5ea1 1249 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
1250 used by non-blocking mode.\r
a41b5272 1251\r
1252 @retval EFI_SUCCESS Reading succeed\r
1253 @retval EFI_ABORTED Command failed\r
1254 @retval EFI_DEVICE_ERROR Device status error.\r
1255\r
1256**/\r
1257EFI_STATUS\r
1258EFIAPI\r
1aff716a 1259AtaNonDataCommandIn (\r
a41b5272 1260 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1261 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1262 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
1263 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
490b5ea1 1264 IN UINT64 Timeout,\r
1265 IN ATA_NONBLOCK_TASK *Task\r
a41b5272 1266 )\r
1267{\r
1268 EFI_STATUS Status;\r
1269\r
1270 if ((PciIo == NULL) || (IdeRegisters == NULL) || (AtaCommandBlock == NULL)) {\r
1271 return EFI_INVALID_PARAMETER;\r
1272 }\r
1273\r
1274 //\r
1275 // Issue ATA command\r
1276 //\r
1277 Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
1278 if (EFI_ERROR (Status)) {\r
1279 Status = EFI_DEVICE_ERROR;\r
1280 goto Exit;\r
1281 }\r
1282\r
1283 //\r
1284 // Wait for command completion\r
1285 //\r
1286 Status = WaitForBSYClear (PciIo, IdeRegisters, Timeout);\r
1287 if (EFI_ERROR (Status)) {\r
1288 Status = EFI_DEVICE_ERROR;\r
1289 goto Exit;\r
1290 }\r
1aff716a 1291\r
a41b5272 1292 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1293 if (EFI_ERROR (Status)) {\r
1294 Status = EFI_DEVICE_ERROR;\r
1295 goto Exit;\r
1296 }\r
1297\r
1298Exit:\r
1299 //\r
1300 // Dump All Ide registers to ATA_STATUS_BLOCK\r
1301 //\r
1302 DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
1aff716a 1303\r
490b5ea1 1304 //\r
1305 // Not support the Non-blocking now,just do the blocking process.\r
1306 //\r
1307 return Status;\r
1308}\r
1309\r
1310/**\r
1311 Wait for memory to be set.\r
1aff716a 1312\r
490b5ea1 1313 @param[in] PciIo The PCI IO protocol instance.\r
8536cc4b 1314 @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
490b5ea1 1315\r
1316 @retval EFI_DEVICE_ERROR The memory is not set.\r
1317 @retval EFI_TIMEOUT The memory setting is time out.\r
1318 @retval EFI_SUCCESS The memory is correct set.\r
1319\r
1320**/\r
1321EFI_STATUS\r
1322AtaUdmStatusWait (\r
1323 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
8536cc4b 1324 IN EFI_IDE_REGISTERS *IdeRegisters\r
1aff716a 1325 )\r
490b5ea1 1326{\r
1327 UINT8 RegisterValue;\r
1328 EFI_STATUS Status;\r
8536cc4b 1329 UINT16 IoPortForBmis;\r
490b5ea1 1330 UINT64 Timeout;\r
1331\r
1332 Timeout = 2000;\r
1333\r
1334 while (TRUE) {\r
8536cc4b 1335 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1336 if (EFI_ERROR (Status)) {\r
1337 Status = EFI_DEVICE_ERROR;\r
1338 break;\r
1339 }\r
490b5ea1 1340\r
8536cc4b 1341 IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
1342 RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
490b5ea1 1343 if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
1344 DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
1345 Status = EFI_DEVICE_ERROR;\r
1346 break;\r
1347 }\r
1348\r
1349 if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
1350 Status = EFI_SUCCESS;\r
490b5ea1 1351 break;\r
1352 }\r
1353 //\r
1354 // Stall for 1 milliseconds.\r
1355 //\r
1356 MicroSecondDelay (1000);\r
1357 Timeout--;\r
1358 }\r
a41b5272 1359\r
1360 return Status;\r
1361}\r
1362\r
490b5ea1 1363/**\r
1364 Check if the memory to be set.\r
1aff716a 1365\r
490b5ea1 1366 @param[in] PciIo The PCI IO protocol instance.\r
1367 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
1368 used by non-blocking mode.\r
8536cc4b 1369 @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
490b5ea1 1370\r
1371 @retval EFI_DEVICE_ERROR The memory setting met a issue.\r
1372 @retval EFI_NOT_READY The memory is not set.\r
1373 @retval EFI_TIMEOUT The memory setting is time out.\r
1374 @retval EFI_SUCCESS The memory is correct set.\r
1375\r
1376**/\r
1377EFI_STATUS\r
1378AtaUdmStatusCheck (\r
1379 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1380 IN ATA_NONBLOCK_TASK *Task,\r
8536cc4b 1381 IN EFI_IDE_REGISTERS *IdeRegisters\r
490b5ea1 1382 )\r
1383{\r
8536cc4b 1384 UINT8 RegisterValue;\r
1385 UINT16 IoPortForBmis;\r
1386 EFI_STATUS Status;\r
490b5ea1 1387\r
1388 Task->RetryTimes--;\r
8536cc4b 1389\r
1390 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1391 if (EFI_ERROR (Status)) {\r
1392 return EFI_DEVICE_ERROR;\r
1393 }\r
1394\r
1395 IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
1396 RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
490b5ea1 1397\r
1398 if ((RegisterValue & BMIS_ERROR) != 0) {\r
1399 DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
1400 return EFI_DEVICE_ERROR;\r
1401 }\r
1402\r
1403 if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
490b5ea1 1404 return EFI_SUCCESS;\r
1405 }\r
1406\r
1407 if (Task->RetryTimes == 0) {\r
1408 return EFI_TIMEOUT;\r
1409 } else {\r
1410 //\r
1411 // The memory is not set.\r
1412 //\r
1413 return EFI_NOT_READY;\r
1414 }\r
1415}\r
a41b5272 1416\r
1417/**\r
1418 Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
1419\r
490b5ea1 1420 @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
1421 structure.\r
1422 @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1423 @param[in] Read Flag used to determine the data transfer\r
1424 direction. Read equals 1, means data transferred\r
1425 from device to host;Read equals 0, means data\r
1426 transferred from host to device.\r
1427 @param[in] DataBuffer A pointer to the source buffer for the data.\r
1428 @param[in] DataLength The length of the data.\r
1429 @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
1430 @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
8536cc4b 1431 @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
490b5ea1 1432 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
1433 used by non-blocking mode.\r
a41b5272 1434\r
1435 @retval EFI_SUCCESS the operation is successful.\r
1436 @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
1437 @retval EFI_UNSUPPORTED Unknown channel or operations command\r
1438 @retval EFI_DEVICE_ERROR Ata command execute failed\r
1439\r
1440**/\r
1441EFI_STATUS\r
1442EFIAPI\r
1443AtaUdmaInOut (\r
490b5ea1 1444 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
1445 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1446 IN BOOLEAN Read,\r
1447 IN VOID *DataBuffer,\r
1448 IN UINT64 DataLength,\r
1449 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
1450 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
1451 IN UINT64 Timeout,\r
1452 IN ATA_NONBLOCK_TASK *Task\r
a41b5272 1453 )\r
1454{\r
1455 EFI_STATUS Status;\r
1456 UINT16 IoPortForBmic;\r
1457 UINT16 IoPortForBmis;\r
1458 UINT16 IoPortForBmid;\r
1459\r
a41b5272 1460 UINTN PrdTableSize;\r
1461 EFI_PHYSICAL_ADDRESS PrdTableMapAddr;\r
1462 VOID *PrdTableMap;\r
490b5ea1 1463 EFI_ATA_DMA_PRD *PrdBaseAddr;\r
2525e221 1464 EFI_ATA_DMA_PRD *TempPrdBaseAddr;\r
490b5ea1 1465 UINTN PrdTableNum;\r
a41b5272 1466\r
490b5ea1 1467 UINT8 RegisterValue;\r
a41b5272 1468 UINTN PageCount;\r
1469 UINTN ByteCount;\r
1470 UINTN ByteRemaining;\r
a41b5272 1471 UINT8 DeviceControl;\r
1472\r
1473 VOID *BufferMap;\r
1474 EFI_PHYSICAL_ADDRESS BufferMapAddress;\r
1475 EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;\r
1476\r
1477 UINT8 DeviceHead;\r
490b5ea1 1478 EFI_PCI_IO_PROTOCOL *PciIo;\r
1479 EFI_TPL OldTpl;\r
a41b5272 1480\r
490b5ea1 1481\r
1482 Status = EFI_SUCCESS;\r
1483 PrdBaseAddr = NULL;\r
1484 PrdTableMap = NULL;\r
1485 BufferMap = NULL;\r
1486 PageCount = 0;\r
1487 PciIo = Instance->PciIo;\r
a41b5272 1488\r
1489 if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {\r
1490 return EFI_INVALID_PARAMETER;\r
1491 }\r
1492\r
490b5ea1 1493 //\r
1494 // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
1495 // BlockIO tasks.\r
1496 // Delay 1ms to simulate the blocking time out checking.\r
1497 //\r
1aff716a 1498 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
490b5ea1 1499 while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
490b5ea1 1500 AsyncNonBlockingTransferRoutine (NULL, Instance);\r
490b5ea1 1501 //\r
1502 // Stall for 1 milliseconds.\r
1503 //\r
1504 MicroSecondDelay (1000);\r
1aff716a 1505 }\r
1506 gBS->RestoreTPL (OldTpl);\r
490b5ea1 1507\r
a41b5272 1508 //\r
1509 // The data buffer should be even alignment\r
1510 //\r
1511 if (((UINTN)DataBuffer & 0x1) != 0) {\r
1512 return EFI_INVALID_PARAMETER;\r
1513 }\r
1514\r
1515 //\r
490b5ea1 1516 // Set relevant IO Port address.\r
a41b5272 1517 //\r
490b5ea1 1518 IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
1519 IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
1520 IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
a41b5272 1521\r
1522 //\r
1aff716a 1523 // For Blocking mode, start the command.\r
490b5ea1 1524 // For non-blocking mode, when the command is not started, start it, otherwise\r
1525 // go to check the status.\r
1aff716a 1526 //\r
490b5ea1 1527 if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {\r
1528 //\r
1529 // Calculate the number of PRD entry.\r
1530 // Every entry in PRD table can specify a 64K memory region.\r
1531 //\r
1532 PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
a41b5272 1533\r
490b5ea1 1534 //\r
1535 // Make sure that the memory region of PRD table is not cross 64K boundary\r
1536 //\r
1537 PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
1538 if (PrdTableSize > 0x10000) {\r
1539 return EFI_INVALID_PARAMETER;\r
1540 }\r
a41b5272 1541\r
490b5ea1 1542 //\r
1543 // Allocate buffer for PRD table initialization.\r
1544 //\r
1545 PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
1546 Status = PciIo->AllocateBuffer (\r
1547 PciIo,\r
1548 AllocateAnyPages,\r
1549 EfiBootServicesData,\r
1550 PageCount,\r
1551 (VOID **)&PrdBaseAddr,\r
1552 0\r
1553 );\r
1554 if (EFI_ERROR (Status)) {\r
1555 return EFI_OUT_OF_RESOURCES;\r
1556 }\r
a41b5272 1557\r
490b5ea1 1558 ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
1559 Status = PciIo->Map (\r
1560 PciIo,\r
1561 EfiPciIoOperationBusMasterCommonBuffer,\r
1562 PrdBaseAddr,\r
1563 &ByteCount,\r
1564 &PrdTableMapAddr,\r
1565 &PrdTableMap\r
1566 );\r
1567 if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
1568 //\r
1569 // If the data length actually mapped is not equal to the requested amount,\r
1570 // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
1571 // Can't handle this case.\r
1572 //\r
1573 PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
1574 return EFI_OUT_OF_RESOURCES;\r
1575 }\r
a41b5272 1576\r
490b5ea1 1577 ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
a41b5272 1578\r
490b5ea1 1579 //\r
1580 // Map the host address of DataBuffer to DMA master address.\r
1581 //\r
1582 if (Read) {\r
1583 PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
1584 } else {\r
1585 PciIoOperation = EfiPciIoOperationBusMasterRead;\r
1586 }\r
a41b5272 1587\r
490b5ea1 1588 ByteCount = (UINTN)DataLength;\r
1589 Status = PciIo->Map (\r
1590 PciIo,\r
1591 PciIoOperation,\r
1592 DataBuffer,\r
1593 &ByteCount,\r
1594 &BufferMapAddress,\r
1595 &BufferMap\r
1596 );\r
1597 if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
1598 PciIo->Unmap (PciIo, PrdTableMap);\r
1599 PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
1600 return EFI_OUT_OF_RESOURCES;\r
1601 }\r
1602\r
1603 //\r
1604 // According to Ata spec, it requires the buffer address and size to be even.\r
1605 //\r
1606 ASSERT ((BufferMapAddress & 0x1) == 0);\r
1607 ASSERT ((ByteCount & 0x1) == 0);\r
1608\r
1609 //\r
1610 // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
1611 //\r
2525e221 1612 ByteRemaining = ByteCount;\r
1613 TempPrdBaseAddr = PrdBaseAddr;\r
490b5ea1 1614 while (ByteRemaining != 0) {\r
1615 if (ByteRemaining <= 0x10000) {\r
2525e221 1616 TempPrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
1617 TempPrdBaseAddr->ByteCount = (UINT16) ByteRemaining;\r
1618 TempPrdBaseAddr->EndOfTable = 0x8000;\r
490b5ea1 1619 break;\r
1620 }\r
a41b5272 1621\r
2525e221 1622 TempPrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
1623 TempPrdBaseAddr->ByteCount = (UINT16) 0x0;\r
a41b5272 1624\r
490b5ea1 1625 ByteRemaining -= 0x10000;\r
1626 BufferMapAddress += 0x10000;\r
2525e221 1627 TempPrdBaseAddr++;\r
490b5ea1 1628 }\r
a41b5272 1629\r
490b5ea1 1630 //\r
1631 // Start to enable the DMA operation\r
1632 //\r
1633 DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
a41b5272 1634\r
490b5ea1 1635 IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
a41b5272 1636\r
490b5ea1 1637 //\r
1638 // Enable interrupt to support UDMA\r
1639 //\r
1640 DeviceControl = 0;\r
1641 IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
a41b5272 1642\r
490b5ea1 1643 //\r
1644 // Read BMIS register and clear ERROR and INTR bit\r
1645 //\r
1646 RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
1647 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
8536cc4b 1648 IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
a41b5272 1649\r
490b5ea1 1650 //\r
1651 // Set the base address to BMID register\r
1652 //\r
1653 IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
a41b5272 1654\r
490b5ea1 1655 //\r
1656 // Set BMIC register to identify the operation direction\r
1657 //\r
1658 RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
1659 if (Read) {\r
1660 RegisterValue |= BMIC_NREAD;\r
1661 } else {\r
1662 RegisterValue &= ~((UINT8) BMIC_NREAD);\r
1663 }\r
1664 IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
a41b5272 1665\r
1aff716a 1666 if (Task != NULL) {\r
1667 //\r
1668 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
1669 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
1670 // So set the variable Count to 2000, for about 2 second Timeout time.\r
1671 //\r
1672 Task->RetryTimes = 2000;\r
1673 Task->Map = BufferMap;\r
1674 Task->TableMap = PrdTableMap;\r
1675 Task->MapBaseAddress = PrdBaseAddr;\r
1676 Task->PageCount = PageCount;\r
1677 Task->IsStart = TRUE;\r
1678 }\r
1679\r
490b5ea1 1680 //\r
1681 // Issue ATA command\r
1682 //\r
1683 Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
a41b5272 1684\r
490b5ea1 1685 if (EFI_ERROR (Status)) {\r
1686 Status = EFI_DEVICE_ERROR;\r
1687 goto Exit;\r
1688 }\r
a41b5272 1689\r
8536cc4b 1690 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1691 if (EFI_ERROR (Status)) {\r
1692 Status = EFI_DEVICE_ERROR;\r
1693 goto Exit;\r
1694 }\r
490b5ea1 1695 //\r
1696 // Set START bit of BMIC register\r
1697 //\r
1698 RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
1699 RegisterValue |= BMIC_START;\r
1700 IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
a41b5272 1701\r
a41b5272 1702 }\r
1703\r
a41b5272 1704 //\r
1705 // Check the INTERRUPT and ERROR bit of BMIS\r
1706 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
1707 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
1708 // So set the variable Count to 2000, for about 2 second Timeout time.\r
1709 //\r
490b5ea1 1710 if (Task != NULL) {\r
8536cc4b 1711 Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters);\r
490b5ea1 1712 } else {\r
8536cc4b 1713 Status = AtaUdmStatusWait (PciIo, IdeRegisters);\r
a41b5272 1714 }\r
1715\r
1716 //\r
490b5ea1 1717 // For blocking mode, clear registers and free buffers.\r
1718 // For non blocking mode, when the related registers have been set or time\r
1719 // out, or a error has been happened, it needs to clear the register and free\r
1720 // buffer.\r
a41b5272 1721 //\r
490b5ea1 1722 if ((Task == NULL) || Status != EFI_NOT_READY) {\r
1723 //\r
1724 // Read BMIS register and clear ERROR and INTR bit\r
1725 //\r
1726 RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
1727 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
1728 IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
a41b5272 1729\r
490b5ea1 1730 //\r
1731 // Read Status Register of IDE device to clear interrupt\r
1732 //\r
1733 RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
a41b5272 1734\r
490b5ea1 1735 //\r
1736 // Clear START bit of BMIC register\r
1737 //\r
1738 RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
1739 RegisterValue &= ~((UINT8) BMIC_START);\r
1740 IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
a41b5272 1741\r
490b5ea1 1742 //\r
1743 // Disable interrupt of Select device\r
1744 //\r
1745 DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
1746 DeviceControl |= ATA_CTLREG_IEN_L;\r
1747 IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
1748 //\r
1749 // Stall for 10 milliseconds.\r
1750 //\r
1751 MicroSecondDelay (10000);\r
1752\r
1753 }\r
a41b5272 1754\r
1755Exit:\r
1756 //\r
1757 // Free all allocated resource\r
1758 //\r
490b5ea1 1759 if ((Task == NULL) || Status != EFI_NOT_READY) {\r
1760 if (Task != NULL) {\r
1761 PciIo->Unmap (PciIo, Task->TableMap);\r
1762 PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);\r
1763 PciIo->Unmap (PciIo, Task->Map);\r
1764 } else {\r
1765 PciIo->Unmap (PciIo, PrdTableMap);\r
1766 PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
1767 PciIo->Unmap (PciIo, BufferMap);\r
1768 }\r
a41b5272 1769\r
490b5ea1 1770 //\r
1771 // Dump All Ide registers to ATA_STATUS_BLOCK\r
1772 //\r
1773 DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
1774 }\r
1aff716a 1775\r
a41b5272 1776 return Status;\r
1777}\r
1778\r
1779/**\r
1780 This function reads the pending data in the device.\r
1781\r
1782 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
1783 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1784\r
1785 @retval EFI_SUCCESS Successfully read.\r
1786 @retval EFI_NOT_READY The BSY is set avoiding reading.\r
1787\r
1788**/\r
1789EFI_STATUS\r
1790EFIAPI\r
1791AtaPacketReadPendingData (\r
1792 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1793 IN EFI_IDE_REGISTERS *IdeRegisters\r
1794 )\r
1795{\r
1796 UINT8 AltRegister;\r
1797 UINT16 TempWordBuffer;\r
1798\r
1799 AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
1800 if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) {\r
1801 return EFI_NOT_READY;\r
1802 }\r
1803\r
1804 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
1805 TempWordBuffer = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
1806 while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
1807 IdeReadPortWMultiple (\r
1808 PciIo,\r
1aff716a 1809 IdeRegisters->Data,\r
1810 1,\r
a41b5272 1811 &TempWordBuffer\r
1812 );\r
1813 TempWordBuffer = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
1814 }\r
1815 }\r
1816 return EFI_SUCCESS;\r
1817}\r
1818\r
1819/**\r
1aff716a 1820 This function is called by AtaPacketCommandExecute().\r
a41b5272 1821 It is used to transfer data between host and device. The data direction is specified\r
1822 by the fourth parameter.\r
1823\r
1824 @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
1825 @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
1826 @param Buffer Buffer contained data transferred between host and device.\r
1827 @param ByteCount Data size in byte unit of the buffer.\r
1828 @param Read Flag used to determine the data transfer direction.\r
1829 Read equals 1, means data transferred from device to host;\r
1830 Read equals 0, means data transferred from host to device.\r
8536cc4b 1831 @param Timeout Timeout value for wait DRQ ready before each data stream's transfer\r
1832 , uses 100ns as a unit.\r
a41b5272 1833\r
1834 @retval EFI_SUCCESS data is transferred successfully.\r
1835 @retval EFI_DEVICE_ERROR the device failed to transfer data.\r
1836**/\r
1837EFI_STATUS\r
1838EFIAPI\r
1839AtaPacketReadWrite (\r
1840 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1841 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1842 IN OUT VOID *Buffer,\r
1843 IN UINT64 ByteCount,\r
1844 IN BOOLEAN Read,\r
1845 IN UINT64 Timeout\r
1846 )\r
1847{\r
1848 UINT32 RequiredWordCount;\r
1849 UINT32 ActualWordCount;\r
1850 UINT32 WordCount;\r
1851 EFI_STATUS Status;\r
1852 UINT16 *PtrBuffer;\r
1853\r
1854 //\r
1855 // No data transfer is premitted.\r
1856 //\r
1857 if (ByteCount == 0) {\r
1858 return EFI_SUCCESS;\r
1859 }\r
1aff716a 1860\r
a41b5272 1861 PtrBuffer = Buffer;\r
1862 RequiredWordCount = (UINT32)RShiftU64(ByteCount, 1);\r
1863 //\r
1864 // ActuralWordCount means the word count of data really transferred.\r
1865 //\r
1866 ActualWordCount = 0;\r
1867\r
1868 while (ActualWordCount < RequiredWordCount) {\r
1869 //\r
1870 // before each data transfer stream, the host should poll DRQ bit ready,\r
1871 // to see whether indicates device is ready to transfer data.\r
1872 //\r
1873 Status = DRQReady2 (PciIo, IdeRegisters, Timeout);\r
1874 if (EFI_ERROR (Status)) {\r
aca84419 1875 return CheckStatusRegister (PciIo, IdeRegisters);\r
a41b5272 1876 }\r
1877\r
1878 //\r
1879 // get current data transfer size from Cylinder Registers.\r
1880 //\r
1881 WordCount = IdeReadPortB (PciIo, IdeRegisters->CylinderMsb) << 8;\r
1882 WordCount = WordCount | IdeReadPortB (PciIo, IdeRegisters->CylinderLsb);\r
1883 WordCount = WordCount & 0xffff;\r
1884 WordCount /= 2;\r
1885\r
1886 WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount));\r
1887\r
1888 if (Read) {\r
1889 IdeReadPortWMultiple (\r
1890 PciIo,\r
1891 IdeRegisters->Data,\r
1892 WordCount,\r
1893 PtrBuffer\r
1894 );\r
1895 } else {\r
1896 IdeWritePortWMultiple (\r
1897 PciIo,\r
1898 IdeRegisters->Data,\r
1899 WordCount,\r
1900 PtrBuffer\r
1901 );\r
1902 }\r
1903\r
1904 //\r
1905 // read status register to check whether error happens.\r
1906 //\r
1907 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1908 if (EFI_ERROR (Status)) {\r
1909 return EFI_DEVICE_ERROR;\r
1910 }\r
1911\r
1912 PtrBuffer += WordCount;\r
1913 ActualWordCount += WordCount;\r
1914 }\r
1aff716a 1915\r
a41b5272 1916 if (Read) {\r
1917 //\r
1918 // In the case where the drive wants to send more data than we need to read,\r
1919 // the DRQ bit will be set and cause delays from DRQClear2().\r
1920 // We need to read data from the drive until it clears DRQ so we can move on.\r
1921 //\r
1922 AtaPacketReadPendingData (PciIo, IdeRegisters);\r
1923 }\r
1924\r
1925 //\r
1926 // read status register to check whether error happens.\r
1927 //\r
1928 Status = CheckStatusRegister (PciIo, IdeRegisters);\r
1929 if (EFI_ERROR (Status)) {\r
1930 return EFI_DEVICE_ERROR;\r
1931 }\r
1932\r
1933 //\r
1934 // After data transfer is completed, normally, DRQ bit should clear.\r
1935 //\r
8536cc4b 1936 Status = DRQClear (PciIo, IdeRegisters, Timeout);\r
a41b5272 1937 if (EFI_ERROR (Status)) {\r
1938 return EFI_DEVICE_ERROR;\r
1939 }\r
1aff716a 1940\r
a41b5272 1941 return Status;\r
1942}\r
1943\r
a41b5272 1944/**\r
1aff716a 1945 This function is used to send out ATAPI commands conforms to the Packet Command\r
a41b5272 1946 with PIO Data In Protocol.\r
1947\r
1948 @param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
1949 @param[in] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to\r
1950 store the IDE i/o port registers' base addresses\r
1951 @param[in] Channel The channel number of device.\r
1952 @param[in] Device The device number of device.\r
1953 @param[in] Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET data structure.\r
1954\r
1955 @retval EFI_SUCCESS send out the ATAPI packet command successfully\r
1956 and device sends data successfully.\r
1957 @retval EFI_DEVICE_ERROR the device failed to send data.\r
1958\r
1959**/\r
1960EFI_STATUS\r
1961EFIAPI\r
1962AtaPacketCommandExecute (\r
1963 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1964 IN EFI_IDE_REGISTERS *IdeRegisters,\r
1965 IN UINT8 Channel,\r
1966 IN UINT8 Device,\r
1967 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
1968 )\r
1969{\r
a41b5272 1970 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
1971 EFI_STATUS Status;\r
1972 UINT8 Count;\r
1973 UINT8 PacketCommand[12];\r
1974\r
1975 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
1976\r
1977 //\r
1978 // Fill ATAPI Command Packet according to CDB.\r
1979 // For Atapi cmd, its length should be less than or equal to 12 bytes.\r
1980 //\r
1981 if (Packet->CdbLength > 12) {\r
1982 return EFI_INVALID_PARAMETER;\r
1983 }\r
1984\r
1985 ZeroMem (PacketCommand, 12);\r
1986 CopyMem (PacketCommand, Packet->Cdb, Packet->CdbLength);\r
1987\r
1988 //\r
1989 // No OVL; No DMA\r
1990 //\r
1991 AtaCommandBlock.AtaFeatures = 0x00;\r
1992 //\r
1993 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device\r
1994 // determine how many data should be transferred.\r
1995 //\r
1996 AtaCommandBlock.AtaCylinderLow = (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff);\r
1997 AtaCommandBlock.AtaCylinderHigh = (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8);\r
aca84419 1998 AtaCommandBlock.AtaDeviceHead = (UINT8) (Device << 0x4);\r
a41b5272 1999 AtaCommandBlock.AtaCommand = ATA_CMD_PACKET;\r
2000\r
2001 IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | (Device << 0x4)));\r
2002 //\r
2003 // Disable interrupt\r
2004 //\r
2005 IdeWritePortB (PciIo, IdeRegisters->AltOrDev, ATA_DEFAULT_CTL);\r
2006\r
2007 //\r
2008 // Issue ATA PACKET command firstly\r
2009 //\r
2010 Status = AtaIssueCommand (PciIo, IdeRegisters, &AtaCommandBlock, Packet->Timeout);\r
2011 if (EFI_ERROR (Status)) {\r
2012 return Status;\r
2013 }\r
2014\r
2015 Status = DRQReady (PciIo, IdeRegisters, Packet->Timeout);\r
2016 if (EFI_ERROR (Status)) {\r
2017 return Status;\r
2018 }\r
2019\r
2020 //\r
2021 // Send out ATAPI command packet\r
2022 //\r
2023 for (Count = 0; Count < 6; Count++) {\r
1aff716a 2024 IdeWritePortW (PciIo, IdeRegisters->Data, *((UINT16*)PacketCommand + Count));\r
a41b5272 2025 //\r
2026 // Stall for 10 microseconds.\r
2027 //\r
2028 MicroSecondDelay (10);\r
2029 }\r
2030\r
2031 //\r
2032 // Read/Write the data of ATAPI Command\r
2033 //\r
2034 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
73a9e822
TF
2035 Status = AtaPacketReadWrite (\r
2036 PciIo,\r
2037 IdeRegisters,\r
2038 Packet->InDataBuffer,\r
2039 Packet->InTransferLength,\r
2040 TRUE,\r
2041 Packet->Timeout\r
2042 );\r
a41b5272 2043 } else {\r
73a9e822
TF
2044 Status = AtaPacketReadWrite (\r
2045 PciIo,\r
2046 IdeRegisters,\r
2047 Packet->OutDataBuffer,\r
2048 Packet->OutTransferLength,\r
2049 FALSE,\r
2050 Packet->Timeout\r
2051 );\r
a41b5272 2052 }\r
2053\r
73a9e822 2054 return Status;\r
a41b5272 2055}\r
2056\r
2057\r
2058/**\r
2059 Set the calculated Best transfer mode to a detected device.\r
2060\r
2061 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2062 @param Channel The channel number of device.\r
2063 @param Device The device number of device.\r
2064 @param TransferMode A pointer to EFI_ATA_TRANSFER_MODE data structure.\r
2065 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2066\r
2067 @retval EFI_SUCCESS Set transfer mode successfully.\r
2068 @retval EFI_DEVICE_ERROR Set transfer mode failed.\r
2069 @retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
2070\r
2071**/\r
2072EFI_STATUS\r
2073EFIAPI\r
2074SetDeviceTransferMode (\r
2075 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2076 IN UINT8 Channel,\r
2077 IN UINT8 Device,\r
2078 IN EFI_ATA_TRANSFER_MODE *TransferMode,\r
2079 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
2080 )\r
2081{\r
2082 EFI_STATUS Status;\r
2083 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
2084\r
2085 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
2086\r
2087 AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;\r
2088 AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
2089 AtaCommandBlock.AtaFeatures = 0x03;\r
2090 AtaCommandBlock.AtaSectorCount = *((UINT8 *)TransferMode);\r
2091\r
2092 //\r
2093 // Send SET FEATURE command (sub command 0x03) to set pio mode.\r
2094 //\r
2095 Status = AtaNonDataCommandIn (\r
2096 Instance->PciIo,\r
2097 &Instance->IdeRegisters[Channel],\r
2098 &AtaCommandBlock,\r
2099 AtaStatusBlock,\r
490b5ea1 2100 ATA_ATAPI_TIMEOUT,\r
2101 NULL\r
a41b5272 2102 );\r
2103\r
2104 return Status;\r
2105}\r
2106\r
2107/**\r
2108 Set drive parameters for devices not support PACKETS command.\r
2109\r
2110 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2111 @param Channel The channel number of device.\r
2112 @param Device The device number of device.\r
2113 @param DriveParameters A pointer to EFI_ATA_DRIVE_PARMS data structure.\r
2114 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2115\r
2116 @retval EFI_SUCCESS Set drive parameter successfully.\r
2117 @retval EFI_DEVICE_ERROR Set drive parameter failed.\r
2118 @retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
2119\r
2120**/\r
2121EFI_STATUS\r
2122EFIAPI\r
2123SetDriveParameters (\r
2124 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2125 IN UINT8 Channel,\r
2126 IN UINT8 Device,\r
2127 IN EFI_ATA_DRIVE_PARMS *DriveParameters,\r
2128 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
a41b5272 2129 )\r
2130{\r
2131 EFI_STATUS Status;\r
2132 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
2133\r
2134 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
1aff716a 2135\r
a41b5272 2136 AtaCommandBlock.AtaCommand = ATA_CMD_INIT_DRIVE_PARAM;\r
2137 AtaCommandBlock.AtaSectorCount = DriveParameters->Sector;\r
2138 AtaCommandBlock.AtaDeviceHead = (UINT8) ((Device << 0x4) + DriveParameters->Heads);\r
2139\r
2140 //\r
2141 // Send Init drive parameters\r
2142 //\r
2143 Status = AtaNonDataCommandIn (\r
2144 Instance->PciIo,\r
2145 &Instance->IdeRegisters[Channel],\r
2146 &AtaCommandBlock,\r
2147 AtaStatusBlock,\r
1aff716a 2148 ATA_ATAPI_TIMEOUT,\r
490b5ea1 2149 NULL\r
a41b5272 2150 );\r
2151\r
2152 //\r
2153 // Send Set Multiple parameters\r
2154 //\r
2155 AtaCommandBlock.AtaCommand = ATA_CMD_SET_MULTIPLE_MODE;\r
2156 AtaCommandBlock.AtaSectorCount = DriveParameters->MultipleSector;\r
2157 AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
2158\r
2159 Status = AtaNonDataCommandIn (\r
2160 Instance->PciIo,\r
2161 &Instance->IdeRegisters[Channel],\r
2162 &AtaCommandBlock,\r
2163 AtaStatusBlock,\r
1aff716a 2164 ATA_ATAPI_TIMEOUT,\r
490b5ea1 2165 NULL\r
a41b5272 2166 );\r
2167\r
2168 return Status;\r
2169}\r
2170\r
12873d57 2171/**\r
2172 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.\r
2173\r
2174 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2175 @param Channel The channel number of device.\r
2176 @param Device The device number of device.\r
2177 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2178\r
2179 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.\r
2180 @retval Others Fail to get return status data.\r
2181\r
2182**/\r
2183EFI_STATUS\r
2184EFIAPI\r
2185IdeAtaSmartReturnStatusCheck (\r
2186 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2187 IN UINT8 Channel,\r
2188 IN UINT8 Device,\r
2189 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
2190 )\r
2191{\r
2192 EFI_STATUS Status;\r
2193 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
2194 UINT8 LBAMid;\r
2195 UINT8 LBAHigh;\r
2196\r
2197 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
2198\r
2199 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
2200 AtaCommandBlock.AtaFeatures = ATA_SMART_RETURN_STATUS;\r
2201 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
2202 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
2203 AtaCommandBlock.AtaDeviceHead = (UINT8) ((Device << 0x4) | 0xe0);\r
2204\r
2205 //\r
2206 // Send S.M.A.R.T Read Return Status command to device\r
2207 //\r
2208 Status = AtaNonDataCommandIn (\r
2209 Instance->PciIo,\r
2210 &Instance->IdeRegisters[Channel],\r
2211 &AtaCommandBlock,\r
2212 AtaStatusBlock,\r
490b5ea1 2213 ATA_ATAPI_TIMEOUT,\r
2214 NULL\r
12873d57 2215 );\r
2216\r
2217 if (EFI_ERROR (Status)) {\r
cffd2171
EL
2218 REPORT_STATUS_CODE (\r
2219 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
2220 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
2221 );\r
12873d57 2222 return EFI_DEVICE_ERROR;\r
2223 }\r
2224\r
cffd2171
EL
2225 REPORT_STATUS_CODE (\r
2226 EFI_PROGRESS_CODE,\r
2227 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
2228 );\r
2229\r
12873d57 2230 LBAMid = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderLsb);\r
2231 LBAHigh = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderMsb);\r
2232\r
2233 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
2234 //\r
2235 // The threshold exceeded condition is not detected by the device\r
2236 //\r
2237 DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));\r
cffd2171
EL
2238 REPORT_STATUS_CODE (\r
2239 EFI_PROGRESS_CODE,\r
2240 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
2241 );\r
12873d57 2242 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
2243 //\r
2244 // The threshold exceeded condition is detected by the device\r
2245 //\r
2246 DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));\r
cffd2171
EL
2247 REPORT_STATUS_CODE (\r
2248 EFI_PROGRESS_CODE,\r
2249 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
2250 );\r
12873d57 2251 }\r
2252\r
2253 return EFI_SUCCESS;\r
2254}\r
2255\r
2256/**\r
2257 Enable SMART command of the disk if supported.\r
2258\r
2259 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2260 @param Channel The channel number of device.\r
2261 @param Device The device number of device.\r
2262 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.\r
2263 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2264\r
2265**/\r
2266VOID\r
2267EFIAPI\r
2268IdeAtaSmartSupport (\r
2269 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2270 IN UINT8 Channel,\r
2271 IN UINT8 Device,\r
2272 IN EFI_IDENTIFY_DATA *IdentifyData,\r
2273 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
2274 )\r
2275{\r
2276 EFI_STATUS Status;\r
2277 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
2278\r
2279 //\r
2280 // Detect if the device supports S.M.A.R.T.\r
2281 //\r
2282 if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
2283 //\r
2284 // S.M.A.R.T is not supported by the device\r
2285 //\r
1aff716a 2286 DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at [%a] channel [%a] device!\n",\r
12873d57 2287 (Channel == 1) ? "secondary" : "primary", (Device == 1) ? "slave" : "master"));\r
cffd2171
EL
2288 REPORT_STATUS_CODE (\r
2289 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
2290 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
2291 );\r
12873d57 2292 } else {\r
2293 //\r
2294 // Check if the feature is enabled. If not, then enable S.M.A.R.T.\r
2295 //\r
2296 if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {\r
2297\r
cffd2171
EL
2298 REPORT_STATUS_CODE (\r
2299 EFI_PROGRESS_CODE,\r
2300 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)\r
2301 );\r
2302\r
12873d57 2303 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
2304\r
2305 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
2306 AtaCommandBlock.AtaFeatures = ATA_SMART_ENABLE_OPERATION;\r
2307 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
2308 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
2309 AtaCommandBlock.AtaDeviceHead = (UINT8) ((Device << 0x4) | 0xe0);\r
2310\r
2311 //\r
2312 // Send S.M.A.R.T Enable command to device\r
2313 //\r
2314 Status = AtaNonDataCommandIn (\r
2315 Instance->PciIo,\r
2316 &Instance->IdeRegisters[Channel],\r
2317 &AtaCommandBlock,\r
2318 AtaStatusBlock,\r
490b5ea1 2319 ATA_ATAPI_TIMEOUT,\r
2320 NULL\r
12873d57 2321 );\r
2322\r
2323 if (!EFI_ERROR (Status)) {\r
2324 //\r
2325 // Send S.M.A.R.T AutoSave command to device\r
2326 //\r
2327 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
2328\r
2329 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
2330 AtaCommandBlock.AtaFeatures = 0xD2;\r
2331 AtaCommandBlock.AtaSectorCount = 0xF1;\r
2332 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
2333 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
2334 AtaCommandBlock.AtaDeviceHead = (UINT8) ((Device << 0x4) | 0xe0);\r
2335\r
2336 Status = AtaNonDataCommandIn (\r
2337 Instance->PciIo,\r
2338 &Instance->IdeRegisters[Channel],\r
2339 &AtaCommandBlock,\r
2340 AtaStatusBlock,\r
490b5ea1 2341 ATA_ATAPI_TIMEOUT,\r
2342 NULL\r
12873d57 2343 );\r
2344 if (!EFI_ERROR (Status)) {\r
2345 Status = IdeAtaSmartReturnStatusCheck (\r
2346 Instance,\r
2347 Channel,\r
2348 Device,\r
2349 AtaStatusBlock\r
2350 );\r
2351 }\r
2352 }\r
2353 }\r
2354\r
1aff716a 2355 DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at [%a] channel [%a] device!\n",\r
12873d57 2356 (Channel == 1) ? "secondary" : "primary", (Device == 1) ? "slave" : "master"));\r
2357\r
2358 }\r
2359\r
2360 return ;\r
2361}\r
2362\r
490b5ea1 2363\r
a41b5272 2364/**\r
2365 Sends out an ATA Identify Command to the specified device.\r
2366\r
2367 This function is called by DiscoverIdeDevice() during its device\r
2368 identification. It sends out the ATA Identify Command to the\r
2369 specified device. Only ATA device responses to this command. If\r
2370 the command succeeds, it returns the Identify data structure which\r
2371 contains information about the device. This function extracts the\r
2372 information it needs to fill the IDE_BLK_IO_DEV data structure,\r
2373 including device type, media block size, media capacity, and etc.\r
2374\r
2375 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2376 @param Channel The channel number of device.\r
2377 @param Device The device number of device.\r
2378 @param Buffer A pointer to data buffer which is used to contain IDENTIFY data.\r
2379 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2380\r
2381 @retval EFI_SUCCESS Identify ATA device successfully.\r
2382 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.\r
2383 @retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
490b5ea1 2384\r
a41b5272 2385**/\r
2386EFI_STATUS\r
2387EFIAPI\r
2388AtaIdentify (\r
2389 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2390 IN UINT8 Channel,\r
2391 IN UINT8 Device,\r
2392 IN OUT EFI_IDENTIFY_DATA *Buffer,\r
2393 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
2394 )\r
2395{\r
2396 EFI_STATUS Status;\r
490b5ea1 2397 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
a41b5272 2398\r
2399 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
490b5ea1 2400\r
a41b5272 2401 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
2402 AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
2403\r
2404 Status = AtaPioDataInOut (\r
2405 Instance->PciIo,\r
2406 &Instance->IdeRegisters[Channel],\r
2407 Buffer,\r
2408 sizeof (EFI_IDENTIFY_DATA),\r
2409 TRUE,\r
2410 &AtaCommandBlock,\r
2411 AtaStatusBlock,\r
490b5ea1 2412 ATA_ATAPI_TIMEOUT,\r
2413 NULL\r
a41b5272 2414 );\r
2415\r
2416 return Status;\r
2417}\r
2418\r
2419/**\r
2420 This function is called by DiscoverIdeDevice() during its device\r
2421 identification.\r
2422 Its main purpose is to get enough information for the device media\r
2423 to fill in the Media data structure of the Block I/O Protocol interface.\r
2424\r
2425 There are 5 steps to reach such objective:\r
1aff716a 2426 1. Sends out the ATAPI Identify Command to the specified device.\r
a41b5272 2427 Only ATAPI device responses to this command. If the command succeeds,\r
1aff716a 2428 it returns the Identify data structure which filled with information\r
2429 about the device. Since the ATAPI device contains removable media,\r
a41b5272 2430 the only meaningful information is the device module name.\r
2431 2. Sends out ATAPI Inquiry Packet Command to the specified device.\r
2432 This command will return inquiry data of the device, which contains\r
2433 the device type information.\r
2434 3. Allocate sense data space for future use. We don't detect the media\r
1aff716a 2435 presence here to improvement boot performance, especially when CD\r
a41b5272 2436 media is present. The media detection will be performed just before\r
2437 each BLK_IO read/write\r
1aff716a 2438\r
a41b5272 2439 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2440 @param Channel The channel number of device.\r
2441 @param Device The device number of device.\r
2442 @param Buffer A pointer to data buffer which is used to contain IDENTIFY data.\r
2443 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
2444\r
2445 @retval EFI_SUCCESS Identify ATAPI device successfully.\r
2446 @retval EFI_DEVICE_ERROR ATA Identify Packet Device Command failed or device type\r
2447 is not supported by this IDE driver.\r
2448 @retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
2449\r
2450**/\r
2451EFI_STATUS\r
2452EFIAPI\r
2453AtaIdentifyPacket (\r
2454 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2455 IN UINT8 Channel,\r
2456 IN UINT8 Device,\r
2457 IN OUT EFI_IDENTIFY_DATA *Buffer,\r
2458 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
2459 )\r
2460{\r
2461 EFI_STATUS Status;\r
2462 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
2463\r
2464 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
1aff716a 2465\r
a41b5272 2466 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;\r
2467 AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
2468\r
2469 //\r
2470 // Send ATAPI Identify Command to get IDENTIFY data.\r
2471 //\r
2472 Status = AtaPioDataInOut (\r
2473 Instance->PciIo,\r
2474 &Instance->IdeRegisters[Channel],\r
2475 (VOID *) Buffer,\r
2476 sizeof (EFI_IDENTIFY_DATA),\r
2477 TRUE,\r
2478 &AtaCommandBlock,\r
2479 AtaStatusBlock,\r
490b5ea1 2480 ATA_ATAPI_TIMEOUT,\r
2481 NULL\r
a41b5272 2482 );\r
2483\r
2484 return Status;\r
2485}\r
2486\r
2487\r
2488/**\r
2489 This function is used for detect whether the IDE device exists in the\r
2490 specified Channel as the specified Device Number.\r
2491\r
2492 There is two IDE channels: one is Primary Channel, the other is\r
2493 Secondary Channel.(Channel is the logical name for the physical "Cable".)\r
2494 Different channel has different register group.\r
2495\r
2496 On each IDE channel, at most two IDE devices attach,\r
2497 one is called Device 0 (Master device), the other is called Device 1\r
2498 (Slave device). The devices on the same channel co-use the same register\r
2499 group, so before sending out a command for a specified device via command\r
2500 register, it is a must to select the current device to accept the command\r
2501 by set the device number in the Head/Device Register.\r
2502\r
2503 @param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
2504 @param IdeChannel The channel number of device.\r
2505\r
2506 @retval EFI_SUCCESS successfully detects device.\r
2507 @retval other any failure during detection process will return this value.\r
2508\r
2509**/\r
2510EFI_STATUS\r
2511EFIAPI\r
2512DetectAndConfigIdeDevice (\r
2513 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
2514 IN UINT8 IdeChannel\r
2515 )\r
2516{\r
2517 EFI_STATUS Status;\r
2518 UINT8 SectorCountReg;\r
2519 UINT8 LBALowReg;\r
2520 UINT8 LBAMidReg;\r
2521 UINT8 LBAHighReg;\r
2522 EFI_ATA_DEVICE_TYPE DeviceType;\r
aca84419 2523 UINT8 IdeDevice;\r
a41b5272 2524 EFI_IDE_REGISTERS *IdeRegisters;\r
2525 EFI_IDENTIFY_DATA Buffer;\r
2526\r
2527 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
2528 EFI_PCI_IO_PROTOCOL *PciIo;\r
2529\r
2530 EFI_ATA_COLLECTIVE_MODE *SupportedModes;\r
2531 EFI_ATA_TRANSFER_MODE TransferMode;\r
2532 EFI_ATA_DRIVE_PARMS DriveParameters;\r
2533\r
2534 IdeRegisters = &Instance->IdeRegisters[IdeChannel];\r
2535 IdeInit = Instance->IdeControllerInit;\r
2536 PciIo = Instance->PciIo;\r
2537\r
490b5ea1 2538 for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {\r
a41b5272 2539 //\r
2540 // Send ATA Device Execut Diagnostic command.\r
2541 // This command should work no matter DRDY is ready or not\r
2542 //\r
2543 IdeWritePortB (PciIo, IdeRegisters->CmdOrStatus, ATA_CMD_EXEC_DRIVE_DIAG);\r
1aff716a 2544\r
a41b5272 2545 Status = WaitForBSYClear (PciIo, IdeRegisters, 350000000);\r
2546 if (EFI_ERROR (Status)) {\r
2547 DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));\r
2548 continue;\r
2549 }\r
2550\r
2551 //\r
2552 // Select Master or Slave device to get the return signature for ATA DEVICE DIAGNOSTIC cmd.\r
2553 //\r
2554 IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)((IdeDevice << 4) | 0xe0));\r
2555 //\r
2556 // Stall for 1 milliseconds.\r
2557 //\r
2558 MicroSecondDelay (1000);\r
2559\r
2560 SectorCountReg = IdeReadPortB (PciIo, IdeRegisters->SectorCount);\r
2561 LBALowReg = IdeReadPortB (PciIo, IdeRegisters->SectorNumber);\r
2562 LBAMidReg = IdeReadPortB (PciIo, IdeRegisters->CylinderLsb);\r
2563 LBAHighReg = IdeReadPortB (PciIo, IdeRegisters->CylinderMsb);\r
2564\r
2565 //\r
2566 // Refer to ATA/ATAPI 4 Spec, section 9.1\r
2567 //\r
2568 if ((SectorCountReg == 0x1) && (LBALowReg == 0x1) && (LBAMidReg == 0x0) && (LBAHighReg == 0x0)) {\r
2569 DeviceType = EfiIdeHarddisk;\r
2570 } else if ((LBAMidReg == 0x14) && (LBAHighReg == 0xeb)) {\r
2571 DeviceType = EfiIdeCdrom;\r
2572 } else {\r
2573 continue;\r
2574 }\r
2575\r
2576 //\r
2577 // Send IDENTIFY cmd to the device to test if it is really attached.\r
2578 //\r
2579 if (DeviceType == EfiIdeHarddisk) {\r
2580 Status = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
2581 //\r
2582 // if identifying ata device is failure, then try to send identify packet cmd.\r
2583 //\r
2584 if (EFI_ERROR (Status)) {\r
3d0a2385 2585 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));\r
2586\r
a41b5272 2587 DeviceType = EfiIdeCdrom;\r
2588 Status = AtaIdentifyPacket (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
2589 }\r
2590 } else {\r
2591 Status = AtaIdentifyPacket (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
2592 //\r
2593 // if identifying atapi device is failure, then try to send identify cmd.\r
2594 //\r
2595 if (EFI_ERROR (Status)) {\r
2596 DeviceType = EfiIdeHarddisk;\r
2597 Status = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
490b5ea1 2598 }\r
a41b5272 2599 }\r
2600\r
2601 if (EFI_ERROR (Status)) {\r
2602 //\r
2603 // No device is found at this port\r
2604 //\r
2605 continue;\r
490b5ea1 2606 }\r
2607\r
1aff716a 2608 DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n",\r
a41b5272 2609 (IdeChannel == 1) ? "secondary" : "primary ", (IdeDevice == 1) ? "slave " : "master",\r
2610 DeviceType == EfiIdeCdrom ? "cdrom " : "harddisk"));\r
12873d57 2611 //\r
2612 // If the device is a hard disk, then try to enable S.M.A.R.T feature\r
2613 //\r
fc80ee69 2614 if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {\r
12873d57 2615 IdeAtaSmartSupport (\r
2616 Instance,\r
2617 IdeChannel,\r
2618 IdeDevice,\r
2619 &Buffer,\r
2620 NULL\r
2621 );\r
2622 }\r
2623\r
a41b5272 2624 //\r
2625 // Submit identify data to IDE controller init driver\r
2626 //\r
2627 IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &Buffer);\r
2628\r
2629 //\r
2630 // Now start to config ide device parameter and transfer mode.\r
2631 //\r
2632 Status = IdeInit->CalculateMode (\r
2633 IdeInit,\r
2634 IdeChannel,\r
2635 IdeDevice,\r
2636 &SupportedModes\r
2637 );\r
2638 if (EFI_ERROR (Status)) {\r
2639 DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));\r
2640 continue;\r
2641 }\r
2642\r
2643 //\r
2644 // Set best supported PIO mode on this IDE device\r
2645 //\r
2646 if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {\r
2647 TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;\r
2648 } else {\r
2649 TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;\r
2650 }\r
2651\r
2652 TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);\r
2653\r
2654 if (SupportedModes->ExtModeCount == 0){\r
2655 Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
2656\r
2657 if (EFI_ERROR (Status)) {\r
2658 DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
2659 continue;\r
2660 }\r
2661 }\r
490b5ea1 2662\r
a41b5272 2663 //\r
2664 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
2665 // be set together. Only one DMA mode can be set to a device. If setting\r
2666 // DMA mode operation fails, we can continue moving on because we only use\r
2667 // PIO mode at boot time. DMA modes are used by certain kind of OS booting\r
2668 //\r
2669 if (SupportedModes->UdmaMode.Valid) {\r
2670 TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
2671 TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
2672 Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
490b5ea1 2673\r
a41b5272 2674 if (EFI_ERROR (Status)) {\r
2675 DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
2676 continue;\r
2677 }\r
2678 } else if (SupportedModes->MultiWordDmaMode.Valid) {\r
2679 TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
2680 TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
2681 Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
490b5ea1 2682\r
a41b5272 2683 if (EFI_ERROR (Status)) {\r
2684 DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
2685 continue;\r
2686 }\r
2687 }\r
490b5ea1 2688\r
a41b5272 2689 //\r
2690 // Set Parameters for the device:\r
2691 // 1) Init\r
2692 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command\r
2693 //\r
2694 if (DeviceType == EfiIdeHarddisk) {\r
2695 //\r
2696 // Init driver parameters\r
2697 //\r
2698 DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->sectors_per_track;\r
aca84419 2699 DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->heads - 1);\r
a41b5272 2700 DriveParameters.MultipleSector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->multi_sector_cmd_max_sct_cnt;\r
490b5ea1 2701\r
a41b5272 2702 Status = SetDriveParameters (Instance, IdeChannel, IdeDevice, &DriveParameters, NULL);\r
2703 }\r
490b5ea1 2704\r
a41b5272 2705 //\r
2706 // Set IDE controller Timing Blocks in the PCI Configuration Space\r
2707 //\r
2708 IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);\r
2709\r
2710 //\r
2711 // IDE controller and IDE device timing is configured successfully.\r
2712 // Now insert the device into device list.\r
2713 //\r
2714 Status = CreateNewDeviceInfo (Instance, IdeChannel, IdeDevice, DeviceType, &Buffer);\r
2715 if (EFI_ERROR (Status)) {\r
2716 continue;\r
2717 }\r
3d0a2385 2718\r
2719 if (DeviceType == EfiIdeHarddisk) {\r
2720 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));\r
2721 }\r
a41b5272 2722 }\r
2723 return EFI_SUCCESS;\r
2724}\r
2725\r
2726\r
2727/**\r
2728 Initialize ATA host controller at IDE mode.\r
1aff716a 2729\r
2730 The function is designed to initialize ATA host controller.\r
2731\r
a41b5272 2732 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
2733\r
2734**/\r
2735EFI_STATUS\r
2736EFIAPI\r
2737IdeModeInitialization (\r
2738 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
2739 )\r
2740{\r
a41b5272 2741 EFI_STATUS Status;\r
2742 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
2743 EFI_PCI_IO_PROTOCOL *PciIo;\r
2744 UINT8 Channel;\r
2745 UINT8 IdeChannel;\r
2746 BOOLEAN ChannelEnabled;\r
2747 UINT8 MaxDevices;\r
2748\r
2749 IdeInit = Instance->IdeControllerInit;\r
2750 PciIo = Instance->PciIo;\r
a41b5272 2751 Channel = IdeInit->ChannelCount;\r
2752\r
2753 //\r
2754 // Obtain IDE IO port registers' base addresses\r
2755 //\r
2756 Status = GetIdeRegisterIoAddr (PciIo, Instance->IdeRegisters);\r
2757 if (EFI_ERROR (Status)) {\r
2758 goto ErrorExit;\r
2759 }\r
2760\r
2761 for (IdeChannel = 0; IdeChannel < Channel; IdeChannel++) {\r
2762 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);\r
2763\r
2764 //\r
2765 // now obtain channel information fron IdeControllerInit protocol.\r
2766 //\r
2767 Status = IdeInit->GetChannelInfo (\r
2768 IdeInit,\r
2769 IdeChannel,\r
2770 &ChannelEnabled,\r
2771 &MaxDevices\r
2772 );\r
2773 if (EFI_ERROR (Status)) {\r
2774 DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));\r
2775 continue;\r
2776 }\r
2777\r
2778 if (!ChannelEnabled) {\r
2779 continue;\r
2780 }\r
2781\r
2782 ASSERT (MaxDevices <= 2);\r
2783 //\r
2784 // Now inform the IDE Controller Init Module.\r
2785 //\r
2786 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);\r
2787\r
2788 //\r
2789 // No reset channel function implemented.\r
2790 //\r
2791 IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);\r
2792\r
2793 //\r
2794 // Now inform the IDE Controller Init Module.\r
2795 //\r
2796 IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, IdeChannel);\r
2797\r
2798 //\r
2799 // Detect all attached ATA devices and set the transfer mode for each device.\r
2800 //\r
2801 DetectAndConfigIdeDevice (Instance, IdeChannel);\r
2802 }\r
2803\r
2804 //\r
2805 // All configurations done! Notify IdeController to do post initialization\r
2806 // work such as saving IDE controller PCI settings for S3 resume\r
2807 //\r
2808 IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);\r
2809\r
2810ErrorExit:\r
2811 return Status;\r
2812}\r
2813\r