devpccard, pci: fix pccard support and handle pci expansion roms
let pci.c deal with the special cardbus controller bar0 and expansion roms. handle apic interrupt routing for devices behind a cardbus slot. do not free the pcidev on card removal, as the drivers most certanly are not prepared to handle this yet. instead, we provide a pcidevfree() function that just unlinks the device from pcilist and the parent bridge.
This commit is contained in:
parent
3555843110
commit
a0404ff582
8 changed files with 283 additions and 218 deletions
|
@ -210,7 +210,7 @@ pcicfginit(void)
|
||||||
|
|
||||||
fmtinstall('T', tbdffmt);
|
fmtinstall('T', tbdffmt);
|
||||||
|
|
||||||
pciscan(0, &pciroot);
|
pciscan(0, &pciroot, nil);
|
||||||
if(pciroot == nil)
|
if(pciroot == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ pcicfginit(void)
|
||||||
list = &pciroot;
|
list = &pciroot;
|
||||||
for(bno = 0; bno <= pcimaxbno; bno++) {
|
for(bno = 0; bno <= pcimaxbno; bno++) {
|
||||||
int sbno = bno;
|
int sbno = bno;
|
||||||
bno = pciscan(bno, list);
|
bno = pciscan(bno, list, nil);
|
||||||
|
|
||||||
while(*list)
|
while(*list)
|
||||||
list = &(*list)->link;
|
list = &(*list)->link;
|
||||||
|
|
|
@ -101,7 +101,6 @@ enum {
|
||||||
|
|
||||||
PciPMC = 0xa4,
|
PciPMC = 0xa4,
|
||||||
|
|
||||||
Nbars = 6,
|
|
||||||
Ncmd = 10,
|
Ncmd = 10,
|
||||||
CBIRQ = 9,
|
CBIRQ = 9,
|
||||||
|
|
||||||
|
@ -346,7 +345,7 @@ engine(Cardbus *cb, int message)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: Invalid message %s in SlotEmpty state\n",
|
print("#Y%zd: Invalid message %s in SlotEmpty state\n",
|
||||||
cb - cbslots, messages[message]);
|
cb - cbslots, messages[message]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -365,7 +364,7 @@ engine(Cardbus *cb, int message)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: Invalid message %s in SlotFull state\n",
|
print("#Y%zd: Invalid message %s in SlotFull state\n",
|
||||||
cb - cbslots, messages[message]);
|
cb - cbslots, messages[message]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +382,7 @@ engine(Cardbus *cb, int message)
|
||||||
powerdown(cb);
|
powerdown(cb);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
print("#Y%ld: Invalid message %s in SlotPowered state\n",
|
print("#Y%zd: Invalid message %s in SlotPowered state\n",
|
||||||
cb - cbslots, messages[message]);
|
cb - cbslots, messages[message]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +398,7 @@ engine(Cardbus *cb, int message)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: Invalid message %s in SlotConfigured state\n",
|
print("#Y%zd: Invalid message %s in SlotConfigured state\n",
|
||||||
cb - cbslots, messages[message]);
|
cb - cbslots, messages[message]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +491,7 @@ cbinterrupt(Ureg *, void *)
|
||||||
rdreg(cb, Rcsc); /* Ack the interrupt */
|
rdreg(cb, Rcsc); /* Ack the interrupt */
|
||||||
|
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n",
|
print("#Y%zd: interrupt: event %.8lX, state %.8lX, (%s)\n",
|
||||||
cb - cbslots, event, state, states[cb->state]);
|
cb - cbslots, event, state, states[cb->state]);
|
||||||
|
|
||||||
if (event & SE_CCD) {
|
if (event & SE_CCD) {
|
||||||
|
@ -520,7 +519,6 @@ devpccardlink(void)
|
||||||
static int initialized;
|
static int initialized;
|
||||||
Pcidev *pci;
|
Pcidev *pci;
|
||||||
int i;
|
int i;
|
||||||
uchar intl;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (initialized)
|
if (initialized)
|
||||||
|
@ -539,9 +537,7 @@ devpccardlink(void)
|
||||||
|
|
||||||
/* Find all CardBus controllers */
|
/* Find all CardBus controllers */
|
||||||
pci = nil;
|
pci = nil;
|
||||||
intl = 0xff;
|
|
||||||
while ((pci = pcimatch(pci, 0, 0)) != nil) {
|
while ((pci = pcimatch(pci, 0, 0)) != nil) {
|
||||||
uvlong baddr;
|
|
||||||
Cardbus *cb;
|
Cardbus *cb;
|
||||||
uchar pin;
|
uchar pin;
|
||||||
|
|
||||||
|
@ -559,20 +555,20 @@ devpccardlink(void)
|
||||||
cb->pci = pci;
|
cb->pci = pci;
|
||||||
cb->variant = &variant[i];
|
cb->variant = &variant[i];
|
||||||
|
|
||||||
if (pci->vid != TI_vid) {
|
if(pci->mem[0].size == 0 || (pci->mem[0].bar & 0xF) != 0)
|
||||||
/*
|
continue;
|
||||||
* Gross hack, needs a fix. Inherit the mappings from
|
cb->regs = (ulong *)vmap(pci->mem[0].bar & ~0xFULL, pci->mem[0].size);
|
||||||
* 9load for the TIs (pb)
|
if(cb->regs == nil)
|
||||||
*/
|
continue;
|
||||||
pcicfgw32(pci, PciCBMBR0, 0xffffffff);
|
|
||||||
pcicfgw32(pci, PciCBMLR0, 0);
|
pcicfgw32(pci, PciCBMBR0, 0xffffffff);
|
||||||
pcicfgw32(pci, PciCBMBR1, 0xffffffff);
|
pcicfgw32(pci, PciCBMLR0, 0);
|
||||||
pcicfgw32(pci, PciCBMLR1, 0);
|
pcicfgw32(pci, PciCBMBR1, 0xffffffff);
|
||||||
pcicfgw32(pci, PciCBIBR0, 0xffffffff);
|
pcicfgw32(pci, PciCBMLR1, 0);
|
||||||
pcicfgw32(pci, PciCBILR0, 0);
|
pcicfgw32(pci, PciCBIBR0, 0xffffffff);
|
||||||
pcicfgw32(pci, PciCBIBR1, 0xffffffff);
|
pcicfgw32(pci, PciCBILR0, 0);
|
||||||
pcicfgw32(pci, PciCBILR1, 0);
|
pcicfgw32(pci, PciCBIBR1, 0xffffffff);
|
||||||
}
|
pcicfgw32(pci, PciCBILR1, 0);
|
||||||
|
|
||||||
/* Set up PCI bus numbers if needed. */
|
/* Set up PCI bus numbers if needed. */
|
||||||
if (pcicfgr8(pci, PciSBN) == 0) {
|
if (pcicfgr8(pci, PciSBN) == 0) {
|
||||||
|
@ -590,7 +586,7 @@ devpccardlink(void)
|
||||||
pcicfgw8(pci, PciINTL, pci->intl);
|
pcicfgw8(pci, PciINTL, pci->intl);
|
||||||
|
|
||||||
if (pci->intl == 0xff || pci->intl == 0)
|
if (pci->intl == 0xff || pci->intl == 0)
|
||||||
print("#Y%ld: No interrupt?\n", cb - cbslots);
|
print("#Y%zd: No interrupt?\n", cb - cbslots);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't you love standards! */
|
/* Don't you love standards! */
|
||||||
|
@ -632,30 +628,15 @@ devpccardlink(void)
|
||||||
pcicfgw8(cb->pci, 0x94, 0xCA);
|
pcicfgw8(cb->pci, 0x94, 0xCA);
|
||||||
pcicfgw8(cb->pci, 0xD4, 0xCA);
|
pcicfgw8(cb->pci, 0xD4, 0xCA);
|
||||||
}
|
}
|
||||||
|
|
||||||
baddr = pcicfgr32(cb->pci, PciBAR0);
|
|
||||||
if (baddr == 0) {
|
|
||||||
int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
|
|
||||||
baddr = upaalloc(-1ULL, size, size);
|
|
||||||
if(baddr == -1)
|
|
||||||
continue;
|
|
||||||
pcicfgw32(cb->pci, PciBAR0, (ulong)baddr);
|
|
||||||
cb->regs = (ulong *)vmap(baddr, size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cb->regs = (ulong *)vmap(baddr, 4096);
|
|
||||||
if(cb->regs == nil)
|
|
||||||
continue;
|
|
||||||
cb->state = SlotEmpty;
|
cb->state = SlotEmpty;
|
||||||
|
|
||||||
if (intl != 0xff && intl != pci->intl)
|
intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
|
||||||
intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
|
|
||||||
|
|
||||||
/* Don't really know what to do with this... */
|
/* Don't really know what to do with this... */
|
||||||
i82365probe(cb, LegacyAddr, LegacyAddr + 1);
|
i82365probe(cb, LegacyAddr, LegacyAddr + 1);
|
||||||
|
|
||||||
print("#Y%ld: %s, %.8lluX intl %d\n", cb - cbslots,
|
print("#Y%zd: %s, %.8lluX intl %d\n", cb - cbslots,
|
||||||
variant[i].name, baddr, pci->intl);
|
variant[i].name, pci->mem[0].bar, pci->intl);
|
||||||
|
|
||||||
nslots++;
|
nslots++;
|
||||||
}
|
}
|
||||||
|
@ -699,7 +680,7 @@ powerup(Cardbus *cb)
|
||||||
state = cb->regs[SocketState];
|
state = cb->regs[SocketState];
|
||||||
if (state & SS_PC16) {
|
if (state & SS_PC16) {
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: Probed a PC16 card, powering up card\n",
|
print("#Y%zd: Probed a PC16 card, powering up card\n",
|
||||||
cb - cbslots);
|
cb - cbslots);
|
||||||
cb->type = PC16;
|
cb->type = PC16;
|
||||||
memset(&cb->linfo, 0, sizeof(Pcminfo));
|
memset(&cb->linfo, 0, sizeof(Pcminfo));
|
||||||
|
@ -719,19 +700,19 @@ powerup(Cardbus *cb)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (state & SS_NOTCARD) {
|
if (state & SS_NOTCARD) {
|
||||||
print("#Y%ld: No card inserted\n", cb - cbslots);
|
print("#Y%zd: No card inserted\n", cb - cbslots);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
|
if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
|
||||||
print("#Y%ld: Unsupported voltage, powering down card!\n",
|
print("#Y%zd: Unsupported voltage, powering down card!\n",
|
||||||
cb - cbslots);
|
cb - cbslots);
|
||||||
cb->regs[SocketControl] = 0;
|
cb->regs[SocketControl] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
|
print("#Y%zd: card %spowered at %d volt\n", cb - cbslots,
|
||||||
(state & SS_POWER)? "": "not ",
|
(state & SS_POWER)? "": "not ",
|
||||||
(state & SS_3V)? 3: (state & SS_5V)? 5: -1);
|
(state & SS_3V)? 3: (state & SS_5V)? 5: -1);
|
||||||
|
|
||||||
|
@ -777,10 +758,9 @@ powerdown(Cardbus *cb)
|
||||||
static void
|
static void
|
||||||
configure(Cardbus *cb)
|
configure(Cardbus *cb)
|
||||||
{
|
{
|
||||||
int i, r;
|
|
||||||
Pcidev *pci;
|
Pcidev *pci;
|
||||||
uvlong romlen, memlen, membase, rombase, bar;
|
ulong iobase, iolen;
|
||||||
ulong iobase, iolen, size;
|
uvlong membase, memlen;
|
||||||
|
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);
|
print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);
|
||||||
|
@ -796,102 +776,68 @@ configure(Cardbus *cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan the CardBus for new PCI devices */
|
/* Scan the CardBus for new PCI devices */
|
||||||
pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
|
pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge, cb->pci);
|
||||||
|
|
||||||
/*
|
/* size the devices on the bus, reserve a minimum for devices arriving later */
|
||||||
* size the devices on the bus, reserve a minimum for devices arriving later,
|
pcibussize(cb->pci->bridge, &memlen, &iolen);
|
||||||
* allow for ROM space, allocate space, and set the cardbus mapping registers
|
|
||||||
*/
|
|
||||||
pcibussize(cb->pci->bridge, &memlen, &iolen); /* TO DO: need initial alignments */
|
|
||||||
|
|
||||||
romlen = 0;
|
|
||||||
for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
|
|
||||||
size = pcibarsize(pci, PciEBAR0);
|
|
||||||
if(size > 0){
|
|
||||||
pci->rom.bar = -1;
|
|
||||||
pci->rom.size = size;
|
|
||||||
romlen += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(iolen < 512)
|
if(iolen < 512)
|
||||||
iolen = 512;
|
iolen = 512;
|
||||||
iobase = ioreserve(-1, iolen, 0, "cardbus");
|
|
||||||
if(iobase == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rombase = memlen;
|
|
||||||
memlen += romlen;
|
|
||||||
if(memlen < 1*1024*1024)
|
if(memlen < 1*1024*1024)
|
||||||
memlen = 1*1024*1024;
|
memlen = 1*1024*1024;
|
||||||
membase = upaalloc(-1ULL, memlen, 4*1024*1024); /* TO DO: better alignment */
|
|
||||||
if(membase == -1)
|
print("#Y%zd: iolen=%lud, memlen=%llud\n", cb - cbslots, iolen, memlen);
|
||||||
|
|
||||||
|
if(cb->pci->parent == nil){
|
||||||
|
iobase = ioreserve(-1,
|
||||||
|
iolen, iolen, "cardbus");
|
||||||
|
if(iobase == -1){
|
||||||
|
NoIO:
|
||||||
|
print("#Y%zd: can't allocate io space\n", cb - cbslots);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
membase = upaalloc(-1ULL,
|
||||||
|
memlen, 4*1024*1024);
|
||||||
|
} else {
|
||||||
|
iobase = ioreservewin(cb->pci->parent->ioa.bar, cb->pci->parent->ioa.size,
|
||||||
|
iolen, iolen, "cardbus");
|
||||||
|
if(iobase == -1)
|
||||||
|
goto NoIO;
|
||||||
|
membase = upaallocwin(cb->pci->parent->mema.bar, cb->pci->parent->mema.size,
|
||||||
|
memlen, 4*1024*1024);
|
||||||
|
}
|
||||||
|
if(membase == -1){
|
||||||
|
print("#Y%zd: can't allocate memory space\n", cb - cbslots);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("#Y%zd: iobase=%lux, membase=%llux\n", cb - cbslots, iobase, membase);
|
||||||
|
|
||||||
pcicfgw32(cb->pci, PciCBIBR0, iobase);
|
pcicfgw32(cb->pci, PciCBIBR0, iobase);
|
||||||
pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
|
pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
|
||||||
pcicfgw32(cb->pci, PciCBIBR1, 0);
|
pcicfgw32(cb->pci, PciCBIBR1, 0xffffffff);
|
||||||
pcicfgw32(cb->pci, PciCBILR1, 0);
|
pcicfgw32(cb->pci, PciCBILR1, 0);
|
||||||
|
cb->pci->ioa.bar = iobase;
|
||||||
|
cb->pci->ioa.size = iolen;
|
||||||
|
|
||||||
pcicfgw32(cb->pci, PciCBMBR0, (ulong)membase);
|
pcicfgw32(cb->pci, PciCBMBR0, (ulong)membase);
|
||||||
pcicfgw32(cb->pci, PciCBMLR0, (ulong)membase + memlen-1);
|
pcicfgw32(cb->pci, PciCBMLR0, (ulong)membase + memlen-1);
|
||||||
pcicfgw32(cb->pci, PciCBMBR1, 0);
|
pcicfgw32(cb->pci, PciCBMBR1, 0xffffffff);
|
||||||
pcicfgw32(cb->pci, PciCBMLR1, 0);
|
pcicfgw32(cb->pci, PciCBMLR1, 0);
|
||||||
|
cb->pci->mema.bar = membase;
|
||||||
|
cb->pci->mema.size = memlen;
|
||||||
|
|
||||||
// pcibussize(cb->pci->bridge, &membase, &iobase); /* now assign them */
|
/* Route interrupts to INTA#/B#, Disable prefetch for MEM0/1 */
|
||||||
rombase += membase;
|
pcicfgw16(cb->pci, PciBCR, pcicfgr16(cb->pci, PciBCR) & ~(7 << 7));
|
||||||
|
|
||||||
for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
|
/* Assign resources */
|
||||||
r = pcicfgr16(pci, PciPCR);
|
pcibusmap(cb->pci->bridge, &membase, &iobase, 1);
|
||||||
r &= ~(PciPCR_IO|PciPCR_MEM);
|
|
||||||
pcicfgw16(pci, PciPCR, r);
|
|
||||||
|
|
||||||
/*
|
/* Assign legacy IRQ's */
|
||||||
* Treat the found device as an ordinary PCI card.
|
for(pci = cb->pci->bridge; pci != nil; pci = pci->link) {
|
||||||
* It seems that the CIS is not always present in
|
if(pcicfgr8(pci, PciINTP) != 0) {
|
||||||
* CardBus cards.
|
pci->intl = cb->pci->intl;
|
||||||
* XXX, need to support multifunction cards
|
|
||||||
*/
|
|
||||||
for(i = 0; i < Nbars; i++) {
|
|
||||||
if(pci->mem[i].size == 0)
|
|
||||||
continue;
|
|
||||||
bar = pci->mem[i].bar;
|
|
||||||
if(bar & 1)
|
|
||||||
bar += iobase;
|
|
||||||
else
|
|
||||||
bar += membase;
|
|
||||||
pci->mem[i].bar = bar;
|
|
||||||
pcicfgw32(pci, PciBAR0 + 4*i, bar);
|
|
||||||
if((bar & 1) == 0){
|
|
||||||
print("%T mem[%d] %8.8llux %d\n", pci->tbdf, i, bar, pci->mem[i].size);
|
|
||||||
if(bar & 0x80){ /* TO DO: enable prefetch */
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((size = pcibarsize(pci, PciEBAR0)) > 0) { /* TO DO: can this be done by pci.c? */
|
|
||||||
pci->rom.bar = rombase;
|
|
||||||
pci->rom.size = size;
|
|
||||||
rombase += size;
|
|
||||||
pcicfgw32(pci, PciEBAR0, pci->rom.bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the basic PCI registers for the device */
|
|
||||||
pci->pcr = pcicfgr16(pci, PciPCR);
|
|
||||||
pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
|
|
||||||
pci->cls = 8;
|
|
||||||
pci->ltr = 64;
|
|
||||||
pcicfgw16(pci, PciPCR, pci->pcr);
|
|
||||||
pcicfgw8(pci, PciCLS, pci->cls);
|
|
||||||
pcicfgw8(pci, PciLTR, pci->ltr);
|
|
||||||
|
|
||||||
if (pcicfgr8(pci, PciINTP)) {
|
|
||||||
pci->intl = pcicfgr8(cb->pci, PciINTL);
|
|
||||||
pcicfgw8(pci, PciINTL, pci->intl);
|
pcicfgw8(pci, PciINTL, pci->intl);
|
||||||
|
|
||||||
/* Route interrupts to INTA#/B# */
|
|
||||||
pcicfgw16(cb->pci, PciBCR,
|
|
||||||
pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -899,58 +845,51 @@ configure(Cardbus *cb)
|
||||||
static void
|
static void
|
||||||
unconfigure(Cardbus *cb)
|
unconfigure(Cardbus *cb)
|
||||||
{
|
{
|
||||||
Pcidev *pci;
|
|
||||||
int i, ioindex, memindex, r;
|
|
||||||
|
|
||||||
if (cb->type == PC16) {
|
if (cb->type == PC16) {
|
||||||
print("#Y%d: Don't know how to unconfigure a PC16 card\n",
|
print("#Y%zd: Don't know how to unconfigure a PC16 card\n", cb - cbslots);
|
||||||
(int)(cb - cbslots));
|
|
||||||
|
|
||||||
memset(&cb->linfo, 0, sizeof(Pcminfo));
|
memset(&cb->linfo, 0, sizeof(Pcminfo));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci = cb->pci->bridge;
|
pcicfgw32(cb->pci, PciCBIBR0, 0xffffffff);
|
||||||
if (pci == nil)
|
pcicfgw32(cb->pci, PciCBILR0, 0);
|
||||||
return; /* Not configured */
|
pcicfgw32(cb->pci, PciCBIBR1, 0xffffffff);
|
||||||
cb->pci->bridge = nil;
|
pcicfgw32(cb->pci, PciCBILR1, 0);
|
||||||
|
|
||||||
memindex = ioindex = 0;
|
pcicfgw32(cb->pci, PciCBMBR0, 0xffffffff);
|
||||||
while (pci) {
|
pcicfgw32(cb->pci, PciCBMLR0, 0);
|
||||||
Pcidev *_pci;
|
pcicfgw32(cb->pci, PciCBMBR1, 0xffffffff);
|
||||||
|
pcicfgw32(cb->pci, PciCBMLR1, 0);
|
||||||
|
|
||||||
for (i = 0; i != Nbars; i++) {
|
/* free i/o space */
|
||||||
if (pci->mem[i].size == 0)
|
if(cb->pci->ioa.size){
|
||||||
continue;
|
Pcidev *pci;
|
||||||
if (pci->mem[i].bar & 1) {
|
int i;
|
||||||
|
|
||||||
|
for(pci = cb->pci->bridge; pci != nil; pci = pci->link) {
|
||||||
|
for(i = 0; i < nelem(pci->mem); i++) {
|
||||||
|
if((pci->mem[i].size == 0)
|
||||||
|
|| (pci->mem[i].bar & 1) == 0
|
||||||
|
|| (pci->mem[i].bar & ~3) == 0)
|
||||||
|
continue;
|
||||||
iofree(pci->mem[i].bar & ~3);
|
iofree(pci->mem[i].bar & ~3);
|
||||||
pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
|
|
||||||
(ushort)-1);
|
|
||||||
pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
|
|
||||||
ioindex++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
|
|
||||||
pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
|
|
||||||
pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
|
|
||||||
r = pcicfgr16(cb->pci, PciBCR);
|
|
||||||
r &= ~(1 << (8 + memindex));
|
|
||||||
pcicfgw16(cb->pci, PciBCR, r);
|
|
||||||
memindex++;
|
|
||||||
}
|
}
|
||||||
|
iofree(cb->pci->ioa.bar);
|
||||||
if (pci->rom.bar && memindex < 2) {
|
cb->pci->ioa.bar = 0;
|
||||||
upafree(pci->rom.bar & ~0xF, pci->rom.size);
|
cb->pci->ioa.size = 0;
|
||||||
pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
|
|
||||||
pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
|
|
||||||
memindex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pci = pci->list;
|
|
||||||
free(_pci);
|
|
||||||
pci = _pci;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free memory space */
|
||||||
|
if(cb->pci->mema.size){
|
||||||
|
upafree(cb->pci->mema.bar, cb->pci->mema.size);
|
||||||
|
cb->pci->mema.bar = 0;
|
||||||
|
cb->pci->mema.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the devices */
|
||||||
|
while(cb->pci->bridge != nil)
|
||||||
|
pcidevfree(cb->pci->bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1174,7 +1113,7 @@ pccard_pcmspecial(char *idstr, ISAConf *isa)
|
||||||
pi->irq = isa->irq;
|
pi->irq = isa->irq;
|
||||||
unlock(cb);
|
unlock(cb);
|
||||||
|
|
||||||
print("#Y%ld: %s irq %d, port %lluX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);
|
print("#Y%zd: %s irq %d, port %lluX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);
|
||||||
return (int)(cb - cbslots);
|
return (int)(cb - cbslots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1321,10 +1260,10 @@ pccardread(Chan *c, void *a, long n, vlong offset)
|
||||||
Pcidev *pci = cb->pci->bridge;
|
Pcidev *pci = cb->pci->bridge;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while (pci) {
|
while (pci != nil) {
|
||||||
p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
|
p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
|
||||||
pci->vid, pci->did, pci->intl);
|
pci->vid, pci->did, pci->intl);
|
||||||
for (i = 0; i != Nbars; i++)
|
for (i = 0; i < nelem(pci->mem); i++)
|
||||||
if (pci->mem[i].size)
|
if (pci->mem[i].size)
|
||||||
p = seprint(p, e,
|
p = seprint(p, e,
|
||||||
"\tmem[%d] %.8ullX (%.8uX)\n",
|
"\tmem[%d] %.8ullX (%.8uX)\n",
|
||||||
|
@ -1333,7 +1272,7 @@ pccardread(Chan *c, void *a, long n, vlong offset)
|
||||||
if (pci->rom.size)
|
if (pci->rom.size)
|
||||||
p = seprint(p, e, "\tROM %.8ullX (%.8uX)\n",
|
p = seprint(p, e, "\tROM %.8ullX (%.8uX)\n",
|
||||||
pci->rom.bar, pci->rom.size);
|
pci->rom.bar, pci->rom.size);
|
||||||
pci = pci->list;
|
pci = pci->link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -351,13 +351,19 @@ Findbus:
|
||||||
|
|
||||||
if(bus == nil){
|
if(bus == nil){
|
||||||
/*
|
/*
|
||||||
* if the PCI device is behind a PCI-PCI bridge thats not described
|
* if the PCI device is behind a bridge thats not described
|
||||||
* by the MP or ACPI tables then walk up the bus translating interrupt
|
* by the MP or ACPI tables then walk up the bus translating
|
||||||
* pin to parent bus.
|
* interrupt pin to parent bus.
|
||||||
*/
|
*/
|
||||||
if(pci != nil && pci->parent != nil && pin > 0){
|
if(pci != nil && pci->parent != nil && pin > 0){
|
||||||
pin = ((dno+(pin-1))%4)+1;
|
|
||||||
pci = pci->parent;
|
pci = pci->parent;
|
||||||
|
if(pci->ccrb == 6 && pci->ccru == 7){
|
||||||
|
/* Cardbus bridge, use controllers interrupt pin */
|
||||||
|
pin = pcicfgr8(pci, PciINTP);
|
||||||
|
} else {
|
||||||
|
/* PCI-PCI bridge */
|
||||||
|
pin = ((dno+(pin-1))%4)+1;
|
||||||
|
}
|
||||||
bno = BUSBNO(pci->tbdf);
|
bno = BUSBNO(pci->tbdf);
|
||||||
dno = BUSDNO(pci->tbdf);
|
dno = BUSDNO(pci->tbdf);
|
||||||
goto Findbus;
|
goto Findbus;
|
||||||
|
|
|
@ -557,6 +557,10 @@ pcireserve(void)
|
||||||
upaalloc(pa, p->mem[i].size, 0);
|
upaalloc(pa, p->mem[i].size, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(p->rom.size && (p->rom.bar & 1) != 0){
|
||||||
|
pa = p->rom.bar & ~0x7FFULL;
|
||||||
|
upaalloc(pa, p->rom.size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -688,7 +692,7 @@ pcicfginit(void)
|
||||||
list = &pciroot;
|
list = &pciroot;
|
||||||
for(bno = 0; bno <= pcimaxbno; bno++) {
|
for(bno = 0; bno <= pcimaxbno; bno++) {
|
||||||
int sbno = bno;
|
int sbno = bno;
|
||||||
bno = pciscan(bno, list);
|
bno = pciscan(bno, list, nil);
|
||||||
|
|
||||||
while(*list)
|
while(*list)
|
||||||
list = &(*list)->link;
|
list = &(*list)->link;
|
||||||
|
|
|
@ -18,8 +18,7 @@ struct Pcisiz
|
||||||
int pcimaxdno;
|
int pcimaxdno;
|
||||||
|
|
||||||
static Lock pcicfglock;
|
static Lock pcicfglock;
|
||||||
static Pcidev* pcilist;
|
static Pcidev *pcilist, **pcitail;
|
||||||
static Pcidev* pcitail;
|
|
||||||
|
|
||||||
static char* bustypes[] = {
|
static char* bustypes[] = {
|
||||||
"CBUSI",
|
"CBUSI",
|
||||||
|
@ -68,6 +67,46 @@ tbdffmt(Fmt* fmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Pcidev*
|
||||||
|
pcidevalloc(void)
|
||||||
|
{
|
||||||
|
Pcidev *p;
|
||||||
|
|
||||||
|
p = xalloc(sizeof(*p));
|
||||||
|
if(p == nil)
|
||||||
|
panic("pci: no memory for Pcidev");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pcidevfree(Pcidev *p)
|
||||||
|
{
|
||||||
|
Pcidev **l;
|
||||||
|
|
||||||
|
if(p == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while(p->bridge != nil)
|
||||||
|
pcidevfree(p->bridge);
|
||||||
|
|
||||||
|
if(p->parent != nil){
|
||||||
|
for(l = &p->parent->bridge; *l != nil; l = &(*l)->link) {
|
||||||
|
if(*l == p) {
|
||||||
|
*l = p->link;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(l = &pcilist; *l != nil; l = &(*l)->list) {
|
||||||
|
if(*l == p) {
|
||||||
|
if((*l = p->list) == nil)
|
||||||
|
pcitail = l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* leaked */
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pcicfgr8(Pcidev* p, int rno)
|
pcicfgr8(Pcidev* p, int rno)
|
||||||
{
|
{
|
||||||
|
@ -135,12 +174,15 @@ pcibarsize(Pcidev *p, int rno)
|
||||||
pcicfgrw32(p->tbdf, rno, v, 0);
|
pcicfgrw32(p->tbdf, rno, v, 0);
|
||||||
iunlock(&pcicfglock);
|
iunlock(&pcicfglock);
|
||||||
|
|
||||||
if(v & 1){
|
if(rno == PciEBAR0 || rno == PciEBAR1){
|
||||||
|
size &= ~0x7FF;
|
||||||
|
} else if(v & 1){
|
||||||
size = (short)size;
|
size = (short)size;
|
||||||
size &= ~3;
|
size &= ~3;
|
||||||
} else {
|
} else {
|
||||||
size &= ~0xF;
|
size &= ~0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -size;
|
return -size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +259,7 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
|
||||||
ntb++;
|
ntb++;
|
||||||
|
|
||||||
ntb *= (PciCIS-PciBAR0)/4;
|
ntb *= (PciCIS-PciBAR0)/4;
|
||||||
table = malloc(2*ntb*sizeof(Pcisiz));
|
table = malloc((2*ntb+1)*sizeof(Pcisiz));
|
||||||
if(table == nil)
|
if(table == nil)
|
||||||
panic("pcibusmap: can't allocate memory");
|
panic("pcibusmap: can't allocate memory");
|
||||||
itb = table;
|
itb = table;
|
||||||
|
@ -228,6 +270,22 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
|
||||||
*/
|
*/
|
||||||
for(p = root; p != nil; p = p->link) {
|
for(p = root; p != nil; p = p->link) {
|
||||||
if(p->ccrb == 0x06) {
|
if(p->ccrb == 0x06) {
|
||||||
|
/* carbus bridge? */
|
||||||
|
if(p->ccru == 0x07){
|
||||||
|
if(pcicfgr32(p, PciBAR0) & 1)
|
||||||
|
continue;
|
||||||
|
size = pcibarsize(p, PciBAR0);
|
||||||
|
if(size == 0)
|
||||||
|
continue;
|
||||||
|
mtb->dev = p;
|
||||||
|
mtb->bar = 0;
|
||||||
|
mtb->siz = size;
|
||||||
|
mtb->typ = 0;
|
||||||
|
mtb++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pci bridge? */
|
||||||
if(p->ccru != 0x04 || p->bridge == nil)
|
if(p->ccru != 0x04 || p->bridge == nil)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -252,9 +310,27 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
|
||||||
mtb->siz = hole;
|
mtb->siz = hole;
|
||||||
mtb->typ = 0;
|
mtb->typ = 0;
|
||||||
mtb++;
|
mtb++;
|
||||||
|
|
||||||
|
size = pcibarsize(p, PciEBAR1);
|
||||||
|
if(size != 0){
|
||||||
|
mtb->dev = p;
|
||||||
|
mtb->bar = -3;
|
||||||
|
mtb->siz = size;
|
||||||
|
mtb->typ = 0;
|
||||||
|
mtb++;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = pcibarsize(p, PciEBAR0);
|
||||||
|
if(size != 0){
|
||||||
|
mtb->dev = p;
|
||||||
|
mtb->bar = -2;
|
||||||
|
mtb->siz = size;
|
||||||
|
mtb->typ = 0;
|
||||||
|
mtb++;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < nelem(p->mem); i++) {
|
for(i = 0; i < nelem(p->mem); i++) {
|
||||||
rno = PciBAR0 + i*4;
|
rno = PciBAR0 + i*4;
|
||||||
v = pcicfgr32(p, rno);
|
v = pcicfgr32(p, rno);
|
||||||
|
@ -321,6 +397,14 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
|
||||||
if(tptr->bar == -1) {
|
if(tptr->bar == -1) {
|
||||||
p->mema.bar = mema;
|
p->mema.bar = mema;
|
||||||
p->mema.size = tptr->siz;
|
p->mema.size = tptr->siz;
|
||||||
|
} else if(tptr->bar == -2) {
|
||||||
|
p->rom.bar = mema|1;
|
||||||
|
p->rom.size = tptr->siz;
|
||||||
|
pcisetbar(p, PciEBAR0, p->rom.bar);
|
||||||
|
} else if(tptr->bar == -3) {
|
||||||
|
p->rom.bar = mema|1;
|
||||||
|
p->rom.size = tptr->siz;
|
||||||
|
pcisetbar(p, PciEBAR1, p->rom.bar);
|
||||||
} else {
|
} else {
|
||||||
p->mem[tptr->bar].size = tptr->siz;
|
p->mem[tptr->bar].size = tptr->siz;
|
||||||
p->mem[tptr->bar].bar = mema|tptr->typ;
|
p->mem[tptr->bar].bar = mema|tptr->typ;
|
||||||
|
@ -409,10 +493,10 @@ pcivalidbar(Pcidev *p, uvlong bar, int size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
pciscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
{
|
{
|
||||||
Pcidev *p, *head, *tail;
|
Pcidev *p, *head, **tail;
|
||||||
int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
|
int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
|
||||||
|
|
||||||
maxubn = bno;
|
maxubn = bno;
|
||||||
|
@ -437,19 +521,11 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
|
|
||||||
if(l == 0xFFFFFFFF || l == 0)
|
if(l == 0xFFFFFFFF || l == 0)
|
||||||
continue;
|
continue;
|
||||||
p = malloc(sizeof(*p));
|
p = pcidevalloc();
|
||||||
if(p == nil)
|
|
||||||
panic("pcilscan: can't allocate memory");
|
|
||||||
p->tbdf = tbdf;
|
p->tbdf = tbdf;
|
||||||
p->vid = l;
|
p->vid = l;
|
||||||
p->did = l>>16;
|
p->did = l>>16;
|
||||||
|
|
||||||
if(pcilist != nil)
|
|
||||||
pcitail->list = p;
|
|
||||||
else
|
|
||||||
pcilist = p;
|
|
||||||
pcitail = p;
|
|
||||||
|
|
||||||
p->pcr = pcicfgr16(p, PciPCR);
|
p->pcr = pcicfgr16(p, PciPCR);
|
||||||
p->rid = pcicfgr8(p, PciRID);
|
p->rid = pcicfgr8(p, PciRID);
|
||||||
p->ccrp = pcicfgr8(p, PciCCRp);
|
p->ccrp = pcicfgr8(p, PciCCRp);
|
||||||
|
@ -502,20 +578,43 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
}
|
}
|
||||||
rno += 4;
|
rno += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->rom.bar = (ulong)pcicfgr32(p, PciEBAR0);
|
||||||
|
p->rom.size = pcibarsize(p, PciEBAR0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: /* memory controller */
|
|
||||||
case 0x06: /* bridge device */
|
case 0x06: /* bridge device */
|
||||||
|
/* cardbus bridge? */
|
||||||
|
if(p->ccru == 0x07){
|
||||||
|
p->mem[0].bar = (ulong)pcicfgr32(p, PciBAR0);
|
||||||
|
p->mem[0].size = pcibarsize(p, PciBAR0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pci bridge? */
|
||||||
|
if(p->ccru != 0x04)
|
||||||
|
break;
|
||||||
|
|
||||||
|
p->rom.bar = (ulong)pcicfgr32(p, PciEBAR1);
|
||||||
|
p->rom.size = pcibarsize(p, PciEBAR1);
|
||||||
|
break;
|
||||||
|
case 0x05: /* memory controller */
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->parent = parent;
|
p->parent = parent;
|
||||||
if(head != nil)
|
if(head != nil)
|
||||||
tail->link = p;
|
*tail = p;
|
||||||
else
|
else
|
||||||
head = p;
|
head = p;
|
||||||
tail = p;
|
tail = &p->link;
|
||||||
|
|
||||||
|
if(pcilist != nil)
|
||||||
|
*pcitail = p;
|
||||||
|
else
|
||||||
|
pcilist = p;
|
||||||
|
pcitail = &p->list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,6 +628,7 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
if(p->ccru == 0x04)
|
if(p->ccru == 0x04)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* check and clear invalid membars for non bridges */
|
||||||
for(i = 0; i < nelem(p->mem); i++) {
|
for(i = 0; i < nelem(p->mem); i++) {
|
||||||
if(p->mem[i].size == 0)
|
if(p->mem[i].size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -540,9 +640,24 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar);
|
pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(p->rom.size) {
|
||||||
|
if((p->rom.bar & 1) == 0
|
||||||
|
|| !pcivalidbar(p, p->rom.bar & ~0x7FFUL, p->rom.size)){
|
||||||
|
p->rom.bar = 0;
|
||||||
|
pcisetbar(p, PciEBAR0, p->rom.bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(p->rom.size) {
|
||||||
|
if((p->rom.bar & 1) == 0
|
||||||
|
|| !pcivalidbar(p, p->rom.bar & ~0x7FFULL, p->rom.size)){
|
||||||
|
p->rom.bar = 0;
|
||||||
|
pcisetbar(p, PciEBAR1, p->rom.bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the secondary or subordinate bus number is not
|
* If the secondary or subordinate bus number is not
|
||||||
* initialised try to do what the PCI BIOS should have
|
* initialised try to do what the PCI BIOS should have
|
||||||
|
@ -581,7 +696,7 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
pcisetwin(p, 0xFFF00000|0, 0);
|
pcisetwin(p, 0xFFF00000|0, 0);
|
||||||
pcisetwin(p, 0xFFF00000|8, 0);
|
pcisetwin(p, 0xFFF00000|8, 0);
|
||||||
|
|
||||||
maxubn = pcilscan(sbn, &p->bridge, p);
|
maxubn = pciscan(sbn, &p->bridge, p);
|
||||||
l = (maxubn<<16)|(sbn<<8)|bno;
|
l = (maxubn<<16)|(sbn<<8)|bno;
|
||||||
|
|
||||||
pcicfgw32(p, PciPBN, l);
|
pcicfgw32(p, PciPBN, l);
|
||||||
|
@ -635,19 +750,13 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
|
|
||||||
if(ubn > maxubn)
|
if(ubn > maxubn)
|
||||||
maxubn = ubn;
|
maxubn = ubn;
|
||||||
pcilscan(sbn, &p->bridge, p);
|
pciscan(sbn, &p->bridge, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxubn;
|
return maxubn;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
pciscan(int bno, Pcidev **list)
|
|
||||||
{
|
|
||||||
return pcilscan(bno, list, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pcibussize(Pcidev *root, uvlong *msize, ulong *iosize)
|
pcibussize(Pcidev *root, uvlong *msize, ulong *iosize)
|
||||||
{
|
{
|
||||||
|
@ -720,6 +829,8 @@ pcilhinv(Pcidev* p)
|
||||||
continue;
|
continue;
|
||||||
print("%d:%.8llux %d ", i, t->mem[i].bar, t->mem[i].size);
|
print("%d:%.8llux %d ", i, t->mem[i].bar, t->mem[i].size);
|
||||||
}
|
}
|
||||||
|
if(t->rom.bar || t->rom.size)
|
||||||
|
print("rom:%.8llux %d ", t->rom.bar, t->rom.size);
|
||||||
if(t->ioa.bar || t->ioa.size)
|
if(t->ioa.bar || t->ioa.size)
|
||||||
print("ioa:%.8llux-%.8llux %d ", t->ioa.bar, t->ioa.bar+t->ioa.size, t->ioa.size);
|
print("ioa:%.8llux-%.8llux %d ", t->ioa.bar, t->ioa.bar+t->ioa.size, t->ioa.size);
|
||||||
if(t->mema.bar || t->mema.size)
|
if(t->mema.bar || t->mema.size)
|
||||||
|
|
|
@ -96,7 +96,7 @@ enum { /* type 1 pre-defined header */
|
||||||
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
|
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
|
||||||
PciIUBR = 0x30, /* I/O base upper 16 bits */
|
PciIUBR = 0x30, /* I/O base upper 16 bits */
|
||||||
PciIULR = 0x32, /* I/O limit upper 16 bits */
|
PciIULR = 0x32, /* I/O limit upper 16 bits */
|
||||||
PciEBAR1 = 0x28, /* expansion ROM base address */
|
PciEBAR1 = 0x38, /* expansion ROM base address */
|
||||||
PciBCR = 0x3E, /* bridge control register */
|
PciBCR = 0x3E, /* bridge control register */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -173,30 +173,33 @@ struct Pcidev
|
||||||
uchar cls;
|
uchar cls;
|
||||||
uchar ltr;
|
uchar ltr;
|
||||||
|
|
||||||
|
uchar intl; /* interrupt line */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uvlong bar; /* base address */
|
uvlong bar; /* base address */
|
||||||
int size;
|
int size;
|
||||||
} mem[6];
|
} mem[6];
|
||||||
|
|
||||||
struct {
|
struct { /* expansion rom bar */
|
||||||
uvlong bar;
|
uvlong bar;
|
||||||
int size;
|
int size;
|
||||||
} rom;
|
} rom;
|
||||||
uchar intl; /* interrupt line */
|
|
||||||
|
struct { /* 32-bit io and memory windows */
|
||||||
|
uvlong bar;
|
||||||
|
int size;
|
||||||
|
} ioa, mema;
|
||||||
|
|
||||||
|
struct { /* 64-bit prefechable memory window */
|
||||||
|
uvlong bar;
|
||||||
|
uvlong size;
|
||||||
|
} prefa;
|
||||||
|
|
||||||
Pcidev* list;
|
Pcidev* list;
|
||||||
Pcidev* link; /* next device on this bno */
|
Pcidev* link; /* next device on this bno */
|
||||||
|
|
||||||
Pcidev* parent; /* up a bus */
|
Pcidev* parent; /* up a bus */
|
||||||
Pcidev* bridge; /* down a bus */
|
Pcidev* bridge; /* down a bus */
|
||||||
struct {
|
|
||||||
uvlong bar;
|
|
||||||
int size;
|
|
||||||
} ioa, mema;
|
|
||||||
struct {
|
|
||||||
uvlong bar;
|
|
||||||
uvlong size;
|
|
||||||
} prefa;
|
|
||||||
|
|
||||||
int pmrb; /* power management register block */
|
int pmrb; /* power management register block */
|
||||||
int msi; /* MSI capability register block */
|
int msi; /* MSI capability register block */
|
||||||
|
@ -221,6 +224,8 @@ enum
|
||||||
|
|
||||||
extern int pcimaxdno;
|
extern int pcimaxdno;
|
||||||
|
|
||||||
|
extern void pcidevfree(Pcidev* pcidev);
|
||||||
|
|
||||||
extern int pcicfgr32(Pcidev* pcidev, int rno);
|
extern int pcicfgr32(Pcidev* pcidev, int rno);
|
||||||
extern void pcicfgw32(Pcidev* pcidev, int rno, int data);
|
extern void pcicfgw32(Pcidev* pcidev, int rno, int data);
|
||||||
extern int pcicfgr16(Pcidev* pcidev, int rno);
|
extern int pcicfgr16(Pcidev* pcidev, int rno);
|
||||||
|
@ -228,7 +233,7 @@ extern void pcicfgw16(Pcidev* pcidev, int rno, int data);
|
||||||
extern int pcicfgr8(Pcidev* pcidev, int rno);
|
extern int pcicfgr8(Pcidev* pcidev, int rno);
|
||||||
extern void pcicfgw8(Pcidev* pcidev, int rno, int data);
|
extern void pcicfgw8(Pcidev* pcidev, int rno, int data);
|
||||||
|
|
||||||
extern int pciscan(int bno, Pcidev **list);
|
extern int pciscan(int bno, Pcidev **list, Pcidev *parent);
|
||||||
extern void pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg);
|
extern void pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg);
|
||||||
extern void pcibussize(Pcidev *root, uvlong *msize, ulong *iosize);
|
extern void pcibussize(Pcidev *root, uvlong *msize, ulong *iosize);
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ pcicfginit(void)
|
||||||
list = &pciroot;
|
list = &pciroot;
|
||||||
/* was bno = 0; trimslice needs to start at 1 */
|
/* was bno = 0; trimslice needs to start at 1 */
|
||||||
for(bno = 1; bno <= pcimaxbno; bno++) {
|
for(bno = 1; bno <= pcimaxbno; bno++) {
|
||||||
bno = pciscan(bno, list);
|
bno = pciscan(bno, list, nil);
|
||||||
while(*list)
|
while(*list)
|
||||||
list = &(*list)->link;
|
list = &(*list)->link;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue