rtfps.c revision 1.3
1/*	$NetBSD: rtfps.c,v 1.3 1994/11/04 18:35:18 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#ifndef NEWCONFIG
17#include <i386/isa/isa_device.h>
18#endif
19#include <i386/isa/icu.h>
20#include <i386/isa/isavar.h>
21
22struct rtfps_softc {
23	struct device sc_dev;
24	struct intrhand sc_ih;
25
26	u_short sc_iobase;
27	u_short sc_irq;
28	int sc_alive;		/* mask of slave units attached */
29	void *sc_slaves[4];	/* com device unit numbers */
30};
31
32int rtfpsprobe();
33void rtfpsattach();
34int rtfpsintr __P((struct rtfps_softc *));
35void rt_resetintr __P((/*u_short*/));
36
37struct cfdriver rtfpscd = {
38	NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc)
39};
40
41int
42rtfpsprobe(parent, self, aux)
43	struct device *parent, *self;
44	void *aux;
45{
46	struct isa_attach_args *ia = aux;
47
48	/*
49	 * Do the normal com probe for the first UART and assume
50	 * its presence means there is a multiport board there.
51	 * XXX Needs more robustness.
52	 */
53	ia->ia_iosize = 4 * 8;
54	return comprobe1(ia->ia_iobase);
55}
56
57struct rtfps_attach_args {
58	u_short ra_iobase;
59	int ra_slave;
60};
61
62int
63rtfpssubmatch(parent, self, aux)
64	struct device *parent, *self;
65	void *aux;
66{
67	struct rtfps_softc *sc = (void *)parent;
68	struct rtfps_attach_args *aa = aux;
69	struct cfdata *cf = self->dv_cfdata;
70	int found, frobbed = 0;
71#ifdef NEWCONFIG
72
73#define cf_slave cf_loc[6]
74	if (cf->cf_slave != -1 && cf->cf_slave != aa->ra_slave)
75		return 0;
76	if (cf->cf_iobase == IOBASEUNK) {
77		frobbed = 1;
78		cf->cf_iobase = aa->ra_iobase;
79	}
80#undef cf_slave
81#else
82	struct isa_device *id = (void *)cf->cf_loc;
83
84	if (id->id_physid != -1 && id->id_physid != aa->ra_slave)
85		return 0;
86	if (id->id_iobase == 0) {
87		frobbed = 1;
88		id->id_iobase = aa->ra_iobase;
89	}
90#endif
91	found = isasubmatch(parent, self, aux);
92	if (found) {
93		sc->sc_slaves[aa->ra_slave] = self;
94		sc->sc_alive |= 1 << aa->ra_slave;
95	}
96	/*
97	 * If we changed the iobase, we have to set it back now, because it
98	 * might be a clone device, and the iobase wouldn't get set properly on
99	 * the next iteration.
100	 */
101#ifdef NEWCONFIG
102	if (frobbed)
103		cf->cf_iobase = IOBASEUNK;
104#else
105	if (frobbed)
106		id->id_iobase = 0;
107#endif
108	return found;
109}
110
111void
112rtfpsattach(parent, self, aux)
113	struct device *parent, *self;
114	void *aux;
115{
116	struct rtfps_softc *sc = (void *)self;
117	struct isa_attach_args *ia = aux;
118	struct rtfps_attach_args aa;
119
120	sc->sc_iobase = ia->ia_iobase;
121	sc->sc_irq = ia->ia_irq;
122
123	rt_resetintr(ia->ia_irq);
124
125	printf("\n");
126
127	for (aa.ra_slave = 0, aa.ra_iobase = sc->sc_iobase;
128	    aa.ra_slave < 4;
129	    aa.ra_slave++, aa.ra_iobase += 8)
130		config_search(rtfpssubmatch, self, &aa);
131
132	sc->sc_ih.ih_fun = rtfpsintr;
133	sc->sc_ih.ih_arg = sc;
134	sc->sc_ih.ih_level = IPL_TTY;
135	intr_establish(ia->ia_irq, &sc->sc_ih);
136}
137
138int
139rtfpsintr(sc)
140	struct rtfps_softc *sc;
141{
142	u_short iobase = sc->sc_iobase;
143	int alive = sc->sc_alive;
144
145	rt_resetintr(sc->sc_irq);
146
147#define	TRY(n) \
148	if (alive & (1 << (n))) \
149		comintr(sc->sc_slaves[n]);
150	TRY(0);
151	TRY(1);
152	TRY(2);
153	TRY(3);
154#undef TRY
155
156	return 1;
157}
158
159void
160rt_resetintr(irq)
161	u_short irq;
162{
163
164	switch (irq) {
165	case 9:
166		outb(0x2f2, 0);
167		break;
168	case 10:
169		outb(0x6f2, 0);
170		break;
171	case 11:
172		outb(0x6f3, 0);
173		break;
174	default:
175		panic("rt_resetintr: invalid irq");
176	}
177}
178