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

Annotation of sys/arch/sparc64/dev/z8530sc.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: z8530sc.c,v 1.3 2003/06/02 23:27:55 millert Exp $     */
        !             2: /*     $NetBSD: z8530sc.c,v 1.15 2001/07/07 15:53:22 thorpej 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 <sparc64/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: RX, 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: static void zsnull_rxint(struct zs_chanstate *);
        !           311: static void zsnull_stint(struct zs_chanstate *, int);
        !           312: static void zsnull_txint(struct zs_chanstate *);
        !           313: static void zsnull_softint(struct zs_chanstate *);
        !           314:
        !           315: static void
        !           316: zsnull_rxint(cs)
        !           317:        struct zs_chanstate *cs;
        !           318: {
        !           319:        /* Ask for softint() call. */
        !           320:        cs->cs_softreq = 1;
        !           321: }
        !           322:
        !           323: static 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: static void
        !           333: zsnull_txint(cs)
        !           334:        struct zs_chanstate *cs;
        !           335: {
        !           336:        /* Ask for softint() call. */
        !           337:        cs->cs_softreq = 1;
        !           338: }
        !           339:
        !           340: static 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