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