]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/IdeControllerDxe/IdeController.c
Add IDE support for edk2 Duet platform.
[mirror_edk2.git] / DuetPkg / IdeControllerDxe / IdeController.c
1 /*++
2
3 Copyright (c) 2006 - 2007 Intel Corporation. All rights reserved
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 IdeController.c
16
17 Abstract:
18
19 This driver module produces IDE_CONTROLLER_INIT protocol and will be used by
20 IDE Bus driver to support platform dependent timing information. This driver
21 is responsible for early initialization of IDE controller.
22
23 Revision History
24 --*/
25
26 #include "IdeController.h"
27 #include "IdeData.h"
28
29 //
30 // IDE Controller Init Guid
31 //
32 EFI_GUID
33 gIdeControllerDriverGuid = { 0x91e365e9, 0xe0c0, 0x4647, 0xb0, 0xeb, 0xf6, 0x78, 0xf6, 0x21, 0xf8, 0x8d };
34
35 //
36 // EFI_DRIVER_BINDING_PROTOCOL instance
37 //
38 EFI_DRIVER_BINDING_PROTOCOL gIdeControllerDriverBinding = {
39 IdeControllerSupported,
40 IdeControllerStart,
41 IdeControllerStop,
42 0xa,
43 NULL,
44 NULL
45 };
46
47 //
48 // Internal function definitions
49 //
50 EFI_STATUS
51 EnableNativeIdeDecode (
52 IN EFI_PCI_IO_PROTOCOL *PciIo
53 );
54
55 EFI_STATUS
56 EnableLegacyIdeDecode (
57 EFI_EVENT Event,
58 VOID *Context
59 );
60
61 EFI_STATUS
62 IdeDetectCableType (
63 IN UINT8 Channel,
64 IN UINT8 Device,
65 IN EFI_PCI_IO_PROTOCOL *PciIo,
66 IN EFI_IDENTIFY_DATA *IdentifyData
67 );
68
69 EFI_STATUS
70 AdjustUdmaModeByCableType (
71 IN UINT8 Channel,
72 IN UINT8 Device,
73 IN EFI_PCI_IO_PROTOCOL *PciIo,
74 IN OUT EFI_ATA_COLLECTIVE_MODE *Modes
75 );
76
77 EFI_STATUS
78 CalculateBestPioMode (
79 IN EFI_IDENTIFY_DATA * IdentifyData,
80 IN UINT16 *DisPioMode OPTIONAL,
81 OUT UINT16 *SelectedMode
82 );
83
84 EFI_STATUS
85 CalculateBestUdmaMode (
86 IN EFI_IDENTIFY_DATA * IdentifyData,
87 IN UINT16 *DisUDmaMode OPTIONAL,
88 OUT UINT16 *SelectedMode
89 );
90
91 EFI_STATUS
92 IdeInitSetUdmaTiming (
93 IN UINT8 Channel,
94 IN UINT8 Device,
95 IN EFI_PCI_IO_PROTOCOL *PciIo,
96 IN EFI_ATA_COLLECTIVE_MODE *Modes
97 );
98
99 EFI_STATUS
100 IdeInitSetPioTiming (
101 IN UINT8 Channel,
102 IN UINT8 Device,
103 IN EFI_PCI_IO_PROTOCOL *PciIo,
104 IN EFI_IDENTIFY_DATA *IdentifyData,
105 IN EFI_ATA_COLLECTIVE_MODE *Modes
106 );
107
108 //
109 // *************************************
110 // IdeController Driver Entry Point
111 // *************************************
112 //
113 EFI_STATUS
114 EFIAPI
115 InitializeIdeControllerDriver (
116 IN EFI_HANDLE ImageHandle,
117 IN EFI_SYSTEM_TABLE *SystemTable
118 )
119 /*++
120 Routine Description:
121
122 Chipset Ide Driver EntryPoint function. It follows the standard EFI driver
123 model. It's called by StartImage() of DXE Core
124
125 Argments:
126
127 ImageHnadle -- While the driver image loaded be the ImageLoader(),
128 an image handle is assigned to this driver binary,
129 all activities of the driver is tied to this ImageHandle
130 *SystemTable -- A pointer to the system table, for all BS(Boo Services) and
131 RT(Runtime Services)
132
133 Retruns:
134
135 Always call EfiLibInstallDriverBindingProtocol( ) and retrun the result
136
137 --*/
138 {
139
140 return EfiLibInstallDriverBindingComponentName2 (
141 ImageHandle,
142 SystemTable,
143 &gIdeControllerDriverBinding,
144 ImageHandle,
145 &gIdeControllerName,
146 &gIdeControllerName2
147 );
148 }
149
150 EFI_STATUS
151 EFIAPI
152 IdeControllerSupported (
153 IN EFI_DRIVER_BINDING_PROTOCOL *This,
154 IN EFI_HANDLE Controller,
155 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
156 )
157 /*++
158
159 Routine Description:
160
161 Register Driver Binding protocol for this driver.
162
163 Arguments:
164
165 This -- a pointer points to the Binding Protocol instance
166 Controller -- The handle of controller to be tested.
167 *RemainingDevicePath -- A pointer to the device path. Ignored by device
168 driver but used by bus driver
169
170 Returns:
171
172 EFI_SUCCESS -- Driver loaded.
173 other -- Driver not loaded.
174 --*/
175 {
176 EFI_STATUS Status;
177 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
178 EFI_PCI_IO_PROTOCOL *PciIo;
179 PCI_TYPE00 PciData;
180
181 //
182 // Ide Controller is a device driver, and should ingore the
183 // "RemainingDevicePath" according to EFI spec
184 //
185 Status = gBS->OpenProtocol (
186 Controller,
187 &gEfiDevicePathProtocolGuid,
188 (VOID *) &ParentDevicePath,
189 This->DriverBindingHandle,
190 Controller,
191 EFI_OPEN_PROTOCOL_BY_DRIVER
192 );
193 if (EFI_ERROR (Status)) {
194 //
195 // EFI_ALREADY_STARTED is also an error
196 //
197 return Status;
198 }
199 //
200 // Close the protocol because we don't use it here
201 //
202 gBS->CloseProtocol (
203 Controller,
204 &gEfiDevicePathProtocolGuid,
205 This->DriverBindingHandle,
206 Controller
207 );
208
209 //
210 // Now test the EfiPciIoProtocol
211 //
212 Status = gBS->OpenProtocol (
213 Controller,
214 &gEfiPciIoProtocolGuid,
215 (VOID **) &PciIo,
216 This->DriverBindingHandle,
217 Controller,
218 EFI_OPEN_PROTOCOL_BY_DRIVER
219 );
220 if (EFI_ERROR (Status)) {
221 return Status;
222 }
223 //
224 // Now further check the PCI header: Base class (offset 0x0B) and
225 // Sub Class (offset 0x0A). This controller should be an Ide controller
226 //
227 Status = PciIo->Pci.Read (
228 PciIo,
229 EfiPciIoWidthUint8,
230 0,
231 sizeof (PciData),
232 &PciData
233 );
234
235 if (EFI_ERROR (Status)) {
236 gBS->CloseProtocol (
237 Controller,
238 &gEfiPciIoProtocolGuid,
239 This->DriverBindingHandle,
240 Controller
241 );
242 return EFI_UNSUPPORTED;
243 }
244 //
245 // Examine Ide PCI Configuration table fields
246 //
247 if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) ||
248 (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)
249 ) {
250
251 Status = EFI_UNSUPPORTED;
252 }
253
254 gBS->CloseProtocol (
255 Controller,
256 &gEfiPciIoProtocolGuid,
257 This->DriverBindingHandle,
258 Controller
259 );
260
261 return Status;
262 }
263
264 EFI_STATUS
265 EFIAPI
266 IdeControllerStart (
267 IN EFI_DRIVER_BINDING_PROTOCOL *This,
268 IN EFI_HANDLE Controller,
269 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
270 )
271 /*++
272
273 Routine Description:
274
275 This routine is called right after the .Supported() called and return
276 EFI_SUCCESS. Notes: The supported protocols are checked but the Protocols
277 are closed.
278
279 Arguments:
280
281 This -- a pointer points to the Binding Protocol instance
282 Controller -- The handle of controller to be tested. Parameter
283 passed by the caller
284 *RemainingDevicePath -- A pointer to the device path. Should be ignored by
285 device driver
286 --*/
287 {
288 EFI_STATUS Status;
289 EFI_PCI_IO_PROTOCOL *PciIo;
290 EFI_IDE_CONTROLLER_PRIVATE_DATA *IdePrivateData;
291
292 //
293 // Now test and open the EfiPciIoProtocol
294 //
295 Status = gBS->OpenProtocol (
296 Controller,
297 &gEfiPciIoProtocolGuid,
298 (VOID **) &PciIo,
299 This->DriverBindingHandle,
300 Controller,
301 EFI_OPEN_PROTOCOL_BY_DRIVER
302 );
303
304 //
305 // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
306 // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
307 // that the protocol has been opened and should be treated as a
308 // normal condition and the program proceeds. The Protocol will not
309 // opened 'again' by this call.
310 // Status != ALREADY_STARTED - Error status, terminate program execution
311 //
312 if (EFI_ERROR (Status)) {
313 //
314 // EFI_ALREADY_STARTED is also an error
315 //
316 return Status;
317 }
318 //
319 // Allocate Ide private data structure
320 //
321 Status = gBS->AllocatePool (
322 EfiBootServicesData,
323 sizeof (EFI_IDE_CONTROLLER_PRIVATE_DATA),
324 (VOID **) &IdePrivateData
325 );
326 if (EFI_ERROR (Status)) {
327 return EFI_OUT_OF_RESOURCES;
328 }
329 //
330 // Initialize Ide controller private data
331 //
332 ZeroMem (IdePrivateData, sizeof (EFI_IDE_CONTROLLER_PRIVATE_DATA));
333 IdePrivateData->Signature = IDE_CONTROLLER_SIGNATURE;
334 IdePrivateData->PciIo = PciIo;
335 IdePrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;
336 IdePrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;
337 IdePrivateData->IdeInit.SubmitData = IdeInitSubmitData;
338 IdePrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;
339 IdePrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;
340 IdePrivateData->IdeInit.SetTiming = IdeInitSetTiming;
341 IdePrivateData->IdeInit.EnumAll = ICH_IDE_ENUMER_ALL;
342 IdePrivateData->IdeInit.ChannelCount = ICH_IDE_MAX_CHANNEL;
343
344 //
345 // Install IDE_CONTROLLER_INIT protocol & private data to this instance
346 //
347 Status = gBS->InstallMultipleProtocolInterfaces (
348 &Controller,
349 &gIdeControllerDriverGuid,
350 IdePrivateData,
351 &gEfiIdeControllerInitProtocolGuid,
352 &(IdePrivateData->IdeInit),
353 NULL
354 );
355
356 return Status;
357 }
358
359 EFI_STATUS
360 EFIAPI
361 IdeControllerStop (
362 IN EFI_DRIVER_BINDING_PROTOCOL *This,
363 IN EFI_HANDLE Controller,
364 IN UINTN NumberOfChildren,
365 IN EFI_HANDLE *ChildHandleBuffer
366 )
367 /*++
368
369 Routine Description:
370 Stop this driver on Controller Handle.
371
372 Arguments:
373 This - Protocol instance pointer.
374 Controller - Handle of device to stop driver on
375 NumberOfChildren - Not used
376 ChildHandleBuffer - Not used
377
378 Returns:
379 EFI_SUCCESS - This driver is removed DeviceHandle
380 other - This driver was not removed from this device
381
382 --*/
383 {
384 EFI_STATUS Status;
385 EFI_IDE_CONTROLLER_PRIVATE_DATA *IdePrivateData;
386
387 //
388 // Get private data
389 //
390 Status = gBS->OpenProtocol (
391 Controller,
392 &gIdeControllerDriverGuid,
393 (VOID **) &IdePrivateData,
394 This->DriverBindingHandle,
395 Controller,
396 EFI_OPEN_PROTOCOL_GET_PROTOCOL
397 );
398 ASSERT_EFI_ERROR (Status);
399
400 //
401 // Close protocols opened by Ide controller driver
402 //
403 Status = gBS->CloseProtocol (
404 Controller,
405 &gEfiPciIoProtocolGuid,
406 This->DriverBindingHandle,
407 Controller
408 );
409
410 gBS->UninstallMultipleProtocolInterfaces (
411 Controller,
412 &gIdeControllerDriverGuid,
413 IdePrivateData,
414 &gEfiIdeControllerInitProtocolGuid,
415 &(IdePrivateData->IdeInit),
416 NULL
417 );
418
419 gBS->FreePool (IdePrivateData);
420
421 return EFI_SUCCESS;
422 }
423
424 //
425 // Interface functions of IDE_CONTROLLER_INIT protocol
426 //
427 EFI_STATUS
428 EFIAPI
429 IdeInitGetChannelInfo (
430 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
431 IN UINT8 Channel,
432 OUT BOOLEAN *Enabled,
433 OUT UINT8 *MaxDevices
434 )
435 /*++
436 Routine Description:
437
438 This function can be used to obtain information about a specified channel.
439 It's usually used by IDE Bus driver during enumeration process.
440
441 Arguments:
442
443 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
444 Channel -- Channel number (0 based, either 0 or 1)
445 Enabled -- TRUE if the channel is enabled. If the channel is disabled,
446 then it will no be enumerated.
447 MaxDevices -- The Max number of IDE devices that the bus driver can expect
448 on this channel. For ATA/ATAPI, this number is either 1 or 2.
449
450 Returns:
451 EFI_STATUS
452
453 --*/
454 {
455 //
456 // Channel number (0 based, either 0 or 1)
457 //
458 if (Channel < ICH_IDE_MAX_CHANNEL) {
459 *Enabled = TRUE;
460 *MaxDevices = ICH_IDE_MAX_DEVICES;
461 return EFI_SUCCESS;
462 }
463
464 *Enabled = FALSE;
465 return EFI_INVALID_PARAMETER;
466 }
467
468
469 EFI_STATUS
470 EFIAPI
471 IdeInitNotifyPhase (
472 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
473 IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase,
474 IN UINT8 Channel
475 )
476 /*++
477
478 Routine Description:
479
480 This function is called by IdeBus driver before executing certain actions.
481 This allows IDE Controller Init to prepare for each action.
482
483 Arguments:
484
485 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
486 Phase -- phase indicator defined by IDE_CONTROLLER_INIT protocol
487 Channel -- Channel number (0 based, either 0 or 1)
488
489 Returns:
490
491 --*/
492 {
493 return EFI_SUCCESS;
494 }
495
496 EFI_STATUS
497 EFIAPI
498 IdeInitSubmitData (
499 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
500 IN UINT8 Channel,
501 IN UINT8 Device,
502 IN EFI_IDENTIFY_DATA *IdentifyData
503 )
504 /*++
505
506 Routine Description:
507
508 This function is called by IdeBus driver to submit EFI_IDENTIFY_DATA data structure
509 obtained from IDE deivce. This structure is used to set IDE timing
510
511 Arguments:
512
513 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
514 Channel -- IDE channel number (0 based, either 0 or 1)
515 Device -- IDE device number
516 IdentifyData -- A pointer to EFI_IDENTIFY_DATA data structure
517
518 Returns:
519
520 --*/
521 {
522 return EFI_SUCCESS;
523 }
524
525 EFI_STATUS
526 EFIAPI
527 IdeInitDisqualifyMode (
528 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
529 IN UINT8 Channel,
530 IN UINT8 Device,
531 IN EFI_ATA_COLLECTIVE_MODE *BadModes
532 )
533 /*++
534
535 Routine Description:
536
537 This function is called by IdeBus driver to disqualify unsupported operation
538 mode on specfic IDE device
539
540 Arguments:
541
542 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
543 Channel -- IDE channel number (0 based, either 0 or 1)
544 Device -- IDE device number
545 BadModes -- Operation mode indicator
546
547 Returns:
548
549 --*/
550 {
551 return EFI_SUCCESS;
552 }
553
554 EFI_STATUS
555 EFIAPI
556 IdeInitCalculateMode (
557 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
558 IN UINT8 Channel,
559 IN UINT8 Device,
560 OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes
561 )
562 /*++
563
564 Routine Description:
565
566 This function is called by IdeBus driver to calculate the best operation mode
567 supported by specific IDE device
568
569 Arguments:
570
571 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
572 Channel -- IDE channel number (0 based, either 0 or 1)
573 Device -- IDE device number
574 SupportedModes -- Modes collection supported by IDE device
575
576 Returns:
577
578 --*/
579 {
580 if (Channel >= ICH_IDE_MAX_CHANNEL || Device >= ICH_IDE_MAX_DEVICES) {
581 return EFI_INVALID_PARAMETER;
582 }
583
584 *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));
585 if (*SupportedModes == NULL) {
586 return EFI_OUT_OF_RESOURCES;
587 }
588
589 //
590 // In EoE enviroment, when nothing is known about the platform hardware,
591 // just set the mode to lowest PIO mode for compatibility.
592 //
593 (*SupportedModes)->PioMode.Valid = TRUE;
594 (*SupportedModes)->PioMode.Mode = AtaPioModeBelow2;
595 (*SupportedModes)->UdmaMode.Valid = FALSE;
596 (*SupportedModes)->SingleWordDmaMode.Valid = FALSE;
597 (*SupportedModes)->MultiWordDmaMode.Valid = FALSE;
598
599 return EFI_SUCCESS;
600 }
601
602
603 EFI_STATUS
604 EFIAPI
605 IdeInitSetTiming (
606 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
607 IN UINT8 Channel,
608 IN UINT8 Device,
609 IN EFI_ATA_COLLECTIVE_MODE *Modes
610 )
611 /*++
612
613 Routine Description:
614
615 This function is called by IdeBus driver to set appropriate timing on IDE
616 controller according supported operation mode
617
618 Arguments:
619
620 This -- the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
621 Channel -- IDE channel number (0 based, either 0 or 1)
622 Device -- IDE device number
623
624 Returns:
625
626 --*/
627 {
628 return EFI_SUCCESS;
629 }
630
631