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