Home | History | Annotate | Line # | Download | only in apbus
zs_ap.c revision 1.31
      1  1.31   thorpej /*	$NetBSD: zs_ap.c,v 1.31 2021/04/24 23:36:44 thorpej Exp $	*/
      2   1.1    tsubai 
      3   1.1    tsubai /*-
      4   1.1    tsubai  * Copyright (c) 1996 The NetBSD Foundation, Inc.
      5   1.1    tsubai  * All rights reserved.
      6   1.1    tsubai  *
      7   1.1    tsubai  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1    tsubai  * by Gordon W. Ross.
      9   1.1    tsubai  *
     10   1.1    tsubai  * Redistribution and use in source and binary forms, with or without
     11   1.1    tsubai  * modification, are permitted provided that the following conditions
     12   1.1    tsubai  * are met:
     13   1.1    tsubai  * 1. Redistributions of source code must retain the above copyright
     14   1.1    tsubai  *    notice, this list of conditions and the following disclaimer.
     15   1.1    tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1    tsubai  *    notice, this list of conditions and the following disclaimer in the
     17   1.1    tsubai  *    documentation and/or other materials provided with the distribution.
     18   1.1    tsubai  *
     19   1.1    tsubai  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1    tsubai  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1    tsubai  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1    tsubai  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1    tsubai  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1    tsubai  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1    tsubai  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1    tsubai  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1    tsubai  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1    tsubai  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1    tsubai  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1    tsubai  */
     31   1.1    tsubai 
     32   1.1    tsubai /*
     33   1.1    tsubai  * Zilog Z8530 Dual UART driver (machine-dependent part)
     34   1.1    tsubai  *
     35   1.1    tsubai  * Runs two serial lines per chip using slave drivers.
     36   1.1    tsubai  * Plain tty/async lines use the zs_async slave.
     37   1.1    tsubai  * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
     38   1.1    tsubai  */
     39  1.16     lukem 
     40  1.16     lukem #include <sys/cdefs.h>
     41  1.31   thorpej __KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.31 2021/04/24 23:36:44 thorpej Exp $");
     42   1.1    tsubai 
     43   1.1    tsubai #include <sys/param.h>
     44   1.1    tsubai #include <sys/systm.h>
     45   1.1    tsubai #include <sys/device.h>
     46   1.1    tsubai #include <sys/tty.h>
     47   1.6   gehenna #include <sys/conf.h>
     48  1.23        ad #include <sys/cpu.h>
     49  1.23        ad #include <sys/intr.h>
     50  1.29   tsutsui #ifdef NEWS4000_ZS_AP_POLLING
     51  1.29   tsutsui #include <sys/callout.h>
     52  1.29   tsutsui #endif
     53   1.1    tsubai 
     54   1.1    tsubai #include <machine/adrsmap.h>
     55   1.1    tsubai #include <machine/z8530var.h>
     56   1.1    tsubai 
     57   1.1    tsubai #include <dev/cons.h>
     58   1.1    tsubai #include <dev/ic/z8530reg.h>
     59   1.1    tsubai 
     60   1.1    tsubai #include <newsmips/apbus/apbusvar.h>
     61   1.1    tsubai 
     62   1.1    tsubai #include "zsc.h"	/* NZSC */
     63   1.1    tsubai #define NZS NZSC
     64   1.1    tsubai 
     65   1.1    tsubai /* Make life easier for the initialized arrays here. */
     66   1.1    tsubai #if NZS < 2
     67   1.1    tsubai #undef  NZS
     68   1.1    tsubai #define NZS 2
     69   1.1    tsubai #endif
     70   1.1    tsubai 
     71  1.29   tsutsui #define NEWS5000_PORTB_TXPORT	0x00000000
     72  1.29   tsutsui #define NEWS5000_PORTB_RXPORT	0x00010000
     73  1.29   tsutsui #define NEWS5000_PORTA_TXPORT	0x00020000
     74  1.29   tsutsui #define NEWS5000_PORTA_RXPORT	0x00030000
     75  1.29   tsutsui #define   NEWS5000_DMA_MODE_REG		3
     76  1.29   tsutsui #define     NEWS5000_DMA_ENABLE		0x01	/* DMA enable */
     77  1.29   tsutsui #define     NEWS5000_DMA_DIR_DM		0x00	/* device to memory */
     78  1.29   tsutsui #define     NEWS5000_DMA_DIR_MD		0x02	/* memory to device */
     79  1.29   tsutsui #define     NEWS5000_DMA_EXTRDY		0x08	/* DMA external ready */
     80  1.29   tsutsui #define NEWS5000_PORTB_OFFSET	0x00040000
     81  1.29   tsutsui #define NEWS5000_PORTA_OFFSET	0x00050000
     82  1.29   tsutsui #define   NEWS5000_PORT_CTL		2
     83  1.29   tsutsui #define     NEWS5000_PORTCTL_RI		0x01
     84  1.29   tsutsui #define     NEWS5000_PORTCTL_DSR	0x02
     85  1.29   tsutsui #define     NEWS5000_PORTCTL_DTR	0x04
     86  1.29   tsutsui #define   NEWS5000_PORT_SEL		3
     87  1.29   tsutsui #define     NEWS5000_PORTSEL_LOCALTALK	0x01
     88  1.29   tsutsui #define     NEWS5000_PORTSEL_RS232C	0x02
     89  1.29   tsutsui #define NEWS5000_ESCC_REG	0x00060000
     90  1.29   tsutsui #define   NEWS5000_ESCCREG_INTSTAT	0
     91  1.29   tsutsui #define     NEWS5000_INTSTAT_SCC	0x01
     92  1.29   tsutsui #define   NEWS5000_ESCCREG_INTMASK	1
     93  1.29   tsutsui #define     NEWS5000_INTMASK_SCC	0x01
     94  1.29   tsutsui 
     95  1.29   tsutsui #define NEWS4000_PORTB_TXPORT	0x00000000	/* XXX: not confirmed */
     96  1.29   tsutsui #define NEWS4000_PORTB_RXPORT	0x00010000	/* XXX: not confirmed */
     97  1.29   tsutsui #define NEWS4000_PORTA_TXPORT	0x00040000	/* XXX: not confirmed */
     98  1.29   tsutsui #define NEWS4000_PORTA_RXPORT	0x00050000	/* XXX: not confirmed */
     99  1.29   tsutsui #define   NEWS4000_DMA_MODE_REG		3
    100  1.29   tsutsui #define     NEWS4000_DMA_ENABLE		0x01	/* DMA enable */
    101  1.29   tsutsui #define     NEWS4000_DMA_DIR_DM		0x00	/* device to memory */
    102  1.29   tsutsui #define     NEWS4000_DMA_DIR_MD		0x02	/* memory to device */
    103  1.29   tsutsui #define     NEWS4000_DMA_EXTRDY		0x08	/* DMA external ready */
    104  1.29   tsutsui #define NEWS4000_PORTB_CTL	0x00020000	/* XXX: not confirmed */
    105  1.29   tsutsui #define NEWS4000_PORTA_CTL	0x00060000	/* XXX: not confirmed */
    106  1.29   tsutsui #define   NEWS4000_PORT_CTL		4
    107  1.29   tsutsui #define     NEWS4000_PORTCTL_RI		0x01
    108  1.29   tsutsui #define     NEWS4000_PORTCTL_DSR	0x02
    109  1.29   tsutsui #define     NEWS4000_PORTCTL_DTR	0x04
    110  1.29   tsutsui #define   NEWS4000_PORT_SEL		5
    111  1.29   tsutsui #define     NEWS4000_PORTSEL_LOCALTALK	0x01
    112  1.29   tsutsui #define     NEWS4000_PORTSEL_RS232C	0x02
    113  1.29   tsutsui #define NEWS4000_ESCC_REG	0x00060000	/* XXX:  not confirmed */
    114  1.29   tsutsui #define   NEWS4000_ESCCREG_INTSTAT	0
    115  1.29   tsutsui #define     NEWS4000_INTSTAT_SCC	0x01
    116  1.29   tsutsui #define   NEWS4000_ESCCREG_INTMASK	1
    117  1.29   tsutsui #define     NEWS4000_INTMASK_SCC	0x01
    118  1.29   tsutsui #define NEWS4000_PORTB_OFFSET	0x00080000
    119  1.29   tsutsui #define NEWS4000_PORTA_OFFSET	0x00080008
    120   1.1    tsubai 
    121   1.1    tsubai extern int zs_def_cflag;
    122  1.17   tsutsui extern void (*zs_delay)(void);
    123   1.1    tsubai 
    124   1.1    tsubai /*
    125   1.1    tsubai  * The news5000 provides a 9.8304 MHz clock to the ZS chips.
    126   1.1    tsubai  */
    127   1.1    tsubai #define PCLK	(9600 * 1024)	/* PCLK pin input clock rate */
    128   1.1    tsubai 
    129   1.1    tsubai #define ZS_DELAY()	DELAY(2)
    130   1.1    tsubai 
    131   1.1    tsubai /* The layout of this is hardware-dependent (padding, order). */
    132   1.1    tsubai struct zschan {
    133  1.24   tsutsui 	volatile uint8_t pad1[3];
    134  1.24   tsutsui 	volatile uint8_t zc_csr;	/* ctrl,status, and indirect access */
    135  1.24   tsutsui 	volatile uint8_t pad2[3];
    136  1.24   tsutsui 	volatile uint8_t zc_data;	/* data */
    137   1.1    tsubai };
    138   1.1    tsubai 
    139  1.20  christos static void *zsaddr[NZS];
    140   1.1    tsubai 
    141   1.1    tsubai /* Default speed for all channels */
    142   1.1    tsubai static int zs_defspeed = 9600;
    143   1.1    tsubai 
    144  1.30   tsutsui /* console status from cninit */
    145  1.30   tsutsui static struct zs_chanstate zs_ap_conschan_store;
    146  1.30   tsutsui static struct zs_chanstate *zs_ap_conschan;
    147  1.30   tsutsui static struct zschan *zc_ap_cons;
    148  1.30   tsutsui 
    149  1.24   tsutsui static uint8_t zs_init_reg[16] = {
    150   1.1    tsubai 	0,	/* 0: CMD (reset, etc.) */
    151   1.1    tsubai 	0,	/* 1: No interrupts yet. */
    152   1.1    tsubai 	0,	/* IVECT */
    153   1.1    tsubai 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
    154   1.1    tsubai 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
    155   1.1    tsubai 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
    156   1.1    tsubai 	0,	/* 6: TXSYNC/SYNCLO */
    157   1.1    tsubai 	0,	/* 7: RXSYNC/SYNCHI */
    158   1.1    tsubai 	0,	/* 8: alias for data port */
    159   1.1    tsubai 	ZSWR9_MASTER_IE,
    160   1.1    tsubai 	0,	/*10: Misc. TX/RX control bits */
    161   1.1    tsubai 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
    162  1.30   tsutsui 	BPS_TO_TCONST(PCLK/16,9600),	/*12: BAUDLO (default=9600) */
    163   1.1    tsubai 	0,			/*13: BAUDHI (default=9600) */
    164   1.1    tsubai 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
    165   1.1    tsubai 	ZSWR15_BREAK_IE,
    166   1.1    tsubai };
    167   1.1    tsubai 
    168  1.29   tsutsui #ifdef NEWS4000_ZS_AP_POLLING
    169  1.29   tsutsui static struct callout zscallout;
    170  1.29   tsutsui #endif
    171  1.29   tsutsui 
    172  1.17   tsutsui static struct zschan * zs_get_chan_addr(int, int);
    173  1.17   tsutsui static void zs_ap_delay(void);
    174  1.17   tsutsui static int zshard_ap(void *);
    175  1.17   tsutsui static int zs_getc(void *);
    176  1.17   tsutsui static void zs_putc(void *, int);
    177   1.1    tsubai 
    178   1.1    tsubai struct zschan *
    179  1.17   tsutsui zs_get_chan_addr(int zs_unit, int channel)
    180   1.1    tsubai {
    181  1.20  christos 	void *addr;
    182  1.29   tsutsui 	struct zschan *zc = NULL;
    183   1.1    tsubai 
    184   1.1    tsubai 	if (zs_unit >= NZS)
    185   1.1    tsubai 		return NULL;
    186   1.1    tsubai 	addr = zsaddr[zs_unit];
    187   1.1    tsubai 	if (addr == NULL)
    188   1.1    tsubai 		return NULL;
    189  1.29   tsutsui 	if (systype == NEWS5000) {
    190  1.29   tsutsui 		if (channel == 0) {
    191  1.29   tsutsui 			zc = (void *)((uint8_t *)addr + NEWS5000_PORTA_OFFSET);
    192  1.29   tsutsui 		} else {
    193  1.29   tsutsui 			zc = (void *)((uint8_t *)addr + NEWS5000_PORTB_OFFSET);
    194  1.29   tsutsui 		}
    195  1.29   tsutsui 	}
    196  1.29   tsutsui 	if (systype == NEWS4000) {
    197  1.29   tsutsui 		if (channel == 0) {
    198  1.29   tsutsui 			zc = (void *)((uint8_t *)addr + NEWS4000_PORTA_OFFSET);
    199  1.29   tsutsui 		} else {
    200  1.29   tsutsui 			zc = (void *)((uint8_t *)addr + NEWS4000_PORTB_OFFSET);
    201  1.29   tsutsui 		}
    202   1.1    tsubai 	}
    203  1.17   tsutsui 	return zc;
    204   1.1    tsubai }
    205   1.1    tsubai 
    206   1.1    tsubai void
    207  1.17   tsutsui zs_ap_delay(void)
    208   1.1    tsubai {
    209  1.13   tsutsui 
    210   1.1    tsubai 	ZS_DELAY();
    211   1.1    tsubai }
    212   1.1    tsubai 
    213   1.1    tsubai /****************************************************************
    214   1.1    tsubai  * Autoconfig
    215   1.1    tsubai  ****************************************************************/
    216   1.1    tsubai 
    217   1.1    tsubai /* Definition of the driver for autoconfig. */
    218  1.24   tsutsui int zs_ap_match(device_t, cfdata_t, void *);
    219  1.24   tsutsui void zs_ap_attach(device_t, device_t, void *);
    220   1.1    tsubai 
    221  1.24   tsutsui CFATTACH_DECL_NEW(zsc_ap, sizeof(struct zsc_softc),
    222   1.8   thorpej     zs_ap_match, zs_ap_attach, NULL, NULL);
    223   1.1    tsubai 
    224   1.1    tsubai /*
    225   1.1    tsubai  * Is the zs chip present?
    226   1.1    tsubai  */
    227   1.1    tsubai int
    228  1.24   tsutsui zs_ap_match(device_t parent, cfdata_t cf, void *aux)
    229   1.1    tsubai {
    230   1.1    tsubai 	struct apbus_attach_args *apa = aux;
    231   1.1    tsubai 
    232  1.29   tsutsui 	if (strcmp("esccf", apa->apa_name) == 0 ||
    233  1.29   tsutsui 	    strcmp("esccg", apa->apa_name) == 0)
    234  1.29   tsutsui 		return 1;
    235   1.1    tsubai 
    236  1.29   tsutsui 	return 0;
    237   1.1    tsubai }
    238   1.1    tsubai 
    239   1.1    tsubai /*
    240   1.1    tsubai  * Attach a found zs.
    241   1.1    tsubai  *
    242   1.1    tsubai  * Match slave number to zs unit number, so that misconfiguration will
    243   1.1    tsubai  * not set up the keyboard as ttya, etc.
    244   1.1    tsubai  */
    245   1.1    tsubai void
    246  1.24   tsutsui zs_ap_attach(device_t parent, device_t self, void *aux)
    247   1.1    tsubai {
    248  1.24   tsutsui 	struct zsc_softc *zsc = device_private(self);
    249   1.1    tsubai 	struct apbus_attach_args *apa = aux;
    250   1.1    tsubai 	struct zsc_attach_args zsc_args;
    251   1.1    tsubai 	volatile struct zschan *zc;
    252   1.1    tsubai 	struct zs_chanstate *cs;
    253   1.1    tsubai 	int s, zs_unit, channel;
    254  1.29   tsutsui 	volatile uint32_t *txBfifo;
    255  1.29   tsutsui 	volatile uint32_t *rxBfifo;
    256  1.29   tsutsui 	volatile uint32_t *txAfifo;
    257  1.29   tsutsui 	volatile uint32_t *rxAfifo;
    258  1.29   tsutsui 	volatile uint32_t *portBctl;
    259  1.29   tsutsui 	volatile uint32_t *portActl;
    260  1.29   tsutsui 	volatile uint32_t *esccregs;
    261   1.1    tsubai 
    262  1.24   tsutsui 	zsc->zsc_dev = self;
    263  1.24   tsutsui 	zs_unit = device_unit(self);
    264  1.20  christos 	zsaddr[zs_unit] = (void *)apa->apa_hwbase;
    265   1.1    tsubai 
    266  1.24   tsutsui 	aprint_normal(" slot%d addr 0x%lx\n", apa->apa_slotno, apa->apa_hwbase);
    267   1.1    tsubai 
    268  1.29   tsutsui 	/* XXX: appease gcc -Wuninitialized */
    269  1.29   tsutsui 	txBfifo  = (void *)(apa->apa_hwbase);
    270  1.29   tsutsui 	rxBfifo  = (void *)(apa->apa_hwbase);
    271  1.29   tsutsui 	txAfifo  = (void *)(apa->apa_hwbase);
    272  1.29   tsutsui 	rxAfifo  = (void *)(apa->apa_hwbase);
    273  1.29   tsutsui 	portBctl = (void *)(apa->apa_hwbase);
    274  1.29   tsutsui 	portActl = (void *)(apa->apa_hwbase);
    275  1.29   tsutsui 	esccregs = (void *)(apa->apa_hwbase);
    276  1.29   tsutsui 
    277  1.29   tsutsui 	if (systype == NEWS5000) {
    278  1.29   tsutsui 		txBfifo  = (void *)(apa->apa_hwbase + NEWS5000_PORTB_TXPORT);
    279  1.29   tsutsui 		rxBfifo  = (void *)(apa->apa_hwbase + NEWS5000_PORTB_RXPORT);
    280  1.29   tsutsui 		txAfifo  = (void *)(apa->apa_hwbase + NEWS5000_PORTA_TXPORT);
    281  1.29   tsutsui 		rxAfifo  = (void *)(apa->apa_hwbase + NEWS5000_PORTA_RXPORT);
    282  1.29   tsutsui 		portBctl = (void *)(apa->apa_hwbase + NEWS5000_PORTB_OFFSET);
    283  1.29   tsutsui 		portActl = (void *)(apa->apa_hwbase + NEWS5000_PORTA_OFFSET);
    284  1.29   tsutsui 		esccregs = (void *)(apa->apa_hwbase + NEWS5000_ESCC_REG);
    285  1.29   tsutsui 	}
    286  1.29   tsutsui 	if (systype == NEWS4000) {
    287  1.29   tsutsui 		txBfifo  = (void *)(apa->apa_hwbase + NEWS4000_PORTB_TXPORT);
    288  1.29   tsutsui 		rxBfifo  = (void *)(apa->apa_hwbase + NEWS4000_PORTB_RXPORT);
    289  1.29   tsutsui 		txAfifo  = (void *)(apa->apa_hwbase + NEWS4000_PORTA_TXPORT);
    290  1.29   tsutsui 		rxAfifo  = (void *)(apa->apa_hwbase + NEWS4000_PORTA_RXPORT);
    291  1.29   tsutsui 		portBctl = (void *)(apa->apa_hwbase + NEWS4000_PORTB_CTL);
    292  1.29   tsutsui 		portActl = (void *)(apa->apa_hwbase + NEWS4000_PORTA_CTL);
    293  1.29   tsutsui 		esccregs = (void *)(apa->apa_hwbase + NEWS4000_ESCC_REG);
    294  1.29   tsutsui 	}
    295   1.1    tsubai 
    296  1.29   tsutsui 	if (systype == NEWS5000) {
    297  1.29   tsutsui 		txAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
    298  1.29   tsutsui 		rxAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
    299  1.29   tsutsui 		txBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
    300  1.29   tsutsui 		rxBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
    301  1.29   tsutsui 
    302  1.29   tsutsui 		/* assert DTR */			/* XXX */
    303  1.29   tsutsui 		portBctl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
    304  1.29   tsutsui 		portActl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
    305   1.1    tsubai 
    306  1.29   tsutsui 		/* select RS-232C (ch1 only) */
    307  1.29   tsutsui 		portActl[NEWS5000_PORT_SEL] = NEWS5000_PORTSEL_RS232C;
    308   1.1    tsubai 
    309  1.29   tsutsui 		/* enable SCC interrupts */
    310  1.29   tsutsui 		esccregs[NEWS5000_ESCCREG_INTMASK] = NEWS5000_INTMASK_SCC;
    311  1.29   tsutsui 	}
    312  1.29   tsutsui 
    313  1.29   tsutsui 	if (systype == NEWS4000) {
    314  1.29   tsutsui 		txAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
    315  1.29   tsutsui 		rxAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
    316  1.29   tsutsui 		txBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
    317  1.29   tsutsui 		rxBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
    318  1.29   tsutsui 
    319  1.29   tsutsui #if 1	/* XXX: zsc on news4000 seems mangled by these ops */
    320  1.29   tsutsui 		/* assert DTR */			/* XXX */
    321  1.29   tsutsui 		portBctl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
    322  1.29   tsutsui 		portActl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
    323  1.29   tsutsui 
    324  1.29   tsutsui 		/* select RS-232C (ch1 only) */
    325  1.29   tsutsui 		portActl[NEWS4000_PORT_SEL] = NEWS4000_PORTSEL_RS232C;
    326  1.29   tsutsui #endif
    327  1.29   tsutsui 
    328  1.29   tsutsui 		/* enable SCC interrupts */
    329  1.29   tsutsui 		esccregs[NEWS4000_ESCCREG_INTMASK] = NEWS4000_INTMASK_SCC;
    330  1.29   tsutsui 	}
    331   1.1    tsubai 
    332   1.1    tsubai 	zs_delay = zs_ap_delay;
    333   1.1    tsubai 
    334   1.1    tsubai 	/*
    335   1.1    tsubai 	 * Initialize software state for each channel.
    336   1.1    tsubai 	 */
    337   1.1    tsubai 	for (channel = 0; channel < 2; channel++) {
    338   1.1    tsubai 		zsc_args.channel = channel;
    339   1.1    tsubai 		cs = &zsc->zsc_cs_store[channel];
    340   1.1    tsubai 		zsc->zsc_cs[channel] = cs;
    341   1.1    tsubai 
    342  1.22        ad 		zs_lock_init(cs);
    343   1.1    tsubai 		cs->cs_channel = channel;
    344   1.1    tsubai 		cs->cs_private = NULL;
    345   1.1    tsubai 		cs->cs_ops = &zsops_null;
    346   1.1    tsubai 		cs->cs_brg_clk = PCLK / 16;
    347   1.1    tsubai 
    348   1.1    tsubai 		zc = zs_get_chan_addr(zs_unit, channel);
    349   1.1    tsubai 
    350  1.30   tsutsui 		if (zc == zc_ap_cons) {
    351  1.30   tsutsui 			memcpy(cs, zs_ap_conschan, sizeof(struct zs_chanstate));
    352  1.30   tsutsui 			zs_ap_conschan = cs;
    353  1.30   tsutsui 			zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
    354  1.30   tsutsui 		} else {
    355  1.30   tsutsui 			cs->cs_reg_csr  = &zc->zc_csr;
    356  1.30   tsutsui 			cs->cs_reg_data = &zc->zc_data;
    357  1.30   tsutsui 			memcpy(cs->cs_creg, zs_init_reg, 16);
    358  1.30   tsutsui 			memcpy(cs->cs_preg, zs_init_reg, 16);
    359   1.1    tsubai 			cs->cs_defspeed = zs_defspeed;
    360  1.30   tsutsui 			zsc_args.hwflags = 0;
    361  1.30   tsutsui 		}
    362   1.1    tsubai 		cs->cs_defcflag = zs_def_cflag;
    363   1.1    tsubai 
    364   1.1    tsubai 		/* Make these correspond to cs_defcflag (-crtscts) */
    365   1.1    tsubai 		cs->cs_rr0_dcd = ZSRR0_DCD;
    366   1.1    tsubai 		cs->cs_rr0_cts = 0;
    367   1.1    tsubai 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
    368   1.1    tsubai 		cs->cs_wr5_rts = 0;
    369   1.1    tsubai 
    370   1.1    tsubai 		/*
    371   1.1    tsubai 		 * Clear the master interrupt enable.
    372   1.1    tsubai 		 * The INTENA is common to both channels,
    373   1.1    tsubai 		 * so just do it on the A channel.
    374   1.1    tsubai 		 */
    375   1.1    tsubai 		if (channel == 0) {
    376   1.1    tsubai 			zs_write_reg(cs, 9, 0);
    377   1.1    tsubai 		}
    378   1.1    tsubai 
    379   1.1    tsubai 		/*
    380   1.1    tsubai 		 * Look for a child driver for this channel.
    381   1.1    tsubai 		 * The child attach will setup the hardware.
    382   1.1    tsubai 		 */
    383  1.31   thorpej 		if (!config_found(self, (void *)&zsc_args, zs_print,
    384  1.31   thorpej 		    CFARG_EOL)) {
    385   1.1    tsubai 			/* No sub-driver.  Just reset it. */
    386  1.24   tsutsui 			uint8_t reset = (channel == 0) ?
    387  1.24   tsutsui 			    ZSWR9_A_RESET : ZSWR9_B_RESET;
    388   1.1    tsubai 			s = splhigh();
    389   1.1    tsubai 			zs_write_reg(cs, 9, reset);
    390   1.1    tsubai 			splx(s);
    391   1.1    tsubai 		}
    392   1.1    tsubai 	}
    393   1.1    tsubai 
    394   1.1    tsubai 	/*
    395  1.26   tsutsui 	 * Now safe to install interrupt handlers.
    396   1.1    tsubai 	 */
    397  1.27   tsutsui 	zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
    398  1.27   tsutsui 	    (void (*)(void *))zsc_intr_soft, zsc);
    399  1.29   tsutsui 	if (systype == NEWS5000) {
    400  1.29   tsutsui 		apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
    401  1.29   tsutsui 				     NEWS5000_INT1_SCC,
    402  1.29   tsutsui 				     0, /* priority */
    403  1.29   tsutsui 				     zshard_ap, zsc,
    404  1.29   tsutsui 				     device_xname(self), apa->apa_ctlnum);
    405  1.29   tsutsui 	}
    406  1.29   tsutsui 	if (systype == NEWS4000) {
    407  1.29   tsutsui 		apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
    408  1.29   tsutsui 				     0x0200,
    409  1.29   tsutsui 				     0, /* priority */
    410  1.29   tsutsui 				     zshard_ap, zsc,
    411  1.29   tsutsui 				     device_xname(self), apa->apa_ctlnum);
    412  1.29   tsutsui #ifdef NEWS4000_ZS_AP_POLLING
    413  1.29   tsutsui 		/* XXX: no info how to enable zs ap interrupt for now */
    414  1.29   tsutsui 		callout_init(&zscallout, 0);
    415  1.29   tsutsui 		callout_reset(&zscallout, 1,
    416  1.29   tsutsui 		    (void (*)(void *))zshard_ap, (void *)zsc);
    417  1.29   tsutsui #endif
    418  1.29   tsutsui 	}
    419   1.1    tsubai 	/* XXX; evcnt_attach() ? */
    420   1.1    tsubai 
    421   1.1    tsubai #if 0
    422   1.1    tsubai {
    423   1.1    tsubai 	u_int x;
    424   1.1    tsubai 
    425   1.1    tsubai 	/* determine SCC/ESCC type */
    426   1.1    tsubai 	x = zs_read_reg(cs, 15);
    427   1.1    tsubai 	zs_write_reg(cs, 15, x | ZSWR15_ENABLE_ENHANCED);
    428   1.1    tsubai 
    429   1.1    tsubai 	if (zs_read_reg(cs, 15) & ZSWR15_ENABLE_ENHANCED) { /* ESCC Z85230 */
    430   1.1    tsubai 		zs_write_reg(cs, 7, ZSWR7P_EXTEND_READ | ZSWR7P_TX_FIFO);
    431   1.1    tsubai 	}
    432   1.1    tsubai }
    433   1.1    tsubai #endif
    434   1.1    tsubai 
    435   1.1    tsubai 	/*
    436   1.1    tsubai 	 * Set the master interrupt enable and interrupt vector.
    437   1.1    tsubai 	 * (common to both channels, do it on A)
    438   1.1    tsubai 	 */
    439   1.1    tsubai 	cs = zsc->zsc_cs[0];
    440   1.1    tsubai 	s = splhigh();
    441   1.1    tsubai 	/* interrupt vector */
    442   1.1    tsubai 	zs_write_reg(cs, 2, zs_init_reg[2]);
    443   1.1    tsubai 	/* master interrupt control (enable) */
    444   1.1    tsubai 	zs_write_reg(cs, 9, zs_init_reg[9]);
    445   1.1    tsubai 	splx(s);
    446   1.1    tsubai }
    447   1.1    tsubai 
    448   1.5      onoe static int
    449  1.17   tsutsui zshard_ap(void *arg)
    450   1.1    tsubai {
    451  1.13   tsutsui 
    452   1.3    tsubai 	zshard(arg);
    453  1.29   tsutsui #ifdef NEWS4000_ZS_AP_POLLING
    454  1.29   tsutsui 	if (systype == NEWS4000) {
    455  1.29   tsutsui 		callout_schedule(&zscallout, 1);
    456  1.29   tsutsui 	}
    457  1.29   tsutsui #endif
    458   1.5      onoe 	return 1;
    459   1.1    tsubai }
    460   1.1    tsubai 
    461   1.1    tsubai /*
    462   1.1    tsubai  * Polled input char.
    463   1.1    tsubai  */
    464   1.1    tsubai int
    465  1.17   tsutsui zs_getc(void *arg)
    466   1.1    tsubai {
    467  1.13   tsutsui 	volatile struct zschan *zc = arg;
    468  1.24   tsutsui 	int s, c;
    469  1.24   tsutsui 	uint8_t rr0;
    470   1.1    tsubai 
    471   1.1    tsubai 	s = splhigh();
    472   1.1    tsubai 	/* Wait for a character to arrive. */
    473   1.1    tsubai 	do {
    474   1.1    tsubai 		rr0 = zc->zc_csr;
    475   1.1    tsubai 		ZS_DELAY();
    476   1.1    tsubai 	} while ((rr0 & ZSRR0_RX_READY) == 0);
    477   1.1    tsubai 
    478   1.1    tsubai 	c = zc->zc_data;
    479   1.1    tsubai 	ZS_DELAY();
    480   1.1    tsubai 	splx(s);
    481   1.1    tsubai 
    482   1.1    tsubai 	/*
    483   1.1    tsubai 	 * This is used by the kd driver to read scan codes,
    484   1.1    tsubai 	 * so don't translate '\r' ==> '\n' here...
    485   1.1    tsubai 	 */
    486  1.17   tsutsui 	return c;
    487   1.1    tsubai }
    488   1.1    tsubai 
    489   1.1    tsubai /*
    490   1.1    tsubai  * Polled output char.
    491   1.1    tsubai  */
    492   1.1    tsubai void
    493  1.17   tsutsui zs_putc(void *arg, int c)
    494   1.1    tsubai {
    495  1.13   tsutsui 	volatile struct zschan *zc = arg;
    496  1.24   tsutsui 	int s;
    497  1.24   tsutsui 	uint8_t rr0;
    498   1.1    tsubai 
    499   1.1    tsubai 	s = splhigh();
    500   1.1    tsubai 	/* Wait for transmitter to become ready. */
    501   1.1    tsubai 	do {
    502   1.1    tsubai 		rr0 = zc->zc_csr;
    503   1.1    tsubai 		ZS_DELAY();
    504   1.1    tsubai 	} while ((rr0 & ZSRR0_TX_READY) == 0);
    505   1.1    tsubai 
    506   1.1    tsubai 	zc->zc_data = c;
    507   1.1    tsubai 	ZS_DELAY();
    508   1.1    tsubai 	splx(s);
    509   1.1    tsubai }
    510   1.1    tsubai 
    511   1.1    tsubai /*****************************************************************/
    512   1.1    tsubai 
    513  1.17   tsutsui static void zscnprobe(struct consdev *);
    514  1.17   tsutsui static void zscninit(struct consdev *);
    515  1.17   tsutsui static int  zscngetc(dev_t);
    516  1.17   tsutsui static void zscnputc(dev_t, int);
    517   1.1    tsubai 
    518   1.1    tsubai struct consdev consdev_zs_ap = {
    519   1.1    tsubai 	zscnprobe,
    520   1.1    tsubai 	zscninit,
    521   1.1    tsubai 	zscngetc,
    522   1.1    tsubai 	zscnputc,
    523  1.13   tsutsui 	nullcnpollc,
    524  1.13   tsutsui 	NULL,
    525  1.13   tsutsui 	NULL,
    526   1.4   thorpej 	NULL,
    527  1.13   tsutsui 	NODEV,
    528  1.13   tsutsui 	CN_DEAD
    529   1.1    tsubai };
    530   1.1    tsubai 
    531  1.13   tsutsui static void
    532  1.17   tsutsui zscnprobe(struct consdev *cn)
    533   1.1    tsubai {
    534   1.1    tsubai }
    535   1.1    tsubai 
    536  1.13   tsutsui static void
    537  1.17   tsutsui zscninit(struct consdev *cn)
    538   1.1    tsubai {
    539   1.6   gehenna 	extern const struct cdevsw zstty_cdevsw;
    540  1.30   tsutsui 	struct zs_chanstate *cs;
    541  1.30   tsutsui 	u_int tconst;
    542  1.30   tsutsui 
    543  1.30   tsutsui 	/* Wait a while for PROM console output to complete */
    544  1.30   tsutsui 	DELAY(20000);
    545   1.6   gehenna 
    546   1.6   gehenna 	cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
    547   1.1    tsubai 	cn->cn_pri = CN_REMOTE;
    548  1.30   tsutsui 
    549  1.30   tsutsui 	zc_ap_cons = sccport0a;
    550  1.30   tsutsui 	zs_delay = zs_ap_delay;
    551  1.30   tsutsui 
    552  1.30   tsutsui 	zs_ap_conschan = cs = &zs_ap_conschan_store;
    553  1.30   tsutsui 
    554  1.30   tsutsui 	/* Setup temporary chanstate. */
    555  1.30   tsutsui 	cs->cs_reg_csr  = &zc_ap_cons->zc_csr;
    556  1.30   tsutsui 	cs->cs_reg_data = &zc_ap_cons->zc_data;
    557  1.30   tsutsui 
    558  1.30   tsutsui 	/* Initialize the pending registers. */
    559  1.30   tsutsui 	memcpy(cs->cs_preg, zs_init_reg, 16);
    560  1.30   tsutsui 	cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
    561  1.30   tsutsui 
    562  1.30   tsutsui 	cs->cs_brg_clk = PCLK / 16;
    563  1.30   tsutsui 	cs->cs_defspeed = 9600;	/* PROM use 9600 bps */
    564  1.30   tsutsui 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, cs->cs_defspeed);
    565  1.30   tsutsui 	cs->cs_preg[12] = tconst;
    566  1.30   tsutsui 	cs->cs_preg[13] = tconst >> 8;
    567  1.30   tsutsui 
    568  1.30   tsutsui 	/* Clear the master interrupt enable. */
    569  1.30   tsutsui 	zs_write_reg(cs, 9, 0);
    570  1.30   tsutsui 
    571  1.30   tsutsui 	/* Reset the whole SCC chip. */
    572  1.30   tsutsui 	zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
    573  1.30   tsutsui 
    574  1.30   tsutsui 	/* Copy "pending" to "current" and H/W */
    575  1.30   tsutsui 	zs_loadchannelregs(cs);
    576   1.1    tsubai }
    577   1.1    tsubai 
    578  1.13   tsutsui static int
    579  1.17   tsutsui zscngetc(dev_t dev)
    580   1.1    tsubai {
    581  1.29   tsutsui 
    582  1.29   tsutsui 	return zs_getc(sccport0a);
    583   1.1    tsubai }
    584   1.1    tsubai 
    585  1.13   tsutsui static void
    586  1.17   tsutsui zscnputc(dev_t dev, int c)
    587   1.1    tsubai {
    588  1.13   tsutsui 
    589  1.29   tsutsui 	zs_putc(sccport0a, c);
    590   1.1    tsubai }
    591