19c564b6cSJohn Hay /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
464220a7eSMarcel Moolenaar * Copyright (c) 2006 Marcel Moolenaar
564220a7eSMarcel Moolenaar * All rights reserved.
69c564b6cSJohn Hay *
79c564b6cSJohn Hay * Redistribution and use in source and binary forms, with or without
89c564b6cSJohn Hay * modification, are permitted provided that the following conditions
99c564b6cSJohn Hay * are met:
1064220a7eSMarcel Moolenaar *
119c564b6cSJohn Hay * 1. Redistributions of source code must retain the above copyright
12ac673f9aSWarner Losh * notice, this list of conditions and the following disclaimer.
139c564b6cSJohn Hay * 2. Redistributions in binary form must reproduce the above copyright
149c564b6cSJohn Hay * notice, this list of conditions and the following disclaimer in the
159c564b6cSJohn Hay * documentation and/or other materials provided with the distribution.
169c564b6cSJohn Hay *
179c564b6cSJohn Hay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189c564b6cSJohn Hay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199c564b6cSJohn Hay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209c564b6cSJohn Hay * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219c564b6cSJohn Hay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229c564b6cSJohn Hay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239c564b6cSJohn Hay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249c564b6cSJohn Hay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259c564b6cSJohn Hay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269c564b6cSJohn Hay * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279c564b6cSJohn Hay */
289c564b6cSJohn Hay
299c564b6cSJohn Hay #include <sys/param.h>
309c564b6cSJohn Hay #include <sys/systm.h>
319c564b6cSJohn Hay #include <sys/kernel.h>
329c564b6cSJohn Hay #include <sys/bus.h>
339c564b6cSJohn Hay #include <sys/conf.h>
349c564b6cSJohn Hay #include <sys/malloc.h>
3564220a7eSMarcel Moolenaar #include <sys/mutex.h>
36ddfc9c4cSWarner Losh #include <sys/sbuf.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
61bab8274cSDimitry Andric bool 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
6964220a7eSMarcel Moolenaar const char puc_driver_name[] = "puc";
70c9168019SPoul-Henning Kamp
71d745c852SEd Schouten static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver");
7264220a7eSMarcel Moolenaar
737029da5cSPawel Biernacki SYSCTL_NODE(_hw, OID_AUTO, puc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
7409e5d910SMitchell Horne "puc(4) driver configuration");
759725900bSRyan Stone
7664220a7eSMarcel Moolenaar struct puc_bar *
puc_get_bar(struct puc_softc * sc,int rid)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
puc_intr(void * arg)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
puc_bfe_attach(device_t dev)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
3185b56413dSWarner Losh port->p_dev = device_add_child(dev, NULL, DEVICE_UNIT_ANY);
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:
376*925e1016SJohn Baldwin device_delete_children(dev);
37764220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) {
37864220a7eSMarcel Moolenaar port = &sc->sc_port[idx];
37964220a7eSMarcel Moolenaar if (port->p_rres != NULL)
38064220a7eSMarcel Moolenaar rman_release_resource(port->p_rres);
38164220a7eSMarcel Moolenaar if (port->p_ires != NULL)
38264220a7eSMarcel Moolenaar rman_release_resource(port->p_ires);
383a3732274SDoug Ambrisko }
38464220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) {
38564220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx];
38664220a7eSMarcel Moolenaar if (bar->b_res != NULL)
38764220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type,
38864220a7eSMarcel Moolenaar bar->b_rid, bar->b_res);
38964220a7eSMarcel Moolenaar }
39064220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq);
39164220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
39264220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem);
39364220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
39464220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport);
39564220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
39664220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC);
39764220a7eSMarcel Moolenaar return (error);
3989c564b6cSJohn Hay }
3999c564b6cSJohn Hay
40032f606d1SPoul-Henning Kamp int
puc_bfe_detach(device_t dev)40164220a7eSMarcel Moolenaar puc_bfe_detach(device_t dev)
40264220a7eSMarcel Moolenaar {
40364220a7eSMarcel Moolenaar struct puc_bar *bar;
40464220a7eSMarcel Moolenaar struct puc_port *port;
40564220a7eSMarcel Moolenaar struct puc_softc *sc;
40664220a7eSMarcel Moolenaar int error, idx;
40764220a7eSMarcel Moolenaar
40864220a7eSMarcel Moolenaar sc = device_get_softc(dev);
40964220a7eSMarcel Moolenaar
41064220a7eSMarcel Moolenaar /* Detach our children. */
41111a91178SJohn Baldwin error = bus_generic_detach(dev);
41211a91178SJohn Baldwin if (error != 0)
41311a91178SJohn Baldwin return (error);
41411a91178SJohn Baldwin
41564220a7eSMarcel Moolenaar for (idx = 0; idx < sc->sc_nports; idx++) {
41664220a7eSMarcel Moolenaar port = &sc->sc_port[idx];
41764220a7eSMarcel Moolenaar if (port->p_dev == NULL)
41864220a7eSMarcel Moolenaar continue;
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 }
42464220a7eSMarcel Moolenaar
42564220a7eSMarcel Moolenaar if (sc->sc_serdevs != 0UL)
42664220a7eSMarcel Moolenaar bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
42764220a7eSMarcel Moolenaar bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires);
42864220a7eSMarcel Moolenaar
42964220a7eSMarcel Moolenaar for (idx = 0; idx < PUC_PCI_BARS; idx++) {
43064220a7eSMarcel Moolenaar bar = &sc->sc_bar[idx];
43164220a7eSMarcel Moolenaar if (bar->b_res != NULL)
43264220a7eSMarcel Moolenaar bus_release_resource(sc->sc_dev, bar->b_type,
43364220a7eSMarcel Moolenaar bar->b_rid, bar->b_res);
43464220a7eSMarcel Moolenaar }
43564220a7eSMarcel Moolenaar
43664220a7eSMarcel Moolenaar rman_fini(&sc->sc_irq);
43764220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
43864220a7eSMarcel Moolenaar rman_fini(&sc->sc_iomem);
43964220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
44064220a7eSMarcel Moolenaar rman_fini(&sc->sc_ioport);
44164220a7eSMarcel Moolenaar free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
44264220a7eSMarcel Moolenaar free(sc->sc_port, M_PUC);
44364220a7eSMarcel Moolenaar return (0);
44464220a7eSMarcel Moolenaar }
44564220a7eSMarcel Moolenaar
44664220a7eSMarcel Moolenaar int
puc_bfe_probe(device_t dev,const struct puc_cfg * cfg)44764220a7eSMarcel Moolenaar puc_bfe_probe(device_t dev, const struct puc_cfg *cfg)
44864220a7eSMarcel Moolenaar {
44964220a7eSMarcel Moolenaar struct puc_softc *sc;
45064220a7eSMarcel Moolenaar intptr_t res;
45164220a7eSMarcel Moolenaar int error;
45264220a7eSMarcel Moolenaar
45364220a7eSMarcel Moolenaar sc = device_get_softc(dev);
45464220a7eSMarcel Moolenaar sc->sc_dev = dev;
45564220a7eSMarcel Moolenaar sc->sc_cfg = cfg;
45664220a7eSMarcel Moolenaar
45764220a7eSMarcel Moolenaar /* We don't attach to single-port serial cards. */
45864220a7eSMarcel Moolenaar if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P)
45964220a7eSMarcel Moolenaar return (EDOOFUS);
46064220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
46164220a7eSMarcel Moolenaar if (error)
46264220a7eSMarcel Moolenaar return (error);
46364220a7eSMarcel Moolenaar error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res);
46464220a7eSMarcel Moolenaar if (error)
46564220a7eSMarcel Moolenaar return (error);
46664220a7eSMarcel Moolenaar if (res != 0)
46764220a7eSMarcel Moolenaar device_set_desc(dev, (const char *)res);
46864220a7eSMarcel Moolenaar return (BUS_PROBE_DEFAULT);
46964220a7eSMarcel Moolenaar }
47064220a7eSMarcel Moolenaar
47164220a7eSMarcel Moolenaar struct resource *
puc_bus_alloc_resource(device_t dev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)47264220a7eSMarcel Moolenaar puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
4732dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
47464220a7eSMarcel Moolenaar {
47564220a7eSMarcel Moolenaar struct puc_port *port;
47664220a7eSMarcel Moolenaar struct resource *res;
47764220a7eSMarcel Moolenaar device_t assigned, originator;
47864220a7eSMarcel Moolenaar int error;
47964220a7eSMarcel Moolenaar
48064220a7eSMarcel Moolenaar /* Get our immediate child. */
48164220a7eSMarcel Moolenaar originator = child;
48264220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
48364220a7eSMarcel Moolenaar child = device_get_parent(child);
48464220a7eSMarcel Moolenaar if (child == NULL)
48564220a7eSMarcel Moolenaar return (NULL);
48664220a7eSMarcel Moolenaar
48764220a7eSMarcel Moolenaar port = device_get_ivars(child);
48864220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
48964220a7eSMarcel Moolenaar
49064220a7eSMarcel Moolenaar if (rid == NULL || *rid != 0)
49164220a7eSMarcel Moolenaar return (NULL);
49264220a7eSMarcel Moolenaar
49364220a7eSMarcel Moolenaar /* We only support default allocations. */
49482ed3cb0SJustin Hibbits if (!RMAN_IS_DEFAULT_RANGE(start, end))
49564220a7eSMarcel Moolenaar return (NULL);
49664220a7eSMarcel Moolenaar
49764220a7eSMarcel Moolenaar if (type == port->p_bar->b_type)
49864220a7eSMarcel Moolenaar res = port->p_rres;
49964220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ)
50064220a7eSMarcel Moolenaar res = port->p_ires;
50164220a7eSMarcel Moolenaar else
50264220a7eSMarcel Moolenaar return (NULL);
50364220a7eSMarcel Moolenaar
50464220a7eSMarcel Moolenaar if (res == NULL)
50564220a7eSMarcel Moolenaar return (NULL);
50664220a7eSMarcel Moolenaar
50764220a7eSMarcel Moolenaar assigned = rman_get_device(res);
50864220a7eSMarcel Moolenaar if (assigned == NULL) /* Not allocated */
50964220a7eSMarcel Moolenaar rman_set_device(res, originator);
51064220a7eSMarcel Moolenaar else if (assigned != originator)
51164220a7eSMarcel Moolenaar return (NULL);
51264220a7eSMarcel Moolenaar
51364220a7eSMarcel Moolenaar if (flags & RF_ACTIVE) {
51464220a7eSMarcel Moolenaar error = rman_activate_resource(res);
51564220a7eSMarcel Moolenaar if (error) {
51664220a7eSMarcel Moolenaar if (assigned == NULL)
51764220a7eSMarcel Moolenaar rman_set_device(res, NULL);
51864220a7eSMarcel Moolenaar return (NULL);
51964220a7eSMarcel Moolenaar }
52064220a7eSMarcel Moolenaar }
52164220a7eSMarcel Moolenaar
52264220a7eSMarcel Moolenaar return (res);
52364220a7eSMarcel Moolenaar }
52464220a7eSMarcel Moolenaar
52564220a7eSMarcel Moolenaar int
puc_bus_release_resource(device_t dev,device_t child,struct resource * res)5269dbf5b0eSJohn Baldwin puc_bus_release_resource(device_t dev, device_t child, struct resource *res)
5279c564b6cSJohn Hay {
52864220a7eSMarcel Moolenaar struct puc_port *port;
52964220a7eSMarcel Moolenaar device_t originator;
53064220a7eSMarcel Moolenaar
53164220a7eSMarcel Moolenaar /* Get our immediate child. */
53264220a7eSMarcel Moolenaar originator = child;
53364220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
53464220a7eSMarcel Moolenaar child = device_get_parent(child);
53564220a7eSMarcel Moolenaar if (child == NULL)
53664220a7eSMarcel Moolenaar return (EINVAL);
53764220a7eSMarcel Moolenaar
53864220a7eSMarcel Moolenaar port = device_get_ivars(child);
53964220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
54064220a7eSMarcel Moolenaar
5419dbf5b0eSJohn Baldwin if (res == NULL)
54264220a7eSMarcel Moolenaar return (EINVAL);
54364220a7eSMarcel Moolenaar
5449dbf5b0eSJohn Baldwin if (res == port->p_ires) {
54564220a7eSMarcel Moolenaar if (port->p_hasintr)
54664220a7eSMarcel Moolenaar return (EBUSY);
5479dbf5b0eSJohn Baldwin } else if (res != port->p_rres)
54864220a7eSMarcel Moolenaar return (EINVAL);
54964220a7eSMarcel Moolenaar
55064220a7eSMarcel Moolenaar if (rman_get_device(res) != originator)
55164220a7eSMarcel Moolenaar return (ENXIO);
55264220a7eSMarcel Moolenaar if (rman_get_flags(res) & RF_ACTIVE)
55364220a7eSMarcel Moolenaar rman_deactivate_resource(res);
55464220a7eSMarcel Moolenaar rman_set_device(res, NULL);
5559c564b6cSJohn Hay return (0);
5569c564b6cSJohn Hay }
5579c564b6cSJohn Hay
55832f606d1SPoul-Henning Kamp int
puc_bus_get_resource(device_t dev,device_t child,int type,int rid,rman_res_t * startp,rman_res_t * countp)55964220a7eSMarcel Moolenaar puc_bus_get_resource(device_t dev, device_t child, int type, int rid,
5602dd1bdf1SJustin Hibbits rman_res_t *startp, rman_res_t *countp)
5619c564b6cSJohn Hay {
56264220a7eSMarcel Moolenaar struct puc_port *port;
56364220a7eSMarcel Moolenaar struct resource *res;
5642dd1bdf1SJustin Hibbits rman_res_t start;
5659c564b6cSJohn Hay
56664220a7eSMarcel Moolenaar /* Get our immediate child. */
56764220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
56864220a7eSMarcel Moolenaar child = device_get_parent(child);
56964220a7eSMarcel Moolenaar if (child == NULL)
57064220a7eSMarcel Moolenaar return (EINVAL);
5719c564b6cSJohn Hay
57264220a7eSMarcel Moolenaar port = device_get_ivars(child);
57364220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
57464220a7eSMarcel Moolenaar
57564220a7eSMarcel Moolenaar if (type == port->p_bar->b_type)
57664220a7eSMarcel Moolenaar res = port->p_rres;
57764220a7eSMarcel Moolenaar else if (type == SYS_RES_IRQ)
57864220a7eSMarcel Moolenaar res = port->p_ires;
57964220a7eSMarcel Moolenaar else
58064220a7eSMarcel Moolenaar return (ENXIO);
58164220a7eSMarcel Moolenaar
58264220a7eSMarcel Moolenaar if (rid != 0 || res == NULL)
58364220a7eSMarcel Moolenaar return (ENXIO);
58464220a7eSMarcel Moolenaar
58564220a7eSMarcel Moolenaar start = rman_get_start(res);
5869c564b6cSJohn Hay if (startp != NULL)
58764220a7eSMarcel Moolenaar *startp = start;
5889c564b6cSJohn Hay if (countp != NULL)
58964220a7eSMarcel Moolenaar *countp = rman_get_end(res) - start + 1;
5909c564b6cSJohn Hay return (0);
5919c564b6cSJohn Hay }
5929c564b6cSJohn Hay
59332f606d1SPoul-Henning Kamp int
puc_bus_setup_intr(device_t dev,device_t child,struct resource * res,int flags,driver_filter_t * filt,void (* ihand)(void *),void * arg,void ** cookiep)59464220a7eSMarcel Moolenaar puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
595ef544f63SPaolo Pisati int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
5969c564b6cSJohn Hay {
59764220a7eSMarcel Moolenaar struct puc_port *port;
5989c564b6cSJohn Hay struct puc_softc *sc;
59964220a7eSMarcel Moolenaar device_t originator;
60064220a7eSMarcel Moolenaar int i, isrc, serdev;
6019c564b6cSJohn Hay
60264220a7eSMarcel Moolenaar sc = device_get_softc(dev);
60364220a7eSMarcel Moolenaar
60464220a7eSMarcel Moolenaar /* Get our immediate child. */
60564220a7eSMarcel Moolenaar originator = child;
60664220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
60764220a7eSMarcel Moolenaar child = device_get_parent(child);
60864220a7eSMarcel Moolenaar if (child == NULL)
60964220a7eSMarcel Moolenaar return (EINVAL);
61064220a7eSMarcel Moolenaar
61164220a7eSMarcel Moolenaar port = device_get_ivars(child);
61264220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
61364220a7eSMarcel Moolenaar
6148d715a35SPaolo Pisati if (cookiep == NULL || res != port->p_ires)
61564220a7eSMarcel Moolenaar return (EINVAL);
6168d715a35SPaolo Pisati /* We demand that serdev devices use filter_only interrupts. */
617323e149aSJohn Baldwin if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
6188d715a35SPaolo Pisati return (ENXIO);
61964220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator)
620d3c10e33SPoul-Henning Kamp return (ENXIO);
62164220a7eSMarcel Moolenaar
62264220a7eSMarcel Moolenaar /*
62364220a7eSMarcel Moolenaar * Have non-serdev ports handled by the bus implementation. It
62464220a7eSMarcel Moolenaar * supports multiple handlers for a single interrupt as it is,
62564220a7eSMarcel Moolenaar * so we wouldn't add value if we did it ourselves.
62664220a7eSMarcel Moolenaar */
62764220a7eSMarcel Moolenaar serdev = 0;
62864220a7eSMarcel Moolenaar if (port->p_type == PUC_TYPE_SERIAL) {
62964220a7eSMarcel Moolenaar i = 0, isrc = SER_INT_OVERRUN;
63064220a7eSMarcel Moolenaar while (i < PUC_ISRCCNT) {
63164220a7eSMarcel Moolenaar port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
63264220a7eSMarcel Moolenaar if (port->p_ihsrc[i] != NULL)
63364220a7eSMarcel Moolenaar serdev = 1;
63464220a7eSMarcel Moolenaar i++, isrc <<= 1;
63564220a7eSMarcel Moolenaar }
63664220a7eSMarcel Moolenaar }
63764220a7eSMarcel Moolenaar if (!serdev)
63864220a7eSMarcel Moolenaar return (BUS_SETUP_INTR(device_get_parent(dev), originator,
639ef544f63SPaolo Pisati sc->sc_ires, flags, filt, ihand, arg, cookiep));
64064220a7eSMarcel Moolenaar
64164220a7eSMarcel Moolenaar sc->sc_serdevs |= 1UL << (port->p_nr - 1);
64264220a7eSMarcel Moolenaar
64364220a7eSMarcel Moolenaar port->p_hasintr = 1;
64464220a7eSMarcel Moolenaar port->p_iharg = arg;
64564220a7eSMarcel Moolenaar
64664220a7eSMarcel Moolenaar *cookiep = port;
6479c564b6cSJohn Hay return (0);
6489c564b6cSJohn Hay }
6499c564b6cSJohn Hay
65032f606d1SPoul-Henning Kamp int
puc_bus_teardown_intr(device_t dev,device_t child,struct resource * res,void * cookie)65164220a7eSMarcel Moolenaar puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res,
6529c564b6cSJohn Hay void *cookie)
6539c564b6cSJohn Hay {
65464220a7eSMarcel Moolenaar struct puc_port *port;
6559c564b6cSJohn Hay struct puc_softc *sc;
65664220a7eSMarcel Moolenaar device_t originator;
65764220a7eSMarcel Moolenaar int i;
6589c564b6cSJohn Hay
65964220a7eSMarcel Moolenaar sc = device_get_softc(dev);
66064220a7eSMarcel Moolenaar
66164220a7eSMarcel Moolenaar /* Get our immediate child. */
66264220a7eSMarcel Moolenaar originator = child;
66364220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
66464220a7eSMarcel Moolenaar child = device_get_parent(child);
66564220a7eSMarcel Moolenaar if (child == NULL)
66664220a7eSMarcel Moolenaar return (EINVAL);
66764220a7eSMarcel Moolenaar
66864220a7eSMarcel Moolenaar port = device_get_ivars(child);
66964220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
67064220a7eSMarcel Moolenaar
67164220a7eSMarcel Moolenaar if (res != port->p_ires)
67264220a7eSMarcel Moolenaar return (EINVAL);
67364220a7eSMarcel Moolenaar if (rman_get_device(port->p_ires) != originator)
6749c564b6cSJohn Hay return (ENXIO);
67564220a7eSMarcel Moolenaar
67664220a7eSMarcel Moolenaar if (!port->p_hasintr)
67764220a7eSMarcel Moolenaar return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator,
67864220a7eSMarcel Moolenaar sc->sc_ires, cookie));
67964220a7eSMarcel Moolenaar
68064220a7eSMarcel Moolenaar if (cookie != port)
68164220a7eSMarcel Moolenaar return (EINVAL);
68264220a7eSMarcel Moolenaar
68364220a7eSMarcel Moolenaar port->p_hasintr = 0;
68464220a7eSMarcel Moolenaar port->p_iharg = NULL;
68564220a7eSMarcel Moolenaar
68664220a7eSMarcel Moolenaar for (i = 0; i < PUC_ISRCCNT; i++)
68764220a7eSMarcel Moolenaar port->p_ihsrc[i] = NULL;
68864220a7eSMarcel Moolenaar
68964220a7eSMarcel Moolenaar return (0);
6909c564b6cSJohn Hay }
6919c564b6cSJohn Hay
69232f606d1SPoul-Henning Kamp int
puc_bus_read_ivar(device_t dev,device_t child,int index,uintptr_t * result)69364220a7eSMarcel Moolenaar puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
6949c564b6cSJohn Hay {
69564220a7eSMarcel Moolenaar struct puc_port *port;
6969c564b6cSJohn Hay
69764220a7eSMarcel Moolenaar /* Get our immediate child. */
69864220a7eSMarcel Moolenaar while (child != NULL && device_get_parent(child) != dev)
69964220a7eSMarcel Moolenaar child = device_get_parent(child);
70064220a7eSMarcel Moolenaar if (child == NULL)
70164220a7eSMarcel Moolenaar return (EINVAL);
70264220a7eSMarcel Moolenaar
70364220a7eSMarcel Moolenaar port = device_get_ivars(child);
70464220a7eSMarcel Moolenaar KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
70564220a7eSMarcel Moolenaar
70664220a7eSMarcel Moolenaar if (result == NULL)
70764220a7eSMarcel Moolenaar return (EINVAL);
7089c564b6cSJohn Hay
7099c564b6cSJohn Hay switch(index) {
71064220a7eSMarcel Moolenaar case PUC_IVAR_CLOCK:
71164220a7eSMarcel Moolenaar *result = port->p_rclk;
7129c564b6cSJohn Hay break;
71364220a7eSMarcel Moolenaar case PUC_IVAR_TYPE:
71464220a7eSMarcel Moolenaar *result = port->p_type;
715153bbe3eSMarcel Moolenaar break;
7169c564b6cSJohn Hay default:
7179c564b6cSJohn Hay return (ENOENT);
7189c564b6cSJohn Hay }
7199c564b6cSJohn Hay return (0);
7209c564b6cSJohn Hay }
721573e64d4SJohn Baldwin
722573e64d4SJohn Baldwin int
puc_bus_print_child(device_t dev,device_t child)723573e64d4SJohn Baldwin puc_bus_print_child(device_t dev, device_t child)
724573e64d4SJohn Baldwin {
725573e64d4SJohn Baldwin struct puc_port *port;
726573e64d4SJohn Baldwin int retval;
727573e64d4SJohn Baldwin
728573e64d4SJohn Baldwin port = device_get_ivars(child);
729573e64d4SJohn Baldwin retval = 0;
730573e64d4SJohn Baldwin
731573e64d4SJohn Baldwin retval += bus_print_child_header(dev, child);
732573e64d4SJohn Baldwin retval += printf(" at port %d", port->p_nr);
733573e64d4SJohn Baldwin retval += bus_print_child_footer(dev, child);
734573e64d4SJohn Baldwin
735573e64d4SJohn Baldwin return (retval);
736573e64d4SJohn Baldwin }
737573e64d4SJohn Baldwin
738573e64d4SJohn Baldwin int
puc_bus_child_location(device_t dev,device_t child,struct sbuf * sb)739ddfc9c4cSWarner Losh puc_bus_child_location(device_t dev, device_t child, struct sbuf *sb)
740573e64d4SJohn Baldwin {
741573e64d4SJohn Baldwin struct puc_port *port;
742573e64d4SJohn Baldwin
743573e64d4SJohn Baldwin port = device_get_ivars(child);
744ddfc9c4cSWarner Losh sbuf_printf(sb, "port=%d", port->p_nr);
745573e64d4SJohn Baldwin return (0);
746573e64d4SJohn Baldwin }
747573e64d4SJohn Baldwin
748573e64d4SJohn Baldwin int
puc_bus_child_pnpinfo(device_t dev,device_t child,struct sbuf * sb)749ddfc9c4cSWarner Losh puc_bus_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb)
750573e64d4SJohn Baldwin {
751573e64d4SJohn Baldwin struct puc_port *port;
752573e64d4SJohn Baldwin
753573e64d4SJohn Baldwin port = device_get_ivars(child);
754ddfc9c4cSWarner Losh sbuf_printf(sb, "type=%d", port->p_type);
755573e64d4SJohn Baldwin return (0);
756573e64d4SJohn Baldwin }
757