]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
Some library instance's PCD is missing in FPD file for a module, it break single...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / ide.c
1 /** @file
2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 **/
12
13 #include "idebus.h"
14
15 BOOLEAN SlaveDeviceExist = FALSE;
16 BOOLEAN MasterDeviceExist = FALSE;
17
18 /**
19 TODO: Add function description
20
21 @param PciIo TODO: add argument description
22 @param Port TODO: add argument description
23
24 TODO: add return values
25
26 **/
27 UINT8
28 IDEReadPortB (
29 IN EFI_PCI_IO_PROTOCOL *PciIo,
30 IN UINT16 Port
31 )
32 {
33 UINT8 Data;
34
35 Data = 0;
36 //
37 // perform 1-byte data read from register
38 //
39 PciIo->Io.Read (
40 PciIo,
41 EfiPciIoWidthUint8,
42 EFI_PCI_IO_PASS_THROUGH_BAR,
43 (UINT64) Port,
44 1,
45 &Data
46 );
47 return Data;
48 }
49
50 /**
51 Reads multiple words of data from the IDE data port.
52 Call the IO abstraction once to do the complete read,
53 not one word at a time
54
55 @param PciIo Pointer to the EFI_PCI_IO instance
56 @param Port IO port to read
57 @param Count No. of UINT16's to read
58 @param Buffer Pointer to the data buffer for read
59
60 **/
61 VOID
62 IDEReadPortWMultiple (
63 IN EFI_PCI_IO_PROTOCOL *PciIo,
64 IN UINT16 Port,
65 IN UINTN Count,
66 IN VOID *Buffer
67 )
68 {
69 UINT16 *AlignedBuffer;
70 UINT16 *WorkingBuffer;
71 UINTN Size;
72
73 //
74 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
75 // not perform actual I/O operations if buffer pointer passed in is not at
76 // natural boundary. The "Buffer" argument is passed in by user and may not
77 // at 16-bit natural boundary.
78 //
79 Size = sizeof (UINT16) * Count;
80
81 gBS->AllocatePool (
82 EfiBootServicesData,
83 Size + 1,
84 (VOID**)&WorkingBuffer
85 );
86
87 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
88
89 //
90 // Perform UINT16 data read from FIFO
91 //
92 PciIo->Io.Read (
93 PciIo,
94 EfiPciIoWidthFifoUint16,
95 EFI_PCI_IO_PASS_THROUGH_BAR,
96 (UINT64) Port,
97 Count,
98 (UINT16*)AlignedBuffer
99 );
100
101 //
102 // Copy data to user buffer
103 //
104 CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
105 gBS->FreePool (WorkingBuffer);
106 }
107
108 /**
109 TODO: Add function description
110
111 @param PciIo TODO: add argument description
112 @param Port TODO: add argument description
113 @param Data TODO: add argument description
114
115 TODO: add return values
116
117 **/
118 VOID
119 IDEWritePortB (
120 IN EFI_PCI_IO_PROTOCOL *PciIo,
121 IN UINT16 Port,
122 IN UINT8 Data
123 )
124 {
125 //
126 // perform 1-byte data write to register
127 //
128 PciIo->Io.Write (
129 PciIo,
130 EfiPciIoWidthUint8,
131 EFI_PCI_IO_PASS_THROUGH_BAR,
132 (UINT64) Port,
133 1,
134 &Data
135 );
136
137 }
138
139 /**
140 TODO: Add function description
141
142 @param PciIo TODO: add argument description
143 @param Port TODO: add argument description
144 @param Data TODO: add argument description
145
146 TODO: add return values
147
148 **/
149 VOID
150 IDEWritePortW (
151 IN EFI_PCI_IO_PROTOCOL *PciIo,
152 IN UINT16 Port,
153 IN UINT16 Data
154 )
155 {
156 //
157 // perform 1-word data write to register
158 //
159 PciIo->Io.Write (
160 PciIo,
161 EfiPciIoWidthUint16,
162 EFI_PCI_IO_PASS_THROUGH_BAR,
163 (UINT64) Port,
164 1,
165 &Data
166 );
167 }
168
169 /**
170 Write multiple words of data to the IDE data port.
171 Call the IO abstraction once to do the complete read,
172 not one word at a time
173
174 @param PciIo Pointer to the EFI_PCI_IO instance
175 @param Port IO port to read
176 @param Count No. of UINT16's to read
177 @param Buffer Pointer to the data buffer for read
178
179 **/
180 VOID
181 IDEWritePortWMultiple (
182 IN EFI_PCI_IO_PROTOCOL *PciIo,
183 IN UINT16 Port,
184 IN UINTN Count,
185 IN VOID *Buffer
186 )
187 {
188 UINT16 *AlignedBuffer;
189 UINT32 *WorkingBuffer;
190 UINTN Size;
191
192 //
193 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
194 // not perform actual I/O operations if buffer pointer passed in is not at
195 // natural boundary. The "Buffer" argument is passed in by user and may not
196 // at 16-bit natural boundary.
197 //
198 Size = sizeof (UINT16) * Count;
199
200 gBS->AllocatePool (
201 EfiBootServicesData,
202 Size + 1,
203 (VOID **) &WorkingBuffer
204 );
205
206 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
207
208 //
209 // Copy data from user buffer to working buffer
210 //
211 CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
212
213 //
214 // perform UINT16 data write to the FIFO
215 //
216 PciIo->Io.Write (
217 PciIo,
218 EfiPciIoWidthFifoUint16,
219 EFI_PCI_IO_PASS_THROUGH_BAR,
220 (UINT64) Port,
221 Count,
222 (UINT16 *) AlignedBuffer
223 );
224
225 gBS->FreePool (WorkingBuffer);
226 }
227
228 /**
229 TODO: Add function description
230
231 @param IdeDev TODO: add argument description
232
233 TODO: add return values
234
235 **/
236 BOOLEAN
237 BadIdeDeviceCheck (
238 IN IDE_BLK_IO_DEV *IdeDev
239 )
240 {
241 //
242 // check whether all registers return 0xff,
243 // if so, deem the channel is disabled.
244 //
245 #ifdef EFI_DEBUG
246
247 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Data) != 0xff) {
248 return FALSE;
249 }
250
251 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature) != 0xff) {
252 return FALSE;
253 }
254
255 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount) != 0xff) {
256 return FALSE;
257 }
258
259 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber) != 0xff) {
260 return FALSE;
261 }
262
263 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb) != 0xff) {
264 return FALSE;
265 }
266
267 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) != 0xff) {
268 return FALSE;
269 }
270
271 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Head) != 0xff) {
272 return FALSE;
273 }
274
275 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command) != 0xff) {
276 return FALSE;
277 }
278
279 if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus) != 0xff) {
280 return FALSE;
281 }
282
283 return TRUE;
284
285 #else
286
287 return FALSE;
288
289 #endif
290 }
291
292 //
293 // GetIdeRegistersBaseAddr
294 //
295 /**
296 Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
297 use fixed addresses. In Native-PCI mode, get base addresses from BARs in
298 the PCI IDE controller's Configuration Space.
299
300 The steps to get IDE IO port registers' base addresses for each channel
301 as follows:
302
303 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
304 controller's Configuration Space to determine the operating mode.
305
306 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
307 <pre>
308 ___________________________________________
309 | | Command Block | Control Block |
310 | Channel | Registers | Registers |
311 |___________|_______________|_______________|
312 | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
313 |___________|_______________|_______________|
314 | Secondary | 170h - 177h | 376h - 377h |
315 |___________|_______________|_______________|
316
317 Table 1. Compatibility resource mappings
318 </pre>
319
320 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
321 in IDE controller's PCI Configuration Space, shown in the Table 2 below.
322 <pre>
323 ___________________________________________________
324 | | Command Block | Control Block |
325 | Channel | Registers | Registers |
326 |___________|___________________|___________________|
327 | Primary | BAR at offset 0x10| BAR at offset 0x14|
328 |___________|___________________|___________________|
329 | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
330 |___________|___________________|___________________|
331
332 Table 2. BARs for Register Mapping
333 </pre>
334 @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
335 primary, 0374h for secondary. So 2 bytes extra offset should be
336 added to the base addresses read from BARs.
337
338 For more details, please refer to PCI IDE Controller Specification and Intel
339 ICH4 Datasheet.
340
341 @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
342 @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
343 receive IDE IO port registers' base addresses
344
345 **/
346 EFI_STATUS
347 GetIdeRegistersBaseAddr (
348 IN EFI_PCI_IO_PROTOCOL *PciIo,
349 OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
350 )
351 // TODO: EFI_UNSUPPORTED - add return value to function comment
352 // TODO: EFI_UNSUPPORTED - add return value to function comment
353 // TODO: EFI_SUCCESS - add return value to function comment
354 {
355 EFI_STATUS Status;
356 PCI_TYPE00 PciData;
357
358 Status = PciIo->Pci.Read (
359 PciIo,
360 EfiPciIoWidthUint8,
361 0,
362 sizeof (PciData),
363 &PciData
364 );
365
366 if (EFI_ERROR (Status)) {
367 return Status;
368 }
369
370 if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
371 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;
372 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;
373 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
374 (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
375 } else {
376 //
377 // The BARs should be of IO type
378 //
379 if ((PciData.Device.Bar[0] & bit0) == 0 ||
380 (PciData.Device.Bar[1] & bit0) == 0) {
381 return EFI_UNSUPPORTED;
382 }
383
384 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =
385 (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
386 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =
387 (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
388 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
389 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
390 }
391
392 if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
393 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;
394 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;
395 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
396 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
397 } else {
398 //
399 // The BARs should be of IO type
400 //
401 if ((PciData.Device.Bar[2] & bit0) == 0 ||
402 (PciData.Device.Bar[3] & bit0) == 0) {
403 return EFI_UNSUPPORTED;
404 }
405
406 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =
407 (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
408 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =
409 (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
410 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
411 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
412 }
413
414 return EFI_SUCCESS;
415 }
416
417 /**
418 This function is used to requery IDE resources. The IDE controller will
419 probably switch between native and legacy modes during the EFI->CSM->OS
420 transfer. We do this everytime before an BlkIo operation to ensure its
421 succeess.
422
423 @param IdeDev The BLK_IO private data which specifies the IDE device
424
425 **/
426 EFI_STATUS
427 ReassignIdeResources (
428 IN IDE_BLK_IO_DEV *IdeDev
429 )
430 // TODO: EFI_SUCCESS - add return value to function comment
431 {
432 EFI_STATUS Status;
433 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
434 UINT16 CommandBlockBaseAddr;
435 UINT16 ControlBlockBaseAddr;
436
437 //
438 // Requery IDE IO port registers' base addresses in case of the switch of
439 // native and legacy modes
440 //
441 Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
442 if (EFI_ERROR (Status)) {
443 return Status;
444 }
445
446 ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
447 CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
448 ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
449
450 IdeDev->IoPort->Data = CommandBlockBaseAddr;
451 (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
452 IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
453 IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
454 IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
455 IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
456 IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
457
458 (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
459 (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr;
460 IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
461 IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
462
463 IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
464 return EFI_SUCCESS;
465 }
466
467 /**
468 Read SATA registers to detect SATA disks
469
470 @param IdeDev The BLK_IO private data which specifies the IDE device
471
472 **/
473 EFI_STATUS
474 CheckPowerMode (
475 IDE_BLK_IO_DEV *IdeDev
476 )
477 // TODO: EFI_NOT_FOUND - add return value to function comment
478 // TODO: EFI_SUCCESS - add return value to function comment
479 // TODO: EFI_NOT_FOUND - add return value to function comment
480 {
481 UINT8 ErrorRegister;
482 EFI_STATUS Status;
483
484 IDEWritePortB (
485 IdeDev->PciIo,
486 IdeDev->IoPort->Head,
487 (UINT8) ((IdeDev->Device << 4) | 0xe0)
488 );
489
490 //
491 // Wait 31 seconds for BSY clear. BSY should be in clear state if there exists
492 // a device (initial state). Normally, BSY is also in clear state if there is
493 // no device
494 //
495 Status = WaitForBSYClear (IdeDev, 31000);
496 if (EFI_ERROR (Status)) {
497 return EFI_NOT_FOUND;
498 }
499
500 //
501 // select device, read error register
502 //
503 IDEWritePortB (
504 IdeDev->PciIo,
505 IdeDev->IoPort->Head,
506 (UINT8) ((IdeDev->Device << 4) | 0xe0)
507 );
508 Status = DRDYReady (IdeDev, 200);
509
510 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
511 if ((ErrorRegister == 0x01) || (ErrorRegister == 0x81)) {
512 return EFI_SUCCESS;
513 } else {
514 return EFI_NOT_FOUND;
515 }
516 }
517
518 //
519 // DiscoverIdeDevice
520 //
521 /**
522 Detect if there is disk connected to this port
523
524 @param IdeDev The BLK_IO private data which specifies the IDE device
525
526 **/
527 EFI_STATUS
528 DiscoverIdeDevice (
529 IN IDE_BLK_IO_DEV *IdeDev
530 )
531 // TODO: EFI_NOT_FOUND - add return value to function comment
532 // TODO: EFI_NOT_FOUND - add return value to function comment
533 // TODO: EFI_SUCCESS - add return value to function comment
534 {
535 EFI_STATUS Status;
536 BOOLEAN SataFlag;
537
538 SataFlag = FALSE;
539 //
540 // This extra detection is for SATA disks
541 //
542 Status = CheckPowerMode (IdeDev);
543 if (Status == EFI_SUCCESS) {
544 SataFlag = TRUE;
545 }
546
547 //
548 // If a channel has not been checked, check it now. Then set it to "checked" state
549 // After this step, all devices in this channel have been checked.
550 //
551 Status = DetectIDEController (IdeDev);
552
553 if ((EFI_ERROR (Status)) && !SataFlag) {
554 return EFI_NOT_FOUND;
555 }
556
557 //
558 // Device exists. test if it is an ATA device
559 //
560 Status = ATAIdentify (IdeDev);
561 if (EFI_ERROR (Status)) {
562 //
563 // if not ATA device, test if it is an ATAPI device
564 //
565 Status = ATAPIIdentify (IdeDev);
566 if (EFI_ERROR (Status)) {
567 //
568 // if not ATAPI device either, return error.
569 //
570 return EFI_NOT_FOUND;
571 }
572 }
573
574 //
575 // Init Block I/O interface
576 //
577 IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
578 IdeDev->BlkIo.Reset = IDEBlkIoReset;
579 IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks;
580 IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks;
581 IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks;
582
583 IdeDev->BlkMedia.LogicalPartition = FALSE;
584 IdeDev->BlkMedia.WriteCaching = FALSE;
585
586 //
587 // Init Disk Info interface
588 //
589 gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
590 IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry;
591 IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify;
592 IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData;
593 IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde;
594
595 return EFI_SUCCESS;
596 }
597
598 /**
599 This function is called by DiscoverIdeDevice(). It is used for detect
600 whether the IDE device exists in the specified Channel as the specified
601 Device Number.
602
603 There is two IDE channels: one is Primary Channel, the other is
604 Secondary Channel.(Channel is the logical name for the physical "Cable".)
605 Different channel has different register group.
606
607 On each IDE channel, at most two IDE devices attach,
608 one is called Device 0 (Master device), the other is called Device 1
609 (Slave device). The devices on the same channel co-use the same register
610 group, so before sending out a command for a specified device via command
611 register, it is a must to select the current device to accept the command
612 by set the device number in the Head/Device Register.
613
614 @param[in] *IdeDev
615 pointer pointing to IDE_BLK_IO_DEV data structure, used
616 to record all the information of the IDE device.
617
618 @retval TRUE
619 successfully detects device.
620
621 @retval FALSE
622 any failure during detection process will return this
623 value.
624
625 @note
626 TODO: EFI_SUCCESS - add return value to function comment
627 TODO: EFI_NOT_FOUND - add return value to function comment
628
629 **/
630 EFI_STATUS
631 DetectIDEController (
632 IN IDE_BLK_IO_DEV *IdeDev
633 )
634 {
635 EFI_STATUS Status;
636 UINT8 ErrorReg;
637 UINT8 StatusReg;
638 UINT8 InitStatusReg;
639 EFI_STATUS DeviceStatus;
640
641 //
642 // Slave device has been detected with master device.
643 //
644 if ((IdeDev->Device) == 1) {
645 if (SlaveDeviceExist) {
646 //
647 // If master not exists but slave exists, slave have to wait a while
648 //
649 if (!MasterDeviceExist) {
650 //
651 // if single slave can't be detected, add delay 4s here.
652 //
653 gBS->Stall (4000000);
654 }
655
656 return EFI_SUCCESS;
657 } else {
658 return EFI_NOT_FOUND;
659 }
660 }
661
662 //
663 // Select slave device
664 //
665 IDEWritePortB (
666 IdeDev->PciIo,
667 IdeDev->IoPort->Head,
668 (UINT8) ((1 << 4) | 0xe0)
669 );
670 gBS->Stall (100);
671
672 //
673 // Save the init slave status register
674 //
675 InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
676
677 //
678 // Select master back
679 //
680 IDEWritePortB (
681 IdeDev->PciIo,
682 IdeDev->IoPort->Head,
683 (UINT8) ((0 << 4) | 0xe0)
684 );
685 gBS->Stall (100);
686 //
687 // Send ATA Device Execut Diagnostic command.
688 // This command should work no matter DRDY is ready or not
689 //
690 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
691
692 Status = WaitForBSYClear (IdeDev, 3500);
693
694 ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
695
696 //
697 // Master Error register is 0x01. D0 passed, D1 passed or not present.
698 // Master Error register is 0x81. D0 passed, D1 failed. Return.
699 // Master Error register is other value. D0 failed, D1 passed or not present..
700 //
701 if (ErrorReg == 0x01) {
702 MasterDeviceExist = TRUE;
703 DeviceStatus = EFI_SUCCESS;
704 } else if (ErrorReg == 0x81) {
705
706 MasterDeviceExist = TRUE;
707 DeviceStatus = EFI_SUCCESS;
708 SlaveDeviceExist = FALSE;
709
710 return DeviceStatus;
711 } else {
712 MasterDeviceExist = FALSE;
713 DeviceStatus = EFI_NOT_FOUND;
714 }
715
716 //
717 // Master Error register is not 0x81, Go on check Slave
718 //
719
720 //
721 // select slave
722 //
723 IDEWritePortB (
724 IdeDev->PciIo,
725 IdeDev->IoPort->Head,
726 (UINT8) ((1 << 4) | 0xe0)
727 );
728
729 gBS->Stall (300);
730 ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
731
732 //
733 // Slave Error register is not 0x01, D1 failed. Return.
734 //
735 if (ErrorReg != 0x01) {
736 SlaveDeviceExist = FALSE;
737 return DeviceStatus;
738 }
739
740 StatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
741
742 //
743 // Most ATAPI devices don't set DRDY bit, so test with a slow but accurate
744 // "ATAPI TEST UNIT READY" command
745 //
746 if (((StatusReg & DRDY) == 0) && ((InitStatusReg & DRDY) == 0)) {
747 Status = AtapiTestUnitReady (IdeDev);
748
749 //
750 // Still fail, Slave doesn't exist.
751 //
752 if (EFI_ERROR (Status)) {
753 SlaveDeviceExist = FALSE;
754 return DeviceStatus;
755 }
756 }
757
758 //
759 // Error reg is 0x01 and DRDY is ready,
760 // or ATAPI test unit ready success,
761 // or init Slave status DRDY is ready
762 // Slave exists.
763 //
764 SlaveDeviceExist = TRUE;
765
766 return DeviceStatus;
767
768 }
769
770 /**
771 This function is used to poll for the DRQ bit clear in the Status
772 Register. DRQ is cleared when the device is finished transferring data.
773 So this function is called after data transfer is finished.
774
775 @param[in] *IdeDev
776 pointer pointing to IDE_BLK_IO_DEV data structure, used
777 to record all the information of the IDE device.
778
779 @param[in] TimeoutInMilliSeconds
780 used to designate the timeout for the DRQ clear.
781
782 @retval EFI_SUCCESS
783 DRQ bit clear within the time out.
784
785 @retval EFI_TIMEOUT
786 DRQ bit not clear within the time out.
787
788 @note
789 Read Status Register will clear interrupt status.
790
791 **/
792 EFI_STATUS
793 DRQClear (
794 IN IDE_BLK_IO_DEV *IdeDev,
795 IN UINTN TimeoutInMilliSeconds
796 )
797 // TODO: function comment is missing 'Routine Description:'
798 // TODO: function comment is missing 'Arguments:'
799 // TODO: IdeDev - add argument and description to function comment
800 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
801 // TODO: EFI_ABORTED - add return value to function comment
802 {
803 UINT32 Delay;
804 UINT8 StatusRegister;
805 UINT8 ErrorRegister;
806
807 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
808 do {
809
810 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
811
812 //
813 // wait for BSY == 0 and DRQ == 0
814 //
815 if ((StatusRegister & (DRQ | BSY)) == 0) {
816 break;
817 }
818
819 if ((StatusRegister & (BSY | ERR)) == ERR) {
820
821 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
822 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
823 return EFI_ABORTED;
824 }
825 }
826
827 //
828 // Stall for 30 us
829 //
830 gBS->Stall (30);
831
832 Delay--;
833
834 } while (Delay);
835
836 if (Delay == 0) {
837 return EFI_TIMEOUT;
838 }
839
840 return EFI_SUCCESS;
841 }
842
843 /**
844 This function is used to poll for the DRQ bit clear in the Alternate
845 Status Register. DRQ is cleared when the device is finished
846 transferring data. So this function is called after data transfer
847 is finished.
848
849 @param[in] *IdeDev
850 pointer pointing to IDE_BLK_IO_DEV data structure, used
851 to record all the information of the IDE device.
852
853 @param[in] TimeoutInMilliSeconds
854 used to designate the timeout for the DRQ clear.
855
856 @retval EFI_SUCCESS
857 DRQ bit clear within the time out.
858
859 @retval EFI_TIMEOUT
860 DRQ bit not clear within the time out.
861
862 @note
863 Read Alternate Status Register will not clear interrupt status.
864
865 **/
866 EFI_STATUS
867 DRQClear2 (
868 IN IDE_BLK_IO_DEV *IdeDev,
869 IN UINTN TimeoutInMilliSeconds
870 )
871 // TODO: function comment is missing 'Routine Description:'
872 // TODO: function comment is missing 'Arguments:'
873 // TODO: IdeDev - add argument and description to function comment
874 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
875 // TODO: EFI_ABORTED - add return value to function comment
876 {
877 UINT32 Delay;
878 UINT8 AltRegister;
879 UINT8 ErrorRegister;
880
881 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
882 do {
883
884 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
885
886 //
887 // wait for BSY == 0 and DRQ == 0
888 //
889 if ((AltRegister & (DRQ | BSY)) == 0) {
890 break;
891 }
892
893 if ((AltRegister & (BSY | ERR)) == ERR) {
894
895 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
896 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
897 return EFI_ABORTED;
898 }
899 }
900
901 //
902 // Stall for 30 us
903 //
904 gBS->Stall (30);
905
906 Delay--;
907
908 } while (Delay);
909
910 if (Delay == 0) {
911 return EFI_TIMEOUT;
912 }
913
914 return EFI_SUCCESS;
915 }
916
917 /**
918 This function is used to poll for the DRQ bit set in the
919 Status Register.
920 DRQ is set when the device is ready to transfer data. So this function
921 is called after the command is sent to the device and before required
922 data is transferred.
923
924 @param[in] IDE_BLK_IO_DEV IN *IdeDev
925 pointer pointing to IDE_BLK_IO_DEV data structure,used
926 to record all the information of the IDE device.
927
928 @param[in] UINTN IN TimeoutInMilliSeconds
929 used to designate the timeout for the DRQ ready.
930
931 @retval EFI_SUCCESS
932 DRQ bit set within the time out.
933
934 @retval EFI_TIMEOUT
935 DRQ bit not set within the time out.
936
937 @retval EFI_ABORTED
938 DRQ bit not set caused by the command abort.
939
940 @note
941 Read Status Register will clear interrupt status.
942
943 **/
944 EFI_STATUS
945 DRQReady (
946 IN IDE_BLK_IO_DEV *IdeDev,
947 IN UINTN TimeoutInMilliSeconds
948 )
949 // TODO: function comment is missing 'Routine Description:'
950 // TODO: function comment is missing 'Arguments:'
951 // TODO: IdeDev - add argument and description to function comment
952 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
953 {
954 UINT32 Delay;
955 UINT8 StatusRegister;
956 UINT8 ErrorRegister;
957
958 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
959 do {
960 //
961 // read Status Register will clear interrupt
962 //
963 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
964
965 //
966 // BSY==0,DRQ==1
967 //
968 if ((StatusRegister & (BSY | DRQ)) == DRQ) {
969 break;
970 }
971
972 if ((StatusRegister & (BSY | ERR)) == ERR) {
973
974 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
975 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
976 return EFI_ABORTED;
977 }
978 }
979
980 //
981 // Stall for 30 us
982 //
983 gBS->Stall (30);
984
985 Delay--;
986 } while (Delay);
987
988 if (Delay == 0) {
989 return EFI_TIMEOUT;
990 }
991
992 return EFI_SUCCESS;
993 }
994
995 /**
996 This function is used to poll for the DRQ bit set in the
997 Alternate Status Register. DRQ is set when the device is ready to
998 transfer data. So this function is called after the command
999 is sent to the device and before required data is transferred.
1000
1001 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1002 pointer pointing to IDE_BLK_IO_DEV data structure, used
1003 to record all the information of the IDE device.
1004
1005 @param[in] UINTN IN TimeoutInMilliSeconds
1006 used to designate the timeout for the DRQ ready.
1007
1008 @retval EFI_SUCCESS
1009 DRQ bit set within the time out.
1010
1011 @retval EFI_TIMEOUT
1012 DRQ bit not set within the time out.
1013
1014 @retval EFI_ABORTED
1015 DRQ bit not set caused by the command abort.
1016
1017 @note
1018 Read Alternate Status Register will not clear interrupt status.
1019
1020 **/
1021 EFI_STATUS
1022 DRQReady2 (
1023 IN IDE_BLK_IO_DEV *IdeDev,
1024 IN UINTN TimeoutInMilliSeconds
1025 )
1026 // TODO: function comment is missing 'Routine Description:'
1027 // TODO: function comment is missing 'Arguments:'
1028 // TODO: IdeDev - add argument and description to function comment
1029 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
1030 {
1031 UINT32 Delay;
1032 UINT8 AltRegister;
1033 UINT8 ErrorRegister;
1034
1035 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1036
1037 do {
1038 //
1039 // Read Alternate Status Register will not clear interrupt status
1040 //
1041 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
1042 //
1043 // BSY == 0 , DRQ == 1
1044 //
1045 if ((AltRegister & (BSY | DRQ)) == DRQ) {
1046 break;
1047 }
1048
1049 if ((AltRegister & (BSY | ERR)) == ERR) {
1050
1051 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
1052 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
1053 return EFI_ABORTED;
1054 }
1055 }
1056
1057 //
1058 // Stall for 30 us
1059 //
1060 gBS->Stall (30);
1061
1062 Delay--;
1063 } while (Delay);
1064
1065 if (Delay == 0) {
1066 return EFI_TIMEOUT;
1067 }
1068
1069 return EFI_SUCCESS;
1070 }
1071
1072 /**
1073 This function is used to poll for the BSY bit clear in the
1074 Status Register. BSY is clear when the device is not busy.
1075 Every command must be sent after device is not busy.
1076
1077 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1078 pointer pointing to IDE_BLK_IO_DEV data structure, used
1079 to record all the information of the IDE device.
1080
1081 @param[in] UINTN IN TimeoutInMilliSeconds
1082 used to designate the timeout for the DRQ ready.
1083
1084 @retval EFI_SUCCESS
1085 BSY bit clear within the time out.
1086
1087 @retval EFI_TIMEOUT
1088 BSY bit not clear within the time out.
1089
1090 @note
1091 Read Status Register will clear interrupt status.
1092
1093 **/
1094 EFI_STATUS
1095 WaitForBSYClear (
1096 IN IDE_BLK_IO_DEV *IdeDev,
1097 IN UINTN TimeoutInMilliSeconds
1098 )
1099 // TODO: function comment is missing 'Routine Description:'
1100 // TODO: function comment is missing 'Arguments:'
1101 // TODO: IdeDev - add argument and description to function comment
1102 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
1103 {
1104 UINT32 Delay;
1105 UINT8 StatusRegister;
1106
1107 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1108 do {
1109
1110 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
1111 if ((StatusRegister & BSY) == 0x00) {
1112 break;
1113 }
1114
1115 //
1116 // Stall for 30 us
1117 //
1118 gBS->Stall (30);
1119
1120 Delay--;
1121
1122 } while (Delay);
1123
1124 if (Delay == 0) {
1125 return EFI_TIMEOUT;
1126 }
1127
1128 return EFI_SUCCESS;
1129 }
1130 //
1131 // WaitForBSYClear2
1132 //
1133 /**
1134 This function is used to poll for the BSY bit clear in the
1135 Alternate Status Register. BSY is clear when the device is not busy.
1136 Every command must be sent after device is not busy.
1137
1138 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1139 pointer pointing to IDE_BLK_IO_DEV data structure, used
1140 to record all the information of the IDE device.
1141
1142 @param[in] UINTN IN TimeoutInMilliSeconds
1143 used to designate the timeout for the DRQ ready.
1144
1145 @retval EFI_SUCCESS
1146 BSY bit clear within the time out.
1147
1148 @retval EFI_TIMEOUT
1149 BSY bit not clear within the time out.
1150
1151 @note
1152 Read Alternate Status Register will not clear interrupt status.
1153
1154 **/
1155 EFI_STATUS
1156 WaitForBSYClear2 (
1157 IN IDE_BLK_IO_DEV *IdeDev,
1158 IN UINTN TimeoutInMilliSeconds
1159 )
1160 // TODO: function comment is missing 'Routine Description:'
1161 // TODO: function comment is missing 'Arguments:'
1162 // TODO: IdeDev - add argument and description to function comment
1163 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
1164 {
1165 UINT32 Delay;
1166 UINT8 AltRegister;
1167
1168 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1169 do {
1170 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
1171 if ((AltRegister & BSY) == 0x00) {
1172 break;
1173 }
1174
1175 gBS->Stall (30);
1176
1177 Delay--;
1178
1179 } while (Delay);
1180
1181 if (Delay == 0) {
1182 return EFI_TIMEOUT;
1183 }
1184
1185 return EFI_SUCCESS;
1186 }
1187
1188 //
1189 // DRDYReady
1190 //
1191 /**
1192 This function is used to poll for the DRDY bit set in the
1193 Status Register. DRDY bit is set when the device is ready
1194 to accept command. Most ATA commands must be sent after
1195 DRDY set except the ATAPI Packet Command.
1196
1197 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1198 pointer pointing to IDE_BLK_IO_DEV data structure, used
1199 to record all the information of the IDE device.
1200
1201 @param[in] UINTN IN TimeoutInMilliSeconds
1202 used to designate the timeout for the DRQ ready.
1203
1204 @retval EFI_SUCCESS
1205 DRDY bit set within the time out.
1206
1207 @retval EFI_TIMEOUT
1208 DRDY bit not set within the time out.
1209
1210 @note
1211 Read Status Register will clear interrupt status.
1212
1213 **/
1214 EFI_STATUS
1215 DRDYReady (
1216 IN IDE_BLK_IO_DEV *IdeDev,
1217 IN UINTN DelayInMilliSeconds
1218 )
1219 // TODO: function comment is missing 'Routine Description:'
1220 // TODO: function comment is missing 'Arguments:'
1221 // TODO: IdeDev - add argument and description to function comment
1222 // TODO: DelayInMilliSeconds - add argument and description to function comment
1223 // TODO: EFI_ABORTED - add return value to function comment
1224 {
1225 UINT32 Delay;
1226 UINT8 StatusRegister;
1227 UINT8 ErrorRegister;
1228
1229 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1230 do {
1231 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
1232 //
1233 // BSY == 0 , DRDY == 1
1234 //
1235 if ((StatusRegister & (DRDY | BSY)) == DRDY) {
1236 break;
1237 }
1238
1239 if ((StatusRegister & (BSY | ERR)) == ERR) {
1240
1241 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
1242 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
1243 return EFI_ABORTED;
1244 }
1245 }
1246
1247 gBS->Stall (15);
1248
1249 Delay--;
1250 } while (Delay);
1251
1252 if (Delay == 0) {
1253 return EFI_TIMEOUT;
1254 }
1255
1256 return EFI_SUCCESS;
1257 }
1258
1259 //
1260 // DRDYReady2
1261 //
1262 /**
1263 This function is used to poll for the DRDY bit set in the
1264 Alternate Status Register. DRDY bit is set when the device is ready
1265 to accept command. Most ATA commands must be sent after
1266 DRDY set except the ATAPI Packet Command.
1267
1268 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1269 pointer pointing to IDE_BLK_IO_DEV data structure, used
1270 to record all the information of the IDE device.
1271
1272 @param[in] UINTN IN TimeoutInMilliSeconds
1273 used to designate the timeout for the DRQ ready.
1274
1275 @retval EFI_SUCCESS
1276 DRDY bit set within the time out.
1277
1278 @retval EFI_TIMEOUT
1279 DRDY bit not set within the time out.
1280
1281 @note
1282 Read Alternate Status Register will clear interrupt status.
1283
1284 **/
1285 EFI_STATUS
1286 DRDYReady2 (
1287 IN IDE_BLK_IO_DEV *IdeDev,
1288 IN UINTN DelayInMilliSeconds
1289 )
1290 // TODO: function comment is missing 'Routine Description:'
1291 // TODO: function comment is missing 'Arguments:'
1292 // TODO: IdeDev - add argument and description to function comment
1293 // TODO: DelayInMilliSeconds - add argument and description to function comment
1294 // TODO: EFI_ABORTED - add return value to function comment
1295 {
1296 UINT32 Delay;
1297 UINT8 AltRegister;
1298 UINT8 ErrorRegister;
1299
1300 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1301 do {
1302 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
1303 //
1304 // BSY == 0 , DRDY == 1
1305 //
1306 if ((AltRegister & (DRDY | BSY)) == DRDY) {
1307 break;
1308 }
1309
1310 if ((AltRegister & (BSY | ERR)) == ERR) {
1311
1312 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
1313 if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
1314 return EFI_ABORTED;
1315 }
1316 }
1317
1318 gBS->Stall (30);
1319
1320 Delay--;
1321 } while (Delay);
1322
1323 if (Delay == 0) {
1324 return EFI_TIMEOUT;
1325 }
1326
1327 return EFI_SUCCESS;
1328 }
1329
1330 //
1331 // SwapStringChars
1332 //
1333 /**
1334 This function is a helper function used to change the char order in a
1335 string. It is designed specially for the PrintAtaModuleName() function.
1336 After the IDE device is detected, the IDE driver gets the device module
1337 name by sending ATA command called ATA Identify Command or ATAPI
1338 Identify Command to the specified IDE device. The module name returned
1339 is a string of ASCII characters: the first character is bit8--bit15
1340 of the first word, the second character is bit0--bit7 of the first word
1341 and so on. Thus the string can not be print directly before it is
1342 preprocessed by this func to change the order of characters in
1343 each word in the string.
1344
1345 @param[in] CHAR8 IN *Destination
1346 Indicates the destination string.
1347
1348 @param[in] CHAR8 IN *Source
1349 Indicates the source string.
1350
1351 @param[in] UINT8 IN Size
1352 the length of the string
1353
1354 **/
1355 VOID
1356 SwapStringChars (
1357 IN CHAR8 *Destination,
1358 IN CHAR8 *Source,
1359 IN UINT32 Size
1360 )
1361 {
1362 UINT32 Index;
1363 CHAR8 Temp;
1364
1365 for (Index = 0; Index < Size; Index += 2) {
1366
1367 Temp = Source[Index + 1];
1368 Destination[Index + 1] = Source[Index];
1369 Destination[Index] = Temp;
1370 }
1371 }
1372
1373 //
1374 // ReleaseIdeResources
1375 //
1376 /**
1377 Release resources of an IDE device before stopping it.
1378
1379 @param[in] *IdeBlkIoDevice Standard IDE device private data structure
1380
1381 **/
1382 VOID
1383 ReleaseIdeResources (
1384 IN IDE_BLK_IO_DEV *IdeBlkIoDevice
1385 )
1386 {
1387 if (IdeBlkIoDevice == NULL) {
1388 return ;
1389 }
1390
1391 //
1392 // Release all the resourses occupied by the IDE_BLK_IO_DEV
1393 //
1394
1395 if (IdeBlkIoDevice->SenseData != NULL) {
1396 gBS->FreePool (IdeBlkIoDevice->SenseData);
1397 IdeBlkIoDevice->SenseData = NULL;
1398 }
1399
1400 if (IdeBlkIoDevice->Cache != NULL) {
1401 gBS->FreePool (IdeBlkIoDevice->Cache);
1402 IdeBlkIoDevice->Cache = NULL;
1403 }
1404
1405 if (IdeBlkIoDevice->pIdData != NULL) {
1406 gBS->FreePool (IdeBlkIoDevice->pIdData);
1407 IdeBlkIoDevice->pIdData = NULL;
1408 }
1409
1410 if (IdeBlkIoDevice->pInquiryData != NULL) {
1411 gBS->FreePool (IdeBlkIoDevice->pInquiryData);
1412 IdeBlkIoDevice->pInquiryData = NULL;
1413 }
1414
1415 if (IdeBlkIoDevice->ControllerNameTable != NULL) {
1416 FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
1417 IdeBlkIoDevice->ControllerNameTable = NULL;
1418 }
1419
1420 if (IdeBlkIoDevice->IoPort != NULL) {
1421 gBS->FreePool (IdeBlkIoDevice->IoPort);
1422 }
1423
1424 if (IdeBlkIoDevice->DevicePath != NULL) {
1425 gBS->FreePool (IdeBlkIoDevice->DevicePath);
1426 }
1427
1428 gBS->FreePool (IdeBlkIoDevice);
1429 IdeBlkIoDevice = NULL;
1430
1431 return ;
1432 }
1433
1434 //
1435 // SetDeviceTransferMode
1436 //
1437 /**
1438 Set the calculated Best transfer mode to a detected device
1439
1440 @param[in] *IdeDev Standard IDE device private data structure
1441 @param[in] *TransferMode The device transfer mode to be set
1442
1443 @return Set transfer mode Command execute status
1444
1445 **/
1446 EFI_STATUS
1447 SetDeviceTransferMode (
1448 IN IDE_BLK_IO_DEV *IdeDev,
1449 IN ATA_TRANSFER_MODE *TransferMode
1450 )
1451 // TODO: function comment is missing 'Routine Description:'
1452 {
1453 EFI_STATUS Status;
1454 UINT8 DeviceSelect;
1455 UINT8 SectorCount;
1456
1457 DeviceSelect = 0;
1458 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
1459 SectorCount = *((UINT8 *) TransferMode);
1460
1461 //
1462 // Send SET FEATURE command (sub command 0x03) to set pio mode.
1463 //
1464 Status = AtaNonDataCommandIn (
1465 IdeDev,
1466 SET_FEATURES_CMD,
1467 DeviceSelect,
1468 0x03,
1469 SectorCount,
1470 0,
1471 0,
1472 0
1473 );
1474
1475 return Status;
1476 }
1477
1478 /**
1479 Send ATA command into device with NON_DATA protocol
1480
1481 @param IdeDev Standard IDE device private data structure
1482 @param AtaCommand The ATA command to be sent
1483 @param Device The value in Device register
1484 @param Feature The value in Feature register
1485 @param SectorCount The value in SectorCount register
1486 @param LbaLow The value in LBA_LOW register
1487 @param LbaMiddle The value in LBA_MIDDLE register
1488 @param LbaHigh The value in LBA_HIGH register
1489
1490 @retval EFI_SUCCESS Reading succeed
1491 @retval EFI_ABORTED Command failed
1492 @retval EFI_DEVICE_ERROR Device status error
1493
1494 **/
1495 EFI_STATUS
1496 AtaNonDataCommandIn (
1497 IN IDE_BLK_IO_DEV *IdeDev,
1498 IN UINT8 AtaCommand,
1499 IN UINT8 Device,
1500 IN UINT8 Feature,
1501 IN UINT8 SectorCount,
1502 IN UINT8 LbaLow,
1503 IN UINT8 LbaMiddle,
1504 IN UINT8 LbaHigh
1505 )
1506 {
1507 EFI_STATUS Status;
1508 UINT8 StatusRegister;
1509
1510 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
1511 if (EFI_ERROR (Status)) {
1512 return EFI_DEVICE_ERROR;
1513 }
1514
1515 //
1516 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
1517 //
1518 IDEWritePortB (
1519 IdeDev->PciIo,
1520 IdeDev->IoPort->Head,
1521 (UINT8) ((IdeDev->Device << 4) | 0xe0)
1522 );
1523
1524 //
1525 // ATA commands for ATA device must be issued when DRDY is set
1526 //
1527 Status = DRDYReady (IdeDev, ATATIMEOUT);
1528 if (EFI_ERROR (Status)) {
1529 return EFI_DEVICE_ERROR;
1530 }
1531
1532 //
1533 // Pass parameter into device register block
1534 //
1535 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
1536 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);
1537 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
1538 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
1539 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);
1540 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
1541
1542 //
1543 // Send command via Command Register
1544 //
1545 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
1546
1547 //
1548 // Wait for command completion
1549 //
1550 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
1551 if (EFI_ERROR (Status)) {
1552 return EFI_DEVICE_ERROR;
1553 }
1554
1555 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
1556 if ((StatusRegister & ERR) == ERR) {
1557 //
1558 // Failed to execute command, abort operation
1559 //
1560 return EFI_ABORTED;
1561 }
1562
1563 return EFI_SUCCESS;
1564 }
1565
1566 /**
1567 Send ATA Ext command into device with NON_DATA protocol
1568
1569 @param IdeDev Standard IDE device private data structure
1570 @param AtaCommand The ATA command to be sent
1571 @param Device The value in Device register
1572 @param Feature The value in Feature register
1573 @param SectorCount The value in SectorCount register
1574 @param LbaAddress The LBA address in 48-bit mode
1575
1576 @retval EFI_SUCCESS Reading succeed
1577 @retval EFI_ABORTED Command failed
1578 @retval EFI_DEVICE_ERROR Device status error
1579
1580 **/
1581 EFI_STATUS
1582 AtaNonDataCommandInExt (
1583 IN IDE_BLK_IO_DEV *IdeDev,
1584 IN UINT8 AtaCommand,
1585 IN UINT8 Device,
1586 IN UINT16 Feature,
1587 IN UINT16 SectorCount,
1588 IN EFI_LBA LbaAddress
1589 )
1590 {
1591 EFI_STATUS Status;
1592 UINT8 StatusRegister;
1593 UINT8 SectorCount8;
1594 UINT8 Feature8;
1595 UINT8 LbaLow;
1596 UINT8 LbaMid;
1597 UINT8 LbaHigh;
1598
1599 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
1600 if (EFI_ERROR (Status)) {
1601 return EFI_DEVICE_ERROR;
1602 }
1603
1604 //
1605 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
1606 //
1607 IDEWritePortB (
1608 IdeDev->PciIo,
1609 IdeDev->IoPort->Head,
1610 (UINT8) ((IdeDev->Device << 4) | 0xe0)
1611 );
1612
1613 //
1614 // ATA commands for ATA device must be issued when DRDY is set
1615 //
1616 Status = DRDYReady (IdeDev, ATATIMEOUT);
1617 if (EFI_ERROR (Status)) {
1618 return EFI_DEVICE_ERROR;
1619 }
1620
1621 //
1622 // Pass parameter into device register block
1623 //
1624 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
1625
1626 //
1627 // Fill the feature register, which is a two-byte FIFO. Need write twice.
1628 //
1629 Feature8 = (UINT8) (Feature >> 8);
1630 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
1631
1632 Feature8 = (UINT8) Feature;
1633 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
1634
1635 //
1636 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
1637 //
1638 SectorCount8 = (UINT8) (SectorCount >> 8);
1639 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
1640
1641 SectorCount8 = (UINT8) SectorCount;
1642 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
1643
1644 //
1645 // Fill the start LBA registers, which are also two-byte FIFO
1646 //
1647 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
1648 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
1649 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
1650 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
1651 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
1652 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
1653
1654 LbaLow = (UINT8) LbaAddress;
1655 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
1656 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
1657 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
1658 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
1659 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
1660
1661 //
1662 // Send command via Command Register
1663 //
1664 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
1665
1666 //
1667 // Wait for command completion
1668 //
1669 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
1670 if (EFI_ERROR (Status)) {
1671 return EFI_DEVICE_ERROR;
1672 }
1673
1674 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
1675 if ((StatusRegister & ERR) == ERR) {
1676 //
1677 // Failed to execute command, abort operation
1678 //
1679 return EFI_ABORTED;
1680 }
1681
1682 return EFI_SUCCESS;
1683 }
1684
1685 //
1686 // SetDriveParameters
1687 //
1688 /**
1689 Set drive parameters for devices not support PACKETS command
1690
1691 @param[in] IdeDev Standard IDE device private data structure
1692 @param[in] DriveParameters The device parameters to be set into the disk
1693
1694 @return SetParameters Command execute status
1695
1696 **/
1697 EFI_STATUS
1698 SetDriveParameters (
1699 IN IDE_BLK_IO_DEV *IdeDev,
1700 IN ATA_DRIVE_PARMS *DriveParameters
1701 )
1702 {
1703 EFI_STATUS Status;
1704 UINT8 DeviceSelect;
1705
1706 DeviceSelect = 0;
1707 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
1708
1709 //
1710 // Send Init drive parameters
1711 //
1712 Status = AtaPioDataIn (
1713 IdeDev,
1714 NULL,
1715 0,
1716 INIT_DRIVE_PARAM_CMD,
1717 (UINT8) (DeviceSelect + DriveParameters->Heads),
1718 DriveParameters->Sector,
1719 0,
1720 0,
1721 0
1722 );
1723
1724 //
1725 // Send Set Multiple parameters
1726 //
1727 Status = AtaPioDataIn (
1728 IdeDev,
1729 NULL,
1730 0,
1731 SET_MULTIPLE_MODE_CMD,
1732 DeviceSelect,
1733 DriveParameters->MultipleSector,
1734 0,
1735 0,
1736 0
1737 );
1738
1739 return Status;
1740 }
1741
1742 /**
1743 TODO: Add function description
1744
1745 @param IdeDev TODO: add argument description
1746
1747 @retval EFI_SUCCESS TODO: Add description for return value
1748
1749 **/
1750 EFI_STATUS
1751 EnableInterrupt (
1752 IN IDE_BLK_IO_DEV *IdeDev
1753 )
1754 {
1755 UINT8 DeviceControl;
1756
1757 //
1758 // Enable interrupt for DMA operation
1759 //
1760 DeviceControl = 0;
1761 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
1762
1763 return EFI_SUCCESS;
1764 }