diff options
author | imp <imp@FreeBSD.org> | 2002-02-27 05:09:14 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2002-02-27 05:09:14 +0000 |
commit | 08e793ff1516af442ad2104e345dc13f96a5189c (patch) | |
tree | ee76a2dce2896540a9561f86f7b47399fc382ce4 /sys | |
parent | c8a6bd99227ca59b48fafa66f2a21ddb86096d9e (diff) | |
download | FreeBSD-src-08e793ff1516af442ad2104e345dc13f96a5189c.zip FreeBSD-src-08e793ff1516af442ad2104e345dc13f96a5189c.tar.gz |
Use the pci.c code wherever possible, rather than copying all the pci
code into cardbus and s/pci/cardbus. This exposes a few pci_*
functions that are now static.
This work is similar to work Justin posted to the mobile list about a
year or two ago, which I have neglected since then.
This is a subset of his current work with the multiple inheritance
newbus architecutre. When completed, that will eliminate the need for
pci/pci_private.h.
Similar work is needed for the cardbus_cis and pccard_cis code as well.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/cardbus/cardbus.c | 990 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_cis.c | 79 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbusvar.h | 21 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 103 | ||||
-rw-r--r-- | sys/dev/pci/pci_private.h | 67 |
5 files changed, 220 insertions, 1040 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index c6a30e5..c6f1f8f 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -28,12 +28,11 @@ * $FreeBSD$ */ +/* XXX pci_cfgfree vs cardbus_cfgfree */ + /* * Cardbus Bus Driver * - * much of the bus code was stolen directly from sys/pci/pci.c - * (Copyright (c) 1997, Stefan Esser <se@freebsd.org>) - * * Written by Jonathan Chen <jon@freebsd.org> */ @@ -49,9 +48,10 @@ #include <sys/rman.h> #include <machine/resource.h> +#include <sys/pciio.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <sys/pciio.h> +#include <dev/pci/pci_private.h> #include <dev/cardbus/cardbusreg.h> #include <dev/cardbus/cardbusvar.h> @@ -82,62 +82,8 @@ static void device_setup_regs(device_t brdev, int b, int s, int f, static int cardbus_attach_card(device_t cbdev); static int cardbus_detach_card(device_t cbdev, int flags); static void cardbus_driver_added(device_t cbdev, driver_t *driver); -static void cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg); -static void cardbus_hdrtypedata(device_t brdev, int b, int s, int f, - pcicfgregs *cfg); -static struct cardbus_devinfo *cardbus_read_device(device_t brdev, int b, - int s, int f); -static int cardbus_freecfg(struct cardbus_devinfo *dinfo); -static void cardbus_print_verbose(struct cardbus_devinfo *dinfo); -static int cardbus_set_resource(device_t cbdev, device_t child, int type, - int rid, u_long start, u_long count, struct resource *res); -static int cardbus_get_resource(device_t cbdev, device_t child, int type, - int rid, u_long *startp, u_long *countp); -static void cardbus_delete_resource(device_t cbdev, device_t child, - int type, int rid); -static int cardbus_set_resource_method(device_t cbdev, device_t child, - int type, int rid, u_long start, u_long count); -static int cardbus_get_resource_method(device_t cbdev, device_t child, - int type, int rid, u_long *startp, u_long *countp); -static void cardbus_delete_resource_method(device_t cbdev, device_t child, - int type, int rid); static void cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo); -static struct resource *cardbus_alloc_resource(device_t cbdev, device_t child, - int type, int *rid, u_long start, u_long end, u_long count, - u_int flags); -static int cardbus_release_resource(device_t cbdev, device_t child, - int type, int rid, struct resource *r); -static int cardbus_setup_intr(device_t cbdev, device_t child, - struct resource *irq, int flags, driver_intr_t *intr, - void *arg, void **cookiep); -static int cardbus_teardown_intr(device_t cbdev, device_t child, - struct resource *irq, void *cookie); -static int cardbus_print_resources(struct resource_list *rl, - const char *name, int type, const char *format); -static int cardbus_print_child(device_t cbdev, device_t child); -static void cardbus_probe_nomatch(device_t cbdev, device_t child); -static int cardbus_read_ivar(device_t cbdev, device_t child, int which, - u_long *result); -static int cardbus_write_ivar(device_t cbdev, device_t child, int which, - uintptr_t value); -static int cardbus_set_powerstate_method(device_t cbdev, device_t child, - int state); -static int cardbus_get_powerstate_method(device_t cbdev, device_t child); -static u_int32_t cardbus_read_config_method(device_t cbdev, - device_t child, int reg, int width); -static void cardbus_write_config_method(device_t cbdev, device_t child, - int reg, u_int32_t val, int width); -static __inline void cardbus_set_command_bit(device_t cbdev, device_t child, - u_int16_t bit); -static __inline void cardbus_clear_command_bit(device_t cbdev, device_t child, - u_int16_t bit); -static void cardbus_enable_busmaster_method(device_t cbdev, device_t child); -static void cardbus_disable_busmaster_method(device_t cbdev, device_t child); -static void cardbus_enable_io_method(device_t cbdev, device_t child, - int space); -static void cardbus_disable_io_method(device_t cbdev, device_t child, - int space); /************************************************************************/ /* Probe/Attach */ @@ -207,6 +153,8 @@ cardbus_attach_card(device_t cbdev) int cardattached = 0; static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */ int bus, slot, func; + struct cardbus_devinfo *dinfo; + int cardbusfunchigh = 0; cardbus_detach_card(cbdev, 0); /* detach existing cards */ @@ -226,28 +174,28 @@ cardbus_attach_card(device_t cbdev) } /* For each function, set it up and try to attach a driver to it */ for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) { - int cardbusfunchigh = 0; + cardbusfunchigh = 0; for (func = 0; func <= cardbusfunchigh; func++) { - struct cardbus_devinfo *dinfo = - cardbus_read_device(brdev, bus, slot, func); + dinfo = (struct cardbus_devinfo *) + pci_read_device(brdev, bus, slot, func); if (dinfo == NULL) continue; - if (dinfo->cfg.mfdev) + if (dinfo->pci.cfg.mfdev) cardbusfunchigh = CARDBUS_FUNCMAX; - device_setup_regs(brdev, bus, slot, func, &dinfo->cfg); - cardbus_print_verbose(dinfo); - dinfo->cfg.dev = device_add_child(cbdev, NULL, -1); - if (!dinfo->cfg.dev) { + device_setup_regs(brdev, bus, slot, func, + &dinfo->pci.cfg); + pci_print_verbose(&dinfo->pci); + dinfo->pci.cfg.dev = device_add_child(cbdev, NULL, -1); + if (!dinfo->pci.cfg.dev) { DEVPRINTF((cbdev, "Cannot add child!\n")); - cardbus_freecfg(dinfo); + pci_freecfg(&dinfo->pci); continue; } - resource_list_init(&dinfo->resources); - SLIST_INIT(&dinfo->intrlist); - device_set_ivars(dinfo->cfg.dev, dinfo); - cardbus_do_cis(cbdev, dinfo->cfg.dev); - if (device_probe_and_attach(dinfo->cfg.dev) != 0) { + resource_list_init(&dinfo->pci.resources); + device_set_ivars(dinfo->pci.cfg.dev, &dinfo->pci); + cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); + if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) { /* when fail, release all resources */ cardbus_release_all_resources(cbdev, dinfo); } else @@ -268,6 +216,8 @@ cardbus_detach_card(device_t cbdev, int flags) device_t *devlist; int tmp; int err = 0; + struct cardbus_devinfo *dinfo; + int status; device_get_children(cbdev, &devlist, &numdevs); @@ -280,22 +230,22 @@ cardbus_detach_card(device_t cbdev, int flags) } for (tmp = 0; tmp < numdevs; tmp++) { - struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); - int status = device_get_state(devlist[tmp]); + dinfo = device_get_ivars(devlist[tmp]); + status = device_get_state(devlist[tmp]); if (status == DS_ATTACHED || status == DS_BUSY) { - if (device_detach(dinfo->cfg.dev) == 0 || + if (device_detach(dinfo->pci.cfg.dev) == 0 || flags & DETACH_FORCE) { cardbus_release_all_resources(cbdev, dinfo); device_delete_child(cbdev, devlist[tmp]); } else { err++; } - cardbus_freecfg(dinfo); + pci_freecfg(&dinfo->pci); } else { cardbus_release_all_resources(cbdev, dinfo); device_delete_child(cbdev, devlist[tmp]); - cardbus_freecfg(dinfo); + pci_freecfg(&dinfo->pci); } } if (err == 0) @@ -307,10 +257,10 @@ cardbus_detach_card(device_t cbdev, int flags) static void cardbus_driver_added(device_t cbdev, driver_t *driver) { - /* XXX check if 16-bit or cardbus! */ int numdevs; device_t *devlist; int tmp, cardattached; + struct cardbus_devinfo *dinfo; device_get_children(cbdev, &devlist, &numdevs); @@ -329,14 +279,13 @@ cardbus_driver_added(device_t cbdev, driver_t *driver) DEVICE_IDENTIFY(driver, cbdev); for (tmp = 0; tmp < numdevs; tmp++) { if (device_get_state(devlist[tmp]) == DS_NOTPRESENT) { - struct cardbus_devinfo *dinfo; dinfo = device_get_ivars(devlist[tmp]); cardbus_release_all_resources(cbdev, dinfo); - resource_list_init(&dinfo->resources); - cardbus_do_cis(cbdev, dinfo->cfg.dev); - if (device_probe_and_attach(dinfo->cfg.dev) != 0) { + resource_list_init(&dinfo->pci.resources); + cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); + if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) cardbus_release_all_resources(cbdev, dinfo); - } else + else cardattached++; } } @@ -345,343 +294,16 @@ cardbus_driver_added(device_t cbdev, driver_t *driver) } /************************************************************************/ -/* PCI-Like config reading (copied from pci.c */ -/************************************************************************/ - -/* read configuration header into pcicfgrect structure */ - -static void -cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg) -{ -#define REG(n, w) PCIB_READ_CONFIG(cbdev, cfg->bus, cfg->slot, cfg->func, n, w) - int ptr, nextptr, ptrptr; - - switch (cfg->hdrtype) { - case 0: - ptrptr = 0x34; - break; - case 2: - ptrptr = 0x14; - break; - default: - return; /* no extended capabilities support */ - } - nextptr = REG(ptrptr, 1); /* sanity check? */ - - /* - * Read capability entries. - */ - while (nextptr != 0) { - /* Sanity check */ - if (nextptr > 255) { - printf("illegal PCI extended capability offset %d\n", - nextptr); - return; - } - /* Find the next entry */ - ptr = nextptr; - nextptr = REG(ptr + 1, 1); - - /* Process this entry */ - switch (REG(ptr, 1)) { - case 0x01: /* PCI power management */ - if (cfg->pp_cap == 0) { - cfg->pp_cap = REG(ptr + PCIR_POWER_CAP, 2); - cfg->pp_status = ptr + PCIR_POWER_STATUS; - cfg->pp_pmcsr = ptr + PCIR_POWER_PMCSR; - if ((nextptr - ptr) > PCIR_POWER_DATA) - cfg->pp_data = ptr + PCIR_POWER_DATA; - } - break; - default: - break; - } - } -#undef REG -} - -/* extract header type specific config data */ - -static void -cardbus_hdrtypedata(device_t brdev, int b, int s, int f, pcicfgregs *cfg) -{ -#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) - switch (cfg->hdrtype) { - case 0: - cfg->subvendor = REG(PCIR_SUBVEND_0, 2); - cfg->subdevice = REG(PCIR_SUBDEV_0, 2); - cfg->nummaps = PCI_MAXMAPS_0; - break; - case 1: - cfg->subvendor = REG(PCIR_SUBVEND_1, 2); - cfg->subdevice = REG(PCIR_SUBDEV_1, 2); - cfg->nummaps = PCI_MAXMAPS_1; - break; - case 2: - cfg->subvendor = REG(PCIR_SUBVEND_2, 2); - cfg->subdevice = REG(PCIR_SUBDEV_2, 2); - cfg->nummaps = PCI_MAXMAPS_2; - break; - } -#undef REG -} - -static struct cardbus_devinfo * -cardbus_read_device(device_t brdev, int b, int s, int f) -{ -#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) - pcicfgregs *cfg = NULL; - struct cardbus_devinfo *devlist_entry = NULL; - - if (REG(PCIR_DEVVENDOR, 4) != -1) { - devlist_entry = malloc(sizeof(struct cardbus_devinfo), - M_DEVBUF, M_WAITOK | M_ZERO); - if (devlist_entry == NULL) - return (NULL); - - cfg = &devlist_entry->cfg; - - cfg->bus = b; - cfg->slot = s; - cfg->func = f; - cfg->vendor = REG(PCIR_VENDOR, 2); - cfg->device = REG(PCIR_DEVICE, 2); - cfg->cmdreg = REG(PCIR_COMMAND, 2); - cfg->statreg = REG(PCIR_STATUS, 2); - cfg->baseclass = REG(PCIR_CLASS, 1); - cfg->subclass = REG(PCIR_SUBCLASS, 1); - cfg->progif = REG(PCIR_PROGIF, 1); - cfg->revid = REG(PCIR_REVID, 1); - cfg->hdrtype = REG(PCIR_HEADERTYPE, 1); - cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1); - cfg->lattimer = REG(PCIR_LATTIMER, 1); - cfg->intpin = REG(PCIR_INTPIN, 1); - cfg->intline = REG(PCIR_INTLINE, 1); - - cfg->mingnt = REG(PCIR_MINGNT, 1); - cfg->maxlat = REG(PCIR_MAXLAT, 1); - - cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; - cfg->hdrtype &= ~PCIM_MFDEV; - - cardbus_hdrtypedata(brdev, b, s, f, cfg); - - if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT) - cardbus_read_extcap(brdev, cfg); - - devlist_entry->conf.pc_sel.pc_bus = cfg->bus; - devlist_entry->conf.pc_sel.pc_dev = cfg->slot; - devlist_entry->conf.pc_sel.pc_func = cfg->func; - devlist_entry->conf.pc_hdr = cfg->hdrtype; - - devlist_entry->conf.pc_subvendor = cfg->subvendor; - devlist_entry->conf.pc_subdevice = cfg->subdevice; - devlist_entry->conf.pc_vendor = cfg->vendor; - devlist_entry->conf.pc_device = cfg->device; - - devlist_entry->conf.pc_class = cfg->baseclass; - devlist_entry->conf.pc_subclass = cfg->subclass; - devlist_entry->conf.pc_progif = cfg->progif; - devlist_entry->conf.pc_revid = cfg->revid; - } - return (devlist_entry); -#undef REG -} - -/* free pcicfgregs structure and all depending data structures */ - -static int -cardbus_freecfg(struct cardbus_devinfo *dinfo) -{ - free(dinfo, M_DEVBUF); - - return (0); -} - -static void -cardbus_print_verbose(struct cardbus_devinfo *dinfo) -{ -#ifndef CARDBUS_DEBUG - if (bootverbose) -#endif /* CARDBUS_DEBUG */ - { - pcicfgregs *cfg = &dinfo->cfg; - - printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", - cfg->vendor, cfg->device, cfg->revid); - printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", - cfg->baseclass, cfg->subclass, cfg->progif, - cfg->hdrtype, cfg->mfdev); -#ifdef CARDBUS_DEBUG - printf("\tcmdreg=0x%04x, statreg=0x%04x, " - "cachelnsz=%d (dwords)\n", - cfg->cmdreg, cfg->statreg, cfg->cachelnsz); - printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), " - "maxlat=0x%02x (%d ns)\n", - cfg->lattimer, cfg->lattimer * 30, - cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, - cfg->maxlat * 250); -#endif /* CARDBUS_DEBUG */ - if (cfg->intpin > 0) - printf("\tintpin=%c, irq=%d\n", - cfg->intpin + 'a' - 1, cfg->intline); - } -} - -/************************************************************************/ /* Resources */ /************************************************************************/ -static int -cardbus_set_resource(device_t cbdev, device_t child, int type, int rid, - u_long start, u_long count, struct resource *res) -{ - struct cardbus_devinfo *dinfo; - struct resource_list *rl; - struct resource_list_entry *rle; - - if (device_get_parent(child) != cbdev) - return ENOENT; - - dinfo = device_get_ivars(child); - rl = &dinfo->resources; - rle = resource_list_find(rl, type, rid); - if (rle == NULL) { - resource_list_add(rl, type, rid, start, start + count - 1, - count); - if (res != NULL) { - rle = resource_list_find(rl, type, rid); - rle->res = res; - } - } else { - if (rle->res == NULL) { - } else if (rle->res->r_dev == cbdev && - (!(rman_get_flags(rle->res) & RF_ACTIVE))) { - int f; - f = rman_get_flags(rle->res); - bus_release_resource(cbdev, type, rid, res); - rle->res = bus_alloc_resource(cbdev, type, &rid, - start, start + count - 1, - count, f); - } else { - device_printf(cbdev, "set_resource: resource busy\n"); - return EBUSY; - } - rle->start = start; - rle->end = start + count - 1; - rle->count = count; - if (res != NULL) - rle->res = res; - } - if (device_get_parent(child) == cbdev) - pci_write_config(child, rid, start, 4); - return 0; -} - -static int -cardbus_get_resource(device_t cbdev, device_t child, int type, int rid, - u_long *startp, u_long *countp) -{ - struct cardbus_devinfo *dinfo; - struct resource_list *rl; - struct resource_list_entry *rle; - - if (device_get_parent(child) != cbdev) - return ENOENT; - - dinfo = device_get_ivars(child); - rl = &dinfo->resources; - rle = resource_list_find(rl, type, rid); - if (!rle) - return ENOENT; - if (startp) - *startp = rle->start; - if (countp) - *countp = rle->count; - return 0; -} - -static void -cardbus_delete_resource(device_t cbdev, device_t child, int type, int rid) -{ - struct cardbus_devinfo *dinfo; - struct resource_list *rl; - struct resource_list_entry *rle; - - if (device_get_parent(child) != cbdev) - return; - - dinfo = device_get_ivars(child); - rl = &dinfo->resources; - rle = resource_list_find(rl, type, rid); - if (rle) { - if (rle->res) { - if (rle->res->r_dev != cbdev || - rman_get_flags(rle->res) & RF_ACTIVE) { - device_printf(cbdev, "delete_resource: " - "Resource still owned by child, oops. " - "(type=%d, rid=%d, addr=%lx)\n", - rle->type, rle->rid, - rman_get_start(rle->res)); - return; - } - bus_release_resource(cbdev, type, rid, rle->res); - } - resource_list_delete(rl, type, rid); - } - if (device_get_parent(child) == cbdev) - pci_write_config(child, rid, 0, 4); -} - -static int -cardbus_set_resource_method(device_t cbdev, device_t child, int type, int rid, - u_long start, u_long count) -{ - int ret; - ret = cardbus_set_resource(cbdev, child, type, rid, start, count, NULL); - if (ret != 0) - return ret; - return BUS_SET_RESOURCE(device_get_parent(cbdev), child, type, rid, - start, count); -} - -static int -cardbus_get_resource_method(device_t cbdev, device_t child, int type, int rid, - u_long *startp, u_long *countp) -{ - int ret; - ret = cardbus_get_resource(cbdev, child, type, rid, startp, countp); - if (ret != 0) - return ret; - return BUS_GET_RESOURCE(device_get_parent(cbdev), child, type, rid, - startp, countp); -} - -static void -cardbus_delete_resource_method(device_t cbdev, device_t child, - int type, int rid) -{ - cardbus_delete_resource(cbdev, child, type, rid); - BUS_DELETE_RESOURCE(device_get_parent(cbdev), child, type, rid); -} - static void cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) { struct resource_list_entry *rle; - struct cardbus_intrlist *ile; - - /* Remove any interrupt handlers */ - while (NULL != (ile = SLIST_FIRST(&dinfo->intrlist))) { - device_printf(cbdev, "release_all_resource: " - "intr handler still active, removing.\n"); - bus_teardown_intr(ile->dev, ile->irq, ile->cookie); - SLIST_REMOVE_HEAD(&dinfo->intrlist, link); - free(ile, M_DEVBUF); - } /* Free all allocated resources */ - SLIST_FOREACH(rle, &dinfo->resources, link) { + SLIST_FOREACH(rle, &dinfo->pci.resources, link) { if (rle->res) { if (rle->res->r_dev != cbdev) device_printf(cbdev, "release_all_resource: " @@ -698,511 +320,10 @@ cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) * zero out config so the card won't acknowledge * access to the space anymore */ - pci_write_config(dinfo->cfg.dev, rle->rid, 0, 4); - } - } - resource_list_free(&dinfo->resources); -} - -static struct resource * -cardbus_alloc_resource(device_t cbdev, device_t child, int type, - int *rid, u_long start, u_long end, u_long count, u_int flags) -{ - struct cardbus_devinfo *dinfo; - struct resource_list_entry *rle = 0; - int passthrough = (device_get_parent(child) != cbdev); - - if (passthrough) { - return (BUS_ALLOC_RESOURCE(device_get_parent(cbdev), child, - type, rid, start, end, count, flags)); - } - - dinfo = device_get_ivars(child); - rle = resource_list_find(&dinfo->resources, type, *rid); - - if (!rle) - return NULL; /* no resource of that type/rid */ - - if (!rle->res) { - device_printf(cbdev, "WARNING: Resource not reserved by bus\n"); - return NULL; - } else { - /* Release the cardbus hold on the resource */ - if (rle->res->r_dev != cbdev) - return NULL; - bus_release_resource(cbdev, type, *rid, rle->res); - rle->res = NULL; - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - if (!(flags & RF_ALIGNMENT_MASK)) - flags |= rman_make_alignment_flags(rle->count); - break; - case SYS_RES_IRQ: - flags |= RF_SHAREABLE; - break; + pci_write_config(dinfo->pci.cfg.dev, rle->rid, 0, 4); } - /* Allocate the resource to the child */ - return resource_list_alloc(&dinfo->resources, cbdev, child, - type, rid, rle->start, rle->end, rle->count, flags); - } -} - -static int -cardbus_release_resource(device_t cbdev, device_t child, int type, int rid, - struct resource *r) -{ - struct cardbus_devinfo *dinfo; - int passthrough = (device_get_parent(child) != cbdev); - struct resource_list_entry *rle = 0; - int flags; - int ret; - - if (passthrough) { - return BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, - type, rid, r); - } - - dinfo = device_get_ivars(child); - /* - * According to the PCI 2.2 spec, devices may share an address - * decoder between memory mapped ROM access and memory - * mapped register access. To be safe, disable ROM access - * whenever it is released. - */ - if (rid == CARDBUS_ROM_REG) { - uint32_t rom_reg; - - rom_reg = pci_read_config(child, rid, 4); - rom_reg &= ~CARDBUS_ROM_ENABLE; - pci_write_config(child, rid, rom_reg, 4); - } - - rle = resource_list_find(&dinfo->resources, type, rid); - - if (!rle) { - device_printf(cbdev, "Allocated resource not found\n"); - return ENOENT; - } - if (!rle->res) { - device_printf(cbdev, "Allocated resource not recorded\n"); - return ENOENT; - } - - ret = BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, - type, rid, r); - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - flags = rman_make_alignment_flags(rle->count); - break; - case SYS_RES_IRQ: - flags = RF_SHAREABLE; - break; - default: - flags = 0; - } - /* Restore cardbus hold on the resource */ - rle->res = bus_alloc_resource(cbdev, type, &rid, - rle->start, rle->end, rle->count, flags); - if (rle->res == NULL) - device_printf(cbdev, "release_resource: " - "unable to reacquire resource\n"); - return ret; -} - -static int -cardbus_setup_intr(device_t cbdev, device_t child, struct resource *irq, - int flags, driver_intr_t *intr, void *arg, void **cookiep) -{ - int ret; - struct cardbus_intrlist *ile; - device_t cdev; - struct cardbus_devinfo *dinfo; - - ret = bus_generic_setup_intr(cbdev, child, irq, flags, intr, arg, - cookiep); - if (ret != 0) - return ret; - - for (cdev = child; cbdev != device_get_parent(cdev); - cdev = device_get_parent(cdev)) - /* NOTHING */; - dinfo = device_get_ivars(cdev); - - /* record interrupt handler */ - ile = malloc(sizeof(struct cardbus_intrlist), M_DEVBUF, M_NOWAIT); - ile->dev = child; - ile->irq = irq; - ile->cookie = *cookiep; - - SLIST_INSERT_HEAD(&dinfo->intrlist, ile, link); - return 0; -} - -static int -cardbus_teardown_intr(device_t cbdev, device_t child, struct resource *irq, - void *cookie) -{ - int ret; - struct cardbus_intrlist *ile; - device_t cdev; - struct cardbus_devinfo *dinfo; - - ret = bus_generic_teardown_intr(cbdev, child, irq, cookie); - if (ret != 0) - return ret; - - for (cdev = child; cbdev != device_get_parent(cdev); - cdev = device_get_parent(cdev)) - /* NOTHING */; - dinfo = device_get_ivars(cdev); - - /* remove interrupt handler from record */ - SLIST_FOREACH(ile, &dinfo->intrlist, link) { - if (ile->irq == irq && ile->cookie == cookie) { - SLIST_REMOVE(&dinfo->intrlist, ile, cardbus_intrlist, - link); - free(ile, M_DEVBUF); - return 0; - } - } - device_printf(cbdev, "teardown_intr: intr handler not recorded.\n"); - return ENOENT; -} - - -/************************************************************************/ -/* Other Bus Methods */ -/************************************************************************/ - -static int -cardbus_print_resources(struct resource_list *rl, const char *name, - int type, const char *format) -{ - struct resource_list_entry *rle; - int printed, retval; - - printed = 0; - retval = 0; - /* Yes, this is kinda cheating */ - SLIST_FOREACH(rle, rl, link) { - if (rle->type == type) { - if (printed == 0) - retval += printf(" %s ", name); - else if (printed > 0) - retval += printf(","); - printed++; - retval += printf(format, rle->start); - if (rle->count > 1) { - retval += printf("-"); - retval += printf(format, rle->start + - rle->count - 1); - } - } - } - return retval; -} - -static int -cardbus_print_child(device_t cbdev, device_t child) -{ - struct cardbus_devinfo *dinfo; - struct resource_list *rl; - pcicfgregs *cfg; - int retval = 0; - - dinfo = device_get_ivars(child); - cfg = &dinfo->cfg; - rl = &dinfo->resources; - - retval += bus_print_child_header(cbdev, child); - - retval += cardbus_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx"); - retval += cardbus_print_resources(rl, "mem", SYS_RES_MEMORY, "%#lx"); - retval += cardbus_print_resources(rl, "irq", SYS_RES_IRQ, "%ld"); - if (device_get_flags(cbdev)) - retval += printf(" flags %#x", device_get_flags(cbdev)); - - retval += printf(" at device %d.%d", pci_get_slot(child), - pci_get_function(child)); - - retval += bus_print_child_footer(cbdev, child); - - return (retval); -} - -static void -cardbus_probe_nomatch(device_t cbdev, device_t child) -{ - struct cardbus_devinfo *dinfo; - pcicfgregs *cfg; - - dinfo = device_get_ivars(child); - cfg = &dinfo->cfg; - device_printf(cbdev, "<unknown card>"); - 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"); - - return; -} - -static int -cardbus_read_ivar(device_t cbdev, device_t child, int which, u_long *result) -{ - struct cardbus_devinfo *dinfo; - pcicfgregs *cfg; - - dinfo = device_get_ivars(child); - cfg = &dinfo->cfg; - - switch (which) { - case PCI_IVAR_SUBVENDOR: - *result = cfg->subvendor; - break; - case PCI_IVAR_SUBDEVICE: - *result = cfg->subdevice; - break; - case PCI_IVAR_VENDOR: - *result = cfg->vendor; - break; - case PCI_IVAR_DEVICE: - *result = cfg->device; - break; - case PCI_IVAR_DEVID: - *result = (cfg->device << 16) | cfg->vendor; - break; - case PCI_IVAR_CLASS: - *result = cfg->baseclass; - break; - case PCI_IVAR_SUBCLASS: - *result = cfg->subclass; - break; - case PCI_IVAR_PROGIF: - *result = cfg->progif; - break; - case PCI_IVAR_REVID: - *result = cfg->revid; - break; - case PCI_IVAR_INTPIN: - *result = cfg->intpin; - break; - case PCI_IVAR_IRQ: - *result = cfg->intline; - break; - case PCI_IVAR_BUS: - *result = cfg->bus; - break; - case PCI_IVAR_SLOT: - *result = cfg->slot; - break; - case PCI_IVAR_FUNCTION: - *result = cfg->func; - break; - default: - return ENOENT; - } - return 0; -} - -static int -cardbus_write_ivar(device_t cbdev, device_t child, int which, uintptr_t value) -{ - struct cardbus_devinfo *dinfo; - pcicfgregs *cfg; - - dinfo = device_get_ivars(child); - cfg = &dinfo->cfg; - - switch (which) { - case PCI_IVAR_SUBVENDOR: - case PCI_IVAR_SUBDEVICE: - case PCI_IVAR_VENDOR: - case PCI_IVAR_DEVICE: - case PCI_IVAR_DEVID: - case PCI_IVAR_CLASS: - case PCI_IVAR_SUBCLASS: - case PCI_IVAR_PROGIF: - case PCI_IVAR_REVID: - case PCI_IVAR_INTPIN: - case PCI_IVAR_IRQ: - case PCI_IVAR_BUS: - case PCI_IVAR_SLOT: - case PCI_IVAR_FUNCTION: - return EINVAL; /* disallow for now */ - default: - return ENOENT; - } - return 0; -} - -/************************************************************************/ -/* Compatibility with PCI bus (XXX: Do we need this?) */ -/************************************************************************/ - -/* - * PCI power manangement - */ -static int -cardbus_set_powerstate_method(device_t cbdev, device_t child, int state) -{ - struct cardbus_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - u_int16_t status; - int result; - - if (cfg->pp_cap != 0) { - status = PCI_READ_CONFIG(cbdev, child, cfg->pp_status, 2) - & ~PCIM_PSTAT_DMASK; - result = 0; - switch (state) { - case PCI_POWERSTATE_D0: - status |= PCIM_PSTAT_D0; - break; - case PCI_POWERSTATE_D1: - if (cfg->pp_cap & PCIM_PCAP_D1SUPP) { - status |= PCIM_PSTAT_D1; - } else { - result = EOPNOTSUPP; - } - break; - case PCI_POWERSTATE_D2: - if (cfg->pp_cap & PCIM_PCAP_D2SUPP) { - status |= PCIM_PSTAT_D2; - } else { - result = EOPNOTSUPP; - } - break; - case PCI_POWERSTATE_D3: - status |= PCIM_PSTAT_D3; - break; - default: - result = EINVAL; - } - if (result == 0) - PCI_WRITE_CONFIG(cbdev, child, cfg->pp_status, - status, 2); - } else { - result = ENXIO; - } - return (result); -} - -static int -cardbus_get_powerstate_method(device_t cbdev, device_t child) -{ - struct cardbus_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - u_int16_t status; - int result; - - if (cfg->pp_cap != 0) { - status = PCI_READ_CONFIG(cbdev, child, cfg->pp_status, 2); - switch (status & PCIM_PSTAT_DMASK) { - case PCIM_PSTAT_D0: - result = PCI_POWERSTATE_D0; - break; - case PCIM_PSTAT_D1: - result = PCI_POWERSTATE_D1; - break; - case PCIM_PSTAT_D2: - result = PCI_POWERSTATE_D2; - break; - case PCIM_PSTAT_D3: - result = PCI_POWERSTATE_D3; - break; - default: - result = PCI_POWERSTATE_UNKNOWN; - break; - } - } else { - /* No support, device is always at D0 */ - result = PCI_POWERSTATE_D0; - } - return (result); -} - -static u_int32_t -cardbus_read_config_method(device_t cbdev, device_t child, int reg, int width) -{ - struct cardbus_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - - return PCIB_READ_CONFIG(device_get_parent(cbdev), - cfg->bus, cfg->slot, cfg->func, reg, width); -} - -static void -cardbus_write_config_method(device_t cbdev, device_t child, int reg, - u_int32_t val, int width) -{ - struct cardbus_devinfo *dinfo = device_get_ivars(child); - pcicfgregs *cfg = &dinfo->cfg; - - PCIB_WRITE_CONFIG(device_get_parent(cbdev), - cfg->bus, cfg->slot, cfg->func, reg, val, width); -} - -static __inline void -cardbus_set_command_bit(device_t cbdev, device_t child, u_int16_t bit) -{ - u_int16_t command; - - command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2); - command |= bit; - PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2); -} - -static __inline void -cardbus_clear_command_bit(device_t cbdev, device_t child, u_int16_t bit) -{ - u_int16_t command; - - command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2); - command &= ~bit; - PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2); -} - -static void -cardbus_enable_busmaster_method(device_t cbdev, device_t child) -{ - cardbus_set_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); -} - -static void -cardbus_disable_busmaster_method(device_t cbdev, device_t child) -{ - cardbus_clear_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); -} - -static void -cardbus_enable_io_method(device_t cbdev, device_t child, int space) -{ - switch (space) { - case SYS_RES_IOPORT: - cardbus_set_command_bit(cbdev, child, PCIM_CMD_PORTEN); - break; - case SYS_RES_MEMORY: - cardbus_set_command_bit(cbdev, child, PCIM_CMD_MEMEN); - break; - } -} - -static void -cardbus_disable_io_method(device_t cbdev, device_t child, int space) -{ - switch (space) { - case SYS_RES_IOPORT: - cardbus_clear_command_bit(cbdev, child, PCIM_CMD_PORTEN); - break; - case SYS_RES_MEMORY: - cardbus_clear_command_bit(cbdev, child, PCIM_CMD_MEMEN); - break; } + resource_list_free(&dinfo->pci.resources); } static device_method_t cardbus_methods[] = { @@ -1215,21 +336,22 @@ static device_method_t cardbus_methods[] = { DEVMETHOD(device_resume, cardbus_resume), /* Bus interface */ - DEVMETHOD(bus_print_child, cardbus_print_child), - DEVMETHOD(bus_probe_nomatch, cardbus_probe_nomatch), - DEVMETHOD(bus_read_ivar, cardbus_read_ivar), - DEVMETHOD(bus_write_ivar, cardbus_write_ivar), + DEVMETHOD(bus_print_child, pci_print_child), + DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch), + DEVMETHOD(bus_read_ivar, pci_read_ivar), + DEVMETHOD(bus_write_ivar, pci_write_ivar), DEVMETHOD(bus_driver_added, cardbus_driver_added), - DEVMETHOD(bus_alloc_resource, cardbus_alloc_resource), - DEVMETHOD(bus_release_resource, cardbus_release_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + DEVMETHOD(bus_get_resource_list,pci_get_resource_list), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_delete_resource, pci_delete_resource), + DEVMETHOD(bus_alloc_resource, pci_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, cardbus_setup_intr), - DEVMETHOD(bus_teardown_intr, cardbus_teardown_intr), - - DEVMETHOD(bus_set_resource, cardbus_set_resource_method), - DEVMETHOD(bus_get_resource, cardbus_get_resource_method), - DEVMETHOD(bus_delete_resource, cardbus_delete_resource_method), /* Card Interface */ DEVMETHOD(card_attach_card, cardbus_attach_card), @@ -1238,14 +360,14 @@ static device_method_t cardbus_methods[] = { DEVMETHOD(card_cis_free, cardbus_cis_free), /* Cardbus/PCI interface */ - DEVMETHOD(pci_read_config, cardbus_read_config_method), - DEVMETHOD(pci_write_config, cardbus_write_config_method), - DEVMETHOD(pci_enable_busmaster, cardbus_enable_busmaster_method), - DEVMETHOD(pci_disable_busmaster, cardbus_disable_busmaster_method), - DEVMETHOD(pci_enable_io, cardbus_enable_io_method), - DEVMETHOD(pci_disable_io, cardbus_disable_io_method), - DEVMETHOD(pci_get_powerstate, cardbus_get_powerstate_method), - DEVMETHOD(pci_set_powerstate, cardbus_set_powerstate_method), + DEVMETHOD(pci_read_config, pci_read_config_method), + DEVMETHOD(pci_write_config, pci_write_config_method), + DEVMETHOD(pci_enable_busmaster, pci_enable_busmaster_method), + DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method), + DEVMETHOD(pci_enable_io, pci_enable_io_method), + DEVMETHOD(pci_disable_io, pci_disable_io_method), + DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), + DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), {0,0} }; diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c index f0b4274..e2bbe90 100644 --- a/sys/dev/cardbus/cardbus_cis.c +++ b/sys/dev/cardbus/cardbus_cis.c @@ -44,9 +44,9 @@ #include <machine/resource.h> #include <sys/rman.h> +#include <sys/pciio.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> -#include <sys/pciio.h> #include <dev/cardbus/cardbusreg.h> #include <dev/cardbus/cardbusvar.h> @@ -318,7 +318,7 @@ DECODE_PROTOTYPE(bar) :(dinfo->ibelow1mb&BARBIT(bar))?" (Below 1Mb)":"" )); - resource_list_add(&dinfo->resources, type, bar, 0UL, ~0UL, len); + resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len); } return 0; } @@ -614,15 +614,14 @@ cardbus_alloc_resources(device_t cbdev, device_t child) int rid, flags; count = 0; - SLIST_FOREACH(rle, &dinfo->resources, link) { + SLIST_FOREACH(rle, &dinfo->pci.resources, link) count++; - } if (count == 0) return 0; barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF, M_WAITOK); count = 0; - SLIST_FOREACH(rle, &dinfo->resources, link) { + SLIST_FOREACH(rle, &dinfo->pci.resources, link) { barlist[count] = rle; if (rle->type == SYS_RES_IOPORT) { io_size += rle->count; @@ -689,20 +688,22 @@ cardbus_alloc_resources(device_t cbdev, device_t child) DEVPRINTF((cbdev, "Cannot pre-allocate " "prefetchable memory, will try as " "non-prefetchable.\n")); - } else { - barlist[tmp]->start = - rman_get_start(barlist[tmp]->res); - barlist[tmp]->end = - rman_get_end(barlist[tmp]->res); - pci_write_config(child, - barlist[tmp]->rid, - barlist[tmp]->start, 4); - DEVPRINTF((cbdev, "Prefetchable memory " - "rid=%x at %lx-%lx\n", - barlist[tmp]->rid, - barlist[tmp]->start, - barlist[tmp]->end)); + continue; } + barlist[tmp]->start = + rman_get_start(barlist[tmp]->res); + barlist[tmp]->end = + rman_get_end(barlist[tmp]->res); + pci_write_config(child, + barlist[tmp]->rid, + barlist[tmp]->start, 4); + bus_release_resource(cbdev, SYS_RES_MEMORY, + barlist[tmp]->rid, barlist[tmp]->res); + DEVPRINTF((cbdev, "Prefetchable memory " + "rid=%x at %lx-%lx\n", + barlist[tmp]->rid, + barlist[tmp]->start, + barlist[tmp]->end)); } } } @@ -749,7 +750,7 @@ cardbus_alloc_resources(device_t cbdev, device_t child) if (barlist[tmp]->res == NULL) { DEVPRINTF((cbdev, "Cannot pre-allocate " "memory for cardbus device\n")); - return ENOMEM; + return (ENOMEM); } barlist[tmp]->start = rman_get_start(barlist[tmp]->res); @@ -757,6 +758,9 @@ cardbus_alloc_resources(device_t cbdev, device_t child) barlist[tmp]->res); pci_write_config(child, barlist[tmp]->rid, barlist[tmp]->start, 4); + bus_release_resource(cbdev, SYS_RES_MEMORY, + barlist[tmp]->rid, barlist[tmp]->res); + barlist[tmp]->res = NULL; DEVPRINTF((cbdev, "Non-prefetchable memory " "rid=%x at %lx-%lx (%lx)\n", barlist[tmp]->rid, barlist[tmp]->start, @@ -784,14 +788,15 @@ cardbus_alloc_resources(device_t cbdev, device_t child) * (XXX: Perhaps there might be a better way to do this?) */ rid = 0; - res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0, - (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags); + res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0, ~0UL, + io_size, flags); start = rman_get_start(res); end = rman_get_end(res); DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end)); /* * Now that we know the region is free, release it and hand it - * out piece by piece. + * out piece by piece. XXX Need to interlock with the RM + * so we don't race here. */ bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res); for (tmp = 0; tmp < count; tmp++) { @@ -811,26 +816,27 @@ cardbus_alloc_resources(device_t cbdev, device_t child) rman_get_start(barlist[tmp]->res); barlist[tmp]->end = rman_get_end(barlist[tmp]->res); - pci_write_config(child, barlist[tmp]->rid, - barlist[tmp]->start, 4); - DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n", - barlist[tmp]->rid, barlist[tmp]->start, - barlist[tmp]->end)); + pci_write_config(child, barlist[tmp]->rid, + barlist[tmp]->start, 4); + bus_release_resource(cbdev, SYS_RES_IOPORT, + barlist[tmp]->rid, barlist[tmp]->res); + barlist[tmp]->res = NULL; + DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n", + barlist[tmp]->rid, barlist[tmp]->start, + barlist[tmp]->end)); } } } /* Allocate IRQ */ - /* XXX: Search CIS for IRQ description */ rid = 0; res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1, RF_SHAREABLE); - resource_list_add(&dinfo->resources, SYS_RES_IRQ, rid, + resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid, rman_get_start(res), rman_get_end(res), 1); - rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid); - rle->res = res; - dinfo->cfg.intline = rman_get_start(res); + dinfo->pci.cfg.intline = rman_get_start(res); pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1); + bus_release_resource(cbdev, SYS_RES_IRQ, rid, res); return 0; } @@ -848,7 +854,7 @@ cardbus_add_map(device_t cbdev, device_t child, int reg) u_int32_t testval; int type; - SLIST_FOREACH(rle, &dinfo->resources, link) { + SLIST_FOREACH(rle, &dinfo->pci.resources, link) { if (rle->rid == reg) return; } @@ -872,7 +878,7 @@ cardbus_add_map(device_t cbdev, device_t child, int reg) size = CARDBUS_MAPREG_MEM_SIZE(testval); device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n", reg, size); - resource_list_add(&dinfo->resources, type, reg, 0UL, ~0UL, size); + resource_list_add(&dinfo->pci.resources, type, reg, 0UL, ~0UL, size); } static void @@ -888,12 +894,13 @@ cardbus_pickup_maps(device_t cbdev, device_t child) * the driver in its CIS. * XXX: should we do this or use quirks? */ - for (reg = 0; reg < dinfo->cfg.nummaps; reg++) { + for (reg = 0; reg < dinfo->pci.cfg.nummaps; reg++) { cardbus_add_map(cbdev, child, PCIR_MAPS + reg * 4); } for (q = &cardbus_quirks[0]; q->devid; q++) { - if (q->devid == ((dinfo->cfg.device << 16) | dinfo->cfg.vendor) + if (q->devid == ((dinfo->pci.cfg.device << 16) | + dinfo->pci.cfg.vendor) && q->type == CARDBUS_QUIRK_MAP_REG) { cardbus_add_map(cbdev, child, q->arg1); } diff --git a/sys/dev/cardbus/cardbusvar.h b/sys/dev/cardbus/cardbusvar.h index 814af16..1cfdde5 100644 --- a/sys/dev/cardbus/cardbusvar.h +++ b/sys/dev/cardbus/cardbusvar.h @@ -31,21 +31,10 @@ /* * Structure definitions for the Cardbus Bus driver */ - -struct cardbus_intrlist { - SLIST_ENTRY(cardbus_intrlist) link; - device_t dev; - struct resource *irq; - void *cookie; -}; - struct cardbus_devinfo { - struct resource_list resources; - pcicfgregs cfg; - struct pci_conf conf; - u_int8_t mprefetchable; /* bit mask of prefetchable BARs */ - u_int8_t mbelow1mb; /* bit mask of BARs which require below 1Mb */ - u_int8_t ibelow1mb; /* bit mask of BARs which require below 1Mb */ -#define BARBIT(RID) (1<<((RID)-CARDBUS_BASE0_REG)/4) - SLIST_HEAD(, cardbus_intrlist) intrlist; + struct pci_devinfo pci; + u_int8_t mprefetchable; /* bit mask of prefetchable BARs */ + u_int8_t mbelow1mb; /* bit mask of BARs which require below 1Mb */ + u_int8_t ibelow1mb; /* bit mask of BARs which require below 1Mb */ +#define BARBIT(RID) (1<<((RID)-CARDBUS_BASE0_REG)/4) }; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index a9f37ba5..7a758ae 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -53,8 +53,9 @@ #include <machine/resource.h> #include <sys/pciio.h> -#include <pci/pcireg.h> -#include <pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pci_private.h> #include "pcib_if.h" #include "pci_if.h" @@ -66,10 +67,8 @@ static int pci_maprange(unsigned mapreg); static void pci_fixancient(pcicfgregs *cfg); static void pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg); -static struct pci_devinfo *pci_read_device(device_t pcib, int b, int s, int f); static void pci_read_extcap(device_t pcib, pcicfgregs *cfg); -static void pci_print_verbose(struct pci_devinfo *dinfo); static int pci_porten(device_t pcib, int b, int s, int f); static int pci_memen(device_t pcib, int b, int s, int f); static int pci_add_map(device_t pcib, int b, int s, int f, int reg, @@ -78,36 +77,9 @@ static void pci_add_resources(device_t pcib, int b, int s, int f, device_t dev); static void pci_add_children(device_t dev, int busno); static int pci_probe(device_t dev); -static int pci_print_child(device_t dev, device_t child); -static void pci_probe_nomatch(device_t dev, device_t child); static int pci_describe_parse_line(char **ptr, int *vendor, int *device, char **desc); static char *pci_describe_device(device_t dev); -static int pci_read_ivar(device_t dev, device_t child, int which, - uintptr_t *result); -static int pci_write_ivar(device_t dev, device_t child, int which, - uintptr_t value); -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); -static void pci_delete_resource(device_t dev, device_t child, - int type, int rid); -static struct resource_list *pci_get_resource_list (device_t dev, device_t child); -static u_int32_t pci_read_config_method(device_t dev, device_t child, - int reg, int width); -static void pci_write_config_method(device_t dev, device_t child, - int reg, u_int32_t val, int width); -static void pci_enable_busmaster_method(device_t dev, - device_t child); -static void pci_disable_busmaster_method(device_t dev, - device_t child); -static void pci_enable_io_method(device_t dev, device_t child, - int space); -static void pci_disable_io_method(device_t dev, device_t child, - int space); -static int pci_set_powerstate_method(device_t dev, device_t child, - int state); -static int pci_get_powerstate_method(device_t dev, device_t child); static int pci_modevent(module_t mod, int what, void *arg); static device_method_t pci_methods[] = { @@ -337,7 +309,7 @@ pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg) /* read configuration header into pcicfgregs structure */ -static struct pci_devinfo * +struct pci_devinfo * pci_read_device(device_t pcib, int b, int s, int f) { #define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) @@ -460,18 +432,15 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg) #undef REG } -#if 0 /* free pcicfgregs structure and all depending data structures */ -static int +int pci_freecfg(struct pci_devinfo *dinfo) { struct devlist *devlist_head; devlist_head = &pci_devq; - if (dinfo->cfg.map != NULL) - free(dinfo->cfg.map, M_DEVBUF); /* XXX this hasn't been tested */ STAILQ_REMOVE(devlist_head, dinfo, pci_devinfo, pci_links); free(dinfo, M_DEVBUF); @@ -483,12 +452,11 @@ pci_freecfg(struct pci_devinfo *dinfo) pci_numdevs--; return (0); } -#endif /* * PCI power manangement */ -static int +int pci_set_powerstate_method(device_t dev, device_t child, int state) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -531,7 +499,7 @@ pci_set_powerstate_method(device_t dev, device_t child, int state) return(result); } -static int +int pci_get_powerstate_method(device_t dev, device_t child) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -589,19 +557,19 @@ pci_clear_command_bit(device_t dev, device_t child, u_int16_t bit) PCI_WRITE_CONFIG(dev, child, PCIR_COMMAND, command, 2); } -static void +void pci_enable_busmaster_method(device_t dev, device_t child) { pci_set_command_bit(dev, child, PCIM_CMD_BUSMASTEREN); } -static void +void pci_disable_busmaster_method(device_t dev, device_t child) { pci_clear_command_bit(dev, child, PCIM_CMD_BUSMASTEREN); } -static void +void pci_enable_io_method(device_t dev, device_t child, int space) { switch(space) { @@ -614,7 +582,7 @@ pci_enable_io_method(device_t dev, device_t child, int space) } } -static void +void pci_disable_io_method(device_t dev, device_t child, int space) { switch(space) { @@ -632,7 +600,7 @@ pci_disable_io_method(device_t dev, device_t child, int space) * pci-pci-bridge. Both kinds are represented by instances of pcib. */ -static void +void pci_print_verbose(struct pci_devinfo *dinfo) { if (bootverbose) { @@ -865,7 +833,7 @@ pci_probe(device_t dev) return 0; } -static int +int pci_print_child(device_t dev, device_t child) { struct pci_devinfo *dinfo; @@ -956,7 +924,7 @@ static struct {0, 0, NULL} }; -static void +void pci_probe_nomatch(device_t dev, device_t child) { int i; @@ -1118,7 +1086,7 @@ pci_describe_device(device_t dev) return(desc); } -static int +int pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct pci_devinfo *dinfo; @@ -1176,7 +1144,7 @@ pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) return 0; } -static int +int pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) { struct pci_devinfo *dinfo; @@ -1208,7 +1176,7 @@ pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) return 0; } -static struct resource * +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) { @@ -1241,13 +1209,40 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, start, end, count, flags); } -static void +void pci_delete_resource(device_t dev, device_t child, int type, int rid) { - printf("pci_delete_resource: PCI resources can not be deleted\n"); + struct pci_devinfo *dinfo; + struct resource_list *rl; + struct resource_list_entry *rle; + + if (device_get_parent(child) != dev) + return; + + dinfo = device_get_ivars(child); + rl = &dinfo->resources; + rle = resource_list_find(rl, type, rid); + if (rle) { + if (rle->res) { + if (rle->res->r_dev != dev || + rman_get_flags(rle->res) & RF_ACTIVE) { + device_printf(dev, "delete_resource: " + "Resource still owned by child, oops. " + "(type=%d, rid=%d, addr=%lx)\n", + rle->type, rle->rid, + rman_get_start(rle->res)); + return; + } + bus_release_resource(dev, type, rid, rle->res); + } + resource_list_delete(rl, type, rid); + } + /* I don't understand the next line */ + pci_write_config(child, rid, 0, 4); + BUS_DELETE_RESOURCE(device_get_parent(dev), child, type, rid); } -static struct resource_list * +struct resource_list * pci_get_resource_list (device_t dev, device_t child) { struct pci_devinfo * dinfo = device_get_ivars(child); @@ -1259,7 +1254,7 @@ pci_get_resource_list (device_t dev, device_t child) return (rl); } -static u_int32_t +u_int32_t pci_read_config_method(device_t dev, device_t child, int reg, int width) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -1270,7 +1265,7 @@ pci_read_config_method(device_t dev, device_t child, int reg, int width) reg, width); } -static void +void pci_write_config_method(device_t dev, device_t child, int reg, u_int32_t val, int width) { diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h new file mode 100644 index 0000000..9c6e6f5 --- /dev/null +++ b/sys/dev/pci/pci_private.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997, Stefan Esser <se@freebsd.org> + * 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 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 _PCI_PRIVATE_H_ +#define _PCI_PRIVATE_H_ + +/* + * Export definitions of the pci bus so that we can more easily share + * it with "subclass" busses. A more generic subclassing mechanism would + * be nice, but is not present in the tree at this time. + */ +int pci_print_child(device_t dev, device_t child); +void pci_probe_nomatch(device_t dev, device_t child); +int pci_read_ivar(device_t dev, device_t child, int which, + uintptr_t *result); +int pci_write_ivar(device_t dev, device_t child, int which, + uintptr_t value); +int pci_set_powerstate_method(device_t dev, device_t child, + int state); +int pci_get_powerstate_method(device_t dev, device_t child); +u_int32_t pci_read_config_method(device_t dev, device_t child, + int reg, int width); +void pci_write_config_method(device_t dev, device_t child, + int reg, u_int32_t val, int width); +void pci_enable_busmaster_method(device_t dev, device_t child); +void pci_disable_busmaster_method(device_t dev, device_t child); +void pci_enable_io_method(device_t dev, device_t child, int space); +void pci_disable_io_method(device_t dev, device_t child, int space); +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); +void pci_delete_resource(device_t dev, device_t child, + int type, int rid); +struct resource_list *pci_get_resource_list (device_t dev, device_t child); +struct pci_devinfo *pci_read_device(device_t pcib, int b, int s, int f); +void pci_print_verbose(struct pci_devinfo *dinfo); +int pci_freecfg(struct pci_devinfo *dinfo); + +#endif /* _PCI_PRIVATE_H_ */ |