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/dev/si/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) 2000, 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  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #ifndef lint
   39 static const char si_copyright1[] =  "@(#) Copyright (C) Specialix International, 1990,1992,1998",
   40                   si_copyright2[] =  "@(#) Copyright (C) Andy Rutter 1993",
   41                   si_copyright3[] =  "@(#) Copyright (C) Peter Wemm 2000";
   42 #endif  /* not lint */
   43 
   44 #include "opt_compat.h"
   45 #include "opt_debug_si.h"
   46 #include "opt_tty.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #ifndef BURN_BRIDGES
   51 #if defined(COMPAT_43)
   52 #include <sys/ioctl_compat.h>
   53 #endif
   54 #endif
   55 #include <sys/tty.h>
   56 #include <sys/conf.h>
   57 #include <sys/fcntl.h>
   58 #include <sys/kernel.h>
   59 #include <sys/malloc.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/bus.h>
   62 #include <machine/bus.h>
   63 #include <sys/rman.h>
   64 #include <machine/resource.h>
   65 
   66 
   67 #include <vm/vm.h>
   68 #include <vm/pmap.h>
   69 
   70 #include <machine/stdarg.h>
   71 
   72 #include <dev/si/sireg.h>
   73 #include <dev/si/sivar.h>
   74 #include <dev/si/si.h>
   75 
   76 /*
   77  * This device driver is designed to interface the Specialix International
   78  * SI, XIO and SX range of serial multiplexor cards to FreeBSD on an ISA,
   79  * EISA or PCI bus machine.
   80  *
   81  * The controller is interfaced to the host via dual port RAM
   82  * and an interrupt.
   83  *
   84  * The code for the Host 1 (very old ISA cards) has not been tested.
   85  */
   86 
   87 #define POLL            /* turn on poller to scan for lost interrupts */
   88 #define REALPOLL        /* on each poll, scan for work regardless */
   89 #define POLLHZ  (hz/10) /* 10 times per second */
   90 #define SI_I_HIGH_WATER (TTYHOG - 2 * SI_BUFFERSIZE)
   91 #define INT_COUNT 25000         /* max of 125 ints per second */
   92 #define JET_INT_COUNT 100       /* max of 100 ints per second */
   93 #define RXINT_COUNT 1   /* one rxint per 10 milliseconds */
   94 
   95 enum si_mctl { GET, SET, BIS, BIC };
   96 
   97 static void si_command(struct si_port *, int, int);
   98 static int si_modem(struct si_port *, enum si_mctl, int);
   99 static void si_write_enable(struct si_port *, int);
  100 static int si_Sioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
  101 static void si_start(struct tty *);
  102 static void si_stop(struct tty *, int);
  103 static timeout_t si_lstart;
  104 static void sihardclose(struct si_port *pp);
  105 
  106 #ifdef SI_DEBUG
  107 static char     *si_mctl2str(enum si_mctl cmd);
  108 #endif
  109 
  110 static int      siparam(struct tty *, struct termios *);
  111 
  112 static void     si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip);
  113 static char *   si_modulename(int host_type, int uart_type);
  114 
  115 static  d_open_t        siopen;
  116 static  d_close_t       siclose;
  117 static  d_write_t       siwrite;
  118 static  d_ioctl_t       siioctl;
  119 
  120 static struct cdevsw si_cdevsw = {
  121         .d_version =    D_VERSION,
  122         .d_open =       siopen,
  123         .d_close =      siclose,
  124         .d_write =      siwrite,
  125         .d_ioctl =      siioctl,
  126         .d_name =       "si",
  127         .d_flags =      D_TTY | D_NEEDGIANT,
  128 };
  129 
  130 static int si_Nports;
  131 static int si_Nmodules;
  132 static int si_debug = 0;        /* data, not bss, so it's patchable */
  133 
  134 SYSCTL_INT(_machdep, OID_AUTO, si_debug, CTLFLAG_RW, &si_debug, 0, "");
  135 TUNABLE_INT("machdep.si_debug", &si_debug);
  136 
  137 static int si_numunits;
  138 
  139 devclass_t si_devclass;
  140 
  141 #ifndef B2000   /* not standard, but the hardware knows it. */
  142 # define B2000 2000
  143 #endif
  144 static struct speedtab bdrates[] = {
  145         { B75,          CLK75, },       /* 0x0 */
  146         { B110,         CLK110, },      /* 0x1 */
  147         { B150,         CLK150, },      /* 0x3 */
  148         { B300,         CLK300, },      /* 0x4 */
  149         { B600,         CLK600, },      /* 0x5 */
  150         { B1200,        CLK1200, },     /* 0x6 */
  151         { B2000,        CLK2000, },     /* 0x7 */
  152         { B2400,        CLK2400, },     /* 0x8 */
  153         { B4800,        CLK4800, },     /* 0x9 */
  154         { B9600,        CLK9600, },     /* 0xb */
  155         { B19200,       CLK19200, },    /* 0xc */
  156         { B38400,       CLK38400, },    /* 0x2 (out of order!) */
  157         { B57600,       CLK57600, },    /* 0xd */
  158         { B115200,      CLK110, },      /* 0x1 (dupe!, 110 baud on "si") */
  159         { -1,           -1 },
  160 };
  161 
  162 
  163 /* populated with approx character/sec rates - translated at card
  164  * initialisation time to chars per tick of the clock */
  165 static int done_chartimes = 0;
  166 static struct speedtab chartimes[] = {
  167         { B75,          8, },
  168         { B110,         11, },
  169         { B150,         15, },
  170         { B300,         30, },
  171         { B600,         60, },
  172         { B1200,        120, },
  173         { B2000,        200, },
  174         { B2400,        240, },
  175         { B4800,        480, },
  176         { B9600,        960, },
  177         { B19200,       1920, },
  178         { B38400,       3840, },
  179         { B57600,       5760, },
  180         { B115200,      11520, },
  181         { -1,           -1 },
  182 };
  183 static volatile int in_intr = 0;        /* Inside interrupt handler? */
  184 
  185 #ifdef POLL
  186 static int si_pollrate;                 /* in addition to irq */
  187 static int si_realpoll = 0;             /* poll HW on timer */
  188 
  189 SYSCTL_INT(_machdep, OID_AUTO, si_pollrate, CTLFLAG_RW, &si_pollrate, 0, "");
  190 SYSCTL_INT(_machdep, OID_AUTO, si_realpoll, CTLFLAG_RW, &si_realpoll, 0, "");
  191 
  192 static int init_finished = 0;
  193 static void si_poll(void *);
  194 #endif
  195 
  196 /*
  197  * Array of adapter types and the corresponding RAM size. The order of
  198  * entries here MUST match the ordinal of the adapter type.
  199  */
  200 static char *si_type[] = {
  201         "EMPTY",
  202         "SIHOST",
  203         "SIMCA",                /* FreeBSD does not support Microchannel */
  204         "SIHOST2",
  205         "SIEISA",
  206         "SIPCI",
  207         "SXPCI",
  208         "SXISA",
  209 };
  210 
  211 /*
  212  * We have to make an 8 bit version of bcopy, since some cards can't
  213  * deal with 32 bit I/O
  214  */
  215 static void __inline
  216 si_bcopy(const void *src, void *dst, size_t len)
  217 {
  218         u_char *d;
  219         const u_char *s;
  220 
  221         d = dst;
  222         s = src;
  223         while (len--)
  224                 *d++ = *s++;
  225 }
  226 static void __inline
  227 si_vbcopy(const volatile void *src, void *dst, size_t len)
  228 {
  229         u_char *d;
  230         const volatile u_char *s;
  231 
  232         d = dst;
  233         s = src;
  234         while (len--)
  235                 *d++ = *s++;
  236 }
  237 static void __inline
  238 si_bcopyv(const void *src, volatile void *dst, size_t len)
  239 {
  240         volatile u_char *d;
  241         const u_char *s;
  242 
  243         d = dst;
  244         s = src;
  245         while (len--)
  246                 *d++ = *s++;
  247 }
  248 
  249 /*
  250  * Attach the device.  Initialize the card.
  251  */
  252 int
  253 siattach(device_t dev)
  254 {
  255         int unit;
  256         struct si_softc *sc;
  257         struct si_port *pp;
  258         volatile struct si_channel *ccbp;
  259         volatile struct si_reg *regp;
  260         volatile caddr_t maddr;
  261         struct si_module *modp;
  262         struct speedtab *spt;
  263         int nmodule, nport, x, y;
  264         int uart_type;
  265 
  266         sc = device_get_softc(dev);
  267         unit = device_get_unit(dev);
  268 
  269         sc->sc_typename = si_type[sc->sc_type];
  270         if (si_numunits < unit + 1)
  271                 si_numunits = unit + 1;
  272 
  273         DPRINT((0, DBG_AUTOBOOT, "si%d: siattach\n", unit));
  274 
  275 #ifdef POLL
  276         if (si_pollrate == 0) {
  277                 si_pollrate = POLLHZ;           /* in addition to irq */
  278 #ifdef REALPOLL
  279                 si_realpoll = 1;                /* scan always */
  280 #endif
  281         }
  282 #endif
  283 
  284         DPRINT((0, DBG_AUTOBOOT, "si%d: type: %s paddr: %x maddr: %x\n", unit,
  285                 sc->sc_typename, sc->sc_paddr, sc->sc_maddr));
  286 
  287         sc->sc_ports = NULL;                    /* mark as uninitialised */
  288 
  289         maddr = sc->sc_maddr;
  290 
  291         /* Stop the CPU first so it won't stomp around while we load */
  292 
  293         switch (sc->sc_type) {
  294                 case SIEISA:
  295                         outb(sc->sc_iobase + 2, sc->sc_irq << 4);
  296                 break;
  297                 case SIPCI:
  298                         *(maddr+SIPCIRESET) = 0;
  299                 break;
  300                 case SIJETPCI: /* fall through to JET ISA */
  301                 case SIJETISA:
  302                         *(maddr+SIJETCONFIG) = 0;
  303                 break;
  304                 case SIHOST2:
  305                         *(maddr+SIPLRESET) = 0;
  306                 break;
  307                 case SIHOST:
  308                         *(maddr+SIRESET) = 0;
  309                 break;
  310                 default: /* this should never happen */
  311                         printf("si%d: unsupported configuration\n", unit);
  312                         return EINVAL;
  313                 break;
  314         }
  315 
  316         /* OK, now lets download the download code */
  317 
  318         if (SI_ISJET(sc->sc_type)) {
  319                 DPRINT((0, DBG_DOWNLOAD, "si%d: jet_download: nbytes %d\n",
  320                         unit, si3_t225_dsize));
  321                 si_bcopy(si3_t225_download, maddr + si3_t225_downloadaddr,
  322                         si3_t225_dsize);
  323                 DPRINT((0, DBG_DOWNLOAD,
  324                         "si%d: jet_bootstrap: nbytes %d -> %x\n",
  325                         unit, si3_t225_bsize, si3_t225_bootloadaddr));
  326                 si_bcopy(si3_t225_bootstrap, maddr + si3_t225_bootloadaddr,
  327                         si3_t225_bsize);
  328         } else {
  329                 DPRINT((0, DBG_DOWNLOAD, "si%d: si_download: nbytes %d\n",
  330                         unit, si2_z280_dsize));
  331                 si_bcopy(si2_z280_download, maddr + si2_z280_downloadaddr,
  332                         si2_z280_dsize);
  333         }
  334 
  335         /* Now start the CPU */
  336 
  337         switch (sc->sc_type) {
  338         case SIEISA:
  339                 /* modify the download code to tell it that it's on an EISA */
  340                 *(maddr + 0x42) = 1;
  341                 outb(sc->sc_iobase + 2, (sc->sc_irq << 4) | 4);
  342                 (void)inb(sc->sc_iobase + 3); /* reset interrupt */
  343                 break;
  344         case SIPCI:
  345                 /* modify the download code to tell it that it's on a PCI */
  346                 *(maddr+0x42) = 1;
  347                 *(maddr+SIPCIRESET) = 1;
  348                 *(maddr+SIPCIINTCL) = 0;
  349                 break;
  350         case SIJETPCI:
  351                 *(maddr+SIJETRESET) = 0;
  352                 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN;
  353                 break;
  354         case SIJETISA:
  355                 *(maddr+SIJETRESET) = 0;
  356                 switch (sc->sc_irq) {
  357                 case 9:
  358                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0x90;
  359                         break;
  360                 case 10:
  361                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xa0;
  362                         break;
  363                 case 11:
  364                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xb0;
  365                         break;
  366                 case 12:
  367                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xc0;
  368                         break;
  369                 case 15:
  370                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xf0;
  371                         break;
  372                 }
  373                 break;
  374         case SIHOST:
  375                 *(maddr+SIRESET_CL) = 0;
  376                 *(maddr+SIINTCL_CL) = 0;
  377                 break;
  378         case SIHOST2:
  379                 *(maddr+SIPLRESET) = 0x10;
  380                 switch (sc->sc_irq) {
  381                 case 11:
  382                         *(maddr+SIPLIRQ11) = 0x10;
  383                         break;
  384                 case 12:
  385                         *(maddr+SIPLIRQ12) = 0x10;
  386                         break;
  387                 case 15:
  388                         *(maddr+SIPLIRQ15) = 0x10;
  389                         break;
  390                 }
  391                 *(maddr+SIPLIRQCLR) = 0x10;
  392                 break;
  393         default: /* this should _REALLY_ never happen */
  394                 printf("si%d: Uh, it was supported a second ago...\n", unit);
  395                 return EINVAL;
  396         }
  397 
  398         DELAY(1000000);                 /* wait around for a second */
  399 
  400         regp = (struct si_reg *)maddr;
  401         y = 0;
  402                                         /* wait max of 5 sec for init OK */
  403         while (regp->initstat == 0 && y++ < 10) {
  404                 DELAY(500000);
  405         }
  406         switch (regp->initstat) {
  407         case 0:
  408                 printf("si%d: startup timeout - aborting\n", unit);
  409                 sc->sc_type = SIEMPTY;
  410                 return EINVAL;
  411         case 1:
  412                 if (SI_ISJET(sc->sc_type)) {
  413                         /* set throttle to 100 times per second */
  414                         regp->int_count = JET_INT_COUNT;
  415                         /* rx_intr_count is a NOP in Jet */
  416                 } else {
  417                         /* set throttle to 125 times per second */
  418                         regp->int_count = INT_COUNT;
  419                         /* rx intr max of 25 times per second */
  420                         regp->rx_int_count = RXINT_COUNT;
  421                 }
  422                 regp->int_pending = 0;          /* no intr pending */
  423                 regp->int_scounter = 0; /* reset counter */
  424                 break;
  425         case 0xff:
  426                 /*
  427                  * No modules found, so give up on this one.
  428                  */
  429                 printf("si%d: %s - no ports found\n", unit,
  430                         si_type[sc->sc_type]);
  431                 return 0;
  432         default:
  433                 printf("si%d: download code version error - initstat %x\n",
  434                         unit, regp->initstat);
  435                 return EINVAL;
  436         }
  437 
  438         /*
  439          * First time around the ports just count them in order
  440          * to allocate some memory.
  441          */
  442         nport = 0;
  443         modp = (struct si_module *)(maddr + 0x80);
  444         for (;;) {
  445                 DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp));
  446                 switch (modp->sm_type) {
  447                 case TA4:
  448                         DPRINT((0, DBG_DOWNLOAD,
  449                                 "si%d: Found old TA4 module, 4 ports\n",
  450                                 unit));
  451                         x = 4;
  452                         break;
  453                 case TA8:
  454                         DPRINT((0, DBG_DOWNLOAD,
  455                                 "si%d: Found old TA8 module, 8 ports\n",
  456                                 unit));
  457                         x = 8;
  458                         break;
  459                 case TA4_ASIC:
  460                         DPRINT((0, DBG_DOWNLOAD,
  461                                 "si%d: Found ASIC TA4 module, 4 ports\n",
  462                                 unit));
  463                         x = 4;
  464                         break;
  465                 case TA8_ASIC:
  466                         DPRINT((0, DBG_DOWNLOAD,
  467                                 "si%d: Found ASIC TA8 module, 8 ports\n",
  468                                 unit));
  469                         x = 8;
  470                         break;
  471                 case MTA:
  472                         DPRINT((0, DBG_DOWNLOAD,
  473                                 "si%d: Found CD1400 module, 8 ports\n",
  474                                 unit));
  475                         x = 8;
  476                         break;
  477                 case SXDC:
  478                         DPRINT((0, DBG_DOWNLOAD,
  479                                 "si%d: Found SXDC module, 8 ports\n",
  480                                 unit));
  481                         x = 8;
  482                         break;
  483                 default:
  484                         printf("si%d: unknown module type %d\n",
  485                                 unit, modp->sm_type);
  486                         goto try_next;
  487                 }
  488 
  489                 /* this was limited in firmware and is also a driver issue */
  490                 if ((nport + x) > SI_MAXPORTPERCARD) {
  491                         printf("si%d: extra ports ignored\n", unit);
  492                         goto try_next;
  493                 }
  494 
  495                 nport += x;
  496                 si_Nports += x;
  497                 si_Nmodules++;
  498 
  499 try_next:
  500                 if (modp->sm_next == 0)
  501                         break;
  502                 modp = (struct si_module *)
  503                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
  504         }
  505         sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport,
  506                 M_DEVBUF, M_NOWAIT | M_ZERO);
  507         if (sc->sc_ports == 0) {
  508                 printf("si%d: fail to malloc memory for port structs\n",
  509                         unit);
  510                 return EINVAL;
  511         }
  512         sc->sc_nport = nport;
  513 
  514         /*
  515          * Scan round the ports again, this time initialising.
  516          */
  517         pp = sc->sc_ports;
  518         nmodule = 0;
  519         modp = (struct si_module *)(maddr + 0x80);
  520         uart_type = 1000;       /* arbitary, > uchar_max */
  521         for (;;) {
  522                 switch (modp->sm_type) {
  523                 case TA4:
  524                         nport = 4;
  525                         break;
  526                 case TA8:
  527                         nport = 8;
  528                         break;
  529                 case TA4_ASIC:
  530                         nport = 4;
  531                         break;
  532                 case TA8_ASIC:
  533                         nport = 8;
  534                         break;
  535                 case MTA:
  536                         nport = 8;
  537                         break;
  538                 case SXDC:
  539                         nport = 8;
  540                         break;
  541                 default:
  542                         goto try_next2;
  543                 }
  544                 nmodule++;
  545                 ccbp = (struct si_channel *)((char *)modp + 0x100);
  546                 if (uart_type == 1000)
  547                         uart_type = ccbp->type;
  548                 else if (uart_type != ccbp->type)
  549                         printf("si%d: Warning: module %d mismatch! (%d%s != %d%s)\n",
  550                             unit, nmodule,
  551                             ccbp->type, si_modulename(sc->sc_type, ccbp->type),
  552                             uart_type, si_modulename(sc->sc_type, uart_type));
  553 
  554                 for (x = 0; x < nport; x++, pp++, ccbp++) {
  555                         pp->sp_ccb = ccbp;      /* save the address */
  556                         pp->sp_tty = ttymalloc(NULL);
  557                         pp->sp_pend = IDLE_CLOSE;
  558                         pp->sp_state = 0;       /* internal flag */
  559                         pp->sp_iin.c_iflag = TTYDEF_IFLAG;
  560                         pp->sp_iin.c_oflag = TTYDEF_OFLAG;
  561                         pp->sp_iin.c_cflag = TTYDEF_CFLAG;
  562                         pp->sp_iin.c_lflag = TTYDEF_LFLAG;
  563                         termioschars(&pp->sp_iin);
  564                         pp->sp_iin.c_ispeed = pp->sp_iin.c_ospeed =
  565                                 TTYDEF_SPEED;;
  566                         pp->sp_iout = pp->sp_iin;
  567                 }
  568 try_next2:
  569                 if (modp->sm_next == 0) {
  570                         printf("si%d: card: %s, ports: %d, modules: %d, type: %d%s\n",
  571                                 unit,
  572                                 sc->sc_typename,
  573                                 sc->sc_nport,
  574                                 nmodule,
  575                                 uart_type,
  576                                 si_modulename(sc->sc_type, uart_type));
  577                         break;
  578                 }
  579                 modp = (struct si_module *)
  580                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
  581         }
  582         if (done_chartimes == 0) {
  583                 for (spt = chartimes ; spt->sp_speed != -1; spt++) {
  584                         if ((spt->sp_code /= hz) == 0)
  585                                 spt->sp_code = 1;
  586                 }
  587                 done_chartimes = 1;
  588         }
  589 
  590 /*      path    name    devsw           minor   type   uid gid perm*/
  591         for (x = 0; x < sc->sc_nport; x++) {
  592                 /* sync with the manuals that start at 1 */
  593                 y = x + 1 + unit * (1 << SI_CARDSHIFT);
  594                 make_dev(&si_cdevsw, x, 0, 0, 0600, "ttyA%02d", y);
  595                 make_dev(&si_cdevsw, x + 0x00080, 0, 0, 0600, "cuaA%02d", y);
  596                 make_dev(&si_cdevsw, x + 0x10000, 0, 0, 0600, "ttyiA%02d", y);
  597                 make_dev(&si_cdevsw, x + 0x10080, 0, 0, 0600, "cuaiA%02d", y);
  598                 make_dev(&si_cdevsw, x + 0x20000, 0, 0, 0600, "ttylA%02d", y);
  599                 make_dev(&si_cdevsw, x + 0x20080, 0, 0, 0600, "cualA%02d", y);
  600         }
  601         make_dev(&si_cdevsw, 0x40000, 0, 0, 0600, "si_control");
  602         return (0);
  603 }
  604 
  605 static  int
  606 siopen(struct cdev *dev, int flag, int mode, struct thread *td)
  607 {
  608         int oldspl, error;
  609         int card, port;
  610         struct si_softc *sc;
  611         struct tty *tp;
  612         volatile struct si_channel *ccbp;
  613         struct si_port *pp;
  614         int mynor = minor(dev);
  615 
  616         /* quickly let in /dev/si_control */
  617         if (IS_CONTROLDEV(mynor)) {
  618                 if ((error = suser(td)))
  619                         return(error);
  620                 return(0);
  621         }
  622 
  623         card = SI_CARD(mynor);
  624         sc = devclass_get_softc(si_devclass, card);
  625         if (sc == NULL)
  626                 return (ENXIO);
  627 
  628         if (sc->sc_type == SIEMPTY) {
  629                 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",
  630                         card, sc->sc_typename));
  631                 return(ENXIO);
  632         }
  633 
  634         port = SI_PORT(mynor);
  635         if (port >= sc->sc_nport) {
  636                 DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",
  637                         card, sc->sc_nport));
  638                 return(ENXIO);
  639         }
  640 
  641 #ifdef  POLL
  642         /*
  643          * We've now got a device, so start the poller.
  644          */
  645         if (init_finished == 0) {
  646                 timeout(si_poll, (caddr_t)0L, si_pollrate);
  647                 init_finished = 1;
  648         }
  649 #endif
  650 
  651         /* initial/lock device */
  652         if (IS_STATE(mynor)) {
  653                 return(0);
  654         }
  655 
  656         pp = sc->sc_ports + port;
  657         tp = pp->sp_tty;                        /* the "real" tty */
  658         dev->si_tty = tp;
  659         ccbp = pp->sp_ccb;                      /* Find control block */
  660         DPRINT((pp, DBG_ENTRY|DBG_OPEN, "siopen(%s,%x,%x,%x)\n",
  661                 devtoname(dev), flag, mode, td));
  662 
  663         oldspl = spltty();                      /* Keep others out */
  664         error = 0;
  665 
  666 open_top:
  667         error = ttydtrwaitsleep(tp);
  668         if (error != 0)
  669                 goto out;
  670 
  671         if (tp->t_state & TS_ISOPEN) {
  672                 /*
  673                  * The device is open, so everything has been initialised.
  674                  * handle conflicts.
  675                  */
  676                 if (IS_CALLOUT(mynor)) {
  677                         if (!pp->sp_active_out) {
  678                                 error = EBUSY;
  679                                 goto out;
  680                         }
  681                 } else {
  682                         if (pp->sp_active_out) {
  683                                 if (flag & O_NONBLOCK) {
  684                                         error = EBUSY;
  685                                         goto out;
  686                                 }
  687                                 error = tsleep(&pp->sp_active_out,
  688                                                 TTIPRI|PCATCH, "sibi", 0);
  689                                 if (error != 0)
  690                                         goto out;
  691                                 goto open_top;
  692                         }
  693                 }
  694                 if (tp->t_state & TS_XCLUDE &&
  695                     suser(td)) {
  696                         DPRINT((pp, DBG_OPEN|DBG_FAIL,
  697                                 "already open and EXCLUSIVE set\n"));
  698                         error = EBUSY;
  699                         goto out;
  700                 }
  701         } else {
  702                 /*
  703                  * The device isn't open, so there are no conflicts.
  704                  * Initialize it. Avoid sleep... :-)
  705                  */
  706                 DPRINT((pp, DBG_OPEN, "first open\n"));
  707                 tp->t_oproc = si_start;
  708                 tp->t_stop = si_stop;
  709                 tp->t_param = siparam;
  710                 tp->t_dev = dev;
  711                 tp->t_termios = mynor & SI_CALLOUT_MASK
  712                                 ? pp->sp_iout : pp->sp_iin;
  713 
  714                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
  715 
  716                 ++pp->sp_wopeners;      /* in case of sleep in siparam */
  717 
  718                 error = siparam(tp, &tp->t_termios);
  719 
  720                 --pp->sp_wopeners;
  721                 if (error != 0)
  722                         goto out;
  723                 /* XXX: we should goto_top if siparam slept */
  724 
  725                 /* set initial DCD state */
  726                 pp->sp_last_hi_ip = ccbp->hi_ip;
  727                 if ((pp->sp_last_hi_ip & IP_DCD) || IS_CALLOUT(mynor)) {
  728                         ttyld_modem(tp, 1);
  729                 }
  730         }
  731 
  732         /* whoops! we beat the close! */
  733         if (pp->sp_state & SS_CLOSING) {
  734                 /* try and stop it from proceeding to bash the hardware */
  735                 pp->sp_state &= ~SS_CLOSING;
  736         }
  737 
  738         /*
  739          * Wait for DCD if necessary
  740          */
  741         if (!(tp->t_state & TS_CARR_ON) &&
  742             !IS_CALLOUT(mynor) &&
  743             !(tp->t_cflag & CLOCAL) &&
  744             !(flag & O_NONBLOCK)) {
  745                 ++pp->sp_wopeners;
  746                 DPRINT((pp, DBG_OPEN, "sleeping for carrier\n"));
  747                 error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "sidcd", 0);
  748                 --pp->sp_wopeners;
  749                 if (error != 0)
  750                         goto out;
  751                 goto open_top;
  752         }
  753 
  754         error = ttyld_open(tp, dev);
  755         ttyldoptim(tp);
  756         if (tp->t_state & TS_ISOPEN && IS_CALLOUT(mynor))
  757                 pp->sp_active_out = TRUE;
  758 
  759         pp->sp_state |= SS_OPEN;        /* made it! */
  760 
  761 out:
  762         splx(oldspl);
  763 
  764         DPRINT((pp, DBG_OPEN, "leaving siopen\n"));
  765 
  766         if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0)
  767                 sihardclose(pp);
  768 
  769         return(error);
  770 }
  771 
  772 static  int
  773 siclose(struct cdev *dev, int flag, int mode, struct thread *td)
  774 {
  775         struct si_port *pp;
  776         struct tty *tp;
  777         int oldspl;
  778         int error = 0;
  779         int mynor = minor(dev);
  780 
  781         if (IS_SPECIAL(mynor))
  782                 return(0);
  783 
  784         oldspl = spltty();
  785 
  786         pp = MINOR2PP(mynor);
  787         tp = pp->sp_tty;
  788 
  789         DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "siclose(%s,%x,%x,%x) sp_state:%x\n",
  790                 devtoname(dev), flag, mode, td, pp->sp_state));
  791 
  792         /* did we sleep and loose a race? */
  793         if (pp->sp_state & SS_CLOSING) {
  794                 /* error = ESOMETING? */
  795                 goto out;
  796         }
  797 
  798         /* begin race detection.. */
  799         pp->sp_state |= SS_CLOSING;
  800 
  801         si_write_enable(pp, 0);         /* block writes for ttywait() */
  802 
  803         /* THIS MAY SLEEP IN TTYWAIT!!! */
  804         ttyld_close(tp, flag);
  805 
  806         si_write_enable(pp, 1);
  807 
  808         /* did we sleep and somebody started another open? */
  809         if (!(pp->sp_state & SS_CLOSING)) {
  810                 /* error = ESOMETING? */
  811                 goto out;
  812         }
  813         /* ok. we are now still on the right track.. nuke the hardware */
  814 
  815         if (pp->sp_state & SS_LSTART) {
  816                 untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
  817                 pp->sp_state &= ~SS_LSTART;
  818         }
  819 
  820         sihardclose(pp);
  821         tty_close(tp);
  822         pp->sp_state &= ~SS_OPEN;
  823 
  824 out:
  825         DPRINT((pp, DBG_CLOSE|DBG_EXIT, "close done, returning\n"));
  826         splx(oldspl);
  827         return(error);
  828 }
  829 
  830 static void
  831 sihardclose(struct si_port *pp)
  832 {
  833         int oldspl;
  834         struct tty *tp;
  835         volatile struct si_channel *ccbp;
  836 
  837         oldspl = spltty();
  838 
  839         tp = pp->sp_tty;
  840         ccbp = pp->sp_ccb;                      /* Find control block */
  841         if (tp->t_cflag & HUPCL ||
  842             (!pp->sp_active_out &&
  843              !(ccbp->hi_ip & IP_DCD) &&
  844              !(pp->sp_iin.c_cflag && CLOCAL)) ||
  845             !(tp->t_state & TS_ISOPEN)) {
  846 
  847                 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
  848                 (void) si_command(pp, FCLOSE, SI_NOWAIT);
  849 
  850                 ttydtrwaitstart(tp);
  851         }
  852         pp->sp_active_out = FALSE;
  853         wakeup(&pp->sp_active_out);
  854         wakeup(TSA_CARR_ON(tp));
  855 
  856         splx(oldspl);
  857 }
  858 
  859 static  int
  860 siwrite(struct cdev *dev, struct uio *uio, int flag)
  861 {
  862         struct si_port *pp;
  863         struct tty *tp;
  864         int error = 0;
  865         int mynor = minor(dev);
  866         int oldspl;
  867 
  868         if (IS_SPECIAL(mynor)) {
  869                 DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_WRITE, "siwrite(CONTROLDEV!!)\n"));
  870                 return(ENODEV);
  871         }
  872         pp = MINOR2PP(mynor);
  873         tp = pp->sp_tty;
  874         DPRINT((pp, DBG_WRITE, "siwrite(%s,%x,%x)\n", devtoname(dev), uio, flag));
  875 
  876         oldspl = spltty();
  877         /*
  878          * If writes are currently blocked, wait on the "real" tty
  879          */
  880         while (pp->sp_state & SS_BLOCKWRITE) {
  881                 pp->sp_state |= SS_WAITWRITE;
  882                 DPRINT((pp, DBG_WRITE, "in siwrite, wait for SS_BLOCKWRITE to clear\n"));
  883                 if ((error = ttysleep(tp, (caddr_t)pp, TTOPRI|PCATCH,
  884                                      "siwrite", tp->t_timeout))) {
  885                         if (error == EWOULDBLOCK)
  886                                 error = EIO;
  887                         goto out;
  888                 }
  889         }
  890 
  891         error = ttyld_write(tp, uio, flag);
  892 out:
  893         splx(oldspl);
  894         return (error);
  895 }
  896 
  897 
  898 static  int
  899 siioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  900 {
  901         struct si_port *pp;
  902         struct tty *tp;
  903         int error;
  904         int mynor = minor(dev);
  905         int oldspl;
  906         int blocked = 0;
  907 #ifndef BURN_BRIDGES
  908 #if defined(COMPAT_43)
  909         u_long oldcmd;
  910         struct termios term;
  911 #endif
  912 #endif
  913 
  914         if (IS_SI_IOCTL(cmd))
  915                 return(si_Sioctl(dev, cmd, data, flag, td));
  916 
  917         pp = MINOR2PP(mynor);
  918         tp = pp->sp_tty;
  919 
  920         DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "siioctl(%s,%lx,%x,%x)\n",
  921                 devtoname(dev), cmd, data, flag));
  922         if (IS_STATE(mynor)) {
  923                 struct termios *ct;
  924 
  925                 switch (mynor & SI_STATE_MASK) {
  926                 case SI_INIT_STATE_MASK:
  927                         ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin;
  928                         break;
  929                 case SI_LOCK_STATE_MASK:
  930                         ct = IS_CALLOUT(mynor) ? &pp->sp_lout : &pp->sp_lin;
  931                         break;
  932                 default:
  933                         return (ENODEV);
  934                 }
  935                 switch (cmd) {
  936                 case TIOCSETA:
  937                         error = suser(td);
  938                         if (error != 0)
  939                                 return (error);
  940                         *ct = *(struct termios *)data;
  941                         return (0);
  942                 case TIOCGETA:
  943                         *(struct termios *)data = *ct;
  944                         return (0);
  945                 case TIOCGETD:
  946                         *(int *)data = TTYDISC;
  947                         return (0);
  948                 case TIOCGWINSZ:
  949                         bzero(data, sizeof(struct winsize));
  950                         return (0);
  951                 default:
  952                         return (ENOTTY);
  953                 }
  954         }
  955         /*
  956          * Do the old-style ioctl compat routines...
  957          */
  958 #ifndef BURN_BRIDGES
  959 #if defined(COMPAT_43)
  960         term = tp->t_termios;
  961         oldcmd = cmd;
  962         error = ttsetcompat(tp, &cmd, data, &term);
  963         if (error != 0)
  964                 return (error);
  965         if (cmd != oldcmd)
  966                 data = (caddr_t)&term;
  967 #endif
  968 #endif
  969         /*
  970          * Do the initial / lock state business
  971          */
  972         if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
  973                 int     cc;
  974                 struct termios *dt = (struct termios *)data;
  975                 struct termios *lt = mynor & SI_CALLOUT_MASK
  976                                      ? &pp->sp_lout : &pp->sp_lin;
  977 
  978                 dt->c_iflag = (tp->t_iflag & lt->c_iflag) |
  979                         (dt->c_iflag & ~lt->c_iflag);
  980                 dt->c_oflag = (tp->t_oflag & lt->c_oflag) |
  981                         (dt->c_oflag & ~lt->c_oflag);
  982                 dt->c_cflag = (tp->t_cflag & lt->c_cflag) |
  983                         (dt->c_cflag & ~lt->c_cflag);
  984                 dt->c_lflag = (tp->t_lflag & lt->c_lflag) |
  985                         (dt->c_lflag & ~lt->c_lflag);
  986                 for (cc = 0; cc < NCCS; ++cc)
  987                         if (lt->c_cc[cc] != 0)
  988                                 dt->c_cc[cc] = tp->t_cc[cc];
  989                 if (lt->c_ispeed != 0)
  990                         dt->c_ispeed = tp->t_ispeed;
  991                 if (lt->c_ospeed != 0)
  992                         dt->c_ospeed = tp->t_ospeed;
  993         }
  994 
  995         /*
  996          * Block user-level writes to give the ttywait()
  997          * a chance to completely drain for commands
  998          * that require the port to be in a quiescent state.
  999          */
 1000         switch (cmd) {
 1001         case TIOCSETAW:
 1002         case TIOCSETAF:
 1003         case TIOCDRAIN:
 1004 #ifndef BURN_BRIDGES
 1005 #ifdef COMPAT_43
 1006         case TIOCSETP:
 1007 #endif
 1008 #endif
 1009                 blocked++;      /* block writes for ttywait() and siparam() */
 1010                 si_write_enable(pp, 0);
 1011         }
 1012 
 1013         error = ttyioctl(dev, cmd, data, flag, td);
 1014         ttyldoptim(tp);
 1015         if (error != ENOTTY)
 1016                 goto out;
 1017 
 1018         oldspl = spltty();
 1019 
 1020         error = 0;
 1021         switch (cmd) {
 1022         case TIOCSBRK:
 1023                 si_command(pp, SBREAK, SI_WAIT);
 1024                 break;
 1025         case TIOCCBRK:
 1026                 si_command(pp, EBREAK, SI_WAIT);
 1027                 break;
 1028         case TIOCSDTR:
 1029                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
 1030                 break;
 1031         case TIOCCDTR:
 1032                 (void) si_modem(pp, SET, 0);
 1033                 break;
 1034         case TIOCMSET:
 1035                 (void) si_modem(pp, SET, *(int *)data);
 1036                 break;
 1037         case TIOCMBIS:
 1038                 (void) si_modem(pp, BIS, *(int *)data);
 1039                 break;
 1040         case TIOCMBIC:
 1041                 (void) si_modem(pp, BIC, *(int *)data);
 1042                 break;
 1043         case TIOCMGET:
 1044                 *(int *)data = si_modem(pp, GET, 0);
 1045                 break;
 1046         default:
 1047                 error = ENOTTY;
 1048         }
 1049         splx(oldspl);
 1050 
 1051 out:
 1052         DPRINT((pp, DBG_IOCTL|DBG_EXIT, "siioctl ret %d\n", error));
 1053         if (blocked)
 1054                 si_write_enable(pp, 1);
 1055         return(error);
 1056 }
 1057 
 1058 /*
 1059  * Handle the Specialix ioctls. All MUST be called via the CONTROL device
 1060  */
 1061 static int
 1062 si_Sioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
 1063 {
 1064         struct si_softc *xsc;
 1065         struct si_port *xpp;
 1066         volatile struct si_reg *regp;
 1067         struct si_tcsi *dp;
 1068         struct si_pstat *sps;
 1069         int *ip, error = 0;
 1070         int oldspl;
 1071         int card, port;
 1072         int mynor = minor(dev);
 1073 
 1074         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%s,%lx,%x,%x)\n",
 1075                 devtoname(dev), cmd, data, flag));
 1076 
 1077 #if 1
 1078         DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT));
 1079         DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB));
 1080         DPRINT((0, DBG_IOCTL, "TCSI_TTY=%x\n", TCSI_TTY));
 1081 #endif
 1082 
 1083         if (!IS_CONTROLDEV(mynor)) {
 1084                 DPRINT((0, DBG_IOCTL|DBG_FAIL, "not called from control device!\n"));
 1085                 return(ENODEV);
 1086         }
 1087 
 1088         oldspl = spltty();      /* better safe than sorry */
 1089 
 1090         ip = (int *)data;
 1091 
 1092 #define SUCHECK if ((error = suser(td))) goto out
 1093 
 1094         switch (cmd) {
 1095         case TCSIPORTS:
 1096                 *ip = si_Nports;
 1097                 goto out;
 1098         case TCSIMODULES:
 1099                 *ip = si_Nmodules;
 1100                 goto out;
 1101         case TCSISDBG_ALL:
 1102                 SUCHECK;
 1103                 si_debug = *ip;
 1104                 goto out;
 1105         case TCSIGDBG_ALL:
 1106                 *ip = si_debug;
 1107                 goto out;
 1108         default:
 1109                 /*
 1110                  * Check that a controller for this port exists
 1111                  */
 1112 
 1113                 /* may also be a struct si_pstat, a superset of si_tcsi */
 1114 
 1115                 dp = (struct si_tcsi *)data;
 1116                 sps = (struct si_pstat *)data;
 1117                 card = dp->tc_card;
 1118                 xsc = devclass_get_softc(si_devclass, card);    /* check.. */
 1119                 if (xsc == NULL || xsc->sc_type == SIEMPTY) {
 1120                         error = ENOENT;
 1121                         goto out;
 1122                 }
 1123                 /*
 1124                  * And check that a port exists
 1125                  */
 1126                 port = dp->tc_port;
 1127                 if (port < 0 || port >= xsc->sc_nport) {
 1128                         error = ENOENT;
 1129                         goto out;
 1130                 }
 1131                 xpp = xsc->sc_ports + port;
 1132                 regp = (struct si_reg *)xsc->sc_maddr;
 1133         }
 1134 
 1135         switch (cmd) {
 1136         case TCSIDEBUG:
 1137 #ifdef  SI_DEBUG
 1138                 SUCHECK;
 1139                 if (xpp->sp_debug)
 1140                         xpp->sp_debug = 0;
 1141                 else {
 1142                         xpp->sp_debug = DBG_ALL;
 1143                         DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",
 1144                                 (xpp->sp_debug&DBG_ALL)?"ON":"OFF"));
 1145                 }
 1146                 break;
 1147 #else
 1148                 error = ENODEV;
 1149                 goto out;
 1150 #endif
 1151         case TCSISDBG_LEVEL:
 1152         case TCSIGDBG_LEVEL:
 1153 #ifdef  SI_DEBUG
 1154                 if (cmd == TCSIGDBG_LEVEL) {
 1155                         dp->tc_dbglvl = xpp->sp_debug;
 1156                 } else {
 1157                         SUCHECK;
 1158                         xpp->sp_debug = dp->tc_dbglvl;
 1159                 }
 1160                 break;
 1161 #else
 1162                 error = ENODEV;
 1163                 goto out;
 1164 #endif
 1165         case TCSIGRXIT:
 1166                 dp->tc_int = regp->rx_int_count;
 1167                 break;
 1168         case TCSIRXIT:
 1169                 SUCHECK;
 1170                 regp->rx_int_count = dp->tc_int;
 1171                 break;
 1172         case TCSIGIT:
 1173                 dp->tc_int = regp->int_count;
 1174                 break;
 1175         case TCSIIT:
 1176                 SUCHECK;
 1177                 regp->int_count = dp->tc_int;
 1178                 break;
 1179         case TCSISTATE:
 1180                 dp->tc_int = xpp->sp_ccb->hi_ip;
 1181                 break;
 1182         /* these next three use a different structure */
 1183         case TCSI_PORT:
 1184                 SUCHECK;
 1185                 si_bcopy(xpp, &sps->tc_siport, sizeof(sps->tc_siport));
 1186                 break;
 1187         case TCSI_CCB:
 1188                 SUCHECK;
 1189                 si_vbcopy(xpp->sp_ccb, &sps->tc_ccb, sizeof(sps->tc_ccb));
 1190                 break;
 1191         case TCSI_TTY:
 1192                 SUCHECK;
 1193                 si_bcopy(xpp->sp_tty, &sps->tc_tty, sizeof(sps->tc_tty));
 1194                 break;
 1195         default:
 1196                 error = EINVAL;
 1197                 goto out;
 1198         }
 1199 out:
 1200         splx(oldspl);
 1201         return(error);          /* success */
 1202 }
 1203 
 1204 /*
 1205  *      siparam()       : Configure line params
 1206  *      called at spltty();
 1207  *      this may sleep, does not flush, nor wait for drain, nor block writes
 1208  *      caller must arrange this if it's important..
 1209  */
 1210 static int
 1211 siparam(struct tty *tp, struct termios *t)
 1212 {
 1213         struct si_port *pp = TP2PP(tp);
 1214         volatile struct si_channel *ccbp;
 1215         int oldspl, cflag, iflag, oflag, lflag;
 1216         int error = 0;          /* shutup gcc */
 1217         int ispeed = 0;         /* shutup gcc */
 1218         int ospeed = 0;         /* shutup gcc */
 1219         BYTE val;
 1220 
 1221         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
 1222         cflag = t->c_cflag;
 1223         iflag = t->c_iflag;
 1224         oflag = t->c_oflag;
 1225         lflag = t->c_lflag;
 1226         DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",
 1227                 oflag, cflag, iflag, lflag));
 1228 
 1229         /* XXX - if Jet host and SXDC module, use extended baud rates */
 1230 
 1231         /* if not hung up.. */
 1232         if (t->c_ospeed != 0) {
 1233                 /* translate baud rate to firmware values */
 1234                 ospeed = ttspeedtab(t->c_ospeed, bdrates);
 1235                 ispeed = t->c_ispeed ?
 1236                          ttspeedtab(t->c_ispeed, bdrates) : ospeed;
 1237 
 1238                 /* enforce legit baud rate */
 1239                 if (ospeed < 0 || ispeed < 0)
 1240                         return (EINVAL);
 1241         }
 1242 
 1243         oldspl = spltty();
 1244 
 1245         ccbp = pp->sp_ccb;
 1246 
 1247         /* ========== set hi_break ========== */
 1248         val = 0;
 1249         if (iflag & IGNBRK)             /* Breaks */
 1250                 val |= BR_IGN;
 1251         if (iflag & BRKINT)             /* Interrupt on break? */
 1252                 val |= BR_INT;
 1253         if (iflag & PARMRK)             /* Parity mark? */
 1254                 val |= BR_PARMRK;
 1255         if (iflag & IGNPAR)             /* Ignore chars with parity errors? */
 1256                 val |= BR_PARIGN;
 1257         ccbp->hi_break = val;
 1258 
 1259         /* ========== set hi_csr ========== */
 1260         /* if not hung up.. */
 1261         if (t->c_ospeed != 0) {
 1262                 /* Set I/O speeds */
 1263                  val = (ispeed << 4) | ospeed;
 1264         }
 1265         ccbp->hi_csr = val;
 1266 
 1267         /* ========== set hi_mr2 ========== */
 1268         val = 0;
 1269         if (cflag & CSTOPB)                             /* Stop bits */
 1270                 val |= MR2_2_STOP;
 1271         else
 1272                 val |= MR2_1_STOP;
 1273         /*
 1274          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
 1275          * a DCE, hence the reverse sense of RTS and CTS
 1276          */
 1277         /* Output Flow - RTS must be raised before data can be sent */
 1278         if (cflag & CCTS_OFLOW)
 1279                 val |= MR2_RTSCONT;
 1280 
 1281         ccbp->hi_mr2 = val;
 1282 
 1283         /* ========== set hi_mr1 ========== */
 1284         val = 0;
 1285         if (!(cflag & PARENB))                          /* Parity */
 1286                 val |= MR1_NONE;
 1287         else
 1288                 val |= MR1_WITH;
 1289         if (cflag & PARODD)
 1290                 val |= MR1_ODD;
 1291 
 1292         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
 1293                 val |= MR1_8_BITS;
 1294         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
 1295                 val |= MR1_7_BITS;
 1296         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
 1297                 val |= MR1_6_BITS;
 1298         } else {                                        /* Must be 5 */
 1299                 val |= MR1_5_BITS;
 1300         }
 1301         /*
 1302          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
 1303          * a DCE, hence the reverse sense of RTS and CTS
 1304          */
 1305         /* Input Flow - CTS is raised when port is ready to receive data */
 1306         if (cflag & CRTS_IFLOW)
 1307                 val |= MR1_CTSCONT;
 1308 
 1309         ccbp->hi_mr1 = val;
 1310 
 1311         /* ========== set hi_mask ========== */
 1312         val = 0xff;
 1313         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
 1314                 val &= 0xFF;
 1315         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
 1316                 val &= 0x7F;
 1317         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
 1318                 val &= 0x3F;
 1319         } else {                                        /* Must be 5 */
 1320                 val &= 0x1F;
 1321         }
 1322         if (iflag & ISTRIP)
 1323                 val &= 0x7F;
 1324 
 1325         ccbp->hi_mask = val;
 1326 
 1327         /* ========== set hi_prtcl ========== */
 1328         val = SP_DCEN;          /* Monitor DCD always, or TIOCMGET misses it */
 1329         if (iflag & IXANY)
 1330                 val |= SP_TANY;
 1331         if (iflag & IXON)
 1332                 val |= SP_TXEN;
 1333         if (iflag & IXOFF)
 1334                 val |= SP_RXEN;
 1335         if (iflag & INPCK)
 1336                 val |= SP_PAEN;
 1337 
 1338         ccbp->hi_prtcl = val;
 1339 
 1340 
 1341         /* ========== set hi_{rx|tx}{on|off} ========== */
 1342         /* XXX: the card TOTALLY shields us from the flow control... */
 1343         ccbp->hi_txon = t->c_cc[VSTART];
 1344         ccbp->hi_txoff = t->c_cc[VSTOP];
 1345 
 1346         ccbp->hi_rxon = t->c_cc[VSTART];
 1347         ccbp->hi_rxoff = t->c_cc[VSTOP];
 1348 
 1349         /* ========== send settings to the card ========== */
 1350         /* potential sleep here */
 1351         if (ccbp->hi_stat == IDLE_CLOSE)                /* Not yet open */
 1352                 si_command(pp, LOPEN, SI_WAIT);         /* open it */
 1353         else
 1354                 si_command(pp, CONFIG, SI_WAIT);        /* change params */
 1355 
 1356         /* ========== set DTR etc ========== */
 1357         /* Hangup if ospeed == 0 */
 1358         if (t->c_ospeed == 0) {
 1359                 (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
 1360         } else {
 1361                 /*
 1362                  * If the previous speed was 0, may need to re-enable
 1363                  * the modem signals
 1364                  */
 1365                 (void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);
 1366         }
 1367 
 1368         DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x\n",
 1369                 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));
 1370 
 1371         splx(oldspl);
 1372         return(error);
 1373 }
 1374 
 1375 /*
 1376  * Enable or Disable the writes to this channel...
 1377  * "state" ->  enabled = 1; disabled = 0;
 1378  */
 1379 static void
 1380 si_write_enable(struct si_port *pp, int state)
 1381 {
 1382         int oldspl;
 1383 
 1384         oldspl = spltty();
 1385 
 1386         if (state) {
 1387                 pp->sp_state &= ~SS_BLOCKWRITE;
 1388                 if (pp->sp_state & SS_WAITWRITE) {
 1389                         pp->sp_state &= ~SS_WAITWRITE;
 1390                         /* thunder away! */
 1391                         wakeup(pp);
 1392                 }
 1393         } else {
 1394                 pp->sp_state |= SS_BLOCKWRITE;
 1395         }
 1396 
 1397         splx(oldspl);
 1398 }
 1399 
 1400 /*
 1401  * Set/Get state of modem control lines.
 1402  * Due to DCE-like behaviour of the adapter, some signals need translation:
 1403  *      TIOCM_DTR       DSR
 1404  *      TIOCM_RTS       CTS
 1405  */
 1406 static int
 1407 si_modem(struct si_port *pp, enum si_mctl cmd, int bits)
 1408 {
 1409         volatile struct si_channel *ccbp;
 1410         int x;
 1411 
 1412         DPRINT((pp, DBG_ENTRY|DBG_MODEM, "si_modem(%x,%s,%x)\n", pp, si_mctl2str(cmd), bits));
 1413         ccbp = pp->sp_ccb;              /* Find channel address */
 1414         switch (cmd) {
 1415         case GET:
 1416                 x = ccbp->hi_ip;
 1417                 bits = TIOCM_LE;
 1418                 if (x & IP_DCD)         bits |= TIOCM_CAR;
 1419                 if (x & IP_DTR)         bits |= TIOCM_DTR;
 1420                 if (x & IP_RTS)         bits |= TIOCM_RTS;
 1421                 if (x & IP_RI)          bits |= TIOCM_RI;
 1422                 return(bits);
 1423         case SET:
 1424                 ccbp->hi_op &= ~(OP_DSR|OP_CTS);
 1425                 /* fall through */
 1426         case BIS:
 1427                 x = 0;
 1428                 if (bits & TIOCM_DTR)
 1429                         x |= OP_DSR;
 1430                 if (bits & TIOCM_RTS)
 1431                         x |= OP_CTS;
 1432                 ccbp->hi_op |= x;
 1433                 break;
 1434         case BIC:
 1435                 if (bits & TIOCM_DTR)
 1436                         ccbp->hi_op &= ~OP_DSR;
 1437                 if (bits & TIOCM_RTS)
 1438                         ccbp->hi_op &= ~OP_CTS;
 1439         }
 1440         return 0;
 1441 }
 1442 
 1443 /*
 1444  * Handle change of modem state
 1445  */
 1446 static void
 1447 si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip)
 1448 {
 1449                                                         /* if a modem dev */
 1450         if (hi_ip & IP_DCD) {
 1451                 if (!(pp->sp_last_hi_ip & IP_DCD)) {
 1452                         DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n",
 1453                                 tp->t_line));
 1454                         (void)ttyld_modem(tp, 1);
 1455                 }
 1456         } else {
 1457                 if (pp->sp_last_hi_ip & IP_DCD) {
 1458                         DPRINT((pp, DBG_INTR, "modem carr off\n"));
 1459                         if (ttyld_modem(tp, 0))
 1460                                 (void) si_modem(pp, SET, 0);
 1461                 }
 1462         }
 1463         pp->sp_last_hi_ip = hi_ip;
 1464 
 1465 }
 1466 
 1467 /*
 1468  * Poller to catch missed interrupts.
 1469  *
 1470  * Note that the SYSV Specialix drivers poll at 100 times per second to get
 1471  * better response.  We could really use a "periodic" version timeout(). :-)
 1472  */
 1473 #ifdef POLL
 1474 static void
 1475 si_poll(void *nothing)
 1476 {
 1477         struct si_softc *sc;
 1478         int i;
 1479         volatile struct si_reg *regp;
 1480         struct si_port *pp;
 1481         int lost, oldspl, port;
 1482 
 1483         DPRINT((0, DBG_POLL, "si_poll()\n"));
 1484         oldspl = spltty();
 1485         if (in_intr)
 1486                 goto out;
 1487         lost = 0;
 1488         for (i = 0; i < si_numunits; i++) {
 1489                 sc = devclass_get_softc(si_devclass, i);
 1490                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1491                         continue;
 1492                 regp = (struct si_reg *)sc->sc_maddr;
 1493 
 1494                 /*
 1495                  * See if there has been a pending interrupt for 2 seconds
 1496                  * or so. The test (int_scounter >= 200) won't correspond
 1497                  * to 2 seconds if int_count gets changed.
 1498                  */
 1499                 if (regp->int_pending != 0) {
 1500                         if (regp->int_scounter >= 200 &&
 1501                             regp->initstat == 1) {
 1502                                 printf("si%d: lost intr\n", i);
 1503                                 lost++;
 1504                         }
 1505                 } else {
 1506                         regp->int_scounter = 0;
 1507                 }
 1508 
 1509                 /*
 1510                  * gripe about no input flow control..
 1511                  */
 1512                 pp = sc->sc_ports;
 1513                 for (port = 0; port < sc->sc_nport; pp++, port++) {
 1514                         if (pp->sp_delta_overflows > 0) {
 1515                                 printf("si%d: %d tty level buffer overflows\n",
 1516                                         i, pp->sp_delta_overflows);
 1517                                 pp->sp_delta_overflows = 0;
 1518                         }
 1519                 }
 1520         }
 1521         if (lost || si_realpoll)
 1522                 si_intr(NULL);  /* call intr with fake vector */
 1523 out:
 1524         splx(oldspl);
 1525 
 1526         timeout(si_poll, (caddr_t)0L, si_pollrate);
 1527 }
 1528 #endif  /* ifdef POLL */
 1529 
 1530 /*
 1531  * The interrupt handler polls ALL ports on ALL adapters each time
 1532  * it is called.
 1533  */
 1534 
 1535 static BYTE si_rxbuf[SI_BUFFERSIZE];    /* input staging area */
 1536 static BYTE si_txbuf[SI_BUFFERSIZE];    /* output staging area */
 1537 
 1538 void
 1539 si_intr(void *arg)
 1540 {
 1541         struct si_softc *sc;
 1542         struct si_port *pp;
 1543         volatile struct si_channel *ccbp;
 1544         struct tty *tp;
 1545         volatile caddr_t maddr;
 1546         BYTE op, ip;
 1547         int x, card, port, n, i, isopen;
 1548         volatile BYTE *z;
 1549         BYTE c;
 1550 
 1551         sc = arg;
 1552 
 1553         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "si_intr\n"));
 1554         if (in_intr)
 1555                 return;
 1556         in_intr = 1;
 1557 
 1558         /*
 1559          * When we get an int we poll all the channels and do ALL pending
 1560          * work, not just the first one we find. This allows all cards to
 1561          * share the same vector.
 1562          *
 1563          * XXX - But if we're sharing the vector with something that's NOT
 1564          * a SI/XIO/SX card, we may be making more work for ourselves.
 1565          */
 1566         for (card = 0; card < si_numunits; card++) {
 1567                 sc = devclass_get_softc(si_devclass, card);
 1568                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1569                         continue;
 1570 
 1571                 /*
 1572                  * First, clear the interrupt
 1573                  */
 1574                 switch(sc->sc_type) {
 1575                 case SIHOST:
 1576                         maddr = sc->sc_maddr;
 1577                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1578                                                         /* flag nothing pending */
 1579                         *(maddr+SIINTCL) = 0x00;        /* Set IRQ clear */
 1580                         *(maddr+SIINTCL_CL) = 0x00;     /* Clear IRQ clear */
 1581                         break;
 1582                 case SIHOST2:
 1583                         maddr = sc->sc_maddr;
 1584                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1585                         *(maddr+SIPLIRQCLR) = 0x00;
 1586                         *(maddr+SIPLIRQCLR) = 0x10;
 1587                         break;
 1588                 case SIPCI:
 1589                         maddr = sc->sc_maddr;
 1590                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1591                         *(maddr+SIPCIINTCL) = 0x0;
 1592                         break;
 1593                 case SIJETPCI:  /* fall through to JETISA case */
 1594                 case SIJETISA:
 1595                         maddr = sc->sc_maddr;
 1596                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1597                         *(maddr+SIJETINTCL) = 0x0;
 1598                         break;
 1599                 case SIEISA:
 1600                         maddr = sc->sc_maddr;
 1601                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1602                         (void)inb(sc->sc_iobase + 3);
 1603                         break;
 1604                 case SIEMPTY:
 1605                 default:
 1606                         continue;
 1607                 }
 1608                 ((volatile struct si_reg *)maddr)->int_scounter = 0;
 1609 
 1610                 /*
 1611                  * check each port
 1612                  */
 1613                 for (pp = sc->sc_ports, port = 0; port < sc->sc_nport;
 1614                      pp++, port++) {
 1615                         ccbp = pp->sp_ccb;
 1616                         tp = pp->sp_tty;
 1617 
 1618                         /*
 1619                          * See if a command has completed ?
 1620                          */
 1621                         if (ccbp->hi_stat != pp->sp_pend) {
 1622                                 DPRINT((pp, DBG_INTR,
 1623                                         "si_intr hi_stat = 0x%x, pend = %d\n",
 1624                                         ccbp->hi_stat, pp->sp_pend));
 1625                                 switch(pp->sp_pend) {
 1626                                 case LOPEN:
 1627                                 case MPEND:
 1628                                 case MOPEN:
 1629                                 case CONFIG:
 1630                                 case SBREAK:
 1631                                 case EBREAK:
 1632                                         pp->sp_pend = ccbp->hi_stat;
 1633                                                 /* sleeping in si_command */
 1634                                         wakeup(&pp->sp_state);
 1635                                         break;
 1636                                 default:
 1637                                         pp->sp_pend = ccbp->hi_stat;
 1638                                 }
 1639                         }
 1640 
 1641                         /*
 1642                          * Continue on if it's closed
 1643                          */
 1644                         if (ccbp->hi_stat == IDLE_CLOSE) {
 1645                                 continue;
 1646                         }
 1647 
 1648                         /*
 1649                          * Do modem state change if not a local device
 1650                          */
 1651                         si_modem_state(pp, tp, ccbp->hi_ip);
 1652 
 1653                         /*
 1654                          * Check to see if we should 'receive' characters.
 1655                          */
 1656                         if (tp->t_state & TS_CONNECTED &&
 1657                             tp->t_state & TS_ISOPEN)
 1658                                 isopen = 1;
 1659                         else
 1660                                 isopen = 0;
 1661 
 1662                         /*
 1663                          * Do input break processing
 1664                          */
 1665                         if (ccbp->hi_state & ST_BREAK) {
 1666                                 if (isopen) {
 1667                                     ttyld_rint(tp, TTY_BI);
 1668                                 }
 1669                                 ccbp->hi_state &= ~ST_BREAK;   /* A Bit iffy this */
 1670                                 DPRINT((pp, DBG_INTR, "si_intr break\n"));
 1671                         }
 1672 
 1673                         /*
 1674                          * Do RX stuff - if not open then dump any characters.
 1675                          * XXX: This is VERY messy and needs to be cleaned up.
 1676                          *
 1677                          * XXX: can we leave data in the host adapter buffer
 1678                          * when the clists are full?  That may be dangerous
 1679                          * if the user cannot get an interrupt signal through.
 1680                          */
 1681 
 1682         more_rx:        /* XXX Sorry. the nesting was driving me bats! :-( */
 1683 
 1684                         if (!isopen) {
 1685                                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1686                                 goto end_rx;
 1687                         }
 1688 
 1689                         /*
 1690                          * If the tty input buffers are blocked, stop emptying
 1691                          * the incoming buffers and let the auto flow control
 1692                          * assert..
 1693                          */
 1694                         if (tp->t_state & TS_TBLOCK) {
 1695                                 goto end_rx;
 1696                         }
 1697 
 1698                         /*
 1699                          * Process read characters if not skipped above
 1700                          */
 1701                         op = ccbp->hi_rxopos;
 1702                         ip = ccbp->hi_rxipos;
 1703                         c = ip - op;
 1704                         if (c == 0) {
 1705                                 goto end_rx;
 1706                         }
 1707 
 1708                         n = c & 0xff;
 1709                         if (n > 250)
 1710                                 n = 250;
 1711 
 1712                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 1713                                                 n, op, ip));
 1714 
 1715                         /*
 1716                          * Suck characters out of host card buffer into the
 1717                          * "input staging buffer" - so that we dont leave the
 1718                          * host card in limbo while we're possibly echoing
 1719                          * characters and possibly flushing input inside the
 1720                          * ldisc l_rint() routine.
 1721                          */
 1722                         if (n <= SI_BUFFERSIZE - op) {
 1723 
 1724                                 DPRINT((pp, DBG_INTR, "\tsingle copy\n"));
 1725                                 z = ccbp->hi_rxbuf + op;
 1726                                 si_vbcopy(z, si_rxbuf, n);
 1727 
 1728                                 op += n;
 1729                         } else {
 1730                                 x = SI_BUFFERSIZE - op;
 1731 
 1732                                 DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
 1733                                 z = ccbp->hi_rxbuf + op;
 1734                                 si_vbcopy(z, si_rxbuf, x);
 1735 
 1736                                 DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n",
 1737                                         n - x));
 1738                                 z = ccbp->hi_rxbuf;
 1739                                 si_vbcopy(z, si_rxbuf + x, n - x);
 1740 
 1741                                 op += n;
 1742                         }
 1743 
 1744                         /* clear collected characters from buffer */
 1745                         ccbp->hi_rxopos = op;
 1746 
 1747                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 1748                                                 n, op, ip));
 1749 
 1750                         /*
 1751                          * at this point...
 1752                          * n = number of chars placed in si_rxbuf
 1753                          */
 1754 
 1755                         /*
 1756                          * Avoid the grotesquely inefficient lineswitch
 1757                          * routine (ttyinput) in "raw" mode. It usually
 1758                          * takes about 450 instructions (that's without
 1759                          * canonical processing or echo!). slinput is
 1760                          * reasonably fast (usually 40 instructions
 1761                          * plus call overhead).
 1762                          */
 1763                         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 1764 
 1765                                 /* block if the driver supports it */
 1766                                 if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER &&
 1767                                     (tp->t_cflag & CRTS_IFLOW ||
 1768                                      tp->t_iflag & IXOFF) &&
 1769                                     !(tp->t_state & TS_TBLOCK))
 1770                                         ttyblock(tp);
 1771 
 1772                                 tk_nin += n;
 1773                                 tk_rawcc += n;
 1774                                 tp->t_rawcc += n;
 1775 
 1776                                 pp->sp_delta_overflows +=
 1777                                     b_to_q((char *)si_rxbuf, n, &tp->t_rawq);
 1778 
 1779                                 ttwakeup(tp);
 1780                                 if (tp->t_state & TS_TTSTOP &&
 1781                                     (tp->t_iflag & IXANY ||
 1782                                      tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
 1783                                         tp->t_state &= ~TS_TTSTOP;
 1784                                         tp->t_lflag &= ~FLUSHO;
 1785                                         si_start(tp);
 1786                                 }
 1787                         } else {
 1788                                 /*
 1789                                  * It'd be nice to not have to go through the
 1790                                  * function call overhead for each char here.
 1791                                  * It'd be nice to block input it, saving a
 1792                                  * loop here and the call/return overhead.
 1793                                  */
 1794                                 for(x = 0; x < n; x++) {
 1795                                         i = si_rxbuf[x];
 1796                                         if (ttyld_rint(tp, i)
 1797                                              == -1) {
 1798                                                 pp->sp_delta_overflows++;
 1799                                         }
 1800                                 }
 1801                         }
 1802                         goto more_rx;   /* try for more until RXbuf is empty */
 1803 
 1804         end_rx:         /* XXX: Again, sorry about the gotos.. :-) */
 1805 
 1806                         /*
 1807                          * Do TX stuff
 1808                          */
 1809                         ttyld_start(tp);
 1810 
 1811                 } /* end of for (all ports on this controller) */
 1812         } /* end of for (all controllers) */
 1813 
 1814         in_intr = 0;
 1815         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "end si_intr\n"));
 1816 }
 1817 
 1818 /*
 1819  * Nudge the transmitter...
 1820  *
 1821  * XXX: I inherited some funny code here.  It implies the host card only
 1822  * interrupts when the transmit buffer reaches the low-water-mark, and does
 1823  * not interrupt when it's actually hits empty.  In some cases, we have
 1824  * processes waiting for complete drain, and we need to simulate an interrupt
 1825  * about when we think the buffer is going to be empty (and retry if not).
 1826  * I really am not certain about this...  I *need* the hardware manuals.
 1827  */
 1828 static void
 1829 si_start(struct tty *tp)
 1830 {
 1831         struct si_port *pp;
 1832         volatile struct si_channel *ccbp;
 1833         struct clist *qp;
 1834         BYTE ipos;
 1835         int nchar;
 1836         int oldspl, count, n, amount, buffer_full;
 1837 
 1838         oldspl = spltty();
 1839 
 1840         qp = &tp->t_outq;
 1841         pp = TP2PP(tp);
 1842 
 1843         DPRINT((pp, DBG_ENTRY|DBG_START,
 1844                 "si_start(%x) t_state %x sp_state %x t_outq.c_cc %d\n",
 1845                 tp, tp->t_state, pp->sp_state, qp->c_cc));
 1846 
 1847         if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
 1848                 goto out;
 1849 
 1850         buffer_full = 0;
 1851         ccbp = pp->sp_ccb;
 1852 
 1853         count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
 1854         DPRINT((pp, DBG_START, "count %d\n", (BYTE)count));
 1855 
 1856         while ((nchar = qp->c_cc) > 0) {
 1857                 if ((BYTE)count >= 255) {
 1858                         buffer_full++;
 1859                         break;
 1860                 }
 1861                 amount = min(nchar, (255 - (BYTE)count));
 1862                 ipos = (unsigned int)ccbp->hi_txipos;
 1863                 n = q_to_b(&tp->t_outq, si_txbuf, amount);
 1864                 /* will it fit in one lump? */
 1865                 if ((SI_BUFFERSIZE - ipos) >= n) {
 1866                         si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n);
 1867                 } else {
 1868                         si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos],
 1869                                 SI_BUFFERSIZE - ipos);
 1870                         si_bcopyv(si_txbuf + (SI_BUFFERSIZE - ipos),
 1871                                 &ccbp->hi_txbuf[0], n - (SI_BUFFERSIZE - ipos));
 1872                 }
 1873                 ccbp->hi_txipos += n;
 1874                 count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
 1875         }
 1876 
 1877         if (count != 0 && nchar == 0) {
 1878                 tp->t_state |= TS_BUSY;
 1879         } else {
 1880                 tp->t_state &= ~TS_BUSY;
 1881         }
 1882 
 1883         /* wakeup time? */
 1884         ttwwakeup(tp);
 1885 
 1886         DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n",
 1887                 (BYTE)count, nchar, tp->t_state));
 1888 
 1889         if (tp->t_state & TS_BUSY)
 1890         {
 1891                 int time;
 1892 
 1893                 time = ttspeedtab(tp->t_ospeed, chartimes);
 1894 
 1895                 if (time > 0) {
 1896                         if (time < nchar)
 1897                                 time = nchar / time;
 1898                         else
 1899                                 time = 2;
 1900                 } else {
 1901                         DPRINT((pp, DBG_START,
 1902                                 "bad char time value! %d\n", time));
 1903                         time = hz/10;
 1904                 }
 1905 
 1906                 if ((pp->sp_state & (SS_LSTART|SS_INLSTART)) == SS_LSTART) {
 1907                         untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
 1908                 } else {
 1909                         pp->sp_state |= SS_LSTART;
 1910                 }
 1911                 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
 1912                 pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time);
 1913         }
 1914 
 1915 out:
 1916         splx(oldspl);
 1917         DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
 1918 }
 1919 
 1920 /*
 1921  * Note: called at splsoftclock from the timeout code
 1922  * This has to deal with two things...  cause wakeups while waiting for
 1923  * tty drains on last process exit, and call l_start at about the right
 1924  * time for protocols like ppp.
 1925  */
 1926 static void
 1927 si_lstart(void *arg)
 1928 {
 1929         struct si_port *pp = arg;
 1930         struct tty *tp;
 1931         int oldspl;
 1932 
 1933         DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n",
 1934                 pp, pp->sp_state));
 1935 
 1936         oldspl = spltty();
 1937 
 1938         if ((pp->sp_state & SS_OPEN) == 0 || (pp->sp_state & SS_LSTART) == 0) {
 1939                 splx(oldspl);
 1940                 return;
 1941         }
 1942         pp->sp_state &= ~SS_LSTART;
 1943         pp->sp_state |= SS_INLSTART;
 1944 
 1945         tp = pp->sp_tty;
 1946 
 1947         /* deal with the process exit case */
 1948         ttwwakeup(tp);
 1949 
 1950         /* nudge protocols - eg: ppp */
 1951         ttyld_start(tp);
 1952 
 1953         pp->sp_state &= ~SS_INLSTART;
 1954         splx(oldspl);
 1955 }
 1956 
 1957 /*
 1958  * Stop output on a line. called at spltty();
 1959  */
 1960 static void
 1961 si_stop(struct tty *tp, int rw)
 1962 {
 1963         volatile struct si_channel *ccbp;
 1964         struct si_port *pp;
 1965 
 1966         pp = TP2PP(tp);
 1967         ccbp = pp->sp_ccb;
 1968 
 1969         DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "si_stop(%x,%x)\n", tp, rw));
 1970 
 1971         /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
 1972         if (rw & FWRITE) {
 1973                 /* what level are we meant to be flushing anyway? */
 1974                 if (tp->t_state & TS_BUSY) {
 1975                         si_command(TP2PP(tp), WFLUSH, SI_NOWAIT);
 1976                         tp->t_state &= ~TS_BUSY;
 1977                         ttwwakeup(tp);  /* Bruce???? */
 1978                 }
 1979         }
 1980 #if 1   /* XXX: this doesn't work right yet.. */
 1981         /* XXX: this may have been failing because we used to call l_rint()
 1982          * while we were looping based on these two counters. Now, we collect
 1983          * the data and then loop stuffing it into l_rint(), making this
 1984          * useless.  Should we cause this to blow away the staging buffer?
 1985          */
 1986         if (rw & FREAD) {
 1987                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1988         }
 1989 #endif
 1990 }
 1991 
 1992 /*
 1993  * Issue a command to the host card CPU.
 1994  */
 1995 
 1996 static void
 1997 si_command(struct si_port *pp, int cmd, int waitflag)
 1998 {
 1999         int oldspl;
 2000         volatile struct si_channel *ccbp = pp->sp_ccb;
 2001         int x;
 2002 
 2003         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%x,%d): hi_stat 0x%x\n",
 2004                 pp, cmd, waitflag, ccbp->hi_stat));
 2005 
 2006         oldspl = spltty();              /* Keep others out */
 2007 
 2008         /* wait until it's finished what it was doing.. */
 2009         /* XXX: sits in IDLE_BREAK until something disturbs it or break
 2010          * is turned off. */
 2011         while((x = ccbp->hi_stat) != IDLE_OPEN &&
 2012                         x != IDLE_CLOSE &&
 2013                         x != IDLE_BREAK &&
 2014                         x != cmd) {
 2015                 if (in_intr) {                  /* Prevent sleep in intr */
 2016                         DPRINT((pp, DBG_PARAM,
 2017                                 "cmd intr collision - completing %d\trequested %d\n",
 2018                                 x, cmd));
 2019                         splx(oldspl);
 2020                         return;
 2021                 } else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,
 2022                                 "sicmd1", 1)) {
 2023                         splx(oldspl);
 2024                         return;
 2025                 }
 2026         }
 2027         /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */
 2028 
 2029         /* if there was a pending command, cause a state-change wakeup */
 2030         switch(pp->sp_pend) {
 2031         case LOPEN:
 2032         case MPEND:
 2033         case MOPEN:
 2034         case CONFIG:
 2035         case SBREAK:
 2036         case EBREAK:
 2037                 wakeup(&pp->sp_state);
 2038                 break;
 2039         default:
 2040                 break;
 2041         }
 2042 
 2043         pp->sp_pend = cmd;              /* New command pending */
 2044         ccbp->hi_stat = cmd;            /* Post it */
 2045 
 2046         if (waitflag) {
 2047                 if (in_intr) {          /* If in interrupt handler */
 2048                         DPRINT((pp, DBG_PARAM,
 2049                                 "attempt to sleep in si_intr - cmd req %d\n",
 2050                                 cmd));
 2051                         splx(oldspl);
 2052                         return;
 2053                 } else while(ccbp->hi_stat != IDLE_OPEN &&
 2054                              ccbp->hi_stat != IDLE_BREAK) {
 2055                         if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,
 2056                             "sicmd2", 0))
 2057                                 break;
 2058                 }
 2059         }
 2060         splx(oldspl);
 2061 }
 2062 
 2063 
 2064 #ifdef  SI_DEBUG
 2065 
 2066 void
 2067 si_dprintf(struct si_port *pp, int flags, const char *fmt, ...)
 2068 {
 2069         va_list ap;
 2070 
 2071         if ((pp == NULL && (si_debug&flags)) ||
 2072             (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
 2073                 if (pp != NULL)
 2074                         printf("%ci%d(%d): ", 's',
 2075                                 (int)SI_CARD(minor(pp->sp_tty->t_dev)),
 2076                                 (int)SI_PORT(minor(pp->sp_tty->t_dev)));
 2077                 va_start(ap, fmt);
 2078                 vprintf(fmt, ap);
 2079                 va_end(ap);
 2080         }
 2081 }
 2082 
 2083 static char *
 2084 si_mctl2str(enum si_mctl cmd)
 2085 {
 2086         switch (cmd) {
 2087         case GET:
 2088                 return("GET");
 2089         case SET:
 2090                 return("SET");
 2091         case BIS:
 2092                 return("BIS");
 2093         case BIC:
 2094                 return("BIC");
 2095         }
 2096         return("BAD");
 2097 }
 2098 
 2099 #endif  /* DEBUG */
 2100 
 2101 static char *
 2102 si_modulename(int host_type, int uart_type)
 2103 {
 2104         switch (host_type) {
 2105         /* Z280 based cards */
 2106         case SIEISA:
 2107         case SIHOST2:
 2108         case SIHOST:
 2109         case SIPCI:
 2110                 switch (uart_type) {
 2111                 case 0:
 2112                         return(" (XIO)");
 2113                 case 1:
 2114                         return(" (SI)");
 2115                 }
 2116                 break;
 2117         /* T225 based hosts */
 2118         case SIJETPCI:
 2119         case SIJETISA:
 2120                 switch (uart_type) {
 2121                 case 0:
 2122                         return(" (SI)");
 2123                 case 40:
 2124                         return(" (XIO)");
 2125                 case 72:
 2126                         return(" (SXDC)");
 2127                 }
 2128                 break;
 2129         }
 2130         return("");
 2131 }

Cache object: f2c3559b233fdddaa60ee66df4188cec


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