si.c revision 10161
1/* 2 * Device driver for Specialix range (SLXOS) of serial line multiplexors. 3 * 4 * Copyright (C) 1990, 1992 Specialix International, 5 * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk> 6 * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com> 7 * 8 * Originally derived from: SunOS 4.x version 9 * Ported from BSDI version to FreeBSD by Peter Wemm. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notices, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notices, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Andy Rutter of 22 * Advanced Methods and Tools Ltd. based on original information 23 * from Specialix International. 24 * 4. Neither the name of Advanced Methods and Tools, nor Specialix 25 * International may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 30 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 31 * NO EVENT SHALL THE AUTHORS BE LIABLE. 32 * 33 * $Id: si.c,v 1.4 1995/08/13 15:44:37 peter Exp $ 34 */ 35 36#ifndef lint 37static char si_copyright1[] = "@(#) (C) Specialix International, 1990,1992", 38 si_copyright2[] = "@(#) (C) Andy Rutter 1993", 39 si_copyright3[] = "@(#) (C) Peter Wemm 1995"; 40#endif /* not lint */ 41 42#define SI_DEBUG /* turn driver debugging on */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/ioctl.h> 47#include <sys/tty.h> 48#include <sys/ttydefaults.h> 49#include <sys/proc.h> 50#include <sys/user.h> 51#include <sys/conf.h> 52#include <sys/file.h> 53#include <sys/uio.h> 54#include <sys/dkstat.h> 55#include <sys/kernel.h> 56#include <sys/syslog.h> 57#include <sys/device.h> 58#include <sys/malloc.h> 59#include <sys/devconf.h> 60 61#include <machine/clock.h> 62 63#include <i386/isa/icu.h> 64#include <i386/isa/isa.h> 65#include <i386/isa/isa_device.h> 66 67#include <i386/isa/sireg.h> 68#include <machine/si.h> 69 70#include "si.h" 71 72/* 73 * This device driver is designed to interface the Specialix International 74 * range of serial multiplexor cards (SLXOS) to BSDI/386 on an ISA bus machine. 75 * 76 * The controller is interfaced to the host via dual port ram 77 * and a (programmable - SIHOST2) interrupt at IRQ 11,12 or 15. 78 */ 79 80#define POLL /* turn on poller to generate buffer empty interrupt */ 81#define SI_DEF_HWFLOW /* turn on default CRTSCTS flow control */ 82#define SI_I_HIGH_WATER (TTYHOG - SLXOS_BUFFERSIZE) 83 84enum si_mctl { GET, SET, BIS, BIC }; 85 86static void si_command __P((struct si_port *, int, int)); 87static int si_modem __P((struct si_port *, enum si_mctl, int)); 88static void si_write_enable __P((struct si_port *, int)); 89static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *)); 90static void si_start __P((struct tty *)); 91static void si_lstart __P((struct si_port *)); 92static void si_disc_optim __P((struct tty *tp, struct termios *t, 93 struct si_port *pp)); 94static void sihardclose __P((struct si_port *pp)); 95static void sidtrwakeup __P((void *chan)); 96 97void sistop __P((struct tty *tp, int rw)); 98int siparam __P((struct tty *, struct termios *)); 99int siintr __P((int bdnum)); 100 101static int si_Nports = 0; 102static int si_Nmodules = 0; 103static int si_debug = 0; 104 105/* where the firmware lives */ 106extern int si_dsize; 107extern unsigned char si_download[]; 108 109struct si_softc { 110 struct device sc_dev; /* base device */ 111 112 int sc_type; /* adapter type */ 113 char *sc_typename; /* adapter type string */ 114 115 struct si_port *sc_ports; /* port structures for this card */ 116 117 caddr_t sc_paddr; /* physical addr of iomem */ 118 caddr_t sc_maddr; /* kvaddr of iomem */ 119 int sc_nport; /* # ports on this card */ 120 int sc_irq; /* copy of attach irq */ 121 int sc_eisa_iobase; /* EISA io port address */ 122 int sc_eisa_irqbits; 123 struct kern_devconf sc_kdc; 124}; 125struct si_softc si_softc[NSI]; /* up to 4 elements */ 126 127#ifndef B2000 /* not standard */ 128# define B2000 2000 129#endif 130static struct speedtab bdrates[] = { 131 B75, CLK75, /* 0x0 */ 132 B110, CLK110, /* 0x1 */ 133 B150, CLK150, /* 0x3 */ 134 B300, CLK300, /* 0x4 */ 135 B600, CLK600, /* 0x5 */ 136 B1200, CLK1200, /* 0x6 */ 137 B2000, CLK2000, /* 0x7 */ 138 B2400, CLK2400, /* 0x8 */ 139 B4800, CLK4800, /* 0x9 */ 140 B9600, CLK9600, /* 0xb */ 141 B19200, CLK19200, /* 0xc */ 142 B38400, CLK38400, /* 0x2 (out of order!) */ 143 B57600, CLK57600, /* 0xd */ 144 B115200, CLK110, /* 0x1 (dupe!, 110 baud on "si") */ 145 -1, -1 146}; 147 148 149/* populated with approx character/sec rates - translated at card 150 * initialisation time to chars per tick of the clock */ 151static int done_chartimes = 0; 152static struct speedtab chartimes[] = { 153 B75, 8, 154 B110, 11, 155 B150, 15, 156 B300, 30, 157 B600, 60, 158 B1200, 120, 159 B2000, 200, 160 B2400, 240, 161 B4800, 480, 162 B9600, 960, 163 B19200, 1920, 164 B38400, 3840, 165 B57600, 5760, 166 B115200, 11520, 167 -1, -1 168}; 169static volatile int in_intr = 0; /* Inside interrupt handler? */ 170 171static int si_default_rate = TTYDEF_SPEED; 172static int si_default_iflag = 0; 173static int si_default_oflag = 0; 174static int si_default_lflag = 0; 175#ifdef SI_DEF_HWFLOW 176static int si_default_cflag = TTYDEF_CFLAG | CRTSCTS; 177#else 178static int si_default_cflag = TTYDEF_CFLAG; 179#endif 180 181#ifdef POLL 182#define POLL_INTERVAL (hz/2) 183static int init_finished = 0; 184static void si_poll __P((void *)); 185#endif 186 187/* 188 * Array of adapter types and the corresponding RAM size. The order of 189 * entries here MUST match the ordinal of the adapter type. 190 */ 191static char *si_type[] = { 192 "EMPTY", 193 "SIHOST", 194 "SI2", /* MCA */ 195 "SIHOST2", 196 "SIEISA", 197}; 198 199 200static struct kern_devconf si_kdc[NSI] = { { 201 0, 0, 0, /* filled in by dev_attach */ 202 "si", 0, { MDDT_ISA, 0, "tty" }, 203 isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 204 &kdc_isa0, /* parent */ 205 0, /* parent data */ 206 DC_UNCONFIGURED, /* state */ 207 "Specialix SI/XIO Host adapter", 208 DC_CLS_SERIAL, /* class */ 209} }; 210 211void 212si_registerdev(id) 213 struct isa_device *id; 214{ 215 if (id->id_unit != 0) { 216 si_kdc[id->id_unit] = si_kdc[0]; /* struct copy */ 217 } 218 si_kdc[id->id_unit].kdc_unit = id->id_unit; 219 si_kdc[id->id_unit].kdc_isa = id; 220 dev_attach(&si_kdc[id->id_unit]); 221} 222 223/* Look for a valid board at the given mem addr */ 224int 225siprobe(id) 226 struct isa_device *id; 227{ 228 struct si_softc *sc; 229 int type; 230 u_int i, ramsize; 231 volatile BYTE was, *ux; 232 volatile unsigned char *maddr; 233 unsigned char *paddr; 234 235 si_registerdev(id); 236 237 maddr = id->id_maddr; /* virtual address... */ 238 paddr = (caddr_t)vtophys(id->id_maddr); /* physical address... */ 239 240 DPRINT((0, DBG_AUTOBOOT, "SLXOS probe at virtual=0x%x physical=0x%x\n", 241 id->id_maddr, paddr)); 242 243 /* 244 * this is a lie, but it's easier than trying to handle caching 245 * and ram conflicts in the >1M and <16M region. 246 */ 247 if ((caddr_t)paddr < (caddr_t)IOM_BEGIN || 248 (caddr_t)paddr >= (caddr_t)IOM_END) { 249 printf("si%d: iomem (%x) out of range\n", 250 id->id_unit, paddr); 251 return(0); 252 } 253 254 if (id->id_unit >= NSI) { 255 /* THIS IS IMPOSSIBLE */ 256 return(0); 257 } 258 259 if (((u_int)paddr & 0x7fff) != 0) { 260 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 261 "si%d: iomem (%x) not on 32k boundary\n", 262 id->id_unit, paddr)); 263 return(0); 264 } 265 266 267 for (i=0; i < NSI; i++) { 268 if ((sc = &si_softc[i]) == NULL) 269 continue; 270 if ((caddr_t)sc->sc_paddr == (caddr_t)paddr) { 271 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 272 "si%d: iomem (%x) already configured to si%d\n", 273 id->id_unit, sc->sc_paddr, i)); 274 return(0); 275 } 276 } 277 278#if NEISA > 0 279 if (id->id_iobase > 0x0fff) { /* EISA card */ 280 int irq, port; 281 unsigned long base; 282 int eisa_irqs[] = { 0,IRQ1,IRQ2,IRQ3,IRQ4,IRQ5,IRQ6,IRQ7, 283 IRQ8,IRQ9,IRQ10,IRQ11,IRQ12,IRQ13,IRQ14,IRQ15 }; 284 285 port = id->id_iobase; 286 base = (inb(port+1) << 24) | (inb(port) << 16); 287 irq = ((inb(port+2) >> 4) & 0xf); 288 289 id->id_irq = eisa_irqs[irq]; 290 291 DPRINT((0, DBG_AUTOBOOT, 292 "SLXOS: si%d: EISA base %x, irq %x, id_irq %x, port %x\n", 293 id->id_unit, base, irq, id->id_irq, port)); 294 295 if ((id->id_irq&(IRQ1|IRQ2|IRQ8|IRQ13)) != 0) 296 goto bad_irq; 297 298 id->id_iobase &= 0xf000; 299 id->id_iosize = 0x0fff; 300 301 type = EISA; 302 outb(p+2, (BYTE)irq << 4); 303 304 sc->sc_eisa_iobase = p; 305 sc->sc_eisa_irqbits = irq << 4; 306 ramsize = SIEISA_RAMSIZE; 307 goto got_card; 308 } 309#endif 310 311 /* Is there anything out there? (0x17 is just an arbitrary number) */ 312 *maddr = 0x17; 313 if (*maddr != 0x17) { 314 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 315 "si%d: 0x17 check fail at phys 0x%x\n", 316 id->id_unit, paddr)); 317fail: 318 return(0); 319 } 320 /* 321 * OK, now to see if whatever responded is really an SI card. 322 * Try for a MK II first (SIHOST2) 323 */ 324 for (i=SIPLSIG; i<SIPLSIG+8; i++) 325 if ((*(maddr+i) & 7) != (~(BYTE)i & 7)) 326 goto try_mk1; 327 328 /* It must be an SIHOST2 */ 329 *(maddr + SIPLRESET) = 0; 330 *(maddr + SIPLIRQCLR) = 0; 331 *(maddr + SIPLIRQSET) = 0x10; 332 type = SIHOST2; 333 ramsize = SIHOST2_RAMSIZE; 334 goto got_card; 335 336 /* 337 * Its not a MK II, so try for a MK I (SIHOST) 338 */ 339try_mk1: 340 *(maddr+SIRESET) = 0x0; /* reset the card */ 341 *(maddr+SIINTCL) = 0x0; /* clear int */ 342 *(maddr+SIRAM) = 0x17; 343 if (*(maddr+SIRAM) != (BYTE)0x17) 344 goto fail; 345 *(maddr+0x7ff8) = 0x17; 346 if (*(maddr+0x7ff8) != (BYTE)0x17) { 347 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 348 "si%d: 0x17 check fail at phys 0x%x = 0x%x\n", 349 id->id_unit, paddr+0x77f8, *(maddr+0x77f8))); 350 goto fail; 351 } 352 353 /* It must be an SIHOST (maybe?) - there must be a better way XXXX */ 354 type = SIHOST; 355 ramsize = SIHOST_RAMSIZE; 356 357got_card: 358 DPRINT((0, DBG_AUTOBOOT, "SLXOS: found type %d card, try memory test\n", type)); 359 /* Try the acid test */ 360 ux = (BYTE *)(maddr + SIRAM); 361 for (i=0; i<ramsize; i++, ux++) 362 *ux = (BYTE)(i&0xff); 363 ux = (BYTE *)(maddr + SIRAM); 364 for (i=0; i<ramsize; i++, ux++) { 365 if ((was = *ux) != (BYTE)(i&0xff)) { 366 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 367 "SLXOS si%d: match fail at phys 0x%x, was %x should be %x\n", 368 id->id_unit, paddr+i, was, i&0xff)); 369 goto fail; 370 } 371 } 372 373 /* clear out the RAM */ 374 ux = (BYTE *)(maddr + SIRAM); 375 for (i=0; i<ramsize; i++) 376 *ux++ = 0; 377 ux = (BYTE *)(maddr + SIRAM); 378 for (i=0; i<ramsize; i++) { 379 if ((was = *ux++) != 0) { 380 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 381 "SLXOS si%d: clear fail at phys 0x%x, was %x\n", 382 id->id_unit, paddr+i, was)); 383 goto fail; 384 } 385 } 386 387 /* 388 * Success, we've found a valid board, now fill in 389 * the adapter structure. 390 */ 391 switch (type) { 392 case SIHOST2: 393 if ((id->id_irq&(IRQ11|IRQ12|IRQ15)) == 0) { 394bad_irq: 395 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL, 396 "si%d: bad IRQ value - %d\n", 397 id->id_unit, id->id_irq)); 398 return(0); 399 } 400 id->id_msize = SIHOST2_MEMSIZE; 401 break; 402 case SIHOST: 403 if ((id->id_irq&(IRQ11|IRQ12|IRQ15)) == 0) { 404 goto bad_irq; 405 } 406 id->id_msize = SIHOST_MEMSIZE; 407 break; 408 case SIEISA: 409 id->id_msize = SIEISA_MEMSIZE; 410 break; 411 case SI2: /* MCA */ 412 default: 413 printf("si%d: %s not supported\n", id->id_unit, si_type[type]); 414 return(0); 415 } 416 si_softc[id->id_unit].sc_type = type; 417 si_softc[id->id_unit].sc_typename = si_type[type]; 418 return(-1); /* -1 == found */ 419} 420 421/* 422 * Attach the device. Initialize the card. 423 */ 424int 425siattach(id) 426 struct isa_device *id; 427{ 428 int unit = id->id_unit; 429 struct si_softc *sc = &si_softc[unit]; 430 struct si_port *pp; 431 volatile struct si_channel *ccbp; 432 volatile struct si_reg *regp; 433 volatile caddr_t maddr; 434 struct si_module *modp; 435 struct tty *tp; 436 struct speedtab *spt; 437 int nmodule, nport, x, y; 438 439 DPRINT((0, DBG_AUTOBOOT, "SLXOS siattach\n")); 440 441 sc->sc_paddr = (caddr_t)vtophys(id->id_maddr); 442 sc->sc_maddr = id->id_maddr; 443 sc->sc_irq = id->id_irq; 444 445 sc->sc_ports = NULL; /* mark as uninitialised */ 446 447 maddr = sc->sc_maddr; 448 449 /* 450 * OK, now lets download the firmware and try and boot the CPU.. 451 */ 452 453 DPRINT((0, DBG_DOWNLOAD, "SLXOS si_download: nbytes %d\n", si_dsize)); 454 bcopy(si_download, maddr, si_dsize); 455 456 switch (sc->sc_type) { 457 case SIEISA: 458#if NEISA > 0 459 /* modify the Z280 firmware to tell it that it's on an EISA */ 460 *(maddr+0x42) = 1; 461 outb(sc->sc_eisa_iobase+2, sc->sc_eisa_irqbits | 4); 462 (void)inb(sc->sc_eisa_iobase+3); /* reset interrupt */ 463 break; 464#endif /* fall-through if not EISA */ 465 case SI2: 466 /* must get around to writing the code for 467 * these one day */ 468 return 0; 469 case SIHOST: 470 *(maddr+SIRESET_CL) = 0; 471 *(maddr+SIINTCL_CL) = 0; 472 break; 473 case SIHOST2: 474 *(maddr+SIPLRESET) = 0x10; 475 switch (sc->sc_irq) { 476 case IRQ11: 477 *(maddr+SIPLIRQ11) = 0x10; 478 break; 479 case IRQ12: 480 *(maddr+SIPLIRQ12) = 0x10; 481 break; 482 case IRQ15: 483 *(maddr+SIPLIRQ15) = 0x10; 484 break; 485 } 486 *(maddr+SIPLIRQCLR) = 0x10; 487 break; 488 } 489 490 DELAY(1000000); /* wait around for a second */ 491 492 regp = (struct si_reg *)maddr; 493 y = 0; 494 /* wait max of 5 sec for init OK */ 495 while (regp->initstat == 0 && y++ < 10) { 496 DELAY(500000); 497 } 498 switch (regp->initstat) { 499 case 0: 500 printf("si%d: startup timeout - aborting\n", unit); 501 sc->sc_type = NULL; 502 return 0; 503 case 1: 504 /* set throttle to 100 intr per second */ 505 regp->int_count = 25000; 506 /* rx intr max of 25 timer per second */ 507 regp->rx_int_count = 4; 508 regp->int_pending = 0; /* no intr pending */ 509 regp->int_scounter = 0; /* reset counter */ 510 break; 511 case 0xff: 512 /* 513 * No modules found, so give up on this one. 514 */ 515 printf("si%d: %s - no ports found\n", unit, 516 si_type[sc->sc_type]); 517 return 0; 518 default: 519 printf("si%d: Z280 version error - initstat %x\n", 520 unit, regp->initstat); 521 return 0; 522 } 523 524 /* 525 * First time around the ports just count them in order 526 * to allocate some memory. 527 */ 528 nport = 0; 529 modp = (struct si_module *)(maddr + 0x80); 530 for (;;) { 531 DPRINT((0, DBG_DOWNLOAD, "SLXOS si%d: ccb addr 0x%x\n", unit, modp)); 532 switch (modp->sm_type & (~MMASK)) { 533 case M232: 534 case M422: 535 DPRINT((0, DBG_DOWNLOAD, 536 "SLXOS si%d: Found 232/422 module, %d ports\n", 537 unit, (int)(modp->sm_type & MMASK))); 538 539 /* this is a firmware issue */ 540 if (si_Nports == SI_MAXPORTPERCARD) { 541 printf("si%d: extra ports ignored\n", unit); 542 continue; 543 } 544 545 x = modp->sm_type & MMASK; 546 nport += x; 547 si_Nports += x; 548 si_Nmodules++; 549 break; 550 default: 551 printf("si%d: unknown module type %d\n", 552 unit, modp->sm_type); 553 break; 554 } 555 if (modp->sm_next == 0) 556 break; 557 modp = (struct si_module *) 558 (maddr + (unsigned)(modp->sm_next & 0x7fff)); 559 } 560 sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport, 561 M_DEVBUF, M_NOWAIT); 562 if (sc->sc_ports == 0) { 563mem_fail: 564 printf("si%d: fail to malloc memory for port structs\n", 565 unit); 566 return 0; 567 } 568 bzero(sc->sc_ports, sizeof(struct si_port) * nport); 569 sc->sc_nport = nport; 570 571 /* 572 * allocate tty structures for ports 573 */ 574 tp = (struct tty *)malloc(sizeof(*tp) * nport, M_DEVBUF, M_NOWAIT); 575 if (tp == 0) 576 goto mem_fail; 577 bzero(tp, sizeof(*tp) * nport); 578 579 /* mark the device state as attached */ 580 si_kdc[unit].kdc_state = DC_BUSY; 581 582 /* 583 * Scan round the ports again, this time initialising. 584 */ 585 pp = sc->sc_ports; 586 nmodule = 0; 587 modp = (struct si_module *)(maddr + 0x80); 588 for (;;) { 589 switch (modp->sm_type & (~MMASK)) { 590 case M232: 591 case M422: 592 nmodule++; 593 nport = (modp->sm_type & MMASK); 594 ccbp = (struct si_channel *)((char *)modp+0x100); 595 for (x = 0; x < nport; x++, pp++, ccbp++) { 596 pp->sp_ccb = ccbp; /* save the address */ 597 pp->sp_tty = tp++; 598 pp->sp_pend = IDLE_CLOSE; 599 pp->sp_flags = 0; 600 pp->sp_state = 0; /* internal flag */ 601 pp->sp_dtr_wait = 3 * hz; 602 pp->sp_iin.c_iflag = si_default_iflag; 603 pp->sp_iin.c_oflag = si_default_oflag; 604 pp->sp_iin.c_cflag = si_default_cflag; 605 pp->sp_iin.c_lflag = si_default_lflag; 606 termioschars(&pp->sp_iin); 607 pp->sp_iin.c_ispeed = pp->sp_iin.c_ospeed = 608 si_default_rate; 609 pp->sp_iout = pp->sp_iin; 610 } 611 break; 612 default: 613 break; 614 } 615 if (modp->sm_next == 0) { 616 printf("si%d: %s, ports: %d, modules: %d\n", 617 unit, 618 sc->sc_typename, 619 sc->sc_nport, 620 nmodule); 621 break; 622 } 623 modp = (struct si_module *) 624 (maddr + (unsigned)(modp->sm_next & 0x7fff)); 625 } 626 if (done_chartimes == 0) { 627 for (spt = chartimes ; spt->sp_speed != -1; spt++) { 628 if ((spt->sp_code /= hz) == 0) 629 spt->sp_code = 1; 630 } 631 done_chartimes = 1; 632 633/* tell them where we stand.. */ 634printf("\ 635si%d: -------------------USE AT YOUR OWN RISK!!!!--------------------\n\ 636si%d: WARNING!! THIS DRIVER IS NOT COMPLETE NOR SUFFICIENTLY TESTED!!\n\ 637si%d: -------------------USE AT YOUR OWN RISK!!!!--------------------\n\ 638", unit, unit, unit); 639 640 } 641 return (1); 642} 643 644struct isa_driver sidriver = 645 { siprobe, siattach, "si" }; 646 647 648int 649siopen(dev, flag, mode, p) 650 dev_t dev; 651 int flag, mode; 652 struct proc *p; 653{ 654 int oldspl, error; 655 int card, port; 656 register struct si_softc *sc; 657 register struct tty *tp; 658 volatile struct si_channel *ccbp; 659 struct si_port *pp; 660 int mynor = minor(dev); 661 662 /* quickly let in /dev/si_control */ 663 if (IS_CONTROLDEV(mynor)) { 664 if (error = suser(p->p_ucred, &p->p_acflag)) 665 return(error); 666 return(0); 667 } 668 669 card = SI_CARD(mynor); 670 if (card >= NSI) 671 return (ENXIO); 672 sc = &si_softc[card]; 673 674 if (sc->sc_type == NULL) { 675 DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: type %s??\n", 676 card, sc->sc_typename)); 677 return(ENXIO); 678 } 679 680 port = SI_PORT(mynor); 681 if (port >= sc->sc_nport) { 682 DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: nports %d\n", 683 card, sc->sc_nport)); 684 return(ENXIO); 685 } 686 687#ifdef POLL 688 /* 689 * We've now got a device, so start the poller. 690 */ 691 if (init_finished == 0) { 692 timeout(si_poll, (caddr_t)0L, POLL_INTERVAL); 693 init_finished = 1; 694 } 695#endif 696 697 /* initial/lock device */ 698 if (IS_STATE(mynor)) { 699 return(0); 700 } 701 702 pp = sc->sc_ports + port; 703 tp = pp->sp_tty; /* the "real" tty */ 704 ccbp = pp->sp_ccb; /* Find control block */ 705 DPRINT((pp, DBG_ENTRY|DBG_OPEN, "siopen(%x,%x,%x,%x)\n", 706 dev, flag, mode, p)); 707 708 oldspl = spltty(); /* Keep others out */ 709 error = 0; 710 711open_top: 712 while (pp->sp_state & SS_DTR_OFF) { 713 error = tsleep(&pp->sp_dtr_wait, TTIPRI|PCATCH, "sidtr", 0); 714 if (error != 0) 715 goto out; 716 } 717 718 if (tp->t_state & TS_ISOPEN) { 719 /* 720 * The device is open, so everything has been initialised. 721 * handle conflicts. 722 */ 723 if (IS_CALLOUT(mynor)) { 724 if (!pp->sp_active_out) { 725 error = EBUSY; 726 goto out; 727 } 728 } else { 729 if (pp->sp_active_out) { 730 if (flag & O_NONBLOCK) { 731 error = EBUSY; 732 goto out; 733 } 734 error = tsleep(&pp->sp_active_out, 735 TTIPRI|PCATCH, "sibi", 0); 736 if (error != 0) 737 goto out; 738 goto open_top; 739 } 740 } 741 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 742 DPRINT((pp, DBG_OPEN|DBG_FAIL, 743 "already open and EXCLUSIVE set\n")); 744 error = EBUSY; 745 goto out; 746 } 747 } else { 748 /* 749 * The device isn't open, so there are no conflicts. 750 * Initialize it. Avoid sleep... :-) 751 */ 752 DPRINT((pp, DBG_OPEN, "first open\n")); 753 tp->t_oproc = si_start; 754 tp->t_param = siparam; 755 tp->t_dev = dev; 756 tp->t_termios = mynor & SI_CALLOUT_MASK 757 ? pp->sp_iout : pp->sp_iin; 758 759 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS); 760 761 ++pp->sp_wopeners; /* in case of sleep in siparam */ 762 763 error = siparam(tp, &tp->t_termios); 764 765 --pp->sp_wopeners; 766 if (error != 0) 767 goto out; 768 /* XXX: we should goto_top if siparam slept */ 769 770 ttsetwater(tp); 771 772 /* set initial DCD state */ 773 pp->sp_last_hi_ip = ccbp->hi_ip; 774 if ((pp->sp_last_hi_ip & IP_DCD) || IS_CALLOUT(mynor)) { 775 (*linesw[tp->t_line].l_modem)(tp, 1); 776 } 777 } 778 779 /* whoops! we beat the close! */ 780 if (pp->sp_state & SS_CLOSING) { 781 /* try and stop it from proceeding to bash the hardware */ 782 pp->sp_state &= ~SS_CLOSING; 783 } 784 785 /* 786 * Wait for DCD if necessary 787 */ 788 if (!(tp->t_state & TS_CARR_ON) 789 && !IS_CALLOUT(mynor) 790 && !(tp->t_cflag & CLOCAL) 791 && !(flag & O_NONBLOCK)) { 792 ++pp->sp_wopeners; 793 DPRINT((pp, DBG_OPEN, "sleeping for carrier\n")); 794 error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "sidcd", 0); 795 --pp->sp_wopeners; 796 if (error != 0) 797 goto out; 798 goto open_top; 799 } 800 801 error = (*linesw[tp->t_line].l_open)(dev, tp); 802 si_disc_optim(tp, &tp->t_termios, pp); 803 if (tp->t_state & TS_ISOPEN && IS_CALLOUT(mynor)) 804 pp->sp_active_out = TRUE; 805 806 pp->sp_state |= SS_OPEN; /* made it! */ 807 808out: 809 splx(oldspl); 810 811 DPRINT((pp, DBG_OPEN, "leaving siopen\n")); 812 813 if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0) 814 sihardclose(pp); 815 816 return(error); 817} 818 819int 820siclose(dev, flag, mode, p) 821 dev_t dev; 822 int flag, mode; 823 struct proc *p; 824{ 825 register struct si_port *pp; 826 register struct tty *tp; 827 int oldspl; 828 int error = 0; 829 int mynor = minor(dev); 830 831 if (IS_SPECIAL(mynor)) 832 return(0); 833 834 oldspl = spltty(); 835 836 pp = MINOR2PP(mynor); 837 tp = pp->sp_tty; 838 839 DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "siclose(%x,%x,%x,%x) sp_state:%x\n", 840 dev, flag, mode, p, pp->sp_state)); 841 842 /* did we sleep and loose a race? */ 843 if (pp->sp_state & SS_CLOSING) { 844 /* error = ESOMETING? */ 845 goto out; 846 } 847 848 /* begin race detection.. */ 849 pp->sp_state |= SS_CLOSING; 850 851 si_write_enable(pp, 0); /* block writes for ttywait() */ 852 853 /* THIS MAY SLEEP IN TTYWAIT!!! */ 854 (*linesw[tp->t_line].l_close)(tp, flag); 855 856 si_write_enable(pp, 1); 857 858 /* did we sleep and somebody started another open? */ 859 if (!(pp->sp_state & SS_CLOSING)) { 860 /* error = ESOMETING? */ 861 goto out; 862 } 863 /* ok. we are now still on the right track.. nuke the hardware */ 864 865 if (pp->sp_state & SS_LSTART) { 866 untimeout((timeout_func_t)si_lstart, (caddr_t)pp); 867 pp->sp_state &= ~SS_LSTART; 868 } 869 870 sistop(tp, FREAD | FWRITE); 871 872 sihardclose(pp); 873 ttyclose(tp); 874 pp->sp_state &= ~SS_OPEN; 875 876out: 877 DPRINT((pp, DBG_CLOSE|DBG_EXIT, "close done, returning\n")); 878 splx(oldspl); 879 return(error); 880} 881 882static void 883sihardclose(pp) 884 struct si_port *pp; 885{ 886 int oldspl; 887 struct tty *tp; 888 volatile struct si_channel *ccbp; 889 890 oldspl = spltty(); 891 892 tp = pp->sp_tty; 893 ccbp = pp->sp_ccb; /* Find control block */ 894 if (tp->t_cflag & HUPCL 895 || !pp->sp_active_out 896 && !(ccbp->hi_ip & IP_DCD) 897 && !(pp->sp_iin.c_cflag && CLOCAL) 898 || !(tp->t_state & TS_ISOPEN)) { 899 900 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS); 901 (void) si_command(pp, FCLOSE, SI_NOWAIT); 902 903 if (pp->sp_dtr_wait != 0) { 904 timeout(sidtrwakeup, pp, pp->sp_dtr_wait); 905 pp->sp_state |= SS_DTR_OFF; 906 } 907 908 } 909 pp->sp_active_out = FALSE; 910 wakeup((caddr_t)&pp->sp_active_out); 911 wakeup(TSA_CARR_ON(tp)); 912 913 splx(oldspl); 914} 915 916 917/* 918 * called at splsoftclock()... 919 */ 920static void 921sidtrwakeup(chan) 922 void *chan; 923{ 924 struct si_port *pp; 925 int oldspl; 926 927 oldspl = spltty(); 928 929 pp = (struct si_port *)chan; 930 pp->sp_state &= ~SS_DTR_OFF; 931 wakeup(&pp->sp_dtr_wait); 932 933 splx(oldspl); 934} 935 936/* 937 * User level stuff - read and write 938 */ 939int 940siread(dev, uio, flag) 941 register dev_t dev; 942 struct uio *uio; 943 int flag; 944{ 945 register struct tty *tp; 946 int mynor = minor(dev); 947 948 if (IS_SPECIAL(mynor)) { 949 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_READ, "siread(CONTROLDEV!!)\n")); 950 return(ENODEV); 951 } 952 tp = MINOR2TP(mynor); 953 DPRINT((TP2PP(tp), DBG_ENTRY|DBG_READ, 954 "siread(%x,%x,%x)\n", dev, uio, flag)); 955 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 956} 957 958 959int 960siwrite(dev, uio, flag) 961 dev_t dev; 962 struct uio *uio; 963 int flag; 964{ 965 register struct si_port *pp; 966 register struct tty *tp; 967 int error = 0; 968 int mynor = minor(dev); 969 int oldspl; 970 971 if (IS_SPECIAL(mynor)) { 972 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_WRITE, "siwrite(CONTROLDEV!!)\n")); 973 return(ENODEV); 974 } 975 pp = MINOR2PP(mynor); 976 tp = pp->sp_tty; 977 DPRINT((pp, DBG_WRITE, "siwrite(%x,%x,%x)\n", dev, uio, flag)); 978 979 oldspl = spltty(); 980 /* 981 * If writes are currently blocked, wait on the "real" tty 982 */ 983 while (pp->sp_state & SS_BLOCKWRITE) { 984 pp->sp_state |= SS_WAITWRITE; 985 DPRINT((pp, DBG_WRITE, "in siwrite, wait for SS_BLOCKWRITE to clear\n")); 986 if (error = ttysleep(tp, (caddr_t)pp, TTOPRI|PCATCH, 987 "siwrite", 0)) 988 goto out; 989 } 990 991 error = (*linesw[tp->t_line].l_write)(tp, uio, flag); 992out: 993 splx(oldspl); 994 return (error); 995} 996 997 998struct tty * 999sidevtotty(dev_t dev) 1000{ 1001 struct si_port *pp; 1002 int mynor = minor(dev); 1003 struct si_softc *sc = &si_softc[SI_CARD(mynor)]; 1004 1005 if (IS_SPECIAL(mynor)) 1006 return(NULL); 1007 if (SI_PORT(mynor) >= sc->sc_nport) 1008 return(NULL); 1009 pp = MINOR2PP(mynor); 1010 return (pp->sp_tty); 1011} 1012 1013int 1014siioctl(dev, cmd, data, flag, p) 1015 dev_t dev; 1016 int cmd; 1017 caddr_t data; 1018 int flag; 1019 struct proc *p; 1020{ 1021 struct si_port *pp; 1022 register struct tty *tp; 1023 int error; 1024 int mynor = minor(dev); 1025 int oldspl; 1026 int blocked = 0; 1027#if defined(COMPAT_43) 1028 int oldcmd; 1029 struct termios term; 1030#endif 1031 1032 if (IS_SI_IOCTL(cmd)) 1033 return(si_Sioctl(dev, cmd, data, flag, p)); 1034 1035 pp = MINOR2PP(mynor); 1036 tp = pp->sp_tty; 1037 1038 DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "siioctl(%x,%x,%x,%x)\n", 1039 dev, cmd, data, flag)); 1040 if (IS_STATE(mynor)) { 1041 struct termios *ct; 1042 1043 switch (mynor & SI_STATE_MASK) { 1044 case SI_INIT_STATE_MASK: 1045 ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin; 1046 break; 1047 case SI_LOCK_STATE_MASK: 1048 ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin; 1049 break; 1050 default: 1051 return (ENODEV); 1052 } 1053 switch (cmd) { 1054 case TIOCSETA: 1055 error = suser(p->p_ucred, &p->p_acflag); 1056 if (error != 0) 1057 return (error); 1058 *ct = *(struct termios *)data; 1059 return (0); 1060 case TIOCGETA: 1061 *(struct termios *)data = *ct; 1062 return (0); 1063 case TIOCGETD: 1064 *(int *)data = TTYDISC; 1065 return (0); 1066 case TIOCGWINSZ: 1067 bzero(data, sizeof(struct winsize)); 1068 return (0); 1069 default: 1070 return (ENOTTY); 1071 } 1072 } 1073 /* 1074 * Do the old-style ioctl compat routines... 1075 */ 1076#if defined(COMPAT_43) 1077 term = tp->t_termios; 1078 oldcmd = cmd; 1079 error = ttsetcompat(tp, &cmd, data, &term); 1080 if (error != 0) 1081 return (error); 1082 if (cmd != oldcmd) 1083 data = (caddr_t)&term; 1084#endif 1085 /* 1086 * Do the initial / lock state business 1087 */ 1088 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1089 int cc; 1090 struct termios *dt = (struct termios *)data; 1091 struct termios *lt = mynor & SI_CALLOUT_MASK 1092 ? &pp->sp_lout : &pp->sp_lin; 1093 1094 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1095 | (dt->c_iflag & ~lt->c_iflag); 1096 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1097 | (dt->c_oflag & ~lt->c_oflag); 1098 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1099 | (dt->c_cflag & ~lt->c_cflag); 1100 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1101 | (dt->c_lflag & ~lt->c_lflag); 1102 for (cc = 0; cc < NCCS; ++cc) 1103 if (lt->c_cc[cc] != 0) 1104 dt->c_cc[cc] = tp->t_cc[cc]; 1105 if (lt->c_ispeed != 0) 1106 dt->c_ispeed = tp->t_ispeed; 1107 if (lt->c_ospeed != 0) 1108 dt->c_ospeed = tp->t_ospeed; 1109 } 1110 1111 /* 1112 * Block user-level writes to give the ttywait() 1113 * a chance to completely drain for commands 1114 * that require the port to be in a quiescent state. 1115 */ 1116 switch (cmd) { 1117 case TIOCSETAW: case TIOCSETAF: 1118 case TIOCDRAIN: case TIOCSETP: 1119 blocked++; /* block writes for ttywait() and siparam() */ 1120 si_write_enable(pp, 0); 1121 } 1122 1123 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1124 if (error >= 0) 1125 goto out; 1126 1127 oldspl = spltty(); 1128 1129 error = ttioctl(tp, cmd, data, flag); 1130 si_disc_optim(tp, &tp->t_termios, pp); 1131 if (error >= 0) 1132 goto outspl; 1133 1134 switch (cmd) { 1135 case TIOCSBRK: 1136 si_command(pp, SBREAK, SI_NOWAIT); 1137 break; 1138 case TIOCCBRK: 1139 si_command(pp, EBREAK, SI_NOWAIT); 1140 break; 1141 case TIOCSDTR: 1142 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS); 1143 break; 1144 case TIOCCDTR: 1145 (void) si_modem(pp, SET, 0); 1146 break; 1147 case TIOCMSET: 1148 (void) si_modem(pp, SET, *(int *)data); 1149 break; 1150 case TIOCMBIS: 1151 (void) si_modem(pp, BIS, *(int *)data); 1152 break; 1153 case TIOCMBIC: 1154 (void) si_modem(pp, BIC, *(int *)data); 1155 break; 1156 case TIOCMGET: 1157 *(int *)data = si_modem(pp, GET, 0); 1158 break; 1159 case TIOCMSDTRWAIT: 1160 /* must be root since the wait applies to following logins */ 1161 error = suser(p->p_ucred, &p->p_acflag); 1162 if (error != 0) { 1163 goto outspl; 1164 } 1165 pp->sp_dtr_wait = *(int *)data * hz / 100; 1166 break; 1167 case TIOCMGDTRWAIT: 1168 *(int *)data = pp->sp_dtr_wait * 100 / hz; 1169 break; 1170 1171 default: 1172 error = ENOTTY; 1173 } 1174 error = 0; 1175outspl: 1176 splx(oldspl); 1177out: 1178 DPRINT((pp, DBG_IOCTL|DBG_EXIT, "siioctl ret %d\n", error)); 1179 if (blocked) 1180 si_write_enable(pp, 1); 1181 return(error); 1182} 1183 1184/* 1185 * Handle the Specialix ioctls. All MUST be called via the CONTROL device 1186 */ 1187static int 1188si_Sioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 1189{ 1190 struct si_softc *xsc; 1191 register struct si_port *xpp; 1192 volatile struct si_reg *regp; 1193 struct si_tcsi *dp; 1194 struct si_pstat *sps; 1195 BYTE *bp; 1196 int i, *ip, error = 0; 1197 int oldspl; 1198 int card, port; 1199 unsigned short *usp; 1200 int mynor = minor(dev); 1201 1202 DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%x,%x,%x,%x)\n", 1203 dev, cmd, data, flag)); 1204 1205#if 1 1206 DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT)); 1207 DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB)); 1208 DPRINT((0, DBG_IOCTL, "TCSI_TTY=%x\n", TCSI_TTY)); 1209#endif 1210 1211 if (!IS_CONTROLDEV(mynor)) { 1212 DPRINT((0, DBG_IOCTL|DBG_FAIL, "not called from control device!\n")); 1213 return(ENODEV); 1214 } 1215 1216 oldspl = spltty(); /* better safe than sorry */ 1217 1218 ip = (int *)data; 1219 1220#define SUCHECK if (error = suser(p->p_ucred, &p->p_acflag)) goto out 1221 1222 switch (cmd) { 1223 case TCSIPORTS: 1224 *ip = si_Nports; 1225 goto out; 1226 case TCSIMODULES: 1227 *ip = si_Nmodules; 1228 goto out; 1229 case TCSISDBG_ALL: 1230 SUCHECK; 1231 si_debug = *ip; 1232 goto out; 1233 case TCSIGDBG_ALL: 1234 *ip = si_debug; 1235 goto out; 1236 default: 1237 /* 1238 * Check that a controller for this port exists 1239 */ 1240 1241 /* may also be a struct si_pstat, a superset of si_tcsi */ 1242 1243 dp = (struct si_tcsi *)data; 1244 sps = (struct si_pstat *)data; 1245 card = dp->tc_card; 1246 xsc = &si_softc[card]; /* check.. */ 1247 if (card < 0 || card >= NSI || xsc->sc_type == NULL) { 1248 error = ENOENT; 1249 goto out; 1250 } 1251 /* 1252 * And check that a port exists 1253 */ 1254 port = dp->tc_port; 1255 if (port < 0 || port >= xsc->sc_nport) { 1256 error = ENOENT; 1257 goto out; 1258 } 1259 xpp = xsc->sc_ports + port; 1260 regp = (struct si_reg *)xsc->sc_maddr; 1261 } 1262 1263 switch (cmd) { 1264 case TCSIDEBUG: 1265#ifdef SI_DEBUG 1266 SUCHECK; 1267 if (xpp->sp_debug) 1268 xpp->sp_debug = 0; 1269 else { 1270 xpp->sp_debug = DBG_ALL; 1271 DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n", 1272 (xpp->sp_debug&DBG_ALL)?"ON":"OFF")); 1273 } 1274 break; 1275#else 1276 error = ENODEV; 1277 goto out; 1278#endif 1279 case TCSISDBG_LEVEL: 1280 case TCSIGDBG_LEVEL: 1281#ifdef SI_DEBUG 1282 if (cmd == TCSIGDBG_LEVEL) { 1283 dp->tc_dbglvl = xpp->sp_debug; 1284 } else { 1285 SUCHECK; 1286 xpp->sp_debug = dp->tc_dbglvl; 1287 } 1288 break; 1289#else 1290 error = ENODEV; 1291 goto out; 1292#endif 1293 case TCSIGRXIT: 1294 dp->tc_int = regp->rx_int_count; 1295 break; 1296 case TCSIRXIT: 1297 SUCHECK; 1298 regp->rx_int_count = dp->tc_int; 1299 break; 1300 case TCSIGIT: 1301 dp->tc_int = regp->int_count; 1302 break; 1303 case TCSIIT: 1304 SUCHECK; 1305 regp->int_count = dp->tc_int; 1306 break; 1307 case TCSISTATE: 1308 dp->tc_int = xpp->sp_ccb->hi_ip; 1309 break; 1310 /* these next three use a different structure */ 1311 case TCSI_PORT: 1312 SUCHECK; 1313 sps->tc_siport = *xpp; 1314 break; 1315 case TCSI_CCB: 1316 SUCHECK; 1317 sps->tc_ccb = *xpp->sp_ccb; 1318 break; 1319 case TCSI_TTY: 1320 SUCHECK; 1321 sps->tc_tty = *xpp->sp_tty; 1322 break; 1323 default: 1324 error = EINVAL; 1325 goto out; 1326 } 1327out: 1328 splx(oldspl); 1329 return(error); /* success */ 1330} 1331 1332/* 1333 * siparam() : Configure line params 1334 * called at spltty(); 1335 * this may sleep, does not flush, nor wait for drain, nor block writes 1336 * caller must arrange this if it's important.. 1337 */ 1338int 1339siparam(tp, t) 1340 register struct tty *tp; 1341 register struct termios *t; 1342{ 1343 register struct si_port *pp = TP2PP(tp); 1344 volatile struct si_channel *ccbp; 1345 int oldspl, cflag, iflag, oflag, lflag; 1346 int error = 0; /* shutup gcc */ 1347 int ispeed = 0; /* shutup gcc */ 1348 int ospeed = 0; /* shutup gcc */ 1349 BYTE val; 1350 1351 DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t)); 1352 cflag = t->c_cflag; 1353 iflag = t->c_iflag; 1354 oflag = t->c_oflag; 1355 lflag = t->c_lflag; 1356 DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n", 1357 oflag, cflag, iflag, lflag)); 1358 1359 1360 /* if not hung up.. */ 1361 if (t->c_ospeed != 0) { 1362 /* translate baud rate to firmware values */ 1363 ospeed = ttspeedtab(t->c_ospeed, bdrates); 1364 ispeed = t->c_ispeed ? 1365 ttspeedtab(t->c_ispeed, bdrates) : ospeed; 1366 1367 /* enforce legit baud rate */ 1368 if (ospeed < 0 || ispeed < 0) 1369 return (EINVAL); 1370 } 1371 1372 1373 oldspl = spltty(); 1374 1375 ccbp = pp->sp_ccb; 1376 1377 /* ========== set hi_break ========== */ 1378 val = 0; 1379 if (iflag & IGNBRK) /* Breaks */ 1380 val |= BR_IGN; 1381 if (iflag & BRKINT) /* Interrupt on break? */ 1382 val |= BR_INT; 1383 if (iflag & PARMRK) /* Parity mark? */ 1384 val |= BR_PARMRK; 1385 if (iflag & IGNPAR) /* Ignore chars with parity errors? */ 1386 val |= BR_PARIGN; 1387 ccbp->hi_break = val; 1388 1389 /* ========== set hi_csr ========== */ 1390 /* if not hung up.. */ 1391 if (t->c_ospeed != 0) { 1392 /* Set I/O speeds */ 1393 val = (ispeed << 4) | ospeed; 1394 } 1395 ccbp->hi_csr = val; 1396 1397 /* ========== set hi_mr2 ========== */ 1398 val = 0; 1399 if (cflag & CSTOPB) /* Stop bits */ 1400 val |= MR2_2_STOP; 1401 else 1402 val |= MR2_1_STOP; 1403 /* 1404 * Enable H/W RTS/CTS handshaking. The default TA/MTA is 1405 * a DCE, hence the reverse sense of RTS and CTS 1406 */ 1407 /* Output Flow - RTS must be raised before data can be sent */ 1408 if (cflag & CCTS_OFLOW) 1409 val |= MR2_RTSCONT; 1410 1411 ccbp->hi_mr1 = val; 1412 1413 /* ========== set hi_mr1 ========== */ 1414 val = 0; 1415 if (!(cflag & PARENB)) /* Parity */ 1416 val |= MR1_NONE; 1417 else 1418 val |= MR1_WITH; 1419 if (cflag & PARODD) 1420 val |= MR1_ODD; 1421 1422 if ((cflag & CS8) == CS8) { /* 8 data bits? */ 1423 val |= MR1_8_BITS; 1424 } else if ((cflag & CS7) == CS7) { /* 7 data bits? */ 1425 val |= MR1_7_BITS; 1426 } else if ((cflag & CS6) == CS6) { /* 6 data bits? */ 1427 val |= MR1_6_BITS; 1428 } else { /* Must be 5 */ 1429 val |= MR1_5_BITS; 1430 } 1431 /* 1432 * Enable H/W RTS/CTS handshaking. The default TA/MTA is 1433 * a DCE, hence the reverse sense of RTS and CTS 1434 */ 1435 /* Input Flow - CTS is raised when port is ready to receive data */ 1436 if (cflag & CRTS_IFLOW) 1437 val |= MR1_CTSCONT; 1438 1439 ccbp->hi_mr1 = val; 1440 1441 /* ========== set hi_mask ========== */ 1442 val = 0xff; 1443 if ((cflag & CS8) == CS8) { /* 8 data bits? */ 1444 val &= 0xFF; 1445 } else if ((cflag & CS7) == CS7) { /* 7 data bits? */ 1446 val &= 0x7F; 1447 } else if ((cflag & CS6) == CS6) { /* 6 data bits? */ 1448 val &= 0x3F; 1449 } else { /* Must be 5 */ 1450 val &= 0x1F; 1451 } 1452 if (iflag & ISTRIP) 1453 val &= 0x7F; 1454 1455 ccbp->hi_mask = val; 1456 1457 /* ========== set hi_prtcl ========== */ 1458 val = 0; 1459 /* Monitor DCD etc. if a modem */ 1460 if (!(cflag & CLOCAL)) 1461 val |= SP_DCEN; 1462 if (iflag & IXANY) 1463 val |= SP_TANY; 1464 if (iflag & IXON) 1465 val |= SP_TXEN; 1466 if (iflag & IXOFF) 1467 val |= SP_RXEN; 1468 if (iflag & INPCK) 1469 val |= SP_PAEN; 1470 1471 ccbp->hi_prtcl = val; 1472 1473 1474 /* ========== set hi_{rx|tx}{on|off} ========== */ 1475 /* XXX: the card TOTALLY shields us from the flow control... */ 1476 ccbp->hi_txon = t->c_cc[VSTART]; 1477 ccbp->hi_txoff = t->c_cc[VSTOP]; 1478 1479 ccbp->hi_rxon = t->c_cc[VSTART]; 1480 ccbp->hi_rxoff = t->c_cc[VSTOP]; 1481 1482 /* ========== send settings to the card ========== */ 1483 /* potential sleep here */ 1484 if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */ 1485 si_command(pp, LOPEN, SI_WAIT); /* open it */ 1486 else 1487 si_command(pp, CONFIG, SI_WAIT); /* change params */ 1488 1489 /* ========== set DTR etc ========== */ 1490 /* Hangup if ospeed == 0 */ 1491 if (t->c_ospeed == 0) { 1492 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS); 1493 } else { 1494 /* 1495 * If the previous speed was 0, may need to re-enable 1496 * the modem signals 1497 */ 1498 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS); 1499 } 1500 1501 DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x\n", 1502 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break)); 1503 1504 splx(oldspl); 1505out: 1506 return(error); 1507} 1508 1509/* 1510 * Enable or Disable the writes to this channel... 1511 * "state" -> enabled = 1; disabled = 0; 1512 */ 1513static void 1514si_write_enable(pp, state) 1515 register struct si_port *pp; 1516 int state; 1517{ 1518 int oldspl; 1519 1520 oldspl = spltty(); 1521 1522 if (state) { 1523 pp->sp_state &= ~SS_BLOCKWRITE; 1524 if (pp->sp_state & SS_WAITWRITE) { 1525 pp->sp_state &= ~SS_WAITWRITE; 1526 /* thunder away! */ 1527 wakeup((caddr_t)pp); 1528 } 1529 } else { 1530 pp->sp_state |= SS_BLOCKWRITE; 1531 } 1532 1533 splx(oldspl); 1534} 1535 1536/* 1537 * Set/Get state of modem control lines. 1538 * Due to DCE-like behaviour of the adapter, some signals need translation: 1539 * TIOCM_DTR DSR 1540 * TIOCM_RTS CTS 1541 */ 1542static int 1543si_modem(pp, cmd, bits) 1544 struct si_port *pp; 1545 enum si_mctl cmd; 1546 int bits; 1547{ 1548 volatile struct si_channel *ccbp; 1549 int x; 1550 1551 DPRINT((pp, DBG_ENTRY|DBG_MODEM, "si_modem(%x,%s,%x)\n", pp, si_mctl2str(cmd), bits)); 1552 ccbp = pp->sp_ccb; /* Find channel address */ 1553 switch (cmd) { 1554 case GET: 1555 x = ccbp->hi_ip; 1556 bits = TIOCM_LE; 1557 if (x & IP_DCD) bits |= TIOCM_CAR; 1558 if (x & IP_DTR) bits |= TIOCM_DTR; 1559 if (x & IP_RTS) bits |= TIOCM_RTS; 1560 if (x & IP_RI) bits |= TIOCM_RI; 1561 return(bits); 1562 case SET: 1563 ccbp->hi_op &= ~(OP_DSR|OP_CTS); 1564 /* fall through */ 1565 case BIS: 1566 x = 0; 1567 if (bits & TIOCM_DTR) 1568 x |= OP_DSR; 1569 if (bits & TIOCM_RTS) 1570 x |= OP_CTS; 1571 ccbp->hi_op |= x; 1572 break; 1573 case BIC: 1574 if (bits & TIOCM_DTR) 1575 ccbp->hi_op &= ~OP_DSR; 1576 if (bits & TIOCM_RTS) 1577 ccbp->hi_op &= ~OP_CTS; 1578 } 1579 return 0; 1580} 1581 1582/* 1583 * Handle change of modem state 1584 */ 1585static void 1586si_modem_state(pp, tp, hi_ip) 1587 register struct si_port *pp; 1588 register struct tty *tp; 1589 register int hi_ip; 1590{ 1591 /* if a modem dev */ 1592 if (hi_ip & IP_DCD) { 1593 if ( !(pp->sp_last_hi_ip & IP_DCD)) { 1594 DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n", 1595 tp->t_line)); 1596 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 1597 } 1598 } else { 1599 if (pp->sp_last_hi_ip & IP_DCD) { 1600 DPRINT((pp, DBG_INTR, "modem carr off\n")); 1601 if ((*linesw[tp->t_line].l_modem)(tp, 0)) 1602 (void) si_modem(pp, SET, 0); 1603 } 1604 } 1605 pp->sp_last_hi_ip = hi_ip; 1606 1607} 1608 1609/* 1610 * Poller to catch missed interrupts. 1611 */ 1612#ifdef POLL 1613void 1614si_poll(void *nothing) 1615{ 1616 register struct si_softc *sc; 1617 register int i; 1618 volatile struct si_reg *regp; 1619 int lost, oldspl; 1620 1621 DPRINT((0, DBG_POLL, "si_poll()\n")); 1622 if (in_intr) 1623 goto out; 1624 oldspl = spltty(); 1625 lost = 0; 1626 for (i=0; i<NSI; i++) { 1627 sc = &si_softc[i]; 1628 if (sc->sc_type == NULL) 1629 continue; 1630 regp = (struct si_reg *)sc->sc_maddr; 1631 /* 1632 * See if there has been a pending interrupt for 2 seconds 1633 * or so. The test <int_scounter >= 200) won't correspond 1634 * to 2 seconds if int_count gets changed. 1635 */ 1636 if (regp->int_pending != 0) { 1637 if (regp->int_scounter >= 200 && 1638 regp->initstat == 1) { 1639 printf("SLXOS si%d: lost intr\n", i); 1640 lost++; 1641 } 1642 } else { 1643 regp->int_scounter = 0; 1644 } 1645 1646 } 1647 if (lost) 1648 siintr(-1); /* call intr with fake vector */ 1649 splx(oldspl); 1650 1651out: 1652 timeout(si_poll, (caddr_t)0L, POLL_INTERVAL); 1653} 1654#endif /* ifdef POLL */ 1655 1656/* 1657 * The interrupt handler polls ALL ports on ALL adapters each time 1658 * it is called. 1659 */ 1660 1661static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */ 1662 1663int 1664siintr(int bdnum) 1665{ 1666 struct si_softc *Isc = NULL; 1667 register struct si_softc *sc; 1668 1669 register struct si_port *pp; 1670 volatile struct si_channel *ccbp; 1671 register struct tty *tp; 1672 volatile caddr_t maddr; 1673 BYTE op, ip, cc; 1674 int x, card, port, n, i; 1675 volatile BYTE *z; 1676 BYTE c; 1677 static int in_poll = 0; 1678 1679 if (bdnum < 0) { 1680 Isc = NULL; 1681 in_poll = 1; 1682 } else { 1683 Isc = &si_softc[bdnum]; 1684 } 1685 1686 DPRINT((0, (Isc == 0)?DBG_POLL:DBG_INTR, "siintr(0x%x)\n", Isc)); 1687 if (in_intr != 0) { 1688 if (Isc == NULL) /* should never happen */ 1689 return(0); 1690 printf("SLXOS si%d: Warning interrupt handler re-entered\n", 1691 Isc==0 ? -1 : Isc->sc_dev.dv_unit); 1692 return(0); 1693 } 1694 in_intr = 1; 1695 1696 /* 1697 * When we get an int we poll all the channels and do ALL pending 1698 * work, not just the first one we find. This allows all cards to 1699 * share the same vector. 1700 */ 1701 for (card=0; card < NSI; card++) { 1702 sc = &si_softc[card]; 1703 if (sc->sc_type == NULL) 1704 continue; 1705 switch(sc->sc_type) { 1706 case SIHOST : 1707 maddr = sc->sc_maddr; 1708 ((volatile struct si_reg *)maddr)->int_pending = 0; 1709 /* flag nothing pending */ 1710 *(maddr+SIINTCL) = 0x00; /* Set IRQ clear */ 1711 *(maddr+SIINTCL_CL) = 0x00; /* Clear IRQ clear */ 1712 break; 1713 case SIHOST2: 1714 maddr = sc->sc_maddr; 1715 ((volatile struct si_reg *)maddr)->int_pending = 0; 1716 *(maddr+SIPLIRQCLR) = 0x00; 1717 *(maddr+SIPLIRQCLR) = 0x10; 1718 break; 1719 case SIEISA: 1720#if NEISA > 0 1721 maddr = sc->sc_maddr; 1722 ((volatile struct si_reg *)maddr)->int_pending = 0; 1723 (void)inb(sc->sc_eisa_iobase+3); 1724 break; 1725#endif /* fall through if not EISA kernel */ 1726 case SIEMPTY: 1727 default: 1728 continue; 1729 } 1730 ((volatile struct si_reg *)maddr)->int_scounter = 0; 1731 1732 for (pp = sc->sc_ports, port=0; 1733 port < sc->sc_nport; 1734 pp++, port++) { 1735 ccbp = pp->sp_ccb; 1736 tp = pp->sp_tty; 1737 1738 /* 1739 * See if a command has completed ? 1740 */ 1741 if (ccbp->hi_stat != pp->sp_pend) { 1742 DPRINT((pp, DBG_INTR, 1743 "siintr hi_stat = 0x%x, pend = %d\n", 1744 ccbp->hi_stat, pp->sp_pend)); 1745 switch(pp->sp_pend) { 1746 case LOPEN: 1747 case MPEND: 1748 case MOPEN: 1749 case CONFIG: 1750 pp->sp_pend = ccbp->hi_stat; 1751 /* sleeping in si_command */ 1752 wakeup(&pp->sp_state); 1753 break; 1754 default: 1755 pp->sp_pend = ccbp->hi_stat; 1756 } 1757 } 1758 1759 /* 1760 * Continue on if it's closed 1761 */ 1762 if (ccbp->hi_stat == IDLE_CLOSE) { 1763 continue; 1764 } 1765 1766 /* 1767 * Do modem state change if not a local device 1768 */ 1769 si_modem_state(pp, tp, ccbp->hi_ip); 1770 1771 /* 1772 * Do break processing 1773 */ 1774 if (ccbp->hi_state & ST_BREAK) { 1775 if (tp->t_state & TS_CONNECTED) { 1776 (*linesw[tp->t_line].l_rint)(TTY_BI, tp); 1777 } 1778 ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */ 1779 DPRINT((pp, DBG_INTR, "si_intr break\n")); 1780 } 1781 1782 /* 1783 * Do RX stuff - if not open then 1784 * dump any characters. 1785 */ 1786 1787 if ((tp->t_state & TS_CONNECTED) == 0) { 1788 ccbp->hi_rxopos = ccbp->hi_rxipos; 1789 } else { 1790 while ((c = ccbp->hi_rxipos - ccbp->hi_rxopos) != 0) { 1791 1792 op = ccbp->hi_rxopos; 1793 ip = ccbp->hi_rxipos; 1794 n = c & 0xff; 1795 1796 DPRINT((pp, DBG_INTR, 1797 "n = %d, op = %d, ip = %d\n", 1798 n, op, ip)); 1799 if (n <= SLXOS_BUFFERSIZE - op) { 1800 1801 DPRINT((pp, DBG_INTR, 1802 "\tsingle copy\n")); 1803 z = ccbp->hi_rxbuf + op; 1804 bcopy((caddr_t)z, rxbuf, n); 1805 1806 op += n; 1807 } else { 1808 x = SLXOS_BUFFERSIZE - op; 1809 1810 DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x)); 1811 z = ccbp->hi_rxbuf + op; 1812 bcopy((caddr_t)z, rxbuf, x); 1813 1814 DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x)); 1815 z = ccbp->hi_rxbuf; 1816 bcopy((caddr_t)z, rxbuf+x, n-x); 1817 1818 op += n; 1819 } 1820 1821 ccbp->hi_rxopos = op; 1822 1823 DPRINT((pp, DBG_INTR, 1824 "n = %d, op = %d, ip = %d\n", 1825 n, op, ip)); 1826 1827 /* 1828 * at this point... 1829 * n = number of chars placed in rxbuf 1830 */ 1831 /* 1832 * Avoid the grotesquely inefficient lineswitch routine 1833 * (ttyinput) in "raw" mode. It usually takes about 450 1834 * instructions (that's without canonical processing or echo!). 1835 * slinput is reasonably fast (usually 40 instructions plus 1836 * call overhead). 1837 */ 1838 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1839 1840 /* block if the driver supports it */ 1841 if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER 1842 && (tp->t_cflag & CRTS_IFLOW 1843 || tp->t_iflag & IXOFF) 1844 && !(tp->t_state & TS_TBLOCK)) 1845 ttyblock(tp); 1846 1847 tk_nin += n; 1848 tk_rawcc += n; 1849 tp->t_rawcc += n; 1850 1851 b_to_q((char *)rxbuf, n, &tp->t_rawq); 1852 ttwakeup(tp); 1853 if (tp->t_state & TS_TTSTOP 1854 && (tp->t_iflag & IXANY 1855 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1856 tp->t_state &= ~TS_TTSTOP; 1857 tp->t_lflag &= ~FLUSHO; 1858 si_start(tp); 1859 } 1860 } else { 1861 for(x = 0; x < n; x++) { 1862 i = rxbuf[x]; 1863 (*linesw[tp->t_line].l_rint)(rxbuf[x], tp); 1864 if (pp->sp_hotchar && i == pp->sp_hotchar) { 1865 setsofttty(); 1866 } 1867 } 1868 } 1869 1870 } /* end of RX while */ 1871 } /* end TS_CONNECTED */ 1872 1873 /* 1874 * Do TX stuff 1875 */ 1876 (*linesw[tp->t_line].l_start)(tp); 1877 1878 } /* end of for (all ports on this controller) */ 1879 } /* end of for (all controllers) */ 1880 1881 in_poll = in_intr = 0; 1882 DPRINT((0, (Isc==0)?DBG_POLL:DBG_INTR, "end of siintr()\n")); 1883 return(1); /* say it was expected */ 1884} 1885 1886/* 1887 * Nudge the transmitter... 1888 */ 1889static void 1890si_start(tp) 1891 register struct tty *tp; 1892{ 1893 struct si_port *pp; 1894 volatile struct si_channel *ccbp; 1895 register struct clist *qp; 1896 register char *dptr; 1897 BYTE ipos; 1898 int nchar; 1899 int oldspl, count, n, amount, buffer_full; 1900 int do_exitproc; 1901 1902 oldspl = spltty(); 1903 1904 qp = &tp->t_outq; 1905 pp = TP2PP(tp); 1906 1907 DPRINT((pp, DBG_ENTRY|DBG_START, 1908 "si_start(%x) t_state %x sp_state %x t_outq.c_cc %d\n", 1909 tp, tp->t_state, pp->sp_state, qp->c_cc)); 1910 1911 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 1912 goto out; 1913 1914 do_exitproc = 0; 1915 buffer_full = 0; 1916 ccbp = pp->sp_ccb; 1917 1918 /* 1919 * Handle the case where ttywait() is called on process exit 1920 * this may be BSDI specific, I dont know... 1921 */ 1922 if (tp->t_session != NULL && tp->t_session->s_leader != NULL && 1923 (tp->t_session->s_leader->p_flag & P_WEXIT)) { 1924 do_exitproc++; 1925 } 1926 1927 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos; 1928 DPRINT((pp, DBG_START, "count %d\n", (BYTE)count)); 1929 1930 dptr = (char *)ccbp->hi_txbuf; /* data buffer */ 1931 1932 while ((nchar = qp->c_cc) > 0) { 1933 if ((BYTE)count >= 255) { 1934 buffer_full++; 1935 break; 1936 } 1937 amount = min(nchar, (255 - (BYTE)count)); 1938 ipos = (unsigned int)ccbp->hi_txipos; 1939 /* will it fit in one lump? */ 1940 if ((SLXOS_BUFFERSIZE - ipos) >= amount) { 1941 n = q_to_b(&tp->t_outq, 1942 (char *)&ccbp->hi_txbuf[ipos], amount); 1943 } else { 1944 n = q_to_b(&tp->t_outq, 1945 (char *)&ccbp->hi_txbuf[ipos], 1946 SLXOS_BUFFERSIZE-ipos); 1947 if (n == SLXOS_BUFFERSIZE-ipos) { 1948 n += q_to_b(&tp->t_outq, 1949 (char *)&ccbp->hi_txbuf[0], 1950 amount - (SLXOS_BUFFERSIZE-ipos)); 1951 } 1952 } 1953 ccbp->hi_txipos += n; 1954 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos; 1955 } 1956 1957 if (count != 0 && nchar == 0) { 1958 tp->t_state |= TS_BUSY; 1959 } else { 1960 tp->t_state &= ~TS_BUSY; 1961 } 1962 1963 /* wakeup time? */ 1964 ttwwakeup(tp); 1965 1966 DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n", 1967 (BYTE)count, nchar, tp->t_state)); 1968 1969 if ((tp->t_state & TS_BUSY) || do_exitproc) 1970 { 1971 int time; 1972 1973 if (do_exitproc != 0) { 1974 time = hz / 10; 1975 } else { 1976 time = ttspeedtab(tp->t_ospeed, chartimes); 1977 1978 if (time > 0) { 1979 if (time < nchar) 1980 time = nchar / time; 1981 else 1982 time = 2; 1983 } else { 1984 printf("SLXOS si%d: bad char time value!!\n", 1985 SI_CARD(tp->t_dev)); 1986 goto out; 1987 } 1988 } 1989 1990 if ((pp->sp_state & (SS_LSTART|SS_INLSTART)) == SS_LSTART) { 1991 untimeout((timeout_func_t)si_lstart, (caddr_t)pp); 1992 } else { 1993 pp->sp_state |= SS_LSTART; 1994 } 1995 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time)); 1996 timeout((timeout_func_t)si_lstart, (caddr_t)pp, time); 1997 } 1998 1999out: 2000 splx(oldspl); 2001 DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n")); 2002} 2003 2004/* 2005 * Note: called at splsoftclock from the timeout code 2006 * This has to deal with two things... cause wakeups while waiting for 2007 * tty drains on last process exit, and call l_start at about the right 2008 * time for protocols like ppp. 2009 */ 2010static void 2011si_lstart(pp) 2012 register struct si_port *pp; 2013{ 2014 register struct tty *tp; 2015 int oldspl; 2016 2017 DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n", 2018 pp, pp->sp_state)); 2019 2020 oldspl = spltty(); 2021 2022 if ((pp->sp_state & SS_OPEN) == 0 || (pp->sp_state & SS_LSTART) == 0) { 2023 splx(oldspl); 2024 return; 2025 } 2026 pp->sp_state &= ~SS_LSTART; 2027 pp->sp_state |= SS_INLSTART; 2028 2029 tp = pp->sp_tty; 2030 2031 /* deal with the process exit case */ 2032 ttwwakeup(tp); 2033 2034 /* nudge protocols */ 2035 (*linesw[tp->t_line].l_start)(tp); 2036 2037 pp->sp_state &= ~SS_INLSTART; 2038 splx(oldspl); 2039} 2040 2041/* 2042 * Stop output on a line. called at spltty(); 2043 */ 2044void 2045sistop(tp, rw) 2046 register struct tty *tp; 2047 int rw; 2048{ 2049 volatile struct si_channel *ccbp; 2050 struct si_port *pp; 2051 2052 pp = TP2PP(tp); 2053 ccbp = pp->sp_ccb; 2054 2055 DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "sistop(%x,%x)\n", tp, rw)); 2056 2057 /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */ 2058 if (rw & FWRITE) { 2059 /* what level are we meant to be flushing anyway? */ 2060 if (tp->t_state & TS_BUSY) { 2061 si_command(TP2PP(tp), WFLUSH, SI_NOWAIT); 2062 tp->t_state &= ~TS_BUSY; 2063 ttwwakeup(tp); /* Bruce???? */ 2064 } 2065 } 2066#if 0 /* this doesn't work right yet.. */ 2067 if (rw & FREAD) { 2068 ccbp->hi_rxopos = ccbp->hi_rxipos; 2069 } 2070#endif 2071} 2072 2073/* 2074 * Issue a command to the Z280 host card CPU. 2075 */ 2076 2077static void 2078si_command(pp, cmd, waitflag) 2079 struct si_port *pp; /* port control block (local) */ 2080 int cmd; 2081 int waitflag; 2082{ 2083 int oldspl; 2084 volatile struct si_channel *ccbp = pp->sp_ccb; 2085 int x; 2086 2087 DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%x,%d): hi_stat 0x%x\n", 2088 pp, cmd, waitflag, ccbp->hi_stat)); 2089 2090 oldspl = spltty(); /* Keep others out */ 2091 2092 /* wait until it's finished what it was doing.. */ 2093 while((x = ccbp->hi_stat) != IDLE_OPEN && 2094 x != IDLE_CLOSE && 2095 x != cmd) { 2096 if (in_intr) { /* Prevent sleep in intr */ 2097 DPRINT((pp, DBG_PARAM, 2098 "cmd intr collision - completing %d\trequested %d\n", 2099 x, cmd)); 2100 splx(oldspl); 2101 return; 2102 } else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, 2103 "sicmd1", 1)) { 2104 splx(oldspl); 2105 return; 2106 } 2107 } 2108 /* it should now be in IDLE_OPEN, IDLE_CLOSE, or "cmd" */ 2109 2110 /* if there was a pending command, cause a state-change wakeup */ 2111 if (pp->sp_pend != IDLE_OPEN) { 2112 switch(pp->sp_pend) { 2113 case LOPEN: 2114 case MPEND: 2115 case MOPEN: 2116 case CONFIG: 2117 wakeup(&pp->sp_state); 2118 break; 2119 default: 2120 break; 2121 } 2122 } 2123 2124 pp->sp_pend = cmd; /* New command pending */ 2125 ccbp->hi_stat = cmd; /* Post it */ 2126 2127 if (waitflag) { 2128 if (in_intr) { /* If in interrupt handler */ 2129 DPRINT((pp, DBG_PARAM, 2130 "attempt to sleep in si_intr - cmd req %d\n", 2131 cmd)); 2132 splx(oldspl); 2133 return; 2134 } else while(ccbp->hi_stat != IDLE_OPEN) { 2135 if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, 2136 "sicmd2", 0)) 2137 break; 2138 } 2139 } 2140 splx(oldspl); 2141} 2142 2143static void 2144si_disc_optim(tp, t, pp) 2145 struct tty *tp; 2146 struct termios *t; 2147 struct si_port *pp; 2148{ 2149 /* 2150 * XXX can skip a lot more cases if Smarts. Maybe 2151 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2152 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2153 */ 2154 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2155 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2156 && (!(t->c_iflag & PARMRK) 2157 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2158 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2159 && linesw[tp->t_line].l_rint == ttyinput) 2160 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2161 else 2162 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2163 2164 /* 2165 * Prepare to reduce input latency for packet 2166 * discplines with a end of packet character. 2167 */ 2168 if (tp->t_line == SLIPDISC) 2169 pp->sp_hotchar = 0xc0; 2170 else if (tp->t_line == PPPDISC) 2171 pp->sp_hotchar = 0x7e; 2172 else 2173 pp->sp_hotchar = 0; 2174 2175 DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n", 2176 (tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off", 2177 pp->sp_hotchar)); 2178} 2179 2180 2181#ifdef SI_DEBUG 2182static void 2183si_dprintf(pp, flags, str, a1, a2, a3, a4, a5, a6) 2184 struct si_port *pp; 2185 int flags; 2186 char *str; 2187 int a1, a2, a3, a4, a5, a6; 2188{ 2189 if ((pp == NULL && (si_debug&flags)) || 2190 (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) { 2191 if (pp != NULL) 2192 printf("SLXOS %ci%d(%d): ", 's', 2193 SI_CARD(pp->sp_tty->t_dev), 2194 SI_PORT(pp->sp_tty->t_dev)); 2195 printf(str, a1, a2, a3, a4, a5, a6); 2196 } 2197} 2198 2199static char * 2200si_mctl2str(cmd) 2201 enum si_mctl cmd; 2202{ 2203 switch (cmd) { 2204 case GET: return("GET"); 2205 case SET: return("SET"); 2206 case BIS: return("BIS"); 2207 case BIC: return("BIC"); 2208 } 2209 return("BAD"); 2210} 2211#endif 2212