puc.c revision 102714
1102714Sphk#define PUC_DEBUG 290731Sjhay/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */ 390731Sjhay 490731Sjhay/*- 590731Sjhay * Copyright (c) 2002 JF Hay. All rights reserved. 690731Sjhay * Copyright (c) 2000 M. Warner Losh. All rights reserved. 790731Sjhay * 890731Sjhay * Redistribution and use in source and binary forms, with or without 990731Sjhay * modification, are permitted provided that the following conditions 1090731Sjhay * are met: 1190731Sjhay * 1. Redistributions of source code must retain the above copyright 1290731Sjhay * notice unmodified, this list of conditions, and the following 1390731Sjhay * disclaimer. 1490731Sjhay * 2. Redistributions in binary form must reproduce the above copyright 1590731Sjhay * notice, this list of conditions and the following disclaimer in the 1690731Sjhay * documentation and/or other materials provided with the distribution. 1790731Sjhay * 1890731Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1990731Sjhay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2090731Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2190731Sjhay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2290731Sjhay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2390731Sjhay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2490731Sjhay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2590731Sjhay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2690731Sjhay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2790731Sjhay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2890731Sjhay */ 2990731Sjhay 3090731Sjhay/* 3190731Sjhay * Copyright (c) 1996, 1998, 1999 3290731Sjhay * Christopher G. Demetriou. All rights reserved. 3390731Sjhay * 3490731Sjhay * Redistribution and use in source and binary forms, with or without 3590731Sjhay * modification, are permitted provided that the following conditions 3690731Sjhay * are met: 3790731Sjhay * 1. Redistributions of source code must retain the above copyright 3890731Sjhay * notice, this list of conditions and the following disclaimer. 3990731Sjhay * 2. Redistributions in binary form must reproduce the above copyright 4090731Sjhay * notice, this list of conditions and the following disclaimer in the 4190731Sjhay * documentation and/or other materials provided with the distribution. 4290731Sjhay * 3. All advertising materials mentioning features or use of this software 4390731Sjhay * must display the following acknowledgement: 4490731Sjhay * This product includes software developed by Christopher G. Demetriou 4590731Sjhay * for the NetBSD Project. 4690731Sjhay * 4. The name of the author may not be used to endorse or promote products 4790731Sjhay * derived from this software without specific prior written permission 4890731Sjhay * 4990731Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 5090731Sjhay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5190731Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 5290731Sjhay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 5390731Sjhay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5490731Sjhay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5590731Sjhay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5690731Sjhay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5790731Sjhay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5890731Sjhay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5990731Sjhay */ 6090731Sjhay 6190731Sjhay#include <sys/cdefs.h> 6290731Sjhay__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 102714 2002-08-31 18:38:43Z phk $"); 6390731Sjhay 6490731Sjhay/* 6590731Sjhay * PCI "universal" communication card device driver, glues com, lpt, 6690731Sjhay * and similar ports to PCI via bridge chip often much larger than 6790731Sjhay * the devices being glued. 6890731Sjhay * 6990731Sjhay * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD 7090731Sjhay * sys/dev/pci/pciide.c, revision 1.6). 7190731Sjhay * 7290731Sjhay * These devices could be (and some times are) described as 7390731Sjhay * communications/{serial,parallel}, etc. devices with known 7490731Sjhay * programming interfaces, but those programming interfaces (in 7590731Sjhay * particular the BAR assignments for devices, etc.) in fact are not 7690731Sjhay * particularly well defined. 7790731Sjhay * 7890731Sjhay * After I/we have seen more of these devices, it may be possible 7990731Sjhay * to generalize some of these bits. In particular, devices which 8090731Sjhay * describe themselves as communications/serial/16[45]50, and 8190731Sjhay * communications/parallel/??? might be attached via direct 8290731Sjhay * 'com' and 'lpt' attachments to pci. 8390731Sjhay */ 8490731Sjhay 8590731Sjhay#include <sys/param.h> 8690731Sjhay#include <sys/systm.h> 8790731Sjhay#include <sys/kernel.h> 8890731Sjhay#include <sys/bus.h> 8990731Sjhay#include <sys/conf.h> 9090731Sjhay#include <sys/malloc.h> 9190731Sjhay 9290731Sjhay#include <machine/bus.h> 9390731Sjhay#include <machine/resource.h> 9490731Sjhay#include <sys/rman.h> 9590731Sjhay 9690731Sjhay#include <dev/pci/pcireg.h> 9790731Sjhay#include <dev/pci/pcivar.h> 98102714Sphk 99102714Sphk#define PUC_ENTRAILS 1 10090731Sjhay#include <dev/puc/pucvar.h> 10190731Sjhay 10290731Sjhay#include <opt_puc.h> 10390731Sjhay 10490731Sjhay 10590731Sjhaystruct puc_device { 10690731Sjhay struct resource_list resources; 10790731Sjhay u_int serialfreq; 10890731Sjhay}; 10990731Sjhay 11090731Sjhaystatic void puc_intr(void *arg); 11190731Sjhay 11290731Sjhaystatic void puc_config_superio(device_t); 11390731Sjhaystatic void puc_config_win877(struct resource *); 11490731Sjhaystatic int puc_find_free_unit(char *); 11590731Sjhay#ifdef PUC_DEBUG 11690731Sjhaystatic void puc_print_win877(bus_space_tag_t, bus_space_handle_t, u_int, 11790731Sjhay u_int); 11890731Sjhaystatic void puc_print_resource_list(struct resource_list *); 11990731Sjhay#endif 12090731Sjhay 121102714Sphkint 122102714Sphkpuc_attach(device_t dev, const struct puc_device_description *desc) 12390731Sjhay{ 12490731Sjhay char *typestr; 12590731Sjhay int bidx, childunit, i, irq_setup, rid; 12690731Sjhay struct puc_softc *sc; 12790731Sjhay struct puc_device *pdev; 12890731Sjhay struct resource *res; 12990731Sjhay struct resource_list_entry *rle; 13090731Sjhay 13190731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 13290731Sjhay bzero(sc, sizeof(*sc)); 133102714Sphk sc->sc_desc = desc; 134102714Sphk 13590731Sjhay if (sc->sc_desc == NULL) 13690731Sjhay return (ENXIO); 13790731Sjhay 13890731Sjhay#ifdef PUC_DEBUG 13990731Sjhay bootverbose = 1; 14090731Sjhay 14190731Sjhay printf("puc: name: %s\n", sc->sc_desc->name); 14290731Sjhay#endif 14390731Sjhay rid = 0; 14490731Sjhay res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 14590731Sjhay RF_ACTIVE | RF_SHAREABLE); 14690731Sjhay if (!res) 14790731Sjhay return (ENXIO); 14890731Sjhay 14990731Sjhay sc->irqres = res; 15090731Sjhay sc->irqrid = rid; 15190731Sjhay#ifdef PUC_FASTINTR 15290731Sjhay irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 15390731Sjhay INTR_TYPE_TTY | INTR_FAST, puc_intr, sc, &sc->intr_cookie); 15490731Sjhay#else 15590731Sjhay irq_setup = ENXIO; 15690731Sjhay#endif 15790731Sjhay if (irq_setup != 0) 15890731Sjhay irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res, 15990731Sjhay INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie); 16090731Sjhay if (irq_setup != 0) 16190731Sjhay return (ENXIO); 16290731Sjhay 16390731Sjhay rid = 0; 16490731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 16590731Sjhay if (rid == sc->sc_desc->ports[i].bar) 16690731Sjhay sc->barmuxed = 1; 16790731Sjhay rid = sc->sc_desc->ports[i].bar; 16890731Sjhay bidx = PUC_PORT_BAR_INDEX(rid); 16990731Sjhay 17090731Sjhay if (sc->sc_bar_mappings[bidx].res != NULL) 17190731Sjhay continue; 17290731Sjhay res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 17390731Sjhay 0ul, ~0ul, 1, RF_ACTIVE); 17490731Sjhay if (res == NULL) { 17590731Sjhay printf("could not get resource\n"); 17690731Sjhay continue; 17790731Sjhay } 17890731Sjhay sc->sc_bar_mappings[bidx].res = res; 17990731Sjhay#ifdef PUC_DEBUG 18090731Sjhay printf("port bst %x, start %x, end %x\n", 18190731Sjhay (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), 18290731Sjhay (u_int)rman_get_end(res)); 18390731Sjhay#endif 18490731Sjhay } 18590731Sjhay 18690731Sjhay puc_config_superio(dev); 18790731Sjhay 18890731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 18990731Sjhay rid = sc->sc_desc->ports[i].bar; 19090731Sjhay bidx = PUC_PORT_BAR_INDEX(rid); 19190731Sjhay if (sc->sc_bar_mappings[bidx].res == NULL) 19290731Sjhay continue; 19390731Sjhay 19490731Sjhay switch (sc->sc_desc->ports[i].type) { 19590731Sjhay case PUC_PORT_TYPE_COM: 19690731Sjhay typestr = "sio"; 19790731Sjhay break; 19890731Sjhay default: 19990731Sjhay continue; 20090731Sjhay } 20190731Sjhay pdev = malloc(sizeof(struct puc_device), M_DEVBUF, 20290731Sjhay M_NOWAIT | M_ZERO); 20390731Sjhay if (!pdev) 20490731Sjhay continue; 20590731Sjhay resource_list_init(&pdev->resources); 20690731Sjhay 20790731Sjhay /* First fake up an IRQ resource. */ 20890731Sjhay resource_list_add(&pdev->resources, SYS_RES_IRQ, 0, 20990731Sjhay rman_get_start(sc->irqres), rman_get_end(sc->irqres), 21090731Sjhay rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1); 21190731Sjhay rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0); 21290731Sjhay rle->res = sc->irqres; 21390731Sjhay 21490731Sjhay /* Now fake an IOPORT resource */ 21590731Sjhay res = sc->sc_bar_mappings[bidx].res; 21690731Sjhay resource_list_add(&pdev->resources, SYS_RES_IOPORT, 0, 21790731Sjhay rman_get_start(res) + sc->sc_desc->ports[i].offset, 21890731Sjhay rman_get_end(res) + sc->sc_desc->ports[i].offset + 8 - 1, 21990731Sjhay 8); 22090731Sjhay rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 0); 22190731Sjhay 22290731Sjhay if (sc->barmuxed == 0) { 22390731Sjhay rle->res = sc->sc_bar_mappings[bidx].res; 22490731Sjhay } else { 22590731Sjhay rle->res = malloc(sizeof(struct resource), M_DEVBUF, 22690731Sjhay M_WAITOK | M_ZERO); 22790925Snyan if (rle->res == NULL) { 22890925Snyan free(pdev, M_DEVBUF); 22990731Sjhay return (ENOMEM); 23090925Snyan } 23190731Sjhay 23290731Sjhay rle->res->r_start = rman_get_start(res) + 23390731Sjhay sc->sc_desc->ports[i].offset; 23490731Sjhay rle->res->r_end = rle->res->r_start + 8 - 1; 23590731Sjhay rle->res->r_bustag = rman_get_bustag(res); 23690731Sjhay bus_space_subregion(rle->res->r_bustag, 23790731Sjhay rman_get_bushandle(res), 23890731Sjhay sc->sc_desc->ports[i].offset, 8, 23990731Sjhay &rle->res->r_bushandle); 24090731Sjhay } 24190731Sjhay 24290731Sjhay pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; 24390731Sjhay 24490731Sjhay childunit = puc_find_free_unit(typestr); 24590731Sjhay sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); 24690925Snyan if (sc->sc_ports[i].dev == NULL) { 24790925Snyan if (sc->barmuxed) { 24890925Snyan bus_space_unmap(rman_get_bustag(rle->res), 24990925Snyan rman_get_bushandle(rle->res), 25090925Snyan 8); 25190925Snyan free(rle->res, M_DEVBUF); 25290925Snyan free(pdev, M_DEVBUF); 25390925Snyan } 25490731Sjhay continue; 25590925Snyan } 25690731Sjhay device_set_ivars(sc->sc_ports[i].dev, pdev); 25790731Sjhay device_set_desc(sc->sc_ports[i].dev, sc->sc_desc->name); 25890731Sjhay if (!bootverbose) 25990731Sjhay device_quiet(sc->sc_ports[i].dev); 26090731Sjhay#ifdef PUC_DEBUG 26190731Sjhay printf("puc: type %d, bar %x, offset %x\n", 26290731Sjhay sc->sc_desc->ports[i].type, 26390731Sjhay sc->sc_desc->ports[i].bar, 26490731Sjhay sc->sc_desc->ports[i].offset); 265102714Sphk puc_print_resource_list(&pdev->resources); 26690731Sjhay#endif 26790925Snyan if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { 26890925Snyan if (sc->barmuxed) { 26990925Snyan bus_space_unmap(rman_get_bustag(rle->res), 27090925Snyan rman_get_bushandle(rle->res), 27190925Snyan 8); 27290925Snyan free(rle->res, M_DEVBUF); 27390925Snyan free(pdev, M_DEVBUF); 27490925Snyan } 27590925Snyan } 27690731Sjhay } 27790731Sjhay 27890731Sjhay#ifdef PUC_DEBUG 27990731Sjhay bootverbose = 0; 28090731Sjhay#endif 28190731Sjhay return (0); 28290731Sjhay} 28390731Sjhay 28490731Sjhay/* 28590731Sjhay * This is just an brute force interrupt handler. It just calls all the 28690731Sjhay * registered handlers sequencially. 28790731Sjhay * 28890731Sjhay * Later on we should maybe have a different handler for boards that can 28990731Sjhay * tell us which device generated the interrupt. 29090731Sjhay */ 29190731Sjhaystatic void 29290731Sjhaypuc_intr(void *arg) 29390731Sjhay{ 29490731Sjhay int i; 29590731Sjhay struct puc_softc *sc; 29690731Sjhay 29790731Sjhay sc = (struct puc_softc *)arg; 29890731Sjhay for (i = 0; i < PUC_MAX_PORTS; i++) 29990731Sjhay if (sc->sc_ports[i].ihand != NULL) 30090731Sjhay (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg); 30190731Sjhay} 30290731Sjhay 303102714Sphkconst struct puc_device_description * 30490731Sjhaypuc_find_description(uint32_t vend, uint32_t prod, uint32_t svend, 30590731Sjhay uint32_t sprod) 30690731Sjhay{ 30790731Sjhay int i; 30890731Sjhay 30990731Sjhay#define checkreg(val, index) \ 31090731Sjhay (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)]) 31190731Sjhay 31290731Sjhay for (i = 0; puc_devices[i].name != NULL; i++) { 31390731Sjhay if (checkreg(vend, PUC_REG_VEND) && 31490731Sjhay checkreg(prod, PUC_REG_PROD) && 31590731Sjhay checkreg(svend, PUC_REG_SVEND) && 31690731Sjhay checkreg(sprod, PUC_REG_SPROD)) 31790731Sjhay return (&puc_devices[i]); 31890731Sjhay } 31990731Sjhay 32090731Sjhay#undef checkreg 32190731Sjhay 32290731Sjhay return (NULL); 32390731Sjhay} 32490731Sjhay 32590731Sjhay/* 32690731Sjhay * It might be possible to make these more generic if we can detect patterns. 32790731Sjhay * For instance maybe if the size of a bar is 0x400 (the old isa space) it 32890731Sjhay * might contain one or more superio chips. 32990731Sjhay */ 33090731Sjhaystatic void 33190731Sjhaypuc_config_superio(device_t dev) 33290731Sjhay{ 33390731Sjhay struct puc_softc *sc = (struct puc_softc *)device_get_softc(dev); 33490731Sjhay 33590731Sjhay if (sc->sc_desc->rval[PUC_REG_VEND] == 0x1592 && 33690731Sjhay sc->sc_desc->rval[PUC_REG_PROD] == 0x0781) 33790731Sjhay puc_config_win877(sc->sc_bar_mappings[0].res); 33890731Sjhay} 33990731Sjhay 34090731Sjhay#define rdspio(indx) (bus_space_write_1(bst, bsh, efir, indx), \ 34190731Sjhay bus_space_read_1(bst, bsh, efdr)) 34290731Sjhay#define wrspio(indx,data) (bus_space_write_1(bst, bsh, efir, indx), \ 34390731Sjhay bus_space_write_1(bst, bsh, efdr, data)) 34490731Sjhay 34590731Sjhay#ifdef PUC_DEBUG 34690731Sjhaystatic void 34790731Sjhaypuc_print_win877(bus_space_tag_t bst, bus_space_handle_t bsh, u_int efir, 34890731Sjhay u_int efdr) 34990731Sjhay{ 35090731Sjhay u_char cr00, cr01, cr04, cr09, cr0d, cr14, cr15, cr16, cr17; 35190731Sjhay u_char cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32; 35290731Sjhay 35390731Sjhay cr00 = rdspio(0x00); 35490731Sjhay cr01 = rdspio(0x01); 35590731Sjhay cr04 = rdspio(0x04); 35690731Sjhay cr09 = rdspio(0x09); 35790731Sjhay cr0d = rdspio(0x0d); 35890731Sjhay cr14 = rdspio(0x14); 35990731Sjhay cr15 = rdspio(0x15); 36090731Sjhay cr16 = rdspio(0x16); 36190731Sjhay cr17 = rdspio(0x17); 36290731Sjhay cr18 = rdspio(0x18); 36390731Sjhay cr19 = rdspio(0x19); 36490731Sjhay cr24 = rdspio(0x24); 36590731Sjhay cr25 = rdspio(0x25); 36690731Sjhay cr28 = rdspio(0x28); 36790731Sjhay cr2c = rdspio(0x2c); 36890731Sjhay cr31 = rdspio(0x31); 36990731Sjhay cr32 = rdspio(0x32); 37090731Sjhay printf("877T: cr00 %x, cr01 %x, cr04 %x, cr09 %x, cr0d %x, cr14 %x, " 37190731Sjhay "cr15 %x, cr16 %x, cr17 %x, cr18 %x, cr19 %x, cr24 %x, cr25 %x, " 37290731Sjhay "cr28 %x, cr2c %x, cr31 %x, cr32 %x\n", cr00, cr01, cr04, cr09, 37390731Sjhay cr0d, cr14, cr15, cr16, cr17, 37490731Sjhay cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32); 37590731Sjhay} 37690731Sjhay#endif 37790731Sjhay 37890731Sjhaystatic void 37990731Sjhaypuc_config_win877(struct resource *res) 38090731Sjhay{ 38190731Sjhay u_char val; 38290731Sjhay u_int efir, efdr; 38390731Sjhay bus_space_tag_t bst; 38490731Sjhay bus_space_handle_t bsh; 38590731Sjhay 38690731Sjhay bst = rman_get_bustag(res); 38790731Sjhay bsh = rman_get_bushandle(res); 38890731Sjhay 38990731Sjhay /* configure the first W83877TF */ 39090731Sjhay bus_space_write_1(bst, bsh, 0x250, 0x89); 39190731Sjhay efir = 0x251; 39290731Sjhay efdr = 0x252; 39390731Sjhay val = rdspio(0x09) & 0x0f; 39490731Sjhay if (val != 0x0c) { 39590731Sjhay printf("conf_win877: Oops not a W83877TF\n"); 39690731Sjhay return; 39790731Sjhay } 39890731Sjhay 39990731Sjhay#ifdef PUC_DEBUG 40090731Sjhay printf("before: "); 40190731Sjhay puc_print_win877(bst, bsh, efir, efdr); 40290731Sjhay#endif 40390731Sjhay 40490731Sjhay val = rdspio(0x16); 40590731Sjhay val |= 0x04; 40690731Sjhay wrspio(0x16, val); 40790731Sjhay val &= ~0x04; 40890731Sjhay wrspio(0x16, val); 40990731Sjhay 41090731Sjhay wrspio(0x24, 0x2e8 >> 2); 41190731Sjhay wrspio(0x25, 0x2f8 >> 2); 41290731Sjhay wrspio(0x17, 0x03); 41390731Sjhay wrspio(0x28, 0x43); 41490731Sjhay 41590731Sjhay#ifdef PUC_DEBUG 41690731Sjhay printf("after: "); 41790731Sjhay puc_print_win877(bst, bsh, efir, efdr); 41890731Sjhay#endif 41990731Sjhay 42090731Sjhay bus_space_write_1(bst, bsh, 0x250, 0xaa); 42190731Sjhay 42290731Sjhay /* configure the second W83877TF */ 42390731Sjhay bus_space_write_1(bst, bsh, 0x3f0, 0x87); 42490731Sjhay bus_space_write_1(bst, bsh, 0x3f0, 0x87); 42590731Sjhay efir = 0x3f0; 42690731Sjhay efdr = 0x3f1; 42790731Sjhay val = rdspio(0x09) & 0x0f; 42890731Sjhay if (val != 0x0c) { 42990731Sjhay printf("conf_win877: Oops not a W83877TF\n"); 43090731Sjhay return; 43190731Sjhay } 43290731Sjhay 43390731Sjhay#ifdef PUC_DEBUG 43490731Sjhay printf("before: "); 43590731Sjhay puc_print_win877(bst, bsh, efir, efdr); 43690731Sjhay#endif 43790731Sjhay 43890731Sjhay val = rdspio(0x16); 43990731Sjhay val |= 0x04; 44090731Sjhay wrspio(0x16, val); 44190731Sjhay val &= ~0x04; 44290731Sjhay wrspio(0x16, val); 44390731Sjhay 44490731Sjhay wrspio(0x24, 0x3e8 >> 2); 44590731Sjhay wrspio(0x25, 0x3f8 >> 2); 44690731Sjhay wrspio(0x17, 0x03); 44790731Sjhay wrspio(0x28, 0x43); 44890731Sjhay 44990731Sjhay#ifdef PUC_DEBUG 45090731Sjhay printf("after: "); 45190731Sjhay puc_print_win877(bst, bsh, efir, efdr); 45290731Sjhay#endif 45390731Sjhay 45490731Sjhay bus_space_write_1(bst, bsh, 0x3f0, 0xaa); 45590731Sjhay} 45690731Sjhay 45790731Sjhay#undef rdspio 45890731Sjhay#undef wrspio 45990731Sjhay 46090731Sjhaystatic int puc_find_free_unit(char *name) 46190731Sjhay{ 46290731Sjhay devclass_t dc; 46390731Sjhay int start; 46490731Sjhay int unit; 46590731Sjhay 46690731Sjhay unit = 0; 46790731Sjhay start = 0; 46890731Sjhay while (resource_int_value(name, unit, "port", &start) == 0 && 46990731Sjhay start > 0) 47090731Sjhay unit++; 47190731Sjhay dc = devclass_find(name); 47290731Sjhay if (dc == NULL) 47390731Sjhay return (-1); 47490731Sjhay while (devclass_get_device(dc, unit)) 47590731Sjhay unit++; 47690731Sjhay#ifdef PUC_DEBUG 47790731Sjhay printf("puc: Using %s%d\n", name, unit); 47890731Sjhay#endif 47990731Sjhay return (unit); 48090731Sjhay} 48190731Sjhay 48290731Sjhay#ifdef PUC_DEBUG 48390731Sjhaystatic void 48490731Sjhaypuc_print_resource_list(struct resource_list *rl) 48590731Sjhay{ 48690731Sjhay struct resource_list_entry *rle; 48790731Sjhay 48890731Sjhay printf("print_resource_list: rl %p\n", rl); 48990731Sjhay SLIST_FOREACH(rle, rl, link) 49090731Sjhay printf("type %x, rid %x\n", rle->type, rle->rid); 49190731Sjhay printf("print_resource_list: end.\n"); 49290731Sjhay} 49390731Sjhay#endif 49490731Sjhay 495102714Sphkstruct resource * 49690731Sjhaypuc_alloc_resource(device_t dev, device_t child, int type, int *rid, 49790731Sjhay u_long start, u_long end, u_long count, u_int flags) 49890731Sjhay{ 49990731Sjhay struct puc_device *pdev; 50090731Sjhay struct resource *retval; 50190731Sjhay struct resource_list *rl; 50290731Sjhay struct resource_list_entry *rle; 50390731Sjhay 50490731Sjhay pdev = device_get_ivars(child); 50590731Sjhay rl = &pdev->resources; 50690731Sjhay 50790731Sjhay#ifdef PUC_DEBUG 50890731Sjhay printf("puc_alloc_resource: pdev %p, looking for t %x, r %x\n", 50990731Sjhay pdev, type, *rid); 51090731Sjhay puc_print_resource_list(rl); 51190731Sjhay#endif 51290731Sjhay retval = NULL; 51390731Sjhay rle = resource_list_find(rl, type, *rid); 51490731Sjhay if (rle) { 51590731Sjhay start = rle->start; 51690731Sjhay end = rle->end; 51790731Sjhay count = rle->count; 51890731Sjhay#ifdef PUC_DEBUG 51990731Sjhay printf("found rle, %lx, %lx, %lx\n", start, end, count); 52090731Sjhay#endif 52190731Sjhay retval = rle->res; 52290731Sjhay } else 52390731Sjhay printf("oops rle is gone\n"); 52490731Sjhay 52590731Sjhay return (retval); 52690731Sjhay} 52790731Sjhay 528102714Sphkint 52990731Sjhaypuc_release_resource(device_t dev, device_t child, int type, int rid, 53090731Sjhay struct resource *res) 53190731Sjhay{ 53290731Sjhay return (0); 53390731Sjhay} 53490731Sjhay 535102714Sphkint 53690731Sjhaypuc_get_resource(device_t dev, device_t child, int type, int rid, 53790731Sjhay u_long *startp, u_long *countp) 53890731Sjhay{ 53990731Sjhay struct puc_device *pdev; 54090731Sjhay struct resource_list *rl; 54190731Sjhay struct resource_list_entry *rle; 54290731Sjhay 54390731Sjhay pdev = device_get_ivars(child); 54490731Sjhay rl = &pdev->resources; 54590731Sjhay 54690731Sjhay#ifdef PUC_DEBUG 54790731Sjhay printf("puc_get_resource: pdev %p, looking for t %x, r %x\n", pdev, 54890731Sjhay type, rid); 54990731Sjhay puc_print_resource_list(rl); 55090731Sjhay#endif 55190731Sjhay rle = resource_list_find(rl, type, rid); 55290731Sjhay if (rle) { 55390731Sjhay#ifdef PUC_DEBUG 55490731Sjhay printf("found rle %p,", rle); 55590731Sjhay#endif 55690731Sjhay if (startp != NULL) 55790731Sjhay *startp = rle->start; 55890731Sjhay if (countp != NULL) 55990731Sjhay *countp = rle->count; 56090731Sjhay#ifdef PUC_DEBUG 56190731Sjhay printf(" %lx, %lx\n", rle->start, rle->count); 56290731Sjhay#endif 56390731Sjhay return (0); 56490731Sjhay } else 56590731Sjhay printf("oops rle is gone\n"); 56690731Sjhay return (ENXIO); 56790731Sjhay} 56890731Sjhay 569102714Sphkint 57090731Sjhaypuc_setup_intr(device_t dev, device_t child, struct resource *r, int flags, 57190731Sjhay void (*ihand)(void *), void *arg, void **cookiep) 57290731Sjhay{ 57390731Sjhay int i; 57490731Sjhay struct puc_softc *sc; 57590731Sjhay 57690731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 57790731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 57890731Sjhay if (sc->sc_ports[i].dev == child) { 57990731Sjhay if (sc->sc_ports[i].ihand != 0) 58090731Sjhay return (ENXIO); 58190731Sjhay sc->sc_ports[i].ihand = ihand; 58290731Sjhay sc->sc_ports[i].ihandarg = arg; 58390731Sjhay *cookiep = arg; 58490731Sjhay return (0); 58590731Sjhay } 58690731Sjhay } 58790731Sjhay return (ENXIO); 58890731Sjhay} 58990731Sjhay 590102714Sphkint 59190731Sjhaypuc_teardown_intr(device_t dev, device_t child, struct resource *r, 59290731Sjhay void *cookie) 59390731Sjhay{ 59490731Sjhay int i; 59590731Sjhay struct puc_softc *sc; 59690731Sjhay 59790731Sjhay sc = (struct puc_softc *)device_get_softc(dev); 59890731Sjhay for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { 59990731Sjhay if (sc->sc_ports[i].dev == child) { 60090731Sjhay sc->sc_ports[i].ihand = NULL; 60190731Sjhay sc->sc_ports[i].ihandarg = NULL; 60290731Sjhay return (0); 60390731Sjhay } 60490731Sjhay } 60590731Sjhay return (ENXIO); 60690731Sjhay} 60790731Sjhay 608102714Sphkint 60990731Sjhaypuc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 61090731Sjhay{ 61190731Sjhay struct puc_device *pdev; 61290731Sjhay 61390731Sjhay pdev = device_get_ivars(child); 61490731Sjhay if (pdev == NULL) 61590731Sjhay return (ENOENT); 61690731Sjhay 61790731Sjhay switch(index) { 61890731Sjhay case PUC_IVAR_FREQ: 61990731Sjhay *result = pdev->serialfreq; 62090731Sjhay break; 62190731Sjhay default: 62290731Sjhay return (ENOENT); 62390731Sjhay } 62490731Sjhay return (0); 62590731Sjhay} 62690731Sjhay 627102714Sphkdevclass_t puc_devclass; 62890731Sjhay 629