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