xref: /netbsd-src/sys/dev/isa/rtfps.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
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 
18 struct 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 
28 int rtfpsprobe();
29 void rtfpsattach();
30 int rtfpsintr __P((struct rtfps_softc *));
31 
32 struct cfdriver rtfpscd = {
33 	NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc), 1
34 };
35 
36 int
37 rtfpsprobe(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 
52 struct rtfps_attach_args {
53 	int ra_slave;
54 };
55 
56 int
57 rtfpssubmatch(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 
72 int
73 rtfpsprint(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 
83 void
84 rtfpsattach(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 
130 int
131 rtfpsintr(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