rtfps.c revision 1.8
1/*	$NetBSD: rtfps.c,v 1.8 1995/01/02 22:27:47 mycroft Exp $	*/
2
3/*
4 * Multi-port serial card interrupt demuxing support.
5 * Roland McGrath 3/20/94
6 * The author disclaims copyright and places this file in the public domain.
7 *
8 * Modified by: Charles Hannum, 3/22/94
9 */
10
11#include <sys/param.h>
12#include <sys/device.h>
13
14#include <machine/pio.h>
15
16#include <i386/isa/isavar.h>
17
18struct rtfps_softc {
19	struct device sc_dev;
20	struct intrhand sc_ih;
21
22	int sc_iobase;
23	int sc_irqport;
24	int sc_alive;		/* mask of slave units attached */
25	void *sc_slaves[4];	/* com device unit numbers */
26};
27
28int rtfpsprobe();
29void rtfpsattach();
30int rtfpsintr __P((struct rtfps_softc *));
31
32struct cfdriver rtfpscd = {
33	NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc)
34};
35
36int
37rtfpsprobe(parent, self, aux)
38	struct device *parent, *self;
39	void *aux;
40{
41	struct isa_attach_args *ia = aux;
42
43	/*
44	 * Do the normal com probe for the first UART and assume
45	 * its presence means there is a multiport board there.
46	 * XXX Needs more robustness.
47	 */
48	ia->ia_iosize = 4 * 8;
49	return comprobe1(ia->ia_iobase);
50}
51
52struct rtfps_attach_args {
53	int ra_slave;
54};
55
56int
57rtfpssubmatch(parent, match, aux)
58	struct device *parent;
59	void *match, *aux;
60{
61	struct rtfps_softc *sc = (void *)parent;
62	struct device *self = match;
63	struct isa_attach_args *ia = aux;
64	struct rtfps_attach_args *ra = ia->ia_aux;
65	struct cfdata *cf = self->dv_cfdata;
66
67	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ra->ra_slave)
68		return (0);
69	return ((*cf->cf_driver->cd_match)(parent, match, ia));
70}
71
72int
73rtfpsprint(aux, rtfps)
74	void *aux;
75	char *rtfps;
76{
77	struct isa_attach_args *ia = aux;
78	struct rtfps_attach_args *ra = ia->ia_aux;
79
80	printf(" slave %d", ra->ra_slave);
81}
82
83void
84rtfpsattach(parent, self, aux)
85	struct device *parent, *self;
86	void *aux;
87{
88	struct rtfps_softc *sc = (void *)self;
89	struct isa_attach_args *ia = aux;
90	struct rtfps_attach_args ra;
91	struct isa_attach_args isa;
92	static int irqport[] = {
93		IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK,
94		IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK,
95		IOBASEUNK,     0x2f2,     0x6f2,     0x6f3,
96		IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK
97	};
98
99	sc->sc_iobase = ia->ia_iobase;
100
101	if (ia->ia_irq >= 16 || irqport[ia->ia_irq] == IOBASEUNK)
102		panic("rtfpsattach: invalid irq");
103	sc->sc_irqport = irqport[ia->ia_irq];
104
105	outb(sc->sc_irqport, 0);
106
107	printf("\n");
108
109	isa.ia_aux = &ra;
110	for (ra.ra_slave = 0; ra.ra_slave < 4; ra.ra_slave++) {
111		struct cfdata *cf;
112		isa.ia_iobase = sc->sc_iobase + 8 * ra.ra_slave;
113		isa.ia_iosize = 0x666;
114		isa.ia_irq = IRQUNK;
115		isa.ia_drq = DRQUNK;
116		isa.ia_msize = 0;
117		if ((cf = config_search(rtfpssubmatch, self, &isa)) != 0) {
118			config_attach(self, cf, &isa, rtfpsprint);
119			sc->sc_slaves[ra.ra_slave] =
120			    cf->cf_driver->cd_devs[cf->cf_unit];
121			sc->sc_alive |= 1 << ra.ra_slave;
122		}
123	}
124
125	sc->sc_ih.ih_fun = rtfpsintr;
126	sc->sc_ih.ih_arg = sc;
127	sc->sc_ih.ih_level = IPL_TTY;
128	intr_establish(ia->ia_irq, &sc->sc_ih);
129}
130
131int
132rtfpsintr(sc)
133	struct rtfps_softc *sc;
134{
135	int iobase = sc->sc_iobase;
136	int alive = sc->sc_alive;
137
138	outb(sc->sc_irqport, 0);
139
140#define	TRY(n) \
141	if (alive & (1 << (n))) \
142		comintr(sc->sc_slaves[n]);
143	TRY(0);
144	TRY(1);
145	TRY(2);
146	TRY(3);
147#undef TRY
148
149	return (1);
150}
151