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