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

Cache object: 2a795777d975b4feb23d5b8a3d127e0b


[ 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.