The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/si.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
    3  *
    4  * Copyright (C) 1990, 1992, 1998 Specialix International,
    5  * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
    6  * Copyright (C) 1995, Peter Wemm <peter@netplex.com.au>
    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  * $FreeBSD: src/sys/i386/isa/si.c,v 1.53.2.5 1999/09/05 08:13:26 peter Exp $
   34  */
   35 
   36 #ifndef lint
   37 static const char si_copyright1[] =  "@(#) Copyright (C) Specialix International, 1990,1992,1998",
   38                   si_copyright2[] =  "@(#) Copyright (C) Andy Rutter 1993",
   39                   si_copyright3[] =  "@(#) Copyright (C) Peter Wemm 1995";
   40 #endif  /* not lint */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/ioctl.h>
   45 #include <sys/tty.h>
   46 #include <sys/ttydefaults.h>
   47 #include <sys/proc.h>
   48 #include <sys/conf.h>
   49 #include <sys/file.h>
   50 #include <sys/uio.h>
   51 #include <sys/dkstat.h>
   52 #include <sys/kernel.h>
   53 #include <sys/syslog.h>
   54 #include <sys/malloc.h>
   55 #include <sys/sysctl.h>
   56 #ifdef DEVFS
   57 #include <sys/devfsext.h>
   58 #endif /*DEVFS*/
   59 
   60 #include <machine/clock.h>
   61 
   62 #include <vm/vm.h>
   63 #include <vm/vm_param.h>
   64 #include <vm/pmap.h>
   65 
   66 #include <i386/isa/icu.h>
   67 #include <i386/isa/isa.h>
   68 #include <i386/isa/isa_device.h>
   69 
   70 #include <i386/isa/sireg.h>
   71 #include <machine/si.h>
   72 #include <machine/stdarg.h>
   73 
   74 #include "pci.h"
   75 #if NPCI > 0
   76 #include <pci/pcivar.h>
   77 #include <pci/pcireg.h>
   78 #endif
   79 
   80 #include "eisa.h"
   81 #if NEISA > 0
   82 #include <i386/eisa/eisaconf.h>
   83 #include <i386/isa/icu.h>
   84 #endif
   85 
   86 #include "si.h"
   87 
   88 /*
   89  * This device driver is designed to interface the Specialix International
   90  * SI, XIO and SX range of serial multiplexor cards to FreeBSD on an ISA,
   91  * EISA or PCI bus machine.
   92  *
   93  * The controller is interfaced to the host via dual port RAM
   94  * and an interrupt.
   95  *
   96  * The code for the Host 1 (very old ISA cards) has not been tested.
   97  */
   98 
   99 #define POLL            /* turn on poller to scan for lost interrupts */
  100 #define REALPOLL        /* on each poll, scan for work regardless */
  101 #define POLLHZ  (hz/10) /* 10 times per second */
  102 #define SI_I_HIGH_WATER (TTYHOG - 2 * SI_BUFFERSIZE)
  103 #define INT_COUNT 25000         /* max of 125 ints per second */
  104 #define JET_INT_COUNT 100       /* max of 100 ints per second */
  105 #define RXINT_COUNT 1   /* one rxint per 10 milliseconds */
  106 
  107 enum si_mctl { GET, SET, BIS, BIC };
  108 
  109 static void si_command __P((struct si_port *, int, int));
  110 static int si_modem __P((struct si_port *, enum si_mctl, int));
  111 static void si_write_enable __P((struct si_port *, int));
  112 static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *));
  113 static void si_start __P((struct tty *));
  114 static void si_lstart __P((struct si_port *));
  115 static void si_disc_optim __P((struct tty *tp, struct termios *t,
  116                                         struct si_port *pp));
  117 static void sihardclose __P((struct si_port *pp));
  118 static void sidtrwakeup __P((void *chan));
  119 
  120 static int      siparam __P((struct tty *, struct termios *));
  121 
  122 static  int     siprobe __P((struct isa_device *id));
  123 static  int     siattach __P((struct isa_device *id));
  124 static  void    si_modem_state __P((struct si_port *pp, struct tty *tp, int hi_ip));
  125 static void     si_intr __P((int unit));
  126 static char *   si_modulename __P((int host_type, int uart_type));
  127 
  128 struct isa_driver sidriver =
  129         { siprobe, siattach, "si" };
  130 
  131 static u_long sipcieisacount = 0;
  132 
  133 #if NPCI > 0
  134 
  135 static char *sipciprobe __P((pcici_t, pcidi_t));
  136 static void sipciattach __P((pcici_t, int));
  137 
  138 static struct pci_device sipcidev = {
  139         "si",
  140         sipciprobe,
  141         sipciattach,
  142         &sipcieisacount,
  143         NULL,
  144 };
  145 
  146 DATA_SET (pcidevice_set, sipcidev);
  147 
  148 #endif
  149 
  150 #if NEISA > 0
  151 
  152 static int si_eisa_probe __P((void));
  153 static int si_eisa_attach __P((struct eisa_device *ed));
  154 
  155 static struct eisa_driver si_eisa_driver = {
  156         "si",
  157         si_eisa_probe,
  158         si_eisa_attach,
  159         NULL,
  160         &sipcieisacount,
  161 };
  162 
  163 DATA_SET(eisadriver_set, si_eisa_driver);
  164 
  165 #endif
  166 
  167 static  d_open_t        siopen;
  168 static  d_close_t       siclose;
  169 static  d_read_t        siread;
  170 static  d_write_t       siwrite;
  171 static  d_ioctl_t       siioctl;
  172 static  d_stop_t        sistop;
  173 static  d_devtotty_t    sidevtotty;
  174 
  175 #define CDEV_MAJOR 68
  176 static struct cdevsw si_cdevsw =
  177         { siopen,       siclose,        siread,         siwrite,        /*68*/
  178           siioctl,      sistop,         noreset,        sidevtotty,/* si */
  179           ttselect,     nommap,         NULL,   "si",   NULL,   -1 };
  180 
  181 
  182 #ifdef SI_DEBUG         /* use: ``options "SI_DEBUG"'' in your config file */
  183 
  184 static  void    si_dprintf __P((struct si_port *pp, int flags, const char *fmt,
  185                                 ...));
  186 static  char    *si_mctl2str __P((enum si_mctl cmd));
  187 
  188 #define DPRINT(x)       si_dprintf x
  189 
  190 #else
  191 #define DPRINT(x)       /* void */
  192 #endif
  193 
  194 static int si_Nports;
  195 static int si_Nmodules;
  196 static int si_debug = 0;        /* data, not bss, so it's patchable */
  197 
  198 SYSCTL_INT(_machdep, OID_AUTO, si_debug, CTLFLAG_RW, &si_debug, 0, "");
  199 
  200 static struct tty *si_tty;
  201 
  202 /* where the firmware lives; defined in si2_z280.c and si3_t225.c */
  203 /* old: si2_z280.c */
  204 extern unsigned char si2_z280_download[];
  205 extern unsigned short si2_z280_downloadaddr;
  206 extern int si2_z280_dsize;
  207 /* new: si3_t225.c */
  208 extern unsigned char si3_t225_download[];
  209 extern unsigned short si3_t225_downloadaddr;
  210 extern int si3_t225_dsize;
  211 extern unsigned char si3_t225_bootstrap[];
  212 extern unsigned short si3_t225_bootloadaddr;
  213 extern int si3_t225_bsize;
  214 
  215 
  216 struct si_softc {
  217         int             sc_type;        /* adapter type */
  218         char            *sc_typename;   /* adapter type string */
  219 
  220         struct si_port  *sc_ports;      /* port structures for this card */
  221 
  222         caddr_t         sc_paddr;       /* physical addr of iomem */
  223         caddr_t         sc_maddr;       /* kvaddr of iomem */
  224         int             sc_nport;       /* # ports on this card */
  225         int             sc_irq;         /* copy of attach irq */
  226 #if NEISA > 0
  227         int             sc_eisa_iobase; /* EISA io port address */
  228         int             sc_eisa_irq;    /* EISA irq number */
  229 #endif
  230 #ifdef  DEVFS
  231         struct {
  232                 void    *ttya;
  233                 void    *cuaa;
  234                 void    *ttyl;
  235                 void    *cual;
  236                 void    *ttyi;
  237                 void    *cuai;
  238         } devfs_token[32]; /* what is the max per card? */
  239         void    *control_token;
  240 #endif
  241 };
  242 static struct si_softc si_softc[NSI];           /* up to 4 elements */
  243 
  244 #ifndef B2000   /* not standard, but the hardware knows it. */
  245 # define B2000 2000
  246 #endif
  247 static struct speedtab bdrates[] = {
  248         B75,    CLK75,          /* 0x0 */
  249         B110,   CLK110,         /* 0x1 */
  250         B150,   CLK150,         /* 0x3 */
  251         B300,   CLK300,         /* 0x4 */
  252         B600,   CLK600,         /* 0x5 */
  253         B1200,  CLK1200,        /* 0x6 */
  254         B2000,  CLK2000,        /* 0x7 */
  255         B2400,  CLK2400,        /* 0x8 */
  256         B4800,  CLK4800,        /* 0x9 */
  257         B9600,  CLK9600,        /* 0xb */
  258         B19200, CLK19200,       /* 0xc */
  259         B38400, CLK38400,       /* 0x2 (out of order!) */
  260         B57600, CLK57600,       /* 0xd */
  261         B115200, CLK110,        /* 0x1 (dupe!, 110 baud on "si") */
  262         -1,     -1
  263 };
  264 
  265 
  266 /* populated with approx character/sec rates - translated at card
  267  * initialisation time to chars per tick of the clock */
  268 static int done_chartimes = 0;
  269 static struct speedtab chartimes[] = {
  270         B75,    8,
  271         B110,   11,
  272         B150,   15,
  273         B300,   30,
  274         B600,   60,
  275         B1200,  120,
  276         B2000,  200,
  277         B2400,  240,
  278         B4800,  480,
  279         B9600,  960,
  280         B19200, 1920,
  281         B38400, 3840,
  282         B57600, 5760,
  283         B115200, 11520,
  284         -1,     -1
  285 };
  286 static volatile int in_intr = 0;        /* Inside interrupt handler? */
  287 
  288 #ifdef POLL
  289 static int si_pollrate;                 /* in addition to irq */
  290 static int si_realpoll;                 /* poll HW on timer */
  291 
  292 SYSCTL_INT(_machdep, OID_AUTO, si_pollrate, CTLFLAG_RW, &si_pollrate, 0, "");
  293 SYSCTL_INT(_machdep, OID_AUTO, si_realpoll, CTLFLAG_RW, &si_realpoll, 0, "");
  294                  
  295 static int init_finished = 0;
  296 static void si_poll __P((void *));
  297 #endif
  298 
  299 /*
  300  * Array of adapter types and the corresponding RAM size. The order of
  301  * entries here MUST match the ordinal of the adapter type.
  302  */
  303 static char *si_type[] = {
  304         "EMPTY",
  305         "SIHOST",
  306         "SIMCA",                /* FreeBSD does not support Microchannel */
  307         "SIHOST2",
  308         "SIEISA",
  309         "SIPCI",
  310         "SXPCI",
  311         "SXISA",
  312 };
  313 
  314 #if NPCI > 0
  315 
  316 static char *
  317 sipciprobe(configid, deviceid)
  318 pcici_t configid;
  319 pcidi_t deviceid;
  320 {
  321         switch (deviceid)
  322         {
  323                 case 0x400011cb:
  324                         return("Specialix SI/XIO PCI host card");
  325                         break;
  326                 case 0x200011cb:
  327                         if (pci_conf_read(configid, SIJETSSIDREG) == 0x020011cb)
  328                                 return("Specialix SX PCI host card");
  329                         else
  330                                 return NULL;
  331                         break;
  332                 default:
  333                         return NULL;
  334         }
  335         /*NOTREACHED*/
  336 }
  337 
  338 void
  339 sipciattach(configid, unit)
  340 pcici_t configid;
  341 int unit;
  342 {
  343         struct isa_device id;
  344         vm_offset_t vaddr,paddr;
  345         u_long mapval = 0;      /* shut up gcc, should not be needed */
  346 
  347         switch ( pci_conf_read(configid, 0) >> 16 )
  348         {
  349                 case 0x4000:
  350                         si_softc[unit].sc_type = SIPCI;
  351                         mapval = SIPCIBADR;
  352                         break;
  353                 case 0x2000:
  354                         si_softc[unit].sc_type = SIJETPCI;
  355                         mapval = SIJETBADR;
  356                         break;
  357         }
  358         if (!pci_map_mem(configid, mapval, &vaddr, &paddr))
  359         {
  360                 printf("si%d: couldn't map memory\n", unit);
  361         }
  362 
  363         /*
  364          * We're cheating here a little bit. The argument to an ISA
  365          * interrupt routine is the unit number. The argument to a
  366          * PCI interrupt handler is a void *, but we're simply going
  367          * to be lazy and hand it the unit number.
  368          */
  369         if (!pci_map_int(configid, (pci_inthand_t *) si_intr, (void *)unit, &tty_imask)) {
  370                 printf("si%d: couldn't map interrupt\n", unit);
  371         }
  372         si_softc[unit].sc_typename = si_type[si_softc[unit].sc_type];
  373 
  374         /*
  375          * More cheating: We're going to dummy up a struct isa_device
  376          * and call the other attach routine. We don't really have to
  377          * fill in very much of the structure, since we filled in a
  378          * little of the soft state already.
  379          */
  380         id.id_unit = unit;
  381         id.id_maddr = (caddr_t) vaddr;
  382         siattach(&id);
  383 }
  384 
  385 #endif
  386 
  387 #if NEISA > 0
  388 
  389 static const char *si_eisa_match __P((eisa_id_t id));
  390 
  391 static const char *
  392 si_eisa_match(id)
  393         eisa_id_t id;
  394 {
  395         if (id == SIEISADEVID)
  396                 return ("Specialix SI/XIO EISA host card");
  397         return (NULL);
  398 }
  399 
  400 static int
  401 si_eisa_probe(void)
  402 {
  403         struct eisa_device *ed = NULL;
  404         int count, irq;
  405 
  406         for (count=0; (ed = eisa_match_dev(ed, si_eisa_match)) != NULL; count++)
  407         {
  408                 u_long port,maddr;
  409 
  410                 port = (ed->ioconf.slot * EISA_SLOT_SIZE) + SIEISABASE;
  411                 eisa_add_iospace(ed, port, SIEISAIOSIZE, RESVADDR_NONE);
  412                 maddr = (inb(port+1) << 24) | (inb(port) << 16);
  413                 irq  = ((inb(port+2) >> 4) & 0xf);
  414                 eisa_add_mspace(ed, maddr, SIEISA_MEMSIZE, RESVADDR_NONE);
  415                 eisa_add_intr(ed, irq);
  416                 eisa_registerdev(ed, &si_eisa_driver);
  417                 count++;
  418         }
  419         return count;
  420 }
  421 
  422 static int
  423 si_eisa_attach(ed)
  424         struct eisa_device *ed;
  425 {
  426         struct isa_device id;
  427         resvaddr_t *maddr,*iospace;
  428         u_int irq;
  429         struct si_softc *sc;
  430 
  431         sc = &si_softc[ed->unit];
  432 
  433         sc->sc_type = SIEISA;
  434         sc->sc_typename = si_type[sc->sc_type];
  435 
  436         if ((iospace = ed->ioconf.ioaddrs.lh_first) == NULL) {
  437                 printf("si%d: no iospace??\n", ed->unit);
  438                 return -1;
  439         }
  440         sc->sc_eisa_iobase = iospace->addr;
  441 
  442         irq  = ((inb(iospace->addr + 2) >> 4) & 0xf);
  443         sc->sc_eisa_irq = irq;
  444 
  445         if ((maddr = ed->ioconf.maddrs.lh_first) == NULL) {
  446                 printf("si%d: where am I??\n", ed->unit);
  447                 return -1;
  448         }
  449         eisa_reg_start(ed);
  450         if (eisa_reg_iospace(ed, iospace)) {
  451                 printf("si%d: failed to register iospace 0x%x\n",
  452                         ed->unit, iospace);
  453                 return -1;
  454         }
  455         if (eisa_reg_mspace(ed, maddr)) {
  456                 printf("si%d: failed to register memspace 0x%x\n",
  457                         ed->unit, maddr);
  458                 return -1;
  459         }
  460         /*
  461          * We're cheating here a little bit. The argument to an ISA
  462          * interrupt routine is the unit number. The argument to a
  463          * EISA interrupt handler is a void *, but we're simply going
  464          * to be lazy and hand it the unit number.
  465          */
  466         if (eisa_reg_intr(ed, irq, (void (*)(void *)) si_intr,
  467                 (void *)(ed->unit), &tty_imask, 1)) {
  468                 printf("si%d: failed to register interrupt %d\n",
  469                         ed->unit, irq);
  470                 return -1;
  471         }
  472         eisa_reg_end(ed);
  473         if (eisa_enable_intr(ed, irq)) {
  474                 return -1;
  475         }
  476 
  477         /*
  478          * More cheating: We're going to dummy up a struct isa_device
  479          * and call the other attach routine. We don't really have to
  480          * fill in very much of the structure, since we filled in a
  481          * little of the soft state already.
  482          */
  483         id.id_unit = ed->unit;
  484         id.id_maddr = (caddr_t) pmap_mapdev(maddr->addr, SIEISA_MEMSIZE);
  485         return (siattach(&id));
  486 }
  487 
  488 #endif
  489 
  490 
  491 /* Look for a valid board at the given mem addr */
  492 static int
  493 siprobe(id)
  494         struct isa_device *id;
  495 {
  496         struct si_softc *sc;
  497         int type;
  498         u_int i, ramsize;
  499         volatile BYTE was, *ux;
  500         volatile unsigned char *maddr;
  501         unsigned char *paddr;
  502 
  503         si_pollrate = POLLHZ;           /* default 10 per second */
  504 #ifdef REALPOLL
  505         si_realpoll = 1;                /* scan always */
  506 #endif
  507         maddr = id->id_maddr;           /* virtual address... */
  508         paddr = (caddr_t)vtophys(id->id_maddr); /* physical address... */
  509 
  510         DPRINT((0, DBG_AUTOBOOT, "si%d: probe at virtual=0x%x physical=0x%x\n",
  511                 id->id_unit, id->id_maddr, paddr));
  512 
  513         /*
  514          * this is a lie, but it's easier than trying to handle caching
  515          * and ram conflicts in the >1M and <16M region.
  516          */
  517         if ((caddr_t)paddr < (caddr_t)IOM_BEGIN ||
  518             (caddr_t)paddr >= (caddr_t)IOM_END) {
  519                 printf("si%d: iomem (%lx) out of range\n",
  520                         id->id_unit, (long)paddr);
  521                 return(0);
  522         }
  523 
  524         if (id->id_unit >= NSI) {
  525                 /* THIS IS IMPOSSIBLE */
  526                 return(0);
  527         }
  528 
  529         if (((u_int)paddr & 0x7fff) != 0) {
  530                 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  531                         "si%d: iomem (%x) not on 32k boundary\n",
  532                         id->id_unit, paddr));
  533                 return(0);
  534         }
  535 
  536         if (si_softc[id->id_unit].sc_typename) {
  537                 /* EISA or PCI has taken this unit, choose another */
  538                 for (i=0; i < NSI; i++) {
  539                         if (si_softc[i].sc_typename == NULL) {
  540                                 id->id_unit = i;
  541                                 break;
  542                         }
  543                 }
  544                 if (i >= NSI) {
  545                         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  546                                 "si%d: cannot realloc unit\n", id->id_unit));
  547                         return (0);
  548                 }
  549         }
  550 
  551         for (i=0; i < NSI; i++) {
  552                 sc = &si_softc[i];
  553                 if ((caddr_t)sc->sc_paddr == (caddr_t)paddr) {
  554                         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  555                                 "si%d: iomem (%x) already configured to si%d\n",
  556                                 id->id_unit, sc->sc_paddr, i));
  557                         return(0);
  558                 }
  559         }
  560 
  561         /* Is there anything out there? (0x17 is just an arbitrary number) */
  562         *maddr = 0x17;
  563         if (*maddr != 0x17) {
  564                 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  565                         "si%d: 0x17 check fail at phys 0x%x\n",
  566                         id->id_unit, paddr));
  567 fail:
  568                 return(0);
  569         }
  570         /*
  571          * Let's look first for a JET ISA card, since that's pretty easy
  572          *
  573          * All jet hosts are supposed to have this string in the IDROM,
  574          * but it's not worth checking on self-IDing busses like PCI.
  575          */
  576         {
  577                 unsigned char *jet_chk_str = "JET HOST BY KEV#";
  578 
  579                 for (i = 0; i < strlen(jet_chk_str); i++)
  580                         if (jet_chk_str[i] != *(maddr + SIJETIDSTR + 2 * i))
  581                                 goto try_mk2;
  582         }
  583         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  584                 "si%d: JET first check - 0x%x\n",
  585                 id->id_unit, (*(maddr+SIJETIDBASE))));
  586         if (*(maddr+SIJETIDBASE) != (SISPLXID&0xff))
  587                 goto try_mk2;
  588         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  589                 "si%d: JET second check - 0x%x\n",
  590                 id->id_unit, (*(maddr+SIJETIDBASE+2))));
  591         if (*(maddr+SIJETIDBASE+2) != ((SISPLXID&0xff00)>>8))
  592                 goto try_mk2;
  593         /* It must be a Jet ISA or RIO card */
  594         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  595                 "si%d: JET id check - 0x%x\n",
  596                 id->id_unit, (*(maddr+SIUNIQID))));
  597         if ((*(maddr+SIUNIQID) & 0xf0) !=0x20)
  598                 goto try_mk2;
  599         /* It must be a Jet ISA SI/XIO card */
  600         *(maddr + SIJETCONFIG) = 0;
  601         type = SIJETISA;
  602         ramsize = SIJET_RAMSIZE;
  603         goto got_card;
  604         /*
  605          * OK, now to see if whatever responded is really an SI card.
  606          * Try for a MK II next (SIHOST2)
  607          */
  608 try_mk2:
  609         for (i = SIPLSIG; i < SIPLSIG + 8; i++)
  610                 if ((*(maddr+i) & 7) != (~(BYTE)i & 7))
  611                         goto try_mk1;
  612 
  613         /* It must be an SIHOST2 */
  614         *(maddr + SIPLRESET) = 0;
  615         *(maddr + SIPLIRQCLR) = 0;
  616         *(maddr + SIPLIRQSET) = 0x10;
  617         type = SIHOST2;
  618         ramsize = SIHOST2_RAMSIZE;
  619         goto got_card;
  620 
  621         /*
  622          * Its not a MK II, so try for a MK I (SIHOST)
  623          */
  624 try_mk1:
  625         *(maddr+SIRESET) = 0x0;         /* reset the card */
  626         *(maddr+SIINTCL) = 0x0;         /* clear int */
  627         *(maddr+SIRAM) = 0x17;
  628         if (*(maddr+SIRAM) != (BYTE)0x17)
  629                 goto fail;
  630         *(maddr+0x7ff8) = 0x17;
  631         if (*(maddr+0x7ff8) != (BYTE)0x17) {
  632                 DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  633                         "si%d: 0x17 check fail at phys 0x%x = 0x%x\n",
  634                         id->id_unit, paddr+0x77f8, *(maddr+0x77f8)));
  635                 goto fail;
  636         }
  637 
  638         /* It must be an SIHOST (maybe?) - there must be a better way XXX */
  639         type = SIHOST;
  640         ramsize = SIHOST_RAMSIZE;
  641 
  642 got_card:
  643         DPRINT((0, DBG_AUTOBOOT, "si%d: found type %d card, try memory test\n",
  644                 id->id_unit, type));
  645         /* Try the acid test */
  646         ux = maddr + SIRAM;
  647         for (i = 0; i < ramsize; i++, ux++)
  648                 *ux = (BYTE)(i&0xff);
  649         ux = maddr + SIRAM;
  650         for (i = 0; i < ramsize; i++, ux++) {
  651                 if ((was = *ux) != (BYTE)(i&0xff)) {
  652                         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  653                                 "si%d: match fail at phys 0x%x, was %x should be %x\n",
  654                                 id->id_unit, paddr + i, was, i&0xff));
  655                         goto fail;
  656                 }
  657         }
  658 
  659         /* clear out the RAM */
  660         ux = maddr + SIRAM;
  661         for (i = 0; i < ramsize; i++)
  662                 *ux++ = 0;
  663         ux = maddr + SIRAM;
  664         for (i = 0; i < ramsize; i++) {
  665                 if ((was = *ux++) != 0) {
  666                         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  667                                 "si%d: clear fail at phys 0x%x, was %x\n",
  668                                 id->id_unit, paddr + i, was));
  669                         goto fail;
  670                 }
  671         }
  672 
  673         /*
  674          * Success, we've found a valid board, now fill in
  675          * the adapter structure.
  676          */
  677         switch (type) {
  678         case SIHOST2:
  679                 if ((id->id_irq & (IRQ11|IRQ12|IRQ15)) == 0) {
  680 bad_irq:
  681                         DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
  682                                 "si%d: bad IRQ value - %d\n",
  683                                 id->id_unit, id->id_irq));
  684                         return(0);
  685                 }
  686                 id->id_msize = SIHOST2_MEMSIZE;
  687                 break;
  688         case SIHOST:
  689                 if ((id->id_irq & (IRQ11|IRQ12|IRQ15)) == 0) {
  690                         goto bad_irq;
  691                 }
  692                 id->id_msize = SIHOST_MEMSIZE;
  693                 break;
  694         case SIJETISA:
  695                 if ((id->id_irq & (IRQ9|IRQ10|IRQ11|IRQ12|IRQ15)) == 0) {
  696                         goto bad_irq;
  697                 }
  698                 id->id_msize = SIJETISA_MEMSIZE;
  699                 break;
  700         case SIMCA:             /* MCA */
  701         default:
  702                 printf("si%d: %s not supported\n", id->id_unit, si_type[type]);
  703                 return(0);
  704         }
  705         id->id_intr = (inthand2_t *)si_intr; /* set here instead of config */
  706         si_softc[id->id_unit].sc_type = type;
  707         si_softc[id->id_unit].sc_typename = si_type[type];
  708         return(-1);     /* -1 == found */
  709 }
  710 
  711 /*
  712  * We have to make an 8 bit version of bcopy, since some cards can't
  713  * deal with 32 bit I/O
  714  */
  715 #if 1
  716 static void
  717 si_bcopy(const void *src, void *dst, size_t len)
  718 {
  719         while (len--)
  720                 *(((u_char *)dst)++) = *(((u_char *)src)++);
  721 }
  722 #else
  723 #define si_bcopy bcopy
  724 #endif
  725 
  726 
  727 /*
  728  * Attach the device.  Initialize the card.
  729  *
  730  * This routine also gets called by the EISA and PCI attach routines.
  731  * It presumes that the softstate for the unit has had had its type field
  732  * and the EISA specific stuff filled in, as well as the kernel virtual
  733  * base address and the unit number of the isa_device struct.
  734  */
  735 static int
  736 siattach(id)
  737         struct isa_device *id;
  738 {
  739         int unit = id->id_unit;
  740         struct si_softc *sc = &si_softc[unit];
  741         struct si_port *pp;
  742         volatile struct si_channel *ccbp;
  743         volatile struct si_reg *regp;
  744         volatile caddr_t maddr;
  745         struct si_module *modp;
  746         struct tty *tp;
  747         struct speedtab *spt;
  748         int nmodule, nport, x, y;
  749         int uart_type;
  750 
  751         DPRINT((0, DBG_AUTOBOOT, "si%d: siattach\n", id->id_unit));
  752 
  753         sc->sc_paddr = (caddr_t)vtophys(id->id_maddr);
  754         sc->sc_maddr = id->id_maddr;
  755         sc->sc_irq = id->id_irq;
  756 
  757         DPRINT((0, DBG_AUTOBOOT, "si%d: type: %s paddr: %x maddr: %x\n", unit,
  758                 sc->sc_typename, sc->sc_paddr, sc->sc_maddr));
  759 
  760         sc->sc_ports = NULL;                    /* mark as uninitialised */
  761 
  762         maddr = sc->sc_maddr;
  763 
  764         /* Stop the CPU first so it won't stomp around while we load */
  765 
  766         switch (sc->sc_type) {
  767 #if NEISA > 0
  768                 case SIEISA:
  769                         outb(sc->sc_eisa_iobase + 2, sc->sc_eisa_irq << 4);
  770                 break;
  771 #endif
  772 #if NPCI > 0
  773                 case SIPCI:
  774                         *(maddr+SIPCIRESET) = 0;
  775                 break;
  776                 case SIJETPCI: /* fall through to JET ISA */
  777 #endif
  778                 case SIJETISA:
  779                         *(maddr+SIJETCONFIG) = 0;
  780                 break;
  781                 case SIHOST2:
  782                         *(maddr+SIPLRESET) = 0;
  783                 break;
  784                 case SIHOST:
  785                         *(maddr+SIRESET) = 0;
  786                 break;
  787                 default: /* this should never happen */
  788                         printf("si%d: unsupported configuration\n", unit);
  789                         return 0;
  790                 break;
  791         }
  792 
  793         /* OK, now lets download the download code */
  794 
  795         if (SI_ISJET(sc->sc_type)) {
  796                 DPRINT((0, DBG_DOWNLOAD, "si%d: jet_download: nbytes %d\n",
  797                         id->id_unit, si3_t225_dsize));
  798                 si_bcopy(si3_t225_download, maddr + si3_t225_downloadaddr,
  799                         si3_t225_dsize);
  800                 DPRINT((0, DBG_DOWNLOAD,
  801                         "si%d: jet_bootstrap: nbytes %d -> %x\n",
  802                         id->id_unit, si3_t225_bsize, si3_t225_bootloadaddr));
  803                 si_bcopy(si3_t225_bootstrap, maddr + si3_t225_bootloadaddr,
  804                         si3_t225_bsize);
  805         } else {
  806                 DPRINT((0, DBG_DOWNLOAD, "si%d: si_download: nbytes %d\n",
  807                         id->id_unit, si2_z280_dsize));
  808                 si_bcopy(si2_z280_download, maddr + si2_z280_downloadaddr,
  809                         si2_z280_dsize);
  810         }
  811 
  812         /* Now start the CPU */
  813 
  814         switch (sc->sc_type) {
  815 #if NEISA > 0
  816         case SIEISA:
  817                 /* modify the download code to tell it that it's on an EISA */
  818                 *(maddr + 0x42) = 1;
  819                 outb(sc->sc_eisa_iobase + 2, (sc->sc_eisa_irq << 4) | 4);
  820                 (void)inb(sc->sc_eisa_iobase + 3); /* reset interrupt */
  821                 break;
  822 #endif
  823         case SIPCI:
  824                 /* modify the download code to tell it that it's on a PCI */
  825                 *(maddr+0x42) = 1;
  826                 *(maddr+SIPCIRESET) = 1;
  827                 *(maddr+SIPCIINTCL) = 0;
  828                 break;
  829         case SIJETPCI:
  830                 *(maddr+SIJETRESET) = 0;
  831                 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN;
  832                 break;
  833         case SIJETISA:
  834                 *(maddr+SIJETRESET) = 0;
  835                 switch (sc->sc_irq) {
  836                 case IRQ9:
  837                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0x90;
  838                         break;
  839                 case IRQ10:
  840                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xa0;
  841                         break;
  842                 case IRQ11:
  843                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xb0;
  844                         break;
  845                 case IRQ12:
  846                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xc0;
  847                         break;
  848                 case IRQ15:
  849                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xf0;
  850                         break;
  851                 }
  852                 break;
  853         case SIHOST:
  854                 *(maddr+SIRESET_CL) = 0;
  855                 *(maddr+SIINTCL_CL) = 0;
  856                 break;
  857         case SIHOST2:
  858                 *(maddr+SIPLRESET) = 0x10;
  859                 switch (sc->sc_irq) {
  860                 case IRQ11:
  861                         *(maddr+SIPLIRQ11) = 0x10;
  862                         break;
  863                 case IRQ12:
  864                         *(maddr+SIPLIRQ12) = 0x10;
  865                         break;
  866                 case IRQ15:
  867                         *(maddr+SIPLIRQ15) = 0x10;
  868                         break;
  869                 }
  870                 *(maddr+SIPLIRQCLR) = 0x10;
  871                 break;
  872         default: /* this should _REALLY_ never happen */
  873                 printf("si%d: Uh, it was supported a second ago...\n", unit);
  874                 return 0;
  875         }
  876 
  877         DELAY(1000000);                 /* wait around for a second */
  878 
  879         regp = (struct si_reg *)maddr;
  880         y = 0;
  881                                         /* wait max of 5 sec for init OK */
  882         while (regp->initstat == 0 && y++ < 10) {
  883                 DELAY(500000);
  884         }
  885         switch (regp->initstat) {
  886         case 0:
  887                 printf("si%d: startup timeout - aborting\n", unit);
  888                 sc->sc_type = SIEMPTY;
  889                 return 0;
  890         case 1:
  891                 if (SI_ISJET(sc->sc_type)) {
  892                         /* set throttle to 100 times per second */
  893                         regp->int_count = JET_INT_COUNT;
  894                         /* rx_intr_count is a NOP in Jet */
  895                 } else {
  896                         /* set throttle to 125 times per second */
  897                         regp->int_count = INT_COUNT;
  898                         /* rx intr max of 25 times per second */
  899                         regp->rx_int_count = RXINT_COUNT;
  900                 }
  901                 regp->int_pending = 0;          /* no intr pending */
  902                 regp->int_scounter = 0; /* reset counter */
  903                 break;
  904         case 0xff:
  905                 /*
  906                  * No modules found, so give up on this one.
  907                  */
  908                 printf("si%d: %s - no ports found\n", unit,
  909                         si_type[sc->sc_type]);
  910                 return 0;
  911         default:
  912                 printf("si%d: download code version error - initstat %x\n",
  913                         unit, regp->initstat);
  914                 return 0;
  915         }
  916 
  917         /*
  918          * First time around the ports just count them in order
  919          * to allocate some memory.
  920          */
  921         nport = 0;
  922         modp = (struct si_module *)(maddr + 0x80);
  923         for (;;) {
  924                 DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp));
  925                 switch (modp->sm_type) {
  926                 case TA4:
  927                         DPRINT((0, DBG_DOWNLOAD,
  928                                 "si%d: Found old TA4 module, 4 ports\n",
  929                                 unit));
  930                         x = 4;
  931                         break;
  932                 case TA8:
  933                         DPRINT((0, DBG_DOWNLOAD,
  934                                 "si%d: Found old TA8 module, 8 ports\n",
  935                                 unit));
  936                         x = 8;
  937                         break;
  938                 case TA4_ASIC:
  939                         DPRINT((0, DBG_DOWNLOAD,
  940                                 "si%d: Found ASIC TA4 module, 4 ports\n",
  941                                 unit));
  942                         x = 4;
  943                         break;
  944                 case TA8_ASIC:
  945                         DPRINT((0, DBG_DOWNLOAD,
  946                                 "si%d: Found ASIC TA8 module, 8 ports\n",
  947                                 unit));
  948                         x = 8;
  949                         break;
  950                 case MTA:
  951                         DPRINT((0, DBG_DOWNLOAD,
  952                                 "si%d: Found CD1400 module, 8 ports\n",
  953                                 unit));
  954                         x = 8;
  955                         break;
  956                 case SXDC:
  957                         DPRINT((0, DBG_DOWNLOAD,
  958                                 "si%d: Found SXDC module, 8 ports\n",
  959                                 unit));
  960                         x = 8;
  961                         break;
  962                 default:
  963                         printf("si%d: unknown module type %d\n",
  964                                 unit, modp->sm_type);
  965                         goto try_next;
  966                 }
  967 
  968                 /* this was limited in firmware and is also a driver issue */
  969                 if ((nport + x) > SI_MAXPORTPERCARD) {
  970                         printf("si%d: extra ports ignored\n", unit);
  971                         goto try_next;
  972                 }
  973 
  974                 nport += x;
  975                 si_Nports += x;
  976                 si_Nmodules++;
  977 
  978 try_next:
  979                 if (modp->sm_next == 0)
  980                         break;
  981                 modp = (struct si_module *)
  982                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
  983         }
  984         sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport,
  985                 M_DEVBUF, M_NOWAIT);
  986         if (sc->sc_ports == 0) {
  987 mem_fail:
  988                 printf("si%d: fail to malloc memory for port structs\n",
  989                         unit);
  990                 return 0;
  991         }
  992         bzero(sc->sc_ports, sizeof(struct si_port) * nport);
  993         sc->sc_nport = nport;
  994 
  995         /*
  996          * allocate tty structures for ports
  997          */
  998         tp = (struct tty *)malloc(sizeof(*tp) * nport, M_DEVBUF, M_NOWAIT);
  999         if (tp == 0)
 1000                 goto mem_fail;
 1001         bzero(tp, sizeof(*tp) * nport);
 1002         si_tty = tp;
 1003 
 1004         /*
 1005          * Scan round the ports again, this time initialising.
 1006          */
 1007         pp = sc->sc_ports;
 1008         nmodule = 0;
 1009         modp = (struct si_module *)(maddr + 0x80);
 1010         uart_type = 1000;       /* arbitary, > uchar_max */
 1011         for (;;) {
 1012                 switch (modp->sm_type) {
 1013                 case TA4:
 1014                         nport = 4;
 1015                         break;
 1016                 case TA8:
 1017                         nport = 8;
 1018                         break;
 1019                 case TA4_ASIC:
 1020                         nport = 4;
 1021                         break;
 1022                 case TA8_ASIC:
 1023                         nport = 8;
 1024                         break;
 1025                 case MTA:
 1026                         nport = 8;
 1027                         break;
 1028                 case SXDC:
 1029                         nport = 8;
 1030                         break;
 1031                 default:
 1032                         goto try_next2;
 1033                 }
 1034                 nmodule++;
 1035                 ccbp = (struct si_channel *)((char *)modp + 0x100);
 1036                 if (uart_type == 1000)
 1037                         uart_type = ccbp->type;
 1038                 else if (uart_type != ccbp->type)
 1039                         printf("si%d: Warning: module %d mismatch! (%d%s != %d%s)\n",
 1040                             unit, nmodule,
 1041                             ccbp->type, si_modulename(sc->sc_type, ccbp->type),
 1042                             uart_type, si_modulename(sc->sc_type, uart_type));
 1043 
 1044                 for (x = 0; x < nport; x++, pp++, ccbp++) {
 1045                         pp->sp_ccb = ccbp;      /* save the address */
 1046                         pp->sp_tty = tp++;
 1047                         pp->sp_pend = IDLE_CLOSE;
 1048                         pp->sp_state = 0;       /* internal flag */
 1049                         pp->sp_dtr_wait = 3 * hz;
 1050                         pp->sp_iin.c_iflag = TTYDEF_IFLAG;
 1051                         pp->sp_iin.c_oflag = TTYDEF_OFLAG;
 1052                         pp->sp_iin.c_cflag = TTYDEF_CFLAG;
 1053                         pp->sp_iin.c_lflag = TTYDEF_LFLAG;
 1054                         termioschars(&pp->sp_iin);
 1055                         pp->sp_iin.c_ispeed = pp->sp_iin.c_ospeed =
 1056                                 TTYDEF_SPEED;;
 1057                         pp->sp_iout = pp->sp_iin;
 1058                 }
 1059 try_next2:
 1060                 if (modp->sm_next == 0) {
 1061                         printf("si%d: card: %s, ports: %d, modules: %d, type: %d%s\n",
 1062                                 unit,
 1063                                 sc->sc_typename,
 1064                                 sc->sc_nport,
 1065                                 nmodule,
 1066                                 uart_type,
 1067                                 si_modulename(sc->sc_type, uart_type));
 1068                         break;
 1069                 }
 1070                 modp = (struct si_module *)
 1071                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
 1072         }
 1073         if (done_chartimes == 0) {
 1074                 for (spt = chartimes ; spt->sp_speed != -1; spt++) {
 1075                         if ((spt->sp_code /= hz) == 0)
 1076                                 spt->sp_code = 1;
 1077                 }
 1078                 done_chartimes = 1;
 1079         }
 1080 
 1081 #ifdef DEVFS
 1082 /*      path    name    devsw           minor   type   uid gid perm*/
 1083         for ( x = 0; x < sc->sc_nport; x++ ) {
 1084                 /* sync with the manuals that start at 1 */
 1085                 y = x + 1 + id->id_unit * (1 << SI_CARDSHIFT);
 1086                 sc->devfs_token[x].ttya = devfs_add_devswf(
 1087                         &si_cdevsw, x,
 1088                         DV_CHR, 0, 0, 0600, "ttyA%02d", y);
 1089                 sc->devfs_token[x].cuaa = devfs_add_devswf(
 1090                         &si_cdevsw, x + 0x00080,
 1091                         DV_CHR, 0, 0, 0600, "cuaA%02d", y);
 1092                 sc->devfs_token[x].ttyi = devfs_add_devswf(
 1093                         &si_cdevsw, x + 0x10000,
 1094                         DV_CHR, 0, 0, 0600, "ttyiA%02d", y);
 1095                 sc->devfs_token[x].cuai = devfs_add_devswf(
 1096                         &si_cdevsw, x + 0x10080,
 1097                         DV_CHR, 0, 0, 0600, "cuaiA%02d", y);
 1098                 sc->devfs_token[x].ttyl = devfs_add_devswf(
 1099                         &si_cdevsw, x + 0x20000,
 1100                         DV_CHR, 0, 0, 0600, "ttylA%02d", y);
 1101                 sc->devfs_token[x].cual = devfs_add_devswf(
 1102                         &si_cdevsw, x + 0x20080,
 1103                         DV_CHR, 0, 0, 0600, "cualA%02d", y);
 1104         }
 1105         sc->control_token = 
 1106                 devfs_add_devswf(&si_cdevsw, 0x40000, DV_CHR, 0, 0, 0600, 
 1107                                  "si_control");
 1108 #endif
 1109         return (1);
 1110 }
 1111 
 1112 static  int
 1113 siopen(dev, flag, mode, p)
 1114         dev_t dev;
 1115         int flag, mode;
 1116         struct proc *p;
 1117 {
 1118         int oldspl, error;
 1119         int card, port;
 1120         register struct si_softc *sc;
 1121         register struct tty *tp;
 1122         volatile struct si_channel *ccbp;
 1123         struct si_port *pp;
 1124         int mynor = minor(dev);
 1125 
 1126         /* quickly let in /dev/si_control */
 1127         if (IS_CONTROLDEV(mynor)) {
 1128                 if ((error = suser(p->p_ucred, &p->p_acflag)))
 1129                         return(error);
 1130                 return(0);
 1131         }
 1132 
 1133         card = SI_CARD(mynor);
 1134         if (card >= NSI)
 1135                 return (ENXIO);
 1136         sc = &si_softc[card];
 1137 
 1138         if (sc->sc_type == SIEMPTY) {
 1139                 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",
 1140                         card, sc->sc_typename));
 1141                 return(ENXIO);
 1142         }
 1143 
 1144         port = SI_PORT(mynor);
 1145         if (port >= sc->sc_nport) {
 1146                 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",
 1147                         card, sc->sc_nport));
 1148                 return(ENXIO);
 1149         }
 1150 
 1151 #ifdef  POLL
 1152         /*
 1153          * We've now got a device, so start the poller.
 1154          */
 1155         if (init_finished == 0) {
 1156                 timeout(si_poll, (caddr_t)0L, si_pollrate);
 1157                 init_finished = 1;
 1158         }
 1159 #endif
 1160 
 1161         /* initial/lock device */
 1162         if (IS_STATE(mynor)) {
 1163                 return(0);
 1164         }
 1165 
 1166         pp = sc->sc_ports + port;
 1167         tp = pp->sp_tty;                        /* the "real" tty */
 1168         ccbp = pp->sp_ccb;                      /* Find control block */
 1169         DPRINT((pp, DBG_ENTRY|DBG_OPEN, "siopen(%x,%x,%x,%x)\n",
 1170                 dev, flag, mode, p));
 1171 
 1172         oldspl = spltty();                      /* Keep others out */
 1173         error = 0;
 1174 
 1175 open_top:
 1176         while (pp->sp_state & SS_DTR_OFF) {
 1177                 error = tsleep(&pp->sp_dtr_wait, TTIPRI|PCATCH, "sidtr", 0);
 1178                 if (error != 0)
 1179                         goto out;
 1180         }
 1181 
 1182         if (tp->t_state & TS_ISOPEN) {
 1183                 /*
 1184                  * The device is open, so everything has been initialised.
 1185                  * handle conflicts.
 1186                  */
 1187                 if (IS_CALLOUT(mynor)) {
 1188                         if (!pp->sp_active_out) {
 1189                                 error = EBUSY;
 1190                                 goto out;
 1191                         }
 1192                 } else {
 1193                         if (pp->sp_active_out) {
 1194                                 if (flag & O_NONBLOCK) {
 1195                                         error = EBUSY;
 1196                                         goto out;
 1197                                 }
 1198                                 error = tsleep(&pp->sp_active_out,
 1199                                                 TTIPRI|PCATCH, "sibi", 0);
 1200                                 if (error != 0)
 1201                                         goto out;
 1202                                 goto open_top;
 1203                         }
 1204                 }
 1205                 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
 1206                         DPRINT((pp, DBG_OPEN|DBG_FAIL,
 1207                                 "already open and EXCLUSIVE set\n"));
 1208                         error = EBUSY;
 1209                         goto out;
 1210                 }
 1211         } else {
 1212                 /*
 1213                  * The device isn't open, so there are no conflicts.
 1214                  * Initialize it. Avoid sleep... :-)
 1215                  */
 1216                 DPRINT((pp, DBG_OPEN, "first open\n"));
 1217                 tp->t_oproc = si_start;
 1218                 tp->t_param = siparam;
 1219                 tp->t_dev = dev;
 1220                 tp->t_termios = mynor & SI_CALLOUT_MASK
 1221                                 ? pp->sp_iout : pp->sp_iin;
 1222 
 1223                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
 1224 
 1225                 ++pp->sp_wopeners;      /* in case of sleep in siparam */
 1226 
 1227                 error = siparam(tp, &tp->t_termios);
 1228 
 1229                 --pp->sp_wopeners;
 1230                 if (error != 0)
 1231                         goto out;
 1232                 /* XXX: we should goto_top if siparam slept */
 1233 
 1234                 ttsetwater(tp);
 1235 
 1236                 /* set initial DCD state */
 1237                 pp->sp_last_hi_ip = ccbp->hi_ip;
 1238                 if ((pp->sp_last_hi_ip & IP_DCD) || IS_CALLOUT(mynor)) {
 1239                         (*linesw[tp->t_line].l_modem)(tp, 1);
 1240                 }
 1241         }
 1242 
 1243         /* whoops! we beat the close! */
 1244         if (pp->sp_state & SS_CLOSING) {
 1245                 /* try and stop it from proceeding to bash the hardware */
 1246                 pp->sp_state &= ~SS_CLOSING;
 1247         }
 1248 
 1249         /*
 1250          * Wait for DCD if necessary
 1251          */
 1252         if (!(tp->t_state & TS_CARR_ON)
 1253             && !IS_CALLOUT(mynor)
 1254             && !(tp->t_cflag & CLOCAL)
 1255             && !(flag & O_NONBLOCK)) {
 1256                 ++pp->sp_wopeners;
 1257                 DPRINT((pp, DBG_OPEN, "sleeping for carrier\n"));
 1258                 error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "sidcd", 0);
 1259                 --pp->sp_wopeners;
 1260                 if (error != 0)
 1261                         goto out;
 1262                 goto open_top;
 1263         }
 1264 
 1265         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1266         si_disc_optim(tp, &tp->t_termios, pp);
 1267         if (tp->t_state & TS_ISOPEN && IS_CALLOUT(mynor))
 1268                 pp->sp_active_out = TRUE;
 1269 
 1270         pp->sp_state |= SS_OPEN;        /* made it! */
 1271 
 1272 out:
 1273         splx(oldspl);
 1274 
 1275         DPRINT((pp, DBG_OPEN, "leaving siopen\n"));
 1276 
 1277         if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0)
 1278                 sihardclose(pp);
 1279 
 1280         return(error);
 1281 }
 1282 
 1283 static  int
 1284 siclose(dev, flag, mode, p)
 1285         dev_t dev;
 1286         int flag, mode;
 1287         struct proc *p;
 1288 {
 1289         register struct si_port *pp;
 1290         register struct tty *tp;
 1291         int oldspl;
 1292         int error = 0;
 1293         int mynor = minor(dev);
 1294 
 1295         if (IS_SPECIAL(mynor))
 1296                 return(0);
 1297 
 1298         oldspl = spltty();
 1299 
 1300         pp = MINOR2PP(mynor);
 1301         tp = pp->sp_tty;
 1302 
 1303         DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "siclose(%x,%x,%x,%x) sp_state:%x\n",
 1304                 dev, flag, mode, p, pp->sp_state));
 1305 
 1306         /* did we sleep and loose a race? */
 1307         if (pp->sp_state & SS_CLOSING) {
 1308                 /* error = ESOMETING? */
 1309                 goto out;
 1310         }
 1311 
 1312         /* begin race detection.. */
 1313         pp->sp_state |= SS_CLOSING;
 1314 
 1315         si_write_enable(pp, 0);         /* block writes for ttywait() */
 1316 
 1317         /* THIS MAY SLEEP IN TTYWAIT!!! */
 1318         (*linesw[tp->t_line].l_close)(tp, flag);
 1319 
 1320         si_write_enable(pp, 1);
 1321 
 1322         /* did we sleep and somebody started another open? */
 1323         if (!(pp->sp_state & SS_CLOSING)) {
 1324                 /* error = ESOMETING? */
 1325                 goto out;
 1326         }
 1327         /* ok. we are now still on the right track.. nuke the hardware */
 1328 
 1329         if (pp->sp_state & SS_LSTART) {
 1330                 untimeout((timeout_func_t)si_lstart, (caddr_t)pp);
 1331                 pp->sp_state &= ~SS_LSTART;
 1332         }
 1333 
 1334         sistop(tp, FREAD | FWRITE);
 1335 
 1336         sihardclose(pp);
 1337         ttyclose(tp);
 1338         pp->sp_state &= ~SS_OPEN;
 1339 
 1340 out:
 1341         DPRINT((pp, DBG_CLOSE|DBG_EXIT, "close done, returning\n"));
 1342         splx(oldspl);
 1343         return(error);
 1344 }
 1345 
 1346 static void
 1347 sihardclose(pp)
 1348         struct si_port *pp;
 1349 {
 1350         int oldspl;
 1351         struct tty *tp;
 1352         volatile struct si_channel *ccbp;
 1353 
 1354         oldspl = spltty();
 1355 
 1356         tp = pp->sp_tty;
 1357         ccbp = pp->sp_ccb;                      /* Find control block */
 1358         if (tp->t_cflag & HUPCL
 1359             || (!pp->sp_active_out
 1360                 && !(ccbp->hi_ip & IP_DCD)
 1361                 && !(pp->sp_iin.c_cflag && CLOCAL))
 1362             || !(tp->t_state & TS_ISOPEN)) {
 1363 
 1364                 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
 1365                 (void) si_command(pp, FCLOSE, SI_NOWAIT);
 1366 
 1367                 if (pp->sp_dtr_wait != 0) {
 1368                         timeout(sidtrwakeup, pp, pp->sp_dtr_wait);
 1369                         pp->sp_state |= SS_DTR_OFF;
 1370                 }
 1371 
 1372         }
 1373         pp->sp_active_out = FALSE;
 1374         wakeup((caddr_t)&pp->sp_active_out);
 1375         wakeup(TSA_CARR_ON(tp));
 1376 
 1377         splx(oldspl);
 1378 }
 1379 
 1380 
 1381 /*
 1382  * called at splsoftclock()...
 1383  */
 1384 static void
 1385 sidtrwakeup(chan)
 1386         void *chan;
 1387 {
 1388         struct si_port *pp;
 1389         int oldspl;
 1390 
 1391         oldspl = spltty();
 1392 
 1393         pp = (struct si_port *)chan;
 1394         pp->sp_state &= ~SS_DTR_OFF;
 1395         wakeup(&pp->sp_dtr_wait);
 1396 
 1397         splx(oldspl);
 1398 }
 1399 
 1400 /*
 1401  * User level stuff - read and write
 1402  */
 1403 static  int
 1404 siread(dev, uio, flag)
 1405         register dev_t dev;
 1406         struct uio *uio;
 1407         int flag;
 1408 {
 1409         register struct tty *tp;
 1410         int mynor = minor(dev);
 1411 
 1412         if (IS_SPECIAL(mynor)) {
 1413                 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_READ, "siread(CONTROLDEV!!)\n"));
 1414                 return(ENODEV);
 1415         }
 1416         tp = MINOR2TP(mynor);
 1417         DPRINT((TP2PP(tp), DBG_ENTRY|DBG_READ,
 1418                 "siread(%x,%x,%x)\n", dev, uio, flag));
 1419         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 1420 }
 1421 
 1422 
 1423 static  int
 1424 siwrite(dev, uio, flag)
 1425         dev_t dev;
 1426         struct uio *uio;
 1427         int flag;
 1428 {
 1429         register struct si_port *pp;
 1430         register struct tty *tp;
 1431         int error = 0;
 1432         int mynor = minor(dev);
 1433         int oldspl;
 1434 
 1435         if (IS_SPECIAL(mynor)) {
 1436                 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_WRITE, "siwrite(CONTROLDEV!!)\n"));
 1437                 return(ENODEV);
 1438         }
 1439         pp = MINOR2PP(mynor);
 1440         tp = pp->sp_tty;
 1441         DPRINT((pp, DBG_WRITE, "siwrite(%x,%x,%x)\n", dev, uio, flag));
 1442 
 1443         oldspl = spltty();
 1444         /*
 1445          * If writes are currently blocked, wait on the "real" tty
 1446          */
 1447         while (pp->sp_state & SS_BLOCKWRITE) {
 1448                 pp->sp_state |= SS_WAITWRITE;
 1449                 DPRINT((pp, DBG_WRITE, "in siwrite, wait for SS_BLOCKWRITE to clear\n"));
 1450                 if ((error = ttysleep(tp, (caddr_t)pp, TTOPRI|PCATCH,
 1451                                      "siwrite", tp->t_timeout))) {
 1452                         if (error == EWOULDBLOCK)
 1453                                 error = EIO;
 1454                         goto out;
 1455                 }
 1456         }
 1457 
 1458         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
 1459 out:
 1460         splx(oldspl);
 1461         return (error);
 1462 }
 1463 
 1464 
 1465 static  struct tty *
 1466 sidevtotty(dev_t dev)
 1467 {
 1468         struct si_port *pp;
 1469         int mynor = minor(dev);
 1470         struct si_softc *sc = &si_softc[SI_CARD(mynor)];
 1471 
 1472         if (IS_SPECIAL(mynor))
 1473                 return(NULL);
 1474         if (SI_PORT(mynor) >= sc->sc_nport)
 1475                 return(NULL);
 1476         pp = MINOR2PP(mynor);
 1477         return (pp->sp_tty);
 1478 }
 1479 
 1480 static  int
 1481 siioctl(dev, cmd, data, flag, p)
 1482         dev_t dev;
 1483         int cmd;
 1484         caddr_t data;
 1485         int flag;
 1486         struct proc *p;
 1487 {
 1488         struct si_port *pp;
 1489         register struct tty *tp;
 1490         int error;
 1491         int mynor = minor(dev);
 1492         int oldspl;
 1493         int blocked = 0;
 1494 #if defined(COMPAT_43)
 1495         int oldcmd;
 1496         struct termios term;
 1497 #endif
 1498 
 1499         if (IS_SI_IOCTL(cmd))
 1500                 return(si_Sioctl(dev, cmd, data, flag, p));
 1501 
 1502         pp = MINOR2PP(mynor);
 1503         tp = pp->sp_tty;
 1504 
 1505         DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "siioctl(%x,%x,%x,%x)\n",
 1506                 dev, cmd, data, flag));
 1507         if (IS_STATE(mynor)) {
 1508                 struct termios *ct;
 1509 
 1510                 switch (mynor & SI_STATE_MASK) {
 1511                 case SI_INIT_STATE_MASK:
 1512                         ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin;
 1513                         break;
 1514                 case SI_LOCK_STATE_MASK:
 1515                         ct = IS_CALLOUT(mynor) ? &pp->sp_lout : &pp->sp_lin;
 1516                         break;
 1517                 default:
 1518                         return (ENODEV);
 1519                 }
 1520                 switch (cmd) {
 1521                 case TIOCSETA:
 1522                         error = suser(p->p_ucred, &p->p_acflag);
 1523                         if (error != 0)
 1524                                 return (error);
 1525                         *ct = *(struct termios *)data;
 1526                         return (0);
 1527                 case TIOCGETA:
 1528                         *(struct termios *)data = *ct;
 1529                         return (0);
 1530                 case TIOCGETD:
 1531                         *(int *)data = TTYDISC;
 1532                         return (0);
 1533                 case TIOCGWINSZ:
 1534                         bzero(data, sizeof(struct winsize));
 1535                         return (0);
 1536                 default:
 1537                         return (ENOTTY);
 1538                 }
 1539         }
 1540         /*
 1541          * Do the old-style ioctl compat routines...
 1542          */
 1543 #if defined(COMPAT_43)
 1544         term = tp->t_termios;
 1545         oldcmd = cmd;
 1546         error = ttsetcompat(tp, &cmd, data, &term);
 1547         if (error != 0)
 1548                 return (error);
 1549         if (cmd != oldcmd)
 1550                 data = (caddr_t)&term;
 1551 #endif
 1552         /*
 1553          * Do the initial / lock state business
 1554          */
 1555         if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
 1556                 int     cc;
 1557                 struct termios *dt = (struct termios *)data;
 1558                 struct termios *lt = mynor & SI_CALLOUT_MASK
 1559                                      ? &pp->sp_lout : &pp->sp_lin;
 1560 
 1561                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1562                         | (dt->c_iflag & ~lt->c_iflag);
 1563                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1564                         | (dt->c_oflag & ~lt->c_oflag);
 1565                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1566                         | (dt->c_cflag & ~lt->c_cflag);
 1567                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1568                         | (dt->c_lflag & ~lt->c_lflag);
 1569                 for (cc = 0; cc < NCCS; ++cc)
 1570                         if (lt->c_cc[cc] != 0)
 1571                                 dt->c_cc[cc] = tp->t_cc[cc];
 1572                 if (lt->c_ispeed != 0)
 1573                         dt->c_ispeed = tp->t_ispeed;
 1574                 if (lt->c_ospeed != 0)
 1575                         dt->c_ospeed = tp->t_ospeed;
 1576         }
 1577 
 1578         /*
 1579          * Block user-level writes to give the ttywait()
 1580          * a chance to completely drain for commands
 1581          * that require the port to be in a quiescent state.
 1582          */
 1583         switch (cmd) {
 1584         case TIOCSETAW:
 1585         case TIOCSETAF:
 1586         case TIOCDRAIN:
 1587 #ifdef COMPAT_43
 1588         case TIOCSETP:
 1589 #endif
 1590                 blocked++;      /* block writes for ttywait() and siparam() */
 1591                 si_write_enable(pp, 0);
 1592         }
 1593 
 1594         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 1595         if (error >= 0)
 1596                 goto out;
 1597 
 1598         oldspl = spltty();
 1599 
 1600         error = ttioctl(tp, cmd, data, flag);
 1601         si_disc_optim(tp, &tp->t_termios, pp);
 1602         if (error >= 0)
 1603                 goto outspl;
 1604 
 1605         switch (cmd) {
 1606         case TIOCSBRK:
 1607                 si_command(pp, SBREAK, SI_WAIT);
 1608                 break;
 1609         case TIOCCBRK:
 1610                 si_command(pp, EBREAK, SI_WAIT);
 1611                 break;
 1612         case TIOCSDTR:
 1613                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
 1614                 break;
 1615         case TIOCCDTR:
 1616                 (void) si_modem(pp, SET, 0);
 1617                 break;
 1618         case TIOCMSET:
 1619                 (void) si_modem(pp, SET, *(int *)data);
 1620                 break;
 1621         case TIOCMBIS:
 1622                 (void) si_modem(pp, BIS, *(int *)data);
 1623                 break;
 1624         case TIOCMBIC:
 1625                 (void) si_modem(pp, BIC, *(int *)data);
 1626                 break;
 1627         case TIOCMGET:
 1628                 *(int *)data = si_modem(pp, GET, 0);
 1629                 break;
 1630         case TIOCMSDTRWAIT:
 1631                 /* must be root since the wait applies to following logins */
 1632                 error = suser(p->p_ucred, &p->p_acflag);
 1633                 if (error != 0) {
 1634                         goto outspl;
 1635                 }
 1636                 pp->sp_dtr_wait = *(int *)data * hz / 100;
 1637                 break;
 1638         case TIOCMGDTRWAIT:
 1639                 *(int *)data = pp->sp_dtr_wait * 100 / hz;
 1640                 break;
 1641 
 1642         default:
 1643                 error = ENOTTY;
 1644         }
 1645         error = 0;
 1646 outspl:
 1647         splx(oldspl);
 1648 out:
 1649         DPRINT((pp, DBG_IOCTL|DBG_EXIT, "siioctl ret %d\n", error));
 1650         if (blocked)
 1651                 si_write_enable(pp, 1);
 1652         return(error);
 1653 }
 1654 
 1655 /*
 1656  * Handle the Specialix ioctls. All MUST be called via the CONTROL device
 1657  */
 1658 static int
 1659 si_Sioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 1660 {
 1661         struct si_softc *xsc;
 1662         register struct si_port *xpp;
 1663         volatile struct si_reg *regp;
 1664         struct si_tcsi *dp;
 1665         struct si_pstat *sps;
 1666         int *ip, error = 0;
 1667         int oldspl;
 1668         int card, port;
 1669         int mynor = minor(dev);
 1670 
 1671         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%x,%x,%x,%x)\n",
 1672                 dev, cmd, data, flag));
 1673 
 1674 #if 1
 1675         DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT));
 1676         DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB));
 1677         DPRINT((0, DBG_IOCTL, "TCSI_TTY=%x\n", TCSI_TTY));
 1678 #endif
 1679 
 1680         if (!IS_CONTROLDEV(mynor)) {
 1681                 DPRINT((0, DBG_IOCTL|DBG_FAIL, "not called from control device!\n"));
 1682                 return(ENODEV);
 1683         }
 1684 
 1685         oldspl = spltty();      /* better safe than sorry */
 1686 
 1687         ip = (int *)data;
 1688 
 1689 #define SUCHECK if ((error = suser(p->p_ucred, &p->p_acflag))) goto out
 1690 
 1691         switch (cmd) {
 1692         case TCSIPORTS:
 1693                 *ip = si_Nports;
 1694                 goto out;
 1695         case TCSIMODULES:
 1696                 *ip = si_Nmodules;
 1697                 goto out;
 1698         case TCSISDBG_ALL:
 1699                 SUCHECK;
 1700                 si_debug = *ip;
 1701                 goto out;
 1702         case TCSIGDBG_ALL:
 1703                 *ip = si_debug;
 1704                 goto out;
 1705         default:
 1706                 /*
 1707                  * Check that a controller for this port exists
 1708                  */
 1709 
 1710                 /* may also be a struct si_pstat, a superset of si_tcsi */
 1711 
 1712                 dp = (struct si_tcsi *)data;
 1713                 sps = (struct si_pstat *)data;
 1714                 card = dp->tc_card;
 1715                 xsc = &si_softc[card];  /* check.. */
 1716                 if (card < 0 || card >= NSI || xsc->sc_type == SIEMPTY) {
 1717                         error = ENOENT;
 1718                         goto out;
 1719                 }
 1720                 /*
 1721                  * And check that a port exists
 1722                  */
 1723                 port = dp->tc_port;
 1724                 if (port < 0 || port >= xsc->sc_nport) {
 1725                         error = ENOENT;
 1726                         goto out;
 1727                 }
 1728                 xpp = xsc->sc_ports + port;
 1729                 regp = (struct si_reg *)xsc->sc_maddr;
 1730         }
 1731 
 1732         switch (cmd) {
 1733         case TCSIDEBUG:
 1734 #ifdef  SI_DEBUG
 1735                 SUCHECK;
 1736                 if (xpp->sp_debug)
 1737                         xpp->sp_debug = 0;
 1738                 else {
 1739                         xpp->sp_debug = DBG_ALL;
 1740                         DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",
 1741                                 (xpp->sp_debug&DBG_ALL)?"ON":"OFF"));
 1742                 }
 1743                 break;
 1744 #else
 1745                 error = ENODEV;
 1746                 goto out;
 1747 #endif
 1748         case TCSISDBG_LEVEL:
 1749         case TCSIGDBG_LEVEL:
 1750 #ifdef  SI_DEBUG
 1751                 if (cmd == TCSIGDBG_LEVEL) {
 1752                         dp->tc_dbglvl = xpp->sp_debug;
 1753                 } else {
 1754                         SUCHECK;
 1755                         xpp->sp_debug = dp->tc_dbglvl;
 1756                 }
 1757                 break;
 1758 #else
 1759                 error = ENODEV;
 1760                 goto out;
 1761 #endif
 1762         case TCSIGRXIT:
 1763                 dp->tc_int = regp->rx_int_count;
 1764                 break;
 1765         case TCSIRXIT:
 1766                 SUCHECK;
 1767                 regp->rx_int_count = dp->tc_int;
 1768                 break;
 1769         case TCSIGIT:
 1770                 dp->tc_int = regp->int_count;
 1771                 break;
 1772         case TCSIIT:
 1773                 SUCHECK;
 1774                 regp->int_count = dp->tc_int;
 1775                 break;
 1776         case TCSISTATE:
 1777                 dp->tc_int = xpp->sp_ccb->hi_ip;
 1778                 break;
 1779         /* these next three use a different structure */
 1780         case TCSI_PORT:
 1781                 SUCHECK;
 1782                 si_bcopy(xpp, &sps->tc_siport, sizeof(sps->tc_siport));
 1783                 break;
 1784         case TCSI_CCB:
 1785                 SUCHECK;
 1786                 si_bcopy((char *)xpp->sp_ccb, &sps->tc_ccb, sizeof(sps->tc_ccb));
 1787                 break;
 1788         case TCSI_TTY:
 1789                 SUCHECK;
 1790                 si_bcopy(xpp->sp_tty, &sps->tc_tty, sizeof(sps->tc_tty));
 1791                 break;
 1792         default:
 1793                 error = EINVAL;
 1794                 goto out;
 1795         }
 1796 out:
 1797         splx(oldspl);
 1798         return(error);          /* success */
 1799 }
 1800 
 1801 /*
 1802  *      siparam()       : Configure line params
 1803  *      called at spltty();
 1804  *      this may sleep, does not flush, nor wait for drain, nor block writes
 1805  *      caller must arrange this if it's important..
 1806  */
 1807 static int
 1808 siparam(tp, t)
 1809         register struct tty *tp;
 1810         register struct termios *t;
 1811 {
 1812         register struct si_port *pp = TP2PP(tp);
 1813         volatile struct si_channel *ccbp;
 1814         int oldspl, cflag, iflag, oflag, lflag;
 1815         int error = 0;          /* shutup gcc */
 1816         int ispeed = 0;         /* shutup gcc */
 1817         int ospeed = 0;         /* shutup gcc */
 1818         BYTE val;
 1819 
 1820         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
 1821         cflag = t->c_cflag;
 1822         iflag = t->c_iflag;
 1823         oflag = t->c_oflag;
 1824         lflag = t->c_lflag;
 1825         DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",
 1826                 oflag, cflag, iflag, lflag));
 1827 
 1828         /* XXX - if Jet host and SXDC module, use extended baud rates */
 1829 
 1830         /* if not hung up.. */
 1831         if (t->c_ospeed != 0) {
 1832                 /* translate baud rate to firmware values */
 1833                 ospeed = ttspeedtab(t->c_ospeed, bdrates);
 1834                 ispeed = t->c_ispeed ?
 1835                          ttspeedtab(t->c_ispeed, bdrates) : ospeed;
 1836 
 1837                 /* enforce legit baud rate */
 1838                 if (ospeed < 0 || ispeed < 0)
 1839                         return (EINVAL);
 1840         }
 1841 
 1842         oldspl = spltty();
 1843 
 1844         ccbp = pp->sp_ccb;
 1845 
 1846         /* ========== set hi_break ========== */
 1847         val = 0;
 1848         if (iflag & IGNBRK)             /* Breaks */
 1849                 val |= BR_IGN;
 1850         if (iflag & BRKINT)             /* Interrupt on break? */
 1851                 val |= BR_INT;
 1852         if (iflag & PARMRK)             /* Parity mark? */
 1853                 val |= BR_PARMRK;
 1854         if (iflag & IGNPAR)             /* Ignore chars with parity errors? */
 1855                 val |= BR_PARIGN;
 1856         ccbp->hi_break = val;
 1857 
 1858         /* ========== set hi_csr ========== */
 1859         /* if not hung up.. */
 1860         if (t->c_ospeed != 0) {
 1861                 /* Set I/O speeds */
 1862                  val = (ispeed << 4) | ospeed;
 1863         }
 1864         ccbp->hi_csr = val;
 1865 
 1866         /* ========== set hi_mr2 ========== */
 1867         val = 0;
 1868         if (cflag & CSTOPB)                             /* Stop bits */
 1869                 val |= MR2_2_STOP;
 1870         else
 1871                 val |= MR2_1_STOP;
 1872         /*
 1873          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
 1874          * a DCE, hence the reverse sense of RTS and CTS
 1875          */
 1876         /* Output Flow - RTS must be raised before data can be sent */
 1877         if (cflag & CCTS_OFLOW)
 1878                 val |= MR2_RTSCONT;
 1879 
 1880         ccbp->hi_mr2 = val;
 1881 
 1882         /* ========== set hi_mr1 ========== */
 1883         val = 0;
 1884         if (!(cflag & PARENB))                          /* Parity */
 1885                 val |= MR1_NONE;
 1886         else
 1887                 val |= MR1_WITH;
 1888         if (cflag & PARODD)
 1889                 val |= MR1_ODD;
 1890 
 1891         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
 1892                 val |= MR1_8_BITS;
 1893         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
 1894                 val |= MR1_7_BITS;
 1895         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
 1896                 val |= MR1_6_BITS;
 1897         } else {                                        /* Must be 5 */
 1898                 val |= MR1_5_BITS;
 1899         }
 1900         /*
 1901          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
 1902          * a DCE, hence the reverse sense of RTS and CTS
 1903          */
 1904         /* Input Flow - CTS is raised when port is ready to receive data */
 1905         if (cflag & CRTS_IFLOW)
 1906                 val |= MR1_CTSCONT;
 1907 
 1908         ccbp->hi_mr1 = val;
 1909 
 1910         /* ========== set hi_mask ========== */
 1911         val = 0xff;
 1912         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
 1913                 val &= 0xFF;
 1914         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
 1915                 val &= 0x7F;
 1916         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
 1917                 val &= 0x3F;
 1918         } else {                                        /* Must be 5 */
 1919                 val &= 0x1F;
 1920         }
 1921         if (iflag & ISTRIP)
 1922                 val &= 0x7F;
 1923 
 1924         ccbp->hi_mask = val;
 1925 
 1926         /* ========== set hi_prtcl ========== */
 1927         val = 0;
 1928                                 /* Monitor DCD etc. if a modem */
 1929         if (!(cflag & CLOCAL))
 1930                 val |= SP_DCEN;
 1931         if (iflag & IXANY)
 1932                 val |= SP_TANY;
 1933         if (iflag & IXON)
 1934                 val |= SP_TXEN;
 1935         if (iflag & IXOFF)
 1936                 val |= SP_RXEN;
 1937         if (iflag & INPCK)
 1938                 val |= SP_PAEN;
 1939 
 1940         ccbp->hi_prtcl = val;
 1941 
 1942 
 1943         /* ========== set hi_{rx|tx}{on|off} ========== */
 1944         /* XXX: the card TOTALLY shields us from the flow control... */
 1945         ccbp->hi_txon = t->c_cc[VSTART];
 1946         ccbp->hi_txoff = t->c_cc[VSTOP];
 1947 
 1948         ccbp->hi_rxon = t->c_cc[VSTART];
 1949         ccbp->hi_rxoff = t->c_cc[VSTOP];
 1950 
 1951         /* ========== send settings to the card ========== */
 1952         /* potential sleep here */
 1953         if (ccbp->hi_stat == IDLE_CLOSE)                /* Not yet open */
 1954                 si_command(pp, LOPEN, SI_WAIT);         /* open it */
 1955         else
 1956                 si_command(pp, CONFIG, SI_WAIT);        /* change params */
 1957 
 1958         /* ========== set DTR etc ========== */
 1959         /* Hangup if ospeed == 0 */
 1960         if (t->c_ospeed == 0) {
 1961                 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
 1962         } else {
 1963                 /*
 1964                  * If the previous speed was 0, may need to re-enable
 1965                  * the modem signals
 1966                  */
 1967                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
 1968         }
 1969 
 1970         DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x\n",
 1971                 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));
 1972 
 1973         splx(oldspl);
 1974         return(error);
 1975 }
 1976 
 1977 /*
 1978  * Enable or Disable the writes to this channel...
 1979  * "state" ->  enabled = 1; disabled = 0;
 1980  */
 1981 static void
 1982 si_write_enable(pp, state)
 1983         register struct si_port *pp;
 1984         int state;
 1985 {
 1986         int oldspl;
 1987 
 1988         oldspl = spltty();
 1989 
 1990         if (state) {
 1991                 pp->sp_state &= ~SS_BLOCKWRITE;
 1992                 if (pp->sp_state & SS_WAITWRITE) {
 1993                         pp->sp_state &= ~SS_WAITWRITE;
 1994                         /* thunder away! */
 1995                         wakeup((caddr_t)pp);
 1996                 }
 1997         } else {
 1998                 pp->sp_state |= SS_BLOCKWRITE;
 1999         }
 2000 
 2001         splx(oldspl);
 2002 }
 2003 
 2004 /*
 2005  * Set/Get state of modem control lines.
 2006  * Due to DCE-like behaviour of the adapter, some signals need translation:
 2007  *      TIOCM_DTR       DSR
 2008  *      TIOCM_RTS       CTS
 2009  */
 2010 static int
 2011 si_modem(pp, cmd, bits)
 2012         struct si_port *pp;
 2013         enum si_mctl cmd;
 2014         int bits;
 2015 {
 2016         volatile struct si_channel *ccbp;
 2017         int x;
 2018 
 2019         DPRINT((pp, DBG_ENTRY|DBG_MODEM, "si_modem(%x,%s,%x)\n", pp, si_mctl2str(cmd), bits));
 2020         ccbp = pp->sp_ccb;              /* Find channel address */
 2021         switch (cmd) {
 2022         case GET:
 2023                 x = ccbp->hi_ip;
 2024                 bits = TIOCM_LE;
 2025                 if (x & IP_DCD)         bits |= TIOCM_CAR;
 2026                 if (x & IP_DTR)         bits |= TIOCM_DTR;
 2027                 if (x & IP_RTS)         bits |= TIOCM_RTS;
 2028                 if (x & IP_RI)          bits |= TIOCM_RI;
 2029                 return(bits);
 2030         case SET:
 2031                 ccbp->hi_op &= ~(OP_DSR|OP_CTS);
 2032                 /* fall through */
 2033         case BIS:
 2034                 x = 0;
 2035                 if (bits & TIOCM_DTR)
 2036                         x |= OP_DSR;
 2037                 if (bits & TIOCM_RTS)
 2038                         x |= OP_CTS;
 2039                 ccbp->hi_op |= x;
 2040                 break;
 2041         case BIC:
 2042                 if (bits & TIOCM_DTR)
 2043                         ccbp->hi_op &= ~OP_DSR;
 2044                 if (bits & TIOCM_RTS)
 2045                         ccbp->hi_op &= ~OP_CTS;
 2046         }
 2047         return 0;
 2048 }
 2049 
 2050 /*
 2051  * Handle change of modem state
 2052  */
 2053 static void
 2054 si_modem_state(pp, tp, hi_ip)
 2055         register struct si_port *pp;
 2056         register struct tty *tp;
 2057         register int hi_ip;
 2058 {
 2059                                                         /* if a modem dev */
 2060         if (hi_ip & IP_DCD) {
 2061                 if ( !(pp->sp_last_hi_ip & IP_DCD)) {
 2062                         DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n",
 2063                                 tp->t_line));
 2064                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 2065                 }
 2066         } else {
 2067                 if (pp->sp_last_hi_ip & IP_DCD) {
 2068                         DPRINT((pp, DBG_INTR, "modem carr off\n"));
 2069                         if ((*linesw[tp->t_line].l_modem)(tp, 0))
 2070                                 (void) si_modem(pp, SET, 0);
 2071                 }
 2072         }
 2073         pp->sp_last_hi_ip = hi_ip;
 2074 
 2075 }
 2076 
 2077 /*
 2078  * Poller to catch missed interrupts.
 2079  *
 2080  * Note that the SYSV Specialix drivers poll at 100 times per second to get
 2081  * better response.  We could really use a "periodic" version timeout(). :-)
 2082  */
 2083 #ifdef POLL
 2084 static void
 2085 si_poll(void *nothing)
 2086 {
 2087         register struct si_softc *sc;
 2088         register int i;
 2089         volatile struct si_reg *regp;
 2090         register struct si_port *pp;
 2091         int lost, oldspl, port;
 2092 
 2093         DPRINT((0, DBG_POLL, "si_poll()\n"));
 2094         oldspl = spltty();
 2095         if (in_intr)
 2096                 goto out;
 2097         lost = 0;
 2098         for (i=0; i<NSI; i++) {
 2099                 sc = &si_softc[i];
 2100                 if (sc->sc_type == SIEMPTY)
 2101                         continue;
 2102                 regp = (struct si_reg *)sc->sc_maddr;
 2103 
 2104                 /*
 2105                  * See if there has been a pending interrupt for 2 seconds
 2106                  * or so. The test (int_scounter >= 200) won't correspond
 2107                  * to 2 seconds if int_count gets changed.
 2108                  */
 2109                 if (regp->int_pending != 0) {
 2110                         if (regp->int_scounter >= 200 &&
 2111                             regp->initstat == 1) {
 2112                                 printf("si%d: lost intr\n", i);
 2113                                 lost++;
 2114                         }
 2115                 } else {
 2116                         regp->int_scounter = 0;
 2117                 }
 2118 
 2119                 /*
 2120                  * gripe about no input flow control..
 2121                  */
 2122                 pp = sc->sc_ports;
 2123                 for (port = 0; port < sc->sc_nport; pp++, port++) {
 2124                         if (pp->sp_delta_overflows > 0) {
 2125                                 printf("si%d: %d tty level buffer overflows\n",
 2126                                         i, pp->sp_delta_overflows);
 2127                                 pp->sp_delta_overflows = 0;
 2128                         }
 2129                 }
 2130         }
 2131         if (lost || si_realpoll)
 2132                 si_intr(-1);    /* call intr with fake vector */
 2133 out:
 2134         splx(oldspl);
 2135 
 2136         timeout(si_poll, (caddr_t)0L, si_pollrate);
 2137 }
 2138 #endif  /* ifdef POLL */
 2139 
 2140 /*
 2141  * The interrupt handler polls ALL ports on ALL adapters each time
 2142  * it is called.
 2143  */
 2144 
 2145 static BYTE si_rxbuf[SI_BUFFERSIZE];    /* input staging area */
 2146 static BYTE si_txbuf[SI_BUFFERSIZE];    /* output staging area */
 2147 
 2148 static void
 2149 si_intr(int unit)
 2150 {
 2151         register struct si_softc *sc;
 2152 
 2153         register struct si_port *pp;
 2154         volatile struct si_channel *ccbp;
 2155         register struct tty *tp;
 2156         volatile caddr_t maddr;
 2157         BYTE op, ip;
 2158         int x, card, port, n, i, isopen;
 2159         volatile BYTE *z;
 2160         BYTE c;
 2161 
 2162         DPRINT((0, (unit < 0) ? DBG_POLL:DBG_INTR, "si_intr(%d)\n", unit));
 2163         if (in_intr) {
 2164                 if (unit < 0)   /* should never happen */
 2165                         printf("si%d: Warning poll entered during interrupt\n",
 2166                                 unit);
 2167                 else
 2168                         printf("si%d: Warning interrupt handler re-entered\n",
 2169                                 unit);
 2170                 return;
 2171         }
 2172         in_intr = 1;
 2173 
 2174         /*
 2175          * When we get an int we poll all the channels and do ALL pending
 2176          * work, not just the first one we find. This allows all cards to
 2177          * share the same vector.
 2178          *
 2179          * XXX - But if we're sharing the vector with something that's NOT
 2180          * a SI/XIO/SX card, we may be making more work for ourselves.
 2181          */
 2182         for (card = 0; card < NSI; card++) {
 2183                 sc = &si_softc[card];
 2184                 if (sc->sc_type == SIEMPTY)
 2185                         continue;
 2186 
 2187                 /*
 2188                  * First, clear the interrupt
 2189                  */
 2190                 switch(sc->sc_type) {
 2191                 case SIHOST:
 2192                         maddr = sc->sc_maddr;
 2193                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 2194                                                         /* flag nothing pending */
 2195                         *(maddr+SIINTCL) = 0x00;        /* Set IRQ clear */
 2196                         *(maddr+SIINTCL_CL) = 0x00;     /* Clear IRQ clear */
 2197                         break;
 2198                 case SIHOST2:
 2199                         maddr = sc->sc_maddr;
 2200                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 2201                         *(maddr+SIPLIRQCLR) = 0x00;
 2202                         *(maddr+SIPLIRQCLR) = 0x10;
 2203                         break;
 2204 #if NPCI > 0
 2205                 case SIPCI:
 2206                         maddr = sc->sc_maddr;
 2207                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 2208                         *(maddr+SIPCIINTCL) = 0x0;
 2209                         break;
 2210                 case SIJETPCI:  /* fall through to JETISA case */
 2211 #endif
 2212                 case SIJETISA:
 2213                         maddr = sc->sc_maddr;
 2214                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 2215                         *(maddr+SIJETINTCL) = 0x0;
 2216                         break;
 2217 #if NEISA > 0
 2218                 case SIEISA:
 2219                         maddr = sc->sc_maddr;
 2220                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 2221                         (void)inb(sc->sc_eisa_iobase + 3);
 2222                         break;
 2223 #endif
 2224                 case SIEMPTY:
 2225                 default:
 2226                         continue;
 2227                 }
 2228                 ((volatile struct si_reg *)maddr)->int_scounter = 0;
 2229 
 2230                 /*
 2231                  * check each port
 2232                  */
 2233                 for (pp = sc->sc_ports, port=0; port < sc->sc_nport;
 2234                      pp++, port++) {
 2235                         ccbp = pp->sp_ccb;
 2236                         tp = pp->sp_tty;
 2237 
 2238                         /*
 2239                          * See if a command has completed ?
 2240                          */
 2241                         if (ccbp->hi_stat != pp->sp_pend) {
 2242                                 DPRINT((pp, DBG_INTR,
 2243                                         "si_intr hi_stat = 0x%x, pend = %d\n",
 2244                                         ccbp->hi_stat, pp->sp_pend));
 2245                                 switch(pp->sp_pend) {
 2246                                 case LOPEN:
 2247                                 case MPEND:
 2248                                 case MOPEN:
 2249                                 case CONFIG:
 2250                                 case SBREAK:
 2251                                 case EBREAK:
 2252                                         pp->sp_pend = ccbp->hi_stat;
 2253                                                 /* sleeping in si_command */
 2254                                         wakeup(&pp->sp_state);
 2255                                         break;
 2256                                 default:
 2257                                         pp->sp_pend = ccbp->hi_stat;
 2258                                 }
 2259                         }
 2260 
 2261                         /*
 2262                          * Continue on if it's closed
 2263                          */
 2264                         if (ccbp->hi_stat == IDLE_CLOSE) {
 2265                                 continue;
 2266                         }
 2267 
 2268                         /*
 2269                          * Do modem state change if not a local device
 2270                          */
 2271                         si_modem_state(pp, tp, ccbp->hi_ip);
 2272 
 2273                         /*
 2274                          * Check to see if we should 'receive' characters.
 2275                          */
 2276                         if (tp->t_state & TS_CONNECTED &&
 2277                             tp->t_state & TS_ISOPEN)
 2278                                 isopen = 1;
 2279                         else
 2280                                 isopen = 0;
 2281 
 2282                         /*
 2283                          * Do input break processing
 2284                          */
 2285                         if (ccbp->hi_state & ST_BREAK) {
 2286                                 if (isopen) {
 2287                                     (*linesw[tp->t_line].l_rint)(TTY_BI, tp);
 2288                                 }
 2289                                 ccbp->hi_state &= ~ST_BREAK;   /* A Bit iffy this */
 2290                                 DPRINT((pp, DBG_INTR, "si_intr break\n"));
 2291                         }
 2292 
 2293                         /*
 2294                          * Do RX stuff - if not open then dump any characters.
 2295                          * XXX: This is VERY messy and needs to be cleaned up.
 2296                          *
 2297                          * XXX: can we leave data in the host adapter buffer
 2298                          * when the clists are full?  That may be dangerous
 2299                          * if the user cannot get an interrupt signal through.
 2300                          */
 2301 
 2302         more_rx:        /* XXX Sorry. the nesting was driving me bats! :-( */
 2303 
 2304                         if (!isopen) {
 2305                                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 2306                                 goto end_rx;
 2307                         }
 2308 
 2309                         /*
 2310                          * If the tty input buffers are blocked, stop emptying
 2311                          * the incoming buffers and let the auto flow control
 2312                          * assert..
 2313                          */
 2314                         if (tp->t_state & TS_TBLOCK) {
 2315                                 goto end_rx;
 2316                         }
 2317 
 2318                         /*
 2319                          * Process read characters if not skipped above
 2320                          */
 2321                         op = ccbp->hi_rxopos;
 2322                         ip = ccbp->hi_rxipos;
 2323                         c = ip - op;
 2324                         if (c == 0) {
 2325                                 goto end_rx;
 2326                         }
 2327 
 2328                         n = c & 0xff;
 2329                         if (n > 250)
 2330                                 n = 250;
 2331 
 2332                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 2333                                                 n, op, ip));
 2334 
 2335                         /*
 2336                          * Suck characters out of host card buffer into the
 2337                          * "input staging buffer" - so that we dont leave the
 2338                          * host card in limbo while we're possibly echoing
 2339                          * characters and possibly flushing input inside the
 2340                          * ldisc l_rint() routine.
 2341                          */
 2342                         if (n <= SI_BUFFERSIZE - op) {
 2343 
 2344                                 DPRINT((pp, DBG_INTR, "\tsingle copy\n"));
 2345                                 z = ccbp->hi_rxbuf + op;
 2346                                 si_bcopy((caddr_t)z, si_rxbuf, n);
 2347 
 2348                                 op += n;
 2349                         } else {
 2350                                 x = SI_BUFFERSIZE - op;
 2351 
 2352                                 DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
 2353                                 z = ccbp->hi_rxbuf + op;
 2354                                 si_bcopy((caddr_t)z, si_rxbuf, x);
 2355 
 2356                                 DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n",
 2357                                         n - x));
 2358                                 z = ccbp->hi_rxbuf;
 2359                                 si_bcopy((caddr_t)z, si_rxbuf + x, n - x);
 2360 
 2361                                 op += n;
 2362                         }
 2363 
 2364                         /* clear collected characters from buffer */
 2365                         ccbp->hi_rxopos = op;
 2366 
 2367                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 2368                                                 n, op, ip));
 2369 
 2370                         /*
 2371                          * at this point...
 2372                          * n = number of chars placed in si_rxbuf
 2373                          */
 2374 
 2375                         /*
 2376                          * Avoid the grotesquely inefficient lineswitch
 2377                          * routine (ttyinput) in "raw" mode. It usually
 2378                          * takes about 450 instructions (that's without
 2379                          * canonical processing or echo!). slinput is
 2380                          * reasonably fast (usually 40 instructions
 2381                          * plus call overhead).
 2382                          */
 2383                         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 2384 
 2385                                 /* block if the driver supports it */
 2386                                 if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER
 2387                                     && (tp->t_cflag & CRTS_IFLOW
 2388                                         || tp->t_iflag & IXOFF)
 2389                                     && !(tp->t_state & TS_TBLOCK))
 2390                                         ttyblock(tp);
 2391 
 2392                                 tk_nin += n;
 2393                                 tk_rawcc += n;
 2394                                 tp->t_rawcc += n;
 2395 
 2396                                 pp->sp_delta_overflows +=
 2397                                     b_to_q((char *)si_rxbuf, n, &tp->t_rawq);
 2398 
 2399                                 ttwakeup(tp);
 2400                                 if (tp->t_state & TS_TTSTOP
 2401                                     && (tp->t_iflag & IXANY
 2402                                         || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
 2403                                         tp->t_state &= ~TS_TTSTOP;
 2404                                         tp->t_lflag &= ~FLUSHO;
 2405                                         si_start(tp);
 2406                                 }
 2407                         } else {
 2408                                 /*
 2409                                  * It'd be nice to not have to go through the
 2410                                  * function call overhead for each char here.
 2411                                  * It'd be nice to block input it, saving a
 2412                                  * loop here and the call/return overhead.
 2413                                  */
 2414                                 for(x = 0; x < n; x++) {
 2415                                         i = si_rxbuf[x];
 2416                                         if ((*linesw[tp->t_line].l_rint)(i, tp)
 2417                                              == -1) {
 2418                                                 pp->sp_delta_overflows++;
 2419                                         }
 2420                                         /*
 2421                                          * doesn't seem to be much point doing
 2422                                          * this here.. this driver has no
 2423                                          * softtty processing! ??
 2424                                          */
 2425                                         if (pp->sp_hotchar && i == pp->sp_hotchar) {
 2426                                                 setsofttty();
 2427                                         }
 2428                                 }
 2429                         }
 2430                         goto more_rx;   /* try for more until RXbuf is empty */
 2431 
 2432         end_rx:         /* XXX: Again, sorry about the gotos.. :-) */
 2433 
 2434                         /*
 2435                          * Do TX stuff
 2436                          */
 2437                         (*linesw[tp->t_line].l_start)(tp);
 2438 
 2439                 } /* end of for (all ports on this controller) */
 2440         } /* end of for (all controllers) */
 2441 
 2442         in_intr = 0;
 2443         DPRINT((0, (unit < 0) ? DBG_POLL:DBG_INTR, "end si_intr(%d)\n", unit));
 2444 }
 2445 
 2446 /*
 2447  * Nudge the transmitter...
 2448  *
 2449  * XXX: I inherited some funny code here.  It implies the host card only
 2450  * interrupts when the transmit buffer reaches the low-water-mark, and does
 2451  * not interrupt when it's actually hits empty.  In some cases, we have
 2452  * processes waiting for complete drain, and we need to simulate an interrupt
 2453  * about when we think the buffer is going to be empty (and retry if not).
 2454  * I really am not certain about this...  I *need* the hardware manuals.
 2455  */
 2456 static void
 2457 si_start(tp)
 2458         register struct tty *tp;
 2459 {
 2460         struct si_port *pp;
 2461         volatile struct si_channel *ccbp;
 2462         register struct clist *qp;
 2463         BYTE ipos;
 2464         int nchar;
 2465         int oldspl, count, n, amount, buffer_full;
 2466 
 2467         oldspl = spltty();
 2468 
 2469         qp = &tp->t_outq;
 2470         pp = TP2PP(tp);
 2471 
 2472         DPRINT((pp, DBG_ENTRY|DBG_START,
 2473                 "si_start(%x) t_state %x sp_state %x t_outq.c_cc %d\n",
 2474                 tp, tp->t_state, pp->sp_state, qp->c_cc));
 2475 
 2476         if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
 2477                 goto out;
 2478 
 2479         buffer_full = 0;
 2480         ccbp = pp->sp_ccb;
 2481 
 2482         count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
 2483         DPRINT((pp, DBG_START, "count %d\n", (BYTE)count));
 2484 
 2485         while ((nchar = qp->c_cc) > 0) {
 2486                 if ((BYTE)count >= 255) {
 2487                         buffer_full++;
 2488                         break;
 2489                 }
 2490                 amount = min(nchar, (255 - (BYTE)count));
 2491                 ipos = (unsigned int)ccbp->hi_txipos;
 2492                 n = q_to_b(&tp->t_outq, si_txbuf, amount);
 2493                 /* will it fit in one lump? */
 2494                 if ((SI_BUFFERSIZE - ipos) >= n) {
 2495                         si_bcopy(si_txbuf, (char *)&ccbp->hi_txbuf[ipos], n);
 2496                 } else {
 2497                         si_bcopy(si_txbuf, (char *)&ccbp->hi_txbuf[ipos],
 2498                                 SI_BUFFERSIZE - ipos);
 2499                         si_bcopy(si_txbuf + (SI_BUFFERSIZE - ipos),
 2500                                 (char *)&ccbp->hi_txbuf[0],
 2501                                 n - (SI_BUFFERSIZE - ipos));
 2502                 }
 2503                 ccbp->hi_txipos += n;
 2504                 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
 2505         }
 2506 
 2507         if (count != 0 && nchar == 0) {
 2508                 tp->t_state |= TS_BUSY;
 2509         } else {
 2510                 tp->t_state &= ~TS_BUSY;
 2511         }
 2512 
 2513         /* wakeup time? */
 2514         ttwwakeup(tp);
 2515 
 2516         DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n",
 2517                 (BYTE)count, nchar, tp->t_state));
 2518 
 2519         if (tp->t_state & TS_BUSY)
 2520         {
 2521                 int time;
 2522 
 2523                 time = ttspeedtab(tp->t_ospeed, chartimes);
 2524 
 2525                 if (time > 0) {
 2526                         if (time < nchar)
 2527                                 time = nchar / time;
 2528                         else
 2529                                 time = 2;
 2530                 } else {
 2531                         DPRINT((pp, DBG_START,
 2532                                 "bad char time value! %d\n", time));
 2533                         time = hz/10;
 2534                 }
 2535 
 2536                 if ((pp->sp_state & (SS_LSTART|SS_INLSTART)) == SS_LSTART) {
 2537                         untimeout((timeout_func_t)si_lstart, (caddr_t)pp);
 2538                 } else {
 2539                         pp->sp_state |= SS_LSTART;
 2540                 }
 2541                 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
 2542                 timeout((timeout_func_t)si_lstart, (caddr_t)pp, time);
 2543         }
 2544 
 2545 out:
 2546         splx(oldspl);
 2547         DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
 2548 }
 2549 
 2550 /*
 2551  * Note: called at splsoftclock from the timeout code
 2552  * This has to deal with two things...  cause wakeups while waiting for
 2553  * tty drains on last process exit, and call l_start at about the right
 2554  * time for protocols like ppp.
 2555  */
 2556 static void
 2557 si_lstart(pp)
 2558         register struct si_port *pp;
 2559 {
 2560         register struct tty *tp;
 2561         int oldspl;
 2562 
 2563         DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n",
 2564                 pp, pp->sp_state));
 2565 
 2566         oldspl = spltty();
 2567 
 2568         if ((pp->sp_state & SS_OPEN) == 0 || (pp->sp_state & SS_LSTART) == 0) {
 2569                 splx(oldspl);
 2570                 return;
 2571         }
 2572         pp->sp_state &= ~SS_LSTART;
 2573         pp->sp_state |= SS_INLSTART;
 2574 
 2575         tp = pp->sp_tty;
 2576 
 2577         /* deal with the process exit case */
 2578         ttwwakeup(tp);
 2579 
 2580         /* nudge protocols - eg: ppp */
 2581         (*linesw[tp->t_line].l_start)(tp);
 2582 
 2583         pp->sp_state &= ~SS_INLSTART;
 2584         splx(oldspl);
 2585 }
 2586 
 2587 /*
 2588  * Stop output on a line. called at spltty();
 2589  */
 2590 void
 2591 sistop(tp, rw)
 2592         register struct tty *tp;
 2593         int rw;
 2594 {
 2595         volatile struct si_channel *ccbp;
 2596         struct si_port *pp;
 2597 
 2598         pp = TP2PP(tp);
 2599         ccbp = pp->sp_ccb;
 2600 
 2601         DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "sistop(%x,%x)\n", tp, rw));
 2602 
 2603         /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
 2604         if (rw & FWRITE) {
 2605                 /* what level are we meant to be flushing anyway? */
 2606                 if (tp->t_state & TS_BUSY) {
 2607                         si_command(TP2PP(tp), WFLUSH, SI_NOWAIT);
 2608                         tp->t_state &= ~TS_BUSY;
 2609                         ttwwakeup(tp);  /* Bruce???? */
 2610                 }
 2611         }
 2612 #if 1   /* XXX: this doesn't work right yet.. */
 2613         /* XXX: this may have been failing because we used to call l_rint()
 2614          * while we were looping based on these two counters. Now, we collect
 2615          * the data and then loop stuffing it into l_rint(), making this
 2616          * useless.  Should we cause this to blow away the staging buffer?
 2617          */
 2618         if (rw & FREAD) {
 2619                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 2620         }
 2621 #endif
 2622 }
 2623 
 2624 /*
 2625  * Issue a command to the host card CPU.
 2626  */
 2627 
 2628 static void
 2629 si_command(pp, cmd, waitflag)
 2630         struct si_port *pp;             /* port control block (local) */
 2631         int cmd;
 2632         int waitflag;
 2633 {
 2634         int oldspl;
 2635         volatile struct si_channel *ccbp = pp->sp_ccb;
 2636         int x;
 2637 
 2638         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%x,%d): hi_stat 0x%x\n",
 2639                 pp, cmd, waitflag, ccbp->hi_stat));
 2640 
 2641         oldspl = spltty();              /* Keep others out */
 2642 
 2643         /* wait until it's finished what it was doing.. */
 2644         /* XXX: sits in IDLE_BREAK until something disturbs it or break
 2645          * is turned off. */
 2646         while((x = ccbp->hi_stat) != IDLE_OPEN &&
 2647                         x != IDLE_CLOSE &&
 2648                         x != IDLE_BREAK &&
 2649                         x != cmd) {
 2650                 if (in_intr) {                  /* Prevent sleep in intr */
 2651                         DPRINT((pp, DBG_PARAM,
 2652                                 "cmd intr collision - completing %d\trequested %d\n",
 2653                                 x, cmd));
 2654                         splx(oldspl);
 2655                         return;
 2656                 } else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,
 2657                                 "sicmd1", 1)) {
 2658                         splx(oldspl);
 2659                         return;
 2660                 }
 2661         }
 2662         /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */
 2663 
 2664         /* if there was a pending command, cause a state-change wakeup */
 2665         switch(pp->sp_pend) {
 2666         case LOPEN:
 2667         case MPEND:
 2668         case MOPEN:
 2669         case CONFIG:
 2670         case SBREAK:
 2671         case EBREAK:
 2672                 wakeup(&pp->sp_state);
 2673                 break;
 2674         default:
 2675                 break;
 2676         }
 2677 
 2678         pp->sp_pend = cmd;              /* New command pending */
 2679         ccbp->hi_stat = cmd;            /* Post it */
 2680 
 2681         if (waitflag) {
 2682                 if (in_intr) {          /* If in interrupt handler */
 2683                         DPRINT((pp, DBG_PARAM,
 2684                                 "attempt to sleep in si_intr - cmd req %d\n",
 2685                                 cmd));
 2686                         splx(oldspl);
 2687                         return;
 2688                 } else while(ccbp->hi_stat != IDLE_OPEN &&
 2689                              ccbp->hi_stat != IDLE_BREAK) {
 2690                         if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,
 2691                             "sicmd2", 0))
 2692                                 break;
 2693                 }
 2694         }
 2695         splx(oldspl);
 2696 }
 2697 
 2698 static void
 2699 si_disc_optim(tp, t, pp)
 2700         struct tty      *tp;
 2701         struct termios  *t;
 2702         struct si_port  *pp;
 2703 {
 2704         /*
 2705          * XXX can skip a lot more cases if Smarts.  Maybe
 2706          * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
 2707          * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
 2708          */
 2709         if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
 2710             && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
 2711             && (!(t->c_iflag & PARMRK)
 2712                 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
 2713             && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
 2714             && linesw[tp->t_line].l_rint == ttyinput)
 2715                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 2716         else
 2717                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 2718 
 2719         /*
 2720          * Prepare to reduce input latency for packet
 2721          * discplines with a end of packet character.
 2722          */
 2723         if (tp->t_line == SLIPDISC)
 2724                 pp->sp_hotchar = 0xc0;
 2725         else if (tp->t_line == PPPDISC)
 2726                 pp->sp_hotchar = 0x7e;
 2727         else
 2728                 pp->sp_hotchar = 0;
 2729 
 2730         DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n", 
 2731                 (tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",
 2732                 pp->sp_hotchar));
 2733 }
 2734 
 2735 
 2736 #ifdef  SI_DEBUG
 2737 
 2738 static void
 2739 #ifdef __STDC__
 2740 si_dprintf(struct si_port *pp, int flags, const char *fmt, ...)
 2741 #else
 2742 si_dprintf(pp, flags, fmt, va_alist)
 2743         struct si_port *pp;
 2744         int flags;
 2745         char *fmt;
 2746 #endif
 2747 {
 2748         va_list ap;
 2749 
 2750         if ((pp == NULL && (si_debug&flags)) ||
 2751             (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
 2752                 if (pp != NULL)
 2753                         printf("%ci%d(%d): ", 's',
 2754                                 (int)SI_CARD(pp->sp_tty->t_dev),
 2755                                 (int)SI_PORT(pp->sp_tty->t_dev));
 2756                 va_start(ap, fmt);
 2757                 vprintf(fmt, ap);
 2758                 va_end(ap);
 2759         }
 2760 }
 2761 
 2762 static char *
 2763 si_mctl2str(cmd)
 2764         enum si_mctl cmd;
 2765 {
 2766         switch (cmd) {
 2767         case GET:
 2768                 return("GET");
 2769         case SET:
 2770                 return("SET");
 2771         case BIS:
 2772                 return("BIS");
 2773         case BIC:
 2774                 return("BIC");
 2775         }
 2776         return("BAD");
 2777 }
 2778 
 2779 #endif  /* DEBUG */
 2780 
 2781 static char *
 2782 si_modulename(host_type, uart_type)
 2783         int host_type, uart_type;
 2784 {
 2785         switch (host_type) {
 2786         /* Z280 based cards */
 2787 #if NEISA > 0
 2788         case SIEISA: 
 2789 #endif
 2790         case SIHOST2:  
 2791         case SIHOST:
 2792 #if NPCI > 0
 2793         case SIPCI:
 2794 #endif
 2795                 switch (uart_type) {
 2796                 case 0:
 2797                         return(" (XIO)");
 2798                 case 1:
 2799                         return(" (SI)");
 2800                 }
 2801                 break;
 2802         /* T225 based hosts */
 2803 #if NPCI > 0
 2804         case SIJETPCI:
 2805 #endif
 2806         case SIJETISA:
 2807                 switch (uart_type) {
 2808                 case 0:
 2809                         return(" (SI)");
 2810                 case 40:
 2811                         return(" (XIO)");
 2812                 case 80:
 2813                         return(" (SX)");
 2814                 }
 2815                 break;
 2816         }
 2817         return("");
 2818 }
 2819 
 2820 static si_devsw_installed = 0;
 2821 
 2822 static void 
 2823 si_drvinit(void *unused)
 2824 {
 2825         dev_t dev;
 2826 
 2827         if (!si_devsw_installed) {
 2828                 dev = makedev(CDEV_MAJOR, 0);
 2829                 cdevsw_add(&dev,&si_cdevsw, NULL);
 2830                 si_devsw_installed = 1;
 2831         }
 2832 }
 2833 
 2834 SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,si_drvinit,NULL)

Cache object: a262d5cd9871ea6f1e4f6a37a8531dea


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.