19c564b6cSJohn Hay /*- 264220a7eSMarcel Moolenaar * Copyright (c) 2006 Marcel Moolenaar 364220a7eSMarcel Moolenaar * All rights reserved. 49c564b6cSJohn Hay * 59c564b6cSJohn Hay * Redistribution and use in source and binary forms, with or without 69c564b6cSJohn Hay * modification, are permitted provided that the following conditions 79c564b6cSJohn Hay * are met: 864220a7eSMarcel Moolenaar * 99c564b6cSJohn Hay * 1. Redistributions of source code must retain the above copyright 10ac673f9aSWarner Losh * notice, this list of conditions and the following disclaimer. 119c564b6cSJohn Hay * 2. Redistributions in binary form must reproduce the above copyright 129c564b6cSJohn Hay * notice, this list of conditions and the following disclaimer in the 139c564b6cSJohn Hay * documentation and/or other materials provided with the distribution. 149c564b6cSJohn Hay * 159c564b6cSJohn Hay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 169c564b6cSJohn Hay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 179c564b6cSJohn Hay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 189c564b6cSJohn Hay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 199c564b6cSJohn Hay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 209c564b6cSJohn Hay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 219c564b6cSJohn Hay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 229c564b6cSJohn Hay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 239c564b6cSJohn Hay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 249c564b6cSJohn Hay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 259c564b6cSJohn Hay */ 269c564b6cSJohn Hay 279c564b6cSJohn Hay #include <sys/cdefs.h> 289c564b6cSJohn Hay __FBSDID("$FreeBSD$"); 299c564b6cSJohn Hay 309c564b6cSJohn Hay #include <sys/param.h> 319c564b6cSJohn Hay #include <sys/systm.h> 329c564b6cSJohn Hay #include <sys/kernel.h> 339c564b6cSJohn Hay #include <sys/bus.h> 349c564b6cSJohn Hay #include <sys/conf.h> 359c564b6cSJohn Hay #include <sys/malloc.h> 3664220a7eSMarcel Moolenaar #include <sys/mutex.h> 379c564b6cSJohn Hay 389c564b6cSJohn Hay #include <machine/bus.h> 399c564b6cSJohn Hay #include <machine/resource.h> 409c564b6cSJohn Hay #include <sys/rman.h> 419c564b6cSJohn Hay 429c564b6cSJohn Hay #include <dev/pci/pcireg.h> 439c564b6cSJohn Hay #include <dev/pci/pcivar.h> 4432f606d1SPoul-Henning Kamp 4564220a7eSMarcel Moolenaar #include <dev/puc/puc_bus.h> 4664220a7eSMarcel Moolenaar #include <dev/puc/puc_cfg.h> 47482aa6a3SDavid E. O'Brien #include <dev/puc/puc_bfe.h> 489c564b6cSJohn Hay 4964220a7eSMarcel Moolenaar #define PUC_ISRCCNT 5 5064220a7eSMarcel Moolenaar 5164220a7eSMarcel Moolenaar struct puc_port { 5264220a7eSMarcel Moolenaar struct puc_bar *p_bar; 5364220a7eSMarcel Moolenaar struct resource *p_rres; 5464220a7eSMarcel Moolenaar struct resource *p_ires; 5564220a7eSMarcel Moolenaar device_t p_dev; 5664220a7eSMarcel Moolenaar int p_nr; 5764220a7eSMarcel Moolenaar int p_type; 5864220a7eSMarcel Moolenaar int p_rclk; 5964220a7eSMarcel Moolenaar 6064220a7eSMarcel Moolenaar int p_hasintr:1; 6164220a7eSMarcel Moolenaar 6264220a7eSMarcel Moolenaar serdev_intr_t *p_ihsrc[PUC_ISRCCNT]; 6364220a7eSMarcel Moolenaar void *p_iharg; 6464220a7eSMarcel Moolenaar 6564220a7eSMarcel Moolenaar int p_ipend; 669c564b6cSJohn Hay }; 679c564b6cSJohn Hay 68c9168019SPoul-Henning Kamp devclass_t puc_devclass; 6964220a7eSMarcel Moolenaar const char puc_driver_name[] = "puc"; 70c9168019SPoul-Henning Kamp 71d745c852SEd Schouten static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver"); 7264220a7eSMarcel Moolenaar 7364220a7eSMarcel Moolenaar struct puc_bar * 7464220a7eSMarcel Moolenaar puc_get_bar(struct puc_softc *sc, int rid) 751e89655aSPoul-Henning Kamp { 7664220a7eSMarcel Moolenaar struct puc_bar *bar; 7764220a7eSMarcel Moolenaar struct rman *rm; 7864220a7eSMarcel Moolenaar u_long end, start; 7964220a7eSMarcel Moolenaar int error, i; 801e89655aSPoul-Henning Kamp 8164220a7eSMarcel Moolenaar /* Find the BAR entry with the given RID. */ 8264220a7eSMarcel Moolenaar i = 0; 8364220a7eSMarcel Moolenaar while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid) 8464220a7eSMarcel Moolenaar i++; 8564220a7eSMarcel Moolenaar if (i < PUC_PCI_BARS) 8664220a7eSMarcel Moolenaar return (&sc->sc_bar[i]); 871e89655aSPoul-Henning Kamp 8864220a7eSMarcel Moolenaar /* Not found. If we're looking for an unused entry, return NULL. */ 8964220a7eSMarcel Moolenaar if (rid == -1) 9064220a7eSMarcel Moolenaar return (NULL); 91084254f8SMaxim Sobolev 9264220a7eSMarcel Moolenaar /* Get an unused entry for us to fill. */ 9364220a7eSMarcel Moolenaar bar = puc_get_bar(sc, -1); 9464220a7eSMarcel Moolenaar if (bar == NULL) 9564220a7eSMarcel Moolenaar return (NULL); 9664220a7eSMarcel Moolenaar bar->b_rid = rid; 9764220a7eSMarcel Moolenaar bar->b_type = SYS_RES_IOPORT; 9864220a7eSMarcel Moolenaar bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 9964220a7eSMarcel Moolenaar &bar->b_rid, RF_ACTIVE); 10064220a7eSMarcel Moolenaar if (bar->b_res == NULL) { 10164220a7eSMarcel Moolenaar bar->b_rid = rid; 10264220a7eSMarcel Moolenaar bar->b_type = SYS_RES_MEMORY; 10364220a7eSMarcel Moolenaar bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 10464220a7eSMarcel Moolenaar &bar->b_rid, RF_ACTIVE); 10564220a7eSMarcel Moolenaar if (bar->b_res == NULL) { 10664220a7eSMarcel Moolenaar bar->b_rid = -1; 10764220a7eSMarcel Moolenaar return (NULL); 1085aa967d9SYoshihiro Takahashi } 1095aa967d9SYoshihiro Takahashi } 11064220a7eSMarcel Moolenaar 11164220a7eSMarcel Moolenaar /* Update our managed space. */ 11264220a7eSMarcel Moolenaar rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem; 11364220a7eSMarcel Moolenaar start = rman_get_start(bar->b_res); 11464220a7eSMarcel Moolenaar end = rman_get_end(bar->b_res); 11564220a7eSMarcel Moolenaar error = rman_manage_region(rm, start, end); 11664220a7eSMarcel Moolenaar if (error) { 11764220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, 11864220a7eSMarcel Moolenaar bar->b_res); 11964220a7eSMarcel Moolenaar bar->b_res = NULL; 12064220a7eSMarcel Moolenaar bar->b_rid = -1; 12164220a7eSMarcel Moolenaar bar = NULL; 1229c564b6cSJohn Hay } 1239c564b6cSJohn Hay 12464220a7eSMarcel Moolenaar return (bar); 1259c564b6cSJohn Hay } 1269c564b6cSJohn Hay 127ef544f63SPaolo Pisati static int 1289c564b6cSJohn Hay puc_intr(void *arg) 1299c564b6cSJohn Hay { 13064220a7eSMarcel Moolenaar struct puc_port *port; 13164220a7eSMarcel Moolenaar struct puc_softc *sc = arg; 13257467e59SMarcel Moolenaar u_long ds, dev, devs; 13357467e59SMarcel Moolenaar int i, idx, ipend, isrc, nints; 13464220a7eSMarcel Moolenaar uint8_t ilr; 13564220a7eSMarcel Moolenaar 13657467e59SMarcel Moolenaar nints = 0; 13757467e59SMarcel Moolenaar while (1) { 13857467e59SMarcel Moolenaar /* 13957467e59SMarcel Moolenaar * Obtain the set of devices with pending interrupts. 14057467e59SMarcel Moolenaar */ 14164220a7eSMarcel Moolenaar devs = sc->sc_serdevs; 14264220a7eSMarcel Moolenaar if (sc->sc_ilr == PUC_ILR_DIGI) { 14364220a7eSMarcel Moolenaar idx = 0; 14464220a7eSMarcel Moolenaar while (devs & (0xfful << idx)) { 14564220a7eSMarcel Moolenaar ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7); 14664220a7eSMarcel Moolenaar devs &= ~0ul ^ ((u_long)ilr << idx); 14764220a7eSMarcel Moolenaar idx += 8; 14864220a7eSMarcel Moolenaar } 14964220a7eSMarcel Moolenaar } else if (sc->sc_ilr == PUC_ILR_QUATECH) { 15064220a7eSMarcel Moolenaar /* 15164220a7eSMarcel Moolenaar * Don't trust the value if it's the same as the option 15264220a7eSMarcel Moolenaar * register. It may mean that the ILR is not active and 15364220a7eSMarcel Moolenaar * we're reading the option register instead. This may 15464220a7eSMarcel Moolenaar * lead to false positives on 8-port boards. 15564220a7eSMarcel Moolenaar */ 15664220a7eSMarcel Moolenaar ilr = bus_read_1(sc->sc_port[0].p_rres, 7); 15764220a7eSMarcel Moolenaar if (ilr != (sc->sc_cfg_data & 0xff)) 15864220a7eSMarcel Moolenaar devs &= (u_long)ilr; 15964220a7eSMarcel Moolenaar } 16057467e59SMarcel Moolenaar if (devs == 0UL) 16157467e59SMarcel Moolenaar break; 16264220a7eSMarcel Moolenaar 16357467e59SMarcel Moolenaar /* 16457467e59SMarcel Moolenaar * Obtain the set of interrupt sources from those devices 16557467e59SMarcel Moolenaar * that have pending interrupts. 16657467e59SMarcel Moolenaar */ 16764220a7eSMarcel Moolenaar ipend = 0; 16864220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 16957467e59SMarcel Moolenaar ds = devs; 17057467e59SMarcel Moolenaar while (ds != 0UL) { 17157467e59SMarcel Moolenaar while ((ds & dev) == 0UL) 17264220a7eSMarcel Moolenaar idx++, dev <<= 1; 17357467e59SMarcel Moolenaar ds &= ~dev; 17464220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 17564220a7eSMarcel Moolenaar port->p_ipend = SERDEV_IPEND(port->p_dev); 17664220a7eSMarcel Moolenaar ipend |= port->p_ipend; 17764220a7eSMarcel Moolenaar } 17857467e59SMarcel Moolenaar if (ipend == 0) 17957467e59SMarcel Moolenaar break; 18064220a7eSMarcel Moolenaar 18164220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 18264220a7eSMarcel Moolenaar while (ipend) { 18364220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT && !(ipend & isrc)) 18464220a7eSMarcel Moolenaar i++, isrc <<= 1; 18564220a7eSMarcel Moolenaar KASSERT(i < PUC_ISRCCNT, ("%s", __func__)); 18664220a7eSMarcel Moolenaar ipend &= ~isrc; 18764220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 18857467e59SMarcel Moolenaar ds = devs; 18957467e59SMarcel Moolenaar while (ds != 0UL) { 19057467e59SMarcel Moolenaar while ((ds & dev) == 0UL) 19164220a7eSMarcel Moolenaar idx++, dev <<= 1; 19257467e59SMarcel Moolenaar ds &= ~dev; 19364220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 19464220a7eSMarcel Moolenaar if (!(port->p_ipend & isrc)) 19564220a7eSMarcel Moolenaar continue; 19664220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 19764220a7eSMarcel Moolenaar (*port->p_ihsrc[i])(port->p_iharg); 19857467e59SMarcel Moolenaar nints++; 19964220a7eSMarcel Moolenaar } 20064220a7eSMarcel Moolenaar } 20157467e59SMarcel Moolenaar } 20257467e59SMarcel Moolenaar 20357467e59SMarcel Moolenaar return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY); 20464220a7eSMarcel Moolenaar } 20564220a7eSMarcel Moolenaar 20664220a7eSMarcel Moolenaar int 20764220a7eSMarcel Moolenaar puc_bfe_attach(device_t dev) 20864220a7eSMarcel Moolenaar { 20964220a7eSMarcel Moolenaar char buffer[64]; 21064220a7eSMarcel Moolenaar struct puc_bar *bar; 21164220a7eSMarcel Moolenaar struct puc_port *port; 2129c564b6cSJohn Hay struct puc_softc *sc; 21364220a7eSMarcel Moolenaar struct rman *rm; 21464220a7eSMarcel Moolenaar intptr_t res; 21564220a7eSMarcel Moolenaar bus_addr_t ofs, start; 21664220a7eSMarcel Moolenaar bus_size_t size; 21764220a7eSMarcel Moolenaar bus_space_handle_t bsh; 21864220a7eSMarcel Moolenaar bus_space_tag_t bst; 21964220a7eSMarcel Moolenaar int error, idx; 2209c564b6cSJohn Hay 22164220a7eSMarcel Moolenaar sc = device_get_softc(dev); 22264220a7eSMarcel Moolenaar 22364220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) 22464220a7eSMarcel Moolenaar sc->sc_bar[idx].b_rid = -1; 22564220a7eSMarcel Moolenaar 22664220a7eSMarcel Moolenaar do { 22764220a7eSMarcel Moolenaar sc->sc_ioport.rm_type = RMAN_ARRAY; 22864220a7eSMarcel Moolenaar error = rman_init(&sc->sc_ioport); 22964220a7eSMarcel Moolenaar if (!error) { 23064220a7eSMarcel Moolenaar sc->sc_iomem.rm_type = RMAN_ARRAY; 23164220a7eSMarcel Moolenaar error = rman_init(&sc->sc_iomem); 23264220a7eSMarcel Moolenaar if (!error) { 23364220a7eSMarcel Moolenaar sc->sc_irq.rm_type = RMAN_ARRAY; 23464220a7eSMarcel Moolenaar error = rman_init(&sc->sc_irq); 23564220a7eSMarcel Moolenaar if (!error) 23664220a7eSMarcel Moolenaar break; 23764220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 23864220a7eSMarcel Moolenaar } 23964220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 24064220a7eSMarcel Moolenaar } 24164220a7eSMarcel Moolenaar return (error); 24264220a7eSMarcel Moolenaar } while (0); 24364220a7eSMarcel Moolenaar 24464220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O port mapping", 24564220a7eSMarcel Moolenaar device_get_nameunit(dev)); 24664220a7eSMarcel Moolenaar sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); 24764220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", 24864220a7eSMarcel Moolenaar device_get_nameunit(dev)); 24964220a7eSMarcel Moolenaar sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); 25064220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s port numbers", 25164220a7eSMarcel Moolenaar device_get_nameunit(dev)); 25264220a7eSMarcel Moolenaar sc->sc_irq.rm_descr = strdup(buffer, M_PUC); 25364220a7eSMarcel Moolenaar 25464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 25564220a7eSMarcel Moolenaar KASSERT(error == 0, ("%s %d", __func__, __LINE__)); 25664220a7eSMarcel Moolenaar sc->sc_nports = (int)res; 25764220a7eSMarcel Moolenaar sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), 25864220a7eSMarcel Moolenaar M_PUC, M_WAITOK|M_ZERO); 25964220a7eSMarcel Moolenaar 26064220a7eSMarcel Moolenaar error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); 26164220a7eSMarcel Moolenaar if (error) 26264220a7eSMarcel Moolenaar goto fail; 26364220a7eSMarcel Moolenaar 26464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_SETUP, 0, &res); 26564220a7eSMarcel Moolenaar if (error) 26664220a7eSMarcel Moolenaar goto fail; 26764220a7eSMarcel Moolenaar 26864220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 26964220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 27064220a7eSMarcel Moolenaar port->p_nr = idx + 1; 27164220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); 27264220a7eSMarcel Moolenaar if (error) 27364220a7eSMarcel Moolenaar goto fail; 27464220a7eSMarcel Moolenaar port->p_type = res; 27564220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); 27664220a7eSMarcel Moolenaar if (error) 27764220a7eSMarcel Moolenaar goto fail; 27864220a7eSMarcel Moolenaar bar = puc_get_bar(sc, res); 27964220a7eSMarcel Moolenaar if (bar == NULL) { 28064220a7eSMarcel Moolenaar error = ENXIO; 28164220a7eSMarcel Moolenaar goto fail; 28264220a7eSMarcel Moolenaar } 28364220a7eSMarcel Moolenaar port->p_bar = bar; 28464220a7eSMarcel Moolenaar start = rman_get_start(bar->b_res); 28564220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); 28664220a7eSMarcel Moolenaar if (error) 28764220a7eSMarcel Moolenaar goto fail; 28864220a7eSMarcel Moolenaar ofs = res; 28964220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); 29064220a7eSMarcel Moolenaar if (error) 29164220a7eSMarcel Moolenaar goto fail; 29264220a7eSMarcel Moolenaar size = res; 29364220a7eSMarcel Moolenaar rm = (bar->b_type == SYS_RES_IOPORT) 29464220a7eSMarcel Moolenaar ? &sc->sc_ioport: &sc->sc_iomem; 29564220a7eSMarcel Moolenaar port->p_rres = rman_reserve_resource(rm, start + ofs, 29664220a7eSMarcel Moolenaar start + ofs + size - 1, size, 0, NULL); 29764220a7eSMarcel Moolenaar if (port->p_rres != NULL) { 29864220a7eSMarcel Moolenaar bsh = rman_get_bushandle(bar->b_res); 29964220a7eSMarcel Moolenaar bst = rman_get_bustag(bar->b_res); 30064220a7eSMarcel Moolenaar bus_space_subregion(bst, bsh, ofs, size, &bsh); 30164220a7eSMarcel Moolenaar rman_set_bushandle(port->p_rres, bsh); 30264220a7eSMarcel Moolenaar rman_set_bustag(port->p_rres, bst); 30364220a7eSMarcel Moolenaar } 30464220a7eSMarcel Moolenaar port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, 30564220a7eSMarcel Moolenaar port->p_nr, 1, 0, NULL); 30664220a7eSMarcel Moolenaar if (port->p_ires == NULL) { 30764220a7eSMarcel Moolenaar error = ENXIO; 30864220a7eSMarcel Moolenaar goto fail; 30964220a7eSMarcel Moolenaar } 31064220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); 31164220a7eSMarcel Moolenaar if (error) 31264220a7eSMarcel Moolenaar goto fail; 31364220a7eSMarcel Moolenaar port->p_rclk = res; 31464220a7eSMarcel Moolenaar 31564220a7eSMarcel Moolenaar port->p_dev = device_add_child(dev, NULL, -1); 31664220a7eSMarcel Moolenaar if (port->p_dev != NULL) 31764220a7eSMarcel Moolenaar device_set_ivars(port->p_dev, (void *)port); 3189c564b6cSJohn Hay } 3199c564b6cSJohn Hay 32064220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); 32164220a7eSMarcel Moolenaar if (error) 32264220a7eSMarcel Moolenaar goto fail; 32364220a7eSMarcel Moolenaar sc->sc_ilr = res; 32464220a7eSMarcel Moolenaar if (bootverbose && sc->sc_ilr != 0) 32564220a7eSMarcel Moolenaar device_printf(dev, "using interrupt latch register\n"); 3269c564b6cSJohn Hay 32764220a7eSMarcel Moolenaar sc->sc_irid = 0; 32864220a7eSMarcel Moolenaar sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, 32964220a7eSMarcel Moolenaar RF_ACTIVE|RF_SHAREABLE); 33064220a7eSMarcel Moolenaar if (sc->sc_ires != NULL) { 33164220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 332ef544f63SPaolo Pisati INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); 33364220a7eSMarcel Moolenaar if (error) 33464220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 335ef544f63SPaolo Pisati INTR_TYPE_TTY | INTR_MPSAFE, NULL, 336ef544f63SPaolo Pisati (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); 33764220a7eSMarcel Moolenaar else 33864220a7eSMarcel Moolenaar sc->sc_fastintr = 1; 33964220a7eSMarcel Moolenaar 34064220a7eSMarcel Moolenaar if (error) { 34164220a7eSMarcel Moolenaar device_printf(dev, "could not activate interrupt\n"); 34264220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 34364220a7eSMarcel Moolenaar sc->sc_ires); 34464220a7eSMarcel Moolenaar sc->sc_ires = NULL; 34564220a7eSMarcel Moolenaar } 34664220a7eSMarcel Moolenaar } 34764220a7eSMarcel Moolenaar if (sc->sc_ires == NULL) { 34864220a7eSMarcel Moolenaar /* XXX no interrupt resource. Force polled mode. */ 34964220a7eSMarcel Moolenaar sc->sc_polled = 1; 3509c564b6cSJohn Hay } 3519c564b6cSJohn Hay 35264220a7eSMarcel Moolenaar /* Probe and attach our children. */ 35364220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 35464220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 35564220a7eSMarcel Moolenaar if (port->p_dev == NULL) 35664220a7eSMarcel Moolenaar continue; 35764220a7eSMarcel Moolenaar error = device_probe_and_attach(port->p_dev); 35864220a7eSMarcel Moolenaar if (error) { 35964220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 36064220a7eSMarcel Moolenaar port->p_dev = NULL; 3619c564b6cSJohn Hay } 36264220a7eSMarcel Moolenaar } 3639c564b6cSJohn Hay 364a3732274SDoug Ambrisko /* 36564220a7eSMarcel Moolenaar * If there are no serdev devices, then our interrupt handler 36664220a7eSMarcel Moolenaar * will do nothing. Tear it down. 367a3732274SDoug Ambrisko */ 36864220a7eSMarcel Moolenaar if (sc->sc_serdevs == 0UL) 36964220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 370a3732274SDoug Ambrisko 37164220a7eSMarcel Moolenaar return (0); 3729c564b6cSJohn Hay 37364220a7eSMarcel Moolenaar fail: 37464220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 37564220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 37664220a7eSMarcel Moolenaar if (port->p_dev != NULL) 37764220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 37864220a7eSMarcel Moolenaar if (port->p_rres != NULL) 37964220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 38064220a7eSMarcel Moolenaar if (port->p_ires != NULL) 38164220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 382a3732274SDoug Ambrisko } 38364220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 38464220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 38564220a7eSMarcel Moolenaar if (bar->b_res != NULL) 38664220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 38764220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 38864220a7eSMarcel Moolenaar } 38964220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 39064220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 39164220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 39264220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 39364220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 39464220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 39564220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 39664220a7eSMarcel Moolenaar return (error); 3979c564b6cSJohn Hay } 3989c564b6cSJohn Hay 39932f606d1SPoul-Henning Kamp int 40064220a7eSMarcel Moolenaar puc_bfe_detach(device_t dev) 40164220a7eSMarcel Moolenaar { 40264220a7eSMarcel Moolenaar struct puc_bar *bar; 40364220a7eSMarcel Moolenaar struct puc_port *port; 40464220a7eSMarcel Moolenaar struct puc_softc *sc; 40564220a7eSMarcel Moolenaar int error, idx; 40664220a7eSMarcel Moolenaar 40764220a7eSMarcel Moolenaar sc = device_get_softc(dev); 40864220a7eSMarcel Moolenaar 40964220a7eSMarcel Moolenaar /* Detach our children. */ 41064220a7eSMarcel Moolenaar error = 0; 41164220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 41264220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 41364220a7eSMarcel Moolenaar if (port->p_dev == NULL) 41464220a7eSMarcel Moolenaar continue; 41564220a7eSMarcel Moolenaar if (device_detach(port->p_dev) == 0) { 41664220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 41764220a7eSMarcel Moolenaar if (port->p_rres != NULL) 41864220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 41964220a7eSMarcel Moolenaar if (port->p_ires != NULL) 42064220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 42164220a7eSMarcel Moolenaar } else 42264220a7eSMarcel Moolenaar error = ENXIO; 42364220a7eSMarcel Moolenaar } 42464220a7eSMarcel Moolenaar if (error) 42564220a7eSMarcel Moolenaar return (error); 42664220a7eSMarcel Moolenaar 42764220a7eSMarcel Moolenaar if (sc->sc_serdevs != 0UL) 42864220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 42964220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); 43064220a7eSMarcel Moolenaar 43164220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 43264220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 43364220a7eSMarcel Moolenaar if (bar->b_res != NULL) 43464220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 43564220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 43664220a7eSMarcel Moolenaar } 43764220a7eSMarcel Moolenaar 43864220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 43964220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 44064220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 44164220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 44264220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 44364220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 44464220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 44564220a7eSMarcel Moolenaar return (0); 44664220a7eSMarcel Moolenaar } 44764220a7eSMarcel Moolenaar 44864220a7eSMarcel Moolenaar int 44964220a7eSMarcel Moolenaar puc_bfe_probe(device_t dev, const struct puc_cfg *cfg) 45064220a7eSMarcel Moolenaar { 45164220a7eSMarcel Moolenaar struct puc_softc *sc; 45264220a7eSMarcel Moolenaar intptr_t res; 45364220a7eSMarcel Moolenaar int error; 45464220a7eSMarcel Moolenaar 45564220a7eSMarcel Moolenaar sc = device_get_softc(dev); 45664220a7eSMarcel Moolenaar sc->sc_dev = dev; 45764220a7eSMarcel Moolenaar sc->sc_cfg = cfg; 45864220a7eSMarcel Moolenaar 45964220a7eSMarcel Moolenaar /* We don't attach to single-port serial cards. */ 46064220a7eSMarcel Moolenaar if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P) 46164220a7eSMarcel Moolenaar return (EDOOFUS); 46264220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 46364220a7eSMarcel Moolenaar if (error) 46464220a7eSMarcel Moolenaar return (error); 46564220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res); 46664220a7eSMarcel Moolenaar if (error) 46764220a7eSMarcel Moolenaar return (error); 46864220a7eSMarcel Moolenaar if (res != 0) 46964220a7eSMarcel Moolenaar device_set_desc(dev, (const char *)res); 47064220a7eSMarcel Moolenaar return (BUS_PROBE_DEFAULT); 47164220a7eSMarcel Moolenaar } 47264220a7eSMarcel Moolenaar 47364220a7eSMarcel Moolenaar struct resource * 47464220a7eSMarcel Moolenaar puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid, 47564220a7eSMarcel Moolenaar u_long start, u_long end, u_long count, u_int flags) 47664220a7eSMarcel Moolenaar { 47764220a7eSMarcel Moolenaar struct puc_port *port; 47864220a7eSMarcel Moolenaar struct resource *res; 47964220a7eSMarcel Moolenaar device_t assigned, originator; 48064220a7eSMarcel Moolenaar int error; 48164220a7eSMarcel Moolenaar 48264220a7eSMarcel Moolenaar /* Get our immediate child. */ 48364220a7eSMarcel Moolenaar originator = child; 48464220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 48564220a7eSMarcel Moolenaar child = device_get_parent(child); 48664220a7eSMarcel Moolenaar if (child == NULL) 48764220a7eSMarcel Moolenaar return (NULL); 48864220a7eSMarcel Moolenaar 48964220a7eSMarcel Moolenaar port = device_get_ivars(child); 49064220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 49164220a7eSMarcel Moolenaar 49264220a7eSMarcel Moolenaar if (rid == NULL || *rid != 0) 49364220a7eSMarcel Moolenaar return (NULL); 49464220a7eSMarcel Moolenaar 49564220a7eSMarcel Moolenaar /* We only support default allocations. */ 49664220a7eSMarcel Moolenaar if (start != 0UL || end != ~0UL) 49764220a7eSMarcel Moolenaar return (NULL); 49864220a7eSMarcel Moolenaar 49964220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 50064220a7eSMarcel Moolenaar res = port->p_rres; 50164220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 50264220a7eSMarcel Moolenaar res = port->p_ires; 50364220a7eSMarcel Moolenaar else 50464220a7eSMarcel Moolenaar return (NULL); 50564220a7eSMarcel Moolenaar 50664220a7eSMarcel Moolenaar if (res == NULL) 50764220a7eSMarcel Moolenaar return (NULL); 50864220a7eSMarcel Moolenaar 50964220a7eSMarcel Moolenaar assigned = rman_get_device(res); 51064220a7eSMarcel Moolenaar if (assigned == NULL) /* Not allocated */ 51164220a7eSMarcel Moolenaar rman_set_device(res, originator); 51264220a7eSMarcel Moolenaar else if (assigned != originator) 51364220a7eSMarcel Moolenaar return (NULL); 51464220a7eSMarcel Moolenaar 51564220a7eSMarcel Moolenaar if (flags & RF_ACTIVE) { 51664220a7eSMarcel Moolenaar error = rman_activate_resource(res); 51764220a7eSMarcel Moolenaar if (error) { 51864220a7eSMarcel Moolenaar if (assigned == NULL) 51964220a7eSMarcel Moolenaar rman_set_device(res, NULL); 52064220a7eSMarcel Moolenaar return (NULL); 52164220a7eSMarcel Moolenaar } 52264220a7eSMarcel Moolenaar } 52364220a7eSMarcel Moolenaar 52464220a7eSMarcel Moolenaar return (res); 52564220a7eSMarcel Moolenaar } 52664220a7eSMarcel Moolenaar 52764220a7eSMarcel Moolenaar int 52864220a7eSMarcel Moolenaar puc_bus_release_resource(device_t dev, device_t child, int type, int rid, 5299c564b6cSJohn Hay struct resource *res) 5309c564b6cSJohn Hay { 53164220a7eSMarcel Moolenaar struct puc_port *port; 53264220a7eSMarcel Moolenaar device_t originator; 53364220a7eSMarcel Moolenaar 53464220a7eSMarcel Moolenaar /* Get our immediate child. */ 53564220a7eSMarcel Moolenaar originator = child; 53664220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 53764220a7eSMarcel Moolenaar child = device_get_parent(child); 53864220a7eSMarcel Moolenaar if (child == NULL) 53964220a7eSMarcel Moolenaar return (EINVAL); 54064220a7eSMarcel Moolenaar 54164220a7eSMarcel Moolenaar port = device_get_ivars(child); 54264220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 54364220a7eSMarcel Moolenaar 54464220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 54564220a7eSMarcel Moolenaar return (EINVAL); 54664220a7eSMarcel Moolenaar 54764220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) { 54864220a7eSMarcel Moolenaar if (res != port->p_rres) 54964220a7eSMarcel Moolenaar return (EINVAL); 55064220a7eSMarcel Moolenaar } else if (type == SYS_RES_IRQ) { 55164220a7eSMarcel Moolenaar if (res != port->p_ires) 55264220a7eSMarcel Moolenaar return (EINVAL); 55364220a7eSMarcel Moolenaar if (port->p_hasintr) 55464220a7eSMarcel Moolenaar return (EBUSY); 55564220a7eSMarcel Moolenaar } else 55664220a7eSMarcel Moolenaar return (EINVAL); 55764220a7eSMarcel Moolenaar 55864220a7eSMarcel Moolenaar if (rman_get_device(res) != originator) 55964220a7eSMarcel Moolenaar return (ENXIO); 56064220a7eSMarcel Moolenaar if (rman_get_flags(res) & RF_ACTIVE) 56164220a7eSMarcel Moolenaar rman_deactivate_resource(res); 56264220a7eSMarcel Moolenaar rman_set_device(res, NULL); 5639c564b6cSJohn Hay return (0); 5649c564b6cSJohn Hay } 5659c564b6cSJohn Hay 56632f606d1SPoul-Henning Kamp int 56764220a7eSMarcel Moolenaar puc_bus_get_resource(device_t dev, device_t child, int type, int rid, 5689c564b6cSJohn Hay u_long *startp, u_long *countp) 5699c564b6cSJohn Hay { 57064220a7eSMarcel Moolenaar struct puc_port *port; 57164220a7eSMarcel Moolenaar struct resource *res; 57264220a7eSMarcel Moolenaar u_long start; 5739c564b6cSJohn Hay 57464220a7eSMarcel Moolenaar /* Get our immediate child. */ 57564220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 57664220a7eSMarcel Moolenaar child = device_get_parent(child); 57764220a7eSMarcel Moolenaar if (child == NULL) 57864220a7eSMarcel Moolenaar return (EINVAL); 5799c564b6cSJohn Hay 58064220a7eSMarcel Moolenaar port = device_get_ivars(child); 58164220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 58264220a7eSMarcel Moolenaar 58364220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 58464220a7eSMarcel Moolenaar res = port->p_rres; 58564220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 58664220a7eSMarcel Moolenaar res = port->p_ires; 58764220a7eSMarcel Moolenaar else 58864220a7eSMarcel Moolenaar return (ENXIO); 58964220a7eSMarcel Moolenaar 59064220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 59164220a7eSMarcel Moolenaar return (ENXIO); 59264220a7eSMarcel Moolenaar 59364220a7eSMarcel Moolenaar start = rman_get_start(res); 5949c564b6cSJohn Hay if (startp != NULL) 59564220a7eSMarcel Moolenaar *startp = start; 5969c564b6cSJohn Hay if (countp != NULL) 59764220a7eSMarcel Moolenaar *countp = rman_get_end(res) - start + 1; 5989c564b6cSJohn Hay return (0); 5999c564b6cSJohn Hay } 6009c564b6cSJohn Hay 60132f606d1SPoul-Henning Kamp int 60264220a7eSMarcel Moolenaar puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, 603ef544f63SPaolo Pisati int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) 6049c564b6cSJohn Hay { 60564220a7eSMarcel Moolenaar struct puc_port *port; 6069c564b6cSJohn Hay struct puc_softc *sc; 60764220a7eSMarcel Moolenaar device_t originator; 60864220a7eSMarcel Moolenaar int i, isrc, serdev; 6099c564b6cSJohn Hay 61064220a7eSMarcel Moolenaar sc = device_get_softc(dev); 61164220a7eSMarcel Moolenaar 61264220a7eSMarcel Moolenaar /* Get our immediate child. */ 61364220a7eSMarcel Moolenaar originator = child; 61464220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 61564220a7eSMarcel Moolenaar child = device_get_parent(child); 61664220a7eSMarcel Moolenaar if (child == NULL) 61764220a7eSMarcel Moolenaar return (EINVAL); 61864220a7eSMarcel Moolenaar 61964220a7eSMarcel Moolenaar port = device_get_ivars(child); 62064220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 62164220a7eSMarcel Moolenaar 6228d715a35SPaolo Pisati if (cookiep == NULL || res != port->p_ires) 62364220a7eSMarcel Moolenaar return (EINVAL); 6248d715a35SPaolo Pisati /* We demand that serdev devices use filter_only interrupts. */ 625*323e149aSJohn Baldwin if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL) 6268d715a35SPaolo Pisati return (ENXIO); 62764220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 628d3c10e33SPoul-Henning Kamp return (ENXIO); 62964220a7eSMarcel Moolenaar 63064220a7eSMarcel Moolenaar /* 63164220a7eSMarcel Moolenaar * Have non-serdev ports handled by the bus implementation. It 63264220a7eSMarcel Moolenaar * supports multiple handlers for a single interrupt as it is, 63364220a7eSMarcel Moolenaar * so we wouldn't add value if we did it ourselves. 63464220a7eSMarcel Moolenaar */ 63564220a7eSMarcel Moolenaar serdev = 0; 63664220a7eSMarcel Moolenaar if (port->p_type == PUC_TYPE_SERIAL) { 63764220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 63864220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT) { 63964220a7eSMarcel Moolenaar port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc); 64064220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 64164220a7eSMarcel Moolenaar serdev = 1; 64264220a7eSMarcel Moolenaar i++, isrc <<= 1; 64364220a7eSMarcel Moolenaar } 64464220a7eSMarcel Moolenaar } 64564220a7eSMarcel Moolenaar if (!serdev) 64664220a7eSMarcel Moolenaar return (BUS_SETUP_INTR(device_get_parent(dev), originator, 647ef544f63SPaolo Pisati sc->sc_ires, flags, filt, ihand, arg, cookiep)); 64864220a7eSMarcel Moolenaar 64964220a7eSMarcel Moolenaar sc->sc_serdevs |= 1UL << (port->p_nr - 1); 65064220a7eSMarcel Moolenaar 65164220a7eSMarcel Moolenaar port->p_hasintr = 1; 65264220a7eSMarcel Moolenaar port->p_iharg = arg; 65364220a7eSMarcel Moolenaar 65464220a7eSMarcel Moolenaar *cookiep = port; 6559c564b6cSJohn Hay return (0); 6569c564b6cSJohn Hay } 6579c564b6cSJohn Hay 65832f606d1SPoul-Henning Kamp int 65964220a7eSMarcel Moolenaar puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res, 6609c564b6cSJohn Hay void *cookie) 6619c564b6cSJohn Hay { 66264220a7eSMarcel Moolenaar struct puc_port *port; 6639c564b6cSJohn Hay struct puc_softc *sc; 66464220a7eSMarcel Moolenaar device_t originator; 66564220a7eSMarcel Moolenaar int i; 6669c564b6cSJohn Hay 66764220a7eSMarcel Moolenaar sc = device_get_softc(dev); 66864220a7eSMarcel Moolenaar 66964220a7eSMarcel Moolenaar /* Get our immediate child. */ 67064220a7eSMarcel Moolenaar originator = child; 67164220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 67264220a7eSMarcel Moolenaar child = device_get_parent(child); 67364220a7eSMarcel Moolenaar if (child == NULL) 67464220a7eSMarcel Moolenaar return (EINVAL); 67564220a7eSMarcel Moolenaar 67664220a7eSMarcel Moolenaar port = device_get_ivars(child); 67764220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 67864220a7eSMarcel Moolenaar 67964220a7eSMarcel Moolenaar if (res != port->p_ires) 68064220a7eSMarcel Moolenaar return (EINVAL); 68164220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 6829c564b6cSJohn Hay return (ENXIO); 68364220a7eSMarcel Moolenaar 68464220a7eSMarcel Moolenaar if (!port->p_hasintr) 68564220a7eSMarcel Moolenaar return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator, 68664220a7eSMarcel Moolenaar sc->sc_ires, cookie)); 68764220a7eSMarcel Moolenaar 68864220a7eSMarcel Moolenaar if (cookie != port) 68964220a7eSMarcel Moolenaar return (EINVAL); 69064220a7eSMarcel Moolenaar 69164220a7eSMarcel Moolenaar port->p_hasintr = 0; 69264220a7eSMarcel Moolenaar port->p_iharg = NULL; 69364220a7eSMarcel Moolenaar 69464220a7eSMarcel Moolenaar for (i = 0; i < PUC_ISRCCNT; i++) 69564220a7eSMarcel Moolenaar port->p_ihsrc[i] = NULL; 69664220a7eSMarcel Moolenaar 69764220a7eSMarcel Moolenaar return (0); 6989c564b6cSJohn Hay } 6999c564b6cSJohn Hay 70032f606d1SPoul-Henning Kamp int 70164220a7eSMarcel Moolenaar puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 7029c564b6cSJohn Hay { 70364220a7eSMarcel Moolenaar struct puc_port *port; 7049c564b6cSJohn Hay 70564220a7eSMarcel Moolenaar /* Get our immediate child. */ 70664220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 70764220a7eSMarcel Moolenaar child = device_get_parent(child); 70864220a7eSMarcel Moolenaar if (child == NULL) 70964220a7eSMarcel Moolenaar return (EINVAL); 71064220a7eSMarcel Moolenaar 71164220a7eSMarcel Moolenaar port = device_get_ivars(child); 71264220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 71364220a7eSMarcel Moolenaar 71464220a7eSMarcel Moolenaar if (result == NULL) 71564220a7eSMarcel Moolenaar return (EINVAL); 7169c564b6cSJohn Hay 7179c564b6cSJohn Hay switch(index) { 71864220a7eSMarcel Moolenaar case PUC_IVAR_CLOCK: 71964220a7eSMarcel Moolenaar *result = port->p_rclk; 7209c564b6cSJohn Hay break; 72164220a7eSMarcel Moolenaar case PUC_IVAR_TYPE: 72264220a7eSMarcel Moolenaar *result = port->p_type; 723153bbe3eSMarcel Moolenaar break; 7249c564b6cSJohn Hay default: 7259c564b6cSJohn Hay return (ENOENT); 7269c564b6cSJohn Hay } 7279c564b6cSJohn Hay return (0); 7289c564b6cSJohn Hay } 729573e64d4SJohn Baldwin 730573e64d4SJohn Baldwin int 731573e64d4SJohn Baldwin puc_bus_print_child(device_t dev, device_t child) 732573e64d4SJohn Baldwin { 733573e64d4SJohn Baldwin struct puc_port *port; 734573e64d4SJohn Baldwin int retval; 735573e64d4SJohn Baldwin 736573e64d4SJohn Baldwin port = device_get_ivars(child); 737573e64d4SJohn Baldwin retval = 0; 738573e64d4SJohn Baldwin 739573e64d4SJohn Baldwin retval += bus_print_child_header(dev, child); 740573e64d4SJohn Baldwin retval += printf(" at port %d", port->p_nr); 741573e64d4SJohn Baldwin retval += bus_print_child_footer(dev, child); 742573e64d4SJohn Baldwin 743573e64d4SJohn Baldwin return (retval); 744573e64d4SJohn Baldwin } 745573e64d4SJohn Baldwin 746573e64d4SJohn Baldwin int 747573e64d4SJohn Baldwin puc_bus_child_location_str(device_t dev, device_t child, char *buf, 748573e64d4SJohn Baldwin size_t buflen) 749573e64d4SJohn Baldwin { 750573e64d4SJohn Baldwin struct puc_port *port; 751573e64d4SJohn Baldwin 752573e64d4SJohn Baldwin port = device_get_ivars(child); 753573e64d4SJohn Baldwin snprintf(buf, buflen, "port=%d", port->p_nr); 754573e64d4SJohn Baldwin return (0); 755573e64d4SJohn Baldwin } 756573e64d4SJohn Baldwin 757573e64d4SJohn Baldwin int 758573e64d4SJohn Baldwin puc_bus_child_pnpinfo_str(device_t dev, device_t child, char *buf, 759573e64d4SJohn Baldwin size_t buflen) 760573e64d4SJohn Baldwin { 761573e64d4SJohn Baldwin struct puc_port *port; 762573e64d4SJohn Baldwin 763573e64d4SJohn Baldwin port = device_get_ivars(child); 764573e64d4SJohn Baldwin snprintf(buf, buflen, "type=%d", port->p_type); 765573e64d4SJohn Baldwin return (0); 766573e64d4SJohn Baldwin } 767