1 /*++
2
3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4 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 Module Name:
13
14 DeviceIo.c
15
16 Abstract:
17
18 EFI PC-AT PCI Device IO driver
19
20 --*/
21 #include "PcatPciRootBridge.h"
22 #include "DeviceIo.h"
23
24 EFI_STATUS
DeviceIoConstructor(IN EFI_HANDLE Handle,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * PciRootBridgeIo,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN UINT16 PrimaryBus,IN UINT16 SubordinateBus)25 DeviceIoConstructor (
26 IN EFI_HANDLE Handle,
27 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
28 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
29 IN UINT16 PrimaryBus,
30 IN UINT16 SubordinateBus
31 )
32 /*++
33
34 Routine Description:
35
36 Initialize and install a Device IO protocol on a empty device path handle.
37
38 Arguments:
39
40 Handle - Handle of PCI RootBridge IO instance
41 PciRootBridgeIo - PCI RootBridge IO instance
42 DevicePath - Device Path of PCI RootBridge IO instance
43 PrimaryBus - Primary Bus
44 SubordinateBus - Subordinate Bus
45
46 Returns:
47
48 EFI_SUCCESS - This driver is added to ControllerHandle.
49 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
50 Others - This driver does not support this device.
51
52 --*/
53 {
54 EFI_STATUS Status;
55 DEVICE_IO_PRIVATE_DATA *Private;
56
57 //
58 // Initialize the Device IO device instance.
59 //
60 Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
61 if (Private == NULL) {
62 return EFI_OUT_OF_RESOURCES;
63 }
64
65 Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
66 Private->Handle = Handle;
67 Private->PciRootBridgeIo = PciRootBridgeIo;
68 Private->DevicePath = DevicePath;
69 Private->PrimaryBus = PrimaryBus;
70 Private->SubordinateBus = SubordinateBus;
71
72 Private->DeviceIo.Mem.Read = DeviceIoMemRead;
73 Private->DeviceIo.Mem.Write = DeviceIoMemWrite;
74 Private->DeviceIo.Io.Read = DeviceIoIoRead;
75 Private->DeviceIo.Io.Write = DeviceIoIoWrite;
76 Private->DeviceIo.Pci.Read = DeviceIoPciRead;
77 Private->DeviceIo.Pci.Write = DeviceIoPciWrite;
78 Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;
79 Private->DeviceIo.Map = DeviceIoMap;
80 Private->DeviceIo.Unmap = DeviceIoUnmap;
81 Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;
82 Private->DeviceIo.Flush = DeviceIoFlush;
83 Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;
84
85 //
86 // Install protocol interfaces for the Device IO device.
87 //
88 Status = gBS->InstallMultipleProtocolInterfaces (
89 &Private->Handle,
90 &gEfiDeviceIoProtocolGuid,
91 &Private->DeviceIo,
92 NULL
93 );
94 ASSERT_EFI_ERROR (Status);
95
96 return Status;
97 }
98
99 EFI_STATUS
100 EFIAPI
DeviceIoMemRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)101 DeviceIoMemRead (
102 IN EFI_DEVICE_IO_PROTOCOL *This,
103 IN EFI_IO_WIDTH Width,
104 IN UINT64 Address,
105 IN UINTN Count,
106 IN OUT VOID *Buffer
107 )
108 /*++
109
110 Routine Description:
111
112 Perform reading memory mapped I/O space of device.
113
114 Arguments:
115
116 This - A pointer to EFI_DEVICE_IO protocol instance.
117 Width - Width of I/O operations.
118 Address - The base address of I/O operations.
119 Count - The number of I/O operations to perform.
120 Bytes moves is Width size * Count, starting at Address.
121 Buffer - The destination buffer to store results.
122
123 Returns:
124
125 EFI_SUCCESS - The data was read from the device.
126 EFI_INVALID_PARAMETER - Width is invalid.
127 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
128
129 --*/
130 {
131 EFI_STATUS Status;
132 DEVICE_IO_PRIVATE_DATA *Private;
133
134 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
135
136 if (Width > MMIO_COPY_UINT64) {
137 return EFI_INVALID_PARAMETER;
138 }
139 if (Width >= MMIO_COPY_UINT8) {
140 Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
141 Status = Private->PciRootBridgeIo->CopyMem (
142 Private->PciRootBridgeIo,
143 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
144 (UINT64)(UINTN) Buffer,
145 Address,
146 Count
147 );
148 } else {
149 Status = Private->PciRootBridgeIo->Mem.Read (
150 Private->PciRootBridgeIo,
151 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
152 Address,
153 Count,
154 Buffer
155 );
156 }
157
158 return Status;
159 }
160
161
162
163 EFI_STATUS
164 EFIAPI
DeviceIoMemWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)165 DeviceIoMemWrite (
166 IN EFI_DEVICE_IO_PROTOCOL *This,
167 IN EFI_IO_WIDTH Width,
168 IN UINT64 Address,
169 IN UINTN Count,
170 IN OUT VOID *Buffer
171 )
172 /*++
173
174 Routine Description:
175
176 Perform writing memory mapped I/O space of device.
177
178 Arguments:
179
180 This - A pointer to EFI_DEVICE_IO protocol instance.
181 Width - Width of I/O operations.
182 Address - The base address of I/O operations.
183 Count - The number of I/O operations to perform.
184 Bytes moves is Width size * Count, starting at Address.
185 Buffer - The source buffer of data to be written.
186
187 Returns:
188
189 EFI_SUCCESS - The data was written to the device.
190 EFI_INVALID_PARAMETER - Width is invalid.
191 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
192
193 --*/
194 {
195 EFI_STATUS Status;
196 DEVICE_IO_PRIVATE_DATA *Private;
197
198 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
199
200 if (Width > MMIO_COPY_UINT64) {
201 return EFI_INVALID_PARAMETER;
202 }
203 if (Width >= MMIO_COPY_UINT8) {
204 Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
205 Status = Private->PciRootBridgeIo->CopyMem (
206 Private->PciRootBridgeIo,
207 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
208 Address,
209 (UINT64)(UINTN) Buffer,
210 Count
211 );
212 } else {
213 Status = Private->PciRootBridgeIo->Mem.Write (
214 Private->PciRootBridgeIo,
215 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
216 Address,
217 Count,
218 Buffer
219 );
220 }
221
222 return Status;
223 }
224
225 EFI_STATUS
226 EFIAPI
DeviceIoIoRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)227 DeviceIoIoRead (
228 IN EFI_DEVICE_IO_PROTOCOL *This,
229 IN EFI_IO_WIDTH Width,
230 IN UINT64 Address,
231 IN UINTN Count,
232 IN OUT VOID *Buffer
233 )
234 /*++
235
236 Routine Description:
237
238 Perform reading I/O space of device.
239
240 Arguments:
241
242 This - A pointer to EFI_DEVICE_IO protocol instance.
243 Width - Width of I/O operations.
244 Address - The base address of I/O operations.
245 Count - The number of I/O operations to perform.
246 Bytes moves is Width size * Count, starting at Address.
247 Buffer - The destination buffer to store results.
248
249 Returns:
250
251 EFI_SUCCESS - The data was read from the device.
252 EFI_INVALID_PARAMETER - Width is invalid.
253 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
254
255 --*/
256 {
257 EFI_STATUS Status;
258 DEVICE_IO_PRIVATE_DATA *Private;
259
260 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
261
262 if (Width >= MMIO_COPY_UINT8) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 Status = Private->PciRootBridgeIo->Io.Read (
267 Private->PciRootBridgeIo,
268 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
269 Address,
270 Count,
271 Buffer
272 );
273
274 return Status;
275 }
276
277 EFI_STATUS
278 EFIAPI
DeviceIoIoWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)279 DeviceIoIoWrite (
280 IN EFI_DEVICE_IO_PROTOCOL *This,
281 IN EFI_IO_WIDTH Width,
282 IN UINT64 Address,
283 IN UINTN Count,
284 IN OUT VOID *Buffer
285 )
286 /*++
287
288 Routine Description:
289
290 Perform writing I/O space of device.
291
292 Arguments:
293
294 This - A pointer to EFI_DEVICE_IO protocol instance.
295 Width - Width of I/O operations.
296 Address - The base address of I/O operations.
297 Count - The number of I/O operations to perform.
298 Bytes moves is Width size * Count, starting at Address.
299 Buffer - The source buffer of data to be written.
300
301 Returns:
302
303 EFI_SUCCESS - The data was written to the device.
304 EFI_INVALID_PARAMETER - Width is invalid.
305 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
306
307 --*/
308 {
309 EFI_STATUS Status;
310 DEVICE_IO_PRIVATE_DATA *Private;
311
312 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
313
314 if (Width >= MMIO_COPY_UINT8) {
315 return EFI_INVALID_PARAMETER;
316 }
317
318 Status = Private->PciRootBridgeIo->Io.Write (
319 Private->PciRootBridgeIo,
320 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
321 Address,
322 Count,
323 Buffer
324 );
325
326 return Status;
327 }
328
329 EFI_STATUS
330 EFIAPI
DeviceIoPciRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)331 DeviceIoPciRead (
332 IN EFI_DEVICE_IO_PROTOCOL *This,
333 IN EFI_IO_WIDTH Width,
334 IN UINT64 Address,
335 IN UINTN Count,
336 IN OUT VOID *Buffer
337 )
338 /*++
339
340 Routine Description:
341
342 Perform reading PCI configuration space of device
343
344 Arguments:
345
346 This - A pointer to EFI_DEVICE_IO protocol instance.
347 Width - Width of I/O operations.
348 Address - The base address of I/O operations.
349 Count - The number of I/O operations to perform.
350 Bytes moves is Width size * Count, starting at Address.
351 Buffer - The destination buffer to store results.
352
353 Returns:
354
355 EFI_SUCCESS - The data was read from the device.
356 EFI_INVALID_PARAMETER - Width is invalid.
357 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
358
359 --*/
360 {
361 EFI_STATUS Status;
362 DEVICE_IO_PRIVATE_DATA *Private;
363
364 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
365
366 if ((UINT32)Width >= MMIO_COPY_UINT8) {
367 return EFI_INVALID_PARAMETER;
368 }
369
370 Status = Private->PciRootBridgeIo->Pci.Read (
371 Private->PciRootBridgeIo,
372 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
373 Address,
374 Count,
375 Buffer
376 );
377
378 return Status;
379 }
380
381 EFI_STATUS
382 EFIAPI
DeviceIoPciWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)383 DeviceIoPciWrite (
384 IN EFI_DEVICE_IO_PROTOCOL *This,
385 IN EFI_IO_WIDTH Width,
386 IN UINT64 Address,
387 IN UINTN Count,
388 IN OUT VOID *Buffer
389 )
390 /*++
391
392 Routine Description:
393
394 Perform writing PCI configuration space of device.
395
396 Arguments:
397
398 This - A pointer to EFI_DEVICE_IO protocol instance.
399 Width - Width of I/O operations.
400 Address - The base address of I/O operations.
401 Count - The number of I/O operations to perform.
402 Bytes moves is Width size * Count, starting at Address.
403 Buffer - The source buffer of data to be written.
404
405 Returns:
406
407 EFI_SUCCESS - The data was written to the device.
408 EFI_INVALID_PARAMETER - Width is invalid.
409 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
410
411 --*/
412 {
413 EFI_STATUS Status;
414 DEVICE_IO_PRIVATE_DATA *Private;
415
416 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
417
418 if ((UINT32)Width >= MMIO_COPY_UINT8) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 Status = Private->PciRootBridgeIo->Pci.Write (
423 Private->PciRootBridgeIo,
424 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
425 Address,
426 Count,
427 Buffer
428 );
429
430 return Status;
431 }
432
433 EFI_DEVICE_PATH_PROTOCOL *
AppendPciDevicePath(IN DEVICE_IO_PRIVATE_DATA * Private,IN UINT8 Bus,IN UINT8 Device,IN UINT8 Function,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN OUT UINT16 * BridgePrimaryBus,IN OUT UINT16 * BridgeSubordinateBus)434 AppendPciDevicePath (
435 IN DEVICE_IO_PRIVATE_DATA *Private,
436 IN UINT8 Bus,
437 IN UINT8 Device,
438 IN UINT8 Function,
439 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
440 IN OUT UINT16 *BridgePrimaryBus,
441 IN OUT UINT16 *BridgeSubordinateBus
442 )
443 /*++
444
445 Routine Description:
446
447 Append a PCI device path node to another device path.
448
449 Arguments:
450
451 Private - A pointer to DEVICE_IO_PRIVATE_DATA instance.
452 Bus - PCI bus number of the device.
453 Device - PCI device number of the device.
454 Function - PCI function number of the device.
455 DevicePath - Original device path which will be appended a PCI device path node.
456 BridgePrimaryBus - Primary bus number of the bridge.
457 BridgeSubordinateBus - Subordinate bus number of the bridge.
458
459 Returns:
460
461 Pointer to the appended PCI device path.
462
463 --*/
464 {
465 UINT16 ThisBus;
466 UINT8 ThisDevice;
467 UINT8 ThisFunc;
468 UINT64 Address;
469 PCI_TYPE01 PciBridge;
470 PCI_TYPE01 *PciPtr;
471 EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
472 PCI_DEVICE_PATH PciNode;
473
474 PciPtr = &PciBridge;
475 for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
476 for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
477 for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
478 Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
479 ZeroMem (PciPtr, sizeof (PCI_TYPE01));
480 Private->DeviceIo.Pci.Read (
481 &Private->DeviceIo,
482 IO_UINT32,
483 Address,
484 1,
485 &(PciPtr->Hdr.VendorId)
486 );
487 if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
488 break;
489 }
490 if (PciPtr->Hdr.VendorId == 0xffff) {
491 continue;
492 }
493
494 Private->DeviceIo.Pci.Read (
495 &Private->DeviceIo,
496 IO_UINT32,
497 Address,
498 sizeof (PCI_TYPE01) / sizeof (UINT32),
499 PciPtr
500 );
501 if (IS_PCI_BRIDGE (PciPtr)) {
502 if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
503
504 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
505 PciNode.Header.SubType = HW_PCI_DP;
506 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
507
508 PciNode.Device = ThisDevice;
509 PciNode.Function = ThisFunc;
510 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
511
512 *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
513 *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
514 return ReturnDevicePath;
515 }
516 }
517
518 if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
519 //
520 // Skip sub functions, this is not a multi function device
521 //
522 break;
523 }
524 }
525 }
526 }
527
528 ZeroMem (&PciNode, sizeof (PciNode));
529 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
530 PciNode.Header.SubType = HW_PCI_DP;
531 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
532 PciNode.Device = Device;
533 PciNode.Function = Function;
534
535 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
536
537 *BridgePrimaryBus = 0xffff;
538 *BridgeSubordinateBus = 0xffff;
539 return ReturnDevicePath;
540 }
541
542 EFI_STATUS
543 EFIAPI
DeviceIoPciDevicePath(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINT64 Address,IN OUT EFI_DEVICE_PATH_PROTOCOL ** PciDevicePath)544 DeviceIoPciDevicePath (
545 IN EFI_DEVICE_IO_PROTOCOL *This,
546 IN UINT64 Address,
547 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
548 )
549 /*++
550
551 Routine Description:
552
553 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
554
555 Arguments:
556
557 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
558 Address - The PCI configuration space address of the device whose Device Path
559 is going to be returned.
560 PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.
561 Memory for the Device Path is allocated from the pool.
562
563 Returns:
564
565 EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.
566 EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path.
567 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
568
569 --*/
570 {
571 DEVICE_IO_PRIVATE_DATA *Private;
572 UINT16 PrimaryBus;
573 UINT16 SubordinateBus;
574 UINT8 Bus;
575 UINT8 Device;
576 UINT8 Func;
577
578 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
579
580 Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
581 Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
582 Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
583
584 if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
585 return EFI_UNSUPPORTED;
586 }
587
588 *PciDevicePath = Private->DevicePath;
589 PrimaryBus = Private->PrimaryBus;
590 SubordinateBus = Private->SubordinateBus;
591 do {
592 *PciDevicePath = AppendPciDevicePath (
593 Private,
594 Bus,
595 Device,
596 Func,
597 *PciDevicePath,
598 &PrimaryBus,
599 &SubordinateBus
600 );
601 if (*PciDevicePath == NULL) {
602 return EFI_OUT_OF_RESOURCES;
603 }
604 } while (PrimaryBus != 0xffff);
605
606 return EFI_SUCCESS;
607 }
608
609 EFI_STATUS
610 EFIAPI
DeviceIoMap(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_OPERATION_TYPE Operation,IN EFI_PHYSICAL_ADDRESS * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)611 DeviceIoMap (
612 IN EFI_DEVICE_IO_PROTOCOL *This,
613 IN EFI_IO_OPERATION_TYPE Operation,
614 IN EFI_PHYSICAL_ADDRESS *HostAddress,
615 IN OUT UINTN *NumberOfBytes,
616 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
617 OUT VOID **Mapping
618 )
619 /*++
620
621 Routine Description:
622
623 Provides the device-specific addresses needed to access system memory.
624
625 Arguments:
626
627 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
628 Operation - Indicates if the bus master is going to read or write to system memory.
629 HostAddress - The system memory address to map to the device.
630 NumberOfBytes - On input the number of bytes to map. On output the number of bytes
631 that were mapped.
632 DeviceAddress - The resulting map address for the bus master device to use to access the
633 hosts HostAddress.
634 Mapping - A resulting value to pass to Unmap().
635
636 Returns:
637
638 EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
639 EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
640 EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
641 EFI_DEVICE_ERROR - The system hardware could not map the requested address.
642 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
643
644 --*/
645 {
646 EFI_STATUS Status;
647 DEVICE_IO_PRIVATE_DATA *Private;
648
649 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
650
651 if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
652 return EFI_INVALID_PARAMETER;
653 }
654
655 if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
656 return EFI_UNSUPPORTED;
657 }
658
659 Status = Private->PciRootBridgeIo->Map (
660 Private->PciRootBridgeIo,
661 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
662 (VOID *) (UINTN) (*HostAddress),
663 NumberOfBytes,
664 DeviceAddress,
665 Mapping
666 );
667
668 return Status;
669 }
670
671 EFI_STATUS
672 EFIAPI
DeviceIoUnmap(IN EFI_DEVICE_IO_PROTOCOL * This,IN VOID * Mapping)673 DeviceIoUnmap (
674 IN EFI_DEVICE_IO_PROTOCOL *This,
675 IN VOID *Mapping
676 )
677 /*++
678
679 Routine Description:
680
681 Completes the Map() operation and releases any corresponding resources.
682
683 Arguments:
684
685 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
686 Mapping - The mapping value returned from Map().
687
688 Returns:
689
690 EFI_SUCCESS - The range was unmapped.
691 EFI_DEVICE_ERROR - The data was not committed to the target system memory.
692
693 --*/
694 {
695 EFI_STATUS Status;
696 DEVICE_IO_PRIVATE_DATA *Private;
697
698 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
699
700 Status = Private->PciRootBridgeIo->Unmap (
701 Private->PciRootBridgeIo,
702 Mapping
703 );
704
705 return Status;
706 }
707
708 EFI_STATUS
709 EFIAPI
DeviceIoAllocateBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN OUT EFI_PHYSICAL_ADDRESS * PhysicalAddress)710 DeviceIoAllocateBuffer (
711 IN EFI_DEVICE_IO_PROTOCOL *This,
712 IN EFI_ALLOCATE_TYPE Type,
713 IN EFI_MEMORY_TYPE MemoryType,
714 IN UINTN Pages,
715 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
716 )
717 /*++
718
719 Routine Description:
720
721 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
722
723 Arguments:
724
725 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
726 Type - The type allocation to perform.
727 MemoryType - The type of memory to allocate, EfiBootServicesData or
728 EfiRuntimeServicesData.
729 Pages - The number of pages to allocate.
730 PhysicalAddress - A pointer to store the base address of the allocated range.
731
732 Returns:
733
734 EFI_SUCCESS - The requested memory pages were allocated.
735 EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
736 EFI_INVALID_PARAMETER - The requested memory type is invalid.
737 EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
738 this platform.
739
740 --*/
741 {
742 EFI_STATUS Status;
743 EFI_PHYSICAL_ADDRESS HostAddress;
744
745 HostAddress = *PhysicalAddress;
746
747 if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
748 return EFI_INVALID_PARAMETER;
749 }
750
751 if ((UINT32)Type >= MaxAllocateType) {
752 return EFI_INVALID_PARAMETER;
753 }
754
755 if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
756 return EFI_UNSUPPORTED;
757 }
758
759 if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
760 Type = AllocateMaxAddress;
761 HostAddress = MAX_COMMON_BUFFER;
762 }
763
764 Status = gBS->AllocatePages (
765 Type,
766 MemoryType,
767 Pages,
768 &HostAddress
769 );
770 if (EFI_ERROR (Status)) {
771 return Status;
772 }
773
774
775 *PhysicalAddress = HostAddress;
776
777 return EFI_SUCCESS;
778 }
779
780 EFI_STATUS
781 EFIAPI
DeviceIoFlush(IN EFI_DEVICE_IO_PROTOCOL * This)782 DeviceIoFlush (
783 IN EFI_DEVICE_IO_PROTOCOL *This
784 )
785 /*++
786
787 Routine Description:
788
789 Flushes any posted write data to the device.
790
791 Arguments:
792
793 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
794
795 Returns:
796
797 EFI_SUCCESS - The buffers were flushed.
798 EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
799
800 --*/
801 {
802 EFI_STATUS Status;
803 DEVICE_IO_PRIVATE_DATA *Private;
804
805 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
806
807 Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
808
809 return Status;
810 }
811
812 EFI_STATUS
813 EFIAPI
DeviceIoFreeBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINTN Pages,IN EFI_PHYSICAL_ADDRESS HostAddress)814 DeviceIoFreeBuffer (
815 IN EFI_DEVICE_IO_PROTOCOL *This,
816 IN UINTN Pages,
817 IN EFI_PHYSICAL_ADDRESS HostAddress
818 )
819 /*++
820
821 Routine Description:
822
823 Frees pages that were allocated with AllocateBuffer().
824
825 Arguments:
826
827 This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
828 Pages - The number of pages to free.
829 HostAddress - The base address of the range to free.
830
831 Returns:
832
833 EFI_SUCCESS - The requested memory pages were freed.
834 EFI_NOT_FOUND - The requested memory pages were not allocated with
835 AllocateBuffer().
836 EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
837
838 --*/
839 {
840 if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
841 return EFI_INVALID_PARAMETER;
842 }
843
844 return gBS->FreePages (HostAddress, Pages);
845 }
846