Annotation of sys/dev/isa/hsq.c, Revision 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