puc.c revision 114344
1189747Ssam/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 2217751Sadrian 3189747Ssam/*- 4189747Ssam * Copyright (c) 2002 JF Hay. All rights reserved. 5189747Ssam * Copyright (c) 2000 M. Warner Losh. All rights reserved. 6189747Ssam * 7189747Ssam * Redistribution and use in source and binary forms, with or without 8189747Ssam * modification, are permitted provided that the following conditions 9189747Ssam * are met: 10189747Ssam * 1. Redistributions of source code must retain the above copyright 11189747Ssam * notice unmodified, this list of conditions, and the following 12189747Ssam * disclaimer. 13189747Ssam * 2. Redistributions in binary form must reproduce the above copyright 14189747Ssam * notice, this list of conditions and the following disclaimer in the 15189747Ssam * documentation and/or other materials provided with the distribution. 16189747Ssam * 17189747Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18189747Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19189747Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20189747Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21189747Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22189747Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23189747Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24189747Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25189747Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26189747Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27217751Sadrian */ 28217751Sadrian 29189747Ssam/* 30189747Ssam * Copyright (c) 1996, 1998, 1999 31189747Ssam * Christopher G. Demetriou. All rights reserved. 32217751Sadrian * 33189747Ssam * Redistribution and use in source and binary forms, with or without 34189747Ssam * modification, are permitted provided that the following conditions 35189747Ssam * are met: 36189747Ssam * 1. Redistributions of source code must retain the above copyright 37189747Ssam * notice, this list of conditions and the following disclaimer. 38217751Sadrian * 2. Redistributions in binary form must reproduce the above copyright 39189747Ssam * notice, this list of conditions and the following disclaimer in the 40217751Sadrian * documentation and/or other materials provided with the distribution. 41189747Ssam * 3. All advertising materials mentioning features or use of this software 42189747Ssam * must display the following acknowledgement: 43189747Ssam * This product includes software developed by Christopher G. Demetriou 44189747Ssam * for the NetBSD Project. 45189747Ssam * 4. The name of the author may not be used to endorse or promote products 46217751Sadrian * derived from this software without specific prior written permission 47189747Ssam * 48189747Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 49189747Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 50189747Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 51189747Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 52217751Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53189747Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 54189747Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55189747Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56189747Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 57189747Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58189747Ssam */ 59189747Ssam 60189747Ssam#include <sys/cdefs.h> 61217751Sadrian__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 114344 2003-04-30 22:15:47Z sobomax $"); 62189747Ssam 63189747Ssam/* 64217751Sadrian * PCI "universal" communication card device driver, glues com, lpt, 65189747Ssam * and similar ports to PCI via bridge chip often much larger than 66189747Ssam * the devices being glued. 67189747Ssam * 68189747Ssam * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 69189747Ssam * sys/dev/pci/pciide.c, revision 1.6). 70217751Sadrian * 71189747Ssam * These devices could be (and some times are) described as 72189747Ssam * communications/{serial,parallel}, etc. devices with known 73189747Ssam * programming interfaces, but those programming interfaces (in 74189747Ssam * particular the BAR assignments for devices, etc.) in fact are not 75189747Ssam * particularly well defined. 76189747Ssam * 77189747Ssam * After I/we have seen more of these devices, it may be possible 78189747Ssam * to generalize some of these bits. In particular, devices which 79189747Ssam * describe themselves as communications/serial/16[45]50, and 80189747Ssam * communications/parallel/??? might be attached via direct 81189747Ssam * 'com' and 'lpt' attachments to pci. 82189747Ssam */ 83189747Ssam 84189747Ssam#include "opt_puc.h" 85189747Ssam 86189747Ssam#include <sys/param.h> 87189747Ssam#include <sys/systm.h> 88189747Ssam#include <sys/kernel.h> 89189747Ssam#include <sys/bus.h> 90189747Ssam#include <sys/conf.h> 91189747Ssam#include <sys/malloc.h> 92189747Ssam 93189747Ssam#include <machine/bus.h> 94189747Ssam#include <machine/resource.h> 95189747Ssam#include <sys/rman.h> 96189747Ssam 97189747Ssam#include <dev/pci/pcireg.h> 98189747Ssam#include <dev/pci/pcivar.h> 99189747Ssam 100189747Ssam#define PUC_ENTRAILS 1 101189747Ssam#include <dev/puc/pucvar.h> 102189747Ssam 103189747Ssamstruct puc_device { 104189747Ssam struct resource_list resources; 105189747Ssam u_int serialfreq; 106189747Ssam}; 107189747Ssam 108189747Ssamstatic void puc_intr(void *arg); 109189747Ssam 110189747Ssamstatic int puc_find_free_unit(char *); 111189747Ssam#ifdef PUC_DEBUG 112189747Ssamstatic void puc_print_resource_list(struct resource_list *); 113189747Ssam#endif 114189747Ssam 115189747Ssamdevclass_t puc_devclass; 116189747Ssam 117189747Ssamstatic int 118189747Ssampuc_port_bar_index(struct puc_softc *sc, int bar) 119189747Ssam{ 120189747Ssam int i; 121189747Ssam 122189747Ssam for (i = 0; i < PUC_MAX_BAR; i += 1) { 123189747Ssam if (!sc->sc_bar_mappings[i].used) 124189747Ssam break; 125189747Ssam if (sc->sc_bar_mappings[i].bar == bar) 126189747Ssam return (i); 127189747Ssam } 128189747Ssam sc->sc_bar_mappings[i].bar = bar; 129189747Ssam sc->sc_bar_mappings[i].used = 1; 130189747Ssam return (i); 131189747Ssam} 132189747Ssam 133189747Ssamstatic int 134189747Ssampuc_probe_ilr(struct puc_softc *sc, struct resource *res) 135189747Ssam{ 136189747Ssam u_char t1, t2; 137189747Ssam int i; 138189747Ssam 139189747Ssam switch (sc->sc_desc->ilr_type) { 140189747Ssam case PUC_ILR_TYPE_DIGI: 141189747Ssam sc->ilr_st = rman_get_bustag(res); 142189747Ssam sc->ilr_sh = rman_get_bushandle(res); 143189747Ssam for (i = 0; i < 2 && sc->sc_desc->ilr_offset[i] != 0; i++) { 144189747Ssam t1 = bus_space_read_1(sc->ilr_st, sc->ilr_sh, 145189747Ssam sc->sc_desc->ilr_offset[i]); 146189747Ssam t1 = ~t1; 147189747Ssam bus_space_write_1(sc->ilr_st, sc->ilr_sh, 148189747Ssam sc->sc_desc->ilr_offset[i], t1); 149189747Ssam t2 = bus_space_read_1(sc->ilr_st, sc->ilr_sh, 150189747Ssam sc->sc_desc->ilr_offset[i]); 151189747Ssam if (t2 == t1) 152189747Ssam return (0); 153189747Ssam } 154189747Ssam return (1); 155189747Ssam 156189747Ssam default: 157189747Ssam break; 158189747Ssam } 159189747Ssam return (0); 160189747Ssam} 161189747Ssam 162189747Ssamint 163189747Ssampuc_attach(device_t dev, const struct puc_device_description *desc) 164189747Ssam{ 165189747Ssam char *typestr; 166189747Ssam int bidx, childunit, i, irq_setup, rid, type; 167189747Ssam struct puc_softc *sc; 168189747Ssam struct puc_device *pdev; 169189747Ssam struct resource *res; 170189747Ssam struct resource_list_entry *rle; 171189747Ssam 172189747Ssam sc = (struct puc_softc *)device_get_softc(dev); 173189747Ssam bzero(sc, sizeof(*sc)); 174189747Ssam sc->sc_desc = desc; 175189747Ssam if (sc->sc_desc == NULL) 176189747Ssam return (ENXIO); 177189747Ssam 178189747Ssam#ifdef PUC_DEBUG 179189747Ssam bootverbose = 1; 180189747Ssam 181189747Ssam printf("puc: name: %s\n", sc->sc_desc->name); 182189747Ssam#endif 183189747Ssam rid = 0; 184189747Ssam res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 185189747Ssam RF_ACTIVE | RF_SHAREABLE); 186189747Ssam if (!res) 187189747Ssam return (ENXIO); 188189747Ssam 189189747Ssam sc->irqres = res; 190189747Ssam sc->irqrid = rid; 191189747Ssam#ifdef PUC_FASTINTR 192189747Ssam irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 193189747Ssam INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 194189747Ssam if (irq_setup == 0) 195189747Ssam sc->fastintr = INTR_FAST; 196189747Ssam else 197189747Ssam irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 198189747Ssam INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 199189747Ssam#else 200189747Ssam irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 201189747Ssam INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 202189747Ssam#endif 203189747Ssam if (irq_setup != 0) 204189747Ssam return (ENXIO); 205189747Ssam 206189747Ssam rid = 0; 207189747Ssam for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 208189747Ssam if (i > 0 && rid == sc->sc_desc->ports[i].bar) 209189747Ssam sc->barmuxed = 1; 210189747Ssam rid = sc->sc_desc->ports[i].bar; 211189747Ssam bidx = puc_port_bar_index(sc, rid); 212189747Ssam 213189747Ssam if (sc->sc_bar_mappings[bidx].res != NULL) 214189747Ssam continue; 215189747Ssam 216189747Ssam type = (sc->sc_desc->ports[i].flags & PUC_FLAGS_MEMORY) 217189747Ssam ? SYS_RES_MEMORY : SYS_RES_IOPORT; 218189747Ssam 219189747Ssam res = bus_alloc_resource(dev, type, &rid, 0ul, ~0ul, 1, 220189747Ssam RF_ACTIVE); 221189747Ssam if (res == NULL) { 222189747Ssam printf("could not get resource\n"); 223189747Ssam continue; 224189747Ssam } 225189747Ssam sc->sc_bar_mappings[bidx].type = type; 226189747Ssam sc->sc_bar_mappings[bidx].res = res; 227189747Ssam 228189747Ssam if (sc->sc_desc->ilr_type != PUC_ILR_TYPE_NONE) { 229189747Ssam sc->ilr_enabled = puc_probe_ilr(sc, res); 230189747Ssam if (sc->ilr_enabled) 231189747Ssam device_printf(dev, "ILR enabled\n"); 232189747Ssam else 233189747Ssam device_printf(dev, "ILR disabled\n"); 234189747Ssam } 235189747Ssam#ifdef PUC_DEBUG 236189747Ssam printf("%s rid %d bst %x, start %x, end %x\n", 237189747Ssam (type == SYS_RES_MEMORY) ? "memory" : "port", rid, 238189747Ssam (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 239189747Ssam (u_int)rman_get_end(res)); 240189747Ssam#endif 241217751Sadrian } 242189747Ssam 243189747Ssam if (desc->init != NULL) { 244189747Ssam i = desc->init(sc); 245189747Ssam if (i != 0) 246189747Ssam return (i); 247189747Ssam } 248189747Ssam 249189747Ssam for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 250189747Ssam rid = sc->sc_desc->ports[i].bar; 251189747Ssam bidx = puc_port_bar_index(sc, rid); 252189747Ssam if (sc->sc_bar_mappings[bidx].res == NULL) 253189747Ssam continue; 254189747Ssam 255189747Ssam switch (sc->sc_desc->ports[i].type) { 256189747Ssam case PUC_PORT_TYPE_COM: 257189747Ssam typestr = "sio"; 258189747Ssam break; 259189747Ssam default: 260189747Ssam continue; 261217751Sadrian } 262189747Ssam pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 263189747Ssam M_NOWAIT | M_ZERO); 264189747Ssam if (!pdev) 265189747Ssam continue; 266189747Ssam resource_list_init(&pdev->resources); 267189747Ssam 268189747Ssam /* First fake up an IRQ resource. */ 269189747Ssam resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 270189747Ssam rman_get_start(sc->irqres), rman_get_end(sc->irqres), 271189747Ssam rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 272189747Ssam rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 273189747Ssam rle->res = sc->irqres; 274189747Ssam 275189747Ssam /* Now fake an IOPORT or MEMORY resource */ 276189747Ssam res = sc->sc_bar_mappings[bidx].res; 277189747Ssam type = sc->sc_bar_mappings[bidx].type; 278189747Ssam resource_list_add(&pdev->resources, type, 0, 279189747Ssam rman_get_start(res) + sc->sc_desc->ports[i].offset, 280189747Ssam rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1, 281189747Ssam 8); 282189747Ssam rle = resource_list_find(&pdev->resources, type, 0); 283189747Ssam 284189747Ssam if (sc->barmuxed == 0) { 285189747Ssam rle->res = sc->sc_bar_mappings[bidx].res; 286189747Ssam } else { 287189747Ssam rle->res = malloc(sizeof(struct resource), M_DEVBUF, 288189747Ssam M_WAITOK | M_ZERO); 289189747Ssam if (rle->res == NULL) { 290189747Ssam free(pdev, M_DEVBUF); 291189747Ssam return (ENOMEM); 292217751Sadrian } 293189747Ssam 294189747Ssam rle->res->r_start = rman_get_start(res) + 295189747Ssam sc->sc_desc->ports[i].offset; 296189747Ssam rle->res->r_end = rle->res->r_start + 8 - 1; 297189747Ssam rle->res->r_bustag = rman_get_bustag(res); 298189747Ssam bus_space_subregion(rle->res->r_bustag, 299189747Ssam rman_get_bushandle(res), 300189747Ssam sc->sc_desc->ports[i].offset, 8, 301189747Ssam &rle->res->r_bushandle); 302189747Ssam } 303189747Ssam 304189747Ssam pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 305189747Ssam 306189747Ssam childunit = puc_find_free_unit(typestr); 307189747Ssam sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 308189747Ssam if (sc->sc_ports[i].dev == NULL) { 309189747Ssam if (sc->barmuxed) { 310217751Sadrian bus_space_unmap(rman_get_bustag(rle->res), 311217751Sadrian rman_get_bushandle(rle->res), 8); 312217751Sadrian free(rle->res, M_DEVBUF); 313217751Sadrian free(pdev, M_DEVBUF); 314217751Sadrian } 315217751Sadrian continue; 316189747Ssam } 317189747Ssam device_set_ivars(sc->sc_ports[i].dev, pdev); 318189747Ssam device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 319189747Ssam if (!bootverbose) 320189747Ssam device_quiet(sc->sc_ports[i].dev); 321189747Ssam#ifdef PUC_DEBUG 322189747Ssam printf("puc: type %d, bar %x, offset %x\n", 323189747Ssam sc->sc_desc->ports[i].type, 324189747Ssam sc->sc_desc->ports[i].bar, 325189747Ssam sc->sc_desc->ports[i].offset); 326189747Ssam puc_print_resource_list(&pdev->resources); 327189747Ssam#endif 328189747Ssam device_set_flags(sc->sc_ports[i].dev, 329189747Ssam sc->sc_desc->ports[i].flags); 330189747Ssam if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 331189747Ssam if (sc->barmuxed) { 332189747Ssam bus_space_unmap(rman_get_bustag(rle->res), 333189747Ssam rman_get_bushandle(rle->res), 334189747Ssam 8); 335189747Ssam free(rle->res, M_DEVBUF); 336189747Ssam free(pdev, M_DEVBUF); 337189747Ssam } 338189747Ssam } 339189747Ssam } 340189747Ssam 341189747Ssam#ifdef PUC_DEBUG 342217751Sadrian bootverbose = 0; 343217751Sadrian#endif 344189747Ssam return (0); 345189747Ssam} 346189747Ssam 347189747Ssamstatic u_int32_t 348189747Ssampuc_ilr_read(struct puc_softc *sc) 349189747Ssam{ 350189747Ssam u_int32_t mask; 351189747Ssam int i; 352189747Ssam 353189747Ssam mask = 0; 354189747Ssam switch (sc->sc_desc->ilr_type) { 355189747Ssam case PUC_ILR_TYPE_DIGI: 356189747Ssam for (i = 1; i >= 0 && sc->sc_desc->ilr_offset[i] != 0; i--) { 357189747Ssam mask = (mask << 8) | (bus_space_read_1(sc->ilr_st, 358189747Ssam sc->ilr_sh, sc->sc_desc->ilr_offset[i]) & 0xff); 359189747Ssam } 360189747Ssam break; 361189747Ssam 362189747Ssam default: 363189747Ssam mask = 0xffffffff; 364189747Ssam break; 365189747Ssam } 366189747Ssam return (mask); 367189747Ssam} 368189747Ssam 369189747Ssam/* 370189747Ssam * This is an interrupt handler. For boards that can't tell us which 371189747Ssam * device generated the interrupt it just calls all the registered 372189747Ssam * handlers sequencially, but for boards that can tell us which 373189747Ssam * device(s) generated the interrupt it calls only handlers for devices 374189747Ssam * that actually generated the interrupt. 375189747Ssam */ 376189747Ssamstatic void 377189747Ssampuc_intr(void *arg) 378189747Ssam{ 379189747Ssam int i; 380189747Ssam u_int32_t ilr_mask; 381189747Ssam struct puc_softc *sc; 382189747Ssam 383189747Ssam sc = (struct puc_softc *)arg; 384189747Ssam ilr_mask = sc->ilr_enabled ? puc_ilr_read(sc) : 0xffffffff; 385189747Ssam for (i = 0; i < PUC_MAX_PORTS; i++) 386189747Ssam if (sc->sc_ports[i].ihand != NULL && 387189747Ssam ((ilr_mask >> i) & 0x00000001)) 388189747Ssam (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 389189747Ssam} 390189747Ssam 391189747Ssamconst struct puc_device_description * 392189747Ssampuc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 393189747Ssam uint32_t sprod) 394189747Ssam{ 395189747Ssam int i; 396189747Ssam 397189747Ssam#define checkreg(val, index) \ 398189747Ssam (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 399189747Ssam 400189747Ssam for (i = 0; puc_devices[i].name != NULL; i++) { 401189747Ssam if (checkreg(vend, PUC_REG_VEND) && 402189747Ssam checkreg(prod, PUC_REG_PROD) && 403189747Ssam checkreg(svend, PUC_REG_SVEND) && 404189747Ssam checkreg(sprod, PUC_REG_SPROD)) 405189747Ssam return (&puc_devices[i]); 406189747Ssam } 407189747Ssam 408189747Ssam#undef checkreg 409189747Ssam 410189747Ssam return (NULL); 411189747Ssam} 412189747Ssam 413189747Ssamstatic int 414217751Sadrianpuc_find_free_unit(char *name) 415189747Ssam{ 416189747Ssam devclass_t dc; 417189747Ssam int start; 418189747Ssam int unit; 419189747Ssam 420189747Ssam unit = 0; 421189747Ssam start = 0; 422217751Sadrian while (resource_int_value(name, unit, "port", &start) == 0 && 423189747Ssam start > 0) 424189747Ssam unit++; 425189747Ssam dc = devclass_find(name); 426189747Ssam if (dc == NULL) 427189747Ssam return (-1); 428189747Ssam while (devclass_get_device(dc, unit)) 429189747Ssam unit++; 430189747Ssam#ifdef PUC_DEBUG 431189747Ssam printf("puc: Using %s%d\n", name, unit); 432189747Ssam#endif 433189747Ssam return (unit); 434189747Ssam} 435189747Ssam 436189747Ssam#ifdef PUC_DEBUG 437189747Ssamstatic void 438189747Ssampuc_print_resource_list(struct resource_list *rl) 439189747Ssam{ 440189747Ssam#if 0 441189747Ssam struct resource_list_entry *rle; 442189747Ssam 443189747Ssam printf("print_resource_list: rl %p\n", rl); 444189747Ssam SLIST_FOREACH(rle, rl, link) 445189747Ssam printf(" type %x, rid %x start %x end %x count %x\n", 446189747Ssam rle->type, rle->rid, rle->start, rle->end, rle->count); 447189747Ssam printf("print_resource_list: end.\n"); 448189747Ssam#endif 449189747Ssam} 450189747Ssam#endif 451189747Ssam 452189747Ssamstruct resource * 453189747Ssampuc_alloc_resource(device_t dev, device_t child, int type, int *rid, 454189747Ssam u_long start, u_long end, u_long count, u_int flags) 455189747Ssam{ 456189747Ssam struct puc_device *pdev; 457189747Ssam struct resource *retval; 458189747Ssam struct resource_list *rl; 459189747Ssam struct resource_list_entry *rle; 460189747Ssam 461189747Ssam pdev = device_get_ivars(child); 462189747Ssam rl = &pdev->resources; 463189747Ssam 464189747Ssam#ifdef PUC_DEBUG 465189747Ssam printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 466189747Ssam pdev, type, *rid); 467189747Ssam puc_print_resource_list(rl); 468189747Ssam#endif 469189747Ssam retval = NULL; 470189747Ssam rle = resource_list_find(rl, type, *rid); 471189747Ssam if (rle) { 472189747Ssam start = rle->start; 473189747Ssam end = rle->end; 474189747Ssam count = rle->count; 475189747Ssam#ifdef PUC_DEBUG 476189747Ssam printf("found rle, %lx, %lx, %lx\n", start, end, count); 477189747Ssam#endif 478189747Ssam retval = rle->res; 479189747Ssam } else 480189747Ssam printf("oops rle is gone\n"); 481217751Sadrian 482217751Sadrian return (retval); 483217751Sadrian} 484217751Sadrian 485217751Sadrianint 486217751Sadrianpuc_release_resource(device_t dev, device_t child, int type, int rid, 487217751Sadrian struct resource *res) 488217751Sadrian{ 489217751Sadrian return (0); 490217751Sadrian} 491217751Sadrian 492217751Sadrianint 493217751Sadrianpuc_get_resource(device_t dev, device_t child, int type, int rid, 494217751Sadrian u_long *startp, u_long *countp) 495217751Sadrian{ 496217751Sadrian struct puc_device *pdev; 497217751Sadrian struct resource_list *rl; 498217751Sadrian struct resource_list_entry *rle; 499217751Sadrian 500217751Sadrian pdev = device_get_ivars(child); 501217751Sadrian rl = &pdev->resources; 502217751Sadrian 503217751Sadrian#ifdef PUC_DEBUG 504217751Sadrian printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 505217751Sadrian type, rid); 506217751Sadrian puc_print_resource_list(rl); 507217751Sadrian#endif 508217751Sadrian rle = resource_list_find(rl, type, rid); 509217751Sadrian if (rle) { 510217751Sadrian#ifdef PUC_DEBUG 511217751Sadrian printf("found rle %p,", rle); 512217751Sadrian#endif 513217751Sadrian if (startp != NULL) 514217751Sadrian *startp = rle->start; 515217751Sadrian if (countp != NULL) 516217751Sadrian *countp = rle->count; 517217751Sadrian#ifdef PUC_DEBUG 518217751Sadrian printf(" %lx, %lx\n", rle->start, rle->count); 519217751Sadrian#endif 520217751Sadrian return (0); 521217751Sadrian } else 522217751Sadrian printf("oops rle is gone\n"); 523217751Sadrian return (ENXIO); 524217751Sadrian} 525217751Sadrian 526217751Sadrianint 527217751Sadrianpuc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 528217751Sadrian void (*ihand)(void *), void *arg, void **cookiep) 529217751Sadrian{ 530217751Sadrian int i; 531217751Sadrian struct puc_softc *sc; 532217751Sadrian 533217751Sadrian sc = (struct puc_softc *)device_get_softc(dev); 534217751Sadrian if ((flags & INTR_FAST) != sc->fastintr) 535217751Sadrian return (ENXIO); 536217751Sadrian for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 537217751Sadrian if (sc->sc_ports[i].dev == child) { 538217751Sadrian if (sc->sc_ports[i].ihand != 0) 539217751Sadrian return (ENXIO); 540217751Sadrian sc->sc_ports[i].ihand = ihand; 541217751Sadrian sc->sc_ports[i].ihandarg = arg; 542217751Sadrian *cookiep = arg; 543217751Sadrian return (0); 544217751Sadrian } 545217751Sadrian } 546217751Sadrian return (ENXIO); 547217751Sadrian} 548217751Sadrian 549217751Sadrianint 550217751Sadrianpuc_teardown_intr(device_t dev, device_t child, struct resource *r, 551217751Sadrian void *cookie) 552217751Sadrian{ 553217751Sadrian int i; 554217751Sadrian struct puc_softc *sc; 555217751Sadrian 556217751Sadrian sc = (struct puc_softc *)device_get_softc(dev); 557217751Sadrian for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 558217751Sadrian if (sc->sc_ports[i].dev == child) { 559217751Sadrian sc->sc_ports[i].ihand = NULL; 560217751Sadrian sc->sc_ports[i].ihandarg = NULL; 561217751Sadrian return (0); 562189747Ssam } 563189747Ssam } 564189747Ssam return (ENXIO); 565189747Ssam} 566217751Sadrian 567217751Sadrianint 568217751Sadrianpuc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 569217751Sadrian{ 570217751Sadrian struct puc_device *pdev; 571189747Ssam 572189747Ssam pdev = device_get_ivars(child); 573189747Ssam if (pdev == NULL) 574189747Ssam return (ENOENT); 575189747Ssam 576189747Ssam switch(index) { 577189747Ssam case PUC_IVAR_FREQ: 578189747Ssam *result = pdev->serialfreq; 579189747Ssam break; 580189747Ssam default: 581189747Ssam return (ENOENT); 582189747Ssam } 583189747Ssam return (0); 584189747Ssam} 585189747Ssam