VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxIdeBusDxe/IdeBus.c@ 48947

Last change on this file since 48947 was 48947, checked in by vboxsync, 12 years ago

Devices: Whitespace and svn:keyword cleanups by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.3 KB
Line 
1/* $Id: IdeBus.c 48947 2013-10-07 21:41:00Z vboxsync $ */
2/** @file
3 * IdeBus.c
4 */
5
6/*
7 * Copyright (C) 2009-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/** @file
28 This file implement UEFI driver for IDE Bus which includes device identification,
29 Child device(Disk, CDROM, etc) enumeration and child handler installation, and
30 driver stop.
31
32 Copyright (c) 2006 - 2009, Intel Corporation
33 All rights reserved. This program and the accompanying materials
34 are licensed and made available under the terms and conditions of the BSD License
35 which accompanies this distribution. The full text of the license may be found at
36 http://opensource.org/licenses/bsd-license.php
37
38 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
39 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
40
41 @par Revision Reference:
42 This module is modified from DXE\IDE module for Ide Controller Init support
43
44**/
45
46#include "IdeBus.h"
47
48#define PCI_CLASS_MASS_STORAGE 0x01
49#define PCI_SUB_CLASS_IDE 0x01
50
51
52//
53// IDE Bus Driver Binding Protocol Instance
54//
55EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
56 IDEBusDriverBindingSupported,
57 IDEBusDriverBindingStart,
58 IDEBusDriverBindingStop,
59 0xa,
60 NULL,
61 NULL
62};
63/**
64 Deregister an IDE device and free resources
65
66 @param This Protocol instance pointer.
67 @param Controller Ide device handle
68 @param Handle Handle of device to deregister driver on
69
70 @retval EFI_SUCCESS Deregister a specific IDE device successfully
71
72
73**/
74EFI_STATUS
75DeRegisterIdeDevice (
76 IN EFI_DRIVER_BINDING_PROTOCOL *This,
77 IN EFI_HANDLE Controller,
78 IN EFI_HANDLE Handle
79 )
80{
81 EFI_STATUS Status;
82 EFI_BLOCK_IO_PROTOCOL *BlkIo;
83 IDE_BLK_IO_DEV *IdeBlkIoDevice;
84 EFI_PCI_IO_PROTOCOL *PciIo;
85 UINTN Index;
86
87 Status = gBS->OpenProtocol (
88 Handle,
89 &gEfiBlockIoProtocolGuid,
90 (VOID **) &BlkIo,
91 This->DriverBindingHandle,
92 Controller,
93 EFI_OPEN_PROTOCOL_GET_PROTOCOL
94 );
95 if (EFI_ERROR (Status)) {
96 return Status;
97 }
98
99 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
100
101 //
102 // Report Status code: Device disabled
103 //
104 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
105 EFI_PROGRESS_CODE,
106 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
107 IdeBlkIoDevice->DevicePath
108 );
109
110 //
111 // Close the child handle
112 //
113 Status = gBS->CloseProtocol (
114 Controller,
115 &gEfiPciIoProtocolGuid,
116 This->DriverBindingHandle,
117 Handle
118 );
119
120 Status = gBS->UninstallMultipleProtocolInterfaces (
121 Handle,
122 &gEfiDevicePathProtocolGuid,
123 IdeBlkIoDevice->DevicePath,
124 &gEfiBlockIoProtocolGuid,
125 &IdeBlkIoDevice->BlkIo,
126 &gEfiDiskInfoProtocolGuid,
127 &IdeBlkIoDevice->DiskInfo,
128 NULL
129 );
130
131 if (EFI_ERROR (Status)) {
132 gBS->OpenProtocol (
133 Controller,
134 &gEfiPciIoProtocolGuid,
135 (VOID **) &PciIo,
136 This->DriverBindingHandle,
137 Handle,
138 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
139 );
140 return Status;
141 }
142
143 //
144 // Release allocated resources
145 //
146 Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
147 if (Index < MAX_IDE_DEVICE) {
148 IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
149 }
150 ReleaseIdeResources (IdeBlkIoDevice);
151
152 return EFI_SUCCESS;
153}
154/**
155 Supported function of Driver Binding protocol for this driver.
156
157 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
158 @param ControllerHandle The handle of the controller to test.
159 @param RemainingDevicePath A pointer to the remaining portion of a device path.
160
161 @retval EFI_SUCCESS Driver loaded.
162 @retval other Driver not loaded.
163
164**/
165EFI_STATUS
166EFIAPI
167IDEBusDriverBindingSupported (
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,
169 IN EFI_HANDLE Controller,
170 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
171 )
172{
173 EFI_STATUS Status;
174 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
175 EFI_DEV_PATH *Node;
176 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
177
178 if (RemainingDevicePath != NULL) {
179 Node = (EFI_DEV_PATH *) RemainingDevicePath;
180 //
181 // Check if RemainingDevicePath is the End of Device Path Node,
182 // if yes, go on checking other conditions
183 //
184 if (!IsDevicePathEnd (Node)) {
185 //
186 // If RemainingDevicePath isn't the End of Device Path Node,
187 // check its validation
188 //
189 if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
190 Node->DevPath.SubType != MSG_ATAPI_DP ||
191 DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
192 return EFI_UNSUPPORTED;
193 }
194 }
195 }
196
197 //
198 // Verify the Ide Controller Init Protocol, which installed by the
199 // IdeController module.
200 // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
201 // open BY_DRIVER here) That's why we don't check pciio protocol
202 // Note 2: ide_init driver check ide controller's pci config space, so we dont
203 // check here any more to save code size
204 //
205 Status = gBS->OpenProtocol (
206 Controller,
207 &gEfiIdeControllerInitProtocolGuid,
208 (VOID **) &IdeInit,
209 This->DriverBindingHandle,
210 Controller,
211 EFI_OPEN_PROTOCOL_BY_DRIVER
212 );
213
214 if (Status == EFI_ALREADY_STARTED) {
215 return EFI_SUCCESS;
216 }
217
218 if (EFI_ERROR (Status)) {
219 return Status;
220 }
221
222 //
223 // Close the I/O Abstraction(s) used to perform the supported test
224 //
225 gBS->CloseProtocol (
226 Controller,
227 &gEfiIdeControllerInitProtocolGuid,
228 This->DriverBindingHandle,
229 Controller
230 );
231
232 //
233 // Open the EFI Device Path protocol needed to perform the supported test
234 //
235 Status = gBS->OpenProtocol (
236 Controller,
237 &gEfiDevicePathProtocolGuid,
238 (VOID **) &ParentDevicePath,
239 This->DriverBindingHandle,
240 Controller,
241 EFI_OPEN_PROTOCOL_BY_DRIVER
242 );
243 if (Status == EFI_ALREADY_STARTED) {
244 return EFI_SUCCESS;
245 }
246
247 //
248 // Close protocol, don't use device path protocol in the Support() function
249 //
250 gBS->CloseProtocol (
251 Controller,
252 &gEfiDevicePathProtocolGuid,
253 This->DriverBindingHandle,
254 Controller
255 );
256
257 return Status;
258}
259
260
261/**
262 Start function of Driver binding protocol which start this driver on Controller
263 by detecting all disks and installing BlockIo protocol on them.
264
265 @param This Protocol instance pointer.
266 @param Controller Handle of device to bind driver to.
267 @param RemainingDevicePath produce all possible children.
268
269 @retval EFI_SUCCESS This driver is added to ControllerHandle.
270 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
271 @retval other This driver does not support this device.
272
273**/
274EFI_STATUS
275EFIAPI
276IDEBusDriverBindingStart (
277 IN EFI_DRIVER_BINDING_PROTOCOL *This,
278 IN EFI_HANDLE Controller,
279 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
280 )
281{
282 EFI_STATUS Status;
283 EFI_STATUS SavedStatus;
284 EFI_PCI_IO_PROTOCOL *PciIo;
285 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
286 EFI_DEV_PATH *Node;
287 UINT8 IdeChannel;
288 UINT8 BeginningIdeChannel;
289 UINT8 EndIdeChannel;
290 UINT8 IdeDevice;
291 UINT8 BeginningIdeDevice;
292 UINT8 EndIdeDevice;
293 IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
294 IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;
295 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
296 ATA_TRANSFER_MODE TransferMode;
297 ATA_DRIVE_PARMS DriveParameters;
298 EFI_DEV_PATH NewNode;
299 UINT8 ConfigurationOptions;
300 UINT16 CommandBlockBaseAddr;
301 UINT16 ControlBlockBaseAddr;
302 UINTN DataSize;
303 IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
304 UINT64 Supports;
305
306 //
307 // Local variables declaration for IdeControllerInit support
308 //
309 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
310 BOOLEAN EnumAll;
311 BOOLEAN ChannelEnabled;
312 UINT8 MaxDevices;
313 EFI_IDENTIFY_DATA IdentifyData;
314 EFI_ATA_COLLECTIVE_MODE *SupportedModes;
315
316 IdeBusDriverPrivateData = NULL;
317 SupportedModes = NULL;
318
319 //
320 // Perform IdeBus initialization
321 //
322 Status = gBS->OpenProtocol (
323 Controller,
324 &gEfiDevicePathProtocolGuid,
325 (VOID **) &ParentDevicePath,
326 This->DriverBindingHandle,
327 Controller,
328 EFI_OPEN_PROTOCOL_BY_DRIVER
329 );
330 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
331 return Status;
332 }
333
334 //
335 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
336 //
337 Status = gBS->OpenProtocol (
338 Controller,
339 &gEfiIdeControllerInitProtocolGuid,
340 (VOID **) &IdeInit,
341 This->DriverBindingHandle,
342 Controller,
343 EFI_OPEN_PROTOCOL_BY_DRIVER
344 );
345
346 //
347 // The following OpenProtocol function with _GET_PROTOCOL attribute and
348 // will not return EFI_ALREADY_STARTED, so save it for now
349 //
350 SavedStatus = Status;
351
352 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
353 DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
354 //
355 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
356 //
357 goto ErrorExit;
358 }
359
360 //
361 // Save Enumall. Step7.2
362 //
363 EnumAll = IdeInit->EnumAll;
364
365 //
366 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
367 // attribute will not return EFI_ALREADY_STARTED
368 //
369 Status = gBS->OpenProtocol (
370 Controller,
371 &gEfiPciIoProtocolGuid,
372 (VOID **) &PciIo,
373 This->DriverBindingHandle,
374 Controller,
375 EFI_OPEN_PROTOCOL_GET_PROTOCOL
376 );
377 if (EFI_ERROR (Status)) {
378 DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
379 goto ErrorExit;
380 }
381
382 //
383 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
384 //
385 if (SavedStatus != EFI_ALREADY_STARTED) {
386 IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
387 if (IdeBusDriverPrivateData == NULL) {
388 Status = EFI_OUT_OF_RESOURCES;
389 goto ErrorExit;
390 }
391
392 ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
393 Status = gBS->InstallMultipleProtocolInterfaces (
394 &Controller,
395 &gEfiCallerIdGuid,
396 IdeBusDriverPrivateData,
397 NULL
398 );
399 if (EFI_ERROR (Status)) {
400 goto ErrorExit;
401 }
402
403 } else {
404 Status = gBS->OpenProtocol (
405 Controller,
406 &gEfiCallerIdGuid,
407 (VOID **) &IdeBusDriverPrivateData,
408 This->DriverBindingHandle,
409 Controller,
410 EFI_OPEN_PROTOCOL_GET_PROTOCOL
411 );
412 if (EFI_ERROR (Status)) {
413 IdeBusDriverPrivateData = NULL;
414 goto ErrorExit;
415 }
416 }
417
418 Status = PciIo->Attributes (
419 PciIo,
420 EfiPciIoAttributeOperationSupported,
421 0,
422 &Supports
423 );
424 if (!EFI_ERROR (Status)) {
425 Supports &= EFI_PCI_DEVICE_ENABLE;
426 Status = PciIo->Attributes (
427 PciIo,
428 EfiPciIoAttributeOperationEnable,
429 Supports,
430 NULL
431 );
432 }
433
434 if (EFI_ERROR (Status)) {
435 goto ErrorExit;
436 }
437
438 //
439 // Read the environment variable that contains the IDEBus Driver's
440 // Config options that were set by the Driver Configuration Protocol
441 //
442 DataSize = sizeof (ConfigurationOptions);
443 Status = gRT->GetVariable (
444 (CHAR16 *) L"Configuration",
445 &gEfiCallerIdGuid,
446 NULL,
447 &DataSize,
448 &ConfigurationOptions
449 );
450 if (EFI_ERROR (Status)) {
451 ConfigurationOptions = 0x0f;
452 }
453
454 if (EnumAll || RemainingDevicePath == NULL) {
455 //
456 // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,
457 // must enumerate all IDE devices anyway
458 //
459 BeginningIdeChannel = IdePrimary;
460 EndIdeChannel = IdeSecondary;
461 BeginningIdeDevice = IdeMaster;
462 EndIdeDevice = IdeSlave;
463
464 } else if (!IsDevicePathEnd (RemainingDevicePath)) {
465 //
466 // If RemainingDevicePath isn't the End of Device Path Node,
467 // only scan the specified device by RemainingDevicePath
468 //
469 Node = (EFI_DEV_PATH *) RemainingDevicePath;
470 BeginningIdeChannel = Node->Atapi.PrimarySecondary;
471 EndIdeChannel = BeginningIdeChannel;
472 BeginningIdeDevice = Node->Atapi.SlaveMaster;
473 EndIdeDevice = BeginningIdeDevice;
474 if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {
475 Status = EFI_INVALID_PARAMETER;
476 goto ErrorExit;
477 }
478 if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {
479 Status = EFI_INVALID_PARAMETER;
480 goto ErrorExit;
481 }
482
483 } else {
484 //
485 // If RemainingDevicePath is the End of Device Path Node,
486 // skip enumerate any device and return EFI_SUCCESS
487 //
488 BeginningIdeChannel = IdeMaxChannel;
489 EndIdeChannel = IdeMaxChannel - 1;
490 BeginningIdeDevice = IdeMaxDevice;
491 EndIdeDevice = IdeMaxDevice - 1;
492 }
493
494 //
495 // Obtain IDE IO port registers' base addresses
496 //
497 Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
498 if (EFI_ERROR (Status)) {
499 goto ErrorExit;
500 }
501
502 //
503 // Report status code: begin IdeBus initialization
504 //
505 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
506 EFI_PROGRESS_CODE,
507 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
508 ParentDevicePath
509 );
510
511 //
512 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
513 //
514 for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
515
516 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
517
518 //
519 // now obtain channel information fron IdeControllerInit protocol. Step9
520 //
521 Status = IdeInit->GetChannelInfo (
522 IdeInit,
523 IdeChannel,
524 &ChannelEnabled,
525 &MaxDevices
526 );
527 if (EFI_ERROR (Status)) {
528 DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
529 continue;
530 }
531
532 if (!ChannelEnabled) {
533 continue;
534 }
535
536 EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);
537 ASSERT (EndIdeDevice < IdeMaxDevice);
538 //
539 // Now inform the IDE Controller Init Module. Sept10
540 //
541 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
542
543 //
544 // No reset channel function implemented. Sept11
545 //
546 IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
547
548 //
549 // Step13
550 //
551 IdeInit->NotifyPhase (
552 IdeInit,
553 EfiIdeBusBeforeDevicePresenceDetection,
554 IdeChannel
555 );
556
557 //
558 // Prepare to detect IDE device of this channel
559 //
560 InitializeIDEChannelData ();
561
562 //
563 // -- 1st inner loop --- Master/Slave ------------ Step14
564 //
565 for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
566 //
567 // Check whether the configuration options allow this device
568 //
569 if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {
570 continue;
571 }
572
573 //
574 // The device has been scanned in another Start(), No need to scan it again
575 // for perf optimization.
576 //
577 if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
578 continue;
579 }
580
581 //
582 // create child handle for the detected device.
583 //
584 IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
585 if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
586 continue;
587 }
588
589 IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
590
591 ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
592
593 IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;
594 IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel;
595 IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice;
596
597 //
598 // initialize Block IO interface's Media pointer
599 //
600 IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
601
602 //
603 // Initialize IDE IO port addresses, including Command Block registers
604 // and Control Block registers
605 //
606 IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
607 if (IdeBlkIoDevicePtr->IoPort == NULL) {
608 continue;
609 }
610
611 ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
612 CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
613 ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
614
615 IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
616 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
617 IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
618 IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
619 IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
620 IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
621 IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
622 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
623
624 (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
625 IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
626
627 IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
628
629 IdeBlkIoDevicePtr->PciIo = PciIo;
630 IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
631 IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
632
633 //
634 // Report Status code: is about to detect IDE drive
635 //
636 REPORT_STATUS_CODE_EX (
637 EFI_PROGRESS_CODE,
638 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
639 0,
640 &gEfiCallerIdGuid,
641 NULL,
642 NULL,
643 0
644 );
645
646 //
647 // Discover device, now!
648 //
649 PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);
650 Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
651 PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);
652
653 IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;
654 IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;
655
656 if (!EFI_ERROR (Status)) {
657 //
658 // Set Device Path
659 //
660 ZeroMem (&NewNode, sizeof (NewNode));
661 NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;
662 NewNode.DevPath.SubType = MSG_ATAPI_DP;
663 SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
664
665 NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;
666 NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;
667 NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;
668 IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
669 ParentDevicePath,
670 &NewNode.DevPath
671 );
672 if (IdeBlkIoDevicePtr->DevicePath == NULL) {
673 ReleaseIdeResources (IdeBlkIoDevicePtr);
674 continue;
675 }
676
677 //
678 // Submit identify data to IDE controller init driver
679 //
680 CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));
681 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
682 IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
683 } else {
684 //
685 // Device detection failed
686 //
687 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
688 IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
689 ReleaseIdeResources (IdeBlkIoDevicePtr);
690 IdeBlkIoDevicePtr = NULL;
691 }
692 //
693 // end of 1st inner loop ---
694 //
695 }
696 //
697 // end of 1st outer loop =========
698 //
699 }
700
701 //
702 // = 2nd outer loop == Primary/Secondary =================
703 //
704 for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
705
706 //
707 // -- 2nd inner loop --- Master/Slave --------
708 //
709 for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
710
711 if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
712 continue;
713 }
714
715 if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
716 continue;
717 }
718
719 Status = IdeInit->CalculateMode (
720 IdeInit,
721 IdeChannel,
722 IdeDevice,
723 &SupportedModes
724 );
725 if (EFI_ERROR (Status)) {
726 DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
727 continue;
728 }
729
730 IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
731
732 //
733 // Set best supported PIO mode on this IDE device
734 //
735 if (SupportedModes->PioMode.Mode <= AtaPioMode2) {
736 TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
737 } else {
738 TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
739 }
740
741 TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
742
743 if (SupportedModes->ExtModeCount == 0){
744 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
745
746 if (EFI_ERROR (Status)) {
747 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
748 ReleaseIdeResources (IdeBlkIoDevicePtr);
749 IdeBlkIoDevicePtr = NULL;
750 continue;
751 }
752 }
753
754 //
755 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cannot
756 // be set together. Only one DMA mode can be set to a device. If setting
757 // DMA mode operation fails, we can continue moving on because we only use
758 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
759 //
760 if (SupportedModes->UdmaMode.Valid) {
761
762 TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
763 TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
764 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
765
766 if (EFI_ERROR (Status)) {
767 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
768 ReleaseIdeResources (IdeBlkIoDevicePtr);
769 IdeBlkIoDevicePtr = NULL;
770 continue;
771 }
772 //
773 // Record Udma Mode
774 //
775 IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
776 IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode;
777 EnableInterrupt (IdeBlkIoDevicePtr);
778 } else if (SupportedModes->MultiWordDmaMode.Valid) {
779
780 TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
781 TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
782 Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
783
784 if (EFI_ERROR (Status)) {
785 IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
786 ReleaseIdeResources (IdeBlkIoDevicePtr);
787 IdeBlkIoDevicePtr = NULL;
788 continue;
789 }
790
791 EnableInterrupt (IdeBlkIoDevicePtr);
792 }
793 //
794 // Init driver parameters
795 //
796 DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.sectors_per_track;
797 DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->IdData->AtaData.heads - 1);
798 DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;
799 //
800 // Set Parameters for the device:
801 // 1) Init
802 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
803 //
804 if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
805 Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
806 }
807
808 //
809 // Record PIO mode used in private data
810 //
811 IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
812
813 //
814 // Set IDE controller Timing Blocks in the PCI Configuration Space
815 //
816 IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
817
818 //
819 // Add Component Name for the IDE/ATAPI device that was discovered.
820 //
821 IdeBlkIoDevicePtr->ControllerNameTable = NULL;
822 ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);
823
824 Status = gBS->InstallMultipleProtocolInterfaces (
825 &IdeBlkIoDevicePtr->Handle,
826 &gEfiDevicePathProtocolGuid,
827 IdeBlkIoDevicePtr->DevicePath,
828 &gEfiBlockIoProtocolGuid,
829 &IdeBlkIoDevicePtr->BlkIo,
830 &gEfiDiskInfoProtocolGuid,
831 &IdeBlkIoDevicePtr->DiskInfo,
832 NULL
833 );
834
835 if (EFI_ERROR (Status)) {
836 ReleaseIdeResources (IdeBlkIoDevicePtr);
837 }
838
839 gBS->OpenProtocol (
840 Controller,
841 &gEfiPciIoProtocolGuid,
842 (VOID **) &PciIo,
843 This->DriverBindingHandle,
844 IdeBlkIoDevicePtr->Handle,
845 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
846 );
847
848 IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
849
850 //
851 // Report status code: device enabled!
852 //
853 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
854 EFI_PROGRESS_CODE,
855 (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
856 IdeBlkIoDevicePtr->DevicePath
857 );
858
859 //
860 // Create event to clear pending IDE interrupt
861 //
862 Status = gBS->CreateEventEx (
863 EVT_NOTIFY_SIGNAL,
864 TPL_NOTIFY,
865 ClearInterrupt,
866 IdeBlkIoDevicePtr,
867 &gEfiEventExitBootServicesGuid,
868 &IdeBlkIoDevicePtr->ExitBootServiceEvent
869 );
870
871 //
872 // end of 2nd inner loop ----
873 //
874 }
875 //
876 // end of 2nd outer loop ==========
877 //
878 }
879
880 //
881 // All configurations done! Notify IdeController to do post initialization
882 // work such as saving IDE controller PCI settings for S3 resume
883 //
884 IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
885
886 if (SupportedModes != NULL) {
887 FreePool (SupportedModes);
888 }
889
890 PERF_START (NULL, "Finish IDE detection", "IDE", 1);
891 PERF_END (NULL, "Finish IDE detection", "IDE", 0);
892
893 return EFI_SUCCESS;
894
895ErrorExit:
896
897 //
898 // Report error code: controller error
899 //
900 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
901 EFI_ERROR_CODE | EFI_ERROR_MINOR,
902 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
903 ParentDevicePath
904 );
905
906 gBS->CloseProtocol (
907 Controller,
908 &gEfiIdeControllerInitProtocolGuid,
909 This->DriverBindingHandle,
910 Controller
911 );
912
913 gBS->UninstallMultipleProtocolInterfaces (
914 Controller,
915 &gEfiCallerIdGuid,
916 IdeBusDriverPrivateData,
917 NULL
918 );
919
920 if (IdeBusDriverPrivateData != NULL) {
921 gBS->FreePool (IdeBusDriverPrivateData);
922 }
923
924 if (SupportedModes != NULL) {
925 gBS->FreePool (SupportedModes);
926 }
927
928 gBS->CloseProtocol (
929 Controller,
930 &gEfiPciIoProtocolGuid,
931 This->DriverBindingHandle,
932 Controller
933 );
934
935 gBS->CloseProtocol (
936 Controller,
937 &gEfiDevicePathProtocolGuid,
938 This->DriverBindingHandle,
939 Controller
940 );
941
942 return Status;
943
944}
945/**
946 Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
947 child handle attached to the controller handle if there are.
948
949 @param This Protocol instance pointer.
950 @param Controller Handle of device to stop driver on
951 @param NumberOfChildren Not used
952 @param ChildHandleBuffer Not used
953
954 @retval EFI_SUCCESS This driver is removed DeviceHandle
955 @retval other This driver was not removed from this device
956
957**/
958EFI_STATUS
959EFIAPI
960IDEBusDriverBindingStop (
961 IN EFI_DRIVER_BINDING_PROTOCOL *This,
962 IN EFI_HANDLE Controller,
963 IN UINTN NumberOfChildren,
964 IN EFI_HANDLE *ChildHandleBuffer
965 )
966{
967 EFI_STATUS Status;
968 EFI_PCI_IO_PROTOCOL *PciIo;
969 BOOLEAN AllChildrenStopped;
970 UINTN Index;
971 IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
972 UINT64 Supports;
973
974 IdeBusDriverPrivateData = NULL;
975
976 if (NumberOfChildren == 0) {
977
978 Status = gBS->OpenProtocol (
979 Controller,
980 &gEfiPciIoProtocolGuid,
981 (VOID **) &PciIo,
982 This->DriverBindingHandle,
983 Controller,
984 EFI_OPEN_PROTOCOL_GET_PROTOCOL
985 );
986 if (!EFI_ERROR (Status)) {
987 Status = PciIo->Attributes (
988 PciIo,
989 EfiPciIoAttributeOperationSupported,
990 0,
991 &Supports
992 );
993 if (!EFI_ERROR (Status)) {
994 Supports &= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;
995 PciIo->Attributes (
996 PciIo,
997 EfiPciIoAttributeOperationDisable,
998 Supports,
999 NULL
1000 );
1001 }
1002 }
1003
1004 gBS->OpenProtocol (
1005 Controller,
1006 &gEfiCallerIdGuid,
1007 (VOID **) &IdeBusDriverPrivateData,
1008 This->DriverBindingHandle,
1009 Controller,
1010 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1011 );
1012
1013 gBS->UninstallMultipleProtocolInterfaces (
1014 Controller,
1015 &gEfiCallerIdGuid,
1016 IdeBusDriverPrivateData,
1017 NULL
1018 );
1019
1020 if (IdeBusDriverPrivateData != NULL) {
1021 gBS->FreePool (IdeBusDriverPrivateData);
1022 }
1023 //
1024 // Close the bus driver
1025 //
1026 gBS->CloseProtocol (
1027 Controller,
1028 &gEfiIdeControllerInitProtocolGuid,
1029 This->DriverBindingHandle,
1030 Controller
1031 );
1032 gBS->CloseProtocol (
1033 Controller,
1034 &gEfiPciIoProtocolGuid,
1035 This->DriverBindingHandle,
1036 Controller
1037 );
1038 gBS->CloseProtocol (
1039 Controller,
1040 &gEfiDevicePathProtocolGuid,
1041 This->DriverBindingHandle,
1042 Controller
1043 );
1044
1045 return EFI_SUCCESS;
1046 }
1047
1048 AllChildrenStopped = TRUE;
1049
1050 for (Index = 0; Index < NumberOfChildren; Index++) {
1051
1052 Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
1053
1054 if (EFI_ERROR (Status)) {
1055 AllChildrenStopped = FALSE;
1056 }
1057 }
1058
1059 if (!AllChildrenStopped) {
1060 return EFI_DEVICE_ERROR;
1061 }
1062
1063 return EFI_SUCCESS;
1064}
1065
1066/**
1067 issue ATA or ATAPI command to reset a block IO device.
1068 @param This Block IO protocol instance pointer.
1069 @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
1070 If TRUE, for ATAPI device, driver need invoke ATA reset method after
1071 invoke ATAPI reset method
1072
1073 @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.
1074 @retval EFI_SUCCESS The device reset successfully
1075
1076**/
1077EFI_STATUS
1078EFIAPI
1079IDEBlkIoReset (
1080 IN EFI_BLOCK_IO_PROTOCOL *This,
1081 IN BOOLEAN ExtendedVerification
1082 )
1083{
1084 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1085 EFI_STATUS Status;
1086 EFI_TPL OldTpl;
1087
1088 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1089
1090 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1091 //
1092 // Requery IDE IO resources in case of the switch of native and legacy modes
1093 //
1094 ReassignIdeResources (IdeBlkIoDevice);
1095
1096 //
1097 // for ATA device, using ATA reset method
1098 //
1099 if (IdeBlkIoDevice->Type == IdeHardDisk ||
1100 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1101 Status = AtaSoftReset (IdeBlkIoDevice);
1102 goto Done;
1103 }
1104
1105 if (IdeBlkIoDevice->Type == IdeUnknown) {
1106 Status = EFI_DEVICE_ERROR;
1107 goto Done;
1108 }
1109
1110 //
1111 // for ATAPI device, using ATAPI reset method
1112 //
1113 Status = AtapiSoftReset (IdeBlkIoDevice);
1114 if (ExtendedVerification) {
1115 Status = AtaSoftReset (IdeBlkIoDevice);
1116 }
1117
1118Done:
1119 gBS->RestoreTPL (OldTpl);
1120 return Status;
1121}
1122
1123/**
1124 Read data from a block IO device
1125
1126 @param This Block IO protocol instance pointer.
1127 @param MediaId The media ID of the device
1128 @param Lba Starting LBA address to read data
1129 @param BufferSize The size of data to be read
1130 @param Buffer Caller supplied buffer to save data
1131
1132 @retval EFI_DEVICE_ERROR unknown device type
1133 @retval other read data status.
1134
1135**/
1136EFI_STATUS
1137EFIAPI
1138IDEBlkIoReadBlocks (
1139 IN EFI_BLOCK_IO_PROTOCOL *This,
1140 IN UINT32 MediaId,
1141 IN EFI_LBA Lba,
1142 IN UINTN BufferSize,
1143 OUT VOID *Buffer
1144 )
1145{
1146 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1147 EFI_STATUS Status;
1148 EFI_TPL OldTpl;
1149
1150 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1151
1152 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1153
1154 //
1155 // Requery IDE IO resources in case of the switch of native and legacy modes
1156 //
1157 ReassignIdeResources (IdeBlkIoDevice);
1158
1159 //
1160 // For ATA compatible device, use ATA read block's mechanism
1161 //
1162 if (IdeBlkIoDevice->Type == IdeHardDisk ||
1163 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1164 Status = AtaBlkIoReadBlocks (
1165 IdeBlkIoDevice,
1166 MediaId,
1167 Lba,
1168 BufferSize,
1169 Buffer
1170 );
1171 goto Done;
1172 }
1173
1174 if (IdeBlkIoDevice->Type == IdeUnknown) {
1175 Status = EFI_DEVICE_ERROR;
1176 goto Done;
1177 }
1178
1179 //
1180 // for ATAPI device, using ATAPI read block's mechanism
1181 //
1182 Status = AtapiBlkIoReadBlocks (
1183 IdeBlkIoDevice,
1184 MediaId,
1185 Lba,
1186 BufferSize,
1187 Buffer
1188 );
1189
1190Done:
1191 gBS->RestoreTPL (OldTpl);
1192
1193 return Status;
1194}
1195
1196/**
1197 Write data to block io device.
1198
1199 @param This Protocol instance pointer.
1200 @param MediaId The media ID of the device
1201 @param Lba Starting LBA address to write data
1202 @param BufferSize The size of data to be written
1203 @param Buffer Caller supplied buffer to save data
1204
1205 @retval EFI_DEVICE_ERROR unknown device type
1206 @retval other write data status
1207
1208**/
1209EFI_STATUS
1210EFIAPI
1211IDEBlkIoWriteBlocks (
1212 IN EFI_BLOCK_IO_PROTOCOL *This,
1213 IN UINT32 MediaId,
1214 IN EFI_LBA Lba,
1215 IN UINTN BufferSize,
1216 IN VOID *Buffer
1217 )
1218{
1219 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1220 EFI_STATUS Status;
1221 EFI_TPL OldTpl;
1222
1223 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1224
1225 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1226 //
1227 // Requery IDE IO resources in case of the switch of native and legacy modes
1228 //
1229 ReassignIdeResources (IdeBlkIoDevice);
1230
1231 //
1232 // for ATA device, using ATA write block's mechanism
1233 //
1234 if (IdeBlkIoDevice->Type == IdeHardDisk ||
1235 IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1236
1237 Status = AtaBlkIoWriteBlocks (
1238 IdeBlkIoDevice,
1239 MediaId,
1240 Lba,
1241 BufferSize,
1242 Buffer
1243 );
1244 goto Done;
1245 }
1246
1247 if (IdeBlkIoDevice->Type == IdeUnknown) {
1248 Status = EFI_DEVICE_ERROR;
1249 goto Done;
1250 }
1251
1252 //
1253 // for ATAPI device, using ATAPI write block's mechanism
1254 //
1255 Status = AtapiBlkIoWriteBlocks (
1256 IdeBlkIoDevice,
1257 MediaId,
1258 Lba,
1259 BufferSize,
1260 Buffer
1261 );
1262
1263Done:
1264 gBS->RestoreTPL (OldTpl);
1265 return Status;
1266}
1267/**
1268 Flushes all modified data to a physical block devices
1269
1270 @param This Indicates a pointer to the calling context which to specify a
1271 specific block device
1272
1273 @retval EFI_SUCCESS Always return success.
1274**/
1275EFI_STATUS
1276EFIAPI
1277IDEBlkIoFlushBlocks (
1278 IN EFI_BLOCK_IO_PROTOCOL *This
1279 )
1280{
1281 //
1282 // return directly
1283 //
1284 return EFI_SUCCESS;
1285}
1286
1287/**
1288 This function is used by the IDE bus driver to get inquiry data.
1289 Data format of Identify data is defined by the Interface GUID.
1290
1291 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1292 @param InquiryData Pointer to a buffer for the inquiry data.
1293 @param InquiryDataSize Pointer to the value for the inquiry data size.
1294
1295 @retval EFI_SUCCESS The command was accepted without any errors.
1296 @retval EFI_NOT_FOUND Device does not support this data class
1297 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1298 @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough
1299
1300**/
1301EFI_STATUS
1302EFIAPI
1303IDEDiskInfoInquiry (
1304 IN EFI_DISK_INFO_PROTOCOL *This,
1305 IN OUT VOID *InquiryData,
1306 IN OUT UINT32 *InquiryDataSize
1307 )
1308{
1309 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1310
1311 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1312
1313 if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {
1314 *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
1315 return EFI_BUFFER_TOO_SMALL;
1316 }
1317
1318 if (IdeBlkIoDevice->InquiryData == NULL) {
1319 return EFI_NOT_FOUND;
1320 }
1321
1322 gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));
1323 *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
1324
1325 return EFI_SUCCESS;
1326}
1327
1328/**
1329 This function is used by the IDE bus driver to get identify data.
1330 Data format of Identify data is defined by the Interface GUID.
1331
1332 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1333 @param IdentifyData Pointer to a buffer for the identify data.
1334 @param IdentifyDataSize Pointer to the value for the identify data size.
1335
1336 @retval EFI_SUCCESS The command was accepted without any errors.
1337 @retval EFI_NOT_FOUND Device does not support this data class
1338 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1339 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1340
1341**/
1342EFI_STATUS
1343EFIAPI
1344IDEDiskInfoIdentify (
1345 IN EFI_DISK_INFO_PROTOCOL *This,
1346 IN OUT VOID *IdentifyData,
1347 IN OUT UINT32 *IdentifyDataSize
1348 )
1349{
1350 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1351
1352 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1353
1354 if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
1355 *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
1356 return EFI_BUFFER_TOO_SMALL;
1357 }
1358
1359 if (IdeBlkIoDevice->IdData == NULL) {
1360 return EFI_NOT_FOUND;
1361 }
1362
1363 gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));
1364 *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
1365
1366 return EFI_SUCCESS;
1367}
1368
1369/**
1370 This function is used by the IDE bus driver to get sense data.
1371 Data format of Sense data is defined by the Interface GUID.
1372
1373 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1374 @param SenseData Pointer to the SenseData.
1375 @param SenseDataSize Size of SenseData in bytes.
1376 @param SenseDataNumber Pointer to the value for the identify data size.
1377
1378 @retval EFI_SUCCESS The command was accepted without any errors.
1379 @retval EFI_NOT_FOUND Device does not support this data class
1380 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1381 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1382
1383**/
1384EFI_STATUS
1385EFIAPI
1386IDEDiskInfoSenseData (
1387 IN EFI_DISK_INFO_PROTOCOL *This,
1388 IN OUT VOID *SenseData,
1389 IN OUT UINT32 *SenseDataSize,
1390 OUT UINT8 *SenseDataNumber
1391 )
1392{
1393 return EFI_NOT_FOUND;
1394}
1395
1396/**
1397 This function is used by the IDE bus driver to get controller information.
1398
1399 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1400 @param IdeChannel Pointer to the Ide Channel number. Primary or secondary.
1401 @param IdeDevice Pointer to the Ide Device number. Master or slave.
1402
1403 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1404 @retval EFI_UNSUPPORTED This is not an IDE device
1405
1406**/
1407EFI_STATUS
1408EFIAPI
1409IDEDiskInfoWhichIde (
1410 IN EFI_DISK_INFO_PROTOCOL *This,
1411 OUT UINT32 *IdeChannel,
1412 OUT UINT32 *IdeDevice
1413 )
1414{
1415 IDE_BLK_IO_DEV *IdeBlkIoDevice;
1416
1417 IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1418 *IdeChannel = IdeBlkIoDevice->Channel;
1419 *IdeDevice = IdeBlkIoDevice->Device;
1420
1421 return EFI_SUCCESS;
1422}
1423
1424/**
1425 The is an event(generally the event is exitBootService event) call back function.
1426 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1427
1428 @param Event Pointer to this event
1429 @param Context Event handler private data
1430
1431**/
1432VOID
1433EFIAPI
1434ClearInterrupt (
1435 IN EFI_EVENT Event,
1436 IN VOID *Context
1437 )
1438{
1439 EFI_STATUS Status;
1440 UINT64 IoPortForBmis;
1441 UINT8 RegisterValue;
1442 IDE_BLK_IO_DEV *IdeDev;
1443
1444 //
1445 // Get our context
1446 //
1447 IdeDev = (IDE_BLK_IO_DEV *) Context;
1448
1449 //
1450 // Obtain IDE IO port registers' base addresses
1451 //
1452 Status = ReassignIdeResources (IdeDev);
1453 if (EFI_ERROR (Status)) {
1454 return;
1455 }
1456
1457 //
1458 // Check whether interrupt is pending
1459 //
1460
1461 //
1462 // Reset IDE device to force it de-assert interrupt pin
1463 // Note: this will reset all devices on this IDE channel
1464 //
1465 AtaSoftReset (IdeDev);
1466 if (EFI_ERROR (Status)) {
1467 return;
1468 }
1469
1470 //
1471 // Get base address of IDE Bus Master Status Register
1472 //
1473 if (IdePrimary == IdeDev->Channel) {
1474 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
1475 } else {
1476 if (IdeSecondary == IdeDev->Channel) {
1477 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
1478 } else {
1479 return;
1480 }
1481 }
1482 //
1483 // Read BMIS register and clear ERROR and INTR bit
1484 //
1485 IdeDev->PciIo->Io.Read (
1486 IdeDev->PciIo,
1487 EfiPciIoWidthUint8,
1488 EFI_PCI_IO_PASS_THROUGH_BAR,
1489 IoPortForBmis,
1490 1,
1491 &RegisterValue
1492 );
1493
1494 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
1495
1496 IdeDev->PciIo->Io.Write (
1497 IdeDev->PciIo,
1498 EfiPciIoWidthUint8,
1499 EFI_PCI_IO_PASS_THROUGH_BAR,
1500 IoPortForBmis,
1501 1,
1502 &RegisterValue
1503 );
1504
1505 //
1506 // Select the other device on this channel to ensure this device to release the interrupt pin
1507 //
1508 if (IdeDev->Device == 0) {
1509 RegisterValue = (1 << 4) | 0xe0;
1510 } else {
1511 RegisterValue = (0 << 4) | 0xe0;
1512 }
1513 IDEWritePortB (
1514 IdeDev->PciIo,
1515 IdeDev->IoPort->Head,
1516 RegisterValue
1517 );
1518
1519}
1520
1521/**
1522 The user Entry Point for module IdeBus. The user code starts with this function.
1523
1524 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1525 @param[in] SystemTable A pointer to the EFI System Table.
1526
1527 @retval EFI_SUCCESS The entry point is executed successfully.
1528 @retval other Some error occurs when executing this entry point.
1529
1530**/
1531EFI_STATUS
1532EFIAPI
1533InitializeIdeBus(
1534 IN EFI_HANDLE ImageHandle,
1535 IN EFI_SYSTEM_TABLE *SystemTable
1536 )
1537{
1538 EFI_STATUS Status;
1539
1540 //
1541 // Install driver model protocol(s).
1542 //
1543 Status = EfiLibInstallAllDriverProtocols2 (
1544 ImageHandle,
1545 SystemTable,
1546 &gIDEBusDriverBinding,
1547 ImageHandle,
1548 &gIDEBusComponentName,
1549 &gIDEBusComponentName2,
1550 NULL,
1551 NULL,
1552 &gIDEBusDriverDiagnostics,
1553 &gIDEBusDriverDiagnostics2
1554 );
1555 ASSERT_EFI_ERROR (Status);
1556
1557 return Status;
1558}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette