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