Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/isa_pci.c
| Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
| #include <machine/resource.h> | #include <machine/resource.h> | ||||
| static int isab_pci_probe(device_t dev); | static int isab_pci_probe(device_t dev); | ||||
| static int isab_pci_attach(device_t dev); | static int isab_pci_attach(device_t dev); | ||||
| static struct resource * isab_pci_alloc_resource(device_t dev, | static struct resource * isab_pci_alloc_resource(device_t dev, | ||||
| device_t child, int type, int *rid, rman_res_t start, rman_res_t end, | device_t child, int type, int *rid, rman_res_t start, rman_res_t end, | ||||
| rman_res_t count, u_int flags); | rman_res_t count, u_int flags); | ||||
| static int isab_pci_release_resource(device_t dev, device_t child, | static int isab_pci_release_resource(device_t dev, device_t child, | ||||
| int type, int rid, struct resource *r); | struct resource *r); | ||||
| static device_method_t isab_methods[] = { | static device_method_t isab_methods[] = { | ||||
| /* Device interface */ | /* Device interface */ | ||||
| DEVMETHOD(device_probe, isab_pci_probe), | DEVMETHOD(device_probe, isab_pci_probe), | ||||
| DEVMETHOD(device_attach, isab_pci_attach), | DEVMETHOD(device_attach, isab_pci_attach), | ||||
| DEVMETHOD(device_detach, bus_generic_detach), | DEVMETHOD(device_detach, bus_generic_detach), | ||||
| DEVMETHOD(device_shutdown, bus_generic_shutdown), | DEVMETHOD(device_shutdown, bus_generic_shutdown), | ||||
| DEVMETHOD(device_suspend, bus_generic_suspend), | DEVMETHOD(device_suspend, bus_generic_suspend), | ||||
| ▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | case SYS_RES_IOPORT: | ||||
| return (sc->isab_pci_res[bar].ip_res); | return (sc->isab_pci_res[bar].ip_res); | ||||
| } | } | ||||
| return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, | return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, | ||||
| start, end, count, flags)); | start, end, count, flags)); | ||||
| } | } | ||||
| static int | static int | ||||
| isab_pci_release_resource(device_t dev, device_t child, int type, int rid, | isab_pci_release_resource(device_t dev, device_t child, struct resource *r) | ||||
| struct resource *r) | |||||
| { | { | ||||
| struct isab_pci_softc *sc; | struct isab_pci_softc *sc; | ||||
| int bar, error; | int bar, error; | ||||
| if (device_get_parent(child) != dev) | if (device_get_parent(child) != dev) | ||||
| return bus_generic_release_resource(dev, child, type, rid, r); | return bus_generic_release_resource(dev, child, r); | ||||
| switch (type) { | switch (rman_get_type(r)) { | ||||
| case SYS_RES_MEMORY: | case SYS_RES_MEMORY: | ||||
| case SYS_RES_IOPORT: | case SYS_RES_IOPORT: | ||||
| /* | /* | ||||
| * For BARs, we release the resource from the PCI bus | * For BARs, we release the resource from the PCI bus | ||||
| * when the last child reference goes away. | * when the last child reference goes away. | ||||
| */ | */ | ||||
| bar = PCI_RID2BAR(rid); | bar = PCI_RID2BAR(rman_get_rid(r)); | ||||
| if (bar < 0 || bar > PCIR_MAX_BAR_0) | if (bar < 0 || bar > PCIR_MAX_BAR_0) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
| if (sc->isab_pci_res[bar].ip_res == NULL) | if (sc->isab_pci_res[bar].ip_res == NULL) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| KASSERT(sc->isab_pci_res[bar].ip_res == r, | KASSERT(sc->isab_pci_res[bar].ip_res == r, | ||||
| ("isa_pci resource mismatch")); | ("isa_pci resource mismatch")); | ||||
| if (sc->isab_pci_res[bar].ip_refs > 1) { | if (sc->isab_pci_res[bar].ip_refs > 1) { | ||||
| sc->isab_pci_res[bar].ip_refs--; | sc->isab_pci_res[bar].ip_refs--; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| KASSERT(sc->isab_pci_res[bar].ip_refs > 0, | KASSERT(sc->isab_pci_res[bar].ip_refs > 0, | ||||
| ("isa_pci resource reference count underflow")); | ("isa_pci resource reference count underflow")); | ||||
| error = bus_release_resource(dev, type, rid, r); | error = bus_release_resource(dev, r); | ||||
| if (error == 0) { | if (error == 0) { | ||||
| sc->isab_pci_res[bar].ip_res = NULL; | sc->isab_pci_res[bar].ip_res = NULL; | ||||
| sc->isab_pci_res[bar].ip_refs = 0; | sc->isab_pci_res[bar].ip_refs = 0; | ||||
| } | } | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, | return (bus_generic_release_resource(dev, child, r)); | ||||
| rid, r)); | |||||
| } | } | ||||