puc.c revision 104068
121259Swollman/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 221259Swollman 321259Swollman/*- 421259Swollman * Copyright (c) 2002 JF Hay. All rights reserved. 521259Swollman * Copyright (c) 2000 M. Warner Losh. All rights reserved. 621259Swollman * 721259Swollman * Redistribution and use in source and binary forms, with or without 821259Swollman * modification, are permitted provided that the following conditions 921259Swollman * are met: 1021259Swollman * 1. Redistributions of source code must retain the above copyright 1121259Swollman * notice unmodified, this list of conditions, and the following 1221259Swollman * disclaimer. 1321259Swollman * 2. Redistributions in binary form must reproduce the above copyright 1421259Swollman * notice, this list of conditions and the following disclaimer in the 1521259Swollman * documentation and/or other materials provided with the distribution. 1621259Swollman * 1721259Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1821259Swollman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1921259Swollman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2021259Swollman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2121259Swollman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2221259Swollman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2321259Swollman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2421259Swollman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2521259Swollman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2621259Swollman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2721259Swollman */ 2821259Swollman 2921259Swollman/* 3021259Swollman * Copyright (c) 1996, 1998, 1999 3121259Swollman * Christopher G. Demetriou. All rights reserved. 3221259Swollman * 3321259Swollman * Redistribution and use in source and binary forms, with or without 3450477Speter * modification, are permitted provided that the following conditions 3521259Swollman * are met: 3621259Swollman * 1. Redistributions of source code must retain the above copyright 3721259Swollman * notice, this list of conditions and the following disclaimer. 3821259Swollman * 2. Redistributions in binary form must reproduce the above copyright 3921259Swollman * notice, this list of conditions and the following disclaimer in the 4021259Swollman * documentation and/or other materials provided with the distribution. 4121259Swollman * 3. All advertising materials mentioning features or use of this software 4221259Swollman * must display the following acknowledgement: 4321259Swollman * This product includes software developed by Christopher G. Demetriou 4421259Swollman * for the NetBSD Project. 4521259Swollman * 4. The name of the author may not be used to endorse or promote products 4621259Swollman * derived from this software without specific prior written permission 4721259Swollman * 4821259Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4921259Swollman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5021259Swollman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 5121259Swollman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 5221259Swollman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5321259Swollman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5421259Swollman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55108533Sschweikh * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5621259Swollman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5721259Swollman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5821259Swollman */ 5921259Swollman 60108533Sschweikh#include <sys/cdefs.h> 6121259Swollman__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 104068 2002-09-27 22:01:32Z phk $"); 6221259Swollman 6321259Swollman/* 6421259Swollman * PCI "universal" communication card device driver, glues com, lpt, 6521259Swollman * and similar ports to PCI via bridge chip often much larger than 6621259Swollman * the devices being glued. 6721259Swollman * 6821259Swollman * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 6921259Swollman * sys/dev/pci/pciide.c, revision 1.6). 7083366Sjulian * 7121259Swollman * These devices could be (and some times are) described as 7285074Sru * communications/{serial,parallel}, etc. devices with known 7321259Swollman * programming interfaces, but those programming interfaces (in 7421259Swollman * particular the BAR assignments for devices, etc.) in fact are not 7521259Swollman * particularly well defined. 7621259Swollman * 77101849Srwatson * After I/we have seen more of these devices, it may be possible 7821259Swollman * to generalize some of these bits. In particular, devices which 7921259Swollman * describe themselves as communications/serial/16[45]50, and 8069224Sjlemon * communications/parallel/??? might be attached via direct 8169152Sjlemon * 'com' and 'lpt' attachments to pci. 8269224Sjlemon */ 8374914Sjhb 8474914Sjhb#include "opt_puc.h" 8583130Sjlemon 8669152Sjlemon#include <sys/param.h> 8760938Sjake#include <sys/systm.h> 8860938Sjake#include <sys/kernel.h> 8960938Sjake#include <sys/bus.h> 9072084Sphk#include <sys/conf.h> 9121259Swollman#include <sys/malloc.h> 9221259Swollman 9321259Swollman#include <machine/bus.h> 9421259Swollman#include <machine/resource.h> 9521259Swollman#include <sys/rman.h> 9621259Swollman 9721259Swollman#include <dev/pci/pcireg.h> 9821259Swollman#include <dev/pci/pcivar.h> 9921259Swollman 10021259Swollman#define PUC_ENTRAILS 1 10169152Sjlemon#include <dev/puc/pucvar.h> 10221259Swollman 10321259Swollmanstruct puc_device { 10421259Swollman struct resource_list resources; 10521259Swollman u_int serialfreq; 10621259Swollman}; 10721259Swollman 10821259Swollmanstatic void puc_intr(void *arg); 10984380Smjacob 11084380Smjacobstatic int puc_find_free_unit(char *); 11184380Smjacob#ifdef PUC_DEBUG 11284380Smjacobstatic void puc_print_resource_list(struct resource_list *); 11386797Sluigi#endif 11486797Sluigi 11586797Sluigidevclass_t puc_devclass; 11686797Sluigi 11786797Sluigistatic int 11886797Sluigipuc_port_bar_index(struct puc_softc *sc, int bar) 11986797Sluigi{ 12086797Sluigi int i; 12186797Sluigi 12286797Sluigi for (i = 0; i < PUC_MAX_BAR; i += 1) { 12386797Sluigi if (!sc->sc_bar_mappings[i].used) 12486797Sluigi break; 12586797Sluigi if (sc->sc_bar_mappings[i].bar == bar) 12686797Sluigi return (i); 12786797Sluigi } 12884380Smjacob sc->sc_bar_mappings[i].bar = bar; 12921259Swollman sc->sc_bar_mappings[i].used = 1; 13021259Swollman return (i); 13121259Swollman} 13260938Sjake 13321259Swollmanint 13483130Sjlemonpuc_attach(device_t dev, const struct puc_device_description *desc) 13583130Sjlemon{ 13621259Swollman char *typestr; 13721259Swollman int bidx, childunit, i, irq_setup, rid; 13821259Swollman struct puc_softc *sc; 13921259Swollman struct puc_device *pdev; 140106931Ssam struct resource *res; 141102052Ssobomax struct resource_list_entry *rle; 14283624Sjlemon 14383624Sjlemon sc = (struct puc_softc *)device_get_softc(dev); 14421259Swollman bzero(sc, sizeof(*sc)); 14521259Swollman sc->sc_desc = desc; 14621259Swollman if (sc->sc_desc == NULL) 14721259Swollman return (ENXIO); 14821404Swollman 14921404Swollman#ifdef PUC_DEBUG 15021259Swollman bootverbose = 1; 15121259Swollman 15292725Salfred printf("puc: name: %s\n", sc->sc_desc->name); 15392725Salfred#endif 154106931Ssam rid = 0; 155106931Ssam res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 15621259Swollman RF_ACTIVE | RF_SHAREABLE); 15792725Salfred if (!res) 15821259Swollman return (ENXIO); 15992725Salfred 16021259Swollman sc->irqres = res; 16192725Salfred sc->irqrid = rid; 16221259Swollman#ifdef PUC_FASTINTR 16392725Salfred irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 16421259Swollman INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 16592725Salfred if (irq_setup == 0) 16621259Swollman sc->fastintr = INTR_FAST; 16792725Salfred else 16821259Swollman irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 16992725Salfred INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 17021259Swollman#else 17192725Salfred irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 17221259Swollman INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 17392725Salfred#endif 17421404Swollman if (irq_setup != 0) 17592725Salfred return (ENXIO); 17621259Swollman 17721259Swollman rid = 0; 17852904Sshin for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 17984931Sfjoe if (i > 0 && rid == sc->sc_desc->ports[i].bar) 180100992Srwatson sc->barmuxed = 1; 18121259Swollman rid = sc->sc_desc->ports[i].bar; 18269152Sjlemon bidx = puc_port_bar_index(sc, rid); 18392725Salfred 18421259Swollman if (sc->sc_bar_mappings[bidx].res != NULL) 18521259Swollman continue; 18621259Swollman res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 18721259Swollman 0ul, ~0ul, 1, RF_ACTIVE); 18821259Swollman if (res == NULL) { 18921259Swollman printf("could not get resource\n"); 19021259Swollman continue; 19121259Swollman } 19258698Sjlemon sc->sc_bar_mappings[bidx].res = res; 19321259Swollman#ifdef PUC_DEBUG 19421259Swollman printf("port rid %d bst %x, start %x, end %x\n", rid, 19521259Swollman (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 19621259Swollman (u_int)rman_get_end(res)); 19721259Swollman#endif 19821259Swollman } 19921259Swollman 20021259Swollman if (desc->init != NULL) { 20121259Swollman i = desc->init(sc); 20221259Swollman if (i != 0) 20321259Swollman return (i); 20421259Swollman } 20521259Swollman 20621259Swollman for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 20721259Swollman rid = sc->sc_desc->ports[i].bar; 20821259Swollman bidx = puc_port_bar_index(sc, rid); 20953541Sshin if (sc->sc_bar_mappings[bidx].res == NULL) 21053541Sshin continue; 21153541Sshin 21253541Sshin switch (sc->sc_desc->ports[i].type) { 21321259Swollman case PUC_PORT_TYPE_COM: 21421259Swollman typestr = "sio"; 21521259Swollman break; 21621259Swollman default: 21721259Swollman continue; 21821259Swollman } 21921259Swollman pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 22021259Swollman M_NOWAIT | M_ZERO); 22121259Swollman if (!pdev) 22221259Swollman continue; 22321259Swollman resource_list_init(&pdev->resources); 22421259Swollman 22572200Sbmilekic /* First fake up an IRQ resource. */ 22672200Sbmilekic resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 22769152Sjlemon rman_get_start(sc->irqres), rman_get_end(sc->irqres), 22869152Sjlemon rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 22969152Sjlemon rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 23021259Swollman rle->res = sc->irqres; 23169152Sjlemon 23269152Sjlemon /* Now fake an IOPORT resource */ 23369152Sjlemon res = sc->sc_bar_mappings[bidx].res; 23469152Sjlemon resource_list_add(&pdev->resources, SYS_RES_IOPORT, 0, 23569152Sjlemon rman_get_start(res) + sc->sc_desc->ports[i].offset, 23669152Sjlemon rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1, 23769152Sjlemon 8); 23869152Sjlemon rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 0); 23969152Sjlemon 24069152Sjlemon if (sc->barmuxed == 0) { 24169152Sjlemon rle->res = sc->sc_bar_mappings[bidx].res; 24269152Sjlemon } else { 24369152Sjlemon rle->res = malloc(sizeof(struct resource), M_DEVBUF, 24469152Sjlemon M_WAITOK | M_ZERO); 24569152Sjlemon if (rle->res == NULL) { 24669152Sjlemon free(pdev, M_DEVBUF); 24769152Sjlemon return (ENOMEM); 24869152Sjlemon } 24969152Sjlemon 25069152Sjlemon rle->res->r_start = rman_get_start(res) + 25169152Sjlemon sc->sc_desc->ports[i].offset; 25269152Sjlemon rle->res->r_end = rle->res->r_start + 8 - 1; 25369152Sjlemon rle->res->r_bustag = rman_get_bustag(res); 25469152Sjlemon bus_space_subregion(rle->res->r_bustag, 25569152Sjlemon rman_get_bushandle(res), 25669152Sjlemon sc->sc_desc->ports[i].offset, 8, 25769152Sjlemon &rle->res->r_bushandle); 25869152Sjlemon } 25969152Sjlemon 26069152Sjlemon pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 26169152Sjlemon 26269152Sjlemon childunit = puc_find_free_unit(typestr); 26369152Sjlemon sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 26469152Sjlemon if (sc->sc_ports[i].dev == NULL) { 26569152Sjlemon if (sc->barmuxed) { 26669152Sjlemon bus_space_unmap(rman_get_bustag(rle->res), 26769152Sjlemon rman_get_bushandle(rle->res), 26869152Sjlemon 8); 26969152Sjlemon free(rle->res, M_DEVBUF); 27069152Sjlemon free(pdev, M_DEVBUF); 27169152Sjlemon } 27269152Sjlemon continue; 27369152Sjlemon } 27469152Sjlemon device_set_ivars(sc->sc_ports[i].dev, pdev); 27569152Sjlemon device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 27669152Sjlemon if (!bootverbose) 27769152Sjlemon device_quiet(sc->sc_ports[i].dev); 27869152Sjlemon#ifdef PUC_DEBUG 27969152Sjlemon printf("puc: type %d, bar %x, offset %x\n", 28069152Sjlemon sc->sc_desc->ports[i].type, 28169152Sjlemon sc->sc_desc->ports[i].bar, 28269152Sjlemon sc->sc_desc->ports[i].offset); 28369152Sjlemon puc_print_resource_list(&pdev->resources); 28469152Sjlemon#endif 28569152Sjlemon device_set_flags(sc->sc_ports[i].dev, 28669152Sjlemon sc->sc_desc->ports[i].flags); 28769152Sjlemon if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 28869152Sjlemon if (sc->barmuxed) { 28955205Speter bus_space_unmap(rman_get_bustag(rle->res), 29069152Sjlemon rman_get_bushandle(rle->res), 29169152Sjlemon 8); 29221259Swollman free(rle->res, M_DEVBUF); 29335210Sbde free(pdev, M_DEVBUF); 29469152Sjlemon } 29521259Swollman } 29669152Sjlemon } 29721259Swollman 29869152Sjlemon#ifdef PUC_DEBUG 29969152Sjlemon bootverbose = 0; 30069152Sjlemon#endif 30169152Sjlemon return (0); 30269152Sjlemon} 30369152Sjlemon 30469152Sjlemon/* 30569152Sjlemon * This is just an brute force interrupt handler. It just calls all the 30669152Sjlemon * registered handlers sequencially. 30769152Sjlemon * 30869152Sjlemon * Later on we should maybe have a different handler for boards that can 30969152Sjlemon * tell us which device generated the interrupt. 31069152Sjlemon */ 31169152Sjlemonstatic void 31269152Sjlemonpuc_intr(void *arg) 31386364Sjhb{ 31496173Simp int i; 31569152Sjlemon struct puc_softc *sc; 31621259Swollman 31721259Swollman sc = (struct puc_softc *)arg; 31849459Sbrian for (i = 0; i < PUC_MAX_PORTS; i++) 31949459Sbrian if (sc->sc_ports[i].ihand != NULL) 32049459Sbrian (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 32149459Sbrian} 32249459Sbrian 32349459Sbrianconst struct puc_device_description * 32449459Sbrianpuc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 32555205Speter uint32_t sprod) 32621259Swollman{ 32721259Swollman int i; 32821259Swollman 32921259Swollman#define checkreg(val, index) \ 33021259Swollman (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 33121259Swollman 33221259Swollman for (i = 0; puc_devices[i].name != NULL; i++) { 33321259Swollman if (checkreg(vend, PUC_REG_VEND) && 33421259Swollman checkreg(prod, PUC_REG_PROD) && 33521259Swollman checkreg(svend, PUC_REG_SVEND) && 33621259Swollman checkreg(sprod, PUC_REG_SPROD)) 33721259Swollman return (&puc_devices[i]); 33867334Sjoe } 33921259Swollman 34060938Sjake#undef checkreg 34121259Swollman 34292725Salfred return (NULL); 34321259Swollman} 34447254Spb 34521259Swollmanstatic int 34621259Swollmanpuc_find_free_unit(char *name) 34721259Swollman{ 34821259Swollman devclass_t dc; 34928845Sjulian int start; 35092725Salfred int unit; 351108033Shsu 35221259Swollman unit = 0; 35321259Swollman start = 0; 35421259Swollman while (resource_int_value(name, unit, "port", &start) == 0 && 35553541Sshin start > 0) 35653541Sshin unit++; 35753541Sshin dc = devclass_find(name); 358108033Shsu if (dc == NULL) 359108033Shsu return (-1); 360108033Shsu while (devclass_get_device(dc, unit)) 361108033Shsu unit++; 362108033Shsu#ifdef PUC_DEBUG 363108033Shsu printf("puc: Using %s%d\n", name, unit); 36421404Swollman#endif 36552904Sshin return (unit); 36652904Sshin} 367108470Sschweikh 36853541Sshin#ifdef PUC_DEBUG 36952904Sshinstatic void 37052904Sshinpuc_print_resource_list(struct resource_list *rl) 37152904Sshin{ 37252904Sshin#if 0 37360938Sjake struct resource_list_entry *rle; 37452904Sshin 37552904Sshin printf("print_resource_list: rl %p\n", rl); 37652904Sshin SLIST_FOREACH(rle, rl, link) 37752904Sshin printf(" type %x, rid %x start %x end %x count %x\n", 37852904Sshin rle->type, rle->rid, rle->start, rle->end, rle->count); 37921404Swollman printf("print_resource_list: end.\n"); 38021404Swollman#endif 38121404Swollman} 38221404Swollman#endif 38321404Swollman 38421404Swollmanstruct resource * 38572084Sphkpuc_alloc_resource(device_t dev, device_t child, int type, int *rid, 38621434Swollman u_long start, u_long end, u_long count, u_int flags) 38721434Swollman{ 38821434Swollman struct puc_device *pdev; 38921434Swollman struct resource *retval; 39021434Swollman struct resource_list *rl; 39121404Swollman struct resource_list_entry *rle; 39221404Swollman 39355205Speter pdev = device_get_ivars(child); 394108036Shsu rl = &pdev->resources; 395108036Shsu 396108036Shsu#ifdef PUC_DEBUG 397108036Shsu printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 398108036Shsu pdev, type, *rid); 399108036Shsu puc_print_resource_list(rl); 400108036Shsu#endif 401108036Shsu retval = NULL; 402108036Shsu rle = resource_list_find(rl, type, *rid); 403108036Shsu if (rle) { 40446568Speter start = rle->start; 40521259Swollman end = rle->end; 406108036Shsu count = rle->count; 407108036Shsu#ifdef PUC_DEBUG 408108036Shsu printf("found rle, %lx, %lx, %lx\n", start, end, count); 409108036Shsu#endif 410108036Shsu retval = rle->res; 411108033Shsu } else 412108033Shsu printf("oops rle is gone\n"); 413108172Shsu 414108298Shsu return (retval); 415108298Shsu} 416108172Shsu 417108172Shsuint 418108172Shsupuc_release_resource(device_t dev, device_t child, int type, int rid, 419108172Shsu struct resource *res) 420108172Shsu{ 42183130Sjlemon return (0); 42287914Sjlemon} 42383130Sjlemon 42483130Sjlemonint 42583130Sjlemonpuc_get_resource(device_t dev, device_t child, int type, int rid, 42683130Sjlemon u_long *startp, u_long *countp) 42783130Sjlemon{ 42883130Sjlemon struct puc_device *pdev; 42983130Sjlemon struct resource_list *rl; 43083130Sjlemon struct resource_list_entry *rle; 43121259Swollman 43283130Sjlemon pdev = device_get_ivars(child); 43321259Swollman rl = &pdev->resources; 43471791Speter 43521259Swollman#ifdef PUC_DEBUG 43621259Swollman printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 43792725Salfred type, rid); 43892725Salfred puc_print_resource_list(rl); 43992725Salfred#endif 44092725Salfred rle = resource_list_find(rl, type, rid); 44192725Salfred if (rle) { 44292725Salfred#ifdef PUC_DEBUG 443103900Sbrooks printf("found rle %p,", rle); 44492725Salfred#endif 44592725Salfred if (startp != NULL) 44692725Salfred *startp = rle->start; 44792725Salfred if (countp != NULL) 44892725Salfred *countp = rle->count; 44992725Salfred#ifdef PUC_DEBUG 45092725Salfred printf(" %lx, %lx\n", rle->start, rle->count); 45192725Salfred#endif 45292725Salfred return (0); 45321259Swollman } else 45492725Salfred printf("oops rle is gone\n"); 45592725Salfred return (ENXIO); 45692725Salfred} 45792725Salfred 45892725Salfredint 45992725Salfredpuc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 46021259Swollman void (*ihand)(void *), void *arg, void **cookiep) 46192725Salfred{ 46292725Salfred int i; 46392725Salfred struct puc_softc *sc; 46492725Salfred 46592725Salfred sc = (struct puc_softc *)device_get_softc(dev); 46621259Swollman if ((flags & INTR_FAST) != sc->fastintr) 46792725Salfred return (ENXIO); 46892725Salfred for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 46921434Swollman if (sc->sc_ports[i].dev == child) { 47092725Salfred if (sc->sc_ports[i].ihand != 0) 47192725Salfred return (ENXIO); 47279103Sbrooks sc->sc_ports[i].ihand = ihand; 47392725Salfred sc->sc_ports[i].ihandarg = arg; 47492725Salfred *cookiep = arg; 47579103Sbrooks return (0); 47684931Sfjoe } 47784931Sfjoe } 47884931Sfjoe return (ENXIO); 47987902Sluigi} 48087902Sluigi 48187902Sluigiint 48292725Salfredpuc_teardown_intr(device_t dev, device_t child, struct resource *r, 48392725Salfred void *cookie) 48492725Salfred{ 48587902Sluigi int i; 48687902Sluigi struct puc_softc *sc; 48755205Speter 48821259Swollman sc = (struct puc_softc *)device_get_softc(dev); 48921259Swollman for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 490 if (sc->sc_ports[i].dev == child) { 491 sc->sc_ports[i].ihand = NULL; 492 sc->sc_ports[i].ihandarg = NULL; 493 return (0); 494 } 495 } 496 return (ENXIO); 497} 498 499int 500puc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 501{ 502 struct puc_device *pdev; 503 504 pdev = device_get_ivars(child); 505 if (pdev == NULL) 506 return (ENOENT); 507 508 switch(index) { 509 case PUC_IVAR_FREQ: 510 *result = pdev->serialfreq; 511 break; 512 default: 513 return (ENOENT); 514 } 515 return (0); 516} 517