Fix some resource allocation peculiarities of the intpm device.

This commit is contained in:
Doug Rabson 1999-10-28 08:06:59 +00:00
parent c864a1a7e8
commit f8ef46e907
3 changed files with 217 additions and 152 deletions

View File

@ -60,6 +60,23 @@
#include <machine/smp.h>
#endif /* APIC_IO */
struct pci_quirk {
u_int32_t devid; /* Vendor/device of the card */
int type;
#define PCI_QUIRK_MAP_REG 1 /* PCI map register in wierd place */
int arg1;
int arg2;
};
struct pci_quirk pci_quirks[] = {
/*
* The Intel 82371AB has a map register at offset 0x90.
*/
{ 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 },
{ 0 }
};
/* map register information */
#define PCI_MAPMEM 0x01 /* memory map */
#define PCI_MAPMEMP 0x02 /* prefetchable memory map */
@ -970,81 +987,100 @@ pci_memen(pcicfgregs *cfg)
return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
}
/*
* Add a resource based on a pci map register. Return 1 if the map
* register is a 32bit map register or 2 if it is a 64bit register.
*/
static int
pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
u_int8_t ln2range;
u_int32_t testval;
int type;
map = pci_cfgread(cfg, reg, 4);
if (map == 0 || map == 0xffffffff)
return 1; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
type = SYS_RES_MEMORY;
else
type = SYS_RES_IOPORT;
ln2size = pci_mapsize(testval);
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if(cfg->hose){
if (base & 0x80000000) {
printf("base addr = 0x%x\n", base);
printf("hacked addr = 0x%x\n",
base | (cfg->hose << 31));
panic("hose encoding hack would clobber base addr");
}
if (cfg->hose > 1)
panic("only one hose supported!");
base |= (cfg->hose << 31);
}
#endif
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
return 1;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
return 1;
resource_list_add(rl, type, reg,
base, base + (1 << ln2size) - 1,
(1 << ln2size));
if (bootverbose) {
printf("\tmap[%02x]: type %x, range %2d, base %08x, size %2d\n",
reg, pci_maptype(base), ln2range,
(unsigned int) base, ln2size);
}
return (ln2range == 64) ? 2 : 1;
}
static void
pci_add_resources(device_t dev, pcicfgregs* cfg)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
struct pci_quirk *q;
int i;
for (i = 0; i < cfg->nummaps; i++) {
int reg = PCIR_MAPS + i*4;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
u_int8_t ln2range;
u_int32_t testval;
int type;
map = pci_cfgread(cfg, reg, 4);
if (map == 0 || map == 0xffffffff)
continue; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
type = SYS_RES_MEMORY;
else
type = SYS_RES_IOPORT;
ln2size = pci_mapsize(testval);
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
i++;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if(cfg->hose){
if (base & 0x80000000) {
printf("base addr = 0x%x\n", base);
printf("hacked addr = 0x%x\n",
base | (cfg->hose << 31));
panic("hose encoding hack would clobber base addr");
}
if (cfg->hose > 1)
panic("only one hose supported!");
base |= (cfg->hose << 31);
}
#endif
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
continue;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
continue;
resource_list_add(rl, type, reg,
base, base + (1 << ln2size) - 1,
(1 << ln2size));
if (bootverbose) {
printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
i, pci_maptype(base), ln2range,
(unsigned int) base, ln2size);
}
for (i = 0; i < cfg->nummaps;) {
i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
}
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == ((cfg->device << 16) | cfg->vendor)
&& q->type == PCI_QUIRK_MAP_REG)
pci_add_map(dev, cfg, q->arg1);
}
if (cfg->intline != 255)
resource_list_add(rl, SYS_RES_IRQ, 0,
cfg->intline, cfg->intline, 1);
@ -1278,8 +1314,11 @@ static int
pci_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
{
printf("pci_set_resource: PCI resources can not be changed\n");
return EINVAL;
struct pci_devinfo *dinfo = device_get_ivars(child);
struct resource_list *rl = &dinfo->resources;
resource_list_add(rl, type, rid, start, start + count - 1, count);
return 0;
}
static int
@ -1304,7 +1343,6 @@ static void
pci_delete_resource(device_t dev, device_t child, int type, int rid)
{
printf("pci_set_resource: PCI resources can not be deleted\n");
return EINVAL;
}
static u_int32_t

View File

@ -663,20 +663,8 @@ intpm_attach(device_t dev)
}
rid=PCI_BASE_ADDR_SMB;
#if 0
res=bus_alloc_resource(dev,SYS_RES_IOPORT,&rid,
0,~0,1,RF_ACTIVE);
if(res==NULL){
device_printf(dev,"IO FAILED Trying Memory\n");
res=bus_alloc_resource(dev,SYS_RES_MEMORY,&rid,0,~0,
1,RF_ACTIVE);
}
#else
/*Do as I tell!*/
value=pci_read_config(dev,rid,4);
res=bus_alloc_resource(dev,SYS_RES_IOPORT,&rid,value&(~1),
(value&(~1))+256,256,RF_ACTIVE);
#endif
if(res==NULL){
device_printf(dev,"Could not allocate Bus space\n");
return ENXIO;
@ -744,6 +732,7 @@ intpm_probe(device_t dev)
++ep;
if(ep->desc!=NULL){
device_set_desc(dev,ep->desc);
bus_set_resource(dev,SYS_RES_IRQ,0,9,1); /* XXX setup intr resource */
return 0;
}else{
return ENXIO;

View File

@ -60,6 +60,23 @@
#include <machine/smp.h>
#endif /* APIC_IO */
struct pci_quirk {
u_int32_t devid; /* Vendor/device of the card */
int type;
#define PCI_QUIRK_MAP_REG 1 /* PCI map register in wierd place */
int arg1;
int arg2;
};
struct pci_quirk pci_quirks[] = {
/*
* The Intel 82371AB has a map register at offset 0x90.
*/
{ 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 },
{ 0 }
};
/* map register information */
#define PCI_MAPMEM 0x01 /* memory map */
#define PCI_MAPMEMP 0x02 /* prefetchable memory map */
@ -970,81 +987,100 @@ pci_memen(pcicfgregs *cfg)
return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
}
/*
* Add a resource based on a pci map register. Return 1 if the map
* register is a 32bit map register or 2 if it is a 64bit register.
*/
static int
pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
u_int8_t ln2range;
u_int32_t testval;
int type;
map = pci_cfgread(cfg, reg, 4);
if (map == 0 || map == 0xffffffff)
return 1; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
type = SYS_RES_MEMORY;
else
type = SYS_RES_IOPORT;
ln2size = pci_mapsize(testval);
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if(cfg->hose){
if (base & 0x80000000) {
printf("base addr = 0x%x\n", base);
printf("hacked addr = 0x%x\n",
base | (cfg->hose << 31));
panic("hose encoding hack would clobber base addr");
}
if (cfg->hose > 1)
panic("only one hose supported!");
base |= (cfg->hose << 31);
}
#endif
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
return 1;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
return 1;
resource_list_add(rl, type, reg,
base, base + (1 << ln2size) - 1,
(1 << ln2size));
if (bootverbose) {
printf("\tmap[%02x]: type %x, range %2d, base %08x, size %2d\n",
reg, pci_maptype(base), ln2range,
(unsigned int) base, ln2size);
}
return (ln2range == 64) ? 2 : 1;
}
static void
pci_add_resources(device_t dev, pcicfgregs* cfg)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
struct pci_quirk *q;
int i;
for (i = 0; i < cfg->nummaps; i++) {
int reg = PCIR_MAPS + i*4;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
u_int8_t ln2range;
u_int32_t testval;
int type;
map = pci_cfgread(cfg, reg, 4);
if (map == 0 || map == 0xffffffff)
continue; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
type = SYS_RES_MEMORY;
else
type = SYS_RES_IOPORT;
ln2size = pci_mapsize(testval);
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
i++;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if(cfg->hose){
if (base & 0x80000000) {
printf("base addr = 0x%x\n", base);
printf("hacked addr = 0x%x\n",
base | (cfg->hose << 31));
panic("hose encoding hack would clobber base addr");
}
if (cfg->hose > 1)
panic("only one hose supported!");
base |= (cfg->hose << 31);
}
#endif
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
continue;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
continue;
resource_list_add(rl, type, reg,
base, base + (1 << ln2size) - 1,
(1 << ln2size));
if (bootverbose) {
printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
i, pci_maptype(base), ln2range,
(unsigned int) base, ln2size);
}
for (i = 0; i < cfg->nummaps;) {
i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
}
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == ((cfg->device << 16) | cfg->vendor)
&& q->type == PCI_QUIRK_MAP_REG)
pci_add_map(dev, cfg, q->arg1);
}
if (cfg->intline != 255)
resource_list_add(rl, SYS_RES_IRQ, 0,
cfg->intline, cfg->intline, 1);
@ -1278,8 +1314,11 @@ static int
pci_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
{
printf("pci_set_resource: PCI resources can not be changed\n");
return EINVAL;
struct pci_devinfo *dinfo = device_get_ivars(child);
struct resource_list *rl = &dinfo->resources;
resource_list_add(rl, type, rid, start, start + count - 1, count);
return 0;
}
static int
@ -1304,7 +1343,6 @@ static void
pci_delete_resource(device_t dev, device_t child, int type, int rid)
{
printf("pci_set_resource: PCI resources can not be deleted\n");
return EINVAL;
}
static u_int32_t