VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxIdeBusDxe/IdeBus.c@ 33114

Last change on this file since 33114 was 33027, checked in by vboxsync, 14 years ago

EFI: legal notes.

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

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