1*9ef1f84bSDavid du Colombier #include "u.h"
2*9ef1f84bSDavid du Colombier #include "../port/lib.h"
3*9ef1f84bSDavid du Colombier #include "mem.h"
4*9ef1f84bSDavid du Colombier #include "dat.h"
5*9ef1f84bSDavid du Colombier #include "fns.h"
6*9ef1f84bSDavid du Colombier
7*9ef1f84bSDavid du Colombier #include "io.h"
8*9ef1f84bSDavid du Colombier
9*9ef1f84bSDavid du Colombier static void
htcapabilities(Pcidev * pci,int cp)10*9ef1f84bSDavid du Colombier htcapabilities(Pcidev* pci, int cp)
11*9ef1f84bSDavid du Colombier {
12*9ef1f84bSDavid du Colombier u64int idr;
13*9ef1f84bSDavid du Colombier u32int command, r;
14*9ef1f84bSDavid du Colombier
15*9ef1f84bSDavid du Colombier /*
16*9ef1f84bSDavid du Colombier * Top 5 bits of command give type:
17*9ef1f84bSDavid du Colombier * 000xx slave or primary interface
18*9ef1f84bSDavid du Colombier * 001xx host or secondary interface
19*9ef1f84bSDavid du Colombier * 10000 interrupt discovery and configuration
20*9ef1f84bSDavid du Colombier * Other values don't concern this interface.
21*9ef1f84bSDavid du Colombier */
22*9ef1f84bSDavid du Colombier r = pcicfgr32(pci, cp);
23*9ef1f84bSDavid du Colombier command = (r>>16) & 0xFFFF;
24*9ef1f84bSDavid du Colombier if((command & 0xE000) == 0x0000){
25*9ef1f84bSDavid du Colombier DBG("HT: slave or primary interface\n");
26*9ef1f84bSDavid du Colombier }
27*9ef1f84bSDavid du Colombier else if((command & 0xE000) == 0x2000){
28*9ef1f84bSDavid du Colombier DBG("HT: host or secondary interface\n");
29*9ef1f84bSDavid du Colombier }
30*9ef1f84bSDavid du Colombier else if((command & 0xF800) == 0x8000){
31*9ef1f84bSDavid du Colombier /*
32*9ef1f84bSDavid du Colombier * The Interrupt and Discovery block uses
33*9ef1f84bSDavid du Colombier * an index and data scheme to access the
34*9ef1f84bSDavid du Colombier * registers. Index is a byte at +2, data is
35*9ef1f84bSDavid du Colombier * 32 bits at +4.
36*9ef1f84bSDavid du Colombier * The only interesting information is the 64-bit
37*9ef1f84bSDavid du Colombier * Interrupt Definition Register at offset 0x10.
38*9ef1f84bSDavid du Colombier */
39*9ef1f84bSDavid du Colombier pcicfgw8(pci, cp+0x02, 0x11);
40*9ef1f84bSDavid du Colombier idr = pcicfgr32(pci, cp+0x04);
41*9ef1f84bSDavid du Colombier idr <<= 32;
42*9ef1f84bSDavid du Colombier pcicfgw8(pci, cp+0x02, 0x10);
43*9ef1f84bSDavid du Colombier idr |= (u32int)pcicfgr32(pci, cp+0x04);
44*9ef1f84bSDavid du Colombier DBG("HT: Interrupt and discovery block: idr %#16.16llux\n", idr);
45*9ef1f84bSDavid du Colombier }
46*9ef1f84bSDavid du Colombier else{
47*9ef1f84bSDavid du Colombier DBG("HT: capability code %#ux\n", command>>11);
48*9ef1f84bSDavid du Colombier }
49*9ef1f84bSDavid du Colombier }
50*9ef1f84bSDavid du Colombier
51*9ef1f84bSDavid du Colombier void
htlink(void)52*9ef1f84bSDavid du Colombier htlink(void)
53*9ef1f84bSDavid du Colombier {
54*9ef1f84bSDavid du Colombier int cp;
55*9ef1f84bSDavid du Colombier char *p;
56*9ef1f84bSDavid du Colombier Pcidev *pci;
57*9ef1f84bSDavid du Colombier u32int r, *rp;
58*9ef1f84bSDavid du Colombier
59*9ef1f84bSDavid du Colombier pci = nil;
60*9ef1f84bSDavid du Colombier while(pci = pcimatch(pci, 0, 0)){
61*9ef1f84bSDavid du Colombier /*
62*9ef1f84bSDavid du Colombier * AMD-8111 Hypertransport I/O Hub
63*9ef1f84bSDavid du Colombier */
64*9ef1f84bSDavid du Colombier if(pci->vid == 0x1022 && pci->did == 0x1100){
65*9ef1f84bSDavid du Colombier DBG("HT: AMD-8111: tc %#8.8ux ic %#8.8ux\n",
66*9ef1f84bSDavid du Colombier pcicfgr32(pci, 0x68), pcicfgr32(pci, 0x6C));
67*9ef1f84bSDavid du Colombier }
68*9ef1f84bSDavid du Colombier
69*9ef1f84bSDavid du Colombier /*
70*9ef1f84bSDavid du Colombier * AMD-8111 PCI Bridge
71*9ef1f84bSDavid du Colombier */
72*9ef1f84bSDavid du Colombier if(pci->vid == 0x1022 && pci->did == 0x7460){
73*9ef1f84bSDavid du Colombier pcicfgw32(pci, 0xF0, 1);
74*9ef1f84bSDavid du Colombier DBG("HT: AMD-8111: 0xF4: %#8.8ux\n",
75*9ef1f84bSDavid du Colombier pcicfgr32(pci, 0xF4));
76*9ef1f84bSDavid du Colombier pcicfgw32(pci, 0xF0, 0x10);
77*9ef1f84bSDavid du Colombier DBG("HT: AMD-8111: 0x10: %#8.8ux\n",
78*9ef1f84bSDavid du Colombier pcicfgr32(pci, 0xF4));
79*9ef1f84bSDavid du Colombier pcicfgw32(pci, 0xF0, 0x11);
80*9ef1f84bSDavid du Colombier DBG("HT: AMD-8111: 0x11: %#8.8ux\n",
81*9ef1f84bSDavid du Colombier pcicfgr32(pci, 0xF4));
82*9ef1f84bSDavid du Colombier }
83*9ef1f84bSDavid du Colombier
84*9ef1f84bSDavid du Colombier /*
85*9ef1f84bSDavid du Colombier * AMD-8111 LPC Bridge
86*9ef1f84bSDavid du Colombier */
87*9ef1f84bSDavid du Colombier if(pci->vid == 0x1022 && pci->did == 0x7468){
88*9ef1f84bSDavid du Colombier r = pcicfgr32(pci, 0xA0);
89*9ef1f84bSDavid du Colombier DBG("HT: HPET @ %#ux\n", r);
90*9ef1f84bSDavid du Colombier if((rp = vmap(r & ~0x0F, 0x200)) != nil){
91*9ef1f84bSDavid du Colombier DBG("HT: HPET00: %#8.8ux%8.8ux\n",
92*9ef1f84bSDavid du Colombier rp[4/4], rp[0/4]);
93*9ef1f84bSDavid du Colombier DBG("HT: HPET10: %#8.8ux%8.8ux\n",
94*9ef1f84bSDavid du Colombier rp[0x10/4], rp[0x10/4]);
95*9ef1f84bSDavid du Colombier DBG("HT: HPET20: %#8.8ux%8.8ux\n",
96*9ef1f84bSDavid du Colombier rp[0x24/4], rp[0x20/4]);
97*9ef1f84bSDavid du Colombier DBG("HT: HPETF0: %#8.8ux%8.8ux\n",
98*9ef1f84bSDavid du Colombier rp[0xF4/4], rp[0xF0/4]);
99*9ef1f84bSDavid du Colombier DBG("HT: HPET100: %#8.8ux%8.8ux\n",
100*9ef1f84bSDavid du Colombier rp[0x104/4], rp[0x100/4]);
101*9ef1f84bSDavid du Colombier DBG("HT: HPET120: %#8.8ux%8.8ux\n",
102*9ef1f84bSDavid du Colombier rp[0x124/4], rp[0x120/4]);
103*9ef1f84bSDavid du Colombier DBG("HT: HPET140: %#8.8ux%8.8ux\n",
104*9ef1f84bSDavid du Colombier rp[0x144/4], rp[0x140/4]);
105*9ef1f84bSDavid du Colombier vunmap(rp, 0x200);
106*9ef1f84bSDavid du Colombier }
107*9ef1f84bSDavid du Colombier }
108*9ef1f84bSDavid du Colombier
109*9ef1f84bSDavid du Colombier /*
110*9ef1f84bSDavid du Colombier * Check if there are extended capabilities implemented,
111*9ef1f84bSDavid du Colombier * (bit 4 in the status register).
112*9ef1f84bSDavid du Colombier * Find the capabilities pointer based on PCI header type.
113*9ef1f84bSDavid du Colombier *
114*9ef1f84bSDavid du Colombier * Make this more general (e.g. pcigetcap(pcidev, id, cp))
115*9ef1f84bSDavid du Colombier * and merge back into PCI code.
116*9ef1f84bSDavid du Colombier */
117*9ef1f84bSDavid du Colombier if(!(pcicfgr16(pci, PciPSR) & 0x0010))
118*9ef1f84bSDavid du Colombier continue;
119*9ef1f84bSDavid du Colombier
120*9ef1f84bSDavid du Colombier switch(pcicfgr8(pci, PciHDT)){
121*9ef1f84bSDavid du Colombier default:
122*9ef1f84bSDavid du Colombier continue;
123*9ef1f84bSDavid du Colombier case 0: /* all other */
124*9ef1f84bSDavid du Colombier case 1: /* PCI to PCI bridge */
125*9ef1f84bSDavid du Colombier cp = PciCP;
126*9ef1f84bSDavid du Colombier break;
127*9ef1f84bSDavid du Colombier }
128*9ef1f84bSDavid du Colombier
129*9ef1f84bSDavid du Colombier for(cp = pcicfgr8(pci, cp); cp != 0; cp = pcicfgr8(pci, cp+1)){
130*9ef1f84bSDavid du Colombier /*
131*9ef1f84bSDavid du Colombier * Check for validity.
132*9ef1f84bSDavid du Colombier * Can't be in standard header and must be double
133*9ef1f84bSDavid du Colombier * word aligned.
134*9ef1f84bSDavid du Colombier */
135*9ef1f84bSDavid du Colombier if(cp < 0x40 || (cp & ~0xFC))
136*9ef1f84bSDavid du Colombier break;
137*9ef1f84bSDavid du Colombier r = pcicfgr32(pci, cp);
138*9ef1f84bSDavid du Colombier switch(r & 0xFF){
139*9ef1f84bSDavid du Colombier default:
140*9ef1f84bSDavid du Colombier DBG("HT: %#4.4ux/%#4.4ux: unknown ID %d\n",
141*9ef1f84bSDavid du Colombier pci->vid, pci->did, r & 0xFF);
142*9ef1f84bSDavid du Colombier continue;
143*9ef1f84bSDavid du Colombier case 0x01:
144*9ef1f84bSDavid du Colombier p = "PMI";
145*9ef1f84bSDavid du Colombier break;
146*9ef1f84bSDavid du Colombier case 0x02:
147*9ef1f84bSDavid du Colombier p = "AGP";
148*9ef1f84bSDavid du Colombier break;
149*9ef1f84bSDavid du Colombier case 0x03:
150*9ef1f84bSDavid du Colombier p = "VPD";
151*9ef1f84bSDavid du Colombier break;
152*9ef1f84bSDavid du Colombier case 0x04:
153*9ef1f84bSDavid du Colombier p = "Slot Identification";
154*9ef1f84bSDavid du Colombier break;
155*9ef1f84bSDavid du Colombier case 0x05:
156*9ef1f84bSDavid du Colombier p = "MSI";
157*9ef1f84bSDavid du Colombier break;
158*9ef1f84bSDavid du Colombier case 0x06:
159*9ef1f84bSDavid du Colombier p = "CPCI Hot Swap";
160*9ef1f84bSDavid du Colombier break;
161*9ef1f84bSDavid du Colombier case 0x07:
162*9ef1f84bSDavid du Colombier p = "PCI-X";
163*9ef1f84bSDavid du Colombier break;
164*9ef1f84bSDavid du Colombier case 0x08:
165*9ef1f84bSDavid du Colombier DBG("HT: %#4.4ux/%#4.4ux: HT\n",
166*9ef1f84bSDavid du Colombier pci->vid, pci->did);
167*9ef1f84bSDavid du Colombier htcapabilities(pci, cp);
168*9ef1f84bSDavid du Colombier continue;
169*9ef1f84bSDavid du Colombier case 0x09:
170*9ef1f84bSDavid du Colombier p = "Vendor Specific";
171*9ef1f84bSDavid du Colombier break;
172*9ef1f84bSDavid du Colombier case 0x0A:
173*9ef1f84bSDavid du Colombier p = "Debug Port";
174*9ef1f84bSDavid du Colombier break;
175*9ef1f84bSDavid du Colombier case 0x0B:
176*9ef1f84bSDavid du Colombier p = "CPCI Central Resource Control";
177*9ef1f84bSDavid du Colombier break;
178*9ef1f84bSDavid du Colombier case 0x0C:
179*9ef1f84bSDavid du Colombier p = "PCI Hot-Plug";
180*9ef1f84bSDavid du Colombier break;
181*9ef1f84bSDavid du Colombier case 0x0E:
182*9ef1f84bSDavid du Colombier p = "AGP 8x";
183*9ef1f84bSDavid du Colombier break;
184*9ef1f84bSDavid du Colombier case 0x0F:
185*9ef1f84bSDavid du Colombier p = "Secure Device";
186*9ef1f84bSDavid du Colombier break;
187*9ef1f84bSDavid du Colombier case 0x10:
188*9ef1f84bSDavid du Colombier p = "PCIe";
189*9ef1f84bSDavid du Colombier break;
190*9ef1f84bSDavid du Colombier case 0x11:
191*9ef1f84bSDavid du Colombier p = "MSI-X";
192*9ef1f84bSDavid du Colombier break;
193*9ef1f84bSDavid du Colombier case 0x12:
194*9ef1f84bSDavid du Colombier p = "SATA HBA";
195*9ef1f84bSDavid du Colombier break;
196*9ef1f84bSDavid du Colombier }
197*9ef1f84bSDavid du Colombier DBG("HT: %#4.4ux/%#4.4ux: %s\n", pci->vid, pci->did, p);
198*9ef1f84bSDavid du Colombier }
199*9ef1f84bSDavid du Colombier }
200*9ef1f84bSDavid du Colombier }
201