diff options
-rw-r--r-- | sys/dev/cardbus/cardbus.c | 330 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_cis.c | 129 |
2 files changed, 49 insertions, 410 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index eddfe61..1559712 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -71,40 +71,18 @@ SYSCTL_INT(_hw_cardbus, OID_AUTO, cis_debug, CTLFLAG_RW, #define DEVPRINTF(x) if (cardbus_debug) device_printf x -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_attach(device_t cbdev); static int cardbus_attach_card(device_t cbdev); -static void cardbus_delete_resource(device_t cbdev, device_t child, - int type, int rid); -static void cardbus_delete_resource_method(device_t cbdev, device_t child, - int type, int rid); static int cardbus_detach(device_t cbdev); static int cardbus_detach_card(device_t cbdev); static void cardbus_device_setup_regs(device_t brdev, int b, int s, int f, pcicfgregs *cfg); static void cardbus_driver_added(device_t cbdev, driver_t *driver); -static int cardbus_get_resource(device_t cbdev, device_t child, int type, - int rid, u_long *startp, u_long *countp); -static int cardbus_get_resource_method(device_t cbdev, device_t child, - int type, int rid, u_long *startp, u_long *countp); static int cardbus_probe(device_t cbdev); static int cardbus_read_ivar(device_t cbdev, device_t child, int which, uintptr_t *result); static void cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo); -static int cardbus_release_resource(device_t cbdev, device_t child, - int type, int rid, struct resource *r); -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_set_resource_method(device_t cbdev, device_t child, - int type, int rid, u_long start, u_long count); -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_write_ivar(device_t cbdev, device_t child, int which, uintptr_t value); @@ -300,143 +278,6 @@ cardbus_driver_added(device_t cbdev, driver_t *driver) free(devlist, M_TEMP); } -/************************************************************************/ -/* 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->pci.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 (rman_get_device(rle->res) == 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->pci.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->pci.resources; - rle = resource_list_find(rl, type, rid); - if (rle) { - if (rle->res) { - if (rman_get_device(rle->res) != 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) { @@ -464,155 +305,6 @@ cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) resource_list_free(&dinfo->pci.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->pci.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 (rman_get_device(rle->res) != 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; - } - /* Allocate the resource to the child */ - return resource_list_alloc(&dinfo->pci.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->pci.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; - 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); - - return 0; -} - -static int -cardbus_teardown_intr(device_t cbdev, device_t child, struct resource *irq, - void *cookie) -{ - int ret; - 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); - - return (0); -} - - /************************************************************************/ /* Other Bus Methods */ /************************************************************************/ @@ -665,16 +357,18 @@ static device_method_t cardbus_methods[] = { DEVMETHOD(bus_read_ivar, cardbus_read_ivar), DEVMETHOD(bus_write_ivar, cardbus_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_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), + 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, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method), DEVMETHOD(bus_child_location_str, pci_child_location_str_method), @@ -707,7 +401,3 @@ static devclass_t cardbus_devclass; DRIVER_MODULE(cardbus, cbb, cardbus_driver, cardbus_devclass, 0, 0); MODULE_VERSION(cardbus, 1); -MODULE_DEPEND(cardbus, exca, 1, 1, 1); -/* -MODULE_DEPEND(cardbus, pccbb, 1, 1, 1); -*/ diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c index 2b8e2b2..250ac65 100644 --- a/sys/dev/cardbus/cardbus_cis.c +++ b/sys/dev/cardbus/cardbus_cis.c @@ -456,7 +456,6 @@ decode_tuple_bar(device_t cbdev, device_t child, int id, * device drivers will know which type of BARs can be used. */ pci_enable_io(child, type); - return (0); } @@ -770,6 +769,14 @@ cardbus_parse_cis(device_t cbdev, device_t child, return (0); } +static void +cardbus_do_res(struct resource_list_entry *rle, device_t child, uint32_t start) +{ + rle->start = start; + rle->end = start + rle->count - 1; + pci_write_config(child, rle->rid, rle->start, 4); +} + static int barsort(const void *a, const void *b) { @@ -821,10 +828,11 @@ cardbus_alloc_resources(device_t cbdev, device_t child) /* Allocate prefetchable memory */ flags = 0; for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_MEMORY && - dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) { - flags = rman_make_alignment_flags(barlist[tmp]->count); + rle = barlist[tmp]; + if (rle->res == NULL && + rle->type == SYS_RES_MEMORY && + dinfo->mprefetchable & BARBIT(rle->rid)) { + flags = rman_make_alignment_flags(rle->count); break; } } @@ -850,36 +858,11 @@ cardbus_alloc_resources(device_t cbdev, device_t child) */ bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_MEMORY && - dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) { - barlist[tmp]->res = bus_alloc_resource(cbdev, - barlist[tmp]->type, - &barlist[tmp]->rid, start, end, - barlist[tmp]->count, - rman_make_alignment_flags( - barlist[tmp]->count)); - if (barlist[tmp]->res == NULL) { - mem_nsize += barlist[tmp]->count; - dinfo->mprefetchable &= - ~BARBIT(barlist[tmp]->rid); - 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)); - } + rle = barlist[tmp]; + if (rle->type == SYS_RES_MEMORY && + dinfo->mprefetchable & BARBIT(rle->rid)) { + cardbus_do_res(rle, child, start); + start += rle->count; } } } @@ -887,9 +870,10 @@ cardbus_alloc_resources(device_t cbdev, device_t child) /* Allocate non-prefetchable memory */ flags = 0; for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_MEMORY) { - flags = rman_make_alignment_flags(barlist[tmp]->count); + rle = barlist[tmp]; + if (rle->type == SYS_RES_MEMORY && + (dinfo->mprefetchable & BARBIT(rle->rid)) == 0) { + flags = rman_make_alignment_flags(rle->count); break; } } @@ -916,29 +900,11 @@ cardbus_alloc_resources(device_t cbdev, device_t child) */ bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_MEMORY) { - barlist[tmp]->res = bus_alloc_resource(cbdev, - barlist[tmp]->type, &barlist[tmp]->rid, - start, end, barlist[tmp]->count, - rman_make_alignment_flags( - barlist[tmp]->count)); - if (barlist[tmp]->res == NULL) { - DEVPRINTF((cbdev, "Cannot pre-allocate " - "memory for cardbus device\n")); - free(barlist, M_DEVBUF); - return (ENOMEM); - } - 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, "Non-prefetchable memory " - "rid=%x at %lx-%lx (%lx)\n", - barlist[tmp]->rid, barlist[tmp]->start, - barlist[tmp]->end, barlist[tmp]->count)); + rle = barlist[tmp]; + if (rle->type == SYS_RES_MEMORY && + (dinfo->mprefetchable & BARBIT(rle->rid)) == 0) { + cardbus_do_res(rle, child, start); + start += rle->count; } } } @@ -946,9 +912,9 @@ cardbus_alloc_resources(device_t cbdev, device_t child) /* Allocate IO ports */ flags = 0; for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_IOPORT) { - flags = rman_make_alignment_flags(barlist[tmp]->count); + rle = barlist[tmp]; + if (rle->type == SYS_RES_IOPORT) { + flags = rman_make_alignment_flags(rle->count); break; } } @@ -973,28 +939,10 @@ cardbus_alloc_resources(device_t cbdev, device_t child) */ bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res); for (tmp = 0; tmp < count; tmp++) { - if (barlist[tmp]->res == NULL && - barlist[tmp]->type == SYS_RES_IOPORT) { - barlist[tmp]->res = bus_alloc_resource(cbdev, - barlist[tmp]->type, &barlist[tmp]->rid, - start, end, barlist[tmp]->count, - rman_make_alignment_flags( - barlist[tmp]->count)); - if (barlist[tmp]->res == NULL) { - DEVPRINTF((cbdev, "Cannot pre-allocate " - "IO port for cardbus device\n")); - free(barlist, M_DEVBUF); - return (ENOMEM); - } - 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, "IO port rid=%x at %lx-%lx\n", - barlist[tmp]->rid, barlist[tmp]->start, - barlist[tmp]->end)); + rle = barlist[tmp]; + if (rle->type == SYS_RES_IOPORT) { + cardbus_do_res(rle, child, start); + start += rle->count; } } } @@ -1003,10 +951,11 @@ cardbus_alloc_resources(device_t cbdev, device_t child) rid = 0; res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1, RF_SHAREABLE); - resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid, - rman_get_start(res), rman_get_end(res), 1); - rle = resource_list_find(&dinfo->pci.resources, SYS_RES_IRQ, rid); - rle->res = res; + start = rman_get_start(res); + end = rman_get_end(res); + bus_release_resource(cbdev, SYS_RES_IRQ, rid, res); + resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid, start, end, + 1); dinfo->pci.cfg.intline = rman_get_start(res); pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1); |