puc.c revision 112270
190731Sjhay/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 2158124Smarcel 3158124Smarcel/*- 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: 36158124Smarcel * 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 44102714Sphk * for the NetBSD Project. 45158124Smarcel * 4. The name of the author may not be used to endorse or promote products 46158124Smarcel * derived from this software without specific prior written permission 47160030Sobrien * 4890731Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 49158124Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5090731Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 51158124Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 52158124Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53158124Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 54158124Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55158124Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56158124Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 57158124Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58158124Smarcel */ 5990731Sjhay 60158124Smarcel#include <sys/cdefs.h> 6190731Sjhay__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 112270 2003-03-15 16:25:40Z sobomax $"); 62158124Smarcel 63158124Smarcel/* 64158124Smarcel * PCI "universal" communication card device driver, glues com, lpt, 65158124Smarcel * and similar ports to PCI via bridge chip often much larger than 66158124Smarcel * the devices being glued. 67158124Smarcel * 68158124Smarcel * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 69102893Sphk * sys/dev/pci/pciide.c, revision 1.6). 70158124Smarcel * 71102893Sphk * These devices could be (and some times are) described as 72158124Smarcel * communications/{serial,parallel}, etc. devices with known 73158124Smarcel * programming interfaces, but those programming interfaces (in 74158124Smarcel * particular the BAR assignments for devices, etc.) in fact are not 75158124Smarcel * particularly well defined. 76102734Sphk * 77158124Smarcel * After I/we have seen more of these devices, it may be possible 78158124Smarcel * to generalize some of these bits. In particular, devices which 79158124Smarcel * describe themselves as communications/serial/16[45]50, and 80158124Smarcel * communications/parallel/??? might be attached via direct 81102734Sphk * 'com' and 'lpt' attachments to pci. 82158124Smarcel */ 83158124Smarcel 84158124Smarcel#include "opt_puc.h" 85158124Smarcel 86158124Smarcel#include <sys/param.h> 87158124Smarcel#include <sys/systm.h> 88158124Smarcel#include <sys/kernel.h> 89158124Smarcel#include <sys/bus.h> 90158124Smarcel#include <sys/conf.h> 91158124Smarcel#include <sys/malloc.h> 92158124Smarcel 93158124Smarcel#include <machine/bus.h> 94158124Smarcel#include <machine/resource.h> 95158124Smarcel#include <sys/rman.h> 96158124Smarcel 97158124Smarcel#include <dev/pci/pcireg.h> 98158124Smarcel#include <dev/pci/pcivar.h> 99158124Smarcel 100158124Smarcel#define PUC_ENTRAILS 1 101158124Smarcel#include <dev/puc/pucvar.h> 102158124Smarcel 103158124Smarcelstruct puc_device { 104158124Smarcel struct resource_list resources; 105158124Smarcel u_int serialfreq; 106158124Smarcel}; 107158124Smarcel 108158124Smarcelstatic void puc_intr(void *arg); 109158124Smarcel 110102734Sphkstatic int puc_find_free_unit(char *); 111158124Smarcel#ifdef PUC_DEBUG 112158124Smarcelstatic void puc_print_resource_list(struct resource_list *); 113158124Smarcel#endif 114158124Smarcel 115158124Smarceldevclass_t puc_devclass; 116158124Smarcel 117158124Smarcelstatic int 118158124Smarcelpuc_port_bar_index(struct puc_softc *sc, int bar) 119158124Smarcel{ 120158124Smarcel int i; 121158124Smarcel 122158124Smarcel for (i = 0; i < PUC_MAX_BAR; i += 1) { 123142502Ssam if (!sc->sc_bar_mappings[i].used) 124158124Smarcel break; 125158124Smarcel if (sc->sc_bar_mappings[i].bar == bar) 126102734Sphk return (i); 127102734Sphk } 128158124Smarcel sc->sc_bar_mappings[i].bar = bar; 129158124Smarcel sc->sc_bar_mappings[i].used = 1; 130112270Ssobomax return (i); 131158124Smarcel} 132158124Smarcel 133158124Smarcelstatic int 134158124Smarcelpuc_probe_ilr(struct puc_softc *sc, struct resource *res) 135158124Smarcel{ 136112270Ssobomax u_char t1, t2; 137158124Smarcel int i; 138158124Smarcel 139158124Smarcel switch (sc->sc_desc->ilr_type) { 140158124Smarcel case PUC_ILR_TYPE_DIGI: 141158124Smarcel sc->ilr_st = rman_get_bustag(res); 142158124Smarcel sc->ilr_sh = rman_get_bushandle(res); 143158124Smarcel for (i = 0; i < 2; i++) { 144112270Ssobomax t1 = bus_space_read_1(sc->ilr_st, sc->ilr_sh, 145158124Smarcel sc->sc_desc->ilr_offset[i]); 146158124Smarcel t1 = ~t1; 147158124Smarcel bus_space_write_1(sc->ilr_st, sc->ilr_sh, 148158124Smarcel sc->sc_desc->ilr_offset[i], t1); 149158124Smarcel t2 = bus_space_read_1(sc->ilr_st, sc->ilr_sh, 150158124Smarcel sc->sc_desc->ilr_offset[i]); 151158124Smarcel if (t2 == t1) 152158124Smarcel return (0); 153158124Smarcel } 154158124Smarcel return (1); 155158124Smarcel 156112270Ssobomax default: 157158124Smarcel break; 158158124Smarcel } 159158124Smarcel return (0); 160158124Smarcel} 161158124Smarcel 162158124Smarcelint 163158124Smarcelpuc_attach(device_t dev, const struct puc_device_description *desc) 164158124Smarcel{ 165158124Smarcel char *typestr; 166112270Ssobomax int bidx, childunit, i, irq_setup, rid, type; 167158124Smarcel struct puc_softc *sc; 168158124Smarcel struct puc_device *pdev; 169158124Smarcel struct resource *res; 170158124Smarcel struct resource_list_entry *rle; 171158124Smarcel 172158124Smarcel sc = (struct puc_softc *)device_get_softc(dev); 173158124Smarcel bzero(sc, sizeof(*sc)); 174158124Smarcel sc->sc_desc = desc; 175158124Smarcel if (sc->sc_desc == NULL) 176158124Smarcel return (ENXIO); 177158124Smarcel 178158124Smarcel#ifdef PUC_DEBUG 179158124Smarcel bootverbose = 1; 180158124Smarcel 181158124Smarcel printf("puc: name: %s\n", sc->sc_desc->name); 182158124Smarcel#endif 183158124Smarcel rid = 0; 184158124Smarcel res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 185158124Smarcel RF_ACTIVE | RF_SHAREABLE); 186158124Smarcel if (!res) 187112270Ssobomax return (ENXIO); 188112270Ssobomax 189102714Sphk sc->irqres = res; 190158124Smarcel sc->irqrid = rid; 19190731Sjhay#ifdef PUC_FASTINTR 192158124Smarcel irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 193158124Smarcel INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 194158124Smarcel if (irq_setup == 0) 19590731Sjhay sc->fastintr = INTR_FAST; 196158124Smarcel else 197158124Smarcel irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 198158124Smarcel INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 199158124Smarcel#else 200158124Smarcel irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 201158124Smarcel INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 202158124Smarcel#endif 20390731Sjhay if (irq_setup != 0) 204158124Smarcel return (ENXIO); 205119814Smarcel 206158124Smarcel rid = 0; 207158124Smarcel for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 20890731Sjhay if (i > 0 && rid == sc->sc_desc->ports[i].bar) 209158124Smarcel sc->barmuxed = 1; 210158124Smarcel rid = sc->sc_desc->ports[i].bar; 211158124Smarcel bidx = puc_port_bar_index(sc, rid); 212158124Smarcel 213158124Smarcel if (sc->sc_bar_mappings[bidx].res != NULL) 214158124Smarcel continue; 215158124Smarcel 216158124Smarcel type = (sc->sc_desc->ports[i].flags & PUC_FLAGS_MEMORY) 217158124Smarcel ? SYS_RES_MEMORY : SYS_RES_IOPORT; 218158124Smarcel 219158124Smarcel res = bus_alloc_resource(dev, type, &rid, 0ul, ~0ul, 1, 220158124Smarcel RF_ACTIVE); 221158124Smarcel if (res == NULL) { 222158124Smarcel printf("could not get resource\n"); 223158124Smarcel continue; 224158124Smarcel } 225158124Smarcel sc->sc_bar_mappings[bidx].type = type; 22690731Sjhay sc->sc_bar_mappings[bidx].res = res; 227158124Smarcel 228158124Smarcel if (sc->sc_desc->ilr_type != PUC_ILR_TYPE_NONE) { 229158124Smarcel sc->ilr_enabled = puc_probe_ilr(sc, res); 230158124Smarcel if (sc->ilr_enabled) 231158124Smarcel device_printf(dev, "ILR enabled\n"); 232158124Smarcel else 233158124Smarcel device_printf(dev, "ILR disabled\n"); 234158124Smarcel } 235158124Smarcel#ifdef PUC_DEBUG 23690731Sjhay printf("%s rid %d bst %x, start %x, end %x\n", 237158124Smarcel (type == SYS_RES_MEMORY) ? "memory" : "port", rid, 238158124Smarcel (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 239158124Smarcel (u_int)rman_get_end(res)); 240158124Smarcel#endif 241158124Smarcel } 24290731Sjhay 243158124Smarcel if (desc->init != NULL) { 244158124Smarcel i = desc->init(sc); 245158124Smarcel if (i != 0) 24690731Sjhay return (i); 247158124Smarcel } 248158124Smarcel 249158124Smarcel for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 250109458Smarcel rid = sc->sc_desc->ports[i].bar; 251158124Smarcel bidx = puc_port_bar_index(sc, rid); 252158124Smarcel if (sc->sc_bar_mappings[bidx].res == NULL) 253158124Smarcel continue; 254158124Smarcel 255158124Smarcel switch (sc->sc_desc->ports[i].type) { 256158124Smarcel case PUC_PORT_TYPE_COM: 257158124Smarcel typestr = "sio"; 258158124Smarcel break; 259158124Smarcel default: 260158124Smarcel continue; 261158124Smarcel } 262158124Smarcel pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 263158124Smarcel M_NOWAIT | M_ZERO); 264158124Smarcel if (!pdev) 265119814Smarcel continue; 266158124Smarcel resource_list_init(&pdev->resources); 267158124Smarcel 268158124Smarcel /* First fake up an IRQ resource. */ 269158124Smarcel resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 270158124Smarcel rman_get_start(sc->irqres), rman_get_end(sc->irqres), 271158124Smarcel rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 272158124Smarcel rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 273158124Smarcel rle->res = sc->irqres; 274158124Smarcel 275158124Smarcel /* Now fake an IOPORT or MEMORY resource */ 276158124Smarcel res = sc->sc_bar_mappings[bidx].res; 277158124Smarcel type = sc->sc_bar_mappings[bidx].type; 278158124Smarcel resource_list_add(&pdev->resources, type, 0, 279158124Smarcel rman_get_start(res) + sc->sc_desc->ports[i].offset, 280158124Smarcel rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1, 281158124Smarcel 8); 282158124Smarcel rle = resource_list_find(&pdev->resources, type, 0); 283158124Smarcel 284158124Smarcel if (sc->barmuxed == 0) { 285158124Smarcel rle->res = sc->sc_bar_mappings[bidx].res; 28690731Sjhay } else { 287158124Smarcel rle->res = malloc(sizeof(struct resource), M_DEVBUF, 288158124Smarcel M_WAITOK | M_ZERO); 289158124Smarcel if (rle->res == NULL) { 290158124Smarcel free(pdev, M_DEVBUF); 291158124Smarcel return (ENOMEM); 292112270Ssobomax } 293158124Smarcel 294158124Smarcel rle->res->r_start = rman_get_start(res) + 295158124Smarcel sc->sc_desc->ports[i].offset; 296158124Smarcel rle->res->r_end = rle->res->r_start + 8 - 1; 29790731Sjhay rle->res->r_bustag = rman_get_bustag(res); 298158124Smarcel bus_space_subregion(rle->res->r_bustag, 299158124Smarcel rman_get_bushandle(res), 300158124Smarcel sc->sc_desc->ports[i].offset, 8, 301102734Sphk &rle->res->r_bushandle); 30290731Sjhay } 303158124Smarcel 304158124Smarcel pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 305158124Smarcel 306158124Smarcel childunit = puc_find_free_unit(typestr); 307158124Smarcel sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 308158124Smarcel if (sc->sc_ports[i].dev == NULL) { 30990731Sjhay if (sc->barmuxed) { 310158124Smarcel bus_space_unmap(rman_get_bustag(rle->res), 311158124Smarcel rman_get_bushandle(rle->res), 8); 312158124Smarcel free(rle->res, M_DEVBUF); 313158124Smarcel free(pdev, M_DEVBUF); 314158124Smarcel } 315158124Smarcel continue; 316158124Smarcel } 317158124Smarcel device_set_ivars(sc->sc_ports[i].dev, pdev); 318158124Smarcel device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 319158124Smarcel if (!bootverbose) 320158124Smarcel device_quiet(sc->sc_ports[i].dev); 321158124Smarcel#ifdef PUC_DEBUG 32290731Sjhay printf("puc: type %d, bar %x, offset %x\n", 323158124Smarcel sc->sc_desc->ports[i].type, 324158124Smarcel sc->sc_desc->ports[i].bar, 325158124Smarcel sc->sc_desc->ports[i].offset); 326158124Smarcel puc_print_resource_list(&pdev->resources); 327158124Smarcel#endif 32890731Sjhay device_set_flags(sc->sc_ports[i].dev, 329158124Smarcel sc->sc_desc->ports[i].flags); 330158124Smarcel if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 331158124Smarcel if (sc->barmuxed) { 332158124Smarcel bus_space_unmap(rman_get_bustag(rle->res), 333158124Smarcel rman_get_bushandle(rle->res), 33490731Sjhay 8); 335158124Smarcel free(rle->res, M_DEVBUF); 336158124Smarcel free(pdev, M_DEVBUF); 337158124Smarcel } 338158124Smarcel } 33990731Sjhay } 340158124Smarcel 341158124Smarcel#ifdef PUC_DEBUG 342158124Smarcel bootverbose = 0; 343158124Smarcel#endif 34490925Snyan return (0); 34590731Sjhay} 34690731Sjhay 347158124Smarcelstatic u_int32_t 348158124Smarcelpuc_ilr_read(struct puc_softc *sc) 349158124Smarcel{ 350158124Smarcel u_int32_t mask; 351158124Smarcel int i; 352158124Smarcel 353158124Smarcel mask = 0; 35490731Sjhay switch (sc->sc_desc->ilr_type) { 355158124Smarcel case PUC_ILR_TYPE_DIGI: 356158124Smarcel for (i = 1; i >= 0; i--) { 357158124Smarcel mask = (mask << 8) | (bus_space_read_1(sc->ilr_st, 358158124Smarcel sc->ilr_sh, sc->sc_desc->ilr_offset[i]) & 0xff); 359158124Smarcel } 360158124Smarcel break; 361158124Smarcel 362158124Smarcel default: 363158124Smarcel mask = 0xffffffff; 364158124Smarcel break; 365158124Smarcel } 366158124Smarcel return (mask); 367158124Smarcel} 368158124Smarcel 369158124Smarcel/* 370158124Smarcel * This is an interrupt handler. For boards that can't tell us which 371158124Smarcel * device generated the interrupt it just calls all the registered 372158124Smarcel * handlers sequencially, but for boards that can tell us which 373158124Smarcel * device(s) generated the interrupt it calls only handlers for devices 374158124Smarcel * that actually generated the interrupt. 375158124Smarcel */ 376158124Smarcelstatic void 377158124Smarcelpuc_intr(void *arg) 378158124Smarcel{ 379158124Smarcel int i; 38090731Sjhay u_int32_t ilr_mask; 38190731Sjhay struct puc_softc *sc; 382158124Smarcel 383158124Smarcel sc = (struct puc_softc *)arg; 384112270Ssobomax ilr_mask = sc->ilr_enabled ? puc_ilr_read(sc) : 0xffffffff; 385158124Smarcel for (i = 0; i < PUC_MAX_PORTS; i++) 386158124Smarcel if (sc->sc_ports[i].ihand != NULL && 387158124Smarcel ((ilr_mask >> i) & 0x00000001)) 388158124Smarcel (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 389112270Ssobomax} 390158124Smarcel 391112270Ssobomaxconst struct puc_device_description * 392158124Smarcelpuc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 393158124Smarcel uint32_t sprod) 394158124Smarcel{ 395158124Smarcel int i; 396158124Smarcel 397158124Smarcel#define checkreg(val, index) \ 398158124Smarcel (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 399158124Smarcel 400158124Smarcel for (i = 0; puc_devices[i].name != NULL; i++) { 401158124Smarcel if (checkreg(vend, PUC_REG_VEND) && 402158124Smarcel checkreg(prod, PUC_REG_PROD) && 403158124Smarcel checkreg(svend, PUC_REG_SVEND) && 404158124Smarcel checkreg(sprod, PUC_REG_SPROD)) 405158124Smarcel return (&puc_devices[i]); 406112270Ssobomax } 407158124Smarcel 408158124Smarcel#undef checkreg 409112270Ssobomax 410158124Smarcel return (NULL); 411158124Smarcel} 412158124Smarcel 41390731Sjhaystatic int 414158124Smarcelpuc_find_free_unit(char *name) 415158124Smarcel{ 416158124Smarcel devclass_t dc; 417158124Smarcel int start; 418158124Smarcel int unit; 419158124Smarcel 420158124Smarcel unit = 0; 421158124Smarcel start = 0; 422158124Smarcel while (resource_int_value(name, unit, "port", &start) == 0 && 423158124Smarcel start > 0) 424158124Smarcel unit++; 425158124Smarcel dc = devclass_find(name); 426158124Smarcel if (dc == NULL) 427158124Smarcel return (-1); 428158124Smarcel while (devclass_get_device(dc, unit)) 42990731Sjhay unit++; 43090731Sjhay#ifdef PUC_DEBUG 431158124Smarcel printf("puc: Using %s%d\n", name, unit); 432158124Smarcel#endif 43390731Sjhay return (unit); 434158124Smarcel} 435158124Smarcel 436158124Smarcel#ifdef PUC_DEBUG 43790731Sjhaystatic void 438158124Smarcelpuc_print_resource_list(struct resource_list *rl) 439158124Smarcel{ 440158124Smarcel#if 0 44190731Sjhay struct resource_list_entry *rle; 442158124Smarcel 443158124Smarcel printf("print_resource_list: rl %p\n", rl); 444158124Smarcel SLIST_FOREACH(rle, rl, link) 445158124Smarcel printf(" type %x, rid %x start %x end %x count %x\n", 446158124Smarcel rle->type, rle->rid, rle->start, rle->end, rle->count); 447158124Smarcel printf("print_resource_list: end.\n"); 448158124Smarcel#endif 449158124Smarcel} 450158124Smarcel#endif 451158124Smarcel 452158124Smarcelstruct resource * 453158124Smarcelpuc_alloc_resource(device_t dev, device_t child, int type, int *rid, 45490731Sjhay u_long start, u_long end, u_long count, u_int flags) 45590731Sjhay{ 456102714Sphk struct puc_device *pdev; 457158124Smarcel struct resource *retval; 45890731Sjhay struct resource_list *rl; 45990731Sjhay struct resource_list_entry *rle; 460158124Smarcel 461158124Smarcel pdev = device_get_ivars(child); 462158124Smarcel rl = &pdev->resources; 463158124Smarcel 46490731Sjhay#ifdef PUC_DEBUG 465158124Smarcel printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 466158124Smarcel pdev, type, *rid); 467158124Smarcel puc_print_resource_list(rl); 468158124Smarcel#endif 469158124Smarcel retval = NULL; 470158124Smarcel rle = resource_list_find(rl, type, *rid); 471118292Sambrisko if (rle) { 472158124Smarcel start = rle->start; 473158124Smarcel end = rle->end; 47490731Sjhay count = rle->count; 475158124Smarcel#ifdef PUC_DEBUG 476158124Smarcel printf("found rle, %lx, %lx, %lx\n", start, end, count); 477158124Smarcel#endif 478158124Smarcel retval = rle->res; 479158124Smarcel } else 480158124Smarcel printf("oops rle is gone\n"); 481158124Smarcel 482158124Smarcel return (retval); 483158124Smarcel} 484158124Smarcel 485158124Smarcelint 486118292Sambriskopuc_release_resource(device_t dev, device_t child, int type, int rid, 487158124Smarcel struct resource *res) 48890731Sjhay{ 489158124Smarcel return (0); 490158124Smarcel} 491158124Smarcel 492158124Smarcelint 493158124Smarcelpuc_get_resource(device_t dev, device_t child, int type, int rid, 494158124Smarcel u_long *startp, u_long *countp) 495158124Smarcel{ 496158124Smarcel struct puc_device *pdev; 497158124Smarcel struct resource_list *rl; 498158124Smarcel struct resource_list_entry *rle; 499158124Smarcel 500158124Smarcel pdev = device_get_ivars(child); 501158124Smarcel rl = &pdev->resources; 502158124Smarcel 503158124Smarcel#ifdef PUC_DEBUG 504158124Smarcel printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 505158124Smarcel type, rid); 506158124Smarcel puc_print_resource_list(rl); 507158124Smarcel#endif 50890731Sjhay rle = resource_list_find(rl, type, rid); 50990731Sjhay if (rle) { 510102714Sphk#ifdef PUC_DEBUG 511158124Smarcel printf("found rle %p,", rle); 51290731Sjhay#endif 51390731Sjhay if (startp != NULL) 514158124Smarcel *startp = rle->start; 515158124Smarcel if (countp != NULL) 516158124Smarcel *countp = rle->count; 517158124Smarcel#ifdef PUC_DEBUG 518158124Smarcel printf(" %lx, %lx\n", rle->start, rle->count); 519158124Smarcel#endif 520158124Smarcel return (0); 521158124Smarcel } else 522158124Smarcel printf("oops rle is gone\n"); 523158124Smarcel return (ENXIO); 524158124Smarcel} 525158124Smarcel 526158124Smarcelint 527158124Smarcelpuc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 528158124Smarcel void (*ihand)(void *), void *arg, void **cookiep) 529158124Smarcel{ 530158124Smarcel int i; 531158124Smarcel struct puc_softc *sc; 532158124Smarcel 533158124Smarcel sc = (struct puc_softc *)device_get_softc(dev); 534158124Smarcel if ((flags & INTR_FAST) != sc->fastintr) 535158124Smarcel return (ENXIO); 536158124Smarcel for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 537158124Smarcel if (sc->sc_ports[i].dev == child) { 538158124Smarcel if (sc->sc_ports[i].ihand != 0) 539158124Smarcel return (ENXIO); 540158124Smarcel sc->sc_ports[i].ihand = ihand; 541158124Smarcel sc->sc_ports[i].ihandarg = arg; 542158124Smarcel *cookiep = arg; 543158124Smarcel return (0); 544158124Smarcel } 545158124Smarcel } 54690731Sjhay return (ENXIO); 54790731Sjhay} 54890731Sjhay 549102714Sphkint 550158124Smarcelpuc_teardown_intr(device_t dev, device_t child, struct resource *r, 55190731Sjhay void *cookie) 55290731Sjhay{ 553158124Smarcel int i; 554158124Smarcel struct puc_softc *sc; 555158124Smarcel 55690731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 557158124Smarcel for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 558158124Smarcel if (sc->sc_ports[i].dev == child) { 559158124Smarcel sc->sc_ports[i].ihand = NULL; 560158124Smarcel sc->sc_ports[i].ihandarg = NULL; 561158124Smarcel return (0); 56290731Sjhay } 563158124Smarcel } 564158124Smarcel return (ENXIO); 565158124Smarcel} 566158124Smarcel 567158124Smarcelint 568158124Smarcelpuc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 569158124Smarcel{ 570158124Smarcel struct puc_device *pdev; 571158124Smarcel 572158124Smarcel pdev = device_get_ivars(child); 573158124Smarcel if (pdev == NULL) 574158124Smarcel return (ENOENT); 575158124Smarcel 576158124Smarcel switch(index) { 577158124Smarcel case PUC_IVAR_FREQ: 578158124Smarcel *result = pdev->serialfreq; 579158124Smarcel break; 580158124Smarcel default: 581158124Smarcel return (ENOENT); 58290731Sjhay } 58390731Sjhay return (0); 584102714Sphk} 585158124Smarcel