puc.c revision 109458
190731Sjhay/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 290731Sjhay 390731Sjhay/*- 490731Sjhay * Copyright (c) 2002 JF Hay. All rights reserved. 590731Sjhay * Copyright (c) 2000 M. Warner Losh. All rights reserved. 690731Sjhay * 790731Sjhay * Redistribution and use in source and binary forms, with or without 890731Sjhay * modification, are permitted provided that the following conditions 990731Sjhay * are met: 1090731Sjhay * 1. Redistributions of source code must retain the above copyright 1190731Sjhay * notice unmodified, this list of conditions, and the following 1290731Sjhay * disclaimer. 1390731Sjhay * 2. Redistributions in binary form must reproduce the above copyright 1490731Sjhay * notice, this list of conditions and the following disclaimer in the 1590731Sjhay * documentation and/or other materials provided with the distribution. 1690731Sjhay * 1790731Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1890731Sjhay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1990731Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2090731Sjhay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2190731Sjhay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2290731Sjhay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2390731Sjhay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2490731Sjhay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2590731Sjhay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2690731Sjhay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2790731Sjhay */ 2890731Sjhay 2990731Sjhay/* 3090731Sjhay * Copyright (c) 1996, 1998, 1999 3190731Sjhay * Christopher G. Demetriou. All rights reserved. 3290731Sjhay * 3390731Sjhay * Redistribution and use in source and binary forms, with or without 3490731Sjhay * modification, are permitted provided that the following conditions 3590731Sjhay * are met: 3690731Sjhay * 1. Redistributions of source code must retain the above copyright 3790731Sjhay * notice, this list of conditions and the following disclaimer. 3890731Sjhay * 2. Redistributions in binary form must reproduce the above copyright 3990731Sjhay * notice, this list of conditions and the following disclaimer in the 4090731Sjhay * documentation and/or other materials provided with the distribution. 4190731Sjhay * 3. All advertising materials mentioning features or use of this software 4290731Sjhay * must display the following acknowledgement: 4390731Sjhay * This product includes software developed by Christopher G. Demetriou 4490731Sjhay * for the NetBSD Project. 4590731Sjhay * 4. The name of the author may not be used to endorse or promote products 4690731Sjhay * derived from this software without specific prior written permission 4790731Sjhay * 4890731Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4990731Sjhay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5090731Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 5190731Sjhay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 5290731Sjhay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5390731Sjhay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5490731Sjhay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5590731Sjhay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5690731Sjhay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5790731Sjhay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5890731Sjhay */ 5990731Sjhay 6090731Sjhay#include <sys/cdefs.h> 6190731Sjhay__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 109458 2003-01-18 02:54:16Z marcel $"); 6290731Sjhay 6390731Sjhay/* 6490731Sjhay * PCI "universal" communication card device driver, glues com, lpt, 6590731Sjhay * and similar ports to PCI via bridge chip often much larger than 6690731Sjhay * the devices being glued. 6790731Sjhay * 6890731Sjhay * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 6990731Sjhay * sys/dev/pci/pciide.c, revision 1.6). 7090731Sjhay * 7190731Sjhay * These devices could be (and some times are) described as 7290731Sjhay * communications/{serial,parallel}, etc. devices with known 7390731Sjhay * programming interfaces, but those programming interfaces (in 7490731Sjhay * particular the BAR assignments for devices, etc.) in fact are not 7590731Sjhay * particularly well defined. 7690731Sjhay * 7790731Sjhay * After I/we have seen more of these devices, it may be possible 7890731Sjhay * to generalize some of these bits. In particular, devices which 7990731Sjhay * describe themselves as communications/serial/16[45]50, and 8090731Sjhay * communications/parallel/??? might be attached via direct 8190731Sjhay * 'com' and 'lpt' attachments to pci. 8290731Sjhay */ 8390731Sjhay 84102751Sjmallett#include "opt_puc.h" 85102751Sjmallett 8690731Sjhay#include <sys/param.h> 8790731Sjhay#include <sys/systm.h> 8890731Sjhay#include <sys/kernel.h> 8990731Sjhay#include <sys/bus.h> 9090731Sjhay#include <sys/conf.h> 9190731Sjhay#include <sys/malloc.h> 9290731Sjhay 9390731Sjhay#include <machine/bus.h> 9490731Sjhay#include <machine/resource.h> 9590731Sjhay#include <sys/rman.h> 9690731Sjhay 9790731Sjhay#include <dev/pci/pcireg.h> 9890731Sjhay#include <dev/pci/pcivar.h> 99102714Sphk 100102714Sphk#define PUC_ENTRAILS 1 10190731Sjhay#include <dev/puc/pucvar.h> 10290731Sjhay 10390731Sjhaystruct puc_device { 10490731Sjhay struct resource_list resources; 10590731Sjhay u_int serialfreq; 10690731Sjhay}; 10790731Sjhay 10890731Sjhaystatic void puc_intr(void *arg); 10990731Sjhay 11090731Sjhaystatic int puc_find_free_unit(char *); 11190731Sjhay#ifdef PUC_DEBUG 11290731Sjhaystatic void puc_print_resource_list(struct resource_list *); 11390731Sjhay#endif 11490731Sjhay 115102893Sphkdevclass_t puc_devclass; 116102893Sphk 117102734Sphkstatic int 118102734Sphkpuc_port_bar_index(struct puc_softc *sc, int bar) 119102734Sphk{ 120102734Sphk int i; 121102734Sphk 122102734Sphk for (i = 0; i < PUC_MAX_BAR; i += 1) { 123102734Sphk if (!sc->sc_bar_mappings[i].used) 124102734Sphk break; 125102734Sphk if (sc->sc_bar_mappings[i].bar == bar) 126102734Sphk return (i); 127102734Sphk } 128102734Sphk sc->sc_bar_mappings[i].bar = bar; 129102734Sphk sc->sc_bar_mappings[i].used = 1; 130102734Sphk return (i); 131102734Sphk} 132102734Sphk 133102714Sphkint 134102714Sphkpuc_attach(device_t dev, const struct puc_device_description *desc) 13590731Sjhay{ 13690731Sjhay char *typestr; 137109458Smarcel int bidx, childunit, i, irq_setup, rid, type; 13890731Sjhay struct puc_softc *sc; 13990731Sjhay struct puc_device *pdev; 14090731Sjhay struct resource *res; 14190731Sjhay struct resource_list_entry *rle; 14290731Sjhay 14390731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 14490731Sjhay bzero(sc, sizeof(*sc)); 145102714Sphk sc->sc_desc = desc; 14690731Sjhay if (sc->sc_desc == NULL) 14790731Sjhay return (ENXIO); 14890731Sjhay 14990731Sjhay#ifdef PUC_DEBUG 15090731Sjhay bootverbose = 1; 15190731Sjhay 15290731Sjhay printf("puc: name: %s\n", sc->sc_desc->name); 15390731Sjhay#endif 15490731Sjhay rid = 0; 15590731Sjhay res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 15690731Sjhay RF_ACTIVE | RF_SHAREABLE); 15790731Sjhay if (!res) 15890731Sjhay return (ENXIO); 15990731Sjhay 16090731Sjhay sc->irqres = res; 16190731Sjhay sc->irqrid = rid; 162102929Sphk#ifdef PUC_FASTINTR 16390731Sjhay irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 164102929Sphk INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 165102929Sphk if (irq_setup == 0) 166102931Sphk sc->fastintr = INTR_FAST; 167102929Sphk else 168102929Sphk irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 169102929Sphk INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 170102929Sphk#else 171102929Sphk irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 172102895Sphk INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 173102929Sphk#endif 17490731Sjhay if (irq_setup != 0) 17590731Sjhay return (ENXIO); 17690731Sjhay 17790731Sjhay rid = 0; 17890731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 179102734Sphk if (i > 0 && rid == sc->sc_desc->ports[i].bar) 18090731Sjhay sc->barmuxed = 1; 18190731Sjhay rid = sc->sc_desc->ports[i].bar; 182102734Sphk bidx = puc_port_bar_index(sc, rid); 18390731Sjhay 18490731Sjhay if (sc->sc_bar_mappings[bidx].res != NULL) 18590731Sjhay continue; 186109458Smarcel 187109458Smarcel type = (sc->sc_desc->ports[i].flags & PUC_FLAGS_MEMORY) 188109458Smarcel ? SYS_RES_MEMORY : SYS_RES_IOPORT; 189109458Smarcel 190109458Smarcel res = bus_alloc_resource(dev, type, &rid, 0ul, ~0ul, 1, 191109458Smarcel RF_ACTIVE); 19290731Sjhay if (res == NULL) { 19390731Sjhay printf("could not get resource\n"); 19490731Sjhay continue; 19590731Sjhay } 196109458Smarcel sc->sc_bar_mappings[bidx].type = type; 19790731Sjhay sc->sc_bar_mappings[bidx].res = res; 19890731Sjhay#ifdef PUC_DEBUG 199109458Smarcel printf("%s rid %d bst %x, start %x, end %x\n", 200109458Smarcel (type == SYS_RES_MEMORY) ? "memory" : "port", rid, 20190731Sjhay (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 20290731Sjhay (u_int)rman_get_end(res)); 20390731Sjhay#endif 20490731Sjhay } 20590731Sjhay 206102734Sphk if (desc->init != NULL) { 207102734Sphk i = desc->init(sc); 208102734Sphk if (i != 0) 209102734Sphk return (i); 210102734Sphk } 21190731Sjhay 21290731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 21390731Sjhay rid = sc->sc_desc->ports[i].bar; 214102734Sphk bidx = puc_port_bar_index(sc, rid); 21590731Sjhay if (sc->sc_bar_mappings[bidx].res == NULL) 21690731Sjhay continue; 21790731Sjhay 21890731Sjhay switch (sc->sc_desc->ports[i].type) { 21990731Sjhay case PUC_PORT_TYPE_COM: 22090731Sjhay typestr = "sio"; 22190731Sjhay break; 22290731Sjhay default: 22390731Sjhay continue; 22490731Sjhay } 22590731Sjhay pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 22690731Sjhay M_NOWAIT | M_ZERO); 22790731Sjhay if (!pdev) 22890731Sjhay continue; 22990731Sjhay resource_list_init(&pdev->resources); 23090731Sjhay 23190731Sjhay /* First fake up an IRQ resource. */ 23290731Sjhay resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 23390731Sjhay rman_get_start(sc->irqres), rman_get_end(sc->irqres), 23490731Sjhay rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 23590731Sjhay rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 23690731Sjhay rle->res = sc->irqres; 23790731Sjhay 238109458Smarcel /* Now fake an IOPORT or MEMORY resource */ 23990731Sjhay res = sc->sc_bar_mappings[bidx].res; 240109458Smarcel type = sc->sc_bar_mappings[bidx].type; 241109458Smarcel resource_list_add(&pdev->resources, type, 0, 24290731Sjhay rman_get_start(res) + sc->sc_desc->ports[i].offset, 243102734Sphk rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1, 24490731Sjhay 8); 245109458Smarcel rle = resource_list_find(&pdev->resources, type, 0); 24690731Sjhay 24790731Sjhay if (sc->barmuxed == 0) { 24890731Sjhay rle->res = sc->sc_bar_mappings[bidx].res; 24990731Sjhay } else { 25090731Sjhay rle->res = malloc(sizeof(struct resource), M_DEVBUF, 25190731Sjhay M_WAITOK | M_ZERO); 25290925Snyan if (rle->res == NULL) { 25390925Snyan free(pdev, M_DEVBUF); 25490731Sjhay return (ENOMEM); 25590925Snyan } 25690731Sjhay 25790731Sjhay rle->res->r_start = rman_get_start(res) + 25890731Sjhay sc->sc_desc->ports[i].offset; 25990731Sjhay rle->res->r_end = rle->res->r_start + 8 - 1; 26090731Sjhay rle->res->r_bustag = rman_get_bustag(res); 26190731Sjhay bus_space_subregion(rle->res->r_bustag, 26290731Sjhay rman_get_bushandle(res), 26390731Sjhay sc->sc_desc->ports[i].offset, 8, 26490731Sjhay &rle->res->r_bushandle); 26590731Sjhay } 26690731Sjhay 26790731Sjhay pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 26890731Sjhay 26990731Sjhay childunit = puc_find_free_unit(typestr); 27090731Sjhay sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 27190925Snyan if (sc->sc_ports[i].dev == NULL) { 27290925Snyan if (sc->barmuxed) { 27390925Snyan bus_space_unmap(rman_get_bustag(rle->res), 274109458Smarcel rman_get_bushandle(rle->res), 8); 27590925Snyan free(rle->res, M_DEVBUF); 27690925Snyan free(pdev, M_DEVBUF); 27790925Snyan } 27890731Sjhay continue; 27990925Snyan } 28090731Sjhay device_set_ivars(sc->sc_ports[i].dev, pdev); 28190731Sjhay device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 28290731Sjhay if (!bootverbose) 28390731Sjhay device_quiet(sc->sc_ports[i].dev); 28490731Sjhay#ifdef PUC_DEBUG 28590731Sjhay printf("puc: type %d, bar %x, offset %x\n", 28690731Sjhay sc->sc_desc->ports[i].type, 28790731Sjhay sc->sc_desc->ports[i].bar, 28890731Sjhay sc->sc_desc->ports[i].offset); 289102714Sphk puc_print_resource_list(&pdev->resources); 29090731Sjhay#endif 291104068Sphk device_set_flags(sc->sc_ports[i].dev, 292104068Sphk sc->sc_desc->ports[i].flags); 29390925Snyan if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 29490925Snyan if (sc->barmuxed) { 29590925Snyan bus_space_unmap(rman_get_bustag(rle->res), 29690925Snyan rman_get_bushandle(rle->res), 29790925Snyan 8); 29890925Snyan free(rle->res, M_DEVBUF); 29990925Snyan free(pdev, M_DEVBUF); 30090925Snyan } 30190925Snyan } 30290731Sjhay } 30390731Sjhay 30490731Sjhay#ifdef PUC_DEBUG 30590731Sjhay bootverbose = 0; 30690731Sjhay#endif 30790731Sjhay return (0); 30890731Sjhay} 30990731Sjhay 31090731Sjhay/* 311108470Sschweikh * This is just a brute force interrupt handler. It just calls all the 31290731Sjhay * registered handlers sequencially. 31390731Sjhay * 31490731Sjhay * Later on we should maybe have a different handler for boards that can 31590731Sjhay * tell us which device generated the interrupt. 31690731Sjhay */ 31790731Sjhaystatic void 31890731Sjhaypuc_intr(void *arg) 31990731Sjhay{ 32090731Sjhay int i; 32190731Sjhay struct puc_softc *sc; 32290731Sjhay 32390731Sjhay sc = (struct puc_softc *)arg; 32490731Sjhay for (i = 0; i < PUC_MAX_PORTS; i++) 32590731Sjhay if (sc->sc_ports[i].ihand != NULL) 32690731Sjhay (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 32790731Sjhay} 32890731Sjhay 329102714Sphkconst struct puc_device_description * 33090731Sjhaypuc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 33190731Sjhay uint32_t sprod) 33290731Sjhay{ 33390731Sjhay int i; 33490731Sjhay 33590731Sjhay#define checkreg(val, index) \ 33690731Sjhay (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 33790731Sjhay 33890731Sjhay for (i = 0; puc_devices[i].name != NULL; i++) { 33990731Sjhay if (checkreg(vend, PUC_REG_VEND) && 34090731Sjhay checkreg(prod, PUC_REG_PROD) && 34190731Sjhay checkreg(svend, PUC_REG_SVEND) && 34290731Sjhay checkreg(sprod, PUC_REG_SPROD)) 34390731Sjhay return (&puc_devices[i]); 34490731Sjhay } 34590731Sjhay 34690731Sjhay#undef checkreg 34790731Sjhay 34890731Sjhay return (NULL); 34990731Sjhay} 350102894Sphk 351102894Sphkstatic int 352102894Sphkpuc_find_free_unit(char *name) 35390731Sjhay{ 35490731Sjhay devclass_t dc; 35590731Sjhay int start; 35690731Sjhay int unit; 35790731Sjhay 35890731Sjhay unit = 0; 35990731Sjhay start = 0; 36090731Sjhay while (resource_int_value(name, unit, "port", &start) == 0 && 36190731Sjhay start > 0) 36290731Sjhay unit++; 36390731Sjhay dc = devclass_find(name); 36490731Sjhay if (dc == NULL) 36590731Sjhay return (-1); 36690731Sjhay while (devclass_get_device(dc, unit)) 36790731Sjhay unit++; 36890731Sjhay#ifdef PUC_DEBUG 36990731Sjhay printf("puc: Using %s%d\n", name, unit); 37090731Sjhay#endif 37190731Sjhay return (unit); 37290731Sjhay} 37390731Sjhay 37490731Sjhay#ifdef PUC_DEBUG 37590731Sjhaystatic void 37690731Sjhaypuc_print_resource_list(struct resource_list *rl) 37790731Sjhay{ 378102734Sphk#if 0 37990731Sjhay struct resource_list_entry *rle; 38090731Sjhay 38190731Sjhay printf("print_resource_list: rl %p\n", rl); 38290731Sjhay SLIST_FOREACH(rle, rl, link) 383102734Sphk printf(" type %x, rid %x start %x end %x count %x\n", 384102734Sphk rle->type, rle->rid, rle->start, rle->end, rle->count); 38590731Sjhay printf("print_resource_list: end.\n"); 386102734Sphk#endif 38790731Sjhay} 38890731Sjhay#endif 38990731Sjhay 390102714Sphkstruct resource * 39190731Sjhaypuc_alloc_resource(device_t dev, device_t child, int type, int *rid, 39290731Sjhay u_long start, u_long end, u_long count, u_int flags) 39390731Sjhay{ 39490731Sjhay struct puc_device *pdev; 39590731Sjhay struct resource *retval; 39690731Sjhay struct resource_list *rl; 39790731Sjhay struct resource_list_entry *rle; 39890731Sjhay 39990731Sjhay pdev = device_get_ivars(child); 40090731Sjhay rl = &pdev->resources; 40190731Sjhay 40290731Sjhay#ifdef PUC_DEBUG 40390731Sjhay printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 40490731Sjhay pdev, type, *rid); 40590731Sjhay puc_print_resource_list(rl); 40690731Sjhay#endif 40790731Sjhay retval = NULL; 40890731Sjhay rle = resource_list_find(rl, type, *rid); 40990731Sjhay if (rle) { 41090731Sjhay start = rle->start; 41190731Sjhay end = rle->end; 41290731Sjhay count = rle->count; 41390731Sjhay#ifdef PUC_DEBUG 41490731Sjhay printf("found rle, %lx, %lx, %lx\n", start, end, count); 41590731Sjhay#endif 41690731Sjhay retval = rle->res; 41790731Sjhay } else 41890731Sjhay printf("oops rle is gone\n"); 41990731Sjhay 42090731Sjhay return (retval); 42190731Sjhay} 42290731Sjhay 423102714Sphkint 42490731Sjhaypuc_release_resource(device_t dev, device_t child, int type, int rid, 42590731Sjhay struct resource *res) 42690731Sjhay{ 42790731Sjhay return (0); 42890731Sjhay} 42990731Sjhay 430102714Sphkint 43190731Sjhaypuc_get_resource(device_t dev, device_t child, int type, int rid, 43290731Sjhay u_long *startp, u_long *countp) 43390731Sjhay{ 43490731Sjhay struct puc_device *pdev; 43590731Sjhay struct resource_list *rl; 43690731Sjhay struct resource_list_entry *rle; 43790731Sjhay 43890731Sjhay pdev = device_get_ivars(child); 43990731Sjhay rl = &pdev->resources; 44090731Sjhay 44190731Sjhay#ifdef PUC_DEBUG 44290731Sjhay printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 44390731Sjhay type, rid); 44490731Sjhay puc_print_resource_list(rl); 44590731Sjhay#endif 44690731Sjhay rle = resource_list_find(rl, type, rid); 44790731Sjhay if (rle) { 44890731Sjhay#ifdef PUC_DEBUG 44990731Sjhay printf("found rle %p,", rle); 45090731Sjhay#endif 45190731Sjhay if (startp != NULL) 45290731Sjhay *startp = rle->start; 45390731Sjhay if (countp != NULL) 45490731Sjhay *countp = rle->count; 45590731Sjhay#ifdef PUC_DEBUG 45690731Sjhay printf(" %lx, %lx\n", rle->start, rle->count); 45790731Sjhay#endif 45890731Sjhay return (0); 45990731Sjhay } else 46090731Sjhay printf("oops rle is gone\n"); 46190731Sjhay return (ENXIO); 46290731Sjhay} 46390731Sjhay 464102714Sphkint 46590731Sjhaypuc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 46690731Sjhay void (*ihand)(void *), void *arg, void **cookiep) 46790731Sjhay{ 46890731Sjhay int i; 46990731Sjhay struct puc_softc *sc; 47090731Sjhay 471102929Sphk sc = (struct puc_softc *)device_get_softc(dev); 472102931Sphk if ((flags & INTR_FAST) != sc->fastintr) 473102895Sphk return (ENXIO); 47490731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 47590731Sjhay if (sc->sc_ports[i].dev == child) { 47690731Sjhay if (sc->sc_ports[i].ihand != 0) 47790731Sjhay return (ENXIO); 47890731Sjhay sc->sc_ports[i].ihand = ihand; 47990731Sjhay sc->sc_ports[i].ihandarg = arg; 48090731Sjhay *cookiep = arg; 48190731Sjhay return (0); 48290731Sjhay } 48390731Sjhay } 48490731Sjhay return (ENXIO); 48590731Sjhay} 48690731Sjhay 487102714Sphkint 48890731Sjhaypuc_teardown_intr(device_t dev, device_t child, struct resource *r, 48990731Sjhay void *cookie) 49090731Sjhay{ 49190731Sjhay int i; 49290731Sjhay struct puc_softc *sc; 49390731Sjhay 49490731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 49590731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 49690731Sjhay if (sc->sc_ports[i].dev == child) { 49790731Sjhay sc->sc_ports[i].ihand = NULL; 49890731Sjhay sc->sc_ports[i].ihandarg = NULL; 49990731Sjhay return (0); 50090731Sjhay } 50190731Sjhay } 50290731Sjhay return (ENXIO); 50390731Sjhay} 50490731Sjhay 505102714Sphkint 50690731Sjhaypuc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 50790731Sjhay{ 50890731Sjhay struct puc_device *pdev; 50990731Sjhay 51090731Sjhay pdev = device_get_ivars(child); 51190731Sjhay if (pdev == NULL) 51290731Sjhay return (ENOENT); 51390731Sjhay 51490731Sjhay switch(index) { 51590731Sjhay case PUC_IVAR_FREQ: 51690731Sjhay *result = pdev->serialfreq; 51790731Sjhay break; 51890731Sjhay default: 51990731Sjhay return (ENOENT); 52090731Sjhay } 52190731Sjhay return (0); 52290731Sjhay} 523