rtfps.c revision 1.7
1/*	$NetBSD: rtfps.c,v 1.7 1994/11/18 22:25:19 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), 1
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		void *match;
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 ((match = config_search(rtfpssubmatch, self, &isa)) != 0) {
118			sc->sc_slaves[ra.ra_slave] = match;
119			sc->sc_alive |= 1 << ra.ra_slave;
120			config_attach(self, match, &isa, rtfpsprint);
121		}
122	}
123
124	sc->sc_ih.ih_fun = rtfpsintr;
125	sc->sc_ih.ih_arg = sc;
126	sc->sc_ih.ih_level = IPL_TTY;
127	intr_establish(ia->ia_irq, &sc->sc_ih);
128}
129
130int
131rtfpsintr(sc)
132	struct rtfps_softc *sc;
133{
134	int iobase = sc->sc_iobase;
135	int alive = sc->sc_alive;
136
137	outb(sc->sc_irqport, 0);
138
139#define	TRY(n) \
140	if (alive & (1 << (n))) \
141		comintr(sc->sc_slaves[n]);
142	TRY(0);
143	TRY(1);
144	TRY(2);
145	TRY(3);
146#undef TRY
147
148	return (1);
149}
150