From 45f0aa1f0eebf8b631f6091da422e9a44f675d8d Mon Sep 17 00:00:00 2001 From: Doug Rabson Date: Thu, 14 Oct 1999 21:38:33 +0000 Subject: [PATCH] * Implement bus_set/get/delete_resource for pci. * Change the hack used on the alpha for mapping devices into DENSE or BWX memory spaces to a simpler one. Its still a hack and should be a seperate api to explicitly map the resource. * Add $FreeBSD$ as necessary. --- sys/alpha/include/resource.h | 2 - sys/alpha/pci/pcibus.c | 21 +- sys/amd64/include/resource.h | 3 +- sys/dev/pci/pci.c | 405 ++++++++++++--------------------- sys/dev/pci/pcivar.h | 30 +-- sys/i386/include/resource.h | 3 +- sys/pci/pci.c | 405 ++++++++++++--------------------- sys/pci/pci_compat.c | 8 +- sys/pci/pcisupport.c | 11 +- sys/pci/pcivar.h | 30 +-- sys/powerpc/include/resource.h | 3 +- 11 files changed, 321 insertions(+), 600 deletions(-) diff --git a/sys/alpha/include/resource.h b/sys/alpha/include/resource.h index c9253c9dc0db..28fcc98ea1be 100644 --- a/sys/alpha/include/resource.h +++ b/sys/alpha/include/resource.h @@ -40,7 +40,5 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#define SYS_RES_DENSE 5 /* i/o memory in dense space */ -#define SYS_RES_BWX 6 /* i/i memory in bwx space */ #endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c index d49a57c60d4b..b668c827759f 100644 --- a/sys/alpha/pci/pcibus.c +++ b/sys/alpha/pci/pcibus.c @@ -207,8 +207,6 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, rm = &port_rman; break; - case SYS_RES_DENSE: - case SYS_RES_BWX: case SYS_RES_MEMORY: rm = &mem_rman; break; @@ -225,19 +223,12 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, case SYS_RES_MEMORY: rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM); rman_set_bushandle(rv, rv->r_start); - rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */ - break; - - case SYS_RES_DENSE: - rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM); - rman_set_bushandle(rv, rv->r_start); - rman_set_virtual(rv, pci_cvt_to_dense(rv->r_start)); - break; - - case SYS_RES_BWX: - rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM); - rman_set_bushandle(rv, rv->r_start); - rman_set_virtual(rv, pci_cvt_to_bwx(rv->r_start)); + if (flags & PCI_RF_DENSE) + rman_set_virtual(rv, pci_cvt_to_dense(rv->r_start)); + else if (flags & PCI_RF_BWX) + rman_set_virtual(rv, pci_cvt_to_bwx(rv->r_start)); + else + rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */ break; case SYS_RES_IOPORT: diff --git a/sys/amd64/include/resource.h b/sys/amd64/include/resource.h index adcf0ce00f9d..28fcc98ea1be 100644 --- a/sys/amd64/include/resource.h +++ b/sys/amd64/include/resource.h @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright 1998 Massachusetts Institute of Technology * @@ -39,7 +40,5 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#define SYS_RES_DENSE SYS_RES_MEMORY -#define SYS_RES_BWX SYS_RES_MEMORY #endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index bfdf9d0452e0..f5da2d81c91c 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -60,13 +60,25 @@ #include #endif /* APIC_IO */ +/* map register information */ +#define PCI_MAPMEM 0x01 /* memory map */ +#define PCI_MAPMEMP 0x02 /* prefetchable memory map */ +#define PCI_MAPPORT 0x04 /* port map */ + +struct pci_devinfo { + STAILQ_ENTRY(pci_devinfo) pci_links; + struct resource_list resources; + pcicfgregs cfg; + struct pci_conf conf; +}; + static STAILQ_HEAD(devlist, pci_devinfo) pci_devq; u_int32_t pci_numdevs = 0; static u_int32_t pci_generation = 0; /* return base address of memory or port map */ -static int +static u_int32_t pci_mapbase(unsigned mapreg) { int mask = 0x03; @@ -135,91 +147,6 @@ pci_maprange(unsigned mapreg) return (ln2range); } -/* extract map parameters into newly allocated array of pcimap structures */ - -static pcimap * -pci_readmaps(pcicfgregs *cfg, int maxmaps) -{ - int i, j = 0; - pcimap *map; - int map64 = 0; - int reg = PCIR_MAPS; - - for (i = 0; i < maxmaps; i++) { - int reg = PCIR_MAPS + i*4; - u_int32_t base; - u_int32_t ln2range; - - base = pci_cfgread(cfg, reg, 4); - ln2range = pci_maprange(base); - - if (base == 0 || ln2range == 0 || base == 0xffffffff) - continue; /* skip invalid entry */ - else { - j++; - if (ln2range > 32) { - i++; - j++; - } - } - } - - map = malloc(j * sizeof (pcimap), M_DEVBUF, M_WAITOK); - if (map != NULL) { - bzero(map, sizeof(pcimap) * j); - cfg->nummaps = j; - - for (i = 0, j = 0; i < maxmaps; i++, reg += 4) { - u_int32_t base; - u_int32_t testval; - - base = pci_cfgread(cfg, reg, 4); - - if (map64 == 0) { - if (base == 0 || base == 0xffffffff) - continue; /* skip invalid entry */ - - pci_cfgwrite(cfg, reg, 0xffffffff, 4); - testval = pci_cfgread(cfg, reg, 4); - pci_cfgwrite(cfg, reg, base, 4); - - map[j].reg = reg; - map[j].base = pci_mapbase(base); - map[j].type = pci_maptype(base); - map[j].ln2size = pci_mapsize(testval); - map[j].ln2range = pci_maprange(testval); - map64 = map[j].ln2range == 64; - } else { - /* only fill in base, other fields are 0 */ - map[j].base = base; - map64 = 0; - } -#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(map[j].base & 0x80000000){ - printf("base addr = 0x%x\n", map[j].base); - printf("hacked addr = 0x%x\n", - map[j].base | (cfg->hose << 31)); - - panic("hose encoding hack would clobber base addr"); - } - if(cfg->hose > 1 ) - panic("only one hose supported!"); - map[j].base |= (cfg->hose << 31); - } -#endif - j++; - } - } - return (map); -} - /* adjust some values from PCI 1.0 devices to match 2.0 standards ... */ static void @@ -312,14 +239,14 @@ pci_hdrtypedata(pcicfgregs *cfg) case 0: cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2); cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_0); + cfg->nummaps = PCI_MAXMAPS_0; break; case 1: cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2); cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2); cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1); cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_1); + cfg->nummaps = PCI_MAXMAPS_1; cfg->hdrspec = pci_readppb(cfg); break; case 2: @@ -327,7 +254,7 @@ pci_hdrtypedata(pcicfgregs *cfg) cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2); cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1); cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_2); + cfg->nummaps = PCI_MAXMAPS_2; cfg->hdrspec = pci_readpcb(cfg); break; } @@ -1010,7 +937,6 @@ static void pci_print_verbose(struct pci_devinfo *dinfo) { if (bootverbose) { - int i; pcicfgregs *cfg = &dinfo->cfg; printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", @@ -1029,20 +955,105 @@ pci_print_verbose(struct pci_devinfo *dinfo) #endif /* PCI_DEBUG */ if (cfg->intpin > 0) printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); - - for (i = 0; i < cfg->nummaps; i++) { - pcimap *m = &cfg->map[i]; - printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", - i, m->type, m->ln2range, m->base, m->ln2size); - } } } static int +pci_porten(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); +} + +static int +pci_memen(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); +} + +static void +pci_add_resources(device_t dev, pcicfgregs* cfg) +{ + + struct pci_devinfo *dinfo = device_get_ivars(dev); + struct resource_list *rl = &dinfo->resources; + 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_IOPORT && !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); + } + } + if (cfg->intline) + resource_list_add(rl, SYS_RES_IRQ, 0, + cfg->intline, cfg->intline, 1); +} + +static void pci_add_children(device_t dev, int busno) { pcicfgregs probe; - int bushigh = busno; #ifdef SIMOS #undef PCI_SLOTMAX @@ -1069,16 +1080,10 @@ pci_add_children(device_t dev, int busno) pci_print_verbose(dinfo); dinfo->cfg.dev = device_add_child(dev, NULL, -1, dinfo); - - if (bushigh < dinfo->cfg.subordinatebus) - bushigh = dinfo->cfg.subordinatebus; - if (bushigh < dinfo->cfg.secondarybus) - bushigh = dinfo->cfg.secondarybus; + pci_add_resources(dinfo->cfg.dev, &dinfo->cfg); } } } - - return bushigh; } static int @@ -1248,181 +1253,58 @@ pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) return 0; } -static int -pci_mapno(pcicfgregs *cfg, int reg) -{ - int i, nummaps; - pcimap *map; - - nummaps = cfg->nummaps; - map = cfg->map; - - for (i = 0; i < nummaps; i++) - if (map[i].reg == reg) - return (i); - return (-1); -} - -static int -pci_porten(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); -} - -static int -pci_isportmap(pcicfgregs *cfg, int map) - -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPPORT) != 0); -} - -static int -pci_memen(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); -} - -static int -pci_ismemmap(pcicfgregs *cfg, int map) -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPMEM) != 0); -} - static struct resource * pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - int isdefault; struct pci_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - struct resource *rv, **rvp = 0; - int map; + struct resource_list *rl = &dinfo->resources; - isdefault = (device_get_parent(child) == dev - && start == 0UL && end == ~0UL); - - switch (type) { - case SYS_RES_IRQ: - if (*rid != 0) - return 0; - if (isdefault && cfg->intline != 255) { - start = cfg->intline; - end = cfg->intline; - count = 1; - } - break; - - case SYS_RES_DRQ: /* passthru for child isa */ - break; - -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - if (isdefault) { - map = pci_mapno(cfg, *rid); - if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { - start = cfg->map[map].base; - count = 1 << cfg->map[map].ln2size; - end = start + count; - rvp = &cfg->map[map].res; - } else - return 0; - } - break; - - case SYS_RES_IOPORT: - if (isdefault) { - map = pci_mapno(cfg, *rid); - if (pci_porten(cfg) && pci_isportmap(cfg, map)) { - start = cfg->map[map].base; - count = 1 << cfg->map[map].ln2size; - end = start + count; - rvp = &cfg->map[map].res; - } else - return 0; - } - break; - - default: - return 0; - } - - rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - type, rid, start, end, count, flags); - if (rvp) - *rvp = rv; - - return rv; + return resource_list_alloc(rl, dev, child, type, rid, + start, end, count, flags); } static int pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { - int rv; struct pci_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - int map = 0; - int passthrough = (device_get_parent(child) != dev); + struct resource_list *rl = &dinfo->resources; - switch (type) { - case SYS_RES_IRQ: - if (rid != 0) - return EINVAL; - break; + return resource_list_release(rl, dev, child, type, rid, r); +} - case SYS_RES_DRQ: /* passthru for child isa */ - break; +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; +} -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - case SYS_RES_IOPORT: - /* - * Only check the map registers if this is a direct - * descendant. - */ - map = passthrough ? -1 : pci_mapno(cfg, rid); - break; +static int +pci_get_resource(device_t dev, device_t child, int type, int rid, + u_long *startp, u_long *countp) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + struct resource_list *rl = &dinfo->resources; + struct resource_list_entry *rle; - default: - return (ENOENT); - } + rle = resource_list_find(rl, type, rid); + if (!rle) + return ENOENT; + + *startp = rle->start; + *countp = rle->count; - rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); + return 0; +} - if (rv == 0) { - switch (type) { - case SYS_RES_IRQ: - if (!passthrough) - cfg->irqres = 0; - break; - - case SYS_RES_DRQ: /* passthru for child isa */ - break; - -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - case SYS_RES_IOPORT: - if (map != -1) - cfg->map[map].res = 0; - break; - - default: - return ENOENT; - } - } - - return rv; +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 @@ -1477,6 +1359,9 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_set_resource, pci_set_resource), + DEVMETHOD(bus_get_resource, pci_get_resource), + DEVMETHOD(bus_delete_resource, pci_delete_resource), /* PCI interface */ DEVMETHOD(pci_read_config, pci_read_config_method), diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index ae4958dbf265..31cea00aa440 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -56,28 +56,11 @@ typedef u_int64_t pci_addr_t; /* u_int64_t for system with 64bit addresses */ typedef u_int32_t pci_addr_t; /* u_int64_t for system with 64bit addresses */ #endif -/* map register information */ - -typedef struct { - u_int32_t base; - u_int8_t type; -#define PCI_MAPMEM 0x01 /* memory map */ -#define PCI_MAPMEMP 0x02 /* prefetchable memory map */ -#define PCI_MAPPORT 0x04 /* port map */ - u_int8_t ln2size; - u_int8_t ln2range; - u_int8_t reg; /* offset of map register in config space */ -/* u_int8_t dummy;*/ - struct resource *res; /* handle from resource manager */ -} pcimap; - /* config header information common to all header types */ typedef struct pcicfg { struct device *dev; /* device which owns this */ - pcimap *map; /* pointer to array of PCI maps */ void *hdrspec; /* pointer to header type specific data */ - struct resource *irqres; /* resource descriptor for interrupt mapping */ u_int16_t subvendor; /* card vendor ID */ u_int16_t subdevice; /* card device ID, assigned by card vendor */ @@ -163,12 +146,6 @@ typedef struct pciattach { struct pciattach *next; } pciattach; -struct pci_devinfo { - STAILQ_ENTRY(pci_devinfo) pci_links; - pcicfgregs cfg; - struct pci_conf conf; -}; - extern u_int32_t pci_numdevs; @@ -192,6 +169,13 @@ pcicfgregs * pci_devlist_get_parent(pcicfgregs *cfg); #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, diff --git a/sys/i386/include/resource.h b/sys/i386/include/resource.h index adcf0ce00f9d..28fcc98ea1be 100644 --- a/sys/i386/include/resource.h +++ b/sys/i386/include/resource.h @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright 1998 Massachusetts Institute of Technology * @@ -39,7 +40,5 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#define SYS_RES_DENSE SYS_RES_MEMORY -#define SYS_RES_BWX SYS_RES_MEMORY #endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/sys/pci/pci.c b/sys/pci/pci.c index bfdf9d0452e0..f5da2d81c91c 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -60,13 +60,25 @@ #include #endif /* APIC_IO */ +/* map register information */ +#define PCI_MAPMEM 0x01 /* memory map */ +#define PCI_MAPMEMP 0x02 /* prefetchable memory map */ +#define PCI_MAPPORT 0x04 /* port map */ + +struct pci_devinfo { + STAILQ_ENTRY(pci_devinfo) pci_links; + struct resource_list resources; + pcicfgregs cfg; + struct pci_conf conf; +}; + static STAILQ_HEAD(devlist, pci_devinfo) pci_devq; u_int32_t pci_numdevs = 0; static u_int32_t pci_generation = 0; /* return base address of memory or port map */ -static int +static u_int32_t pci_mapbase(unsigned mapreg) { int mask = 0x03; @@ -135,91 +147,6 @@ pci_maprange(unsigned mapreg) return (ln2range); } -/* extract map parameters into newly allocated array of pcimap structures */ - -static pcimap * -pci_readmaps(pcicfgregs *cfg, int maxmaps) -{ - int i, j = 0; - pcimap *map; - int map64 = 0; - int reg = PCIR_MAPS; - - for (i = 0; i < maxmaps; i++) { - int reg = PCIR_MAPS + i*4; - u_int32_t base; - u_int32_t ln2range; - - base = pci_cfgread(cfg, reg, 4); - ln2range = pci_maprange(base); - - if (base == 0 || ln2range == 0 || base == 0xffffffff) - continue; /* skip invalid entry */ - else { - j++; - if (ln2range > 32) { - i++; - j++; - } - } - } - - map = malloc(j * sizeof (pcimap), M_DEVBUF, M_WAITOK); - if (map != NULL) { - bzero(map, sizeof(pcimap) * j); - cfg->nummaps = j; - - for (i = 0, j = 0; i < maxmaps; i++, reg += 4) { - u_int32_t base; - u_int32_t testval; - - base = pci_cfgread(cfg, reg, 4); - - if (map64 == 0) { - if (base == 0 || base == 0xffffffff) - continue; /* skip invalid entry */ - - pci_cfgwrite(cfg, reg, 0xffffffff, 4); - testval = pci_cfgread(cfg, reg, 4); - pci_cfgwrite(cfg, reg, base, 4); - - map[j].reg = reg; - map[j].base = pci_mapbase(base); - map[j].type = pci_maptype(base); - map[j].ln2size = pci_mapsize(testval); - map[j].ln2range = pci_maprange(testval); - map64 = map[j].ln2range == 64; - } else { - /* only fill in base, other fields are 0 */ - map[j].base = base; - map64 = 0; - } -#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(map[j].base & 0x80000000){ - printf("base addr = 0x%x\n", map[j].base); - printf("hacked addr = 0x%x\n", - map[j].base | (cfg->hose << 31)); - - panic("hose encoding hack would clobber base addr"); - } - if(cfg->hose > 1 ) - panic("only one hose supported!"); - map[j].base |= (cfg->hose << 31); - } -#endif - j++; - } - } - return (map); -} - /* adjust some values from PCI 1.0 devices to match 2.0 standards ... */ static void @@ -312,14 +239,14 @@ pci_hdrtypedata(pcicfgregs *cfg) case 0: cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2); cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_0); + cfg->nummaps = PCI_MAXMAPS_0; break; case 1: cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2); cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2); cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1); cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_1); + cfg->nummaps = PCI_MAXMAPS_1; cfg->hdrspec = pci_readppb(cfg); break; case 2: @@ -327,7 +254,7 @@ pci_hdrtypedata(pcicfgregs *cfg) cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2); cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1); cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1); - cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_2); + cfg->nummaps = PCI_MAXMAPS_2; cfg->hdrspec = pci_readpcb(cfg); break; } @@ -1010,7 +937,6 @@ static void pci_print_verbose(struct pci_devinfo *dinfo) { if (bootverbose) { - int i; pcicfgregs *cfg = &dinfo->cfg; printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", @@ -1029,20 +955,105 @@ pci_print_verbose(struct pci_devinfo *dinfo) #endif /* PCI_DEBUG */ if (cfg->intpin > 0) printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); - - for (i = 0; i < cfg->nummaps; i++) { - pcimap *m = &cfg->map[i]; - printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", - i, m->type, m->ln2range, m->base, m->ln2size); - } } } static int +pci_porten(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); +} + +static int +pci_memen(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); +} + +static void +pci_add_resources(device_t dev, pcicfgregs* cfg) +{ + + struct pci_devinfo *dinfo = device_get_ivars(dev); + struct resource_list *rl = &dinfo->resources; + 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_IOPORT && !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); + } + } + if (cfg->intline) + resource_list_add(rl, SYS_RES_IRQ, 0, + cfg->intline, cfg->intline, 1); +} + +static void pci_add_children(device_t dev, int busno) { pcicfgregs probe; - int bushigh = busno; #ifdef SIMOS #undef PCI_SLOTMAX @@ -1069,16 +1080,10 @@ pci_add_children(device_t dev, int busno) pci_print_verbose(dinfo); dinfo->cfg.dev = device_add_child(dev, NULL, -1, dinfo); - - if (bushigh < dinfo->cfg.subordinatebus) - bushigh = dinfo->cfg.subordinatebus; - if (bushigh < dinfo->cfg.secondarybus) - bushigh = dinfo->cfg.secondarybus; + pci_add_resources(dinfo->cfg.dev, &dinfo->cfg); } } } - - return bushigh; } static int @@ -1248,181 +1253,58 @@ pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) return 0; } -static int -pci_mapno(pcicfgregs *cfg, int reg) -{ - int i, nummaps; - pcimap *map; - - nummaps = cfg->nummaps; - map = cfg->map; - - for (i = 0; i < nummaps; i++) - if (map[i].reg == reg) - return (i); - return (-1); -} - -static int -pci_porten(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); -} - -static int -pci_isportmap(pcicfgregs *cfg, int map) - -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPPORT) != 0); -} - -static int -pci_memen(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); -} - -static int -pci_ismemmap(pcicfgregs *cfg, int map) -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPMEM) != 0); -} - static struct resource * pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - int isdefault; struct pci_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - struct resource *rv, **rvp = 0; - int map; + struct resource_list *rl = &dinfo->resources; - isdefault = (device_get_parent(child) == dev - && start == 0UL && end == ~0UL); - - switch (type) { - case SYS_RES_IRQ: - if (*rid != 0) - return 0; - if (isdefault && cfg->intline != 255) { - start = cfg->intline; - end = cfg->intline; - count = 1; - } - break; - - case SYS_RES_DRQ: /* passthru for child isa */ - break; - -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - if (isdefault) { - map = pci_mapno(cfg, *rid); - if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { - start = cfg->map[map].base; - count = 1 << cfg->map[map].ln2size; - end = start + count; - rvp = &cfg->map[map].res; - } else - return 0; - } - break; - - case SYS_RES_IOPORT: - if (isdefault) { - map = pci_mapno(cfg, *rid); - if (pci_porten(cfg) && pci_isportmap(cfg, map)) { - start = cfg->map[map].base; - count = 1 << cfg->map[map].ln2size; - end = start + count; - rvp = &cfg->map[map].res; - } else - return 0; - } - break; - - default: - return 0; - } - - rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - type, rid, start, end, count, flags); - if (rvp) - *rvp = rv; - - return rv; + return resource_list_alloc(rl, dev, child, type, rid, + start, end, count, flags); } static int pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { - int rv; struct pci_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - int map = 0; - int passthrough = (device_get_parent(child) != dev); + struct resource_list *rl = &dinfo->resources; - switch (type) { - case SYS_RES_IRQ: - if (rid != 0) - return EINVAL; - break; + return resource_list_release(rl, dev, child, type, rid, r); +} - case SYS_RES_DRQ: /* passthru for child isa */ - break; +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; +} -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - case SYS_RES_IOPORT: - /* - * Only check the map registers if this is a direct - * descendant. - */ - map = passthrough ? -1 : pci_mapno(cfg, rid); - break; +static int +pci_get_resource(device_t dev, device_t child, int type, int rid, + u_long *startp, u_long *countp) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + struct resource_list *rl = &dinfo->resources; + struct resource_list_entry *rle; - default: - return (ENOENT); - } + rle = resource_list_find(rl, type, rid); + if (!rle) + return ENOENT; + + *startp = rle->start; + *countp = rle->count; - rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); + return 0; +} - if (rv == 0) { - switch (type) { - case SYS_RES_IRQ: - if (!passthrough) - cfg->irqres = 0; - break; - - case SYS_RES_DRQ: /* passthru for child isa */ - break; - -#ifdef __alpha__ - case SYS_RES_DENSE: - case SYS_RES_BWX: -#endif - case SYS_RES_MEMORY: - case SYS_RES_IOPORT: - if (map != -1) - cfg->map[map].res = 0; - break; - - default: - return ENOENT; - } - } - - return rv; +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 @@ -1477,6 +1359,9 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_set_resource, pci_set_resource), + DEVMETHOD(bus_get_resource, pci_get_resource), + DEVMETHOD(bus_delete_resource, pci_delete_resource), /* PCI interface */ DEVMETHOD(pci_read_config, pci_read_config_method), diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c index c007dc577063..d8c4139b05aa 100644 --- a/sys/pci/pci_compat.c +++ b/sys/pci/pci_compat.c @@ -112,8 +112,8 @@ pci_map_dense(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) struct resource *res; rid = reg; - res = bus_alloc_resource(cfg->dev, SYS_RES_DENSE, &rid, - 0, ~0, 1, RF_ACTIVE); + res = bus_alloc_resource(cfg->dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE|PCI_RF_DENSE); if (res) { *pa = rman_get_start(res); *va = (vm_offset_t) rman_get_virtual(res); @@ -129,8 +129,8 @@ pci_map_bwx(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) struct resource *res; rid = reg; - res = bus_alloc_resource(cfg->dev, SYS_RES_BWX, &rid, - 0, ~0, 1, RF_ACTIVE); + res = bus_alloc_resource(cfg->dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE|PCI_RF_BWX); if (res) { *pa = rman_get_start(res); *va = (vm_offset_t) rman_get_virtual(res); diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c index 33ea09c41a53..c49daf864ffb 100644 --- a/sys/pci/pcisupport.c +++ b/sys/pci/pcisupport.c @@ -769,16 +769,13 @@ static int pcib_probe(device_t dev) static int pcib_attach(device_t dev) { - struct pci_devinfo *dinfo; - pcicfgregs *cfg; - - dinfo = device_get_ivars(dev); - cfg = &dinfo->cfg; + u_int8_t secondary; chipset_attach(dev, device_get_unit(dev)); - if (cfg->secondarybus) { - device_add_child(dev, "pci", cfg->secondarybus, 0); + secondary = pci_get_secondarybus(dev); + if (secondary) { + device_add_child(dev, "pci", secondary, 0); return bus_generic_attach(dev); } else return 0; diff --git a/sys/pci/pcivar.h b/sys/pci/pcivar.h index ae4958dbf265..31cea00aa440 100644 --- a/sys/pci/pcivar.h +++ b/sys/pci/pcivar.h @@ -56,28 +56,11 @@ typedef u_int64_t pci_addr_t; /* u_int64_t for system with 64bit addresses */ typedef u_int32_t pci_addr_t; /* u_int64_t for system with 64bit addresses */ #endif -/* map register information */ - -typedef struct { - u_int32_t base; - u_int8_t type; -#define PCI_MAPMEM 0x01 /* memory map */ -#define PCI_MAPMEMP 0x02 /* prefetchable memory map */ -#define PCI_MAPPORT 0x04 /* port map */ - u_int8_t ln2size; - u_int8_t ln2range; - u_int8_t reg; /* offset of map register in config space */ -/* u_int8_t dummy;*/ - struct resource *res; /* handle from resource manager */ -} pcimap; - /* config header information common to all header types */ typedef struct pcicfg { struct device *dev; /* device which owns this */ - pcimap *map; /* pointer to array of PCI maps */ void *hdrspec; /* pointer to header type specific data */ - struct resource *irqres; /* resource descriptor for interrupt mapping */ u_int16_t subvendor; /* card vendor ID */ u_int16_t subdevice; /* card device ID, assigned by card vendor */ @@ -163,12 +146,6 @@ typedef struct pciattach { struct pciattach *next; } pciattach; -struct pci_devinfo { - STAILQ_ENTRY(pci_devinfo) pci_links; - pcicfgregs cfg; - struct pci_conf conf; -}; - extern u_int32_t pci_numdevs; @@ -192,6 +169,13 @@ pcicfgregs * pci_devlist_get_parent(pcicfgregs *cfg); #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, diff --git a/sys/powerpc/include/resource.h b/sys/powerpc/include/resource.h index adcf0ce00f9d..28fcc98ea1be 100644 --- a/sys/powerpc/include/resource.h +++ b/sys/powerpc/include/resource.h @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright 1998 Massachusetts Institute of Technology * @@ -39,7 +40,5 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#define SYS_RES_DENSE SYS_RES_MEMORY -#define SYS_RES_BWX SYS_RES_MEMORY #endif /* !_MACHINE_RESOURCE_H_ */