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