]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c
8ab81b14dd7ea2eb052b0e2c4de58c6cae6df47e
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / Ide.c
1 /** @file
2 The file ontaining the helper functions implement of the Ide Bus driver
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "IdeBus.h"
10
11 BOOLEAN ChannelDeviceDetected = FALSE;
12 BOOLEAN SlaveDeviceExist = FALSE;
13 UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE;
14 BOOLEAN MasterDeviceExist = FALSE;
15 UINT8 MasterDeviceType = INVALID_DEVICE_TYPE;
16
17 /**
18 read a one-byte data from a IDE port.
19
20 @param PciIo The PCI IO protocol instance
21 @param Port the IDE Port number
22
23 @return the one-byte data read from IDE port
24 **/
25 UINT8
26 IDEReadPortB (
27 IN EFI_PCI_IO_PROTOCOL *PciIo,
28 IN UINT16 Port
29 )
30 {
31 UINT8 Data;
32
33 Data = 0;
34 //
35 // perform 1-byte data read from register
36 //
37 PciIo->Io.Read (
38 PciIo,
39 EfiPciIoWidthUint8,
40 EFI_PCI_IO_PASS_THROUGH_BAR,
41 (UINT64) Port,
42 1,
43 &Data
44 );
45 return Data;
46 }
47 /**
48 Reads multiple words of data from the IDE data port.
49 Call the IO abstraction once to do the complete read,
50 not one word at a time
51
52 @param PciIo Pointer to the EFI_PCI_IO instance
53 @param Port IO port to read
54 @param Count No. of UINT16's to read
55 @param Buffer Pointer to the data buffer for read
56
57 **/
58 VOID
59 IDEReadPortWMultiple (
60 IN EFI_PCI_IO_PROTOCOL *PciIo,
61 IN UINT16 Port,
62 IN UINTN Count,
63 OUT VOID *Buffer
64 )
65 {
66 UINT16 *AlignedBuffer;
67 UINT16 *WorkingBuffer;
68 UINTN Size;
69
70 //
71 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
72 // not perform actual I/O operations if buffer pointer passed in is not at
73 // natural boundary. The "Buffer" argument is passed in by user and may not
74 // at 16-bit natural boundary.
75 //
76 Size = sizeof (UINT16) * Count;
77
78 gBS->AllocatePool (
79 EfiBootServicesData,
80 Size + 1,
81 (VOID**)&WorkingBuffer
82 );
83
84 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
85
86 //
87 // Perform UINT16 data read from FIFO
88 //
89 PciIo->Io.Read (
90 PciIo,
91 EfiPciIoWidthFifoUint16,
92 EFI_PCI_IO_PASS_THROUGH_BAR,
93 (UINT64) Port,
94 Count,
95 (UINT16*)AlignedBuffer
96 );
97
98 //
99 // Copy data to user buffer
100 //
101 CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
102 gBS->FreePool (WorkingBuffer);
103 }
104
105 /**
106 write a 1-byte data to a specific IDE port.
107
108 @param PciIo PCI IO protocol instance
109 @param Port The IDE port to be writen
110 @param Data The data to write to the port
111 **/
112 VOID
113 IDEWritePortB (
114 IN EFI_PCI_IO_PROTOCOL *PciIo,
115 IN UINT16 Port,
116 IN UINT8 Data
117 )
118 {
119 //
120 // perform 1-byte data write to register
121 //
122 PciIo->Io.Write (
123 PciIo,
124 EfiPciIoWidthUint8,
125 EFI_PCI_IO_PASS_THROUGH_BAR,
126 (UINT64) Port,
127 1,
128 &Data
129 );
130
131 }
132
133 /**
134 write a 1-word data to a specific IDE port.
135
136 @param PciIo PCI IO protocol instance
137 @param Port The IDE port to be writen
138 @param Data The data to write to the port
139 **/
140 VOID
141 IDEWritePortW (
142 IN EFI_PCI_IO_PROTOCOL *PciIo,
143 IN UINT16 Port,
144 IN UINT16 Data
145 )
146 {
147 //
148 // perform 1-word data write to register
149 //
150 PciIo->Io.Write (
151 PciIo,
152 EfiPciIoWidthUint16,
153 EFI_PCI_IO_PASS_THROUGH_BAR,
154 (UINT64) Port,
155 1,
156 &Data
157 );
158 }
159
160 /**
161 Write multiple words of data to the IDE data port.
162 Call the IO abstraction once to do the complete read,
163 not one word at a time
164
165 @param PciIo Pointer to the EFI_PCI_IO instance
166 @param Port IO port to read
167 @param Count No. of UINT16's to read
168 @param Buffer Pointer to the data buffer for read
169
170 **/
171 VOID
172 IDEWritePortWMultiple (
173 IN EFI_PCI_IO_PROTOCOL *PciIo,
174 IN UINT16 Port,
175 IN UINTN Count,
176 IN VOID *Buffer
177 )
178 {
179 UINT16 *AlignedBuffer;
180 UINT32 *WorkingBuffer;
181 UINTN Size;
182
183 //
184 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
185 // not perform actual I/O operations if buffer pointer passed in is not at
186 // natural boundary. The "Buffer" argument is passed in by user and may not
187 // at 16-bit natural boundary.
188 //
189 Size = sizeof (UINT16) * Count;
190
191 gBS->AllocatePool (
192 EfiBootServicesData,
193 Size + 1,
194 (VOID **) &WorkingBuffer
195 );
196
197 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
198
199 //
200 // Copy data from user buffer to working buffer
201 //
202 CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
203
204 //
205 // perform UINT16 data write to the FIFO
206 //
207 PciIo->Io.Write (
208 PciIo,
209 EfiPciIoWidthFifoUint16,
210 EFI_PCI_IO_PASS_THROUGH_BAR,
211 (UINT64) Port,
212 Count,
213 (UINT16 *) AlignedBuffer
214 );
215
216 gBS->FreePool (WorkingBuffer);
217 }
218 /**
219 Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
220 use fixed addresses. In Native-PCI mode, get base addresses from BARs in
221 the PCI IDE controller's Configuration Space.
222
223 The steps to get IDE IO port registers' base addresses for each channel
224 as follows:
225
226 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
227 controller's Configuration Space to determine the operating mode.
228
229 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
230 <pre>
231 ___________________________________________
232 | | Command Block | Control Block |
233 | Channel | Registers | Registers |
234 |___________|_______________|_______________|
235 | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
236 |___________|_______________|_______________|
237 | Secondary | 170h - 177h | 376h - 377h |
238 |___________|_______________|_______________|
239
240 Table 1. Compatibility resource mappings
241 </pre>
242
243 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
244 in IDE controller's PCI Configuration Space, shown in the Table 2 below.
245 <pre>
246 ___________________________________________________
247 | | Command Block | Control Block |
248 | Channel | Registers | Registers |
249 |___________|___________________|___________________|
250 | Primary | BAR at offset 0x10| BAR at offset 0x14|
251 |___________|___________________|___________________|
252 | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
253 |___________|___________________|___________________|
254
255 Table 2. BARs for Register Mapping
256 </pre>
257 @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
258 primary, 0374h for secondary. So 2 bytes extra offset should be
259 added to the base addresses read from BARs.
260
261 For more details, please refer to PCI IDE Controller Specification and Intel
262 ICH4 Datasheet.
263
264 @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
265 @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
266 receive IDE IO port registers' base addresses
267
268 @retval EFI_UNSUPPORTED return this value when the BARs is not IO type
269 @retval EFI_SUCCESS Get the Base address successfully
270 @retval other read the pci configureation data error
271
272 **/
273 EFI_STATUS
274 GetIdeRegistersBaseAddr (
275 IN EFI_PCI_IO_PROTOCOL *PciIo,
276 OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
277 )
278 {
279 EFI_STATUS Status;
280 PCI_TYPE00 PciData;
281
282 Status = PciIo->Pci.Read (
283 PciIo,
284 EfiPciIoWidthUint8,
285 0,
286 sizeof (PciData),
287 &PciData
288 );
289
290 if (EFI_ERROR (Status)) {
291 return Status;
292 }
293
294 if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
295 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;
296 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;
297 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
298 (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
299 } else {
300 //
301 // The BARs should be of IO type
302 //
303 if ((PciData.Device.Bar[0] & BIT0) == 0 ||
304 (PciData.Device.Bar[1] & BIT0) == 0) {
305 return EFI_UNSUPPORTED;
306 }
307
308 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =
309 (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
310 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =
311 (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
312 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
313 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
314 }
315
316 if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
317 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;
318 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;
319 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
320 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
321 } else {
322 //
323 // The BARs should be of IO type
324 //
325 if ((PciData.Device.Bar[2] & BIT0) == 0 ||
326 (PciData.Device.Bar[3] & BIT0) == 0) {
327 return EFI_UNSUPPORTED;
328 }
329
330 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =
331 (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
332 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =
333 (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
334 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
335 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
336 }
337
338 return EFI_SUCCESS;
339 }
340
341 /**
342 This function is used to requery IDE resources. The IDE controller will
343 probably switch between native and legacy modes during the EFI->CSM->OS
344 transfer. We do this everytime before an BlkIo operation to ensure its
345 succeess.
346
347 @param IdeDev The BLK_IO private data which specifies the IDE device
348
349 @retval EFI_INVALID_PARAMETER return this value when the channel is invalid
350 @retval EFI_SUCCESS reassign the IDE IO resource successfully
351 @retval other get the IDE current base address effor
352
353 **/
354 EFI_STATUS
355 ReassignIdeResources (
356 IN IDE_BLK_IO_DEV *IdeDev
357 )
358 {
359 EFI_STATUS Status;
360 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
361 UINT16 CommandBlockBaseAddr;
362 UINT16 ControlBlockBaseAddr;
363
364 if (IdeDev->Channel >= IdeMaxChannel) {
365 return EFI_INVALID_PARAMETER;
366 }
367
368 //
369 // Requery IDE IO port registers' base addresses in case of the switch of
370 // native and legacy modes
371 //
372 Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
373 if (EFI_ERROR (Status)) {
374 return Status;
375 }
376
377 ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
378 CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
379 ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
380
381 IdeDev->IoPort->Data = CommandBlockBaseAddr;
382 (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
383 IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
384 IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
385 IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
386 IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
387 IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
388
389 (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
390 (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr;
391 IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
392 IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
393
394 IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
395 return EFI_SUCCESS;
396 }
397
398 /**
399 This function is called by DiscoverIdeDevice(). It is used for detect
400 whether the IDE device exists in the specified Channel as the specified
401 Device Number.
402
403 There is two IDE channels: one is Primary Channel, the other is
404 Secondary Channel.(Channel is the logical name for the physical "Cable".)
405 Different channel has different register group.
406
407 On each IDE channel, at most two IDE devices attach,
408 one is called Device 0 (Master device), the other is called Device 1
409 (Slave device). The devices on the same channel co-use the same register
410 group, so before sending out a command for a specified device via command
411 register, it is a must to select the current device to accept the command
412 by set the device number in the Head/Device Register.
413
414 @param IdeDev pointer to IDE_BLK_IO_DEV data structure, used to record all the
415 information of the IDE device.
416
417 @retval EFI_SUCCESS successfully detects device.
418
419 @retval other any failure during detection process will return this value.
420
421 **/
422 EFI_STATUS
423 DetectIDEController (
424 IN IDE_BLK_IO_DEV *IdeDev
425 )
426 {
427 EFI_STATUS Status;
428 UINT8 SectorCountReg;
429 UINT8 LBALowReg;
430 UINT8 LBAMidReg;
431 UINT8 LBAHighReg;
432 UINT8 InitStatusReg;
433 UINT8 StatusReg;
434
435 //
436 // Select slave device
437 //
438 IDEWritePortB (
439 IdeDev->PciIo,
440 IdeDev->IoPort->Head,
441 (UINT8) ((1 << 4) | 0xe0)
442 );
443 gBS->Stall (100);
444
445 //
446 // Save the init slave status register
447 //
448 InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
449
450 //
451 // Select Master back
452 //
453 IDEWritePortB (
454 IdeDev->PciIo,
455 IdeDev->IoPort->Head,
456 (UINT8) ((0 << 4) | 0xe0)
457 );
458 gBS->Stall (100);
459
460 //
461 // Send ATA Device Execut Diagnostic command.
462 // This command should work no matter DRDY is ready or not
463 //
464 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
465
466 Status = WaitForBSYClear (IdeDev, 3500);
467 if (EFI_ERROR (Status)) {
468 DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));
469 return Status;
470 }
471 //
472 // Read device signature
473 //
474 //
475 // Select Master
476 //
477 IDEWritePortB (
478 IdeDev->PciIo,
479 IdeDev->IoPort->Head,
480 (UINT8) ((0 << 4) | 0xe0)
481 );
482 gBS->Stall (100);
483 SectorCountReg = IDEReadPortB (
484 IdeDev->PciIo,
485 IdeDev->IoPort->SectorCount
486 );
487 LBALowReg = IDEReadPortB (
488 IdeDev->PciIo,
489 IdeDev->IoPort->SectorNumber
490 );
491 LBAMidReg = IDEReadPortB (
492 IdeDev->PciIo,
493 IdeDev->IoPort->CylinderLsb
494 );
495 LBAHighReg = IDEReadPortB (
496 IdeDev->PciIo,
497 IdeDev->IoPort->CylinderMsb
498 );
499 if ((SectorCountReg == 0x1) &&
500 (LBALowReg == 0x1) &&
501 (LBAMidReg == 0x0) &&
502 (LBAHighReg == 0x0)) {
503 MasterDeviceExist = TRUE;
504 MasterDeviceType = ATA_DEVICE_TYPE;
505 } else {
506 if ((LBAMidReg == 0x14) &&
507 (LBAHighReg == 0xeb)) {
508 MasterDeviceExist = TRUE;
509 MasterDeviceType = ATAPI_DEVICE_TYPE;
510 }
511 }
512
513 //
514 // For some Hard Drive, it takes some time to get
515 // the right signature when operating in single slave mode.
516 // We stall 20ms to work around this.
517 //
518 if (!MasterDeviceExist) {
519 gBS->Stall (20000);
520 }
521
522 //
523 // Select Slave
524 //
525 IDEWritePortB (
526 IdeDev->PciIo,
527 IdeDev->IoPort->Head,
528 (UINT8) ((1 << 4) | 0xe0)
529 );
530 gBS->Stall (100);
531 SectorCountReg = IDEReadPortB (
532 IdeDev->PciIo,
533 IdeDev->IoPort->SectorCount
534 );
535 LBALowReg = IDEReadPortB (
536 IdeDev->PciIo,
537 IdeDev->IoPort->SectorNumber
538 );
539 LBAMidReg = IDEReadPortB (
540 IdeDev->PciIo,
541 IdeDev->IoPort->CylinderLsb
542 );
543 LBAHighReg = IDEReadPortB (
544 IdeDev->PciIo,
545 IdeDev->IoPort->CylinderMsb
546 );
547 StatusReg = IDEReadPortB (
548 IdeDev->PciIo,
549 IdeDev->IoPort->Reg.Status
550 );
551 if ((SectorCountReg == 0x1) &&
552 (LBALowReg == 0x1) &&
553 (LBAMidReg == 0x0) &&
554 (LBAHighReg == 0x0)) {
555 SlaveDeviceExist = TRUE;
556 SlaveDeviceType = ATA_DEVICE_TYPE;
557 } else {
558 if ((LBAMidReg == 0x14) &&
559 (LBAHighReg == 0xeb)) {
560 SlaveDeviceExist = TRUE;
561 SlaveDeviceType = ATAPI_DEVICE_TYPE;
562 }
563 }
564
565 //
566 // When single master is plugged, slave device
567 // will be wrongly detected. Here's the workaround
568 // for ATA devices by detecting DRY bit in status
569 // register.
570 // NOTE: This workaround doesn't apply to ATAPI.
571 //
572 if (MasterDeviceExist && SlaveDeviceExist &&
573 (StatusReg & ATA_STSREG_DRDY) == 0 &&
574 (InitStatusReg & ATA_STSREG_DRDY) == 0 &&
575 MasterDeviceType == SlaveDeviceType &&
576 SlaveDeviceType != ATAPI_DEVICE_TYPE) {
577 SlaveDeviceExist = FALSE;
578 }
579
580 //
581 // Indicate this channel has been detected
582 //
583 ChannelDeviceDetected = TRUE;
584 return EFI_SUCCESS;
585 }
586 /**
587 Detect if there is disk attached to this port
588
589 @param IdeDev The BLK_IO private data which specifies the IDE device.
590
591 @retval EFI_NOT_FOUND The device or channel is not found
592 @retval EFI_SUCCESS The device is found
593
594 **/
595 EFI_STATUS
596 DiscoverIdeDevice (
597 IN IDE_BLK_IO_DEV *IdeDev
598 )
599 {
600 EFI_STATUS Status;
601 EFI_STATUS LongPhyStatus;
602
603 //
604 // If a channel has not been checked, check it now. Then set it to "checked" state
605 // After this step, all devices in this channel have been checked.
606 //
607 if (!ChannelDeviceDetected) {
608 Status = DetectIDEController (IdeDev);
609 if (EFI_ERROR (Status)) {
610 return EFI_NOT_FOUND;
611 }
612 }
613
614 Status = EFI_NOT_FOUND;
615
616 //
617 // Device exists. test if it is an ATA device.
618 // Prefer the result from DetectIDEController,
619 // if failed, try another device type to handle
620 // devices that not follow the spec.
621 //
622 if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {
623 if (MasterDeviceType == ATA_DEVICE_TYPE) {
624 Status = ATAIdentify (IdeDev);
625 if (EFI_ERROR (Status)) {
626 Status = ATAPIIdentify (IdeDev);
627 if (!EFI_ERROR (Status)) {
628 MasterDeviceType = ATAPI_DEVICE_TYPE;
629 }
630 }
631 } else {
632 Status = ATAPIIdentify (IdeDev);
633 if (EFI_ERROR (Status)) {
634 Status = ATAIdentify (IdeDev);
635 if (!EFI_ERROR (Status)) {
636 MasterDeviceType = ATA_DEVICE_TYPE;
637 }
638 }
639 }
640 }
641 if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {
642 if (SlaveDeviceType == ATA_DEVICE_TYPE) {
643 Status = ATAIdentify (IdeDev);
644 if (EFI_ERROR (Status)) {
645 Status = ATAPIIdentify (IdeDev);
646 if (!EFI_ERROR (Status)) {
647 SlaveDeviceType = ATAPI_DEVICE_TYPE;
648 }
649 }
650 } else {
651 Status = ATAPIIdentify (IdeDev);
652 if (EFI_ERROR (Status)) {
653 Status = ATAIdentify (IdeDev);
654 if (!EFI_ERROR (Status)) {
655 SlaveDeviceType = ATA_DEVICE_TYPE;
656 }
657 }
658 }
659 }
660 if (EFI_ERROR (Status)) {
661 return EFI_NOT_FOUND;
662 }
663 //
664 // Init Block I/O interface
665 //
666 LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev);
667 if (!EFI_ERROR (LongPhyStatus)) {
668 IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
669 } else {
670 IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
671 }
672 IdeDev->BlkIo.Reset = IDEBlkIoReset;
673 IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks;
674 IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks;
675 IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks;
676
677 IdeDev->BlkMedia.LogicalPartition = FALSE;
678 IdeDev->BlkMedia.WriteCaching = FALSE;
679
680 //
681 // Init Disk Info interface
682 //
683 gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
684 IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry;
685 IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify;
686 IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData;
687 IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde;
688
689 return EFI_SUCCESS;
690 }
691
692 /**
693 This interface is used to initialize all state data related to the detection of one
694 channel.
695 **/
696 VOID
697 InitializeIDEChannelData (
698 VOID
699 )
700 {
701 ChannelDeviceDetected = FALSE;
702 MasterDeviceExist = FALSE;
703 MasterDeviceType = 0xff;
704 SlaveDeviceExist = FALSE;
705 SlaveDeviceType = 0xff;
706 }
707 /**
708 This function is used to poll for the DRQ bit clear in the Status
709 Register. DRQ is cleared when the device is finished transferring data.
710 So this function is called after data transfer is finished.
711
712 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
713 to record all the information of the IDE device.
714 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear.
715
716 @retval EFI_SUCCESS DRQ bit clear within the time out.
717
718 @retval EFI_TIMEOUT DRQ bit not clear within the time out.
719
720 @note
721 Read Status Register will clear interrupt status.
722
723 **/
724 EFI_STATUS
725 DRQClear (
726 IN IDE_BLK_IO_DEV *IdeDev,
727 IN UINTN TimeoutInMilliSeconds
728 )
729 {
730 UINT32 Delay;
731 UINT8 StatusRegister;
732 UINT8 ErrorRegister;
733
734 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
735 do {
736
737 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
738
739 //
740 // wait for BSY == 0 and DRQ == 0
741 //
742 if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
743 break;
744 }
745
746 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
747
748 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
749 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
750 return EFI_ABORTED;
751 }
752 }
753
754 //
755 // Stall for 30 us
756 //
757 gBS->Stall (30);
758
759 Delay--;
760
761 } while (Delay > 0);
762
763 if (Delay == 0) {
764 return EFI_TIMEOUT;
765 }
766
767 return EFI_SUCCESS;
768 }
769 /**
770 This function is used to poll for the DRQ bit clear in the Alternate
771 Status Register. DRQ is cleared when the device is finished
772 transferring data. So this function is called after data transfer
773 is finished.
774
775 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
776 to record all the information of the IDE device.
777
778 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear.
779
780 @retval EFI_SUCCESS DRQ bit clear within the time out.
781
782 @retval EFI_TIMEOUT DRQ bit not clear within the time out.
783 @note Read Alternate Status Register will not clear interrupt status.
784
785 **/
786 EFI_STATUS
787 DRQClear2 (
788 IN IDE_BLK_IO_DEV *IdeDev,
789 IN UINTN TimeoutInMilliSeconds
790 )
791 {
792 UINT32 Delay;
793 UINT8 AltRegister;
794 UINT8 ErrorRegister;
795
796 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
797 do {
798
799 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
800
801 //
802 // wait for BSY == 0 and DRQ == 0
803 //
804 if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
805 break;
806 }
807
808 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
809
810 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
811 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
812 return EFI_ABORTED;
813 }
814 }
815
816 //
817 // Stall for 30 us
818 //
819 gBS->Stall (30);
820
821 Delay--;
822
823 } while (Delay > 0);
824
825 if (Delay == 0) {
826 return EFI_TIMEOUT;
827 }
828
829 return EFI_SUCCESS;
830 }
831
832 /**
833 This function is used to poll for the DRQ bit set in the
834 Status Register.
835 DRQ is set when the device is ready to transfer data. So this function
836 is called after the command is sent to the device and before required
837 data is transferred.
838
839 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to
840 record all the information of the IDE device.
841 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
842
843 @retval EFI_SUCCESS DRQ bit set within the time out.
844 @retval EFI_TIMEOUT DRQ bit not set within the time out.
845 @retval EFI_ABORTED DRQ bit not set caused by the command abort.
846
847 @note Read Status Register will clear interrupt status.
848
849 **/
850 EFI_STATUS
851 DRQReady (
852 IN IDE_BLK_IO_DEV *IdeDev,
853 IN UINTN TimeoutInMilliSeconds
854 )
855 {
856 UINT32 Delay;
857 UINT8 StatusRegister;
858 UINT8 ErrorRegister;
859
860 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
861 do {
862 //
863 // read Status Register will clear interrupt
864 //
865 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
866
867 //
868 // BSY==0,DRQ==1
869 //
870 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
871 break;
872 }
873
874 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
875
876 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
877 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
878 return EFI_ABORTED;
879 }
880 }
881
882 //
883 // Stall for 30 us
884 //
885 gBS->Stall (30);
886
887 Delay--;
888 } while (Delay > 0);
889
890 if (Delay == 0) {
891 return EFI_TIMEOUT;
892 }
893
894 return EFI_SUCCESS;
895 }
896 /**
897 This function is used to poll for the DRQ bit set in the Alternate Status Register.
898 DRQ is set when the device is ready to transfer data. So this function is called after
899 the command is sent to the device and before required data is transferred.
900
901 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to
902 record all the information of the IDE device.
903
904 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
905
906 @retval EFI_SUCCESS DRQ bit set within the time out.
907 @retval EFI_TIMEOUT DRQ bit not set within the time out.
908 @retval EFI_ABORTED DRQ bit not set caused by the command abort.
909 @note Read Alternate Status Register will not clear interrupt status.
910
911 **/
912 EFI_STATUS
913 DRQReady2 (
914 IN IDE_BLK_IO_DEV *IdeDev,
915 IN UINTN TimeoutInMilliSeconds
916 )
917 {
918 UINT32 Delay;
919 UINT8 AltRegister;
920 UINT8 ErrorRegister;
921
922 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
923
924 do {
925 //
926 // Read Alternate Status Register will not clear interrupt status
927 //
928 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
929 //
930 // BSY == 0 , DRQ == 1
931 //
932 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
933 break;
934 }
935
936 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
937
938 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
939 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
940 return EFI_ABORTED;
941 }
942 }
943
944 //
945 // Stall for 30 us
946 //
947 gBS->Stall (30);
948
949 Delay--;
950 } while (Delay > 0);
951
952 if (Delay == 0) {
953 return EFI_TIMEOUT;
954 }
955
956 return EFI_SUCCESS;
957 }
958
959 /**
960 This function is used to poll for the BSY bit clear in the Status Register. BSY
961 is clear when the device is not busy. Every command must be sent after device is not busy.
962
963 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
964 to record all the information of the IDE device.
965 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
966
967 @retval EFI_SUCCESS BSY bit clear within the time out.
968 @retval EFI_TIMEOUT BSY bit not clear within the time out.
969
970 @note Read Status Register will clear interrupt status.
971 **/
972 EFI_STATUS
973 WaitForBSYClear (
974 IN IDE_BLK_IO_DEV *IdeDev,
975 IN UINTN TimeoutInMilliSeconds
976 )
977 {
978 UINT32 Delay;
979 UINT8 StatusRegister;
980
981 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
982 do {
983
984 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
985 if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {
986 break;
987 }
988
989 //
990 // Stall for 30 us
991 //
992 gBS->Stall (30);
993
994 Delay--;
995
996 } while (Delay > 0);
997
998 if (Delay == 0) {
999 return EFI_TIMEOUT;
1000 }
1001
1002 return EFI_SUCCESS;
1003 }
1004 /**
1005 This function is used to poll for the BSY bit clear in the Alternate Status Register.
1006 BSY is clear when the device is not busy. Every command must be sent after device is
1007 not busy.
1008
1009 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record
1010 all the information of the IDE device.
1011 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
1012
1013 @retval EFI_SUCCESS BSY bit clear within the time out.
1014 @retval EFI_TIMEOUT BSY bit not clear within the time out.
1015 @note Read Alternate Status Register will not clear interrupt status.
1016
1017 **/
1018 EFI_STATUS
1019 WaitForBSYClear2 (
1020 IN IDE_BLK_IO_DEV *IdeDev,
1021 IN UINTN TimeoutInMilliSeconds
1022 )
1023 {
1024 UINT32 Delay;
1025 UINT8 AltRegister;
1026
1027 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1028 do {
1029 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
1030 if ((AltRegister & ATA_STSREG_BSY) == 0x00) {
1031 break;
1032 }
1033
1034 gBS->Stall (30);
1035
1036 Delay--;
1037
1038 } while (Delay > 0);
1039
1040 if (Delay == 0) {
1041 return EFI_TIMEOUT;
1042 }
1043
1044 return EFI_SUCCESS;
1045 }
1046 /**
1047 This function is used to poll for the DRDY bit set in the Status Register. DRDY
1048 bit is set when the device is ready to accept command. Most ATA commands must be
1049 sent after DRDY set except the ATAPI Packet Command.
1050
1051 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1052 to record all the information of the IDE device.
1053 @param DelayInMilliSeconds used to designate the timeout for the DRQ ready.
1054
1055 @retval EFI_SUCCESS DRDY bit set within the time out.
1056 @retval EFI_TIMEOUT DRDY bit not set within the time out.
1057
1058 @note Read Status Register will clear interrupt status.
1059 **/
1060 EFI_STATUS
1061 DRDYReady (
1062 IN IDE_BLK_IO_DEV *IdeDev,
1063 IN UINTN DelayInMilliSeconds
1064 )
1065 {
1066 UINT32 Delay;
1067 UINT8 StatusRegister;
1068 UINT8 ErrorRegister;
1069
1070 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1071 do {
1072 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
1073 //
1074 // BSY == 0 , DRDY == 1
1075 //
1076 if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
1077 break;
1078 }
1079
1080 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
1081
1082 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
1083 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
1084 return EFI_ABORTED;
1085 }
1086 }
1087
1088 gBS->Stall (30);
1089
1090 Delay--;
1091 } while (Delay > 0);
1092
1093 if (Delay == 0) {
1094 return EFI_TIMEOUT;
1095 }
1096
1097 return EFI_SUCCESS;
1098 }
1099 /**
1100 This function is used to poll for the DRDY bit set in the Alternate Status Register.
1101 DRDY bit is set when the device is ready to accept command. Most ATA commands must
1102 be sent after DRDY set except the ATAPI Packet Command.
1103
1104 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1105 to record all the information of the IDE device.
1106 @param DelayInMilliSeconds used to designate the timeout for the DRQ ready.
1107
1108 @retval EFI_SUCCESS DRDY bit set within the time out.
1109 @retval EFI_TIMEOUT DRDY bit not set within the time out.
1110
1111 @note Read Alternate Status Register will clear interrupt status.
1112
1113 **/
1114 EFI_STATUS
1115 DRDYReady2 (
1116 IN IDE_BLK_IO_DEV *IdeDev,
1117 IN UINTN DelayInMilliSeconds
1118 )
1119 {
1120 UINT32 Delay;
1121 UINT8 AltRegister;
1122 UINT8 ErrorRegister;
1123
1124 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
1125 do {
1126 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
1127 //
1128 // BSY == 0 , DRDY == 1
1129 //
1130 if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
1131 break;
1132 }
1133
1134 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
1135
1136 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
1137 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
1138 return EFI_ABORTED;
1139 }
1140 }
1141
1142 gBS->Stall (30);
1143
1144 Delay--;
1145 } while (Delay > 0);
1146
1147 if (Delay == 0) {
1148 return EFI_TIMEOUT;
1149 }
1150
1151 return EFI_SUCCESS;
1152 }
1153 /**
1154 Release resources of an IDE device before stopping it.
1155
1156 @param IdeBlkIoDevice Standard IDE device private data structure
1157
1158 **/
1159 VOID
1160 ReleaseIdeResources (
1161 IN IDE_BLK_IO_DEV *IdeBlkIoDevice
1162 )
1163 {
1164 if (IdeBlkIoDevice == NULL) {
1165 return ;
1166 }
1167
1168 //
1169 // Release all the resourses occupied by the IDE_BLK_IO_DEV
1170 //
1171
1172 if (IdeBlkIoDevice->SenseData != NULL) {
1173 gBS->FreePool (IdeBlkIoDevice->SenseData);
1174 IdeBlkIoDevice->SenseData = NULL;
1175 }
1176
1177 if (IdeBlkIoDevice->Cache != NULL) {
1178 gBS->FreePool (IdeBlkIoDevice->Cache);
1179 IdeBlkIoDevice->Cache = NULL;
1180 }
1181
1182 if (IdeBlkIoDevice->IdData != NULL) {
1183 gBS->FreePool (IdeBlkIoDevice->IdData);
1184 IdeBlkIoDevice->IdData = NULL;
1185 }
1186
1187 if (IdeBlkIoDevice->InquiryData != NULL) {
1188 gBS->FreePool (IdeBlkIoDevice->InquiryData);
1189 IdeBlkIoDevice->InquiryData = NULL;
1190 }
1191
1192 if (IdeBlkIoDevice->ControllerNameTable != NULL) {
1193 FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
1194 IdeBlkIoDevice->ControllerNameTable = NULL;
1195 }
1196
1197 if (IdeBlkIoDevice->IoPort != NULL) {
1198 gBS->FreePool (IdeBlkIoDevice->IoPort);
1199 }
1200
1201 if (IdeBlkIoDevice->DevicePath != NULL) {
1202 gBS->FreePool (IdeBlkIoDevice->DevicePath);
1203 }
1204
1205 if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {
1206 gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);
1207 IdeBlkIoDevice->ExitBootServiceEvent = NULL;
1208 }
1209
1210 gBS->FreePool (IdeBlkIoDevice);
1211 IdeBlkIoDevice = NULL;
1212
1213 return ;
1214 }
1215 /**
1216 Set the calculated Best transfer mode to a detected device.
1217
1218 @param IdeDev Standard IDE device private data structure
1219 @param TransferMode The device transfer mode to be set
1220 @return Set transfer mode Command execute status.
1221
1222 **/
1223 EFI_STATUS
1224 SetDeviceTransferMode (
1225 IN IDE_BLK_IO_DEV *IdeDev,
1226 IN ATA_TRANSFER_MODE *TransferMode
1227 )
1228 {
1229 EFI_STATUS Status;
1230 UINT8 DeviceSelect;
1231 UINT8 SectorCount;
1232
1233 DeviceSelect = 0;
1234 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
1235 SectorCount = *((UINT8 *) TransferMode);
1236
1237 //
1238 // Send SET FEATURE command (sub command 0x03) to set pio mode.
1239 //
1240 Status = AtaNonDataCommandIn (
1241 IdeDev,
1242 ATA_CMD_SET_FEATURES,
1243 DeviceSelect,
1244 0x03,
1245 SectorCount,
1246 0,
1247 0,
1248 0
1249 );
1250
1251 return Status;
1252 }
1253 /**
1254 Set drive parameters for devices not support PACKETS command.
1255
1256 @param IdeDev Standard IDE device private data structure
1257 @param DriveParameters The device parameters to be set into the disk
1258 @return SetParameters Command execute status.
1259
1260 **/
1261 EFI_STATUS
1262 SetDriveParameters (
1263 IN IDE_BLK_IO_DEV *IdeDev,
1264 IN ATA_DRIVE_PARMS *DriveParameters
1265 )
1266 {
1267 EFI_STATUS Status;
1268 UINT8 DeviceSelect;
1269
1270 DeviceSelect = 0;
1271 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
1272
1273 //
1274 // Send Init drive parameters
1275 //
1276 Status = AtaNonDataCommandIn (
1277 IdeDev,
1278 ATA_CMD_INIT_DRIVE_PARAM,
1279 (UINT8) (DeviceSelect + DriveParameters->Heads),
1280 0,
1281 DriveParameters->Sector,
1282 0,
1283 0,
1284 0
1285 );
1286
1287 //
1288 // Send Set Multiple parameters
1289 //
1290 Status = AtaNonDataCommandIn (
1291 IdeDev,
1292 ATA_CMD_SET_MULTIPLE_MODE,
1293 DeviceSelect,
1294 0,
1295 DriveParameters->MultipleSector,
1296 0,
1297 0,
1298 0
1299 );
1300 return Status;
1301 }
1302
1303 /**
1304 Enable Interrupt on IDE controller.
1305
1306 @param IdeDev Standard IDE device private data structure
1307
1308 @retval EFI_SUCCESS Enable Interrupt successfully
1309 **/
1310 EFI_STATUS
1311 EnableInterrupt (
1312 IN IDE_BLK_IO_DEV *IdeDev
1313 )
1314 {
1315 UINT8 DeviceControl;
1316
1317 //
1318 // Enable interrupt for DMA operation
1319 //
1320 DeviceControl = 0;
1321 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
1322
1323 return EFI_SUCCESS;
1324 }