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


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

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/stallion.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 
    3 /*
    4  * stallion.c  -- stallion multiport serial driver.
    5  *
    6  * Copyright (c) 1995-1999 Greg Ungerer (gerg@stallion.oz.au).
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by Greg Ungerer.
   20  * 4. Neither the name of the author nor the names of any co-contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * Id: stallion.c,v 1.4 2000/10/01 10:23:03 wayne Exp
   37  * $FreeBSD$
   38  */
   39 
   40 /*****************************************************************************/
   41 
   42 #define TTYDEFCHARS     1
   43 
   44 #include "opt_compat.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/tty.h>
   51 #include <sys/proc.h>
   52 #include <sys/conf.h>
   53 #include <sys/fcntl.h>
   54 #include <machine/clock.h>
   55 #include <i386/isa/isa_device.h>
   56 #include <i386/isa/ic/scd1400.h>
   57 #include <i386/isa/ic/sc26198.h>
   58 #include <machine/comstats.h>
   59 
   60 #include "pci.h"
   61 #if NPCI > 0
   62 #include <pci/pcivar.h>
   63 #include <pci/pcireg.h>
   64 #endif
   65 
   66 /*****************************************************************************/
   67 
   68 /*
   69  *      Define the version level of the kernel - so we can compile in the
   70  *      appropriate bits of code. By default this will compile for a 4.x
   71  *      level kernel.
   72  */
   73 #define VFREEBSD        400
   74 #define STATIC          static
   75 
   76 /*****************************************************************************/
   77 
   78 /*
   79  *      Define different board types. At the moment I have only declared
   80  *      those boards that this driver supports. But I will use the standard
   81  *      "assigned" board numbers. In the future this driver will support
   82  *      some of the other Stallion boards. Currently supported boards are
   83  *      abbreviated as EIO = EasyIO and ECH = EasyConnection 8/32.
   84  */
   85 #define BRD_EASYIO      20
   86 #define BRD_ECH         21
   87 #define BRD_ECHMC       22
   88 #define BRD_ECHPCI      26
   89 #define BRD_ECH64PCI    27
   90 #define BRD_EASYIOPCI   28
   91 
   92 /*
   93  *      When using the BSD "config" stuff there is no easy way to specifiy
   94  *      a secondary IO address region. So it is hard wired here. Also the
   95  *      shared interrupt information is hard wired here...
   96  */
   97 static unsigned int     stl_ioshared = 0x280;
   98 static unsigned int     stl_irqshared = 0;
   99 
  100 /*****************************************************************************/
  101 
  102 /*
  103  *      Define important driver limitations.
  104  */
  105 #define STL_MAXBRDS             8
  106 #define STL_MAXPANELS           4
  107 #define STL_MAXBANKS            8
  108 #define STL_PORTSPERPANEL       16
  109 #define STL_PORTSPERBRD         64
  110 
  111 /*
  112  *      Define the important minor number break down bits. These have been
  113  *      chosen to be "compatable" with the standard sio driver minor numbers.
  114  *      Extra high bits are used to distinguish between boards.
  115  */
  116 #define STL_CALLOUTDEV          0x80
  117 #define STL_CTRLLOCK            0x40
  118 #define STL_CTRLINIT            0x20
  119 #define STL_CTRLDEV             (STL_CTRLLOCK | STL_CTRLINIT)
  120 
  121 #define STL_MEMDEV              0x07000000
  122 
  123 #define STL_DEFSPEED            9600
  124 #define STL_DEFCFLAG            (CS8 | CREAD | HUPCL)
  125 
  126 /*
  127  *      I haven't really decided (or measured) what buffer sizes give
  128  *      a good balance between performance and memory usage. These seem
  129  *      to work pretty well...
  130  */
  131 #define STL_RXBUFSIZE           2048
  132 #define STL_TXBUFSIZE           2048
  133 
  134 #define STL_TXBUFLOW            (STL_TXBUFSIZE / 4)
  135 #define STL_RXBUFHIGH           (3 * STL_RXBUFSIZE / 4)
  136 
  137 /*****************************************************************************/
  138 
  139 /*
  140  *      Define our local driver identity first. Set up stuff to deal with
  141  *      all the local structures required by a serial tty driver.
  142  */
  143 static const char       stl_drvname[] = "stl";
  144 static const char       stl_drvtitle[] = "Stallion Multiport Serial Driver";
  145 static const char       stl_drvversion[] = "5.6.0b1";
  146 static int              stl_brdprobed[STL_MAXBRDS];
  147 
  148 static int              stl_nrbrds = 0;
  149 static int              stl_doingtimeout = 0;
  150 
  151 static const char       __file__[] = /*__FILE__*/ "stallion.c";
  152 
  153 /*
  154  *      Define global stats structures. Not used often, and can be
  155  *      re-used for each stats call.
  156  */
  157 static combrd_t         stl_brdstats;
  158 static comstats_t       stl_comstats;
  159 
  160 /*****************************************************************************/
  161 
  162 /*
  163  *      Define a set of structures to hold all the board/panel/port info
  164  *      for our ports. These will be dynamically allocated as required.
  165  */
  166 
  167 /*
  168  *      Define a ring queue structure for each port. This will hold the
  169  *      TX data waiting to be output. Characters are fed into this buffer
  170  *      from the line discipline (or even direct from user space!) and
  171  *      then fed into the UARTs during interrupts. Will use a clasic ring
  172  *      queue here for this. The good thing about this type of ring queue
  173  *      is that the head and tail pointers can be updated without interrupt
  174  *      protection - since "write" code only needs to change the head, and
  175  *      interrupt code only needs to change the tail.
  176  */
  177 typedef struct {
  178         char    *buf;
  179         char    *endbuf;
  180         char    *head;
  181         char    *tail;
  182 } stlrq_t;
  183 
  184 /*
  185  *      Port, panel and board structures to hold status info about each.
  186  *      The board structure contains pointers to structures for each panel
  187  *      connected to it, and in turn each panel structure contains pointers
  188  *      for each port structure for each port on that panel. Note that
  189  *      the port structure also contains the board and panel number that it
  190  *      is associated with, this makes it (fairly) easy to get back to the
  191  *      board/panel info for a port. Also note that the tty struct is at
  192  *      the top of the structure, this is important, since the code uses
  193  *      this fact to get the port struct pointer from the tty struct
  194  *      pointer!
  195  */
  196 typedef struct stlport {
  197         struct tty      tty;
  198         int             portnr;
  199         int             panelnr;
  200         int             brdnr;
  201         int             ioaddr;
  202         int             uartaddr;
  203         int             pagenr;
  204         int             callout;
  205         int             brklen;
  206         int             dtrwait;
  207         int             dotimestamp;
  208         int             waitopens;
  209         int             hotchar;
  210         void            *uartp;
  211         unsigned int    state;
  212         unsigned int    hwid;
  213         unsigned int    sigs;
  214         unsigned int    rxignoremsk;
  215         unsigned int    rxmarkmsk;
  216         unsigned int    crenable;
  217         unsigned int    imr;
  218         unsigned long   clk;
  219         struct termios  initintios;
  220         struct termios  initouttios;
  221         struct termios  lockintios;
  222         struct termios  lockouttios;
  223         struct timeval  timestamp;
  224         comstats_t      stats;
  225         stlrq_t         tx;
  226         stlrq_t         rx;
  227         stlrq_t         rxstatus;
  228         dev_t           dev_ttyE;
  229         dev_t           dev_ttyiE;
  230         dev_t           dev_ttylE;
  231         dev_t           dev_cue;
  232         dev_t           dev_cuie;
  233         dev_t           dev_cule;
  234 } stlport_t;
  235 
  236 typedef struct stlpanel {
  237         int             panelnr;
  238         int             brdnr;
  239         int             pagenr;
  240         int             nrports;
  241         int             iobase;
  242         unsigned int    hwid;
  243         unsigned int    ackmask;
  244         void            (*isr)(struct stlpanel *panelp, unsigned int iobase);
  245         void            *uartp;
  246         stlport_t       *ports[STL_PORTSPERPANEL];
  247 } stlpanel_t;
  248 
  249 typedef struct stlbrd {
  250         int             brdnr;
  251         int             brdtype;
  252         int             unitid;
  253         int             state;
  254         int             nrpanels;
  255         int             nrports;
  256         int             nrbnks;
  257         int             irq;
  258         int             irqtype;
  259         unsigned int    ioaddr1;
  260         unsigned int    ioaddr2;
  261         unsigned int    iostatus;
  262         unsigned int    ioctrl;
  263         unsigned int    ioctrlval;
  264         unsigned int    hwid;
  265         unsigned long   clk;
  266         void            (*isr)(struct stlbrd *brdp);
  267         unsigned int    bnkpageaddr[STL_MAXBANKS];
  268         unsigned int    bnkstataddr[STL_MAXBANKS];
  269         stlpanel_t      *bnk2panel[STL_MAXBANKS];
  270         stlpanel_t      *panels[STL_MAXPANELS];
  271         stlport_t       *ports[STL_PORTSPERBRD];
  272         dev_t           dev_staliomem;
  273 } stlbrd_t;
  274 
  275 static stlbrd_t         *stl_brds[STL_MAXBRDS];
  276 
  277 /*
  278  *      Per board state flags. Used with the state field of the board struct.
  279  *      Not really much here yet!
  280  */
  281 #define BRD_FOUND       0x1
  282 
  283 /*
  284  *      Define the port structure state flags. These set of flags are
  285  *      modified at interrupt time - so setting and reseting them needs
  286  *      to be atomic.
  287  */
  288 #define ASY_TXLOW       0x1
  289 #define ASY_RXDATA      0x2
  290 #define ASY_DCDCHANGE   0x4
  291 #define ASY_DTRWAIT     0x8
  292 #define ASY_RTSFLOW     0x10
  293 #define ASY_RTSFLOWMODE 0x20
  294 #define ASY_CTSFLOWMODE 0x40
  295 #define ASY_TXFLOWED    0x80
  296 #define ASY_TXBUSY      0x100
  297 #define ASY_TXEMPTY     0x200
  298 
  299 #define ASY_ACTIVE      (ASY_TXEMPTY | ASY_TXLOW | ASY_RXDATA | ASY_DCDCHANGE)
  300 
  301 /*
  302  *      Define an array of board names as printable strings. Handy for
  303  *      referencing boards when printing trace and stuff.
  304  */
  305 static char     *stl_brdnames[] = {
  306         (char *) NULL,
  307         (char *) NULL,
  308         (char *) NULL,
  309         (char *) NULL,
  310         (char *) NULL,
  311         (char *) NULL,
  312         (char *) NULL,
  313         (char *) NULL,
  314         (char *) NULL,
  315         (char *) NULL,
  316         (char *) NULL,
  317         (char *) NULL,
  318         (char *) NULL,
  319         (char *) NULL,
  320         (char *) NULL,
  321         (char *) NULL,
  322         (char *) NULL,
  323         (char *) NULL,
  324         (char *) NULL,
  325         (char *) NULL,
  326         "EasyIO",
  327         "EC8/32-AT",
  328         "EC8/32-MC",
  329         (char *) NULL,
  330         (char *) NULL,
  331         (char *) NULL,
  332         "EC8/32-PCI",
  333         "EC8/64-PCI",
  334         "EasyIO-PCI",
  335 };
  336 
  337 /*****************************************************************************/
  338 
  339 /*
  340  *      Hardware ID bits for the EasyIO and ECH boards. These defines apply
  341  *      to the directly accessable io ports of these boards (not the cd1400
  342  *      or 26198 uarts - they are in scd1400.h and sc26198.h).
  343  */
  344 #define EIO_8PORTRS     0x04
  345 #define EIO_4PORTRS     0x05
  346 #define EIO_8PORTDI     0x00
  347 #define EIO_8PORTM      0x06
  348 #define EIO_MK3         0x03
  349 #define EIO_IDBITMASK   0x07
  350 
  351 #define EIO_BRDMASK     0xf0
  352 #define ID_BRD4         0x10
  353 #define ID_BRD8         0x20
  354 #define ID_BRD16        0x30
  355 
  356 #define EIO_INTRPEND    0x08
  357 #define EIO_INTEDGE     0x00
  358 #define EIO_INTLEVEL    0x08
  359 
  360 #define ECH_ID          0xa0
  361 #define ECH_IDBITMASK   0xe0
  362 #define ECH_BRDENABLE   0x08
  363 #define ECH_BRDDISABLE  0x00
  364 #define ECH_INTENABLE   0x01
  365 #define ECH_INTDISABLE  0x00
  366 #define ECH_INTLEVEL    0x02
  367 #define ECH_INTEDGE     0x00
  368 #define ECH_INTRPEND    0x01
  369 #define ECH_BRDRESET    0x01
  370 
  371 #define ECHMC_INTENABLE 0x01
  372 #define ECHMC_BRDRESET  0x02
  373 
  374 #define ECH_PNLSTATUS   2
  375 #define ECH_PNL16PORT   0x20
  376 #define ECH_PNLIDMASK   0x07
  377 #define ECH_PNLXPID     0x40
  378 #define ECH_PNLINTRPEND 0x80
  379 #define ECH_ADDR2MASK   0x1e0
  380 
  381 #define EIO_CLK         25000000
  382 #define EIO_CLK8M       20000000
  383 #define ECH_CLK         EIO_CLK
  384 
  385 /*****************************************************************************/
  386 
  387 /*
  388  *      Define the PCI vendor and device ID for Stallion PCI boards.
  389  */
  390 #define STL_PCINSVENDID 0x100b
  391 #define STL_PCINSDEVID  0xd001
  392 
  393 #define STL_PCIVENDID   0x124d
  394 #define STL_PCI32DEVID  0x0000
  395 #define STL_PCI64DEVID  0x0002
  396 #define STL_PCIEIODEVID 0x0003
  397 
  398 #define STL_PCIBADCLASS 0x0101
  399 
  400 typedef struct stlpcibrd {
  401         unsigned short          vendid;
  402         unsigned short          devid;
  403         int                     brdtype;
  404 } stlpcibrd_t;
  405 
  406 static stlpcibrd_t      stl_pcibrds[] = {
  407         { STL_PCIVENDID, STL_PCI64DEVID, BRD_ECH64PCI },
  408         { STL_PCIVENDID, STL_PCIEIODEVID, BRD_EASYIOPCI },
  409         { STL_PCIVENDID, STL_PCI32DEVID, BRD_ECHPCI },
  410         { STL_PCINSVENDID, STL_PCINSDEVID, BRD_ECHPCI },
  411 };
  412 
  413 static int      stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);
  414 
  415 /*****************************************************************************/
  416 
  417 /*
  418  *      Define the vector mapping bits for the programmable interrupt board
  419  *      hardware. These bits encode the interrupt for the board to use - it
  420  *      is software selectable (except the EIO-8M).
  421  */
  422 static unsigned char    stl_vecmap[] = {
  423         0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
  424         0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
  425 };
  426 
  427 /*
  428  *      Set up enable and disable macros for the ECH boards. They require
  429  *      the secondary io address space to be activated and deactivated.
  430  *      This way all ECH boards can share their secondary io region.
  431  *      If this is an ECH-PCI board then also need to set the page pointer
  432  *      to point to the correct page.
  433  */
  434 #define BRDENABLE(brdnr,pagenr)                                         \
  435         if (stl_brds[(brdnr)]->brdtype == BRD_ECH)                      \
  436                 outb(stl_brds[(brdnr)]->ioctrl,                         \
  437                         (stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE));\
  438         else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)              \
  439                 outb(stl_brds[(brdnr)]->ioctrl, (pagenr));
  440 
  441 #define BRDDISABLE(brdnr)                                               \
  442         if (stl_brds[(brdnr)]->brdtype == BRD_ECH)                      \
  443                 outb(stl_brds[(brdnr)]->ioctrl,                         \
  444                         (stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE));
  445 
  446 /*
  447  *      Define some spare buffer space for un-wanted received characters.
  448  */
  449 static char     stl_unwanted[SC26198_RXFIFOSIZE];
  450 
  451 /*****************************************************************************/
  452 
  453 /*
  454  *      Define macros to extract a brd and port number from a minor number.
  455  *      This uses the extended minor number range in the upper 2 bytes of
  456  *      the device number. This gives us plenty of minor numbers to play
  457  *      with...
  458  */
  459 #define MKDEV2BRD(m)    ((minor(m) & 0x00700000) >> 20)
  460 #define MKDEV2PORT(m)   ((minor(m) & 0x1f) | ((minor(m) & 0x00010000) >> 11))
  461 
  462 /*
  463  *      Define some handy local macros...
  464  */
  465 #ifndef MIN
  466 #define MIN(a,b)        (((a) <= (b)) ? (a) : (b))
  467 #endif
  468 
  469 /*****************************************************************************/
  470 
  471 /*
  472  *      Declare all those functions in this driver!  First up is the set of
  473  *      externally visible functions.
  474  */
  475 
  476 static int      stlprobe(struct isa_device *idp);
  477 static int      stlattach(struct isa_device *idp);
  478 
  479 STATIC  d_open_t        stlopen;
  480 STATIC  d_close_t       stlclose;
  481 STATIC  d_ioctl_t       stlioctl;
  482 
  483 /*
  484  *      Internal function prototypes.
  485  */
  486 static stlport_t *stl_dev2port(dev_t dev);
  487 static int      stl_findfreeunit(void);
  488 static int      stl_rawopen(stlport_t *portp);
  489 static int      stl_rawclose(stlport_t *portp);
  490 static void     stl_flush(stlport_t *portp, int flag);
  491 static int      stl_param(struct tty *tp, struct termios *tiosp);
  492 static void     stl_start(struct tty *tp);
  493 static void     stl_stop(struct tty *tp, int);
  494 static void     stl_ttyoptim(stlport_t *portp, struct termios *tiosp);
  495 static void     stl_dotimeout(void);
  496 static void     stl_poll(void *arg);
  497 static void     stl_rxprocess(stlport_t *portp);
  498 static void     stl_flowcontrol(stlport_t *portp, int hw, int sw);
  499 static void     stl_dtrwakeup(void *arg);
  500 static int      stl_brdinit(stlbrd_t *brdp);
  501 static int      stl_initeio(stlbrd_t *brdp);
  502 static int      stl_initech(stlbrd_t *brdp);
  503 static int      stl_initports(stlbrd_t *brdp, stlpanel_t *panelp, int strtport);
  504 static void     stl_eiointr(stlbrd_t *brdp);
  505 static void     stl_echatintr(stlbrd_t *brdp);
  506 static void     stl_echmcaintr(stlbrd_t *brdp);
  507 static void     stl_echpciintr(stlbrd_t *brdp);
  508 static void     stl_echpci64intr(stlbrd_t *brdp);
  509 static int      stl_memioctl(dev_t dev, unsigned long cmd, caddr_t data,
  510                              int flag, struct proc *p);
  511 static int      stl_getbrdstats(caddr_t data);
  512 static int      stl_getportstats(stlport_t *portp, caddr_t data);
  513 static int      stl_clrportstats(stlport_t *portp, caddr_t data);
  514 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
  515 
  516 #if NPCI > 0
  517 static const char *stlpciprobe(pcici_t tag, pcidi_t type);
  518 static void     stlpciattach(pcici_t tag, int unit);
  519 static void     stlpciintr(void * arg);
  520 #endif
  521 
  522 void            stlintr(int unit);
  523 
  524 
  525 /*
  526  *      CD1400 uart specific handling functions.
  527  */
  528 static void     stl_cd1400setreg(stlport_t *portp, int regnr, int value);
  529 static int      stl_cd1400getreg(stlport_t *portp, int regnr);
  530 static int      stl_cd1400updatereg(stlport_t *portp, int regnr, int value);
  531 static int      stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
  532 static void     stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
  533 static int      stl_cd1400setport(stlport_t *portp, struct termios *tiosp);
  534 static int      stl_cd1400getsignals(stlport_t *portp);
  535 static void     stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);
  536 static void     stl_cd1400ccrwait(stlport_t *portp);
  537 static void     stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);
  538 static void     stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);
  539 static void     stl_cd1400disableintrs(stlport_t *portp);
  540 static void     stl_cd1400sendbreak(stlport_t *portp, long len);
  541 static void     stl_cd1400sendflow(stlport_t *portp, int hw, int sw);
  542 static int      stl_cd1400datastate(stlport_t *portp);
  543 static void     stl_cd1400flush(stlport_t *portp, int flag);
  544 static void     stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);
  545 static void     stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);
  546 static void     stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);
  547 static void     stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);
  548 static void     stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);
  549 
  550 /*
  551  *      SC26198 uart specific handling functions.
  552  */
  553 static void     stl_sc26198setreg(stlport_t *portp, int regnr, int value);
  554 static int      stl_sc26198getreg(stlport_t *portp, int regnr);
  555 static int      stl_sc26198updatereg(stlport_t *portp, int regnr, int value);
  556 static int      stl_sc26198getglobreg(stlport_t *portp, int regnr);
  557 static int      stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
  558 static void     stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
  559 static int      stl_sc26198setport(stlport_t *portp, struct termios *tiosp);
  560 static int      stl_sc26198getsignals(stlport_t *portp);
  561 static void     stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);
  562 static void     stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);
  563 static void     stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);
  564 static void     stl_sc26198disableintrs(stlport_t *portp);
  565 static void     stl_sc26198sendbreak(stlport_t *portp, long len);
  566 static void     stl_sc26198sendflow(stlport_t *portp, int hw, int sw);
  567 static int      stl_sc26198datastate(stlport_t *portp);
  568 static void     stl_sc26198flush(stlport_t *portp, int flag);
  569 static void     stl_sc26198txunflow(stlport_t *portp);
  570 static void     stl_sc26198wait(stlport_t *portp);
  571 static void     stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);
  572 static void     stl_sc26198txisr(stlport_t *port);
  573 static void     stl_sc26198rxisr(stlport_t *port, unsigned int iack);
  574 static void     stl_sc26198rxgoodchars(stlport_t *portp);
  575 static void     stl_sc26198rxbadchars(stlport_t *portp);
  576 static void     stl_sc26198otherisr(stlport_t *port, unsigned int iack);
  577 
  578 /*****************************************************************************/
  579 
  580 /*
  581  *      Generic UART support structure.
  582  */
  583 typedef struct uart {
  584         int     (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp);
  585         void    (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
  586         int     (*setport)(stlport_t *portp, struct termios *tiosp);
  587         int     (*getsignals)(stlport_t *portp);
  588         void    (*setsignals)(stlport_t *portp, int dtr, int rts);
  589         void    (*enablerxtx)(stlport_t *portp, int rx, int tx);
  590         void    (*startrxtx)(stlport_t *portp, int rx, int tx);
  591         void    (*disableintrs)(stlport_t *portp);
  592         void    (*sendbreak)(stlport_t *portp, long len);
  593         void    (*sendflow)(stlport_t *portp, int hw, int sw);
  594         void    (*flush)(stlport_t *portp, int flag);
  595         int     (*datastate)(stlport_t *portp);
  596         void    (*intr)(stlpanel_t *panelp, unsigned int iobase);
  597 } uart_t;
  598 
  599 /*
  600  *      Define some macros to make calling these functions nice and clean.
  601  */
  602 #define stl_panelinit           (* ((uart_t *) panelp->uartp)->panelinit)
  603 #define stl_portinit            (* ((uart_t *) portp->uartp)->portinit)
  604 #define stl_setport             (* ((uart_t *) portp->uartp)->setport)
  605 #define stl_getsignals          (* ((uart_t *) portp->uartp)->getsignals)
  606 #define stl_setsignals          (* ((uart_t *) portp->uartp)->setsignals)
  607 #define stl_enablerxtx          (* ((uart_t *) portp->uartp)->enablerxtx)
  608 #define stl_startrxtx           (* ((uart_t *) portp->uartp)->startrxtx)
  609 #define stl_disableintrs        (* ((uart_t *) portp->uartp)->disableintrs)
  610 #define stl_sendbreak           (* ((uart_t *) portp->uartp)->sendbreak)
  611 #define stl_sendflow            (* ((uart_t *) portp->uartp)->sendflow)
  612 #define stl_uartflush           (* ((uart_t *) portp->uartp)->flush)
  613 #define stl_datastate           (* ((uart_t *) portp->uartp)->datastate)
  614 
  615 /*****************************************************************************/
  616 
  617 /*
  618  *      CD1400 UART specific data initialization.
  619  */
  620 static uart_t stl_cd1400uart = {
  621         stl_cd1400panelinit,
  622         stl_cd1400portinit,
  623         stl_cd1400setport,
  624         stl_cd1400getsignals,
  625         stl_cd1400setsignals,
  626         stl_cd1400enablerxtx,
  627         stl_cd1400startrxtx,
  628         stl_cd1400disableintrs,
  629         stl_cd1400sendbreak,
  630         stl_cd1400sendflow,
  631         stl_cd1400flush,
  632         stl_cd1400datastate,
  633         stl_cd1400eiointr
  634 };
  635 
  636 /*
  637  *      Define the offsets within the register bank of a cd1400 based panel.
  638  *      These io address offsets are common to the EasyIO board as well.
  639  */
  640 #define EREG_ADDR       0
  641 #define EREG_DATA       4
  642 #define EREG_RXACK      5
  643 #define EREG_TXACK      6
  644 #define EREG_MDACK      7
  645 
  646 #define EREG_BANKSIZE   8
  647 
  648 #define CD1400_CLK      25000000
  649 #define CD1400_CLK8M    20000000
  650 
  651 /*
  652  *      Define the cd1400 baud rate clocks. These are used when calculating
  653  *      what clock and divisor to use for the required baud rate. Also
  654  *      define the maximum baud rate allowed, and the default base baud.
  655  */
  656 static int      stl_cd1400clkdivs[] = {
  657         CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
  658 };
  659 
  660 /*
  661  *      Define the maximum baud rate of the cd1400 devices.
  662  */
  663 #define CD1400_MAXBAUD  230400
  664 
  665 /*****************************************************************************/
  666 
  667 /*
  668  *      SC26198 UART specific data initization.
  669  */
  670 static uart_t stl_sc26198uart = {
  671         stl_sc26198panelinit,
  672         stl_sc26198portinit,
  673         stl_sc26198setport,
  674         stl_sc26198getsignals,
  675         stl_sc26198setsignals,
  676         stl_sc26198enablerxtx,
  677         stl_sc26198startrxtx,
  678         stl_sc26198disableintrs,
  679         stl_sc26198sendbreak,
  680         stl_sc26198sendflow,
  681         stl_sc26198flush,
  682         stl_sc26198datastate,
  683         stl_sc26198intr
  684 };
  685 
  686 /*
  687  *      Define the offsets within the register bank of a sc26198 based panel.
  688  */
  689 #define XP_DATA         0
  690 #define XP_ADDR         1
  691 #define XP_MODID        2
  692 #define XP_STATUS       2
  693 #define XP_IACK         3
  694 
  695 #define XP_BANKSIZE     4
  696 
  697 /*
  698  *      Define the sc26198 baud rate table. Offsets within the table
  699  *      represent the actual baud rate selector of sc26198 registers.
  700  */
  701 static unsigned int     sc26198_baudtable[] = {
  702         50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
  703         4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
  704         230400, 460800
  705 };
  706 
  707 #define SC26198_NRBAUDS         (sizeof(sc26198_baudtable) / sizeof(unsigned int))
  708 
  709 /*
  710  *      Define the maximum baud rate of the sc26198 devices.
  711  */
  712 #define SC26198_MAXBAUD 460800
  713 
  714 /*****************************************************************************/
  715 
  716 /*
  717  *      Declare the driver isa structure.
  718  */
  719 struct isa_driver       stldriver = {
  720         stlprobe, stlattach, "stl"
  721 };
  722 
  723 /*****************************************************************************/
  724 
  725 #if NPCI > 0
  726 
  727 /*
  728  *      Declare the driver pci structure.
  729  */
  730 static unsigned long    stl_count;
  731 
  732 static struct pci_device        stlpcidriver = {
  733         "stl",
  734         stlpciprobe,
  735         stlpciattach,
  736         &stl_count,
  737         NULL,
  738 };
  739 
  740 COMPAT_PCI_DRIVER (stlpci, stlpcidriver);
  741 
  742 #endif
  743 
  744 /*****************************************************************************/
  745 
  746 
  747 /*
  748  *      FreeBSD-2.2+ kernel linkage.
  749  */
  750 
  751 #define CDEV_MAJOR      72
  752 static struct cdevsw stl_cdevsw = {
  753         /* open */      stlopen,
  754         /* close */     stlclose,
  755         /* read */      ttyread,
  756         /* write */     ttywrite,
  757         /* ioctl */     stlioctl,
  758         /* poll */      ttypoll,
  759         /* mmap */      nommap,
  760         /* strategy */  nostrategy,
  761         /* name */      "stl",
  762         /* maj */       CDEV_MAJOR,
  763         /* dump */      nodump,
  764         /* psize */     nopsize,
  765         /* flags */     D_TTY,
  766         /* bmaj */      -1
  767 };
  768 
  769 static void stl_drvinit(void *unused)
  770 {
  771 
  772         cdevsw_add(&stl_cdevsw);
  773 }
  774 
  775 SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,stl_drvinit,NULL)
  776 
  777 
  778 
  779 /*****************************************************************************/
  780 
  781 /*
  782  *      Probe for some type of EasyIO or EasyConnection 8/32 board at
  783  *      the supplied address. All we do is check if we can find the
  784  *      board ID for the board... (Note, PCI boards not checked here,
  785  *      they are done in the stlpciprobe() routine).
  786  */
  787 
  788 static int stlprobe(struct isa_device *idp)
  789 {
  790         unsigned int    status;
  791 
  792 #if DEBUG
  793         printf("stlprobe(idp=%x): unit=%d iobase=%x\n", (int) idp,
  794                 idp->id_unit, idp->id_iobase);
  795 #endif
  796 
  797         if (idp->id_unit > STL_MAXBRDS)
  798                 return(0);
  799 
  800         status = inb(idp->id_iobase + 1);
  801         if ((status & ECH_IDBITMASK) == ECH_ID) {
  802                 stl_brdprobed[idp->id_unit] = BRD_ECH;
  803                 return(1);
  804         }
  805 
  806         status = inb(idp->id_iobase + 2);
  807         switch (status & EIO_IDBITMASK) {
  808         case EIO_8PORTRS:
  809         case EIO_8PORTM:
  810         case EIO_8PORTDI:
  811         case EIO_4PORTRS:
  812         case EIO_MK3:
  813                 stl_brdprobed[idp->id_unit] = BRD_EASYIO;
  814                 return(1);
  815         default:
  816                 break;
  817         }
  818         
  819         return(0);
  820 }
  821 
  822 /*****************************************************************************/
  823 
  824 /*
  825  *      Find an available internal board number (unit number). The problem
  826  *      is that the same unit numbers can be assigned to different boards
  827  *      detected during the ISA and PCI initialization phases.
  828  */
  829 
  830 static int stl_findfreeunit()
  831 {
  832         int     i;
  833 
  834         for (i = 0; (i < STL_MAXBRDS); i++)
  835                 if (stl_brds[i] == (stlbrd_t *) NULL)
  836                         break;
  837         return((i >= STL_MAXBRDS) ? -1 : i);
  838 }
  839 
  840 /*****************************************************************************/
  841 
  842 /*
  843  *      Allocate resources for and initialize the specified board.
  844  */
  845 
  846 static int stlattach(struct isa_device *idp)
  847 {
  848         stlbrd_t        *brdp;
  849 
  850 #if DEBUG
  851         printf("stlattach(idp=%p): unit=%d iobase=%x\n", (void *) idp,
  852                 idp->id_unit, idp->id_iobase);
  853 #endif
  854 
  855         idp->id_ointr = stlintr;
  856 
  857         brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT);
  858         if (brdp == (stlbrd_t *) NULL) {
  859                 printf("STALLION: failed to allocate memory (size=%d)\n",
  860                         sizeof(stlbrd_t));
  861                 return(0);
  862         }
  863         bzero(brdp, sizeof(stlbrd_t));
  864 
  865         if ((brdp->brdnr = stl_findfreeunit()) < 0) {
  866                 printf("STALLION: too many boards found, max=%d\n",
  867                         STL_MAXBRDS);
  868                 return(0);
  869         }
  870         if (brdp->brdnr >= stl_nrbrds)
  871                 stl_nrbrds = brdp->brdnr + 1;
  872 
  873         brdp->unitid = idp->id_unit;
  874         brdp->brdtype = stl_brdprobed[idp->id_unit];
  875         brdp->ioaddr1 = idp->id_iobase;
  876         brdp->ioaddr2 = stl_ioshared;
  877         brdp->irq = ffs(idp->id_irq) - 1;
  878         brdp->irqtype = stl_irqshared;
  879         stl_brdinit(brdp);
  880 
  881         return(1);
  882 }
  883 
  884 /*****************************************************************************/
  885 
  886 #if NPCI > 0
  887 
  888 /*
  889  *      Probe specifically for the PCI boards. We need to be a little
  890  *      carefull here, since it looks sort like a Nat Semi IDE chip...
  891  */
  892 
  893 static const char *stlpciprobe(pcici_t tag, pcidi_t type)
  894 {
  895         unsigned long   class;
  896         int             i, brdtype;
  897 
  898 #if DEBUG
  899         printf("stlpciprobe(tag=%x,type=%x)\n", (int) &tag, (int) type);
  900 #endif
  901 
  902         brdtype = 0;
  903         for (i = 0; (i < stl_nrpcibrds); i++) {
  904                 if (((type & 0xffff) == stl_pcibrds[i].vendid) &&
  905                     (((type >> 16) & 0xffff) == stl_pcibrds[i].devid)) {
  906                         brdtype = stl_pcibrds[i].brdtype;
  907                         break;
  908                 }
  909         }
  910 
  911         if (brdtype == 0)
  912                 return((char *) NULL);
  913 
  914         class = pci_conf_read(tag, PCI_CLASS_REG);
  915         if ((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE)
  916                 return((char *) NULL);
  917 
  918         return(stl_brdnames[brdtype]);
  919 }
  920 
  921 /*****************************************************************************/
  922 
  923 /*
  924  *      Allocate resources for and initialize the specified PCI board.
  925  */
  926 
  927 void stlpciattach(pcici_t tag, int unit)
  928 {
  929         stlbrd_t        *brdp;
  930         unsigned int    bar[4];
  931         unsigned int    id;
  932         int             i;
  933 
  934 #if DEBUG
  935         printf("stlpciattach(tag=%x,unit=%x)\n", (int) &tag, unit);
  936 #endif
  937 
  938         brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT);
  939         if (brdp == (stlbrd_t *) NULL) {
  940                 printf("STALLION: failed to allocate memory (size=%d)\n",
  941                         sizeof(stlbrd_t));
  942                 return;
  943         }
  944         bzero(brdp, sizeof(stlbrd_t));
  945 
  946         if ((unit < 0) || (unit > STL_MAXBRDS)) {
  947                 printf("STALLION: bad PCI board unit number=%d\n", unit);
  948                 return;
  949         }
  950 
  951 /*
  952  *      Allocate us a new driver unique unit number.
  953  */
  954         if ((brdp->brdnr = stl_findfreeunit()) < 0) {
  955                 printf("STALLION: too many boards found, max=%d\n",
  956                         STL_MAXBRDS);
  957                 return;
  958         }
  959         if (brdp->brdnr >= stl_nrbrds)
  960                 stl_nrbrds = brdp->brdnr + 1;
  961 
  962 /*
  963  *      Determine what type of PCI board this is...
  964  */
  965         id = (unsigned int) pci_conf_read(tag, 0x0);
  966         for (i = 0; (i < stl_nrpcibrds); i++) {
  967                 if (((id & 0xffff) == stl_pcibrds[i].vendid) &&
  968                     (((id >> 16) & 0xffff) == stl_pcibrds[i].devid)) {
  969                         brdp->brdtype = stl_pcibrds[i].brdtype;
  970                         break;
  971                 }
  972         }
  973 
  974         if (i >= stl_nrpcibrds) {
  975                 printf("STALLION: probed PCI board unknown type=%x\n", id);
  976                 return;
  977         }
  978 
  979         for (i = 0; (i < 4); i++)
  980                 bar[i] = (unsigned int) pci_conf_read(tag, 0x10 + (i * 4)) &
  981                         0xfffc;
  982 
  983         switch (brdp->brdtype) {
  984         case BRD_ECH64PCI:
  985                 brdp->ioaddr1 = bar[1];
  986                 brdp->ioaddr2 = bar[2];
  987                 break;
  988         case BRD_EASYIOPCI:
  989                 brdp->ioaddr1 = bar[2];
  990                 brdp->ioaddr2 = bar[1];
  991                 break;
  992         case BRD_ECHPCI:
  993                 brdp->ioaddr1 = bar[1];
  994                 brdp->ioaddr2 = bar[0];
  995                 break;
  996         default:
  997                 printf("STALLION: unknown PCI board type=%d\n", brdp->brdtype);
  998                 return;
  999                 break;
 1000         }
 1001 
 1002         brdp->unitid = 0;
 1003         brdp->irq = ((int) pci_conf_read(tag, 0x3c)) & 0xff;
 1004         brdp->irqtype = 0;
 1005         if (pci_map_int(tag, stlpciintr, (void *) NULL, &tty_imask) == 0) {
 1006                 printf("STALLION: failed to map interrupt irq=%d for unit=%d\n",
 1007                         brdp->irq, brdp->brdnr);
 1008                 return;
 1009         }
 1010 
 1011         stl_brdinit(brdp);
 1012 }
 1013 
 1014 #endif
 1015 
 1016 /*****************************************************************************/
 1017 
 1018 STATIC int stlopen(dev_t dev, int flag, int mode, struct proc *p)
 1019 {
 1020         struct tty      *tp;
 1021         stlport_t       *portp;
 1022         int             error, callout, x;
 1023 
 1024 #if DEBUG
 1025         printf("stlopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
 1026                 mode, (int) p);
 1027 #endif
 1028 
 1029 /*
 1030  *      Firstly check if the supplied device number is a valid device.
 1031  */
 1032         if (minor(dev) & STL_MEMDEV)
 1033                 return(0);
 1034 
 1035         portp = stl_dev2port(dev);
 1036         if (portp == (stlport_t *) NULL)
 1037                 return(ENXIO);
 1038         if (minor(dev) & STL_CTRLDEV)
 1039                 return(0);
 1040         tp = &portp->tty;
 1041         dev->si_tty = tp;
 1042         callout = minor(dev) & STL_CALLOUTDEV;
 1043         error = 0;
 1044 
 1045         x = spltty();
 1046 
 1047 stlopen_restart:
 1048 /*
 1049  *      Wait here for the DTR drop timeout period to expire.
 1050  */
 1051         while (portp->state & ASY_DTRWAIT) {
 1052                 error = tsleep(&portp->dtrwait, (TTIPRI | PCATCH),
 1053                         "stldtr", 0);
 1054                 if (error)
 1055                         goto stlopen_end;
 1056         }
 1057         
 1058 /*
 1059  *      We have a valid device, so now we check if it is already open.
 1060  *      If not then initialize the port hardware and set up the tty
 1061  *      struct as required.
 1062  */
 1063         if ((tp->t_state & TS_ISOPEN) == 0) {
 1064                 tp->t_oproc = stl_start;
 1065                 tp->t_stop = stl_stop;
 1066                 tp->t_param = stl_param;
 1067                 tp->t_dev = dev;
 1068                 tp->t_termios = callout ? portp->initouttios :
 1069                         portp->initintios;
 1070                 stl_rawopen(portp);
 1071                 ttsetwater(tp);
 1072                 if ((portp->sigs & TIOCM_CD) || callout)
 1073                         (*linesw[tp->t_line].l_modem)(tp, 1);
 1074         } else {
 1075                 if (callout) {
 1076                         if (portp->callout == 0) {
 1077                                 error = EBUSY;
 1078                                 goto stlopen_end;
 1079                         }
 1080                 } else {
 1081                         if (portp->callout != 0) {
 1082                                 if (flag & O_NONBLOCK) {
 1083                                         error = EBUSY;
 1084                                         goto stlopen_end;
 1085                                 }
 1086                                 error = tsleep(&portp->callout,
 1087                                         (TTIPRI | PCATCH), "stlcall", 0);
 1088                                 if (error)
 1089                                         goto stlopen_end;
 1090                                 goto stlopen_restart;
 1091                         }
 1092                 }
 1093                 if ((tp->t_state & TS_XCLUDE) && (p->p_ucred->cr_uid != 0)) {
 1094                         error = EBUSY;
 1095                         goto stlopen_end;
 1096                 }
 1097         }
 1098 
 1099 /*
 1100  *      If this port is not the callout device and we do not have carrier
 1101  *      then we need to sleep, waiting for it to be asserted.
 1102  */
 1103         if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
 1104             ((tp->t_cflag & CLOCAL) == 0) && ((flag & O_NONBLOCK) == 0)) {
 1105                 portp->waitopens++;
 1106                 error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stldcd", 0);
 1107                 portp->waitopens--;
 1108                 if (error)
 1109                         goto stlopen_end;
 1110                 goto stlopen_restart;
 1111         }
 1112 
 1113 /*
 1114  *      Open the line discipline.
 1115  */
 1116         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1117         stl_ttyoptim(portp, &tp->t_termios);
 1118         if ((tp->t_state & TS_ISOPEN) && callout)
 1119                 portp->callout = 1;
 1120 
 1121 /*
 1122  *      If for any reason we get to here and the port is not actually
 1123  *      open then close of the physical hardware - no point leaving it
 1124  *      active when the open failed...
 1125  */
 1126 stlopen_end:
 1127         splx(x);
 1128         if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
 1129                 stl_rawclose(portp);
 1130 
 1131         return(error);
 1132 }
 1133 
 1134 /*****************************************************************************/
 1135 
 1136 STATIC int stlclose(dev_t dev, int flag, int mode, struct proc *p)
 1137 {
 1138         struct tty      *tp;
 1139         stlport_t       *portp;
 1140         int             x;
 1141 
 1142 #if DEBUG
 1143         printf("stlclose(dev=%s,flag=%x,mode=%x,p=%p)\n", devtoname(dev),
 1144                 flag, mode, (void *) p);
 1145 #endif
 1146 
 1147         if (minor(dev) & STL_MEMDEV)
 1148                 return(0);
 1149         if (minor(dev) & STL_CTRLDEV)
 1150                 return(0);
 1151 
 1152         portp = stl_dev2port(dev);
 1153         if (portp == (stlport_t *) NULL)
 1154                 return(ENXIO);
 1155         tp = &portp->tty;
 1156 
 1157         x = spltty();
 1158         (*linesw[tp->t_line].l_close)(tp, flag);
 1159         stl_ttyoptim(portp, &tp->t_termios);
 1160         stl_rawclose(portp);
 1161         ttyclose(tp);
 1162         splx(x);
 1163         return(0);
 1164 }
 1165 
 1166 /*****************************************************************************/
 1167 
 1168 STATIC void stl_stop(struct tty *tp, int rw)
 1169 {
 1170 #if DEBUG
 1171         printf("stlstop(tp=%x,rw=%x)\n", (int) tp, rw);
 1172 #endif
 1173 
 1174         stl_flush((stlport_t *) tp, rw);
 1175 }
 1176 
 1177 
 1178 /*****************************************************************************/
 1179 
 1180 STATIC int stlioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
 1181                     struct proc *p)
 1182 {
 1183         struct termios  *newtios, *localtios;
 1184         struct tty      *tp;
 1185         stlport_t       *portp;
 1186         int             error, i, x;
 1187 
 1188 #if DEBUG
 1189         printf("stlioctl(dev=%s,cmd=%lx,data=%p,flag=%x,p=%p)\n",
 1190                 devtoname(dev), cmd, (void *) data, flag, (void *) p);
 1191 #endif
 1192 
 1193         if (minor(dev) & STL_MEMDEV)
 1194                 return(stl_memioctl(dev, cmd, data, flag, p));
 1195 
 1196         portp = stl_dev2port(dev);
 1197         if (portp == (stlport_t *) NULL)
 1198                 return(ENODEV);
 1199         tp = &portp->tty;
 1200         error = 0;
 1201         
 1202 /*
 1203  *      First up handle ioctls on the control devices.
 1204  */
 1205         if (minor(dev) & STL_CTRLDEV) {
 1206                 if ((minor(dev) & STL_CTRLDEV) == STL_CTRLINIT)
 1207                         localtios = (minor(dev) & STL_CALLOUTDEV) ?
 1208                                 &portp->initouttios : &portp->initintios;
 1209                 else if ((minor(dev) & STL_CTRLDEV) == STL_CTRLLOCK)
 1210                         localtios = (minor(dev) & STL_CALLOUTDEV) ?
 1211                                 &portp->lockouttios : &portp->lockintios;
 1212                 else
 1213                         return(ENODEV);
 1214 
 1215                 switch (cmd) {
 1216                 case TIOCSETA:
 1217                         if ((error = suser(p)) == 0)
 1218                                 *localtios = *((struct termios *) data);
 1219                         break;
 1220                 case TIOCGETA:
 1221                         *((struct termios *) data) = *localtios;
 1222                         break;
 1223                 case TIOCGETD:
 1224                         *((int *) data) = TTYDISC;
 1225                         break;
 1226                 case TIOCGWINSZ:
 1227                         bzero(data, sizeof(struct winsize));
 1228                         break;
 1229                 default:
 1230                         error = ENOTTY;
 1231                         break;
 1232                 }
 1233                 return(error);
 1234         }
 1235 
 1236 /*
 1237  *      Deal with 4.3 compatability issues if we have too...
 1238  */
 1239 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1240         if (1) {
 1241                 struct termios  tios;
 1242                 unsigned long   oldcmd;
 1243 
 1244                 tios = tp->t_termios;
 1245                 oldcmd = cmd;
 1246                 if ((error = ttsetcompat(tp, &cmd, data, &tios)))
 1247                         return(error);
 1248                 if (cmd != oldcmd)
 1249                         data = (caddr_t) &tios;
 1250         }
 1251 #endif
 1252 
 1253 /*
 1254  *      Carry out some pre-cmd processing work first...
 1255  *      Hmmm, not so sure we want this, disable for now...
 1256  */
 1257         if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1258                 newtios = (struct termios *) data;
 1259                 localtios = (minor(dev) & STL_CALLOUTDEV) ? 
 1260                         &portp->lockouttios : &portp->lockintios;
 1261 
 1262                 newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
 1263                         (newtios->c_iflag & ~localtios->c_iflag);
 1264                 newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
 1265                         (newtios->c_oflag & ~localtios->c_oflag);
 1266                 newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
 1267                         (newtios->c_cflag & ~localtios->c_cflag);
 1268                 newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
 1269                         (newtios->c_lflag & ~localtios->c_lflag);
 1270                 for (i = 0; (i < NCCS); i++) {
 1271                         if (localtios->c_cc[i] != 0)
 1272                                 newtios->c_cc[i] = tp->t_cc[i];
 1273                 }
 1274                 if (localtios->c_ispeed != 0)
 1275                         newtios->c_ispeed = tp->t_ispeed;
 1276                 if (localtios->c_ospeed != 0)
 1277                         newtios->c_ospeed = tp->t_ospeed;
 1278         }
 1279 
 1280 /*
 1281  *      Call the line discipline and the common command processing to
 1282  *      process this command (if they can).
 1283  */
 1284         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 1285         if (error != ENOIOCTL)
 1286                 return(error);
 1287 
 1288         x = spltty();
 1289         error = ttioctl(tp, cmd, data, flag);
 1290         stl_ttyoptim(portp, &tp->t_termios);
 1291         if (error != ENOIOCTL) {
 1292                 splx(x);
 1293                 return(error);
 1294         }
 1295 
 1296         error = 0;
 1297 
 1298 /*
 1299  *      Process local commands here. These are all commands that only we
 1300  *      can take care of (they all rely on actually doing something special
 1301  *      to the actual hardware).
 1302  */
 1303         switch (cmd) {
 1304         case TIOCSBRK:
 1305                 stl_sendbreak(portp, -1);
 1306                 break;
 1307         case TIOCCBRK:
 1308                 stl_sendbreak(portp, -2);
 1309                 break;
 1310         case TIOCSDTR:
 1311                 stl_setsignals(portp, 1, -1);
 1312                 break;
 1313         case TIOCCDTR:
 1314                 stl_setsignals(portp, 0, -1);
 1315                 break;
 1316         case TIOCMSET:
 1317                 i = *((int *) data);
 1318                 stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : 0),
 1319                         ((i & TIOCM_RTS) ? 1 : 0));
 1320                 break;
 1321         case TIOCMBIS:
 1322                 i = *((int *) data);
 1323                 stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : -1),
 1324                         ((i & TIOCM_RTS) ? 1 : -1));
 1325                 break;
 1326         case TIOCMBIC:
 1327                 i = *((int *) data);
 1328                 stl_setsignals(portp, ((i & TIOCM_DTR) ? 0 : -1),
 1329                         ((i & TIOCM_RTS) ? 0 : -1));
 1330                 break;
 1331         case TIOCMGET:
 1332                 *((int *) data) = (stl_getsignals(portp) | TIOCM_LE);
 1333                 break;
 1334         case TIOCMSDTRWAIT:
 1335                 if ((error = suser(p)) == 0)
 1336                         portp->dtrwait = *((int *) data) * hz / 100;
 1337                 break;
 1338         case TIOCMGDTRWAIT:
 1339                 *((int *) data) = portp->dtrwait * 100 / hz;
 1340                 break;
 1341         case TIOCTIMESTAMP:
 1342                 portp->dotimestamp = 1;
 1343                 *((struct timeval *) data) = portp->timestamp;
 1344                 break;
 1345         default:
 1346                 error = ENOTTY;
 1347                 break;
 1348         }
 1349         splx(x);
 1350 
 1351         return(error);
 1352 }
 1353 
 1354 /*****************************************************************************/
 1355 
 1356 /*
 1357  *      Convert the specified minor device number into a port struct
 1358  *      pointer. Return NULL if the device number is not a valid port.
 1359  */
 1360 
 1361 STATIC stlport_t *stl_dev2port(dev_t dev)
 1362 {
 1363         stlbrd_t        *brdp;
 1364 
 1365         brdp = stl_brds[MKDEV2BRD(dev)];
 1366         if (brdp == (stlbrd_t *) NULL)
 1367                 return((stlport_t *) NULL);
 1368         return(brdp->ports[MKDEV2PORT(dev)]);
 1369 }
 1370 
 1371 /*****************************************************************************/
 1372 
 1373 /*
 1374  *      Initialize the port hardware. This involves enabling the transmitter
 1375  *      and receiver, setting the port configuration, and setting the initial
 1376  *      signal state.
 1377  */
 1378 
 1379 static int stl_rawopen(stlport_t *portp)
 1380 {
 1381 #if DEBUG
 1382         printf("stl_rawopen(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
 1383                 (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
 1384 #endif
 1385 
 1386         stl_setport(portp, &portp->tty.t_termios);
 1387         portp->sigs = stl_getsignals(portp);
 1388         stl_setsignals(portp, 1, 1);
 1389         stl_enablerxtx(portp, 1, 1);
 1390         stl_startrxtx(portp, 1, 0);
 1391         return(0);
 1392 }
 1393 
 1394 /*****************************************************************************/
 1395 
 1396 /*
 1397  *      Shutdown the hardware of a port. Disable its transmitter and
 1398  *      receiver, and maybe drop signals if appropriate.
 1399  */
 1400 
 1401 static int stl_rawclose(stlport_t *portp)
 1402 {
 1403         struct tty      *tp;
 1404 
 1405 #if DEBUG
 1406         printf("stl_rawclose(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
 1407                 (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
 1408 #endif
 1409 
 1410         tp = &portp->tty;
 1411         stl_disableintrs(portp);
 1412         stl_enablerxtx(portp, 0, 0);
 1413         stl_flush(portp, (FWRITE | FREAD));
 1414         if (tp->t_cflag & HUPCL) {
 1415                 stl_setsignals(portp, 0, 0);
 1416                 if (portp->dtrwait != 0) {
 1417                         portp->state |= ASY_DTRWAIT;
 1418                         timeout(stl_dtrwakeup, portp, portp->dtrwait);
 1419                 }
 1420         }
 1421         portp->callout = 0;
 1422         portp->brklen = 0;
 1423         portp->state &= ~(ASY_ACTIVE | ASY_RTSFLOW);
 1424         wakeup(&portp->callout);
 1425         wakeup(TSA_CARR_ON(tp));
 1426         return(0);
 1427 }
 1428 
 1429 /*****************************************************************************/
 1430 
 1431 /*
 1432  *      Clear the DTR waiting flag, and wake up any sleepers waiting for
 1433  *      DTR wait period to finish.
 1434  */
 1435 
 1436 static void stl_dtrwakeup(void *arg)
 1437 {
 1438         stlport_t       *portp;
 1439 
 1440         portp = (stlport_t *) arg;
 1441         portp->state &= ~ASY_DTRWAIT;
 1442         wakeup(&portp->dtrwait);
 1443 }
 1444 
 1445 /*****************************************************************************/
 1446 
 1447 /*
 1448  *      Start (or continue) the transfer of TX data on this port. If the
 1449  *      port is not currently busy then load up the interrupt ring queue
 1450  *      buffer and kick of the transmitter. If the port is running low on
 1451  *      TX data then refill the ring queue. This routine is also used to
 1452  *      activate input flow control.
 1453  */
 1454 
 1455 static void stl_start(struct tty *tp)
 1456 {
 1457         stlport_t       *portp;
 1458         unsigned int    len, stlen;
 1459         char            *head, *tail;
 1460         int             count, x;
 1461 
 1462         portp = (stlport_t *) tp;
 1463 
 1464 #if DEBUG
 1465         printf("stl_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp, 
 1466                 portp->brdnr, portp->portnr);
 1467 #endif
 1468 
 1469         x = spltty();
 1470 
 1471 /*
 1472  *      Check if the ports input has been blocked, and take appropriate action.
 1473  *      Not very often do we really need to do anything, so make it quick.
 1474  */
 1475         if (tp->t_state & TS_TBLOCK) {
 1476                 if ((portp->state & ASY_RTSFLOWMODE) &&
 1477                     ((portp->state & ASY_RTSFLOW) == 0))
 1478                         stl_flowcontrol(portp, 0, -1);
 1479         } else {
 1480                 if (portp->state & ASY_RTSFLOW)
 1481                         stl_flowcontrol(portp, 1, -1);
 1482         }
 1483 
 1484 
 1485         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1486                 splx(x);
 1487                 return;
 1488         }
 1489 
 1490 /*
 1491  *      Copy data from the clists into the interrupt ring queue. This will
 1492  *      require at most 2 copys... What we do is calculate how many chars
 1493  *      can fit into the ring queue, and how many can fit in 1 copy. If after
 1494  *      the first copy there is still more room then do the second copy. 
 1495  *      The beauty of this type of ring queue is that we do not need to
 1496  *      spl protect our-selves, since we only ever update the head pointer,
 1497  *      and the interrupt routine only ever updates the tail pointer.
 1498  */
 1499         if (tp->t_outq.c_cc != 0) {
 1500                 head = portp->tx.head;
 1501                 tail = portp->tx.tail;
 1502                 if (head >= tail) {
 1503                         len = STL_TXBUFSIZE - (head - tail) - 1;
 1504                         stlen = portp->tx.endbuf - head;
 1505                 } else {
 1506                         len = tail - head - 1;
 1507                         stlen = len;
 1508                 }
 1509 
 1510                 if (len > 0) {
 1511                         stlen = MIN(len, stlen);
 1512                         count = q_to_b(&tp->t_outq, head, stlen);
 1513                         len -= count;
 1514                         head += count;
 1515                         if (head >= portp->tx.endbuf) {
 1516                                 head = portp->tx.buf;
 1517                                 if (len > 0) {
 1518                                         stlen = q_to_b(&tp->t_outq, head, len);
 1519                                         head += stlen;
 1520                                         count += stlen;
 1521                                 }
 1522                         }
 1523                         portp->tx.head = head;
 1524                         if (count > 0)
 1525                                 stl_startrxtx(portp, -1, 1);
 1526                 }
 1527 
 1528 /*
 1529  *              If we sent something, make sure we are called again.
 1530  */
 1531                 tp->t_state |= TS_BUSY;
 1532         }
 1533 
 1534 /*
 1535  *      Do any writer wakeups.
 1536  */
 1537         ttwwakeup(tp);
 1538 
 1539         splx(x);
 1540 }
 1541 
 1542 /*****************************************************************************/
 1543 
 1544 static void stl_flush(stlport_t *portp, int flag)
 1545 {
 1546         char    *head, *tail;
 1547         int     len, x;
 1548 
 1549 #if DEBUG
 1550         printf("stl_flush(portp=%x,flag=%x)\n", (int) portp, flag);
 1551 #endif
 1552 
 1553         if (portp == (stlport_t *) NULL)
 1554                 return;
 1555 
 1556         x = spltty();
 1557 
 1558         if (flag & FWRITE) {
 1559                 stl_uartflush(portp, FWRITE);
 1560                 portp->tx.tail = portp->tx.head;
 1561         }
 1562 
 1563 /*
 1564  *      The only thing to watch out for when flushing the read side is
 1565  *      the RX status buffer. The interrupt code relys on the status
 1566  *      bytes as being zeroed all the time (it does not bother setting
 1567  *      a good char status to 0, it expects that it already will be).
 1568  *      We also need to un-flow the RX channel if flow control was
 1569  *      active.
 1570  */
 1571         if (flag & FREAD) {
 1572                 head = portp->rx.head;
 1573                 tail = portp->rx.tail;
 1574                 if (head != tail) {
 1575                         if (head >= tail) {
 1576                                 len = head - tail;
 1577                         } else {
 1578                                 len = portp->rx.endbuf - tail;
 1579                                 bzero(portp->rxstatus.buf,
 1580                                         (head - portp->rx.buf));
 1581                         }
 1582                         bzero((tail + STL_RXBUFSIZE), len);
 1583                         portp->rx.tail = head;
 1584                 }
 1585                 stl_uartflush(portp, FREAD);
 1586 
 1587                 if ((portp->state & ASY_RTSFLOW) &&
 1588                     ((portp->tty.t_state & TS_TBLOCK) == 0))
 1589                         stl_flowcontrol(portp, 1, -1);
 1590         }
 1591 
 1592         splx(x);
 1593 }
 1594 
 1595 /*****************************************************************************/
 1596 
 1597 /*
 1598  *      Interrupt handler for host based boards. Interrupts for all boards
 1599  *      are vectored through here.
 1600  */
 1601 
 1602 void stlintr(int unit)
 1603 {
 1604         stlbrd_t        *brdp;
 1605         int             i;
 1606 
 1607 #if DEBUG
 1608         printf("stlintr(unit=%d)\n", unit);
 1609 #endif
 1610 
 1611         for (i = 0; (i < stl_nrbrds); i++) {
 1612                 if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
 1613                         continue;
 1614                 if (brdp->state == 0)
 1615                         continue;
 1616                 (* brdp->isr)(brdp);
 1617         }
 1618 }
 1619 
 1620 /*****************************************************************************/
 1621 
 1622 #if NPCI > 0
 1623 #if VFREEBSD >= 220
 1624 
 1625 static void stlpciintr(void *arg)
 1626 {
 1627         stlintr(0);
 1628 }
 1629 
 1630 #else
 1631 
 1632 static int stlpciintr(void *arg)
 1633 {
 1634         stlintr(0);
 1635         return(0);
 1636 }
 1637 
 1638 #endif
 1639 #endif
 1640 
 1641 /*****************************************************************************/
 1642 
 1643 /*
 1644  *      Interrupt service routine for EasyIO boards.
 1645  */
 1646 
 1647 static void stl_eiointr(stlbrd_t *brdp)
 1648 {
 1649         stlpanel_t      *panelp;
 1650         int             iobase;
 1651 
 1652 #if DEBUG
 1653         printf("stl_eiointr(brdp=%x)\n", brdp);
 1654 #endif
 1655 
 1656         panelp = (stlpanel_t *) brdp->panels[0];
 1657         iobase = panelp->iobase;
 1658         while (inb(brdp->iostatus) & EIO_INTRPEND)
 1659                 (* panelp->isr)(panelp, iobase);
 1660 }
 1661 
 1662 /*****************************************************************************/
 1663 
 1664 /*
 1665  *      Interrupt service routine for ECH-AT board types.
 1666  */
 1667 
 1668 static void stl_echatintr(stlbrd_t *brdp)
 1669 {
 1670         stlpanel_t      *panelp;
 1671         unsigned int    ioaddr;
 1672         int             bnknr;
 1673 
 1674         outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
 1675 
 1676         while (inb(brdp->iostatus) & ECH_INTRPEND) {
 1677                 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 1678                         ioaddr = brdp->bnkstataddr[bnknr];
 1679                         if (inb(ioaddr) & ECH_PNLINTRPEND) {
 1680                                 panelp = brdp->bnk2panel[bnknr];
 1681                                 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
 1682                         }
 1683                 }
 1684         }
 1685 
 1686         outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
 1687 }
 1688 
 1689 /*****************************************************************************/
 1690 
 1691 /*
 1692  *      Interrupt service routine for ECH-MCA board types.
 1693  */
 1694 
 1695 static void stl_echmcaintr(stlbrd_t *brdp)
 1696 {
 1697         stlpanel_t      *panelp;
 1698         unsigned int    ioaddr;
 1699         int             bnknr;
 1700 
 1701         while (inb(brdp->iostatus) & ECH_INTRPEND) {
 1702                 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 1703                         ioaddr = brdp->bnkstataddr[bnknr];
 1704                         if (inb(ioaddr) & ECH_PNLINTRPEND) {
 1705                                 panelp = brdp->bnk2panel[bnknr];
 1706                                 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
 1707                         }
 1708                 }
 1709         }
 1710 }
 1711 
 1712 /*****************************************************************************/
 1713 
 1714 /*
 1715  *      Interrupt service routine for ECH-PCI board types.
 1716  */
 1717 
 1718 static void stl_echpciintr(stlbrd_t *brdp)
 1719 {
 1720         stlpanel_t      *panelp;
 1721         unsigned int    ioaddr;
 1722         int             bnknr, recheck;
 1723 
 1724 #if DEBUG
 1725         printf("stl_echpciintr(brdp=%x)\n", (int) brdp);
 1726 #endif
 1727 
 1728         for (;;) {
 1729                 recheck = 0;
 1730                 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 1731                         outb(brdp->ioctrl, brdp->bnkpageaddr[bnknr]);
 1732                         ioaddr = brdp->bnkstataddr[bnknr];
 1733                         if (inb(ioaddr) & ECH_PNLINTRPEND) {
 1734                                 panelp = brdp->bnk2panel[bnknr];
 1735                                 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
 1736                                 recheck++;
 1737                         }
 1738                 }
 1739                 if (! recheck)
 1740                         break;
 1741         }
 1742 }
 1743 
 1744 /*****************************************************************************/
 1745 
 1746 /*
 1747  *      Interrupt service routine for EC8/64-PCI board types.
 1748  */
 1749 
 1750 static void stl_echpci64intr(stlbrd_t *brdp)
 1751 {
 1752         stlpanel_t      *panelp;
 1753         unsigned int    ioaddr;
 1754         int             bnknr;
 1755 
 1756 #if DEBUG
 1757         printf("stl_echpci64intr(brdp=%x)\n", (int) brdp);
 1758 #endif
 1759 
 1760         while (inb(brdp->ioctrl) & 0x1) {
 1761                 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 1762                         ioaddr = brdp->bnkstataddr[bnknr];
 1763 #if DEBUG
 1764 printf("    --> ioaddr=%x status=%x(%x)\n", ioaddr, inb(ioaddr) & ECH_PNLINTRPEND, inb(ioaddr));
 1765 #endif
 1766                         if (inb(ioaddr) & ECH_PNLINTRPEND) {
 1767                                 panelp = brdp->bnk2panel[bnknr];
 1768                                 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
 1769                         }
 1770                 }
 1771         }
 1772 }
 1773 
 1774 /*****************************************************************************/
 1775 
 1776 /*
 1777  *      If we haven't scheduled a timeout then do it, some port needs high
 1778  *      level processing.
 1779  */
 1780 
 1781 static void stl_dotimeout()
 1782 {
 1783 #if DEBUG
 1784         printf("stl_dotimeout()\n");
 1785 #endif
 1786 
 1787         if (stl_doingtimeout == 0) {
 1788                 timeout(stl_poll, 0, 1);
 1789                 stl_doingtimeout++;
 1790         }
 1791 }
 1792 
 1793 /*****************************************************************************/
 1794 
 1795 /*
 1796  *      Service "software" level processing. Too slow or painfull to be done
 1797  *      at real hardware interrupt time. This way we might also be able to
 1798  *      do some service on other waiting ports as well...
 1799  */
 1800 
 1801 static void stl_poll(void *arg)
 1802 {
 1803         stlbrd_t        *brdp;
 1804         stlport_t       *portp;
 1805         struct tty      *tp;
 1806         int             brdnr, portnr, rearm, x;
 1807 
 1808 #if DEBUG
 1809         printf("stl_poll()\n");
 1810 #endif
 1811 
 1812         stl_doingtimeout = 0;
 1813         rearm = 0;
 1814 
 1815         x = spltty();
 1816         for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
 1817                 if ((brdp = stl_brds[brdnr]) == (stlbrd_t *) NULL)
 1818                         continue;
 1819                 for (portnr = 0; (portnr < brdp->nrports); portnr++) {
 1820                         if ((portp = brdp->ports[portnr]) == (stlport_t *) NULL)
 1821                                 continue;
 1822                         if ((portp->state & ASY_ACTIVE) == 0)
 1823                                 continue;
 1824                         tp = &portp->tty;
 1825 
 1826                         if (portp->state & ASY_RXDATA)
 1827                                 stl_rxprocess(portp);
 1828                         if (portp->state & ASY_DCDCHANGE) {
 1829                                 portp->state &= ~ASY_DCDCHANGE;
 1830                                 portp->sigs = stl_getsignals(portp);
 1831                                 (*linesw[tp->t_line].l_modem)(tp,
 1832                                         (portp->sigs & TIOCM_CD));
 1833                         }
 1834                         if (portp->state & ASY_TXEMPTY) {
 1835                                 if (stl_datastate(portp) == 0) {
 1836                                         portp->state &= ~ASY_TXEMPTY;
 1837                                         tp->t_state &= ~TS_BUSY;
 1838                                         (*linesw[tp->t_line].l_start)(tp);
 1839                                 }
 1840                         }
 1841                         if (portp->state & ASY_TXLOW) {
 1842                                 portp->state &= ~ASY_TXLOW;
 1843                                 (*linesw[tp->t_line].l_start)(tp);
 1844                         }
 1845 
 1846                         if (portp->state & ASY_ACTIVE)
 1847                                 rearm++;
 1848                 }
 1849         }
 1850         splx(x);
 1851 
 1852         if (rearm)
 1853                 stl_dotimeout();
 1854 }
 1855 
 1856 /*****************************************************************************/
 1857 
 1858 /*
 1859  *      Process the RX data that has been buffered up in the RX ring queue.
 1860  */
 1861 
 1862 static void stl_rxprocess(stlport_t *portp)
 1863 {
 1864         struct tty      *tp;
 1865         unsigned int    len, stlen, lostlen;
 1866         char            *head, *tail;
 1867         char            status;
 1868         int             ch;
 1869 
 1870 #if DEBUG
 1871         printf("stl_rxprocess(portp=%x): brdnr=%d portnr=%d\n", (int) portp, 
 1872                 portp->brdnr, portp->portnr);
 1873 #endif
 1874 
 1875         tp = &portp->tty;
 1876         portp->state &= ~ASY_RXDATA;
 1877 
 1878         if ((tp->t_state & TS_ISOPEN) == 0) {
 1879                 stl_flush(portp, FREAD);
 1880                 return;
 1881         }
 1882 
 1883 /*
 1884  *      Calculate the amount of data in the RX ring queue. Also calculate
 1885  *      the largest single copy size...
 1886  */
 1887         head = portp->rx.head;
 1888         tail = portp->rx.tail;
 1889         if (head >= tail) {
 1890                 len = head - tail;
 1891                 stlen = len;
 1892         } else {
 1893                 len = STL_RXBUFSIZE - (tail - head);
 1894                 stlen = portp->rx.endbuf - tail;
 1895         }
 1896 
 1897         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 1898                 if (len > 0) {
 1899                         if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
 1900                             ((portp->state & ASY_RTSFLOWMODE) ||
 1901                             (tp->t_iflag & IXOFF)) &&
 1902                             ((tp->t_state & TS_TBLOCK) == 0)) {
 1903                                 ch = TTYHOG - tp->t_rawq.c_cc - 1;
 1904                                 len = (ch > 0) ? ch : 0;
 1905                                 stlen = MIN(stlen, len);
 1906                                 ttyblock(tp);
 1907                         }
 1908                         lostlen = b_to_q(tail, stlen, &tp->t_rawq);
 1909                         tail += stlen;
 1910                         len -= stlen;
 1911                         if (tail >= portp->rx.endbuf) {
 1912                                 tail = portp->rx.buf;
 1913                                 lostlen += b_to_q(tail, len, &tp->t_rawq);
 1914                                 tail += len;
 1915                         }
 1916                         portp->stats.rxlost += lostlen;
 1917                         ttwakeup(tp);
 1918                         portp->rx.tail = tail;
 1919                 }
 1920         } else {
 1921                 while (portp->rx.tail != head) {
 1922                         ch = (unsigned char) *(portp->rx.tail);
 1923                         if ((status = *(portp->rx.tail + STL_RXBUFSIZE))) {
 1924                                 *(portp->rx.tail + STL_RXBUFSIZE) = 0;
 1925                                 if (status & ST_BREAK)
 1926                                         ch |= TTY_BI;
 1927                                 if (status & ST_FRAMING)
 1928                                         ch |= TTY_FE;
 1929                                 if (status & ST_PARITY)
 1930                                         ch |= TTY_PE;
 1931                                 if (status & ST_OVERRUN)
 1932                                         ch |= TTY_OE;
 1933                         }
 1934                         (*linesw[tp->t_line].l_rint)(ch, tp);
 1935                         if (portp->rx.tail == head)
 1936                                 break;
 1937 
 1938                         if (++(portp->rx.tail) >= portp->rx.endbuf)
 1939                                 portp->rx.tail = portp->rx.buf;
 1940                 }
 1941         }
 1942 
 1943         if (head != portp->rx.tail)
 1944                 portp->state |= ASY_RXDATA;
 1945 
 1946 /*
 1947  *      If we where flow controled then maybe the buffer is low enough that
 1948  *      we can re-activate it.
 1949  */
 1950         if ((portp->state & ASY_RTSFLOW) && ((tp->t_state & TS_TBLOCK) == 0))
 1951                 stl_flowcontrol(portp, 1, -1);
 1952 }
 1953 
 1954 /*****************************************************************************/
 1955 
 1956 static int stl_param(struct tty *tp, struct termios *tiosp)
 1957 {
 1958         stlport_t       *portp;
 1959 
 1960         portp = (stlport_t *) tp;
 1961         if (portp == (stlport_t *) NULL)
 1962                 return(ENODEV);
 1963 
 1964         return(stl_setport(portp, tiosp));
 1965 }
 1966 
 1967 /*****************************************************************************/
 1968 
 1969 /*
 1970  *      Action the flow control as required. The hw and sw args inform the
 1971  *      routine what flow control methods it should try.
 1972  */
 1973 
 1974 static void stl_flowcontrol(stlport_t *portp, int hw, int sw)
 1975 {
 1976         unsigned char   *head, *tail;
 1977         int             len, hwflow;
 1978 
 1979 #if DEBUG
 1980         printf("stl_flowcontrol(portp=%x,hw=%d,sw=%d)\n", (int) portp, hw, sw);
 1981 #endif
 1982 
 1983         hwflow = -1;
 1984 
 1985         if (portp->state & ASY_RTSFLOWMODE) {
 1986                 if (hw == 0) {
 1987                         if ((portp->state & ASY_RTSFLOW) == 0)
 1988                                 hwflow = 0;
 1989                 } else if (hw > 0) {
 1990                         if (portp->state & ASY_RTSFLOW) {
 1991                                 head = portp->rx.head;
 1992                                 tail = portp->rx.tail;
 1993                                 len = (head >= tail) ? (head - tail) :
 1994                                         (STL_RXBUFSIZE - (tail - head));
 1995                                 if (len < STL_RXBUFHIGH)
 1996                                         hwflow = 1;
 1997                         }
 1998                 }
 1999         }
 2000 
 2001 /*
 2002  *      We have worked out what to do, if anything. So now apply it to the
 2003  *      UART port.
 2004  */
 2005         stl_sendflow(portp, hwflow, sw);
 2006 }
 2007 
 2008 /*****************************************************************************/
 2009 
 2010 /*
 2011  *      Enable l_rint processing bypass mode if tty modes allow it.
 2012  */
 2013 
 2014 static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp)
 2015 {
 2016         struct tty      *tp;
 2017 
 2018         tp = &portp->tty;
 2019         if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP)) == 0) &&
 2020             (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
 2021             (((tiosp->c_iflag & PARMRK) == 0) ||
 2022             ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
 2023             ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
 2024             (linesw[tp->t_line].l_rint == ttyinput))
 2025                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 2026         else
 2027                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 2028 
 2029         if (tp->t_line == SLIPDISC)
 2030                 portp->hotchar = 0xc0;
 2031         else if (tp->t_line == PPPDISC)
 2032                 portp->hotchar = 0x7e;
 2033         else
 2034                 portp->hotchar = 0;
 2035 }
 2036 
 2037 /*****************************************************************************/
 2038 
 2039 /*
 2040  *      Try and find and initialize all the ports on a panel. We don't care
 2041  *      what sort of board these ports are on - since the port io registers
 2042  *      are almost identical when dealing with ports.
 2043  */
 2044 
 2045 static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp, int strtport)
 2046 {
 2047         stlport_t       *portp;
 2048         unsigned int    chipmask;
 2049         int             i, j;
 2050         unsigned int    mindev, unit;
 2051 
 2052 #if DEBUG
 2053         printf("stl_initports(panelp=%x)\n", (int) panelp);
 2054 #endif
 2055 
 2056         chipmask = stl_panelinit(brdp, panelp);
 2057 
 2058 /*
 2059  *      All UART's are initialized if found. Now go through and setup
 2060  *      each ports data structures. Also initialize each individual
 2061  *      UART port.
 2062  */
 2063         for (i = 0; (i < panelp->nrports); i++) {
 2064                 portp = (stlport_t *) malloc(sizeof(stlport_t), M_TTYS,
 2065                         M_NOWAIT);
 2066                 if (portp == (stlport_t *) NULL) {
 2067                         printf("STALLION: failed to allocate port memory "
 2068                                 "(size=%d)\n", sizeof(stlport_t));
 2069                         break;
 2070                 }
 2071                 bzero(portp, sizeof(stlport_t));
 2072 
 2073                 portp->portnr = i;
 2074                 portp->brdnr = panelp->brdnr;
 2075                 portp->panelnr = panelp->panelnr;
 2076                 portp->uartp = panelp->uartp;
 2077                 portp->clk = brdp->clk;
 2078                 panelp->ports[i] = portp;
 2079 
 2080                 j = STL_TXBUFSIZE + (2 * STL_RXBUFSIZE);
 2081                 portp->tx.buf = (char *) malloc(j, M_TTYS, M_NOWAIT);
 2082                 if (portp->tx.buf == (char *) NULL) {
 2083                         printf("STALLION: failed to allocate buffer memory "
 2084                                 "(size=%d)\n", j);
 2085                         break;
 2086                 }
 2087                 portp->tx.endbuf = portp->tx.buf + STL_TXBUFSIZE;
 2088                 portp->tx.head = portp->tx.buf;
 2089                 portp->tx.tail = portp->tx.buf;
 2090                 portp->rx.buf = portp->tx.buf + STL_TXBUFSIZE;
 2091                 portp->rx.endbuf = portp->rx.buf + STL_RXBUFSIZE;
 2092                 portp->rx.head = portp->rx.buf;
 2093                 portp->rx.tail = portp->rx.buf;
 2094                 portp->rxstatus.buf = portp->rx.buf + STL_RXBUFSIZE;
 2095                 portp->rxstatus.endbuf = portp->rxstatus.buf + STL_RXBUFSIZE;
 2096                 portp->rxstatus.head = portp->rxstatus.buf;
 2097                 portp->rxstatus.tail = portp->rxstatus.buf;
 2098                 bzero(portp->rxstatus.head, STL_RXBUFSIZE);
 2099 
 2100                 portp->initintios.c_ispeed = STL_DEFSPEED;
 2101                 portp->initintios.c_ospeed = STL_DEFSPEED;
 2102                 portp->initintios.c_cflag = STL_DEFCFLAG;
 2103                 portp->initintios.c_iflag = 0;
 2104                 portp->initintios.c_oflag = 0;
 2105                 portp->initintios.c_lflag = 0;
 2106                 bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
 2107                         sizeof(portp->initintios.c_cc));
 2108                 portp->initouttios = portp->initintios;
 2109                 portp->dtrwait = 3 * hz;
 2110 
 2111                 stl_portinit(brdp, panelp, portp);
 2112 
 2113 /*
 2114  *              If using the device file system then set up the device
 2115  *              nodes for this port. Ports above 32 use the extended minor
 2116  *              number bits (in the upper 2 bytes of the device number).
 2117  */
 2118                 unit = strtport + portp->portnr;
 2119                 mindev = ((portp->brdnr & 0x7) << 20) | 
 2120                         (unit & 0x1f) | ((unit & 0x20) << 11);
 2121                 unit += (portp->brdnr * STL_PORTSPERBRD);
 2122 
 2123                 portp->dev_ttyE = make_dev(&stl_cdevsw, mindev,
 2124                         UID_ROOT, GID_WHEEL, 0600, "ttyE%d", unit);
 2125                 portp->dev_ttyiE = make_dev(&stl_cdevsw,
 2126                         (mindev | STL_CTRLINIT),
 2127                         UID_ROOT, GID_WHEEL, 0600, "ttyiE%d", unit);
 2128                 portp->dev_ttylE = make_dev(&stl_cdevsw,
 2129                         (mindev | STL_CTRLLOCK),
 2130                         UID_ROOT, GID_WHEEL, 0600, "ttylE%d", unit);
 2131                 portp->dev_cue = make_dev(&stl_cdevsw,
 2132                         (mindev | STL_CALLOUTDEV),
 2133                         UID_UUCP, GID_DIALER, 0660, "cue%d", unit);
 2134                 portp->dev_cuie = make_dev(&stl_cdevsw,
 2135                         (mindev | STL_CTRLINIT | STL_CALLOUTDEV),
 2136                         UID_UUCP, GID_DIALER, 0660, "cuie%d", unit);
 2137                 portp->dev_cule = make_dev(&stl_cdevsw,
 2138                         (mindev | STL_CTRLLOCK | STL_CALLOUTDEV), 
 2139                         UID_UUCP, GID_DIALER, 0660, "cule%d", unit);
 2140         }
 2141 
 2142         return(0);
 2143 }
 2144 
 2145 /*****************************************************************************/
 2146 
 2147 /*
 2148  *      Try to find and initialize an EasyIO board.
 2149  */
 2150 
 2151 static int stl_initeio(stlbrd_t *brdp)
 2152 {
 2153         stlpanel_t      *panelp;
 2154         unsigned int    status;
 2155 
 2156 #if DEBUG
 2157         printf("stl_initeio(brdp=%x)\n", (int) brdp);
 2158 #endif
 2159 
 2160         brdp->ioctrl = brdp->ioaddr1 + 1;
 2161         brdp->iostatus = brdp->ioaddr1 + 2;
 2162         brdp->clk = EIO_CLK;
 2163         brdp->isr = stl_eiointr;
 2164 
 2165         status = inb(brdp->iostatus);
 2166         switch (status & EIO_IDBITMASK) {
 2167         case EIO_8PORTM:
 2168                 brdp->clk = EIO_CLK8M;
 2169                 /* fall thru */
 2170         case EIO_8PORTRS:
 2171         case EIO_8PORTDI:
 2172                 brdp->nrports = 8;
 2173                 break;
 2174         case EIO_4PORTRS:
 2175                 brdp->nrports = 4;
 2176                 break;
 2177         case EIO_MK3:
 2178                 switch (status & EIO_BRDMASK) {
 2179                 case ID_BRD4:
 2180                         brdp->nrports = 4;
 2181                         break;
 2182                 case ID_BRD8:
 2183                         brdp->nrports = 8;
 2184                         break;
 2185                 case ID_BRD16:
 2186                         brdp->nrports = 16;
 2187                         break;
 2188                 default:
 2189                         return(ENODEV);
 2190                 }
 2191                 brdp->ioctrl++;
 2192                 break;
 2193         default:
 2194                 return(ENODEV);
 2195         }
 2196 
 2197         if (brdp->brdtype == BRD_EASYIOPCI) {
 2198                 outb((brdp->ioaddr2 + 0x4c), 0x41);
 2199         } else {
 2200 /*
 2201  *              Check that the supplied IRQ is good and then use it to
 2202  *              setup the programmable interrupt bits on EIO board.
 2203  *              Also set the edge/level triggered interrupt bit.
 2204  */
 2205                 if ((brdp->irq < 0) || (brdp->irq > 15) ||
 2206                     (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 2207                         printf("STALLION: invalid irq=%d for brd=%d\n",
 2208                                 brdp->irq, brdp->brdnr);
 2209                         return(EINVAL);
 2210                 }
 2211                 outb(brdp->ioctrl, (stl_vecmap[brdp->irq] |
 2212                         ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)));
 2213         }
 2214 
 2215         panelp = (stlpanel_t *) malloc(sizeof(stlpanel_t), M_TTYS, M_NOWAIT);
 2216         if (panelp == (stlpanel_t *) NULL) {
 2217                 printf("STALLION: failed to allocate memory (size=%d)\n",
 2218                         sizeof(stlpanel_t));
 2219                 return(ENOMEM);
 2220         }
 2221         bzero(panelp, sizeof(stlpanel_t));
 2222 
 2223         panelp->brdnr = brdp->brdnr;
 2224         panelp->panelnr = 0;
 2225         panelp->nrports = brdp->nrports;
 2226         panelp->iobase = brdp->ioaddr1;
 2227         panelp->hwid = status;
 2228         if ((status & EIO_IDBITMASK) == EIO_MK3) {
 2229                 panelp->uartp = (void *) &stl_sc26198uart;
 2230                 panelp->isr = stl_sc26198intr;
 2231         } else {
 2232                 panelp->uartp = (void *) &stl_cd1400uart;
 2233                 panelp->isr = stl_cd1400eiointr;
 2234         }
 2235         brdp->panels[0] = panelp;
 2236         brdp->nrpanels = 1;
 2237         brdp->hwid = status;
 2238         brdp->state |= BRD_FOUND;
 2239         return(0);
 2240 }
 2241 
 2242 /*****************************************************************************/
 2243 
 2244 /*
 2245  *      Try to find an ECH board and initialize it. This code is capable of
 2246  *      dealing with all types of ECH board.
 2247  */
 2248 
 2249 static int stl_initech(stlbrd_t *brdp)
 2250 {
 2251         stlpanel_t      *panelp;
 2252         unsigned int    status, nxtid;
 2253         int             panelnr, ioaddr, banknr, i;
 2254 
 2255 #if DEBUG
 2256         printf("stl_initech(brdp=%x)\n", (int) brdp);
 2257 #endif
 2258 
 2259 /*
 2260  *      Set up the initial board register contents for boards. This varys a
 2261  *      bit between the different board types. So we need to handle each
 2262  *      separately. Also do a check that the supplied IRQ is good.
 2263  */
 2264         switch (brdp->brdtype) {
 2265 
 2266         case BRD_ECH:
 2267                 brdp->isr = stl_echatintr;
 2268                 brdp->ioctrl = brdp->ioaddr1 + 1;
 2269                 brdp->iostatus = brdp->ioaddr1 + 1;
 2270                 status = inb(brdp->iostatus);
 2271                 if ((status & ECH_IDBITMASK) != ECH_ID)
 2272                         return(ENODEV);
 2273                 brdp->hwid = status;
 2274 
 2275                 if ((brdp->irq < 0) || (brdp->irq > 15) ||
 2276                     (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 2277                         printf("STALLION: invalid irq=%d for brd=%d\n",
 2278                                 brdp->irq, brdp->brdnr);
 2279                         return(EINVAL);
 2280                 }
 2281                 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
 2282                 status |= (stl_vecmap[brdp->irq] << 1);
 2283                 outb(brdp->ioaddr1, (status | ECH_BRDRESET));
 2284                 brdp->ioctrlval = ECH_INTENABLE |
 2285                         ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
 2286                 outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
 2287                 outb(brdp->ioaddr1, status);
 2288                 break;
 2289 
 2290         case BRD_ECHMC:
 2291                 brdp->isr = stl_echmcaintr;
 2292                 brdp->ioctrl = brdp->ioaddr1 + 0x20;
 2293                 brdp->iostatus = brdp->ioctrl;
 2294                 status = inb(brdp->iostatus);
 2295                 if ((status & ECH_IDBITMASK) != ECH_ID)
 2296                         return(ENODEV);
 2297                 brdp->hwid = status;
 2298 
 2299                 if ((brdp->irq < 0) || (brdp->irq > 15) ||
 2300                     (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 2301                         printf("STALLION: invalid irq=%d for brd=%d\n",
 2302                                 brdp->irq, brdp->brdnr);
 2303                         return(EINVAL);
 2304                 }
 2305                 outb(brdp->ioctrl, ECHMC_BRDRESET);
 2306                 outb(brdp->ioctrl, ECHMC_INTENABLE);
 2307                 break;
 2308 
 2309         case BRD_ECHPCI:
 2310                 brdp->isr = stl_echpciintr;
 2311                 brdp->ioctrl = brdp->ioaddr1 + 2;
 2312                 break;
 2313 
 2314         case BRD_ECH64PCI:
 2315                 brdp->isr = stl_echpci64intr;
 2316                 brdp->ioctrl = brdp->ioaddr2 + 0x40;
 2317                 outb((brdp->ioaddr1 + 0x4c), 0x43);
 2318                 break;
 2319 
 2320         default:
 2321                 printf("STALLION: unknown board type=%d\n", brdp->brdtype);
 2322                 break;
 2323         }
 2324 
 2325         brdp->clk = ECH_CLK;
 2326 
 2327 /*
 2328  *      Scan through the secondary io address space looking for panels.
 2329  *      As we find'em allocate and initialize panel structures for each.
 2330  */
 2331         ioaddr = brdp->ioaddr2;
 2332         panelnr = 0;
 2333         nxtid = 0;
 2334         banknr = 0;
 2335 
 2336         for (i = 0; (i < STL_MAXPANELS); i++) {
 2337                 /*
 2338                  * ECH and ECHMC boards have a limit of 32 ports, so when
 2339                  * we hit that limit, stop scanning.  The stock driver
 2340                  * has a test to see if the number of boards overflows the
 2341                  * address space allocated, but this test is wrong in that
 2342                  * we have no way to probe additional cards beyond the 32nd
 2343                  * port.  So when we get to 32 ports, stop.
 2344                  */
 2345                 if (brdp->brdtype == BRD_ECH || brdp->brdtype == BRD_ECHMC) {
 2346                         if (brdp->nrports == 32)
 2347                                 break;
 2348                 }
 2349                 /*
 2350                  * ECHPCI boards multiplex pannels at ioaddr2, rather than
 2351                  * having the address regions contiguous like other boards.
 2352                  */
 2353                 if (brdp->brdtype == BRD_ECHPCI) {
 2354                         outb(brdp->ioctrl, nxtid);
 2355                         ioaddr = brdp->ioaddr2;
 2356                 }
 2357                 status = inb(ioaddr + ECH_PNLSTATUS);
 2358                 if ((status & ECH_PNLIDMASK) != nxtid)
 2359                         break;
 2360                 panelp = (stlpanel_t *) malloc(sizeof(stlpanel_t), M_TTYS,
 2361                         M_NOWAIT);
 2362                 if (panelp == (stlpanel_t *) NULL) {
 2363                         printf("STALLION: failed to allocate memory"
 2364                                 "(size=%d)\n", sizeof(stlpanel_t));
 2365                         break;
 2366                 }
 2367                 bzero(panelp, sizeof(stlpanel_t));
 2368                 panelp->brdnr = brdp->brdnr;
 2369                 panelp->panelnr = panelnr;
 2370                 panelp->iobase = ioaddr;
 2371                 panelp->pagenr = nxtid;
 2372                 panelp->hwid = status;
 2373                 brdp->bnk2panel[banknr] = panelp;
 2374                 brdp->bnkpageaddr[banknr] = nxtid;
 2375                 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
 2376 
 2377                 if (status & ECH_PNLXPID) {
 2378                         panelp->uartp = (void *) &stl_sc26198uart;
 2379                         panelp->isr = stl_sc26198intr;
 2380                         if (status & ECH_PNL16PORT) {
 2381                                 panelp->nrports = 16;
 2382                                 brdp->bnk2panel[banknr] = panelp;
 2383                                 brdp->bnkpageaddr[banknr] = nxtid;
 2384                                 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
 2385                                         ECH_PNLSTATUS;
 2386                         } else {
 2387                                 panelp->nrports = 8;
 2388                         }
 2389                 } else {
 2390                         panelp->uartp = (void *) &stl_cd1400uart;
 2391                         panelp->isr = stl_cd1400echintr;
 2392                         if (status & ECH_PNL16PORT) {
 2393                                 /*
 2394                                  * Handle the 8 + 16 + 16 and the 
 2395                                  * 8 + 8 + 8 + 16 cases of bad configuration
 2396                                  * for the EC8/32 class of boards.
 2397                                  */
 2398                                 if ((brdp->brdtype == BRD_ECH
 2399                                     || brdp->brdtype == BRD_ECHMC) &&
 2400                                     (brdp->nrports + 16 > 32)) {
 2401                                         printf(
 2402 "STALLION: Limit of 32 ports exceeded, remove last module on board %d\n",
 2403 brdp->unitid);
 2404                                         free(panelp, M_TTYS);
 2405                                         banknr--;
 2406                                         brdp->bnk2panel[banknr] = 0;
 2407                                         brdp->bnkpageaddr[banknr] = 0;
 2408                                         brdp->bnkstataddr[banknr] = 0;
 2409                                         break;
 2410                                 }
 2411                                 panelp->nrports = 16;
 2412                                 panelp->ackmask = 0x80;
 2413                                 if (brdp->brdtype != BRD_ECHPCI)
 2414                                         ioaddr += EREG_BANKSIZE;
 2415                                 brdp->bnk2panel[banknr] = panelp;
 2416                                 brdp->bnkpageaddr[banknr] = ++nxtid;
 2417                                 brdp->bnkstataddr[banknr++] = ioaddr +
 2418                                         ECH_PNLSTATUS;
 2419                         } else {
 2420                                 panelp->nrports = 8;
 2421                                 panelp->ackmask = 0xc0;
 2422                         }
 2423                 }
 2424 
 2425                 nxtid++;
 2426                 ioaddr += EREG_BANKSIZE;
 2427                 brdp->nrports += panelp->nrports;
 2428                 brdp->panels[panelnr++] = panelp;
 2429         }
 2430 
 2431         brdp->nrpanels = panelnr;
 2432         brdp->nrbnks = banknr;
 2433         if (brdp->brdtype == BRD_ECH)
 2434                 outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
 2435 
 2436         brdp->state |= BRD_FOUND;
 2437         return(0);
 2438 }
 2439 
 2440 /*****************************************************************************/
 2441 
 2442 /*
 2443  *      Initialize and configure the specified board. This firstly probes
 2444  *      for the board, if it is found then the board is initialized and
 2445  *      then all its ports are initialized as well.
 2446  */
 2447 
 2448 static int stl_brdinit(stlbrd_t *brdp)
 2449 {
 2450         stlpanel_t      *panelp;
 2451         int             i, j, k;
 2452 
 2453 #if DEBUG
 2454         printf("stl_brdinit(brdp=%x): unit=%d type=%d io1=%x io2=%x irq=%d\n",
 2455                 (int) brdp, brdp->brdnr, brdp->brdtype, brdp->ioaddr1,
 2456                 brdp->ioaddr2, brdp->irq);
 2457 #endif
 2458 
 2459         switch (brdp->brdtype) {
 2460         case BRD_EASYIO:
 2461         case BRD_EASYIOPCI:
 2462                 stl_initeio(brdp);
 2463                 break;
 2464         case BRD_ECH:
 2465         case BRD_ECHMC:
 2466         case BRD_ECHPCI:
 2467         case BRD_ECH64PCI:
 2468                 stl_initech(brdp);
 2469                 break;
 2470         default:
 2471                 printf("STALLION: unit=%d is unknown board type=%d\n",
 2472                         brdp->brdnr, brdp->brdtype);
 2473                 return(ENODEV);
 2474         }
 2475 
 2476         stl_brds[brdp->brdnr] = brdp;
 2477         if ((brdp->state & BRD_FOUND) == 0) {
 2478 #if 0
 2479                 printf("STALLION: %s board not found, unit=%d io=%x irq=%d\n",
 2480                         stl_brdnames[brdp->brdtype], brdp->brdnr,
 2481                         brdp->ioaddr1, brdp->irq);
 2482 #endif
 2483                 return(ENODEV);
 2484         }
 2485 
 2486         for (i = 0, k = 0; (i < STL_MAXPANELS); i++) {
 2487                 panelp = brdp->panels[i];
 2488                 if (panelp != (stlpanel_t *) NULL) {
 2489                         stl_initports(brdp, panelp, k);
 2490                         for (j = 0; (j < panelp->nrports); j++)
 2491                                 brdp->ports[k++] = panelp->ports[j];
 2492                 }
 2493         }
 2494 
 2495         printf("stl%d: %s (driver version %s) unit=%d nrpanels=%d nrports=%d\n",
 2496                 brdp->unitid, stl_brdnames[brdp->brdtype], stl_drvversion,
 2497                 brdp->brdnr, brdp->nrpanels, brdp->nrports);
 2498 
 2499         brdp->dev_staliomem = make_dev(&stl_cdevsw, (0x1000000 + brdp->brdnr), 
 2500                  UID_ROOT, GID_WHEEL, 0600, "staliomem%d", brdp->brdnr);
 2501 
 2502         return(0);
 2503 }
 2504 
 2505 /*****************************************************************************/
 2506 
 2507 /*
 2508  *      Return the board stats structure to user app.
 2509  */
 2510 
 2511 static int stl_getbrdstats(caddr_t data)
 2512 {
 2513         stlbrd_t        *brdp;
 2514         stlpanel_t      *panelp;
 2515         int             i;
 2516 
 2517         stl_brdstats = *((combrd_t *) data);
 2518         if (stl_brdstats.brd >= STL_MAXBRDS)
 2519                 return(ENODEV);
 2520         brdp = stl_brds[stl_brdstats.brd];
 2521         if (brdp == (stlbrd_t *) NULL)
 2522                 return(ENODEV);
 2523 
 2524         bzero(&stl_brdstats, sizeof(combrd_t));
 2525         stl_brdstats.brd = brdp->brdnr;
 2526         stl_brdstats.type = brdp->brdtype;
 2527         stl_brdstats.hwid = brdp->hwid;
 2528         stl_brdstats.state = brdp->state;
 2529         stl_brdstats.ioaddr = brdp->ioaddr1;
 2530         stl_brdstats.ioaddr2 = brdp->ioaddr2;
 2531         stl_brdstats.irq = brdp->irq;
 2532         stl_brdstats.nrpanels = brdp->nrpanels;
 2533         stl_brdstats.nrports = brdp->nrports;
 2534         for (i = 0; (i < brdp->nrpanels); i++) {
 2535                 panelp = brdp->panels[i];
 2536                 stl_brdstats.panels[i].panel = i;
 2537                 stl_brdstats.panels[i].hwid = panelp->hwid;
 2538                 stl_brdstats.panels[i].nrports = panelp->nrports;
 2539         }
 2540 
 2541         *((combrd_t *) data) = stl_brdstats;;
 2542         return(0);
 2543 }
 2544 
 2545 /*****************************************************************************/
 2546 
 2547 /*
 2548  *      Resolve the referenced port number into a port struct pointer.
 2549  */
 2550 
 2551 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
 2552 {
 2553         stlbrd_t        *brdp;
 2554         stlpanel_t      *panelp;
 2555 
 2556         if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
 2557                 return((stlport_t *) NULL);
 2558         brdp = stl_brds[brdnr];
 2559         if (brdp == (stlbrd_t *) NULL)
 2560                 return((stlport_t *) NULL);
 2561         if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
 2562                 return((stlport_t *) NULL);
 2563         panelp = brdp->panels[panelnr];
 2564         if (panelp == (stlpanel_t *) NULL)
 2565                 return((stlport_t *) NULL);
 2566         if ((portnr < 0) || (portnr >= panelp->nrports))
 2567                 return((stlport_t *) NULL);
 2568         return(panelp->ports[portnr]);
 2569 }
 2570 
 2571 /*****************************************************************************/
 2572 
 2573 /*
 2574  *      Return the port stats structure to user app. A NULL port struct
 2575  *      pointer passed in means that we need to find out from the app
 2576  *      what port to get stats for (used through board control device).
 2577  */
 2578 
 2579 static int stl_getportstats(stlport_t *portp, caddr_t data)
 2580 {
 2581         unsigned char   *head, *tail;
 2582 
 2583         if (portp == (stlport_t *) NULL) {
 2584                 stl_comstats = *((comstats_t *) data);
 2585                 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
 2586                         stl_comstats.port);
 2587                 if (portp == (stlport_t *) NULL)
 2588                         return(ENODEV);
 2589         }
 2590 
 2591         portp->stats.state = portp->state;
 2592         /*portp->stats.flags = portp->flags;*/
 2593         portp->stats.hwid = portp->hwid;
 2594         portp->stats.ttystate = portp->tty.t_state;
 2595         portp->stats.cflags = portp->tty.t_cflag;
 2596         portp->stats.iflags = portp->tty.t_iflag;
 2597         portp->stats.oflags = portp->tty.t_oflag;
 2598         portp->stats.lflags = portp->tty.t_lflag;
 2599 
 2600         head = portp->tx.head;
 2601         tail = portp->tx.tail;
 2602         portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
 2603                 (STL_TXBUFSIZE - (tail - head)));
 2604 
 2605         head = portp->rx.head;
 2606         tail = portp->rx.tail;
 2607         portp->stats.rxbuffered = (head >= tail) ? (head - tail) :
 2608                 (STL_RXBUFSIZE - (tail - head));
 2609 
 2610         portp->stats.signals = (unsigned long) stl_getsignals(portp);
 2611 
 2612         *((comstats_t *) data) = portp->stats;
 2613         return(0);
 2614 }
 2615 
 2616 /*****************************************************************************/
 2617 
 2618 /*
 2619  *      Clear the port stats structure. We also return it zeroed out...
 2620  */
 2621 
 2622 static int stl_clrportstats(stlport_t *portp, caddr_t data)
 2623 {
 2624         if (portp == (stlport_t *) NULL) {
 2625                 stl_comstats = *((comstats_t *) data);
 2626                 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
 2627                         stl_comstats.port);
 2628                 if (portp == (stlport_t *) NULL)
 2629                         return(ENODEV);
 2630         }
 2631 
 2632         bzero(&portp->stats, sizeof(comstats_t));
 2633         portp->stats.brd = portp->brdnr;
 2634         portp->stats.panel = portp->panelnr;
 2635         portp->stats.port = portp->portnr;
 2636         *((comstats_t *) data) = stl_comstats;
 2637         return(0);
 2638 }
 2639 
 2640 /*****************************************************************************/
 2641 
 2642 /*
 2643  *      The "staliomem" device is used for stats collection in this driver.
 2644  */
 2645 
 2646 #if VFREEBSD >= 310
 2647 static int stl_memioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 2648 #else
 2649 static int stl_memioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 2650 #endif
 2651 {
 2652         int     rc;
 2653 
 2654 #if DEBUG
 2655         printf("stl_memioctl(dev=%x,cmd=%x,data=%x,flag=%x)\n", (int) dev,
 2656                 cmd, (int) data, flag);
 2657 #endif
 2658 
 2659         rc = 0;
 2660 
 2661         switch (cmd) {
 2662         case COM_GETPORTSTATS:
 2663                 rc = stl_getportstats((stlport_t *) NULL, data);
 2664                 break;
 2665         case COM_CLRPORTSTATS:
 2666                 rc = stl_clrportstats((stlport_t *) NULL, data);
 2667                 break;
 2668         case COM_GETBRDSTATS:
 2669                 rc = stl_getbrdstats(data);
 2670                 break;
 2671         default:
 2672                 rc = ENOTTY;
 2673                 break;
 2674         }
 2675 
 2676         return(rc);
 2677 }
 2678 
 2679 /*****************************************************************************/
 2680 /*                         CD1400 UART CODE                                  */
 2681 /*****************************************************************************/
 2682 
 2683 /*
 2684  *      These functions get/set/update the registers of the cd1400 UARTs.
 2685  *      Access to the cd1400 registers is via an address/data io port pair.
 2686  */
 2687 
 2688 static int stl_cd1400getreg(stlport_t *portp, int regnr)
 2689 {
 2690         outb(portp->ioaddr, (regnr + portp->uartaddr));
 2691         return(inb(portp->ioaddr + EREG_DATA));
 2692 }
 2693 
 2694 /*****************************************************************************/
 2695 
 2696 static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
 2697 {
 2698         outb(portp->ioaddr, (regnr + portp->uartaddr));
 2699         outb((portp->ioaddr + EREG_DATA), value);
 2700 }
 2701 
 2702 /*****************************************************************************/
 2703 
 2704 static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
 2705 {
 2706         outb(portp->ioaddr, (regnr + portp->uartaddr));
 2707         if (inb(portp->ioaddr + EREG_DATA) != value) {
 2708                 outb((portp->ioaddr + EREG_DATA), value);
 2709                 return(1);
 2710         }
 2711         return(0);
 2712 }
 2713 
 2714 /*****************************************************************************/
 2715 
 2716 static void stl_cd1400flush(stlport_t *portp, int flag)
 2717 {
 2718         int     x;
 2719 
 2720 #if DEBUG
 2721         printf("stl_cd1400flush(portp=%x,flag=%x)\n", (int) portp, flag);
 2722 #endif
 2723 
 2724         if (portp == (stlport_t *) NULL)
 2725                 return;
 2726 
 2727         x = spltty();
 2728 
 2729         if (flag & FWRITE) {
 2730                 BRDENABLE(portp->brdnr, portp->pagenr);
 2731                 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 2732                 stl_cd1400ccrwait(portp);
 2733                 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
 2734                 stl_cd1400ccrwait(portp);
 2735                 BRDDISABLE(portp->brdnr);
 2736         }
 2737 
 2738         if (flag & FREAD) {
 2739                 /* Hmmm */
 2740         }
 2741 
 2742         splx(x);
 2743 }
 2744 
 2745 /*****************************************************************************/
 2746 
 2747 static void stl_cd1400ccrwait(stlport_t *portp)
 2748 {
 2749         int     i;
 2750 
 2751         for (i = 0; (i < CCR_MAXWAIT); i++) {
 2752                 if (stl_cd1400getreg(portp, CCR) == 0)
 2753                         return;
 2754         }
 2755 
 2756         printf("stl%d: cd1400 device not responding, panel=%d port=%d\n",
 2757             portp->brdnr, portp->panelnr, portp->portnr);
 2758 }
 2759 
 2760 /*****************************************************************************/
 2761 
 2762 /*
 2763  *      Transmit interrupt handler. This has gotta be fast!  Handling TX
 2764  *      chars is pretty simple, stuff as many as possible from the TX buffer
 2765  *      into the cd1400 FIFO. Must also handle TX breaks here, since they
 2766  *      are embedded as commands in the data stream. Oh no, had to use a goto!
 2767  */
 2768 
 2769 static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
 2770 {
 2771         struct tty      *tp;
 2772         stlport_t       *portp;
 2773         unsigned char   ioack, srer;
 2774         char            *head, *tail;
 2775         int             len, stlen;
 2776 
 2777 #if DEBUG
 2778         printf("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
 2779 #endif
 2780 
 2781         ioack = inb(ioaddr + EREG_TXACK);
 2782         if (((ioack & panelp->ackmask) != 0) ||
 2783             ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
 2784                 printf("STALLION: bad TX interrupt ack value=%x\n", ioack);
 2785                 return;
 2786         }
 2787         portp = panelp->ports[(ioack >> 3)];
 2788         tp = &portp->tty;
 2789 
 2790 /*
 2791  *      Unfortunately we need to handle breaks in the data stream, since
 2792  *      this is the only way to generate them on the cd1400. Do it now if
 2793  *      a break is to be sent. Some special cases here: brklen is -1 then
 2794  *      start sending an un-timed break, if brklen is -2 then stop sending
 2795  *      an un-timed break, if brklen is -3 then we have just sent an
 2796  *      un-timed break and do not want any data to go out, if brklen is -4
 2797  *      then a break has just completed so clean up the port settings.
 2798  */
 2799         if (portp->brklen != 0) {
 2800                 if (portp->brklen >= -1) {
 2801                         outb(ioaddr, (TDR + portp->uartaddr));
 2802                         outb((ioaddr + EREG_DATA), ETC_CMD);
 2803                         outb((ioaddr + EREG_DATA), ETC_STARTBREAK);
 2804                         if (portp->brklen > 0) {
 2805                                 outb((ioaddr + EREG_DATA), ETC_CMD);
 2806                                 outb((ioaddr + EREG_DATA), ETC_DELAY);
 2807                                 outb((ioaddr + EREG_DATA), portp->brklen);
 2808                                 outb((ioaddr + EREG_DATA), ETC_CMD);
 2809                                 outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
 2810                                 portp->brklen = -4;
 2811                         } else {
 2812                                 portp->brklen = -3;
 2813                         }
 2814                 } else if (portp->brklen == -2) {
 2815                         outb(ioaddr, (TDR + portp->uartaddr));
 2816                         outb((ioaddr + EREG_DATA), ETC_CMD);
 2817                         outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
 2818                         portp->brklen = -4;
 2819                 } else if (portp->brklen == -3) {
 2820                         outb(ioaddr, (SRER + portp->uartaddr));
 2821                         srer = inb(ioaddr + EREG_DATA);
 2822                         srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
 2823                         outb((ioaddr + EREG_DATA), srer);
 2824                 } else {
 2825                         outb(ioaddr, (COR2 + portp->uartaddr));
 2826                         outb((ioaddr + EREG_DATA),
 2827                                 (inb(ioaddr + EREG_DATA) & ~COR2_ETC));
 2828                         portp->brklen = 0;
 2829                 }
 2830                 goto stl_txalldone;
 2831         }
 2832 
 2833         head = portp->tx.head;
 2834         tail = portp->tx.tail;
 2835         len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
 2836         if ((len == 0) || ((len < STL_TXBUFLOW) &&
 2837             ((portp->state & ASY_TXLOW) == 0))) {
 2838                 portp->state |= ASY_TXLOW;
 2839                 stl_dotimeout();
 2840         }
 2841 
 2842         if (len == 0) {
 2843                 outb(ioaddr, (SRER + portp->uartaddr));
 2844                 srer = inb(ioaddr + EREG_DATA);
 2845                 if (srer & SRER_TXDATA) {
 2846                         srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
 2847                 } else {
 2848                         srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
 2849                         portp->state |= ASY_TXEMPTY;
 2850                         portp->state &= ~ASY_TXBUSY;
 2851                 }
 2852                 outb((ioaddr + EREG_DATA), srer);
 2853         } else {
 2854                 len = MIN(len, CD1400_TXFIFOSIZE);
 2855                 portp->stats.txtotal += len;
 2856                 stlen = MIN(len, (portp->tx.endbuf - tail));
 2857                 outb(ioaddr, (TDR + portp->uartaddr));
 2858                 outsb((ioaddr + EREG_DATA), tail, stlen);
 2859                 len -= stlen;
 2860                 tail += stlen;
 2861                 if (tail >= portp->tx.endbuf)
 2862                         tail = portp->tx.buf;
 2863                 if (len > 0) {
 2864                         outsb((ioaddr + EREG_DATA), tail, len);
 2865                         tail += len;
 2866                 }
 2867                 portp->tx.tail = tail;
 2868         }
 2869 
 2870 stl_txalldone:
 2871         outb(ioaddr, (EOSRR + portp->uartaddr));
 2872         outb((ioaddr + EREG_DATA), 0);
 2873 }
 2874 
 2875 /*****************************************************************************/
 2876 
 2877 /*
 2878  *      Receive character interrupt handler. Determine if we have good chars
 2879  *      or bad chars and then process appropriately.
 2880  */
 2881 
 2882 static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
 2883 {
 2884         stlport_t       *portp;
 2885         struct tty      *tp;
 2886         unsigned int    ioack, len, buflen, stlen;
 2887         unsigned char   status;
 2888         char            ch;
 2889         char            *head, *tail;
 2890 
 2891 #if DEBUG
 2892         printf("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
 2893 #endif
 2894 
 2895         ioack = inb(ioaddr + EREG_RXACK);
 2896         if ((ioack & panelp->ackmask) != 0) {
 2897                 printf("STALLION: bad RX interrupt ack value=%x\n", ioack);
 2898                 return;
 2899         }
 2900         portp = panelp->ports[(ioack >> 3)];
 2901         tp = &portp->tty;
 2902 
 2903 /*
 2904  *      First up, calculate how much room there is in the RX ring queue.
 2905  *      We also want to keep track of the longest possible copy length,
 2906  *      this has to allow for the wrapping of the ring queue.
 2907  */
 2908         head = portp->rx.head;
 2909         tail = portp->rx.tail;
 2910         if (head >= tail) {
 2911                 buflen = STL_RXBUFSIZE - (head - tail) - 1;
 2912                 stlen = portp->rx.endbuf - head;
 2913         } else {
 2914                 buflen = tail - head - 1;
 2915                 stlen = buflen;
 2916         }
 2917 
 2918 /*
 2919  *      Check if the input buffer is near full. If so then we should take
 2920  *      some flow control action... It is very easy to do hardware and
 2921  *      software flow control from here since we have the port selected on
 2922  *      the UART.
 2923  */
 2924         if (buflen <= (STL_RXBUFSIZE - STL_RXBUFHIGH)) {
 2925                 if (((portp->state & ASY_RTSFLOW) == 0) &&
 2926                     (portp->state & ASY_RTSFLOWMODE)) {
 2927                         portp->state |= ASY_RTSFLOW;
 2928                         stl_cd1400setreg(portp, MCOR1,
 2929                                 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
 2930                         stl_cd1400setreg(portp, MSVR2, 0);
 2931                         portp->stats.rxrtsoff++;
 2932                 }
 2933         }
 2934 
 2935 /*
 2936  *      OK we are set, process good data... If the RX ring queue is full
 2937  *      just chuck the chars - don't leave them in the UART.
 2938  */
 2939         if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
 2940                 outb(ioaddr, (RDCR + portp->uartaddr));
 2941                 len = inb(ioaddr + EREG_DATA);
 2942                 if (buflen == 0) {
 2943                         len = MIN(len, sizeof(stl_unwanted));
 2944                         outb(ioaddr, (RDSR + portp->uartaddr));
 2945                         insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
 2946                         portp->stats.rxlost += len;
 2947                         portp->stats.rxtotal += len;
 2948                 } else {
 2949                         len = MIN(len, buflen);
 2950                         portp->stats.rxtotal += len;
 2951                         stlen = MIN(len, stlen);
 2952                         if (len > 0) {
 2953                                 outb(ioaddr, (RDSR + portp->uartaddr));
 2954                                 insb((ioaddr + EREG_DATA), head, stlen);
 2955                                 head += stlen;
 2956                                 if (head >= portp->rx.endbuf) {
 2957                                         head = portp->rx.buf;
 2958                                         len -= stlen;
 2959                                         insb((ioaddr + EREG_DATA), head, len);
 2960                                         head += len;
 2961                                 }
 2962                         }
 2963                 }
 2964         } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
 2965                 outb(ioaddr, (RDSR + portp->uartaddr));
 2966                 status = inb(ioaddr + EREG_DATA);
 2967                 ch = inb(ioaddr + EREG_DATA);
 2968                 if (status & ST_BREAK)
 2969                         portp->stats.rxbreaks++;
 2970                 if (status & ST_FRAMING)
 2971                         portp->stats.rxframing++;
 2972                 if (status & ST_PARITY)
 2973                         portp->stats.rxparity++;
 2974                 if (status & ST_OVERRUN)
 2975                         portp->stats.rxoverrun++;
 2976                 if (status & ST_SCHARMASK) {
 2977                         if ((status & ST_SCHARMASK) == ST_SCHAR1)
 2978                                 portp->stats.txxon++;
 2979                         if ((status & ST_SCHARMASK) == ST_SCHAR2)
 2980                                 portp->stats.txxoff++;
 2981                         goto stl_rxalldone;
 2982                 }
 2983                 if ((portp->rxignoremsk & status) == 0) {
 2984                         if ((tp->t_state & TS_CAN_BYPASS_L_RINT) &&
 2985                             ((status & ST_FRAMING) ||
 2986                             ((status & ST_PARITY) && (tp->t_iflag & INPCK))))
 2987                                 ch = 0;
 2988                         if ((portp->rxmarkmsk & status) == 0)
 2989                                 status = 0;
 2990                         *(head + STL_RXBUFSIZE) = status;
 2991                         *head++ = ch;
 2992                         if (head >= portp->rx.endbuf)
 2993                                 head = portp->rx.buf;
 2994                 }
 2995         } else {
 2996                 printf("STALLION: bad RX interrupt ack value=%x\n", ioack);
 2997                 return;
 2998         }
 2999 
 3000         portp->rx.head = head;
 3001         portp->state |= ASY_RXDATA;
 3002         stl_dotimeout();
 3003 
 3004 stl_rxalldone:
 3005         outb(ioaddr, (EOSRR + portp->uartaddr));
 3006         outb((ioaddr + EREG_DATA), 0);
 3007 }
 3008 
 3009 /*****************************************************************************/
 3010 
 3011 /*
 3012  *      Modem interrupt handler. The is called when the modem signal line
 3013  *      (DCD) has changed state.
 3014  */
 3015 
 3016 static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
 3017 {
 3018         stlport_t       *portp;
 3019         unsigned int    ioack;
 3020         unsigned char   misr;
 3021 
 3022 #if DEBUG
 3023         printf("stl_cd1400mdmisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
 3024 #endif
 3025 
 3026         ioack = inb(ioaddr + EREG_MDACK);
 3027         if (((ioack & panelp->ackmask) != 0) ||
 3028             ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
 3029                 printf("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
 3030                 return;
 3031         }
 3032         portp = panelp->ports[(ioack >> 3)];
 3033 
 3034         outb(ioaddr, (MISR + portp->uartaddr));
 3035         misr = inb(ioaddr + EREG_DATA);
 3036         if (misr & MISR_DCD) {
 3037                 portp->state |= ASY_DCDCHANGE;
 3038                 portp->stats.modem++;
 3039                 stl_dotimeout();
 3040         }
 3041 
 3042         outb(ioaddr, (EOSRR + portp->uartaddr));
 3043         outb((ioaddr + EREG_DATA), 0);
 3044 }
 3045 
 3046 /*****************************************************************************/
 3047 
 3048 /*
 3049  *      Interrupt service routine for cd1400 EasyIO boards.
 3050  */
 3051 
 3052 static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
 3053 {
 3054         unsigned char   svrtype;
 3055 
 3056 #if DEBUG
 3057         printf("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", (int) panelp,
 3058                 iobase);
 3059 #endif
 3060 
 3061         outb(iobase, SVRR);
 3062         svrtype = inb(iobase + EREG_DATA);
 3063         if (panelp->nrports > 4) {
 3064                 outb(iobase, (SVRR + 0x80));
 3065                 svrtype |= inb(iobase + EREG_DATA);
 3066         }
 3067 #if DEBUG
 3068 printf("stl_cd1400eiointr(panelp=%x,iobase=%x): svrr=%x\n", (int) panelp, iobase, svrtype);
 3069 #endif
 3070 
 3071         if (svrtype & SVRR_RX)
 3072                 stl_cd1400rxisr(panelp, iobase);
 3073         else if (svrtype & SVRR_TX)
 3074                 stl_cd1400txisr(panelp, iobase);
 3075         else if (svrtype & SVRR_MDM)
 3076                 stl_cd1400mdmisr(panelp, iobase);
 3077 }
 3078 
 3079 /*****************************************************************************/
 3080 
 3081 /*
 3082  *      Interrupt service routine for cd1400 panels.
 3083  */
 3084 
 3085 static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
 3086 {
 3087         unsigned char   svrtype;
 3088 
 3089 #if DEBUG
 3090         printf("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp,
 3091                 iobase);
 3092 #endif
 3093 
 3094         outb(iobase, SVRR);
 3095         svrtype = inb(iobase + EREG_DATA);
 3096         outb(iobase, (SVRR + 0x80));
 3097         svrtype |= inb(iobase + EREG_DATA);
 3098         if (svrtype & SVRR_RX)
 3099                 stl_cd1400rxisr(panelp, iobase);
 3100         else if (svrtype & SVRR_TX)
 3101                 stl_cd1400txisr(panelp, iobase);
 3102         else if (svrtype & SVRR_MDM)
 3103                 stl_cd1400mdmisr(panelp, iobase);
 3104 }
 3105 
 3106 /*****************************************************************************/
 3107 
 3108 /*
 3109  *      Set up the cd1400 registers for a port based on the termios port
 3110  *      settings.
 3111  */
 3112 
 3113 static int stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
 3114 {
 3115         unsigned int    clkdiv;
 3116         unsigned char   cor1, cor2, cor3;
 3117         unsigned char   cor4, cor5, ccr;
 3118         unsigned char   srer, sreron, sreroff;
 3119         unsigned char   mcor1, mcor2, rtpr;
 3120         unsigned char   clk, div;
 3121         int             x;
 3122 
 3123 #if DEBUG
 3124         printf("stl_cd1400setport(portp=%x,tiosp=%x): brdnr=%d portnr=%d\n",
 3125                 (int) portp, (int) tiosp, portp->brdnr, portp->portnr);
 3126 #endif
 3127 
 3128         cor1 = 0;
 3129         cor2 = 0;
 3130         cor3 = 0;
 3131         cor4 = 0;
 3132         cor5 = 0;
 3133         ccr = 0;
 3134         rtpr = 0;
 3135         clk = 0;
 3136         div = 0;
 3137         mcor1 = 0;
 3138         mcor2 = 0;
 3139         sreron = 0;
 3140         sreroff = 0;
 3141 
 3142 /*
 3143  *      Set up the RX char ignore mask with those RX error types we
 3144  *      can ignore. We could have used some special modes of the cd1400
 3145  *      UART to help, but it is better this way because we can keep stats
 3146  *      on the number of each type of RX exception event.
 3147  */
 3148         portp->rxignoremsk = 0;
 3149         if (tiosp->c_iflag & IGNPAR)
 3150                 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
 3151         if (tiosp->c_iflag & IGNBRK)
 3152                 portp->rxignoremsk |= ST_BREAK;
 3153 
 3154         portp->rxmarkmsk = ST_OVERRUN;
 3155         if (tiosp->c_iflag & (INPCK | PARMRK))
 3156                 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
 3157         if (tiosp->c_iflag & BRKINT)
 3158                 portp->rxmarkmsk |= ST_BREAK;
 3159 
 3160 /*
 3161  *      Go through the char size, parity and stop bits and set all the
 3162  *      option registers appropriately.
 3163  */
 3164         switch (tiosp->c_cflag & CSIZE) {
 3165         case CS5:
 3166                 cor1 |= COR1_CHL5;
 3167                 break;
 3168         case CS6:
 3169                 cor1 |= COR1_CHL6;
 3170                 break;
 3171         case CS7:
 3172                 cor1 |= COR1_CHL7;
 3173                 break;
 3174         default:
 3175                 cor1 |= COR1_CHL8;
 3176                 break;
 3177         }
 3178 
 3179         if (tiosp->c_cflag & CSTOPB)
 3180                 cor1 |= COR1_STOP2;
 3181         else
 3182                 cor1 |= COR1_STOP1;
 3183 
 3184         if (tiosp->c_cflag & PARENB) {
 3185                 if (tiosp->c_cflag & PARODD)
 3186                         cor1 |= (COR1_PARENB | COR1_PARODD);
 3187                 else
 3188                         cor1 |= (COR1_PARENB | COR1_PAREVEN);
 3189         } else {
 3190                 cor1 |= COR1_PARNONE;
 3191         }
 3192 
 3193 /*
 3194  *      Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
 3195  *      space for hardware flow control and the like. This should be set to
 3196  *      VMIN. Also here we will set the RX data timeout to 10ms - this should
 3197  *      really be based on VTIME...
 3198  */
 3199         cor3 |= FIFO_RXTHRESHOLD;
 3200         rtpr = 2;
 3201 
 3202 /*
 3203  *      Calculate the baud rate timers. For now we will just assume that
 3204  *      the input and output baud are the same. Could have used a baud
 3205  *      table here, but this way we can generate virtually any baud rate
 3206  *      we like!
 3207  */
 3208         if (tiosp->c_ispeed == 0)
 3209                 tiosp->c_ispeed = tiosp->c_ospeed;
 3210         if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > CD1400_MAXBAUD))
 3211                 return(EINVAL);
 3212 
 3213         if (tiosp->c_ospeed > 0) {
 3214                 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
 3215                         clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) /
 3216                                 tiosp->c_ospeed);
 3217                         if (clkdiv < 0x100)
 3218                                 break;
 3219                 }
 3220                 div = (unsigned char) clkdiv;
 3221         }
 3222 
 3223 /*
 3224  *      Check what form of modem signaling is required and set it up.
 3225  */
 3226         if ((tiosp->c_cflag & CLOCAL) == 0) {
 3227                 mcor1 |= MCOR1_DCD;
 3228                 mcor2 |= MCOR2_DCD;
 3229                 sreron |= SRER_MODEM;
 3230         }
 3231 
 3232 /*
 3233  *      Setup cd1400 enhanced modes if we can. In particular we want to
 3234  *      handle as much of the flow control as possbile automatically. As
 3235  *      well as saving a few CPU cycles it will also greatly improve flow
 3236  *      control reliablilty.
 3237  */
 3238         if (tiosp->c_iflag & IXON) {
 3239                 cor2 |= COR2_TXIBE;
 3240                 cor3 |= COR3_SCD12;
 3241                 if (tiosp->c_iflag & IXANY)
 3242                         cor2 |= COR2_IXM;
 3243         }
 3244 
 3245         if (tiosp->c_cflag & CCTS_OFLOW)
 3246                 cor2 |= COR2_CTSAE;
 3247         if (tiosp->c_cflag & CRTS_IFLOW)
 3248                 mcor1 |= FIFO_RTSTHRESHOLD;
 3249 
 3250 /*
 3251  *      All cd1400 register values calculated so go through and set them
 3252  *      all up.
 3253  */
 3254 #if DEBUG
 3255         printf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr,
 3256                 portp->panelnr, portp->brdnr);
 3257         printf("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2,
 3258                 cor3, cor4, cor5);
 3259         printf("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
 3260                 mcor1, mcor2, rtpr, sreron, sreroff);
 3261         printf("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
 3262         printf("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
 3263                 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART],
 3264                 tiosp->c_cc[VSTOP]);
 3265 #endif
 3266 
 3267         x = spltty();
 3268         BRDENABLE(portp->brdnr, portp->pagenr);
 3269         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3270         srer = stl_cd1400getreg(portp, SRER);
 3271         stl_cd1400setreg(portp, SRER, 0);
 3272         ccr += stl_cd1400updatereg(portp, COR1, cor1);
 3273         ccr += stl_cd1400updatereg(portp, COR2, cor2);
 3274         ccr += stl_cd1400updatereg(portp, COR3, cor3);
 3275         if (ccr) {
 3276                 stl_cd1400ccrwait(portp);
 3277                 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
 3278         }
 3279         stl_cd1400setreg(portp, COR4, cor4);
 3280         stl_cd1400setreg(portp, COR5, cor5);
 3281         stl_cd1400setreg(portp, MCOR1, mcor1);
 3282         stl_cd1400setreg(portp, MCOR2, mcor2);
 3283         if (tiosp->c_ospeed == 0) {
 3284                 stl_cd1400setreg(portp, MSVR1, 0);
 3285         } else {
 3286                 stl_cd1400setreg(portp, MSVR1, MSVR1_DTR);
 3287                 stl_cd1400setreg(portp, TCOR, clk);
 3288                 stl_cd1400setreg(portp, TBPR, div);
 3289                 stl_cd1400setreg(portp, RCOR, clk);
 3290                 stl_cd1400setreg(portp, RBPR, div);
 3291         }
 3292         stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
 3293         stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
 3294         stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
 3295         stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
 3296         stl_cd1400setreg(portp, RTPR, rtpr);
 3297         mcor1 = stl_cd1400getreg(portp, MSVR1);
 3298         if (mcor1 & MSVR1_DCD)
 3299                 portp->sigs |= TIOCM_CD;
 3300         else
 3301                 portp->sigs &= ~TIOCM_CD;
 3302         stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
 3303         BRDDISABLE(portp->brdnr);
 3304         portp->state &= ~(ASY_RTSFLOWMODE | ASY_CTSFLOWMODE);
 3305         portp->state |= ((tiosp->c_cflag & CRTS_IFLOW) ? ASY_RTSFLOWMODE : 0);
 3306         portp->state |= ((tiosp->c_cflag & CCTS_OFLOW) ? ASY_CTSFLOWMODE : 0);
 3307         stl_ttyoptim(portp, tiosp);
 3308         splx(x);
 3309 
 3310         return(0);
 3311 }
 3312 
 3313 /*****************************************************************************/
 3314 
 3315 /*
 3316  *      Action the flow control as required. The hw and sw args inform the
 3317  *      routine what flow control methods it should try.
 3318  */
 3319 
 3320 static void stl_cd1400sendflow(stlport_t *portp, int hw, int sw)
 3321 {
 3322         int     x;
 3323 
 3324 #if DEBUG
 3325         printf("stl_cd1400sendflow(portp=%x,hw=%d,sw=%d)\n",
 3326                 (int) portp, hw, sw);
 3327 #endif
 3328 
 3329         x = spltty();
 3330         BRDENABLE(portp->brdnr, portp->pagenr);
 3331         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 3332 
 3333         if (sw >= 0) {
 3334                 stl_cd1400ccrwait(portp);
 3335                 if (sw) {
 3336                         stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
 3337                         portp->stats.rxxoff++;
 3338                 } else {
 3339                         stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
 3340                         portp->stats.rxxon++;
 3341                 }
 3342                 stl_cd1400ccrwait(portp);
 3343         }
 3344 
 3345         if (hw == 0) {
 3346                 portp->state |= ASY_RTSFLOW;
 3347                 stl_cd1400setreg(portp, MCOR1,
 3348                         (stl_cd1400getreg(portp, MCOR1) & 0xf0));
 3349                 stl_cd1400setreg(portp, MSVR2, 0);
 3350                 portp->stats.rxrtsoff++;
 3351         } else if (hw > 0) {
 3352                 portp->state &= ~ASY_RTSFLOW;
 3353                 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
 3354                 stl_cd1400setreg(portp, MCOR1,
 3355                         (stl_cd1400getreg(portp, MCOR1) | FIFO_RTSTHRESHOLD));
 3356                 portp->stats.rxrtson++;
 3357         }
 3358 
 3359         BRDDISABLE(portp->brdnr);
 3360         splx(x);
 3361 }
 3362 
 3363 /*****************************************************************************/
 3364 
 3365 /*
 3366  *      Return the current state of data flow on this port. This is only
 3367  *      really interresting when determining if data has fully completed
 3368  *      transmission or not... This is easy for the cd1400, it accurately
 3369  *      maintains the busy port flag.
 3370  */
 3371 
 3372 static int stl_cd1400datastate(stlport_t *portp)
 3373 {
 3374 #if DEBUG
 3375         printf("stl_cd1400datastate(portp=%x)\n", (int) portp);
 3376 #endif
 3377 
 3378         if (portp == (stlport_t *) NULL)
 3379                 return(0);
 3380 
 3381         return((portp->state & ASY_TXBUSY) ? 1 : 0);
 3382 }
 3383 
 3384 /*****************************************************************************/
 3385 
 3386 /*
 3387  *      Set the state of the DTR and RTS signals. Got to do some extra
 3388  *      work here to deal hardware flow control.
 3389  */
 3390 
 3391 static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
 3392 {
 3393         unsigned char   msvr1, msvr2;
 3394         int             x;
 3395 
 3396 #if DEBUG
 3397         printf("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n", (int) portp,
 3398                 dtr, rts);
 3399 #endif
 3400 
 3401         msvr1 = 0;
 3402         msvr2 = 0;
 3403         if (dtr > 0)
 3404                 msvr1 = MSVR1_DTR;
 3405         if (rts > 0)
 3406                 msvr2 = MSVR2_RTS;
 3407 
 3408         x = spltty();
 3409         BRDENABLE(portp->brdnr, portp->pagenr);
 3410         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 3411         if (rts >= 0) {
 3412                 if (portp->tty.t_cflag & CRTS_IFLOW) {
 3413                         if (rts == 0) {
 3414                                 stl_cd1400setreg(portp, MCOR1,
 3415                                       (stl_cd1400getreg(portp, MCOR1) & 0xf0));
 3416                                 portp->stats.rxrtsoff++;
 3417                         } else {
 3418                                 stl_cd1400setreg(portp, MCOR1,
 3419                                         (stl_cd1400getreg(portp, MCOR1) |
 3420                                         FIFO_RTSTHRESHOLD));
 3421                                 portp->stats.rxrtson++;
 3422                         }
 3423                 }
 3424                 stl_cd1400setreg(portp, MSVR2, msvr2);
 3425         }
 3426         if (dtr >= 0)
 3427                 stl_cd1400setreg(portp, MSVR1, msvr1);
 3428         BRDDISABLE(portp->brdnr);
 3429         splx(x);
 3430 }
 3431 
 3432 /*****************************************************************************/
 3433 
 3434 /*
 3435  *      Get the state of the signals.
 3436  */
 3437 
 3438 static int stl_cd1400getsignals(stlport_t *portp)
 3439 {
 3440         unsigned char   msvr1, msvr2;
 3441         int             sigs, x;
 3442 
 3443 #if DEBUG
 3444         printf("stl_cd1400getsignals(portp=%x)\n", (int) portp);
 3445 #endif
 3446 
 3447         x = spltty();
 3448         BRDENABLE(portp->brdnr, portp->pagenr);
 3449         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3450         msvr1 = stl_cd1400getreg(portp, MSVR1);
 3451         msvr2 = stl_cd1400getreg(portp, MSVR2);
 3452         BRDDISABLE(portp->brdnr);
 3453         splx(x);
 3454 
 3455         sigs = 0;
 3456         sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
 3457         sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
 3458         sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
 3459         sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
 3460 #if 0
 3461         sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
 3462         sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
 3463 #else
 3464         sigs |= TIOCM_DSR;
 3465 #endif
 3466         return(sigs);
 3467 }
 3468 
 3469 /*****************************************************************************/
 3470 
 3471 /*
 3472  *      Enable or disable the Transmitter and/or Receiver.
 3473  */
 3474 
 3475 static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
 3476 {
 3477         unsigned char   ccr;
 3478         int             x;
 3479 
 3480 #if DEBUG
 3481         printf("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n",
 3482                 (int) portp, rx, tx);
 3483 #endif
 3484 
 3485         ccr = 0;
 3486         if (tx == 0)
 3487                 ccr |= CCR_TXDISABLE;
 3488         else if (tx > 0)
 3489                 ccr |= CCR_TXENABLE;
 3490         if (rx == 0)
 3491                 ccr |= CCR_RXDISABLE;
 3492         else if (rx > 0)
 3493                 ccr |= CCR_RXENABLE;
 3494 
 3495         x = spltty();
 3496         BRDENABLE(portp->brdnr, portp->pagenr);
 3497         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 3498         stl_cd1400ccrwait(portp);
 3499         stl_cd1400setreg(portp, CCR, ccr);
 3500         stl_cd1400ccrwait(portp);
 3501         BRDDISABLE(portp->brdnr);
 3502         splx(x);
 3503 }
 3504 
 3505 /*****************************************************************************/
 3506 
 3507 /*
 3508  *      Start or stop the Transmitter and/or Receiver.
 3509  */
 3510 
 3511 static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
 3512 {
 3513         unsigned char   sreron, sreroff;
 3514         int             x;
 3515 
 3516 #if DEBUG
 3517         printf("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n",
 3518                 (int) portp, rx, tx);
 3519 #endif
 3520 
 3521         sreron = 0;
 3522         sreroff = 0;
 3523         if (tx == 0)
 3524                 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
 3525         else if (tx == 1)
 3526                 sreron |= SRER_TXDATA;
 3527         else if (tx >= 2)
 3528                 sreron |= SRER_TXEMPTY;
 3529         if (rx == 0)
 3530                 sreroff |= SRER_RXDATA;
 3531         else if (rx > 0)
 3532                 sreron |= SRER_RXDATA;
 3533 
 3534         x = spltty();
 3535         BRDENABLE(portp->brdnr, portp->pagenr);
 3536         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3537         stl_cd1400setreg(portp, SRER,
 3538                 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
 3539         BRDDISABLE(portp->brdnr);
 3540         if (tx > 0) {
 3541                 portp->state |= ASY_TXBUSY;
 3542                 portp->tty.t_state |= TS_BUSY;
 3543         }
 3544         splx(x);
 3545 }
 3546 
 3547 /*****************************************************************************/
 3548 
 3549 /*
 3550  *      Disable all interrupts from this port.
 3551  */
 3552 
 3553 static void stl_cd1400disableintrs(stlport_t *portp)
 3554 {
 3555         int     x;
 3556 
 3557 #if DEBUG
 3558         printf("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
 3559 #endif
 3560 
 3561         x = spltty();
 3562         BRDENABLE(portp->brdnr, portp->pagenr);
 3563         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3564         stl_cd1400setreg(portp, SRER, 0);
 3565         BRDDISABLE(portp->brdnr);
 3566         splx(x);
 3567 }
 3568 
 3569 /*****************************************************************************/
 3570 
 3571 static void stl_cd1400sendbreak(stlport_t *portp, long len)
 3572 {
 3573         int     x;
 3574 
 3575 #if DEBUG
 3576         printf("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp,
 3577                 (int) len);
 3578 #endif
 3579 
 3580         x = spltty();
 3581         BRDENABLE(portp->brdnr, portp->pagenr);
 3582         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3583         stl_cd1400setreg(portp, COR2,
 3584                 (stl_cd1400getreg(portp, COR2) | COR2_ETC));
 3585         stl_cd1400setreg(portp, SRER,
 3586                 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
 3587                 SRER_TXEMPTY));
 3588         BRDDISABLE(portp->brdnr);
 3589         if (len > 0) {
 3590                 len = len / 5;
 3591                 portp->brklen = (len > 255) ? 255 : len;
 3592         } else {
 3593                 portp->brklen = len;
 3594         }
 3595         splx(x);
 3596         portp->stats.txbreaks++;
 3597 }
 3598 
 3599 /*****************************************************************************/
 3600 
 3601 /*
 3602  *      Try and find and initialize all the ports on a panel. We don't care
 3603  *      what sort of board these ports are on - since the port io registers
 3604  *      are almost identical when dealing with ports.
 3605  */
 3606 
 3607 static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
 3608 {
 3609 #if DEBUG
 3610         printf("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
 3611                 (int) brdp, (int) panelp, (int) portp);
 3612 #endif
 3613 
 3614         if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
 3615             (portp == (stlport_t *) NULL))
 3616                 return;
 3617 
 3618         portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
 3619                 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
 3620         portp->uartaddr = (portp->portnr & 0x04) << 5;
 3621         portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
 3622 
 3623         BRDENABLE(portp->brdnr, portp->pagenr);
 3624         stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 3625         stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
 3626         portp->hwid = stl_cd1400getreg(portp, GFRCR);
 3627         BRDDISABLE(portp->brdnr);
 3628 }
 3629 
 3630 /*****************************************************************************/
 3631 
 3632 /*
 3633  *      Inbitialize the UARTs in a panel. We don't care what sort of board
 3634  *      these ports are on - since the port io registers are almost
 3635  *      identical when dealing with ports.
 3636  */
 3637 
 3638 static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
 3639 {
 3640         unsigned int    gfrcr;
 3641         int             chipmask, i, j;
 3642         int             nrchips, uartaddr, ioaddr;
 3643 
 3644 #if DEBUG
 3645         printf("stl_cd1400panelinit(brdp=%x,panelp=%x)\n", (int) brdp,
 3646                 (int) panelp);
 3647 #endif
 3648 
 3649         BRDENABLE(panelp->brdnr, panelp->pagenr);
 3650 
 3651 /*
 3652  *      Check that each chip is present and started up OK.
 3653  */
 3654         chipmask = 0;
 3655         nrchips = panelp->nrports / CD1400_PORTS;
 3656         for (i = 0; (i < nrchips); i++) {
 3657                 if (brdp->brdtype == BRD_ECHPCI) {
 3658                         outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
 3659                         ioaddr = panelp->iobase;
 3660                 } else {
 3661                         ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
 3662                 }
 3663                 uartaddr = (i & 0x01) ? 0x080 : 0;
 3664                 outb(ioaddr, (GFRCR + uartaddr));
 3665                 outb((ioaddr + EREG_DATA), 0);
 3666                 outb(ioaddr, (CCR + uartaddr));
 3667                 outb((ioaddr + EREG_DATA), CCR_RESETFULL);
 3668                 outb((ioaddr + EREG_DATA), CCR_RESETFULL);
 3669                 outb(ioaddr, (GFRCR + uartaddr));
 3670                 for (j = 0; (j < CCR_MAXWAIT); j++) {
 3671                         if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
 3672                                 break;
 3673                 }
 3674                 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
 3675                         printf("STALLION: cd1400 not responding, "
 3676                                 "board=%d panel=%d chip=%d\n", panelp->brdnr,
 3677                                 panelp->panelnr, i);
 3678                         continue;
 3679                 }
 3680                 chipmask |= (0x1 << i);
 3681                 outb(ioaddr, (PPR + uartaddr));
 3682                 outb((ioaddr + EREG_DATA), PPR_SCALAR);
 3683         }
 3684 
 3685 
 3686         BRDDISABLE(panelp->brdnr);
 3687         return(chipmask);
 3688 }
 3689 
 3690 /*****************************************************************************/
 3691 /*                      SC26198 HARDWARE FUNCTIONS                           */
 3692 /*****************************************************************************/
 3693 
 3694 /*
 3695  *      These functions get/set/update the registers of the sc26198 UARTs.
 3696  *      Access to the sc26198 registers is via an address/data io port pair.
 3697  *      (Maybe should make this inline...)
 3698  */
 3699 
 3700 static int stl_sc26198getreg(stlport_t *portp, int regnr)
 3701 {
 3702         outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr));
 3703         return(inb(portp->ioaddr + XP_DATA));
 3704 }
 3705 
 3706 static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
 3707 {
 3708         outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr));
 3709         outb((portp->ioaddr + XP_DATA), value);
 3710 }
 3711 
 3712 static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
 3713 {
 3714         outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr));
 3715         if (inb(portp->ioaddr + XP_DATA) != value) {
 3716                 outb((portp->ioaddr + XP_DATA), value);
 3717                 return(1);
 3718         }
 3719         return(0);
 3720 }
 3721 
 3722 /*****************************************************************************/
 3723 
 3724 /*
 3725  *      Functions to get and set the sc26198 global registers.
 3726  */
 3727 
 3728 static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
 3729 {
 3730         outb((portp->ioaddr + XP_ADDR), regnr);
 3731         return(inb(portp->ioaddr + XP_DATA));
 3732 }
 3733 
 3734 #if 0
 3735 static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value)
 3736 {
 3737         outb((portp->ioaddr + XP_ADDR), regnr);
 3738         outb((portp->ioaddr + XP_DATA), value);
 3739 }
 3740 #endif
 3741 
 3742 /*****************************************************************************/
 3743 
 3744 /*
 3745  *      Inbitialize the UARTs in a panel. We don't care what sort of board
 3746  *      these ports are on - since the port io registers are almost
 3747  *      identical when dealing with ports.
 3748  */
 3749 
 3750 static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
 3751 {
 3752         int     chipmask, i;
 3753         int     nrchips, ioaddr;
 3754 
 3755 #if DEBUG
 3756         printf("stl_sc26198panelinit(brdp=%x,panelp=%x)\n", (int) brdp,
 3757                 (int) panelp);
 3758 #endif
 3759 
 3760         BRDENABLE(panelp->brdnr, panelp->pagenr);
 3761 
 3762 /*
 3763  *      Check that each chip is present and started up OK.
 3764  */
 3765         chipmask = 0;
 3766         nrchips = (panelp->nrports + 4) / SC26198_PORTS;
 3767         if (brdp->brdtype == BRD_ECHPCI)
 3768                 outb(brdp->ioctrl, panelp->pagenr);
 3769 
 3770         for (i = 0; (i < nrchips); i++) {
 3771                 ioaddr = panelp->iobase + (i * 4); 
 3772                 outb((ioaddr + XP_ADDR), SCCR);
 3773                 outb((ioaddr + XP_DATA), CR_RESETALL);
 3774                 outb((ioaddr + XP_ADDR), TSTR);
 3775                 if (inb(ioaddr + XP_DATA) != 0) {
 3776                         printf("STALLION: sc26198 not responding, "
 3777                                 "board=%d panel=%d chip=%d\n", panelp->brdnr,
 3778                                 panelp->panelnr, i);
 3779                         continue;
 3780                 }
 3781                 chipmask |= (0x1 << i);
 3782                 outb((ioaddr + XP_ADDR), GCCR);
 3783                 outb((ioaddr + XP_DATA), GCCR_IVRTYPCHANACK);
 3784                 outb((ioaddr + XP_ADDR), WDTRCR);
 3785                 outb((ioaddr + XP_DATA), 0xff);
 3786         }
 3787 
 3788         BRDDISABLE(panelp->brdnr);
 3789         return(chipmask);
 3790 }
 3791 
 3792 /*****************************************************************************/
 3793 
 3794 /*
 3795  *      Initialize hardware specific port registers.
 3796  */
 3797 
 3798 static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
 3799 {
 3800 #if DEBUG
 3801         printf("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n",
 3802                 (int) brdp, (int) panelp, (int) portp);
 3803 #endif
 3804 
 3805         if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
 3806             (portp == (stlport_t *) NULL))
 3807                 return;
 3808 
 3809         portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
 3810         portp->uartaddr = (portp->portnr & 0x07) << 4;
 3811         portp->pagenr = panelp->pagenr;
 3812         portp->hwid = 0x1;
 3813 
 3814         BRDENABLE(portp->brdnr, portp->pagenr);
 3815         stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
 3816         BRDDISABLE(portp->brdnr);
 3817 }
 3818 
 3819 /*****************************************************************************/
 3820 
 3821 /*
 3822  *      Set up the sc26198 registers for a port based on the termios port
 3823  *      settings.
 3824  */
 3825 
 3826 static int stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
 3827 {
 3828         unsigned char   mr0, mr1, mr2, clk;
 3829         unsigned char   imron, imroff, iopr, ipr;
 3830         int             x;
 3831 
 3832 #if DEBUG
 3833         printf("stl_sc26198setport(portp=%x,tiosp=%x): brdnr=%d portnr=%d\n",
 3834                 (int) portp, (int) tiosp, portp->brdnr, portp->portnr);
 3835 #endif
 3836 
 3837         mr0 = 0;
 3838         mr1 = 0;
 3839         mr2 = 0;
 3840         clk = 0;
 3841         iopr = 0;
 3842         imron = 0;
 3843         imroff = 0;
 3844 
 3845 /*
 3846  *      Set up the RX char ignore mask with those RX error types we
 3847  *      can ignore.
 3848  */
 3849         portp->rxignoremsk = 0;
 3850         if (tiosp->c_iflag & IGNPAR)
 3851                 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
 3852                         SR_RXOVERRUN);
 3853         if (tiosp->c_iflag & IGNBRK)
 3854                 portp->rxignoremsk |= SR_RXBREAK;
 3855 
 3856         portp->rxmarkmsk = SR_RXOVERRUN;
 3857         if (tiosp->c_iflag & (INPCK | PARMRK))
 3858                 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
 3859         if (tiosp->c_iflag & BRKINT)
 3860                 portp->rxmarkmsk |= SR_RXBREAK;
 3861 
 3862 /*
 3863  *      Go through the char size, parity and stop bits and set all the
 3864  *      option registers appropriately.
 3865  */
 3866         switch (tiosp->c_cflag & CSIZE) {
 3867         case CS5:
 3868                 mr1 |= MR1_CS5;
 3869                 break;
 3870         case CS6:
 3871                 mr1 |= MR1_CS6;
 3872                 break;
 3873         case CS7:
 3874                 mr1 |= MR1_CS7;
 3875                 break;
 3876         default:
 3877                 mr1 |= MR1_CS8;
 3878                 break;
 3879         }
 3880 
 3881         if (tiosp->c_cflag & CSTOPB)
 3882                 mr2 |= MR2_STOP2;
 3883         else
 3884                 mr2 |= MR2_STOP1;
 3885 
 3886         if (tiosp->c_cflag & PARENB) {
 3887                 if (tiosp->c_cflag & PARODD)
 3888                         mr1 |= (MR1_PARENB | MR1_PARODD);
 3889                 else
 3890                         mr1 |= (MR1_PARENB | MR1_PAREVEN);
 3891         } else {
 3892                 mr1 |= MR1_PARNONE;
 3893         }
 3894 
 3895         mr1 |= MR1_ERRBLOCK;
 3896 
 3897 /*
 3898  *      Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
 3899  *      space for hardware flow control and the like. This should be set to
 3900  *      VMIN.
 3901  */
 3902         mr2 |= MR2_RXFIFOHALF;
 3903 
 3904 /*
 3905  *      Calculate the baud rate timers. For now we will just assume that
 3906  *      the input and output baud are the same. The sc26198 has a fixed
 3907  *      baud rate table, so only discrete baud rates possible.
 3908  */
 3909         if (tiosp->c_ispeed == 0)
 3910                 tiosp->c_ispeed = tiosp->c_ospeed;
 3911         if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > SC26198_MAXBAUD))
 3912                 return(EINVAL);
 3913 
 3914         if (tiosp->c_ospeed > 0) {
 3915                 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
 3916                         if (tiosp->c_ospeed <= sc26198_baudtable[clk])
 3917                                 break;
 3918                 }
 3919         }
 3920 
 3921 /*
 3922  *      Check what form of modem signaling is required and set it up.
 3923  */
 3924         if ((tiosp->c_cflag & CLOCAL) == 0) {
 3925                 iopr |= IOPR_DCDCOS;
 3926                 imron |= IR_IOPORT;
 3927         }
 3928 
 3929 /*
 3930  *      Setup sc26198 enhanced modes if we can. In particular we want to
 3931  *      handle as much of the flow control as possible automatically. As
 3932  *      well as saving a few CPU cycles it will also greatly improve flow
 3933  *      control reliability.
 3934  */
 3935         if (tiosp->c_iflag & IXON) {
 3936                 mr0 |= MR0_SWFTX | MR0_SWFT;
 3937                 imron |= IR_XONXOFF;
 3938         } else {
 3939                 imroff |= IR_XONXOFF;
 3940         }
 3941 #if 0
 3942         if (tiosp->c_iflag & IXOFF)
 3943                 mr0 |= MR0_SWFRX;
 3944 #endif
 3945 
 3946         if (tiosp->c_cflag & CCTS_OFLOW)
 3947                 mr2 |= MR2_AUTOCTS;
 3948         if (tiosp->c_cflag & CRTS_IFLOW)
 3949                 mr1 |= MR1_AUTORTS;
 3950 
 3951 /*
 3952  *      All sc26198 register values calculated so go through and set
 3953  *      them all up.
 3954  */
 3955 
 3956 #if DEBUG
 3957         printf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr,
 3958                 portp->panelnr, portp->brdnr);
 3959         printf("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
 3960         printf("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
 3961         printf("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
 3962                 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
 3963                 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
 3964 #endif
 3965 
 3966         x = spltty();
 3967         BRDENABLE(portp->brdnr, portp->pagenr);
 3968         stl_sc26198setreg(portp, IMR, 0);
 3969         stl_sc26198updatereg(portp, MR0, mr0);
 3970         stl_sc26198updatereg(portp, MR1, mr1);
 3971         stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
 3972         stl_sc26198updatereg(portp, MR2, mr2);
 3973         iopr = (stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr;
 3974         if (tiosp->c_ospeed == 0) {
 3975                 iopr &= ~IPR_DTR;
 3976         } else {
 3977                 iopr |= IPR_DTR;
 3978                 stl_sc26198setreg(portp, TXCSR, clk);
 3979                 stl_sc26198setreg(portp, RXCSR, clk);
 3980         }
 3981         stl_sc26198updatereg(portp, IOPIOR, iopr);
 3982         stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
 3983         stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
 3984         ipr = stl_sc26198getreg(portp, IPR);
 3985         if (ipr & IPR_DCD)
 3986                 portp->sigs &= ~TIOCM_CD;
 3987         else
 3988                 portp->sigs |= TIOCM_CD;
 3989         portp->imr = (portp->imr & ~imroff) | imron;
 3990         stl_sc26198setreg(portp, IMR, portp->imr);
 3991         BRDDISABLE(portp->brdnr);
 3992         portp->state &= ~(ASY_RTSFLOWMODE | ASY_CTSFLOWMODE);
 3993         portp->state |= ((tiosp->c_cflag & CRTS_IFLOW) ? ASY_RTSFLOWMODE : 0);
 3994         portp->state |= ((tiosp->c_cflag & CCTS_OFLOW) ? ASY_CTSFLOWMODE : 0);
 3995         stl_ttyoptim(portp, tiosp);
 3996         splx(x);
 3997 
 3998         return(0);
 3999 }
 4000 
 4001 /*****************************************************************************/
 4002 
 4003 /*
 4004  *      Set the state of the DTR and RTS signals.
 4005  */
 4006 
 4007 static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
 4008 {
 4009         unsigned char   iopioron, iopioroff;
 4010         int             x;
 4011 
 4012 #if DEBUG
 4013         printf("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n",
 4014                 (int) portp, dtr, rts);
 4015 #endif
 4016 
 4017         iopioron = 0;
 4018         iopioroff = 0;
 4019         if (dtr == 0)
 4020                 iopioroff |= IPR_DTR;
 4021         else if (dtr > 0)
 4022                 iopioron |= IPR_DTR;
 4023         if (rts == 0)
 4024                 iopioroff |= IPR_RTS;
 4025         else if (rts > 0)
 4026                 iopioron |= IPR_RTS;
 4027 
 4028         x = spltty();
 4029         BRDENABLE(portp->brdnr, portp->pagenr);
 4030         if ((rts >= 0) && (portp->tty.t_cflag & CRTS_IFLOW)) {
 4031                 if (rts == 0) {
 4032                         stl_sc26198setreg(portp, MR1,
 4033                                 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
 4034                         portp->stats.rxrtsoff++;
 4035                 } else {
 4036                         stl_sc26198setreg(portp, MR1,
 4037                                 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
 4038                         portp->stats.rxrtson++;
 4039                 }
 4040         }
 4041         stl_sc26198setreg(portp, IOPIOR,
 4042                 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
 4043         BRDDISABLE(portp->brdnr);
 4044         splx(x);
 4045 }
 4046 
 4047 /*****************************************************************************/
 4048 
 4049 /*
 4050  *      Return the state of the signals.
 4051  */
 4052 
 4053 static int stl_sc26198getsignals(stlport_t *portp)
 4054 {
 4055         unsigned char   ipr;
 4056         int             x, sigs;
 4057 
 4058 #if DEBUG
 4059         printf("stl_sc26198getsignals(portp=%x)\n", (int) portp);
 4060 #endif
 4061 
 4062         x = spltty();
 4063         BRDENABLE(portp->brdnr, portp->pagenr);
 4064         ipr = stl_sc26198getreg(portp, IPR);
 4065         BRDDISABLE(portp->brdnr);
 4066         splx(x);
 4067 
 4068         sigs = TIOCM_DSR;
 4069         sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
 4070         sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
 4071         sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
 4072         sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
 4073         return(sigs);
 4074 }
 4075 
 4076 /*****************************************************************************/
 4077 
 4078 /*
 4079  *      Enable/Disable the Transmitter and/or Receiver.
 4080  */
 4081 
 4082 static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
 4083 {
 4084         unsigned char   ccr;
 4085         int             x;
 4086 
 4087 #if DEBUG
 4088         printf("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n",
 4089                 (int) portp, rx, tx);
 4090 #endif
 4091 
 4092         ccr = portp->crenable;
 4093         if (tx == 0)
 4094                 ccr &= ~CR_TXENABLE;
 4095         else if (tx > 0)
 4096                 ccr |= CR_TXENABLE;
 4097         if (rx == 0)
 4098                 ccr &= ~CR_RXENABLE;
 4099         else if (rx > 0)
 4100                 ccr |= CR_RXENABLE;
 4101 
 4102         x = spltty();
 4103         BRDENABLE(portp->brdnr, portp->pagenr);
 4104         stl_sc26198setreg(portp, SCCR, ccr);
 4105         BRDDISABLE(portp->brdnr);
 4106         portp->crenable = ccr;
 4107         splx(x);
 4108 }
 4109 
 4110 /*****************************************************************************/
 4111 
 4112 /*
 4113  *      Start/stop the Transmitter and/or Receiver.
 4114  */
 4115 
 4116 static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
 4117 {
 4118         unsigned char   imr;
 4119         int             x;
 4120 
 4121 #if DEBUG
 4122         printf("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n",
 4123                 (int) portp, rx, tx);
 4124 #endif
 4125 
 4126         imr = portp->imr;
 4127         if (tx == 0)
 4128                 imr &= ~IR_TXRDY;
 4129         else if (tx == 1)
 4130                 imr |= IR_TXRDY;
 4131         if (rx == 0)
 4132                 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
 4133         else if (rx > 0)
 4134                 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
 4135 
 4136         x = spltty();
 4137         BRDENABLE(portp->brdnr, portp->pagenr);
 4138         stl_sc26198setreg(portp, IMR, imr);
 4139         BRDDISABLE(portp->brdnr);
 4140         portp->imr = imr;
 4141         if (tx > 0) {
 4142                 portp->state |= ASY_TXBUSY;
 4143                 portp->tty.t_state |= TS_BUSY;
 4144         }
 4145         splx(x);
 4146 }
 4147 
 4148 /*****************************************************************************/
 4149 
 4150 /*
 4151  *      Disable all interrupts from this port.
 4152  */
 4153 
 4154 static void stl_sc26198disableintrs(stlport_t *portp)
 4155 {
 4156         int     x;
 4157 
 4158 #if DEBUG
 4159         printf("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
 4160 #endif
 4161 
 4162         x = spltty();
 4163         BRDENABLE(portp->brdnr, portp->pagenr);
 4164         portp->imr = 0;
 4165         stl_sc26198setreg(portp, IMR, 0);
 4166         BRDDISABLE(portp->brdnr);
 4167         splx(x);
 4168 }
 4169 
 4170 /*****************************************************************************/
 4171 
 4172 static void stl_sc26198sendbreak(stlport_t *portp, long len)
 4173 {
 4174         int     x;
 4175 
 4176 #if DEBUG
 4177         printf("stl_sc26198sendbreak(portp=%x,len=%d)\n",
 4178                 (int) portp, (int) len);
 4179 #endif
 4180 
 4181         x = spltty();
 4182         BRDENABLE(portp->brdnr, portp->pagenr);
 4183         if (len == -1) {
 4184                 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
 4185                 portp->stats.txbreaks++;
 4186         } else {
 4187                 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
 4188         }
 4189         BRDDISABLE(portp->brdnr);
 4190         splx(x);
 4191 }
 4192 
 4193 /*****************************************************************************/
 4194 
 4195 /*
 4196  *      Take flow control actions...
 4197  */
 4198 
 4199 static void stl_sc26198sendflow(stlport_t *portp, int hw, int sw)
 4200 {
 4201         unsigned char   mr0;
 4202         int             x;
 4203 
 4204 #if DEBUG
 4205         printf("stl_sc26198sendflow(portp=%x,hw=%d,sw=%d)\n",
 4206                 (int) portp, hw, sw);
 4207 #endif
 4208 
 4209         if (portp == (stlport_t *) NULL)
 4210                 return;
 4211 
 4212         x = spltty();
 4213         BRDENABLE(portp->brdnr, portp->pagenr);
 4214 
 4215         if (sw >= 0) {
 4216                 mr0 = stl_sc26198getreg(portp, MR0);
 4217                 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
 4218                 if (sw > 0) {
 4219                         stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
 4220                         mr0 &= ~MR0_SWFRX;
 4221                         portp->stats.rxxoff++;
 4222                 } else {
 4223                         stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
 4224                         mr0 |= MR0_SWFRX;
 4225                         portp->stats.rxxon++;
 4226                 }
 4227                 stl_sc26198wait(portp);
 4228                 stl_sc26198setreg(portp, MR0, mr0);
 4229         }
 4230 
 4231         if (hw == 0) {
 4232                 portp->state |= ASY_RTSFLOW;
 4233                 stl_sc26198setreg(portp, MR1,
 4234                         (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
 4235                 stl_sc26198setreg(portp, IOPIOR,
 4236                         (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
 4237                 portp->stats.rxrtsoff++;
 4238         } else if (hw > 0) {
 4239                 portp->state &= ~ASY_RTSFLOW;
 4240                 stl_sc26198setreg(portp, MR1,
 4241                         (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
 4242                 stl_sc26198setreg(portp, IOPIOR,
 4243                         (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
 4244                 portp->stats.rxrtson++;
 4245         }
 4246 
 4247         BRDDISABLE(portp->brdnr);
 4248         splx(x);
 4249 }
 4250 
 4251 /*****************************************************************************/
 4252 
 4253 /*
 4254  *      Return the current state of data flow on this port. This is only
 4255  *      really interresting when determining if data has fully completed
 4256  *      transmission or not... The sc26198 interrupt scheme cannot
 4257  *      determine when all data has actually drained, so we need to
 4258  *      check the port statusy register to be sure.
 4259  */
 4260 
 4261 static int stl_sc26198datastate(stlport_t *portp)
 4262 {
 4263         unsigned char   sr;
 4264         int             x;
 4265 
 4266 #if DEBUG
 4267         printf("stl_sc26198datastate(portp=%x)\n", (int) portp);
 4268 #endif
 4269 
 4270         if (portp == (stlport_t *) NULL)
 4271                 return(0);
 4272         if (portp->state & ASY_TXBUSY) 
 4273                 return(1);
 4274 
 4275         x = spltty();
 4276         BRDENABLE(portp->brdnr, portp->pagenr);
 4277         sr = stl_sc26198getreg(portp, SR);
 4278         BRDDISABLE(portp->brdnr);
 4279         splx(x);
 4280 
 4281         return((sr & SR_TXEMPTY) ? 0 : 1);
 4282 }
 4283 
 4284 /*****************************************************************************/
 4285 
 4286 static void stl_sc26198flush(stlport_t *portp, int flag)
 4287 {
 4288         int     x;
 4289 
 4290 #if DEBUG
 4291         printf("stl_sc26198flush(portp=%x,flag=%x)\n", (int) portp, flag);
 4292 #endif
 4293 
 4294         if (portp == (stlport_t *) NULL)
 4295                 return;
 4296 
 4297         x = spltty();
 4298         BRDENABLE(portp->brdnr, portp->pagenr);
 4299         if (flag & FWRITE) {
 4300                 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
 4301                 stl_sc26198setreg(portp, SCCR, portp->crenable);
 4302         }
 4303         if (flag & FREAD) {
 4304                 while (stl_sc26198getreg(portp, SR) & SR_RXRDY)
 4305                         stl_sc26198getreg(portp, RXFIFO);
 4306         }
 4307         BRDDISABLE(portp->brdnr);
 4308         splx(x);
 4309 }
 4310 
 4311 /*****************************************************************************/
 4312 
 4313 /*
 4314  *      If we are TX flow controlled and in IXANY mode then we may
 4315  *      need to unflow control here. We gotta do this because of the
 4316  *      automatic flow control modes of the sc26198 - which downs't
 4317  *      support any concept of an IXANY mode.
 4318  */
 4319 
 4320 static void stl_sc26198txunflow(stlport_t *portp)
 4321 {
 4322         unsigned char   mr0;
 4323 
 4324         mr0 = stl_sc26198getreg(portp, MR0);
 4325         stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
 4326         stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
 4327         stl_sc26198setreg(portp, MR0, mr0);
 4328         portp->state &= ~ASY_TXFLOWED;
 4329 }
 4330 
 4331 /*****************************************************************************/
 4332 
 4333 /*
 4334  *      Delay for a small amount of time, to give the sc26198 a chance
 4335  *      to process a command...
 4336  */
 4337 
 4338 static void stl_sc26198wait(stlport_t *portp)
 4339 {
 4340         int     i;
 4341 
 4342 #if DEBUG
 4343         printf("stl_sc26198wait(portp=%x)\n", (int) portp);
 4344 #endif
 4345 
 4346         if (portp == (stlport_t *) NULL)
 4347                 return;
 4348 
 4349         for (i = 0; (i < 20); i++)
 4350                 stl_sc26198getglobreg(portp, TSTR);
 4351 }
 4352 
 4353 /*****************************************************************************/
 4354 
 4355 /*
 4356  *      Transmit interrupt handler. This has gotta be fast!  Handling TX
 4357  *      chars is pretty simple, stuff as many as possible from the TX buffer
 4358  *      into the sc26198 FIFO.
 4359  */
 4360 
 4361 static void stl_sc26198txisr(stlport_t *portp)
 4362 {
 4363         unsigned int    ioaddr;
 4364         unsigned char   mr0;
 4365         char            *head, *tail;
 4366         int             len, stlen;
 4367 
 4368 #if DEBUG
 4369         printf("stl_sc26198txisr(portp=%x)\n", (int) portp);
 4370 #endif
 4371 
 4372         ioaddr = portp->ioaddr;
 4373 
 4374         head = portp->tx.head;
 4375         tail = portp->tx.tail;
 4376         len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
 4377         if ((len == 0) || ((len < STL_TXBUFLOW) &&
 4378             ((portp->state & ASY_TXLOW) == 0))) {
 4379                 portp->state |= ASY_TXLOW;
 4380                 stl_dotimeout();
 4381         }
 4382 
 4383         if (len == 0) {
 4384                 outb((ioaddr + XP_ADDR), (MR0 | portp->uartaddr));
 4385                 mr0 = inb(ioaddr + XP_DATA);
 4386                 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
 4387                         portp->imr &= ~IR_TXRDY;
 4388                         outb((ioaddr + XP_ADDR), (IMR | portp->uartaddr));
 4389                         outb((ioaddr + XP_DATA), portp->imr);
 4390                         portp->state |= ASY_TXEMPTY;
 4391                         portp->state &= ~ASY_TXBUSY;
 4392                 } else {
 4393                         mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
 4394                         outb((ioaddr + XP_DATA), mr0);
 4395                 }
 4396         } else {
 4397                 len = MIN(len, SC26198_TXFIFOSIZE);
 4398                 portp->stats.txtotal += len;
 4399                 stlen = MIN(len, (portp->tx.endbuf - tail));
 4400                 outb((ioaddr + XP_ADDR), GTXFIFO);
 4401                 outsb((ioaddr + XP_DATA), tail, stlen);
 4402                 len -= stlen;
 4403                 tail += stlen;
 4404                 if (tail >= portp->tx.endbuf)
 4405                         tail = portp->tx.buf;
 4406                 if (len > 0) {
 4407                         outsb((ioaddr + XP_DATA), tail, len);
 4408                         tail += len;
 4409                 }
 4410                 portp->tx.tail = tail;
 4411         }
 4412 }
 4413 
 4414 /*****************************************************************************/
 4415 
 4416 /*
 4417  *      Receive character interrupt handler. Determine if we have good chars
 4418  *      or bad chars and then process appropriately. Good chars are easy
 4419  *      just shove the lot into the RX buffer and set all status byte to 0.
 4420  *      If a bad RX char then process as required. This routine needs to be
 4421  *      fast!
 4422  */
 4423 
 4424 static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
 4425 {
 4426 #if DEBUG
 4427         printf("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack);
 4428 #endif
 4429 
 4430         if ((iack & IVR_TYPEMASK) == IVR_RXDATA)
 4431                 stl_sc26198rxgoodchars(portp);
 4432         else
 4433                 stl_sc26198rxbadchars(portp);
 4434 
 4435 /*
 4436  *      If we are TX flow controlled and in IXANY mode then we may need
 4437  *      to unflow control here. We gotta do this because of the automatic
 4438  *      flow control modes of the sc26198.
 4439  */
 4440         if ((portp->state & ASY_TXFLOWED) && (portp->tty.t_iflag & IXANY))
 4441                 stl_sc26198txunflow(portp);
 4442 }
 4443 
 4444 /*****************************************************************************/
 4445 
 4446 /*
 4447  *      Process the good received characters from RX FIFO.
 4448  */
 4449 
 4450 static void stl_sc26198rxgoodchars(stlport_t *portp)
 4451 {
 4452         unsigned int    ioaddr, len, buflen, stlen;
 4453         char            *head, *tail;
 4454 
 4455 #if DEBUG
 4456         printf("stl_sc26198rxgoodchars(port=%x)\n", (int) portp);
 4457 #endif
 4458 
 4459         ioaddr = portp->ioaddr;
 4460 
 4461 /*
 4462  *      First up, calculate how much room there is in the RX ring queue.
 4463  *      We also want to keep track of the longest possible copy length,
 4464  *      this has to allow for the wrapping of the ring queue.
 4465  */
 4466         head = portp->rx.head;
 4467         tail = portp->rx.tail;
 4468         if (head >= tail) {
 4469                 buflen = STL_RXBUFSIZE - (head - tail) - 1;
 4470                 stlen = portp->rx.endbuf - head;
 4471         } else {
 4472                 buflen = tail - head - 1;
 4473                 stlen = buflen;
 4474         }
 4475 
 4476 /*
 4477  *      Check if the input buffer is near full. If so then we should take
 4478  *      some flow control action... It is very easy to do hardware and
 4479  *      software flow control from here since we have the port selected on
 4480  *      the UART.
 4481  */
 4482         if (buflen <= (STL_RXBUFSIZE - STL_RXBUFHIGH)) {
 4483                 if (((portp->state & ASY_RTSFLOW) == 0) &&
 4484                     (portp->state & ASY_RTSFLOWMODE)) {
 4485                         portp->state |= ASY_RTSFLOW;
 4486                         stl_sc26198setreg(portp, MR1,
 4487                                 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
 4488                         stl_sc26198setreg(portp, IOPIOR,
 4489                                 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
 4490                         portp->stats.rxrtsoff++;
 4491                 }
 4492         }
 4493 
 4494 /*
 4495  *      OK we are set, process good data... If the RX ring queue is full
 4496  *      just chuck the chars - don't leave them in the UART.
 4497  */
 4498         outb((ioaddr + XP_ADDR), GIBCR);
 4499         len = inb(ioaddr + XP_DATA) + 1;
 4500         if (buflen == 0) {
 4501                 len = MIN(len, sizeof(stl_unwanted));
 4502                 outb((ioaddr + XP_ADDR), GRXFIFO);
 4503                 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
 4504                 portp->stats.rxlost += len;
 4505                 portp->stats.rxtotal += len;
 4506         } else {
 4507                 len = MIN(len, buflen);
 4508                 portp->stats.rxtotal += len;
 4509                 stlen = MIN(len, stlen);
 4510                 if (len > 0) {
 4511                         outb((ioaddr + XP_ADDR), GRXFIFO);
 4512                         insb((ioaddr + XP_DATA), head, stlen);
 4513                         head += stlen;
 4514                         if (head >= portp->rx.endbuf) {
 4515                                 head = portp->rx.buf;
 4516                                 len -= stlen;
 4517                                 insb((ioaddr + XP_DATA), head, len);
 4518                                 head += len;
 4519                         }
 4520                 }
 4521         }
 4522 
 4523         portp->rx.head = head;
 4524         portp->state |= ASY_RXDATA;
 4525         stl_dotimeout();
 4526 }
 4527 
 4528 /*****************************************************************************/
 4529 
 4530 /*
 4531  *      Process all characters in the RX FIFO of the UART. Check all char
 4532  *      status bytes as well, and process as required. We need to check
 4533  *      all bytes in the FIFO, in case some more enter the FIFO while we
 4534  *      are here. To get the exact character error type we need to switch
 4535  *      into CHAR error mode (that is why we need to make sure we empty
 4536  *      the FIFO).
 4537  */
 4538 
 4539 static void stl_sc26198rxbadchars(stlport_t *portp)
 4540 {
 4541         unsigned char   mr1;
 4542         unsigned int    status;
 4543         char            *head, *tail;
 4544         char            ch;
 4545         int             len;
 4546 
 4547 /*
 4548  *      First up, calculate how much room there is in the RX ring queue.
 4549  *      We also want to keep track of the longest possible copy length,
 4550  *      this has to allow for the wrapping of the ring queue.
 4551  */
 4552         head = portp->rx.head;
 4553         tail = portp->rx.tail;
 4554         len = (head >= tail) ? (STL_RXBUFSIZE - (head - tail) - 1) :
 4555                 (tail - head - 1);
 4556 
 4557 /*
 4558  *      To get the precise error type for each character we must switch
 4559  *      back into CHAR error mode.
 4560  */
 4561         mr1 = stl_sc26198getreg(portp, MR1);
 4562         stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
 4563 
 4564         while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
 4565                 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
 4566                 ch = stl_sc26198getreg(portp, RXFIFO);
 4567 
 4568                 if (status & SR_RXBREAK)
 4569                         portp->stats.rxbreaks++;
 4570                 if (status & SR_RXFRAMING)
 4571                         portp->stats.rxframing++;
 4572                 if (status & SR_RXPARITY)
 4573                         portp->stats.rxparity++;
 4574                 if (status & SR_RXOVERRUN)
 4575                         portp->stats.rxoverrun++;
 4576                 if ((portp->rxignoremsk & status) == 0) {
 4577                         if ((portp->tty.t_state & TS_CAN_BYPASS_L_RINT) &&
 4578                             ((status & SR_RXFRAMING) ||
 4579                             ((status & SR_RXPARITY) &&
 4580                             (portp->tty.t_iflag & INPCK))))
 4581                                 ch = 0;
 4582                         if ((portp->rxmarkmsk & status) == 0)
 4583                                 status = 0;
 4584                         if (len > 0) {
 4585                                 *(head + STL_RXBUFSIZE) = status;
 4586                                 *head++ = ch;
 4587                                 if (head >= portp->rx.endbuf)
 4588                                         head = portp->rx.buf;
 4589                                 len--;
 4590                         }
 4591                 }
 4592         }
 4593 
 4594 /*
 4595  *      To get correct interrupt class we must switch back into BLOCK
 4596  *      error mode.
 4597  */
 4598         stl_sc26198setreg(portp, MR1, mr1);
 4599 
 4600         portp->rx.head = head;
 4601         portp->state |= ASY_RXDATA;
 4602         stl_dotimeout();
 4603 }
 4604 
 4605 /*****************************************************************************/
 4606 
 4607 /*
 4608  *      Other interrupt handler. This includes modem signals, flow
 4609  *      control actions, etc.
 4610  */
 4611 
 4612 static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
 4613 {
 4614         unsigned char   cir, ipr, xisr;
 4615 
 4616 #if DEBUG
 4617         printf("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack);
 4618 #endif
 4619 
 4620         cir = stl_sc26198getglobreg(portp, CIR);
 4621 
 4622         switch (cir & CIR_SUBTYPEMASK) {
 4623         case CIR_SUBCOS:
 4624                 ipr = stl_sc26198getreg(portp, IPR);
 4625                 if (ipr & IPR_DCDCHANGE) {
 4626                         portp->state |= ASY_DCDCHANGE;
 4627                         portp->stats.modem++;
 4628                         stl_dotimeout();
 4629                 }
 4630                 break;
 4631         case CIR_SUBXONXOFF:
 4632                 xisr = stl_sc26198getreg(portp, XISR);
 4633                 if (xisr & XISR_RXXONGOT) {
 4634                         portp->state |= ASY_TXFLOWED;
 4635                         portp->stats.txxoff++;
 4636                 }
 4637                 if (xisr & XISR_RXXOFFGOT) {
 4638                         portp->state &= ~ASY_TXFLOWED;
 4639                         portp->stats.txxon++;
 4640                 }
 4641                 break;
 4642         case CIR_SUBBREAK:
 4643                 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
 4644                 stl_sc26198rxbadchars(portp);
 4645                 break;
 4646         default:
 4647                 break;
 4648         }
 4649 }
 4650 
 4651 /*****************************************************************************/
 4652 
 4653 /*
 4654  *      Interrupt service routine for sc26198 panels.
 4655  */
 4656 
 4657 static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
 4658 {
 4659         stlport_t       *portp;
 4660         unsigned int    iack;
 4661 
 4662 /* 
 4663  *      Work around bug in sc26198 chip... Cannot have A6 address
 4664  *      line of UART high, else iack will be returned as 0.
 4665  */
 4666         outb((iobase + 1), 0);
 4667 
 4668         iack = inb(iobase + XP_IACK);
 4669 #if DEBUG
 4670 printf("stl_sc26198intr(panelp=%x,iobase=%x): iack=%x\n", panelp, iobase, iack);
 4671 #endif
 4672         portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
 4673 
 4674         if (iack & IVR_RXDATA)
 4675                 stl_sc26198rxisr(portp, iack);
 4676         else if (iack & IVR_TXDATA)
 4677                 stl_sc26198txisr(portp);
 4678         else
 4679                 stl_sc26198otherisr(portp, iack);
 4680 }
 4681 
 4682 /*****************************************************************************/

Cache object: 6ef56625d60d6163f268241e61a64d6e


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