[BACK]Return to z8530sc.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / dev

Annotation of sys/arch/sparc/dev/z8530sc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: z8530sc.c,v 1.2 2003/06/02 23:27:54 millert Exp $ */
                      2: /*     $NetBSD: z8530sc.c,v 1.4 1996/05/17 19:30:34 gwr Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (c) 1994 Gordon W. Ross
                      6:  * Copyright (c) 1992, 1993
                      7:  *     The Regents of the University of California.  All rights reserved.
                      8:  *
                      9:  * This software was developed by the Computer Systems Engineering group
                     10:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     11:  * contributed to Berkeley.
                     12:  *
                     13:  * All advertising materials mentioning features or use of this software
                     14:  * must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Lawrence Berkeley Laboratory.
                     17:  *
                     18:  * Redistribution and use in source and binary forms, with or without
                     19:  * modification, are permitted provided that the following conditions
                     20:  * are met:
                     21:  * 1. Redistributions of source code must retain the above copyright
                     22:  *    notice, this list of conditions and the following disclaimer.
                     23:  * 2. Redistributions in binary form must reproduce the above copyright
                     24:  *    notice, this list of conditions and the following disclaimer in the
                     25:  *    documentation and/or other materials provided with the distribution.
                     26:  * 3. Neither the name of the University nor the names of its contributors
                     27:  *    may be used to endorse or promote products derived from this software
                     28:  *    without specific prior written permission.
                     29:  *
                     30:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     31:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     32:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     33:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     34:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     35:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     36:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     37:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     38:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     39:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     40:  * SUCH DAMAGE.
                     41:  *
                     42:  *     @(#)zs.c        8.1 (Berkeley) 7/19/93
                     43:  */
                     44:
                     45: /*
                     46:  * Zilog Z8530 Dual UART driver (common part)
                     47:  *
                     48:  * This file contains the machine-independent parts of the
                     49:  * driver common to tty and keyboard/mouse sub-drivers.
                     50:  */
                     51:
                     52: #include <sys/param.h>
                     53: #include <sys/systm.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/device.h>
                     56: #include <sys/conf.h>
                     57: #include <sys/file.h>
                     58: #include <sys/ioctl.h>
                     59: #include <sys/tty.h>
                     60: #include <sys/time.h>
                     61: #include <sys/kernel.h>
                     62: #include <sys/syslog.h>
                     63:
                     64: #include <sparc/dev/z8530reg.h>
                     65: #include <machine/z8530var.h>
                     66:
                     67: void
                     68: zs_break(cs, set)
                     69:        struct zs_chanstate *cs;
                     70:        int set;
                     71: {
                     72:
                     73:        if (set) {
                     74:                cs->cs_preg[5] |= ZSWR5_BREAK;
                     75:                cs->cs_creg[5] |= ZSWR5_BREAK;
                     76:        } else {
                     77:                cs->cs_preg[5] &= ~ZSWR5_BREAK;
                     78:                cs->cs_creg[5] &= ~ZSWR5_BREAK;
                     79:        }
                     80:        zs_write_reg(cs, 5, cs->cs_creg[5]);
                     81: }
                     82:
                     83:
                     84: /*
                     85:  * drain on-chip fifo
                     86:  */
                     87: void
                     88: zs_iflush(cs)
                     89:        struct zs_chanstate *cs;
                     90: {
                     91:        u_char c, rr0, rr1;
                     92:        int i;
                     93:
                     94:        /*
                     95:         * Count how many times we loop. Some systems, such as some
                     96:         * Apple PowerBooks, claim to have SCC's which they really don't.
                     97:         */
                     98:        for (i = 0; i < 32; i++) {
                     99:                /* Is there input available? */
                    100:                rr0 = zs_read_csr(cs);
                    101:                if ((rr0 & ZSRR0_RX_READY) == 0)
                    102:                        break;
                    103:
                    104:                /*
                    105:                 * First read the status, because reading the data
                    106:                 * destroys the status of this char.
                    107:                 */
                    108:                rr1 = zs_read_reg(cs, 1);
                    109:                c = zs_read_data(cs);
                    110:
                    111:                if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
                    112:                        /* Clear the receive error. */
                    113:                        zs_write_csr(cs, ZSWR0_RESET_ERRORS);
                    114:                }
                    115:        }
                    116: }
                    117:
                    118:
                    119: /*
                    120:  * Write the given register set to the given zs channel in the proper order.
                    121:  * The channel must not be transmitting at the time.  The receiver will
                    122:  * be disabled for the time it takes to write all the registers.
                    123:  * Call this with interrupts disabled.
                    124:  */
                    125: void
                    126: zs_loadchannelregs(cs)
                    127:        struct zs_chanstate *cs;
                    128: {
                    129:        u_char *reg;
                    130:
                    131:        zs_write_csr(cs, ZSM_RESET_ERR);        /* XXX: reset error condition */
                    132:
                    133: #if 1
                    134:        /*
                    135:         * XXX: Is this really a good idea?
                    136:         * XXX: Should go elsewhere! -gwr
                    137:         */
                    138:        zs_iflush(cs);  /* XXX */
                    139: #endif
                    140:
                    141:        if (memcmp((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16) == 0)
                    142:                return;         /* only change if values are different */
                    143:
                    144:        /* Copy "pending" regs to "current" */
                    145:        memcpy((caddr_t)cs->cs_creg, (caddr_t)cs->cs_preg, 16);
                    146:        reg = cs->cs_creg;      /* current regs */
                    147:
                    148:        /* disable interrupts */
                    149:        zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
                    150:
                    151:        /* baud clock divisor, stop bits, parity */
                    152:        zs_write_reg(cs, 4, reg[4]);
                    153:
                    154:        /* misc. TX/RX control bits */
                    155:        zs_write_reg(cs, 10, reg[10]);
                    156:
                    157:        /* char size, enable (RX/TX) */
                    158:        zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
                    159:        zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
                    160:
                    161:        /* synchronous mode stuff */
                    162:        zs_write_reg(cs, 6, reg[6]);
                    163:        zs_write_reg(cs, 7, reg[7]);
                    164:
                    165: #if 0
                    166:        /*
                    167:         * Registers 2 and 9 are special because they are
                    168:         * actually common to both channels, but must be
                    169:         * programmed through channel A.  The "zsc" attach
                    170:         * function takes care of setting these registers
                    171:         * and they should not be touched thereafter.
                    172:         */
                    173:        /* interrupt vector */
                    174:        zs_write_reg(cs, 2, reg[2]);
                    175:        /* master interrupt control */
                    176:        zs_write_reg(cs, 9, reg[9]);
                    177: #endif
                    178:
                    179:        /* Shut down the BRG */
                    180:        zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
                    181:
                    182: #ifdef ZS_MD_SETCLK
                    183:        /* Let the MD code setup any external clock. */
                    184:        ZS_MD_SETCLK(cs);
                    185: #endif /* ZS_MD_SETCLK */
                    186:
                    187:        /* clock mode control */
                    188:        zs_write_reg(cs, 11, reg[11]);
                    189:
                    190:        /* baud rate (lo/hi) */
                    191:        zs_write_reg(cs, 12, reg[12]);
                    192:        zs_write_reg(cs, 13, reg[13]);
                    193:
                    194:        /* Misc. control bits */
                    195:        zs_write_reg(cs, 14, reg[14]);
                    196:
                    197:        /* which lines cause status interrupts */
                    198:        zs_write_reg(cs, 15, reg[15]);
                    199:
                    200:        /*
                    201:         * Zilog docs recommend resetting external status twice at this
                    202:         * point. Mainly as the status bits are latched, and the first
                    203:         * interrupt clear might unlatch them to new values, generating
                    204:         * a second interrupt request.
                    205:         */
                    206:        zs_write_csr(cs, ZSM_RESET_STINT);
                    207:        zs_write_csr(cs, ZSM_RESET_STINT);
                    208:
                    209:        /* char size, enable (RX/TX)*/
                    210:        zs_write_reg(cs, 3, reg[3]);
                    211:        zs_write_reg(cs, 5, reg[5]);
                    212:
                    213:        /* interrupt enables: TX, TX, STATUS */
                    214:        zs_write_reg(cs, 1, reg[1]);
                    215: }
                    216:
                    217:
                    218: /*
                    219:  * ZS hardware interrupt.  Scan all ZS channels.  NB: we know here that
                    220:  * channels are kept in (A,B) pairs.
                    221:  *
                    222:  * Do just a little, then get out; set a software interrupt if more
                    223:  * work is needed.
                    224:  *
                    225:  * We deliberately ignore the vectoring Zilog gives us, and match up
                    226:  * only the number of `reset interrupt under service' operations, not
                    227:  * the order.
                    228:  */
                    229: int
                    230: zsc_intr_hard(arg)
                    231:        void *arg;
                    232: {
                    233:        struct zsc_softc *zsc = arg;
                    234:        struct zs_chanstate *cs;
                    235:        u_char rr3;
                    236:
                    237:        /* First look at channel A. */
                    238:        cs = &zsc->zsc_cs[0];
                    239:        /* Note: only channel A has an RR3 */
                    240:        rr3 = zs_read_reg(cs, 3);
                    241:
                    242:        /*
                    243:         * Clear interrupt first to avoid a race condition.
                    244:         * If a new interrupt condition happens while we are
                    245:         * servicing this one, we will get another interrupt
                    246:         * shortly.  We can NOT just sit here in a loop, or
                    247:         * we will cause horrible latency for other devices
                    248:         * on this interrupt level (i.e. sun3x floppy disk).
                    249:         */
                    250:        if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
                    251:                zs_write_csr(cs, ZSWR0_CLR_INTR);
                    252:                if (rr3 & ZSRR3_IP_A_RX)
                    253:                        (*cs->cs_ops->zsop_rxint)(cs);
                    254:                if (rr3 & ZSRR3_IP_A_STAT)
                    255:                        (*cs->cs_ops->zsop_stint)(cs, 0);
                    256:                if (rr3 & ZSRR3_IP_A_TX)
                    257:                        (*cs->cs_ops->zsop_txint)(cs);
                    258:        }
                    259:
                    260:        /* Now look at channel B. */
                    261:        cs = &zsc->zsc_cs[1];
                    262:        if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
                    263:                zs_write_csr(cs, ZSWR0_CLR_INTR);
                    264:                if (rr3 & ZSRR3_IP_B_RX)
                    265:                        (*cs->cs_ops->zsop_rxint)(cs);
                    266:                if (rr3 & ZSRR3_IP_B_STAT)
                    267:                        (*cs->cs_ops->zsop_stint)(cs, 0);
                    268:                if (rr3 & ZSRR3_IP_B_TX)
                    269:                        (*cs->cs_ops->zsop_txint)(cs);
                    270:        }
                    271:
                    272:        /* Note: caller will check cs_x->cs_softreq and DTRT. */
                    273:        return (rr3);
                    274: }
                    275:
                    276:
                    277: /*
                    278:  * ZS software interrupt.  Scan all channels for deferred interrupts.
                    279:  */
                    280: int
                    281: zsc_intr_soft(arg)
                    282:        void *arg;
                    283: {
                    284:        struct zsc_softc *zsc = arg;
                    285:        struct zs_chanstate *cs;
                    286:        int rval, chan;
                    287:
                    288:        rval = 0;
                    289:        for (chan = 0; chan < 2; chan++) {
                    290:                cs = &zsc->zsc_cs[chan];
                    291:
                    292:                /*
                    293:                 * The softint flag can be safely cleared once
                    294:                 * we have decided to call the softint routine.
                    295:                 * (No need to do splzs() first.)
                    296:                 */
                    297:                if (cs->cs_softreq) {
                    298:                        cs->cs_softreq = 0;
                    299:                        (*cs->cs_ops->zsop_softint)(cs);
                    300:                        rval++;
                    301:                }
                    302:        }
                    303:        return (rval);
                    304: }
                    305:
                    306: /*
                    307:  * Provide a null zs "ops" vector.
                    308:  */
                    309:
                    310: void zsnull_rxint(struct zs_chanstate *);
                    311: void zsnull_stint(struct zs_chanstate *, int);
                    312: void zsnull_txint(struct zs_chanstate *);
                    313: void zsnull_softint(struct zs_chanstate *);
                    314:
                    315: void
                    316: zsnull_rxint(cs)
                    317:        struct zs_chanstate *cs;
                    318: {
                    319:        /* Ask for softint() call. */
                    320:        cs->cs_softreq = 1;
                    321: }
                    322:
                    323: void
                    324: zsnull_stint(cs, force)
                    325:        struct zs_chanstate *cs;
                    326:        int force;
                    327: {
                    328:        /* Ask for softint() call. */
                    329:        cs->cs_softreq = 1;
                    330: }
                    331:
                    332: void
                    333: zsnull_txint(cs)
                    334:        struct zs_chanstate *cs;
                    335: {
                    336:        /* Ask for softint() call. */
                    337:        cs->cs_softreq = 1;
                    338: }
                    339:
                    340: void
                    341: zsnull_softint(cs)
                    342:        struct zs_chanstate *cs;
                    343: {
                    344:        zs_write_reg(cs,  1, 0);
                    345:        zs_write_reg(cs, 15, 0);
                    346: }
                    347:
                    348: struct zsops zsops_null = {
                    349:        zsnull_rxint,   /* receive char available */
                    350:        zsnull_stint,   /* external/status */
                    351:        zsnull_txint,   /* xmit buffer empty */
                    352:        zsnull_softint, /* process software interrupt */
                    353: };

CVSweb