xref: /freebsd/sys/i386/pci/pci_pir.c (revision 1d66272a85cde1c8a69c58f4b5dd649babd6eca6)
1 /*
2  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3  * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
4  * Copyright (c) 2000, BSDi
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  *
30  */
31 
32 #include <sys/param.h>		/* XXX trim includes */
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/malloc.h>
38 #include <vm/vm.h>
39 #include <vm/pmap.h>
40 #include <machine/md_var.h>
41 #include <pci/pcivar.h>
42 #include <pci/pcireg.h>
43 #include <isa/isavar.h>
44 #include <machine/nexusvar.h>
45 #include <machine/pci_cfgreg.h>
46 #include <machine/segments.h>
47 #include <machine/pc/bios.h>
48 
49 #ifdef APIC_IO
50 #include <machine/smp.h>
51 #endif /* APIC_IO */
52 
53 #include "pcib_if.h"
54 
55 static int cfgmech;
56 static int devmax;
57 static int usebios;
58 
59 static int	pci_cfgintr_unique(struct PIR_entry *pe, int pin);
60 static int	pci_cfgintr_linked(struct PIR_entry *pe, int pin);
61 static int	pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
62 static int	pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
63 
64 static int	pcibios_cfgread(int bus, int slot, int func, int reg, int bytes);
65 static void	pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
66 static int	pcibios_cfgopen(void);
67 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
68 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
69 static int	pcireg_cfgopen(void);
70 
71 static struct PIR_table	*pci_route_table;
72 static int		pci_route_count;
73 
74 /*
75  * Initialise access to PCI configuration space
76  */
77 int
78 pci_cfgregopen(void)
79 {
80     static int			opened = 0;
81     u_long			sigaddr;
82     static struct PIR_table	*pt;
83     u_int8_t			ck, *cv;
84     int				i;
85 
86     if (opened)
87 	return(1);
88 
89     if (pcibios_cfgopen() != 0) {
90 	usebios = 1;
91     } else if (pcireg_cfgopen() != 0) {
92 	usebios = 0;
93     } else {
94 	return(0);
95     }
96 
97     /*
98      * Look for the interrupt routing table.
99      */
100     /* XXX use PCI BIOS if it's available */
101 
102     if ((pt == NULL) && ((sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0)) {
103 	pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
104 	for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) {
105 	    ck += cv[i];
106 	}
107 	if (ck == 0) {
108 	    pci_route_table = pt;
109 	    pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry);
110 	    printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table);
111 	}
112     }
113 
114     opened = 1;
115     return(1);
116 }
117 
118 /*
119  * Read configuration space register
120  */
121 u_int32_t
122 pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
123 {
124     return(usebios ?
125 	   pcibios_cfgread(bus, slot, func, reg, bytes) :
126 	   pcireg_cfgread(bus, slot, func, reg, bytes));
127 }
128 
129 u_int32_t
130 pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
131 {
132 #ifdef APIC_IO
133     /*
134      * If we are using the APIC, the contents of the intline register will probably
135      * be wrong (since they are set up for use with the PIC.
136      * Rather than rewrite these registers (maybe that would be smarter) we trap
137      * attempts to read them and translate to our private vector numbers.
138      */
139     if ((reg == PCIR_INTLINE) && (bytes == 1)) {
140 	int	pin, line, airq;
141 
142 	pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
143 	line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
144 
145 	if (pin != 0) {
146 	    int airq;
147 
148 	    airq = pci_apic_irq(bus, slot, pin);
149 	    if (airq >= 0) {
150 		/* PCI specific entry found in MP table */
151 		if (airq != line)
152 		    undirect_pci_irq(line);
153 		return(airq);
154 	    } else {
155 		/*
156 		 * PCI interrupts might be redirected to the
157 		 * ISA bus according to some MP tables. Use the
158 		 * same methods as used by the ISA devices
159 		 * devices to find the proper IOAPIC int pin.
160 		 */
161 		airq = isa_apic_irq(line);
162 		if ((airq >= 0) && (airq != line)) {
163 		    /* XXX: undirect_pci_irq() ? */
164 		    undirect_isa_irq(line);
165 		    return(airq);
166 		}
167 	    }
168 	}
169 	return(line);
170     }
171 #endif /* APIC_IO */
172     return(pci_do_cfgregread(bus, slot, func, reg, bytes));
173 }
174 
175 /*
176  * Write configuration space register
177  */
178 void
179 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
180 {
181     return(usebios ?
182 	   pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
183 	   pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
184 }
185 
186 /*
187  * Route a PCI interrupt
188  *
189  * XXX we don't do anything "right" with the function number in the PIR table
190  *     (because the consumer isn't currently passing it in).  We don't care
191  *     anyway, due to the way PCI interrupts are assigned.
192  */
193 int
194 pci_cfgintr(int bus, int device, int pin)
195 {
196     struct PIR_entry	*pe;
197     int			i, irq;
198     struct bios_regs	args;
199 
200     if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
201       (pin < 1) || (pin > 4))
202 	return(255);
203 
204     /*
205      * Scan the entry table for a contender
206      */
207     for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) {
208 	if ((bus != pe->pe_bus) || (device != pe->pe_device))
209 	    continue;
210 
211 	irq = pci_cfgintr_unique(pe, pin);
212 	if (irq == 255)
213 	    irq = pci_cfgintr_linked(pe, pin);
214 	if (irq == 255)
215 	    irq = pci_cfgintr_virgin(pe, pin);
216 
217 	if (irq == 255)
218 	    break;
219 
220 
221 	/*
222 	 * Ask the BIOS to route the interrupt
223 	 */
224 	args.eax = PCIBIOS_ROUTE_INTERRUPT;
225 	args.ebx = (bus << 8) | (device << 3);
226 	args.ecx = (irq << 8) | (0xa + pin - 1);	/* pin value is 0xa - 0xd */
227 	bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
228 
229 	/*
230 	 * XXX if it fails, we should try to smack the router hardware directly
231 	 */
232 
233 	printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n",
234 	       bus, device, 'A' + pin - 1, irq);
235 	return(irq);
236     }
237 
238     printf("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1);
239     return(255);
240 }
241 
242 /*
243  * Look to see if the routing table claims this pin is uniquely routed.
244  */
245 static int
246 pci_cfgintr_unique(struct PIR_entry *pe, int pin)
247 {
248     int		irq;
249 
250     if (powerof2(pe->pe_intpin[pin - 1].irqs)) {
251 	irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
252 	printf("pci_cfgintr_unique: hard-routed to irq %d\n", irq);
253 	return(irq);
254     }
255     return(255);
256 }
257 
258 /*
259  * Look for another device which shares the same link byte and
260  * already has a unique IRQ, or which has had one routed already.
261  */
262 static int
263 pci_cfgintr_linked(struct PIR_entry *pe, int pin)
264 {
265     struct PIR_entry	*oe;
266     struct PIR_intpin	*pi;
267     int			i, j, irq;
268 
269     /*
270      * Scan table slots.
271      */
272     for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) {
273 
274 	/* scan interrupt pins */
275 	for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
276 
277 	    /* don't look at the entry we're trying to match with */
278 	    if ((pe == oe) && (i == (pin - 1)))
279 		continue;
280 
281 	    /* compare link bytes */
282 	    if (pi->link != pe->pe_intpin[pin - 1].link)
283 		continue;
284 
285 	    /* link destination mapped to a unique interrupt? */
286 	    if (powerof2(pi->irqs)) {
287 		irq = ffs(pi->irqs) - 1;
288 		printf("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
289 		       pi->link, irq);
290 		return(irq);
291 	    }
292 
293 	    /* look for the real PCI device that matches this table entry */
294 	    if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255)
295 		return(irq);
296 	}
297     }
298     return(255);
299 }
300 
301 /*
302  * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and
303  * see if it has already been assigned an interrupt.
304  */
305 static int
306 pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
307 {
308     devclass_t		pci_devclass;
309     device_t		*pci_devices;
310     int			pci_count;
311     device_t		*pci_children;
312     int			pci_childcount;
313     device_t		*busp, *childp;
314     int			i, j, irq;
315 
316     /*
317      * Find all the PCI busses.
318      */
319     pci_count = 0;
320     if ((pci_devclass = devclass_find("pci")) != NULL)
321 	devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
322 
323     /*
324      * Scan all the PCI busses/devices looking for this one.
325      */
326     for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) {
327 	pci_childcount = 0;
328 	device_get_children(*busp, &pci_children, &pci_childcount);
329 
330 	for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
331 	    if ((pci_get_bus(*childp) == bus) &&
332 		(pci_get_slot(*childp) == device) &&
333 		(pci_get_intpin(*childp) == matchpin) &&
334 		((irq = pci_get_irq(*childp)) != 255)) {
335 		printf("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
336 		       irq, pe->pe_intpin[pin - 1].link,
337 		       pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp));
338 		return(irq);
339 	    }
340 	}
341     }
342     return(255);
343 }
344 
345 /*
346  * Pick a suitable IRQ from those listed as routable to this device.
347  */
348 static int
349 pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
350 {
351     int		irq, ibit;
352 
353     /* first scan the set of PCI-only interrupts and see if any of these are routable */
354     for (irq = 0; irq < 16; irq++) {
355 	ibit = (1 << irq);
356 
357 	/* can we use this interrupt? */
358 	if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
359 	    (pe->pe_intpin[pin - 1].irqs & ibit)) {
360 	    printf("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq);
361 	    return(irq);
362 	}
363     }
364 
365     /* life is tough, so just pick an interrupt */
366     for (irq = 0; irq < 16; irq++) {
367 	ibit = (1 << irq);
368 
369 	if (pe->pe_intpin[pin - 1].irqs & ibit) {
370 	    printf("pci_cfgintr_virgin: using routable interrupt %d\n", irq);
371 	    return(irq);
372 	}
373     }
374     return(255);
375 }
376 
377 
378 /*
379  * Config space access using BIOS functions
380  */
381 static int
382 pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
383 {
384     struct bios_regs args;
385     u_int mask;
386 
387     switch(bytes) {
388     case 1:
389 	args.eax = PCIBIOS_READ_CONFIG_BYTE;
390 	mask = 0xff;
391 	break;
392     case 2:
393 	args.eax = PCIBIOS_READ_CONFIG_WORD;
394 	mask = 0xffff;
395 	break;
396     case 4:
397 	args.eax = PCIBIOS_READ_CONFIG_DWORD;
398 	mask = 0xffffffff;
399 	break;
400     default:
401 	return(-1);
402     }
403     args.ebx = (bus << 8) | (slot << 3) | func;
404     args.edi = reg;
405     bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
406     /* check call results? */
407     return(args.ecx & mask);
408 }
409 
410 static void
411 pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
412 {
413     struct bios_regs args;
414 
415     switch(bytes) {
416     case 1:
417 	args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
418 	break;
419     case 2:
420 	args.eax = PCIBIOS_WRITE_CONFIG_WORD;
421 	break;
422     case 4:
423 	args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
424 	break;
425     default:
426 	return;
427     }
428     args.ebx = (bus << 8) | (slot << 3) | func;
429     args.ecx = data;
430     args.edi = reg;
431     bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
432 }
433 
434 /*
435  * Determine whether there is a PCI BIOS present
436  */
437 static int
438 pcibios_cfgopen(void)
439 {
440     /* check for a found entrypoint */
441     return(PCIbios.entry != 0);
442 }
443 
444 /*
445  * Configuration space access using direct register operations
446  */
447 
448 /* enable configuration space accesses and return data port address */
449 static int
450 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
451 {
452     int dataport = 0;
453 
454     if (bus <= PCI_BUSMAX
455 	&& slot < devmax
456 	&& func <= PCI_FUNCMAX
457 	&& reg <= PCI_REGMAX
458 	&& bytes != 3
459 	&& (unsigned) bytes <= 4
460 	&& (reg & (bytes -1)) == 0) {
461 	switch (cfgmech) {
462 	case 1:
463 	    outl(CONF1_ADDR_PORT, (1 << 31)
464 		 | (bus << 16) | (slot << 11)
465 		 | (func << 8) | (reg & ~0x03));
466 	    dataport = CONF1_DATA_PORT + (reg & 0x03);
467 	    break;
468 	case 2:
469 	    outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
470 	    outb(CONF2_FORWARD_PORT, bus);
471 	    dataport = 0xc000 | (slot << 8) | reg;
472 	    break;
473 	}
474     }
475     return (dataport);
476 }
477 
478 /* disable configuration space accesses */
479 static void
480 pci_cfgdisable(void)
481 {
482     switch (cfgmech) {
483     case 1:
484 	outl(CONF1_ADDR_PORT, 0);
485 	break;
486     case 2:
487 	outb(CONF2_ENABLE_PORT, 0);
488 	outb(CONF2_FORWARD_PORT, 0);
489 	break;
490     }
491 }
492 
493 static int
494 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
495 {
496     int data = -1;
497     int port;
498 
499     port = pci_cfgenable(bus, slot, func, reg, bytes);
500 
501     if (port != 0) {
502 	switch (bytes) {
503 	case 1:
504 	    data = inb(port);
505 	    break;
506 	case 2:
507 	    data = inw(port);
508 	    break;
509 	case 4:
510 	    data = inl(port);
511 	    break;
512 	}
513 	pci_cfgdisable();
514     }
515     return (data);
516 }
517 
518 static void
519 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
520 {
521     int port;
522 
523     port = pci_cfgenable(bus, slot, func, reg, bytes);
524     if (port != 0) {
525 	switch (bytes) {
526 	case 1:
527 	    outb(port, data);
528 	    break;
529 	case 2:
530 	    outw(port, data);
531 	    break;
532 	case 4:
533 	    outl(port, data);
534 	    break;
535 	}
536 	pci_cfgdisable();
537     }
538 }
539 
540 /* check whether the configuration mechanism has been correctly identified */
541 static int
542 pci_cfgcheck(int maxdev)
543 {
544     u_char device;
545 
546     if (bootverbose)
547 	printf("pci_cfgcheck:\tdevice ");
548 
549     for (device = 0; device < maxdev; device++) {
550 	unsigned id, class, header;
551 	if (bootverbose)
552 	    printf("%d ", device);
553 
554 	id = inl(pci_cfgenable(0, device, 0, 0, 4));
555 	if (id == 0 || id == -1)
556 	    continue;
557 
558 	class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
559 	if (bootverbose)
560 	    printf("[class=%06x] ", class);
561 	if (class == 0 || (class & 0xf870ff) != 0)
562 	    continue;
563 
564 	header = inb(pci_cfgenable(0, device, 0, 14, 1));
565 	if (bootverbose)
566 	    printf("[hdr=%02x] ", header);
567 	if ((header & 0x7e) != 0)
568 	    continue;
569 
570 	if (bootverbose)
571 	    printf("is there (id=%08x)\n", id);
572 
573 	pci_cfgdisable();
574 	return (1);
575     }
576     if (bootverbose)
577 	printf("-- nothing found\n");
578 
579     pci_cfgdisable();
580     return (0);
581 }
582 
583 static int
584 pcireg_cfgopen(void)
585 {
586     unsigned long mode1res,oldval1;
587     unsigned char mode2res,oldval2;
588 
589     oldval1 = inl(CONF1_ADDR_PORT);
590 
591     if (bootverbose) {
592 	printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
593 	       oldval1);
594     }
595 
596     if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
597 
598 	cfgmech = 1;
599 	devmax = 32;
600 
601 	outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
602 	outb(CONF1_ADDR_PORT +3, 0);
603 	mode1res = inl(CONF1_ADDR_PORT);
604 	outl(CONF1_ADDR_PORT, oldval1);
605 
606 	if (bootverbose)
607 	    printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
608 		   mode1res, CONF1_ENABLE_CHK);
609 
610 	if (mode1res) {
611 	    if (pci_cfgcheck(32))
612 		return (cfgmech);
613 	}
614 
615 	outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
616 	mode1res = inl(CONF1_ADDR_PORT);
617 	outl(CONF1_ADDR_PORT, oldval1);
618 
619 	if (bootverbose)
620 	    printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
621 		   mode1res, CONF1_ENABLE_CHK1);
622 
623 	if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
624 	    if (pci_cfgcheck(32))
625 		return (cfgmech);
626 	}
627     }
628 
629     oldval2 = inb(CONF2_ENABLE_PORT);
630 
631     if (bootverbose) {
632 	printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
633 	       oldval2);
634     }
635 
636     if ((oldval2 & 0xf0) == 0) {
637 
638 	cfgmech = 2;
639 	devmax = 16;
640 
641 	outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
642 	mode2res = inb(CONF2_ENABLE_PORT);
643 	outb(CONF2_ENABLE_PORT, oldval2);
644 
645 	if (bootverbose)
646 	    printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
647 		   mode2res, CONF2_ENABLE_CHK);
648 
649 	if (mode2res == CONF2_ENABLE_RES) {
650 	    if (bootverbose)
651 		printf("pci_open(2a):\tnow trying mechanism 2\n");
652 
653 	    if (pci_cfgcheck(16))
654 		return (cfgmech);
655 	}
656     }
657 
658     cfgmech = 0;
659     devmax = 0;
660     return (cfgmech);
661 }
662 
663