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