Annotation of sys/dev/isa/hsq.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hsq.c,v 1.4 2007/04/10 17:47:55 miod Exp $ */
2:
3: /*-
4: * Copyright (c) 1999 Denis A. Doroshenko. All rights reserved.
5: *
6: * This code is derived from BSD-licensed software written by
7: * Christopher G. Demetriou and Charles Hannum, which was
8: * derived from public-domain software written by Roland McGrath.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above
16: * copyright notice, this list of conditions and the following
17: * disclaimer in the documentation and/or other materials provided
18: * with the distribution.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: *
32: * Note: this copyright notice is a version of Berkeley-style license
33: * derived from the original by Regents of the University of California.
34: */
35:
36: /*
37: * This is OpenBSD driver for Hostess 4-channel serial mux -- hsq
38: * ("hsq" stands for "HoStess Quad channel mux"; funny enough).
39: *
40: * Hostess may be the registered trademark of Comtrol Corp.
41: * WARNING! The information that is below about Hostess family
42: * serial cards is not based on any information from Comtrol,
43: * and I DON'T guarantee this information is authentic or right.
44: * For authentic information on Hostess serial cards visit
45: * http://www.comtrol.com
46: *
47: * Hostess mux is a very simple thing -- it's 4/8/16(?) UARTs one
48: * after another, that share one IRQ. Under linux they may be used
49: * with setserial, BSD systems are not so flexible with serial ports,
50: * so i took ast driver and changed it, in the way i think Hostess
51: * muxes should work. It works ifine with my mux (it has ti16c750
52: * UARTs on it, and current pccom driver detects them as 550A, so i
53: * changed it a bit, to use the power of 750).
54: *
55: * Hostess cards use scratch register of lead UART to control the mux.
56: * When a byte is written to the register it is meant as mask, which
57: * enables/disables interrupts from 1-8 UARTs by setting 0-7 bits to
58: * 1/0. Let us call this register UER -- UARTs Enable Register.
59: * When a byte is read it is mask of bits for UARTs, that have some
60: * event(s), which are analyzed using that UART's IIR. Let us call
61: * this register UIR -- UARTs Interrrupt Register.
62: *
63: * Note: four higher bits of the UIR are alway 1 for 4-channel mux,
64: * I have no idea what could that mean, it would be better to have
65: * them zeroed.
66: *
67: * Shitty feature: UER's value upon power up is absolutely random,
68: * so that UARTs can work and can not and you don't uderstand what's up...
69: * Thus, we have to set its value to 0x0f to get all four UARTs
70: * interrupting, just after we've attached the mux...
71: *
72: * Use it and share my fun!
73: * --
74: * Denis A. Doroshenko <cyxob@isl.vtu.lt>
75: */
76:
77: #include <sys/param.h>
78: #include <sys/systm.h>
79: #include <sys/device.h>
80: #include <sys/termios.h>
81:
82: #include <machine/bus.h>
83: #include <machine/intr.h>
84:
85: #include <dev/isa/isavar.h>
86: #include <dev/ic/comreg.h>
87: #include <dev/ic/comvar.h>
88:
89: /*
90: * For 8-channel Hostess serial card change: NSLAVES -> 8, UART_MASK -> 0xff
91: */
92: #define NSLAVES (4)
93: #define UART_MASK (0x0f)
94:
95: #define com_uer (com_scratch)
96: #define com_uir (com_scratch)
97:
98: struct hsq_softc {
99: struct device sc_dev;
100: void *sc_ih;
101:
102: bus_space_tag_t sc_iot;
103: int sc_iobase;
104:
105: void *sc_slaves[NSLAVES]; /* com device unit numbers */
106: bus_space_handle_t sc_slaveioh[NSLAVES];
107: };
108:
109: int hsqprobe(struct device *, void *, void *);
110: void hsqattach(struct device *, struct device *, void *);
111: int hsqintr(void *);
112: int hsqprint(void *, const char *);
113:
114: struct cfattach hsq_ca = {
115: sizeof(struct hsq_softc), hsqprobe, hsqattach
116: };
117:
118: struct cfdriver hsq_cd = {
119: NULL, "hsq", DV_TTY
120: };
121:
122: int
123: hsqprobe(parent, self, aux)
124: struct device *parent;
125: void *self;
126: void *aux;
127: {
128: struct isa_attach_args *ia = aux;
129: int iobase = ia->ia_iobase;
130: bus_space_tag_t iot = ia->ia_iot;
131: bus_space_handle_t ioh;
132: int i, rv = 1;
133:
134: /*
135: * Do the normal com probe for the first UART and assume
136: * its presence, and the ability to map the other UARTs,
137: * means there is a multiport board there.
138: * XXX Needs more robustness.
139: */
140:
141: /* if the first port is in use as console, then it. */
142: if (iobase == comconsaddr && !comconsattached)
143: goto checkmappings;
144:
145: /* map UART ports (COM_NPORTS == 8) */
146: if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
147: rv = 0;
148: goto out;
149: }
150:
151: rv = comprobe1(iot, ioh);
152: bus_space_unmap(iot, ioh, COM_NPORTS);
153: if (rv == 0)
154: goto out;
155:
156: checkmappings:
157: for (i = 1; i < NSLAVES; i++) {
158: iobase += COM_NPORTS;
159:
160: if (iobase == comconsaddr && !comconsattached)
161: continue;
162:
163: if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
164: rv = 0;
165: goto out;
166: }
167: bus_space_unmap(iot, ioh, COM_NPORTS);
168: }
169:
170: out:
171: if (rv)
172: ia->ia_iosize = NSLAVES * COM_NPORTS;
173: return (rv);
174: }
175:
176: int
177: hsqprint(aux, pnp)
178: void *aux;
179: const char *pnp;
180: {
181: struct commulti_attach_args *ca = aux;
182:
183: if (pnp)
184: printf("com at %s", pnp);
185: printf(" slave %d", ca->ca_slave);
186: return (UNCONF);
187: }
188:
189: void
190: hsqattach(parent, self, aux)
191: struct device *parent, *self;
192: void *aux;
193: {
194: struct hsq_softc *sc = (void *)self;
195: struct isa_attach_args *ia = aux;
196: struct commulti_attach_args ca;
197: int i;
198:
199: sc->sc_iot = ia->ia_iot;
200: sc->sc_iobase = ia->ia_iobase;
201:
202: for (i = 0; i < NSLAVES; i++)
203: if (bus_space_map(sc->sc_iot, sc->sc_iobase + i * COM_NPORTS,
204: COM_NPORTS, 0, &sc->sc_slaveioh[i]))
205: panic("hsqattach: couldn't map slave %d", i);
206:
207:
208: printf("\n");
209:
210: for (i = 0; i < NSLAVES; i++) {
211: ca.ca_slave = i;
212: ca.ca_iot = sc->sc_iot;
213: ca.ca_ioh = sc->sc_slaveioh[i];
214: ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
215: ca.ca_noien = 1;
216:
217: sc->sc_slaves[i] = config_found(self, &ca, hsqprint);
218: }
219:
220: /* allow interrupts from all four UARTs */
221: bus_space_write_1(sc->sc_iot, sc->sc_slaveioh[0], com_uer, UART_MASK);
222:
223: sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
224: IPL_TTY, hsqintr, sc, sc->sc_dev.dv_xname);
225: }
226:
227: int
228: hsqintr(arg)
229: void *arg;
230: {
231: struct hsq_softc *sc = arg;
232: bus_space_tag_t iot = sc->sc_iot;
233: int bits;
234:
235: bits = bus_space_read_1(iot, sc->sc_slaveioh[0], com_uir) & UART_MASK;
236: if ( !bits )
237: return (0); /* no interrupts pending */
238:
239: for (;;) {
240: #define TRY(n) \
241: if ( sc->sc_slaves[n] && bits & (1 << (n)) ) \
242: comintr(sc->sc_slaves[n]);
243:
244: TRY(0);
245: TRY(1);
246: TRY(2);
247: TRY(3);
248: #undef TRY
249:
250: bits = bus_space_read_1(iot, sc->sc_slaveioh[0],
251: com_uir) & UART_MASK;
252: if ( !bits )
253: return (1); /* no interrupts pending */
254: }
255: }
CVSweb