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: releng/8.3/sys/dev/si/si.c 193018 2009-05-29 06:41:23Z ed $");
   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         return (0);
  609 }
  610 
  611 static  int
  612 siopen(struct tty *tp)
  613 {
  614 
  615         DPRINT((0, DBG_ENTRY|DBG_OPEN, "siopen()\n"));
  616         mtx_assert(&Giant, MA_OWNED);
  617 #ifdef  POLL
  618         /*
  619          * We've now got a device, so start the poller.
  620          */
  621         if (init_finished == 0) {
  622                 timeout(si_poll, (caddr_t)0L, si_pollrate);
  623                 init_finished = 1;
  624         }
  625 #endif
  626         DPRINT((0, DBG_EXIT|DBG_OPEN, "siopen() finished\n"));
  627         return(0);
  628 }
  629 
  630 static void
  631 siclose(struct tty *tp)
  632 {
  633         struct si_port *pp;
  634 
  635         DPRINT((0, DBG_ENTRY|DBG_CLOSE, "siclose()\n"));
  636         mtx_assert(&Giant, MA_OWNED);
  637         pp = tty_softc(tp);
  638         (void) si_command(pp, FCLOSE, SI_WAIT);
  639         DPRINT((0, DBG_EXIT|DBG_CLOSE, "siclose() finished\n"));
  640 }
  641 
  642 static int
  643 siioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
  644 {
  645         struct si_port *pp;
  646 
  647         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "siioctl(0x%lx,0x%x)\n", cmd, data));
  648         mtx_assert(&Giant, MA_OWNED);
  649         pp = tty_softc(tp);
  650         switch (cmd) {
  651         case TIOCSBRK:
  652                 si_command(pp, SBREAK, SI_WAIT);
  653                 return (0);
  654         case TIOCCBRK:
  655                 si_command(pp, EBREAK, SI_WAIT);
  656                 return (0);
  657         }
  658         return (ENOIOCTL);      /* Let the common tty ioctl handler do it */
  659 }
  660 
  661 /*
  662  * Handle the Specialix ioctls on the control dev.
  663  */
  664 static int
  665 si_Sioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  666 {
  667         struct si_softc *xsc;
  668         struct si_port *xpp;
  669         volatile struct si_reg *regp;
  670         struct si_tcsi *dp;
  671         struct si_pstat *sps;
  672         int *ip, error = 0;
  673         int oldspl;
  674         int card, port;
  675 
  676         DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%s,0x%lx,0x%x)\n",
  677                 devtoname(dev), cmd, data));
  678         mtx_assert(&Giant, MA_OWNED);
  679 
  680 #if 1
  681         DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT));
  682         DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB));
  683 #endif
  684 
  685         oldspl = spltty();      /* better safe than sorry */
  686 
  687         ip = (int *)data;
  688 
  689 #define SUCHECK if ((error = priv_check(td, PRIV_DRIVER))) goto out
  690 
  691         switch (cmd) {
  692         case TCSIPORTS:
  693                 *ip = si_Nports;
  694                 goto out;
  695         case TCSIMODULES:
  696                 *ip = si_Nmodules;
  697                 goto out;
  698         case TCSISDBG_ALL:
  699                 SUCHECK;
  700                 si_debug = *ip;
  701                 goto out;
  702         case TCSIGDBG_ALL:
  703                 *ip = si_debug;
  704                 goto out;
  705         default:
  706                 /*
  707                  * Check that a controller for this port exists
  708                  */
  709 
  710                 /* may also be a struct si_pstat, a superset of si_tcsi */
  711 
  712                 dp = (struct si_tcsi *)data;
  713                 sps = (struct si_pstat *)data;
  714                 card = dp->tc_card;
  715                 xsc = devclass_get_softc(si_devclass, card);    /* check.. */
  716                 if (xsc == NULL || xsc->sc_type == SIEMPTY) {
  717                         error = ENOENT;
  718                         goto out;
  719                 }
  720                 /*
  721                  * And check that a port exists
  722                  */
  723                 port = dp->tc_port;
  724                 if (port < 0 || port >= xsc->sc_nport) {
  725                         error = ENOENT;
  726                         goto out;
  727                 }
  728                 xpp = xsc->sc_ports + port;
  729                 regp = (struct si_reg *)xsc->sc_maddr;
  730         }
  731 
  732         switch (cmd) {
  733         case TCSIDEBUG:
  734 #ifdef  SI_DEBUG
  735                 SUCHECK;
  736                 if (xpp->sp_debug)
  737                         xpp->sp_debug = 0;
  738                 else {
  739                         xpp->sp_debug = DBG_ALL;
  740                         DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",
  741                                 (xpp->sp_debug&DBG_ALL)?"ON":"OFF"));
  742                 }
  743                 break;
  744 #else
  745                 error = ENODEV;
  746                 goto out;
  747 #endif
  748         case TCSISDBG_LEVEL:
  749         case TCSIGDBG_LEVEL:
  750 #ifdef  SI_DEBUG
  751                 if (cmd == TCSIGDBG_LEVEL) {
  752                         dp->tc_dbglvl = xpp->sp_debug;
  753                 } else {
  754                         SUCHECK;
  755                         xpp->sp_debug = dp->tc_dbglvl;
  756                 }
  757                 break;
  758 #else
  759                 error = ENODEV;
  760                 goto out;
  761 #endif
  762         case TCSIGRXIT:
  763                 dp->tc_int = regp->rx_int_count;
  764                 break;
  765         case TCSIRXIT:
  766                 SUCHECK;
  767                 regp->rx_int_count = dp->tc_int;
  768                 break;
  769         case TCSIGIT:
  770                 dp->tc_int = regp->int_count;
  771                 break;
  772         case TCSIIT:
  773                 SUCHECK;
  774                 regp->int_count = dp->tc_int;
  775                 break;
  776         case TCSISTATE:
  777                 dp->tc_int = xpp->sp_ccb->hi_ip;
  778                 break;
  779         /* these next three use a different structure */
  780         case TCSI_PORT:
  781                 SUCHECK;
  782                 si_bcopy(xpp, &sps->tc_siport, sizeof(sps->tc_siport));
  783                 break;
  784         case TCSI_CCB:
  785                 SUCHECK;
  786                 si_vbcopy(xpp->sp_ccb, &sps->tc_ccb, sizeof(sps->tc_ccb));
  787                 break;
  788         default:
  789                 error = EINVAL;
  790                 goto out;
  791         }
  792 out:
  793         splx(oldspl);
  794         return(error);          /* success */
  795 }
  796 
  797 /*
  798  *      siparam()       : Configure line params
  799  *      called at spltty();
  800  *      this may sleep, does not flush, nor wait for drain, nor block writes
  801  *      caller must arrange this if it's important..
  802  */
  803 static int
  804 siparam(struct tty *tp, struct termios *t)
  805 {
  806         struct si_port *pp = tty_softc(tp);
  807         volatile struct si_channel *ccbp;
  808         int oldspl, cflag, iflag, oflag, lflag;
  809         int error = 0;          /* shutup gcc */
  810         int ispeed = 0;         /* shutup gcc */
  811         int ospeed = 0;         /* shutup gcc */
  812         BYTE val;
  813 
  814         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
  815         mtx_assert(&Giant, MA_OWNED);
  816         cflag = t->c_cflag;
  817         iflag = t->c_iflag;
  818         oflag = t->c_oflag;
  819         lflag = t->c_lflag;
  820         DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",
  821                 oflag, cflag, iflag, lflag));
  822 
  823         /* XXX - if Jet host and SXDC module, use extended baud rates */
  824 
  825         /* if not hung up.. */
  826         if (t->c_ospeed != 0) {
  827                 /* translate baud rate to firmware values */
  828                 ospeed = si_speedtab(t->c_ospeed, bdrates);
  829                 ispeed = t->c_ispeed ?
  830                          si_speedtab(t->c_ispeed, bdrates) : ospeed;
  831                 /* enforce legit baud rate */
  832                 if (ospeed < 0 || ispeed < 0)
  833                         return (EINVAL);
  834         }
  835 
  836         oldspl = spltty();
  837 
  838         ccbp = pp->sp_ccb;
  839 
  840         /* ========== set hi_break ========== */
  841         val = 0;
  842         if (iflag & IGNBRK)             /* Breaks */
  843                 val |= BR_IGN;
  844         if (iflag & BRKINT)             /* Interrupt on break? */
  845                 val |= BR_INT;
  846         if (iflag & PARMRK)             /* Parity mark? */
  847                 val |= BR_PARMRK;
  848         if (iflag & IGNPAR)             /* Ignore chars with parity errors? */
  849                 val |= BR_PARIGN;
  850         ccbp->hi_break = val;
  851 
  852         /* ========== set hi_csr ========== */
  853         /* if not hung up.. */
  854         if (t->c_ospeed != 0) {
  855                 /* Set I/O speeds */
  856                  val = (ispeed << 4) | ospeed;
  857         }
  858         ccbp->hi_csr = val;
  859 
  860         /* ========== set hi_mr2 ========== */
  861         val = 0;
  862         if (cflag & CSTOPB)                             /* Stop bits */ 
  863                 val |= MR2_2_STOP;
  864         else
  865                 val |= MR2_1_STOP;
  866 
  867         /*
  868          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
  869          * a DCE, hence the reverse sense of RTS and CTS
  870          */
  871         /* Output Flow - RTS must be raised before data can be sent */
  872         if (cflag & CCTS_OFLOW)
  873                 val |= MR2_RTSCONT;
  874 
  875         ccbp->hi_mr2 = val;
  876 
  877         /* ========== set hi_mr1 ========== */
  878         val = 0;
  879         if (!(cflag & PARENB))                          /* Parity */
  880                 val |= MR1_NONE;
  881         else
  882                 val |= MR1_WITH;
  883         if (cflag & PARODD)
  884                 val |= MR1_ODD;
  885 
  886         if ((cflag & CS8) == CS8)                       /* 8 data bits? */
  887                 val |= MR1_8_BITS;
  888         else if ((cflag & CS7) == CS7)                  /* 7 data bits? */
  889                 val |= MR1_7_BITS;
  890         else if ((cflag & CS6) == CS6)                  /* 6 data bits? */
  891                 val |= MR1_6_BITS;
  892         else                                            /* Must be 5 */
  893                 val |= MR1_5_BITS;
  894 
  895         /*
  896          * Enable H/W RTS/CTS handshaking. The default TA/MTA is
  897          * a DCE, hence the reverse sense of RTS and CTS
  898          */
  899         /* Input Flow - CTS is raised when port is ready to receive data */
  900         if (cflag & CRTS_IFLOW)
  901                 val |= MR1_CTSCONT;
  902 
  903         ccbp->hi_mr1 = val;
  904 
  905         /* ========== set hi_mask ========== */
  906         val = 0xff;
  907         if ((cflag & CS8) == CS8) {                     /* 8 data bits? */
  908                 val &= 0xFF;
  909         } else if ((cflag & CS7) == CS7) {              /* 7 data bits? */
  910                 val &= 0x7F;
  911         } else if ((cflag & CS6) == CS6) {              /* 6 data bits? */
  912                 val &= 0x3F;
  913         } else {                                        /* Must be 5 */
  914                 val &= 0x1F;
  915         }
  916         if (iflag & ISTRIP)
  917                 val &= 0x7F;
  918 
  919         ccbp->hi_mask = val;
  920 
  921         /* ========== set hi_prtcl ========== */
  922         val = SP_DCEN;          /* Monitor DCD always, or TIOCMGET misses it */
  923         if (iflag & IXANY)
  924                 val |= SP_TANY;
  925         if (iflag & IXON)
  926                 val |= SP_TXEN;
  927         if (iflag & IXOFF)
  928                 val |= SP_RXEN;
  929         if (iflag & INPCK)
  930                 val |= SP_PAEN;
  931 
  932         ccbp->hi_prtcl = val;
  933 
  934 
  935         /* ========== set hi_{rx|tx}{on|off} ========== */
  936         /* XXX: the card TOTALLY shields us from the flow control... */
  937         ccbp->hi_txon = t->c_cc[VSTART];
  938         ccbp->hi_txoff = t->c_cc[VSTOP];
  939 
  940         ccbp->hi_rxon = t->c_cc[VSTART];
  941         ccbp->hi_rxoff = t->c_cc[VSTOP];
  942 
  943         /* ========== send settings to the card ========== */
  944         /* potential sleep here */
  945         if (ccbp->hi_stat == IDLE_CLOSE)                /* Not yet open */
  946                 si_command(pp, LOPEN, SI_WAIT);         /* open it */
  947         else
  948                 si_command(pp, CONFIG, SI_WAIT);        /* change params */
  949 
  950         /* ========== set DTR etc ========== */
  951         /* Hangup if ospeed == 0 */
  952         if (t->c_ospeed == 0) {
  953                 (void) simodem(tp, 0, SER_DTR | SER_RTS);
  954         } else {
  955                 /*
  956                  * If the previous speed was 0, may need to re-enable
  957                  * the modem signals
  958                  */
  959                 (void) simodem(tp, SER_DTR | SER_RTS, 0);
  960         }
  961 
  962         DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x HI_CSR %x\n",
  963                 ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break, ccbp->hi_csr));
  964 
  965         splx(oldspl);
  966         return(error);
  967 }
  968 
  969 /*
  970  * Set/Get state of modem control lines.
  971  * Due to DCE-like behaviour of the adapter, some signals need translation:
  972  *      TIOCM_DTR       DSR
  973  *      TIOCM_RTS       CTS
  974  */
  975 static int
  976 simodem(struct tty *tp, int sigon, int sigoff)
  977 {
  978         struct si_port *pp;
  979         volatile struct si_channel *ccbp;
  980         int x;
  981 
  982         pp = tty_softc(tp);
  983         DPRINT((pp, DBG_ENTRY|DBG_MODEM, "simodem(%x,%x)\n", sigon, sigoff));
  984         mtx_assert(&Giant, MA_OWNED);
  985         ccbp = pp->sp_ccb;              /* Find channel address */
  986         if (sigon == 0 && sigoff == 0) {
  987                 x = ccbp->hi_ip;
  988                 /*
  989                  * XXX: not sure this is correct, should it be CTS&DSR ?
  990                  * XXX: or do we (just) miss CTS & DSR ?
  991                  */
  992                 if (x & IP_DCD)         sigon |= SER_DCD;
  993                 if (x & IP_DTR)         sigon |= SER_DTR;
  994                 if (x & IP_RTS)         sigon |= SER_RTS;
  995                 if (x & IP_RI)          sigon |= SER_RI;
  996                 return (sigon);
  997         }
  998 
  999         x = ccbp->hi_op;
 1000         if (sigon & SER_DTR)
 1001                 x |= OP_DSR;
 1002         if (sigoff & SER_DTR)
 1003                 x &= ~OP_DSR;
 1004         if (sigon & SER_RTS)
 1005                 x |= OP_CTS;
 1006         if (sigoff & SER_RTS)
 1007                 x &= ~OP_CTS;
 1008         ccbp->hi_op = x;
 1009         return 0;
 1010 }
 1011 
 1012 /*
 1013  * Handle change of modem state
 1014  */
 1015 static void
 1016 si_modem_state(struct si_port *pp, struct tty *tp, int hi_ip)
 1017 {
 1018                                                         /* if a modem dev */
 1019         mtx_assert(&Giant, MA_OWNED);
 1020         if (hi_ip & IP_DCD) {
 1021                 if (!(pp->sp_last_hi_ip & IP_DCD)) {
 1022                         DPRINT((pp, DBG_INTR, "modem carr on%d\n"));
 1023                         (void)ttydisc_modem(tp, 1);
 1024                 }
 1025         } else {
 1026                 if (pp->sp_last_hi_ip & IP_DCD) {
 1027                         DPRINT((pp, DBG_INTR, "modem carr off\n"));
 1028 #if 0   /* XXX mpsafetty ttyld_modem used to tell us to shutdown the port or not */
 1029                         if (ttydisc_modem(tp, 0))
 1030                                 (void) simodem(tp, 0, SER_DTR | SER_RTS);
 1031 #else
 1032                         ttydisc_modem(tp, 0);
 1033 #endif
 1034                 }
 1035         }
 1036         pp->sp_last_hi_ip = hi_ip;
 1037 
 1038 }
 1039 
 1040 /*
 1041  * Poller to catch missed interrupts.
 1042  *
 1043  * Note that the SYSV Specialix drivers poll at 100 times per second to get
 1044  * better response.  We could really use a "periodic" version timeout(). :-)
 1045  */
 1046 #ifdef POLL
 1047 static void
 1048 si_poll(void *nothing)
 1049 {
 1050         struct si_softc *sc;
 1051         int i;
 1052         volatile struct si_reg *regp;
 1053         struct si_port *pp;
 1054         int lost, oldspl, port;
 1055 
 1056         DPRINT((0, DBG_POLL, "si_poll()\n"));
 1057         oldspl = spltty();
 1058         mtx_assert(&Giant, MA_OWNED);
 1059         lost = 0;
 1060         for (i = 0; i < si_numunits; i++) {
 1061                 sc = devclass_get_softc(si_devclass, i);
 1062                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1063                         continue;
 1064                 regp = (struct si_reg *)sc->sc_maddr;
 1065 
 1066                 /*
 1067                  * See if there has been a pending interrupt for 2 seconds
 1068                  * or so. The test (int_scounter >= 200) won't correspond
 1069                  * to 2 seconds if int_count gets changed.
 1070                  */
 1071                 if (regp->int_pending != 0) {
 1072                         if (regp->int_scounter >= 200 &&
 1073                             regp->initstat == 1) {
 1074                                 printf("si%d: lost intr\n", i);
 1075                                 lost++;
 1076                         }
 1077                 } else {
 1078                         regp->int_scounter = 0;
 1079                 }
 1080 
 1081                 /*
 1082                  * gripe about no input flow control..
 1083                  */
 1084                 pp = sc->sc_ports;
 1085                 for (port = 0; port < sc->sc_nport; pp++, port++) {
 1086                         if (pp->sp_delta_overflows > 0) {
 1087                                 printf("si%d: %d tty level buffer overflows\n",
 1088                                         i, pp->sp_delta_overflows);
 1089                                 pp->sp_delta_overflows = 0;
 1090                         }
 1091                 }
 1092         }
 1093         if (lost || si_realpoll)
 1094                 si_intr(NULL);  /* call intr with fake vector */
 1095         splx(oldspl);
 1096 
 1097         timeout(si_poll, (caddr_t)0L, si_pollrate);
 1098 }
 1099 #endif  /* ifdef POLL */
 1100 
 1101 /*
 1102  * The interrupt handler polls ALL ports on ALL adapters each time
 1103  * it is called.
 1104  */
 1105 
 1106 static BYTE si_rxbuf[SI_BUFFERSIZE];    /* input staging area */
 1107 static BYTE si_txbuf[SI_BUFFERSIZE];    /* output staging area */
 1108 
 1109 void
 1110 si_intr(void *arg)
 1111 {
 1112         struct si_softc *sc;
 1113         struct si_port *pp;
 1114         volatile struct si_channel *ccbp;
 1115         struct tty *tp;
 1116         volatile caddr_t maddr;
 1117         BYTE op, ip;
 1118         int x, card, port, n, i, isopen;
 1119         volatile BYTE *z;
 1120         BYTE c;
 1121 
 1122         sc = arg;
 1123         mtx_assert(&Giant, MA_OWNED);
 1124 
 1125         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "si_intr\n"));
 1126 
 1127         /*
 1128          * When we get an int we poll all the channels and do ALL pending
 1129          * work, not just the first one we find. This allows all cards to
 1130          * share the same vector.
 1131          *
 1132          * XXX - But if we're sharing the vector with something that's NOT
 1133          * a SI/XIO/SX card, we may be making more work for ourselves.
 1134          */
 1135         for (card = 0; card < si_numunits; card++) {
 1136                 sc = devclass_get_softc(si_devclass, card);
 1137                 if (sc == NULL || sc->sc_type == SIEMPTY)
 1138                         continue;
 1139 
 1140                 /*
 1141                  * First, clear the interrupt
 1142                  */
 1143                 switch(sc->sc_type) {
 1144                 case SIHOST:
 1145                         maddr = sc->sc_maddr;
 1146                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1147                                                         /* flag nothing pending */
 1148                         *(maddr+SIINTCL) = 0x00;        /* Set IRQ clear */
 1149                         *(maddr+SIINTCL_CL) = 0x00;     /* Clear IRQ clear */
 1150                         break;
 1151                 case SIHOST2:
 1152                         maddr = sc->sc_maddr;
 1153                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1154                         *(maddr+SIPLIRQCLR) = 0x00;
 1155                         *(maddr+SIPLIRQCLR) = 0x10;
 1156                         break;
 1157                 case SIPCI:
 1158                         maddr = sc->sc_maddr;
 1159                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1160                         *(maddr+SIPCIINTCL) = 0x0;
 1161                         break;
 1162                 case SIJETPCI:  /* fall through to JETISA case */
 1163                 case SIJETISA:
 1164                         maddr = sc->sc_maddr;
 1165                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1166                         *(maddr+SIJETINTCL) = 0x0;
 1167                         break;
 1168 #ifdef DEV_EISA
 1169                 case SIEISA:
 1170                         maddr = sc->sc_maddr;
 1171                         ((volatile struct si_reg *)maddr)->int_pending = 0;
 1172                         (void)inb(sc->sc_iobase + 3);
 1173                         break;
 1174 #endif
 1175                 case SIEMPTY:
 1176                 default:
 1177                         continue;
 1178                 }
 1179                 ((volatile struct si_reg *)maddr)->int_scounter = 0;
 1180 
 1181                 /*
 1182                  * check each port
 1183                  */
 1184                 for (pp = sc->sc_ports, port = 0; port < sc->sc_nport;
 1185                      pp++, port++) {
 1186                         ccbp = pp->sp_ccb;
 1187                         tp = pp->sp_tty;
 1188                         tty_lock(tp);
 1189 
 1190                         /*
 1191                          * See if a command has completed ?
 1192                          */
 1193                         if (ccbp->hi_stat != pp->sp_pend) {
 1194                                 DPRINT((pp, DBG_INTR,
 1195                                         "si_intr hi_stat = %s, pend = %s\n",
 1196                                         si_cmdname(ccbp->hi_stat),
 1197                                         si_cmdname(pp->sp_pend)));
 1198                                 switch(pp->sp_pend) {
 1199                                 case LOPEN:
 1200                                 case MPEND:
 1201                                 case MOPEN:
 1202                                 case FCLOSE:
 1203                                 case CONFIG:
 1204                                 case SBREAK:
 1205                                 case EBREAK:
 1206                                         /* sleeping in si_command */
 1207                                         DPRINT((pp, DBG_INTR, "do wakeup\n"));
 1208                                         wakeup(&pp->sp_state);
 1209                                         break;
 1210                                 }
 1211                                 pp->sp_pend = ccbp->hi_stat;
 1212                         }
 1213 
 1214                         /*
 1215                          * Continue on if it's closed
 1216                          */
 1217                         if (ccbp->hi_stat == IDLE_CLOSE) {
 1218                                 tty_unlock(tp);
 1219                                 continue;
 1220                         }
 1221 
 1222                         /*
 1223                          * Do modem state change if not a local device
 1224                          */
 1225                         si_modem_state(pp, tp, ccbp->hi_ip);
 1226 
 1227                         /*
 1228                          * Check to see if we should 'receive' characters.
 1229                          */
 1230                         isopen = tty_opened(tp);
 1231 
 1232                         /*
 1233                          * Do input break processing
 1234                          */
 1235                         if (ccbp->hi_state & ST_BREAK) {
 1236                                 if (isopen)
 1237                                         ttydisc_rint(tp, 0, TRE_BREAK);
 1238                                 ccbp->hi_state &= ~ST_BREAK;   /* A Bit iffy this */
 1239                                 DPRINT((pp, DBG_INTR, "si_intr break\n"));
 1240                         }
 1241 
 1242                         /*
 1243                          * Do RX stuff - if not open then dump any characters.
 1244                          * XXX: This is VERY messy and needs to be cleaned up.
 1245                          *
 1246                          * XXX: can we leave data in the host adapter buffer
 1247                          * when the clists are full?  That may be dangerous
 1248                          * if the user cannot get an interrupt signal through.
 1249                          */
 1250 
 1251         more_rx:
 1252 
 1253                         if (!isopen) {
 1254                                 DPRINT((pp, DBG_INTR, "intr1: not open\n"));
 1255                                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1256                                 goto end_rx;
 1257                         }
 1258 
 1259 #if 0 /* XXXMPSAFETTY */
 1260                         /*
 1261                          * If the tty input buffers are blocked, stop emptying
 1262                          * the incoming buffers and let the auto flow control
 1263                          * assert..
 1264                          */
 1265                         if (tp->t_state & TS_TBLOCK)
 1266                                 goto end_rx;
 1267 #endif
 1268 
 1269                         /*
 1270                          * Process read characters if not skipped above
 1271                          */
 1272                         op = ccbp->hi_rxopos;
 1273                         ip = ccbp->hi_rxipos;
 1274                         c = ip - op;
 1275                         if (c == 0)
 1276                                 goto end_rx;
 1277 
 1278                         n = c & 0xff;
 1279                         if (n > 250)
 1280                                 n = 250;
 1281 
 1282                         DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
 1283                                                 n, op, ip));
 1284 
 1285                         /*
 1286                          * Suck characters out of host card buffer into the
 1287                          * "input staging buffer" - so that we dont leave the
 1288                          * host card in limbo while we're possibly echoing
 1289                          * characters and possibly flushing input inside the
 1290                          * ldisc l_rint() routine.
 1291                          */
 1292                         if (n <= SI_BUFFERSIZE - op) {
 1293 
 1294                                 z = ccbp->hi_rxbuf + op;
 1295                                 si_vbcopy(z, si_rxbuf, n);
 1296 
 1297                                 op += n;
 1298                         } else {
 1299                                 x = SI_BUFFERSIZE - op;
 1300 
 1301                                 z = ccbp->hi_rxbuf + op;
 1302                                 si_vbcopy(z, si_rxbuf, x);
 1303 
 1304                                 z = ccbp->hi_rxbuf;
 1305                                 si_vbcopy(z, si_rxbuf + x, n - x);
 1306 
 1307                                 op += n;
 1308                         }
 1309 
 1310                         /* clear collected characters from buffer */
 1311                         ccbp->hi_rxopos = op;
 1312 
 1313                         /*
 1314                          * at this point...
 1315                          * n = number of chars placed in si_rxbuf
 1316                          */
 1317 
 1318                         if (0 && ttydisc_can_bypass(tp)) {
 1319 
 1320                                 i =  ttydisc_rint_bypass(tp, (char *)si_rxbuf, n);
 1321                                 if (i < n)
 1322                                         pp->sp_delta_overflows += (n - i);
 1323 
 1324                         } else {
 1325                                 /*
 1326                                  * It'd be nice to not have to go through the
 1327                                  * function call overhead for each char here.
 1328                                  * It'd be nice to block input it, saving a
 1329                                  * loop here and the call/return overhead.
 1330                                  */
 1331                                 for(x = 0; x < n; x++) {
 1332                                         i = si_rxbuf[x];
 1333                                         if (ttydisc_rint(tp, i, 0) == -1)
 1334                                                 pp->sp_delta_overflows++;
 1335                                 }
 1336                         }
 1337                         goto more_rx;   /* try for more until RXbuf is empty */
 1338 
 1339         end_rx:
 1340 
 1341                         ttydisc_rint_done(tp);
 1342 
 1343                         /*
 1344                          * Do TX stuff
 1345                          */
 1346                         si_start(tp);
 1347                         tty_unlock(tp);
 1348 
 1349                 } /* end of for (all ports on this controller) */
 1350         } /* end of for (all controllers) */
 1351 
 1352         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "end si_intr\n"));
 1353 }
 1354 
 1355 /*
 1356  * Nudge the transmitter...
 1357  *
 1358  * XXX: I inherited some funny code here.  It implies the host card only
 1359  * interrupts when the transmit buffer reaches the low-water-mark, and does
 1360  * not interrupt when it's actually hits empty.  In some cases, we have
 1361  * processes waiting for complete drain, and we need to simulate an interrupt
 1362  * about when we think the buffer is going to be empty (and retry if not).
 1363  * I really am not certain about this...  I *need* the hardware manuals.
 1364  */
 1365 static void
 1366 si_start(struct tty *tp)
 1367 {
 1368         struct si_port *pp;
 1369         volatile struct si_channel *ccbp;
 1370         BYTE ipos, count;
 1371 #if 0
 1372         int nchar;
 1373 #endif
 1374         int oldspl, n, amount;
 1375 
 1376         oldspl = spltty();
 1377         mtx_assert(&Giant, MA_OWNED);
 1378 
 1379         pp = tty_softc(tp);
 1380 
 1381         DPRINT((pp, DBG_ENTRY|DBG_START,
 1382                 "si_start(%x) sp_state %x\n",
 1383                 tp, pp->sp_state));
 1384 
 1385         ccbp = pp->sp_ccb;
 1386 
 1387         while ((count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos) < 255) {
 1388                 DPRINT((pp, DBG_START, "txbuf pend count %d\n", (BYTE)count));
 1389                 ipos = (unsigned int)ccbp->hi_txipos;
 1390                 if ((int)ccbp->hi_txopos <= ipos)
 1391                         amount = SI_BUFFERSIZE - ipos;
 1392                 else
 1393                         amount = 255 - count;
 1394                 DPRINT((pp, DBG_START, "spaceleft amount %d\n", amount));
 1395                 if (amount == 0)
 1396                         break;
 1397                 n = ttydisc_getc(tp, si_txbuf, amount);
 1398                 DPRINT((pp, DBG_START, "getc n=%d\n", n));
 1399                 if (n == 0)
 1400                         break;
 1401                 si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n);
 1402                 ccbp->hi_txipos += n;
 1403         }
 1404 
 1405 #if 0
 1406         /*
 1407          * See if there are any characters still to come.  If so, we can
 1408          * depend on si_start being called again.
 1409          *
 1410          * XXX the manual is vague on this.  It implies we get an interrupt
 1411          * when the transmit queue reaches the 25% low water mark, but NOT
 1412          * when it hits empty.
 1413          */
 1414         nchar = ttyoutq_getsize(&tp->t_outq) - ttyoutq_bytesleft(&tp->t_outq);
 1415         DPRINT((pp, DBG_START, "count %d, nchar %d\n",
 1416                 (BYTE)count, nchar));
 1417 
 1418         if (count != 0 && nchar == 0) {
 1419                 int time;
 1420 
 1421                 /* XXX lame. Ticks per character. used to be a table. */
 1422                 time = (tp->t_termios.c_ospeed + 9) / 10;
 1423 
 1424                 if (time > 0) {
 1425                         if (time < nchar)
 1426                                 time = nchar / time;
 1427                         else
 1428                                 time = 2;
 1429                 } else {
 1430                         DPRINT((pp, DBG_START,
 1431                                 "bad char time value! %d\n", time));
 1432                         time = hz/10;
 1433                 }
 1434 
 1435                 if ((pp->sp_state & SS_LSTART) != 0)
 1436                         untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
 1437                 DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
 1438                 pp->sp_state |= SS_LSTART;
 1439                 pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time);
 1440         }
 1441 #endif
 1442 
 1443         splx(oldspl);
 1444         DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
 1445 }
 1446 
 1447 #if 0
 1448 /*
 1449  * Note: called at splsoftclock from the timeout code
 1450  * This has to deal with two things...  cause wakeups while waiting for
 1451  * tty drains on last process exit, and call l_start at about the right
 1452  * time for protocols like ppp.
 1453  */
 1454 static void
 1455 si_lstart(void *arg)
 1456 {
 1457         struct si_port *pp = arg;
 1458         struct tty *tp;
 1459         int oldspl;
 1460 
 1461         DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n",
 1462                 pp, pp->sp_state));
 1463 
 1464         oldspl = spltty();
 1465         mtx_assert(&Giant, MA_OWNED);
 1466         pp->sp_state &= ~SS_LSTART;
 1467         tp = pp->sp_tty;
 1468 
 1469         si_start(tp);
 1470 
 1471         splx(oldspl);
 1472 }
 1473 #endif
 1474 
 1475 #if 0 /* XXX mpsafetty */
 1476 /*
 1477  * Stop output on a line. called at spltty();
 1478  */
 1479 static void
 1480 si_stop(struct tty *tp, int rw)
 1481 {
 1482         volatile struct si_channel *ccbp;
 1483         struct si_port *pp;
 1484 
 1485         mtx_assert(&Giant, MA_OWNED);
 1486         pp = tty_softc(tp);
 1487         ccbp = pp->sp_ccb;
 1488 
 1489         DPRINT((pp, DBG_ENTRY|DBG_STOP, "si_stop(%x,%x)\n", tp, rw));
 1490 
 1491         /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
 1492         if (rw & FWRITE) {
 1493                 /* what level are we meant to be flushing anyway? */
 1494                 if (tp->t_state & TS_BUSY) {
 1495                         si_command(pp, WFLUSH, SI_NOWAIT);
 1496                         tp->t_state &= ~TS_BUSY;
 1497                         ttwwakeup(tp);  /* Bruce???? */
 1498                 }
 1499         }
 1500 #if 1   /* XXX: this doesn't work right yet.. */
 1501         /* XXX: this may have been failing because we used to call l_rint()
 1502          * while we were looping based on these two counters. Now, we collect
 1503          * the data and then loop stuffing it into l_rint(), making this
 1504          * useless.  Should we cause this to blow away the staging buffer?
 1505          */
 1506         if (rw & FREAD) {
 1507                 ccbp->hi_rxopos = ccbp->hi_rxipos;
 1508         }
 1509 #endif
 1510 }
 1511 #endif
 1512 
 1513 /*
 1514  * Issue a command to the host card CPU.
 1515  *
 1516  * XXX This is all just so WRONG!.  Ed says we're not supposed to sleep
 1517  * here anyway.  We sort of get away with it for now by using Giant.
 1518  * Something better will have to be done.
 1519  * Linux does a busy spin here waiting for the 8-bit cpu to notice the
 1520  * posted command and respond to it.  I'm not sure I like that either.
 1521  */
 1522 static void
 1523 si_command(struct si_port *pp, int cmd, int waitflag)
 1524 {
 1525         int oldspl;
 1526         volatile struct si_channel *ccbp = pp->sp_ccb;
 1527         int x;
 1528         int err;
 1529 
 1530         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%s,%d): hi_stat %s, sp_pend: %s\n",
 1531                 pp, si_cmdname(cmd), waitflag, si_cmdname(ccbp->hi_stat),
 1532                 si_cmdname(pp->sp_pend)));
 1533 
 1534         oldspl = spltty();              /* Keep others out */
 1535         mtx_assert(&Giant, MA_OWNED);
 1536 
 1537         /* wait until it's finished what it was doing.. */
 1538         /* XXX: sits in IDLE_BREAK until something disturbs it or break
 1539          * is turned off. */
 1540         while((x = ccbp->hi_stat) != IDLE_OPEN &&
 1541                         x != IDLE_CLOSE &&
 1542                         x != IDLE_BREAK &&
 1543                         x != cmd) {
 1544                 DPRINT((pp, DBG_PARAM, "sicmd1 old cmd pending (going to tsleep): hi_stat (%s)\n", si_cmdname(ccbp->hi_stat)));
 1545                 err = tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd1", hz/4);
 1546                 if (err) {
 1547                         DPRINT((pp, DBG_PARAM, "sicmd1 timeout: hi_stat (%s)\n",
 1548                                 si_cmdname(ccbp->hi_stat)));
 1549                         /* This is very very bad.  The card has crashed. */
 1550                         /* XXX the driver breaks at this point */
 1551                         if (err == ETIMEDOUT)
 1552                                 DPRINT(("%s: tsleep1 timeout. hi_stat %s, sp_pend %s\n", pp->sp_name, si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1553                         splx(oldspl);
 1554                         return;
 1555                 }
 1556         }
 1557         /* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */
 1558         DPRINT((pp, DBG_PARAM, "sicmd1 now in: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1559 
 1560         /* if there was a pending command, cause a state-change wakeup */
 1561         switch(pp->sp_pend) {
 1562         case LOPEN:
 1563         case MPEND:
 1564         case MOPEN:
 1565         case FCLOSE:
 1566         case CONFIG:
 1567         case SBREAK:
 1568         case EBREAK:
 1569                 DPRINT((pp, DBG_PARAM, "si_command: sp_pend %s, doing wakeup\n", si_cmdname(pp->sp_pend)));
 1570                 wakeup(&pp->sp_state);
 1571                 break;
 1572         default:
 1573                 break;
 1574         }
 1575 
 1576         pp->sp_pend = cmd;              /* New command pending */
 1577         ccbp->hi_stat = cmd;            /* Post it */
 1578         DPRINT((pp, DBG_PARAM, "sicmd now posted: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1579 
 1580         if (waitflag) {
 1581                 while((x = ccbp->hi_stat) != IDLE_OPEN &&
 1582                              x != IDLE_CLOSE &&
 1583                              x != IDLE_BREAK) {
 1584                         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)));
 1585                         err = tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd2", hz);
 1586                         if (err) {
 1587                                 DPRINT((pp, DBG_PARAM, "sicmd2 tsleep error: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1588                                 if (err == ETIMEDOUT) {
 1589                                         DPRINT(("%s: tsleep2 timeout. hi_stat %s, sp_pend %s\n", pp->sp_name, si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1590                                 }
 1591                                 break;
 1592                         }
 1593                 }
 1594         }
 1595         DPRINT((pp, DBG_PARAM, "sicmd2 finished: hi_stat (%s) sp_pend (%s)\n", si_cmdname(ccbp->hi_stat), si_cmdname(pp->sp_pend)));
 1596         splx(oldspl);
 1597 }
 1598 
 1599 
 1600 #ifdef  SI_DEBUG
 1601 
 1602 void
 1603 si_dprintf(struct si_port *pp, int flags, const char *fmt, ...)
 1604 {
 1605         va_list ap;
 1606 
 1607         if ((pp == NULL && (si_debug&flags)) ||
 1608             (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
 1609                 if (pp != NULL)
 1610                         printf("%s: ", pp->sp_name);
 1611                 va_start(ap, fmt);
 1612                 vprintf(fmt, ap);
 1613                 va_end(ap);
 1614         }
 1615 }
 1616 
 1617 #endif  /* DEBUG */
 1618 
 1619 static char *
 1620 si_modulename(int host_type, int uart_type)
 1621 {
 1622         switch (host_type) {
 1623         /* Z280 based cards */
 1624 #ifdef DEV_EISA
 1625         case SIEISA:
 1626 #endif
 1627         case SIHOST2:
 1628         case SIHOST:
 1629         case SIPCI:
 1630                 switch (uart_type) {
 1631                 case 0:
 1632                         return(" (XIO)");
 1633                 case 1:
 1634                         return(" (SI)");
 1635                 }
 1636                 break;
 1637         /* T225 based hosts */
 1638         case SIJETPCI:
 1639         case SIJETISA:
 1640                 switch (uart_type) {
 1641                 case 0:
 1642                         return(" (SI)");
 1643                 case 40:
 1644                         return(" (XIO)");
 1645                 case 72:
 1646                         return(" (SXDC)");
 1647                 }
 1648                 break;
 1649         }
 1650         return("");
 1651 }

Cache object: 8635d17407c7aad159c99365c0d5ee4e


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