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