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 7164220a7eSMarcel Moolenaar 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; 13264220a7eSMarcel Moolenaar u_long dev, devs; 13364220a7eSMarcel Moolenaar int i, idx, ipend, isrc; 13464220a7eSMarcel Moolenaar uint8_t ilr; 13564220a7eSMarcel Moolenaar 13664220a7eSMarcel Moolenaar devs = sc->sc_serdevs; 13764220a7eSMarcel Moolenaar if (sc->sc_ilr == PUC_ILR_DIGI) { 13864220a7eSMarcel Moolenaar idx = 0; 13964220a7eSMarcel Moolenaar while (devs & (0xfful << idx)) { 14064220a7eSMarcel Moolenaar ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7); 14164220a7eSMarcel Moolenaar devs &= ~0ul ^ ((u_long)ilr << idx); 14264220a7eSMarcel Moolenaar idx += 8; 14364220a7eSMarcel Moolenaar } 14464220a7eSMarcel Moolenaar } else if (sc->sc_ilr == PUC_ILR_QUATECH) { 14564220a7eSMarcel Moolenaar /* 14664220a7eSMarcel Moolenaar * Don't trust the value if it's the same as the option 14764220a7eSMarcel Moolenaar * register. It may mean that the ILR is not active and 14864220a7eSMarcel Moolenaar * we're reading the option register instead. This may 14964220a7eSMarcel Moolenaar * lead to false positives on 8-port boards. 15064220a7eSMarcel Moolenaar */ 15164220a7eSMarcel Moolenaar ilr = bus_read_1(sc->sc_port[0].p_rres, 7); 15264220a7eSMarcel Moolenaar if (ilr != (sc->sc_cfg_data & 0xff)) 15364220a7eSMarcel Moolenaar devs &= (u_long)ilr; 15464220a7eSMarcel Moolenaar } 15564220a7eSMarcel Moolenaar 15664220a7eSMarcel Moolenaar ipend = 0; 15764220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 15864220a7eSMarcel Moolenaar while (devs != 0UL) { 15964220a7eSMarcel Moolenaar while ((devs & dev) == 0UL) 16064220a7eSMarcel Moolenaar idx++, dev <<= 1; 16164220a7eSMarcel Moolenaar devs &= ~dev; 16264220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 16364220a7eSMarcel Moolenaar port->p_ipend = SERDEV_IPEND(port->p_dev); 16464220a7eSMarcel Moolenaar ipend |= port->p_ipend; 16564220a7eSMarcel Moolenaar } 16664220a7eSMarcel Moolenaar 16764220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 16864220a7eSMarcel Moolenaar while (ipend) { 16964220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT && !(ipend & isrc)) 17064220a7eSMarcel Moolenaar i++, isrc <<= 1; 17164220a7eSMarcel Moolenaar KASSERT(i < PUC_ISRCCNT, ("%s", __func__)); 17264220a7eSMarcel Moolenaar ipend &= ~isrc; 17364220a7eSMarcel Moolenaar idx = 0, dev = 1UL; 17464220a7eSMarcel Moolenaar devs = sc->sc_serdevs; 17564220a7eSMarcel Moolenaar while (devs != 0UL) { 17664220a7eSMarcel Moolenaar while ((devs & dev) == 0UL) 17764220a7eSMarcel Moolenaar idx++, dev <<= 1; 17864220a7eSMarcel Moolenaar devs &= ~dev; 17964220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 18064220a7eSMarcel Moolenaar if (!(port->p_ipend & isrc)) 18164220a7eSMarcel Moolenaar continue; 18264220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 18364220a7eSMarcel Moolenaar (*port->p_ihsrc[i])(port->p_iharg); 18464220a7eSMarcel Moolenaar } 185ef544f63SPaolo Pisati return (FILTER_HANDLED); 18664220a7eSMarcel Moolenaar } 187ef544f63SPaolo Pisati return (FILTER_STRAY); 18864220a7eSMarcel Moolenaar } 18964220a7eSMarcel Moolenaar 19064220a7eSMarcel Moolenaar int 19164220a7eSMarcel Moolenaar puc_bfe_attach(device_t dev) 19264220a7eSMarcel Moolenaar { 19364220a7eSMarcel Moolenaar char buffer[64]; 19464220a7eSMarcel Moolenaar struct puc_bar *bar; 19564220a7eSMarcel Moolenaar struct puc_port *port; 1969c564b6cSJohn Hay struct puc_softc *sc; 19764220a7eSMarcel Moolenaar struct rman *rm; 19864220a7eSMarcel Moolenaar intptr_t res; 19964220a7eSMarcel Moolenaar bus_addr_t ofs, start; 20064220a7eSMarcel Moolenaar bus_size_t size; 20164220a7eSMarcel Moolenaar bus_space_handle_t bsh; 20264220a7eSMarcel Moolenaar bus_space_tag_t bst; 20364220a7eSMarcel Moolenaar int error, idx; 2049c564b6cSJohn Hay 20564220a7eSMarcel Moolenaar sc = device_get_softc(dev); 20664220a7eSMarcel Moolenaar 20764220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) 20864220a7eSMarcel Moolenaar sc->sc_bar[idx].b_rid = -1; 20964220a7eSMarcel Moolenaar 21064220a7eSMarcel Moolenaar do { 21164220a7eSMarcel Moolenaar sc->sc_ioport.rm_type = RMAN_ARRAY; 21264220a7eSMarcel Moolenaar error = rman_init(&sc->sc_ioport); 21364220a7eSMarcel Moolenaar if (!error) { 21464220a7eSMarcel Moolenaar sc->sc_iomem.rm_type = RMAN_ARRAY; 21564220a7eSMarcel Moolenaar error = rman_init(&sc->sc_iomem); 21664220a7eSMarcel Moolenaar if (!error) { 21764220a7eSMarcel Moolenaar sc->sc_irq.rm_type = RMAN_ARRAY; 21864220a7eSMarcel Moolenaar error = rman_init(&sc->sc_irq); 21964220a7eSMarcel Moolenaar if (!error) 22064220a7eSMarcel Moolenaar break; 22164220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 22264220a7eSMarcel Moolenaar } 22364220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 22464220a7eSMarcel Moolenaar } 22564220a7eSMarcel Moolenaar return (error); 22664220a7eSMarcel Moolenaar } while (0); 22764220a7eSMarcel Moolenaar 22864220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O port mapping", 22964220a7eSMarcel Moolenaar device_get_nameunit(dev)); 23064220a7eSMarcel Moolenaar sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); 23164220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", 23264220a7eSMarcel Moolenaar device_get_nameunit(dev)); 23364220a7eSMarcel Moolenaar sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); 23464220a7eSMarcel Moolenaar snprintf(buffer, sizeof(buffer), "%s port numbers", 23564220a7eSMarcel Moolenaar device_get_nameunit(dev)); 23664220a7eSMarcel Moolenaar sc->sc_irq.rm_descr = strdup(buffer, M_PUC); 23764220a7eSMarcel Moolenaar 23864220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 23964220a7eSMarcel Moolenaar KASSERT(error == 0, ("%s %d", __func__, __LINE__)); 24064220a7eSMarcel Moolenaar sc->sc_nports = (int)res; 24164220a7eSMarcel Moolenaar sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), 24264220a7eSMarcel Moolenaar M_PUC, M_WAITOK|M_ZERO); 24364220a7eSMarcel Moolenaar 24464220a7eSMarcel Moolenaar error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); 24564220a7eSMarcel Moolenaar if (error) 24664220a7eSMarcel Moolenaar goto fail; 24764220a7eSMarcel Moolenaar 24864220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_SETUP, 0, &res); 24964220a7eSMarcel Moolenaar if (error) 25064220a7eSMarcel Moolenaar goto fail; 25164220a7eSMarcel Moolenaar 25264220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 25364220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 25464220a7eSMarcel Moolenaar port->p_nr = idx + 1; 25564220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); 25664220a7eSMarcel Moolenaar if (error) 25764220a7eSMarcel Moolenaar goto fail; 25864220a7eSMarcel Moolenaar port->p_type = res; 25964220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); 26064220a7eSMarcel Moolenaar if (error) 26164220a7eSMarcel Moolenaar goto fail; 26264220a7eSMarcel Moolenaar bar = puc_get_bar(sc, res); 26364220a7eSMarcel Moolenaar if (bar == NULL) { 26464220a7eSMarcel Moolenaar error = ENXIO; 26564220a7eSMarcel Moolenaar goto fail; 26664220a7eSMarcel Moolenaar } 26764220a7eSMarcel Moolenaar port->p_bar = bar; 26864220a7eSMarcel Moolenaar start = rman_get_start(bar->b_res); 26964220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); 27064220a7eSMarcel Moolenaar if (error) 27164220a7eSMarcel Moolenaar goto fail; 27264220a7eSMarcel Moolenaar ofs = res; 27364220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); 27464220a7eSMarcel Moolenaar if (error) 27564220a7eSMarcel Moolenaar goto fail; 27664220a7eSMarcel Moolenaar size = res; 27764220a7eSMarcel Moolenaar rm = (bar->b_type == SYS_RES_IOPORT) 27864220a7eSMarcel Moolenaar ? &sc->sc_ioport: &sc->sc_iomem; 27964220a7eSMarcel Moolenaar port->p_rres = rman_reserve_resource(rm, start + ofs, 28064220a7eSMarcel Moolenaar start + ofs + size - 1, size, 0, NULL); 28164220a7eSMarcel Moolenaar if (port->p_rres != NULL) { 28264220a7eSMarcel Moolenaar bsh = rman_get_bushandle(bar->b_res); 28364220a7eSMarcel Moolenaar bst = rman_get_bustag(bar->b_res); 28464220a7eSMarcel Moolenaar bus_space_subregion(bst, bsh, ofs, size, &bsh); 28564220a7eSMarcel Moolenaar rman_set_bushandle(port->p_rres, bsh); 28664220a7eSMarcel Moolenaar rman_set_bustag(port->p_rres, bst); 28764220a7eSMarcel Moolenaar } 28864220a7eSMarcel Moolenaar port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, 28964220a7eSMarcel Moolenaar port->p_nr, 1, 0, NULL); 29064220a7eSMarcel Moolenaar if (port->p_ires == NULL) { 29164220a7eSMarcel Moolenaar error = ENXIO; 29264220a7eSMarcel Moolenaar goto fail; 29364220a7eSMarcel Moolenaar } 29464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); 29564220a7eSMarcel Moolenaar if (error) 29664220a7eSMarcel Moolenaar goto fail; 29764220a7eSMarcel Moolenaar port->p_rclk = res; 29864220a7eSMarcel Moolenaar 29964220a7eSMarcel Moolenaar port->p_dev = device_add_child(dev, NULL, -1); 30064220a7eSMarcel Moolenaar if (port->p_dev != NULL) 30164220a7eSMarcel Moolenaar device_set_ivars(port->p_dev, (void *)port); 3029c564b6cSJohn Hay } 3039c564b6cSJohn Hay 30464220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); 30564220a7eSMarcel Moolenaar if (error) 30664220a7eSMarcel Moolenaar goto fail; 30764220a7eSMarcel Moolenaar sc->sc_ilr = res; 30864220a7eSMarcel Moolenaar if (bootverbose && sc->sc_ilr != 0) 30964220a7eSMarcel Moolenaar device_printf(dev, "using interrupt latch register\n"); 3109c564b6cSJohn Hay 31164220a7eSMarcel Moolenaar sc->sc_irid = 0; 31264220a7eSMarcel Moolenaar sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, 31364220a7eSMarcel Moolenaar RF_ACTIVE|RF_SHAREABLE); 31464220a7eSMarcel Moolenaar if (sc->sc_ires != NULL) { 31564220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 316ef544f63SPaolo Pisati INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); 31764220a7eSMarcel Moolenaar if (error) 31864220a7eSMarcel Moolenaar error = bus_setup_intr(dev, sc->sc_ires, 319ef544f63SPaolo Pisati INTR_TYPE_TTY | INTR_MPSAFE, NULL, 320ef544f63SPaolo Pisati (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); 32164220a7eSMarcel Moolenaar else 32264220a7eSMarcel Moolenaar sc->sc_fastintr = 1; 32364220a7eSMarcel Moolenaar 32464220a7eSMarcel Moolenaar if (error) { 32564220a7eSMarcel Moolenaar device_printf(dev, "could not activate interrupt\n"); 32664220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 32764220a7eSMarcel Moolenaar sc->sc_ires); 32864220a7eSMarcel Moolenaar sc->sc_ires = NULL; 32964220a7eSMarcel Moolenaar } 33064220a7eSMarcel Moolenaar } 33164220a7eSMarcel Moolenaar if (sc->sc_ires == NULL) { 33264220a7eSMarcel Moolenaar /* XXX no interrupt resource. Force polled mode. */ 33364220a7eSMarcel Moolenaar sc->sc_polled = 1; 3349c564b6cSJohn Hay } 3359c564b6cSJohn Hay 33664220a7eSMarcel Moolenaar /* Probe and attach our children. */ 33764220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 33864220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 33964220a7eSMarcel Moolenaar if (port->p_dev == NULL) 34064220a7eSMarcel Moolenaar continue; 34164220a7eSMarcel Moolenaar error = device_probe_and_attach(port->p_dev); 34264220a7eSMarcel Moolenaar if (error) { 34364220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 34464220a7eSMarcel Moolenaar port->p_dev = NULL; 3459c564b6cSJohn Hay } 34664220a7eSMarcel Moolenaar } 3479c564b6cSJohn Hay 348a3732274SDoug Ambrisko /* 34964220a7eSMarcel Moolenaar * If there are no serdev devices, then our interrupt handler 35064220a7eSMarcel Moolenaar * will do nothing. Tear it down. 351a3732274SDoug Ambrisko */ 35264220a7eSMarcel Moolenaar if (sc->sc_serdevs == 0UL) 35364220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 354a3732274SDoug Ambrisko 35564220a7eSMarcel Moolenaar return (0); 3569c564b6cSJohn Hay 35764220a7eSMarcel Moolenaar fail: 35864220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 35964220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 36064220a7eSMarcel Moolenaar if (port->p_dev != NULL) 36164220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 36264220a7eSMarcel Moolenaar if (port->p_rres != NULL) 36364220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 36464220a7eSMarcel Moolenaar if (port->p_ires != NULL) 36564220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 366a3732274SDoug Ambrisko } 36764220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 36864220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 36964220a7eSMarcel Moolenaar if (bar->b_res != NULL) 37064220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 37164220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 37264220a7eSMarcel Moolenaar } 37364220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 37464220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 37564220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 37664220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 37764220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 37864220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 37964220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 38064220a7eSMarcel Moolenaar return (error); 3819c564b6cSJohn Hay } 3829c564b6cSJohn Hay 38332f606d1SPoul-Henning Kamp int 38464220a7eSMarcel Moolenaar puc_bfe_detach(device_t dev) 38564220a7eSMarcel Moolenaar { 38664220a7eSMarcel Moolenaar struct puc_bar *bar; 38764220a7eSMarcel Moolenaar struct puc_port *port; 38864220a7eSMarcel Moolenaar struct puc_softc *sc; 38964220a7eSMarcel Moolenaar int error, idx; 39064220a7eSMarcel Moolenaar 39164220a7eSMarcel Moolenaar sc = device_get_softc(dev); 39264220a7eSMarcel Moolenaar 39364220a7eSMarcel Moolenaar /* Detach our children. */ 39464220a7eSMarcel Moolenaar error = 0; 39564220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) { 39664220a7eSMarcel Moolenaar port = &sc->sc_port[idx]; 39764220a7eSMarcel Moolenaar if (port->p_dev == NULL) 39864220a7eSMarcel Moolenaar continue; 39964220a7eSMarcel Moolenaar if (device_detach(port->p_dev) == 0) { 40064220a7eSMarcel Moolenaar device_delete_child(dev, port->p_dev); 40164220a7eSMarcel Moolenaar if (port->p_rres != NULL) 40264220a7eSMarcel Moolenaar rman_release_resource(port->p_rres); 40364220a7eSMarcel Moolenaar if (port->p_ires != NULL) 40464220a7eSMarcel Moolenaar rman_release_resource(port->p_ires); 40564220a7eSMarcel Moolenaar } else 40664220a7eSMarcel Moolenaar error = ENXIO; 40764220a7eSMarcel Moolenaar } 40864220a7eSMarcel Moolenaar if (error) 40964220a7eSMarcel Moolenaar return (error); 41064220a7eSMarcel Moolenaar 41164220a7eSMarcel Moolenaar if (sc->sc_serdevs != 0UL) 41264220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 41364220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); 41464220a7eSMarcel Moolenaar 41564220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) { 41664220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx]; 41764220a7eSMarcel Moolenaar if (bar->b_res != NULL) 41864220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type, 41964220a7eSMarcel Moolenaar bar->b_rid, bar->b_res); 42064220a7eSMarcel Moolenaar } 42164220a7eSMarcel Moolenaar 42264220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq); 42364220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); 42464220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem); 42564220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); 42664220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport); 42764220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); 42864220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC); 42964220a7eSMarcel Moolenaar return (0); 43064220a7eSMarcel Moolenaar } 43164220a7eSMarcel Moolenaar 43264220a7eSMarcel Moolenaar int 43364220a7eSMarcel Moolenaar puc_bfe_probe(device_t dev, const struct puc_cfg *cfg) 43464220a7eSMarcel Moolenaar { 43564220a7eSMarcel Moolenaar struct puc_softc *sc; 43664220a7eSMarcel Moolenaar intptr_t res; 43764220a7eSMarcel Moolenaar int error; 43864220a7eSMarcel Moolenaar 43964220a7eSMarcel Moolenaar sc = device_get_softc(dev); 44064220a7eSMarcel Moolenaar sc->sc_dev = dev; 44164220a7eSMarcel Moolenaar sc->sc_cfg = cfg; 44264220a7eSMarcel Moolenaar 44364220a7eSMarcel Moolenaar /* We don't attach to single-port serial cards. */ 44464220a7eSMarcel Moolenaar if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P) 44564220a7eSMarcel Moolenaar return (EDOOFUS); 44664220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); 44764220a7eSMarcel Moolenaar if (error) 44864220a7eSMarcel Moolenaar return (error); 44964220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res); 45064220a7eSMarcel Moolenaar if (error) 45164220a7eSMarcel Moolenaar return (error); 45264220a7eSMarcel Moolenaar if (res != 0) 45364220a7eSMarcel Moolenaar device_set_desc(dev, (const char *)res); 45464220a7eSMarcel Moolenaar return (BUS_PROBE_DEFAULT); 45564220a7eSMarcel Moolenaar } 45664220a7eSMarcel Moolenaar 45764220a7eSMarcel Moolenaar struct resource * 45864220a7eSMarcel Moolenaar puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid, 45964220a7eSMarcel Moolenaar u_long start, u_long end, u_long count, u_int flags) 46064220a7eSMarcel Moolenaar { 46164220a7eSMarcel Moolenaar struct puc_port *port; 46264220a7eSMarcel Moolenaar struct resource *res; 46364220a7eSMarcel Moolenaar device_t assigned, originator; 46464220a7eSMarcel Moolenaar int error; 46564220a7eSMarcel Moolenaar 46664220a7eSMarcel Moolenaar /* Get our immediate child. */ 46764220a7eSMarcel Moolenaar originator = child; 46864220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 46964220a7eSMarcel Moolenaar child = device_get_parent(child); 47064220a7eSMarcel Moolenaar if (child == NULL) 47164220a7eSMarcel Moolenaar return (NULL); 47264220a7eSMarcel Moolenaar 47364220a7eSMarcel Moolenaar port = device_get_ivars(child); 47464220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 47564220a7eSMarcel Moolenaar 47664220a7eSMarcel Moolenaar if (rid == NULL || *rid != 0) 47764220a7eSMarcel Moolenaar return (NULL); 47864220a7eSMarcel Moolenaar 47964220a7eSMarcel Moolenaar /* We only support default allocations. */ 48064220a7eSMarcel Moolenaar if (start != 0UL || end != ~0UL) 48164220a7eSMarcel Moolenaar return (NULL); 48264220a7eSMarcel Moolenaar 48364220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 48464220a7eSMarcel Moolenaar res = port->p_rres; 48564220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 48664220a7eSMarcel Moolenaar res = port->p_ires; 48764220a7eSMarcel Moolenaar else 48864220a7eSMarcel Moolenaar return (NULL); 48964220a7eSMarcel Moolenaar 49064220a7eSMarcel Moolenaar if (res == NULL) 49164220a7eSMarcel Moolenaar return (NULL); 49264220a7eSMarcel Moolenaar 49364220a7eSMarcel Moolenaar assigned = rman_get_device(res); 49464220a7eSMarcel Moolenaar if (assigned == NULL) /* Not allocated */ 49564220a7eSMarcel Moolenaar rman_set_device(res, originator); 49664220a7eSMarcel Moolenaar else if (assigned != originator) 49764220a7eSMarcel Moolenaar return (NULL); 49864220a7eSMarcel Moolenaar 49964220a7eSMarcel Moolenaar if (flags & RF_ACTIVE) { 50064220a7eSMarcel Moolenaar error = rman_activate_resource(res); 50164220a7eSMarcel Moolenaar if (error) { 50264220a7eSMarcel Moolenaar if (assigned == NULL) 50364220a7eSMarcel Moolenaar rman_set_device(res, NULL); 50464220a7eSMarcel Moolenaar return (NULL); 50564220a7eSMarcel Moolenaar } 50664220a7eSMarcel Moolenaar } 50764220a7eSMarcel Moolenaar 50864220a7eSMarcel Moolenaar return (res); 50964220a7eSMarcel Moolenaar } 51064220a7eSMarcel Moolenaar 51164220a7eSMarcel Moolenaar int 51264220a7eSMarcel Moolenaar puc_bus_release_resource(device_t dev, device_t child, int type, int rid, 5139c564b6cSJohn Hay struct resource *res) 5149c564b6cSJohn Hay { 51564220a7eSMarcel Moolenaar struct puc_port *port; 51664220a7eSMarcel Moolenaar device_t originator; 51764220a7eSMarcel Moolenaar 51864220a7eSMarcel Moolenaar /* Get our immediate child. */ 51964220a7eSMarcel Moolenaar originator = child; 52064220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 52164220a7eSMarcel Moolenaar child = device_get_parent(child); 52264220a7eSMarcel Moolenaar if (child == NULL) 52364220a7eSMarcel Moolenaar return (EINVAL); 52464220a7eSMarcel Moolenaar 52564220a7eSMarcel Moolenaar port = device_get_ivars(child); 52664220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 52764220a7eSMarcel Moolenaar 52864220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 52964220a7eSMarcel Moolenaar return (EINVAL); 53064220a7eSMarcel Moolenaar 53164220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) { 53264220a7eSMarcel Moolenaar if (res != port->p_rres) 53364220a7eSMarcel Moolenaar return (EINVAL); 53464220a7eSMarcel Moolenaar } else if (type == SYS_RES_IRQ) { 53564220a7eSMarcel Moolenaar if (res != port->p_ires) 53664220a7eSMarcel Moolenaar return (EINVAL); 53764220a7eSMarcel Moolenaar if (port->p_hasintr) 53864220a7eSMarcel Moolenaar return (EBUSY); 53964220a7eSMarcel Moolenaar } else 54064220a7eSMarcel Moolenaar return (EINVAL); 54164220a7eSMarcel Moolenaar 54264220a7eSMarcel Moolenaar if (rman_get_device(res) != originator) 54364220a7eSMarcel Moolenaar return (ENXIO); 54464220a7eSMarcel Moolenaar if (rman_get_flags(res) & RF_ACTIVE) 54564220a7eSMarcel Moolenaar rman_deactivate_resource(res); 54664220a7eSMarcel Moolenaar rman_set_device(res, NULL); 5479c564b6cSJohn Hay return (0); 5489c564b6cSJohn Hay } 5499c564b6cSJohn Hay 55032f606d1SPoul-Henning Kamp int 55164220a7eSMarcel Moolenaar puc_bus_get_resource(device_t dev, device_t child, int type, int rid, 5529c564b6cSJohn Hay u_long *startp, u_long *countp) 5539c564b6cSJohn Hay { 55464220a7eSMarcel Moolenaar struct puc_port *port; 55564220a7eSMarcel Moolenaar struct resource *res; 55664220a7eSMarcel Moolenaar u_long start; 5579c564b6cSJohn Hay 55864220a7eSMarcel Moolenaar /* Get our immediate child. */ 55964220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 56064220a7eSMarcel Moolenaar child = device_get_parent(child); 56164220a7eSMarcel Moolenaar if (child == NULL) 56264220a7eSMarcel Moolenaar return (EINVAL); 5639c564b6cSJohn Hay 56464220a7eSMarcel Moolenaar port = device_get_ivars(child); 56564220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 56664220a7eSMarcel Moolenaar 56764220a7eSMarcel Moolenaar if (type == port->p_bar->b_type) 56864220a7eSMarcel Moolenaar res = port->p_rres; 56964220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ) 57064220a7eSMarcel Moolenaar res = port->p_ires; 57164220a7eSMarcel Moolenaar else 57264220a7eSMarcel Moolenaar return (ENXIO); 57364220a7eSMarcel Moolenaar 57464220a7eSMarcel Moolenaar if (rid != 0 || res == NULL) 57564220a7eSMarcel Moolenaar return (ENXIO); 57664220a7eSMarcel Moolenaar 57764220a7eSMarcel Moolenaar start = rman_get_start(res); 5789c564b6cSJohn Hay if (startp != NULL) 57964220a7eSMarcel Moolenaar *startp = start; 5809c564b6cSJohn Hay if (countp != NULL) 58164220a7eSMarcel Moolenaar *countp = rman_get_end(res) - start + 1; 5829c564b6cSJohn Hay return (0); 5839c564b6cSJohn Hay } 5849c564b6cSJohn Hay 58532f606d1SPoul-Henning Kamp int 58664220a7eSMarcel Moolenaar puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, 587ef544f63SPaolo Pisati int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) 5889c564b6cSJohn Hay { 58964220a7eSMarcel Moolenaar struct puc_port *port; 5909c564b6cSJohn Hay struct puc_softc *sc; 59164220a7eSMarcel Moolenaar device_t originator; 59264220a7eSMarcel Moolenaar int i, isrc, serdev; 5939c564b6cSJohn Hay 59464220a7eSMarcel Moolenaar sc = device_get_softc(dev); 59564220a7eSMarcel Moolenaar 59664220a7eSMarcel Moolenaar /* Get our immediate child. */ 59764220a7eSMarcel Moolenaar originator = child; 59864220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 59964220a7eSMarcel Moolenaar child = device_get_parent(child); 60064220a7eSMarcel Moolenaar if (child == NULL) 60164220a7eSMarcel Moolenaar return (EINVAL); 60264220a7eSMarcel Moolenaar 60364220a7eSMarcel Moolenaar port = device_get_ivars(child); 60464220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 60564220a7eSMarcel Moolenaar 6068d715a35SPaolo Pisati if (cookiep == NULL || res != port->p_ires) 60764220a7eSMarcel Moolenaar return (EINVAL); 6088d715a35SPaolo Pisati /* We demand that serdev devices use filter_only interrupts. */ 6098d715a35SPaolo Pisati if (ihand != NULL) 6108d715a35SPaolo Pisati return (ENXIO); 61164220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 612d3c10e33SPoul-Henning Kamp return (ENXIO); 61364220a7eSMarcel Moolenaar 61464220a7eSMarcel Moolenaar /* 61564220a7eSMarcel Moolenaar * Have non-serdev ports handled by the bus implementation. It 61664220a7eSMarcel Moolenaar * supports multiple handlers for a single interrupt as it is, 61764220a7eSMarcel Moolenaar * so we wouldn't add value if we did it ourselves. 61864220a7eSMarcel Moolenaar */ 61964220a7eSMarcel Moolenaar serdev = 0; 62064220a7eSMarcel Moolenaar if (port->p_type == PUC_TYPE_SERIAL) { 62164220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN; 62264220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT) { 62364220a7eSMarcel Moolenaar port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc); 62464220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL) 62564220a7eSMarcel Moolenaar serdev = 1; 62664220a7eSMarcel Moolenaar i++, isrc <<= 1; 62764220a7eSMarcel Moolenaar } 62864220a7eSMarcel Moolenaar } 62964220a7eSMarcel Moolenaar if (!serdev) 63064220a7eSMarcel Moolenaar return (BUS_SETUP_INTR(device_get_parent(dev), originator, 631ef544f63SPaolo Pisati sc->sc_ires, flags, filt, ihand, arg, cookiep)); 63264220a7eSMarcel Moolenaar 63364220a7eSMarcel Moolenaar sc->sc_serdevs |= 1UL << (port->p_nr - 1); 63464220a7eSMarcel Moolenaar 63564220a7eSMarcel Moolenaar port->p_hasintr = 1; 63664220a7eSMarcel Moolenaar port->p_iharg = arg; 63764220a7eSMarcel Moolenaar 63864220a7eSMarcel Moolenaar *cookiep = port; 6399c564b6cSJohn Hay return (0); 6409c564b6cSJohn Hay } 6419c564b6cSJohn Hay 64232f606d1SPoul-Henning Kamp int 64364220a7eSMarcel Moolenaar puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res, 6449c564b6cSJohn Hay void *cookie) 6459c564b6cSJohn Hay { 64664220a7eSMarcel Moolenaar struct puc_port *port; 6479c564b6cSJohn Hay struct puc_softc *sc; 64864220a7eSMarcel Moolenaar device_t originator; 64964220a7eSMarcel Moolenaar int i; 6509c564b6cSJohn Hay 65164220a7eSMarcel Moolenaar sc = device_get_softc(dev); 65264220a7eSMarcel Moolenaar 65364220a7eSMarcel Moolenaar /* Get our immediate child. */ 65464220a7eSMarcel Moolenaar originator = child; 65564220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 65664220a7eSMarcel Moolenaar child = device_get_parent(child); 65764220a7eSMarcel Moolenaar if (child == NULL) 65864220a7eSMarcel Moolenaar return (EINVAL); 65964220a7eSMarcel Moolenaar 66064220a7eSMarcel Moolenaar port = device_get_ivars(child); 66164220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 66264220a7eSMarcel Moolenaar 66364220a7eSMarcel Moolenaar if (res != port->p_ires) 66464220a7eSMarcel Moolenaar return (EINVAL); 66564220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator) 6669c564b6cSJohn Hay return (ENXIO); 66764220a7eSMarcel Moolenaar 66864220a7eSMarcel Moolenaar if (!port->p_hasintr) 66964220a7eSMarcel Moolenaar return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator, 67064220a7eSMarcel Moolenaar sc->sc_ires, cookie)); 67164220a7eSMarcel Moolenaar 67264220a7eSMarcel Moolenaar if (cookie != port) 67364220a7eSMarcel Moolenaar return (EINVAL); 67464220a7eSMarcel Moolenaar 67564220a7eSMarcel Moolenaar port->p_hasintr = 0; 67664220a7eSMarcel Moolenaar port->p_iharg = NULL; 67764220a7eSMarcel Moolenaar 67864220a7eSMarcel Moolenaar for (i = 0; i < PUC_ISRCCNT; i++) 67964220a7eSMarcel Moolenaar port->p_ihsrc[i] = NULL; 68064220a7eSMarcel Moolenaar 68164220a7eSMarcel Moolenaar return (0); 6829c564b6cSJohn Hay } 6839c564b6cSJohn Hay 68432f606d1SPoul-Henning Kamp int 68564220a7eSMarcel Moolenaar puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 6869c564b6cSJohn Hay { 68764220a7eSMarcel Moolenaar struct puc_port *port; 6889c564b6cSJohn Hay 68964220a7eSMarcel Moolenaar /* Get our immediate child. */ 69064220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev) 69164220a7eSMarcel Moolenaar child = device_get_parent(child); 69264220a7eSMarcel Moolenaar if (child == NULL) 69364220a7eSMarcel Moolenaar return (EINVAL); 69464220a7eSMarcel Moolenaar 69564220a7eSMarcel Moolenaar port = device_get_ivars(child); 69664220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); 69764220a7eSMarcel Moolenaar 69864220a7eSMarcel Moolenaar if (result == NULL) 69964220a7eSMarcel Moolenaar return (EINVAL); 7009c564b6cSJohn Hay 7019c564b6cSJohn Hay switch(index) { 70264220a7eSMarcel Moolenaar case PUC_IVAR_CLOCK: 70364220a7eSMarcel Moolenaar *result = port->p_rclk; 7049c564b6cSJohn Hay break; 70564220a7eSMarcel Moolenaar case PUC_IVAR_TYPE: 70664220a7eSMarcel Moolenaar *result = port->p_type; 707153bbe3eSMarcel Moolenaar break; 7089c564b6cSJohn Hay default: 7099c564b6cSJohn Hay return (ENOENT); 7109c564b6cSJohn Hay } 7119c564b6cSJohn Hay return (0); 7129c564b6cSJohn Hay } 713