]> git.proxmox.com Git - mirror_edk2.git/blob - PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
36f83f62e00c926f7d916d7e06ee6ed5cd0944ba
[mirror_edk2.git] / PcAtChipsetPkg / PciHostBridgeDxe / PciRootBridgeIo.c
1 /** @file
2 PCI Root Bridge Io Protocol implementation
3
4 Copyright (c) 2008 - 2009, Intel Corporation<BR> All rights
5 reserved. This program and the accompanying materials are
6 licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PciHostBridge.h"
16
17 typedef struct {
18 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];
19 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
20 } RESOURCE_CONFIGURATION;
21
22 RESOURCE_CONFIGURATION Configuration = {
23 {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
24 {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
25 {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
26 {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
27 {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
28 {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
29 {0x79, 0}
30 };
31
32 //
33 // Protocol Member Function Prototypes
34 //
35
36 EFI_STATUS
37 EFIAPI
38 RootBridgeIoPollMem (
39 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
40 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
41 IN UINT64 Address,
42 IN UINT64 Mask,
43 IN UINT64 Value,
44 IN UINT64 Delay,
45 OUT UINT64 *Result
46 );
47
48 EFI_STATUS
49 EFIAPI
50 RootBridgeIoPollIo (
51 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
52 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
53 IN UINT64 Address,
54 IN UINT64 Mask,
55 IN UINT64 Value,
56 IN UINT64 Delay,
57 OUT UINT64 *Result
58 );
59
60 EFI_STATUS
61 EFIAPI
62 RootBridgeIoMemRead (
63 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
64 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
65 IN UINT64 Address,
66 IN UINTN Count,
67 IN OUT VOID *Buffer
68 );
69
70 EFI_STATUS
71 EFIAPI
72 RootBridgeIoMemWrite (
73 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
74 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
75 IN UINT64 Address,
76 IN UINTN Count,
77 IN OUT VOID *Buffer
78 );
79
80 EFI_STATUS
81 EFIAPI
82 RootBridgeIoIoRead (
83 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
84 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
85 IN UINT64 UserAddress,
86 IN UINTN Count,
87 IN OUT VOID *UserBuffer
88 );
89
90 EFI_STATUS
91 EFIAPI
92 RootBridgeIoIoWrite (
93 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
94 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
95 IN UINT64 UserAddress,
96 IN UINTN Count,
97 IN OUT VOID *UserBuffer
98 );
99
100 EFI_STATUS
101 EFIAPI
102 RootBridgeIoCopyMem (
103 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
105 IN UINT64 DestAddress,
106 IN UINT64 SrcAddress,
107 IN UINTN Count
108 );
109
110 EFI_STATUS
111 EFIAPI
112 RootBridgeIoPciRead (
113 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
114 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
115 IN UINT64 Address,
116 IN UINTN Count,
117 IN OUT VOID *Buffer
118 );
119
120 EFI_STATUS
121 EFIAPI
122 RootBridgeIoPciWrite (
123 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
124 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
125 IN UINT64 Address,
126 IN UINTN Count,
127 IN OUT VOID *Buffer
128 );
129
130 EFI_STATUS
131 EFIAPI
132 RootBridgeIoMap (
133 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
135 IN VOID *HostAddress,
136 IN OUT UINTN *NumberOfBytes,
137 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
138 OUT VOID **Mapping
139 );
140
141 EFI_STATUS
142 EFIAPI
143 RootBridgeIoUnmap (
144 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
145 IN VOID *Mapping
146 );
147
148 EFI_STATUS
149 EFIAPI
150 RootBridgeIoAllocateBuffer (
151 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
152 IN EFI_ALLOCATE_TYPE Type,
153 IN EFI_MEMORY_TYPE MemoryType,
154 IN UINTN Pages,
155 OUT VOID **HostAddress,
156 IN UINT64 Attributes
157 );
158
159 EFI_STATUS
160 EFIAPI
161 RootBridgeIoFreeBuffer (
162 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
163 IN UINTN Pages,
164 OUT VOID *HostAddress
165 );
166
167 EFI_STATUS
168 EFIAPI
169 RootBridgeIoFlush (
170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
171 );
172
173 EFI_STATUS
174 EFIAPI
175 RootBridgeIoGetAttributes (
176 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
177 OUT UINT64 *Supported,
178 OUT UINT64 *Attributes
179 );
180
181 EFI_STATUS
182 EFIAPI
183 RootBridgeIoSetAttributes (
184 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
185 IN UINT64 Attributes,
186 IN OUT UINT64 *ResourceBase,
187 IN OUT UINT64 *ResourceLength
188 );
189
190 EFI_STATUS
191 EFIAPI
192 RootBridgeIoConfiguration (
193 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
194 OUT VOID **Resources
195 );
196
197 //
198 // Sub Function Prototypes
199 //
200 EFI_STATUS
201 RootBridgeIoPciRW (
202 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
203 IN BOOLEAN Write,
204 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
205 IN UINT64 UserAddress,
206 IN UINTN Count,
207 IN OUT VOID *UserBuffer
208 );
209
210 //
211 // Memory Controller Pci Root Bridge Io Module Variables
212 //
213 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
214 EFI_CPU_IO2_PROTOCOL *mCpuIo;
215
216 EFI_STATUS
217 RootBridgeConstructor (
218 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
219 IN EFI_HANDLE HostBridgeHandle,
220 IN UINT64 Attri,
221 IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture
222 )
223 /*++
224
225 Routine Description:
226
227 Construct the Pci Root Bridge Io protocol
228
229 Arguments:
230
231 Protocol - protocol to initialize
232
233 Returns:
234
235 None
236
237 --*/
238 {
239 EFI_STATUS Status;
240 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
241 PCI_RESOURCE_TYPE Index;
242
243 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
244
245 //
246 // The host to pci bridge, the host memory and io addresses are
247 // direct mapped to pci addresses, so no need translate, set bases to 0.
248 //
249 PrivateData->MemBase = ResAppeture->MemBase;
250 PrivateData->IoBase = ResAppeture->IoBase;
251
252 //
253 // The host bridge only supports 32bit addressing for memory
254 // and standard IA32 16bit io
255 //
256 PrivateData->MemLimit = ResAppeture->MemLimit;
257 PrivateData->IoLimit = ResAppeture->IoLimit;
258
259 //
260 // Bus Appeture for this Root Bridge (Possible Range)
261 //
262 PrivateData->BusBase = ResAppeture->BusBase;
263 PrivateData->BusLimit = ResAppeture->BusLimit;
264
265 //
266 // Specific for this chipset
267 //
268 for (Index = TypeIo; Index < TypeMax; Index++) {
269 PrivateData->ResAllocNode[Index].Type = Index;
270 PrivateData->ResAllocNode[Index].Base = 0;
271 PrivateData->ResAllocNode[Index].Length = 0;
272 PrivateData->ResAllocNode[Index].Status = ResNone;
273 }
274
275
276 EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
277 PrivateData->PciAddress = 0xCF8;
278 PrivateData->PciData = 0xCFC;
279
280 PrivateData->RootBridgeAttrib = Attri;
281
282 PrivateData->Attributes = 0;
283 PrivateData->Supports = 0;
284
285 Protocol->ParentHandle = HostBridgeHandle;
286
287 Protocol->PollMem = RootBridgeIoPollMem;
288 Protocol->PollIo = RootBridgeIoPollIo;
289
290 Protocol->Mem.Read = RootBridgeIoMemRead;
291 Protocol->Mem.Write = RootBridgeIoMemWrite;
292
293 Protocol->Io.Read = RootBridgeIoIoRead;
294 Protocol->Io.Write = RootBridgeIoIoWrite;
295
296 Protocol->CopyMem = RootBridgeIoCopyMem;
297
298 Protocol->Pci.Read = RootBridgeIoPciRead;
299 Protocol->Pci.Write = RootBridgeIoPciWrite;
300
301 Protocol->Map = RootBridgeIoMap;
302 Protocol->Unmap = RootBridgeIoUnmap;
303
304 Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
305 Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
306
307 Protocol->Flush = RootBridgeIoFlush;
308
309 Protocol->GetAttributes = RootBridgeIoGetAttributes;
310 Protocol->SetAttributes = RootBridgeIoSetAttributes;
311
312 Protocol->Configuration = RootBridgeIoConfiguration;
313
314 Protocol->SegmentNumber = 0;
315
316 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);
317 ASSERT_EFI_ERROR (Status);
318
319 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
320 ASSERT_EFI_ERROR (Status);
321
322 return EFI_SUCCESS;
323 }
324
325 EFI_STATUS
326 EFIAPI
327 RootBridgeIoPollMem (
328 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
329 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
330 IN UINT64 Address,
331 IN UINT64 Mask,
332 IN UINT64 Value,
333 IN UINT64 Delay,
334 OUT UINT64 *Result
335 )
336 /*++
337
338 Routine Description:
339 Memory Poll
340
341 Arguments:
342
343 Returns:
344
345 --*/
346 {
347 EFI_STATUS Status;
348 UINT64 NumberOfTicks;
349 UINT32 Remainder;
350
351 if (Result == NULL) {
352 return EFI_INVALID_PARAMETER;
353 }
354
355 if (Width < 0 || Width > EfiPciWidthUint64) {
356 return EFI_INVALID_PARAMETER;
357 }
358
359 //
360 // No matter what, always do a single poll.
361 //
362 Status = This->Mem.Read (This, Width, Address, 1, Result);
363 if (EFI_ERROR (Status)) {
364 return Status;
365 }
366 if ((*Result & Mask) == Value) {
367 return EFI_SUCCESS;
368 }
369
370 if (Delay == 0) {
371 return EFI_SUCCESS;
372
373 } else {
374
375 //
376 // Determine the proper # of metronome ticks to wait for polling the
377 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
378 // The "+1" to account for the possibility of the first tick being short
379 // because we started in the middle of a tick.
380 //
381 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
382 // protocol definition is updated.
383 //
384 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
385 if (Remainder != 0) {
386 NumberOfTicks += 1;
387 }
388 NumberOfTicks += 1;
389
390 while (NumberOfTicks) {
391
392 mMetronome->WaitForTick (mMetronome, 1);
393
394 Status = This->Mem.Read (This, Width, Address, 1, Result);
395 if (EFI_ERROR (Status)) {
396 return Status;
397 }
398
399 if ((*Result & Mask) == Value) {
400 return EFI_SUCCESS;
401 }
402
403 NumberOfTicks -= 1;
404 }
405 }
406 return EFI_TIMEOUT;
407 }
408
409 EFI_STATUS
410 EFIAPI
411 RootBridgeIoPollIo (
412 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
413 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
414 IN UINT64 Address,
415 IN UINT64 Mask,
416 IN UINT64 Value,
417 IN UINT64 Delay,
418 OUT UINT64 *Result
419 )
420 /*++
421
422 Routine Description:
423 Io Poll
424
425 Arguments:
426
427 Returns:
428
429 --*/
430 {
431 EFI_STATUS Status;
432 UINT64 NumberOfTicks;
433 UINT32 Remainder;
434
435 //
436 // No matter what, always do a single poll.
437 //
438
439 if (Result == NULL) {
440 return EFI_INVALID_PARAMETER;
441 }
442
443 if (Width < 0 || Width > EfiPciWidthUint64) {
444 return EFI_INVALID_PARAMETER;
445 }
446
447 Status = This->Io.Read (This, Width, Address, 1, Result);
448 if (EFI_ERROR (Status)) {
449 return Status;
450 }
451 if ((*Result & Mask) == Value) {
452 return EFI_SUCCESS;
453 }
454
455 if (Delay == 0) {
456 return EFI_SUCCESS;
457
458 } else {
459
460 //
461 // Determine the proper # of metronome ticks to wait for polling the
462 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
463 // The "+1" to account for the possibility of the first tick being short
464 // because we started in the middle of a tick.
465 //
466 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
467 if (Remainder != 0) {
468 NumberOfTicks += 1;
469 }
470 NumberOfTicks += 1;
471
472 while (NumberOfTicks) {
473
474 mMetronome->WaitForTick (mMetronome, 1);
475
476 Status = This->Io.Read (This, Width, Address, 1, Result);
477 if (EFI_ERROR (Status)) {
478 return Status;
479 }
480
481 if ((*Result & Mask) == Value) {
482 return EFI_SUCCESS;
483 }
484
485 NumberOfTicks -= 1;
486 }
487 }
488 return EFI_TIMEOUT;
489 }
490
491 EFI_STATUS
492 EFIAPI
493 RootBridgeIoMemRead (
494 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
495 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
496 IN UINT64 Address,
497 IN UINTN Count,
498 IN OUT VOID *Buffer
499 )
500 /*++
501
502 Routine Description:
503 Memory read
504
505 Arguments:
506
507 Returns:
508
509 --*/
510 {
511 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
512 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
513 UINTN OldCount;
514
515 if (Buffer == NULL) {
516 return EFI_INVALID_PARAMETER;
517 }
518
519 if (Width < 0 || Width >= EfiPciWidthMaximum) {
520 return EFI_INVALID_PARAMETER;
521 }
522
523 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
524
525 //
526 // Check memory access limit
527 //
528 if (Address < PrivateData->MemBase) {
529 return EFI_INVALID_PARAMETER;
530 }
531
532 OldWidth = Width;
533 OldCount = Count;
534
535 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
536 Count = 1;
537 }
538
539 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
540
541 if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) {
542 return EFI_INVALID_PARAMETER;
543 }
544
545 return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
546 Address, OldCount, Buffer);
547 }
548
549 EFI_STATUS
550 EFIAPI
551 RootBridgeIoMemWrite (
552 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
553 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
554 IN UINT64 Address,
555 IN UINTN Count,
556 IN OUT VOID *Buffer
557 )
558 /*++
559
560 Routine Description:
561 Memory write
562
563 Arguments:
564
565 Returns:
566
567 --*/
568 {
569 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
570 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
571 UINTN OldCount;
572
573 if (Buffer == NULL) {
574 return EFI_INVALID_PARAMETER;
575 }
576
577 if (Width < 0 || Width >= EfiPciWidthMaximum) {
578 return EFI_INVALID_PARAMETER;
579 }
580
581 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
582
583 //
584 // Check memory access limit
585 //
586 if (Address < PrivateData->MemBase) {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 OldWidth = Width;
591 OldCount = Count;
592 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
593 Count = 1;
594 }
595
596 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
597
598 if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) {
599 return EFI_INVALID_PARAMETER;
600 }
601
602 return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
603 Address, OldCount, Buffer);
604 }
605
606 EFI_STATUS
607 EFIAPI
608 RootBridgeIoIoRead (
609 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
610 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
611 IN UINT64 Address,
612 IN UINTN Count,
613 IN OUT VOID *Buffer
614 )
615 /*++
616
617 Routine Description:
618 Io read
619
620 Arguments:
621
622 Returns:
623
624 --*/
625 {
626
627
628 UINTN AlignMask;
629 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
630 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
631 UINTN OldCount;
632
633 if (Buffer == NULL) {
634 return EFI_INVALID_PARAMETER;
635 }
636
637 if (Width < 0 || Width >= EfiPciWidthMaximum) {
638 return EFI_INVALID_PARAMETER;
639 }
640
641 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
642
643 //AlignMask = (1 << Width) - 1;
644 AlignMask = (1 << (Width & 0x03)) - 1;
645
646 //
647 // check Io access limit
648 //
649 if (Address < PrivateData->IoBase) {
650 return EFI_INVALID_PARAMETER;
651 }
652
653 OldWidth = Width;
654 OldCount = Count;
655 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
656 Count = 1;
657 }
658
659 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
660
661 if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) {
662 return EFI_INVALID_PARAMETER;
663 }
664
665 if (Address & AlignMask) {
666 return EFI_INVALID_PARAMETER;
667 }
668
669 return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
670 Address, OldCount, Buffer);
671
672 }
673
674 EFI_STATUS
675 EFIAPI
676 RootBridgeIoIoWrite (
677 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
678 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
679 IN UINT64 Address,
680 IN UINTN Count,
681 IN OUT VOID *Buffer
682 )
683 /*++
684
685 Routine Description:
686 Io write
687
688 Arguments:
689
690 Returns:
691
692 --*/
693 {
694 UINTN AlignMask;
695 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
696 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
697 UINTN OldCount;
698
699 if (Buffer == NULL) {
700 return EFI_INVALID_PARAMETER;
701 }
702
703 if (Width < 0 || Width >= EfiPciWidthMaximum) {
704 return EFI_INVALID_PARAMETER;
705 }
706
707 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
708
709 //AlignMask = (1 << Width) - 1;
710 AlignMask = (1 << (Width & 0x03)) - 1;
711
712 //
713 // Check Io access limit
714 //
715 if (Address < PrivateData->IoBase) {
716 return EFI_INVALID_PARAMETER;
717 }
718
719 OldWidth = Width;
720 OldCount = Count;
721 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
722 Count = 1;
723 }
724
725 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
726
727 if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) {
728 return EFI_INVALID_PARAMETER;
729 }
730
731 if (Address & AlignMask) {
732 return EFI_INVALID_PARAMETER;
733 }
734
735 return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
736 Address, OldCount, Buffer);
737
738 }
739
740 EFI_STATUS
741 EFIAPI
742 RootBridgeIoCopyMem (
743 IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
744 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
745 IN UINT64 DestAddress,
746 IN UINT64 SrcAddress,
747 IN UINTN Count
748 )
749 /*++
750
751 Routine Description:
752 Memory copy
753
754 Arguments:
755
756 Returns:
757
758 --*/
759 {
760 EFI_STATUS Status;
761 BOOLEAN Direction;
762 UINTN Stride;
763 UINTN Index;
764 UINT64 Result;
765
766 if (Width < 0 || Width > EfiPciWidthUint64) {
767 return EFI_INVALID_PARAMETER;
768 }
769
770 if (DestAddress == SrcAddress) {
771 return EFI_SUCCESS;
772 }
773
774 Stride = (UINTN)(1 << Width);
775
776 Direction = TRUE;
777 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
778 Direction = FALSE;
779 SrcAddress = SrcAddress + (Count-1) * Stride;
780 DestAddress = DestAddress + (Count-1) * Stride;
781 }
782
783 for (Index = 0;Index < Count;Index++) {
784 Status = RootBridgeIoMemRead (
785 This,
786 Width,
787 SrcAddress,
788 1,
789 &Result
790 );
791 if (EFI_ERROR (Status)) {
792 return Status;
793 }
794 Status = RootBridgeIoMemWrite (
795 This,
796 Width,
797 DestAddress,
798 1,
799 &Result
800 );
801 if (EFI_ERROR (Status)) {
802 return Status;
803 }
804 if (Direction) {
805 SrcAddress += Stride;
806 DestAddress += Stride;
807 } else {
808 SrcAddress -= Stride;
809 DestAddress -= Stride;
810 }
811 }
812 return EFI_SUCCESS;
813 }
814
815 EFI_STATUS
816 EFIAPI
817 RootBridgeIoPciRead (
818 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
819 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
820 IN UINT64 Address,
821 IN UINTN Count,
822 IN OUT VOID *Buffer
823 )
824 /*++
825
826 Routine Description:
827 Pci read
828
829 Arguments:
830
831 Returns:
832
833 --*/
834 {
835
836 if (Buffer == NULL) {
837 return EFI_INVALID_PARAMETER;
838 }
839
840 if (Width < 0 || Width >= EfiPciWidthMaximum) {
841 return EFI_INVALID_PARAMETER;
842 }
843 //
844 // Read Pci configuration space
845 //
846 return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
847 }
848
849 EFI_STATUS
850 EFIAPI
851 RootBridgeIoPciWrite (
852 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
853 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
854 IN UINT64 Address,
855 IN UINTN Count,
856 IN OUT VOID *Buffer
857 )
858 /*++
859
860 Routine Description:
861 Pci write
862
863 Arguments:
864
865 Returns:
866
867 --*/
868 {
869
870 if (Buffer == NULL) {
871 return EFI_INVALID_PARAMETER;
872 }
873
874 if (Width < 0 || Width >= EfiPciWidthMaximum) {
875 return EFI_INVALID_PARAMETER;
876 }
877 //
878 // Write Pci configuration space
879 //
880 return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
881 }
882
883 EFI_STATUS
884 EFIAPI
885 RootBridgeIoMap (
886 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
887 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
888 IN VOID *HostAddress,
889 IN OUT UINTN *NumberOfBytes,
890 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
891 OUT VOID **Mapping
892 )
893
894 {
895 EFI_STATUS Status;
896 EFI_PHYSICAL_ADDRESS PhysicalAddress;
897 MAP_INFO *MapInfo;
898
899 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
900 return EFI_INVALID_PARAMETER;
901 }
902
903 //
904 // Initialize the return values to their defaults
905 //
906 *Mapping = NULL;
907
908 //
909 // Make sure that Operation is valid
910 //
911 if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
912 return EFI_INVALID_PARAMETER;
913 }
914
915 //
916 // Most PCAT like chipsets can not handle performing DMA above 4GB.
917 // If any part of the DMA transfer being mapped is above 4GB, then
918 // map the DMA transfer to a buffer below 4GB.
919 //
920 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
921 if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
922
923 //
924 // Common Buffer operations can not be remapped. If the common buffer
925 // if above 4GB, then it is not possible to generate a mapping, so return
926 // an error.
927 //
928 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
929 return EFI_UNSUPPORTED;
930 }
931
932 //
933 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
934 // called later.
935 //
936 Status = gBS->AllocatePool (
937 EfiBootServicesData,
938 sizeof(MAP_INFO),
939 (VOID **)&MapInfo
940 );
941 if (EFI_ERROR (Status)) {
942 *NumberOfBytes = 0;
943 return Status;
944 }
945
946 //
947 // Return a pointer to the MAP_INFO structure in Mapping
948 //
949 *Mapping = MapInfo;
950
951 //
952 // Initialize the MAP_INFO structure
953 //
954 MapInfo->Operation = Operation;
955 MapInfo->NumberOfBytes = *NumberOfBytes;
956 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
957 MapInfo->HostAddress = PhysicalAddress;
958 MapInfo->MappedHostAddress = 0x00000000ffffffff;
959
960 //
961 // Allocate a buffer below 4GB to map the transfer to.
962 //
963 Status = gBS->AllocatePages (
964 AllocateMaxAddress,
965 EfiBootServicesData,
966 MapInfo->NumberOfPages,
967 &MapInfo->MappedHostAddress
968 );
969 if (EFI_ERROR (Status)) {
970 gBS->FreePool (MapInfo);
971 *NumberOfBytes = 0;
972 return Status;
973 }
974
975 //
976 // If this is a read operation from the Bus Master's point of view,
977 // then copy the contents of the real buffer into the mapped buffer
978 // so the Bus Master can read the contents of the real buffer.
979 //
980 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
981 CopyMem (
982 (VOID *)(UINTN)MapInfo->MappedHostAddress,
983 (VOID *)(UINTN)MapInfo->HostAddress,
984 MapInfo->NumberOfBytes
985 );
986 }
987
988 //
989 // The DeviceAddress is the address of the maped buffer below 4GB
990 //
991 *DeviceAddress = MapInfo->MappedHostAddress;
992 } else {
993 //
994 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
995 //
996 *DeviceAddress = PhysicalAddress;
997 }
998
999 return EFI_SUCCESS;
1000 }
1001
1002 EFI_STATUS
1003 EFIAPI
1004 RootBridgeIoUnmap (
1005 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1006 IN VOID *Mapping
1007 )
1008
1009 {
1010 MAP_INFO *MapInfo;
1011
1012 //
1013 // See if the Map() operation associated with this Unmap() required a mapping buffer.
1014 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1015 //
1016 if (Mapping != NULL) {
1017 //
1018 // Get the MAP_INFO structure from Mapping
1019 //
1020 MapInfo = (MAP_INFO *)Mapping;
1021
1022 //
1023 // If this is a write operation from the Bus Master's point of view,
1024 // then copy the contents of the mapped buffer into the real buffer
1025 // so the processor can read the contents of the real buffer.
1026 //
1027 if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
1028 CopyMem (
1029 (VOID *)(UINTN)MapInfo->HostAddress,
1030 (VOID *)(UINTN)MapInfo->MappedHostAddress,
1031 MapInfo->NumberOfBytes
1032 );
1033 }
1034
1035 //
1036 // Free the mapped buffer and the MAP_INFO structure.
1037 //
1038 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
1039 gBS->FreePool (Mapping);
1040 }
1041 return EFI_SUCCESS;
1042 }
1043
1044 EFI_STATUS
1045 EFIAPI
1046 RootBridgeIoAllocateBuffer (
1047 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1048 IN EFI_ALLOCATE_TYPE Type,
1049 IN EFI_MEMORY_TYPE MemoryType,
1050 IN UINTN Pages,
1051 OUT VOID **HostAddress,
1052 IN UINT64 Attributes
1053 )
1054
1055 {
1056 EFI_STATUS Status;
1057 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1058
1059 //
1060 // Validate Attributes
1061 //
1062 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
1063 return EFI_UNSUPPORTED;
1064 }
1065
1066 //
1067 // Check for invalid inputs
1068 //
1069 if (HostAddress == NULL) {
1070 return EFI_INVALID_PARAMETER;
1071 }
1072
1073 //
1074 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1075 //
1076 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1077 return EFI_INVALID_PARAMETER;
1078 }
1079
1080 //
1081 // Limit allocations to memory below 4GB
1082 //
1083 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
1084
1085 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
1086 if (EFI_ERROR (Status)) {
1087 return Status;
1088 }
1089
1090 *HostAddress = (VOID *)(UINTN)PhysicalAddress;
1091
1092 return EFI_SUCCESS;
1093 }
1094
1095 EFI_STATUS
1096 EFIAPI
1097 RootBridgeIoFreeBuffer (
1098 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1099 IN UINTN Pages,
1100 OUT VOID *HostAddress
1101 )
1102
1103 {
1104 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
1105 }
1106
1107 EFI_STATUS
1108 EFIAPI
1109 RootBridgeIoFlush (
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
1111 )
1112 /*++
1113
1114 Routine Description:
1115
1116 Arguments:
1117
1118 Returns:
1119
1120 --*/
1121 {
1122 //
1123 // not supported yet
1124 //
1125 return EFI_SUCCESS;
1126 }
1127
1128 EFI_STATUS
1129 EFIAPI
1130 RootBridgeIoGetAttributes (
1131 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1132 OUT UINT64 *Supported,
1133 OUT UINT64 *Attributes
1134 )
1135 /*++
1136
1137 Routine Description:
1138
1139 Arguments:
1140
1141 Returns:
1142
1143 --*/
1144 {
1145 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1146
1147 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
1148
1149 if (Attributes == NULL && Supported == NULL) {
1150 return EFI_INVALID_PARAMETER;
1151 }
1152
1153 //
1154 // Set the return value for Supported and Attributes
1155 //
1156 if (Supported) {
1157 *Supported = PrivateData->Supports;
1158 }
1159
1160 if (Attributes) {
1161 *Attributes = PrivateData->Attributes;
1162 }
1163
1164 return EFI_SUCCESS;
1165 }
1166
1167 EFI_STATUS
1168 EFIAPI
1169 RootBridgeIoSetAttributes (
1170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1171 IN UINT64 Attributes,
1172 IN OUT UINT64 *ResourceBase,
1173 IN OUT UINT64 *ResourceLength
1174 )
1175 /*++
1176
1177 Routine Description:
1178
1179 Arguments:
1180
1181 Returns:
1182
1183 --*/
1184 {
1185 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1186
1187 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
1188
1189 if (Attributes) {
1190 if ((Attributes & (~(PrivateData->Supports))) != 0) {
1191 return EFI_UNSUPPORTED;
1192 }
1193 }
1194
1195 //
1196 // This is a generic driver for a PC-AT class system. It does not have any
1197 // chipset specific knowlegde, so none of the attributes can be set or
1198 // cleared. Any attempt to set attribute that are already set will succeed,
1199 // and any attempt to set an attribute that is not supported will fail.
1200 //
1201 if (Attributes & (~PrivateData->Attributes)) {
1202 return EFI_UNSUPPORTED;
1203 }
1204
1205 return EFI_SUCCESS;
1206 }
1207
1208 EFI_STATUS
1209 EFIAPI
1210 RootBridgeIoConfiguration (
1211 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1212 OUT VOID **Resources
1213 )
1214 /*++
1215
1216 Routine Description:
1217
1218 Arguments:
1219
1220 Returns:
1221
1222 --*/
1223 {
1224 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1225 UINTN Index;
1226
1227 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1228
1229 for (Index = 0; Index < TypeMax; Index++) {
1230 if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
1231 Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
1232 Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
1233 Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
1234 }
1235 }
1236
1237 *Resources = &Configuration;
1238 return EFI_SUCCESS;
1239 }
1240
1241 //
1242 // Internal function
1243 //
1244 EFI_STATUS
1245 RootBridgeIoPciRW (
1246 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1247 IN BOOLEAN Write,
1248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
1249 IN UINT64 UserAddress,
1250 IN UINTN Count,
1251 IN OUT VOID *UserBuffer
1252 )
1253 {
1254 PCI_CONFIG_ACCESS_CF8 Pci;
1255 PCI_CONFIG_ACCESS_CF8 PciAligned;
1256 UINT32 InStride;
1257 UINT32 OutStride;
1258 UINTN PciData;
1259 UINTN PciDataStride;
1260 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1261 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
1262
1263 if (Width < 0 || Width >= EfiPciWidthMaximum) {
1264 return EFI_INVALID_PARAMETER;
1265 }
1266
1267 if ((Width & 0x03) >= EfiPciWidthUint64) {
1268 return EFI_INVALID_PARAMETER;
1269 }
1270
1271 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
1272
1273 InStride = 1 << (Width & 0x03);
1274 OutStride = InStride;
1275 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
1276 InStride = 0;
1277 }
1278
1279 if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
1280 OutStride = 0;
1281 }
1282
1283 CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
1284
1285 if (PciAddress.ExtendedRegister > 0xFF) {
1286 return EFI_UNSUPPORTED;
1287 }
1288
1289 if (PciAddress.ExtendedRegister != 0) {
1290 Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
1291 } else {
1292 Pci.Bits.Reg = PciAddress.Register;
1293 }
1294
1295 Pci.Bits.Func = PciAddress.Function;
1296 Pci.Bits.Dev = PciAddress.Device;
1297 Pci.Bits.Bus = PciAddress.Bus;
1298 Pci.Bits.Reserved = 0;
1299 Pci.Bits.Enable = 1;
1300
1301 //
1302 // PCI Config access are all 32-bit alligned, but by accessing the
1303 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
1304 // are possible on PCI.
1305 //
1306 // To read a byte of PCI config space you load 0xcf8 and
1307 // read 0xcfc, 0xcfd, 0xcfe, 0xcff
1308 //
1309 PciDataStride = Pci.Bits.Reg & 0x03;
1310
1311 while (Count) {
1312 CopyMem (&PciAligned, &Pci, sizeof (PciAligned));
1313 PciAligned.Bits.Reg &= 0xfc;
1314 PciData = (UINTN)PrivateData->PciData + PciDataStride;
1315 EfiAcquireLock(&PrivateData->PciLock);
1316 This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
1317 if (Write) {
1318 This->Io.Write (This, Width, PciData, 1, UserBuffer);
1319 } else {
1320 This->Io.Read (This, Width, PciData, 1, UserBuffer);
1321 }
1322 EfiReleaseLock(&PrivateData->PciLock);
1323 UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
1324 PciDataStride = (PciDataStride + InStride) % 4;
1325 Pci.Bits.Reg += InStride;
1326 Count -= 1;
1327 }
1328
1329 return EFI_SUCCESS;
1330 }