Home | History | Annotate | Line # | Download | only in dev
zs.c revision 1.19
      1  1.19  tsutsui /*	$NetBSD: zs.c,v 1.19 2004/09/04 11:28:32 tsutsui Exp $	*/
      2   1.1  tsutsui 
      3   1.1  tsutsui /*-
      4   1.1  tsutsui  * Copyright (c) 1996 The NetBSD Foundation, Inc.
      5   1.1  tsutsui  * All rights reserved.
      6   1.1  tsutsui  *
      7   1.1  tsutsui  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1  tsutsui  * by Gordon W. Ross.
      9   1.1  tsutsui  *
     10   1.1  tsutsui  * Redistribution and use in source and binary forms, with or without
     11   1.1  tsutsui  * modification, are permitted provided that the following conditions
     12   1.1  tsutsui  * are met:
     13   1.1  tsutsui  * 1. Redistributions of source code must retain the above copyright
     14   1.1  tsutsui  *    notice, this list of conditions and the following disclaimer.
     15   1.1  tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  tsutsui  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  tsutsui  *    documentation and/or other materials provided with the distribution.
     18   1.1  tsutsui  * 3. All advertising materials mentioning features or use of this software
     19   1.1  tsutsui  *    must display the following acknowledgement:
     20   1.1  tsutsui  *        This product includes software developed by the NetBSD
     21   1.1  tsutsui  *        Foundation, Inc. and its contributors.
     22   1.1  tsutsui  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1  tsutsui  *    contributors may be used to endorse or promote products derived
     24   1.1  tsutsui  *    from this software without specific prior written permission.
     25   1.1  tsutsui  *
     26   1.1  tsutsui  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1  tsutsui  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1  tsutsui  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1  tsutsui  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1  tsutsui  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1  tsutsui  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1  tsutsui  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1  tsutsui  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1  tsutsui  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1  tsutsui  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1  tsutsui  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1  tsutsui  */
     38   1.1  tsutsui 
     39   1.1  tsutsui /*
     40   1.1  tsutsui  * Zilog Z8530 Dual UART driver (machine-dependent part)
     41   1.1  tsutsui  *
     42   1.1  tsutsui  * Runs two serial lines per chip using slave drivers.
     43   1.1  tsutsui  * Plain tty/async lines use the zs_async slave.
     44   1.1  tsutsui  */
     45   1.1  tsutsui 
     46   1.1  tsutsui /*
     47   1.1  tsutsui  * news68k/dev/zs.c - based on {newsmips,x68k,mvme68k}/dev/zs.c
     48   1.1  tsutsui  */
     49  1.18    lukem 
     50  1.18    lukem #include <sys/cdefs.h>
     51  1.19  tsutsui __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.19 2004/09/04 11:28:32 tsutsui Exp $");
     52   1.1  tsutsui 
     53   1.1  tsutsui #include "opt_ddb.h"
     54   1.1  tsutsui 
     55   1.1  tsutsui #include <sys/param.h>
     56   1.1  tsutsui #include <sys/systm.h>
     57   1.1  tsutsui #include <sys/conf.h>
     58   1.1  tsutsui #include <sys/device.h>
     59   1.1  tsutsui #include <sys/tty.h>
     60   1.1  tsutsui 
     61   1.1  tsutsui #include <machine/cpu.h>
     62   1.1  tsutsui #include <machine/z8530var.h>
     63   1.1  tsutsui 
     64   1.1  tsutsui #include <dev/cons.h>
     65   1.1  tsutsui #include <dev/ic/z8530reg.h>
     66   1.1  tsutsui 
     67   1.1  tsutsui #include <news68k/dev/hbvar.h>
     68   1.1  tsutsui 
     69  1.19  tsutsui #include "ioconf.h"
     70  1.19  tsutsui 
     71  1.10  tsutsui int  zs_getc(void *);
     72  1.10  tsutsui void zs_putc(void *, int);
     73   1.1  tsutsui 
     74   1.1  tsutsui /*
     75   1.1  tsutsui  * Some warts needed by z8530tty.c -
     76   1.1  tsutsui  * The default parity REALLY needs to be the same as the PROM uses,
     77   1.1  tsutsui  * or you can not see messages done with printf during boot-up...
     78   1.1  tsutsui  */
     79   1.1  tsutsui int zs_def_cflag = (CREAD | CS8 | HUPCL);
     80   1.1  tsutsui 
     81   1.1  tsutsui /*
     82   1.3  tsutsui  * The news68k machines use three different clocks for the ZS chips.
     83   1.1  tsutsui  */
     84   1.3  tsutsui #define NPCLK	3
     85   1.3  tsutsui #define PCLK0	(9600 * 416)	/*  news1700: 3.9936MHz */
     86   1.3  tsutsui #define PCLK1	(9600 * 512)	/*  news1200: 4.9152MHz */
     87   1.3  tsutsui #define PCLK2	(9600 * 384)	/*  external: 3.6864MHz */
     88   1.3  tsutsui 
     89   1.3  tsutsui static const u_int pclk[NPCLK] = {
     90   1.3  tsutsui 	PCLK0,
     91   1.3  tsutsui 	PCLK1,
     92   1.3  tsutsui 	PCLK2,
     93   1.3  tsutsui };
     94   1.1  tsutsui 
     95   1.1  tsutsui /*
     96   1.1  tsutsui  * Define interrupt levels.
     97   1.1  tsutsui  */
     98   1.1  tsutsui #define ZSHARD_PRI 5
     99   1.1  tsutsui #define ZS_IVECT 64
    100   1.1  tsutsui 
    101   1.1  tsutsui #define ZS_DELAY() /* delay(2) */
    102   1.1  tsutsui 
    103   1.1  tsutsui /* The layout of this is hardware-dependent (padding, order). */
    104   1.1  tsutsui struct zschan {
    105   1.1  tsutsui 	volatile u_char	zc_csr;		/* ctrl,status, and indirect access */
    106   1.1  tsutsui 	volatile u_char	zc_data;	/* data */
    107   1.1  tsutsui };
    108   1.1  tsutsui struct zsdevice {
    109   1.1  tsutsui 	/* Yes, they are backwards. */
    110   1.1  tsutsui 	struct	zschan zs_chan_b;
    111   1.1  tsutsui 	struct	zschan zs_chan_a;
    112   1.1  tsutsui };
    113   1.1  tsutsui 
    114   1.2  tsutsui static u_char zs_sir;
    115   1.1  tsutsui 
    116   1.1  tsutsui /* Default speed for all channels */
    117   1.1  tsutsui static int zs_defspeed = 9600;
    118   1.1  tsutsui 
    119   1.5  tsutsui /* console status from cninit */
    120   1.5  tsutsui static struct zs_chanstate zs_conschan_store;
    121   1.5  tsutsui static struct zs_chanstate *zs_conschan;
    122   1.5  tsutsui static struct zschan *zc_cons;
    123   1.5  tsutsui 
    124   1.1  tsutsui static u_char zs_init_reg[16] = {
    125   1.1  tsutsui 	0,	/* 0: CMD (reset, etc.) */
    126   1.1  tsutsui 	0,	/* 1: No interrupts yet. */
    127   1.1  tsutsui 	ZS_IVECT,	/* IVECT */
    128   1.1  tsutsui 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
    129   1.1  tsutsui 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
    130   1.1  tsutsui 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
    131   1.1  tsutsui 	0,	/* 6: TXSYNC/SYNCLO */
    132   1.1  tsutsui 	0,	/* 7: RXSYNC/SYNCHI */
    133   1.1  tsutsui 	0,	/* 8: alias for data port */
    134   1.1  tsutsui 	ZSWR9_MASTER_IE,
    135   1.1  tsutsui 	0,	/*10: Misc. TX/RX control bits */
    136   1.1  tsutsui 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
    137   1.5  tsutsui 	BPS_TO_TCONST((PCLK0/16), 9600), /*12: BAUDLO (default=9600) */
    138   1.1  tsutsui 	0,			/*13: BAUDHI (default=9600) */
    139   1.1  tsutsui 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
    140   1.1  tsutsui 	ZSWR15_BREAK_IE,
    141   1.1  tsutsui };
    142   1.1  tsutsui 
    143   1.1  tsutsui 
    144   1.1  tsutsui /****************************************************************
    145   1.1  tsutsui  * Autoconfig
    146   1.1  tsutsui  ****************************************************************/
    147   1.1  tsutsui 
    148   1.1  tsutsui /* Definition of the driver for autoconfig. */
    149  1.10  tsutsui static int  zs_match(struct device *, struct cfdata *, void *);
    150  1.10  tsutsui static void zs_attach(struct device *, struct device *, void *);
    151  1.10  tsutsui static int  zs_print(void *, const char *name);
    152   1.1  tsutsui 
    153   1.9  thorpej CFATTACH_DECL(zsc, sizeof(struct zsc_softc),
    154   1.9  thorpej     zs_match, zs_attach, NULL, NULL);
    155   1.1  tsutsui 
    156  1.10  tsutsui static int zshard(void *);
    157  1.10  tsutsui void zssoft(void *);
    158   1.5  tsutsui #if 0
    159  1.10  tsutsui static int zs_get_speed(struct zs_chanstate *);
    160   1.5  tsutsui #endif
    161   1.1  tsutsui 
    162   1.1  tsutsui /*
    163   1.1  tsutsui  * Is the zs chip present?
    164   1.1  tsutsui  */
    165   1.1  tsutsui static int
    166   1.1  tsutsui zs_match(parent, cf, aux)
    167   1.1  tsutsui 	struct device *parent;
    168   1.1  tsutsui 	struct cfdata *cf;
    169   1.1  tsutsui 	void *aux;
    170   1.1  tsutsui {
    171   1.1  tsutsui 	struct hb_attach_args *ha = aux;
    172   1.3  tsutsui 	u_int addr;
    173   1.1  tsutsui 
    174   1.1  tsutsui 	if (strcmp(ha->ha_name, "zsc"))
    175   1.1  tsutsui 		return 0;
    176   1.1  tsutsui 
    177   1.1  tsutsui 	/* XXX no default address */
    178  1.12  tsutsui 	if (ha->ha_address == (u_int)-1)
    179   1.1  tsutsui 		return 0;
    180   1.1  tsutsui 
    181   1.1  tsutsui 	addr = IIOV(ha->ha_address);
    182   1.1  tsutsui 	/* This returns -1 on a fault (bus error). */
    183   1.1  tsutsui 	if (badaddr((void *)addr, 1))
    184   1.1  tsutsui 		return 0;
    185   1.1  tsutsui 
    186   1.1  tsutsui 	return 1;
    187   1.1  tsutsui }
    188   1.1  tsutsui 
    189   1.1  tsutsui /*
    190   1.1  tsutsui  * Attach a found zs.
    191   1.1  tsutsui  */
    192   1.1  tsutsui static void
    193   1.1  tsutsui zs_attach(parent, self, aux)
    194   1.1  tsutsui 	struct device *parent;
    195   1.1  tsutsui 	struct device *self;
    196   1.1  tsutsui 	void *aux;
    197   1.1  tsutsui {
    198   1.1  tsutsui 	struct zsc_softc *zsc = (void *) self;
    199   1.3  tsutsui 	struct cfdata *cf = self->dv_cfdata;
    200   1.1  tsutsui 	struct hb_attach_args *ha = aux;
    201   1.1  tsutsui 	struct zsc_attach_args zsc_args;
    202   1.5  tsutsui 	struct zsdevice *zs;
    203   1.5  tsutsui 	struct zschan *zc;
    204   1.1  tsutsui 	struct zs_chanstate *cs;
    205   1.5  tsutsui 	int s, channel, clk;
    206   1.1  tsutsui 
    207   1.5  tsutsui 	zs = (void *)IIOV(ha->ha_address);
    208   1.1  tsutsui 
    209   1.3  tsutsui 	clk = cf->cf_flags;
    210   1.3  tsutsui 	if (clk < 0 || clk >= NPCLK)
    211   1.3  tsutsui 		clk = 0;
    212   1.3  tsutsui 
    213   1.1  tsutsui 	printf("\n");
    214   1.1  tsutsui 
    215   1.1  tsutsui 	/*
    216   1.1  tsutsui 	 * Initialize software state for each channel.
    217   1.1  tsutsui 	 */
    218   1.1  tsutsui 	for (channel = 0; channel < 2; channel++) {
    219   1.1  tsutsui 		zsc_args.channel = channel;
    220   1.1  tsutsui 		cs = &zsc->zsc_cs_store[channel];
    221  1.13       pk 		simple_lock_init(&cs->cs_lock);
    222  1.13       pk 
    223   1.1  tsutsui 		zsc->zsc_cs[channel] = cs;
    224   1.5  tsutsui 		zc = (channel == 0) ? &zs->zs_chan_a : &zs->zs_chan_b;
    225   1.1  tsutsui 
    226   1.1  tsutsui 		if (ha->ha_vect != -1)
    227   1.1  tsutsui 			zs_init_reg[2] = ha->ha_vect;
    228   1.1  tsutsui 
    229   1.5  tsutsui 		if (zc == zc_cons) {
    230   1.6  tsutsui 			memcpy(cs, zs_conschan, sizeof(struct zs_chanstate));
    231   1.5  tsutsui 			zs_conschan = cs;
    232   1.5  tsutsui 			zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
    233   1.5  tsutsui 		} else {
    234   1.5  tsutsui 			cs->cs_reg_csr  = &zc->zc_csr;
    235   1.5  tsutsui 			cs->cs_reg_data = &zc->zc_data;
    236   1.6  tsutsui 			memcpy(cs->cs_creg, zs_init_reg, 16);
    237   1.6  tsutsui 			memcpy(cs->cs_preg, zs_init_reg, 16);
    238   1.1  tsutsui 			cs->cs_defspeed = zs_defspeed;
    239   1.5  tsutsui 			zsc_args.hwflags = 0;
    240   1.5  tsutsui 		}
    241   1.5  tsutsui 
    242   1.1  tsutsui 		cs->cs_defcflag = zs_def_cflag;
    243   1.1  tsutsui 
    244   1.5  tsutsui 		cs->cs_channel = channel;
    245   1.5  tsutsui 		cs->cs_private = NULL;
    246   1.5  tsutsui 		cs->cs_ops = &zsops_null;
    247   1.5  tsutsui 		cs->cs_brg_clk = pclk[clk] / 16;
    248   1.5  tsutsui 
    249   1.1  tsutsui 		/* Make these correspond to cs_defcflag (-crtscts) */
    250   1.1  tsutsui 		cs->cs_rr0_dcd = ZSRR0_DCD;
    251   1.1  tsutsui 		cs->cs_rr0_cts = 0;
    252   1.1  tsutsui 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    253   1.1  tsutsui 		cs->cs_wr5_rts = 0;
    254   1.1  tsutsui 
    255   1.1  tsutsui 		/*
    256   1.1  tsutsui 		 * Clear the master interrupt enable.
    257   1.1  tsutsui 		 * The INTENA is common to both channels,
    258   1.1  tsutsui 		 * so just do it on the A channel.
    259   1.1  tsutsui 		 */
    260   1.1  tsutsui 		if (channel == 0) {
    261   1.1  tsutsui 			s = splhigh();
    262   1.1  tsutsui 			zs_write_reg(cs, 9, 0);
    263   1.1  tsutsui 			splx(s);
    264   1.1  tsutsui 		}
    265   1.1  tsutsui 
    266   1.1  tsutsui 		/*
    267   1.1  tsutsui 		 * Look for a child driver for this channel.
    268   1.1  tsutsui 		 * The child attach will setup the hardware.
    269   1.1  tsutsui 		 */
    270   1.1  tsutsui 		if (!config_found(self, (void *)&zsc_args, zs_print)) {
    271   1.1  tsutsui 			/* No sub-driver.  Just reset it. */
    272   1.1  tsutsui 			u_char reset = (channel == 0) ?
    273   1.1  tsutsui 				ZSWR9_A_RESET : ZSWR9_B_RESET;
    274   1.1  tsutsui 			s = splhigh();
    275   1.1  tsutsui 			zs_write_reg(cs,  9, reset);
    276   1.1  tsutsui 			splx(s);
    277   1.1  tsutsui 		}
    278   1.1  tsutsui 	}
    279   1.1  tsutsui 
    280   1.1  tsutsui 	/*
    281   1.1  tsutsui 	 * Now safe to install interrupt handlers.
    282   1.1  tsutsui 	 */
    283   1.1  tsutsui 	hb_intr_establish(zs_init_reg[2], zshard, ZSHARD_PRI, zsc);
    284   1.1  tsutsui 
    285   1.1  tsutsui 	/*
    286   1.1  tsutsui 	 * Set the master interrupt enable and interrupt vector.
    287   1.1  tsutsui 	 * (common to both channels, do it on A)
    288   1.1  tsutsui 	 */
    289   1.1  tsutsui 	cs = zsc->zsc_cs[0];
    290   1.1  tsutsui 	s = splhigh();
    291   1.1  tsutsui 	/* interrupt vector */
    292   1.1  tsutsui 	zs_write_reg(cs, 2, zs_init_reg[2]);
    293   1.1  tsutsui 	/* master interrupt control (enable) */
    294   1.1  tsutsui 	zs_write_reg(cs, 9, zs_init_reg[9]);
    295   1.1  tsutsui 	splx(s);
    296   1.1  tsutsui 
    297   1.1  tsutsui 	if (zs_sir == 0)
    298   1.5  tsutsui 		zs_sir = allocate_sir(zssoft, zsc);
    299   1.1  tsutsui }
    300   1.1  tsutsui 
    301   1.1  tsutsui static int
    302   1.1  tsutsui zs_print(aux, name)
    303   1.1  tsutsui 	void *aux;
    304   1.1  tsutsui 	const char *name;
    305   1.1  tsutsui {
    306   1.1  tsutsui 	struct zsc_attach_args *args = aux;
    307   1.1  tsutsui 
    308   1.1  tsutsui 	if (name != NULL)
    309  1.11  thorpej 		aprint_normal("%s: ", name);
    310   1.1  tsutsui 
    311   1.1  tsutsui 	if (args->channel != -1)
    312  1.11  thorpej 		aprint_normal(" channel %d", args->channel);
    313   1.1  tsutsui 
    314   1.1  tsutsui 	return UNCONF;
    315   1.1  tsutsui }
    316   1.1  tsutsui 
    317   1.1  tsutsui /*
    318   1.1  tsutsui  * For news68k-port, we don't use autovectored interrupt.
    319   1.1  tsutsui  * We do not need to look at all of the zs chips.
    320   1.1  tsutsui  */
    321   1.1  tsutsui static int
    322   1.1  tsutsui zshard(arg)
    323   1.1  tsutsui 	void *arg;
    324   1.1  tsutsui {
    325   1.1  tsutsui 	struct zsc_softc *zsc = arg;
    326   1.1  tsutsui 	int rval;
    327   1.1  tsutsui 
    328   1.1  tsutsui 	rval = zsc_intr_hard(zsc);
    329   1.1  tsutsui 
    330   1.1  tsutsui 	/* We are at splzs here, so no need to lock. */
    331   1.1  tsutsui 	if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) {
    332   1.1  tsutsui 		setsoftint(zs_sir);
    333   1.1  tsutsui 	}
    334   1.1  tsutsui 
    335  1.16  tsutsui 	return rval;
    336   1.1  tsutsui }
    337   1.1  tsutsui 
    338   1.1  tsutsui /*
    339   1.1  tsutsui  * Shared among the all chips. We have to look at all of them.
    340   1.1  tsutsui  */
    341   1.5  tsutsui void
    342   1.1  tsutsui zssoft(arg)
    343   1.1  tsutsui 	void *arg;
    344   1.1  tsutsui {
    345   1.1  tsutsui 	struct zsc_softc *zsc;
    346   1.1  tsutsui 	int s, unit;
    347   1.1  tsutsui 
    348   1.1  tsutsui 	/* Make sure we call the tty layer at spltty. */
    349   1.1  tsutsui 	s = spltty();
    350   1.1  tsutsui 	for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
    351   1.1  tsutsui 		zsc = zsc_cd.cd_devs[unit];
    352   1.1  tsutsui 		if (zsc == NULL)
    353   1.1  tsutsui 			continue;
    354   1.1  tsutsui 		(void) zsc_intr_soft(zsc);
    355   1.1  tsutsui 	}
    356   1.1  tsutsui 	splx(s);
    357   1.1  tsutsui }
    358   1.1  tsutsui 
    359   1.1  tsutsui /*
    360   1.1  tsutsui  * Compute the current baud rate given a ZS channel.
    361   1.1  tsutsui  */
    362   1.5  tsutsui #if 0
    363   1.1  tsutsui static int
    364   1.1  tsutsui zs_get_speed(cs)
    365   1.1  tsutsui 	struct zs_chanstate *cs;
    366   1.1  tsutsui {
    367   1.1  tsutsui 	int tconst;
    368   1.1  tsutsui 
    369   1.1  tsutsui 	tconst = zs_read_reg(cs, 12);
    370   1.1  tsutsui 	tconst |= zs_read_reg(cs, 13) << 8;
    371  1.16  tsutsui 	return TCONST_TO_BPS(cs->cs_brg_clk, tconst);
    372   1.1  tsutsui }
    373   1.5  tsutsui #endif
    374   1.1  tsutsui 
    375   1.1  tsutsui /*
    376   1.1  tsutsui  * MD functions for setting the baud rate and control modes.
    377   1.1  tsutsui  */
    378   1.1  tsutsui int
    379   1.1  tsutsui zs_set_speed(cs, bps)
    380   1.1  tsutsui 	struct zs_chanstate *cs;
    381   1.1  tsutsui 	int bps;	/* bits per second */
    382   1.1  tsutsui {
    383   1.1  tsutsui 	int tconst, real_bps;
    384   1.1  tsutsui 
    385   1.1  tsutsui 	if (bps == 0)
    386  1.16  tsutsui 		return 0;
    387   1.1  tsutsui 
    388   1.1  tsutsui #ifdef	DIAGNOSTIC
    389   1.1  tsutsui 	if (cs->cs_brg_clk == 0)
    390   1.1  tsutsui 		panic("zs_set_speed");
    391   1.1  tsutsui #endif
    392   1.1  tsutsui 
    393   1.1  tsutsui 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
    394   1.1  tsutsui 	if (tconst < 0)
    395  1.16  tsutsui 		return EINVAL;
    396   1.1  tsutsui 
    397   1.1  tsutsui 	/* Convert back to make sure we can do it. */
    398   1.1  tsutsui 	real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
    399   1.1  tsutsui 
    400   1.1  tsutsui 	/* XXX - Allow some tolerance here? */
    401   1.1  tsutsui 	if (real_bps != bps)
    402  1.16  tsutsui 		return EINVAL;
    403   1.1  tsutsui 
    404   1.1  tsutsui 	cs->cs_preg[12] = tconst;
    405   1.1  tsutsui 	cs->cs_preg[13] = tconst >> 8;
    406   1.1  tsutsui 
    407   1.1  tsutsui 	/* Caller will stuff the pending registers. */
    408  1.16  tsutsui 	return 0;
    409   1.1  tsutsui }
    410   1.1  tsutsui 
    411   1.1  tsutsui int
    412   1.1  tsutsui zs_set_modes(cs, cflag)
    413   1.1  tsutsui 	struct zs_chanstate *cs;
    414   1.1  tsutsui 	int cflag;	/* bits per second */
    415   1.1  tsutsui {
    416   1.1  tsutsui 	int s;
    417   1.1  tsutsui 
    418   1.1  tsutsui 	/*
    419   1.1  tsutsui 	 * Output hardware flow control on the chip is horrendous:
    420   1.1  tsutsui 	 * if carrier detect drops, the receiver is disabled, and if
    421   1.1  tsutsui 	 * CTS drops, the transmitter is stoped IN MID CHARACTER!
    422   1.1  tsutsui 	 * Therefore, NEVER set the HFC bit, and instead use the
    423   1.1  tsutsui 	 * status interrupt to detect CTS changes.
    424   1.1  tsutsui 	 */
    425   1.1  tsutsui 	s = splzs();
    426   1.1  tsutsui 	cs->cs_rr0_pps = 0;
    427   1.1  tsutsui 	if ((cflag & (CLOCAL | MDMBUF)) != 0) {
    428   1.1  tsutsui 		cs->cs_rr0_dcd = 0;
    429   1.1  tsutsui 		if ((cflag & MDMBUF) == 0)
    430   1.1  tsutsui 			cs->cs_rr0_pps = ZSRR0_DCD;
    431   1.1  tsutsui 	} else
    432   1.1  tsutsui 		cs->cs_rr0_dcd = ZSRR0_DCD;
    433   1.1  tsutsui 	if ((cflag & CRTSCTS) != 0) {
    434   1.1  tsutsui 		cs->cs_wr5_dtr = ZSWR5_DTR;
    435   1.1  tsutsui 		cs->cs_wr5_rts = ZSWR5_RTS;
    436   1.1  tsutsui 		cs->cs_rr0_cts = ZSRR0_CTS;
    437   1.1  tsutsui 	} else if ((cflag & MDMBUF) != 0) {
    438   1.1  tsutsui 		cs->cs_wr5_dtr = 0;
    439   1.1  tsutsui 		cs->cs_wr5_rts = ZSWR5_DTR;
    440   1.1  tsutsui 		cs->cs_rr0_cts = ZSRR0_DCD;
    441   1.1  tsutsui 	} else {
    442   1.1  tsutsui 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    443   1.1  tsutsui 		cs->cs_wr5_rts = 0;
    444   1.1  tsutsui 		cs->cs_rr0_cts = 0;
    445   1.1  tsutsui 	}
    446   1.1  tsutsui 	splx(s);
    447   1.1  tsutsui 
    448   1.1  tsutsui 	/* Caller will stuff the pending registers. */
    449  1.16  tsutsui 	return 0;
    450   1.1  tsutsui }
    451   1.1  tsutsui 
    452   1.1  tsutsui 
    453   1.1  tsutsui /*
    454   1.1  tsutsui  * Read or write the chip with suitable delays.
    455   1.1  tsutsui  */
    456   1.1  tsutsui 
    457   1.1  tsutsui u_char
    458   1.1  tsutsui zs_read_reg(cs, reg)
    459   1.1  tsutsui 	struct zs_chanstate *cs;
    460   1.1  tsutsui 	u_char reg;
    461   1.1  tsutsui {
    462   1.1  tsutsui 	u_char val;
    463   1.1  tsutsui 
    464   1.1  tsutsui 	*cs->cs_reg_csr = reg;
    465   1.1  tsutsui 	ZS_DELAY();
    466   1.1  tsutsui 	val = *cs->cs_reg_csr;
    467   1.1  tsutsui 	ZS_DELAY();
    468   1.1  tsutsui 	return val;
    469   1.1  tsutsui }
    470   1.1  tsutsui 
    471   1.1  tsutsui void
    472   1.1  tsutsui zs_write_reg(cs, reg, val)
    473   1.1  tsutsui 	struct zs_chanstate *cs;
    474   1.1  tsutsui 	u_char reg, val;
    475   1.1  tsutsui {
    476  1.16  tsutsui 
    477   1.1  tsutsui 	*cs->cs_reg_csr = reg;
    478   1.1  tsutsui 	ZS_DELAY();
    479   1.1  tsutsui 	*cs->cs_reg_csr = val;
    480   1.1  tsutsui 	ZS_DELAY();
    481   1.1  tsutsui }
    482   1.1  tsutsui 
    483   1.3  tsutsui u_char
    484   1.3  tsutsui zs_read_csr(cs)
    485   1.1  tsutsui 	struct zs_chanstate *cs;
    486   1.1  tsutsui {
    487   1.1  tsutsui 	u_char val;
    488   1.1  tsutsui 
    489   1.1  tsutsui 	val = *cs->cs_reg_csr;
    490   1.1  tsutsui 	ZS_DELAY();
    491   1.1  tsutsui 	return val;
    492   1.1  tsutsui }
    493   1.1  tsutsui 
    494   1.3  tsutsui void
    495   1.3  tsutsui zs_write_csr(cs, val)
    496   1.1  tsutsui 	struct zs_chanstate *cs;
    497   1.1  tsutsui 	u_char val;
    498   1.1  tsutsui {
    499  1.16  tsutsui 
    500   1.1  tsutsui 	*cs->cs_reg_csr = val;
    501   1.1  tsutsui 	ZS_DELAY();
    502   1.1  tsutsui }
    503   1.1  tsutsui 
    504   1.3  tsutsui u_char
    505   1.3  tsutsui zs_read_data(cs)
    506   1.1  tsutsui 	struct zs_chanstate *cs;
    507   1.1  tsutsui {
    508   1.1  tsutsui 	u_char val;
    509   1.1  tsutsui 
    510   1.1  tsutsui 	val = *cs->cs_reg_data;
    511   1.1  tsutsui 	ZS_DELAY();
    512   1.1  tsutsui 	return val;
    513   1.1  tsutsui }
    514   1.1  tsutsui 
    515   1.3  tsutsui void
    516   1.3  tsutsui zs_write_data(cs, val)
    517   1.1  tsutsui 	struct zs_chanstate *cs;
    518   1.1  tsutsui 	u_char val;
    519   1.1  tsutsui {
    520  1.16  tsutsui 
    521   1.1  tsutsui 	*cs->cs_reg_data = val;
    522   1.1  tsutsui 	ZS_DELAY();
    523   1.1  tsutsui }
    524   1.1  tsutsui 
    525   1.1  tsutsui void
    526   1.1  tsutsui zs_abort(cs)
    527   1.1  tsutsui 	struct zs_chanstate *cs;
    528   1.1  tsutsui {
    529  1.16  tsutsui 
    530   1.1  tsutsui #ifdef DDB
    531   1.1  tsutsui 	Debugger();
    532   1.1  tsutsui #endif
    533   1.1  tsutsui }
    534   1.1  tsutsui 
    535   1.1  tsutsui /*
    536   1.1  tsutsui  * Polled input char.
    537   1.1  tsutsui  */
    538   1.1  tsutsui int
    539   1.1  tsutsui zs_getc(arg)
    540   1.1  tsutsui 	void *arg;
    541   1.1  tsutsui {
    542   1.5  tsutsui 	struct zs_chanstate *cs = arg;
    543   1.1  tsutsui 	int s, c, rr0;
    544   1.1  tsutsui 
    545   1.1  tsutsui 	s = splhigh();
    546   1.1  tsutsui 	/* Wait for a character to arrive. */
    547   1.1  tsutsui 	do {
    548   1.5  tsutsui 		rr0 = *cs->cs_reg_csr;
    549   1.1  tsutsui 		ZS_DELAY();
    550   1.1  tsutsui 	} while ((rr0 & ZSRR0_RX_READY) == 0);
    551   1.1  tsutsui 
    552   1.5  tsutsui 	c = *cs->cs_reg_data;
    553   1.1  tsutsui 	ZS_DELAY();
    554   1.1  tsutsui 	splx(s);
    555   1.1  tsutsui 
    556   1.1  tsutsui 	return c;
    557   1.1  tsutsui }
    558   1.1  tsutsui 
    559   1.1  tsutsui /*
    560   1.1  tsutsui  * Polled output char.
    561   1.1  tsutsui  */
    562   1.1  tsutsui void
    563   1.1  tsutsui zs_putc(arg, c)
    564   1.1  tsutsui 	void *arg;
    565   1.1  tsutsui 	int c;
    566   1.1  tsutsui {
    567   1.5  tsutsui 	struct zs_chanstate *cs = arg;
    568   1.1  tsutsui 	int s, rr0;
    569   1.1  tsutsui 
    570   1.1  tsutsui 	s = splhigh();
    571   1.1  tsutsui 	/* Wait for transmitter to become ready. */
    572   1.1  tsutsui 	do {
    573   1.5  tsutsui 		rr0 = *cs->cs_reg_csr;
    574   1.1  tsutsui 		ZS_DELAY();
    575   1.1  tsutsui 	} while ((rr0 & ZSRR0_TX_READY) == 0);
    576   1.1  tsutsui 
    577   1.5  tsutsui 	*cs->cs_reg_data = c;
    578   1.1  tsutsui 	ZS_DELAY();
    579   1.1  tsutsui 	splx(s);
    580   1.1  tsutsui }
    581   1.1  tsutsui 
    582   1.1  tsutsui /*****************************************************************/
    583   1.1  tsutsui 
    584  1.10  tsutsui static void zscnprobe(struct consdev *);
    585  1.10  tsutsui static void zscninit(struct consdev *);
    586  1.10  tsutsui static int  zscngetc(dev_t);
    587  1.10  tsutsui static void zscnputc(dev_t, int);
    588   1.1  tsutsui 
    589   1.1  tsutsui struct consdev consdev_zs = {
    590   1.1  tsutsui 	zscnprobe,
    591   1.1  tsutsui 	zscninit,
    592   1.1  tsutsui 	zscngetc,
    593   1.1  tsutsui 	zscnputc,
    594   1.4  thorpej 	nullcnpollc,
    595   1.4  thorpej 	NULL,
    596  1.17  tsutsui 	NULL,
    597  1.17  tsutsui 	NULL,
    598  1.17  tsutsui 	NODEV,
    599  1.17  tsutsui 	CN_DEAD
    600   1.1  tsutsui };
    601   1.1  tsutsui 
    602   1.3  tsutsui static void
    603   1.1  tsutsui zscnprobe(cn)
    604   1.1  tsutsui 	struct consdev *cn;
    605   1.1  tsutsui {
    606   1.1  tsutsui }
    607   1.1  tsutsui 
    608   1.3  tsutsui static void
    609   1.1  tsutsui zscninit(cn)
    610   1.1  tsutsui 	struct consdev *cn;
    611   1.1  tsutsui {
    612   1.5  tsutsui 	struct zs_chanstate *cs;
    613   1.5  tsutsui 
    614  1.17  tsutsui 	extern const struct cdevsw zstty_cdevsw;
    615  1.17  tsutsui 	extern int tty00_is_console;
    616   1.3  tsutsui 	extern volatile u_char *sccport0a;
    617  1.17  tsutsui 
    618  1.17  tsutsui 	cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
    619  1.17  tsutsui 	if (tty00_is_console)
    620  1.17  tsutsui 		cn->cn_pri = CN_REMOTE;
    621  1.17  tsutsui 	else
    622  1.17  tsutsui 		cn->cn_pri = CN_NORMAL;
    623   1.3  tsutsui 
    624   1.5  tsutsui 	zc_cons = (struct zschan *)sccport0a; /* XXX */
    625   1.5  tsutsui 
    626   1.5  tsutsui 	zs_conschan = cs = &zs_conschan_store;
    627   1.5  tsutsui 
    628   1.5  tsutsui 	/* Setup temporary chanstate. */
    629   1.5  tsutsui 	cs->cs_reg_csr  = &zc_cons->zc_csr;
    630   1.5  tsutsui 	cs->cs_reg_data = &zc_cons->zc_data;
    631   1.5  tsutsui 
    632   1.5  tsutsui 	/* Initialize the pending registers. */
    633   1.6  tsutsui 	memcpy(cs->cs_preg, zs_init_reg, 16);
    634   1.5  tsutsui 	cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
    635   1.5  tsutsui 
    636   1.5  tsutsui 	cs->cs_preg[12] = BPS_TO_TCONST(pclk[systype] / 16, 9600); /* XXX */
    637   1.5  tsutsui 	cs->cs_preg[13] = 0;
    638   1.5  tsutsui 	cs->cs_defspeed = 9600;
    639   1.5  tsutsui 
    640   1.5  tsutsui 	/* Clear the master interrupt enable. */
    641   1.5  tsutsui 	zs_write_reg(cs, 9, 0);
    642   1.5  tsutsui 
    643   1.5  tsutsui 	/* Reset the whole SCC chip. */
    644   1.5  tsutsui 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    645   1.5  tsutsui 
    646   1.5  tsutsui 	/* Copy "pending" to "current" and H/W */
    647   1.5  tsutsui 	zs_loadchannelregs(cs);
    648   1.1  tsutsui }
    649   1.1  tsutsui 
    650   1.3  tsutsui static int
    651   1.1  tsutsui zscngetc(dev)
    652   1.1  tsutsui 	dev_t dev;
    653   1.1  tsutsui {
    654  1.16  tsutsui 
    655   1.5  tsutsui 	return zs_getc((void *)zs_conschan);
    656   1.1  tsutsui }
    657   1.1  tsutsui 
    658   1.3  tsutsui static void
    659   1.1  tsutsui zscnputc(dev, c)
    660   1.1  tsutsui 	dev_t dev;
    661   1.1  tsutsui 	int c;
    662   1.1  tsutsui {
    663  1.16  tsutsui 
    664   1.5  tsutsui 	zs_putc((void *)zs_conschan, c);
    665   1.1  tsutsui }
    666