Deleted Added
full compact
pci_bus.c (66416) pci_bus.c (66529)
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/i386/pci/pci_bus.c 66416 2000-09-28 00:37:32Z peter $
26 * $FreeBSD: head/sys/i386/pci/pci_bus.c 66529 2000-10-02 07:11:13Z msmith $
27 *
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/malloc.h>
36
37#include <pci/pcivar.h>
38#include <pci/pcireg.h>
27 *
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/malloc.h>
36
37#include <pci/pcivar.h>
38#include <pci/pcireg.h>
39#include <i386/isa/pcibus.h>
40#include <isa/isavar.h>
41#include <machine/nexusvar.h>
39#include <isa/isavar.h>
40#include <machine/nexusvar.h>
42
41#include <machine/pci_cfgreg.h>
43#include <machine/segments.h>
44#include <machine/pc/bios.h>
45
46#include "pcib_if.h"
47
42#include <machine/segments.h>
43#include <machine/pc/bios.h>
44
45#include "pcib_if.h"
46
48static int cfgmech;
49static int devmax;
50static int usebios;
51
52static int pcibios_cfgread(int bus, int slot, int func, int reg,
53 int bytes);
54static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
55 int data, int bytes);
56static int pcibios_cfgopen(void);
57static int pcireg_cfgread(int bus, int slot, int func, int reg,
58 int bytes);
59static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
60 int data, int bytes);
61static int pcireg_cfgopen(void);
62
63/* read configuration space register */
64
65static int
66nexus_pcib_maxslots(device_t dev)
67{
68 return 31;
69}
70
47static int
48nexus_pcib_maxslots(device_t dev)
49{
50 return 31;
51}
52
53/* read configuration space register */
54
71static u_int32_t
72nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
73 int reg, int bytes)
74{
55static u_int32_t
56nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
57 int reg, int bytes)
58{
75 return(usebios ?
76 pcibios_cfgread(bus, slot, func, reg, bytes) :
77 pcireg_cfgread(bus, slot, func, reg, bytes));
59 return(pci_cfgregread(bus, slot, func, reg, bytes));
78}
79
80/* write configuration space register */
81
82static void
83nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
84 int reg, u_int32_t data, int bytes)
85{
60}
61
62/* write configuration space register */
63
64static void
65nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
66 int reg, u_int32_t data, int bytes)
67{
86 return(usebios ?
87 pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
88 pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
68 pci_cfgregwrite(bus, slot, func, reg, data, bytes);
89}
90
69}
70
91/* initialise access to PCI configuration space */
92static int
93pci_cfgopen(void)
94{
95 if (pcibios_cfgopen() != 0) {
96 usebios = 1;
97 } else if (pcireg_cfgopen() != 0) {
98 usebios = 0;
99 } else {
100 return(0);
101 }
102 return(1);
103}
104
105/* config space access using BIOS functions */
106
107static int
108pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
109{
110 struct bios_regs args;
111 u_int mask;
112
113 switch(bytes) {
114 case 1:
115 args.eax = PCIBIOS_READ_CONFIG_BYTE;
116 mask = 0xff;
117 break;
118 case 2:
119 args.eax = PCIBIOS_READ_CONFIG_WORD;
120 mask = 0xffff;
121 break;
122 case 4:
123 args.eax = PCIBIOS_READ_CONFIG_DWORD;
124 mask = 0xffffffff;
125 break;
126 default:
127 return(-1);
128 }
129 args.ebx = (bus << 8) | (slot << 3) | func;
130 args.edi = reg;
131 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
132 /* check call results? */
133 return(args.ecx & mask);
134}
135
136static void
137pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
138{
139 struct bios_regs args;
140
141 switch(bytes) {
142 case 1:
143 args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
144 break;
145 case 2:
146 args.eax = PCIBIOS_WRITE_CONFIG_WORD;
147 break;
148 case 4:
149 args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
150 break;
151 default:
152 return;
153 }
154 args.ebx = (bus << 8) | (slot << 3) | func;
155 args.ecx = data;
156 args.edi = reg;
157 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
158}
159
160/* determine whether there is a PCI BIOS present */
161
162static int
163pcibios_cfgopen(void)
164{
165 /* check for a found entrypoint */
166 return(PCIbios.entry != 0);
167}
168
169/* configuration space access using direct register operations */
170
171/* enable configuration space accesses and return data port address */
172
173static int
174pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
175{
176 int dataport = 0;
177
178 if (bus <= PCI_BUSMAX
179 && slot < devmax
180 && func <= PCI_FUNCMAX
181 && reg <= PCI_REGMAX
182 && bytes != 3
183 && (unsigned) bytes <= 4
184 && (reg & (bytes -1)) == 0) {
185 switch (cfgmech) {
186 case 1:
187 outl(CONF1_ADDR_PORT, (1 << 31)
188 | (bus << 16) | (slot << 11)
189 | (func << 8) | (reg & ~0x03));
190 dataport = CONF1_DATA_PORT + (reg & 0x03);
191 break;
192 case 2:
193 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
194 outb(CONF2_FORWARD_PORT, bus);
195 dataport = 0xc000 | (slot << 8) | reg;
196 break;
197 }
198 }
199 return (dataport);
200}
201
202/* disable configuration space accesses */
203
204static void
205pci_cfgdisable(void)
206{
207 switch (cfgmech) {
208 case 1:
209 outl(CONF1_ADDR_PORT, 0);
210 break;
211 case 2:
212 outb(CONF2_ENABLE_PORT, 0);
213 outb(CONF2_FORWARD_PORT, 0);
214 break;
215 }
216}
217
218static int
219pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
220{
221 int data = -1;
222 int port;
223
224 port = pci_cfgenable(bus, slot, func, reg, bytes);
225
226 if (port != 0) {
227 switch (bytes) {
228 case 1:
229 data = inb(port);
230 break;
231 case 2:
232 data = inw(port);
233 break;
234 case 4:
235 data = inl(port);
236 break;
237 }
238 pci_cfgdisable();
239 }
240 return (data);
241}
242
243static void
244pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
245{
246 int port;
247
248 port = pci_cfgenable(bus, slot, func, reg, bytes);
249 if (port != 0) {
250 switch (bytes) {
251 case 1:
252 outb(port, data);
253 break;
254 case 2:
255 outw(port, data);
256 break;
257 case 4:
258 outl(port, data);
259 break;
260 }
261 pci_cfgdisable();
262 }
263}
264
265/* check whether the configuration mechanism has been correct identified */
266
267static int
268pci_cfgcheck(int maxdev)
269{
270 u_char device;
271
272 if (bootverbose)
273 printf("pci_cfgcheck:\tdevice ");
274
275 for (device = 0; device < maxdev; device++) {
276 unsigned id, class, header;
277 if (bootverbose)
278 printf("%d ", device);
279
280 id = inl(pci_cfgenable(0, device, 0, 0, 4));
281 if (id == 0 || id == -1)
282 continue;
283
284 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
285 if (bootverbose)
286 printf("[class=%06x] ", class);
287 if (class == 0 || (class & 0xf870ff) != 0)
288 continue;
289
290 header = inb(pci_cfgenable(0, device, 0, 14, 1));
291 if (bootverbose)
292 printf("[hdr=%02x] ", header);
293 if ((header & 0x7e) != 0)
294 continue;
295
296 if (bootverbose)
297 printf("is there (id=%08x)\n", id);
298
299 pci_cfgdisable();
300 return (1);
301 }
302 if (bootverbose)
303 printf("-- nothing found\n");
304
305 pci_cfgdisable();
306 return (0);
307}
308
309static int
310pcireg_cfgopen(void)
311{
312 unsigned long mode1res,oldval1;
313 unsigned char mode2res,oldval2;
314
315 oldval1 = inl(CONF1_ADDR_PORT);
316
317 if (bootverbose) {
318 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
319 oldval1);
320 }
321
322 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
323
324 cfgmech = 1;
325 devmax = 32;
326
327 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
328 outb(CONF1_ADDR_PORT +3, 0);
329 mode1res = inl(CONF1_ADDR_PORT);
330 outl(CONF1_ADDR_PORT, oldval1);
331
332 if (bootverbose)
333 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
334 mode1res, CONF1_ENABLE_CHK);
335
336 if (mode1res) {
337 if (pci_cfgcheck(32))
338 return (cfgmech);
339 }
340
341 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
342 mode1res = inl(CONF1_ADDR_PORT);
343 outl(CONF1_ADDR_PORT, oldval1);
344
345 if (bootverbose)
346 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
347 mode1res, CONF1_ENABLE_CHK1);
348
349 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
350 if (pci_cfgcheck(32))
351 return (cfgmech);
352 }
353 }
354
355 oldval2 = inb(CONF2_ENABLE_PORT);
356
357 if (bootverbose) {
358 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
359 oldval2);
360 }
361
362 if ((oldval2 & 0xf0) == 0) {
363
364 cfgmech = 2;
365 devmax = 16;
366
367 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
368 mode2res = inb(CONF2_ENABLE_PORT);
369 outb(CONF2_ENABLE_PORT, oldval2);
370
371 if (bootverbose)
372 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
373 mode2res, CONF2_ENABLE_CHK);
374
375 if (mode2res == CONF2_ENABLE_RES) {
376 if (bootverbose)
377 printf("pci_open(2a):\tnow trying mechanism 2\n");
378
379 if (pci_cfgcheck(16))
380 return (cfgmech);
381 }
382 }
383
384 cfgmech = 0;
385 devmax = 0;
386 return (cfgmech);
387}
388
389static devclass_t pcib_devclass;
390
391static const char *
392nexus_pcib_is_host_bridge(int bus, int slot, int func,
393 u_int32_t id, u_int8_t class, u_int8_t subclass,
394 u_int8_t *busnum)
395{
396 const char *s = NULL;

--- 174 unchanged lines hidden (view full) ---

571{
572 int bus, slot, func;
573 u_int8_t hdrtype;
574 int found = 0;
575 int pcifunchigh;
576 int found824xx = 0;
577 device_t child;
578
71static devclass_t pcib_devclass;
72
73static const char *
74nexus_pcib_is_host_bridge(int bus, int slot, int func,
75 u_int32_t id, u_int8_t class, u_int8_t subclass,
76 u_int8_t *busnum)
77{
78 const char *s = NULL;

--- 174 unchanged lines hidden (view full) ---

253{
254 int bus, slot, func;
255 u_int8_t hdrtype;
256 int found = 0;
257 int pcifunchigh;
258 int found824xx = 0;
259 device_t child;
260
579 if (pci_cfgopen() == 0)
261 if (pci_cfgregopen() == 0)
580 return;
581 bus = 0;
582 retry:
583 for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
584 func = 0;
585 hdrtype = nexus_pcib_read_config(0, bus, slot, func,
586 PCIR_HEADERTYPE, 1);
587 if (hdrtype & PCIM_MFDEV)

--- 60 unchanged lines hidden (view full) ---

648 if (found824xx && bus == 0) {
649 bus++;
650 goto retry;
651 }
652
653 /*
654 * Make sure we add at least one bridge since some old
655 * hardware doesn't actually have a host-pci bridge device.
262 return;
263 bus = 0;
264 retry:
265 for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
266 func = 0;
267 hdrtype = nexus_pcib_read_config(0, bus, slot, func,
268 PCIR_HEADERTYPE, 1);
269 if (hdrtype & PCIM_MFDEV)

--- 60 unchanged lines hidden (view full) ---

330 if (found824xx && bus == 0) {
331 bus++;
332 goto retry;
333 }
334
335 /*
336 * Make sure we add at least one bridge since some old
337 * hardware doesn't actually have a host-pci bridge device.
656 * Note that pci_cfgopen() thinks we have PCI devices..
338 * Note that pci_cfgregopen() thinks we have PCI devices..
657 */
658 if (!found) {
659 if (bootverbose)
660 printf(
661 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
662 child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
663 nexus_set_pcibus(child, 0);
664 }
665}
666
667static int
668nexus_pcib_probe(device_t dev)
669{
670
339 */
340 if (!found) {
341 if (bootverbose)
342 printf(
343 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
344 child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
345 nexus_set_pcibus(child, 0);
346 }
347}
348
349static int
350nexus_pcib_probe(device_t dev)
351{
352
671 if (pci_cfgopen() != 0)
353 if (pci_cfgregopen() != 0)
672 return 0;
673
674 return ENXIO;
675}
676
677static int
678nexus_pcib_attach(device_t dev)
679{

--- 165 unchanged lines hidden ---
354 return 0;
355
356 return ENXIO;
357}
358
359static int
360nexus_pcib_attach(device_t dev)
361{

--- 165 unchanged lines hidden ---