Next phase in the PCI subsystem cleanup.
- Move PCI core code to dev/pci. - Split bridge code out into separate modules. - Remove the descriptive strings from the bridge drivers. If you want to know what a device is, use pciconf. Add support for broadly identifying devices based on class/subclass, and for parsing a preloaded device identification database so that if you want to waste the memory, you can identify *anything* we know about. - Remove machine-dependant code from the core PCI code. APIC interrupt mapping is performed by shadowing the intline register in machine- dependant code. - Bring interrupt routing support to the Alpha (although many platforms don't yet support routing or mapping interrupts entirely correctly). This resulted in spamming <sys/bus.h> into more places than it really should have gone. - Put sys/dev on the kernel/modules include path. This avoids having to change *all* the pci*.h includes.
This commit is contained in:
parent
baeb94c70d
commit
bb0d0a8efc
@ -33,6 +33,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/cpuconf.h>
|
||||
#include <machine/rpb.h>
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -103,12 +104,12 @@ void dec_1000a_init __P((int));
|
||||
static void dec_1000a_cons_init __P((void));
|
||||
|
||||
|
||||
static void dec_1000_intr_map __P((void *));
|
||||
static int dec_1000_intr_route __P((device_t, device_t, int));
|
||||
static void dec_1000_intr_disable __P((int));
|
||||
static void dec_1000_intr_enable __P((int));
|
||||
static void dec_1000_intr_init __P((void));
|
||||
|
||||
static void dec_1000a_intr_map __P((void *));
|
||||
static int dec_1000a_intr_route __P((device_t, device_t, int));
|
||||
static void dec_1000a_intr_disable __P((int));
|
||||
static void dec_1000a_intr_enable __P((int));
|
||||
static void dec_1000a_intr_init __P((void));
|
||||
@ -147,7 +148,7 @@ dec_1000a_init(int cputype)
|
||||
case PCS_PROC_EV4:
|
||||
case PCS_PROC_EV45:
|
||||
platform.iobus = "apecs";
|
||||
platform.pci_intr_map = dec_1000_intr_map;
|
||||
platform.pci_intr_route = dec_1000_intr_route;
|
||||
platform.pci_intr_disable = dec_1000_intr_disable;
|
||||
platform.pci_intr_enable = dec_1000_intr_enable;
|
||||
platform.pci_intr_init = dec_1000_intr_init;
|
||||
@ -155,7 +156,7 @@ dec_1000a_init(int cputype)
|
||||
|
||||
default:
|
||||
platform.iobus = "cia";
|
||||
platform.pci_intr_map = dec_1000a_intr_map;
|
||||
platform.pci_intr_route = dec_1000a_intr_route;
|
||||
platform.pci_intr_disable = dec_1000a_intr_disable;
|
||||
platform.pci_intr_enable = dec_1000a_intr_enable;
|
||||
platform.pci_intr_init = dec_1000a_intr_init;
|
||||
@ -228,34 +229,26 @@ dec_1000a_cons_init()
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dec_1000_intr_map(arg)
|
||||
void *arg;
|
||||
static int
|
||||
dec_1000_intr_route(bus, dev, pin)
|
||||
device_t bus, dev;
|
||||
int pin;
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
if (cfg->intpin == 0) /* No IRQ used. */
|
||||
return;
|
||||
if (!(1 <= cfg->intpin && cfg->intpin <= 4))
|
||||
goto bad;
|
||||
|
||||
switch(cfg->slot) {
|
||||
switch(pci_get_slot(dev)) {
|
||||
case 6:
|
||||
if(cfg->intpin != 1)
|
||||
if (pin != 1)
|
||||
break;
|
||||
cfg->intline = 0xc; /* integrated ncr scsi */
|
||||
return;
|
||||
break;
|
||||
return(0xc); /* integrated ncr scsi */
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
cfg->intline = (cfg->slot - 11) * 4 + cfg->intpin - 1;
|
||||
return((pci_get_slot(dev) - 11) * 4 + pin - 1);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
bad: printf("dec_1000_intr_map: can't map dev %d pin %d\n",
|
||||
cfg->slot, cfg->intpin);
|
||||
pci_get_slot(dev), pin);
|
||||
return(255);
|
||||
}
|
||||
|
||||
|
||||
@ -312,11 +305,12 @@ dec_1000_intr_init()
|
||||
#define IMR2IRQ(bn) ((bn) - 1)
|
||||
#define IRQ2IMR(irq) ((irq) + 1)
|
||||
|
||||
static void
|
||||
dec_1000a_intr_map(arg)
|
||||
void *arg;
|
||||
|
||||
static int
|
||||
dec_1000a_intr_route(bus, dev, pin)
|
||||
device_t bus, dev;
|
||||
int pin;
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
int device, imrbit;
|
||||
/*
|
||||
* Get bit number in mystery ICU imr.
|
||||
@ -341,28 +335,17 @@ dec_1000a_intr_map(arg)
|
||||
/* 14 */ IRQSPLIT(8) /* Corelle */
|
||||
};
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
device = cfg->slot;
|
||||
|
||||
if (cfg->intpin == 0) /* No IRQ used. */
|
||||
return;
|
||||
if (!(1 <= cfg->intpin && cfg->intpin <= 4))
|
||||
goto bad;
|
||||
|
||||
if (0 <= device && device < sizeof imrmap / sizeof imrmap[0]) {
|
||||
imrbit = imrmap[device][cfg->intpin - 1];
|
||||
if (imrbit) {
|
||||
cfg->intline = IMR2IRQ(imrbit);
|
||||
return;
|
||||
}
|
||||
if (0 <= pci_get_slot(dev) && pci_get_slot(dev) < sizeof imrmap / sizeof imrmap[0]) {
|
||||
imrbit = imrmap[device][pin - 1];
|
||||
if (imrbit)
|
||||
return(IMR2IRQ(imrbit));
|
||||
}
|
||||
bad: printf("dec_1000a_intr_map: can't map dev %d pin %d\n",
|
||||
device, cfg->intpin);
|
||||
bad: printf("dec_1000a_intr_route: can't map dev %d pin %d\n",
|
||||
pci_get_slot(dev), pin);
|
||||
return(255);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dec_1000a_intr_enable(irq)
|
||||
int irq;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -58,7 +59,7 @@ static int comcnrate = CONSPEED;
|
||||
|
||||
void dec_2100_a50_init __P((void));
|
||||
static void dec_2100_a50_cons_init __P((void));
|
||||
static void dec_2100_a50_intr_map __P((void *));
|
||||
static int dec_2100_a50_intr_route __P((device_t, device_t, int));
|
||||
void sio_intr_establish __P((int));
|
||||
void sio_intr_disestablish __P((int));
|
||||
void sio_intr_setup __P((void));
|
||||
@ -97,7 +98,7 @@ dec_2100_a50_init()
|
||||
|
||||
platform.iobus = "apecs";
|
||||
platform.cons_init = dec_2100_a50_cons_init;
|
||||
platform.pci_intr_map = dec_2100_a50_intr_map;
|
||||
platform.pci_intr_route = dec_2100_a50_intr_route;
|
||||
}
|
||||
|
||||
/* XXX for forcing comconsole when srm serial console is used */
|
||||
@ -158,35 +159,27 @@ dec_2100_a50_cons_init()
|
||||
|
||||
#define SIO_PCIREG_PIRQ_RTCTRL 0x60 /* PIRQ0 Route Control */
|
||||
|
||||
void
|
||||
dec_2100_a50_intr_map(void *arg)
|
||||
int
|
||||
dec_2100_a50_intr_route(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
u_int8_t pirqline;
|
||||
u_int32_t pirqreg;
|
||||
int pirq;
|
||||
pcicfgregs *cfg;
|
||||
|
||||
pirq = 0; /* gcc -Wuninitialized XXX */
|
||||
cfg = (pcicfgregs *)arg;
|
||||
pirq = 255;
|
||||
|
||||
/*
|
||||
* Slot->interrupt translation. Taken from NetBSD.
|
||||
*/
|
||||
|
||||
if(cfg->intpin == 0)
|
||||
return;
|
||||
|
||||
if(cfg->intpin > 4)
|
||||
panic("dec_2100_a50_intr_map: bad intpin %d",cfg->intpin);
|
||||
|
||||
switch (cfg->slot) {
|
||||
switch (pci_get_slot(dev)) {
|
||||
case 6: /* NCR SCSI */
|
||||
pirq = 3;
|
||||
break;
|
||||
|
||||
case 11: /* slot 1 */
|
||||
case 14: /* slot 3 */
|
||||
switch(cfg->intpin) {
|
||||
switch(pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 0;
|
||||
@ -198,13 +191,12 @@ dec_2100_a50_intr_map(void *arg)
|
||||
pirq = 1;
|
||||
break;
|
||||
default:
|
||||
panic("dec_2100_a50_intr_map bogus PCI pin %d\n",
|
||||
cfg->intpin);
|
||||
|
||||
panic("dec_2100_a50_intr_map bogus PCI pin %d\n", pin);
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: /* slot 2 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 1;
|
||||
@ -216,14 +208,12 @@ dec_2100_a50_intr_map(void *arg)
|
||||
pirq = 2;
|
||||
break;
|
||||
default:
|
||||
panic("dec_2100_a50_intr_map bogus PCI pin %d\n",
|
||||
cfg->intpin);
|
||||
|
||||
panic("dec_2100_a50_intr_map bogus PCI pin %d\n", pin);
|
||||
};
|
||||
break;
|
||||
|
||||
case 13: /* slot 3 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 2;
|
||||
@ -237,8 +227,8 @@ dec_2100_a50_intr_map(void *arg)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
printf("dec_2100_a50_intr_map: weird slot %d\n",
|
||||
cfg->slot);
|
||||
printf("dec_2100_a50_intr_map: weird slot %d\n",
|
||||
pci_get_slot(dev));
|
||||
|
||||
/* return; */
|
||||
}
|
||||
@ -254,5 +244,5 @@ dec_2100_a50_intr_map(void *arg)
|
||||
if ((pirqline & 0x80) != 0)
|
||||
panic("bad pirqline %d",pirqline);
|
||||
pirqline &= 0xf;
|
||||
cfg->intline = pirqline;
|
||||
return(pirqline);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -80,7 +81,7 @@ dec_2100_a500_init(cputype)
|
||||
|
||||
platform.iobus = "t2";
|
||||
platform.cons_init = dec_2100_a500_cons_init;
|
||||
platform.pci_intr_map = t2_intr_map;
|
||||
platform.pci_intr_route = t2_intr_route;
|
||||
platform.pci_intr_init = dec_2100_a500_intr_init;
|
||||
|
||||
t2_init();
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -55,7 +56,7 @@ static int comcnrate = CONSPEED;
|
||||
|
||||
void dec_axppci_33_init __P((void));
|
||||
static void dec_axppci_33_cons_init __P((void));
|
||||
static void dec_axppci_33_intr_map __P((void *));
|
||||
static int dec_axppci_33_intr_route __P((device_t, device_t, int));
|
||||
|
||||
extern int siocnattach __P((int, int));
|
||||
extern int siogdbattach __P((int, int));
|
||||
@ -93,7 +94,7 @@ dec_axppci_33_init()
|
||||
|
||||
platform.iobus = "lca";
|
||||
platform.cons_init = dec_axppci_33_cons_init;
|
||||
platform.pci_intr_map = dec_axppci_33_intr_map;
|
||||
platform.pci_intr_route = dec_axppci_33_intr_route;
|
||||
|
||||
lca_init();
|
||||
|
||||
@ -167,16 +168,13 @@ dec_axppci_33_cons_init()
|
||||
|
||||
#define SIO_PCIREG_PIRQ_RTCTRL 0x60 /* PIRQ0 Route Control */
|
||||
|
||||
void
|
||||
dec_axppci_33_intr_map(void *arg)
|
||||
static int
|
||||
dec_axppci_33_intr_route(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
int pirq;
|
||||
u_int32_t pirqreg;
|
||||
u_int8_t pirqline;
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
|
||||
#ifndef DIAGNOSTIC
|
||||
pirq = 0; /* XXX gcc -Wuninitialized */
|
||||
#endif
|
||||
@ -185,23 +183,13 @@ dec_axppci_33_intr_map(void *arg)
|
||||
* Slot->interrupt translation. Taken from NetBSD.
|
||||
*/
|
||||
|
||||
if (cfg->intpin == 0) {
|
||||
/* No IRQ used. */
|
||||
return;
|
||||
}
|
||||
if (cfg->intpin > 4) {
|
||||
printf("dec_axppci_33_intr_map: bad interrupt pin %d\n",
|
||||
cfg->intpin);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cfg->slot) {
|
||||
switch (pci_get_slot(dev)) {
|
||||
case 6: /* NCR SCSI */
|
||||
pirq = 3;
|
||||
break;
|
||||
|
||||
case 11: /* slot 1 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 0;
|
||||
@ -212,16 +200,11 @@ dec_axppci_33_intr_map(void *arg)
|
||||
case 3:
|
||||
pirq = 1;
|
||||
break;
|
||||
#ifdef DIAGNOSTIC
|
||||
default: /* XXX gcc -Wuninitialized */
|
||||
panic("dec_axppci_33_intr_map: bogus PCI pin %d\n",
|
||||
cfg->intpin);
|
||||
#endif
|
||||
};
|
||||
break;
|
||||
|
||||
case 12: /* slot 2 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 1;
|
||||
@ -232,16 +215,11 @@ dec_axppci_33_intr_map(void *arg)
|
||||
case 3:
|
||||
pirq = 2;
|
||||
break;
|
||||
#ifdef DIAGNOSTIC
|
||||
default: /* XXX gcc -Wuninitialized */
|
||||
panic("dec_axppci_33_intr_map: bogus PCI pin %d\n",
|
||||
cfg->intpin);
|
||||
#endif
|
||||
};
|
||||
break;
|
||||
|
||||
case 8: /* slot 3 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
case 4:
|
||||
pirq = 2;
|
||||
@ -252,35 +230,22 @@ dec_axppci_33_intr_map(void *arg)
|
||||
case 3:
|
||||
pirq = 0;
|
||||
break;
|
||||
#ifdef DIAGNOSTIC
|
||||
default: /* XXX gcc -Wuninitialized */
|
||||
panic("dec_axppci_33_intr_map bogus: PCI pin %d\n",
|
||||
cfg->intpin);
|
||||
#endif
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("dec_axppci_33_intr_map: weird device number %d\n",
|
||||
cfg->slot);
|
||||
return;
|
||||
printf("dec_axppci_33_intr_map: weird slot number %d\n",
|
||||
pci_get_slot(dev));
|
||||
return(255);
|
||||
}
|
||||
|
||||
pirqreg = lca_pcib_read_config(0, 0, 7, 0,
|
||||
SIO_PCIREG_PIRQ_RTCTRL, 4);
|
||||
#if 0
|
||||
printf("dec_axppci_33_intr_map: device %d pin %c: pirq %d, reg = %x\n",
|
||||
device, '@' + cfg->intpin, pirq, pirqreg);
|
||||
#endif
|
||||
pirqline = (pirqreg >> (pirq * 8)) & 0xff;
|
||||
if ((pirqline & 0x80) != 0)
|
||||
panic("bad pirqline %d",pirqline);
|
||||
pirqline &= 0xf;
|
||||
|
||||
#if 0
|
||||
printf("dec_axppci_33_intr_map: device %d pin %c: mapped to line %d\n",
|
||||
device, '@' + cfg->intpin, pirqline);
|
||||
#endif
|
||||
|
||||
cfg->intline = pirqline;
|
||||
return(pirqline);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -77,7 +78,7 @@ dec_eb164_init()
|
||||
platform.iobus = "cia";
|
||||
platform.cons_init = dec_eb164_cons_init;
|
||||
platform.pci_intr_init = eb164_intr_init;
|
||||
platform.pci_intr_map = NULL;
|
||||
platform.pci_intr_route = NULL;
|
||||
if (strncmp(platform.model, "Digital AlphaPC 164 ", 20) == 0) {
|
||||
platform.pci_intr_disable = eb164_intr_disable_icsr;
|
||||
platform.pci_intr_enable = eb164_intr_enable_icsr;
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -109,7 +110,7 @@ dec_eb64plus_init()
|
||||
platform.cons_init = dec_eb64plus_cons_init;
|
||||
platform.pci_intr_init = dec_eb64plus_intr_init;
|
||||
/* SRM handles PCI interrupt mapping */
|
||||
platform.pci_intr_map = NULL;
|
||||
platform.pci_intr_route = NULL;
|
||||
/* see ../pci/pci_eb64plus_intr.s for intr. dis/enable */
|
||||
platform.pci_intr_disable = eb64plus_intr_disable;
|
||||
platform.pci_intr_enable = eb64plus_intr_enable;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
@ -57,7 +58,7 @@ static int comcnrate = CONSPEED;
|
||||
void dec_kn20aa_init __P((void));
|
||||
static void dec_kn20aa_cons_init __P((void));
|
||||
static void dec_kn20aa_intr_init __P((void));
|
||||
static void dec_kn20aa_intr_map __P((void *));
|
||||
static int dec_kn20aa_intr_route __P((device_t, device_t, int));
|
||||
static void dec_kn20aa_intr_disable __P((int));
|
||||
static void dec_kn20aa_intr_enable __P((int));
|
||||
|
||||
@ -92,7 +93,7 @@ dec_kn20aa_init()
|
||||
platform.iobus = "cia";
|
||||
platform.cons_init = dec_kn20aa_cons_init;
|
||||
platform.pci_intr_init = dec_kn20aa_intr_init;
|
||||
platform.pci_intr_map = dec_kn20aa_intr_map;
|
||||
platform.pci_intr_route = dec_kn20aa_intr_route;
|
||||
platform.pci_intr_disable = dec_kn20aa_intr_disable;
|
||||
platform.pci_intr_enable = dec_kn20aa_intr_enable;
|
||||
}
|
||||
@ -276,12 +277,11 @@ dec_kn20aa_intr_init()
|
||||
dec_kn20aa_intr_enable(31);
|
||||
}
|
||||
|
||||
void
|
||||
dec_kn20aa_intr_map(void *arg)
|
||||
static int
|
||||
dec_kn20aa_intr_route(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
int intline;
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
/*
|
||||
* Slot->interrupt translation. Appears to work, though it
|
||||
* may not hold up forever.
|
||||
@ -289,45 +289,46 @@ dec_kn20aa_intr_map(void *arg)
|
||||
* The DEC engineers who did this hardware obviously engaged
|
||||
* in random drug testing.
|
||||
*/
|
||||
switch (cfg->slot) {
|
||||
switch (pci_get_slot(dev)) {
|
||||
case 11:
|
||||
case 12:
|
||||
cfg->intline = ((cfg->slot - 11) + 0) * 4;
|
||||
intline = ((pci_get_slot(dev) - 11) + 0) * 4;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
cfg->intline = 8;
|
||||
intline = 8;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
cfg->intline = 12;
|
||||
intline = 12;
|
||||
break;
|
||||
|
||||
case 6: /* 21040 on AlphaStation 500 */
|
||||
cfg->intline = 13;
|
||||
intline = 13;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
cfg->intline = 16;
|
||||
intline = 16;
|
||||
break;
|
||||
|
||||
case 10: /* 8275EB on AlphaStation 500 */
|
||||
return;
|
||||
return(255);
|
||||
|
||||
default:
|
||||
if(!cfg->bus){
|
||||
if (pci_get_bus(dev) == 0) {
|
||||
printf("dec_kn20aa_intr_map: weird slot %d\n",
|
||||
cfg->slot);
|
||||
return;
|
||||
pci_get_slot(dev));
|
||||
return(255);
|
||||
} else {
|
||||
cfg->intline = cfg->slot;
|
||||
intline = pci_get_slot(dev);
|
||||
}
|
||||
}
|
||||
|
||||
cfg->intline += cfg->bus*16;
|
||||
if (cfg->intline > KN20AA_MAX_IRQ)
|
||||
panic("dec_kn20aa_intr_map: cfg->intline too large (%d)\n",
|
||||
cfg->intline);
|
||||
intline += pci_get_bus(dev) * 16;
|
||||
if (intline > KN20AA_MAX_IRQ)
|
||||
panic("dec_kn20aa_intr_route: intline too large (%d)\n",
|
||||
intline);
|
||||
return(intline);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <sys/termios.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/cpuconf.h>
|
||||
|
@ -67,7 +67,7 @@ static void pyxis_intr_enable __P((int));
|
||||
static void pyxis_intr_disable __P((int));
|
||||
static void st550_intr_enable __P((int));
|
||||
static void st550_intr_disable __P((int));
|
||||
static void st550_intr_map __P((void *));
|
||||
static int st550_intr_route __P((device_t, device_t, int));
|
||||
#define ST550_PCI_IRQ_BEGIN 8
|
||||
#define ST550_PCI_MAX_IRQ 47
|
||||
|
||||
@ -89,7 +89,7 @@ st550_init()
|
||||
platform.iobus = "cia";
|
||||
platform.cons_init = st550_cons_init;
|
||||
platform.pci_intr_init = st550_intr_init;
|
||||
platform.pci_intr_map = st550_intr_map;
|
||||
platform.pci_intr_route = st550_intr_route;
|
||||
platform.pci_intr_disable = st550_intr_disable;
|
||||
platform.pci_intr_enable = st550_intr_enable;
|
||||
}
|
||||
@ -159,12 +159,9 @@ st550_intr_init()
|
||||
pyxis_intr_enable(7); /* enable ISA PIC cascade */
|
||||
}
|
||||
|
||||
static void
|
||||
st550_intr_map(void *arg)
|
||||
static int
|
||||
st550_intr_route(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
|
||||
/* There are two main variants of Miata: Miata 1 (Intel SIO)
|
||||
* and Miata {1.5,2} (Cypress).
|
||||
@ -179,25 +176,28 @@ st550_intr_map(void *arg)
|
||||
* There will be no interrupt mapping for these devices, so just
|
||||
* bail out now.
|
||||
*/
|
||||
if(cfg->bus == 0) {
|
||||
/*
|
||||
* XXX FIXME this code does not match the above description.
|
||||
*/
|
||||
if (pci_get_bus(dev) == 0) {
|
||||
if ((hwrpb->rpb_variation & SV_ST_MASK) < SV_ST_MIATA_1_5) {
|
||||
/* Miata 1 */
|
||||
if (cfg->slot == 7)
|
||||
return;
|
||||
else if (cfg->func == 4)
|
||||
return;
|
||||
if (pci_get_slot(dev) == 7)
|
||||
return(255);
|
||||
else if (pci_get_function(dev) == 4)
|
||||
return(255);
|
||||
} else {
|
||||
/* Miata 1.5 or Miata 2 */
|
||||
if (cfg->slot == 7) {
|
||||
if (cfg->func == 0)
|
||||
return;
|
||||
return;
|
||||
if (pci_get_slot(dev) == 7) {
|
||||
if (pci_get_function(dev) == 0)
|
||||
return(255);
|
||||
return(255);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Account for the PCI interrupt offset. */
|
||||
/* cfg->intline += ST550_PCI_IRQ_BEGIN; */
|
||||
return;
|
||||
return(255);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -55,7 +55,7 @@ static int comcnrate = CONSPEED;
|
||||
void st6600_init __P((void));
|
||||
static void st6600_cons_init __P((void));
|
||||
static void st6600_intr_init __P((void));
|
||||
static void st6600_intr_map __P((void *));
|
||||
static int st6600_intr_route __P((device_t, device_t, int));
|
||||
|
||||
#define ST6600_PCI_IRQ_BEGIN 8
|
||||
#define ST6600_PCI_MAX_IRQ 63
|
||||
@ -77,7 +77,7 @@ st6600_init()
|
||||
platform.iobus = "tsunami";
|
||||
platform.cons_init = st6600_cons_init;
|
||||
platform.pci_intr_init = st6600_intr_init;
|
||||
platform.pci_intr_map = st6600_intr_map;
|
||||
platform.pci_intr_route = st6600_intr_route;
|
||||
}
|
||||
|
||||
extern int comconsole;
|
||||
@ -145,10 +145,10 @@ st6600_intr_init()
|
||||
platform.pci_intr_enable(2);
|
||||
}
|
||||
|
||||
static void
|
||||
st6600_intr_map(void *arg)
|
||||
static int
|
||||
st6600_intr_route(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
|
||||
return;
|
||||
return(255);
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <sys/msgbuf.h>
|
||||
|
@ -72,7 +72,7 @@ extern struct platform {
|
||||
void (*mcheck_handler) __P((unsigned long, struct trapframe *,
|
||||
unsigned long, unsigned long));
|
||||
void (*pci_intr_init) __P((void));
|
||||
void (*pci_intr_map) __P((void *));
|
||||
int (*pci_intr_route) __P((device_t, device_t, int));
|
||||
void (*pci_intr_disable) __P((int));
|
||||
void (*pci_intr_enable) __P((int));
|
||||
int (*pci_setup_ide_intr) __P((struct device *dev,
|
||||
|
@ -71,7 +71,7 @@ int alpha_platform_pci_setup_intr(device_t dev, device_t child,
|
||||
void **cookiep);
|
||||
int alpha_platform_pci_teardown_intr(device_t dev, device_t child,
|
||||
struct resource *irq, void *cookie);
|
||||
int alpha_pci_route_interrupt(device_t bus, device_t dev, int pin);
|
||||
#endif
|
||||
void alpha_platform_assign_pciintr(struct pcicfg *cfg);
|
||||
|
||||
#endif /* !_MACHINE_MD_VAR_H_ */
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <alpha/osf1/osf1.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <alpha/osf1/exec_ecoff.h>
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <sys/msgbuf.h>
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/rman.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <machine/swiz.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <alpha/pci/apecsreg.h>
|
||||
#include <alpha/pci/apecsvar.h>
|
||||
@ -188,6 +189,7 @@ static device_method_t apecs_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, apecs_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, apecs_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, apecs_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -410,6 +410,7 @@ static device_method_t cia_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, cia_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, cia_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, cia_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -202,6 +202,8 @@ static device_method_t irongate_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, irongate_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, irongate_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, irongate_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/rman.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <machine/swiz.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <alpha/pci/lcareg.h>
|
||||
#include <alpha/pci/lcavar.h>
|
||||
@ -184,6 +185,7 @@ static device_method_t lca_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, lca_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, lca_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, lca_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -76,11 +76,18 @@ SYSCTL_LONG(_hw_chipset, OID_AUTO, dense, CTLFLAG_RD, &chipset_dense, 0,
|
||||
SYSCTL_LONG(_hw_chipset, OID_AUTO, hae_mask, CTLFLAG_RD, &chipset_hae_mask, 0,
|
||||
"PCI chipset mask for HAE register");
|
||||
|
||||
void
|
||||
alpha_platform_assign_pciintr(pcicfgregs *cfg)
|
||||
int
|
||||
alpha_pci_route_interrupt(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
if(platform.pci_intr_map)
|
||||
platform.pci_intr_map((void *)cfg);
|
||||
/*
|
||||
* Validate requested pin number.
|
||||
*/
|
||||
if ((pin < 1) || (pin > 4))
|
||||
return(255);
|
||||
|
||||
if (platform.pci_intr_route)
|
||||
return(platform.pci_intr_route(bus, dev, pin));
|
||||
return(255);
|
||||
}
|
||||
|
||||
#if NISA > 0
|
||||
|
@ -382,7 +382,7 @@ t2_attach(device_t dev)
|
||||
*/
|
||||
|
||||
static int
|
||||
t2_ICIC_slot_to_STDIO_irq(pcicfgregs *cfg)
|
||||
t2_ICIC_slot_to_STDIO_irq(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
|
||||
int ret_irq = 0;
|
||||
@ -391,36 +391,42 @@ t2_ICIC_slot_to_STDIO_irq(pcicfgregs *cfg)
|
||||
* Return the interrupt pin number for the PCI slots.
|
||||
*/
|
||||
|
||||
if ((cfg->intpin < 1) || (cfg->intpin > 4))
|
||||
return(-1);
|
||||
|
||||
/* Generate the proper interrupt conversion for the physical
|
||||
/*
|
||||
* Generate the proper interrupt conversion for the physical
|
||||
* PCI slots (for both the primary PCI slots and those behind
|
||||
* a PPB). */
|
||||
|
||||
if ((cfg->slot >= 6) && (cfg->slot <= 9)) {
|
||||
ret_irq = (32 + (4 * (cfg->slot - 6))) +
|
||||
(cfg->intpin - 1) + (16 * cfg->secondarybus);
|
||||
* a PPB).
|
||||
*/
|
||||
/*
|
||||
* XXX This code is wrong; we need to determine the correct
|
||||
* swizzle for devices behind the onboard PCI:PCI bridge
|
||||
* and ensure that the generic bridge code doesn't try to
|
||||
* reroute them.
|
||||
*/
|
||||
if ((pci_get_slot(dev) >= 6) && (pci_get_slot(dev) <= 9)) {
|
||||
ret_irq = (32 + (4 * (pci_get_slot(dev) - 6))) +
|
||||
(pin - 1) + (16 * pci_get_bus(dev));
|
||||
return (ret_irq);
|
||||
}
|
||||
|
||||
/* Convert the NCR810A chip behind the PPB */
|
||||
if (cfg->slot == 1) {
|
||||
if (pci_get_slot(dev) == 1) {
|
||||
ret_irq = 28;
|
||||
return (ret_irq);
|
||||
}
|
||||
|
||||
/* Convert the NCR810A chip on the primary PCI bus or the
|
||||
/*
|
||||
* Convert the NCR810A chip on the primary PCI bus or the
|
||||
* TULIP chip behind the PPB. There is no system that has
|
||||
* both, so there really is no sharing going on although it
|
||||
* looks like it. */
|
||||
if ( (cfg->slot == 4) || (cfg->slot == 0) ) {
|
||||
* looks like it.
|
||||
*/
|
||||
if ((pci_get_slot(dev) == 4) || (pci_get_slot(dev) == 0)) {
|
||||
ret_irq = 24;
|
||||
return (ret_irq);
|
||||
}
|
||||
|
||||
printf("ICIC invalid pci slot: 0x%x intpin: 0x%x bus num:0x%x\n",
|
||||
cfg->slot, cfg->intpin, cfg->bus);
|
||||
pci_get_slot(dev), pin, pci_get_bus(dev));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@ -429,59 +435,54 @@ t2_ICIC_slot_to_STDIO_irq(pcicfgregs *cfg)
|
||||
*/
|
||||
|
||||
static int
|
||||
t2_pci0_slot_to_STDIO_irq(pcicfgregs *cfg)
|
||||
t2_pci0_slot_to_STDIO_irq(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
|
||||
switch(cfg->slot) {
|
||||
switch(pci_get_slot(dev)) {
|
||||
case 0: /* ethernet (tulip) port */
|
||||
return(0x2);
|
||||
case 1: /* scsi 810 */
|
||||
return(0x1);
|
||||
case 6: /* optional slot 0 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1: return(0x0);
|
||||
case 2: return(0x18);
|
||||
case 3: return(0x1a);
|
||||
case 4: return(0x1d);
|
||||
}
|
||||
case 7: /* optional slot 1 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1: return(0x4);
|
||||
case 2: return(0x19);
|
||||
case 3: return(0x1b);
|
||||
case 4: return(0x1e);
|
||||
}
|
||||
case 8: /* optional slot 2 */
|
||||
switch (cfg->intpin) {
|
||||
switch (pin) {
|
||||
case 1: return(0x5);
|
||||
case 2: return(0x14);
|
||||
case 3: return(0x1c);
|
||||
case 4: return(0x1f);
|
||||
}
|
||||
default: /* invalid slot */
|
||||
printf("PCI slot %d unknown\n", cfg->slot);
|
||||
printf("PCI slot %d unknown\n", pci_get_slot(dev));
|
||||
return(-1);
|
||||
}
|
||||
printf("invalid pci0 intpin slot: 0x%x intpin: 0x%x\n",
|
||||
cfg->slot, cfg->intpin);
|
||||
pci_get_slot(dev), pin);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
t2_intr_map(void *arg)
|
||||
int
|
||||
t2_intr_route(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
pcicfgregs *cfg;
|
||||
|
||||
cfg = (pcicfgregs *)arg;
|
||||
if (pci_int_type[0]) {
|
||||
t2_ICIC_slot_to_STDIO_irq(cfg);
|
||||
return (t2_ICIC_slot_to_STDIO_irq(bus, dev, pin));
|
||||
} else {
|
||||
t2_pci0_slot_to_STDIO_irq(cfg);
|
||||
return (t2_pci0_slot_to_STDIO_irq(bus, dev, pin));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* magical mystery table partly obtained from Linux
|
||||
* at least some of their values for PCI masks
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/rman.h>
|
||||
#include <pci/pcivar.h>
|
||||
#include <machine/swiz.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <alpha/pci/t2reg.h>
|
||||
#include <alpha/pci/t2var.h>
|
||||
@ -190,6 +191,7 @@ static device_method_t t2_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, t2_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, t2_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, t2_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -29,4 +29,4 @@
|
||||
extern vm_offset_t sable_lynx_base;
|
||||
|
||||
extern void t2_init(void);
|
||||
void t2_intr_map(void *);
|
||||
extern int t2_intr_route(device_t, device_t, int);
|
||||
|
@ -276,6 +276,7 @@ static device_method_t tsunami_pcib_methods[] = {
|
||||
DEVMETHOD(pcib_maxslots, tsunami_pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, tsunami_pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, tsunami_pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -71,9 +71,9 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
|
||||
/* route interrupt */
|
||||
|
||||
static int
|
||||
nexus_pcib_route_interrupt(device_t bus, int device, int pin)
|
||||
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
return(pci_cfgintr(nexus_get_pcibus(bus), device, pin));
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin));
|
||||
}
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include <machine/segments.h>
|
||||
#include <machine/pc/bios.h>
|
||||
|
||||
#ifdef APIC_IO
|
||||
#include <machine/smp.h>
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#include "pcib_if.h"
|
||||
|
||||
static int cfgmech;
|
||||
@ -112,16 +116,62 @@ pci_cfgregopen(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read configuration space register
|
||||
* Read configuration space register
|
||||
*/
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
return(usebios ?
|
||||
pcibios_cfgread(bus, slot, func, reg, bytes) :
|
||||
pcireg_cfgread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
#ifdef APIC_IO
|
||||
/*
|
||||
* If we are using the APIC, the contents of the intline register will probably
|
||||
* be wrong (since they are set up for use with the PIC.
|
||||
* Rather than rewrite these registers (maybe that would be smarter) we trap
|
||||
* attempts to read them and translate to our private vector numbers.
|
||||
*/
|
||||
if ((reg == PCIR_INTLINE) && (bytes == 1)) {
|
||||
int pin, line, airq;
|
||||
|
||||
pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
|
||||
line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
|
||||
|
||||
if (pin != 0) {
|
||||
int airq;
|
||||
|
||||
airq = pci_apic_irq(bus, slot, pin);
|
||||
if (airq >= 0) {
|
||||
/* PCI specific entry found in MP table */
|
||||
if (airq != line)
|
||||
undirect_pci_irq(line);
|
||||
return(airq);
|
||||
} else {
|
||||
/*
|
||||
* PCI interrupts might be redirected to the
|
||||
* ISA bus according to some MP tables. Use the
|
||||
* same methods as used by the ISA devices
|
||||
* devices to find the proper IOAPIC int pin.
|
||||
*/
|
||||
airq = isa_apic_irq(line);
|
||||
if ((airq >= 0) && (airq != line)) {
|
||||
/* XXX: undirect_pci_irq() ? */
|
||||
undirect_isa_irq(line);
|
||||
return(airq);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(line);
|
||||
}
|
||||
#endif /* APIC_IO */
|
||||
return(pci_do_cfgregread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write configuration space register
|
||||
*/
|
||||
|
128
sys/dev/pci/eisa_pci.c
Normal file
128
sys/dev/pci/eisa_pci.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*-
|
||||
* Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCI:EISA bridge support
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
static int eisab_probe(device_t dev);
|
||||
static int eisab_attach(device_t dev);
|
||||
|
||||
static device_method_t eisab_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, eisab_probe),
|
||||
DEVMETHOD(device_attach, eisab_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t eisab_driver = {
|
||||
"eisab",
|
||||
eisab_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static devclass_t eisab_devclass;
|
||||
|
||||
DRIVER_MODULE(eisab, pci, eisab_driver, eisab_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
eisab_probe(device_t dev)
|
||||
{
|
||||
int matched = 0;
|
||||
|
||||
/*
|
||||
* Generic match by class/subclass.
|
||||
*/
|
||||
if ((pci_get_class(dev) == PCIC_BRIDGE) &&
|
||||
(pci_get_subclass(dev) == PCIS_BRIDGE_EISA))
|
||||
matched = 1;
|
||||
|
||||
/*
|
||||
* Some bridges don't correctly report their class.
|
||||
*/
|
||||
switch (pci_get_devid(dev)) {
|
||||
case 0x04828086: /* reports PCI-HOST class (!) */
|
||||
matched = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
device_set_desc(dev, "PCI-EISA bridge");
|
||||
return(-10000);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
eisab_attach(device_t dev)
|
||||
{
|
||||
device_t child;
|
||||
|
||||
/*
|
||||
* Attach an EISA bus. Note that we can only have one EISA bus.
|
||||
*/
|
||||
child = device_add_child(dev, "eisa", 0);
|
||||
if (child != NULL)
|
||||
return(bus_generic_attach(dev));
|
||||
|
||||
/*
|
||||
* Attach an ISA bus as well (should this be a child of EISA?)
|
||||
*/
|
||||
child = device_add_child(dev, "isa", 0);
|
||||
if (child != NULL)
|
||||
bus_generic_attach(dev);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
116
sys/dev/pci/fixup_pci.c
Normal file
116
sys/dev/pci/fixup_pci.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
/*
|
||||
* Chipset fixups.
|
||||
*
|
||||
* These routines are invoked during the probe phase for devices which
|
||||
* typically don't have specific device drivers, but which require
|
||||
* some cleaning up.
|
||||
*/
|
||||
|
||||
static int fixup_pci_probe(device_t dev);
|
||||
static void fixbushigh_i1225(device_t dev);
|
||||
static void fixwsc_natoma(device_t dev);
|
||||
|
||||
static device_method_t fixup_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, fixup_pci_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t fixup_pci_driver = {
|
||||
"fixup_pci",
|
||||
fixup_pci_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static devclass_t fixup_pci_devclass;
|
||||
|
||||
DRIVER_MODULE(fixup_pci, pci, fixup_pci_driver, fixup_pci_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
fixup_pci_probe(device_t dev)
|
||||
{
|
||||
switch (pci_get_devid(dev)) {
|
||||
case 0x12258086: /* Intel 82454KX/GX (Orion) */
|
||||
fixbushigh_i1225(dev);
|
||||
break;
|
||||
case 0x12378086: /* Intel 82440FX (Natoma) */
|
||||
fixwsc_natoma(dev);
|
||||
break;
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static void
|
||||
fixbushigh_i1225(device_t dev)
|
||||
{
|
||||
int supbus;
|
||||
|
||||
supbus = pci_read_config(dev, 0x41, 1);
|
||||
if (supbus != 0xff) {
|
||||
pci_set_secondarybus(dev, supbus + 1);
|
||||
pci_set_subordinatebus(dev, supbus + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fixwsc_natoma(device_t dev)
|
||||
{
|
||||
int pmccfg;
|
||||
|
||||
pmccfg = pci_read_config(dev, 0x50, 2);
|
||||
#if defined(SMP)
|
||||
if (pmccfg & 0x8000) {
|
||||
printf("Correcting Natoma config for SMP\n");
|
||||
pmccfg &= ~0x8000;
|
||||
pci_write_config(dev, 0x50, 2, pmccfg);
|
||||
}
|
||||
#else
|
||||
if ((pmccfg & 0x8000) == 0) {
|
||||
printf("Correcting Natoma config for non-SMP\n");
|
||||
pmccfg |= 0x8000;
|
||||
pci_write_config(dev, 0x50, 2, pmccfg);
|
||||
}
|
||||
#endif
|
||||
}
|
70
sys/dev/pci/ignore_pci.c
Normal file
70
sys/dev/pci/ignore_pci.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 'Ignore' driver - eats devices that show up errnoeously on PCI
|
||||
* but shouldn't ever be listed or handled by a driver.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
static int ignore_pci_probe(device_t dev);
|
||||
|
||||
static device_method_t ignore_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ignore_pci_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ignore_pci_driver = {
|
||||
"ignore_pci",
|
||||
ignore_pci_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static devclass_t ignore_pci_devclass;
|
||||
|
||||
DRIVER_MODULE(ignore_pci, pci, ignore_pci_driver, ignore_pci_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
ignore_pci_probe(device_t dev)
|
||||
{
|
||||
switch (pci_get_devid(dev)) {
|
||||
case 0x10001042ul: /* SMC 37C665 */
|
||||
device_set_desc(dev, "ignored");
|
||||
device_quiet(dev);
|
||||
return(-10000);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
161
sys/dev/pci/isa_pci.c
Normal file
161
sys/dev/pci/isa_pci.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*-
|
||||
* Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCI:ISA bridge support
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
static int isab_probe(device_t dev);
|
||||
static int isab_attach(device_t dev);
|
||||
|
||||
static device_method_t isab_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, isab_probe),
|
||||
DEVMETHOD(device_attach, isab_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t isab_driver = {
|
||||
"isab",
|
||||
isab_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static devclass_t isab_devclass;
|
||||
|
||||
DRIVER_MODULE(isab, pci, isab_driver, isab_devclass, 0, 0);
|
||||
|
||||
/*
|
||||
* XXX we need to add a quirk list here for bridges that don't correctly
|
||||
* report themselves.
|
||||
*/
|
||||
static int
|
||||
isab_probe(device_t dev)
|
||||
{
|
||||
int matched = 0;
|
||||
|
||||
/*
|
||||
* Try for a generic match based on class/subclass.
|
||||
*/
|
||||
if ((pci_get_class(dev) == PCIC_BRIDGE) &&
|
||||
(pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
|
||||
matched = 1;
|
||||
/*
|
||||
* Some bridges don't report the ISA bus correctly.
|
||||
* (Note that some of the devices listed here probably do, we will
|
||||
* kvetch about this below and request updates.)
|
||||
*/
|
||||
switch (pci_get_devid(dev)) {
|
||||
case 0x04848086: /* Intel 82378ZB/82378IB */
|
||||
case 0x122e8086: /* Intel 82371FB */
|
||||
case 0x70008086: /* Intel 82371SB */
|
||||
case 0x71108086: /* Intel 82371AB */
|
||||
case 0x71988086: /* Intel 82443MX */
|
||||
case 0x24108086: /* Intel 82801AA (ICH) */
|
||||
case 0x24208086: /* Intel 82801AB (ICH0) */
|
||||
case 0x24408086: /* Intel 82801BA (ICH2) */
|
||||
case 0x00061004: /* VLSI 82C593 */
|
||||
case 0x05861106: /* VIA 82C586 */
|
||||
case 0x05961106: /* VIA 82C596 PCI-ISA */
|
||||
case 0x06861106: /* VIA 82C686 PCI-ISA */
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x153310b9: /* AcerLabs M1533 */
|
||||
case 0x154310b9: /* AcerLabs M1543 */
|
||||
case 0x00081039: /* SiS 85c503 */
|
||||
case 0x00001078: /* Cyrix Cx5510 */
|
||||
case 0x01001078: /* Cyrix Cx5530 */
|
||||
case 0xc7001045: /* OPTi 82C700 (FireStar) */
|
||||
case 0x00011033: /* NEC 0001 (C-bus) */
|
||||
case 0x002c1033: /* NEC 002C (C-bus) */
|
||||
case 0x003b1033: /* NEC 003B (C-bus) */
|
||||
case 0x886a1060: /* UMC UM8886 ISA */
|
||||
case 0x02001166: /* ServerWorks IB6566 PCI */
|
||||
matched = 1;
|
||||
/*
|
||||
* Report redundant matches (debugging)
|
||||
*/
|
||||
if ((pci_get_class(dev) == PCIC_BRIDGE) &&
|
||||
(pci_get_subclass(dev) == PCIS_BRIDGE_ISA)) {
|
||||
printf("** REDUNDANT ISA BRIDGE MATCH FOR DEVICE 0x%08x\n", pci_get_devid(dev));
|
||||
printf("** Please report to msmith@freebsd.org\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
device_set_desc(dev, "PCI-ISA bridge");
|
||||
return(-10000);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
isab_attach(device_t dev)
|
||||
{
|
||||
device_t child;
|
||||
|
||||
/*
|
||||
* Attach an ISA bus. Note that we can only have one ISA bus.
|
||||
*/
|
||||
child = device_add_child(dev, "isa", 0);
|
||||
if (child != NULL)
|
||||
return(bus_generic_attach(dev));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -29,13 +29,11 @@
|
||||
|
||||
#include "opt_bus.h"
|
||||
|
||||
#include "opt_simos.h"
|
||||
#include "opt_compat_oldpci.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -50,7 +48,6 @@
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/md_var.h> /* For the Alpha */
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <pci/pcireg.h>
|
||||
@ -58,13 +55,9 @@
|
||||
|
||||
#include "pcib_if.h"
|
||||
|
||||
#ifdef __alpha__
|
||||
#include <machine/rpb.h>
|
||||
#endif
|
||||
|
||||
#ifdef APIC_IO
|
||||
#include <machine/smp.h>
|
||||
#endif /* APIC_IO */
|
||||
static char *pci_vendordata;
|
||||
static size_t pci_vendordata_size;
|
||||
static char *pci_describe_device(device_t dev);
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
@ -178,52 +171,6 @@ pci_fixancient(pcicfgregs *cfg)
|
||||
cfg->hdrtype = 1;
|
||||
}
|
||||
|
||||
/* read config data specific to header type 1 device (PCI to PCI bridge) */
|
||||
|
||||
static void *
|
||||
pci_readppb(device_t pcib, int b, int s, int f)
|
||||
{
|
||||
pcih1cfgregs *p;
|
||||
|
||||
p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
bzero(p, sizeof *p);
|
||||
|
||||
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
|
||||
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
|
||||
|
||||
p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
|
||||
|
||||
p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_IOBASEH_1, 2),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_IOBASEL_1, 1));
|
||||
p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_IOLIMITH_1, 2),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_IOLIMITL_1, 1));
|
||||
|
||||
p->membase = PCI_PPBMEMBASE (0,
|
||||
PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_MEMBASE_1, 2));
|
||||
p->memlimit = PCI_PPBMEMLIMIT (0,
|
||||
PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_MEMLIMIT_1, 2));
|
||||
|
||||
p->pmembase = PCI_PPBMEMBASE (
|
||||
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
|
||||
|
||||
p->pmemlimit = PCI_PPBMEMLIMIT (
|
||||
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,
|
||||
PCIR_PMLIMITH_1, 4),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
/* read config data specific to header type 2 device (PCI to CardBus bridge) */
|
||||
|
||||
static void *
|
||||
@ -231,12 +178,10 @@ pci_readpcb(device_t pcib, int b, int s, int f)
|
||||
{
|
||||
pcih2cfgregs *p;
|
||||
|
||||
p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK);
|
||||
p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
bzero(p, sizeof *p);
|
||||
|
||||
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2);
|
||||
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2);
|
||||
|
||||
@ -271,10 +216,7 @@ pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
|
||||
case 1:
|
||||
cfg->subvendor = REG(PCIR_SUBVEND_1, 2);
|
||||
cfg->subdevice = REG(PCIR_SUBDEV_1, 2);
|
||||
cfg->secondarybus = REG(PCIR_SECBUS_1, 1);
|
||||
cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1);
|
||||
cfg->nummaps = PCI_MAXMAPS_1;
|
||||
cfg->hdrspec = pci_readppb(pcib, b, s, f);
|
||||
break;
|
||||
case 2:
|
||||
cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
|
||||
@ -304,10 +246,9 @@ pci_read_device(device_t pcib, int b, int s, int f)
|
||||
|
||||
if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) {
|
||||
devlist_entry = malloc(sizeof(struct pci_devinfo),
|
||||
M_DEVBUF, M_WAITOK);
|
||||
M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
if (devlist_entry == NULL)
|
||||
return (NULL);
|
||||
bzero(devlist_entry, sizeof *devlist_entry);
|
||||
|
||||
cfg = &devlist_entry->cfg;
|
||||
|
||||
@ -327,37 +268,6 @@ pci_read_device(device_t pcib, int b, int s, int f)
|
||||
cfg->lattimer = REG(PCIR_LATTIMER, 1);
|
||||
cfg->intpin = REG(PCIR_INTPIN, 1);
|
||||
cfg->intline = REG(PCIR_INTLINE, 1);
|
||||
#ifdef __alpha__
|
||||
alpha_platform_assign_pciintr(cfg);
|
||||
#endif
|
||||
|
||||
#ifdef APIC_IO
|
||||
if (cfg->intpin != 0) {
|
||||
int airq;
|
||||
|
||||
airq = pci_apic_irq(cfg->bus, cfg->slot, cfg->intpin);
|
||||
if (airq >= 0) {
|
||||
/* PCI specific entry found in MP table */
|
||||
if (airq != cfg->intline) {
|
||||
undirect_pci_irq(cfg->intline);
|
||||
cfg->intline = airq;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* PCI interrupts might be redirected to the
|
||||
* ISA bus according to some MP tables. Use the
|
||||
* same methods as used by the ISA devices
|
||||
* devices to find the proper IOAPIC int pin.
|
||||
*/
|
||||
airq = isa_apic_irq(cfg->intline);
|
||||
if ((airq >= 0) && (airq != cfg->intline)) {
|
||||
/* XXX: undirect_pci_irq() ? */
|
||||
undirect_isa_irq(cfg->intline);
|
||||
cfg->intline = airq;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* APIC_IO */
|
||||
|
||||
cfg->mingnt = REG(PCIR_MINGNT, 1);
|
||||
cfg->maxlat = REG(PCIR_MAXLAT, 1);
|
||||
@ -1076,6 +986,7 @@ static int
|
||||
pci_probe(device_t dev)
|
||||
{
|
||||
static int once, busno;
|
||||
caddr_t vendordata, info;
|
||||
|
||||
device_set_desc(dev, "PCI bus");
|
||||
|
||||
@ -1095,6 +1006,14 @@ pci_probe(device_t dev)
|
||||
|
||||
if (!once) {
|
||||
make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci");
|
||||
if ((vendordata = preload_search_by_type("pci_vendor_data")) != NULL) {
|
||||
info = preload_search_info(vendordata, MODINFO_ADDR);
|
||||
pci_vendordata = *(char **)info;
|
||||
info = preload_search_info(vendordata, MODINFO_SIZE);
|
||||
pci_vendordata_size = *(size_t *)info;
|
||||
/* terminate the database */
|
||||
pci_vendordata[pci_vendordata_size] = '\n';
|
||||
}
|
||||
once++;
|
||||
}
|
||||
|
||||
@ -1157,42 +1076,212 @@ pci_print_child(device_t dev, device_t child)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int class;
|
||||
int subclass;
|
||||
char *desc;
|
||||
} pci_nomatch_tab[] = {
|
||||
{PCIC_OLD, -1, "old"},
|
||||
{PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"},
|
||||
{PCIC_OLD, PCIS_OLD_VGA, "VGA-compatible display device"},
|
||||
{PCIC_STORAGE, -1, "mass storage"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SCSI, "SCSI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IDE, "ATA"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_FLOPPY, "floppy disk"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IPI, "IPI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_RAID, "RAID"},
|
||||
{PCIC_NETWORK, -1, "network"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ETHERNET, "ethernet"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_TOKENRING, "token ring"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_FDDI, "fddi"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ATM, "ATM"},
|
||||
{PCIC_DISPLAY, -1, "display"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_VGA, "VGA"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_XGA, "XGA"},
|
||||
{PCIC_MULTIMEDIA, -1, "multimedia"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_VIDEO, "video"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_AUDIO, "audio"},
|
||||
{PCIC_MEMORY, -1, "memory"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_RAM, "RAM"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_FLASH, "flash"},
|
||||
{PCIC_BRIDGE, -1, "bridge"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_HOST, "HOST-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_ISA, "PCI-ISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_EISA, "PCI-EISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_MCA, "PCI-MCA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCI, "PCI-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCMCIA, "PCI-PCMCIA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_NUBUS, "PCI-NuBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_CARDBUS, "PCI-CardBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_OTHER, "PCI-unknown"},
|
||||
{PCIC_SIMPLECOMM, -1, "simple comms"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_UART, "UART"}, /* could detect 16550 */
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_PAR, "parallel port"},
|
||||
{PCIC_BASEPERIPH, -1, "base peripheral"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PIC, "interrupt controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_DMA, "DMA controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_TIMER, "timer"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, "realtime clock"},
|
||||
{PCIC_INPUTDEV, -1, "input device"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, "keyboard"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,"digitizer"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_MOUSE, "mouse"},
|
||||
{PCIC_DOCKING, -1, "docking station"},
|
||||
{PCIC_PROCESSOR, -1, "processor"},
|
||||
{PCIC_SERIALBUS, -1, "serial bus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FW, "FireWire"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_ACCESS, "AccessBus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SSA, "SSA"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_USB, "USB"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FC, "Fibre Channel"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SMBUS, "SMBus"},
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
pci_probe_nomatch(device_t dev, device_t child)
|
||||
{
|
||||
struct pci_devinfo *dinfo;
|
||||
pcicfgregs *cfg;
|
||||
const char *desc;
|
||||
int unknown;
|
||||
|
||||
unknown = 0;
|
||||
dinfo = device_get_ivars(child);
|
||||
cfg = &dinfo->cfg;
|
||||
desc = pci_ata_match(child);
|
||||
if (!desc) desc = pci_usb_match(child);
|
||||
if (!desc) desc = pci_vga_match(child);
|
||||
if (!desc) desc = pci_chip_match(child);
|
||||
if (!desc) {
|
||||
desc = "unknown card";
|
||||
unknown++;
|
||||
int i;
|
||||
char *cp, *scp, *device;
|
||||
|
||||
/*
|
||||
* Look for a listing for this device in a loaded device database.
|
||||
*/
|
||||
if ((device = pci_describe_device(child)) != NULL) {
|
||||
printf("<%s>", device);
|
||||
free(device, M_DEVBUF);
|
||||
} else {
|
||||
/*
|
||||
* Scan the class/subclass descriptions for a general description.
|
||||
*/
|
||||
cp = "unknown";
|
||||
scp = NULL;
|
||||
for (i = 0; pci_nomatch_tab[i].desc != NULL; i++) {
|
||||
if (pci_nomatch_tab[i].class == pci_get_class(child)) {
|
||||
if (pci_nomatch_tab[i].subclass == -1) {
|
||||
cp = pci_nomatch_tab[i].desc;
|
||||
} else if (pci_nomatch_tab[i].subclass == pci_get_subclass(child)) {
|
||||
scp = pci_nomatch_tab[i].desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
device_printf(dev, "<%s%s%s>",
|
||||
cp ? : "",
|
||||
((cp != NULL) && (scp != NULL)) ? ", " : "",
|
||||
scp ? : "");
|
||||
}
|
||||
device_printf(dev, "<%s>", desc);
|
||||
if (bootverbose || unknown) {
|
||||
printf(" (vendor=0x%04x, dev=0x%04x)",
|
||||
cfg->vendor,
|
||||
cfg->device);
|
||||
}
|
||||
printf(" at %d.%d",
|
||||
pci_get_slot(child),
|
||||
pci_get_function(child));
|
||||
if (cfg->intpin > 0 && cfg->intline != 255) {
|
||||
printf(" irq %d", cfg->intline);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf(" at %d:%d (no driver attached)\n",
|
||||
pci_get_slot(child),
|
||||
pci_get_function(child));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the PCI device database, if loaded, and return a pointer to a
|
||||
* description of the device.
|
||||
*
|
||||
* The database is flat text formatted as follows:
|
||||
*
|
||||
* Any line not in a valid format is ignored.
|
||||
* Lines are terminated with newline '\n' characters.
|
||||
*
|
||||
* A VENDOR line consists of the 4 digit (hex) vendor code, a TAB, then
|
||||
* the vendor name.
|
||||
*
|
||||
* A DEVICE line is entered immediately below the corresponding VENDOR ID.
|
||||
* - devices cannot be listed without a corresponding VENDOR line.
|
||||
* A DEVICE line consists of a TAB, the 4 digit (hex) device code,
|
||||
* another TAB, then the device name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assuming (ptr) points to the beginning of a line in the database,
|
||||
* return the vendor or device and description of the next entry.
|
||||
* The value of (vendor) or (device) inappropriate for the entry type
|
||||
* is set to -1. Returns nonzero at the end of the database.
|
||||
*
|
||||
* Note that this is slightly unrobust in the face of corrupt data;
|
||||
* we attempt to safeguard against this by spamming the end of the
|
||||
* database with a newline when we initialise.
|
||||
*/
|
||||
static int
|
||||
pci_describe_parse_line(char **ptr, int *vendor, int *device, char **desc)
|
||||
{
|
||||
char *cp = *ptr;
|
||||
|
||||
*device = -1;
|
||||
*vendor = -1;
|
||||
*desc = NULL;
|
||||
for (;;) {
|
||||
if ((cp - pci_vendordata) >= pci_vendordata_size)
|
||||
return(1);
|
||||
|
||||
/* vendor entry? */
|
||||
if (sscanf(cp, "%x\t%80[^\n]", vendor, *desc) == 2)
|
||||
break;
|
||||
/* device entry? */
|
||||
if (sscanf(cp, "\t%x\t%80[^\n]", device, *desc) == 2)
|
||||
break;
|
||||
|
||||
/* skip to next line */
|
||||
while (*cp != '\n')
|
||||
cp++;
|
||||
cp++;
|
||||
}
|
||||
*ptr = cp;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static char *
|
||||
pci_describe_device(device_t dev)
|
||||
{
|
||||
int vendor, device;
|
||||
char *desc, *vp, *dp, *line;
|
||||
|
||||
desc = vp = dp = NULL;
|
||||
|
||||
/*
|
||||
* If we have no vendor data, we can't do anything.
|
||||
*/
|
||||
if (pci_vendordata == NULL)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Scan the vendor data looking for this device
|
||||
*/
|
||||
line = pci_vendordata;
|
||||
if ((vp = malloc(80, M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
goto out;
|
||||
for (;;) {
|
||||
if (pci_describe_parse_line(&line, &vendor, &device, &vp))
|
||||
goto out;
|
||||
if (vendor == pci_get_vendor(dev))
|
||||
break;
|
||||
}
|
||||
if ((dp = malloc(80, M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
goto out;
|
||||
for (;;) {
|
||||
if (pci_describe_parse_line(&line, &vendor, &device, &dp))
|
||||
goto out;
|
||||
if (vendor != -1) {
|
||||
*dp = 0;
|
||||
break;
|
||||
}
|
||||
if (device == pci_get_device(dev))
|
||||
break;
|
||||
}
|
||||
if ((desc = malloc(strlen(vp) + strlen(dp) + 3, M_DEVBUF, M_NOWAIT)) != NULL)
|
||||
sprintf(desc, "%s%s%s", vp, (dp[0] != 0) ? ", " : "", dp);
|
||||
out:
|
||||
if (vp != NULL)
|
||||
free(vp, M_DEVBUF);
|
||||
if (dp != NULL)
|
||||
free(dp, M_DEVBUF);
|
||||
return(desc);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||
{
|
||||
@ -1309,16 +1398,17 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
* XXX add support here for SYS_RES_IOPORT and SYS_RES_MEMORY
|
||||
*/
|
||||
if (device_get_parent(child) == dev) {
|
||||
if ((type == SYS_RES_IRQ) && (cfg->intline == 255)) {
|
||||
#ifdef __i386__
|
||||
cfg->intline = PCIB_ROUTE_INTERRUPT(
|
||||
device_get_parent(dev), pci_get_slot(child),
|
||||
cfg->intpin);
|
||||
#endif /* __i386__ */
|
||||
/*
|
||||
* If device doesn't have an interrupt routed, and is deserving of
|
||||
* an interrupt, try to assign it one.
|
||||
*/
|
||||
if ((type == SYS_RES_IRQ) && (cfg->intline == 255) && (cfg->intpin != 0)) {
|
||||
cfg->intline = PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
|
||||
cfg->intpin);
|
||||
if (cfg->intline != 255) {
|
||||
pci_write_config(child, PCIR_INTLINE, cfg->intline, 1);
|
||||
resource_list_add(rl, SYS_RES_IRQ, 0,
|
||||
cfg->intline, cfg->intline, 1);
|
||||
cfg->intline, cfg->intline, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1419,7 +1509,7 @@ static device_method_t pci_methods[] = {
|
||||
static driver_t pci_driver = {
|
||||
"pci",
|
||||
pci_methods,
|
||||
1, /* no softc */
|
||||
0, /* no softc */
|
||||
};
|
||||
DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0);
|
||||
DRIVER_MODULE(pci, acpi_pcib, pci_driver, pci_devclass, pci_modevent, 0);
|
||||
|
334
sys/dev/pci/pci_pci.c
Normal file
334
sys/dev/pci/pci_pci.c
Normal file
@ -0,0 +1,334 @@
|
||||
/*-
|
||||
* Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCI:PCI bridge support.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
#include "pcib_if.h"
|
||||
|
||||
/*
|
||||
* Bridge-specific data.
|
||||
*/
|
||||
struct pcib_softc
|
||||
{
|
||||
device_t dev;
|
||||
u_int8_t secbus; /* secondary bus number */
|
||||
u_int8_t subbus; /* subordinate bus number */
|
||||
pci_addr_t pmembase; /* base address of prefetchable memory */
|
||||
pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
|
||||
u_int32_t membase; /* base address of memory window */
|
||||
u_int32_t memlimit; /* topmost address of memory window */
|
||||
u_int32_t iobase; /* base address of port window */
|
||||
u_int32_t iolimit; /* topmost address of port window */
|
||||
u_int16_t secstat; /* secondary bus status register */
|
||||
u_int16_t bridgectl; /* bridge control register */
|
||||
u_int8_t seclat; /* secondary bus latency timer */
|
||||
};
|
||||
|
||||
static int pcib_probe(device_t dev);
|
||||
static int pcib_attach(device_t dev);
|
||||
static int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
|
||||
static int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
|
||||
static struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags);
|
||||
static int pcib_maxslots(device_t dev);
|
||||
static u_int32_t pcib_read_config(device_t dev, int b, int s, int f, int reg, int width);
|
||||
static void pcib_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, int width);
|
||||
static int pcib_route_interrupt(device_t pcib, device_t dev, int pin);
|
||||
|
||||
static device_method_t pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pcib_probe),
|
||||
DEVMETHOD(device_attach, pcib_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
/* pcib interface */
|
||||
DEVMETHOD(pcib_maxslots, pcib_maxslots),
|
||||
DEVMETHOD(pcib_read_config, pcib_read_config),
|
||||
DEVMETHOD(pcib_write_config, pcib_write_config),
|
||||
DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t pcib_driver = {
|
||||
"pcib",
|
||||
pcib_methods,
|
||||
sizeof(struct pcib_softc),
|
||||
};
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
|
||||
|
||||
/*
|
||||
* Generic device interface
|
||||
*/
|
||||
static int
|
||||
pcib_probe(device_t dev)
|
||||
{
|
||||
if ((pci_get_class(dev) == PCIC_BRIDGE) &&
|
||||
(pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) {
|
||||
device_set_desc(dev, "PCI-PCI bridge");
|
||||
return(-10000);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
pcib_attach(device_t dev)
|
||||
{
|
||||
struct pcib_softc *sc;
|
||||
device_t pcib, child;
|
||||
int b, s, f;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
pcib = device_get_parent(dev);
|
||||
b = pci_get_bus(dev);
|
||||
s = pci_get_slot(dev);
|
||||
f = pci_get_function(dev);
|
||||
|
||||
sc->secbus = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECBUS_1, 1);
|
||||
sc->subbus = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SUBBUS_1, 1);
|
||||
sc->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
|
||||
sc->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
|
||||
sc->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
|
||||
sc->iobase = PCI_PPBIOBASE(PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASEH_1, 2),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASEL_1, 1));
|
||||
sc->iolimit = PCI_PPBIOLIMIT(PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMITH_1, 2),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMITL_1, 1));
|
||||
sc->membase = PCI_PPBMEMBASE(0, PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE_1, 2));
|
||||
sc->memlimit = PCI_PPBMEMLIMIT(0, PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT_1, 2));
|
||||
sc->pmembase = PCI_PPBMEMBASE((pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
|
||||
sc->pmemlimit = PCI_PPBMEMLIMIT((pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,PCIR_PMLIMITH_1, 4),
|
||||
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(dev, " secondary bus %d\n", sc->secbus);
|
||||
device_printf(dev, " subordinate bus %d\n", sc->subbus);
|
||||
device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit);
|
||||
device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit);
|
||||
device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX If the secondary bus number is zero, we should assign a bus number
|
||||
* since the BIOS hasn't, then initialise the bridge.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX If the subordinate bus number is less than the secondary bus number,
|
||||
* we should pick a better value. One sensible alternative would be to
|
||||
* pick 255; the only tradeoff here is that configuration transactions
|
||||
* would be more widely routed than absolutely necessary.
|
||||
*/
|
||||
|
||||
if (sc->secbus != 0) {
|
||||
child = device_add_child(dev, "pci", -1);
|
||||
if (child != NULL)
|
||||
return(bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
/* no secondary bus; we should have fixed this */
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||
{
|
||||
struct pcib_softc *sc = device_get_softc(dev);
|
||||
|
||||
switch (which) {
|
||||
case PCIB_IVAR_BUS:
|
||||
*result = sc->secbus;
|
||||
return(0);
|
||||
}
|
||||
return(ENOENT);
|
||||
}
|
||||
|
||||
static int
|
||||
pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
|
||||
{
|
||||
struct pcib_softc *sc = device_get_softc(dev);
|
||||
|
||||
switch (which) {
|
||||
case PCIB_IVAR_BUS:
|
||||
sc->secbus = value;
|
||||
break;
|
||||
}
|
||||
return(ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to trap resource allocation requests and ensure that the bridge
|
||||
* is set up to, or capable of handling them.
|
||||
*/
|
||||
static struct resource *
|
||||
pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct pcib_softc *sc = device_get_softc(dev);
|
||||
|
||||
/*
|
||||
* If this is a "default" allocation against this rid, we can't work
|
||||
* out where it's coming from (we should actually never see these) so we
|
||||
* just have to punt.
|
||||
*/
|
||||
if ((start == 0) && (end == ~0)) {
|
||||
device_printf(dev, "can't decode default resource id %d for %s%d, bypassing\n",
|
||||
*rid, device_get_name(child), device_get_unit(child));
|
||||
} else {
|
||||
/*
|
||||
* Fail the allocation for this range if it's not supported.
|
||||
*
|
||||
* XXX we should probably just fix up the bridge decode and soldier on.
|
||||
*/
|
||||
switch (type) {
|
||||
case SYS_RES_IOPORT:
|
||||
if ((start < sc->iobase) || (end > sc->iolimit)) {
|
||||
device_printf(dev, "device %s%d requested unsupported I/O range 0x%lx-0x%lx"
|
||||
" (decoding 0x%x-0x%x)\n",
|
||||
device_get_name(child), device_get_unit(child), start, end,
|
||||
sc->iobase, sc->iolimit);
|
||||
return(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* XXX will have to decide whether the device making the request is asking
|
||||
* for prefetchable memory or not. If it's coming from another bridge
|
||||
* down the line, do we assume not, or ask the bridge to pass in another
|
||||
* flag as the request bubbles up?
|
||||
*/
|
||||
case SYS_RES_MEMORY:
|
||||
if (((start < sc->membase) || (end > sc->memlimit)) &&
|
||||
((start < sc->pmembase) || (end > sc->pmemlimit))) {
|
||||
device_printf(dev, "device %s%d requested unsupported memory range 0x%lx-0x%lx"
|
||||
" (decoding 0x%x-0x%x, 0x%x-0x%x)\n",
|
||||
device_get_name(child), device_get_unit(child), start, end,
|
||||
sc->membase, sc->memlimit, sc->pmembase, sc->pmemlimit);
|
||||
return(NULL);
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
device_printf(sc->dev, "resource request type %d 0x%lx-0x%lx decodes OK\n",
|
||||
type, start, end);
|
||||
/*
|
||||
* Bridge is OK decoding this resource, so pass it up.
|
||||
*/
|
||||
return(bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* PCIB interface.
|
||||
*/
|
||||
static int
|
||||
pcib_maxslots(device_t dev)
|
||||
{
|
||||
return(31);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we are a child of a PCI bus, its parent must support the pcib interface.
|
||||
*/
|
||||
static u_int32_t
|
||||
pcib_read_config(device_t dev, int b, int s, int f, int reg, int width)
|
||||
{
|
||||
return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width));
|
||||
}
|
||||
|
||||
static void
|
||||
pcib_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, int width)
|
||||
{
|
||||
PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Route an interrupt across a PCI bridge.
|
||||
*/
|
||||
static int
|
||||
pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
device_t bus;
|
||||
int parent_intpin;
|
||||
int intnum;
|
||||
|
||||
/*
|
||||
*
|
||||
* The PCI standard defines a swizzle of the child-side device/intpin to
|
||||
* the parent-side intpin as follows.
|
||||
*
|
||||
* device = device on child bus
|
||||
* child_intpin = intpin on child bus slot (0-3)
|
||||
* parent_intpin = intpin on parent bus slot (0-3)
|
||||
*
|
||||
* parent_intpin = (device + child_intpin) % 4
|
||||
*/
|
||||
parent_intpin = (pci_get_slot(pcib) + (pin - 1)) % 4;
|
||||
|
||||
/*
|
||||
* Our parent is a PCI bus. Its parent must export the pcib interface
|
||||
* which includes the ability to route interrupts.
|
||||
*/
|
||||
bus = device_get_parent(pcib);
|
||||
intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1);
|
||||
device_printf(pcib, "routed slot %d INT%c to irq %d\n", pci_get_slot(dev),
|
||||
'A' + pin - 1, intnum);
|
||||
return(intnum);
|
||||
}
|
@ -144,13 +144,6 @@ struct pci_devinfo {
|
||||
};
|
||||
#endif
|
||||
|
||||
/* externally visible functions */
|
||||
|
||||
const char *pci_ata_match(struct device *dev);
|
||||
const char *pci_usb_match(struct device *dev);
|
||||
const char *pci_vga_match(struct device *dev);
|
||||
const char *pci_chip_match(struct device *dev);
|
||||
|
||||
/* low level PCI config register functions provided by pcibus.c */
|
||||
|
||||
int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
|
||||
|
75
sys/dev/pci/vga_pci.c
Normal file
75
sys/dev/pci/vga_pci.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stub handler for PCI VGA-compatible adapters.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
|
||||
static int vga_pci_probe(device_t dev);
|
||||
|
||||
static device_method_t vga_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, vga_pci_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t vga_pci_driver = {
|
||||
"vga_pci",
|
||||
vga_pci_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static devclass_t vga_pci_devclass;
|
||||
|
||||
DRIVER_MODULE(vga_pci, pci, vga_pci_driver, vga_pci_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
vga_pci_probe(device_t dev)
|
||||
{
|
||||
if ((pci_get_class(dev) == PCIC_OLD) &&
|
||||
(pci_get_subclass(dev) == PCIS_OLD_VGA)) {
|
||||
device_set_desc(dev, "VGA-compatible display device");
|
||||
return(-10000);
|
||||
}
|
||||
if ((pci_get_class(dev) == PCIC_DISPLAY) &&
|
||||
(pci_get_subclass(dev) == PCIS_DISPLAY_VGA)) {
|
||||
device_set_desc(dev, "VGA-compatible display device");
|
||||
return(-10000);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
@ -71,9 +71,9 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
|
||||
/* route interrupt */
|
||||
|
||||
static int
|
||||
nexus_pcib_route_interrupt(device_t bus, int device, int pin)
|
||||
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
return(pci_cfgintr(nexus_get_pcibus(bus), device, pin));
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin));
|
||||
}
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include <machine/segments.h>
|
||||
#include <machine/pc/bios.h>
|
||||
|
||||
#ifdef APIC_IO
|
||||
#include <machine/smp.h>
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#include "pcib_if.h"
|
||||
|
||||
static int cfgmech;
|
||||
@ -112,16 +116,62 @@ pci_cfgregopen(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read configuration space register
|
||||
* Read configuration space register
|
||||
*/
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
return(usebios ?
|
||||
pcibios_cfgread(bus, slot, func, reg, bytes) :
|
||||
pcireg_cfgread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
#ifdef APIC_IO
|
||||
/*
|
||||
* If we are using the APIC, the contents of the intline register will probably
|
||||
* be wrong (since they are set up for use with the PIC.
|
||||
* Rather than rewrite these registers (maybe that would be smarter) we trap
|
||||
* attempts to read them and translate to our private vector numbers.
|
||||
*/
|
||||
if ((reg == PCIR_INTLINE) && (bytes == 1)) {
|
||||
int pin, line, airq;
|
||||
|
||||
pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
|
||||
line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
|
||||
|
||||
if (pin != 0) {
|
||||
int airq;
|
||||
|
||||
airq = pci_apic_irq(bus, slot, pin);
|
||||
if (airq >= 0) {
|
||||
/* PCI specific entry found in MP table */
|
||||
if (airq != line)
|
||||
undirect_pci_irq(line);
|
||||
return(airq);
|
||||
} else {
|
||||
/*
|
||||
* PCI interrupts might be redirected to the
|
||||
* ISA bus according to some MP tables. Use the
|
||||
* same methods as used by the ISA devices
|
||||
* devices to find the proper IOAPIC int pin.
|
||||
*/
|
||||
airq = isa_apic_irq(line);
|
||||
if ((airq >= 0) && (airq != line)) {
|
||||
/* XXX: undirect_pci_irq() ? */
|
||||
undirect_isa_irq(line);
|
||||
return(airq);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(line);
|
||||
}
|
||||
#endif /* APIC_IO */
|
||||
return(pci_do_cfgregread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write configuration space register
|
||||
*/
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include <machine/segments.h>
|
||||
#include <machine/pc/bios.h>
|
||||
|
||||
#ifdef APIC_IO
|
||||
#include <machine/smp.h>
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#include "pcib_if.h"
|
||||
|
||||
static int cfgmech;
|
||||
@ -112,16 +116,62 @@ pci_cfgregopen(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read configuration space register
|
||||
* Read configuration space register
|
||||
*/
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
return(usebios ?
|
||||
pcibios_cfgread(bus, slot, func, reg, bytes) :
|
||||
pcireg_cfgread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
|
||||
{
|
||||
#ifdef APIC_IO
|
||||
/*
|
||||
* If we are using the APIC, the contents of the intline register will probably
|
||||
* be wrong (since they are set up for use with the PIC.
|
||||
* Rather than rewrite these registers (maybe that would be smarter) we trap
|
||||
* attempts to read them and translate to our private vector numbers.
|
||||
*/
|
||||
if ((reg == PCIR_INTLINE) && (bytes == 1)) {
|
||||
int pin, line, airq;
|
||||
|
||||
pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
|
||||
line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
|
||||
|
||||
if (pin != 0) {
|
||||
int airq;
|
||||
|
||||
airq = pci_apic_irq(bus, slot, pin);
|
||||
if (airq >= 0) {
|
||||
/* PCI specific entry found in MP table */
|
||||
if (airq != line)
|
||||
undirect_pci_irq(line);
|
||||
return(airq);
|
||||
} else {
|
||||
/*
|
||||
* PCI interrupts might be redirected to the
|
||||
* ISA bus according to some MP tables. Use the
|
||||
* same methods as used by the ISA devices
|
||||
* devices to find the proper IOAPIC int pin.
|
||||
*/
|
||||
airq = isa_apic_irq(line);
|
||||
if ((airq >= 0) && (airq != line)) {
|
||||
/* XXX: undirect_pci_irq() ? */
|
||||
undirect_isa_irq(line);
|
||||
return(airq);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(line);
|
||||
}
|
||||
#endif /* APIC_IO */
|
||||
return(pci_do_cfgregread(bus, slot, func, reg, bytes));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write configuration space register
|
||||
*/
|
||||
|
@ -6,6 +6,6 @@ SRCS = agp.c agp_intel.c agp_via.c agp_sis.c agp_ali.c agp_amd.c
|
||||
SRCS += agp_i810.c agp_if.c
|
||||
SRCS += device_if.h bus_if.h agp_if.h pci_if.h
|
||||
SRCS += opt_bdg.h opt_bus.h opt_pci.h
|
||||
MFILES = kern/device_if.m kern/bus_if.m pci/agp_if.m pci/pci_if.m
|
||||
MFILES = kern/device_if.m kern/bus_if.m pci/agp_if.m dev/pci/pci_if.m
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
KMOD= ng_tty
|
||||
SRCS= ng_tty.c device_if.h bus_if.h pci_if.h
|
||||
MFILES= kern/device_if.m kern/bus_if.m pci/agp_if.m pci/pci_if.m
|
||||
MFILES= kern/device_if.m kern/bus_if.m pci/agp_if.m dev/pci/pci_if.m
|
||||
NOMAN=
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -7,7 +7,7 @@ MAINTAINER= gallatin@FreeBSD.org
|
||||
KMOD= osf1
|
||||
SRCS= osf1_ioctl.c osf1_misc.c osf1_signal.c osf1_sysent.c \
|
||||
osf1_mount.c imgact_osf1.c osf1_sysvec.c opt_compat.h \
|
||||
opt_simos.h opt_nfs.h vnode_if.h
|
||||
opt_simos.h opt_nfs.h device_if.h bus_if.h vnode_if.h
|
||||
|
||||
#CFLAGS+= -g
|
||||
EXPORT_SYMS= _osf1
|
||||
|
1420
sys/pci/pci.c
1420
sys/pci/pci.c
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 1998 Doug Rabson
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
#include <sys/bus.h>
|
||||
|
||||
INTERFACE pci;
|
||||
|
||||
METHOD u_int32_t read_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int reg;
|
||||
int width;
|
||||
};
|
||||
|
||||
METHOD void write_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int reg;
|
||||
u_int32_t val;
|
||||
int width;
|
||||
};
|
@ -1,81 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2000 Doug Rabson
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
#include <sys/bus.h>
|
||||
|
||||
INTERFACE pcib;
|
||||
|
||||
#
|
||||
# Return the number of slots on the attached PCI bus.
|
||||
#
|
||||
METHOD int maxslots {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
#
|
||||
# Read configuration space on the PCI bus. The bus, slot and func
|
||||
# arguments determine the device which is being read and the reg
|
||||
# argument is a byte offset into configuration space for that
|
||||
# device. The width argument (which should be 1, 2 or 4) specifies how
|
||||
# many byte of configuration space to read from that offset.
|
||||
#
|
||||
METHOD u_int32_t read_config {
|
||||
device_t dev;
|
||||
u_int bus;
|
||||
u_int slot;
|
||||
u_int func;
|
||||
u_int reg;
|
||||
int width;
|
||||
};
|
||||
|
||||
#
|
||||
# Write configuration space on the PCI bus. The bus, slot and func
|
||||
# arguments determine the device which is being written and the reg
|
||||
# argument is a byte offset into configuration space for that
|
||||
# device. The value field is written to the configuration space, with
|
||||
# the number of bytes written depending on the width argument.
|
||||
#
|
||||
METHOD void write_config {
|
||||
device_t dev;
|
||||
u_int bus;
|
||||
u_int slot;
|
||||
u_int func;
|
||||
u_int reg;
|
||||
u_int32_t value;
|
||||
int width;
|
||||
};
|
||||
|
||||
#
|
||||
# Route an interrupt. Returns a value suitable for stuffing into
|
||||
# a device's interrupt register.
|
||||
#
|
||||
METHOD int route_interrupt {
|
||||
device_t dev;
|
||||
int device;
|
||||
int pin;
|
||||
};
|
261
sys/pci/pcireg.h
261
sys/pci/pcireg.h
@ -1,261 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCIM_xxx: mask to locate subfield in register
|
||||
* PCIR_xxx: config register offset
|
||||
* PCIC_xxx: device class
|
||||
* PCIS_xxx: device subclass
|
||||
* PCIP_xxx: device programming interface
|
||||
* PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
|
||||
* PCID_xxx: device ID
|
||||
*/
|
||||
|
||||
/* some PCI bus constants */
|
||||
|
||||
#define PCI_BUSMAX 255
|
||||
#define PCI_SLOTMAX 31
|
||||
#define PCI_FUNCMAX 7
|
||||
#define PCI_REGMAX 255
|
||||
|
||||
/* PCI config header registers for all devices */
|
||||
|
||||
#define PCIR_DEVVENDOR 0x00
|
||||
#define PCIR_VENDOR 0x00
|
||||
#define PCIR_DEVICE 0x02
|
||||
#define PCIR_COMMAND 0x04
|
||||
#define PCIM_CMD_PORTEN 0x0001
|
||||
#define PCIM_CMD_MEMEN 0x0002
|
||||
#define PCIM_CMD_MWRICEN 0x0010
|
||||
#define PCIM_CMD_BUSMASTEREN 0x0004
|
||||
#define PCIM_CMD_PERRESPEN 0x0040
|
||||
#define PCIR_STATUS 0x06
|
||||
#define PCIR_REVID 0x08
|
||||
#define PCIR_PROGIF 0x09
|
||||
#define PCIR_SUBCLASS 0x0a
|
||||
#define PCIR_CLASS 0x0b
|
||||
#define PCIR_CACHELNSZ 0x0c
|
||||
#define PCIR_LATTIMER 0x0d
|
||||
#define PCIR_HEADERTYPE 0x0e
|
||||
#define PCIM_MFDEV 0x80
|
||||
#define PCIR_BIST 0x0f
|
||||
|
||||
/* config registers for header type 0 devices */
|
||||
|
||||
#define PCIR_MAPS 0x10
|
||||
#define PCIR_CARDBUSCIS 0x28
|
||||
#define PCIR_SUBVEND_0 0x2c
|
||||
#define PCIR_SUBDEV_0 0x2e
|
||||
#define PCIR_BIOS 0x30
|
||||
#define PCIM_BIOS_ENABLE 0x01
|
||||
#define PCIR_INTLINE 0x3c
|
||||
#define PCIR_INTPIN 0x3d
|
||||
#define PCIR_MINGNT 0x3e
|
||||
#define PCIR_MAXLAT 0x3f
|
||||
|
||||
/* config registers for header type 1 devices */
|
||||
|
||||
#define PCIR_SECSTAT_1 0 /**/
|
||||
|
||||
#define PCIR_PRIBUS_1 0x18
|
||||
#define PCIR_SECBUS_1 0x19
|
||||
#define PCIR_SUBBUS_1 0x1a
|
||||
#define PCIR_SECLAT_1 0x1b
|
||||
|
||||
#define PCIR_IOBASEL_1 0x1c
|
||||
#define PCIR_IOLIMITL_1 0x1d
|
||||
#define PCIR_IOBASEH_1 0 /**/
|
||||
#define PCIR_IOLIMITH_1 0 /**/
|
||||
|
||||
#define PCIR_MEMBASE_1 0x20
|
||||
#define PCIR_MEMLIMIT_1 0x22
|
||||
|
||||
#define PCIR_PMBASEL_1 0x24
|
||||
#define PCIR_PMLIMITL_1 0x26
|
||||
#define PCIR_PMBASEH_1 0 /**/
|
||||
#define PCIR_PMLIMITH_1 0 /**/
|
||||
|
||||
#define PCIR_BRIDGECTL_1 0 /**/
|
||||
|
||||
#define PCIR_SUBVEND_1 0x34
|
||||
#define PCIR_SUBDEV_1 0x36
|
||||
|
||||
/* config registers for header type 2 devices */
|
||||
|
||||
#define PCIR_SECSTAT_2 0x16
|
||||
|
||||
#define PCIR_PRIBUS_2 0x18
|
||||
#define PCIR_SECBUS_2 0x19
|
||||
#define PCIR_SUBBUS_2 0x1a
|
||||
#define PCIR_SECLAT_2 0x1b
|
||||
|
||||
#define PCIR_MEMBASE0_2 0x1c
|
||||
#define PCIR_MEMLIMIT0_2 0x20
|
||||
#define PCIR_MEMBASE1_2 0x24
|
||||
#define PCIR_MEMLIMIT1_2 0x28
|
||||
#define PCIR_IOBASE0_2 0x2c
|
||||
#define PCIR_IOLIMIT0_2 0x30
|
||||
#define PCIR_IOBASE1_2 0x34
|
||||
#define PCIR_IOLIMIT1_2 0x38
|
||||
|
||||
#define PCIR_BRIDGECTL_2 0x3e
|
||||
|
||||
#define PCIR_SUBVEND_2 0x40
|
||||
#define PCIR_SUBDEV_2 0x42
|
||||
|
||||
#define PCIR_PCCARDIF_2 0x44
|
||||
|
||||
/* PCI device class, subclass and programming interface definitions */
|
||||
|
||||
#define PCIC_OLD 0x00
|
||||
#define PCIS_OLD_NONVGA 0x00
|
||||
#define PCIS_OLD_VGA 0x01
|
||||
|
||||
#define PCIC_STORAGE 0x01
|
||||
#define PCIS_STORAGE_SCSI 0x00
|
||||
#define PCIS_STORAGE_IDE 0x01
|
||||
#define PCIP_STORAGE_IDE_MODEPRIM 0x01
|
||||
#define PCIP_STORAGE_IDE_PROGINDPRIM 0x02
|
||||
#define PCIP_STORAGE_IDE_MODESEC 0x04
|
||||
#define PCIP_STORAGE_IDE_PROGINDSEC 0x08
|
||||
#define PCIP_STORAGE_IDE_MASTERDEV 0x80
|
||||
#define PCIS_STORAGE_FLOPPY 0x02
|
||||
#define PCIS_STORAGE_IPI 0x03
|
||||
#define PCIS_STORAGE_RAID 0x04
|
||||
#define PCIS_STORAGE_OTHER 0x80
|
||||
|
||||
#define PCIC_NETWORK 0x02
|
||||
#define PCIS_NETWORK_ETHERNET 0x00
|
||||
#define PCIS_NETWORK_TOKENRING 0x01
|
||||
#define PCIS_NETWORK_FDDI 0x02
|
||||
#define PCIS_NETWORK_ATM 0x03
|
||||
#define PCIS_NETWORK_OTHER 0x80
|
||||
|
||||
#define PCIC_DISPLAY 0x03
|
||||
#define PCIS_DISPLAY_VGA 0x00
|
||||
#define PCIS_DISPLAY_XGA 0x01
|
||||
#define PCIS_DISPLAY_OTHER 0x80
|
||||
|
||||
#define PCIC_MULTIMEDIA 0x04
|
||||
#define PCIS_MULTIMEDIA_VIDEO 0x00
|
||||
#define PCIS_MULTIMEDIA_AUDIO 0x01
|
||||
#define PCIS_MULTIMEDIA_OTHER 0x80
|
||||
|
||||
#define PCIC_MEMORY 0x05
|
||||
#define PCIS_MEMORY_RAM 0x00
|
||||
#define PCIS_MEMORY_FLASH 0x01
|
||||
#define PCIS_MEMORY_OTHER 0x80
|
||||
|
||||
#define PCIC_BRIDGE 0x06
|
||||
#define PCIS_BRIDGE_HOST 0x00
|
||||
#define PCIS_BRIDGE_ISA 0x01
|
||||
#define PCIS_BRIDGE_EISA 0x02
|
||||
#define PCIS_BRIDGE_MCA 0x03
|
||||
#define PCIS_BRIDGE_PCI 0x04
|
||||
#define PCIS_BRIDGE_PCMCIA 0x05
|
||||
#define PCIS_BRIDGE_NUBUS 0x06
|
||||
#define PCIS_BRIDGE_CARDBUS 0x07
|
||||
#define PCIS_BRIDGE_OTHER 0x80
|
||||
|
||||
#define PCIC_SIMPLECOMM 0x07
|
||||
#define PCIS_SIMPLECOMM_UART 0x00
|
||||
#define PCIP_SIMPLECOMM_UART_16550A 0x02
|
||||
#define PCIS_SIMPLECOMM_PAR 0x01
|
||||
#define PCIS_SIMPLECOMM_OTHER 0x80
|
||||
|
||||
#define PCIC_BASEPERIPH 0x08
|
||||
#define PCIS_BASEPERIPH_PIC 0x00
|
||||
#define PCIS_BASEPERIPH_DMA 0x01
|
||||
#define PCIS_BASEPERIPH_TIMER 0x02
|
||||
#define PCIS_BASEPERIPH_RTC 0x03
|
||||
#define PCIS_BASEPERIPH_OTHER 0x80
|
||||
|
||||
#define PCIC_INPUTDEV 0x09
|
||||
#define PCIS_INPUTDEV_KEYBOARD 0x00
|
||||
#define PCIS_INPUTDEV_DIGITIZER 0x01
|
||||
#define PCIS_INPUTDEV_MOUSE 0x02
|
||||
#define PCIS_INPUTDEV_OTHER 0x80
|
||||
|
||||
#define PCIC_DOCKING 0x0a
|
||||
#define PCIS_DOCKING_GENERIC 0x00
|
||||
#define PCIS_DOCKING_OTHER 0x80
|
||||
|
||||
#define PCIC_PROCESSOR 0x0b
|
||||
#define PCIS_PROCESSOR_386 0x00
|
||||
#define PCIS_PROCESSOR_486 0x01
|
||||
#define PCIS_PROCESSOR_PENTIUM 0x02
|
||||
#define PCIS_PROCESSOR_ALPHA 0x10
|
||||
#define PCIS_PROCESSOR_POWERPC 0x20
|
||||
#define PCIS_PROCESSOR_COPROC 0x40
|
||||
|
||||
#define PCIC_SERIALBUS 0x0c
|
||||
#define PCIS_SERIALBUS_FW 0x00
|
||||
#define PCIS_SERIALBUS_ACCESS 0x01
|
||||
#define PCIS_SERIALBUS_SSA 0x02
|
||||
#define PCIS_SERIALBUS_USB 0x03
|
||||
#define PCIS_SERIALBUS_FC 0x04
|
||||
#define PCIS_SERIALBUS_SMBUS 0x05
|
||||
|
||||
#define PCIC_OTHER 0xff
|
||||
|
||||
/* some PCI vendor definitions (only used to identify ancient devices !!! */
|
||||
|
||||
#define PCIV_INTEL 0x8086
|
||||
|
||||
#define PCID_INTEL_SATURN 0x0483
|
||||
#define PCID_INTEL_ORION 0x84c4
|
||||
|
||||
/* for compatibility to FreeBSD-2.2 and 3.x versions of PCI code */
|
||||
|
||||
#if defined(_KERNEL) && !defined(KLD_MODULE)
|
||||
#include "opt_compat_oldpci.h"
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_OLDPCI
|
||||
|
||||
#define PCI_ID_REG 0x00
|
||||
#define PCI_COMMAND_STATUS_REG 0x04
|
||||
#define PCI_COMMAND_IO_ENABLE 0x00000001
|
||||
#define PCI_COMMAND_MEM_ENABLE 0x00000002
|
||||
#define PCI_CLASS_REG 0x08
|
||||
#define PCI_CLASS_MASK 0xff000000
|
||||
#define PCI_SUBCLASS_MASK 0x00ff0000
|
||||
#define PCI_REVISION_MASK 0x000000ff
|
||||
#define PCI_CLASS_PREHISTORIC 0x00000000
|
||||
#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
|
||||
#define PCI_CLASS_MASS_STORAGE 0x01000000
|
||||
#define PCI_CLASS_DISPLAY 0x03000000
|
||||
#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000
|
||||
#define PCI_CLASS_BRIDGE 0x06000000
|
||||
#define PCI_MAP_REG_START 0x10
|
||||
#define PCI_MAP_REG_END 0x28
|
||||
#define PCI_MAP_IO 0x00000001
|
||||
#define PCI_INTERRUPT_REG 0x3c
|
||||
|
||||
#endif /* COMPAT_OLDPCI */
|
1992
sys/pci/pcisupport.c
1992
sys/pci/pcisupport.c
File diff suppressed because it is too large
Load Diff
332
sys/pci/pcivar.h
332
sys/pci/pcivar.h
@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PCIVAR_H_
|
||||
#define _PCIVAR_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/* some PCI bus constants */
|
||||
|
||||
#define PCI_BUSMAX 255 /* highest supported bus number */
|
||||
#define PCI_SLOTMAX 31 /* highest supported slot number */
|
||||
#define PCI_FUNCMAX 7 /* highest supported function number */
|
||||
#define PCI_REGMAX 255 /* highest supported config register addr. */
|
||||
|
||||
#define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */
|
||||
#define PCI_MAXMAPS_1 2 /* max. no. of maps for PCI to PCI bridge */
|
||||
#define PCI_MAXMAPS_2 1 /* max. no. of maps for CardBus bridge */
|
||||
|
||||
/* pci_addr_t covers this system's PCI bus address space: 32 or 64 bit */
|
||||
|
||||
#ifdef PCI_A64
|
||||
typedef u_int64_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
|
||||
#else
|
||||
typedef u_int32_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
|
||||
#endif
|
||||
|
||||
/* config header information common to all header types */
|
||||
|
||||
typedef struct pcicfg {
|
||||
struct device *dev; /* device which owns this */
|
||||
void *hdrspec; /* pointer to header type specific data */
|
||||
|
||||
u_int16_t subvendor; /* card vendor ID */
|
||||
u_int16_t subdevice; /* card device ID, assigned by card vendor */
|
||||
u_int16_t vendor; /* chip vendor ID */
|
||||
u_int16_t device; /* chip device ID, assigned by chip vendor */
|
||||
|
||||
u_int16_t cmdreg; /* disable/enable chip and PCI options */
|
||||
u_int16_t statreg; /* supported PCI features and error state */
|
||||
|
||||
u_int8_t baseclass; /* chip PCI class */
|
||||
u_int8_t subclass; /* chip PCI subclass */
|
||||
u_int8_t progif; /* chip PCI programming interface */
|
||||
u_int8_t revid; /* chip revision ID */
|
||||
|
||||
u_int8_t hdrtype; /* chip config header type */
|
||||
u_int8_t cachelnsz; /* cache line size in 4byte units */
|
||||
u_int8_t intpin; /* PCI interrupt pin */
|
||||
u_int8_t intline; /* interrupt line (IRQ for PC arch) */
|
||||
|
||||
u_int8_t mingnt; /* min. useful bus grant time in 250ns units */
|
||||
u_int8_t maxlat; /* max. tolerated bus grant latency in 250ns */
|
||||
u_int8_t lattimer; /* latency timer in units of 30ns bus cycles */
|
||||
|
||||
u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
|
||||
u_int8_t nummaps; /* actual number of PCI maps used */
|
||||
|
||||
u_int8_t bus; /* config space bus address */
|
||||
u_int8_t slot; /* config space slot address */
|
||||
u_int8_t func; /* config space function number */
|
||||
|
||||
u_int8_t secondarybus; /* bus on secondary side of bridge, if any */
|
||||
u_int8_t subordinatebus; /* topmost bus number behind bridge, if any */
|
||||
} pcicfgregs;
|
||||
|
||||
/* additional type 1 device config header information (PCI to PCI bridge) */
|
||||
|
||||
#ifdef PCI_A64
|
||||
#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
|
||||
#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
|
||||
#else
|
||||
#define PCI_PPBMEMBASE(h,l) (((l)<<16) & ~0xfffff)
|
||||
#define PCI_PPBMEMLIMIT(h,l) (((l)<<16) | 0xfffff)
|
||||
#endif /* PCI_A64 */
|
||||
|
||||
#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff)
|
||||
#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff)
|
||||
|
||||
typedef struct {
|
||||
pci_addr_t pmembase; /* base address of prefetchable memory */
|
||||
pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
|
||||
u_int32_t membase; /* base address of memory window */
|
||||
u_int32_t memlimit; /* topmost address of memory window */
|
||||
u_int32_t iobase; /* base address of port window */
|
||||
u_int32_t iolimit; /* topmost address of port window */
|
||||
u_int16_t secstat; /* secondary bus status register */
|
||||
u_int16_t bridgectl; /* bridge control register */
|
||||
u_int8_t seclat; /* CardBus latency timer */
|
||||
} pcih1cfgregs;
|
||||
|
||||
/* additional type 2 device config header information (CardBus bridge) */
|
||||
|
||||
typedef struct {
|
||||
u_int32_t membase0; /* base address of memory window */
|
||||
u_int32_t memlimit0; /* topmost address of memory window */
|
||||
u_int32_t membase1; /* base address of memory window */
|
||||
u_int32_t memlimit1; /* topmost address of memory window */
|
||||
u_int32_t iobase0; /* base address of port window */
|
||||
u_int32_t iolimit0; /* topmost address of port window */
|
||||
u_int32_t iobase1; /* base address of port window */
|
||||
u_int32_t iolimit1; /* topmost address of port window */
|
||||
u_int32_t pccardif; /* PC Card 16bit IF legacy more base addr. */
|
||||
u_int16_t secstat; /* secondary bus status register */
|
||||
u_int16_t bridgectl; /* bridge control register */
|
||||
u_int8_t seclat; /* CardBus latency timer */
|
||||
} pcih2cfgregs;
|
||||
|
||||
extern u_int32_t pci_numdevs;
|
||||
|
||||
/* Only if the prerequisites are present */
|
||||
#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
|
||||
struct pci_devinfo {
|
||||
STAILQ_ENTRY(pci_devinfo) pci_links;
|
||||
struct resource_list resources;
|
||||
pcicfgregs cfg;
|
||||
struct pci_conf conf;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* externally visible functions */
|
||||
|
||||
const char *pci_ata_match(struct device *dev);
|
||||
const char *pci_usb_match(struct device *dev);
|
||||
const char *pci_vga_match(struct device *dev);
|
||||
const char *pci_chip_match(struct device *dev);
|
||||
|
||||
/* low level PCI config register functions provided by pcibus.c */
|
||||
|
||||
int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
|
||||
void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
|
||||
|
||||
#ifdef __alpha__
|
||||
vm_offset_t pci_cvt_to_dense (vm_offset_t);
|
||||
vm_offset_t pci_cvt_to_bwx (vm_offset_t);
|
||||
#endif /* __alpha__ */
|
||||
|
||||
/* low level devlist operations for the 2.2 compatibility code in pci.c */
|
||||
pcicfgregs * pci_devlist_get_parent(pcicfgregs *cfg);
|
||||
|
||||
#ifdef _SYS_BUS_H_
|
||||
|
||||
#include "pci_if.h"
|
||||
|
||||
/*
|
||||
* Define pci-specific resource flags for accessing memory via dense
|
||||
* or bwx memory spaces. These flags are ignored on i386.
|
||||
*/
|
||||
#define PCI_RF_DENSE 0x10000
|
||||
#define PCI_RF_BWX 0x20000
|
||||
|
||||
enum pci_device_ivars {
|
||||
PCI_IVAR_SUBVENDOR,
|
||||
PCI_IVAR_SUBDEVICE,
|
||||
PCI_IVAR_VENDOR,
|
||||
PCI_IVAR_DEVICE,
|
||||
PCI_IVAR_DEVID,
|
||||
PCI_IVAR_CLASS,
|
||||
PCI_IVAR_SUBCLASS,
|
||||
PCI_IVAR_PROGIF,
|
||||
PCI_IVAR_REVID,
|
||||
PCI_IVAR_INTPIN,
|
||||
PCI_IVAR_IRQ,
|
||||
PCI_IVAR_BUS,
|
||||
PCI_IVAR_SLOT,
|
||||
PCI_IVAR_FUNCTION,
|
||||
PCI_IVAR_SECONDARYBUS,
|
||||
PCI_IVAR_SUBORDINATEBUS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Simplified accessors for pci devices
|
||||
*/
|
||||
#define PCI_ACCESSOR(A, B, T) \
|
||||
\
|
||||
static __inline T pci_get_ ## A(device_t dev) \
|
||||
{ \
|
||||
uintptr_t v; \
|
||||
BUS_READ_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, &v); \
|
||||
return (T) v; \
|
||||
} \
|
||||
\
|
||||
static __inline void pci_set_ ## A(device_t dev, T t) \
|
||||
{ \
|
||||
uintptr_t v = (uintptr_t) t; \
|
||||
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v); \
|
||||
}
|
||||
|
||||
PCI_ACCESSOR(subvendor, SUBVENDOR, u_int16_t)
|
||||
PCI_ACCESSOR(subdevice, SUBDEVICE, u_int16_t)
|
||||
PCI_ACCESSOR(vendor, VENDOR, u_int16_t)
|
||||
PCI_ACCESSOR(device, DEVICE, u_int16_t)
|
||||
PCI_ACCESSOR(devid, DEVID, u_int32_t)
|
||||
PCI_ACCESSOR(class, CLASS, u_int8_t)
|
||||
PCI_ACCESSOR(subclass, SUBCLASS, u_int8_t)
|
||||
PCI_ACCESSOR(progif, PROGIF, u_int8_t)
|
||||
PCI_ACCESSOR(revid, REVID, u_int8_t)
|
||||
PCI_ACCESSOR(intpin, INTPIN, u_int8_t)
|
||||
PCI_ACCESSOR(irq, IRQ, u_int8_t)
|
||||
PCI_ACCESSOR(bus, BUS, u_int8_t)
|
||||
PCI_ACCESSOR(slot, SLOT, u_int8_t)
|
||||
PCI_ACCESSOR(function, FUNCTION, u_int8_t)
|
||||
PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t)
|
||||
PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t)
|
||||
|
||||
#undef PCI_ACCESSOR
|
||||
|
||||
static __inline u_int32_t
|
||||
pci_read_config(device_t dev, int reg, int width)
|
||||
{
|
||||
return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
pci_write_config(device_t dev, int reg, u_int32_t val, int width)
|
||||
{
|
||||
PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ivars for pci bridges.
|
||||
*/
|
||||
|
||||
/*typedef enum pci_device_ivars pcib_device_ivars;*/
|
||||
enum pcib_device_ivars {
|
||||
PCIB_IVAR_BUS
|
||||
};
|
||||
|
||||
#define PCIB_ACCESSOR(A, B, T) \
|
||||
\
|
||||
static __inline T pcib_get_ ## A(device_t dev) \
|
||||
{ \
|
||||
uintptr_t v; \
|
||||
BUS_READ_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, &v); \
|
||||
return (T) v; \
|
||||
} \
|
||||
\
|
||||
static __inline void pcib_set_ ## A(device_t dev, T t) \
|
||||
{ \
|
||||
uintptr_t v = (uintptr_t) t; \
|
||||
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \
|
||||
}
|
||||
|
||||
PCIB_ACCESSOR(bus, BUS, u_int32_t)
|
||||
|
||||
#undef PCIB_ACCESSOR
|
||||
|
||||
#endif
|
||||
|
||||
/* for compatibility to FreeBSD-2.2 and 3.x versions of PCI code */
|
||||
|
||||
#if defined(_KERNEL) && !defined(KLD_MODULE)
|
||||
#include "opt_compat_oldpci.h"
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_OLDPCI
|
||||
|
||||
/* all this is going some day */
|
||||
|
||||
typedef pcicfgregs *pcici_t;
|
||||
typedef unsigned pcidi_t;
|
||||
typedef void pci_inthand_t(void *arg);
|
||||
|
||||
#define pci_max_burst_len (3)
|
||||
|
||||
/* just copied from old PCI code for now ... */
|
||||
|
||||
struct pci_device {
|
||||
char* pd_name;
|
||||
const char* (*pd_probe ) (pcici_t tag, pcidi_t type);
|
||||
void (*pd_attach) (pcici_t tag, int unit);
|
||||
u_long *pd_count;
|
||||
int (*pd_shutdown) (int, int);
|
||||
};
|
||||
|
||||
#ifdef __i386__
|
||||
typedef u_short pci_port_t;
|
||||
#else
|
||||
typedef u_int pci_port_t;
|
||||
#endif
|
||||
|
||||
u_long pci_conf_read (pcici_t tag, u_long reg);
|
||||
void pci_conf_write (pcici_t tag, u_long reg, u_long data);
|
||||
int pci_map_port (pcici_t tag, u_long reg, pci_port_t* pa);
|
||||
int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
|
||||
int pci_map_int (pcici_t tag, pci_inthand_t *handler, void *arg,
|
||||
intrmask_t *maskptr);
|
||||
int pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
|
||||
intrmask_t *maskptr, u_int flags);
|
||||
int pci_unmap_int (pcici_t tag);
|
||||
|
||||
pcici_t pci_get_parent_from_tag(pcici_t tag);
|
||||
int pci_get_bus_from_tag(pcici_t tag);
|
||||
|
||||
struct module;
|
||||
int compat_pci_handler (struct module *, int, void *);
|
||||
#define COMPAT_PCI_DRIVER(name, pcidata) \
|
||||
static moduledata_t name##_mod = { \
|
||||
#name, \
|
||||
compat_pci_handler, \
|
||||
&pcidata \
|
||||
}; \
|
||||
DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_ANY)
|
||||
#endif /* COMPAT_OLDPCI */
|
||||
|
||||
#endif /* _PCIVAR_H_ */
|
@ -71,7 +71,7 @@ int alpha_platform_pci_setup_intr(device_t dev, device_t child,
|
||||
void **cookiep);
|
||||
int alpha_platform_pci_teardown_intr(device_t dev, device_t child,
|
||||
struct resource *irq, void *cookie);
|
||||
int alpha_pci_route_interrupt(device_t bus, device_t dev, int pin);
|
||||
#endif
|
||||
void alpha_platform_assign_pciintr(struct pcicfg *cfg);
|
||||
|
||||
#endif /* !_MACHINE_MD_VAR_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user