zs.c revision 1.41
1/* $NetBSD: zs.c,v 1.41 2003/08/07 16:27:02 agc Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratory. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)zs.c 8.1 (Berkeley) 7/19/93 42 */ 43 44/* 45 * Copyright (c) 1995 L. Weppelman (Atari modifications) 46 * 47 * This software was developed by the Computer Systems Engineering group 48 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 49 * contributed to Berkeley. 50 * 51 * 52 * All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Lawrence Berkeley Laboratory. 56 * 57 * Redistribution and use in source and binary forms, with or without 58 * modification, are permitted provided that the following conditions 59 * are met: 60 * 1. Redistributions of source code must retain the above copyright 61 * notice, this list of conditions and the following disclaimer. 62 * 2. Redistributions in binary form must reproduce the above copyright 63 * notice, this list of conditions and the following disclaimer in the 64 * documentation and/or other materials provided with the distribution. 65 * 3. All advertising materials mentioning features or use of this software 66 * must display the following acknowledgement: 67 * This product includes software developed by the University of 68 * California, Berkeley and its contributors. 69 * 4. Neither the name of the University nor the names of its contributors 70 * may be used to endorse or promote products derived from this software 71 * without specific prior written permission. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 74 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 76 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 77 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 79 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 83 * SUCH DAMAGE. 84 * 85 * @(#)zs.c 8.1 (Berkeley) 7/19/93 86 */ 87 88/* 89 * Zilog Z8530 (ZSCC) driver. 90 * 91 * Runs two tty ports (modem2 and serial2) on zs0. 92 * 93 * This driver knows far too much about chip to usage mappings. 94 */ 95 96#include <sys/cdefs.h> 97__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.41 2003/08/07 16:27:02 agc Exp $"); 98 99#include <sys/param.h> 100#include <sys/systm.h> 101#include <sys/proc.h> 102#include <sys/device.h> 103#include <sys/conf.h> 104#include <sys/file.h> 105#include <sys/ioctl.h> 106#include <sys/malloc.h> 107#include <sys/tty.h> 108#include <sys/time.h> 109#include <sys/kernel.h> 110#include <sys/syslog.h> 111 112#include <machine/cpu.h> 113#include <machine/iomap.h> 114#include <machine/scu.h> 115#include <machine/mfp.h> 116#include <atari/dev/ym2149reg.h> 117 118#include <dev/ic/z8530reg.h> 119#include <atari/dev/zsvar.h> 120#include "zs.h" 121#if NZS > 1 122#error "This driver supports only 1 85C30!" 123#endif 124 125#if NZS > 0 126 127#define PCLK (8053976) /* PCLK pin input clock rate */ 128#define PCLK_HD (9600 * 1536) /* PCLK on Hades pin input clock rate */ 129 130#define splzs spl5 131 132/* 133 * Software state per found chip. 134 */ 135struct zs_softc { 136 struct device zi_dev; /* base device */ 137 volatile struct zsdevice *zi_zs; /* chip registers */ 138 struct zs_chanstate zi_cs[2]; /* chan A and B software state */ 139}; 140 141static u_char cb_scheduled = 0; /* Already asked for callback? */ 142/* 143 * Define the registers for a closed port 144 */ 145static u_char zs_init_regs[16] = { 146/* 0 */ 0, 147/* 1 */ 0, 148/* 2 */ 0x60, 149/* 3 */ 0, 150/* 4 */ 0, 151/* 5 */ 0, 152/* 6 */ 0, 153/* 7 */ 0, 154/* 8 */ 0, 155/* 9 */ ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT, 156/* 10 */ ZSWR10_NRZ, 157/* 11 */ ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 158/* 12 */ 0, 159/* 13 */ 0, 160/* 14 */ ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA, 161/* 15 */ 0 162}; 163 164/* 165 * Define the machine dependant clock frequencies 166 * If BRgen feeds sender/receiver we always use a 167 * divisor 16, therefor the division by 16 can as 168 * well be done here. 169 */ 170static u_long zs_freqs_tt[] = { 171 /* 172 * Atari TT, RTxCB is generated by TT-MFP timer C, 173 * which is set to 307.2KHz during initialisation 174 * and never changed afterwards. 175 */ 176 PCLK/16, /* BRgen, PCLK, divisor 16 */ 177 229500, /* BRgen, RTxCA, divisor 16 */ 178 3672000, /* RTxCA, from PCLK4 */ 179 0, /* TRxCA, external */ 180 181 PCLK/16, /* BRgen, PCLK, divisor 16 */ 182 19200, /* BRgen, RTxCB, divisor 16 */ 183 307200, /* RTxCB, from TT-MFP TCO */ 184 2457600 /* TRxCB, from BCLK */ 185}; 186 187static u_long zs_freqs_falcon[] = { 188 /* 189 * Atari Falcon, XXX no specs available, this might be wrong 190 */ 191 PCLK/16, /* BRgen, PCLK, divisor 16 */ 192 229500, /* BRgen, RTxCA, divisor 16 */ 193 3672000, /* RTxCA, ??? */ 194 0, /* TRxCA, external */ 195 196 PCLK/16, /* BRgen, PCLK, divisor 16 */ 197 229500, /* BRgen, RTxCB, divisor 16 */ 198 3672000, /* RTxCB, ??? */ 199 2457600 /* TRxCB, ??? */ 200}; 201 202static u_long zs_freqs_hades[] = { 203 /* 204 * XXX: Channel-A unchecked!!!!! 205 */ 206 PCLK_HD/16, /* BRgen, PCLK, divisor 16 */ 207 229500, /* BRgen, RTxCA, divisor 16 */ 208 3672000, /* RTxCA, from PCLK4 */ 209 0, /* TRxCA, external */ 210 211 PCLK_HD/16, /* BRgen, PCLK, divisor 16 */ 212 235550, /* BRgen, RTxCB, divisor 16 */ 213 3768800, /* RTxCB, 3.7688MHz */ 214 3768800 /* TRxCB, 3.7688MHz */ 215}; 216 217static u_long zs_freqs_generic[] = { 218 /* 219 * other machines, assume only PCLK is available 220 */ 221 PCLK/16, /* BRgen, PCLK, divisor 16 */ 222 0, /* BRgen, RTxCA, divisor 16 */ 223 0, /* RTxCA, unknown */ 224 0, /* TRxCA, unknown */ 225 226 PCLK/16, /* BRgen, PCLK, divisor 16 */ 227 0, /* BRgen, RTxCB, divisor 16 */ 228 0, /* RTxCB, unknown */ 229 0 /* TRxCB, unknown */ 230}; 231static u_long *zs_frequencies; 232 233/* Definition of the driver for autoconfig. */ 234static int zsmatch __P((struct device *, struct cfdata *, void *)); 235static void zsattach __P((struct device *, struct device *, void *)); 236 237CFATTACH_DECL(zs, sizeof(struct zs_softc), 238 zsmatch, zsattach, NULL, NULL); 239 240extern struct cfdriver zs_cd; 241 242/* {b,c}devsw[] function prototypes */ 243dev_type_open(zsopen); 244dev_type_close(zsclose); 245dev_type_read(zsread); 246dev_type_write(zswrite); 247dev_type_ioctl(zsioctl); 248dev_type_stop(zsstop); 249dev_type_tty(zstty); 250dev_type_poll(zspoll); 251 252const struct cdevsw zs_cdevsw = { 253 zsopen, zsclose, zsread, zswrite, zsioctl, 254 zsstop, zstty, zspoll, nommap, ttykqfilter, D_TTY 255}; 256 257/* Interrupt handlers. */ 258int zshard __P((long)); 259static int zssoft __P((long)); 260static int zsrint __P((struct zs_chanstate *, volatile struct zschan *)); 261static int zsxint __P((struct zs_chanstate *, volatile struct zschan *)); 262static int zssint __P((struct zs_chanstate *, volatile struct zschan *)); 263 264static struct zs_chanstate *zslist; 265 266/* Routines called from other code. */ 267static void zsstart __P((struct tty *)); 268 269/* Routines purely local to this driver. */ 270static void zsoverrun __P((int, long *, char *)); 271static int zsparam __P((struct tty *, struct termios *)); 272static int zsbaudrate __P((int, int, int *, int *, int *, int *)); 273static int zs_modem __P((struct zs_chanstate *, int, int)); 274static void zs_loadchannelregs __P((volatile struct zschan *, u_char *)); 275static void zs_shutdown __P((struct zs_chanstate *)); 276 277static int zsshortcuts; /* number of "shortcut" software interrupts */ 278 279static int 280zsmatch(pdp, cfp, auxp) 281struct device *pdp; 282struct cfdata *cfp; 283void *auxp; 284{ 285 static int zs_matched = 0; 286 287 if(strcmp("zs", auxp) || zs_matched) 288 return(0); 289 zs_matched = 1; 290 return(1); 291} 292 293/* 294 * Attach a found zs. 295 */ 296static void 297zsattach(parent, dev, aux) 298struct device *parent; 299struct device *dev; 300void *aux; 301{ 302 register struct zs_softc *zi; 303 register struct zs_chanstate *cs; 304 register volatile struct zsdevice *addr; 305 char tmp; 306 307 addr = (struct zsdevice *)AD_SCC; 308 zi = (struct zs_softc *)dev; 309 zi->zi_zs = addr; 310 cs = zi->zi_cs; 311 312 /* 313 * Get the command register into a known state. 314 */ 315 tmp = addr->zs_chan[ZS_CHAN_A].zc_csr; 316 tmp = addr->zs_chan[ZS_CHAN_A].zc_csr; 317 tmp = addr->zs_chan[ZS_CHAN_B].zc_csr; 318 tmp = addr->zs_chan[ZS_CHAN_B].zc_csr; 319 320 /* 321 * Do a hardware reset. 322 */ 323 ZS_WRITE(&addr->zs_chan[ZS_CHAN_A], 9, ZSWR9_HARD_RESET); 324 delay(50000); /*enough ? */ 325 ZS_WRITE(&addr->zs_chan[ZS_CHAN_A], 9, 0); 326 327 /* 328 * Initialize both channels 329 */ 330 zs_loadchannelregs(&addr->zs_chan[ZS_CHAN_A], zs_init_regs); 331 zs_loadchannelregs(&addr->zs_chan[ZS_CHAN_B], zs_init_regs); 332 333 if(machineid & ATARI_TT) { 334 /* 335 * ininitialise TT-MFP timer C: 307200Hz 336 * timer C and D share one control register: 337 * bits 0-2 control timer D 338 * bits 4-6 control timer C 339 */ 340 int cr = MFP2->mf_tcdcr & 7; 341 MFP2->mf_tcdcr = cr; /* stop timer C */ 342 MFP2->mf_tcdr = 1; /* counter 1 */ 343 cr |= T_Q004 << 4; /* divisor 4 */ 344 MFP2->mf_tcdcr = cr; /* start timer C */ 345 /* 346 * enable scc related interrupts 347 */ 348 SCU->vme_mask |= SCU_SCC; 349 350 zs_frequencies = zs_freqs_tt; 351 } else if (machineid & ATARI_FALCON) { 352 zs_frequencies = zs_freqs_falcon; 353 } else if (machineid & ATARI_HADES) { 354 zs_frequencies = zs_freqs_hades; 355 } else { 356 zs_frequencies = zs_freqs_generic; 357 } 358 359 /* link into interrupt list with order (A,B) (B=A+1) */ 360 cs[0].cs_next = &cs[1]; 361 cs[1].cs_next = zslist; 362 zslist = cs; 363 364 cs->cs_unit = 0; 365 cs->cs_zc = &addr->zs_chan[ZS_CHAN_A]; 366 cs++; 367 cs->cs_unit = 1; 368 cs->cs_zc = &addr->zs_chan[ZS_CHAN_B]; 369 370 printf(": serial2 on channel a and modem2 on channel b\n"); 371} 372 373/* 374 * Open a zs serial port. 375 */ 376int 377zsopen(dev, flags, mode, p) 378dev_t dev; 379int flags; 380int mode; 381struct proc *p; 382{ 383 register struct tty *tp; 384 register struct zs_chanstate *cs; 385 struct zs_softc *zi; 386 int unit = ZS_UNIT(dev); 387 int zs = unit >> 1; 388 int error, s; 389 390 if(zs >= zs_cd.cd_ndevs || (zi = zs_cd.cd_devs[zs]) == NULL) 391 return (ENXIO); 392 cs = &zi->zi_cs[unit & 1]; 393 394 /* 395 * When port A (ser02) is selected on the TT, make sure 396 * the port is enabled. 397 */ 398 if((machineid & ATARI_TT) && !(unit & 1)) 399 ym2149_ser2(1); 400 401 if (cs->cs_rbuf == NULL) { 402 cs->cs_rbuf = malloc(ZLRB_RING_SIZE * sizeof(int), M_DEVBUF, 403 M_WAITOK); 404 } 405 406 tp = cs->cs_ttyp; 407 if(tp == NULL) { 408 cs->cs_ttyp = tp = ttymalloc(); 409 tty_attach(tp); 410 tp->t_dev = dev; 411 tp->t_oproc = zsstart; 412 tp->t_param = zsparam; 413 } 414 415 if ((tp->t_state & TS_ISOPEN) && 416 (tp->t_state & TS_XCLUDE) && 417 p->p_ucred->cr_uid != 0) 418 return (EBUSY); 419 420 s = spltty(); 421 422 /* 423 * Do the following iff this is a first open. 424 */ 425 if (!(tp->t_state & TS_ISOPEN) && tp->t_wopen == 0) { 426 if(tp->t_ispeed == 0) { 427 tp->t_iflag = TTYDEF_IFLAG; 428 tp->t_oflag = TTYDEF_OFLAG; 429 tp->t_cflag = TTYDEF_CFLAG; 430 tp->t_lflag = TTYDEF_LFLAG; 431 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 432 } 433 ttychars(tp); 434 ttsetwater(tp); 435 436 (void)zsparam(tp, &tp->t_termios); 437 438 /* 439 * Turn on DTR. We must always do this, even if carrier is not 440 * present, because otherwise we'd have to use TIOCSDTR 441 * immediately after setting CLOCAL, which applications do not 442 * expect. We always assert DTR while the device is open 443 * unless explicitly requested to deassert it. 444 */ 445 zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET); 446 /* May never get a status intr. if DCD already on. -gwr */ 447 if((cs->cs_rr0 = cs->cs_zc->zc_csr) & ZSRR0_DCD) 448 tp->t_state |= TS_CARR_ON; 449 if(cs->cs_softcar) 450 tp->t_state |= TS_CARR_ON; 451 } 452 453 splx(s); 454 455 error = ttyopen(tp, ZS_DIALOUT(dev), (flags & O_NONBLOCK)); 456 if (error) 457 goto bad; 458 459 error = tp->t_linesw->l_open(dev, tp); 460 if(error) 461 goto bad; 462 return (0); 463 464bad: 465 if (!(tp->t_state & TS_ISOPEN) && tp->t_wopen == 0) { 466 /* 467 * We failed to open the device, and nobody else had it opened. 468 * Clean up the state as appropriate. 469 */ 470 zs_shutdown(cs); 471 } 472 return(error); 473} 474 475/* 476 * Close a zs serial port. 477 */ 478int 479zsclose(dev, flags, mode, p) 480dev_t dev; 481int flags; 482int mode; 483struct proc *p; 484{ 485 register struct zs_chanstate *cs; 486 register struct tty *tp; 487 struct zs_softc *zi; 488 int unit = ZS_UNIT(dev); 489 490 zi = zs_cd.cd_devs[unit >> 1]; 491 cs = &zi->zi_cs[unit & 1]; 492 tp = cs->cs_ttyp; 493 494 tp->t_linesw->l_close(tp, flags); 495 ttyclose(tp); 496 497 if (!(tp->t_state & TS_ISOPEN) && tp->t_wopen == 0) { 498 /* 499 * Although we got a last close, the device may still be in 500 * use; e.g. if this was the dialout node, and there are still 501 * processes waiting for carrier on the non-dialout node. 502 */ 503 zs_shutdown(cs); 504 } 505 return (0); 506} 507 508/* 509 * Read/write zs serial port. 510 */ 511int 512zsread(dev, uio, flags) 513dev_t dev; 514struct uio *uio; 515int flags; 516{ 517 register struct zs_chanstate *cs; 518 register struct zs_softc *zi; 519 register struct tty *tp; 520 int unit; 521 522 unit = ZS_UNIT(dev); 523 zi = zs_cd.cd_devs[unit >> 1]; 524 cs = &zi->zi_cs[unit & 1]; 525 tp = cs->cs_ttyp; 526 527 return(tp->t_linesw->l_read(tp, uio, flags)); 528} 529 530int 531zswrite(dev, uio, flags) 532dev_t dev; 533struct uio *uio; 534int flags; 535{ 536 register struct zs_chanstate *cs; 537 register struct zs_softc *zi; 538 register struct tty *tp; 539 int unit; 540 541 unit = ZS_UNIT(dev); 542 zi = zs_cd.cd_devs[unit >> 1]; 543 cs = &zi->zi_cs[unit & 1]; 544 tp = cs->cs_ttyp; 545 546 return(tp->t_linesw->l_write(tp, uio, flags)); 547} 548 549int 550zspoll(dev, events, p) 551dev_t dev; 552int events; 553struct proc *p; 554{ 555 register struct zs_chanstate *cs; 556 register struct zs_softc *zi; 557 register struct tty *tp; 558 int unit; 559 560 unit = ZS_UNIT(dev); 561 zi = zs_cd.cd_devs[unit >> 1]; 562 cs = &zi->zi_cs[unit & 1]; 563 tp = cs->cs_ttyp; 564 565 return ((*tp->t_linesw->l_poll)(tp, events, p)); 566} 567 568struct tty * 569zstty(dev) 570dev_t dev; 571{ 572 register struct zs_chanstate *cs; 573 register struct zs_softc *zi; 574 int unit; 575 576 unit = ZS_UNIT(dev); 577 zi = zs_cd.cd_devs[unit >> 1]; 578 cs = &zi->zi_cs[unit & 1]; 579 return(cs->cs_ttyp); 580} 581 582/* 583 * ZS hardware interrupt. Scan all ZS channels. NB: we know here that 584 * channels are kept in (A,B) pairs. 585 * 586 * Do just a little, then get out; set a software interrupt if more 587 * work is needed. 588 * 589 * We deliberately ignore the vectoring Zilog gives us, and match up 590 * only the number of `reset interrupt under service' operations, not 591 * the order. 592 */ 593 594int 595zshard(sr) 596long sr; 597{ 598 register struct zs_chanstate *a; 599#define b (a + 1) 600 register volatile struct zschan *zc; 601 register int rr3, intflags = 0, v, i; 602 603 do { 604 intflags &= ~4; 605 for(a = zslist; a != NULL; a = b->cs_next) { 606 rr3 = ZS_READ(a->cs_zc, 3); 607 if(rr3 & (ZSRR3_IP_A_RX|ZSRR3_IP_A_TX|ZSRR3_IP_A_STAT)) { 608 intflags |= 4|2; 609 zc = a->cs_zc; 610 i = a->cs_rbput; 611 if(rr3 & ZSRR3_IP_A_RX && (v = zsrint(a, zc)) != 0) { 612 a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 613 intflags |= 1; 614 } 615 if(rr3 & ZSRR3_IP_A_TX && (v = zsxint(a, zc)) != 0) { 616 a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 617 intflags |= 1; 618 } 619 if(rr3 & ZSRR3_IP_A_STAT && (v = zssint(a, zc)) != 0) { 620 a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 621 intflags |= 1; 622 } 623 a->cs_rbput = i; 624 } 625 if(rr3 & (ZSRR3_IP_B_RX|ZSRR3_IP_B_TX|ZSRR3_IP_B_STAT)) { 626 intflags |= 4|2; 627 zc = b->cs_zc; 628 i = b->cs_rbput; 629 if(rr3 & ZSRR3_IP_B_RX && (v = zsrint(b, zc)) != 0) { 630 b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 631 intflags |= 1; 632 } 633 if(rr3 & ZSRR3_IP_B_TX && (v = zsxint(b, zc)) != 0) { 634 b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 635 intflags |= 1; 636 } 637 if(rr3 & ZSRR3_IP_B_STAT && (v = zssint(b, zc)) != 0) { 638 b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; 639 intflags |= 1; 640 } 641 b->cs_rbput = i; 642 } 643 } 644 } while(intflags & 4); 645#undef b 646 647 if(intflags & 1) { 648 if(BASEPRI(sr)) { 649 spl1(); 650 zsshortcuts++; 651 return(zssoft(sr)); 652 } 653 else if(!cb_scheduled) { 654 cb_scheduled++; 655 add_sicallback((si_farg)zssoft, 0, 0); 656 } 657 } 658 return(intflags & 2); 659} 660 661static int 662zsrint(cs, zc) 663register struct zs_chanstate *cs; 664register volatile struct zschan *zc; 665{ 666 register int c; 667 668 /* 669 * First read the status, because read of the received char 670 * destroy the status of this char. 671 */ 672 c = ZS_READ(zc, 1); 673 c |= (zc->zc_data << 8); 674 675 /* clear receive error & interrupt condition */ 676 zc->zc_csr = ZSWR0_RESET_ERRORS; 677 zc->zc_csr = ZSWR0_CLR_INTR; 678 679 return(ZRING_MAKE(ZRING_RINT, c)); 680} 681 682static int 683zsxint(cs, zc) 684register struct zs_chanstate *cs; 685register volatile struct zschan *zc; 686{ 687 register int i = cs->cs_tbc; 688 689 if(i == 0) { 690 zc->zc_csr = ZSWR0_RESET_TXINT; 691 zc->zc_csr = ZSWR0_CLR_INTR; 692 return(ZRING_MAKE(ZRING_XINT, 0)); 693 } 694 cs->cs_tbc = i - 1; 695 zc->zc_data = *cs->cs_tba++; 696 zc->zc_csr = ZSWR0_CLR_INTR; 697 return (0); 698} 699 700static int 701zssint(cs, zc) 702register struct zs_chanstate *cs; 703register volatile struct zschan *zc; 704{ 705 register int rr0; 706 707 rr0 = zc->zc_csr; 708 zc->zc_csr = ZSWR0_RESET_STATUS; 709 zc->zc_csr = ZSWR0_CLR_INTR; 710 /* 711 * The chip's hardware flow control is, as noted in zsreg.h, 712 * busted---if the DCD line goes low the chip shuts off the 713 * receiver (!). If we want hardware CTS flow control but do 714 * not have it, and carrier is now on, turn HFC on; if we have 715 * HFC now but carrier has gone low, turn it off. 716 */ 717 if(rr0 & ZSRR0_DCD) { 718 if(cs->cs_ttyp->t_cflag & CCTS_OFLOW && 719 (cs->cs_creg[3] & ZSWR3_HFC) == 0) { 720 cs->cs_creg[3] |= ZSWR3_HFC; 721 ZS_WRITE(zc, 3, cs->cs_creg[3]); 722 } 723 } 724 else { 725 if (cs->cs_creg[3] & ZSWR3_HFC) { 726 cs->cs_creg[3] &= ~ZSWR3_HFC; 727 ZS_WRITE(zc, 3, cs->cs_creg[3]); 728 } 729 } 730 return(ZRING_MAKE(ZRING_SINT, rr0)); 731} 732 733/* 734 * Print out a ring or fifo overrun error message. 735 */ 736static void 737zsoverrun(unit, ptime, what) 738int unit; 739long *ptime; 740char *what; 741{ 742 743 if(*ptime != time.tv_sec) { 744 *ptime = time.tv_sec; 745 log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1, 746 (unit & 1) + 'a', what); 747 } 748} 749 750/* 751 * ZS software interrupt. Scan all channels for deferred interrupts. 752 */ 753int 754zssoft(sr) 755long sr; 756{ 757 register struct zs_chanstate *cs; 758 register volatile struct zschan *zc; 759 register struct linesw *line; 760 register struct tty *tp; 761 register int get, n, c, cc, unit, s; 762 int retval = 0; 763 764 cb_scheduled = 0; 765 s = spltty(); 766 for(cs = zslist; cs != NULL; cs = cs->cs_next) { 767 get = cs->cs_rbget; 768again: 769 n = cs->cs_rbput; /* atomic */ 770 if(get == n) /* nothing more on this line */ 771 continue; 772 retval = 1; 773 unit = cs->cs_unit; /* set up to handle interrupts */ 774 zc = cs->cs_zc; 775 tp = cs->cs_ttyp; 776 line = tp->t_linesw; 777 /* 778 * Compute the number of interrupts in the receive ring. 779 * If the count is overlarge, we lost some events, and 780 * must advance to the first valid one. It may get 781 * overwritten if more data are arriving, but this is 782 * too expensive to check and gains nothing (we already 783 * lost out; all we can do at this point is trade one 784 * kind of loss for another). 785 */ 786 n -= get; 787 if(n > ZLRB_RING_SIZE) { 788 zsoverrun(unit, &cs->cs_rotime, "ring"); 789 get += n - ZLRB_RING_SIZE; 790 n = ZLRB_RING_SIZE; 791 } 792 while(--n >= 0) { 793 /* race to keep ahead of incoming interrupts */ 794 c = cs->cs_rbuf[get++ & ZLRB_RING_MASK]; 795 switch (ZRING_TYPE(c)) { 796 797 case ZRING_RINT: 798 c = ZRING_VALUE(c); 799 if(c & ZSRR1_DO) 800 zsoverrun(unit, &cs->cs_fotime, "fifo"); 801 cc = c >> 8; 802 if(c & ZSRR1_FE) 803 cc |= TTY_FE; 804 if(c & ZSRR1_PE) 805 cc |= TTY_PE; 806 line->l_rint(cc, tp); 807 break; 808 809 case ZRING_XINT: 810 /* 811 * Transmit done: change registers and resume, 812 * or clear BUSY. 813 */ 814 if(cs->cs_heldchange) { 815 int sps; 816 817 sps = splzs(); 818 c = zc->zc_csr; 819 if((c & ZSRR0_DCD) == 0) 820 cs->cs_preg[3] &= ~ZSWR3_HFC; 821 bcopy((caddr_t)cs->cs_preg, 822 (caddr_t)cs->cs_creg, 16); 823 zs_loadchannelregs(zc, cs->cs_creg); 824 splx(sps); 825 cs->cs_heldchange = 0; 826 if(cs->cs_heldtbc 827 && (tp->t_state & TS_TTSTOP) == 0) { 828 cs->cs_tbc = cs->cs_heldtbc - 1; 829 zc->zc_data = *cs->cs_tba++; 830 goto again; 831 } 832 } 833 tp->t_state &= ~TS_BUSY; 834 if(tp->t_state & TS_FLUSH) 835 tp->t_state &= ~TS_FLUSH; 836 else ndflush(&tp->t_outq,cs->cs_tba 837 - (caddr_t)tp->t_outq.c_cf); 838 line->l_start(tp); 839 break; 840 841 case ZRING_SINT: 842 /* 843 * Status line change. HFC bit is run in 844 * hardware interrupt, to avoid locking 845 * at splzs here. 846 */ 847 c = ZRING_VALUE(c); 848 if((c ^ cs->cs_rr0) & ZSRR0_DCD) { 849 cc = (c & ZSRR0_DCD) != 0; 850 if(line->l_modem(tp, cc) == 0) 851 zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, 852 cc ? DMBIS : DMBIC); 853 } 854 cs->cs_rr0 = c; 855 break; 856 857 default: 858 log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n", 859 unit >> 1, (unit & 1) + 'a', c); 860 break; 861 } 862 } 863 cs->cs_rbget = get; 864 goto again; 865 } 866 splx(s); 867 return (retval); 868} 869 870int 871zsioctl(dev, cmd, data, flag, p) 872dev_t dev; 873u_long cmd; 874caddr_t data; 875int flag; 876struct proc *p; 877{ 878 int unit = ZS_UNIT(dev); 879 struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; 880 register struct tty *tp = zi->zi_cs[unit & 1].cs_ttyp; 881 register int error, s; 882 register struct zs_chanstate *cs = &zi->zi_cs[unit & 1]; 883 884 error = tp->t_linesw->l_ioctl(tp, cmd, data, flag, p); 885 if(error != EPASSTHROUGH) 886 return(error); 887 888 error = ttioctl(tp, cmd, data, flag, p); 889 if(error !=EPASSTHROUGH) 890 return (error); 891 892 switch (cmd) { 893 case TIOCSBRK: 894 s = splzs(); 895 cs->cs_preg[5] |= ZSWR5_BREAK; 896 cs->cs_creg[5] |= ZSWR5_BREAK; 897 ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); 898 splx(s); 899 break; 900 case TIOCCBRK: 901 s = splzs(); 902 cs->cs_preg[5] &= ~ZSWR5_BREAK; 903 cs->cs_creg[5] &= ~ZSWR5_BREAK; 904 ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); 905 splx(s); 906 break; 907 case TIOCGFLAGS: { 908 int bits = 0; 909 910 if(cs->cs_softcar) 911 bits |= TIOCFLAG_SOFTCAR; 912 if(cs->cs_creg[15] & ZSWR15_DCD_IE) 913 bits |= TIOCFLAG_CLOCAL; 914 if(cs->cs_creg[3] & ZSWR3_HFC) 915 bits |= TIOCFLAG_CRTSCTS; 916 *(int *)data = bits; 917 break; 918 } 919 case TIOCSFLAGS: { 920 int userbits = 0; 921 922 error = suser(p->p_ucred, &p->p_acflag); 923 if(error != 0) 924 return (EPERM); 925 926 userbits = *(int *)data; 927 928 /* 929 * can have `local' or `softcar', and `rtscts' or `mdmbuf' 930 # defaulting to software flow control. 931 */ 932 if(userbits & TIOCFLAG_SOFTCAR && userbits & TIOCFLAG_CLOCAL) 933 return(EINVAL); 934 if(userbits & TIOCFLAG_MDMBUF) /* don't support this (yet?) */ 935 return(ENODEV); 936 937 s = splzs(); 938 if((userbits & TIOCFLAG_SOFTCAR)) { 939 cs->cs_softcar = 1; /* turn on softcar */ 940 cs->cs_preg[15] &= ~ZSWR15_DCD_IE; /* turn off dcd */ 941 cs->cs_creg[15] &= ~ZSWR15_DCD_IE; 942 ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); 943 } 944 else if(userbits & TIOCFLAG_CLOCAL) { 945 cs->cs_softcar = 0; /* turn off softcar */ 946 cs->cs_preg[15] |= ZSWR15_DCD_IE; /* turn on dcd */ 947 cs->cs_creg[15] |= ZSWR15_DCD_IE; 948 ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); 949 tp->t_termios.c_cflag |= CLOCAL; 950 } 951 if(userbits & TIOCFLAG_CRTSCTS) { 952 cs->cs_preg[15] |= ZSWR15_CTS_IE; 953 cs->cs_creg[15] |= ZSWR15_CTS_IE; 954 ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); 955 cs->cs_preg[3] |= ZSWR3_HFC; 956 cs->cs_creg[3] |= ZSWR3_HFC; 957 ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]); 958 tp->t_termios.c_cflag |= CRTSCTS; 959 } 960 else { 961 /* no mdmbuf, so we must want software flow control */ 962 cs->cs_preg[15] &= ~ZSWR15_CTS_IE; 963 cs->cs_creg[15] &= ~ZSWR15_CTS_IE; 964 ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); 965 cs->cs_preg[3] &= ~ZSWR3_HFC; 966 cs->cs_creg[3] &= ~ZSWR3_HFC; 967 ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]); 968 tp->t_termios.c_cflag &= ~CRTSCTS; 969 } 970 splx(s); 971 break; 972 } 973 case TIOCSDTR: 974 zs_modem(cs, ZSWR5_DTR, DMBIS); 975 break; 976 case TIOCCDTR: 977 zs_modem(cs, ZSWR5_DTR, DMBIC); 978 break; 979 case TIOCMGET: 980 zs_modem(cs, 0, DMGET); 981 break; 982 case TIOCMSET: 983 case TIOCMBIS: 984 case TIOCMBIC: 985 default: 986 return (EPASSTHROUGH); 987 } 988 return (0); 989} 990 991/* 992 * Start or restart transmission. 993 */ 994static void 995zsstart(tp) 996register struct tty *tp; 997{ 998 register struct zs_chanstate *cs; 999 register int s, nch; 1000 int unit = ZS_UNIT(tp->t_dev); 1001 struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; 1002 1003 cs = &zi->zi_cs[unit & 1]; 1004 s = spltty(); 1005 1006 /* 1007 * If currently active or delaying, no need to do anything. 1008 */ 1009 if(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 1010 goto out; 1011 1012 /* 1013 * If there are sleepers, and output has drained below low 1014 * water mark, awaken. 1015 */ 1016 if(tp->t_outq.c_cc <= tp->t_lowat) { 1017 if(tp->t_state & TS_ASLEEP) { 1018 tp->t_state &= ~TS_ASLEEP; 1019 wakeup((caddr_t)&tp->t_outq); 1020 } 1021 selwakeup(&tp->t_wsel); 1022 } 1023 1024 nch = ndqb(&tp->t_outq, 0); /* XXX */ 1025 if(nch) { 1026 register char *p = tp->t_outq.c_cf; 1027 1028 /* mark busy, enable tx done interrupts, & send first byte */ 1029 tp->t_state |= TS_BUSY; 1030 (void) splzs(); 1031 cs->cs_preg[1] |= ZSWR1_TIE; 1032 cs->cs_creg[1] |= ZSWR1_TIE; 1033 ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]); 1034 cs->cs_zc->zc_data = *p; 1035 cs->cs_tba = p + 1; 1036 cs->cs_tbc = nch - 1; 1037 } else { 1038 /* 1039 * Nothing to send, turn off transmit done interrupts. 1040 * This is useful if something is doing polled output. 1041 */ 1042 (void) splzs(); 1043 cs->cs_preg[1] &= ~ZSWR1_TIE; 1044 cs->cs_creg[1] &= ~ZSWR1_TIE; 1045 ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]); 1046 } 1047out: 1048 splx(s); 1049} 1050 1051/* 1052 * Stop output, e.g., for ^S or output flush. 1053 */ 1054void 1055zsstop(tp, flag) 1056register struct tty *tp; 1057 int flag; 1058{ 1059 register struct zs_chanstate *cs; 1060 register int s, unit = ZS_UNIT(tp->t_dev); 1061 struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; 1062 1063 cs = &zi->zi_cs[unit & 1]; 1064 s = splzs(); 1065 if(tp->t_state & TS_BUSY) { 1066 /* 1067 * Device is transmitting; must stop it. 1068 */ 1069 cs->cs_tbc = 0; 1070 if ((tp->t_state & TS_TTSTOP) == 0) 1071 tp->t_state |= TS_FLUSH; 1072 } 1073 splx(s); 1074} 1075 1076static void 1077zs_shutdown(cs) 1078 struct zs_chanstate *cs; 1079{ 1080 struct tty *tp = cs->cs_ttyp; 1081 int s; 1082 1083 s = splzs(); 1084 1085 /* 1086 * Hang up if necessary. Wait a bit, so the other side has time to 1087 * notice even if we immediately open the port again. 1088 */ 1089 if(tp->t_cflag & HUPCL) { 1090 zs_modem(cs, 0, DMSET); 1091 (void)tsleep((caddr_t)cs, TTIPRI, ttclos, hz); 1092 } 1093 1094 /* Clear any break condition set with TIOCSBRK. */ 1095 if(cs->cs_creg[5] & ZSWR5_BREAK) { 1096 cs->cs_preg[5] &= ~ZSWR5_BREAK; 1097 cs->cs_creg[5] &= ~ZSWR5_BREAK; 1098 ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); 1099 } 1100 1101 /* 1102 * Drop all lines and cancel interrupts 1103 */ 1104 zs_loadchannelregs(cs->cs_zc, zs_init_regs); 1105 splx(s); 1106} 1107 1108/* 1109 * Set ZS tty parameters from termios. 1110 * 1111 * This routine makes use of the fact that only registers 1112 * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written. 1113 */ 1114static int 1115zsparam(tp, t) 1116register struct tty *tp; 1117register struct termios *t; 1118{ 1119 int unit = ZS_UNIT(tp->t_dev); 1120 struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; 1121 register struct zs_chanstate *cs = &zi->zi_cs[unit & 1]; 1122 int cdiv, clkm, brgm, tcon; 1123 register int tmp, tmp5, cflag, s; 1124 1125 tmp = t->c_ospeed; 1126 tmp5 = t->c_ispeed; 1127 if(tmp < 0 || (tmp5 && tmp5 != tmp)) 1128 return(EINVAL); 1129 if(tmp == 0) { 1130 /* stty 0 => drop DTR and RTS */ 1131 zs_modem(cs, 0, DMSET); 1132 return(0); 1133 } 1134 tmp = zsbaudrate(unit, tmp, &cdiv, &clkm, &brgm, &tcon); 1135 if (tmp < 0) 1136 return(EINVAL); 1137 tp->t_ispeed = tp->t_ospeed = tmp; 1138 1139 cflag = tp->t_cflag = t->c_cflag; 1140 if (cflag & CSTOPB) 1141 cdiv |= ZSWR4_TWOSB; 1142 else 1143 cdiv |= ZSWR4_ONESB; 1144 if (!(cflag & PARODD)) 1145 cdiv |= ZSWR4_EVENP; 1146 if (cflag & PARENB) 1147 cdiv |= ZSWR4_PARENB; 1148 1149 switch(cflag & CSIZE) { 1150 case CS5: 1151 tmp = ZSWR3_RX_5; 1152 tmp5 = ZSWR5_TX_5; 1153 break; 1154 case CS6: 1155 tmp = ZSWR3_RX_6; 1156 tmp5 = ZSWR5_TX_6; 1157 break; 1158 case CS7: 1159 tmp = ZSWR3_RX_7; 1160 tmp5 = ZSWR5_TX_7; 1161 break; 1162 case CS8: 1163 default: 1164 tmp = ZSWR3_RX_8; 1165 tmp5 = ZSWR5_TX_8; 1166 break; 1167 } 1168 tmp |= ZSWR3_RX_ENABLE; 1169 tmp5 |= ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS; 1170 1171 /* 1172 * Block interrupts so that state will not 1173 * be altered until we are done setting it up. 1174 */ 1175 s = splzs(); 1176 cs->cs_preg[4] = cdiv; 1177 cs->cs_preg[11] = clkm; 1178 cs->cs_preg[12] = tcon; 1179 cs->cs_preg[13] = tcon >> 8; 1180 cs->cs_preg[14] = brgm; 1181 cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE; 1182 cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT; 1183 cs->cs_preg[10] = ZSWR10_NRZ; 1184 cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE; 1185 1186 /* 1187 * Output hardware flow control on the chip is horrendous: if 1188 * carrier detect drops, the receiver is disabled. Hence we 1189 * can only do this when the carrier is on. 1190 */ 1191 if(cflag & CCTS_OFLOW && cs->cs_zc->zc_csr & ZSRR0_DCD) 1192 tmp |= ZSWR3_HFC; 1193 cs->cs_preg[3] = tmp; 1194 cs->cs_preg[5] = tmp5; 1195 1196 /* 1197 * If nothing is being transmitted, set up new current values, 1198 * else mark them as pending. 1199 */ 1200 if(cs->cs_heldchange == 0) { 1201 if (cs->cs_ttyp->t_state & TS_BUSY) { 1202 cs->cs_heldtbc = cs->cs_tbc; 1203 cs->cs_tbc = 0; 1204 cs->cs_heldchange = 1; 1205 } else { 1206 bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16); 1207 zs_loadchannelregs(cs->cs_zc, cs->cs_creg); 1208 } 1209 } 1210 splx(s); 1211 return (0); 1212} 1213 1214/* 1215 * search for the best matching baudrate 1216 */ 1217static int 1218zsbaudrate(unit, wanted, divisor, clockmode, brgenmode, timeconst) 1219int unit, wanted, *divisor, *clockmode, *brgenmode, *timeconst; 1220{ 1221 int bestdiff, bestbps, source; 1222 1223 bestdiff = bestbps = 0; 1224 unit = (unit & 1) << 2; 1225 for (source = 0; source < 4; ++source) { 1226 long freq = zs_frequencies[unit + source]; 1227 int diff, bps, div, clkm, brgm, tcon; 1228 1229 bps = div = clkm = brgm = tcon = 0; 1230 switch (source) { 1231 case 0: /* BRgen, PCLK */ 1232 brgm = ZSWR14_BAUD_ENA|ZSWR14_BAUD_FROM_PCLK; 1233 break; 1234 case 1: /* BRgen, RTxC */ 1235 brgm = ZSWR14_BAUD_ENA; 1236 break; 1237 case 2: /* RTxC */ 1238 clkm = ZSWR11_RXCLK_RTXC|ZSWR11_TXCLK_RTXC; 1239 break; 1240 case 3: /* TRxC */ 1241 clkm = ZSWR11_RXCLK_TRXC|ZSWR11_TXCLK_TRXC; 1242 break; 1243 } 1244 switch (source) { 1245 case 0: 1246 case 1: 1247 div = ZSWR4_CLK_X16; 1248 clkm = ZSWR11_RXCLK_BAUD|ZSWR11_TXCLK_BAUD; 1249 tcon = BPS_TO_TCONST(freq, wanted); 1250 if (tcon < 0) 1251 tcon = 0; 1252 bps = TCONST_TO_BPS(freq, tcon); 1253 break; 1254 case 2: 1255 case 3: 1256 { int b1 = freq / 16, d1 = abs(b1 - wanted); 1257 int b2 = freq / 32, d2 = abs(b2 - wanted); 1258 int b3 = freq / 64, d3 = abs(b3 - wanted); 1259 1260 if (d1 < d2 && d1 < d3) { 1261 div = ZSWR4_CLK_X16; 1262 bps = b1; 1263 } else if (d2 < d3 && d2 < d1) { 1264 div = ZSWR4_CLK_X32; 1265 bps = b2; 1266 } else { 1267 div = ZSWR4_CLK_X64; 1268 bps = b3; 1269 } 1270 brgm = tcon = 0; 1271 break; 1272 } 1273 } 1274 diff = abs(bps - wanted); 1275 if (!source || diff < bestdiff) { 1276 *divisor = div; 1277 *clockmode = clkm; 1278 *brgenmode = brgm; 1279 *timeconst = tcon; 1280 bestbps = bps; 1281 bestdiff = diff; 1282 if (diff == 0) 1283 break; 1284 } 1285 } 1286 /* Allow deviations upto 5% */ 1287 if (20 * bestdiff > wanted) 1288 return -1; 1289 return bestbps; 1290} 1291 1292/* 1293 * Raise or lower modem control (DTR/RTS) signals. If a character is 1294 * in transmission, the change is deferred. 1295 */ 1296static int 1297zs_modem(cs, bits, how) 1298struct zs_chanstate *cs; 1299int bits, how; 1300{ 1301 int s, mbits; 1302 1303 bits &= ZSWR5_DTR | ZSWR5_RTS; 1304 1305 s = splzs(); 1306 mbits = cs->cs_preg[5] & (ZSWR5_DTR | ZSWR5_RTS); 1307 1308 switch(how) { 1309 case DMSET: 1310 mbits = bits; 1311 break; 1312 case DMBIS: 1313 mbits |= bits; 1314 break; 1315 case DMBIC: 1316 mbits &= ~bits; 1317 break; 1318 case DMGET: 1319 splx(s); 1320 return(mbits); 1321 } 1322 1323 cs->cs_preg[5] = (cs->cs_preg[5] & ~(ZSWR5_DTR | ZSWR5_RTS)) | mbits; 1324 if(cs->cs_heldchange == 0) { 1325 if(cs->cs_ttyp->t_state & TS_BUSY) { 1326 cs->cs_heldtbc = cs->cs_tbc; 1327 cs->cs_tbc = 0; 1328 cs->cs_heldchange = 1; 1329 } 1330 else { 1331 ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); 1332 } 1333 } 1334 splx(s); 1335 return(0); 1336} 1337 1338/* 1339 * Write the given register set to the given zs channel in the proper order. 1340 * The channel must not be transmitting at the time. The receiver will 1341 * be disabled for the time it takes to write all the registers. 1342 */ 1343static void 1344zs_loadchannelregs(zc, reg) 1345volatile struct zschan *zc; 1346u_char *reg; 1347{ 1348 int i; 1349 1350 zc->zc_csr = ZSM_RESET_ERR; /* reset error condition */ 1351 i = zc->zc_data; /* drain fifo */ 1352 i = zc->zc_data; 1353 i = zc->zc_data; 1354 ZS_WRITE(zc, 4, reg[4]); 1355 ZS_WRITE(zc, 10, reg[10]); 1356 ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE); 1357 ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE); 1358 ZS_WRITE(zc, 1, reg[1]); 1359 ZS_WRITE(zc, 9, reg[9]); 1360 ZS_WRITE(zc, 11, reg[11]); 1361 ZS_WRITE(zc, 12, reg[12]); 1362 ZS_WRITE(zc, 13, reg[13]); 1363 ZS_WRITE(zc, 14, reg[14]); 1364 ZS_WRITE(zc, 15, reg[15]); 1365 ZS_WRITE(zc, 3, reg[3]); 1366 ZS_WRITE(zc, 5, reg[5]); 1367} 1368#endif /* NZS > 1 */ 1369