1 
2 #include <stdint.h>
3 
4 #include <sys/kassert.h>
5 #include <sys/pci.h>
6 
7 #include <machine/amd64.h>
8 #include <machine/amd64op.h>
9 
10 #define PCI_PORT_ADDR		0xCF8
11 #define PCI_PORT_DATABASE	0xCFC
12 
13 static inline uint32_t
PCIGetAddr(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg)14 PCIGetAddr(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
15 {
16     ASSERT(bus < 256 && slot < 64 && func < 8 && reg < 256);
17     return (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & 0x00fc);
18 }
19 
20 uint8_t
PCICfgRead8(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg)21 PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
22 {
23     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
24     uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
25 
26     outl(PCI_PORT_ADDR, addr);
27     return inb(port);
28 }
29 
30 uint16_t
PCICfgRead16(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg)31 PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
32 {
33     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
34     uint16_t port = PCI_PORT_DATABASE + (reg & 0x2);
35 
36     ASSERT((reg & 0x1) == 0);
37 
38     outl(PCI_PORT_ADDR, addr);
39     return inw(port);
40 }
41 
42 uint32_t
PCICfgRead32(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg)43 PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
44 {
45     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
46     uint16_t port = PCI_PORT_DATABASE;
47 
48     ASSERT((reg & 0x3) == 0);
49 
50     outl(PCI_PORT_ADDR, addr);
51     return inl(port);
52 }
53 
54 void
PCICfgWrite8(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg,uint8_t data)55 PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
56 	      uint8_t data)
57 {
58     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
59     uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
60 
61     outl(PCI_PORT_ADDR, addr);
62     outb(port, data);
63 }
64 
65 void
PCICfgWrite16(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg,uint16_t data)66 PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
67 	       uint16_t data)
68 {
69     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
70     uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
71 
72     outl(PCI_PORT_ADDR, addr);
73     outw(port, data);
74 }
75 
76 void
PCICfgWrite32(uint32_t bus,uint32_t slot,uint32_t func,uint32_t reg,uint32_t data)77 PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
78 	       uint32_t data)
79 {
80     uint32_t addr = PCIGetAddr(bus, slot, func, reg);
81     uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
82 
83     outl(PCI_PORT_ADDR, addr);
84     outl(port, data);
85 }
86 
87