puc.c revision 170386
1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2006 Marcel Moolenaar
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw *
9260684Skaiw * 1. Redistributions of source code must retain the above copyright
10260684Skaiw *    notice, this list of conditions and the following disclaimer.
11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
12260684Skaiw *    notice, this list of conditions and the following disclaimer in the
13260684Skaiw *    documentation and/or other materials provided with the distribution.
14260684Skaiw *
15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18260684Skaiw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include <sys/cdefs.h>
28260684Skaiw__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 170386 2007-06-06 22:17:01Z piso $");
29260684Skaiw
30260684Skaiw#include <sys/param.h>
31260684Skaiw#include <sys/systm.h>
32260684Skaiw#include <sys/kernel.h>
33260684Skaiw#include <sys/bus.h>
34260684Skaiw#include <sys/conf.h>
35260684Skaiw#include <sys/malloc.h>
36260684Skaiw#include <sys/mutex.h>
37260684Skaiw
38260684Skaiw#include <machine/bus.h>
39260684Skaiw#include <machine/resource.h>
40260684Skaiw#include <sys/rman.h>
41260684Skaiw
42260684Skaiw#include <dev/pci/pcireg.h>
43260684Skaiw#include <dev/pci/pcivar.h>
44260684Skaiw
45260684Skaiw#include <dev/puc/puc_bus.h>
46260684Skaiw#include <dev/puc/puc_cfg.h>
47260684Skaiw#include <dev/puc/puc_bfe.h>
48260684Skaiw
49260684Skaiw#define	PUC_ISRCCNT	5
50260684Skaiw
51260684Skaiwstruct puc_port {
52260684Skaiw	struct puc_bar	*p_bar;
53260684Skaiw	struct resource *p_rres;
54260684Skaiw	struct resource *p_ires;
55260684Skaiw	device_t	p_dev;
56260684Skaiw	int		p_nr;
57260684Skaiw	int		p_type;
58260684Skaiw	int		p_rclk;
59260684Skaiw
60260684Skaiw	int		p_hasintr:1;
61260684Skaiw
62260684Skaiw	serdev_intr_t	*p_ihsrc[PUC_ISRCCNT];
63260684Skaiw	void		*p_iharg;
64260684Skaiw
65260684Skaiw	int		p_ipend;
66260684Skaiw};
67260684Skaiw
68260684Skaiwdevclass_t puc_devclass;
69260684Skaiwconst char puc_driver_name[] = "puc";
70260684Skaiw
71260684SkaiwMALLOC_DEFINE(M_PUC, "PUC", "PUC driver");
72260684Skaiw
73260684Skaiwstruct puc_bar *
74260684Skaiwpuc_get_bar(struct puc_softc *sc, int rid)
75260684Skaiw{
76260684Skaiw	struct puc_bar *bar;
77260684Skaiw	struct rman *rm;
78260684Skaiw	u_long end, start;
79260684Skaiw	int error, i;
80260684Skaiw
81260684Skaiw	/* Find the BAR entry with the given RID. */
82260684Skaiw	i = 0;
83260684Skaiw	while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid)
84260684Skaiw		i++;
85260684Skaiw	if (i < PUC_PCI_BARS)
86260684Skaiw		return (&sc->sc_bar[i]);
87260684Skaiw
88260684Skaiw	/* Not found. If we're looking for an unused entry, return NULL. */
89260684Skaiw	if (rid == -1)
90260684Skaiw		return (NULL);
91260684Skaiw
92260684Skaiw	/* Get an unused entry for us to fill.  */
93260684Skaiw	bar = puc_get_bar(sc, -1);
94260684Skaiw	if (bar == NULL)
95260684Skaiw		return (NULL);
96260684Skaiw	bar->b_rid = rid;
97260684Skaiw	bar->b_type = SYS_RES_IOPORT;
98260684Skaiw	bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type,
99260684Skaiw	    &bar->b_rid, RF_ACTIVE);
100260684Skaiw	if (bar->b_res == NULL) {
101260684Skaiw		bar->b_rid = rid;
102260684Skaiw		bar->b_type = SYS_RES_MEMORY;
103260684Skaiw		bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type,
104260684Skaiw		    &bar->b_rid, RF_ACTIVE);
105260684Skaiw		if (bar->b_res == NULL) {
106260684Skaiw			bar->b_rid = -1;
107260684Skaiw			return (NULL);
108260684Skaiw		}
109260684Skaiw	}
110260684Skaiw
111260684Skaiw	/* Update our managed space. */
112260684Skaiw	rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem;
113260684Skaiw	start = rman_get_start(bar->b_res);
114260684Skaiw	end = rman_get_end(bar->b_res);
115260684Skaiw	error = rman_manage_region(rm, start, end);
116260684Skaiw	if (error) {
117260684Skaiw		bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid,
118260684Skaiw		    bar->b_res);
119260684Skaiw		bar->b_res = NULL;
120260684Skaiw		bar->b_rid = -1;
121260684Skaiw		bar = NULL;
122260684Skaiw	}
123260684Skaiw
124260684Skaiw	return (bar);
125260684Skaiw}
126260684Skaiw
127260684Skaiwstatic int
128260684Skaiwpuc_intr(void *arg)
129260684Skaiw{
130260684Skaiw	struct puc_port *port;
131260684Skaiw	struct puc_softc *sc = arg;
132260684Skaiw	u_long dev, devs;
133260684Skaiw	int i, idx, ipend, isrc;
134260684Skaiw	uint8_t ilr;
135260684Skaiw
136260684Skaiw	devs = sc->sc_serdevs;
137260684Skaiw	if (sc->sc_ilr == PUC_ILR_DIGI) {
138260684Skaiw		idx = 0;
139260684Skaiw		while (devs & (0xfful << idx)) {
140260684Skaiw			ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
141260684Skaiw			devs &= ~0ul ^ ((u_long)ilr << idx);
142260684Skaiw			idx += 8;
143260684Skaiw		}
144260684Skaiw	} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
145260684Skaiw		/*
146260684Skaiw		 * Don't trust the value if it's the same as the option
147260684Skaiw		 * register. It may mean that the ILR is not active and
148260684Skaiw		 * we're reading the option register instead. This may
149260684Skaiw		 * lead to false positives on 8-port boards.
150260684Skaiw		 */
151260684Skaiw		ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
152		if (ilr != (sc->sc_cfg_data & 0xff))
153			devs &= (u_long)ilr;
154	}
155
156	ipend = 0;
157	idx = 0, dev = 1UL;
158	while (devs != 0UL) {
159		while ((devs & dev) == 0UL)
160			idx++, dev <<= 1;
161		devs &= ~dev;
162		port = &sc->sc_port[idx];
163		port->p_ipend = SERDEV_IPEND(port->p_dev);
164		ipend |= port->p_ipend;
165	}
166
167	i = 0, isrc = SER_INT_OVERRUN;
168	while (ipend) {
169		while (i < PUC_ISRCCNT && !(ipend & isrc))
170			i++, isrc <<= 1;
171		KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
172		ipend &= ~isrc;
173		idx = 0, dev = 1UL;
174		devs = sc->sc_serdevs;
175		while (devs != 0UL) {
176			while ((devs & dev) == 0UL)
177				idx++, dev <<= 1;
178			devs &= ~dev;
179			port = &sc->sc_port[idx];
180			if (!(port->p_ipend & isrc))
181				continue;
182			if (port->p_ihsrc[i] != NULL)
183				(*port->p_ihsrc[i])(port->p_iharg);
184		}
185		return (FILTER_HANDLED);
186	}
187	return (FILTER_STRAY);
188}
189
190int
191puc_bfe_attach(device_t dev)
192{
193	char buffer[64];
194	struct puc_bar *bar;
195	struct puc_port *port;
196	struct puc_softc *sc;
197	struct rman *rm;
198	intptr_t res;
199	bus_addr_t ofs, start;
200	bus_size_t size;
201	bus_space_handle_t bsh;
202	bus_space_tag_t bst;
203	int error, idx;
204
205	sc = device_get_softc(dev);
206
207	for (idx = 0; idx < PUC_PCI_BARS; idx++)
208		sc->sc_bar[idx].b_rid = -1;
209
210	do {
211		sc->sc_ioport.rm_type = RMAN_ARRAY;
212		error = rman_init(&sc->sc_ioport);
213		if (!error) {
214			sc->sc_iomem.rm_type = RMAN_ARRAY;
215			error = rman_init(&sc->sc_iomem);
216			if (!error) {
217				sc->sc_irq.rm_type = RMAN_ARRAY;
218				error = rman_init(&sc->sc_irq);
219				if (!error)
220					break;
221				rman_fini(&sc->sc_iomem);
222			}
223			rman_fini(&sc->sc_ioport);
224		}
225		return (error);
226	} while (0);
227
228	snprintf(buffer, sizeof(buffer), "%s I/O port mapping",
229	    device_get_nameunit(dev));
230	sc->sc_ioport.rm_descr = strdup(buffer, M_PUC);
231	snprintf(buffer, sizeof(buffer), "%s I/O memory mapping",
232	    device_get_nameunit(dev));
233	sc->sc_iomem.rm_descr = strdup(buffer, M_PUC);
234	snprintf(buffer, sizeof(buffer), "%s port numbers",
235	    device_get_nameunit(dev));
236	sc->sc_irq.rm_descr = strdup(buffer, M_PUC);
237
238	error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
239	KASSERT(error == 0, ("%s %d", __func__, __LINE__));
240	sc->sc_nports = (int)res;
241	sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port),
242	    M_PUC, M_WAITOK|M_ZERO);
243
244	error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports);
245	if (error)
246		goto fail;
247
248	error = puc_config(sc, PUC_CFG_SETUP, 0, &res);
249	if (error)
250		goto fail;
251
252	for (idx = 0; idx < sc->sc_nports; idx++) {
253		port = &sc->sc_port[idx];
254		port->p_nr = idx + 1;
255		error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res);
256		if (error)
257			goto fail;
258		port->p_type = res;
259		error = puc_config(sc, PUC_CFG_GET_RID, idx, &res);
260		if (error)
261			goto fail;
262		bar = puc_get_bar(sc, res);
263		if (bar == NULL) {
264			error = ENXIO;
265			goto fail;
266		}
267		port->p_bar = bar;
268		start = rman_get_start(bar->b_res);
269		error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res);
270		if (error)
271			goto fail;
272		ofs = res;
273		error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res);
274		if (error)
275			goto fail;
276		size = res;
277		rm = (bar->b_type == SYS_RES_IOPORT)
278		    ? &sc->sc_ioport: &sc->sc_iomem;
279		port->p_rres = rman_reserve_resource(rm, start + ofs,
280		    start + ofs + size - 1, size, 0, NULL);
281		if (port->p_rres != NULL) {
282			bsh = rman_get_bushandle(bar->b_res);
283			bst = rman_get_bustag(bar->b_res);
284			bus_space_subregion(bst, bsh, ofs, size, &bsh);
285			rman_set_bushandle(port->p_rres, bsh);
286			rman_set_bustag(port->p_rres, bst);
287		}
288		port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr,
289		    port->p_nr, 1, 0, NULL);
290		if (port->p_ires == NULL) {
291			error = ENXIO;
292			goto fail;
293		}
294		error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res);
295		if (error)
296			goto fail;
297		port->p_rclk = res;
298
299		port->p_dev = device_add_child(dev, NULL, -1);
300		if (port->p_dev != NULL)
301			device_set_ivars(port->p_dev, (void *)port);
302	}
303
304	error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res);
305	if (error)
306		goto fail;
307	sc->sc_ilr = res;
308	if (bootverbose && sc->sc_ilr != 0)
309		device_printf(dev, "using interrupt latch register\n");
310
311	sc->sc_irid = 0;
312	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
313	    RF_ACTIVE|RF_SHAREABLE);
314	if (sc->sc_ires != NULL) {
315		error = bus_setup_intr(dev, sc->sc_ires,
316		    INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie);
317		if (error)
318			error = bus_setup_intr(dev, sc->sc_ires,
319			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
320			    (driver_intr_t *)puc_intr, sc, &sc->sc_icookie);
321		else
322			sc->sc_fastintr = 1;
323
324		if (error) {
325			device_printf(dev, "could not activate interrupt\n");
326			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
327			    sc->sc_ires);
328			sc->sc_ires = NULL;
329		}
330	}
331	if (sc->sc_ires == NULL) {
332		/* XXX no interrupt resource. Force polled mode. */
333		sc->sc_polled = 1;
334	}
335
336	/* Probe and attach our children. */
337	for (idx = 0; idx < sc->sc_nports; idx++) {
338		port = &sc->sc_port[idx];
339		if (port->p_dev == NULL)
340			continue;
341		error = device_probe_and_attach(port->p_dev);
342		if (error) {
343			device_delete_child(dev, port->p_dev);
344			port->p_dev = NULL;
345		}
346	}
347
348	/*
349	 * If there are no serdev devices, then our interrupt handler
350	 * will do nothing. Tear it down.
351	 */
352	if (sc->sc_serdevs == 0UL)
353		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
354
355	return (0);
356
357fail:
358	for (idx = 0; idx < sc->sc_nports; idx++) {
359		port = &sc->sc_port[idx];
360		if (port->p_dev != NULL)
361			device_delete_child(dev, port->p_dev);
362		if (port->p_rres != NULL)
363			rman_release_resource(port->p_rres);
364		if (port->p_ires != NULL)
365			rman_release_resource(port->p_ires);
366	}
367	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
368		bar = &sc->sc_bar[idx];
369		if (bar->b_res != NULL)
370			bus_release_resource(sc->sc_dev, bar->b_type,
371			    bar->b_rid, bar->b_res);
372	}
373	rman_fini(&sc->sc_irq);
374	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
375	rman_fini(&sc->sc_iomem);
376	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
377	rman_fini(&sc->sc_ioport);
378	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
379	free(sc->sc_port, M_PUC);
380	return (error);
381}
382
383int
384puc_bfe_detach(device_t dev)
385{
386	struct puc_bar *bar;
387	struct puc_port *port;
388	struct puc_softc *sc;
389	int error, idx;
390
391	sc = device_get_softc(dev);
392
393	/* Detach our children. */
394	error = 0;
395	for (idx = 0; idx < sc->sc_nports; idx++) {
396		port = &sc->sc_port[idx];
397		if (port->p_dev == NULL)
398			continue;
399		if (device_detach(port->p_dev) == 0) {
400			device_delete_child(dev, port->p_dev);
401			if (port->p_rres != NULL)
402				rman_release_resource(port->p_rres);
403			if (port->p_ires != NULL)
404				rman_release_resource(port->p_ires);
405		} else
406			error = ENXIO;
407	}
408	if (error)
409		return (error);
410
411	if (sc->sc_serdevs != 0UL)
412		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
413	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires);
414
415	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
416		bar = &sc->sc_bar[idx];
417		if (bar->b_res != NULL)
418			bus_release_resource(sc->sc_dev, bar->b_type,
419			    bar->b_rid, bar->b_res);
420	}
421
422	rman_fini(&sc->sc_irq);
423	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
424	rman_fini(&sc->sc_iomem);
425	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
426	rman_fini(&sc->sc_ioport);
427	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
428	free(sc->sc_port, M_PUC);
429	return (0);
430}
431
432int
433puc_bfe_probe(device_t dev, const struct puc_cfg *cfg)
434{
435	struct puc_softc *sc;
436	intptr_t res;
437	int error;
438
439	sc = device_get_softc(dev);
440	sc->sc_dev = dev;
441	sc->sc_cfg = cfg;
442
443	/* We don't attach to single-port serial cards. */
444	if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P)
445		return (EDOOFUS);
446	error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
447	if (error)
448		return (error);
449	error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res);
450	if (error)
451		return (error);
452	if (res != 0)
453		device_set_desc(dev, (const char *)res);
454	return (BUS_PROBE_DEFAULT);
455}
456
457struct resource *
458puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
459    u_long start, u_long end, u_long count, u_int flags)
460{
461	struct puc_port *port;
462	struct resource *res;
463	device_t assigned, originator;
464	int error;
465
466	/* Get our immediate child. */
467	originator = child;
468	while (child != NULL && device_get_parent(child) != dev)
469		child = device_get_parent(child);
470	if (child == NULL)
471		return (NULL);
472
473	port = device_get_ivars(child);
474	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
475
476	if (rid == NULL || *rid != 0)
477		return (NULL);
478
479	/* We only support default allocations. */
480	if (start != 0UL || end != ~0UL)
481		return (NULL);
482
483	if (type == port->p_bar->b_type)
484		res = port->p_rres;
485	else if (type == SYS_RES_IRQ)
486		res = port->p_ires;
487	else
488		return (NULL);
489
490	if (res == NULL)
491		return (NULL);
492
493	assigned = rman_get_device(res);
494	if (assigned == NULL)	/* Not allocated */
495		rman_set_device(res, originator);
496	else if (assigned != originator)
497		return (NULL);
498
499	if (flags & RF_ACTIVE) {
500		error = rman_activate_resource(res);
501		if (error) {
502			if (assigned == NULL)
503				rman_set_device(res, NULL);
504			return (NULL);
505		}
506	}
507
508	return (res);
509}
510
511int
512puc_bus_release_resource(device_t dev, device_t child, int type, int rid,
513    struct resource *res)
514{
515	struct puc_port *port;
516	device_t originator;
517
518	/* Get our immediate child. */
519	originator = child;
520	while (child != NULL && device_get_parent(child) != dev)
521		child = device_get_parent(child);
522	if (child == NULL)
523		return (EINVAL);
524
525	port = device_get_ivars(child);
526	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
527
528	if (rid != 0 || res == NULL)
529		return (EINVAL);
530
531	if (type == port->p_bar->b_type) {
532		if (res != port->p_rres)
533			return (EINVAL);
534	} else if (type == SYS_RES_IRQ) {
535		if (res != port->p_ires)
536			return (EINVAL);
537		if (port->p_hasintr)
538			return (EBUSY);
539	} else
540		return (EINVAL);
541
542	if (rman_get_device(res) != originator)
543		return (ENXIO);
544	if (rman_get_flags(res) & RF_ACTIVE)
545		rman_deactivate_resource(res);
546	rman_set_device(res, NULL);
547	return (0);
548}
549
550int
551puc_bus_get_resource(device_t dev, device_t child, int type, int rid,
552    u_long *startp, u_long *countp)
553{
554	struct puc_port *port;
555	struct resource *res;
556	u_long start;
557
558	/* Get our immediate child. */
559	while (child != NULL && device_get_parent(child) != dev)
560		child = device_get_parent(child);
561	if (child == NULL)
562		return (EINVAL);
563
564	port = device_get_ivars(child);
565	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
566
567	if (type == port->p_bar->b_type)
568		res = port->p_rres;
569	else if (type == SYS_RES_IRQ)
570		res = port->p_ires;
571	else
572		return (ENXIO);
573
574	if (rid != 0 || res == NULL)
575		return (ENXIO);
576
577	start = rman_get_start(res);
578	if (startp != NULL)
579		*startp = start;
580	if (countp != NULL)
581		*countp = rman_get_end(res) - start + 1;
582	return (0);
583}
584
585int
586puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
587    int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
588{
589	struct puc_port *port;
590	struct puc_softc *sc;
591	device_t originator;
592	int i, isrc, serdev;
593
594	sc = device_get_softc(dev);
595
596	/* Get our immediate child. */
597	originator = child;
598	while (child != NULL && device_get_parent(child) != dev)
599		child = device_get_parent(child);
600	if (child == NULL)
601		return (EINVAL);
602
603	port = device_get_ivars(child);
604	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
605
606	if (cookiep == NULL || res != port->p_ires)
607		return (EINVAL);
608	/* We demand that serdev devices use filter_only interrupts. */
609	if (ihand != NULL)
610		return (ENXIO);
611	if (rman_get_device(port->p_ires) != originator)
612		return (ENXIO);
613
614	/*
615	 * Have non-serdev ports handled by the bus implementation. It
616	 * supports multiple handlers for a single interrupt as it is,
617	 * so we wouldn't add value if we did it ourselves.
618	 */
619	serdev = 0;
620	if (port->p_type == PUC_TYPE_SERIAL) {
621		i = 0, isrc = SER_INT_OVERRUN;
622		while (i < PUC_ISRCCNT) {
623			port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
624			if (port->p_ihsrc[i] != NULL)
625				serdev = 1;
626			i++, isrc <<= 1;
627		}
628	}
629	if (!serdev)
630		return (BUS_SETUP_INTR(device_get_parent(dev), originator,
631		    sc->sc_ires, flags, filt, ihand, arg, cookiep));
632
633	sc->sc_serdevs |= 1UL << (port->p_nr - 1);
634
635	port->p_hasintr = 1;
636	port->p_iharg = arg;
637
638	*cookiep = port;
639	return (0);
640}
641
642int
643puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res,
644    void *cookie)
645{
646	struct puc_port *port;
647	struct puc_softc *sc;
648	device_t originator;
649	int i;
650
651	sc = device_get_softc(dev);
652
653	/* Get our immediate child. */
654	originator = child;
655	while (child != NULL && device_get_parent(child) != dev)
656		child = device_get_parent(child);
657	if (child == NULL)
658		return (EINVAL);
659
660	port = device_get_ivars(child);
661	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
662
663	if (res != port->p_ires)
664		return (EINVAL);
665	if (rman_get_device(port->p_ires) != originator)
666		return (ENXIO);
667
668	if (!port->p_hasintr)
669		return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator,
670		    sc->sc_ires, cookie));
671
672	if (cookie != port)
673		return (EINVAL);
674
675	port->p_hasintr = 0;
676	port->p_iharg = NULL;
677
678	for (i = 0; i < PUC_ISRCCNT; i++)
679		port->p_ihsrc[i] = NULL;
680
681	return (0);
682}
683
684int
685puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
686{
687	struct puc_port *port;
688
689	/* Get our immediate child. */
690	while (child != NULL && device_get_parent(child) != dev)
691		child = device_get_parent(child);
692	if (child == NULL)
693		return (EINVAL);
694
695	port = device_get_ivars(child);
696	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
697
698	if (result == NULL)
699		return (EINVAL);
700
701	switch(index) {
702	case PUC_IVAR_CLOCK:
703		*result = port->p_rclk;
704		break;
705	case PUC_IVAR_TYPE:
706		*result = port->p_type;
707		break;
708	default:
709		return (ENOENT);
710	}
711	return (0);
712}
713