rtfps.c revision 1.5
1/*	$NetBSD: rtfps.c,v 1.5 1994/11/07 09:03:51 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	u_short sc_iobase;
23	u_short 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 *));
31void rt_resetintr __P((/*u_short*/));
32
33struct cfdriver rtfpscd = {
34	NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc), 1
35};
36
37int
38rtfpsprobe(parent, self, aux)
39	struct device *parent, *self;
40	void *aux;
41{
42	struct isa_attach_args *ia = aux;
43
44	/*
45	 * Do the normal com probe for the first UART and assume
46	 * its presence means there is a multiport board there.
47	 * XXX Needs more robustness.
48	 */
49	ia->ia_iosize = 4 * 8;
50	return comprobe1(ia->ia_iobase);
51}
52
53struct rtfps_attach_args {
54	int ra_slave;
55};
56
57int
58rtfpssubmatch(parent, match, aux)
59	struct device *parent;
60	void *match, *aux;
61{
62	struct rtfps_softc *sc = (void *)parent;
63	struct device *self = match;
64	struct isa_attach_args *ia = aux;
65	struct rtfps_attach_args *ra = ia->ia_aux;
66	struct cfdata *cf = self->dv_cfdata;
67
68	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ra->ra_slave)
69		return (0);
70	return ((*cf->cf_driver->cd_match)(parent, match, ia));
71}
72
73int
74rtfpsprint(aux, rtfps)
75	void *aux;
76	char *rtfps;
77{
78	struct isa_attach_args *ia = aux;
79	struct rtfps_attach_args *ra = ia->ia_aux;
80
81	printf(" slave %d", ra->ra_slave);
82}
83
84void
85rtfpsattach(parent, self, aux)
86	struct device *parent, *self;
87	void *aux;
88{
89	struct rtfps_softc *sc = (void *)self;
90	struct isa_attach_args *ia = aux;
91	struct rtfps_attach_args ra;
92	struct isa_attach_args isa;
93	static u_short irqport[] = {
94		-1,    -1,    -1,    -1,
95		-1,    -1,    -1,    -1,
96		-1, 0x2f2, 0x6f2, 0x6f3,
97		-1,    -1,    -1,    -1
98	};
99
100	sc->sc_iobase = ia->ia_iobase;
101
102	if (ia->ia_irq >= 16 || irqport[ia->ia_irq] == (u_short)-1)
103		panic("rtfpsattach: invalid irq");
104	sc->sc_irqport = irqport[ia->ia_irq];
105
106	outb(sc->sc_irqport, 0);
107
108	printf("\n");
109
110	isa.ia_aux = &ra;
111	for (ra.ra_slave = 0; ra.ra_slave < 4; ra.ra_slave++) {
112		void *match;
113		isa.ia_iobase = sc->sc_iobase + 8 * ra.ra_slave;
114		isa.ia_iosize = 0x666;
115		isa.ia_irq = IRQUNK;
116		isa.ia_drq = DRQUNK;
117		isa.ia_msize = 0;
118		if ((match = config_search(rtfpssubmatch, self, &isa)) != 0) {
119			sc->sc_slaves[ra.ra_slave] = match;
120			sc->sc_alive |= 1 << ra.ra_slave;
121			config_attach(self, match, &isa, rtfpsprint);
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	u_short 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