xref: /freebsd/sys/dev/puc/puc.c (revision 5bb3134a8c21cb87b30e135ef168483f0333dabb)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2006 Marcel Moolenaar
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/sbuf.h>
40 #include <sys/sysctl.h>
41 
42 #include <machine/bus.h>
43 #include <machine/resource.h>
44 #include <sys/rman.h>
45 
46 #include <dev/pci/pcireg.h>
47 #include <dev/pci/pcivar.h>
48 
49 #include <dev/puc/puc_bus.h>
50 #include <dev/puc/puc_cfg.h>
51 #include <dev/puc/puc_bfe.h>
52 
53 #define	PUC_ISRCCNT	5
54 
55 struct puc_port {
56 	struct puc_bar	*p_bar;
57 	struct resource *p_rres;
58 	struct resource *p_ires;
59 	device_t	p_dev;
60 	int		p_nr;
61 	int		p_type;
62 	int		p_rclk;
63 
64 	int		p_hasintr:1;
65 
66 	serdev_intr_t	*p_ihsrc[PUC_ISRCCNT];
67 	void		*p_iharg;
68 
69 	int		p_ipend;
70 };
71 
72 devclass_t puc_devclass;
73 const char puc_driver_name[] = "puc";
74 
75 static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver");
76 
77 SYSCTL_NODE(_hw, OID_AUTO, puc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
78     "puc(9) driver configuration");
79 
80 struct puc_bar *
81 puc_get_bar(struct puc_softc *sc, int rid)
82 {
83 	struct puc_bar *bar;
84 	struct rman *rm;
85 	rman_res_t end, start;
86 	int error, i;
87 
88 	/* Find the BAR entry with the given RID. */
89 	i = 0;
90 	while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid)
91 		i++;
92 	if (i < PUC_PCI_BARS)
93 		return (&sc->sc_bar[i]);
94 
95 	/* Not found. If we're looking for an unused entry, return NULL. */
96 	if (rid == -1)
97 		return (NULL);
98 
99 	/* Get an unused entry for us to fill.  */
100 	bar = puc_get_bar(sc, -1);
101 	if (bar == NULL)
102 		return (NULL);
103 	bar->b_rid = rid;
104 	bar->b_type = SYS_RES_IOPORT;
105 	bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type,
106 	    &bar->b_rid, RF_ACTIVE);
107 	if (bar->b_res == NULL) {
108 		bar->b_rid = rid;
109 		bar->b_type = SYS_RES_MEMORY;
110 		bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type,
111 		    &bar->b_rid, RF_ACTIVE);
112 		if (bar->b_res == NULL) {
113 			bar->b_rid = -1;
114 			return (NULL);
115 		}
116 	}
117 
118 	/* Update our managed space. */
119 	rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem;
120 	start = rman_get_start(bar->b_res);
121 	end = rman_get_end(bar->b_res);
122 	error = rman_manage_region(rm, start, end);
123 	if (error) {
124 		bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid,
125 		    bar->b_res);
126 		bar->b_res = NULL;
127 		bar->b_rid = -1;
128 		bar = NULL;
129 	}
130 
131 	return (bar);
132 }
133 
134 static int
135 puc_intr(void *arg)
136 {
137 	struct puc_port *port;
138 	struct puc_softc *sc = arg;
139 	u_long ds, dev, devs;
140 	int i, idx, ipend, isrc, nints;
141 	uint8_t ilr;
142 
143 	nints = 0;
144 	while (1) {
145 		/*
146 		 * Obtain the set of devices with pending interrupts.
147 		 */
148 		devs = sc->sc_serdevs;
149 		if (sc->sc_ilr == PUC_ILR_DIGI) {
150 			idx = 0;
151 			while (devs & (0xfful << idx)) {
152 				ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
153 				devs &= ~0ul ^ ((u_long)ilr << idx);
154 				idx += 8;
155 			}
156 		} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
157 			/*
158 			 * Don't trust the value if it's the same as the option
159 			 * register. It may mean that the ILR is not active and
160 			 * we're reading the option register instead. This may
161 			 * lead to false positives on 8-port boards.
162 			 */
163 			ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
164 			if (ilr != (sc->sc_cfg_data & 0xff))
165 				devs &= (u_long)ilr;
166 		}
167 		if (devs == 0UL)
168 			break;
169 
170 		/*
171 		 * Obtain the set of interrupt sources from those devices
172 		 * that have pending interrupts.
173 		 */
174 		ipend = 0;
175 		idx = 0, dev = 1UL;
176 		ds = devs;
177 		while (ds != 0UL) {
178 			while ((ds & dev) == 0UL)
179 				idx++, dev <<= 1;
180 			ds &= ~dev;
181 			port = &sc->sc_port[idx];
182 			port->p_ipend = SERDEV_IPEND(port->p_dev);
183 			ipend |= port->p_ipend;
184 		}
185 		if (ipend == 0)
186 			break;
187 
188 		i = 0, isrc = SER_INT_OVERRUN;
189 		while (ipend) {
190 			while (i < PUC_ISRCCNT && !(ipend & isrc))
191 				i++, isrc <<= 1;
192 			KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
193 			ipend &= ~isrc;
194 			idx = 0, dev = 1UL;
195 			ds = devs;
196 			while (ds != 0UL) {
197 				while ((ds & dev) == 0UL)
198 					idx++, dev <<= 1;
199 				ds &= ~dev;
200 				port = &sc->sc_port[idx];
201 				if (!(port->p_ipend & isrc))
202 					continue;
203 				if (port->p_ihsrc[i] != NULL)
204 					(*port->p_ihsrc[i])(port->p_iharg);
205 				nints++;
206 			}
207 		}
208 	}
209 
210 	return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY);
211 }
212 
213 int
214 puc_bfe_attach(device_t dev)
215 {
216 	char buffer[64];
217 	struct puc_bar *bar;
218 	struct puc_port *port;
219 	struct puc_softc *sc;
220 	struct rman *rm;
221 	intptr_t res;
222 	bus_addr_t ofs, start;
223 	bus_size_t size;
224 	bus_space_handle_t bsh;
225 	bus_space_tag_t bst;
226 	int error, idx;
227 
228 	sc = device_get_softc(dev);
229 
230 	for (idx = 0; idx < PUC_PCI_BARS; idx++)
231 		sc->sc_bar[idx].b_rid = -1;
232 
233 	do {
234 		sc->sc_ioport.rm_type = RMAN_ARRAY;
235 		error = rman_init(&sc->sc_ioport);
236 		if (!error) {
237 			sc->sc_iomem.rm_type = RMAN_ARRAY;
238 			error = rman_init(&sc->sc_iomem);
239 			if (!error) {
240 				sc->sc_irq.rm_type = RMAN_ARRAY;
241 				error = rman_init(&sc->sc_irq);
242 				if (!error)
243 					break;
244 				rman_fini(&sc->sc_iomem);
245 			}
246 			rman_fini(&sc->sc_ioport);
247 		}
248 		return (error);
249 	} while (0);
250 
251 	snprintf(buffer, sizeof(buffer), "%s I/O port mapping",
252 	    device_get_nameunit(dev));
253 	sc->sc_ioport.rm_descr = strdup(buffer, M_PUC);
254 	snprintf(buffer, sizeof(buffer), "%s I/O memory mapping",
255 	    device_get_nameunit(dev));
256 	sc->sc_iomem.rm_descr = strdup(buffer, M_PUC);
257 	snprintf(buffer, sizeof(buffer), "%s port numbers",
258 	    device_get_nameunit(dev));
259 	sc->sc_irq.rm_descr = strdup(buffer, M_PUC);
260 
261 	error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
262 	KASSERT(error == 0, ("%s %d", __func__, __LINE__));
263 	sc->sc_nports = (int)res;
264 	sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port),
265 	    M_PUC, M_WAITOK|M_ZERO);
266 
267 	error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports);
268 	if (error)
269 		goto fail;
270 
271 	error = puc_config(sc, PUC_CFG_SETUP, 0, &res);
272 	if (error)
273 		goto fail;
274 
275 	for (idx = 0; idx < sc->sc_nports; idx++) {
276 		port = &sc->sc_port[idx];
277 		port->p_nr = idx + 1;
278 		error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res);
279 		if (error)
280 			goto fail;
281 		port->p_type = res;
282 		error = puc_config(sc, PUC_CFG_GET_RID, idx, &res);
283 		if (error)
284 			goto fail;
285 		bar = puc_get_bar(sc, res);
286 		if (bar == NULL) {
287 			error = ENXIO;
288 			goto fail;
289 		}
290 		port->p_bar = bar;
291 		start = rman_get_start(bar->b_res);
292 		error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res);
293 		if (error)
294 			goto fail;
295 		ofs = res;
296 		error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res);
297 		if (error)
298 			goto fail;
299 		size = res;
300 		rm = (bar->b_type == SYS_RES_IOPORT)
301 		    ? &sc->sc_ioport: &sc->sc_iomem;
302 		port->p_rres = rman_reserve_resource(rm, start + ofs,
303 		    start + ofs + size - 1, size, 0, NULL);
304 		if (port->p_rres != NULL) {
305 			bsh = rman_get_bushandle(bar->b_res);
306 			bst = rman_get_bustag(bar->b_res);
307 			bus_space_subregion(bst, bsh, ofs, size, &bsh);
308 			rman_set_bushandle(port->p_rres, bsh);
309 			rman_set_bustag(port->p_rres, bst);
310 		}
311 		port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr,
312 		    port->p_nr, 1, 0, NULL);
313 		if (port->p_ires == NULL) {
314 			error = ENXIO;
315 			goto fail;
316 		}
317 		error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res);
318 		if (error)
319 			goto fail;
320 		port->p_rclk = res;
321 
322 		port->p_dev = device_add_child(dev, NULL, -1);
323 		if (port->p_dev != NULL)
324 			device_set_ivars(port->p_dev, (void *)port);
325 	}
326 
327 	error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res);
328 	if (error)
329 		goto fail;
330 	sc->sc_ilr = res;
331 	if (bootverbose && sc->sc_ilr != 0)
332 		device_printf(dev, "using interrupt latch register\n");
333 
334 	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
335 	    RF_ACTIVE|RF_SHAREABLE);
336 	if (sc->sc_ires != NULL) {
337 		error = bus_setup_intr(dev, sc->sc_ires,
338 		    INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie);
339 		if (error)
340 			error = bus_setup_intr(dev, sc->sc_ires,
341 			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
342 			    (driver_intr_t *)puc_intr, sc, &sc->sc_icookie);
343 		else
344 			sc->sc_fastintr = 1;
345 
346 		if (error) {
347 			device_printf(dev, "could not activate interrupt\n");
348 			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
349 			    sc->sc_ires);
350 			sc->sc_ires = NULL;
351 		}
352 	}
353 	if (sc->sc_ires == NULL) {
354 		/* XXX no interrupt resource. Force polled mode. */
355 		sc->sc_polled = 1;
356 	}
357 
358 	/* Probe and attach our children. */
359 	for (idx = 0; idx < sc->sc_nports; idx++) {
360 		port = &sc->sc_port[idx];
361 		if (port->p_dev == NULL)
362 			continue;
363 		error = device_probe_and_attach(port->p_dev);
364 		if (error) {
365 			device_delete_child(dev, port->p_dev);
366 			port->p_dev = NULL;
367 		}
368 	}
369 
370 	/*
371 	 * If there are no serdev devices, then our interrupt handler
372 	 * will do nothing. Tear it down.
373 	 */
374 	if (sc->sc_serdevs == 0UL)
375 		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
376 
377 	return (0);
378 
379 fail:
380 	for (idx = 0; idx < sc->sc_nports; idx++) {
381 		port = &sc->sc_port[idx];
382 		if (port->p_dev != NULL)
383 			device_delete_child(dev, port->p_dev);
384 		if (port->p_rres != NULL)
385 			rman_release_resource(port->p_rres);
386 		if (port->p_ires != NULL)
387 			rman_release_resource(port->p_ires);
388 	}
389 	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
390 		bar = &sc->sc_bar[idx];
391 		if (bar->b_res != NULL)
392 			bus_release_resource(sc->sc_dev, bar->b_type,
393 			    bar->b_rid, bar->b_res);
394 	}
395 	rman_fini(&sc->sc_irq);
396 	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
397 	rman_fini(&sc->sc_iomem);
398 	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
399 	rman_fini(&sc->sc_ioport);
400 	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
401 	free(sc->sc_port, M_PUC);
402 	return (error);
403 }
404 
405 int
406 puc_bfe_detach(device_t dev)
407 {
408 	struct puc_bar *bar;
409 	struct puc_port *port;
410 	struct puc_softc *sc;
411 	int error, idx;
412 
413 	sc = device_get_softc(dev);
414 
415 	/* Detach our children. */
416 	error = 0;
417 	for (idx = 0; idx < sc->sc_nports; idx++) {
418 		port = &sc->sc_port[idx];
419 		if (port->p_dev == NULL)
420 			continue;
421 		if (device_delete_child(dev, port->p_dev) == 0) {
422 			if (port->p_rres != NULL)
423 				rman_release_resource(port->p_rres);
424 			if (port->p_ires != NULL)
425 				rman_release_resource(port->p_ires);
426 		} else
427 			error = ENXIO;
428 	}
429 	if (error)
430 		return (error);
431 
432 	if (sc->sc_serdevs != 0UL)
433 		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
434 	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires);
435 
436 	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
437 		bar = &sc->sc_bar[idx];
438 		if (bar->b_res != NULL)
439 			bus_release_resource(sc->sc_dev, bar->b_type,
440 			    bar->b_rid, bar->b_res);
441 	}
442 
443 	rman_fini(&sc->sc_irq);
444 	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
445 	rman_fini(&sc->sc_iomem);
446 	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
447 	rman_fini(&sc->sc_ioport);
448 	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
449 	free(sc->sc_port, M_PUC);
450 	return (0);
451 }
452 
453 int
454 puc_bfe_probe(device_t dev, const struct puc_cfg *cfg)
455 {
456 	struct puc_softc *sc;
457 	intptr_t res;
458 	int error;
459 
460 	sc = device_get_softc(dev);
461 	sc->sc_dev = dev;
462 	sc->sc_cfg = cfg;
463 
464 	/* We don't attach to single-port serial cards. */
465 	if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P)
466 		return (EDOOFUS);
467 	error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
468 	if (error)
469 		return (error);
470 	error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res);
471 	if (error)
472 		return (error);
473 	if (res != 0)
474 		device_set_desc(dev, (const char *)res);
475 	return (BUS_PROBE_DEFAULT);
476 }
477 
478 struct resource *
479 puc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
480     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
481 {
482 	struct puc_port *port;
483 	struct resource *res;
484 	device_t assigned, originator;
485 	int error;
486 
487 	/* Get our immediate child. */
488 	originator = child;
489 	while (child != NULL && device_get_parent(child) != dev)
490 		child = device_get_parent(child);
491 	if (child == NULL)
492 		return (NULL);
493 
494 	port = device_get_ivars(child);
495 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
496 
497 	if (rid == NULL || *rid != 0)
498 		return (NULL);
499 
500 	/* We only support default allocations. */
501 	if (!RMAN_IS_DEFAULT_RANGE(start, end))
502 		return (NULL);
503 
504 	if (type == port->p_bar->b_type)
505 		res = port->p_rres;
506 	else if (type == SYS_RES_IRQ)
507 		res = port->p_ires;
508 	else
509 		return (NULL);
510 
511 	if (res == NULL)
512 		return (NULL);
513 
514 	assigned = rman_get_device(res);
515 	if (assigned == NULL)	/* Not allocated */
516 		rman_set_device(res, originator);
517 	else if (assigned != originator)
518 		return (NULL);
519 
520 	if (flags & RF_ACTIVE) {
521 		error = rman_activate_resource(res);
522 		if (error) {
523 			if (assigned == NULL)
524 				rman_set_device(res, NULL);
525 			return (NULL);
526 		}
527 	}
528 
529 	return (res);
530 }
531 
532 int
533 puc_bus_release_resource(device_t dev, device_t child, int type, int rid,
534     struct resource *res)
535 {
536 	struct puc_port *port;
537 	device_t originator;
538 
539 	/* Get our immediate child. */
540 	originator = child;
541 	while (child != NULL && device_get_parent(child) != dev)
542 		child = device_get_parent(child);
543 	if (child == NULL)
544 		return (EINVAL);
545 
546 	port = device_get_ivars(child);
547 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
548 
549 	if (rid != 0 || res == NULL)
550 		return (EINVAL);
551 
552 	if (type == port->p_bar->b_type) {
553 		if (res != port->p_rres)
554 			return (EINVAL);
555 	} else if (type == SYS_RES_IRQ) {
556 		if (res != port->p_ires)
557 			return (EINVAL);
558 		if (port->p_hasintr)
559 			return (EBUSY);
560 	} else
561 		return (EINVAL);
562 
563 	if (rman_get_device(res) != originator)
564 		return (ENXIO);
565 	if (rman_get_flags(res) & RF_ACTIVE)
566 		rman_deactivate_resource(res);
567 	rman_set_device(res, NULL);
568 	return (0);
569 }
570 
571 int
572 puc_bus_get_resource(device_t dev, device_t child, int type, int rid,
573     rman_res_t *startp, rman_res_t *countp)
574 {
575 	struct puc_port *port;
576 	struct resource *res;
577 	rman_res_t start;
578 
579 	/* Get our immediate child. */
580 	while (child != NULL && device_get_parent(child) != dev)
581 		child = device_get_parent(child);
582 	if (child == NULL)
583 		return (EINVAL);
584 
585 	port = device_get_ivars(child);
586 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
587 
588 	if (type == port->p_bar->b_type)
589 		res = port->p_rres;
590 	else if (type == SYS_RES_IRQ)
591 		res = port->p_ires;
592 	else
593 		return (ENXIO);
594 
595 	if (rid != 0 || res == NULL)
596 		return (ENXIO);
597 
598 	start = rman_get_start(res);
599 	if (startp != NULL)
600 		*startp = start;
601 	if (countp != NULL)
602 		*countp = rman_get_end(res) - start + 1;
603 	return (0);
604 }
605 
606 int
607 puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
608     int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
609 {
610 	struct puc_port *port;
611 	struct puc_softc *sc;
612 	device_t originator;
613 	int i, isrc, serdev;
614 
615 	sc = device_get_softc(dev);
616 
617 	/* Get our immediate child. */
618 	originator = child;
619 	while (child != NULL && device_get_parent(child) != dev)
620 		child = device_get_parent(child);
621 	if (child == NULL)
622 		return (EINVAL);
623 
624 	port = device_get_ivars(child);
625 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
626 
627 	if (cookiep == NULL || res != port->p_ires)
628 		return (EINVAL);
629 	/* We demand that serdev devices use filter_only interrupts. */
630 	if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
631 		return (ENXIO);
632 	if (rman_get_device(port->p_ires) != originator)
633 		return (ENXIO);
634 
635 	/*
636 	 * Have non-serdev ports handled by the bus implementation. It
637 	 * supports multiple handlers for a single interrupt as it is,
638 	 * so we wouldn't add value if we did it ourselves.
639 	 */
640 	serdev = 0;
641 	if (port->p_type == PUC_TYPE_SERIAL) {
642 		i = 0, isrc = SER_INT_OVERRUN;
643 		while (i < PUC_ISRCCNT) {
644 			port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
645 			if (port->p_ihsrc[i] != NULL)
646 				serdev = 1;
647 			i++, isrc <<= 1;
648 		}
649 	}
650 	if (!serdev)
651 		return (BUS_SETUP_INTR(device_get_parent(dev), originator,
652 		    sc->sc_ires, flags, filt, ihand, arg, cookiep));
653 
654 	sc->sc_serdevs |= 1UL << (port->p_nr - 1);
655 
656 	port->p_hasintr = 1;
657 	port->p_iharg = arg;
658 
659 	*cookiep = port;
660 	return (0);
661 }
662 
663 int
664 puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res,
665     void *cookie)
666 {
667 	struct puc_port *port;
668 	struct puc_softc *sc;
669 	device_t originator;
670 	int i;
671 
672 	sc = device_get_softc(dev);
673 
674 	/* Get our immediate child. */
675 	originator = child;
676 	while (child != NULL && device_get_parent(child) != dev)
677 		child = device_get_parent(child);
678 	if (child == NULL)
679 		return (EINVAL);
680 
681 	port = device_get_ivars(child);
682 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
683 
684 	if (res != port->p_ires)
685 		return (EINVAL);
686 	if (rman_get_device(port->p_ires) != originator)
687 		return (ENXIO);
688 
689 	if (!port->p_hasintr)
690 		return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator,
691 		    sc->sc_ires, cookie));
692 
693 	if (cookie != port)
694 		return (EINVAL);
695 
696 	port->p_hasintr = 0;
697 	port->p_iharg = NULL;
698 
699 	for (i = 0; i < PUC_ISRCCNT; i++)
700 		port->p_ihsrc[i] = NULL;
701 
702 	return (0);
703 }
704 
705 int
706 puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
707 {
708 	struct puc_port *port;
709 
710 	/* Get our immediate child. */
711 	while (child != NULL && device_get_parent(child) != dev)
712 		child = device_get_parent(child);
713 	if (child == NULL)
714 		return (EINVAL);
715 
716 	port = device_get_ivars(child);
717 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
718 
719 	if (result == NULL)
720 		return (EINVAL);
721 
722 	switch(index) {
723 	case PUC_IVAR_CLOCK:
724 		*result = port->p_rclk;
725 		break;
726 	case PUC_IVAR_TYPE:
727 		*result = port->p_type;
728 		break;
729 	default:
730 		return (ENOENT);
731 	}
732 	return (0);
733 }
734 
735 int
736 puc_bus_print_child(device_t dev, device_t child)
737 {
738 	struct puc_port *port;
739 	int retval;
740 
741 	port = device_get_ivars(child);
742 	retval = 0;
743 
744 	retval += bus_print_child_header(dev, child);
745 	retval += printf(" at port %d", port->p_nr);
746 	retval += bus_print_child_footer(dev, child);
747 
748 	return (retval);
749 }
750 
751 int
752 puc_bus_child_location(device_t dev, device_t child, struct sbuf *sb)
753 {
754 	struct puc_port *port;
755 
756 	port = device_get_ivars(child);
757 	sbuf_printf(sb, "port=%d", port->p_nr);
758 	return (0);
759 }
760 
761 int
762 puc_bus_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb)
763 {
764 	struct puc_port *port;
765 
766 	port = device_get_ivars(child);
767 	sbuf_printf(sb, "type=%d", port->p_type);
768 	return (0);
769 }
770