zs.c revision 1.37
1/* $NetBSD: zs.c,v 1.37 2006/08/15 01:53:26 macallan 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.37 2006/08/15 01:53:26 macallan 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/* 92 * Some warts needed by z8530tty.c - 93 */ 94int zs_def_cflag = (CREAD | CS8 | HUPCL); 95 96/* 97 * abort detection on console will now timeout after iterating on a loop 98 * the following # of times. Cheep hack. Also, abort detection is turned 99 * off after a timeout (i.e. maybe there's not a terminal hooked up). 100 */ 101#define ZSABORT_DELAY 3000000 102 103struct zsdevice { 104 /* Yes, they are backwards. */ 105 struct zschan zs_chan_b; 106 struct zschan zs_chan_a; 107}; 108 109static int zs_defspeed[2] = { 110 38400, /* ttyZ0 */ 111 38400, /* ttyZ1 */ 112}; 113 114/* console stuff */ 115void *zs_conschan = 0; 116int zs_conschannel = -1; 117#ifdef ZS_CONSOLE_ABORT 118int zs_cons_canabort = 1; 119#else 120int zs_cons_canabort = 0; 121#endif /* ZS_CONSOLE_ABORT*/ 122 123/* device to which the console is attached--if serial. */ 124/* Mac stuff */ 125 126static int zs_get_speed(struct zs_chanstate *); 127 128/* 129 * Even though zsparam will set up the clock multiples, etc., we 130 * still set them here as: 1) mice & keyboards don't use zsparam, 131 * and 2) the console stuff uses these defaults before device 132 * attach. 133 */ 134 135static u_char zs_init_reg[16] = { 136 0, /* 0: CMD (reset, etc.) */ 137 0, /* 1: No interrupts yet. */ 138 0, /* IVECT */ 139 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 140 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 141 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 142 0, /* 6: TXSYNC/SYNCLO */ 143 0, /* 7: RXSYNC/SYNCHI */ 144 0, /* 8: alias for data port */ 145 ZSWR9_MASTER_IE, 146 0, /*10: Misc. TX/RX control bits */ 147 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 148 ((PCLK/32)/38400)-2, /*12: BAUDLO (default=38400) */ 149 0, /*13: BAUDHI (default=38400) */ 150 ZSWR14_BAUD_ENA, 151 ZSWR15_BREAK_IE, 152}; 153 154/**************************************************************** 155 * Autoconfig 156 ****************************************************************/ 157 158/* Definition of the driver for autoconfig. */ 159static int zsc_match(struct device *, struct cfdata *, void *); 160static void zsc_attach(struct device *, struct device *, void *); 161static int zsc_print(void *, const char *); 162 163CFATTACH_DECL(zsc, sizeof(struct zsc_softc), 164 zsc_match, zsc_attach, NULL, NULL); 165 166extern struct cfdriver zsc_cd; 167 168int zsc_attached; 169 170int zshard(void *); 171int zssoft(void *); 172#ifdef ZS_TXDMA 173static int zs_txdma_int(void *); 174#endif 175 176void zscnprobe(struct consdev *); 177void zscninit(struct consdev *); 178int zscngetc(dev_t); 179void zscnputc(dev_t, int); 180void zscnpollc(dev_t, int); 181 182/* 183 * Is the zs chip present? 184 */ 185static int 186zsc_match(struct device *parent, struct cfdata *cf, void *aux) 187{ 188 struct confargs *ca = aux; 189 190 if (strcmp(ca->ca_name, "escc") != 0) 191 return 0; 192 193 if (zsc_attached) 194 return 0; 195 196 return 1; 197} 198 199/* 200 * Attach a found zs. 201 * 202 * Match slave number to zs unit number, so that misconfiguration will 203 * not set up the keyboard as ttya, etc. 204 */ 205static void 206zsc_attach(struct device *parent, struct device *self, void *aux) 207{ 208 struct zsc_softc *zsc = (void *)self; 209 struct confargs *ca = aux; 210 struct zsc_attach_args zsc_args; 211 volatile struct zschan *zc; 212 struct xzs_chanstate *xcs; 213 struct zs_chanstate *cs; 214 struct zsdevice *zsd; 215 int channel; 216 int s, chip, theflags; 217 int node, intr[2][3]; 218 u_int regs[6]; 219 220 zsc_attached = 1; 221 222 chip = 0; 223 ca->ca_reg[0] += ca->ca_baseaddr; 224 zsd = mapiodev(ca->ca_reg[0], ca->ca_reg[1]); 225 226 node = OF_child(ca->ca_node); /* ch-a */ 227 228 for (channel = 0; channel < 2; channel++) { 229 if (OF_getprop(node, "AAPL,interrupts", 230 intr[channel], sizeof(intr[0])) == -1 && 231 OF_getprop(node, "interrupts", 232 intr[channel], sizeof(intr[0])) == -1) { 233 printf(": cannot find interrupt property\n"); 234 return; 235 } 236 237 if (OF_getprop(node, "reg", regs, sizeof(regs)) < 24) { 238 printf(": cannot find reg property\n"); 239 return; 240 } 241 regs[2] += ca->ca_baseaddr; 242 regs[4] += ca->ca_baseaddr; 243#ifdef ZS_TXDMA 244 zsc->zsc_txdmareg[channel] = mapiodev(regs[2], regs[3]); 245 zsc->zsc_txdmacmd[channel] = 246 dbdma_alloc(sizeof(dbdma_command_t) * 3); 247 memset(zsc->zsc_txdmacmd[channel], 0, 248 sizeof(dbdma_command_t) * 3); 249 dbdma_reset(zsc->zsc_txdmareg[channel]); 250#endif 251 node = OF_peer(node); /* ch-b */ 252 } 253 254 printf(": irq %d,%d\n", intr[0][0], intr[1][0]); 255 256 /* 257 * Initialize software state for each channel. 258 */ 259 for (channel = 0; channel < 2; channel++) { 260 zsc_args.channel = channel; 261 zsc_args.hwflags = (channel == zs_conschannel ? 262 ZS_HWFLAG_CONSOLE : 0); 263 xcs = &zsc->xzsc_xcs_store[channel]; 264 cs = &xcs->xzs_cs; 265 zsc->zsc_cs[channel] = cs; 266 267 simple_lock_init(&cs->cs_lock); 268 cs->cs_channel = channel; 269 cs->cs_private = NULL; 270 cs->cs_ops = &zsops_null; 271 272 zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b; 273 274 cs->cs_reg_csr = &zc->zc_csr; 275 cs->cs_reg_data = &zc->zc_data; 276 277 memcpy(cs->cs_creg, zs_init_reg, 16); 278 memcpy(cs->cs_preg, zs_init_reg, 16); 279 280 /* Current BAUD rate generator clock. */ 281 cs->cs_brg_clk = PCLK / 16; /* RTxC is 230400*16, so use 230400 */ 282 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) 283 cs->cs_defspeed = zs_get_speed(cs); 284 else 285 cs->cs_defspeed = zs_defspeed[channel]; 286 cs->cs_defcflag = zs_def_cflag; 287 288 /* Make these correspond to cs_defcflag (-crtscts) */ 289 cs->cs_rr0_dcd = ZSRR0_DCD; 290 cs->cs_rr0_cts = 0; 291 cs->cs_wr5_dtr = ZSWR5_DTR; 292 cs->cs_wr5_rts = 0; 293 294#ifdef __notyet__ 295 cs->cs_slave_type = ZS_SLAVE_NONE; 296#endif 297 298 /* Define BAUD rate stuff. */ 299 xcs->cs_clocks[0].clk = PCLK; 300 xcs->cs_clocks[0].flags = ZSC_RTXBRG | ZSC_RTXDIV; 301 xcs->cs_clocks[1].flags = 302 ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN; 303 xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE; 304 xcs->cs_clock_count = 3; 305 if (channel == 0) { 306 theflags = 0; /*mac68k_machine.modem_flags;*/ 307 /*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/ 308 /*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/ 309 xcs->cs_clocks[1].clk = 0; 310 xcs->cs_clocks[2].clk = 0; 311 } else { 312 theflags = 0; /*mac68k_machine.print_flags;*/ 313 xcs->cs_clocks[1].flags = ZSC_VARIABLE; 314 /* 315 * Yes, we aren't defining ANY clock source enables for the 316 * printer's DCD clock in. The hardware won't let us 317 * use it. But a clock will freak out the chip, so we 318 * let you set it, telling us to bar interrupts on the line. 319 */ 320 /*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/ 321 /*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/ 322 xcs->cs_clocks[1].clk = 0; 323 xcs->cs_clocks[2].clk = 0; 324 } 325 if (xcs->cs_clocks[1].clk) 326 zsc_args.hwflags |= ZS_HWFLAG_NO_DCD; 327 if (xcs->cs_clocks[2].clk) 328 zsc_args.hwflags |= ZS_HWFLAG_NO_CTS; 329 330 /* Set defaults in our "extended" chanstate. */ 331 xcs->cs_csource = 0; 332 xcs->cs_psource = 0; 333 xcs->cs_cclk_flag = 0; /* Nothing fancy by default */ 334 xcs->cs_pclk_flag = 0; 335 336 if (theflags & ZSMAC_RAW) { 337 zsc_args.hwflags |= ZS_HWFLAG_RAW; 338 printf(" (raw defaults)"); 339 } 340 341 /* 342 * XXX - This might be better done with a "stub" driver 343 * (to replace zstty) that ignores LocalTalk for now. 344 */ 345 if (theflags & ZSMAC_LOCALTALK) { 346 printf(" shielding from LocalTalk"); 347 cs->cs_defspeed = 1; 348 cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff; 349 cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff; 350 zs_write_reg(cs, ZSRR_BAUDLO, 0xff); 351 zs_write_reg(cs, ZSRR_BAUDHI, 0xff); 352 /* 353 * If we might have LocalTalk, then make sure we have the 354 * Baud rate low-enough to not do any damage. 355 */ 356 } 357 358 /* 359 * We used to disable chip interrupts here, but we now 360 * do that in zscnprobe, just in case MacOS left the chip on. 361 */ 362 363 xcs->cs_chip = chip; 364 365 /* Stash away a copy of the final H/W flags. */ 366 xcs->cs_hwflags = zsc_args.hwflags; 367 368 /* 369 * Look for a child driver for this channel. 370 * The child attach will setup the hardware. 371 */ 372 if (!config_found(self, (void *)&zsc_args, zsc_print)) { 373 /* No sub-driver. Just reset it. */ 374 u_char reset = (channel == 0) ? 375 ZSWR9_A_RESET : ZSWR9_B_RESET; 376 s = splzs(); 377 zs_write_reg(cs, 9, reset); 378 splx(s); 379 } 380 } 381 382 /* XXX - Now safe to install interrupt handlers. */ 383 intr_establish(intr[0][0], IST_LEVEL, IPL_TTY, zshard, NULL); 384 intr_establish(intr[1][0], IST_LEVEL, IPL_TTY, zshard, NULL); 385#ifdef ZS_TXDMA 386 intr_establish(intr[0][1], IST_LEVEL, IPL_TTY, zs_txdma_int, (void *)0); 387 intr_establish(intr[1][1], IST_LEVEL, IPL_TTY, zs_txdma_int, (void *)1); 388#endif 389 390#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 391 zsc->zsc_si = softintr_establish(IPL_SOFTSERIAL, 392 (void (*)(void *)) zsc_intr_soft, zsc); 393#endif 394 395 /* 396 * Set the master interrupt enable and interrupt vector. 397 * (common to both channels, do it on A) 398 */ 399 cs = zsc->zsc_cs[0]; 400 s = splzs(); 401 /* interrupt vector */ 402 zs_write_reg(cs, 2, zs_init_reg[2]); 403 /* master interrupt control (enable) */ 404 zs_write_reg(cs, 9, zs_init_reg[9]); 405 splx(s); 406} 407 408static int 409zsc_print(void *aux, const char *name) 410{ 411 struct zsc_attach_args *args = aux; 412 413 if (name != NULL) 414 aprint_normal("%s: ", name); 415 416 if (args->channel != -1) 417 aprint_normal(" channel %d", args->channel); 418 419 return UNCONF; 420} 421 422int 423zsmdioctl(struct zs_chanstate *cs, u_long cmd, caddr_t data) 424{ 425 switch (cmd) { 426 default: 427 return (EPASSTHROUGH); 428 } 429 return (0); 430} 431 432void 433zsmd_setclock(struct zs_chanstate *cs) 434{ 435#ifdef NOTYET 436 struct xzs_chanstate *xcs = (void *)cs; 437 438 if (cs->cs_channel != 0) 439 return; 440 441 /* 442 * If the new clock has the external bit set, then select the 443 * external source. 444 */ 445 via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0); 446#endif 447} 448 449#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 450static int zssoftpending; 451#endif 452 453/* 454 * Our ZS chips all share a common, autovectored interrupt, 455 * so we have to look at all of them on each interrupt. 456 */ 457int 458zshard(void *arg) 459{ 460 struct zsc_softc *zsc; 461 int unit, rval; 462 463 rval = 0; 464 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 465 zsc = zsc_cd.cd_devs[unit]; 466 if (zsc == NULL) 467 continue; 468 rval |= zsc_intr_hard(zsc); 469 if ((zsc->zsc_cs[0]->cs_softreq) || 470 (zsc->zsc_cs[1]->cs_softreq)) 471 { 472#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 473 softintr_schedule(zsc->zsc_si); 474#else 475 /* zsc_req_softint(zsc); */ 476 /* We are at splzs here, so no need to lock. */ 477 if (zssoftpending == 0) { 478 zssoftpending = 1; 479 setsoftserial(); 480 } 481#endif 482 } 483 } 484 return (rval); 485} 486 487#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 488/* 489 * Similar scheme as for zshard (look at all of them) 490 */ 491int 492zssoft(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#endif 516 517#ifdef ZS_TXDMA 518int 519zs_txdma_int(void *arg) 520{ 521 int ch = (int)arg; 522 struct zsc_softc *zsc; 523 struct zs_chanstate *cs; 524 int unit = 0; /* XXX */ 525 526 zsc = zsc_cd.cd_devs[unit]; 527 if (zsc == NULL) 528 panic("zs_txdma_int"); 529 530 cs = zsc->zsc_cs[ch]; 531 zstty_txdma_int(cs); 532 533 if (cs->cs_softreq) { 534#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 535 softintr_schedule(zsc->zsc_si); 536#else 537 if (zssoftpending == 0) { 538 zssoftpending = 1; 539 setsoftserial(); 540 } 541#endif 542 } 543 return 1; 544} 545 546void 547zs_dma_setup(struct zs_chanstate *cs, caddr_t pa, 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 */ 572int 573zs_get_speed(struct zs_chanstate *cs) 574{ 575 int tconst; 576 577 tconst = zs_read_reg(cs, 12); 578 tconst |= zs_read_reg(cs, 13) << 8; 579 return TCONST_TO_BPS(cs->cs_brg_clk, tconst); 580} 581 582#ifndef ZS_TOLERANCE 583#define ZS_TOLERANCE 51 584/* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */ 585#endif 586 587/* 588 * Search through the signal sources in the channel, and 589 * pick the best one for the baud rate requested. Return 590 * a -1 if not achievable in tolerance. Otherwise return 0 591 * and fill in the values. 592 * 593 * This routine draws inspiration from the Atari port's zs.c 594 * driver in NetBSD 1.1 which did the same type of source switching. 595 * Tolerance code inspired by comspeed routine in isa/com.c. 596 * 597 * By Bill Studenmund, 1996-05-12 598 */ 599int 600zs_set_speed(struct zs_chanstate *cs, int bps) 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 zsprintf("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 zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \ 727 bps, tc, src, sf); 728 zsprintf("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 738int 739zs_set_modes(struct zs_chanstate *cs, int cflag) 740{ 741 struct xzs_chanstate *xcs = (void*)cs; 742 int s; 743 744 /* 745 * Make sure we don't enable hfc on a signal line we're ignoring. 746 * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS, 747 * this code also effectivly turns off ZSWR15_CTS_IE. 748 * 749 * Also, disable DCD interrupts if we've been told to ignore 750 * the DCD pin. Happens on mac68k because the input line for 751 * DCD can also be used as a clock input. (Just set CLOCAL.) 752 * 753 * If someone tries to turn an invalid flow mode on, Just Say No 754 * (Suggested by gwr) 755 */ 756 if ((cflag & CDTRCTS) && (cflag & (CRTSCTS | MDMBUF))) 757 return (EINVAL); 758 if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) { 759 if (cflag & MDMBUF) 760 return (EINVAL); 761 cflag |= CLOCAL; 762 } 763 if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & (CRTSCTS | CDTRCTS))) 764 return (EINVAL); 765 766 /* 767 * Output hardware flow control on the chip is horrendous: 768 * if carrier detect drops, the receiver is disabled, and if 769 * CTS drops, the transmitter is stoped IN MID CHARACTER! 770 * Therefore, NEVER set the HFC bit, and instead use the 771 * status interrupt to detect CTS changes. 772 */ 773 s = splzs(); 774 if ((cflag & (CLOCAL | MDMBUF)) != 0) 775 cs->cs_rr0_dcd = 0; 776 else 777 cs->cs_rr0_dcd = ZSRR0_DCD; 778 /* 779 * The mac hardware only has one output, DTR (HSKo in Mac 780 * parlance). In HFC mode, we use it for the functions 781 * typically served by RTS and DTR on other ports, so we 782 * have to fake the upper layer out some. 783 * 784 * CRTSCTS we use CTS as an input which tells us when to shut up. 785 * We make no effort to shut up the other side of the connection. 786 * DTR is used to hang up the modem. 787 * 788 * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to 789 * shut up the other side. 790 */ 791 if ((cflag & CRTSCTS) != 0) { 792 cs->cs_wr5_dtr = ZSWR5_DTR; 793 cs->cs_wr5_rts = 0; 794 cs->cs_rr0_cts = ZSRR0_CTS; 795 } else if ((cflag & CDTRCTS) != 0) { 796 cs->cs_wr5_dtr = 0; 797 cs->cs_wr5_rts = ZSWR5_DTR; 798 cs->cs_rr0_cts = ZSRR0_CTS; 799 } else if ((cflag & MDMBUF) != 0) { 800 cs->cs_wr5_dtr = 0; 801 cs->cs_wr5_rts = ZSWR5_DTR; 802 cs->cs_rr0_cts = ZSRR0_DCD; 803 } else { 804 cs->cs_wr5_dtr = ZSWR5_DTR; 805 cs->cs_wr5_rts = 0; 806 cs->cs_rr0_cts = 0; 807 } 808 splx(s); 809 810 /* Caller will stuff the pending registers. */ 811 return (0); 812} 813 814 815/* 816 * Read or write the chip with suitable delays. 817 * MacII hardware has the delay built in. 818 * No need for extra delay. :-) However, some clock-chirped 819 * macs, or zsc's on serial add-on boards might need it. 820 */ 821#define ZS_DELAY() 822 823u_char 824zs_read_reg(struct zs_chanstate *cs, u_char reg) 825{ 826 u_char val; 827 828 out8(cs->cs_reg_csr, reg); 829 ZS_DELAY(); 830 val = in8(cs->cs_reg_csr); 831 ZS_DELAY(); 832 return val; 833} 834 835void 836zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val) 837{ 838 out8(cs->cs_reg_csr, reg); 839 ZS_DELAY(); 840 out8(cs->cs_reg_csr, val); 841 ZS_DELAY(); 842} 843 844u_char 845zs_read_csr(struct zs_chanstate *cs) 846{ 847 u_char val; 848 849 val = in8(cs->cs_reg_csr); 850 ZS_DELAY(); 851 /* make up for the fact CTS is wired backwards */ 852 val ^= ZSRR0_CTS; 853 return val; 854} 855 856void 857zs_write_csr(struct zs_chanstate *cs, u_char val) 858{ 859 /* Note, the csr does not write CTS... */ 860 out8(cs->cs_reg_csr, val); 861 ZS_DELAY(); 862} 863 864u_char 865zs_read_data(struct zs_chanstate *cs) 866{ 867 u_char val; 868 869 val = in8(cs->cs_reg_data); 870 ZS_DELAY(); 871 return val; 872} 873 874void 875zs_write_data(struct zs_chanstate *cs, u_char val) 876{ 877 out8(cs->cs_reg_data, val); 878 ZS_DELAY(); 879} 880 881/**************************************************************** 882 * Console support functions (powermac specific!) 883 * Note: this code is allowed to know about the layout of 884 * the chip registers, and uses that to keep things simple. 885 * XXX - I think I like the mvme167 code better. -gwr 886 * XXX - Well :-P :-) -wrs 887 ****************************************************************/ 888 889#define zscnpollc nullcnpollc 890cons_decl(zs); 891 892static int stdin, stdout; 893 894/* 895 * Console functions. 896 */ 897 898/* 899 * zscnprobe is the routine which gets called as the kernel is trying to 900 * figure out where the console should be. Each io driver which might 901 * be the console (as defined in mac68k/conf.c) gets probed. The probe 902 * fills in the consdev structure. Important parts are the device #, 903 * and the console priority. Values are CN_DEAD (don't touch me), 904 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL 905 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!) 906 * 907 * As the mac's a bit different, we do extra work here. We mainly check 908 * to see if we have serial echo going on. Also chould check for default 909 * speeds. 910 */ 911 912/* 913 * Polled input char. 914 */ 915int 916zs_getc(void *v) 917{ 918 volatile struct zschan *zc = v; 919 int s, c, rr0; 920 921 s = splhigh(); 922 /* Wait for a character to arrive. */ 923 do { 924 rr0 = in8(&zc->zc_csr); 925 ZS_DELAY(); 926 } while ((rr0 & ZSRR0_RX_READY) == 0); 927 928 c = in8(&zc->zc_data); 929 ZS_DELAY(); 930 splx(s); 931 932 /* 933 * This is used by the kd driver to read scan codes, 934 * so don't translate '\r' ==> '\n' here... 935 */ 936 return (c); 937} 938 939/* 940 * Polled output char. 941 */ 942void 943zs_putc(void *v, int c) 944{ 945 volatile struct zschan *zc = v; 946 int s, rr0; 947 long wait = 0; 948 949 s = splhigh(); 950 /* Wait for transmitter to become ready. */ 951 do { 952 rr0 = in8(&zc->zc_csr); 953 ZS_DELAY(); 954 } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000)); 955 956 if ((rr0 & ZSRR0_TX_READY) != 0) { 957 out8(&zc->zc_data, c); 958 ZS_DELAY(); 959 } 960 splx(s); 961} 962 963 964/* 965 * Polled console input putchar. 966 */ 967int 968zscngetc(dev_t dev) 969{ 970 volatile struct zschan *zc = zs_conschan; 971 int c; 972 973 if (zc) { 974 c = zs_getc(__UNVOLATILE(zc)); 975 } else { 976 char ch = 0; 977 OF_read(stdin, &ch, 1); 978 c = ch; 979 } 980 return c; 981} 982 983/* 984 * Polled console output putchar. 985 */ 986void 987zscnputc(dev_t dev, int c) 988{ 989 volatile struct zschan *zc = zs_conschan; 990 991 if (zc) { 992 zs_putc(__UNVOLATILE(zc), c); 993 } else { 994 char ch = c; 995 OF_write(stdout, &ch, 1); 996 } 997} 998 999/* 1000 * Handle user request to enter kernel debugger. 1001 */ 1002void 1003zs_abort(struct zs_chanstate *cs) 1004{ 1005 volatile struct zschan *zc = zs_conschan; 1006 int rr0; 1007 long wait = 0; 1008 1009 if (zs_cons_canabort == 0) 1010 return; 1011 1012 /* Wait for end of break to avoid PROM abort. */ 1013 do { 1014 rr0 = in8(&zc->zc_csr); 1015 ZS_DELAY(); 1016 } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY)); 1017 1018 if (wait > ZSABORT_DELAY) { 1019 zs_cons_canabort = 0; 1020 /* If we time out, turn off the abort ability! */ 1021 } 1022 1023#if defined(KGDB) 1024 kgdb_connect(1); 1025#elif defined(DDB) 1026 Debugger(); 1027#endif 1028} 1029 1030extern int ofccngetc(dev_t); 1031extern void ofccnputc(dev_t, int); 1032 1033struct consdev consdev_zs = { 1034 zscnprobe, 1035 zscninit, 1036 zscngetc, 1037 zscnputc, 1038 zscnpollc, 1039}; 1040 1041void 1042zscnprobe(struct consdev *cp) 1043{ 1044 int chosen, pkg; 1045 char name[16]; 1046 1047 if ((chosen = OF_finddevice("/chosen")) == -1) 1048 return; 1049 1050 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) 1051 return; 1052 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) 1053 return; 1054 1055 if ((pkg = OF_instance_to_package(stdin)) == -1) 1056 return; 1057 1058 memset(name, 0, sizeof(name)); 1059 if (OF_getprop(pkg, "device_type", name, sizeof(name)) == -1) 1060 return; 1061 1062 if (strcmp(name, "serial") != 0) 1063 return; 1064 1065 memset(name, 0, sizeof(name)); 1066 if (OF_getprop(pkg, "name", name, sizeof(name)) == -1) 1067 return; 1068 1069 cp->cn_pri = CN_REMOTE; 1070} 1071 1072void 1073zscninit(struct consdev *cp) 1074{ 1075 int escc, escc_ch, obio, zs_offset; 1076 u_int32_t reg[5]; 1077 char name[16]; 1078 1079 if ((escc_ch = OF_instance_to_package(stdin)) == -1) 1080 return; 1081 1082 memset(name, 0, sizeof(name)); 1083 if (OF_getprop(escc_ch, "name", name, sizeof(name)) == -1) 1084 return; 1085 1086 zs_conschannel = strcmp(name, "ch-b") == 0; 1087 1088 if (OF_getprop(escc_ch, "reg", reg, sizeof(reg)) < 4) 1089 return; 1090 zs_offset = reg[0]; 1091 1092 escc = OF_parent(escc_ch); 1093 obio = OF_parent(escc); 1094 1095 if (OF_getprop(obio, "assigned-addresses", reg, sizeof(reg)) < 12) 1096 return; 1097 zs_conschan = (void *)(reg[2] + zs_offset); 1098} 1099