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