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