Home | History | Annotate | Line # | Download | only in dev
zs.c revision 1.10
      1 /*	$NetBSD: zs.c,v 1.10 1996/12/09 17:42:19 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Gordon W. Ross.
      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 copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
     30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Zilog Z8530 Dual UART driver (machine-dependent part)
     41  *
     42  * Runs two serial lines per chip using slave drivers.
     43  * Plain tty/async lines use the zs_async slave.
     44  *
     45  * Modified for NetBSD/mvme68k by Jason R. Thorpe <thorpej (at) NetBSD.ORG>
     46  */
     47 
     48 #include <sys/param.h>
     49 #include <sys/systm.h>
     50 #include <sys/proc.h>
     51 #include <sys/device.h>
     52 #include <sys/conf.h>
     53 #include <sys/file.h>
     54 #include <sys/ioctl.h>
     55 #include <sys/tty.h>
     56 #include <sys/time.h>
     57 #include <sys/kernel.h>
     58 #include <sys/syslog.h>
     59 
     60 #include <dev/cons.h>
     61 #include <dev/ic/z8530reg.h>
     62 #include <machine/z8530var.h>
     63 
     64 #include <machine/cpu.h>
     65 
     66 #include <mvme68k/dev/zsvar.h>
     67 
     68 static u_long zs_sir;	/* software interrupt cookie */
     69 
     70 /* Flags from zscnprobe() */
     71 static int zs_hwflags[NZS][2];
     72 
     73 /* Default speed for each channel */
     74 static int zs_defspeed[NZS][2] = {
     75 	{ 9600, 	/* port 1 */
     76 	  9600 },	/* port 2 */
     77 	{ 9600, 	/* port 3 */
     78 	  9600 },	/* port 4 */
     79 };
     80 
     81 static struct zs_chanstate zs_conschan_store;
     82 static struct zs_chanstate *zs_conschan;
     83 
     84 u_char zs_init_reg[16] = {
     85 	0,	/* 0: CMD (reset, etc.) */
     86 	ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE,
     87 	0x18 + ZSHARD_PRI,	/* IVECT */
     88 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
     89 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
     90 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
     91 	0,	/* 6: TXSYNC/SYNCLO */
     92 	0,	/* 7: RXSYNC/SYNCHI */
     93 	0,	/* 8: alias for data port */
     94 	ZSWR9_MASTER_IE,
     95 	0,	/*10: Misc. TX/RX control bits */
     96 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
     97 	14,	/*12: BAUDLO (default=9600) */
     98 	0,	/*13: BAUDHI (default=9600) */
     99 	ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
    100 	ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
    101 };
    102 
    103 
    104 /****************************************************************
    105  * Autoconfig
    106  ****************************************************************/
    107 
    108 /* Definition of the driver for autoconfig. */
    109 static int	zsc_print __P((void *, const char *name));
    110 
    111 struct cfdriver zsc_cd = {
    112 	NULL, "zsc", DV_DULL
    113 };
    114 
    115 
    116 /*
    117  * Configure children of an SCC.
    118  */
    119 void
    120 zs_config(zsc, chan_addr)
    121 	struct zsc_softc *zsc;
    122 	struct zschan *(*chan_addr) __P((int, int));
    123 {
    124 	struct zsc_attach_args zsc_args;
    125 	volatile struct zschan *zc;
    126 	struct zs_chanstate *cs;
    127 	int zsc_unit, channel, s;
    128 	u_char reset;
    129 
    130 	zsc_unit = zsc->zsc_dev.dv_unit;
    131 	printf(": Zilog 8530 SCC\n");
    132 
    133 	/*
    134 	 * Initialize software state for each channel.
    135 	 */
    136 	for (channel = 0; channel < 2; channel++) {
    137 		cs = &zsc->zsc_cs[channel];
    138 
    139 		/*
    140 		 * If we're the console, copy the channel state, and
    141 		 * adjust the console channel pointer.
    142 		 */
    143 		if (zs_hwflags[zsc_unit][channel] & ZS_HWFLAG_CONSOLE) {
    144 			bcopy(zs_conschan, cs, sizeof(struct zs_chanstate));
    145 			zs_conschan = cs;
    146 		} else {
    147 			zc = (*chan_addr)(zsc_unit, channel);
    148 			cs->cs_reg_csr  = &zc->zc_csr;
    149 			cs->cs_reg_data = &zc->zc_data;
    150 
    151 			/* Define BAUD rate clock for the MI code. */
    152 			cs->cs_brg_clk = PCLK / 16;
    153 
    154 			cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
    155 
    156 			bcopy(zs_init_reg, cs->cs_creg, 16);
    157 			bcopy(zs_init_reg, cs->cs_preg, 16);
    158 		}
    159 
    160 		cs->cs_channel = channel;
    161 		cs->cs_private = NULL;
    162 		cs->cs_ops = &zsops_null;
    163 
    164 		/*
    165 		 * Clear the master interrupt enable.
    166 		 * The INTENA is common to both channels,
    167 		 * so just do it on the A channel.
    168 		 */
    169 		if (channel == 0) {
    170 			zs_write_reg(cs, 9, 0);
    171 		}
    172 
    173 		/*
    174 		 * Look for a child driver for this channel.
    175 		 * The child attach will setup the hardware.
    176 		 */
    177 		zsc_args.channel = channel;
    178 		zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
    179 		if (config_found(&zsc->zsc_dev, (void *)&zsc_args,
    180 		    zsc_print) == NULL) {
    181 			/* No sub-driver.  Just reset it. */
    182 			reset = (channel == 0) ?
    183 				ZSWR9_A_RESET : ZSWR9_B_RESET;
    184 			s = splzs();
    185 			zs_write_reg(cs,  9, reset);
    186 			splx(s);
    187 		}
    188 	}
    189 
    190 	/*
    191 	 * Allocate a software interrupt cookie.  Note that the argument
    192 	 * "zsc" is never actually used in the software interrupt
    193 	 * handler.
    194 	 */
    195 	if (zs_sir == 0)
    196 		zs_sir = allocate_sir(zssoft, zsc);
    197 }
    198 
    199 static int
    200 zsc_print(aux, name)
    201 	void *aux;
    202 	const char *name;
    203 {
    204 	struct zsc_attach_args *args = aux;
    205 
    206 	if (name != NULL)
    207 		printf("%s: ", name);
    208 
    209 	if (args->channel != -1)
    210 		printf(" channel %d", args->channel);
    211 
    212 	return UNCONF;
    213 }
    214 
    215 int
    216 zshard(arg)
    217 	void *arg;
    218 {
    219 	struct zsc_softc *zsc;
    220 	int unit, rval;
    221 
    222 	rval = 0;
    223 	for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
    224 		zsc = zsc_cd.cd_devs[unit];
    225 		if (zsc != NULL) {
    226 			rval |= zsc_intr_hard(zsc);
    227 		}
    228 	}
    229 	return (rval);
    230 }
    231 
    232 int zssoftpending;
    233 
    234 void
    235 zsc_req_softint(zsc)
    236 	struct zsc_softc *zsc;
    237 {
    238 	if (zssoftpending == 0) {
    239 		/* We are at splzs here, so no need to lock. */
    240 		zssoftpending = 1;
    241 		setsoftint(zs_sir);
    242 	}
    243 }
    244 
    245 int
    246 zssoft(arg)
    247 	void *arg;
    248 {
    249 	struct zsc_softc *zsc;
    250 	int unit;
    251 
    252 	/* This is not the only ISR on this IPL. */
    253 	if (zssoftpending == 0)
    254 		return (0);
    255 
    256 	/*
    257 	 * The soft intr. bit will be set by zshard only if
    258 	 * the variable zssoftpending is zero.
    259 	 */
    260 	zssoftpending = 0;
    261 
    262 	for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
    263 		zsc = zsc_cd.cd_devs[unit];
    264 		if (zsc != NULL) {
    265 			(void) zsc_intr_soft(zsc);
    266 		}
    267 	}
    268 	return (1);
    269 }
    270 
    271 
    272 /*
    273  * Read or write the chip with suitable delays.
    274  */
    275 
    276 u_char
    277 zs_read_reg(cs, reg)
    278 	struct zs_chanstate *cs;
    279 	u_char reg;
    280 {
    281 	u_char val;
    282 
    283 	*cs->cs_reg_csr = reg;
    284 	ZS_DELAY();
    285 	val = *cs->cs_reg_csr;
    286 	ZS_DELAY();
    287 	return val;
    288 }
    289 
    290 void
    291 zs_write_reg(cs, reg, val)
    292 	struct zs_chanstate *cs;
    293 	u_char reg, val;
    294 {
    295 	*cs->cs_reg_csr = reg;
    296 	ZS_DELAY();
    297 	*cs->cs_reg_csr = val;
    298 	ZS_DELAY();
    299 }
    300 
    301 u_char zs_read_csr(cs)
    302 	struct zs_chanstate *cs;
    303 {
    304 	register u_char v;
    305 
    306 	v = *cs->cs_reg_csr;
    307 	ZS_DELAY();
    308 	return v;
    309 }
    310 
    311 u_char zs_read_data(cs)
    312 	struct zs_chanstate *cs;
    313 {
    314 	register u_char v;
    315 
    316 	v = *cs->cs_reg_data;
    317 	ZS_DELAY();
    318 	return v;
    319 }
    320 
    321 void  zs_write_csr(cs, val)
    322 	struct zs_chanstate *cs;
    323 	u_char val;
    324 {
    325 	*cs->cs_reg_csr = val;
    326 	ZS_DELAY();
    327 }
    328 
    329 void  zs_write_data(cs, val)
    330 	struct zs_chanstate *cs;
    331 	u_char val;
    332 {
    333 	*cs->cs_reg_data = val;
    334 	ZS_DELAY();
    335 }
    336 
    337 /****************************************************************
    338  * Console support functions (MVME specific!)
    339  ****************************************************************/
    340 
    341 /*
    342  * Polled input char.
    343  */
    344 int
    345 zs_getc(arg)
    346 	void *arg;
    347 {
    348 	register struct zs_chanstate *cs = arg;
    349 	register int s, c, rr0, stat;
    350 
    351 	s = splhigh();
    352  top:
    353 	/* Wait for a character to arrive. */
    354 	do {
    355 		rr0 = *cs->cs_reg_csr;
    356 		ZS_DELAY();
    357 	} while ((rr0 & ZSRR0_RX_READY) == 0);
    358 
    359 	/* Read error register. */
    360 	stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE);
    361 	if (stat) {
    362 		zs_write_csr(cs, ZSM_RESET_ERR);
    363 		goto top;
    364 	}
    365 
    366 	/* Read character. */
    367 	c = *cs->cs_reg_data;
    368 	ZS_DELAY();
    369 	splx(s);
    370 
    371 	return (c);
    372 }
    373 
    374 /*
    375  * Polled output char.
    376  */
    377 void
    378 zs_putc(arg, c)
    379 	void *arg;
    380 	int c;
    381 {
    382 	register struct zs_chanstate *cs = arg;
    383 	register int s, rr0;
    384 
    385 	s = splhigh();
    386 	/* Wait for transmitter to become ready. */
    387 	do {
    388 		rr0 = *cs->cs_reg_csr;
    389 		ZS_DELAY();
    390 	} while ((rr0 & ZSRR0_TX_READY) == 0);
    391 
    392 	*cs->cs_reg_data = c;
    393 	ZS_DELAY();
    394 	splx(s);
    395 }
    396 
    397 /*
    398  * Common parts of console init.
    399  */
    400 void
    401 zs_cnconfig(zsc_unit, channel, zcp)
    402 	int zsc_unit, channel;
    403 	struct zschan *zcp;
    404 {
    405 	volatile struct zschan *zc = (volatile struct zschan *)zcp;
    406 	struct zs_chanstate *cs;
    407 
    408 	/*
    409 	 * Pointer to channel state.  Later, the console channel
    410 	 * state is copied into the softc, and the console channel
    411 	 * pointer adjusted to point to the new copy.
    412 	 */
    413 	zs_conschan = cs = &zs_conschan_store;
    414 
    415 	zs_hwflags[zsc_unit][channel] = ZS_HWFLAG_CONSOLE;
    416 
    417 	cs->cs_reg_csr  = &zc->zc_csr;
    418 	cs->cs_reg_data = &zc->zc_data;
    419 
    420 	cs->cs_channel = channel;
    421 	cs->cs_private = NULL;
    422 	cs->cs_ops = &zsops_null;
    423 
    424 	/* Define BAUD rate clock for the MI code. */
    425 	cs->cs_brg_clk = PCLK / 16;
    426 
    427 	cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
    428 
    429 	bcopy(zs_init_reg, cs->cs_creg, 16);
    430 	bcopy(zs_init_reg, cs->cs_preg, 16);
    431 
    432 	/*
    433 	 * Clear the master interrupt enable.
    434 	 * The INTENA is common to both channels,
    435 	 * so just do it on the A channel.
    436 	 */
    437 	if (channel == 0) {
    438 		zs_write_reg(cs, 9, 0);
    439 	}
    440 
    441 	/* Reset the SCC chip. */
    442 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    443 
    444 	/* Initialize a few important registers. */
    445 	zs_write_reg(cs, 10, cs->cs_creg[10]);
    446 	zs_write_reg(cs, 11, cs->cs_creg[11]);
    447 	zs_write_reg(cs, 14, cs->cs_creg[14]);
    448 
    449 	/* Assert DTR and RTS. */
    450 	cs->cs_creg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
    451 	cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
    452 	zs_write_reg(cs, 5, cs->cs_creg[5]);
    453 }
    454 
    455 /*
    456  * Polled console input putchar.
    457  */
    458 int
    459 zscngetc(dev)
    460 	dev_t dev;
    461 {
    462 	register volatile struct zs_chanstate *cs = zs_conschan;
    463 	register int c;
    464 
    465 	c = zs_getc(cs);
    466 	return (c);
    467 }
    468 
    469 /*
    470  * Polled console output putchar.
    471  */
    472 void
    473 zscnputc(dev, c)
    474 	dev_t dev;
    475 	int c;
    476 {
    477 	register volatile struct zs_chanstate *cs = zs_conschan;
    478 
    479 	zs_putc(cs, c);
    480 }
    481 
    482 /*
    483  * Handle user request to enter kernel debugger.
    484  */
    485 void
    486 zs_abort()
    487 {
    488 	register volatile struct zs_chanstate *cs = zs_conschan;
    489 	int rr0;
    490 
    491 	/* Wait for end of break to avoid PROM abort. */
    492 	/* XXX - Limit the wait? */
    493 	do {
    494 		rr0 = *cs->cs_reg_csr;
    495 		ZS_DELAY();
    496 	} while (rr0 & ZSRR0_BREAK);
    497 
    498 	mvme68k_abort("SERIAL LINE ABORT");
    499 }
    500