1 1.26 andvar /* $NetBSD: zs.c,v 1.26 2023/12/12 23:38:11 andvar Exp $ */ 2 1.1 fredette 3 1.1 fredette /*- 4 1.1 fredette * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 1.1 fredette * All rights reserved. 6 1.1 fredette * 7 1.1 fredette * This code is derived from software contributed to The NetBSD Foundation 8 1.1 fredette * by Gordon W. Ross. 9 1.1 fredette * 10 1.1 fredette * Redistribution and use in source and binary forms, with or without 11 1.1 fredette * modification, are permitted provided that the following conditions 12 1.1 fredette * are met: 13 1.1 fredette * 1. Redistributions of source code must retain the above copyright 14 1.1 fredette * notice, this list of conditions and the following disclaimer. 15 1.1 fredette * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 fredette * notice, this list of conditions and the following disclaimer in the 17 1.1 fredette * documentation and/or other materials provided with the distribution. 18 1.1 fredette * 19 1.1 fredette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 fredette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 fredette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 fredette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 fredette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 fredette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 fredette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 fredette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 fredette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 fredette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 fredette * POSSIBILITY OF SUCH DAMAGE. 30 1.1 fredette */ 31 1.1 fredette 32 1.1 fredette /* 33 1.1 fredette * Zilog Z8530 Dual UART driver (machine-dependent part) 34 1.1 fredette * 35 1.1 fredette * Runs two serial lines per chip using slave drivers. 36 1.1 fredette * Plain tty/async lines use the zs_async slave. 37 1.1 fredette * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves. 38 1.1 fredette */ 39 1.8 lukem 40 1.8 lukem #include <sys/cdefs.h> 41 1.26 andvar __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.26 2023/12/12 23:38:11 andvar Exp $"); 42 1.1 fredette 43 1.1 fredette #include "opt_ddb.h" 44 1.1 fredette #include "opt_kgdb.h" 45 1.1 fredette 46 1.1 fredette #include <sys/param.h> 47 1.1 fredette #include <sys/systm.h> 48 1.1 fredette #include <sys/conf.h> 49 1.1 fredette #include <sys/device.h> 50 1.1 fredette #include <sys/file.h> 51 1.1 fredette #include <sys/ioctl.h> 52 1.1 fredette #include <sys/kernel.h> 53 1.1 fredette #include <sys/proc.h> 54 1.1 fredette #include <sys/tty.h> 55 1.1 fredette #include <sys/time.h> 56 1.1 fredette #include <sys/syslog.h> 57 1.16 tsutsui #include <sys/intr.h> 58 1.1 fredette 59 1.1 fredette #include <machine/autoconf.h> 60 1.1 fredette #include <machine/promlib.h> 61 1.1 fredette #include <machine/cpu.h> 62 1.1 fredette #include <machine/eeprom.h> 63 1.1 fredette #include <machine/psl.h> 64 1.1 fredette #include <machine/z8530var.h> 65 1.1 fredette 66 1.1 fredette #include <dev/cons.h> 67 1.1 fredette #include <dev/ic/z8530reg.h> 68 1.1 fredette #include <dev/sun/kbd_ms_ttyvar.h> 69 1.25 riastrad 70 1.25 riastrad #include <ddb/db_active.h> 71 1.1 fredette #include <ddb/db_output.h> 72 1.1 fredette 73 1.1 fredette #include <sun2/dev/cons.h> 74 1.1 fredette 75 1.17 tsutsui #include "ioconf.h" 76 1.1 fredette #include "kbd.h" /* NKBD */ 77 1.1 fredette #include "ms.h" /* NMS */ 78 1.1 fredette 79 1.1 fredette /* 80 1.1 fredette * Some warts needed by z8530tty.c - 81 1.1 fredette * The default parity REALLY needs to be the same as the PROM uses, 82 1.1 fredette * or you can not see messages done with printf during boot-up... 83 1.1 fredette */ 84 1.1 fredette int zs_def_cflag = (CREAD | CS8 | HUPCL); 85 1.1 fredette 86 1.1 fredette /* ZS channel used as the console device (if any) */ 87 1.1 fredette void *zs_conschan_get, *zs_conschan_put; 88 1.1 fredette 89 1.17 tsutsui static uint8_t zs_init_reg[16] = { 90 1.1 fredette 0, /* 0: CMD (reset, etc.) */ 91 1.1 fredette 0, /* 1: No interrupts yet. */ 92 1.1 fredette #ifdef ZS_INIT_IVECT 93 1.1 fredette ZS_INIT_IVECT, /* 2: IVECT */ 94 1.1 fredette #else 95 1.1 fredette 0, /* 2: IVECT */ 96 1.1 fredette #endif 97 1.1 fredette ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 98 1.1 fredette ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 99 1.1 fredette ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 100 1.1 fredette 0, /* 6: TXSYNC/SYNCLO */ 101 1.1 fredette 0, /* 7: RXSYNC/SYNCHI */ 102 1.1 fredette 0, /* 8: alias for data port */ 103 1.1 fredette #ifdef ZS_INIT_IVECT 104 1.1 fredette ZSWR9_MASTER_IE, 105 1.1 fredette #else 106 1.1 fredette ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR, 107 1.1 fredette #endif 108 1.1 fredette 0, /*10: Misc. TX/RX control bits */ 109 1.1 fredette ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 110 1.1 fredette ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */ 111 1.1 fredette 0, /*13: BAUDHI (default=9600) */ 112 1.1 fredette ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 113 1.1 fredette ZSWR15_BREAK_IE, 114 1.1 fredette }; 115 1.1 fredette 116 1.1 fredette /* Console ops */ 117 1.10 chs static int zscngetc(dev_t); 118 1.10 chs static void zscnputc(dev_t, int); 119 1.10 chs static void zscnpollc(dev_t, int); 120 1.1 fredette 121 1.1 fredette struct consdev zs_consdev = { 122 1.1 fredette NULL, 123 1.1 fredette NULL, 124 1.1 fredette zscngetc, 125 1.1 fredette zscnputc, 126 1.1 fredette zscnpollc, 127 1.1 fredette NULL, 128 1.1 fredette }; 129 1.1 fredette 130 1.1 fredette 131 1.1 fredette /**************************************************************** 132 1.1 fredette * Autoconfig 133 1.1 fredette ****************************************************************/ 134 1.1 fredette 135 1.10 chs static int zs_print(void *, const char *name); 136 1.1 fredette 137 1.1 fredette /* Interrupt handlers. */ 138 1.10 chs int zscheckintr(void *); 139 1.10 chs static int zshard(void *); 140 1.10 chs static void zssoft(void *); 141 1.1 fredette 142 1.10 chs static int zs_get_speed(struct zs_chanstate *); 143 1.1 fredette 144 1.1 fredette /* 145 1.1 fredette * Attach a found zs. 146 1.1 fredette * 147 1.1 fredette * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR 148 1.1 fredette * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE? 149 1.1 fredette */ 150 1.25 riastrad void 151 1.10 chs zs_attach(struct zsc_softc *zsc, struct zsdevice *zsd, int pri) 152 1.1 fredette { 153 1.1 fredette struct zsc_attach_args zsc_args; 154 1.1 fredette struct zs_chanstate *cs; 155 1.20 mrg int channel; 156 1.1 fredette 157 1.20 mrg memset(&zsc_args, 0, sizeof zsc_args); 158 1.1 fredette if (zsd == NULL) { 159 1.17 tsutsui aprint_error(": configuration incomplete\n"); 160 1.1 fredette return; 161 1.1 fredette } 162 1.1 fredette 163 1.16 tsutsui #if 0 164 1.14 tsutsui /* we should use ipl2si(softpri) but it isn't exported */ 165 1.17 tsutsui aprint_normal(" softpri %d\n", _IPL_SOFT_LEVEL3); 166 1.16 tsutsui #else 167 1.17 tsutsui aprint_normal("\n"); 168 1.16 tsutsui #endif 169 1.1 fredette 170 1.1 fredette /* 171 1.1 fredette * Initialize software state for each channel. 172 1.1 fredette */ 173 1.1 fredette for (channel = 0; channel < 2; channel++) { 174 1.1 fredette struct zschan *zc; 175 1.21 tsutsui device_t child; 176 1.1 fredette 177 1.1 fredette zsc_args.channel = channel; 178 1.20 mrg zsc_args.hwflags = 0; 179 1.1 fredette cs = &zsc->zsc_cs_store[channel]; 180 1.1 fredette zsc->zsc_cs[channel] = cs; 181 1.1 fredette 182 1.15 ad zs_lock_init(cs); 183 1.1 fredette cs->cs_channel = channel; 184 1.1 fredette cs->cs_private = NULL; 185 1.1 fredette cs->cs_ops = &zsops_null; 186 1.1 fredette cs->cs_brg_clk = PCLK / 16; 187 1.1 fredette 188 1.1 fredette zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b; 189 1.1 fredette 190 1.1 fredette zsc_args.consdev = NULL; 191 1.1 fredette zsc_args.hwflags = zs_console_flags(zsc->zsc_promunit, 192 1.1 fredette zsc->zsc_node, 193 1.1 fredette channel); 194 1.1 fredette 195 1.1 fredette if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 196 1.1 fredette zsc_args.hwflags |= ZS_HWFLAG_USE_CONSDEV; 197 1.1 fredette zsc_args.consdev = &zs_consdev; 198 1.1 fredette } 199 1.1 fredette 200 1.1 fredette if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) { 201 1.1 fredette zs_conschan_get = zc; 202 1.1 fredette } 203 1.1 fredette if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) { 204 1.1 fredette zs_conschan_put = zc; 205 1.1 fredette } 206 1.1 fredette 207 1.1 fredette /* Children need to set cn_dev, etc */ 208 1.1 fredette cs->cs_reg_csr = &zc->zc_csr; 209 1.1 fredette cs->cs_reg_data = &zc->zc_data; 210 1.1 fredette 211 1.5 fredette memcpy(cs->cs_creg, zs_init_reg, 16); 212 1.5 fredette memcpy(cs->cs_preg, zs_init_reg, 16); 213 1.1 fredette 214 1.1 fredette /* XXX: Consult PROM properties for this?! */ 215 1.1 fredette cs->cs_defspeed = zs_get_speed(cs); 216 1.1 fredette cs->cs_defcflag = zs_def_cflag; 217 1.1 fredette 218 1.1 fredette /* Make these correspond to cs_defcflag (-crtscts) */ 219 1.1 fredette cs->cs_rr0_dcd = ZSRR0_DCD; 220 1.1 fredette cs->cs_rr0_cts = 0; 221 1.1 fredette cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 222 1.1 fredette cs->cs_wr5_rts = 0; 223 1.1 fredette 224 1.1 fredette /* 225 1.1 fredette * Clear the master interrupt enable. 226 1.1 fredette * The INTENA is common to both channels, 227 1.1 fredette * so just do it on the A channel. 228 1.1 fredette */ 229 1.1 fredette if (channel == 0) { 230 1.1 fredette zs_write_reg(cs, 9, 0); 231 1.1 fredette } 232 1.1 fredette 233 1.1 fredette /* 234 1.1 fredette * Look for a child driver for this channel. 235 1.1 fredette * The child attach will setup the hardware. 236 1.1 fredette */ 237 1.17 tsutsui if ((child = config_found(zsc->zsc_dev, (void *)&zsc_args, 238 1.23 thorpej zs_print, CFARGS_NONE)) == NULL) { 239 1.1 fredette /* No sub-driver. Just reset it. */ 240 1.17 tsutsui uint8_t reset = (channel == 0) ? 241 1.1 fredette ZSWR9_A_RESET : ZSWR9_B_RESET; 242 1.20 mrg zs_lock_chan(cs); 243 1.1 fredette zs_write_reg(cs, 9, reset); 244 1.20 mrg zs_unlock_chan(cs); 245 1.25 riastrad } 246 1.1 fredette #if (NKBD > 0) || (NMS > 0) 247 1.25 riastrad /* 248 1.1 fredette * If this was a zstty it has a keyboard 249 1.1 fredette * property on it we need to attach the 250 1.1 fredette * sunkbd and sunms line disciplines. 251 1.1 fredette */ 252 1.25 riastrad if (child 253 1.12 thorpej && device_is_a(child, "zstty")) { 254 1.1 fredette struct kbd_ms_tty_attach_args kma; 255 1.25 riastrad struct zstty_softc { 256 1.17 tsutsui /* 257 1.17 tsutsui * The following are the only fields 258 1.17 tsutsui * we need here 259 1.17 tsutsui */ 260 1.17 tsutsui device_t zst_dev; 261 1.1 fredette struct tty *zst_tty; 262 1.1 fredette struct zs_chanstate *zst_cs; 263 1.17 tsutsui } *zst = device_private(child); 264 1.1 fredette struct tty *tp; 265 1.1 fredette 266 1.1 fredette kma.kmta_tp = tp = zst->zst_tty; 267 1.1 fredette if (tp != NULL) { 268 1.1 fredette kma.kmta_dev = tp->t_dev; 269 1.1 fredette kma.kmta_consdev = zsc_args.consdev; 270 1.25 riastrad 271 1.1 fredette /* Attach 'em if we got 'em. */ 272 1.1 fredette switch(zs_peripheral_type(zsc->zsc_promunit, 273 1.1 fredette zsc->zsc_node, 274 1.1 fredette channel)) { 275 1.1 fredette case ZS_PERIPHERAL_SUNKBD: 276 1.1 fredette #if (NKBD > 0) 277 1.1 fredette kma.kmta_name = "keyboard"; 278 1.22 thorpej config_found(child, (void *)&kma, NULL, 279 1.23 thorpej CFARGS_NONE); 280 1.1 fredette #endif 281 1.1 fredette break; 282 1.1 fredette case ZS_PERIPHERAL_SUNMS: 283 1.1 fredette #if (NMS > 0) 284 1.1 fredette kma.kmta_name = "mouse"; 285 1.22 thorpej config_found(child, (void *)&kma, NULL, 286 1.23 thorpej CFARGS_NONE); 287 1.1 fredette #endif 288 1.1 fredette break; 289 1.1 fredette default: 290 1.1 fredette break; 291 1.1 fredette } 292 1.1 fredette } 293 1.1 fredette } 294 1.1 fredette #endif 295 1.1 fredette } 296 1.1 fredette 297 1.1 fredette /* 298 1.13 tsutsui * Now safe to install interrupt handlers. 299 1.1 fredette */ 300 1.1 fredette bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, 0, zshard, zsc); 301 1.17 tsutsui if ((zsc->zsc_softintr = softint_establish(SOFTINT_SERIAL, 302 1.17 tsutsui zssoft, zsc)) == NULL) 303 1.17 tsutsui panic("%s: could not establish soft interrupt", __func__); 304 1.1 fredette 305 1.1 fredette evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL, 306 1.17 tsutsui device_xname(zsc->zsc_dev), "intr"); 307 1.1 fredette 308 1.1 fredette 309 1.1 fredette /* 310 1.1 fredette * Set the master interrupt enable and interrupt vector. 311 1.1 fredette * (common to both channels, do it on A) 312 1.1 fredette */ 313 1.1 fredette cs = zsc->zsc_cs[0]; 314 1.20 mrg zs_lock_chan(cs); 315 1.1 fredette /* interrupt vector */ 316 1.1 fredette zs_write_reg(cs, 2, zs_init_reg[2]); 317 1.1 fredette /* master interrupt control (enable) */ 318 1.1 fredette zs_write_reg(cs, 9, zs_init_reg[9]); 319 1.20 mrg zs_unlock_chan(cs); 320 1.1 fredette 321 1.1 fredette } 322 1.1 fredette 323 1.25 riastrad static int 324 1.10 chs zs_print(void *aux, const char *name) 325 1.1 fredette { 326 1.1 fredette struct zsc_attach_args *args = aux; 327 1.1 fredette 328 1.1 fredette if (name != NULL) 329 1.6 thorpej aprint_normal("%s: ", name); 330 1.1 fredette 331 1.1 fredette if (args->channel != -1) 332 1.6 thorpej aprint_normal(" channel %d", args->channel); 333 1.1 fredette 334 1.1 fredette return (UNCONF); 335 1.1 fredette } 336 1.1 fredette 337 1.25 riastrad static int 338 1.10 chs zshard(void *arg) 339 1.1 fredette { 340 1.17 tsutsui struct zsc_softc *zsc = arg; 341 1.17 tsutsui int rval; 342 1.17 tsutsui uint8_t rr3; 343 1.1 fredette 344 1.1 fredette rval = 0; 345 1.1 fredette while ((rr3 = zsc_intr_hard(zsc))) { 346 1.1 fredette /* Count up the interrupts. */ 347 1.1 fredette rval |= rr3; 348 1.1 fredette zsc->zsc_intrcnt.ev_count++; 349 1.1 fredette } 350 1.1 fredette if (((zsc->zsc_cs[0] && zsc->zsc_cs[0]->cs_softreq) || 351 1.1 fredette (zsc->zsc_cs[1] && zsc->zsc_cs[1]->cs_softreq)) && 352 1.1 fredette zsc->zsc_softintr) { 353 1.16 tsutsui softint_schedule(zsc->zsc_softintr); 354 1.1 fredette } 355 1.1 fredette return (rval); 356 1.1 fredette } 357 1.1 fredette 358 1.25 riastrad int 359 1.10 chs zscheckintr(void *arg) 360 1.1 fredette { 361 1.1 fredette struct zsc_softc *zsc; 362 1.1 fredette int unit, rval; 363 1.1 fredette 364 1.1 fredette rval = 0; 365 1.1 fredette for (unit = 0; unit < zs_cd.cd_ndevs; unit++) { 366 1.1 fredette 367 1.19 cegger zsc = device_lookup_private(&zs_cd, unit); 368 1.1 fredette if (zsc == NULL) 369 1.1 fredette continue; 370 1.1 fredette rval = (zshard((void *)zsc) || rval); 371 1.1 fredette } 372 1.1 fredette return (rval); 373 1.1 fredette } 374 1.1 fredette 375 1.1 fredette 376 1.25 riastrad static void 377 1.10 chs zssoft(void *arg) 378 1.1 fredette { 379 1.17 tsutsui struct zsc_softc *zsc = arg; 380 1.1 fredette int s; 381 1.1 fredette 382 1.1 fredette /* Make sure we call the tty layer at spltty. */ 383 1.1 fredette s = spltty(); 384 1.1 fredette (void)zsc_intr_soft(zsc); 385 1.25 riastrad 386 1.1 fredette splx(s); 387 1.1 fredette } 388 1.1 fredette 389 1.1 fredette 390 1.1 fredette /* 391 1.1 fredette * Compute the current baud rate given a ZS channel. 392 1.1 fredette */ 393 1.25 riastrad static int 394 1.10 chs zs_get_speed(struct zs_chanstate *cs) 395 1.1 fredette { 396 1.1 fredette int tconst; 397 1.1 fredette 398 1.1 fredette tconst = zs_read_reg(cs, 12); 399 1.1 fredette tconst |= zs_read_reg(cs, 13) << 8; 400 1.1 fredette return (TCONST_TO_BPS(cs->cs_brg_clk, tconst)); 401 1.1 fredette } 402 1.1 fredette 403 1.1 fredette /* 404 1.1 fredette * MD functions for setting the baud rate and control modes. 405 1.1 fredette */ 406 1.25 riastrad int 407 1.10 chs zs_set_speed(struct zs_chanstate *cs, int bps) 408 1.1 fredette { 409 1.1 fredette int tconst, real_bps; 410 1.1 fredette 411 1.1 fredette if (bps == 0) 412 1.1 fredette return (0); 413 1.1 fredette 414 1.1 fredette #ifdef DIAGNOSTIC 415 1.1 fredette if (cs->cs_brg_clk == 0) 416 1.1 fredette panic("zs_set_speed"); 417 1.1 fredette #endif 418 1.1 fredette 419 1.1 fredette tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 420 1.1 fredette if (tconst < 0) 421 1.1 fredette return (EINVAL); 422 1.1 fredette 423 1.1 fredette /* Convert back to make sure we can do it. */ 424 1.1 fredette real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 425 1.1 fredette 426 1.1 fredette /* XXX - Allow some tolerance here? */ 427 1.1 fredette if (real_bps != bps) 428 1.1 fredette return (EINVAL); 429 1.1 fredette 430 1.1 fredette cs->cs_preg[12] = tconst; 431 1.1 fredette cs->cs_preg[13] = tconst >> 8; 432 1.1 fredette 433 1.1 fredette /* Caller will stuff the pending registers. */ 434 1.1 fredette return (0); 435 1.1 fredette } 436 1.1 fredette 437 1.25 riastrad int 438 1.10 chs zs_set_modes(struct zs_chanstate *cs, int cflag /* bits per second */) 439 1.1 fredette { 440 1.1 fredette 441 1.1 fredette /* 442 1.1 fredette * Output hardware flow control on the chip is horrendous: 443 1.1 fredette * if carrier detect drops, the receiver is disabled, and if 444 1.24 andvar * CTS drops, the transmitter is stopped IN MID CHARACTER! 445 1.1 fredette * Therefore, NEVER set the HFC bit, and instead use the 446 1.1 fredette * status interrupt to detect CTS changes. 447 1.1 fredette */ 448 1.20 mrg zs_lock_chan(cs); 449 1.1 fredette cs->cs_rr0_pps = 0; 450 1.1 fredette if ((cflag & (CLOCAL | MDMBUF)) != 0) { 451 1.1 fredette cs->cs_rr0_dcd = 0; 452 1.1 fredette if ((cflag & MDMBUF) == 0) 453 1.1 fredette cs->cs_rr0_pps = ZSRR0_DCD; 454 1.1 fredette } else 455 1.1 fredette cs->cs_rr0_dcd = ZSRR0_DCD; 456 1.1 fredette if ((cflag & CRTSCTS) != 0) { 457 1.1 fredette cs->cs_wr5_dtr = ZSWR5_DTR; 458 1.1 fredette cs->cs_wr5_rts = ZSWR5_RTS; 459 1.1 fredette cs->cs_rr0_cts = ZSRR0_CTS; 460 1.1 fredette } else if ((cflag & CDTRCTS) != 0) { 461 1.1 fredette cs->cs_wr5_dtr = 0; 462 1.1 fredette cs->cs_wr5_rts = ZSWR5_DTR; 463 1.1 fredette cs->cs_rr0_cts = ZSRR0_CTS; 464 1.1 fredette } else if ((cflag & MDMBUF) != 0) { 465 1.1 fredette cs->cs_wr5_dtr = 0; 466 1.1 fredette cs->cs_wr5_rts = ZSWR5_DTR; 467 1.1 fredette cs->cs_rr0_cts = ZSRR0_DCD; 468 1.1 fredette } else { 469 1.1 fredette cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 470 1.1 fredette cs->cs_wr5_rts = 0; 471 1.1 fredette cs->cs_rr0_cts = 0; 472 1.1 fredette } 473 1.20 mrg zs_unlock_chan(cs); 474 1.1 fredette 475 1.1 fredette /* Caller will stuff the pending registers. */ 476 1.1 fredette return (0); 477 1.1 fredette } 478 1.1 fredette 479 1.1 fredette 480 1.1 fredette /* 481 1.1 fredette * Read or write the chip with suitable delays. 482 1.1 fredette */ 483 1.1 fredette 484 1.17 tsutsui uint8_t 485 1.17 tsutsui zs_read_reg(struct zs_chanstate *cs, uint8_t reg) 486 1.1 fredette { 487 1.17 tsutsui uint8_t val; 488 1.1 fredette 489 1.1 fredette *cs->cs_reg_csr = reg; 490 1.1 fredette ZS_DELAY(); 491 1.1 fredette val = *cs->cs_reg_csr; 492 1.1 fredette ZS_DELAY(); 493 1.1 fredette return (val); 494 1.1 fredette } 495 1.1 fredette 496 1.1 fredette void 497 1.17 tsutsui zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val) 498 1.1 fredette { 499 1.1 fredette *cs->cs_reg_csr = reg; 500 1.1 fredette ZS_DELAY(); 501 1.1 fredette *cs->cs_reg_csr = val; 502 1.1 fredette ZS_DELAY(); 503 1.1 fredette } 504 1.1 fredette 505 1.17 tsutsui uint8_t 506 1.10 chs zs_read_csr(struct zs_chanstate *cs) 507 1.1 fredette { 508 1.17 tsutsui uint8_t val; 509 1.1 fredette 510 1.1 fredette val = *cs->cs_reg_csr; 511 1.1 fredette ZS_DELAY(); 512 1.1 fredette return (val); 513 1.1 fredette } 514 1.1 fredette 515 1.10 chs void 516 1.17 tsutsui zs_write_csr(struct zs_chanstate *cs, uint8_t val) 517 1.1 fredette { 518 1.1 fredette *cs->cs_reg_csr = val; 519 1.1 fredette ZS_DELAY(); 520 1.1 fredette } 521 1.1 fredette 522 1.17 tsutsui uint8_t 523 1.10 chs zs_read_data(struct zs_chanstate *cs) 524 1.1 fredette { 525 1.17 tsutsui uint8_t val; 526 1.1 fredette 527 1.1 fredette val = *cs->cs_reg_data; 528 1.1 fredette ZS_DELAY(); 529 1.1 fredette return (val); 530 1.1 fredette } 531 1.1 fredette 532 1.10 chs void 533 1.17 tsutsui zs_write_data(struct zs_chanstate *cs, uint8_t val) 534 1.1 fredette { 535 1.1 fredette *cs->cs_reg_data = val; 536 1.1 fredette ZS_DELAY(); 537 1.1 fredette } 538 1.1 fredette 539 1.1 fredette /**************************************************************** 540 1.1 fredette * Console support functions (Sun specific!) 541 1.1 fredette * Note: this code is allowed to know about the layout of 542 1.1 fredette * the chip registers, and uses that to keep things simple. 543 1.1 fredette * XXX - I think I like the mvme167 code better. -gwr 544 1.1 fredette ****************************************************************/ 545 1.1 fredette 546 1.10 chs extern void Debugger(void); 547 1.1 fredette 548 1.1 fredette /* 549 1.1 fredette * Handle user request to enter kernel debugger. 550 1.1 fredette */ 551 1.25 riastrad void 552 1.10 chs zs_abort(struct zs_chanstate *cs) 553 1.1 fredette { 554 1.1 fredette volatile struct zschan *zc = zs_conschan_get; 555 1.1 fredette int rr0; 556 1.1 fredette 557 1.1 fredette /* Wait for end of break to avoid PROM abort. */ 558 1.1 fredette /* XXX - Limit the wait? */ 559 1.1 fredette do { 560 1.1 fredette rr0 = zc->zc_csr; 561 1.1 fredette ZS_DELAY(); 562 1.1 fredette } while (rr0 & ZSRR0_BREAK); 563 1.1 fredette 564 1.1 fredette #if defined(KGDB) 565 1.1 fredette zskgdb(cs); 566 1.1 fredette #elif defined(DDB) 567 1.25 riastrad if (!db_active) 568 1.25 riastrad Debugger(); 569 1.25 riastrad else 570 1.25 riastrad /* Debugger is probably hozed */ 571 1.25 riastrad callrom(); 572 1.1 fredette #else 573 1.1 fredette printf("stopping on keyboard abort\n"); 574 1.1 fredette callrom(); 575 1.1 fredette #endif 576 1.1 fredette } 577 1.1 fredette 578 1.1 fredette /* 579 1.1 fredette * Polled input char. 580 1.1 fredette */ 581 1.25 riastrad int 582 1.10 chs zs_getc(void *arg) 583 1.1 fredette { 584 1.1 fredette volatile struct zschan *zc = arg; 585 1.1 fredette int s, c, rr0; 586 1.1 fredette 587 1.1 fredette s = splhigh(); 588 1.1 fredette /* Wait for a character to arrive. */ 589 1.1 fredette do { 590 1.1 fredette rr0 = zc->zc_csr; 591 1.1 fredette ZS_DELAY(); 592 1.1 fredette } while ((rr0 & ZSRR0_RX_READY) == 0); 593 1.1 fredette 594 1.1 fredette c = zc->zc_data; 595 1.1 fredette ZS_DELAY(); 596 1.1 fredette splx(s); 597 1.1 fredette 598 1.1 fredette /* 599 1.1 fredette * This is used by the kd driver to read scan codes, 600 1.1 fredette * so don't translate '\r' ==> '\n' here... 601 1.1 fredette */ 602 1.1 fredette return (c); 603 1.1 fredette } 604 1.1 fredette 605 1.1 fredette /* 606 1.1 fredette * Polled output char. 607 1.1 fredette */ 608 1.25 riastrad void 609 1.10 chs zs_putc(void *arg, int c) 610 1.1 fredette { 611 1.1 fredette volatile struct zschan *zc = arg; 612 1.1 fredette int s, rr0; 613 1.1 fredette 614 1.1 fredette s = splhigh(); 615 1.1 fredette 616 1.1 fredette /* Wait for transmitter to become ready. */ 617 1.1 fredette do { 618 1.1 fredette rr0 = zc->zc_csr; 619 1.1 fredette ZS_DELAY(); 620 1.1 fredette } while ((rr0 & ZSRR0_TX_READY) == 0); 621 1.1 fredette 622 1.1 fredette /* 623 1.1 fredette * Send the next character. 624 1.1 fredette * Now you'd think that this could be followed by a ZS_DELAY() 625 1.1 fredette * just like all the other chip accesses, but it turns out that 626 1.1 fredette * the `transmit-ready' interrupt isn't de-asserted until 627 1.1 fredette * some period of time after the register write completes 628 1.1 fredette * (more than a couple instructions). So to avoid stray 629 1.9 wiz * interrupts we put in the 2us delay regardless of CPU model. 630 1.1 fredette */ 631 1.1 fredette zc->zc_data = c; 632 1.1 fredette delay(2); 633 1.1 fredette 634 1.1 fredette splx(s); 635 1.1 fredette } 636 1.1 fredette 637 1.1 fredette /*****************************************************************/ 638 1.1 fredette 639 1.1 fredette /* 640 1.1 fredette * Polled console input putchar. 641 1.1 fredette */ 642 1.25 riastrad static int 643 1.10 chs zscngetc(dev_t dev) 644 1.1 fredette { 645 1.1 fredette return (zs_getc(zs_conschan_get)); 646 1.1 fredette } 647 1.1 fredette 648 1.1 fredette /* 649 1.1 fredette * Polled console output putchar. 650 1.1 fredette */ 651 1.25 riastrad static void 652 1.10 chs zscnputc(dev_t dev, int c) 653 1.1 fredette { 654 1.1 fredette zs_putc(zs_conschan_put, c); 655 1.1 fredette } 656 1.1 fredette 657 1.1 fredette int swallow_zsintrs; 658 1.1 fredette 659 1.25 riastrad static void 660 1.10 chs zscnpollc(dev_t dev, int on) 661 1.1 fredette { 662 1.25 riastrad /* 663 1.1 fredette * Need to tell zs driver to acknowledge all interrupts or we get 664 1.1 fredette * annoying spurious interrupt messages. This is because mucking 665 1.1 fredette * with spl() levels during polling does not prevent interrupts from 666 1.1 fredette * being generated. 667 1.1 fredette */ 668 1.1 fredette 669 1.1 fredette if (on) swallow_zsintrs++; 670 1.1 fredette else swallow_zsintrs--; 671 1.1 fredette } 672