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