[BACK]Return to hsq.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

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