19c564b6cSJohn Hay /* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 29c564b6cSJohn Hay 39c564b6cSJohn Hay /*- 49c564b6cSJohn Hay * Copyright (c) 2002 JF Hay. All rights reserved. 59c564b6cSJohn Hay * Copyright (c) 2000 M. Warner Losh. All rights reserved. 69c564b6cSJohn Hay * 79c564b6cSJohn Hay * Redistribution and use in source and binary forms, with or without 89c564b6cSJohn Hay * modification, are permitted provided that the following conditions 99c564b6cSJohn Hay * are met: 109c564b6cSJohn Hay * 1. Redistributions of source code must retain the above copyright 119c564b6cSJohn Hay * notice unmodified, this list of conditions, and the following 129c564b6cSJohn Hay * disclaimer. 139c564b6cSJohn Hay * 2. Redistributions in binary form must reproduce the above copyright 149c564b6cSJohn Hay * notice, this list of conditions and the following disclaimer in the 159c564b6cSJohn Hay * documentation and/or other materials provided with the distribution. 169c564b6cSJohn Hay * 179c564b6cSJohn Hay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 189c564b6cSJohn Hay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 199c564b6cSJohn Hay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 209c564b6cSJohn Hay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 219c564b6cSJohn Hay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 229c564b6cSJohn Hay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239c564b6cSJohn Hay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249c564b6cSJohn Hay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259c564b6cSJohn Hay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 269c564b6cSJohn Hay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279c564b6cSJohn Hay */ 289c564b6cSJohn Hay 299c564b6cSJohn Hay /* 309c564b6cSJohn Hay * Copyright (c) 1996, 1998, 1999 319c564b6cSJohn Hay * Christopher G. Demetriou. All rights reserved. 329c564b6cSJohn Hay * 339c564b6cSJohn Hay * Redistribution and use in source and binary forms, with or without 349c564b6cSJohn Hay * modification, are permitted provided that the following conditions 359c564b6cSJohn Hay * are met: 369c564b6cSJohn Hay * 1. Redistributions of source code must retain the above copyright 379c564b6cSJohn Hay * notice, this list of conditions and the following disclaimer. 389c564b6cSJohn Hay * 2. Redistributions in binary form must reproduce the above copyright 399c564b6cSJohn Hay * notice, this list of conditions and the following disclaimer in the 409c564b6cSJohn Hay * documentation and/or other materials provided with the distribution. 419c564b6cSJohn Hay * 3. All advertising materials mentioning features or use of this software 429c564b6cSJohn Hay * must display the following acknowledgement: 439c564b6cSJohn Hay * This product includes software developed by Christopher G. Demetriou 449c564b6cSJohn Hay * for the NetBSD Project. 459c564b6cSJohn Hay * 4. The name of the author may not be used to endorse or promote products 469c564b6cSJohn Hay * derived from this software without specific prior written permission 479c564b6cSJohn Hay * 489c564b6cSJohn Hay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 499c564b6cSJohn Hay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 509c564b6cSJohn Hay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 519c564b6cSJohn Hay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 529c564b6cSJohn Hay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 539c564b6cSJohn Hay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 549c564b6cSJohn Hay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 559c564b6cSJohn Hay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 569c564b6cSJohn Hay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 579c564b6cSJohn Hay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 589c564b6cSJohn Hay */ 599c564b6cSJohn Hay 609c564b6cSJohn Hay #include <sys/cdefs.h> 619c564b6cSJohn Hay __FBSDID("$FreeBSD$"); 629c564b6cSJohn Hay 639c564b6cSJohn Hay /* 649c564b6cSJohn Hay * PCI "universal" communication card device driver, glues com, lpt, 659c564b6cSJohn Hay * and similar ports to PCI via bridge chip often much larger than 669c564b6cSJohn Hay * the devices being glued. 679c564b6cSJohn Hay * 689c564b6cSJohn Hay * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 699c564b6cSJohn Hay * sys/dev/pci/pciide.c, revision 1.6). 709c564b6cSJohn Hay * 719c564b6cSJohn Hay * These devices could be (and some times are) described as 729c564b6cSJohn Hay * communications/{serial,parallel}, etc. devices with known 739c564b6cSJohn Hay * programming interfaces, but those programming interfaces (in 749c564b6cSJohn Hay * particular the BAR assignments for devices, etc.) in fact are not 759c564b6cSJohn Hay * particularly well defined. 769c564b6cSJohn Hay * 779c564b6cSJohn Hay * After I/we have seen more of these devices, it may be possible 789c564b6cSJohn Hay * to generalize some of these bits. In particular, devices which 799c564b6cSJohn Hay * describe themselves as communications/serial/16[45]50, and 809c564b6cSJohn Hay * communications/parallel/??? might be attached via direct 819c564b6cSJohn Hay * 'com' and 'lpt' attachments to pci. 829c564b6cSJohn Hay */ 839c564b6cSJohn Hay 849c564b6cSJohn Hay #include <sys/param.h> 859c564b6cSJohn Hay #include <sys/systm.h> 869c564b6cSJohn Hay #include <sys/kernel.h> 879c564b6cSJohn Hay #include <sys/bus.h> 889c564b6cSJohn Hay #include <sys/conf.h> 899c564b6cSJohn Hay #include <sys/malloc.h> 909c564b6cSJohn Hay 919c564b6cSJohn Hay #include <machine/bus.h> 929c564b6cSJohn Hay #include <machine/resource.h> 939c564b6cSJohn Hay #include <sys/rman.h> 949c564b6cSJohn Hay 959c564b6cSJohn Hay #include <dev/pci/pcireg.h> 969c564b6cSJohn Hay #include <dev/pci/pcivar.h> 9732f606d1SPoul-Henning Kamp 9832f606d1SPoul-Henning Kamp #define PUC_ENTRAILS 1 999c564b6cSJohn Hay #include <dev/puc/pucvar.h> 1009c564b6cSJohn Hay 1019c564b6cSJohn Hay #include <opt_puc.h> 1029c564b6cSJohn Hay 1039c564b6cSJohn Hay 1049c564b6cSJohn Hay struct puc_device { 1059c564b6cSJohn Hay struct resource_list resources; 1069c564b6cSJohn Hay u_int serialfreq; 1079c564b6cSJohn Hay }; 1089c564b6cSJohn Hay 1099c564b6cSJohn Hay static void puc_intr(void *arg); 1109c564b6cSJohn Hay 1119c564b6cSJohn Hay static int puc_find_free_unit(char *); 1129c564b6cSJohn Hay #ifdef PUC_DEBUG 1139c564b6cSJohn Hay static void puc_print_resource_list(struct resource_list *); 1149c564b6cSJohn Hay #endif 1159c564b6cSJohn Hay 1161e89655aSPoul-Henning Kamp static int 1171e89655aSPoul-Henning Kamp puc_port_bar_index(struct puc_softc *sc, int bar) 1181e89655aSPoul-Henning Kamp { 1191e89655aSPoul-Henning Kamp int i; 1201e89655aSPoul-Henning Kamp 1211e89655aSPoul-Henning Kamp for (i = 0; i < PUC_MAX_BAR; i += 1) { 1221e89655aSPoul-Henning Kamp if (!sc->sc_bar_mappings[i].used) 1231e89655aSPoul-Henning Kamp break; 1241e89655aSPoul-Henning Kamp if (sc->sc_bar_mappings[i].bar == bar) 1251e89655aSPoul-Henning Kamp return (i); 1261e89655aSPoul-Henning Kamp } 1271e89655aSPoul-Henning Kamp sc->sc_bar_mappings[i].bar = bar; 1281e89655aSPoul-Henning Kamp sc->sc_bar_mappings[i].used = 1; 1291e89655aSPoul-Henning Kamp return (i); 1301e89655aSPoul-Henning Kamp } 1311e89655aSPoul-Henning Kamp 13232f606d1SPoul-Henning Kamp int 13332f606d1SPoul-Henning Kamp puc_attach(device_t dev, const struct puc_device_description *desc) 1349c564b6cSJohn Hay { 1359c564b6cSJohn Hay char *typestr; 1369c564b6cSJohn Hay int bidx, childunit, i, irq_setup, rid; 1379c564b6cSJohn Hay struct puc_softc *sc; 1389c564b6cSJohn Hay struct puc_device *pdev; 1399c564b6cSJohn Hay struct resource *res; 1409c564b6cSJohn Hay struct resource_list_entry *rle; 1419c564b6cSJohn Hay 1429c564b6cSJohn Hay sc = (struct puc_softc *)device_get_softc(dev); 1439c564b6cSJohn Hay bzero(sc, sizeof(*sc)); 14432f606d1SPoul-Henning Kamp sc->sc_desc = desc; 1459c564b6cSJohn Hay if (sc->sc_desc == NULL) 1469c564b6cSJohn Hay return (ENXIO); 1479c564b6cSJohn Hay 1489c564b6cSJohn Hay #ifdef PUC_DEBUG 1499c564b6cSJohn Hay bootverbose = 1; 1509c564b6cSJohn Hay 1519c564b6cSJohn Hay printf("puc: name: %s\n", sc->sc_desc->name); 1529c564b6cSJohn Hay #endif 1539c564b6cSJohn Hay rid = 0; 1549c564b6cSJohn Hay res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 1559c564b6cSJohn Hay RF_ACTIVE | RF_SHAREABLE); 1569c564b6cSJohn Hay if (!res) 1579c564b6cSJohn Hay return (ENXIO); 1589c564b6cSJohn Hay 1599c564b6cSJohn Hay sc->irqres = res; 1609c564b6cSJohn Hay sc->irqrid = rid; 1619c564b6cSJohn Hay #ifdef PUC_FASTINTR 1629c564b6cSJohn Hay irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 1639c564b6cSJohn Hay INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 1649c564b6cSJohn Hay #else 1659c564b6cSJohn Hay irq_setup = ENXIO; 1669c564b6cSJohn Hay #endif 1679c564b6cSJohn Hay if (irq_setup != 0) 1689c564b6cSJohn Hay irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 1699c564b6cSJohn Hay INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 1709c564b6cSJohn Hay if (irq_setup != 0) 1719c564b6cSJohn Hay return (ENXIO); 1729c564b6cSJohn Hay 1739c564b6cSJohn Hay rid = 0; 1749c564b6cSJohn Hay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 1751e89655aSPoul-Henning Kamp if (i > 0 && rid == sc->sc_desc->ports[i].bar) 1769c564b6cSJohn Hay sc->barmuxed = 1; 1779c564b6cSJohn Hay rid = sc->sc_desc->ports[i].bar; 1781e89655aSPoul-Henning Kamp bidx = puc_port_bar_index(sc, rid); 1799c564b6cSJohn Hay 1809c564b6cSJohn Hay if (sc->sc_bar_mappings[bidx].res != NULL) 1819c564b6cSJohn Hay continue; 1829c564b6cSJohn Hay res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1839c564b6cSJohn Hay 0ul, ~0ul, 1, RF_ACTIVE); 1849c564b6cSJohn Hay if (res == NULL) { 1859c564b6cSJohn Hay printf("could not get resource\n"); 1869c564b6cSJohn Hay continue; 1879c564b6cSJohn Hay } 1889c564b6cSJohn Hay sc->sc_bar_mappings[bidx].res = res; 1899c564b6cSJohn Hay #ifdef PUC_DEBUG 1901e89655aSPoul-Henning Kamp printf("port rid %d bst %x, start %x, end %x\n", rid, 1919c564b6cSJohn Hay (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 1929c564b6cSJohn Hay (u_int)rman_get_end(res)); 1939c564b6cSJohn Hay #endif 1949c564b6cSJohn Hay } 1959c564b6cSJohn Hay 1961e89655aSPoul-Henning Kamp if (desc->init != NULL) { 1971e89655aSPoul-Henning Kamp i = desc->init(sc); 1981e89655aSPoul-Henning Kamp if (i != 0) 1991e89655aSPoul-Henning Kamp return (i); 2001e89655aSPoul-Henning Kamp } 2019c564b6cSJohn Hay 2029c564b6cSJohn Hay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 2039c564b6cSJohn Hay rid = sc->sc_desc->ports[i].bar; 2041e89655aSPoul-Henning Kamp bidx = puc_port_bar_index(sc, rid); 2059c564b6cSJohn Hay if (sc->sc_bar_mappings[bidx].res == NULL) 2069c564b6cSJohn Hay continue; 2079c564b6cSJohn Hay 2089c564b6cSJohn Hay switch (sc->sc_desc->ports[i].type) { 2099c564b6cSJohn Hay case PUC_PORT_TYPE_COM: 2109c564b6cSJohn Hay typestr = "sio"; 2119c564b6cSJohn Hay break; 2129c564b6cSJohn Hay default: 2139c564b6cSJohn Hay continue; 2149c564b6cSJohn Hay } 2159c564b6cSJohn Hay pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 2169c564b6cSJohn Hay M_NOWAIT | M_ZERO); 2179c564b6cSJohn Hay if (!pdev) 2189c564b6cSJohn Hay continue; 2199c564b6cSJohn Hay resource_list_init(&pdev->resources); 2209c564b6cSJohn Hay 2219c564b6cSJohn Hay /* First fake up an IRQ resource. */ 2229c564b6cSJohn Hay resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 2239c564b6cSJohn Hay rman_get_start(sc->irqres), rman_get_end(sc->irqres), 2249c564b6cSJohn Hay rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 2259c564b6cSJohn Hay rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 2269c564b6cSJohn Hay rle->res = sc->irqres; 2279c564b6cSJohn Hay 2289c564b6cSJohn Hay /* Now fake an IOPORT resource */ 2299c564b6cSJohn Hay res = sc->sc_bar_mappings[bidx].res; 2309c564b6cSJohn Hay resource_list_add(&pdev->resources, SYS_RES_IOPORT, 0, 2319c564b6cSJohn Hay rman_get_start(res) + sc->sc_desc->ports[i].offset, 2321e89655aSPoul-Henning Kamp rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1, 2339c564b6cSJohn Hay 8); 2349c564b6cSJohn Hay rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 0); 2359c564b6cSJohn Hay 2369c564b6cSJohn Hay if (sc->barmuxed == 0) { 2379c564b6cSJohn Hay rle->res = sc->sc_bar_mappings[bidx].res; 2389c564b6cSJohn Hay } else { 2399c564b6cSJohn Hay rle->res = malloc(sizeof(struct resource), M_DEVBUF, 2409c564b6cSJohn Hay M_WAITOK | M_ZERO); 2415aa967d9SYoshihiro Takahashi if (rle->res == NULL) { 2425aa967d9SYoshihiro Takahashi free(pdev, M_DEVBUF); 2439c564b6cSJohn Hay return (ENOMEM); 2445aa967d9SYoshihiro Takahashi } 2459c564b6cSJohn Hay 2469c564b6cSJohn Hay rle->res->r_start = rman_get_start(res) + 2479c564b6cSJohn Hay sc->sc_desc->ports[i].offset; 2489c564b6cSJohn Hay rle->res->r_end = rle->res->r_start + 8 - 1; 2499c564b6cSJohn Hay rle->res->r_bustag = rman_get_bustag(res); 2509c564b6cSJohn Hay bus_space_subregion(rle->res->r_bustag, 2519c564b6cSJohn Hay rman_get_bushandle(res), 2529c564b6cSJohn Hay sc->sc_desc->ports[i].offset, 8, 2539c564b6cSJohn Hay &rle->res->r_bushandle); 2549c564b6cSJohn Hay } 2559c564b6cSJohn Hay 2569c564b6cSJohn Hay pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 2579c564b6cSJohn Hay 2589c564b6cSJohn Hay childunit = puc_find_free_unit(typestr); 2599c564b6cSJohn Hay sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 2605aa967d9SYoshihiro Takahashi if (sc->sc_ports[i].dev == NULL) { 2615aa967d9SYoshihiro Takahashi if (sc->barmuxed) { 2625aa967d9SYoshihiro Takahashi bus_space_unmap(rman_get_bustag(rle->res), 2635aa967d9SYoshihiro Takahashi rman_get_bushandle(rle->res), 2645aa967d9SYoshihiro Takahashi 8); 2655aa967d9SYoshihiro Takahashi free(rle->res, M_DEVBUF); 2665aa967d9SYoshihiro Takahashi free(pdev, M_DEVBUF); 2675aa967d9SYoshihiro Takahashi } 2689c564b6cSJohn Hay continue; 2695aa967d9SYoshihiro Takahashi } 2709c564b6cSJohn Hay device_set_ivars(sc->sc_ports[i].dev, pdev); 2719c564b6cSJohn Hay device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 2729c564b6cSJohn Hay if (!bootverbose) 2739c564b6cSJohn Hay device_quiet(sc->sc_ports[i].dev); 2749c564b6cSJohn Hay #ifdef PUC_DEBUG 2759c564b6cSJohn Hay printf("puc: type %d, bar %x, offset %x\n", 2769c564b6cSJohn Hay sc->sc_desc->ports[i].type, 2779c564b6cSJohn Hay sc->sc_desc->ports[i].bar, 2789c564b6cSJohn Hay sc->sc_desc->ports[i].offset); 27932f606d1SPoul-Henning Kamp puc_print_resource_list(&pdev->resources); 2809c564b6cSJohn Hay #endif 2815aa967d9SYoshihiro Takahashi if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 2825aa967d9SYoshihiro Takahashi if (sc->barmuxed) { 2835aa967d9SYoshihiro Takahashi bus_space_unmap(rman_get_bustag(rle->res), 2845aa967d9SYoshihiro Takahashi rman_get_bushandle(rle->res), 2855aa967d9SYoshihiro Takahashi 8); 2865aa967d9SYoshihiro Takahashi free(rle->res, M_DEVBUF); 2875aa967d9SYoshihiro Takahashi free(pdev, M_DEVBUF); 2885aa967d9SYoshihiro Takahashi } 2895aa967d9SYoshihiro Takahashi } 2909c564b6cSJohn Hay } 2919c564b6cSJohn Hay 2929c564b6cSJohn Hay #ifdef PUC_DEBUG 2939c564b6cSJohn Hay bootverbose = 0; 2949c564b6cSJohn Hay #endif 2959c564b6cSJohn Hay return (0); 2969c564b6cSJohn Hay } 2979c564b6cSJohn Hay 2989c564b6cSJohn Hay /* 2999c564b6cSJohn Hay * This is just an brute force interrupt handler. It just calls all the 3009c564b6cSJohn Hay * registered handlers sequencially. 3019c564b6cSJohn Hay * 3029c564b6cSJohn Hay * Later on we should maybe have a different handler for boards that can 3039c564b6cSJohn Hay * tell us which device generated the interrupt. 3049c564b6cSJohn Hay */ 3059c564b6cSJohn Hay static void 3069c564b6cSJohn Hay puc_intr(void *arg) 3079c564b6cSJohn Hay { 3089c564b6cSJohn Hay int i; 3099c564b6cSJohn Hay struct puc_softc *sc; 3109c564b6cSJohn Hay 3111e89655aSPoul-Henning Kamp printf("puc_intr\n"); 3129c564b6cSJohn Hay sc = (struct puc_softc *)arg; 3139c564b6cSJohn Hay for (i = 0; i < PUC_MAX_PORTS; i++) 3149c564b6cSJohn Hay if (sc->sc_ports[i].ihand != NULL) 3159c564b6cSJohn Hay (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 3169c564b6cSJohn Hay } 3179c564b6cSJohn Hay 31832f606d1SPoul-Henning Kamp const struct puc_device_description * 3199c564b6cSJohn Hay puc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 3209c564b6cSJohn Hay uint32_t sprod) 3219c564b6cSJohn Hay { 3229c564b6cSJohn Hay int i; 3239c564b6cSJohn Hay 3249c564b6cSJohn Hay #define checkreg(val, index) \ 3259c564b6cSJohn Hay (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 3269c564b6cSJohn Hay 3279c564b6cSJohn Hay for (i = 0; puc_devices[i].name != NULL; i++) { 3289c564b6cSJohn Hay if (checkreg(vend, PUC_REG_VEND) && 3299c564b6cSJohn Hay checkreg(prod, PUC_REG_PROD) && 3309c564b6cSJohn Hay checkreg(svend, PUC_REG_SVEND) && 3319c564b6cSJohn Hay checkreg(sprod, PUC_REG_SPROD)) 3329c564b6cSJohn Hay return (&puc_devices[i]); 3339c564b6cSJohn Hay } 3349c564b6cSJohn Hay 3359c564b6cSJohn Hay #undef checkreg 3369c564b6cSJohn Hay 3379c564b6cSJohn Hay return (NULL); 3389c564b6cSJohn Hay } 3399c564b6cSJohn Hay static int puc_find_free_unit(char *name) 3409c564b6cSJohn Hay { 3419c564b6cSJohn Hay devclass_t dc; 3429c564b6cSJohn Hay int start; 3439c564b6cSJohn Hay int unit; 3449c564b6cSJohn Hay 3459c564b6cSJohn Hay unit = 0; 3469c564b6cSJohn Hay start = 0; 3479c564b6cSJohn Hay while (resource_int_value(name, unit, "port", &start) == 0 && 3489c564b6cSJohn Hay start > 0) 3499c564b6cSJohn Hay unit++; 3509c564b6cSJohn Hay dc = devclass_find(name); 3519c564b6cSJohn Hay if (dc == NULL) 3529c564b6cSJohn Hay return (-1); 3539c564b6cSJohn Hay while (devclass_get_device(dc, unit)) 3549c564b6cSJohn Hay unit++; 3559c564b6cSJohn Hay #ifdef PUC_DEBUG 3569c564b6cSJohn Hay printf("puc: Using %s%d\n", name, unit); 3579c564b6cSJohn Hay #endif 3589c564b6cSJohn Hay return (unit); 3599c564b6cSJohn Hay } 3609c564b6cSJohn Hay 3619c564b6cSJohn Hay #ifdef PUC_DEBUG 3629c564b6cSJohn Hay static void 3639c564b6cSJohn Hay puc_print_resource_list(struct resource_list *rl) 3649c564b6cSJohn Hay { 3651e89655aSPoul-Henning Kamp #if 0 3669c564b6cSJohn Hay struct resource_list_entry *rle; 3679c564b6cSJohn Hay 3689c564b6cSJohn Hay printf("print_resource_list: rl %p\n", rl); 3699c564b6cSJohn Hay SLIST_FOREACH(rle, rl, link) 3701e89655aSPoul-Henning Kamp printf(" type %x, rid %x start %x end %x count %x\n", 3711e89655aSPoul-Henning Kamp rle->type, rle->rid, rle->start, rle->end, rle->count); 3729c564b6cSJohn Hay printf("print_resource_list: end.\n"); 3731e89655aSPoul-Henning Kamp #endif 3749c564b6cSJohn Hay } 3759c564b6cSJohn Hay #endif 3769c564b6cSJohn Hay 37732f606d1SPoul-Henning Kamp struct resource * 3789c564b6cSJohn Hay puc_alloc_resource(device_t dev, device_t child, int type, int *rid, 3799c564b6cSJohn Hay u_long start, u_long end, u_long count, u_int flags) 3809c564b6cSJohn Hay { 3819c564b6cSJohn Hay struct puc_device *pdev; 3829c564b6cSJohn Hay struct resource *retval; 3839c564b6cSJohn Hay struct resource_list *rl; 3849c564b6cSJohn Hay struct resource_list_entry *rle; 3859c564b6cSJohn Hay 3869c564b6cSJohn Hay pdev = device_get_ivars(child); 3879c564b6cSJohn Hay rl = &pdev->resources; 3889c564b6cSJohn Hay 3899c564b6cSJohn Hay #ifdef PUC_DEBUG 3909c564b6cSJohn Hay printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 3919c564b6cSJohn Hay pdev, type, *rid); 3929c564b6cSJohn Hay puc_print_resource_list(rl); 3939c564b6cSJohn Hay #endif 3949c564b6cSJohn Hay retval = NULL; 3959c564b6cSJohn Hay rle = resource_list_find(rl, type, *rid); 3969c564b6cSJohn Hay if (rle) { 3979c564b6cSJohn Hay start = rle->start; 3989c564b6cSJohn Hay end = rle->end; 3999c564b6cSJohn Hay count = rle->count; 4009c564b6cSJohn Hay #ifdef PUC_DEBUG 4019c564b6cSJohn Hay printf("found rle, %lx, %lx, %lx\n", start, end, count); 4029c564b6cSJohn Hay #endif 4039c564b6cSJohn Hay retval = rle->res; 4049c564b6cSJohn Hay } else 4059c564b6cSJohn Hay printf("oops rle is gone\n"); 4069c564b6cSJohn Hay 4079c564b6cSJohn Hay return (retval); 4089c564b6cSJohn Hay } 4099c564b6cSJohn Hay 41032f606d1SPoul-Henning Kamp int 4119c564b6cSJohn Hay puc_release_resource(device_t dev, device_t child, int type, int rid, 4129c564b6cSJohn Hay struct resource *res) 4139c564b6cSJohn Hay { 4149c564b6cSJohn Hay return (0); 4159c564b6cSJohn Hay } 4169c564b6cSJohn Hay 41732f606d1SPoul-Henning Kamp int 4189c564b6cSJohn Hay puc_get_resource(device_t dev, device_t child, int type, int rid, 4199c564b6cSJohn Hay u_long *startp, u_long *countp) 4209c564b6cSJohn Hay { 4219c564b6cSJohn Hay struct puc_device *pdev; 4229c564b6cSJohn Hay struct resource_list *rl; 4239c564b6cSJohn Hay struct resource_list_entry *rle; 4249c564b6cSJohn Hay 4259c564b6cSJohn Hay pdev = device_get_ivars(child); 4269c564b6cSJohn Hay rl = &pdev->resources; 4279c564b6cSJohn Hay 4289c564b6cSJohn Hay #ifdef PUC_DEBUG 4299c564b6cSJohn Hay printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 4309c564b6cSJohn Hay type, rid); 4319c564b6cSJohn Hay puc_print_resource_list(rl); 4329c564b6cSJohn Hay #endif 4339c564b6cSJohn Hay rle = resource_list_find(rl, type, rid); 4349c564b6cSJohn Hay if (rle) { 4359c564b6cSJohn Hay #ifdef PUC_DEBUG 4369c564b6cSJohn Hay printf("found rle %p,", rle); 4379c564b6cSJohn Hay #endif 4389c564b6cSJohn Hay if (startp != NULL) 4399c564b6cSJohn Hay *startp = rle->start; 4409c564b6cSJohn Hay if (countp != NULL) 4419c564b6cSJohn Hay *countp = rle->count; 4429c564b6cSJohn Hay #ifdef PUC_DEBUG 4439c564b6cSJohn Hay printf(" %lx, %lx\n", rle->start, rle->count); 4449c564b6cSJohn Hay #endif 4459c564b6cSJohn Hay return (0); 4469c564b6cSJohn Hay } else 4479c564b6cSJohn Hay printf("oops rle is gone\n"); 4489c564b6cSJohn Hay return (ENXIO); 4499c564b6cSJohn Hay } 4509c564b6cSJohn Hay 45132f606d1SPoul-Henning Kamp int 4529c564b6cSJohn Hay puc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 4539c564b6cSJohn Hay void (*ihand)(void *), void *arg, void **cookiep) 4549c564b6cSJohn Hay { 4559c564b6cSJohn Hay int i; 4569c564b6cSJohn Hay struct puc_softc *sc; 4579c564b6cSJohn Hay 4581e89655aSPoul-Henning Kamp printf("puc_setup_intr()\n"); 4599c564b6cSJohn Hay sc = (struct puc_softc *)device_get_softc(dev); 4609c564b6cSJohn Hay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 4619c564b6cSJohn Hay if (sc->sc_ports[i].dev == child) { 4629c564b6cSJohn Hay if (sc->sc_ports[i].ihand != 0) 4639c564b6cSJohn Hay return (ENXIO); 4649c564b6cSJohn Hay sc->sc_ports[i].ihand = ihand; 4659c564b6cSJohn Hay sc->sc_ports[i].ihandarg = arg; 4669c564b6cSJohn Hay *cookiep = arg; 4679c564b6cSJohn Hay return (0); 4689c564b6cSJohn Hay } 4699c564b6cSJohn Hay } 4709c564b6cSJohn Hay return (ENXIO); 4719c564b6cSJohn Hay } 4729c564b6cSJohn Hay 47332f606d1SPoul-Henning Kamp int 4749c564b6cSJohn Hay puc_teardown_intr(device_t dev, device_t child, struct resource *r, 4759c564b6cSJohn Hay void *cookie) 4769c564b6cSJohn Hay { 4779c564b6cSJohn Hay int i; 4789c564b6cSJohn Hay struct puc_softc *sc; 4799c564b6cSJohn Hay 4801e89655aSPoul-Henning Kamp printf("puc_teardown_intr()\n"); 4819c564b6cSJohn Hay sc = (struct puc_softc *)device_get_softc(dev); 4829c564b6cSJohn Hay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 4839c564b6cSJohn Hay if (sc->sc_ports[i].dev == child) { 4849c564b6cSJohn Hay sc->sc_ports[i].ihand = NULL; 4859c564b6cSJohn Hay sc->sc_ports[i].ihandarg = NULL; 4869c564b6cSJohn Hay return (0); 4879c564b6cSJohn Hay } 4889c564b6cSJohn Hay } 4899c564b6cSJohn Hay return (ENXIO); 4909c564b6cSJohn Hay } 4919c564b6cSJohn Hay 49232f606d1SPoul-Henning Kamp int 4939c564b6cSJohn Hay puc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 4949c564b6cSJohn Hay { 4959c564b6cSJohn Hay struct puc_device *pdev; 4969c564b6cSJohn Hay 4979c564b6cSJohn Hay pdev = device_get_ivars(child); 4989c564b6cSJohn Hay if (pdev == NULL) 4999c564b6cSJohn Hay return (ENOENT); 5009c564b6cSJohn Hay 5019c564b6cSJohn Hay switch(index) { 5029c564b6cSJohn Hay case PUC_IVAR_FREQ: 5039c564b6cSJohn Hay *result = pdev->serialfreq; 5049c564b6cSJohn Hay break; 5059c564b6cSJohn Hay default: 5069c564b6cSJohn Hay return (ENOENT); 5079c564b6cSJohn Hay } 5089c564b6cSJohn Hay return (0); 5099c564b6cSJohn Hay } 5109c564b6cSJohn Hay 51132f606d1SPoul-Henning Kamp devclass_t puc_devclass; 5129c564b6cSJohn Hay 513