From fc7b0964cff83d6042d641f971264b4f72cb16ff Mon Sep 17 00:00:00 2001 From: tsutsui Date: Fri, 19 Oct 2018 13:40:33 +0000 Subject: [PATCH] Reorganize APbus zs(4) console handling. - set sccport0a address on early startup and use it for cnputc and cngetc - explicitly initialize zs chip in the cninit function so that zs console can be used even if it is not initialized by PROM firmware Tested on both news50000 and news4000. --- sys/arch/newsmips/apbus/zs_ap.c | 82 ++++++++++++++++++---------- sys/arch/newsmips/include/apbus.h | 3 +- sys/arch/newsmips/newsmips/machdep.c | 13 ++++- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/sys/arch/newsmips/apbus/zs_ap.c b/sys/arch/newsmips/apbus/zs_ap.c index d9771129bd10..ffb848ae8cd6 100644 --- a/sys/arch/newsmips/apbus/zs_ap.c +++ b/sys/arch/newsmips/apbus/zs_ap.c @@ -1,4 +1,4 @@ -/* $NetBSD: zs_ap.c,v 1.29 2018/10/14 00:10:11 tsutsui Exp $ */ +/* $NetBSD: zs_ap.c,v 1.30 2018/10/19 13:40:33 tsutsui Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.29 2018/10/14 00:10:11 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.30 2018/10/19 13:40:33 tsutsui Exp $"); #include #include @@ -138,12 +138,14 @@ struct zschan { static void *zsaddr[NZS]; -/* Flags from cninit() */ -static int zs_hwflags[NZS][2]; - /* Default speed for all channels */ static int zs_defspeed = 9600; +/* console status from cninit */ +static struct zs_chanstate zs_ap_conschan_store; +static struct zs_chanstate *zs_ap_conschan; +static struct zschan *zc_ap_cons; + static uint8_t zs_init_reg[16] = { 0, /* 0: CMD (reset, etc.) */ 0, /* 1: No interrupts yet. */ @@ -157,7 +159,7 @@ static uint8_t zs_init_reg[16] = { ZSWR9_MASTER_IE, 0, /*10: Misc. TX/RX control bits */ ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, - ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */ + BPS_TO_TCONST(PCLK/16,9600), /*12: BAUDLO (default=9600) */ 0, /*13: BAUDHI (default=9600) */ ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, ZSWR15_BREAK_IE, @@ -334,7 +336,6 @@ zs_ap_attach(device_t parent, device_t self, void *aux) */ for (channel = 0; channel < 2; channel++) { zsc_args.channel = channel; - zsc_args.hwflags = zs_hwflags[zs_unit][channel]; cs = &zsc->zsc_cs_store[channel]; zsc->zsc_cs[channel] = cs; @@ -345,18 +346,19 @@ zs_ap_attach(device_t parent, device_t self, void *aux) cs->cs_brg_clk = PCLK / 16; zc = zs_get_chan_addr(zs_unit, channel); - cs->cs_reg_csr = &zc->zc_csr; - cs->cs_reg_data = &zc->zc_data; - memcpy(cs->cs_creg, zs_init_reg, 16); - memcpy(cs->cs_preg, zs_init_reg, 16); - - /* XXX: Get these from the EEPROM instead? */ - /* XXX: See the mvme167 code. Better. */ - if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) - cs->cs_defspeed = zs_get_speed(cs); - else + if (zc == zc_ap_cons) { + memcpy(cs, zs_ap_conschan, sizeof(struct zs_chanstate)); + zs_ap_conschan = cs; + zsc_args.hwflags = ZS_HWFLAG_CONSOLE; + } else { + cs->cs_reg_csr = &zc->zc_csr; + cs->cs_reg_data = &zc->zc_data; + memcpy(cs->cs_creg, zs_init_reg, 16); + memcpy(cs->cs_preg, zs_init_reg, 16); cs->cs_defspeed = zs_defspeed; + zsc_args.hwflags = 0; + } cs->cs_defcflag = zs_def_cflag; /* Make these correspond to cs_defcflag (-crtscts) */ @@ -534,21 +536,47 @@ static void zscninit(struct consdev *cn) { extern const struct cdevsw zstty_cdevsw; + struct zs_chanstate *cs; + u_int tconst; + + /* Wait a while for PROM console output to complete */ + DELAY(20000); cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0); cn->cn_pri = CN_REMOTE; - zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE; + + zc_ap_cons = sccport0a; + zs_delay = zs_ap_delay; + + zs_ap_conschan = cs = &zs_ap_conschan_store; + + /* Setup temporary chanstate. */ + cs->cs_reg_csr = &zc_ap_cons->zc_csr; + cs->cs_reg_data = &zc_ap_cons->zc_data; + + /* Initialize the pending registers. */ + memcpy(cs->cs_preg, zs_init_reg, 16); + cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; + + cs->cs_brg_clk = PCLK / 16; + cs->cs_defspeed = 9600; /* PROM use 9600 bps */ + tconst = BPS_TO_TCONST(cs->cs_brg_clk, cs->cs_defspeed); + cs->cs_preg[12] = tconst; + cs->cs_preg[13] = tconst >> 8; + + /* Clear the master interrupt enable. */ + zs_write_reg(cs, 9, 0); + + /* Reset the whole SCC chip. */ + zs_write_reg(cs, 9, ZSWR9_HARD_RESET); + + /* Copy "pending" to "current" and H/W */ + zs_loadchannelregs(cs); } static int zscngetc(dev_t dev) { - void *sccport0a; - - if (systype == NEWS5000) - sccport0a = (void *)NEWS5000_SCCPORT0A; - if (systype == NEWS4000) - sccport0a = (void *)NEWS4000_SCCPORT0A; return zs_getc(sccport0a); } @@ -556,12 +584,6 @@ zscngetc(dev_t dev) static void zscnputc(dev_t dev, int c) { - void *sccport0a; - - if (systype == NEWS5000) - sccport0a = (void *)NEWS5000_SCCPORT0A; - if (systype == NEWS4000) - sccport0a = (void *)NEWS4000_SCCPORT0A; zs_putc(sccport0a, c); } diff --git a/sys/arch/newsmips/include/apbus.h b/sys/arch/newsmips/include/apbus.h index 81b2b594fcee..4120e9218e73 100644 --- a/sys/arch/newsmips/include/apbus.h +++ b/sys/arch/newsmips/include/apbus.h @@ -1,4 +1,4 @@ -/* $NetBSD: apbus.h,v 1.6 2018/10/14 00:10:11 tsutsui Exp $ */ +/* $NetBSD: apbus.h,v 1.7 2018/10/19 13:40:33 tsutsui Exp $ */ /*- * Copyright (C) 1999 SHIMIZU Ryo. All rights reserved. @@ -104,6 +104,7 @@ struct apbus_sysinfo { extern struct apbus_sysinfo *_sip; extern volatile uint32_t *news_wbflush; +extern void *sccport0a; void apbus_wbflush(void); #endif /* !__MACHINE_APBUS__ */ diff --git a/sys/arch/newsmips/newsmips/machdep.c b/sys/arch/newsmips/newsmips/machdep.c index 235f6a4363a0..cc0c1d1e2c68 100644 --- a/sys/arch/newsmips/newsmips/machdep.c +++ b/sys/arch/newsmips/newsmips/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.120 2018/10/14 00:10:11 tsutsui Exp $ */ +/* $NetBSD: machdep.c,v 1.121 2018/10/19 13:40:33 tsutsui Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -39,7 +39,7 @@ #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.120 2018/10/14 00:10:11 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.121 2018/10/19 13:40:33 tsutsui Exp $"); /* from: Utah Hdr: machdep.c 1.63 91/04/24 */ @@ -111,6 +111,7 @@ struct vm_map *phys_map = NULL; char *bootinfo = NULL; /* pointer to bootinfo structure */ int systype; /* what type of NEWS we are */ struct apbus_sysinfo *_sip = NULL; +void *sccport0a; phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; int mem_cluster_cnt; @@ -194,6 +195,12 @@ mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem) if (systype == 0) systype = NEWS3400; /* XXX compatibility for old boot */ +#ifdef news3400 + if (systype == NEWS3400) { + sccport0a = (void *)SCCPORT0A; + } +#endif + #if defined(news5000) || defined(news4000) if (systype == NEWS5000 || systype == NEWS4000) { int i; @@ -224,6 +231,8 @@ mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem) x_bootdev |= (i << 8); /* partition */ } bootspec_end: + sccport0a = (systype == NEWS5000) ? + (void *)NEWS5000_SCCPORT0A : (void *)NEWS4000_SCCPORT0A; consinit(); } #endif /* news5000 || news4000 */