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