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