zs.c revision 1.52
1/* $NetBSD: zs.c,v 1.52 2021/04/24 23:36:41 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1996, 1998 Bill Studenmund 5 * Copyright (c) 1995 Gordon W. Ross 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * Zilog Z8530 Dual UART driver (machine-dependent part) 31 * 32 * Runs two serial lines per chip using slave drivers. 33 * Plain tty/async lines use the zs_async slave. 34 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves. 35 * Other ports use their own mice & keyboard slaves. 36 * 37 * Credits & history: 38 * 39 * With NetBSD 1.1, port-mac68k started using a port of the port-sparc 40 * (port-sun3?) zs.c driver (which was in turn based on code in the 41 * Berkeley 4.4 Lite release). Bill Studenmund did the port, with 42 * help from Allen Briggs and Gordon Ross <gwr@NetBSD.org>. Noud de 43 * Brouwer field-tested the driver at a local ISP. 44 * 45 * Bill Studenmund and Gordon Ross then ported the machine-independent 46 * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an 47 * intermediate version (mac68k using a local, patched version of 48 * the m.i. drivers), with NetBSD 1.3 containing a full version. 49 */ 50 51#include <sys/cdefs.h> 52__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.52 2021/04/24 23:36:41 thorpej Exp $"); 53 54#include "opt_ddb.h" 55#include "opt_kgdb.h" 56 57#include <sys/param.h> 58#include <sys/systm.h> 59#include <sys/proc.h> 60#include <sys/device.h> 61#include <sys/conf.h> 62#include <sys/file.h> 63#include <sys/ioctl.h> 64#include <sys/tty.h> 65#include <sys/time.h> 66#include <sys/kernel.h> 67#include <sys/syslog.h> 68#include <sys/intr.h> 69#include <sys/cpu.h> 70#ifdef KGDB 71#include <sys/kgdb.h> 72#endif 73 74#include <dev/cons.h> 75#include <dev/ofw/openfirm.h> 76#include <dev/ic/z8530reg.h> 77 78#include <machine/z8530var.h> 79#include <machine/autoconf.h> 80#include <machine/pio.h> 81 82/* Are these in a header file anywhere? */ 83/* Booter flags interface */ 84#define ZSMAC_RAW 0x01 85#define ZSMAC_LOCALTALK 0x02 86 87/* 88 * Some warts needed by z8530tty.c - 89 */ 90int zs_def_cflag = (CREAD | CS8 | HUPCL); 91 92/* 93 * abort detection on console will now timeout after iterating on a loop 94 * the following # of times. Cheep hack. Also, abort detection is turned 95 * off after a timeout (i.e. maybe there's not a terminal hooked up). 96 */ 97#define ZSABORT_DELAY 3000000 98 99struct zsdevice { 100 /* Yes, they are backwards. */ 101 struct zschan zs_chan_b; 102 struct zschan zs_chan_a; 103}; 104 105static int zs_defspeed[2] = { 106 38400, /* ttyZ0 */ 107 38400, /* ttyZ1 */ 108}; 109 110/* console stuff */ 111void *zs_conschan = 0; 112int zs_conschannel = -1; 113#ifdef ZS_CONSOLE_ABORT 114int zs_cons_canabort = 1; 115#else 116int zs_cons_canabort = 0; 117#endif /* ZS_CONSOLE_ABORT*/ 118 119/* device to which the console is attached--if serial. */ 120/* Mac stuff */ 121 122static int zs_get_speed(struct zs_chanstate *); 123 124/* 125 * Even though zsparam will set up the clock multiples, etc., we 126 * still set them here as: 1) mice & keyboards don't use zsparam, 127 * and 2) the console stuff uses these defaults before device 128 * attach. 129 */ 130 131static uint8_t zs_init_reg[16] = { 132 0, /* 0: CMD (reset, etc.) */ 133 0, /* 1: No interrupts yet. */ 134 0, /* IVECT */ 135 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 136 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 137 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 138 0, /* 6: TXSYNC/SYNCLO */ 139 0, /* 7: RXSYNC/SYNCHI */ 140 0, /* 8: alias for data port */ 141 ZSWR9_MASTER_IE, 142 0, /*10: Misc. TX/RX control bits */ 143 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 144 ((PCLK/32)/38400)-2, /*12: BAUDLO (default=38400) */ 145 0, /*13: BAUDHI (default=38400) */ 146 ZSWR14_BAUD_ENA, 147 ZSWR15_BREAK_IE, 148}; 149 150/**************************************************************** 151 * Autoconfig 152 ****************************************************************/ 153 154/* Definition of the driver for autoconfig. */ 155static int zsc_match(device_t, cfdata_t, void *); 156static void zsc_attach(device_t, device_t, void *); 157static int zsc_print(void *, const char *); 158 159CFATTACH_DECL_NEW(zsc, sizeof(struct zsc_softc), 160 zsc_match, zsc_attach, NULL, NULL); 161 162extern struct cfdriver zsc_cd; 163 164int zsc_attached; 165 166int zshard(void *); 167#ifdef ZS_TXDMA 168static int zs_txdma_int(void *); 169#endif 170 171void zscnprobe(struct consdev *); 172void zscninit(struct consdev *); 173int zscngetc(dev_t); 174void zscnputc(dev_t, int); 175void zscnpollc(dev_t, int); 176 177/* 178 * Is the zs chip present? 179 */ 180static int 181zsc_match(device_t parent, cfdata_t cf, void *aux) 182{ 183 struct confargs *ca = aux; 184 185 if (strcmp(ca->ca_name, "escc") != 0) 186 return 0; 187 188 if (zsc_attached) 189 return 0; 190 191 return 1; 192} 193 194/* 195 * Attach a found zs. 196 * 197 * Match slave number to zs unit number, so that misconfiguration will 198 * not set up the keyboard as ttya, etc. 199 */ 200static void 201zsc_attach(device_t parent, device_t self, void *aux) 202{ 203 struct zsc_softc *zsc = device_private(self); 204 struct confargs *ca = aux; 205 struct zsc_attach_args zsc_args; 206 volatile struct zschan *zc; 207 struct xzs_chanstate *xcs; 208 struct zs_chanstate *cs; 209 struct zsdevice *zsd; 210 int channel; 211 int s, chip, theflags; 212 int node, intr[2][3]; 213 u_int regs[6]; 214 char intr_xname[INTRDEVNAMEBUF]; 215 216 zsc_attached = 1; 217 218 zsc->zsc_dev = self; 219 220 chip = 0; 221 ca->ca_reg[0] += ca->ca_baseaddr; 222 zsd = mapiodev(ca->ca_reg[0], ca->ca_reg[1], false); 223 224 node = OF_child(ca->ca_node); /* ch-a */ 225 226 for (channel = 0; channel < 2; channel++) { 227 if (OF_getprop(node, "AAPL,interrupts", 228 intr[channel], sizeof(intr[0])) == -1 && 229 OF_getprop(node, "interrupts", 230 intr[channel], sizeof(intr[0])) == -1) { 231 aprint_error(": cannot find interrupt property\n"); 232 return; 233 } 234 235 if (OF_getprop(node, "reg", regs, sizeof(regs)) < 24) { 236 aprint_error(": cannot find reg property\n"); 237 return; 238 } 239 regs[2] += ca->ca_baseaddr; 240 regs[4] += ca->ca_baseaddr; 241#ifdef ZS_TXDMA 242 zsc->zsc_txdmareg[channel] = mapiodev(regs[2], regs[3], false); 243 zsc->zsc_txdmacmd[channel] = 244 dbdma_alloc(sizeof(dbdma_command_t) * 3); 245 memset(zsc->zsc_txdmacmd[channel], 0, 246 sizeof(dbdma_command_t) * 3); 247 dbdma_reset(zsc->zsc_txdmareg[channel]); 248#endif 249 node = OF_peer(node); /* ch-b */ 250 } 251 252 aprint_normal(" irq %d,%d\n", intr[0][0], intr[1][0]); 253 254 /* 255 * Initialize software state for each channel. 256 */ 257 for (channel = 0; channel < 2; channel++) { 258 zsc_args.channel = channel; 259 zsc_args.hwflags = (channel == zs_conschannel ? 260 ZS_HWFLAG_CONSOLE : 0); 261 xcs = &zsc->xzsc_xcs_store[channel]; 262 cs = &xcs->xzs_cs; 263 zsc->zsc_cs[channel] = cs; 264 265 zs_lock_init(cs); 266 cs->cs_channel = channel; 267 cs->cs_private = NULL; 268 cs->cs_ops = &zsops_null; 269 270 zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b; 271 272 cs->cs_reg_csr = &zc->zc_csr; 273 cs->cs_reg_data = &zc->zc_data; 274 275 memcpy(cs->cs_creg, zs_init_reg, 16); 276 memcpy(cs->cs_preg, zs_init_reg, 16); 277 278 /* Current BAUD rate generator clock. */ 279 cs->cs_brg_clk = PCLK / 16; /* RTxC is 230400*16, so use 230400 */ 280 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) 281 cs->cs_defspeed = zs_get_speed(cs); 282 else 283 cs->cs_defspeed = zs_defspeed[channel]; 284 cs->cs_defcflag = zs_def_cflag; 285 286 /* Make these correspond to cs_defcflag (-crtscts) */ 287 cs->cs_rr0_dcd = ZSRR0_DCD; 288 cs->cs_rr0_cts = 0; 289 cs->cs_wr5_dtr = ZSWR5_DTR; 290 cs->cs_wr5_rts = 0; 291 292#ifdef __notyet__ 293 cs->cs_slave_type = ZS_SLAVE_NONE; 294#endif 295 296 /* Define BAUD rate stuff. */ 297 xcs->cs_clocks[0].clk = PCLK; 298 xcs->cs_clocks[0].flags = ZSC_RTXBRG | ZSC_RTXDIV; 299 xcs->cs_clocks[1].flags = 300 ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN; 301 xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE; 302 xcs->cs_clock_count = 3; 303 if (channel == 0) { 304 theflags = 0; /*mac68k_machine.modem_flags;*/ 305 /*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/ 306 /*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/ 307 xcs->cs_clocks[1].clk = 0; 308 xcs->cs_clocks[2].clk = 0; 309 } else { 310 theflags = 0; /*mac68k_machine.print_flags;*/ 311 xcs->cs_clocks[1].flags = ZSC_VARIABLE; 312 /* 313 * Yes, we aren't defining ANY clock source enables for the 314 * printer's DCD clock in. The hardware won't let us 315 * use it. But a clock will freak out the chip, so we 316 * let you set it, telling us to bar interrupts on the line. 317 */ 318 /*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/ 319 /*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/ 320 xcs->cs_clocks[1].clk = 0; 321 xcs->cs_clocks[2].clk = 0; 322 } 323 if (xcs->cs_clocks[1].clk) 324 zsc_args.hwflags |= ZS_HWFLAG_NO_DCD; 325 if (xcs->cs_clocks[2].clk) 326 zsc_args.hwflags |= ZS_HWFLAG_NO_CTS; 327 328 /* Set defaults in our "extended" chanstate. */ 329 xcs->cs_csource = 0; 330 xcs->cs_psource = 0; 331 xcs->cs_cclk_flag = 0; /* Nothing fancy by default */ 332 xcs->cs_pclk_flag = 0; 333 334 if (theflags & ZSMAC_RAW) { 335 zsc_args.hwflags |= ZS_HWFLAG_RAW; 336 printf(" (raw defaults)"); 337 } 338 339 /* 340 * XXX - This might be better done with a "stub" driver 341 * (to replace zstty) that ignores LocalTalk for now. 342 */ 343 if (theflags & ZSMAC_LOCALTALK) { 344 printf(" shielding from LocalTalk"); 345 cs->cs_defspeed = 1; 346 cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff; 347 cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff; 348 zs_write_reg(cs, ZSRR_BAUDLO, 0xff); 349 zs_write_reg(cs, ZSRR_BAUDHI, 0xff); 350 /* 351 * If we might have LocalTalk, then make sure we have the 352 * Baud rate low-enough to not do any damage. 353 */ 354 } 355 356 /* 357 * We used to disable chip interrupts here, but we now 358 * do that in zscnprobe, just in case MacOS left the chip on. 359 */ 360 361 xcs->cs_chip = chip; 362 363 /* Stash away a copy of the final H/W flags. */ 364 xcs->cs_hwflags = zsc_args.hwflags; 365 366 /* 367 * Look for a child driver for this channel. 368 * The child attach will setup the hardware. 369 */ 370 if (!config_found(self, (void *)&zsc_args, zsc_print, 371 CFARG_EOL)) { 372 /* No sub-driver. Just reset it. */ 373 uint8_t reset = (channel == 0) ? 374 ZSWR9_A_RESET : ZSWR9_B_RESET; 375 s = splzs(); 376 zs_write_reg(cs, 9, reset); 377 splx(s); 378 } 379 } 380 381 /* XXX - Now safe to install interrupt handlers. */ 382 for (channel = 0; channel < 2; channel++) { 383 snprintf(intr_xname, sizeof(intr_xname), "%s pio%d", 384 device_xname(self), channel); 385 intr_establish_xname(intr[channel][0], IST_EDGE, IPL_TTY, 386 zshard, zsc, intr_xname); 387#ifdef ZS_TXDMA 388 snprintf(intr_xname, sizeof(intr_xname), "%s dma%d", 389 device_xname(self), channel); 390 intr_establish_xname(intr[channel][1], IST_EDGE, IPL_TTY, 391 zs_txdma_int, (void *)channel, intr_xname); 392#endif 393 } 394 395 zsc->zsc_si = softint_establish(SOFTINT_SERIAL, 396 (void (*)(void *)) zsc_intr_soft, zsc); 397 398 /* 399 * Set the master interrupt enable and interrupt vector. 400 * (common to both channels, do it on A) 401 */ 402 cs = zsc->zsc_cs[0]; 403 s = splzs(); 404 /* interrupt vector */ 405 zs_write_reg(cs, 2, zs_init_reg[2]); 406 /* master interrupt control (enable) */ 407 zs_write_reg(cs, 9, zs_init_reg[9]); 408 splx(s); 409} 410 411static int 412zsc_print(void *aux, const char *name) 413{ 414 struct zsc_attach_args *args = aux; 415 416 if (name != NULL) 417 aprint_normal("%s: ", name); 418 419 if (args->channel != -1) 420 aprint_normal(" channel %d", args->channel); 421 422 return UNCONF; 423} 424 425int 426zsmdioctl(struct zs_chanstate *cs, u_long cmd, void *data) 427{ 428 switch (cmd) { 429 default: 430 return (EPASSTHROUGH); 431 } 432 return (0); 433} 434 435void 436zsmd_setclock(struct zs_chanstate *cs) 437{ 438#ifdef NOTYET 439 struct xzs_chanstate *xcs = (void *)cs; 440 441 if (cs->cs_channel != 0) 442 return; 443 444 /* 445 * If the new clock has the external bit set, then select the 446 * external source. 447 */ 448 via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0); 449#endif 450} 451 452int 453zshard(void *arg) 454{ 455 struct zsc_softc *zsc; 456 int rval; 457 458 zsc = arg; 459 rval = zsc_intr_hard(zsc); 460 if ((zsc->zsc_cs[0]->cs_softreq) || (zsc->zsc_cs[1]->cs_softreq)) 461 softint_schedule(zsc->zsc_si); 462 463 return rval; 464} 465 466#ifdef ZS_TXDMA 467int 468zs_txdma_int(void *arg) 469{ 470 int ch = (int)arg; 471 struct zsc_softc *zsc; 472 struct zs_chanstate *cs; 473 474 zsc = device_lookup_private(&zsc_cd, ch); 475 if (zsc == NULL) 476 panic("zs_txdma_int"); 477 478 cs = zsc->zsc_cs[ch]; 479 zstty_txdma_int(cs); 480 481 if (cs->cs_softreq) 482 softint_schedule(zsc->zsc_si); 483 484 return 1; 485} 486 487void 488zs_dma_setup(struct zs_chanstate *cs, void *pa, int len) 489{ 490 struct zsc_softc *zsc; 491 dbdma_command_t *cmdp; 492 int ch = cs->cs_channel; 493 494 zsc = device_lookup_private(&zsc_cd, ch); 495 cmdp = zsc->zsc_txdmacmd[ch]; 496 497 DBDMA_BUILD(cmdp, DBDMA_CMD_OUT_LAST, 0, len, kvtop(pa), 498 DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 499 cmdp++; 500 DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0, 501 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 502 503 __asm volatile("eieio"); 504 505 dbdma_start(zsc->zsc_txdmareg[ch], zsc->zsc_txdmacmd[ch]); 506} 507#endif 508 509/* 510 * Compute the current baud rate given a ZS channel. 511 * XXX Assume internal BRG. 512 */ 513int 514zs_get_speed(struct zs_chanstate *cs) 515{ 516 int tconst; 517 518 tconst = zs_read_reg(cs, 12); 519 tconst |= zs_read_reg(cs, 13) << 8; 520 return TCONST_TO_BPS(cs->cs_brg_clk, tconst); 521} 522 523#ifndef ZS_TOLERANCE 524#define ZS_TOLERANCE 51 525/* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */ 526#endif 527 528/* 529 * Search through the signal sources in the channel, and 530 * pick the best one for the baud rate requested. Return 531 * a -1 if not achievable in tolerance. Otherwise return 0 532 * and fill in the values. 533 * 534 * This routine draws inspiration from the Atari port's zs.c 535 * driver in NetBSD 1.1 which did the same type of source switching. 536 * Tolerance code inspired by comspeed routine in isa/com.c. 537 * 538 * By Bill Studenmund, 1996-05-12 539 */ 540int 541zs_set_speed(struct zs_chanstate *cs, int bps) 542{ 543 struct xzs_chanstate *xcs = (void *) cs; 544 int i, tc, tc0 = 0, tc1, s, sf = 0; 545 int src, rate0, rate1, err, tol; 546 547 if (bps == 0) 548 return (0); 549 550 src = -1; /* no valid source yet */ 551 tol = ZS_TOLERANCE; 552 553 /* 554 * Step through all the sources and see which one matches 555 * the best. A source has to match BETTER than tol to be chosen. 556 * Thus if two sources give the same error, the first one will be 557 * chosen. Also, allow for the possability that one source might run 558 * both the BRG and the direct divider (i.e. RTxC). 559 */ 560 for (i = 0; i < xcs->cs_clock_count; i++) { 561 if (xcs->cs_clocks[i].clk <= 0) 562 continue; /* skip non-existent or bad clocks */ 563 if (xcs->cs_clocks[i].flags & ZSC_BRG) { 564 /* check out BRG at /16 */ 565 tc1 = BPS_TO_TCONST(xcs->cs_clocks[i].clk >> 4, bps); 566 if (tc1 >= 0) { 567 rate1 = TCONST_TO_BPS(xcs->cs_clocks[i].clk >> 4, tc1); 568 err = abs(((rate1 - bps)*1000)/bps); 569 if (err < tol) { 570 tol = err; 571 src = i; 572 sf = xcs->cs_clocks[i].flags & ~ZSC_DIV; 573 tc0 = tc1; 574 rate0 = rate1; 575 } 576 } 577 } 578 if (xcs->cs_clocks[i].flags & ZSC_DIV) { 579 /* 580 * Check out either /1, /16, /32, or /64 581 * Note: for /1, you'd better be using a synchronized 582 * clock! 583 */ 584 int b0 = xcs->cs_clocks[i].clk, e0 = abs(b0-bps); 585 int b1 = b0 >> 4, e1 = abs(b1-bps); 586 int b2 = b1 >> 1, e2 = abs(b2-bps); 587 int b3 = b2 >> 1, e3 = abs(b3-bps); 588 589 if (e0 < e1 && e0 < e2 && e0 < e3) { 590 err = e0; 591 rate1 = b0; 592 tc1 = ZSWR4_CLK_X1; 593 } else if (e0 > e1 && e1 < e2 && e1 < e3) { 594 err = e1; 595 rate1 = b1; 596 tc1 = ZSWR4_CLK_X16; 597 } else if (e0 > e2 && e1 > e2 && e2 < e3) { 598 err = e2; 599 rate1 = b2; 600 tc1 = ZSWR4_CLK_X32; 601 } else { 602 err = e3; 603 rate1 = b3; 604 tc1 = ZSWR4_CLK_X64; 605 } 606 607 err = (err * 1000)/bps; 608 if (err < tol) { 609 tol = err; 610 src = i; 611 sf = xcs->cs_clocks[i].flags & ~ZSC_BRG; 612 tc0 = tc1; 613 rate0 = rate1; 614 } 615 } 616 } 617#ifdef ZSMACDEBUG 618 zsprintf("Checking for rate %d. Found source #%d.\n",bps, src); 619#endif 620 if (src == -1) 621 return (EINVAL); /* no can do */ 622 623 /* 624 * The M.I. layer likes to keep cs_brg_clk current, even though 625 * we are the only ones who should be touching the BRG's rate. 626 * 627 * Note: we are assuming that any ZSC_EXTERN signal source comes in 628 * on the RTxC pin. Correct for the mac68k obio zsc. 629 */ 630 if (sf & ZSC_EXTERN) 631 cs->cs_brg_clk = xcs->cs_clocks[i].clk >> 4; 632 else 633 cs->cs_brg_clk = PCLK / 16; 634 635 /* 636 * Now we have a source, so set it up. 637 */ 638 s = splzs(); 639 xcs->cs_psource = src; 640 xcs->cs_pclk_flag = sf; 641 bps = rate0; 642 if (sf & ZSC_BRG) { 643 cs->cs_preg[4] = ZSWR4_CLK_X16; 644 cs->cs_preg[11]= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD; 645 if (sf & ZSC_PCLK) { 646 cs->cs_preg[14] = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK; 647 } else { 648 cs->cs_preg[14] = ZSWR14_BAUD_ENA; 649 } 650 tc = tc0; 651 } else { 652 cs->cs_preg[4] = tc0; 653 if (sf & ZSC_RTXDIV) { 654 cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC; 655 } else { 656 cs->cs_preg[11] = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC; 657 } 658 cs->cs_preg[14]= 0; 659 tc = 0xffff; 660 } 661 /* Set the BAUD rate divisor. */ 662 cs->cs_preg[12] = tc; 663 cs->cs_preg[13] = tc >> 8; 664 splx(s); 665 666#ifdef ZSMACDEBUG 667 zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \ 668 bps, tc, src, sf); 669 zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n", 670 cs->cs_preg[4], cs->cs_preg[11], cs->cs_preg[14]); 671#endif 672 673 cs->cs_preg[5] |= ZSWR5_RTS; /* Make sure the drivers are on! */ 674 675 /* Caller will stuff the pending registers. */ 676 return (0); 677} 678 679int 680zs_set_modes(struct zs_chanstate *cs, int cflag) 681{ 682 struct xzs_chanstate *xcs = (void*)cs; 683 int s; 684 685 /* 686 * Make sure we don't enable hfc on a signal line we're ignoring. 687 * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS, 688 * this code also effectivly turns off ZSWR15_CTS_IE. 689 * 690 * Also, disable DCD interrupts if we've been told to ignore 691 * the DCD pin. Happens on mac68k because the input line for 692 * DCD can also be used as a clock input. (Just set CLOCAL.) 693 * 694 * If someone tries to turn an invalid flow mode on, Just Say No 695 * (Suggested by gwr) 696 */ 697 if ((cflag & CDTRCTS) && (cflag & (CRTSCTS | MDMBUF))) 698 return (EINVAL); 699 if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) { 700 if (cflag & MDMBUF) 701 return (EINVAL); 702 cflag |= CLOCAL; 703 } 704 if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & (CRTSCTS | CDTRCTS))) 705 return (EINVAL); 706 707 /* 708 * Output hardware flow control on the chip is horrendous: 709 * if carrier detect drops, the receiver is disabled, and if 710 * CTS drops, the transmitter is stoped IN MID CHARACTER! 711 * Therefore, NEVER set the HFC bit, and instead use the 712 * status interrupt to detect CTS changes. 713 */ 714 s = splzs(); 715 if ((cflag & (CLOCAL | MDMBUF)) != 0) 716 cs->cs_rr0_dcd = 0; 717 else 718 cs->cs_rr0_dcd = ZSRR0_DCD; 719 /* 720 * The mac hardware only has one output, DTR (HSKo in Mac 721 * parlance). In HFC mode, we use it for the functions 722 * typically served by RTS and DTR on other ports, so we 723 * have to fake the upper layer out some. 724 * 725 * CRTSCTS we use CTS as an input which tells us when to shut up. 726 * We make no effort to shut up the other side of the connection. 727 * DTR is used to hang up the modem. 728 * 729 * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to 730 * shut up the other side. 731 */ 732 if ((cflag & CRTSCTS) != 0) { 733 cs->cs_wr5_dtr = ZSWR5_DTR; 734 cs->cs_wr5_rts = 0; 735 cs->cs_rr0_cts = ZSRR0_CTS; 736 } else if ((cflag & CDTRCTS) != 0) { 737 cs->cs_wr5_dtr = 0; 738 cs->cs_wr5_rts = ZSWR5_DTR; 739 cs->cs_rr0_cts = ZSRR0_CTS; 740 } else if ((cflag & MDMBUF) != 0) { 741 cs->cs_wr5_dtr = 0; 742 cs->cs_wr5_rts = ZSWR5_DTR; 743 cs->cs_rr0_cts = ZSRR0_DCD; 744 } else { 745 cs->cs_wr5_dtr = ZSWR5_DTR; 746 cs->cs_wr5_rts = 0; 747 cs->cs_rr0_cts = 0; 748 } 749 splx(s); 750 751 /* Caller will stuff the pending registers. */ 752 return (0); 753} 754 755 756/* 757 * Read or write the chip with suitable delays. 758 * MacII hardware has the delay built in. 759 * No need for extra delay. :-) However, some clock-chirped 760 * macs, or zsc's on serial add-on boards might need it. 761 */ 762#define ZS_DELAY() 763 764uint8_t 765zs_read_reg(struct zs_chanstate *cs, uint8_t reg) 766{ 767 uint8_t val; 768 769 out8(cs->cs_reg_csr, reg); 770 ZS_DELAY(); 771 val = in8(cs->cs_reg_csr); 772 ZS_DELAY(); 773 return val; 774} 775 776void 777zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val) 778{ 779 out8(cs->cs_reg_csr, reg); 780 ZS_DELAY(); 781 out8(cs->cs_reg_csr, val); 782 ZS_DELAY(); 783} 784 785uint8_t 786zs_read_csr(struct zs_chanstate *cs) 787{ 788 uint8_t val; 789 790 val = in8(cs->cs_reg_csr); 791 ZS_DELAY(); 792 /* make up for the fact CTS is wired backwards */ 793 val ^= ZSRR0_CTS; 794 return val; 795} 796 797void 798zs_write_csr(struct zs_chanstate *cs, uint8_t val) 799{ 800 /* Note, the csr does not write CTS... */ 801 out8(cs->cs_reg_csr, val); 802 ZS_DELAY(); 803} 804 805uint8_t 806zs_read_data(struct zs_chanstate *cs) 807{ 808 uint8_t val; 809 810 val = in8(cs->cs_reg_data); 811 ZS_DELAY(); 812 return val; 813} 814 815void 816zs_write_data(struct zs_chanstate *cs, uint8_t val) 817{ 818 out8(cs->cs_reg_data, val); 819 ZS_DELAY(); 820} 821 822/**************************************************************** 823 * Console support functions (powermac specific!) 824 * Note: this code is allowed to know about the layout of 825 * the chip registers, and uses that to keep things simple. 826 * XXX - I think I like the mvme167 code better. -gwr 827 * XXX - Well :-P :-) -wrs 828 ****************************************************************/ 829 830#define zscnpollc nullcnpollc 831cons_decl(zs); 832 833static int stdin, stdout; 834 835/* 836 * Console functions. 837 */ 838 839/* 840 * zscnprobe is the routine which gets called as the kernel is trying to 841 * figure out where the console should be. Each io driver which might 842 * be the console (as defined in mac68k/conf.c) gets probed. The probe 843 * fills in the consdev structure. Important parts are the device #, 844 * and the console priority. Values are CN_DEAD (don't touch me), 845 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL 846 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!) 847 * 848 * As the mac's a bit different, we do extra work here. We mainly check 849 * to see if we have serial echo going on. Also chould check for default 850 * speeds. 851 */ 852 853/* 854 * Polled input char. 855 */ 856int 857zs_getc(void *v) 858{ 859 volatile struct zschan *zc = v; 860 int s, c, rr0; 861 862 s = splhigh(); 863 /* Wait for a character to arrive. */ 864 do { 865 rr0 = in8(&zc->zc_csr); 866 ZS_DELAY(); 867 } while ((rr0 & ZSRR0_RX_READY) == 0); 868 869 c = in8(&zc->zc_data); 870 ZS_DELAY(); 871 splx(s); 872 873 /* 874 * This is used by the kd driver to read scan codes, 875 * so don't translate '\r' ==> '\n' here... 876 */ 877 return (c); 878} 879 880/* 881 * Polled output char. 882 */ 883void 884zs_putc(void *v, int c) 885{ 886 volatile struct zschan *zc = v; 887 int s, rr0; 888 long wait = 0; 889 890 s = splhigh(); 891 /* Wait for transmitter to become ready. */ 892 do { 893 rr0 = in8(&zc->zc_csr); 894 ZS_DELAY(); 895 } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000)); 896 897 if ((rr0 & ZSRR0_TX_READY) != 0) { 898 out8(&zc->zc_data, c); 899 ZS_DELAY(); 900 } 901 splx(s); 902} 903 904 905/* 906 * Polled console input putchar. 907 */ 908int 909zscngetc(dev_t dev) 910{ 911 volatile struct zschan *zc = zs_conschan; 912 int c; 913 914 if (zc) { 915 c = zs_getc(__UNVOLATILE(zc)); 916 } else { 917 char ch = 0; 918 OF_read(stdin, &ch, 1); 919 c = ch; 920 } 921 return c; 922} 923 924/* 925 * Polled console output putchar. 926 */ 927void 928zscnputc(dev_t dev, int c) 929{ 930 volatile struct zschan *zc = zs_conschan; 931 932 if (zc) { 933 zs_putc(__UNVOLATILE(zc), c); 934 } else { 935 char ch = c; 936 OF_write(stdout, &ch, 1); 937 } 938} 939 940/* 941 * Handle user request to enter kernel debugger. 942 */ 943void 944zs_abort(struct zs_chanstate *cs) 945{ 946 volatile struct zschan *zc = zs_conschan; 947 int rr0; 948 long wait = 0; 949 950 if (zs_cons_canabort == 0) 951 return; 952 953 /* Wait for end of break to avoid PROM abort. */ 954 do { 955 rr0 = in8(&zc->zc_csr); 956 ZS_DELAY(); 957 } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY)); 958 959 if (wait > ZSABORT_DELAY) { 960 zs_cons_canabort = 0; 961 /* If we time out, turn off the abort ability! */ 962 } 963 964#if defined(KGDB) 965 kgdb_connect(1); 966#elif defined(DDB) 967 Debugger(); 968#endif 969} 970 971extern int ofccngetc(dev_t); 972extern void ofccnputc(dev_t, int); 973 974struct consdev consdev_zs = { 975 zscnprobe, 976 zscninit, 977 zscngetc, 978 zscnputc, 979 zscnpollc, 980}; 981 982void 983zscnprobe(struct consdev *cp) 984{ 985 int chosen, pkg; 986 char name[16]; 987 988 if ((chosen = OF_finddevice("/chosen")) == -1) 989 return; 990 991 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) 992 return; 993 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) 994 return; 995 996 if ((pkg = OF_instance_to_package(stdin)) == -1) 997 return; 998 999 memset(name, 0, sizeof(name)); 1000 if (OF_getprop(pkg, "device_type", name, sizeof(name)) == -1) 1001 return; 1002 1003 if (strcmp(name, "serial") != 0) 1004 return; 1005 1006 memset(name, 0, sizeof(name)); 1007 if (OF_getprop(pkg, "name", name, sizeof(name)) == -1) 1008 return; 1009 1010 cp->cn_pri = CN_REMOTE; 1011} 1012 1013void 1014zscninit(struct consdev *cp) 1015{ 1016 int escc, escc_ch, obio, zs_offset; 1017 u_int32_t reg[5]; 1018 char name[16]; 1019 1020 if ((escc_ch = OF_instance_to_package(stdin)) == -1) 1021 return; 1022 1023 memset(name, 0, sizeof(name)); 1024 if (OF_getprop(escc_ch, "name", name, sizeof(name)) == -1) 1025 return; 1026 1027 zs_conschannel = strcmp(name, "ch-b") == 0; 1028 1029 if (OF_getprop(escc_ch, "reg", reg, sizeof(reg)) < 4) 1030 return; 1031 zs_offset = reg[0]; 1032 1033 escc = OF_parent(escc_ch); 1034 obio = OF_parent(escc); 1035 1036 if (OF_getprop(obio, "assigned-addresses", reg, sizeof(reg)) < 12) 1037 return; 1038 zs_conschan = (void *)(reg[2] + zs_offset); 1039} 1040