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> 379725900bSRyan Stone #include <sys/sysctl.h> 389c564b6cSJohn Hay 399c564b6cSJohn Hay #include <machine/bus.h> 409c564b6cSJohn Hay #include <machine/resource.h> 419c564b6cSJohn Hay #include <sys/rman.h> 429c564b6cSJohn Hay 439c564b6cSJohn Hay #include <dev/pci/pcireg.h> 449c564b6cSJohn Hay #include <dev/pci/pcivar.h> 4532f606d1SPoul-Henning Kamp 4664220a7eSMarcel Moolenaar #include <dev/puc/puc_bus.h> 4764220a7eSMarcel Moolenaar #include <dev/puc/puc_cfg.h> 48482aa6a3SDavid E. O'Brien #include <dev/puc/puc_bfe.h> 499c564b6cSJohn Hay 5064220a7eSMarcel Moolenaar #define PUC_ISRCCNT 5 5164220a7eSMarcel Moolenaar 5264220a7eSMarcel Moolenaar struct puc_port { 5364220a7eSMarcel Moolenaar struct puc_bar *p_bar; 5464220a7eSMarcel Moolenaar struct resource *p_rres; 5564220a7eSMarcel Moolenaar struct resource *p_ires; 5664220a7eSMarcel Moolenaar device_t p_dev; 5764220a7eSMarcel Moolenaar int p_nr; 5864220a7eSMarcel Moolenaar int p_type; 5964220a7eSMarcel Moolenaar int p_rclk; 6064220a7eSMarcel Moolenaar 6164220a7eSMarcel Moolenaar int p_hasintr:1; 6264220a7eSMarcel Moolenaar 6364220a7eSMarcel Moolenaar serdev_intr_t *p_ihsrc[PUC_ISRCCNT]; 6464220a7eSMarcel Moolenaar void *p_iharg; 6564220a7eSMarcel Moolenaar 6664220a7eSMarcel Moolenaar int p_ipend; 679c564b6cSJohn Hay }; 689c564b6cSJohn Hay 69c9168019SPoul-Henning Kamp devclass_t puc_devclass; 7064220a7eSMarcel Moolenaar const char puc_driver_name[] = "puc"; 71c9168019SPoul-Henning Kamp 72d745c852SEd Schouten static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver"); 7364220a7eSMarcel Moolenaar 749725900bSRyan Stone SYSCTL_NODE(_hw, OID_AUTO, puc, CTLFLAG_RD, 0, "puc(9) driver configuration"); 759725900bSRyan Stone 7664220a7eSMarcel Moolenaar struct puc_bar * 7764220a7eSMarcel Moolenaar puc_get_bar(struct puc_softc *sc, int rid) 781e89655aSPoul-Henning Kamp { 7964220a7eSMarcel Moolenaar struct puc_bar *bar; 8064220a7eSMarcel Moolenaar struct rman *rm; 812dd1bdf1SJustin Hibbits rman_res_t end, start; 8264220a7eSMarcel Moolenaar int error, i; 831e89655aSPoul-Henning Kamp 8464220a7eSMarcel Moolenaar /* Find the BAR entry with the given RID. */ 8564220a7eSMarcel Moolenaar i = 0; 8664220a7eSMarcel Moolenaar while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid) 8764220a7eSMarcel Moolenaar i++; 8864220a7eSMarcel Moolenaar if (i < PUC_PCI_BARS) 8964220a7eSMarcel Moolenaar return (&sc->sc_bar[i]); 901e89655aSPoul-Henning Kamp 9164220a7eSMarcel Moolenaar /* Not found. If we're looking for an unused entry, return NULL. */ 9264220a7eSMarcel Moolenaar if (rid == -1) 9364220a7eSMarcel Moolenaar return (NULL); 94084254f8SMaxim Sobolev 9564220a7eSMarcel Moolenaar /* Get an unused entry for us to fill. */ 9664220a7eSMarcel Moolenaar bar = puc_get_bar(sc, -1); 9764220a7eSMarcel Moolenaar if (bar == NULL) 9864220a7eSMarcel Moolenaar return (NULL); 9964220a7eSMarcel Moolenaar bar->b_rid = rid; 10064220a7eSMarcel Moolenaar bar->b_type = SYS_RES_IOPORT; 10164220a7eSMarcel Moolenaar bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 10264220a7eSMarcel Moolenaar &bar->b_rid, RF_ACTIVE); 10364220a7eSMarcel Moolenaar if (bar->b_res == NULL) { 10464220a7eSMarcel Moolenaar bar->b_rid = rid; 10564220a7eSMarcel Moolenaar bar->b_type = SYS_RES_MEMORY; 10664220a7eSMarcel Moolenaar bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, 10764220a7eSMarcel Moolenaar &bar->b_rid, RF_ACTIVE); 10864220a7eSMarcel Moolenaar if (bar->b_res == NULL) { 10964220a7eSMarcel Moolenaar bar->b_rid = -1; 11064220a7eSMarcel Moolenaar return (NULL); 1115aa967d9SYoshihiro Takahashi } 1125aa967d9SYoshihiro Takahashi } 11364220a7eSMarcel Moolenaar 11464220a7eSMarcel Moolenaar /* Update our managed space. */ 11564220a7eSMarcel Moolenaar rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem; 11664220a7eSMarcel Moolenaar start = rman_get_start(bar->b_res); 11764220a7eSMarcel Moolenaar end = rman_get_end(bar->b_res); 11864220a7eSMarcel Moolenaar error = rman_manage_region(rm, start, end); 11964220a7eSMarcel Moolenaar if (error) { 12064220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, 12164220a7eSMarcel Moolenaar bar->b_res); 12264220a7eSMarcel Moolenaar bar->b_res = NULL; 12364220a7eSMarcel Moolenaar bar->b_rid = -1; 12464220a7eSMarcel Moolenaar bar = NULL; 1259c564b6cSJohn Hay } 1269c564b6cSJohn Hay 12764220a7eSMarcel Moolenaar return (bar); 1289c564b6cSJohn Hay } 1299c564b6cSJohn Hay 130ef544f63SPaolo Pisati static int 1319c564b6cSJohn Hay puc_intr(void *arg) 1329c564b6cSJohn Hay { 13364220a7eSMarcel Moolenaar struct puc_port *port; 13464220a7eSMarcel Moolenaar struct puc_softc *sc = arg; 13557467e59SMarcel Moolenaar u_long ds, dev, devs; 13657467e59SMarcel Moolenaar int i, idx, ipend, isrc, nints; 13764220a7eSMarcel Moolenaar uint8_t ilr; 13864220a7eSMarcel Moolenaar 13957467e59SMarcel Moolenaar nints = 0; 14057467e59SMarcel Moolenaar while (1) { 14157467e59SMarcel Moolenaar /* 14257467e59SMarcel Moolenaar * Obtain the set of devices with pending interrupts. 14357467e59SMarcel Moolenaar */ 14464220a7eSMarcel Moolenaar devs = sc->sc_serdevs; 14564220a7eSMarcel Moolenaar if (sc->sc_ilr == PUC_ILR_DIGI) { 14664220a7eSMarcel Moolenaar idx = 0; 14764220a7eSMarcel Moolenaar while (devs & (0xfful << idx)) { 14864220a7eSMarcel Moolenaar ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7); 14964220a7eSMarcel Moolenaar devs &= ~0ul ^ ((u_long)ilr << idx); 15064220a7eSMarcel Moolenaar idx += 8; 15164220a7eSMarcel Moolenaar } 15264220a7eSMarcel Moolenaar } else if (sc->sc_ilr == PUC_ILR_QUATECH) { 15364220a7eSMarcel Moolenaar /* 15464220a7eSMarcel Moolenaar * Don't trust the value if it's the same as the option 15564220a7eSMarcel Moolenaar * register. It may mean that the ILR is not active and 15664220a7eSMarcel Moolenaar * we're reading the option register instead. This may 15764220a7eSMarcel Moolenaar * lead to false positives on 8-port boards. 15864220a7eSMarcel Moolenaar */ 15964220a7eSMarcel Moolenaar ilr = bus_read_1(sc->sc_port[0].p_rres, 7); 16064220a7eSMarcel Moolenaar if (ilr != (sc->sc_cfg_data & 0xff)) 16164220a7eSMarcel Moolenaar devs &= (u_long)ilr; 16264220a7eSMarcel Moolenaar } 16357467e59SMarcel Moolenaar if (devs == 0UL) 16457467e59SMarcel Moolenaar break; 16564220a7eSMarcel Moolenaar 16657467e59SMarcel Moolenaar /* 16757467e59SMarcel Moolenaar * Obtain the set of interrupt sources from those devices 16857467e59SMarcel Moolenaar * that have pending interrupts. 16957467e59SMarcel Moolenaar */ 17064220a7eSMarcel Moolenaar ipend = 0; 17164220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 17257467e59SMarcel Moolenaar ds = devs; 17357467e59SMarcel Moolenaar while (ds != 0UL) { 17457467e59SMarcel Moolenaar while ((ds & dev) == 0UL) 17564220a7eSMarcel Moolenaar idx++, dev <<= 1; 17657467e59SMarcel Moolenaar ds &= ~dev; 17764220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 17864220a7eSMarcel Moolenaar port->p_ipend = SERDEV_IPEND(port->p_dev); 17964220a7eSMarcel Moolenaar ipend |= port->p_ipend; 18064220a7eSMarcel Moolenaar } 18157467e59SMarcel Moolenaar if (ipend == 0) 18257467e59SMarcel Moolenaar break; 18364220a7eSMarcel Moolenaar 18464220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 18564220a7eSMarcel Moolenaar while (ipend) { 18664220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT && !(ipend & isrc)) 18764220a7eSMarcel Moolenaar i++, isrc <<= 1; 18864220a7eSMarcel Moolenaar KASSERT(i < PUC_ISRCCNT, ("%s", __func__)); 18964220a7eSMarcel Moolenaar ipend &= ~isrc; 19064220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 19157467e59SMarcel Moolenaar ds = devs; 19257467e59SMarcel Moolenaar while (ds != 0UL) { 19357467e59SMarcel Moolenaar while ((ds & dev) == 0UL) 19464220a7eSMarcel Moolenaar idx++, dev <<= 1; 19557467e59SMarcel Moolenaar ds &= ~dev; 19664220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 19764220a7eSMarcel Moolenaar if (!(port->p_ipend & isrc)) 19864220a7eSMarcel Moolenaar continue; 19964220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 20064220a7eSMarcel Moolenaar (*port->p_ihsrc[i])(port->p_iharg); 20157467e59SMarcel Moolenaar nints++; 20264220a7eSMarcel Moolenaar } 20364220a7eSMarcel Moolenaar } 20457467e59SMarcel Moolenaar } 20557467e59SMarcel Moolenaar 20657467e59SMarcel Moolenaar return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY); 20764220a7eSMarcel Moolenaar } 20864220a7eSMarcel Moolenaar 20964220a7eSMarcel Moolenaar int 21064220a7eSMarcel Moolenaar puc_bfe_attach(device_t dev) 21164220a7eSMarcel Moolenaar { 21264220a7eSMarcel Moolenaar char buffer[64]; 21364220a7eSMarcel Moolenaar struct puc_bar *bar; 21464220a7eSMarcel Moolenaar struct puc_port *port; 2159c564b6cSJohn Hay struct puc_softc *sc; 21664220a7eSMarcel Moolenaar struct rman *rm; 21764220a7eSMarcel Moolenaar intptr_t res; 21864220a7eSMarcel Moolenaar bus_addr_t ofs, start; 21964220a7eSMarcel Moolenaar bus_size_t size; 22064220a7eSMarcel Moolenaar bus_space_handle_t bsh; 22164220a7eSMarcel Moolenaar bus_space_tag_t bst; 22264220a7eSMarcel Moolenaar int error, idx; 2239c564b6cSJohn Hay 22464220a7eSMarcel Moolenaar sc = device_get_softc(dev); 22564220a7eSMarcel Moolenaar 22664220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) 22764220a7eSMarcel Moolenaar sc->sc_bar[idx].b_rid = -1; 22864220a7eSMarcel Moolenaar 22964220a7eSMarcel Moolenaar do { 23064220a7eSMarcel Moolenaar sc->sc_ioport.rm_type = RMAN_ARRAY; 23164220a7eSMarcel Moolenaar error = rman_init(&sc->sc_ioport); 23264220a7eSMarcel Moolenaar if (!error) { 23364220a7eSMarcel Moolenaar sc->sc_iomem.rm_type = RMAN_ARRAY; 23464220a7eSMarcel Moolenaar error = rman_init(&sc->sc_iomem); 23564220a7eSMarcel Moolenaar if (!error) { 23664220a7eSMarcel Moolenaar sc->sc_irq.rm_type = RMAN_ARRAY; 23764220a7eSMarcel Moolenaar error = rman_init(&sc->sc_irq); 23864220a7eSMarcel Moolenaar if (!error) 23964220a7eSMarcel Moolenaar break; 24064220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 24164220a7eSMarcel Moolenaar } 24264220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 24364220a7eSMarcel Moolenaar } 24464220a7eSMarcel Moolenaar return (error); 24564220a7eSMarcel Moolenaar } while (0); 24664220a7eSMarcel Moolenaar 24764220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O port mapping", 24864220a7eSMarcel Moolenaar device_get_nameunit(dev)); 24964220a7eSMarcel Moolenaar sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); 25064220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", 25164220a7eSMarcel Moolenaar device_get_nameunit(dev)); 25264220a7eSMarcel Moolenaar sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); 25364220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s port numbers", 25464220a7eSMarcel Moolenaar device_get_nameunit(dev)); 25564220a7eSMarcel Moolenaar sc->sc_irq.rm_descr = strdup(buffer, M_PUC); 25664220a7eSMarcel Moolenaar 25764220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 25864220a7eSMarcel Moolenaar KASSERT(error == 0, ("%s %d", __func__, __LINE__)); 25964220a7eSMarcel Moolenaar sc->sc_nports = (int)res; 26064220a7eSMarcel Moolenaar sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), 26164220a7eSMarcel Moolenaar M_PUC, M_WAITOK|M_ZERO); 26264220a7eSMarcel Moolenaar 26364220a7eSMarcel Moolenaar error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); 26464220a7eSMarcel Moolenaar if (error) 26564220a7eSMarcel Moolenaar goto fail; 26664220a7eSMarcel Moolenaar 26764220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_SETUP, 0, &res); 26864220a7eSMarcel Moolenaar if (error) 26964220a7eSMarcel Moolenaar goto fail; 27064220a7eSMarcel Moolenaar 27164220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 27264220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 27364220a7eSMarcel Moolenaar port->p_nr = idx + 1; 27464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); 27564220a7eSMarcel Moolenaar if (error) 27664220a7eSMarcel Moolenaar goto fail; 27764220a7eSMarcel Moolenaar port->p_type = res; 27864220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); 27964220a7eSMarcel Moolenaar if (error) 28064220a7eSMarcel Moolenaar goto fail; 28164220a7eSMarcel Moolenaar bar = puc_get_bar(sc, res); 28264220a7eSMarcel Moolenaar if (bar == NULL) { 28364220a7eSMarcel Moolenaar error = ENXIO; 28464220a7eSMarcel Moolenaar goto fail; 28564220a7eSMarcel Moolenaar } 28664220a7eSMarcel Moolenaar port->p_bar = bar; 28764220a7eSMarcel Moolenaar start = rman_get_start(bar->b_res); 28864220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); 28964220a7eSMarcel Moolenaar if (error) 29064220a7eSMarcel Moolenaar goto fail; 29164220a7eSMarcel Moolenaar ofs = res; 29264220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); 29364220a7eSMarcel Moolenaar if (error) 29464220a7eSMarcel Moolenaar goto fail; 29564220a7eSMarcel Moolenaar size = res; 29664220a7eSMarcel Moolenaar rm = (bar->b_type == SYS_RES_IOPORT) 29764220a7eSMarcel Moolenaar ? &sc->sc_ioport: &sc->sc_iomem; 29864220a7eSMarcel Moolenaar port->p_rres = rman_reserve_resource(rm, start + ofs, 29964220a7eSMarcel Moolenaar start + ofs + size - 1, size, 0, NULL); 30064220a7eSMarcel Moolenaar if (port->p_rres != NULL) { 30164220a7eSMarcel Moolenaar bsh = rman_get_bushandle(bar->b_res); 30264220a7eSMarcel Moolenaar bst = rman_get_bustag(bar->b_res); 30364220a7eSMarcel Moolenaar bus_space_subregion(bst, bsh, ofs, size, &bsh); 30464220a7eSMarcel Moolenaar rman_set_bushandle(port->p_rres, bsh); 30564220a7eSMarcel Moolenaar rman_set_bustag(port->p_rres, bst); 30664220a7eSMarcel Moolenaar } 30764220a7eSMarcel Moolenaar port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, 30864220a7eSMarcel Moolenaar port->p_nr, 1, 0, NULL); 30964220a7eSMarcel Moolenaar if (port->p_ires == NULL) { 31064220a7eSMarcel Moolenaar error = ENXIO; 31164220a7eSMarcel Moolenaar goto fail; 31264220a7eSMarcel Moolenaar } 31364220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); 31464220a7eSMarcel Moolenaar if (error) 31564220a7eSMarcel Moolenaar goto fail; 31664220a7eSMarcel Moolenaar port->p_rclk = res; 31764220a7eSMarcel Moolenaar 31864220a7eSMarcel Moolenaar port->p_dev = device_add_child(dev, NULL, -1); 31964220a7eSMarcel Moolenaar if (port->p_dev != NULL) 32064220a7eSMarcel Moolenaar device_set_ivars(port->p_dev, (void *)port); 3219c564b6cSJohn Hay } 3229c564b6cSJohn Hay 32364220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); 32464220a7eSMarcel Moolenaar if (error) 32564220a7eSMarcel Moolenaar goto fail; 32664220a7eSMarcel Moolenaar sc->sc_ilr = res; 32764220a7eSMarcel Moolenaar if (bootverbose && sc->sc_ilr != 0) 32864220a7eSMarcel Moolenaar device_printf(dev, "using interrupt latch register\n"); 3299c564b6cSJohn Hay 33064220a7eSMarcel Moolenaar sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, 33164220a7eSMarcel Moolenaar RF_ACTIVE|RF_SHAREABLE); 33264220a7eSMarcel Moolenaar if (sc->sc_ires != NULL) { 33364220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 334ef544f63SPaolo Pisati INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); 33564220a7eSMarcel Moolenaar if (error) 33664220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 337ef544f63SPaolo Pisati INTR_TYPE_TTY | INTR_MPSAFE, NULL, 338ef544f63SPaolo Pisati (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); 33964220a7eSMarcel Moolenaar else 34064220a7eSMarcel Moolenaar sc->sc_fastintr = 1; 34164220a7eSMarcel Moolenaar 34264220a7eSMarcel Moolenaar if (error) { 34364220a7eSMarcel Moolenaar device_printf(dev, "could not activate interrupt\n"); 34464220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 34564220a7eSMarcel Moolenaar sc->sc_ires); 34664220a7eSMarcel Moolenaar sc->sc_ires = NULL; 34764220a7eSMarcel Moolenaar } 34864220a7eSMarcel Moolenaar } 34964220a7eSMarcel Moolenaar if (sc->sc_ires == NULL) { 35064220a7eSMarcel Moolenaar /* XXX no interrupt resource. Force polled mode. */ 35164220a7eSMarcel Moolenaar sc->sc_polled = 1; 3529c564b6cSJohn Hay } 3539c564b6cSJohn Hay 35464220a7eSMarcel Moolenaar /* Probe and attach our children. */ 35564220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 35664220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 35764220a7eSMarcel Moolenaar if (port->p_dev == NULL) 35864220a7eSMarcel Moolenaar continue; 35964220a7eSMarcel Moolenaar error = device_probe_and_attach(port->p_dev); 36064220a7eSMarcel Moolenaar if (error) { 36164220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 36264220a7eSMarcel Moolenaar port->p_dev = NULL; 3639c564b6cSJohn Hay } 36464220a7eSMarcel Moolenaar } 3659c564b6cSJohn Hay 366a3732274SDoug Ambrisko /* 36764220a7eSMarcel Moolenaar * If there are no serdev devices, then our interrupt handler 36864220a7eSMarcel Moolenaar * will do nothing. Tear it down. 369a3732274SDoug Ambrisko */ 37064220a7eSMarcel Moolenaar if (sc->sc_serdevs == 0UL) 37164220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 372a3732274SDoug Ambrisko 37364220a7eSMarcel Moolenaar return (0); 3749c564b6cSJohn Hay 37564220a7eSMarcel Moolenaar fail: 37664220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 37764220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 37864220a7eSMarcel Moolenaar if (port->p_dev != NULL) 37964220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 38064220a7eSMarcel Moolenaar if (port->p_rres != NULL) 38164220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 38264220a7eSMarcel Moolenaar if (port->p_ires != NULL) 38364220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 384a3732274SDoug Ambrisko } 38564220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 38664220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 38764220a7eSMarcel Moolenaar if (bar->b_res != NULL) 38864220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 38964220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 39064220a7eSMarcel Moolenaar } 39164220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 39264220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 39364220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 39464220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 39564220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 39664220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 39764220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 39864220a7eSMarcel Moolenaar return (error); 3999c564b6cSJohn Hay } 4009c564b6cSJohn Hay 40132f606d1SPoul-Henning Kamp int 40264220a7eSMarcel Moolenaar puc_bfe_detach(device_t dev) 40364220a7eSMarcel Moolenaar { 40464220a7eSMarcel Moolenaar struct puc_bar *bar; 40564220a7eSMarcel Moolenaar struct puc_port *port; 40664220a7eSMarcel Moolenaar struct puc_softc *sc; 40764220a7eSMarcel Moolenaar int error, idx; 40864220a7eSMarcel Moolenaar 40964220a7eSMarcel Moolenaar sc = device_get_softc(dev); 41064220a7eSMarcel Moolenaar 41164220a7eSMarcel Moolenaar /* Detach our children. */ 41264220a7eSMarcel Moolenaar error = 0; 41364220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 41464220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 41564220a7eSMarcel Moolenaar if (port->p_dev == NULL) 41664220a7eSMarcel Moolenaar continue; 41764220a7eSMarcel Moolenaar if (device_detach(port->p_dev) == 0) { 41864220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 41964220a7eSMarcel Moolenaar if (port->p_rres != NULL) 42064220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 42164220a7eSMarcel Moolenaar if (port->p_ires != NULL) 42264220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 42364220a7eSMarcel Moolenaar } else 42464220a7eSMarcel Moolenaar error = ENXIO; 42564220a7eSMarcel Moolenaar } 42664220a7eSMarcel Moolenaar if (error) 42764220a7eSMarcel Moolenaar return (error); 42864220a7eSMarcel Moolenaar 42964220a7eSMarcel Moolenaar if (sc->sc_serdevs != 0UL) 43064220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 43164220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); 43264220a7eSMarcel Moolenaar 43364220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 43464220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 43564220a7eSMarcel Moolenaar if (bar->b_res != NULL) 43664220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 43764220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 43864220a7eSMarcel Moolenaar } 43964220a7eSMarcel Moolenaar 44064220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 44164220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 44264220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 44364220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 44464220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 44564220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 44664220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 44764220a7eSMarcel Moolenaar return (0); 44864220a7eSMarcel Moolenaar } 44964220a7eSMarcel Moolenaar 45064220a7eSMarcel Moolenaar int 45164220a7eSMarcel Moolenaar puc_bfe_probe(device_t dev, const struct puc_cfg *cfg) 45264220a7eSMarcel Moolenaar { 45364220a7eSMarcel Moolenaar struct puc_softc *sc; 45464220a7eSMarcel Moolenaar intptr_t res; 45564220a7eSMarcel Moolenaar int error; 45664220a7eSMarcel Moolenaar 45764220a7eSMarcel Moolenaar sc = device_get_softc(dev); 45864220a7eSMarcel Moolenaar sc->sc_dev = dev; 45964220a7eSMarcel Moolenaar sc->sc_cfg = cfg; 46064220a7eSMarcel Moolenaar 46164220a7eSMarcel Moolenaar /* We don't attach to single-port serial cards. */ 46264220a7eSMarcel Moolenaar if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P) 46364220a7eSMarcel Moolenaar return (EDOOFUS); 46464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 46564220a7eSMarcel Moolenaar if (error) 46664220a7eSMarcel Moolenaar return (error); 46764220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res); 46864220a7eSMarcel Moolenaar if (error) 46964220a7eSMarcel Moolenaar return (error); 47064220a7eSMarcel Moolenaar if (res != 0) 47164220a7eSMarcel Moolenaar device_set_desc(dev, (const char *)res); 47264220a7eSMarcel Moolenaar return (BUS_PROBE_DEFAULT); 47364220a7eSMarcel Moolenaar } 47464220a7eSMarcel Moolenaar 47564220a7eSMarcel Moolenaar struct resource * 47664220a7eSMarcel Moolenaar puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid, 4772dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 47864220a7eSMarcel Moolenaar { 47964220a7eSMarcel Moolenaar struct puc_port *port; 48064220a7eSMarcel Moolenaar struct resource *res; 48164220a7eSMarcel Moolenaar device_t assigned, originator; 48264220a7eSMarcel Moolenaar int error; 48364220a7eSMarcel Moolenaar 48464220a7eSMarcel Moolenaar /* Get our immediate child. */ 48564220a7eSMarcel Moolenaar originator = child; 48664220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 48764220a7eSMarcel Moolenaar child = device_get_parent(child); 48864220a7eSMarcel Moolenaar if (child == NULL) 48964220a7eSMarcel Moolenaar return (NULL); 49064220a7eSMarcel Moolenaar 49164220a7eSMarcel Moolenaar port = device_get_ivars(child); 49264220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 49364220a7eSMarcel Moolenaar 49464220a7eSMarcel Moolenaar if (rid == NULL || *rid != 0) 49564220a7eSMarcel Moolenaar return (NULL); 49664220a7eSMarcel Moolenaar 49764220a7eSMarcel Moolenaar /* We only support default allocations. */ 498*82ed3cb0SJustin Hibbits if (!RMAN_IS_DEFAULT_RANGE(start, end)) 49964220a7eSMarcel Moolenaar return (NULL); 50064220a7eSMarcel Moolenaar 50164220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 50264220a7eSMarcel Moolenaar res = port->p_rres; 50364220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 50464220a7eSMarcel Moolenaar res = port->p_ires; 50564220a7eSMarcel Moolenaar else 50664220a7eSMarcel Moolenaar return (NULL); 50764220a7eSMarcel Moolenaar 50864220a7eSMarcel Moolenaar if (res == NULL) 50964220a7eSMarcel Moolenaar return (NULL); 51064220a7eSMarcel Moolenaar 51164220a7eSMarcel Moolenaar assigned = rman_get_device(res); 51264220a7eSMarcel Moolenaar if (assigned == NULL) /* Not allocated */ 51364220a7eSMarcel Moolenaar rman_set_device(res, originator); 51464220a7eSMarcel Moolenaar else if (assigned != originator) 51564220a7eSMarcel Moolenaar return (NULL); 51664220a7eSMarcel Moolenaar 51764220a7eSMarcel Moolenaar if (flags & RF_ACTIVE) { 51864220a7eSMarcel Moolenaar error = rman_activate_resource(res); 51964220a7eSMarcel Moolenaar if (error) { 52064220a7eSMarcel Moolenaar if (assigned == NULL) 52164220a7eSMarcel Moolenaar rman_set_device(res, NULL); 52264220a7eSMarcel Moolenaar return (NULL); 52364220a7eSMarcel Moolenaar } 52464220a7eSMarcel Moolenaar } 52564220a7eSMarcel Moolenaar 52664220a7eSMarcel Moolenaar return (res); 52764220a7eSMarcel Moolenaar } 52864220a7eSMarcel Moolenaar 52964220a7eSMarcel Moolenaar int 53064220a7eSMarcel Moolenaar puc_bus_release_resource(device_t dev, device_t child, int type, int rid, 5319c564b6cSJohn Hay struct resource *res) 5329c564b6cSJohn Hay { 53364220a7eSMarcel Moolenaar struct puc_port *port; 53464220a7eSMarcel Moolenaar device_t originator; 53564220a7eSMarcel Moolenaar 53664220a7eSMarcel Moolenaar /* Get our immediate child. */ 53764220a7eSMarcel Moolenaar originator = child; 53864220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 53964220a7eSMarcel Moolenaar child = device_get_parent(child); 54064220a7eSMarcel Moolenaar if (child == NULL) 54164220a7eSMarcel Moolenaar return (EINVAL); 54264220a7eSMarcel Moolenaar 54364220a7eSMarcel Moolenaar port = device_get_ivars(child); 54464220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 54564220a7eSMarcel Moolenaar 54664220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 54764220a7eSMarcel Moolenaar return (EINVAL); 54864220a7eSMarcel Moolenaar 54964220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) { 55064220a7eSMarcel Moolenaar if (res != port->p_rres) 55164220a7eSMarcel Moolenaar return (EINVAL); 55264220a7eSMarcel Moolenaar } else if (type == SYS_RES_IRQ) { 55364220a7eSMarcel Moolenaar if (res != port->p_ires) 55464220a7eSMarcel Moolenaar return (EINVAL); 55564220a7eSMarcel Moolenaar if (port->p_hasintr) 55664220a7eSMarcel Moolenaar return (EBUSY); 55764220a7eSMarcel Moolenaar } else 55864220a7eSMarcel Moolenaar return (EINVAL); 55964220a7eSMarcel Moolenaar 56064220a7eSMarcel Moolenaar if (rman_get_device(res) != originator) 56164220a7eSMarcel Moolenaar return (ENXIO); 56264220a7eSMarcel Moolenaar if (rman_get_flags(res) & RF_ACTIVE) 56364220a7eSMarcel Moolenaar rman_deactivate_resource(res); 56464220a7eSMarcel Moolenaar rman_set_device(res, NULL); 5659c564b6cSJohn Hay return (0); 5669c564b6cSJohn Hay } 5679c564b6cSJohn Hay 56832f606d1SPoul-Henning Kamp int 56964220a7eSMarcel Moolenaar puc_bus_get_resource(device_t dev, device_t child, int type, int rid, 5702dd1bdf1SJustin Hibbits rman_res_t *startp, rman_res_t *countp) 5719c564b6cSJohn Hay { 57264220a7eSMarcel Moolenaar struct puc_port *port; 57364220a7eSMarcel Moolenaar struct resource *res; 5742dd1bdf1SJustin Hibbits rman_res_t start; 5759c564b6cSJohn Hay 57664220a7eSMarcel Moolenaar /* Get our immediate child. */ 57764220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 57864220a7eSMarcel Moolenaar child = device_get_parent(child); 57964220a7eSMarcel Moolenaar if (child == NULL) 58064220a7eSMarcel Moolenaar return (EINVAL); 5819c564b6cSJohn Hay 58264220a7eSMarcel Moolenaar port = device_get_ivars(child); 58364220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 58464220a7eSMarcel Moolenaar 58564220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 58664220a7eSMarcel Moolenaar res = port->p_rres; 58764220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 58864220a7eSMarcel Moolenaar res = port->p_ires; 58964220a7eSMarcel Moolenaar else 59064220a7eSMarcel Moolenaar return (ENXIO); 59164220a7eSMarcel Moolenaar 59264220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 59364220a7eSMarcel Moolenaar return (ENXIO); 59464220a7eSMarcel Moolenaar 59564220a7eSMarcel Moolenaar start = rman_get_start(res); 5969c564b6cSJohn Hay if (startp != NULL) 59764220a7eSMarcel Moolenaar *startp = start; 5989c564b6cSJohn Hay if (countp != NULL) 59964220a7eSMarcel Moolenaar *countp = rman_get_end(res) - start + 1; 6009c564b6cSJohn Hay return (0); 6019c564b6cSJohn Hay } 6029c564b6cSJohn Hay 60332f606d1SPoul-Henning Kamp int 60464220a7eSMarcel Moolenaar puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, 605ef544f63SPaolo Pisati int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) 6069c564b6cSJohn Hay { 60764220a7eSMarcel Moolenaar struct puc_port *port; 6089c564b6cSJohn Hay struct puc_softc *sc; 60964220a7eSMarcel Moolenaar device_t originator; 61064220a7eSMarcel Moolenaar int i, isrc, serdev; 6119c564b6cSJohn Hay 61264220a7eSMarcel Moolenaar sc = device_get_softc(dev); 61364220a7eSMarcel Moolenaar 61464220a7eSMarcel Moolenaar /* Get our immediate child. */ 61564220a7eSMarcel Moolenaar originator = child; 61664220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 61764220a7eSMarcel Moolenaar child = device_get_parent(child); 61864220a7eSMarcel Moolenaar if (child == NULL) 61964220a7eSMarcel Moolenaar return (EINVAL); 62064220a7eSMarcel Moolenaar 62164220a7eSMarcel Moolenaar port = device_get_ivars(child); 62264220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 62364220a7eSMarcel Moolenaar 6248d715a35SPaolo Pisati if (cookiep == NULL || res != port->p_ires) 62564220a7eSMarcel Moolenaar return (EINVAL); 6268d715a35SPaolo Pisati /* We demand that serdev devices use filter_only interrupts. */ 627323e149aSJohn Baldwin if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL) 6288d715a35SPaolo Pisati return (ENXIO); 62964220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 630d3c10e33SPoul-Henning Kamp return (ENXIO); 63164220a7eSMarcel Moolenaar 63264220a7eSMarcel Moolenaar /* 63364220a7eSMarcel Moolenaar * Have non-serdev ports handled by the bus implementation. It 63464220a7eSMarcel Moolenaar * supports multiple handlers for a single interrupt as it is, 63564220a7eSMarcel Moolenaar * so we wouldn't add value if we did it ourselves. 63664220a7eSMarcel Moolenaar */ 63764220a7eSMarcel Moolenaar serdev = 0; 63864220a7eSMarcel Moolenaar if (port->p_type == PUC_TYPE_SERIAL) { 63964220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 64064220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT) { 64164220a7eSMarcel Moolenaar port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc); 64264220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 64364220a7eSMarcel Moolenaar serdev = 1; 64464220a7eSMarcel Moolenaar i++, isrc <<= 1; 64564220a7eSMarcel Moolenaar } 64664220a7eSMarcel Moolenaar } 64764220a7eSMarcel Moolenaar if (!serdev) 64864220a7eSMarcel Moolenaar return (BUS_SETUP_INTR(device_get_parent(dev), originator, 649ef544f63SPaolo Pisati sc->sc_ires, flags, filt, ihand, arg, cookiep)); 65064220a7eSMarcel Moolenaar 65164220a7eSMarcel Moolenaar sc->sc_serdevs |= 1UL << (port->p_nr - 1); 65264220a7eSMarcel Moolenaar 65364220a7eSMarcel Moolenaar port->p_hasintr = 1; 65464220a7eSMarcel Moolenaar port->p_iharg = arg; 65564220a7eSMarcel Moolenaar 65664220a7eSMarcel Moolenaar *cookiep = port; 6579c564b6cSJohn Hay return (0); 6589c564b6cSJohn Hay } 6599c564b6cSJohn Hay 66032f606d1SPoul-Henning Kamp int 66164220a7eSMarcel Moolenaar puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res, 6629c564b6cSJohn Hay void *cookie) 6639c564b6cSJohn Hay { 66464220a7eSMarcel Moolenaar struct puc_port *port; 6659c564b6cSJohn Hay struct puc_softc *sc; 66664220a7eSMarcel Moolenaar device_t originator; 66764220a7eSMarcel Moolenaar int i; 6689c564b6cSJohn Hay 66964220a7eSMarcel Moolenaar sc = device_get_softc(dev); 67064220a7eSMarcel Moolenaar 67164220a7eSMarcel Moolenaar /* Get our immediate child. */ 67264220a7eSMarcel Moolenaar originator = child; 67364220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 67464220a7eSMarcel Moolenaar child = device_get_parent(child); 67564220a7eSMarcel Moolenaar if (child == NULL) 67664220a7eSMarcel Moolenaar return (EINVAL); 67764220a7eSMarcel Moolenaar 67864220a7eSMarcel Moolenaar port = device_get_ivars(child); 67964220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 68064220a7eSMarcel Moolenaar 68164220a7eSMarcel Moolenaar if (res != port->p_ires) 68264220a7eSMarcel Moolenaar return (EINVAL); 68364220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 6849c564b6cSJohn Hay return (ENXIO); 68564220a7eSMarcel Moolenaar 68664220a7eSMarcel Moolenaar if (!port->p_hasintr) 68764220a7eSMarcel Moolenaar return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator, 68864220a7eSMarcel Moolenaar sc->sc_ires, cookie)); 68964220a7eSMarcel Moolenaar 69064220a7eSMarcel Moolenaar if (cookie != port) 69164220a7eSMarcel Moolenaar return (EINVAL); 69264220a7eSMarcel Moolenaar 69364220a7eSMarcel Moolenaar port->p_hasintr = 0; 69464220a7eSMarcel Moolenaar port->p_iharg = NULL; 69564220a7eSMarcel Moolenaar 69664220a7eSMarcel Moolenaar for (i = 0; i < PUC_ISRCCNT; i++) 69764220a7eSMarcel Moolenaar port->p_ihsrc[i] = NULL; 69864220a7eSMarcel Moolenaar 69964220a7eSMarcel Moolenaar return (0); 7009c564b6cSJohn Hay } 7019c564b6cSJohn Hay 70232f606d1SPoul-Henning Kamp int 70364220a7eSMarcel Moolenaar puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 7049c564b6cSJohn Hay { 70564220a7eSMarcel Moolenaar struct puc_port *port; 7069c564b6cSJohn Hay 70764220a7eSMarcel Moolenaar /* Get our immediate child. */ 70864220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 70964220a7eSMarcel Moolenaar child = device_get_parent(child); 71064220a7eSMarcel Moolenaar if (child == NULL) 71164220a7eSMarcel Moolenaar return (EINVAL); 71264220a7eSMarcel Moolenaar 71364220a7eSMarcel Moolenaar port = device_get_ivars(child); 71464220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 71564220a7eSMarcel Moolenaar 71664220a7eSMarcel Moolenaar if (result == NULL) 71764220a7eSMarcel Moolenaar return (EINVAL); 7189c564b6cSJohn Hay 7199c564b6cSJohn Hay switch(index) { 72064220a7eSMarcel Moolenaar case PUC_IVAR_CLOCK: 72164220a7eSMarcel Moolenaar *result = port->p_rclk; 7229c564b6cSJohn Hay break; 72364220a7eSMarcel Moolenaar case PUC_IVAR_TYPE: 72464220a7eSMarcel Moolenaar *result = port->p_type; 725153bbe3eSMarcel Moolenaar break; 7269c564b6cSJohn Hay default: 7279c564b6cSJohn Hay return (ENOENT); 7289c564b6cSJohn Hay } 7299c564b6cSJohn Hay return (0); 7309c564b6cSJohn Hay } 731573e64d4SJohn Baldwin 732573e64d4SJohn Baldwin int 733573e64d4SJohn Baldwin puc_bus_print_child(device_t dev, device_t child) 734573e64d4SJohn Baldwin { 735573e64d4SJohn Baldwin struct puc_port *port; 736573e64d4SJohn Baldwin int retval; 737573e64d4SJohn Baldwin 738573e64d4SJohn Baldwin port = device_get_ivars(child); 739573e64d4SJohn Baldwin retval = 0; 740573e64d4SJohn Baldwin 741573e64d4SJohn Baldwin retval += bus_print_child_header(dev, child); 742573e64d4SJohn Baldwin retval += printf(" at port %d", port->p_nr); 743573e64d4SJohn Baldwin retval += bus_print_child_footer(dev, child); 744573e64d4SJohn Baldwin 745573e64d4SJohn Baldwin return (retval); 746573e64d4SJohn Baldwin } 747573e64d4SJohn Baldwin 748573e64d4SJohn Baldwin int 749573e64d4SJohn Baldwin puc_bus_child_location_str(device_t dev, device_t child, char *buf, 750573e64d4SJohn Baldwin size_t buflen) 751573e64d4SJohn Baldwin { 752573e64d4SJohn Baldwin struct puc_port *port; 753573e64d4SJohn Baldwin 754573e64d4SJohn Baldwin port = device_get_ivars(child); 755573e64d4SJohn Baldwin snprintf(buf, buflen, "port=%d", port->p_nr); 756573e64d4SJohn Baldwin return (0); 757573e64d4SJohn Baldwin } 758573e64d4SJohn Baldwin 759573e64d4SJohn Baldwin int 760573e64d4SJohn Baldwin puc_bus_child_pnpinfo_str(device_t dev, device_t child, char *buf, 761573e64d4SJohn Baldwin size_t buflen) 762573e64d4SJohn Baldwin { 763573e64d4SJohn Baldwin struct puc_port *port; 764573e64d4SJohn Baldwin 765573e64d4SJohn Baldwin port = device_get_ivars(child); 766573e64d4SJohn Baldwin snprintf(buf, buflen, "type=%d", port->p_type); 767573e64d4SJohn Baldwin return (0); 768573e64d4SJohn Baldwin } 769