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_eisa.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/serial.h>
   51 #include <sys/tty.h>
   52 #include <sys/conf.h>
   53 #include <sys/fcntl.h>
   54 #include <sys/kernel.h>
   55 #include <sys/malloc.h>
   56 #include <sys/priv.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/bus.h>
   59 #include <machine/bus.h>
   60 #include <sys/rman.h>
   61 #include <machine/resource.h>
   62 
   63 
   64 #include <vm/vm.h>
   65 #include <vm/pmap.h>
   66 
   67 #include <machine/stdarg.h>
   68 
   69 #include <dev/si/sireg.h>
   70 #include <dev/si/sivar.h>
   71 #include <dev/si/si.h>
   72 
   73 /*
   74  * This device driver is designed to interface the Specialix International
   75  * SI, XIO and SX range of serial multiplexor cards to FreeBSD on an ISA,
   76  * EISA or PCI bus machine.
   77  *
   78  * The controller is interfaced to the host via dual port RAM
   79  * and an interrupt.
   80  *
   81  * The code for the Host 1 (very old ISA cards) has not been tested.
   82  */
   83 
   84 #undef  POLL            /* turn on poller to scan for lost interrupts */
   85 #if 0
   86 #define REALPOLL        /* on each poll, scan for work regardless */
   87 #endif
   88 #define POLLHZ  (hz/10) /* 10 times per second */
   89 #define SI_I_HIGH_WATER (TTYHOG - 2 * SI_BUFFERSIZE)
   90 #define INT_COUNT 25000         /* max of 125 ints per second */
   91 #define JET_INT_COUNT 100       /* max of 100 ints per second */
   92 #define RXINT_COUNT 1   /* one rxint per 10 milliseconds */
   93 
   94 static void si_command(struct si_port *, int, int);
   95 static int si_Sioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
   96 /* static void si_stop(struct tty *, int); */
   97 #if 0
   98 static timeout_t si_lstart;
   99 #endif
  100 
  101 static tsw_outwakeup_t si_start;
  102 static tsw_ioctl_t siioctl;
  103 static tsw_close_t siclose;
  104 static tsw_modem_t simodem;
  105 static tsw_open_t siopen;
  106 static tsw_param_t siparam;
  107 
  108 static void     si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip);
  109 static char *   si_modulename(int host_type, int uart_type);
  110 
  111 static struct cdevsw si_Scdevsw = {
  112         .d_version =    D_VERSION,
  113         .d_ioctl =      si_Sioctl,
  114         .d_name =       "si",
  115         .d_flags =      D_TTY | D_NEEDGIANT,
  116 };
  117 
  118 static int si_Nports;
  119 static int si_Nmodules;
  120 static int si_debug;
  121 
  122 SYSCTL_INT(_machdep, OID_AUTO, si_debug, CTLFLAG_RW, &si_debug, 0, "");
  123 TUNABLE_INT("machdep.si_debug", &si_debug);
  124 
  125 static int si_numunits;
  126 
  127 devclass_t si_devclass;
  128 
  129 struct si_speedtab {
  130         int sp_speed;                   /* Speed. */
  131         int sp_code;                    /* Code. */
  132 };
  133 
  134 #ifndef B2000   /* not standard, but the hardware knows it. */
  135 # define B2000 2000
  136 #endif
  137 static struct si_speedtab bdrates[] = {
  138         { B75,          CLK75, },       /* 0x0 */
  139         { B110,         CLK110, },      /* 0x1 */
  140         { B150,         CLK150, },      /* 0x3 */
  141         { B300,         CLK300, },      /* 0x4 */
  142         { B600,         CLK600, },      /* 0x5 */
  143         { B1200,        CLK1200, },     /* 0x6 */
  144         { B2000,        CLK2000, },     /* 0x7 */
  145         { B2400,        CLK2400, },     /* 0x8 */
  146         { B4800,        CLK4800, },     /* 0x9 */
  147         { B9600,        CLK9600, },     /* 0xb */
  148         { B19200,       CLK19200, },    /* 0xc */
  149         { B38400,       CLK38400, },    /* 0x2 (out of order!) */
  150         { B57600,       CLK57600, },    /* 0xd */
  151         { B115200,      CLK110, },      /* 0x1 (dupe!, 110 baud on "si") */
  152         { -1,           -1 },
  153 };
  154 
  155 
  156 #ifdef POLL
  157 static int si_pollrate;                 /* in addition to irq */
  158 static int si_realpoll = 0;             /* poll HW on timer */
  159 
  160 SYSCTL_INT(_machdep, OID_AUTO, si_pollrate, CTLFLAG_RW, &si_pollrate, 0, "");
  161 SYSCTL_INT(_machdep, OID_AUTO, si_realpoll, CTLFLAG_RW, &si_realpoll, 0, "");
  162 
  163 static int init_finished = 0;
  164 static void si_poll(void *);
  165 #endif
  166 
  167 /*
  168  * Array of adapter types and the corresponding RAM size. The order of
  169  * entries here MUST match the ordinal of the adapter type.
  170  */
  171 static const char *si_type[] = {
  172         "EMPTY",
  173         "SIHOST",
  174         "SIMCA",                /* FreeBSD does not support Microchannel */
  175         "SIHOST2",
  176         "SIEISA",
  177         "SIPCI",
  178         "SXPCI",
  179         "SXISA",
  180 };
  181 
  182 #ifdef SI_DEBUG
  183 static char *
  184 si_cmdname(int cmd)
  185 {
  186         static char buf[32];
  187 
  188         switch (cmd) {
  189         case IDLE_OPEN:         return("IDLE_OPEN");
  190         case LOPEN:             return("LOPEN");
  191         case MOPEN:             return("MOPEN");
  192         case MPEND:             return("MPEND");
  193         case CONFIG:            return("CONFIG");
  194         case CLOSE:             return("CLOSE");
  195         case SBREAK:            return("SBREAK");
  196         case EBREAK:            return("EBREAK");
  197         case IDLE_CLOSE:        return("IDLE_CLOSE");
  198         case IDLE_BREAK:        return("IDLE_BREAK");
  199         case FCLOSE:            return("FCLOSE");
  200         case RESUME:            return("RESUME");
  201         case WFLUSH:            return("WFLUSH");
  202         case RFLUSH:            return("RFLUSH");
  203         default:
  204                 sprintf(buf, "?cmd:0x%x?", cmd);
  205                 return (buf);
  206         }
  207 }
  208 #endif
  209 
  210 /*
  211  * We have to make an 8 bit version of bcopy, since some cards can't
  212  * deal with 32 bit I/O
  213  */
  214 static void __inline
  215 si_bcopy(const void *src, void *dst, size_t len)
  216 {
  217         u_char *d;
  218         const u_char *s;
  219 
  220         d = dst;
  221         s = src;
  222         while (len--)
  223                 *d++ = *s++;
  224 }
  225 static void __inline
  226 si_vbcopy(const volatile void *src, void *dst, size_t len)
  227 {
  228         u_char *d;
  229         const volatile u_char *s;
  230 
  231         d = dst;
  232         s = src;
  233         while (len--)
  234                 *d++ = *s++;
  235 }
  236 static void __inline
  237 si_bcopyv(const void *src, volatile void *dst, size_t len)
  238 {
  239         volatile u_char *d;
  240         const u_char *s;
  241 
  242         d = dst;
  243         s = src;
  244         while (len--)
  245                 *d++ = *s++;
  246 }
  247 
  248 static int
  249 si_speedtab(int speed, struct si_speedtab *table)
  250 {
  251         for ( ; table->sp_speed != -1; table++)
  252                 if (table->sp_speed == speed)
  253                         return (table->sp_code);
  254         return (-1);
  255 }
  256 
  257 
  258 static struct ttydevsw si_tty_class = {
  259         .tsw_flags      = TF_INITLOCK|TF_CALLOUT,
  260         .tsw_open       = siopen,
  261         .tsw_close      = siclose,
  262         .tsw_outwakeup  = si_start,
  263         /* .tsw_stop = si_stop */
  264         .tsw_ioctl      = siioctl,
  265         .tsw_param      = siparam,
  266         .tsw_modem      = simodem,
  267 };
  268 
  269 
  270 /*
  271  * Attach the device.  Initialize the card.
  272  */
  273 int
  274 siattach(device_t dev)
  275 {
  276         int unit;
  277         struct si_softc *sc;
  278         struct si_port *pp;
  279         struct tty *tp;
  280         volatile struct si_channel *ccbp;
  281         volatile struct si_reg *regp;
  282         volatile caddr_t maddr;
  283         struct si_module *modp;
  284         int nmodule, nport, x, y;
  285         int uart_type;
  286 
  287         sc = device_get_softc(dev);
  288         unit = device_get_unit(dev);
  289 
  290         sc->sc_typename = si_type[sc->sc_type];
  291         if (si_numunits < unit + 1)
  292                 si_numunits = unit + 1;
  293 
  294         DPRINT((0, DBG_AUTOBOOT, "si%d: siattach\n", unit));
  295 
  296 #ifdef POLL
  297         if (si_pollrate == 0) {
  298                 si_pollrate = POLLHZ;           /* in addition to irq */
  299 #ifdef REALPOLL
  300                 si_realpoll = 1;                /* scan always */
  301 #endif
  302         }
  303 #endif
  304 
  305         DPRINT((0, DBG_AUTOBOOT, "si%d: type: %s paddr: %x maddr: %x\n", unit,
  306                 sc->sc_typename, sc->sc_paddr, sc->sc_maddr));
  307 
  308         sc->sc_ports = NULL;                    /* mark as uninitialised */
  309 
  310         maddr = sc->sc_maddr;
  311 
  312         /* Stop the CPU first so it won't stomp around while we load */
  313 
  314         switch (sc->sc_type) {
  315 #ifdef DEV_EISA
  316                 case SIEISA:
  317                         outb(sc->sc_iobase + 2, sc->sc_irq << 4);
  318 #endif
  319                 break;
  320                 case SIPCI:
  321                         *(maddr+SIPCIRESET) = 0;
  322                 break;
  323                 case SIJETPCI: /* fall through to JET ISA */
  324                 case SIJETISA:
  325                         *(maddr+SIJETCONFIG) = 0;
  326                 break;
  327                 case SIHOST2:
  328                         *(maddr+SIPLRESET) = 0;
  329                 break;
  330                 case SIHOST:
  331                         *(maddr+SIRESET) = 0;
  332                 break;
  333                 default: /* this should never happen */
  334                         printf("si%d: unsupported configuration\n", unit);
  335                         return EINVAL;
  336                 break;
  337         }
  338 
  339         /* OK, now lets download the download code */
  340 
  341         if (SI_ISJET(sc->sc_type)) {
  342                 DPRINT((0, DBG_DOWNLOAD, "si%d: jet_download: nbytes %d\n",
  343                         unit, si3_t225_dsize));
  344                 si_bcopy(si3_t225_download, maddr + si3_t225_downloadaddr,
  345                         si3_t225_dsize);
  346                 DPRINT((0, DBG_DOWNLOAD,
  347                         "si%d: jet_bootstrap: nbytes %d -> %x\n",
  348                         unit, si3_t225_bsize, si3_t225_bootloadaddr));
  349                 si_bcopy(si3_t225_bootstrap, maddr + si3_t225_bootloadaddr,
  350                         si3_t225_bsize);
  351         } else {
  352                 DPRINT((0, DBG_DOWNLOAD, "si%d: si_download: nbytes %d\n",
  353                         unit, si2_z280_dsize));
  354                 si_bcopy(si2_z280_download, maddr + si2_z280_downloadaddr,
  355                         si2_z280_dsize);
  356         }
  357 
  358         /* Now start the CPU */
  359 
  360         switch (sc->sc_type) {
  361 #ifdef DEV_EISA
  362         case SIEISA:
  363                 /* modify the download code to tell it that it's on an EISA */
  364                 *(maddr + 0x42) = 1;
  365                 outb(sc->sc_iobase + 2, (sc->sc_irq << 4) | 4);
  366                 (void)inb(sc->sc_iobase + 3); /* reset interrupt */
  367                 break;
  368 #endif
  369         case SIPCI:
  370                 /* modify the download code to tell it that it's on a PCI */
  371                 *(maddr+0x42) = 1;
  372                 *(maddr+SIPCIRESET) = 1;
  373                 *(maddr+SIPCIINTCL) = 0;
  374                 break;
  375         case SIJETPCI:
  376                 *(maddr+SIJETRESET) = 0;
  377                 *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN;
  378                 break;
  379         case SIJETISA:
  380                 *(maddr+SIJETRESET) = 0;
  381                 switch (sc->sc_irq) {
  382                 case 9:
  383                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0x90;
  384                         break;
  385                 case 10:
  386                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xa0;
  387                         break;
  388                 case 11:
  389                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xb0;
  390                         break;
  391                 case 12:
  392                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xc0;
  393                         break;
  394                 case 15:
  395                         *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xf0;
  396                         break;
  397                 }
  398                 break;
  399         case SIHOST:
  400                 *(maddr+SIRESET_CL) = 0;
  401                 *(maddr+SIINTCL_CL) = 0;
  402                 break;
  403         case SIHOST2:
  404                 *(maddr+SIPLRESET) = 0x10;
  405                 switch (sc->sc_irq) {
  406                 case 11:
  407                         *(maddr+SIPLIRQ11) = 0x10;
  408                         break;
  409                 case 12:
  410                         *(maddr+SIPLIRQ12) = 0x10;
  411                         break;
  412                 case 15:
  413                         *(maddr+SIPLIRQ15) = 0x10;
  414                         break;
  415                 }
  416                 *(maddr+SIPLIRQCLR) = 0x10;
  417                 break;
  418         default: /* this should _REALLY_ never happen */
  419                 printf("si%d: Uh, it was supported a second ago...\n", unit);
  420                 return EINVAL;
  421         }
  422 
  423         DELAY(1000000);                 /* wait around for a second */
  424 
  425         regp = (struct si_reg *)maddr;
  426         y = 0;
  427                                         /* wait max of 5 sec for init OK */
  428         while (regp->initstat == 0 && y++ < 10) {
  429                 DELAY(500000);
  430         }
  431         switch (regp->initstat) {
  432         case 0:
  433                 printf("si%d: startup timeout - aborting\n", unit);
  434                 sc->sc_type = SIEMPTY;
  435                 return EINVAL;
  436         case 1:
  437                 if (SI_ISJET(sc->sc_type)) {
  438                         /* set throttle to 100 times per second */
  439                         regp->int_count = JET_INT_COUNT;
  440                         /* rx_intr_count is a NOP in Jet */
  441                 } else {
  442                         /* set throttle to 125 times per second */
  443                         regp->int_count = INT_COUNT;
  444                         /* rx intr max of 25 times per second */
  445                         regp->rx_int_count = RXINT_COUNT;
  446                 }
  447                 regp->int_pending = 0;          /* no intr pending */
  448                 regp->int_scounter = 0; /* reset counter */
  449                 break;
  450         case 0xff:
  451                 /*
  452                  * No modules found, so give up on this one.
  453                  */
  454                 printf("si%d: %s - no ports found\n", unit,
  455                         si_type[sc->sc_type]);
  456                 return 0;
  457         default:
  458                 printf("si%d: download code version error - initstat %x\n",
  459                         unit, regp->initstat);
  460                 return EINVAL;
  461         }
  462 
  463         /*
  464          * First time around the ports just count them in order
  465          * to allocate some memory.
  466          */
  467         nport = 0;
  468         modp = (struct si_module *)(maddr + 0x80);
  469         for (;;) {
  470                 DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp));
  471                 switch (modp->sm_type) {
  472                 case TA4:
  473                         DPRINT((0, DBG_DOWNLOAD,
  474                                 "si%d: Found old TA4 module, 4 ports\n",
  475                                 unit));
  476                         x = 4;
  477                         break;
  478                 case TA8:
  479                         DPRINT((0, DBG_DOWNLOAD,
  480                                 "si%d: Found old TA8 module, 8 ports\n",
  481                                 unit));
  482                         x = 8;
  483                         break;
  484                 case TA4_ASIC:
  485                         DPRINT((0, DBG_DOWNLOAD,
  486                                 "si%d: Found ASIC TA4 module, 4 ports\n",
  487                                 unit));
  488                         x = 4;
  489                         break;
  490                 case TA8_ASIC:
  491                         DPRINT((0, DBG_DOWNLOAD,
  492                                 "si%d: Found ASIC TA8 module, 8 ports\n",
  493                                 unit));
  494                         x = 8;
  495                         break;
  496                 case MTA:
  497                         DPRINT((0, DBG_DOWNLOAD,
  498                                 "si%d: Found CD1400 module, 8 ports\n",
  499                                 unit));
  500                         x = 8;
  501                         break;
  502                 case SXDC:
  503                         DPRINT((0, DBG_DOWNLOAD,
  504                                 "si%d: Found SXDC module, 8 ports\n",
  505                                 unit));
  506                         x = 8;
  507                         break;
  508                 default:
  509                         printf("si%d: unknown module type %d\n",
  510                                 unit, modp->sm_type);
  511                         goto try_next;
  512                 }
  513 
  514                 /* this was limited in firmware and is also a driver issue */
  515                 if ((nport + x) > SI_MAXPORTPERCARD) {
  516                         printf("si%d: extra ports ignored\n", unit);
  517                         goto try_next;
  518                 }
  519 
  520                 nport += x;
  521                 si_Nports += x;
  522                 si_Nmodules++;
  523 
  524 try_next:
  525                 if (modp->sm_next == 0)
  526                         break;
  527                 modp = (struct si_module *)
  528                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
  529         }
  530         sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport,
  531                 M_DEVBUF, M_NOWAIT | M_ZERO);
  532         if (sc->sc_ports == 0) {
  533                 printf("si%d: fail to malloc memory for port structs\n",
  534                         unit);
  535                 return EINVAL;
  536         }
  537         sc->sc_nport = nport;
  538 
  539         /*
  540          * Scan round the ports again, this time initialising.
  541          */
  542         pp = sc->sc_ports;
  543         nmodule = 0;
  544         modp = (struct si_module *)(maddr + 0x80);
  545         uart_type = 1000;       /* arbitary, > uchar_max */
  546         for (;;) {
  547                 switch (modp->sm_type) {
  548                 case TA4:
  549                         nport = 4;
  550                         break;
  551                 case TA8:
  552                         nport = 8;
  553                         break;
  554                 case TA4_ASIC:
  555                         nport = 4;
  556                         break;
  557                 case TA8_ASIC:
  558                         nport = 8;
  559                         break;
  560                 case MTA:
  561                         nport = 8;
  562                         break;
  563                 case SXDC:
  564                         nport = 8;
  565                         break;
  566                 default:
  567                         goto try_next2;
  568                 }
  569                 nmodule++;
  570                 ccbp = (struct si_channel *)((char *)modp + 0x100);
  571                 if (uart_type == 1000)
  572                         uart_type = ccbp->type;
  573                 else if (uart_type != ccbp->type)
  574                         printf("si%d: Warning: module %d mismatch! (%d%s != %d%s)\n",
  575                             unit, nmodule,
  576                             ccbp->type, si_modulename(sc->sc_type, ccbp->type),
  577                             uart_type, si_modulename(sc->sc_type, uart_type));
  578 
  579                 for (x = 0; x < nport; x++, pp++, ccbp++) {
  580                         pp->sp_ccb = ccbp;      /* save the address */
  581                         pp->sp_pend = IDLE_CLOSE;
  582                         pp->sp_state = 0;       /* internal flag */
  583 #ifdef SI_DEBUG
  584                         sprintf(pp->sp_name, "si%r%r", unit,
  585                             (int)(pp - sc->sc_ports));
  586 #endif
  587                         tp = pp->sp_tty = tty_alloc_mutex(&si_tty_class, pp, &Giant);
  588                         tty_makedev(tp, NULL, "A%r%r", unit, (int)(pp - sc->sc_ports));
  589                 }
  590 try_next2:
  591                 if (modp->sm_next == 0) {
  592                         printf("si%d: card: %s, ports: %d, modules: %d, type: %d%s\n",
  593                                 unit,
  594                                 sc->sc_typename,
  595                                 sc->sc_nport,
  596                                 nmodule,
  597                                 uart_type,
  598                                 si_modulename(sc->sc_type, uart_type));
  599                         break;
  600                 }
  601                 modp = (struct si_module *)
  602                         (maddr + (unsigned)(modp->sm_next & 0x7fff));
  603         }
  604 
  605         if (unit == 0)
  606                 make_dev(&si_Scdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
  607                     "si_control");
  608         device_printf(dev,
  609             "WARNING: This driver is deprecated and will be removed.\n");
  610         return (0);
  611 }
  612 
  613 static  int
  614 siopen(struct tty *tp)
  615 {
  616 
  617         DPRINT((0, DBG_ENTRY|DBG_OPEN, "siopen()\n"));
  618         mtx_assert(&Giant, MA_OWNED);
  619 #ifdef  POLL
  620         /*
  621          * We've now got a device, so start the poller.
  622          */
  623         if (init_finished == 0) {
  624                 timeout(si_poll, (caddr_t)0L, si_pollrate);
  625                 init_finished = 1;
  626         }
  627 #endif
  628         DPRINT((0, DBG_EXIT|DBG_OPEN, "siopen() finished\n"));
  629         return(0);
  630 }
  631 
  632 static void
  633 siclose(struct tty *tp)
  634 {
  635         struct si_port *pp;
  636 
  637         DPRINT((0, DBG_ENTRY|DBG_CLOSE, "siclose()\n"));
  638         mtx_assert(&Giant, MA_OWNED);
  639         pp = tty_softc(tp);
  640         (void) si_command(pp, FCLOSE, SI_WAIT);
  641         DPRINT((0, DBG_EXIT|DBG_CLOSE, "siclose() finished\n"));
  642 }
  643 
  644 static int
  645 siioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
  646 {
  647         struct si_port *pp;
  648 
  649         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "siioctl(0x%lx,0x%x)\n", cmd, data));
  650         mtx_assert(&Giant, MA_OWNED);
  651         pp = tty_softc(tp);
  652         switch (cmd) {
  653         case TIOCSBRK:
  654                 si_command(pp, SBREAK, SI_WAIT);
  655                 return (0);
  656         case TIOCCBRK:
  657                 si_command(pp, EBREAK, SI_WAIT);
  658                 return (0);
  659         }
  660         return (ENOIOCTL);      /* Let the common tty ioctl handler do it */
  661 }
  662 
  663 /*
  664  * Handle the Specialix ioctls on the control dev.
  665  */
  666 static int
  667 si_Sioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  668 {
  669         struct si_softc *xsc;
  670         struct si_port *xpp;
  671         volatile struct si_reg *regp;
  672         struct si_tcsi *dp;
  673         struct si_pstat *sps;
  674         int *ip, error = 0;
  675         int oldspl;
  676         int card, port;
  677 
  678         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%s,0x%lx,0x%x)\n",
  679                 devtoname(dev), cmd, data));
  680         mtx_assert(&Giant, MA_OWNED);
  681 
  682 #if 1
  683         DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT));
  684         DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB));
  685 #endif
  686 
  687         oldspl = spltty();      /* better safe than sorry */
  688 
  689         ip = (int *)data;
  690 
  691 #define SUCHECK if ((error = priv_check(td, PRIV_DRIVER))) goto out
  692 
  693         switch (cmd) {
  694         case TCSIPORTS:
  695                 *ip = si_Nports;
  696                 goto out;
  697         case TCSIMODULES:
  698                 *ip = si_Nmodules;
  699                 goto out;
  700         case TCSISDBG_ALL:
  701                 SUCHECK;
  702                 si_debug = *ip;
  703                 goto out;
  704         case TCSIGDBG_ALL:
  705                 *ip = si_debug;
  706                 goto out;
  707         default:
  708                 /*
  709                  * Check that a controller for this port exists
  710                  */
  711 
  712                 /* may also be a struct si_pstat, a superset of si_tcsi */
  713 
  714                 dp = (struct si_tcsi *)data;
  715                 sps = (struct si_pstat *)data;
  716                 card = dp->tc_card;
  717                 xsc = devclass_get_softc(si_devclass, card);    /* check.. */
  718                 if (xsc == NULL || xsc->sc_type == SIEMPTY) {
  719                         error = ENOENT;
  720                         goto out;
  721                 }
  722                 /*
  723                  * And check that a port exists
  724                  */
  725                 port = dp->tc_port;
  726                 if (port < 0 || port >= xsc->sc_nport) {
  727                         error = ENOENT;
  728                         goto out;
  729                 }
  730                 xpp = xsc->sc_ports + port;
  731                 regp = (struct si_reg *)xsc->sc_maddr;
  732         }
  733 
  734         switch (cmd) {
  735         case TCSIDEBUG:
  736 #ifdef  SI_DEBUG
  737                 SUCHECK;
  738                 if (xpp->sp_debug)
  739                         xpp->sp_debug = 0;
  740                 else {
  741                         xpp->sp_debug = DBG_ALL;
  742                         DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",
  743                                 (xpp->sp_debug&DBG_ALL)?"ON":"OFF"));
  744                 }
  745                 break;
  746 #else
  747                 error = ENODEV;
  748                 goto out;
  749 #endif
  750         case TCSISDBG_LEVEL:
  751         case TCSIGDBG_LEVEL:
  752 #ifdef  SI_DEBUG
  753                 if (cmd == TCSIGDBG_LEVEL) {
  754                         dp->tc_dbglvl = xpp->sp_debug;
  755                 } else {
  756                         SUCHECK;
  757                         xpp->sp_debug = dp->tc_dbglvl;
  758                 }
  759                 break;
  760 #else
  761                 error = ENODEV;
  762                 goto out;
  763 #endif
  764         case TCSIGRXIT:
  765                 dp->tc_int = regp->rx_int_count;
  766                 break;
  767         case TCSIRXIT:
  768                 SUCHECK;
  769                 regp->rx_int_count = dp->tc_int;
  770                 break;
  771         case TCSIGIT:
  772                 dp->tc_int = regp->int_count;
  773                 break;
  774         case TCSIIT:
  775                 SUCHECK;
  776                 regp->int_count = dp->tc_int;
  777                 break;
  778         case TCSISTATE:
  779                 dp->tc_int = xpp->sp_ccb->hi_ip;
  780                 break;
  781         /* these next three use a different structure */
  782         case TCSI_PORT:
  783                 SUCHECK;
  784                 si_bcopy(xpp, &sps->tc_siport, sizeof(sps->tc_siport));
  785                 break;
  786         case TCSI_CCB:
  787                 SUCHECK;
  788                 si_vbcopy(xpp->sp_ccb, &sps->tc_ccb, sizeof(sps->tc_ccb));
  789                 break;
  790         default:
  791                 error = EINVAL;
  792                 goto out;
  793         }
  794 out:
  795         splx(oldspl);
  796         return(error);          /* success */
  797 }
  798 
  799 /*
  800  *      siparam()       : Configure line params
  801  *      called at spltty();
  802  *      this may sleep, does not flush, nor wait for drain, nor block writes
  803  *      caller must arrange this if it's important..
  804  */
  805 static int
  806 siparam(struct tty *tp, struct termios *t)
  807 {
  808         struct si_port *pp = tty_softc(tp);
  809         volatile struct si_channel *ccbp;
  810         int oldspl, cflag, iflag, oflag, lflag;
  811         int error = 0;          /* shutup gcc */
  812         int ispeed = 0;         /* shutup gcc */
  813         int ospeed = 0;         /* shutup gcc */
  814         BYTE val;
  815 
  816         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
  817         mtx_assert(&Giant, MA_OWNED);
  818         cflag = t->c_cflag;
  819         iflag = t->c_iflag;
  820         oflag = t->c_oflag;
  821         lflag = t->c_lflag;
  822         DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",
  823                 oflag, cflag, iflag, lflag));
  824 
  825         /* XXX - if Jet host and SXDC module, use extended baud rates */
  826 
  827         /* if not hung up.. */
  828         if (t->c_ospeed != 0) {
  829                 /* translate baud rate to firmware values */
  830                 ospeed = si_speedtab(t->c_ospeed, bdrates);
  831                 ispeed = t->c_ispeed ?
  832                          si_speedtab(t->c_ispeed, bdrates) : ospeed;
  833                 /* enforce legit baud rate */
  834                 if (ospeed < 0 || ispeed < 0)
  835                         return (EINVAL);
  836         }
  837 
  838         oldspl = spltty();
  839 
  840         ccbp = pp->sp_ccb;
  841 
  842         /* ========== set hi_break ========== */
  843         val = 0;
  844         if (iflag & IGNBRK)             /* Breaks */
  845                 val |= BR_IGN;
  846         if (iflag & BRKINT)             /* Interrupt on break? */
  847                 val |= BR_INT;
  848         if (iflag & PARMRK)             /* Parity mark? */
  849                 val |= BR_PARMRK;
  850         if (iflag & IGNPAR)             /* Ignore chars with parity errors? */
  851                 val |= BR_PARIGN;
  852         ccbp->hi_break = val;
  853 
  854         /* ========== set hi_csr ========== */
  855         /* if not hung up.. */
  856         if (t->c_ospeed != 0) {
  857                 /* Set I/O speeds */
  858                  val = (ispeed << 4) | ospeed;
  859         }
  860         ccbp->hi_csr = val;
  861 
  862         /* ========== set hi_mr2 ========== */
  863         val = 0;
  864         if (cflag & CSTOPB)                             /* Stop bits */ 
  865                 val |= MR2_2_STOP;
  866         else
  867                 val |= MR2_1_STOP;
  868 
  869         /*
  870          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
  871          * a DCE, hence the reverse sense of RTS and CTS
  872          */
  873         /* Output Flow - RTS must be raised before data can be sent */
  874         if (cflag & CCTS_OFLOW)
  875                 val |= MR2_RTSCONT;
  876 
  877         ccbp->hi_mr2 = val;
  878 
  879         /* ========== set hi_mr1 ========== */
  880         val = 0;
  881         if (!(cflag & PARENB))                          /* Parity */
  882                 val |= MR1_NONE;
  883         else
  884                 val |= MR1_WITH;
  885         if (cflag & PARODD)
  886                 val |= MR1_ODD;
  887 
  888         if ((cflag & CS8) == CS8)                       /* 8 data bits? */
  889                 val |= MR1_8_BITS;
  890         else if ((cflag & CS7) == CS7)                  /* 7 data bits? */
  891                 val |= MR1_7_BITS;
  892         else if ((cflag & CS6) == CS6)                  /* 6 data bits? */
  893                 val |= MR1_6_BITS;
  894         else                                            /* Must be 5 */
  895                 val |= MR1_5_BITS;
  896 
  897         /*
  898          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
  899          * a DCE, hence the reverse sense of RTS and CTS
  900          */
  901         /* Input Flow - CTS is raised when port is ready to receive data */
  902         if (cflag & CRTS_IFLOW)
  903                 val |= MR1_CTSCONT;
  904 
  905         ccbp->hi_mr1 = val;
  906 
  907         /* ========== set hi_mask ========== */
  908         val = 0xff;
  909         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
  910                 val &= 0xFF;
  911         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
  912                 val &= 0x7F;
  913         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
  914                 val &= 0x3F;
  915         } else {                                        /* Must be 5 */
  916                 val &= 0x1F;
  917         }
  918         if (iflag & ISTRIP)
  919                 val &= 0x7F;
  920 
  921         ccbp->hi_mask = val;
  922 
  923         /* ========== set hi_prtcl ========== */
  924         val = SP_DCEN;          /* Monitor DCD always, or TIOCMGET misses it */
  925         if (iflag & IXANY)
  926                 val |= SP_TANY;
  927         if (iflag & IXON)
  928                 val |= SP_TXEN;
  929         if (iflag & IXOFF)
  930                 val |= SP_RXEN;
  931         if (iflag & INPCK)
  932                 val |= SP_PAEN;
  933 
  934         ccbp->hi_prtcl = val;
  935 
  936 
  937         /* ========== set hi_{rx|tx}{on|off} ========== */
  938         /* XXX: the card TOTALLY shields us from the flow control... */
  939         ccbp->hi_txon = t->c_cc[VSTART];
  940         ccbp->hi_txoff = t->c_cc[VSTOP];
  941 
  942         ccbp->hi_rxon = t->c_cc[VSTART];
  943         ccbp->hi_rxoff = t->c_cc[VSTOP];
  944 
  945         /* ========== send settings to the card ========== */
  946         /* potential sleep here */
  947         if (ccbp->hi_stat == IDLE_CLOSE)                /* Not yet open */
  948                 si_command(pp, LOPEN, SI_WAIT);         /* open it */
  949         else
  950                 si_command(pp, CONFIG, SI_WAIT);        /* change params */
  951 
  952         /* ========== set DTR etc ========== */
  953         /* Hangup if ospeed == 0 */
  954         if (t->c_ospeed == 0) {
  955                 (void) simodem(tp, 0, SER_DTR | SER_RTS);
  956         } else {
  957                 /*
  958                  * If the previous speed was 0, may need to re-enable
  959                  * the modem signals
  960                  */
  961                 (void) simodem(tp, SER_DTR | SER_RTS, 0);
  962         }
  963 
  964         DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x HI_CSR %x\n",
  965                 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break, ccbp->hi_csr));
  966 
  967         splx(oldspl);
  968         return(error);
  969 }
  970 
  971 /*
  972  * Set/Get state of modem control lines.
  973  * Due to DCE-like behaviour of the adapter, some signals need translation:
  974  *      TIOCM_DTR       DSR
  975  *      TIOCM_RTS       CTS
  976  */
  977 static int
  978 simodem(struct tty *tp, int sigon, int sigoff)
  979 {
  980         struct si_port *pp;
  981         volatile struct si_channel *ccbp;
  982         int x;
  983 
  984         pp = tty_softc(tp);
  985         DPRINT((pp, DBG_ENTRY|DBG_MODEM, "simodem(%x,%x)\n", sigon, sigoff));
  986         mtx_assert(&Giant, MA_OWNED);
  987         ccbp = pp->sp_ccb;              /* Find channel address */
  988         if (sigon == 0 && sigoff == 0) {
  989                 x = ccbp->hi_ip;
  990                 /*
  991                  * XXX: not sure this is correct, should it be CTS&DSR ?
  992                  * XXX: or do we (just) miss CTS & DSR ?
  993                  */
  994                 if (x & IP_DCD)         sigon |= SER_DCD;
  995                 if (x & IP_DTR)         sigon |= SER_DTR;
  996                 if (x & IP_RTS)         sigon |= SER_RTS;
  997                 if (x & IP_RI)          sigon |= SER_RI;
  998                 return (sigon);
  999         }
 1000 
 1001         x = ccbp->hi_op;
 1002         if (sigon & SER_DTR)
 1003                 x |= OP_DSR;
 1004         if (sigoff & SER_DTR)
 1005                 x &= ~OP_DSR;
 1006         if (sigon & SER_RTS)
 1007                 x |= OP_CTS;
 1008         if (sigoff & SER_RTS)
 1009                 x &= ~OP_CTS;
 1010         ccbp->hi_op = x;
 1011         return 0;
 1012 }
 1013 
 1014 /*
 1015  * Handle change of modem state
 1016  */
 1017 static void
 1018 si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip)
 1019 {
 1020                                                         /* if a modem dev */
 1021         mtx_assert(&Giant, MA_OWNED);
 1022         if (hi_ip & IP_DCD) {
 1023                 if (!(pp->sp_last_hi_ip & IP_DCD)) {
 1024                         DPRINT((pp, DBG_INTR, "modem carr on%d\n"));
 1025                         (void)ttydisc_modem(tp, 1);
 1026                 }
 1027         } else {
 1028                 if (pp->sp_last_hi_ip & IP_DCD) {
 1029                         DPRINT((pp, DBG_INTR, "modem carr off\n"));
 1030 #if 0   /* XXX mpsafetty ttyld_modem used to tell us to shutdown the port or not */
 1031                         if (ttydisc_modem(tp, 0))
 1032                                 (void) simodem(tp, 0, SER_DTR | SER_RTS);
 1033 #else
 1034                         ttydisc_modem(tp, 0);
 1035 #endif
 1036                 }
 1037         }
 1038         pp->sp_last_hi_ip = hi_ip;
 1039 
 1040 }
 1041 
 1042 /*
 1043  * Poller to catch missed interrupts.
 1044  *
 1045  * Note that the SYSV Specialix drivers poll at 100 times per second to get
 1046  * better response.  We could really use a "periodic" version timeout(). :-)
 1047  */
 1048 #ifdef POLL
 1049 static void
 1050 si_poll(void *nothing)
 1051 {
 1052         struct si_softc *sc;
 1053         int i;
 1054         volatile struct si_reg *regp;
 1055         struct si_port *pp;
 1056         int lost, oldspl, port;
 1057 
 1058         DPRINT((0, DBG_POLL, "si_poll()\n"));
 1059         oldspl = spltty();
 1060         mtx_assert(&Giant, MA_OWNED);
 1061         lost = 0;
 1062         for (i = 0; i < si_numunits; i++) {
 1063                 sc = devclass_get_softc(si_devclass, i);
 1064                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1065                         continue;
 1066                 regp = (struct si_reg *)sc->sc_maddr;
 1067 
 1068                 /*
 1069                  * See if there has been a pending interrupt for 2 seconds
 1070                  * or so. The test (int_scounter >= 200) won't correspond
 1071                  * to 2 seconds if int_count gets changed.
 1072                  */
 1073                 if (regp->int_pending != 0) {
 1074                         if (regp->int_scounter >= 200 &&
 1075                             regp->initstat == 1) {
 1076                                 printf("si%d: lost intr\n", i);
 1077                                 lost++;
 1078                         }
 1079                 } else {
 1080                         regp->int_scounter = 0;
 1081                 }
 1082 
 1083                 /*
 1084                  * gripe about no input flow control..
 1085                  */
 1086                 pp = sc->sc_ports;
 1087                 for (port = 0; port < sc->sc_nport; pp++, port++) {
 1088                         if (pp->sp_delta_overflows > 0) {
 1089                                 printf("si%d: %d tty level buffer overflows\n",
 1090                                         i, pp->sp_delta_overflows);
 1091                                 pp->sp_delta_overflows = 0;
 1092                         }
 1093                 }
 1094         }
 1095         if (lost || si_realpoll)
 1096                 si_intr(NULL);  /* call intr with fake vector */
 1097         splx(oldspl);
 1098 
 1099         timeout(si_poll, (caddr_t)0L, si_pollrate);
 1100 }
 1101 #endif  /* ifdef POLL */
 1102 
 1103 /*
 1104  * The interrupt handler polls ALL ports on ALL adapters each time
 1105  * it is called.
 1106  */
 1107 
 1108 static BYTE si_rxbuf[SI_BUFFERSIZE];    /* input staging area */
 1109 static BYTE si_txbuf[SI_BUFFERSIZE];    /* output staging area */
 1110 
 1111 void
 1112 si_intr(void *arg)
 1113 {
 1114         struct si_softc *sc;
 1115         struct si_port *pp;
 1116         volatile struct si_channel *ccbp;
 1117         struct tty *tp;
 1118         volatile caddr_t maddr;
 1119         BYTE op, ip;
 1120         int x, card, port, n, i, isopen;
 1121         volatile BYTE *z;
 1122         BYTE c;
 1123 
 1124         sc = arg;
 1125         mtx_assert(&Giant, MA_OWNED);
 1126 
 1127         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "si_intr\n"));
 1128 
 1129         /*
 1130          * When we get an int we poll all the channels and do ALL pending
 1131          * work, not just the first one we find. This allows all cards to
 1132          * share the same vector.
 1133          *
 1134          * XXX - But if we're sharing the vector with something that's NOT
 1135          * a SI/XIO/SX card, we may be making more work for ourselves.
 1136          */
 1137         for (card = 0; card < si_numunits; card++) {
 1138                 sc = devclass_get_softc(si_devclass, card);
 1139                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1140                         continue;
 1141 
 1142                 /*
 1143                  * First, clear the interrupt
 1144                  */
 1145                 switch(sc->sc_type) {
 1146                 case SIHOST:
 1147                         maddr = sc->sc_maddr;
 1148                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1149                                                         /* flag nothing pending */
 1150                         *(maddr+SIINTCL) = 0x00;        /* Set IRQ clear */
 1151                         *(maddr+SIINTCL_CL) = 0x00;     /* Clear IRQ clear */
 1152                         break;
 1153                 case SIHOST2:
 1154                         maddr = sc->sc_maddr;
 1155                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1156                         *(maddr+SIPLIRQCLR) = 0x00;
 1157                         *(maddr+SIPLIRQCLR) = 0x10;
 1158                         break;
 1159                 case SIPCI:
 1160                         maddr = sc->sc_maddr;
 1161                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1162                         *(maddr+SIPCIINTCL) = 0x0;
 1163                         break;
 1164                 case SIJETPCI:  /* fall through to JETISA case */
 1165                 case SIJETISA:
 1166                         maddr = sc->sc_maddr;
 1167                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1168                         *(maddr+SIJETINTCL) = 0x0;
 1169                         break;
 1170 #ifdef DEV_EISA
 1171                 case SIEISA:
 1172                         maddr = sc->sc_maddr;
 1173                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1174                         (void)inb(sc->sc_iobase + 3);
 1175                         break;
 1176 #endif
 1177                 case SIEMPTY:
 1178                 default:
 1179                         continue;
 1180                 }
 1181                 ((volatile struct si_reg *)maddr)->int_scounter = 0;
 1182 
 1183                 /*
 1184                  * check each port
 1185                  */
 1186                 for (pp = sc->sc_ports, port = 0; port < sc->sc_nport;
 1187                      pp++, port++) {
 1188                         ccbp = pp->sp_ccb;
 1189                         tp = pp->sp_tty;
 1190                         tty_lock(tp);
 1191 
 1192                         /*
 1193                          * See if a command has completed ?
 1194                          */
 1195                         if (ccbp->hi_stat != pp->sp_pend) {
 1196                                 DPRINT((pp, DBG_INTR,
 1197                                         "si_intr hi_stat = %s, pend = %s\n",
 1198                                         si_cmdname(ccbp->hi_stat),
 1199                                         si_cmdname(pp->sp_pend)));
 1200                                 switch(pp->sp_pend) {
 1201                                 case LOPEN:
 1202                                 case MPEND:
 1203                                 case MOPEN:
 1204                                 case FCLOSE:
 1205                                 case CONFIG:
 1206                                 case SBREAK:
 1207                                 case EBREAK:
 1208                                         /* sleeping in si_command */
 1209                                         DPRINT((pp, DBG_INTR, "do wakeup\n"));
 1210                                         wakeup(&pp->sp_state);
 1211                                         break;
 1212                                 }
 1213                                 pp->sp_pend = ccbp->hi_stat;
 1214                         }
 1215 
 1216                         /*
 1217                          * Continue on if it's closed
 1218                          */
 1219                         if (ccbp->hi_stat == IDLE_CLOSE) {
 1220                                 tty_unlock(tp);
 1221                                 continue;
 1222                         }
 1223 
 1224                         /*
 1225                          * Do modem state change if not a local device
 1226                          */
 1227                         si_modem_state(pp, tp, ccbp->hi_ip);
 1228 
 1229                         /*
 1230                          * Check to see if we should 'receive' characters.
 1231                          */
 1232                         isopen = tty_opened(tp);
 1233 
 1234                         /*
 1235                          * Do input break processing
 1236                          */
 1237                         if (ccbp->hi_state & ST_BREAK) {
 1238                                 if (isopen)
 1239                                         ttydisc_rint(tp, 0, TRE_BREAK);
 1240                                 ccbp->hi_state &= ~ST_BREAK;   /* A Bit iffy this */
 1241                                 DPRINT((pp, DBG_INTR, "si_intr break\n"));
 1242                         }
 1243 
 1244                         /*
 1245                          * Do RX stuff - if not open then dump any characters.
 1246                          * XXX: This is VERY messy and needs to be cleaned up.
 1247                          *
 1248                          * XXX: can we leave data in the host adapter buffer
 1249                          * when the clists are full?  That may be dangerous
 1250                          * if the user cannot get an interrupt signal through.
 1251                          */
 1252 
 1253         more_rx:
 1254 
 1255                         if (!isopen) {
 1256                                 DPRINT((pp, DBG_INTR, "intr1: not open\n"));
 1257                                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1258                                 goto end_rx;
 1259                         }
 1260 
 1261 #if 0 /* XXXMPSAFETTY */
 1262                         /*
 1263                          * If the tty input buffers are blocked, stop emptying
 1264                          * the incoming buffers and let the auto flow control
 1265                          * assert..
 1266                          */
 1267                         if (tp->t_state & TS_TBLOCK)
 1268                                 goto end_rx;
 1269 #endif
 1270 
 1271                         /*
 1272                          * Process read characters if not skipped above
 1273                          */
 1274                         op = ccbp->hi_rxopos;
 1275                         ip = ccbp->hi_rxipos;
 1276                         c = ip - op;
 1277                         if (c == 0)
 1278                                 goto end_rx;
 1279 
 1280                         n = c & 0xff;
 1281                         if (n > 250)
 1282                                 n = 250;
 1283 
 1284                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 1285                                                 n, op, ip));
 1286 
 1287                         /*
 1288                          * Suck characters out of host card buffer into the
 1289                          * "input staging buffer" - so that we dont leave the
 1290                          * host card in limbo while we're possibly echoing
 1291                          * characters and possibly flushing input inside the
 1292                          * ldisc l_rint() routine.
 1293                          */
 1294                         if (n <= SI_BUFFERSIZE - op) {
 1295 
 1296                                 z = ccbp->hi_rxbuf + op;
 1297                                 si_vbcopy(z, si_rxbuf, n);
 1298 
 1299                                 op += n;
 1300                         } else {
 1301                                 x = SI_BUFFERSIZE - op;
 1302 
 1303                                 z = ccbp->hi_rxbuf + op;
 1304                                 si_vbcopy(z, si_rxbuf, x);
 1305 
 1306                                 z = ccbp->hi_rxbuf;
 1307                                 si_vbcopy(z, si_rxbuf + x, n - x);
 1308 
 1309                                 op += n;
 1310                         }
 1311 
 1312                         /* clear collected characters from buffer */
 1313                         ccbp->hi_rxopos = op;
 1314 
 1315                         /*
 1316                          * at this point...
 1317                          * n = number of chars placed in si_rxbuf
 1318                          */
 1319 
 1320                         if (0 && ttydisc_can_bypass(tp)) {
 1321 
 1322                                 i =  ttydisc_rint_bypass(tp, (char *)si_rxbuf, n);
 1323                                 if (i < n)
 1324                                         pp->sp_delta_overflows += (n - i);
 1325 
 1326                         } else {
 1327                                 /*
 1328                                  * It'd be nice to not have to go through the
 1329                                  * function call overhead for each char here.
 1330                                  * It'd be nice to block input it, saving a
 1331                                  * loop here and the call/return overhead.
 1332                                  */
 1333                                 for(x = 0; x < n; x++) {
 1334                                         i = si_rxbuf[x];
 1335                                         if (ttydisc_rint(tp, i, 0) == -1)
 1336                                                 pp->sp_delta_overflows++;
 1337                                 }
 1338                         }
 1339                         goto more_rx;   /* try for more until RXbuf is empty */
 1340 
 1341         end_rx:
 1342 
 1343                         ttydisc_rint_done(tp);
 1344 
 1345                         /*
 1346                          * Do TX stuff
 1347                          */
 1348                         si_start(tp);
 1349                         tty_unlock(tp);
 1350 
 1351                 } /* end of for (all ports on this controller) */
 1352         } /* end of for (all controllers) */
 1353 
 1354         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "end si_intr\n"));
 1355 }
 1356 
 1357 /*
 1358  * Nudge the transmitter...
 1359  *
 1360  * XXX: I inherited some funny code here.  It implies the host card only
 1361  * interrupts when the transmit buffer reaches the low-water-mark, and does
 1362  * not interrupt when it's actually hits empty.  In some cases, we have
 1363  * processes waiting for complete drain, and we need to simulate an interrupt
 1364  * about when we think the buffer is going to be empty (and retry if not).
 1365  * I really am not certain about this...  I *need* the hardware manuals.
 1366  */
 1367 static void
 1368 si_start(struct tty *tp)
 1369 {
 1370         struct si_port *pp;
 1371         volatile struct si_channel *ccbp;
 1372         BYTE ipos, count;
 1373 #if 0
 1374         int nchar;
 1375 #endif
 1376         int oldspl, n, amount;
 1377 
 1378         oldspl = spltty();
 1379         mtx_assert(&Giant, MA_OWNED);
 1380 
 1381         pp = tty_softc(tp);
 1382 
 1383         DPRINT((pp, DBG_ENTRY|DBG_START,
 1384                 "si_start(%x) sp_state %x\n",
 1385                 tp, pp->sp_state));
 1386 
 1387         ccbp = pp->sp_ccb;
 1388 
 1389         while ((count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos) < 255) {
 1390                 DPRINT((pp, DBG_START, "txbuf pend count %d\n", (BYTE)count));
 1391                 ipos = (unsigned int)ccbp->hi_txipos;
 1392                 if ((int)ccbp->hi_txopos <= ipos)
 1393                         amount = SI_BUFFERSIZE - ipos;
 1394                 else
 1395                         amount = 255 - count;
 1396                 DPRINT((pp, DBG_START, "spaceleft amount %d\n", amount));
 1397                 if (amount == 0)
 1398                         break;
 1399                 n = ttydisc_getc(tp, si_txbuf, amount);
 1400                 DPRINT((pp, DBG_START, "getc n=%d\n", n));
 1401                 if (n == 0)
 1402                         break;
 1403                 si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n);
 1404                 ccbp->hi_txipos += n;
 1405         }
 1406 
 1407 #if 0
 1408         /*
 1409          * See if there are any characters still to come.  If so, we can
 1410          * depend on si_start being called again.
 1411          *
 1412          * XXX the manual is vague on this.  It implies we get an interrupt
 1413          * when the transmit queue reaches the 25% low water mark, but NOT
 1414          * when it hits empty.
 1415          */
 1416         nchar = ttyoutq_getsize(&tp->t_outq) - ttyoutq_bytesleft(&tp->t_outq);
 1417         DPRINT((pp, DBG_START, "count %d, nchar %d\n",
 1418                 (BYTE)count, nchar));
 1419 
 1420         if (count != 0 && nchar == 0) {
 1421                 int time;
 1422 
 1423                 /* XXX lame. Ticks per character. used to be a table. */
 1424                 time = (tp->t_termios.c_ospeed + 9) / 10;
 1425 
 1426                 if (time > 0) {
 1427                         if (time < nchar)
 1428                                 time = nchar / time;
 1429                         else
 1430                                 time = 2;
 1431                 } else {
 1432                         DPRINT((pp, DBG_START,
 1433                                 "bad char time value! %d\n", time));
 1434                         time = hz/10;
 1435                 }
 1436 
 1437                 if ((pp->sp_state & SS_LSTART) != 0)
 1438                         untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
 1439                 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
 1440                 pp->sp_state |= SS_LSTART;
 1441                 pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time);
 1442         }
 1443 #endif
 1444 
 1445         splx(oldspl);
 1446         DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
 1447 }
 1448 
 1449 #if 0
 1450 /*
 1451  * This has to deal with two things...  cause wakeups while waiting for
 1452  * tty drains on last process exit, and call l_start at about the right
 1453  * time for protocols like ppp.
 1454  */
 1455 static void
 1456 si_lstart(void *arg)
 1457 {
 1458         struct si_port *pp = arg;
 1459         struct tty *tp;
 1460         int oldspl;
 1461 
 1462         DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n",
 1463                 pp, pp->sp_state));
 1464 
 1465         oldspl = spltty();
 1466         mtx_assert(&Giant, MA_OWNED);
 1467         pp->sp_state &= ~SS_LSTART;
 1468         tp = pp->sp_tty;
 1469 
 1470         si_start(tp);
 1471 
 1472         splx(oldspl);
 1473 }
 1474 #endif
 1475 
 1476 #if 0 /* XXX mpsafetty */
 1477 /*
 1478  * Stop output on a line. called at spltty();
 1479  */
 1480 static void
 1481 si_stop(struct tty *tp, int rw)
 1482 {
 1483         volatile struct si_channel *ccbp;
 1484         struct si_port *pp;
 1485 
 1486         mtx_assert(&Giant, MA_OWNED);
 1487         pp = tty_softc(tp);
 1488         ccbp = pp->sp_ccb;
 1489 
 1490         DPRINT((pp, DBG_ENTRY|DBG_STOP, "si_stop(%x,%x)\n", tp, rw));
 1491 
 1492         /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
 1493         if (rw & FWRITE) {
 1494                 /* what level are we meant to be flushing anyway? */
 1495                 if (tp->t_state & TS_BUSY) {
 1496                         si_command(pp, WFLUSH, SI_NOWAIT);
 1497                         tp->t_state &= ~TS_BUSY;
 1498                         ttwwakeup(tp);  /* Bruce???? */
 1499                 }
 1500         }
 1501 #if 1   /* XXX: this doesn't work right yet.. */
 1502         /* XXX: this may have been failing because we used to call l_rint()
 1503          * while we were looping based on these two counters. Now, we collect
 1504          * the data and then loop stuffing it into l_rint(), making this
 1505          * useless.  Should we cause this to blow away the staging buffer?
 1506          */
 1507         if (rw & FREAD) {
 1508                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1509         }
 1510 #endif
 1511 }
 1512 #endif
 1513 
 1514 /*
 1515  * Issue a command to the host card CPU.
 1516  *
 1517  * XXX This is all just so WRONG!.  Ed says we're not supposed to sleep
 1518  * here anyway.  We sort of get away with it for now by using Giant.
 1519  * Something better will have to be done.
 1520  * Linux does a busy spin here waiting for the 8-bit cpu to notice the
 1521  * posted command and respond to it.  I'm not sure I like that either.
 1522  */
 1523 static void
 1524 si_command(struct si_port *pp, int cmd, int waitflag)
 1525 {
 1526         int oldspl;
 1527         volatile struct si_channel *ccbp = pp->sp_ccb;
 1528         int x;
 1529         int err;
 1530 
 1531         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%s,%d): hi_stat %s, sp_pend: %s\n",
 1532                 pp, si_cmdname(cmd), waitflag, si_cmdname(ccbp->hi_stat),
 1533                 si_cmdname(pp->sp_pend)));
 1534 
 1535         oldspl = spltty();              /* Keep others out */
 1536         mtx_assert(&Giant, MA_OWNED);
 1537 
 1538         /* wait until it's finished what it was doing.. */
 1539         /* XXX: sits in IDLE_BREAK until something disturbs it or break
 1540          * is turned off. */
 1541         while((x = ccbp->hi_stat) != IDLE_OPEN &&
 1542                         x != IDLE_CLOSE &&
 1543                         x != IDLE_BREAK &&
 1544                         x != cmd) {
 1545                 DPRINT((pp, DBG_PARAM, "sicmd1 old cmd pending (going to tsleep): hi_stat (%s)\n", si_cmdname(ccbp->hi_stat)));
 1546                 err = tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd1", hz/4);
 1547                 if (err) {
 1548                         DPRINT((pp, DBG_PARAM, "sicmd1 timeout: hi_stat (%s)\n",
 1549                                 si_cmdname(ccbp->hi_stat)));
 1550                         /* This is very very bad.  The card has crashed. */
 1551                         /* XXX the driver breaks at this point */
 1552                         if (err == ETIMEDOUT)
 1553                                 DPRINT(("%s: tsleep1 timeout. hi_stat %s, sp_pend %s\n", pp->sp_name, si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1554                         splx(oldspl);
 1555                         return;
 1556                 }
 1557         }
 1558         /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */
 1559         DPRINT((pp, DBG_PARAM, "sicmd1 now in: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1560 
 1561         /* if there was a pending command, cause a state-change wakeup */
 1562         switch(pp->sp_pend) {
 1563         case LOPEN:
 1564         case MPEND:
 1565         case MOPEN:
 1566         case FCLOSE:
 1567         case CONFIG:
 1568         case SBREAK:
 1569         case EBREAK:
 1570                 DPRINT((pp, DBG_PARAM, "si_command: sp_pend %s, doing wakeup\n", si_cmdname(pp->sp_pend)));
 1571                 wakeup(&pp->sp_state);
 1572                 break;
 1573         default:
 1574                 break;
 1575         }
 1576 
 1577         pp->sp_pend = cmd;              /* New command pending */
 1578         ccbp->hi_stat = cmd;            /* Post it */
 1579         DPRINT((pp, DBG_PARAM, "sicmd now posted: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1580 
 1581         if (waitflag) {
 1582                 while((x = ccbp->hi_stat) != IDLE_OPEN &&
 1583                              x != IDLE_CLOSE &&
 1584                              x != IDLE_BREAK) {
 1585                         DPRINT((pp, DBG_PARAM, "sicmd2 now waiting: hi_stat (%s) sp_pend (%s) (going to tsleep)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1586                         err = tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd2", hz);
 1587                         if (err) {
 1588                                 DPRINT((pp, DBG_PARAM, "sicmd2 tsleep error: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1589                                 if (err == ETIMEDOUT) {
 1590                                         DPRINT(("%s: tsleep2 timeout. hi_stat %s, sp_pend %s\n", pp->sp_name, si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1591                                 }
 1592                                 break;
 1593                         }
 1594                 }
 1595         }
 1596         DPRINT((pp, DBG_PARAM, "sicmd2 finished: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1597         splx(oldspl);
 1598 }
 1599 
 1600 
 1601 #ifdef  SI_DEBUG
 1602 
 1603 void
 1604 si_dprintf(struct si_port *pp, int flags, const char *fmt, ...)
 1605 {
 1606         va_list ap;
 1607 
 1608         if ((pp == NULL && (si_debug&flags)) ||
 1609             (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
 1610                 if (pp != NULL)
 1611                         printf("%s: ", pp->sp_name);
 1612                 va_start(ap, fmt);
 1613                 vprintf(fmt, ap);
 1614                 va_end(ap);
 1615         }
 1616 }
 1617 
 1618 #endif  /* DEBUG */
 1619 
 1620 static char *
 1621 si_modulename(int host_type, int uart_type)
 1622 {
 1623         switch (host_type) {
 1624         /* Z280 based cards */
 1625 #ifdef DEV_EISA
 1626         case SIEISA:
 1627 #endif
 1628         case SIHOST2:
 1629         case SIHOST:
 1630         case SIPCI:
 1631                 switch (uart_type) {
 1632                 case 0:
 1633                         return(" (XIO)");
 1634                 case 1:
 1635                         return(" (SI)");
 1636                 }
 1637                 break;
 1638         /* T225 based hosts */
 1639         case SIJETPCI:
 1640         case SIJETISA:
 1641                 switch (uart_type) {
 1642                 case 0:
 1643                         return(" (SI)");
 1644                 case 40:
 1645                         return(" (XIO)");
 1646                 case 72:
 1647                         return(" (SXDC)");
 1648                 }
 1649                 break;
 1650         }
 1651         return("");
 1652 }

Cache object: 205648498cdf8ce1ab05896e670a16e2


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