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