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