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/istallion.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  * istallion.c  -- stallion intelligent multiport serial driver.
    5  *
    6  * Copyright (c) 1994-1996 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  * $FreeBSD: src/sys/i386/isa/istallion.c,v 1.6.2.1 1999/09/05 08:13:06 peter Exp $
   37  */
   38 
   39 /*****************************************************************************/
   40 
   41 #define TTYDEFCHARS     1
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/kernel.h>
   46 #include <sys/malloc.h>
   47 #include <sys/ioctl.h>
   48 #include <sys/tty.h>
   49 #include <sys/proc.h>
   50 #include <sys/conf.h>
   51 #include <sys/file.h>
   52 #include <sys/uio.h>
   53 #include <sys/syslog.h>
   54 #include <machine/cpu.h>
   55 #include <machine/clock.h>
   56 #include <vm/vm.h>
   57 #include <vm/vm_param.h>
   58 #include <vm/pmap.h>
   59 #include <i386/isa/isa_device.h>
   60 #include <machine/cdk.h>
   61 #include <machine/comstats.h>
   62 
   63 /*****************************************************************************/
   64 
   65 /*
   66  *      Define the version level of the kernel - so we can compile in the
   67  *      appropriate bits of code. By default this will compile for a 2.1
   68  *      level kernel.
   69  */
   70 #define VFREEBSD        220
   71 
   72 #if VFREEBSD >= 220
   73 #define STATIC          static
   74 #else
   75 #define STATIC
   76 #endif
   77 
   78 /*****************************************************************************/
   79 
   80 /*
   81  *      Define different board types. Not all of the following board types
   82  *      are supported by this driver. But I will use the standard "assigned"
   83  *      board numbers. Currently supported boards are abbreviated as:
   84  *      ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
   85  *      STAL = Stallion.
   86  */
   87 #define BRD_UNKNOWN     0
   88 #define BRD_STALLION    1
   89 #define BRD_BRUMBY4     2
   90 #define BRD_ONBOARD2    3
   91 #define BRD_ONBOARD     4
   92 #define BRD_BRUMBY8     5
   93 #define BRD_BRUMBY16    6
   94 #define BRD_ONBOARDE    7
   95 #define BRD_ONBOARD32   9
   96 #define BRD_ONBOARD2_32 10
   97 #define BRD_ONBOARDRS   11
   98 #define BRD_EASYIO      20
   99 #define BRD_ECH         21
  100 #define BRD_ECHMC       22
  101 #define BRD_ECP         23
  102 #define BRD_ECPE        24
  103 #define BRD_ECPMC       25
  104 #define BRD_ECHPCI      26
  105 
  106 #define BRD_BRUMBY      BRD_BRUMBY4
  107 
  108 /*****************************************************************************/
  109 
  110 /*
  111  *      Define important driver limitations.
  112  */
  113 #define STL_MAXBRDS             8
  114 #define STL_MAXPANELS           4
  115 #define STL_PORTSPERPANEL       16
  116 #define STL_PORTSPERBRD         64
  117 
  118 #define STL_MAXCHANS            STL_PORTSPERBRD
  119 
  120 
  121 /*
  122  *      Define the important minor number break down bits. These have been
  123  *      chosen to be "compatable" with the standard sio driver minor numbers.
  124  *      Extra high bits are used to distinguish between boards and also for
  125  *      really high port numbers (> 32).
  126  */
  127 #define STL_CALLOUTDEV  0x80
  128 #define STL_CTRLLOCK    0x40
  129 #define STL_CTRLINIT    0x20
  130 #define STL_CTRLDEV     (STL_CTRLLOCK | STL_CTRLINIT)
  131 
  132 #define STL_MEMDEV      0x07000000
  133 
  134 #define STL_DEFSPEED    9600
  135 #define STL_DEFCFLAG    (CS8 | CREAD | HUPCL)
  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 char             stli_drvname[] = "stli";
  144 static char const       stli_longdrvname[] = "Stallion Multiport Serial Driver";
  145 static char const       stli_drvversion[] = "0.0.5";
  146 
  147 static int      stli_nrbrds = 0;
  148 static int      stli_doingtimeout = 0;
  149 
  150 static char     *__file__ = /*__FILE__*/ "istallion.c";
  151 
  152 /*
  153  *      Define some macros to use to class define boards.
  154  */
  155 #define BRD_ISA         0x1
  156 #define BRD_EISA        0x2
  157 #define BRD_MCA         0x4
  158 #define BRD_PCI         0x8
  159 
  160 static unsigned char    stli_stliprobed[STL_MAXBRDS];
  161 
  162 /*****************************************************************************/
  163 
  164 /*
  165  *      Define a set of structures to hold all the board/panel/port info
  166  *      for our ports. These will be dynamically allocated as required at
  167  *      driver initialization time.
  168  */
  169 
  170 /*
  171  *      Port and board structures to hold status info about each object.
  172  *      The board structure contains pointers to structures for each port
  173  *      connected to it. Panels are not distinguished here, since
  174  *      communication with the slave board will always be on a per port
  175  *      basis.
  176  */
  177 typedef struct {
  178         struct tty      tty;
  179         int             portnr;
  180         int             panelnr;
  181         int             brdnr;
  182         int             ioaddr;
  183         int             callout;
  184         int             devnr;
  185         int             dtrwait;
  186         int             dotimestamp;
  187         int             waitopens;
  188         int             hotchar;
  189         int             rc;
  190         int             argsize;
  191         void            *argp;
  192         unsigned int    state;
  193         unsigned int    sigs;
  194         struct termios  initintios;
  195         struct termios  initouttios;
  196         struct termios  lockintios;
  197         struct termios  lockouttios;
  198         struct timeval  timestamp;
  199         asysigs_t       asig;
  200         unsigned long   addr;
  201         unsigned long   rxlost;
  202         unsigned long   rxoffset;
  203         unsigned long   txoffset;
  204         unsigned long   pflag;
  205         unsigned int    rxsize;
  206         unsigned int    txsize;
  207         unsigned char   reqidx;
  208         unsigned char   reqbit;
  209         unsigned char   portidx;
  210         unsigned char   portbit;
  211 } stliport_t;
  212 
  213 /*
  214  *      Use a structure of function pointers to do board level operations.
  215  *      These include, enable/disable, paging shared memory, interrupting, etc.
  216  */
  217 typedef struct stlibrd {
  218         int             brdnr;
  219         int             brdtype;
  220         int             unitid;
  221         int             state;
  222         int             nrpanels;
  223         int             nrports;
  224         int             nrdevs;
  225         unsigned int    iobase;
  226         unsigned long   paddr;
  227         void            *vaddr;
  228         int             memsize;
  229         int             pagesize;
  230         int             hostoffset;
  231         int             slaveoffset;
  232         int             bitsize;
  233         int             confbits;
  234         void            (*init)(struct stlibrd *brdp);
  235         void            (*enable)(struct stlibrd *brdp);
  236         void            (*reenable)(struct stlibrd *brdp);
  237         void            (*disable)(struct stlibrd *brdp);
  238         void            (*intr)(struct stlibrd *brdp);
  239         void            (*reset)(struct stlibrd *brdp);
  240         char            *(*getmemptr)(struct stlibrd *brdp,
  241                                 unsigned long offset, int line);
  242         int             panels[STL_MAXPANELS];
  243         int             panelids[STL_MAXPANELS];
  244         stliport_t      *ports[STL_PORTSPERBRD];
  245 } stlibrd_t;
  246 
  247 static stlibrd_t        *stli_brds[STL_MAXBRDS];
  248 
  249 static int              stli_shared = 0;
  250 
  251 /*
  252  *      Keep a local char buffer for processing chars into the LD. We
  253  *      do this to avoid copying from the boards shared memory one char
  254  *      at a time.
  255  */
  256 static int              stli_rxtmplen;
  257 static stliport_t       *stli_rxtmpport;
  258 static char             stli_rxtmpbuf[TTYHOG];
  259 
  260 /*
  261  *      Define global stats structures. Not used often, and can be re-used
  262  *      for each stats call.
  263  */
  264 static comstats_t       stli_comstats;
  265 static combrd_t         stli_brdstats;
  266 static asystats_t       stli_cdkstats;
  267 
  268 /*
  269  *      Per board state flags. Used with the state field of the board struct.
  270  *      Not really much here... All we need to do is keep track of whether
  271  *      the board has been detected, and whether it is actully running a slave
  272  *      or not.
  273  */
  274 #define BST_FOUND       0x1
  275 #define BST_STARTED     0x2
  276 
  277 /*
  278  *      Define the set of port state flags. These are marked for internal
  279  *      state purposes only, usually to do with the state of communications
  280  *      with the slave. They need to be updated atomically.
  281  */
  282 #define ST_INITIALIZING 0x1
  283 #define ST_INITIALIZED  0x2
  284 #define ST_OPENING      0x4
  285 #define ST_CLOSING      0x8
  286 #define ST_CMDING       0x10
  287 #define ST_RXING        0x20
  288 #define ST_TXBUSY       0x40
  289 #define ST_DOFLUSHRX    0x80
  290 #define ST_DOFLUSHTX    0x100
  291 #define ST_DOSIGS       0x200
  292 #define ST_GETSIGS      0x400
  293 #define ST_DTRWAIT      0x800
  294 
  295 /*
  296  *      Define an array of board names as printable strings. Handy for
  297  *      referencing boards when printing trace and stuff.
  298  */
  299 static char     *stli_brdnames[] = {
  300         "Unknown",
  301         "Stallion",
  302         "Brumby",
  303         "ONboard-MC",
  304         "ONboard",
  305         "Brumby",
  306         "Brumby",
  307         "ONboard-EI",
  308         (char *) NULL,
  309         "ONboard",
  310         "ONboard-MC",
  311         "ONboard-MC",
  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         "EasyIO",
  321         "EC8/32-AT",
  322         "EC8/32-MC",
  323         "EC8/64-AT",
  324         "EC8/64-EI",
  325         "EC8/64-MC",
  326         "EC8/32-PCI",
  327 };
  328 
  329 /*****************************************************************************/
  330 
  331 /*
  332  *      Hardware configuration info for ECP boards. These defines apply
  333  *      to the directly accessable io ports of the ECP. There is a set of
  334  *      defines for each ECP board type, ISA, EISA and MCA.
  335  */
  336 #define ECP_IOSIZE      4
  337 #define ECP_MEMSIZE     (128 * 1024)
  338 #define ECP_ATPAGESIZE  (4 * 1024)
  339 #define ECP_EIPAGESIZE  (64 * 1024)
  340 #define ECP_MCPAGESIZE  (4 * 1024)
  341 
  342 #define STL_EISAID      0x8c4e
  343 
  344 /*
  345  *      Important defines for the ISA class of ECP board.
  346  */
  347 #define ECP_ATIREG      0
  348 #define ECP_ATCONFR     1
  349 #define ECP_ATMEMAR     2
  350 #define ECP_ATMEMPR     3
  351 #define ECP_ATSTOP      0x1
  352 #define ECP_ATINTENAB   0x10
  353 #define ECP_ATENABLE    0x20
  354 #define ECP_ATDISABLE   0x00
  355 #define ECP_ATADDRMASK  0x3f000
  356 #define ECP_ATADDRSHFT  12
  357 
  358 /*
  359  *      Important defines for the EISA class of ECP board.
  360  */
  361 #define ECP_EIIREG      0
  362 #define ECP_EIMEMARL    1
  363 #define ECP_EICONFR     2
  364 #define ECP_EIMEMARH    3
  365 #define ECP_EIENABLE    0x1
  366 #define ECP_EIDISABLE   0x0
  367 #define ECP_EISTOP      0x4
  368 #define ECP_EIEDGE      0x00
  369 #define ECP_EILEVEL     0x80
  370 #define ECP_EIADDRMASKL 0x00ff0000
  371 #define ECP_EIADDRSHFTL 16
  372 #define ECP_EIADDRMASKH 0xff000000
  373 #define ECP_EIADDRSHFTH 24
  374 #define ECP_EIBRDENAB   0xc84
  375 
  376 #define ECP_EISAID      0x4
  377 
  378 /*
  379  *      Important defines for the Micro-channel class of ECP board.
  380  *      (It has a lot in common with the ISA boards.)
  381  */
  382 #define ECP_MCIREG      0
  383 #define ECP_MCCONFR     1
  384 #define ECP_MCSTOP      0x20
  385 #define ECP_MCENABLE    0x80
  386 #define ECP_MCDISABLE   0x00
  387 
  388 /*
  389  *      Hardware configuration info for ONboard and Brumby boards. These
  390  *      defines apply to the directly accessable io ports of these boards.
  391  */
  392 #define ONB_IOSIZE      16
  393 #define ONB_MEMSIZE     (64 * 1024)
  394 #define ONB_ATPAGESIZE  (64 * 1024)
  395 #define ONB_MCPAGESIZE  (64 * 1024)
  396 #define ONB_EIMEMSIZE   (128 * 1024)
  397 #define ONB_EIPAGESIZE  (64 * 1024)
  398 
  399 /*
  400  *      Important defines for the ISA class of ONboard board.
  401  */
  402 #define ONB_ATIREG      0
  403 #define ONB_ATMEMAR     1
  404 #define ONB_ATCONFR     2
  405 #define ONB_ATSTOP      0x4
  406 #define ONB_ATENABLE    0x01
  407 #define ONB_ATDISABLE   0x00
  408 #define ONB_ATADDRMASK  0xff0000
  409 #define ONB_ATADDRSHFT  16
  410 
  411 #define ONB_HIMEMENAB   0x02
  412 
  413 /*
  414  *      Important defines for the EISA class of ONboard board.
  415  */
  416 #define ONB_EIIREG      0
  417 #define ONB_EIMEMARL    1
  418 #define ONB_EICONFR     2
  419 #define ONB_EIMEMARH    3
  420 #define ONB_EIENABLE    0x1
  421 #define ONB_EIDISABLE   0x0
  422 #define ONB_EISTOP      0x4
  423 #define ONB_EIEDGE      0x00
  424 #define ONB_EILEVEL     0x80
  425 #define ONB_EIADDRMASKL 0x00ff0000
  426 #define ONB_EIADDRSHFTL 16
  427 #define ONB_EIADDRMASKH 0xff000000
  428 #define ONB_EIADDRSHFTH 24
  429 #define ONB_EIBRDENAB   0xc84
  430 
  431 #define ONB_EISAID      0x1
  432 
  433 /*
  434  *      Important defines for the Brumby boards. They are pretty simple,
  435  *      there is not much that is programmably configurable.
  436  */
  437 #define BBY_IOSIZE      16
  438 #define BBY_MEMSIZE     (64 * 1024)
  439 #define BBY_PAGESIZE    (16 * 1024)
  440 
  441 #define BBY_ATIREG      0
  442 #define BBY_ATCONFR     1
  443 #define BBY_ATSTOP      0x4
  444 
  445 /*
  446  *      Important defines for the Stallion boards. They are pretty simple,
  447  *      there is not much that is programmably configurable.
  448  */
  449 #define STAL_IOSIZE     16
  450 #define STAL_MEMSIZE    (64 * 1024)
  451 #define STAL_PAGESIZE   (64 * 1024)
  452 
  453 /*
  454  *      Define the set of status register values for EasyConnection panels.
  455  *      The signature will return with the status value for each panel. From
  456  *      this we can determine what is attached to the board - before we have
  457  *      actually down loaded any code to it.
  458  */
  459 #define ECH_PNLSTATUS   2
  460 #define ECH_PNL16PORT   0x20
  461 #define ECH_PNLIDMASK   0x07
  462 #define ECH_PNLINTRPEND 0x80
  463 
  464 /*
  465  *      Define some macros to do things to the board. Even those these boards
  466  *      are somewhat related there is often significantly different ways of
  467  *      doing some operation on it (like enable, paging, reset, etc). So each
  468  *      board class has a set of functions which do the commonly required
  469  *      operations. The macros below basically just call these functions,
  470  *      generally checking for a NULL function - which means that the board
  471  *      needs nothing done to it to achieve this operation!
  472  */
  473 #define EBRDINIT(brdp)                                  \
  474         if (brdp->init != NULL)                         \
  475                 (* brdp->init)(brdp)
  476 
  477 #define EBRDENABLE(brdp)                                \
  478         if (brdp->enable != NULL)                       \
  479                 (* brdp->enable)(brdp);
  480 
  481 #define EBRDDISABLE(brdp)                               \
  482         if (brdp->disable != NULL)                      \
  483                 (* brdp->disable)(brdp);
  484 
  485 #define EBRDINTR(brdp)                                  \
  486         if (brdp->intr != NULL)                         \
  487                 (* brdp->intr)(brdp);
  488 
  489 #define EBRDRESET(brdp)                                 \
  490         if (brdp->reset != NULL)                        \
  491                 (* brdp->reset)(brdp);
  492 
  493 #define EBRDGETMEMPTR(brdp,offset)                      \
  494         (* brdp->getmemptr)(brdp, offset, __LINE__)
  495 
  496 /*
  497  *      Define the maximal baud rate.
  498  */
  499 #define STL_MAXBAUD     230400
  500 
  501 /*****************************************************************************/
  502 
  503 /*
  504  *      Define macros to extract a brd and port number from a minor number.
  505  *      This uses the extended minor number range in the upper 2 bytes of
  506  *      the device number. This gives us plenty of minor numbers to play
  507  *      with...
  508  */
  509 #define MKDEV2BRD(m)    (((m) & 0x00700000) >> 20)
  510 #define MKDEV2PORT(m)   (((m) & 0x1f) | (((m) & 0x00010000) >> 11))
  511 
  512 /*
  513  *      Define some handy local macros...
  514  */
  515 #ifndef MIN
  516 #define MIN(a,b)        (((a) <= (b)) ? (a) : (b))
  517 #endif
  518 
  519 /*****************************************************************************/
  520 
  521 /*
  522  *      Declare all those functions in this driver!  First up is the set of
  523  *      externally visible functions.
  524  */
  525 int     stliprobe(struct isa_device *idp);
  526 int     stliattach(struct isa_device *idp);
  527 
  528 STATIC  d_open_t        stliopen;
  529 STATIC  d_close_t       stliclose;
  530 STATIC  d_read_t        stliread;
  531 STATIC  d_write_t       stliwrite;
  532 STATIC  d_ioctl_t       stliioctl;
  533 STATIC  d_stop_t        stlistop;
  534 
  535 #if VFREEBSD >= 220
  536 STATIC  d_devtotty_t    stlidevtotty;
  537 #else
  538 struct tty              *stlidevtotty(dev_t dev);
  539 #endif
  540 
  541 /*
  542  *      Internal function prototypes.
  543  */
  544 static stliport_t *stli_dev2port(dev_t dev);
  545 static int      stli_chksharemem(void);
  546 static int      stli_isaprobe(struct isa_device *idp);
  547 static int      stli_eisaprobe(struct isa_device *idp);
  548 static int      stli_mcaprobe(struct isa_device *idp);
  549 static int      stli_brdinit(stlibrd_t *brdp);
  550 static int      stli_brdattach(stlibrd_t *brdp);
  551 static int      stli_initecp(stlibrd_t *brdp);
  552 static int      stli_initonb(stlibrd_t *brdp);
  553 static int      stli_initports(stlibrd_t *brdp);
  554 static int      stli_startbrd(stlibrd_t *brdp);
  555 static void     stli_poll(void *arg);
  556 static void     stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp);
  557 static int      stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
  558 static void     stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp);
  559 static void     stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
  560 static long     stli_mktiocm(unsigned long sigvalue);
  561 static void     stli_rxprocess(stlibrd_t *brdp, stliport_t *portp);
  562 static void     stli_flush(stliport_t *portp, int flag);
  563 static void     stli_start(struct tty *tp);
  564 static int      stli_param(struct tty *tp, struct termios *tiosp);
  565 static void     stli_ttyoptim(stliport_t *portp, struct termios *tiosp);
  566 static void     stli_dtrwakeup(void *arg);
  567 static int      stli_initopen(stliport_t *portp);
  568 static int      stli_shutdownclose(stliport_t *portp);
  569 static int      stli_rawopen(stlibrd_t *brdp, stliport_t *portp,
  570                         unsigned long arg, int wait);
  571 static int      stli_rawclose(stlibrd_t *brdp, stliport_t *portp,
  572                         unsigned long arg, int wait);
  573 static int      stli_cmdwait(stlibrd_t *brdp, stliport_t *portp,
  574                         unsigned long cmd, void *arg, int size, int copyback);
  575 static void     stli_sendcmd(stlibrd_t *brdp, stliport_t *portp,
  576                         unsigned long cmd, void *arg, int size, int copyback);
  577 static void     stli_mkasyport(stliport_t *portp, asyport_t *pp,
  578                         struct termios *tiosp);
  579 static int      stli_memrw(dev_t dev, struct uio *uiop, int flag);
  580 static int      stli_memioctl(dev_t dev, int cmd, caddr_t data, int flag,
  581                         struct proc *p);
  582 static int      stli_getbrdstats(caddr_t data);
  583 static int      stli_getportstats(stliport_t *portp, caddr_t data);
  584 static int      stli_clrportstats(stliport_t *portp, caddr_t data);
  585 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
  586 
  587 static void     stli_ecpinit(stlibrd_t *brdp);
  588 static void     stli_ecpenable(stlibrd_t *brdp);
  589 static void     stli_ecpdisable(stlibrd_t *brdp);
  590 static void     stli_ecpreset(stlibrd_t *brdp);
  591 static char     *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset,
  592                         int line);
  593 static void     stli_ecpintr(stlibrd_t *brdp);
  594 static void     stli_ecpeiinit(stlibrd_t *brdp);
  595 static void     stli_ecpeienable(stlibrd_t *brdp);
  596 static void     stli_ecpeidisable(stlibrd_t *brdp);
  597 static void     stli_ecpeireset(stlibrd_t *brdp);
  598 static char     *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset,
  599                         int line);
  600 static void     stli_ecpmcenable(stlibrd_t *brdp);
  601 static void     stli_ecpmcdisable(stlibrd_t *brdp);
  602 static void     stli_ecpmcreset(stlibrd_t *brdp);
  603 static char     *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset,
  604                         int line);
  605 
  606 static void     stli_onbinit(stlibrd_t *brdp);
  607 static void     stli_onbenable(stlibrd_t *brdp);
  608 static void     stli_onbdisable(stlibrd_t *brdp);
  609 static void     stli_onbreset(stlibrd_t *brdp);
  610 static char     *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset,
  611                         int line);
  612 static void     stli_onbeinit(stlibrd_t *brdp);
  613 static void     stli_onbeenable(stlibrd_t *brdp);
  614 static void     stli_onbedisable(stlibrd_t *brdp);
  615 static void     stli_onbereset(stlibrd_t *brdp);
  616 static char     *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset,
  617                         int line);
  618 static void     stli_bbyinit(stlibrd_t *brdp);
  619 static void     stli_bbyreset(stlibrd_t *brdp);
  620 static char     *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset,
  621                         int line);
  622 static void     stli_stalinit(stlibrd_t *brdp);
  623 static void     stli_stalreset(stlibrd_t *brdp);
  624 static char     *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset,
  625                         int line);
  626 
  627 /*****************************************************************************/
  628 
  629 /*
  630  *      Declare the driver isa structure.
  631  */
  632 struct isa_driver       stlidriver = {
  633         stliprobe, stliattach, stli_drvname
  634 };
  635 
  636 /*****************************************************************************/
  637 
  638 #if VFREEBSD >= 220
  639 
  640 /*
  641  *      FreeBSD-2.2+ kernel linkage.
  642  */
  643 
  644 #define CDEV_MAJOR      75
  645 
  646 static struct cdevsw stli_cdevsw = 
  647         { stliopen,     stliclose,      stliread,       stliwrite,
  648           stliioctl,    stlistop,       noreset,        stlidevtotty,
  649           ttselect,     nommap,         NULL,           stli_drvname,
  650           NULL,         -1 };
  651 
  652 static stli_devsw_installed = 0;
  653 
  654 static void stli_drvinit(void *unused)
  655 {
  656         dev_t   dev;
  657 
  658         if (! stli_devsw_installed ) {
  659                 dev = makedev(CDEV_MAJOR, 0);
  660                 cdevsw_add(&dev, &stli_cdevsw, NULL);
  661                 stli_devsw_installed = 1;
  662         }
  663 }
  664 
  665 SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,stli_drvinit,NULL)
  666 
  667 #endif
  668 
  669 /*****************************************************************************/
  670 
  671 static stlibrd_t *stli_brdalloc(void)
  672 {
  673         stlibrd_t       *brdp;
  674 
  675         brdp = (stlibrd_t *) malloc(sizeof(stlibrd_t), M_TTYS, M_NOWAIT);
  676         if (brdp == (stlibrd_t *) NULL) {
  677                 printf("STALLION: failed to allocate memory (size=%d)\n",
  678                         sizeof(stlibrd_t));
  679                 return((stlibrd_t *) NULL);
  680         }
  681         bzero(brdp, sizeof(stlibrd_t));
  682         return(brdp);
  683 }
  684 
  685 /*****************************************************************************/
  686 
  687 /*
  688  *      Find an available internal board number (unit number). The problem
  689  *      is that the same unit numbers can be assigned to different class
  690  *      boards - but we only want to maintain one setup board structures.
  691  */
  692 
  693 static int stli_findfreeunit(void)
  694 {
  695         int     i;
  696 
  697         for (i = 0; (i < STL_MAXBRDS); i++)
  698                 if (stli_brds[i] == (stlibrd_t *) NULL)
  699                         break;
  700         return((i >= STL_MAXBRDS) ? -1 : i);
  701 }
  702 
  703 /*****************************************************************************/
  704 
  705 /*
  706  *      Try and determine the ISA board type. Hopefully the board
  707  *      configuration entry will help us out, using the flags field.
  708  *      If not, we may ne be able to determine the board type...
  709  */
  710 
  711 static int stli_isaprobe(struct isa_device *idp)
  712 {
  713         int     btype;
  714 
  715 #if DEBUG
  716         printf("stli_isaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  717                 (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  718 #endif
  719 
  720         switch (idp->id_flags) {
  721         case BRD_STALLION:
  722         case BRD_BRUMBY4:
  723         case BRD_BRUMBY8:
  724         case BRD_BRUMBY16:
  725         case BRD_ONBOARD:
  726         case BRD_ONBOARD32:
  727         case BRD_ECP:
  728                 btype = idp->id_flags;
  729                 break;
  730         default:
  731                 btype = 0;
  732                 break;
  733         }
  734         return(btype);
  735 }
  736 
  737 /*****************************************************************************/
  738 
  739 /*
  740  *      Probe for an EISA board type. We should be able to read the EISA ID,
  741  *      that will tell us if a board is present or not...
  742  */
  743 
  744 static int stli_eisaprobe(struct isa_device *idp)
  745 {
  746         int     btype, eid;
  747 
  748 #if DEBUG
  749         printf("stli_eisaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  750                 (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  751 #endif
  752 
  753 /*
  754  *      Firstly check if this is an EISA system. Do this by probing for
  755  *      the system board EISA ID. If this is not an EISA system then
  756  *      don't bother going any further!
  757  */
  758         outb(0xc80, 0xff);
  759         if (inb(0xc80) == 0xff)
  760                 return(0);
  761 
  762 /*
  763  *      Try and read the EISA ID from the board at specified address.
  764  *      If one is present it will tell us the board type as well.
  765  */
  766         outb((idp->id_iobase + 0xc80), 0xff);
  767         eid = inb(idp->id_iobase + 0xc80);
  768         eid |= inb(idp->id_iobase + 0xc81) << 8;
  769         if (eid != STL_EISAID)
  770                 return(0);
  771 
  772         btype = 0;
  773         eid = inb(idp->id_iobase + 0xc82);
  774         if (eid == ECP_EISAID)
  775                 btype = BRD_ECPE;
  776         else if (eid == ONB_EISAID)
  777                 btype = BRD_ONBOARDE;
  778 
  779         outb((idp->id_iobase + 0xc84), 0x1);
  780         return(btype);
  781 }
  782 
  783 /*****************************************************************************/
  784 
  785 /*
  786  *      Probe for an MCA board type. Not really sure how to do this yet,
  787  *      so for now just use the supplied flag specifier as board type...
  788  */
  789 
  790 static int stli_mcaprobe(struct isa_device *idp)
  791 {
  792         int     btype;
  793 
  794 #if DEBUG
  795         printf("stli_mcaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  796                 (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  797 #endif
  798 
  799         switch (idp->id_flags) {
  800         case BRD_ONBOARD2:
  801         case BRD_ONBOARD2_32:
  802         case BRD_ONBOARDRS:
  803         case BRD_ECHMC:
  804         case BRD_ECPMC:
  805                 btype = idp->id_flags;
  806                 break;
  807         default:
  808                 btype = 0;
  809                 break;
  810         }
  811         return(0);
  812 }
  813 
  814 /*****************************************************************************/
  815 
  816 /*
  817  *      Probe for a board. This is involved, since we need to enable the
  818  *      shared memory region to see if the board is really there or not...
  819  */
  820 
  821 int stliprobe(struct isa_device *idp)
  822 {
  823         stlibrd_t       *brdp;
  824         int             btype, bclass;
  825 
  826 #if DEBUG
  827         printf("stliprobe(idp=%x): unit=%d iobase=%x flags=%x\n", (int) idp,
  828                 idp->id_unit, idp->id_iobase, idp->id_flags);
  829 #endif
  830 
  831         if (idp->id_unit > STL_MAXBRDS)
  832                 return(0);
  833 
  834 /*
  835  *      First up determine what bus type of board we might be dealing
  836  *      with. It is easy to separate out the ISA from the EISA and MCA
  837  *      boards, based on their IO addresses. We may not be able to tell
  838  *      the EISA and MCA apart on IO address alone...
  839  */
  840         bclass = 0;
  841         if ((idp->id_iobase > 0) && (idp->id_iobase < 0x400)) {
  842                 bclass |= BRD_ISA;
  843         } else {
  844                 /* ONboard2 range */
  845                 if ((idp->id_iobase >= 0x700) && (idp->id_iobase < 0x900))
  846                         bclass |= BRD_MCA;
  847                 /* EC-MCA ranges */
  848                 if ((idp->id_iobase >= 0x7000) && (idp->id_iobase < 0x7400))
  849                         bclass |= BRD_MCA;
  850                 if ((idp->id_iobase >= 0x8000) && (idp->id_iobase < 0xc000))
  851                         bclass |= BRD_MCA;
  852                 /* EISA board range */
  853                 if ((idp->id_iobase & ~0xf000) == 0)
  854                         bclass |= BRD_EISA;
  855         }
  856 
  857         if ((bclass == 0) || (idp->id_iobase == 0))
  858                 return(0);
  859 
  860 /*
  861  *      Based on the board bus type, try and figure out what it might be...
  862  */
  863         btype = 0;
  864         if (bclass & BRD_ISA)
  865                 btype = stli_isaprobe(idp);
  866         if ((btype == 0) && (bclass & BRD_EISA))
  867                 btype = stli_eisaprobe(idp);
  868         if ((btype == 0) && (bclass & BRD_MCA))
  869                 btype = stli_mcaprobe(idp);
  870         if (btype == 0)
  871                 return(0);
  872 
  873 /*
  874  *      Go ahead and try probing for the shared memory region now.
  875  *      This way we will really know if the board is here...
  876  */
  877         if ((brdp = stli_brdalloc()) == (stlibrd_t *) NULL)
  878                 return(0);
  879 
  880         brdp->brdnr = stli_findfreeunit();
  881         brdp->brdtype = btype;
  882         brdp->unitid = idp->id_unit;
  883         brdp->iobase = idp->id_iobase;
  884         brdp->vaddr = idp->id_maddr;
  885         brdp->paddr = vtophys(idp->id_maddr);
  886 
  887 #if DEBUG
  888         printf("%s(%d): btype=%x unit=%d brd=%d io=%x mem=%x(%x)\n",
  889                 __file__, __LINE__, btype, brdp->unitid, brdp->brdnr,
  890                 brdp->iobase, brdp->paddr, brdp->vaddr);
  891 #endif
  892 
  893         stli_stliprobed[idp->id_unit] = brdp->brdnr;
  894         stli_brdinit(brdp);
  895         if ((brdp->state & BST_FOUND) == 0) {
  896                 stli_brds[brdp->brdnr] = (stlibrd_t *) NULL;
  897                 return(0);
  898         }
  899         stli_nrbrds++;
  900         return(1);
  901 }
  902 
  903 /*****************************************************************************/
  904 
  905 /*
  906  *      Allocate resources for and initialize a board.
  907  */
  908 
  909 int stliattach(struct isa_device *idp)
  910 {
  911         stlibrd_t       *brdp;
  912         int             brdnr;
  913 
  914 #if DEBUG
  915         printf("stliattach(idp=%x): unit=%d iobase=%x\n", idp,
  916                 idp->id_unit, idp->id_iobase);
  917 #endif
  918 
  919         brdnr = stli_stliprobed[idp->id_unit];
  920         brdp = stli_brds[brdnr];
  921         if (brdp == (stlibrd_t *) NULL)
  922                 return(0);
  923         if (brdp->state & BST_FOUND)
  924                 stli_brdattach(brdp);
  925         return(1);
  926 }
  927 
  928 
  929 /*****************************************************************************/
  930 
  931 STATIC int stliopen(dev_t dev, int flag, int mode, struct proc *p)
  932 {
  933         struct tty      *tp;
  934         stliport_t      *portp;
  935         int             error, callout, x;
  936 
  937 #if DEBUG
  938         printf("stliopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
  939                 mode, (int) p);
  940 #endif
  941 
  942 /*
  943  *      Firstly check if the supplied device number is a valid device.
  944  */
  945         if (dev & STL_MEMDEV)
  946                 return(0);
  947 
  948         portp = stli_dev2port(dev);
  949         if (portp == (stliport_t *) NULL)
  950                 return(ENXIO);
  951         tp = &portp->tty;
  952         callout = minor(dev) & STL_CALLOUTDEV;
  953         error = 0;
  954 
  955         x = spltty();
  956 
  957 stliopen_restart:
  958 /*
  959  *      Wait here for the DTR drop timeout period to expire.
  960  */
  961         while (portp->state & ST_DTRWAIT) {
  962                 error = tsleep(&portp->dtrwait, (TTIPRI | PCATCH),
  963                         "stlidtr", 0);
  964                 if (error)
  965                         goto stliopen_end;
  966         }
  967 
  968 /*
  969  *      If the port is in its raw hardware initialization phase, then
  970  *      hold up here 'till it is done.
  971  */
  972         while (portp->state & (ST_INITIALIZING | ST_CLOSING)) {
  973                 error = tsleep(&portp->state, (TTIPRI | PCATCH),
  974                         "stliraw", 0);
  975                 if (error)
  976                         goto stliopen_end;
  977         }
  978 
  979 /*
  980  *      We have a valid device, so now we check if it is already open.
  981  *      If not then initialize the port hardware and set up the tty
  982  *      struct as required.
  983  */
  984         if ((tp->t_state & TS_ISOPEN) == 0) {
  985                 tp->t_oproc = stli_start;
  986                 tp->t_param = stli_param;
  987                 tp->t_dev = dev;
  988                 tp->t_termios = callout ? portp->initouttios :
  989                         portp->initintios;
  990                 stli_initopen(portp);
  991                 wakeup(&portp->state);
  992                 ttsetwater(tp);
  993                 if ((portp->sigs & TIOCM_CD) || callout)
  994                         (*linesw[tp->t_line].l_modem)(tp, 1);
  995         } else {
  996                 if (callout) {
  997                         if (portp->callout == 0) {
  998                                 error = EBUSY;
  999                                 goto stliopen_end;
 1000                         }
 1001                 } else {
 1002                         if (portp->callout != 0) {
 1003                                 if (flag & O_NONBLOCK) {
 1004                                         error = EBUSY;
 1005                                         goto stliopen_end;
 1006                                 }
 1007                                 error = tsleep(&portp->callout,
 1008                                         (TTIPRI | PCATCH), "stlicall", 0);
 1009                                 if (error)
 1010                                         goto stliopen_end;
 1011                                 goto stliopen_restart;
 1012                         }
 1013                 }
 1014                 if ((tp->t_state & TS_XCLUDE) && (p->p_ucred->cr_uid != 0)) {
 1015                         error = EBUSY;
 1016                         goto stliopen_end;
 1017                 }
 1018         }
 1019 
 1020 /*
 1021  *      If this port is not the callout device and we do not have carrier
 1022  *      then we need to sleep, waiting for it to be asserted.
 1023  */
 1024         if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
 1025                         ((tp->t_cflag & CLOCAL) == 0) &&
 1026                         ((flag & O_NONBLOCK) == 0)) {
 1027                 portp->waitopens++;
 1028                 error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stlidcd",0);
 1029                 portp->waitopens--;
 1030                 if (error)
 1031                         goto stliopen_end;
 1032                 goto stliopen_restart;
 1033         }
 1034 
 1035 /*
 1036  *      Open the line discipline.
 1037  */
 1038         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1039         stli_ttyoptim(portp, &tp->t_termios);
 1040         if ((tp->t_state & TS_ISOPEN) && callout)
 1041                 portp->callout = 1;
 1042 
 1043 /*
 1044  *      If for any reason we get to here and the port is not actually
 1045  *      open then close of the physical hardware - no point leaving it
 1046  *      active when the open failed...
 1047  */
 1048 stliopen_end:
 1049         splx(x);
 1050         if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
 1051                 stli_shutdownclose(portp);
 1052 
 1053         return(error);
 1054 }
 1055 
 1056 /*****************************************************************************/
 1057 
 1058 STATIC int stliclose(dev_t dev, int flag, int mode, struct proc *p)
 1059 {
 1060         struct tty      *tp;
 1061         stliport_t      *portp;
 1062         int             x;
 1063 
 1064 #if DEBUG
 1065         printf("stliclose(dev=%x,flag=%x,mode=%x,p=%x)\n", dev, flag, mode, p);
 1066 #endif
 1067 
 1068         if (dev & STL_MEMDEV)
 1069                 return(0);
 1070 
 1071         portp = stli_dev2port(dev);
 1072         if (portp == (stliport_t *) NULL)
 1073                 return(ENXIO);
 1074         tp = &portp->tty;
 1075 
 1076         x = spltty();
 1077         (*linesw[tp->t_line].l_close)(tp, flag);
 1078         stli_ttyoptim(portp, &tp->t_termios);
 1079         stli_shutdownclose(portp);
 1080         ttyclose(tp);
 1081         splx(x);
 1082         return(0);
 1083 }
 1084 
 1085 /*****************************************************************************/
 1086 
 1087 STATIC int stliread(dev_t dev, struct uio *uiop, int flag)
 1088 {
 1089         stliport_t      *portp;
 1090 
 1091 #if DEBUG
 1092         printf("stliread(dev=%x,uiop=%x,flag=%x)\n", dev, uiop, flag);
 1093 #endif
 1094 
 1095         if (dev & STL_MEMDEV)
 1096                 return(stli_memrw(dev, uiop, flag));
 1097 
 1098         portp = stli_dev2port(dev);
 1099         if (portp == (stliport_t *) NULL)
 1100                 return(ENODEV);
 1101         return((*linesw[portp->tty.t_line].l_read)(&portp->tty, uiop, flag));
 1102 }
 1103 
 1104 /*****************************************************************************/
 1105 
 1106 #if VFREEBSD >= 220
 1107 
 1108 STATIC void stlistop(struct tty *tp, int rw)
 1109 {
 1110 #if DEBUG
 1111         printf("stlistop(tp=%x,rw=%x)\n", (int) tp, rw);
 1112 #endif
 1113 
 1114         stli_flush((stliport_t *) tp, rw);
 1115 }
 1116 
 1117 #else
 1118 
 1119 STATIC int stlistop(struct tty *tp, int rw)
 1120 {
 1121 #if DEBUG
 1122         printf("stlistop(tp=%x,rw=%x)\n", (int) tp, rw);
 1123 #endif
 1124 
 1125         stli_flush((stliport_t *) tp, rw);
 1126         return(0);
 1127 }
 1128 
 1129 #endif
 1130 
 1131 /*****************************************************************************/
 1132 
 1133 STATIC struct tty *stlidevtotty(dev_t dev)
 1134 {
 1135 #if DEBUG
 1136         printf("stlidevtotty(dev=%x)\n", dev);
 1137 #endif
 1138         return((struct tty *) stli_dev2port(dev));
 1139 }
 1140 
 1141 /*****************************************************************************/
 1142 
 1143 STATIC int stliwrite(dev_t dev, struct uio *uiop, int flag)
 1144 {
 1145         stliport_t      *portp;
 1146 
 1147 #if DEBUG
 1148         printf("stliwrite(dev=%x,uiop=%x,flag=%x)\n", dev, uiop, flag);
 1149 #endif
 1150 
 1151         if (dev & STL_MEMDEV)
 1152                 return(stli_memrw(dev, uiop, flag));
 1153 
 1154         portp = stli_dev2port(dev);
 1155         if (portp == (stliport_t *) NULL)
 1156                 return(ENODEV);
 1157         return((*linesw[portp->tty.t_line].l_write)(&portp->tty, uiop, flag));
 1158 }
 1159 
 1160 /*****************************************************************************/
 1161 
 1162 STATIC int stliioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 1163 {
 1164         struct termios  *newtios, *localtios;
 1165         struct tty      *tp;
 1166         stlibrd_t       *brdp;
 1167         stliport_t      *portp;
 1168         long            arg;
 1169         int             error, i, x;
 1170 
 1171 #if DEBUG
 1172         printf("stliioctl(dev=%x,cmd=%x,data=%x,flag=%x,p=%x)\n", dev, cmd,
 1173                 data, flag, p);
 1174 #endif
 1175 
 1176         dev = minor(dev);
 1177         if (dev & STL_MEMDEV)
 1178                 return(stli_memioctl(dev, cmd, data, flag, p));
 1179 
 1180         portp = stli_dev2port(dev);
 1181         if (portp == (stliport_t *) NULL)
 1182                 return(ENODEV);
 1183         if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1184                 return(ENODEV);
 1185         tp = &portp->tty;
 1186         error = 0;
 1187         
 1188 /*
 1189  *      First up handle ioctls on the control devices.
 1190  */
 1191         if (dev & STL_CTRLDEV) {
 1192                 if ((dev & STL_CTRLDEV) == STL_CTRLINIT)
 1193                         localtios = (dev & STL_CALLOUTDEV) ?
 1194                                 &portp->initouttios : &portp->initintios;
 1195                 else if ((dev & STL_CTRLDEV) == STL_CTRLLOCK)
 1196                         localtios = (dev & STL_CALLOUTDEV) ?
 1197                                 &portp->lockouttios : &portp->lockintios;
 1198                 else
 1199                         return(ENODEV);
 1200 
 1201                 switch (cmd) {
 1202                 case TIOCSETA:
 1203                         if ((error = suser(p->p_ucred, &p->p_acflag)) == 0)
 1204                                 *localtios = *((struct termios *) data);
 1205                         break;
 1206                 case TIOCGETA:
 1207                         *((struct termios *) data) = *localtios;
 1208                         break;
 1209                 case TIOCGETD:
 1210                         *((int *) data) = TTYDISC;
 1211                         break;
 1212                 case TIOCGWINSZ:
 1213                         bzero(data, sizeof(struct winsize));
 1214                         break;
 1215                 default:
 1216                         error = ENOTTY;
 1217                         break;
 1218                 }
 1219                 return(error);
 1220         }
 1221 
 1222 /*
 1223  *      Deal with 4.3 compatability issues if we have too...
 1224  */
 1225 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1226         if (1) {
 1227                 struct termios  tios;
 1228                 int             oldcmd;
 1229 
 1230                 tios = tp->t_termios;
 1231                 oldcmd = cmd;
 1232                 if ((error = ttsetcompat(tp, &cmd, data, &tios)))
 1233                         return(error);
 1234                 if (cmd != oldcmd)
 1235                         data = (caddr_t) &tios;
 1236         }
 1237 #endif
 1238 
 1239 /*
 1240  *      Carry out some pre-cmd processing work first...
 1241  *      Hmmm, not so sure we want this, disable for now...
 1242  */
 1243         if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1244                 newtios = (struct termios *) data;
 1245                 localtios = (dev & STL_CALLOUTDEV) ? &portp->lockouttios :
 1246                          &portp->lockintios;
 1247 
 1248                 newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
 1249                         (newtios->c_iflag & ~localtios->c_iflag);
 1250                 newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
 1251                         (newtios->c_oflag & ~localtios->c_oflag);
 1252                 newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
 1253                         (newtios->c_cflag & ~localtios->c_cflag);
 1254                 newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
 1255                         (newtios->c_lflag & ~localtios->c_lflag);
 1256                 for (i = 0; (i < NCCS); i++) {
 1257                         if (localtios->c_cc[i] != 0)
 1258                                 newtios->c_cc[i] = tp->t_cc[i];
 1259                 }
 1260                 if (localtios->c_ispeed != 0)
 1261                         newtios->c_ispeed = tp->t_ispeed;
 1262                 if (localtios->c_ospeed != 0)
 1263                         newtios->c_ospeed = tp->t_ospeed;
 1264         }
 1265 
 1266 /*
 1267  *      Call the line discipline and the common command processing to
 1268  *      process this command (if they can).
 1269  */
 1270         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 1271         if (error >= 0)
 1272                 return(error);
 1273 
 1274         x = spltty();
 1275         error = ttioctl(tp, cmd, data, flag);
 1276         stli_ttyoptim(portp, &tp->t_termios);
 1277         if (error >= 0) {
 1278                 splx(x);
 1279                 return(error);
 1280         }
 1281 
 1282         error = 0;
 1283 
 1284 /*
 1285  *      Process local commands here. These are all commands that only we
 1286  *      can take care of (they all rely on actually doing something special
 1287  *      to the actual hardware).
 1288  */
 1289         switch (cmd) {
 1290         case TIOCSBRK:
 1291                 arg = BREAKON;
 1292                 error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
 1293                         sizeof(unsigned long), 0);
 1294                 break;
 1295         case TIOCCBRK:
 1296                 arg = BREAKOFF;
 1297                 error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
 1298                         sizeof(unsigned long), 0);
 1299                 break;
 1300         case TIOCSDTR:
 1301                 stli_mkasysigs(&portp->asig, 1, -1);
 1302                 error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1303                         sizeof(asysigs_t), 0);
 1304                 break;
 1305         case TIOCCDTR:
 1306                 stli_mkasysigs(&portp->asig, 0, -1);
 1307                 error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1308                         sizeof(asysigs_t), 0);
 1309                 break;
 1310         case TIOCMSET:
 1311                 i = *((int *) data);
 1312                 stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : 0),
 1313                         ((i & TIOCM_RTS) ? 1 : 0));
 1314                 error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1315                         sizeof(asysigs_t), 0);
 1316                 break;
 1317         case TIOCMBIS:
 1318                 i = *((int *) data);
 1319                 stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : -1),
 1320                         ((i & TIOCM_RTS) ? 1 : -1));
 1321                 error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1322                         sizeof(asysigs_t), 0);
 1323                 break;
 1324         case TIOCMBIC:
 1325                 i = *((int *) data);
 1326                 stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 0 : -1),
 1327                         ((i & TIOCM_RTS) ? 0 : -1));
 1328                 error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1329                         sizeof(asysigs_t), 0);
 1330                 break;
 1331         case TIOCMGET:
 1332                 if ((error = stli_cmdwait(brdp, portp, A_GETSIGNALS,
 1333                                 &portp->asig, sizeof(asysigs_t), 1)) < 0)
 1334                         break;
 1335                 portp->sigs = stli_mktiocm(portp->asig.sigvalue);
 1336                 *((int *) data) = (portp->sigs | TIOCM_LE);
 1337                 break;
 1338         case TIOCMSDTRWAIT:
 1339                 if ((error = suser(p->p_ucred, &p->p_acflag)) == 0)
 1340                         portp->dtrwait = *((int *) data) * hz / 100;
 1341                 break;
 1342         case TIOCMGDTRWAIT:
 1343                 *((int *) data) = portp->dtrwait * 100 / hz;
 1344                 break;
 1345         case TIOCTIMESTAMP:
 1346                 portp->dotimestamp = 1;
 1347                 *((struct timeval *) data) = portp->timestamp;
 1348                 break;
 1349         default:
 1350                 error = ENOTTY;
 1351                 break;
 1352         }
 1353         splx(x);
 1354 
 1355         return(error);
 1356 }
 1357 
 1358 /*****************************************************************************/
 1359 
 1360 /*
 1361  *      Convert the specified minor device number into a port struct
 1362  *      pointer. Return NULL if the device number is not a valid port.
 1363  */
 1364 
 1365 STATIC stliport_t *stli_dev2port(dev_t dev)
 1366 {
 1367         stlibrd_t       *brdp;
 1368 
 1369         brdp = stli_brds[MKDEV2BRD(dev)];
 1370         if (brdp == (stlibrd_t *) NULL)
 1371                 return((stliport_t *) NULL);
 1372         if ((brdp->state & BST_STARTED) == 0)
 1373                 return((stliport_t *) NULL);
 1374         return(brdp->ports[MKDEV2PORT(dev)]);
 1375 }
 1376 
 1377 /*****************************************************************************/
 1378 
 1379 /*
 1380  *      Carry out first open operations on a port. This involves a number of
 1381  *      commands to be sent to the slave. We need to open the port, set the
 1382  *      notification events, set the initial port settings, get and set the
 1383  *      initial signal values. We sleep and wait in between each one. But
 1384  *      this still all happens pretty quickly.
 1385  */
 1386 
 1387 static int stli_initopen(stliport_t *portp)
 1388 {
 1389         stlibrd_t       *brdp;
 1390         asynotify_t     nt;
 1391         asyport_t       aport;
 1392         int             rc;
 1393 
 1394 #if DEBUG
 1395         printf("stli_initopen(portp=%x)\n", (int) portp);
 1396 #endif
 1397 
 1398         if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1399                 return(ENXIO);
 1400         if (portp->state & ST_INITIALIZED)
 1401                 return(0);
 1402         portp->state |= ST_INITIALIZED;
 1403 
 1404         if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
 1405                 return(rc);
 1406 
 1407         bzero(&nt, sizeof(asynotify_t));
 1408         nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
 1409         nt.signal = SG_DCD;
 1410         if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
 1411             sizeof(asynotify_t), 0)) < 0)
 1412                 return(rc);
 1413 
 1414         stli_mkasyport(portp, &aport, &portp->tty.t_termios);
 1415         if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
 1416             sizeof(asyport_t), 0)) < 0)
 1417                 return(rc);
 1418 
 1419         portp->state |= ST_GETSIGS;
 1420         if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
 1421             sizeof(asysigs_t), 1)) < 0)
 1422                 return(rc);
 1423         if (portp->state & ST_GETSIGS) {
 1424                 portp->sigs = stli_mktiocm(portp->asig.sigvalue);
 1425                 portp->state &= ~ST_GETSIGS;
 1426         }
 1427 
 1428         stli_mkasysigs(&portp->asig, 1, 1);
 1429         if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1430             sizeof(asysigs_t), 0)) < 0)
 1431                 return(rc);
 1432 
 1433         return(0);
 1434 }
 1435 
 1436 /*****************************************************************************/
 1437 
 1438 /*
 1439  *      Shutdown the hardware of a port.
 1440  */
 1441 
 1442 static int stli_shutdownclose(stliport_t *portp)
 1443 {
 1444         stlibrd_t       *brdp;
 1445         struct tty      *tp;
 1446 
 1447 #if DEBUG
 1448         printf("stli_shutdownclose(portp=%x): brdnr=%d panelnr=%d portnr=%d\n",
 1449                 portp, portp->brdnr, portp->panelnr, portp->portnr);
 1450 #endif
 1451 
 1452         if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1453                 return(ENXIO);
 1454 
 1455         tp = &portp->tty;
 1456         stli_rawclose(brdp, portp, 0, 0);
 1457         stli_flush(portp, (FWRITE | FREAD));
 1458         if (tp->t_cflag & HUPCL) {
 1459                 disable_intr();
 1460                 stli_mkasysigs(&portp->asig, 0, 0);
 1461                 if (portp->state & ST_CMDING) {
 1462                         portp->state |= ST_DOSIGS;
 1463                 } else {
 1464                         stli_sendcmd(brdp, portp, A_SETSIGNALS,
 1465                                 &portp->asig, sizeof(asysigs_t), 0);
 1466                 }
 1467                 enable_intr();
 1468                 if (portp->dtrwait != 0) {
 1469                         portp->state |= ST_DTRWAIT;
 1470                         timeout(stli_dtrwakeup, portp, portp->dtrwait);
 1471                 }
 1472         }
 1473         portp->callout = 0;
 1474         portp->state &= ~ST_INITIALIZED;
 1475         wakeup(&portp->callout);
 1476         wakeup(TSA_CARR_ON(tp));
 1477         return(0);
 1478 }
 1479 
 1480 /*****************************************************************************/
 1481 
 1482 /*
 1483  *      Clear the DTR waiting flag, and wake up any sleepers waiting for
 1484  *      DTR wait period to finish.
 1485  */
 1486 
 1487 static void stli_dtrwakeup(void *arg)
 1488 {
 1489         stliport_t      *portp;
 1490 
 1491         portp = (stliport_t *) arg;
 1492         portp->state &= ~ST_DTRWAIT;
 1493         wakeup(&portp->dtrwait);
 1494 }
 1495 
 1496 /*****************************************************************************/
 1497 
 1498 /*
 1499  *      Send an open message to the slave. This will sleep waiting for the
 1500  *      acknowledgement, so must have user context. We need to co-ordinate
 1501  *      with close events here, since we don't want open and close events
 1502  *      to overlap.
 1503  */
 1504 
 1505 static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 1506 {
 1507         volatile cdkhdr_t       *hdrp;
 1508         volatile cdkctrl_t      *cp;
 1509         volatile unsigned char  *bits;
 1510         int                     rc;
 1511 
 1512 #if DEBUG
 1513         printf("stli_rawopen(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
 1514                 (int) portp, (int) arg, wait);
 1515 #endif
 1516 
 1517         disable_intr();
 1518 
 1519 /*
 1520  *      Slave is already closing this port. This can happen if a hangup
 1521  *      occurs on this port. So we must wait until it is complete. The
 1522  *      order of opens and closes may not be preserved across shared
 1523  *      memory, so we must wait until it is complete.
 1524  */
 1525         while (portp->state & ST_CLOSING) {
 1526                 rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
 1527                 if (rc) {
 1528                         enable_intr();
 1529                         return(rc);
 1530                 }
 1531         }
 1532 
 1533 /*
 1534  *      Everything is ready now, so write the open message into shared
 1535  *      memory. Once the message is in set the service bits to say that
 1536  *      this port wants service.
 1537  */
 1538         EBRDENABLE(brdp);
 1539         cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1540         cp->openarg = arg;
 1541         cp->open = 1;
 1542         hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1543         bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1544                 portp->portidx;
 1545         *bits |= portp->portbit;
 1546         EBRDDISABLE(brdp);
 1547 
 1548         if (wait == 0) {
 1549                 enable_intr();
 1550                 return(0);
 1551         }
 1552 
 1553 /*
 1554  *      Slave is in action, so now we must wait for the open acknowledgment
 1555  *      to come back.
 1556  */
 1557         rc = 0;
 1558         portp->state |= ST_OPENING;
 1559         while (portp->state & ST_OPENING) {
 1560                 rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
 1561                 if (rc) {
 1562                         enable_intr();
 1563                         return(rc);
 1564                 }
 1565         }
 1566         enable_intr();
 1567 
 1568         if ((rc == 0) && (portp->rc != 0))
 1569                 rc = EIO;
 1570         return(rc);
 1571 }
 1572 
 1573 /*****************************************************************************/
 1574 
 1575 /*
 1576  *      Send a close message to the slave. Normally this will sleep waiting
 1577  *      for the acknowledgement, but if wait parameter is 0 it will not. If
 1578  *      wait is true then must have user context (to sleep).
 1579  */
 1580 
 1581 static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 1582 {
 1583         volatile cdkhdr_t       *hdrp;
 1584         volatile cdkctrl_t      *cp;
 1585         volatile unsigned char  *bits;
 1586         int                     rc;
 1587 
 1588 #if DEBUG
 1589         printf("stli_rawclose(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
 1590                 (int) portp, (int) arg, wait);
 1591 #endif
 1592 
 1593         disable_intr();
 1594 
 1595 /*
 1596  *      Slave is already closing this port. This can happen if a hangup
 1597  *      occurs on this port.
 1598  */
 1599         if (wait) {
 1600                 while (portp->state & ST_CLOSING) {
 1601                         rc = tsleep(&portp->state, (TTIPRI | PCATCH),
 1602                                 "stliraw", 0);
 1603                         if (rc) {
 1604                                 enable_intr();
 1605                                 return(rc);
 1606                         }
 1607                 }
 1608         }
 1609 
 1610 /*
 1611  *      Write the close command into shared memory.
 1612  */
 1613         EBRDENABLE(brdp);
 1614         cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1615         cp->closearg = arg;
 1616         cp->close = 1;
 1617         hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1618         bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1619                 portp->portidx;
 1620         *bits |= portp->portbit;
 1621         EBRDDISABLE(brdp);
 1622 
 1623         portp->state |= ST_CLOSING;
 1624         if (wait == 0) {
 1625                 enable_intr();
 1626                 return(0);
 1627         }
 1628 
 1629 /*
 1630  *      Slave is in action, so now we must wait for the open acknowledgment
 1631  *      to come back.
 1632  */
 1633         rc = 0;
 1634         while (portp->state & ST_CLOSING) {
 1635                 rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
 1636                 if (rc) {
 1637                         enable_intr();
 1638                         return(rc);
 1639                 }
 1640         }
 1641         enable_intr();
 1642 
 1643         if ((rc == 0) && (portp->rc != 0))
 1644                 rc = EIO;
 1645         return(rc);
 1646 }
 1647 
 1648 /*****************************************************************************/
 1649 
 1650 /*
 1651  *      Send a command to the slave and wait for the response. This must
 1652  *      have user context (it sleeps). This routine is generic in that it
 1653  *      can send any type of command. Its purpose is to wait for that command
 1654  *      to complete (as opposed to initiating the command then returning).
 1655  */
 1656 
 1657 static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 1658 {
 1659         int     rc;
 1660 
 1661 #if DEBUG
 1662         printf("stli_cmdwait(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
 1663                 "copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
 1664                 (int) arg, size, copyback);
 1665 #endif
 1666 
 1667         disable_intr();
 1668         while (portp->state & ST_CMDING) {
 1669                 rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
 1670                 if (rc) {
 1671                         enable_intr();
 1672                         return(rc);
 1673                 }
 1674         }
 1675 
 1676         stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
 1677 
 1678         while (portp->state & ST_CMDING) {
 1679                 rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
 1680                 if (rc) {
 1681                         enable_intr();
 1682                         return(rc);
 1683                 }
 1684         }
 1685         enable_intr();
 1686 
 1687         if (portp->rc != 0)
 1688                 return(EIO);
 1689         return(0);
 1690 }
 1691 
 1692 /*****************************************************************************/
 1693 
 1694 /*
 1695  *      Start (or continue) the transfer of TX data on this port. If the
 1696  *      port is not currently busy then load up the interrupt ring queue
 1697  *      buffer and kick of the transmitter. If the port is running low on
 1698  *      TX data then refill the ring queue. This routine is also used to
 1699  *      activate input flow control!
 1700  */
 1701 
 1702 static void stli_start(struct tty *tp)
 1703 {
 1704         volatile cdkasy_t       *ap;
 1705         volatile cdkhdr_t       *hdrp;
 1706         volatile unsigned char  *bits;
 1707         unsigned char           *shbuf;
 1708         stliport_t              *portp;
 1709         stlibrd_t               *brdp;
 1710         unsigned int            len, stlen, head, tail, size;
 1711         int                     count, x;
 1712 
 1713         portp = (stliport_t *) tp;
 1714 
 1715 #if DEBUG
 1716         printf("stli_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp, 
 1717                 portp->brdnr, portp->portnr);
 1718 #endif
 1719 
 1720         x = spltty();
 1721 
 1722 #if VFREEBSD == 205
 1723 /*
 1724  *      Check if the output cooked clist buffers are near empty, wake up
 1725  *      the line discipline to fill it up.
 1726  */
 1727         if (tp->t_outq.c_cc <= tp->t_lowat) {
 1728                 if (tp->t_state & TS_ASLEEP) {
 1729                         tp->t_state &= ~TS_ASLEEP;
 1730                         wakeup(&tp->t_outq);
 1731                 }
 1732                 selwakeup(&tp->t_wsel);
 1733         }
 1734 #endif
 1735 
 1736         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1737                 splx(x);
 1738                 return;
 1739         }
 1740 
 1741 /*
 1742  *      Copy data from the clists into the interrupt ring queue. This will
 1743  *      require at most 2 copys... What we do is calculate how many chars
 1744  *      can fit into the ring queue, and how many can fit in 1 copy. If after
 1745  *      the first copy there is still more room then do the second copy. 
 1746  */
 1747         if (tp->t_outq.c_cc != 0) {
 1748                 brdp = stli_brds[portp->brdnr];
 1749                 if (brdp == (stlibrd_t *) NULL) {
 1750                         splx(x);
 1751                         return;
 1752                 }
 1753 
 1754                 disable_intr();
 1755                 EBRDENABLE(brdp);
 1756                 ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 1757                 head = (unsigned int) ap->txq.head;
 1758                 tail = (unsigned int) ap->txq.tail;
 1759                 if (tail != ((unsigned int) ap->txq.tail))
 1760                         tail = (unsigned int) ap->txq.tail;
 1761                 size = portp->txsize;
 1762                 if (head >= tail) {
 1763                         len = size - (head - tail) - 1;
 1764                         stlen = size - head;
 1765                 } else {
 1766                         len = tail - head - 1;
 1767                         stlen = len;
 1768                 }
 1769 
 1770                 count = 0;
 1771                 shbuf = (char *) EBRDGETMEMPTR(brdp, portp->txoffset);
 1772 
 1773                 if (len > 0) {
 1774                         stlen = MIN(len, stlen);
 1775                         count = q_to_b(&tp->t_outq, (shbuf + head), stlen);
 1776                         len -= count;
 1777                         head += count;
 1778                         if (head >= size) {
 1779                                 head = 0;
 1780                                 if (len > 0) {
 1781                                         stlen = q_to_b(&tp->t_outq, shbuf, len);
 1782                                         head += stlen;
 1783                                         count += stlen;
 1784                                 }
 1785                         }
 1786                 }
 1787 
 1788                 ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 1789                 ap->txq.head = head;
 1790                 hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1791                 bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1792                         portp->portidx;
 1793                 *bits |= portp->portbit;
 1794                 portp->state |= ST_TXBUSY;
 1795                 tp->t_state |= TS_BUSY;
 1796 
 1797                 EBRDDISABLE(brdp);
 1798                 enable_intr();
 1799         }
 1800 
 1801 #if VFREEBSD != 205
 1802 /*
 1803  *      Do any writer wakeups.
 1804  */
 1805         ttwwakeup(tp);
 1806 #endif
 1807 
 1808         splx(x);
 1809 }
 1810 
 1811 /*****************************************************************************/
 1812 
 1813 /*
 1814  *      Send a new port configuration to the slave.
 1815  */
 1816 
 1817 static int stli_param(struct tty *tp, struct termios *tiosp)
 1818 {
 1819         stlibrd_t       *brdp;
 1820         stliport_t      *portp;
 1821         asyport_t       aport;
 1822         int             x, rc;
 1823 
 1824         portp = (stliport_t *) tp;
 1825         if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1826                 return(ENXIO);
 1827 
 1828         x = spltty();
 1829         stli_mkasyport(portp, &aport, tiosp);
 1830         /* can we sleep here? */
 1831         rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
 1832         stli_ttyoptim(portp, tiosp);
 1833         splx(x);
 1834         return(rc);
 1835 }
 1836 
 1837 /*****************************************************************************/
 1838 
 1839 /*
 1840  *      Flush characters from the lower buffer. We may not have user context
 1841  *      so we cannot sleep waiting for it to complete. Also we need to check
 1842  *      if there is chars for this port in the TX cook buffer, and flush them
 1843  *      as well.
 1844  */
 1845 
 1846 static void stli_flush(stliport_t *portp, int flag)
 1847 {
 1848         stlibrd_t       *brdp;
 1849         unsigned long   ftype;
 1850 
 1851 #if DEBUG
 1852         printf("stli_flush(portp=%x,flag=%x)\n", (int) portp, flag);
 1853 #endif
 1854 
 1855         if (portp == (stliport_t *) NULL)
 1856                 return;
 1857         if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
 1858                 return;
 1859         brdp = stli_brds[portp->brdnr];
 1860         if (brdp == (stlibrd_t *) NULL)
 1861                 return;
 1862 
 1863         disable_intr();
 1864         if (portp->state & ST_CMDING) {
 1865                 portp->state |= (flag & FWRITE) ? ST_DOFLUSHTX : 0;
 1866                 portp->state |= (flag & FREAD) ? ST_DOFLUSHRX : 0;
 1867         } else {
 1868                 ftype = (flag & FWRITE) ? FLUSHTX : 0;
 1869                 ftype |= (flag & FREAD) ? FLUSHRX : 0;
 1870                 portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
 1871                 stli_sendcmd(brdp, portp, A_FLUSH, &ftype,
 1872                         sizeof(unsigned long), 0);
 1873         }
 1874         if ((flag & FREAD) && (stli_rxtmpport == portp))
 1875                 stli_rxtmplen = 0;
 1876         enable_intr();
 1877 }
 1878 
 1879 /*****************************************************************************/
 1880 
 1881 /*
 1882  *      Generic send command routine. This will send a message to the slave,
 1883  *      of the specified type with the specified argument. Must be very
 1884  *      carefull of data that will be copied out from shared memory -
 1885  *      containing command results. The command completion is all done from
 1886  *      a poll routine that does not have user coontext. Therefore you cannot
 1887  *      copy back directly into user space, or to the kernel stack of a
 1888  *      process. This routine does not sleep, so can be called from anywhere,
 1889  *      and must be called with interrupt locks set.
 1890  */
 1891 
 1892 static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 1893 {
 1894         volatile cdkhdr_t       *hdrp;
 1895         volatile cdkctrl_t      *cp;
 1896         volatile unsigned char  *bits;
 1897 
 1898 #if DEBUG
 1899         printf("stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
 1900                 "copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
 1901                 (int) arg, size, copyback);
 1902 #endif
 1903 
 1904         if (portp->state & ST_CMDING) {
 1905                 printf("STALLION: command already busy, cmd=%x!\n", (int) cmd);
 1906                 return;
 1907         }
 1908 
 1909         EBRDENABLE(brdp);
 1910         cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1911         if (size > 0) {
 1912                 bcopy(arg, (void *) &(cp->args[0]), size);
 1913                 if (copyback) {
 1914                         portp->argp = arg;
 1915                         portp->argsize = size;
 1916                 }
 1917         }
 1918         cp->status = 0;
 1919         cp->cmd = cmd;
 1920         hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1921         bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1922                 portp->portidx;
 1923         *bits |= portp->portbit;
 1924         portp->state |= ST_CMDING;
 1925         EBRDDISABLE(brdp);
 1926 }
 1927 
 1928 /*****************************************************************************/
 1929 
 1930 /*
 1931  *      Read data from shared memory. This assumes that the shared memory
 1932  *      is enabled and that interrupts are off. Basically we just empty out
 1933  *      the shared memory buffer into the tty buffer. Must be carefull to
 1934  *      handle the case where we fill up the tty buffer, but still have
 1935  *      more chars to unload.
 1936  */
 1937 
 1938 static void stli_rxprocess(stlibrd_t *brdp, stliport_t *portp)
 1939 {
 1940         volatile cdkasyrq_t     *rp;
 1941         volatile char           *shbuf;
 1942         struct tty              *tp;
 1943         unsigned int            head, tail, size;
 1944         unsigned int            len, stlen, i;
 1945         int                     ch;
 1946 
 1947 #if DEBUG
 1948         printf("stli_rxprocess(brdp=%x,portp=%d)\n", (int) brdp, (int) portp);
 1949 #endif
 1950 
 1951         tp = &portp->tty;
 1952         if ((tp->t_state & TS_ISOPEN) == 0) {
 1953                 stli_flush(portp, FREAD);
 1954                 return;
 1955         }
 1956         if (tp->t_state & TS_TBLOCK)
 1957                 return;
 1958 
 1959         rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 1960         head = (unsigned int) rp->head;
 1961         if (head != ((unsigned int) rp->head))
 1962                 head = (unsigned int) rp->head;
 1963         tail = (unsigned int) rp->tail;
 1964         size = portp->rxsize;
 1965         if (head >= tail) {
 1966                 len = head - tail;
 1967                 stlen = len;
 1968         } else {
 1969                 len = size - (tail - head);
 1970                 stlen = size - tail;
 1971         }
 1972 
 1973         if (len == 0)
 1974                 return;
 1975 
 1976         shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
 1977 
 1978 /*
 1979  *      If we can bypass normal LD processing then just copy direct
 1980  *      from board shared memory into the tty buffers.
 1981  */
 1982         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 1983                 if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
 1984                     ((tp->t_cflag & CRTS_IFLOW) || (tp->t_iflag & IXOFF)) &&
 1985                     ((tp->t_state & TS_TBLOCK) == 0)) {
 1986                         ch = TTYHOG - tp->t_rawq.c_cc - 1;
 1987                         len = (ch > 0) ? ch : 0;
 1988                         stlen = MIN(stlen, len);
 1989                         tp->t_state |= TS_TBLOCK;
 1990                 }
 1991                 i = b_to_q((char *) (shbuf + tail), stlen, &tp->t_rawq);
 1992                 tail += stlen;
 1993                 len -= stlen;
 1994                 if (tail >= size) {
 1995                         tail = 0;
 1996                         i += b_to_q((char *) shbuf, len, &tp->t_rawq);
 1997                         tail += len;
 1998                 }
 1999                 portp->rxlost += i;
 2000                 ttwakeup(tp);
 2001                 rp = &((volatile cdkasy_t *)
 2002                         EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 2003                 rp->tail = tail;
 2004 
 2005         } else {
 2006 /*
 2007  *              Copy the data from board shared memory into a local
 2008  *              memory buffer. Then feed them from here into the LD.
 2009  *              We don't want to go into board shared memory one char
 2010  *              at a time, it is too slow...
 2011  */
 2012                 if (len > TTYHOG) {
 2013                         len = TTYHOG - 1;
 2014                         stlen = min(len, stlen);
 2015                 }
 2016                 stli_rxtmpport = portp;
 2017                 stli_rxtmplen = len;
 2018                 bcopy((char *) (shbuf + tail), &stli_rxtmpbuf[0], stlen);
 2019                 len -= stlen;
 2020                 if (len > 0)
 2021                         bcopy((char *) shbuf, &stli_rxtmpbuf[stlen], len);
 2022                 
 2023                 for (i = 0; (i < stli_rxtmplen); i++) {
 2024                         ch = (unsigned char) stli_rxtmpbuf[i];
 2025                         (*linesw[tp->t_line].l_rint)(ch, tp);
 2026                 }
 2027                 EBRDENABLE(brdp);
 2028                 rp = &((volatile cdkasy_t *)
 2029                         EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 2030                 if (stli_rxtmplen == 0) {
 2031                         head = (unsigned int) rp->head;
 2032                         if (head != ((unsigned int) rp->head))
 2033                                 head = (unsigned int) rp->head;
 2034                         tail = head;
 2035                 } else {
 2036                         tail += i;
 2037                         if (tail >= size)
 2038                                 tail -= size;
 2039                 }
 2040                 rp->tail = tail;
 2041                 stli_rxtmpport = (stliport_t *) NULL;
 2042                 stli_rxtmplen = 0;
 2043         }
 2044 
 2045         portp->state |= ST_RXING;
 2046 }
 2047 
 2048 /*****************************************************************************/
 2049 
 2050 /*
 2051  *      Set up and carry out any delayed commands. There is only a small set
 2052  *      of slave commands that can be done "off-level". So it is not too
 2053  *      difficult to deal with them as a special case here.
 2054  */
 2055 
 2056 static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
 2057 {
 2058         int     cmd;
 2059 
 2060         if (portp->state & ST_DOSIGS) {
 2061                 if ((portp->state & ST_DOFLUSHTX) &&
 2062                     (portp->state & ST_DOFLUSHRX))
 2063                         cmd = A_SETSIGNALSF;
 2064                 else if (portp->state & ST_DOFLUSHTX)
 2065                         cmd = A_SETSIGNALSFTX;
 2066                 else if (portp->state & ST_DOFLUSHRX)
 2067                         cmd = A_SETSIGNALSFRX;
 2068                 else
 2069                         cmd = A_SETSIGNALS;
 2070                 portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX | ST_DOSIGS);
 2071                 bcopy((void *) &portp->asig, (void *) &(cp->args[0]),
 2072                         sizeof(asysigs_t));
 2073                 cp->status = 0;
 2074                 cp->cmd = cmd;
 2075                 portp->state |= ST_CMDING;
 2076         } else if ((portp->state & ST_DOFLUSHTX) ||
 2077             (portp->state & ST_DOFLUSHRX)) {
 2078                 cmd = ((portp->state & ST_DOFLUSHTX) ? FLUSHTX : 0);
 2079                 cmd |= ((portp->state & ST_DOFLUSHRX) ? FLUSHRX : 0);
 2080                 portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
 2081                 bcopy((void *) &cmd, (void *) &(cp->args[0]), sizeof(int));
 2082                 cp->status = 0;
 2083                 cp->cmd = A_FLUSH;
 2084                 portp->state |= ST_CMDING;
 2085         }
 2086 }
 2087 
 2088 /*****************************************************************************/
 2089 
 2090 /*
 2091  *      Host command service checking. This handles commands or messages
 2092  *      coming from the slave to the host. Must have board shared memory
 2093  *      enabled and interrupts off when called. Notice that by servicing the
 2094  *      read data last we don't need to change the shared memory pointer
 2095  *      during processing (which is a slow IO operation).
 2096  *      Return value indicates if this port is still awaiting actions from
 2097  *      the slave (like open, command, or even TX data being sent). If 0
 2098  *      then port is still busy, otherwise the port request bit flag is
 2099  *      returned.
 2100  */
 2101 
 2102 static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
 2103 {
 2104         volatile cdkasy_t       *ap;
 2105         volatile cdkctrl_t      *cp;
 2106         asynotify_t             nt;
 2107         unsigned long           oldsigs;
 2108         unsigned int            head, tail;
 2109         int                     rc, donerx;
 2110 
 2111 #if DEBUG
 2112         printf("stli_hostcmd(brdp=%x,portp=%x)\n", (int) brdp, (int) portp);
 2113 #endif
 2114 
 2115         ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 2116         cp = &ap->ctrl;
 2117 
 2118 /*
 2119  *      Check if we are waiting for an open completion message.
 2120  */
 2121         if (portp->state & ST_OPENING) {
 2122                 rc = (int) cp->openarg;
 2123                 if ((cp->open == 0) && (rc != 0)) {
 2124                         if (rc > 0)
 2125                                 rc--;
 2126                         cp->openarg = 0;
 2127                         portp->rc = rc;
 2128                         portp->state &= ~ST_OPENING;
 2129                         wakeup(&portp->state);
 2130                 }
 2131         }
 2132 
 2133 /*
 2134  *      Check if we are waiting for a close completion message.
 2135  */
 2136         if (portp->state & ST_CLOSING) {
 2137                 rc = (int) cp->closearg;
 2138                 if ((cp->close == 0) && (rc != 0)) {
 2139                         if (rc > 0)
 2140                                 rc--;
 2141                         cp->closearg = 0;
 2142                         portp->rc = rc;
 2143                         portp->state &= ~ST_CLOSING;
 2144                         wakeup(&portp->state);
 2145                 }
 2146         }
 2147 
 2148 /*
 2149  *      Check if we are waiting for a command completion message. We may
 2150  *      need to copy out the command results associated with this command.
 2151  */
 2152         if (portp->state & ST_CMDING) {
 2153                 rc = cp->status;
 2154                 if ((cp->cmd == 0) && (rc != 0)) {
 2155                         if (rc > 0)
 2156                                 rc--;
 2157                         if (portp->argp != (void *) NULL) {
 2158                                 bcopy((void *) &(cp->args[0]), portp->argp,
 2159                                         portp->argsize);
 2160                                 portp->argp = (void *) NULL;
 2161                         }
 2162                         cp->status = 0;
 2163                         portp->rc = rc;
 2164                         portp->state &= ~ST_CMDING;
 2165                         stli_dodelaycmd(portp, cp);
 2166                         wakeup(&portp->state);
 2167                 }
 2168         }
 2169 
 2170 /*
 2171  *      Check for any notification messages ready. This includes lots of
 2172  *      different types of events - RX chars ready, RX break received,
 2173  *      TX data low or empty in the slave, modem signals changed state.
 2174  *      Must be extremely carefull if we call to the LD, it may call
 2175  *      other routines of ours that will disable the memory...
 2176  *      Something else we need to be carefull of is race conditions on
 2177  *      marking the TX as empty...
 2178  */
 2179         donerx = 0;
 2180 
 2181         if (ap->notify) {
 2182                 struct tty      *tp;
 2183 
 2184                 nt = ap->changed;
 2185                 ap->notify = 0;
 2186                 tp = &portp->tty;
 2187 
 2188                 if (nt.signal & SG_DCD) {
 2189                         oldsigs = portp->sigs;
 2190                         portp->sigs = stli_mktiocm(nt.sigvalue);
 2191                         portp->state &= ~ST_GETSIGS;
 2192                         (*linesw[tp->t_line].l_modem)(tp,
 2193                                 (portp->sigs & TIOCM_CD));
 2194                         EBRDENABLE(brdp);
 2195                 }
 2196                 if (nt.data & DT_RXBUSY) {
 2197                         donerx++;
 2198                         stli_rxprocess(brdp, portp);
 2199                 }
 2200                 if (nt.data & DT_RXBREAK) {
 2201                         (*linesw[tp->t_line].l_rint)(TTY_BI, tp);
 2202                         EBRDENABLE(brdp);
 2203                 }
 2204                 if (nt.data & DT_TXEMPTY) {
 2205                         ap = (volatile cdkasy_t *)
 2206                                 EBRDGETMEMPTR(brdp, portp->addr);
 2207                         head = (unsigned int) ap->txq.head;
 2208                         tail = (unsigned int) ap->txq.tail;
 2209                         if (tail != ((unsigned int) ap->txq.tail))
 2210                                 tail = (unsigned int) ap->txq.tail;
 2211                         head = (head >= tail) ? (head - tail) :
 2212                                 portp->txsize - (tail - head);
 2213                         if (head == 0) {
 2214                                 portp->state &= ~ST_TXBUSY;
 2215                                 tp->t_state &= ~TS_BUSY;
 2216                         }
 2217                 }
 2218                 if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
 2219                         (*linesw[tp->t_line].l_start)(tp);
 2220                         EBRDENABLE(brdp);
 2221                 }
 2222         }
 2223 
 2224 /*
 2225  *      It might seem odd that we are checking for more RX chars here.
 2226  *      But, we need to handle the case where the tty buffer was previously
 2227  *      filled, but we had more characters to pass up. The slave will not
 2228  *      send any more RX notify messages until the RX buffer has been emptied.
 2229  *      But it will leave the service bits on (since the buffer is not empty).
 2230  *      So from here we can try to process more RX chars.
 2231  */
 2232         if ((!donerx) && (portp->state & ST_RXING)) {
 2233                 portp->state &= ~ST_RXING;
 2234                 stli_rxprocess(brdp, portp);
 2235         }
 2236 
 2237         return((portp->state & (ST_OPENING | ST_CLOSING | ST_CMDING |
 2238                 ST_TXBUSY | ST_RXING)) ? 0 : 1);
 2239 }
 2240 
 2241 /*****************************************************************************/
 2242 
 2243 /*
 2244  *      Service all ports on a particular board. Assumes that the boards
 2245  *      shared memory is enabled, and that the page pointer is pointed
 2246  *      at the cdk header structure.
 2247  */
 2248 
 2249 static inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
 2250 {
 2251         stliport_t      *portp;
 2252         unsigned char   hostbits[(STL_MAXCHANS / 8) + 1];
 2253         unsigned char   slavebits[(STL_MAXCHANS / 8) + 1];
 2254         unsigned char   *slavep;
 2255         int             bitpos, bitat, bitsize;
 2256         int             channr, nrdevs, slavebitchange;
 2257 
 2258         bitsize = brdp->bitsize;
 2259         nrdevs = brdp->nrdevs;
 2260 
 2261 /*
 2262  *      Check if slave wants any service. Basically we try to do as
 2263  *      little work as possible here. There are 2 levels of service
 2264  *      bits. So if there is nothing to do we bail early. We check
 2265  *      8 service bits at a time in the inner loop, so we can bypass
 2266  *      the lot if none of them want service.
 2267  */
 2268         bcopy((((unsigned char *) hdrp) + brdp->hostoffset), &hostbits[0],
 2269                 bitsize);
 2270 
 2271         bzero(&slavebits[0], bitsize);
 2272         slavebitchange = 0;
 2273 
 2274         for (bitpos = 0; (bitpos < bitsize); bitpos++) {
 2275                 if (hostbits[bitpos] == 0)
 2276                         continue;
 2277                 channr = bitpos * 8;
 2278                 bitat = 0x1;
 2279                 for (; (channr < nrdevs); channr++, bitat <<=1) {
 2280                         if (hostbits[bitpos] & bitat) {
 2281                                 portp = brdp->ports[(channr - 1)];
 2282                                 if (stli_hostcmd(brdp, portp)) {
 2283                                         slavebitchange++;
 2284                                         slavebits[bitpos] |= bitat;
 2285                                 }
 2286                         }
 2287                 }
 2288         }
 2289 
 2290 /*
 2291  *      If any of the ports are no longer busy then update them in the
 2292  *      slave request bits. We need to do this after, since a host port
 2293  *      service may initiate more slave requests...
 2294  */
 2295         if (slavebitchange) {
 2296                 hdrp = (volatile cdkhdr_t *)
 2297                         EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 2298                 slavep = ((unsigned char *) hdrp) + brdp->slaveoffset;
 2299                 for (bitpos = 0; (bitpos < bitsize); bitpos++) {
 2300                         if (slavebits[bitpos])
 2301                                 slavep[bitpos] &= ~slavebits[bitpos];
 2302                 }
 2303         }
 2304 }
 2305 
 2306 /*****************************************************************************/
 2307 
 2308 /*
 2309  *      Driver poll routine. This routine polls the boards in use and passes
 2310  *      messages back up to host when neccesary. This is actually very
 2311  *      CPU efficient, since we will always have the kernel poll clock, it
 2312  *      adds only a few cycles when idle (since board service can be
 2313  *      determined very easily), but when loaded generates no interrupts
 2314  *      (with their expensive associated context change).
 2315  */
 2316 
 2317 static void stli_poll(void *arg)
 2318 {
 2319         volatile cdkhdr_t       *hdrp;
 2320         stlibrd_t               *brdp;
 2321         int                     brdnr;
 2322 
 2323         disable_intr();
 2324 
 2325 /*
 2326  *      Check each board and do any servicing required.
 2327  */
 2328         for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
 2329                 brdp = stli_brds[brdnr];
 2330                 if (brdp == (stlibrd_t *) NULL)
 2331                         continue;
 2332                 if ((brdp->state & BST_STARTED) == 0)
 2333                         continue;
 2334 
 2335                 EBRDENABLE(brdp);
 2336                 hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 2337                 if (hdrp->hostreq)
 2338                         stli_brdpoll(brdp, hdrp);
 2339                 EBRDDISABLE(brdp);
 2340         }
 2341         enable_intr();
 2342 
 2343         timeout(stli_poll, 0, 1);
 2344 }
 2345 
 2346 /*****************************************************************************/
 2347 
 2348 /*
 2349  *      Translate the termios settings into the port setting structure of
 2350  *      the slave.
 2351  */
 2352 
 2353 static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
 2354 {
 2355 #if DEBUG
 2356         printf("stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n", (int) portp,
 2357                 (int) pp, (int) tiosp);
 2358 #endif
 2359 
 2360         bzero(pp, sizeof(asyport_t));
 2361 
 2362 /*
 2363  *      Start of by setting the baud, char size, parity and stop bit info.
 2364  */
 2365         if (tiosp->c_ispeed == 0)
 2366                 tiosp->c_ispeed = tiosp->c_ospeed;
 2367         if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > STL_MAXBAUD))
 2368                 tiosp->c_ospeed = STL_MAXBAUD;
 2369         pp->baudout = tiosp->c_ospeed;
 2370         pp->baudin = pp->baudout;
 2371 
 2372         switch (tiosp->c_cflag & CSIZE) {
 2373         case CS5:
 2374                 pp->csize = 5;
 2375                 break;
 2376         case CS6:
 2377                 pp->csize = 6;
 2378                 break;
 2379         case CS7:
 2380                 pp->csize = 7;
 2381                 break;
 2382         default:
 2383                 pp->csize = 8;
 2384                 break;
 2385         }
 2386 
 2387         if (tiosp->c_cflag & CSTOPB)
 2388                 pp->stopbs = PT_STOP2;
 2389         else
 2390                 pp->stopbs = PT_STOP1;
 2391 
 2392         if (tiosp->c_cflag & PARENB) {
 2393                 if (tiosp->c_cflag & PARODD)
 2394                         pp->parity = PT_ODDPARITY;
 2395                 else
 2396                         pp->parity = PT_EVENPARITY;
 2397         } else {
 2398                 pp->parity = PT_NOPARITY;
 2399         }
 2400 
 2401         if (tiosp->c_iflag & ISTRIP)
 2402                 pp->iflag |= FI_ISTRIP;
 2403 
 2404 /*
 2405  *      Set up any flow control options enabled.
 2406  */
 2407         if (tiosp->c_iflag & IXON) {
 2408                 pp->flow |= F_IXON;
 2409                 if (tiosp->c_iflag & IXANY)
 2410                         pp->flow |= F_IXANY;
 2411         }
 2412         if (tiosp->c_iflag & IXOFF)
 2413                 pp->flow |= F_IXOFF;
 2414         if (tiosp->c_cflag & CCTS_OFLOW)
 2415                 pp->flow |= F_CTSFLOW;
 2416         if (tiosp->c_cflag & CRTS_IFLOW)
 2417                 pp->flow |= F_RTSFLOW;
 2418 
 2419         pp->startin = tiosp->c_cc[VSTART];
 2420         pp->stopin = tiosp->c_cc[VSTOP];
 2421         pp->startout = tiosp->c_cc[VSTART];
 2422         pp->stopout = tiosp->c_cc[VSTOP];
 2423 
 2424 /*
 2425  *      Set up the RX char marking mask with those RX error types we must
 2426  *      catch. We can get the slave to help us out a little here, it will
 2427  *      ignore parity errors and breaks for us, and mark parity errors in
 2428  *      the data stream.
 2429  */
 2430         if (tiosp->c_iflag & IGNPAR)
 2431                 pp->iflag |= FI_IGNRXERRS;
 2432         if (tiosp->c_iflag & IGNBRK)
 2433                 pp->iflag |= FI_IGNBREAK;
 2434         if (tiosp->c_iflag & (INPCK | PARMRK))
 2435                 pp->iflag |= FI_1MARKRXERRS;
 2436 
 2437 /*
 2438  *      Transfer any persistent flags into the asyport structure.
 2439  */
 2440         pp->pflag = portp->pflag;
 2441 }
 2442 
 2443 /*****************************************************************************/
 2444 
 2445 /*
 2446  *      Construct a slave signals structure for setting the DTR and RTS
 2447  *      signals as specified.
 2448  */
 2449 
 2450 static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
 2451 {
 2452 #if DEBUG
 2453         printf("stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n", (int) sp, dtr, rts);
 2454 #endif
 2455 
 2456         bzero(sp, sizeof(asysigs_t));
 2457         if (dtr >= 0) {
 2458                 sp->signal |= SG_DTR;
 2459                 sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
 2460         }
 2461         if (rts >= 0) {
 2462                 sp->signal |= SG_RTS;
 2463                 sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
 2464         }
 2465 }
 2466 
 2467 /*****************************************************************************/
 2468 
 2469 /*
 2470  *      Convert the signals returned from the slave into a local TIOCM type
 2471  *      signals value. We keep them localy in TIOCM format.
 2472  */
 2473 
 2474 static long stli_mktiocm(unsigned long sigvalue)
 2475 {
 2476         long    tiocm;
 2477 
 2478 #if DEBUG
 2479         printf("stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
 2480 #endif
 2481 
 2482         tiocm = 0;
 2483         tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
 2484         tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
 2485         tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
 2486         tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
 2487         tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
 2488         tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
 2489         return(tiocm);
 2490 }
 2491 
 2492 /*****************************************************************************/
 2493 
 2494 /*
 2495  *      Enable l_rint processing bypass mode if tty modes allow it.
 2496  */
 2497 
 2498 static void stli_ttyoptim(stliport_t *portp, struct termios *tiosp)
 2499 {
 2500         struct tty      *tp;
 2501 
 2502         tp = &portp->tty;
 2503         if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR)) == 0) &&
 2504             (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
 2505             (((tiosp->c_iflag & PARMRK) == 0) ||
 2506                 ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
 2507             ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
 2508             (linesw[tp->t_line].l_rint == ttyinput))
 2509                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 2510         else
 2511                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 2512 
 2513         if (tp->t_line == SLIPDISC)
 2514                 portp->hotchar = 0xc0;
 2515         else if (tp->t_line == PPPDISC)
 2516                 portp->hotchar = 0x7e;
 2517         else
 2518                 portp->hotchar = 0;
 2519 }
 2520 
 2521 /*****************************************************************************/
 2522 
 2523 /*
 2524  *      All panels and ports actually attached have been worked out. All
 2525  *      we need to do here is set up the appropriate per port data structures.
 2526  */
 2527 
 2528 static int stli_initports(stlibrd_t *brdp)
 2529 {
 2530         stliport_t      *portp;
 2531         int             i, panelnr, panelport;
 2532 
 2533 #if DEBUG
 2534         printf("stli_initports(brdp=%x)\n", (int) brdp);
 2535 #endif
 2536 
 2537         for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
 2538                 portp = (stliport_t *) malloc(sizeof(stliport_t), M_TTYS,
 2539                         M_NOWAIT);
 2540                 if (portp == (stliport_t *) NULL) {
 2541                         printf("STALLION: failed to allocate port structure\n");
 2542                         continue;
 2543                 }
 2544                 bzero(portp, sizeof(stliport_t));
 2545 
 2546                 portp->portnr = i;
 2547                 portp->brdnr = brdp->brdnr;
 2548                 portp->panelnr = panelnr;
 2549                 portp->initintios.c_ispeed = STL_DEFSPEED;
 2550                 portp->initintios.c_ospeed = STL_DEFSPEED;
 2551                 portp->initintios.c_cflag = STL_DEFCFLAG;
 2552                 portp->initintios.c_iflag = 0;
 2553                 portp->initintios.c_oflag = 0;
 2554                 portp->initintios.c_lflag = 0;
 2555                 bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
 2556                         sizeof(portp->initintios.c_cc));
 2557                 portp->initouttios = portp->initintios;
 2558                 portp->dtrwait = 3 * hz;
 2559 
 2560                 panelport++;
 2561                 if (panelport >= brdp->panels[panelnr]) {
 2562                         panelport = 0;
 2563                         panelnr++;
 2564                 }
 2565                 brdp->ports[i] = portp;
 2566         }
 2567 
 2568         return(0);
 2569 }
 2570 
 2571 /*****************************************************************************/
 2572 
 2573 /*
 2574  *      All the following routines are board specific hardware operations.
 2575  */
 2576 
 2577 static void stli_ecpinit(stlibrd_t *brdp)
 2578 {
 2579         unsigned long   memconf;
 2580 
 2581 #if DEBUG
 2582         printf("stli_ecpinit(brdp=%d)\n", (int) brdp);
 2583 #endif
 2584 
 2585         outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
 2586         DELAY(10);
 2587         outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2588         DELAY(100);
 2589 
 2590         memconf = (brdp->paddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
 2591         outb((brdp->iobase + ECP_ATMEMAR), memconf);
 2592 }
 2593 
 2594 /*****************************************************************************/
 2595 
 2596 static void stli_ecpenable(stlibrd_t *brdp)
 2597 {       
 2598 #if DEBUG
 2599         printf("stli_ecpenable(brdp=%x)\n", (int) brdp);
 2600 #endif
 2601         outb((brdp->iobase + ECP_ATCONFR), ECP_ATENABLE);
 2602 }
 2603 
 2604 /*****************************************************************************/
 2605 
 2606 static void stli_ecpdisable(stlibrd_t *brdp)
 2607 {       
 2608 #if DEBUG
 2609         printf("stli_ecpdisable(brdp=%x)\n", (int) brdp);
 2610 #endif
 2611         outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2612 }
 2613 
 2614 /*****************************************************************************/
 2615 
 2616 static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2617 {       
 2618         void            *ptr;
 2619         unsigned char   val;
 2620 
 2621 #if DEBUG
 2622         printf("stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 2623                 (int) offset);
 2624 #endif
 2625 
 2626         if (offset > brdp->memsize) {
 2627                 printf("STALLION: shared memory pointer=%x out of range at "
 2628                         "line=%d(%d), brd=%d\n", (int) offset, line,
 2629                         __LINE__, brdp->brdnr);
 2630                 ptr = 0;
 2631                 val = 0;
 2632         } else {
 2633                 ptr = (char *) brdp->vaddr + (offset % ECP_ATPAGESIZE);
 2634                 val = (unsigned char) (offset / ECP_ATPAGESIZE);
 2635         }
 2636         outb((brdp->iobase + ECP_ATMEMPR), val);
 2637         return(ptr);
 2638 }
 2639 
 2640 /*****************************************************************************/
 2641 
 2642 static void stli_ecpreset(stlibrd_t *brdp)
 2643 {       
 2644 #if DEBUG
 2645         printf("stli_ecpreset(brdp=%x)\n", (int) brdp);
 2646 #endif
 2647 
 2648         outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
 2649         DELAY(10);
 2650         outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2651         DELAY(500);
 2652 }
 2653 
 2654 /*****************************************************************************/
 2655 
 2656 static void stli_ecpintr(stlibrd_t *brdp)
 2657 {       
 2658 #if DEBUG
 2659         printf("stli_ecpintr(brdp=%x)\n", (int) brdp);
 2660 #endif
 2661         outb(brdp->iobase, 0x1);
 2662 }
 2663 
 2664 /*****************************************************************************/
 2665 
 2666 /*
 2667  *      The following set of functions act on ECP EISA boards.
 2668  */
 2669 
 2670 static void stli_ecpeiinit(stlibrd_t *brdp)
 2671 {
 2672         unsigned long   memconf;
 2673 
 2674 #if DEBUG
 2675         printf("stli_ecpeiinit(brdp=%x)\n", (int) brdp);
 2676 #endif
 2677 
 2678         outb((brdp->iobase + ECP_EIBRDENAB), 0x1);
 2679         outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
 2680         DELAY(10);
 2681         outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2682         DELAY(500);
 2683 
 2684         memconf = (brdp->paddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
 2685         outb((brdp->iobase + ECP_EIMEMARL), memconf);
 2686         memconf = (brdp->paddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
 2687         outb((brdp->iobase + ECP_EIMEMARH), memconf);
 2688 }
 2689 
 2690 /*****************************************************************************/
 2691 
 2692 static void stli_ecpeienable(stlibrd_t *brdp)
 2693 {       
 2694         outb((brdp->iobase + ECP_EICONFR), ECP_EIENABLE);
 2695 }
 2696 
 2697 /*****************************************************************************/
 2698 
 2699 static void stli_ecpeidisable(stlibrd_t *brdp)
 2700 {       
 2701         outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2702 }
 2703 
 2704 /*****************************************************************************/
 2705 
 2706 static char *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2707 {       
 2708         void            *ptr;
 2709         unsigned char   val;
 2710 
 2711 #if DEBUG
 2712         printf("stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
 2713                 (int) brdp, (int) offset, line);
 2714 #endif
 2715 
 2716         if (offset > brdp->memsize) {
 2717                 printf("STALLION: shared memory pointer=%x out of range at "
 2718                         "line=%d(%d), brd=%d\n", (int) offset, line,
 2719                         __LINE__, brdp->brdnr);
 2720                 ptr = 0;
 2721                 val = 0;
 2722         } else {
 2723                 ptr = (char *) brdp->vaddr + (offset % ECP_EIPAGESIZE);
 2724                 if (offset < ECP_EIPAGESIZE)
 2725                         val = ECP_EIENABLE;
 2726                 else
 2727                         val = ECP_EIENABLE | 0x40;
 2728         }
 2729         outb((brdp->iobase + ECP_EICONFR), val);
 2730         return(ptr);
 2731 }
 2732 
 2733 /*****************************************************************************/
 2734 
 2735 static void stli_ecpeireset(stlibrd_t *brdp)
 2736 {       
 2737         outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
 2738         DELAY(10);
 2739         outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2740         DELAY(500);
 2741 }
 2742 
 2743 /*****************************************************************************/
 2744 
 2745 /*
 2746  *      The following set of functions act on ECP MCA boards.
 2747  */
 2748 
 2749 static void stli_ecpmcenable(stlibrd_t *brdp)
 2750 {       
 2751         outb((brdp->iobase + ECP_MCCONFR), ECP_MCENABLE);
 2752 }
 2753 
 2754 /*****************************************************************************/
 2755 
 2756 static void stli_ecpmcdisable(stlibrd_t *brdp)
 2757 {       
 2758         outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
 2759 }
 2760 
 2761 /*****************************************************************************/
 2762 
 2763 static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2764 {       
 2765         void            *ptr;
 2766         unsigned char   val;
 2767 
 2768         if (offset > brdp->memsize) {
 2769                 printf("STALLION: shared memory pointer=%x out of range at "
 2770                         "line=%d(%d), brd=%d\n", (int) offset, line,
 2771                         __LINE__, brdp->brdnr);
 2772                 ptr = 0;
 2773                 val = 0;
 2774         } else {
 2775                 ptr = (char *) brdp->vaddr + (offset % ECP_MCPAGESIZE);
 2776                 val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
 2777         }
 2778         outb((brdp->iobase + ECP_MCCONFR), val);
 2779         return(ptr);
 2780 }
 2781 
 2782 /*****************************************************************************/
 2783 
 2784 static void stli_ecpmcreset(stlibrd_t *brdp)
 2785 {       
 2786         outb((brdp->iobase + ECP_MCCONFR), ECP_MCSTOP);
 2787         DELAY(10);
 2788         outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
 2789         DELAY(500);
 2790 }
 2791 
 2792 /*****************************************************************************/
 2793 
 2794 /*
 2795  *      The following routines act on ONboards.
 2796  */
 2797 
 2798 static void stli_onbinit(stlibrd_t *brdp)
 2799 {
 2800         unsigned long   memconf;
 2801         int             i;
 2802 
 2803 #if DEBUG
 2804         printf("stli_onbinit(brdp=%d)\n", (int) brdp);
 2805 #endif
 2806 
 2807         outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
 2808         DELAY(10);
 2809         outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
 2810         for (i = 0; (i < 1000); i++)
 2811                 DELAY(1000);
 2812 
 2813         memconf = (brdp->paddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
 2814         outb((brdp->iobase + ONB_ATMEMAR), memconf);
 2815         outb(brdp->iobase, 0x1);
 2816         DELAY(1000);
 2817 }
 2818 
 2819 /*****************************************************************************/
 2820 
 2821 static void stli_onbenable(stlibrd_t *brdp)
 2822 {       
 2823 #if DEBUG
 2824         printf("stli_onbenable(brdp=%x)\n", (int) brdp);
 2825 #endif
 2826         outb((brdp->iobase + ONB_ATCONFR), (ONB_ATENABLE | brdp->confbits));
 2827 }
 2828 
 2829 /*****************************************************************************/
 2830 
 2831 static void stli_onbdisable(stlibrd_t *brdp)
 2832 {       
 2833 #if DEBUG
 2834         printf("stli_onbdisable(brdp=%x)\n", (int) brdp);
 2835 #endif
 2836         outb((brdp->iobase + ONB_ATCONFR), (ONB_ATDISABLE | brdp->confbits));
 2837 }
 2838 
 2839 /*****************************************************************************/
 2840 
 2841 static char *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2842 {       
 2843         void    *ptr;
 2844 
 2845 #if DEBUG
 2846         printf("stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 2847                 (int) offset);
 2848 #endif
 2849 
 2850         if (offset > brdp->memsize) {
 2851                 printf("STALLION: shared memory pointer=%x out of range at "
 2852                         "line=%d(%d), brd=%d\n", (int) offset, line,
 2853                         __LINE__, brdp->brdnr);
 2854                 ptr = 0;
 2855         } else {
 2856                 ptr = (char *) brdp->vaddr + (offset % ONB_ATPAGESIZE);
 2857         }
 2858         return(ptr);
 2859 }
 2860 
 2861 /*****************************************************************************/
 2862 
 2863 static void stli_onbreset(stlibrd_t *brdp)
 2864 {       
 2865         int     i;
 2866 
 2867 #if DEBUG
 2868         printf("stli_onbreset(brdp=%x)\n", (int) brdp);
 2869 #endif
 2870 
 2871         outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
 2872         DELAY(10);
 2873         outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
 2874         for (i = 0; (i < 1000); i++)
 2875                 DELAY(1000);
 2876 }
 2877 
 2878 /*****************************************************************************/
 2879 
 2880 /*
 2881  *      The following routines act on ONboard EISA.
 2882  */
 2883 
 2884 static void stli_onbeinit(stlibrd_t *brdp)
 2885 {
 2886         unsigned long   memconf;
 2887         int             i;
 2888 
 2889 #if DEBUG
 2890         printf("stli_onbeinit(brdp=%d)\n", (int) brdp);
 2891 #endif
 2892 
 2893         outb((brdp->iobase + ONB_EIBRDENAB), 0x1);
 2894         outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
 2895         DELAY(10);
 2896         outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2897         for (i = 0; (i < 1000); i++)
 2898                 DELAY(1000);
 2899 
 2900         memconf = (brdp->paddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
 2901         outb((brdp->iobase + ONB_EIMEMARL), memconf);
 2902         memconf = (brdp->paddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
 2903         outb((brdp->iobase + ONB_EIMEMARH), memconf);
 2904         outb(brdp->iobase, 0x1);
 2905         DELAY(1000);
 2906 }
 2907 
 2908 /*****************************************************************************/
 2909 
 2910 static void stli_onbeenable(stlibrd_t *brdp)
 2911 {       
 2912 #if DEBUG
 2913         printf("stli_onbeenable(brdp=%x)\n", (int) brdp);
 2914 #endif
 2915         outb((brdp->iobase + ONB_EICONFR), ONB_EIENABLE);
 2916 }
 2917 
 2918 /*****************************************************************************/
 2919 
 2920 static void stli_onbedisable(stlibrd_t *brdp)
 2921 {       
 2922 #if DEBUG
 2923         printf("stli_onbedisable(brdp=%x)\n", (int) brdp);
 2924 #endif
 2925         outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2926 }
 2927 
 2928 /*****************************************************************************/
 2929 
 2930 static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2931 {       
 2932         void            *ptr;
 2933         unsigned char   val;
 2934 
 2935 #if DEBUG
 2936         printf("stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n", (int) brdp,
 2937                 (int) offset, line);
 2938 #endif
 2939 
 2940         if (offset > brdp->memsize) {
 2941                 printf("STALLION: shared memory pointer=%x out of range at "
 2942                         "line=%d(%d), brd=%d\n", (int) offset, line,
 2943                         __LINE__, brdp->brdnr);
 2944                 ptr = 0;
 2945                 val = 0;
 2946         } else {
 2947                 ptr = (char *) brdp->vaddr + (offset % ONB_EIPAGESIZE);
 2948                 if (offset < ONB_EIPAGESIZE)
 2949                         val = ONB_EIENABLE;
 2950                 else
 2951                         val = ONB_EIENABLE | 0x40;
 2952         }
 2953         outb((brdp->iobase + ONB_EICONFR), val);
 2954         return(ptr);
 2955 }
 2956 
 2957 /*****************************************************************************/
 2958 
 2959 static void stli_onbereset(stlibrd_t *brdp)
 2960 {       
 2961         int     i;
 2962 
 2963 #if DEBUG
 2964         printf("stli_onbereset(brdp=%x)\n", (int) brdp);
 2965 #endif
 2966 
 2967         outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
 2968         DELAY(10);
 2969         outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2970         for (i = 0; (i < 1000); i++)
 2971                 DELAY(1000);
 2972 }
 2973 
 2974 /*****************************************************************************/
 2975 
 2976 /*
 2977  *      The following routines act on Brumby boards.
 2978  */
 2979 
 2980 static void stli_bbyinit(stlibrd_t *brdp)
 2981 {
 2982         int     i;
 2983 
 2984 #if DEBUG
 2985         printf("stli_bbyinit(brdp=%d)\n", (int) brdp);
 2986 #endif
 2987 
 2988         outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
 2989         DELAY(10);
 2990         outb((brdp->iobase + BBY_ATCONFR), 0);
 2991         for (i = 0; (i < 1000); i++)
 2992                 DELAY(1000);
 2993         outb(brdp->iobase, 0x1);
 2994         DELAY(1000);
 2995 }
 2996 
 2997 /*****************************************************************************/
 2998 
 2999 static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 3000 {       
 3001         void            *ptr;
 3002         unsigned char   val;
 3003 
 3004 #if DEBUG
 3005         printf("stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 3006                 (int) offset);
 3007 #endif
 3008 
 3009         if (offset > brdp->memsize) {
 3010                 printf("STALLION: shared memory pointer=%x out of range at "
 3011                         "line=%d(%d), brd=%d\n", (int) offset, line,
 3012                         __LINE__, brdp->brdnr);
 3013                 ptr = 0;
 3014                 val = 0;
 3015         } else {
 3016                 ptr = (char *) brdp->vaddr + (offset % BBY_PAGESIZE);
 3017                 val = (unsigned char) (offset / BBY_PAGESIZE);
 3018         }
 3019         outb((brdp->iobase + BBY_ATCONFR), val);
 3020         return(ptr);
 3021 }
 3022 
 3023 /*****************************************************************************/
 3024 
 3025 static void stli_bbyreset(stlibrd_t *brdp)
 3026 {       
 3027         int     i;
 3028 
 3029 #if DEBUG
 3030         printf("stli_bbyreset(brdp=%x)\n", (int) brdp);
 3031 #endif
 3032 
 3033         outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
 3034         DELAY(10);
 3035         outb((brdp->iobase + BBY_ATCONFR), 0);
 3036         for (i = 0; (i < 1000); i++)
 3037                 DELAY(1000);
 3038 }
 3039 
 3040 /*****************************************************************************/
 3041 
 3042 /*
 3043  *      The following routines act on original old Stallion boards.
 3044  */
 3045 
 3046 static void stli_stalinit(stlibrd_t *brdp)
 3047 {
 3048         int     i;
 3049 
 3050 #if DEBUG
 3051         printf("stli_stalinit(brdp=%d)\n", (int) brdp);
 3052 #endif
 3053 
 3054         outb(brdp->iobase, 0x1);
 3055         for (i = 0; (i < 1000); i++)
 3056                 DELAY(1000);
 3057 }
 3058 
 3059 /*****************************************************************************/
 3060 
 3061 static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 3062 {       
 3063         void    *ptr;
 3064 
 3065 #if DEBUG
 3066         printf("stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 3067                 (int) offset);
 3068 #endif
 3069 
 3070         if (offset > brdp->memsize) {
 3071                 printf("STALLION: shared memory pointer=%x out of range at "
 3072                         "line=%d(%d), brd=%d\n", (int) offset, line,
 3073                         __LINE__, brdp->brdnr);
 3074                 ptr = 0;
 3075         } else {
 3076                 ptr = (char *) brdp->vaddr + (offset % STAL_PAGESIZE);
 3077         }
 3078         return(ptr);
 3079 }
 3080 
 3081 /*****************************************************************************/
 3082 
 3083 static void stli_stalreset(stlibrd_t *brdp)
 3084 {       
 3085         volatile unsigned long  *vecp;
 3086         int                     i;
 3087 
 3088 #if DEBUG
 3089         printf("stli_stalreset(brdp=%x)\n", (int) brdp);
 3090 #endif
 3091 
 3092         vecp = (volatile unsigned long *) ((char *) brdp->vaddr + 0x30);
 3093         *vecp = 0xffff0000;
 3094         outb(brdp->iobase, 0);
 3095         for (i = 0; (i < 1000); i++)
 3096                 DELAY(1000);
 3097 }
 3098 
 3099 /*****************************************************************************/
 3100 
 3101 /*
 3102  *      Try to find an ECP board and initialize it. This handles only ECP
 3103  *      board types.
 3104  */
 3105 
 3106 static int stli_initecp(stlibrd_t *brdp)
 3107 {
 3108         cdkecpsig_t     sig;
 3109         cdkecpsig_t     *sigsp;
 3110         unsigned int    status, nxtid;
 3111         int             panelnr;
 3112 
 3113 #if DEBUG
 3114         printf("stli_initecp(brdp=%x)\n", (int) brdp);
 3115 #endif
 3116 
 3117 /*
 3118  *      Do a basic sanity check on the IO and memory addresses.
 3119  */
 3120         if ((brdp->iobase == 0) || (brdp->paddr == 0))
 3121                 return(EINVAL);
 3122 
 3123 /*
 3124  *      Based on the specific board type setup the common vars to access
 3125  *      and enable shared memory. Set all board specific information now
 3126  *      as well.
 3127  */
 3128         switch (brdp->brdtype) {
 3129         case BRD_ECP:
 3130                 brdp->memsize = ECP_MEMSIZE;
 3131                 brdp->pagesize = ECP_ATPAGESIZE;
 3132                 brdp->init = stli_ecpinit;
 3133                 brdp->enable = stli_ecpenable;
 3134                 brdp->reenable = stli_ecpenable;
 3135                 brdp->disable = stli_ecpdisable;
 3136                 brdp->getmemptr = stli_ecpgetmemptr;
 3137                 brdp->intr = stli_ecpintr;
 3138                 brdp->reset = stli_ecpreset;
 3139                 break;
 3140 
 3141         case BRD_ECPE:
 3142                 brdp->memsize = ECP_MEMSIZE;
 3143                 brdp->pagesize = ECP_EIPAGESIZE;
 3144                 brdp->init = stli_ecpeiinit;
 3145                 brdp->enable = stli_ecpeienable;
 3146                 brdp->reenable = stli_ecpeienable;
 3147                 brdp->disable = stli_ecpeidisable;
 3148                 brdp->getmemptr = stli_ecpeigetmemptr;
 3149                 brdp->intr = stli_ecpintr;
 3150                 brdp->reset = stli_ecpeireset;
 3151                 break;
 3152 
 3153         case BRD_ECPMC:
 3154                 brdp->memsize = ECP_MEMSIZE;
 3155                 brdp->pagesize = ECP_MCPAGESIZE;
 3156                 brdp->init = NULL;
 3157                 brdp->enable = stli_ecpmcenable;
 3158                 brdp->reenable = stli_ecpmcenable;
 3159                 brdp->disable = stli_ecpmcdisable;
 3160                 brdp->getmemptr = stli_ecpmcgetmemptr;
 3161                 brdp->intr = stli_ecpintr;
 3162                 brdp->reset = stli_ecpmcreset;
 3163                 break;
 3164 
 3165         default:
 3166                 return(EINVAL);
 3167         }
 3168 
 3169 /*
 3170  *      The per-board operations structure is all setup, so now lets go
 3171  *      and get the board operational. Firstly initialize board configuration
 3172  *      registers.
 3173  */
 3174         EBRDINIT(brdp);
 3175 
 3176 /*
 3177  *      Now that all specific code is set up, enable the shared memory and
 3178  *      look for the a signature area that will tell us exactly what board
 3179  *      this is, and what it is connected to it.
 3180  */
 3181         EBRDENABLE(brdp);
 3182         sigsp = (cdkecpsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
 3183         bcopy(sigsp, &sig, sizeof(cdkecpsig_t));
 3184         EBRDDISABLE(brdp);
 3185 
 3186 #if 0
 3187         printf("%s(%d): sig-> magic=%x rom=%x panel=%x,%x,%x,%x,%x,%x,%x,%x\n",
 3188                 __file__, __LINE__, (int) sig.magic, sig.romver,
 3189                 sig.panelid[0], (int) sig.panelid[1], (int) sig.panelid[2],
 3190                 (int) sig.panelid[3], (int) sig.panelid[4],
 3191                 (int) sig.panelid[5], (int) sig.panelid[6],
 3192                 (int) sig.panelid[7]);
 3193 #endif
 3194 
 3195         if (sig.magic != ECP_MAGIC)
 3196                 return(ENXIO);
 3197 
 3198 /*
 3199  *      Scan through the signature looking at the panels connected to the
 3200  *      board. Calculate the total number of ports as we go.
 3201  */
 3202         for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
 3203                 status = sig.panelid[nxtid];
 3204                 if ((status & ECH_PNLIDMASK) != nxtid)
 3205                         break;
 3206                 brdp->panelids[panelnr] = status;
 3207                 if (status & ECH_PNL16PORT) {
 3208                         brdp->panels[panelnr] = 16;
 3209                         brdp->nrports += 16;
 3210                         nxtid += 2;
 3211                 } else {
 3212                         brdp->panels[panelnr] = 8;
 3213                         brdp->nrports += 8;
 3214                         nxtid++;
 3215                 }
 3216                 brdp->nrpanels++;
 3217         }
 3218 
 3219         brdp->state |= BST_FOUND;
 3220         return(0);
 3221 }
 3222 
 3223 /*****************************************************************************/
 3224 
 3225 /*
 3226  *      Try to find an ONboard, Brumby or Stallion board and initialize it.
 3227  *      This handles only these board types.
 3228  */
 3229 
 3230 static int stli_initonb(stlibrd_t *brdp)
 3231 {
 3232         cdkonbsig_t     sig;
 3233         cdkonbsig_t     *sigsp;
 3234         int             i;
 3235 
 3236 #if DEBUG
 3237         printf("stli_initonb(brdp=%x)\n", (int) brdp);
 3238 #endif
 3239 
 3240 /*
 3241  *      Do a basic sanity check on the IO and memory addresses.
 3242  */
 3243         if ((brdp->iobase == 0) || (brdp->paddr == 0))
 3244                 return(EINVAL);
 3245 
 3246 /*
 3247  *      Based on the specific board type setup the common vars to access
 3248  *      and enable shared memory. Set all board specific information now
 3249  *      as well.
 3250  */
 3251         switch (brdp->brdtype) {
 3252         case BRD_ONBOARD:
 3253         case BRD_ONBOARD32:
 3254         case BRD_ONBOARD2:
 3255         case BRD_ONBOARD2_32:
 3256         case BRD_ONBOARDRS:
 3257                 brdp->memsize = ONB_MEMSIZE;
 3258                 brdp->pagesize = ONB_ATPAGESIZE;
 3259                 brdp->init = stli_onbinit;
 3260                 brdp->enable = stli_onbenable;
 3261                 brdp->reenable = stli_onbenable;
 3262                 brdp->disable = stli_onbdisable;
 3263                 brdp->getmemptr = stli_onbgetmemptr;
 3264                 brdp->intr = stli_ecpintr;
 3265                 brdp->reset = stli_onbreset;
 3266                 brdp->confbits = (brdp->paddr > 0x100000) ? ONB_HIMEMENAB : 0;
 3267                 break;
 3268 
 3269         case BRD_ONBOARDE:
 3270                 brdp->memsize = ONB_EIMEMSIZE;
 3271                 brdp->pagesize = ONB_EIPAGESIZE;
 3272                 brdp->init = stli_onbeinit;
 3273                 brdp->enable = stli_onbeenable;
 3274                 brdp->reenable = stli_onbeenable;
 3275                 brdp->disable = stli_onbedisable;
 3276                 brdp->getmemptr = stli_onbegetmemptr;
 3277                 brdp->intr = stli_ecpintr;
 3278                 brdp->reset = stli_onbereset;
 3279                 break;
 3280 
 3281         case BRD_BRUMBY4:
 3282         case BRD_BRUMBY8:
 3283         case BRD_BRUMBY16:
 3284                 brdp->memsize = BBY_MEMSIZE;
 3285                 brdp->pagesize = BBY_PAGESIZE;
 3286                 brdp->init = stli_bbyinit;
 3287                 brdp->enable = NULL;
 3288                 brdp->reenable = NULL;
 3289                 brdp->disable = NULL;
 3290                 brdp->getmemptr = stli_bbygetmemptr;
 3291                 brdp->intr = stli_ecpintr;
 3292                 brdp->reset = stli_bbyreset;
 3293                 break;
 3294 
 3295         case BRD_STALLION:
 3296                 brdp->memsize = STAL_MEMSIZE;
 3297                 brdp->pagesize = STAL_PAGESIZE;
 3298                 brdp->init = stli_stalinit;
 3299                 brdp->enable = NULL;
 3300                 brdp->reenable = NULL;
 3301                 brdp->disable = NULL;
 3302                 brdp->getmemptr = stli_stalgetmemptr;
 3303                 brdp->intr = stli_ecpintr;
 3304                 brdp->reset = stli_stalreset;
 3305                 break;
 3306 
 3307         default:
 3308                 return(EINVAL);
 3309         }
 3310 
 3311 /*
 3312  *      The per-board operations structure is all setup, so now lets go
 3313  *      and get the board operational. Firstly initialize board configuration
 3314  *      registers.
 3315  */
 3316         EBRDINIT(brdp);
 3317 
 3318 /*
 3319  *      Now that all specific code is set up, enable the shared memory and
 3320  *      look for the a signature area that will tell us exactly what board
 3321  *      this is, and how many ports.
 3322  */
 3323         EBRDENABLE(brdp);
 3324         sigsp = (cdkonbsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
 3325         bcopy(sigsp, &sig, sizeof(cdkonbsig_t));
 3326         EBRDDISABLE(brdp);
 3327 
 3328 #if 0
 3329         printf("%s(%d): sig-> magic=%x:%x:%x:%x romver=%x amask=%x:%x:%x\n",
 3330                 __file__, __LINE__, sig.magic0, sig.magic1, sig.magic2,
 3331                 sig.magic3, sig.romver, sig.amask0, sig.amask1, sig.amask2);
 3332 #endif
 3333 
 3334         if ((sig.magic0 != ONB_MAGIC0) || (sig.magic1 != ONB_MAGIC1) ||
 3335             (sig.magic2 != ONB_MAGIC2) || (sig.magic3 != ONB_MAGIC3))
 3336                 return(ENXIO);
 3337 
 3338 /*
 3339  *      Scan through the signature alive mask and calculate how many ports
 3340  *      there are on this board.
 3341  */
 3342         brdp->nrpanels = 1;
 3343         if (sig.amask1) {
 3344                 brdp->nrports = 32;
 3345         } else {
 3346                 for (i = 0; (i < 16); i++) {
 3347                         if (((sig.amask0 << i) & 0x8000) == 0)
 3348                                 break;
 3349                 }
 3350                 brdp->nrports = i;
 3351         }
 3352         brdp->panels[0] = brdp->nrports;
 3353 
 3354         brdp->state |= BST_FOUND;
 3355         return(0);
 3356 }
 3357 
 3358 /*****************************************************************************/
 3359 
 3360 /*
 3361  *      Start up a running board. This routine is only called after the
 3362  *      code has been down loaded to the board and is operational. It will
 3363  *      read in the memory map, and get the show on the road...
 3364  */
 3365 
 3366 static int stli_startbrd(stlibrd_t *brdp)
 3367 {
 3368         volatile cdkhdr_t       *hdrp;
 3369         volatile cdkmem_t       *memp;
 3370         volatile cdkasy_t       *ap;
 3371         stliport_t              *portp;
 3372         int                     portnr, nrdevs, i, rc;
 3373 
 3374 #if DEBUG
 3375         printf("stli_startbrd(brdp=%x)\n", (int) brdp);
 3376 #endif
 3377 
 3378         rc = 0;
 3379 
 3380         disable_intr();
 3381         EBRDENABLE(brdp);
 3382         hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 3383         nrdevs = hdrp->nrdevs;
 3384 
 3385 #if 0
 3386         printf("%s(%d): CDK version %d.%d.%d --> nrdevs=%d memp=%x hostp=%x "
 3387                 "slavep=%x\n", __file__, __LINE__, hdrp->ver_release,
 3388                 hdrp->ver_modification, hdrp->ver_fix, nrdevs,
 3389                 (int) hdrp->memp, (int) hdrp->hostp, (int) hdrp->slavep);
 3390 #endif
 3391 
 3392         if (nrdevs < (brdp->nrports + 1)) {
 3393                 printf("STALLION: slave failed to allocate memory for all "
 3394                         "devices, devices=%d\n", nrdevs);
 3395                 brdp->nrports = nrdevs - 1;
 3396         }
 3397         brdp->nrdevs = nrdevs;
 3398         brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
 3399         brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
 3400         brdp->bitsize = (nrdevs + 7) / 8;
 3401         memp = (volatile cdkmem_t *) hdrp->memp;
 3402         if (((unsigned long) memp) > brdp->memsize) {
 3403                 printf("STALLION: corrupted shared memory region?\n");
 3404                 rc = EIO;
 3405                 goto stli_donestartup;
 3406         }
 3407         memp = (volatile cdkmem_t *) EBRDGETMEMPTR(brdp, (unsigned long) memp);
 3408         if (memp->dtype != TYP_ASYNCTRL) {
 3409                 printf("STALLION: no slave control device found\n");
 3410                 rc = EIO;
 3411                 goto stli_donestartup;
 3412         }
 3413         memp++;
 3414 
 3415 /*
 3416  *      Cycle through memory allocation of each port. We are guaranteed to
 3417  *      have all ports inside the first page of slave window, so no need to
 3418  *      change pages while reading memory map.
 3419  */
 3420         for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
 3421                 if (memp->dtype != TYP_ASYNC)
 3422                         break;
 3423                 portp = brdp->ports[portnr];
 3424                 if (portp == (stliport_t *) NULL)
 3425                         break;
 3426                 portp->devnr = i;
 3427                 portp->addr = memp->offset;
 3428                 portp->reqidx = (unsigned char) (i * 8 / nrdevs);
 3429                 portp->reqbit = (unsigned char) (0x1 << portp->reqidx);
 3430                 portp->portidx = (unsigned char) (i / 8);
 3431                 portp->portbit = (unsigned char) (0x1 << (i % 8));
 3432         }
 3433 
 3434         hdrp->slavereq = 0xff;
 3435 
 3436 /*
 3437  *      For each port setup a local copy of the RX and TX buffer offsets
 3438  *      and sizes. We do this separate from the above, because we need to
 3439  *      move the shared memory page...
 3440  */
 3441         for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
 3442                 portp = brdp->ports[portnr];
 3443                 if (portp == (stliport_t *) NULL)
 3444                         break;
 3445                 if (portp->addr == 0)
 3446                         break;
 3447                 ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 3448                 if (ap != (volatile cdkasy_t *) NULL) {
 3449                         portp->rxsize = ap->rxq.size;
 3450                         portp->txsize = ap->txq.size;
 3451                         portp->rxoffset = ap->rxq.offset;
 3452                         portp->txoffset = ap->txq.offset;
 3453                 }
 3454         }
 3455 
 3456 stli_donestartup:
 3457         EBRDDISABLE(brdp);
 3458         enable_intr();
 3459 
 3460         if (rc == 0)
 3461                 brdp->state |= BST_STARTED;
 3462 
 3463         if (stli_doingtimeout == 0) {
 3464                 timeout(stli_poll, 0, 1);
 3465                 stli_doingtimeout++;
 3466         }
 3467 
 3468         return(rc);
 3469 }
 3470 
 3471 /*****************************************************************************/
 3472 
 3473 /*
 3474  *      Probe and initialize the specified board.
 3475  */
 3476 
 3477 static int stli_brdinit(stlibrd_t *brdp)
 3478 {
 3479 #if DEBUG
 3480         printf("stli_brdinit(brdp=%x)\n", (int) brdp);
 3481 #endif
 3482 
 3483         stli_brds[brdp->brdnr] = brdp;
 3484 
 3485         switch (brdp->brdtype) {
 3486         case BRD_ECP:
 3487         case BRD_ECPE:
 3488         case BRD_ECPMC:
 3489                 stli_initecp(brdp);
 3490                 break;
 3491         case BRD_ONBOARD:
 3492         case BRD_ONBOARDE:
 3493         case BRD_ONBOARD2:
 3494         case BRD_ONBOARD32:
 3495         case BRD_ONBOARD2_32:
 3496         case BRD_ONBOARDRS:
 3497         case BRD_BRUMBY4:
 3498         case BRD_BRUMBY8:
 3499         case BRD_BRUMBY16:
 3500         case BRD_STALLION:
 3501                 stli_initonb(brdp);
 3502                 break;
 3503         case BRD_EASYIO:
 3504         case BRD_ECH:
 3505         case BRD_ECHMC:
 3506         case BRD_ECHPCI:
 3507                 printf("STALLION: %s board type not supported in this driver\n",
 3508                         stli_brdnames[brdp->brdtype]);
 3509                 return(ENODEV);
 3510         default:
 3511                 printf("STALLION: unit=%d is unknown board type=%d\n",
 3512                         brdp->brdnr, brdp->brdtype);
 3513                 return(ENODEV);
 3514         }
 3515         return(0);
 3516 }
 3517 
 3518 /*****************************************************************************/
 3519 
 3520 /*
 3521  *      Finish off the remaining initialization for a board.
 3522  */
 3523 
 3524 static int stli_brdattach(stlibrd_t *brdp)
 3525 {
 3526 #if DEBUG
 3527         printf("stli_brdattach(brdp=%x)\n", (int) brdp);
 3528 #endif
 3529 
 3530 #if 0
 3531         if ((brdp->state & BST_FOUND) == 0) {
 3532                 printf("STALLION: %s board not found, unit=%d io=%x mem=%x\n",
 3533                         stli_brdnames[brdp->brdtype], brdp->brdnr,
 3534                         brdp->iobase, (int) brdp->paddr);
 3535                 return(ENXIO);
 3536         }
 3537 #endif
 3538 
 3539         stli_initports(brdp);
 3540         printf("stli%d: %s (driver version %s), unit=%d nrpanels=%d "
 3541                 "nrports=%d\n", brdp->unitid, stli_brdnames[brdp->brdtype],
 3542                 stli_drvversion, brdp->brdnr, brdp->nrpanels, brdp->nrports);
 3543         return(0);
 3544 }
 3545 
 3546 /*****************************************************************************/
 3547 
 3548 /*
 3549  *      Check for possible shared memory sharing between boards.
 3550  *      FIX: need to start this optimization somewhere...
 3551  */
 3552 
 3553 static int stli_chksharemem()
 3554 {
 3555         stlibrd_t       *brdp, *nxtbrdp;
 3556         int             i, j;
 3557 
 3558 #if DEBUG
 3559         printf("stli_chksharemem()\n");
 3560 #endif
 3561 
 3562 /*
 3563  *      All found boards are initialized. Now for a little optimization, if
 3564  *      no boards are sharing the "shared memory" regions then we can just
 3565  *      leave them all enabled. This is in fact the usual case.
 3566  */
 3567         stli_shared = 0;
 3568         if (stli_nrbrds > 1) {
 3569                 for (i = 0; (i < stli_nrbrds); i++) {
 3570                         brdp = stli_brds[i];
 3571                         if (brdp == (stlibrd_t *) NULL)
 3572                                 continue;
 3573                         for (j = i + 1; (j < stli_nrbrds); j++) {
 3574                                 nxtbrdp = stli_brds[j];
 3575                                 if (nxtbrdp == (stlibrd_t *) NULL)
 3576                                         continue;
 3577                                 if ((brdp->paddr >= nxtbrdp->paddr) &&
 3578                                     (brdp->paddr <= (nxtbrdp->paddr +
 3579                                     nxtbrdp->memsize - 1))) {
 3580                                         stli_shared++;
 3581                                         break;
 3582                                 }
 3583                         }
 3584                 }
 3585         }
 3586 
 3587         if (stli_shared == 0) {
 3588                 for (i = 0; (i < stli_nrbrds); i++) {
 3589                         brdp = stli_brds[i];
 3590                         if (brdp == (stlibrd_t *) NULL)
 3591                                 continue;
 3592                         if (brdp->state & BST_FOUND) {
 3593                                 EBRDENABLE(brdp);
 3594                                 brdp->enable = NULL;
 3595                                 brdp->disable = NULL;
 3596                         }
 3597                 }
 3598         }
 3599 
 3600         return(0);
 3601 }
 3602 
 3603 /*****************************************************************************/
 3604 
 3605 /*
 3606  *      Return the board stats structure to user app.
 3607  */
 3608 
 3609 static int stli_getbrdstats(caddr_t data)
 3610 {
 3611         stlibrd_t       *brdp;
 3612         int             i;
 3613 
 3614 #if DEBUG
 3615         printf("stli_getbrdstats(data=%x)\n", data);
 3616 #endif
 3617 
 3618         stli_brdstats = *((combrd_t *) data);
 3619         if (stli_brdstats.brd >= STL_MAXBRDS)
 3620                 return(-ENODEV);
 3621         brdp = stli_brds[stli_brdstats.brd];
 3622         if (brdp == (stlibrd_t *) NULL)
 3623                 return(-ENODEV);
 3624 
 3625         bzero(&stli_brdstats, sizeof(combrd_t));
 3626         stli_brdstats.brd = brdp->brdnr;
 3627         stli_brdstats.type = brdp->brdtype;
 3628         stli_brdstats.hwid = 0;
 3629         stli_brdstats.state = brdp->state;
 3630         stli_brdstats.ioaddr = brdp->iobase;
 3631         stli_brdstats.memaddr = brdp->paddr;
 3632         stli_brdstats.nrpanels = brdp->nrpanels;
 3633         stli_brdstats.nrports = brdp->nrports;
 3634         for (i = 0; (i < brdp->nrpanels); i++) {
 3635                 stli_brdstats.panels[i].panel = i;
 3636                 stli_brdstats.panels[i].hwid = brdp->panelids[i];
 3637                 stli_brdstats.panels[i].nrports = brdp->panels[i];
 3638         }
 3639 
 3640         *((combrd_t *) data) = stli_brdstats;
 3641         return(0);
 3642 }
 3643 
 3644 /*****************************************************************************/
 3645 
 3646 /*
 3647  *      Resolve the referenced port number into a port struct pointer.
 3648  */
 3649 
 3650 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
 3651 {
 3652         stlibrd_t       *brdp;
 3653         int             i;
 3654 
 3655         if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
 3656                 return((stliport_t *) NULL);
 3657         brdp = stli_brds[brdnr];
 3658         if (brdp == (stlibrd_t *) NULL)
 3659                 return((stliport_t *) NULL);
 3660         for (i = 0; (i < panelnr); i++)
 3661                 portnr += brdp->panels[i];
 3662         if ((portnr < 0) || (portnr >= brdp->nrports))
 3663                 return((stliport_t *) NULL);
 3664         return(brdp->ports[portnr]);
 3665 }
 3666 
 3667 /*****************************************************************************/
 3668 
 3669 /*
 3670  *      Return the port stats structure to user app. A NULL port struct
 3671  *      pointer passed in means that we need to find out from the app
 3672  *      what port to get stats for (used through board control device).
 3673  */
 3674 
 3675 static int stli_getportstats(stliport_t *portp, caddr_t data)
 3676 {
 3677         stlibrd_t       *brdp;
 3678         int             rc;
 3679 
 3680         if (portp == (stliport_t *) NULL) {
 3681                 stli_comstats = *((comstats_t *) data);
 3682                 portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 3683                         stli_comstats.port);
 3684                 if (portp == (stliport_t *) NULL)
 3685                         return(-ENODEV);
 3686         }
 3687 
 3688         brdp = stli_brds[portp->brdnr];
 3689         if (brdp == (stlibrd_t *) NULL)
 3690                 return(-ENODEV);
 3691 
 3692         if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, &stli_cdkstats,
 3693                         sizeof(asystats_t), 1)) < 0)
 3694                 return(rc);
 3695 
 3696         stli_comstats.brd = portp->brdnr;
 3697         stli_comstats.panel = portp->panelnr;
 3698         stli_comstats.port = portp->portnr;
 3699         stli_comstats.state = portp->state;
 3700         /*stli_comstats.flags = portp->flags;*/
 3701         stli_comstats.ttystate = portp->tty.t_state;
 3702         stli_comstats.cflags = portp->tty.t_cflag;
 3703         stli_comstats.iflags = portp->tty.t_iflag;
 3704         stli_comstats.oflags = portp->tty.t_oflag;
 3705         stli_comstats.lflags = portp->tty.t_lflag;
 3706 
 3707         stli_comstats.txtotal = stli_cdkstats.txchars;
 3708         stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
 3709         stli_comstats.txbuffered = stli_cdkstats.txringq;
 3710         stli_comstats.rxbuffered = stli_cdkstats.rxringq;
 3711         stli_comstats.rxoverrun = stli_cdkstats.overruns;
 3712         stli_comstats.rxparity = stli_cdkstats.parity;
 3713         stli_comstats.rxframing = stli_cdkstats.framing;
 3714         stli_comstats.rxlost = stli_cdkstats.ringover + portp->rxlost;
 3715         stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
 3716         stli_comstats.txbreaks = stli_cdkstats.txbreaks;
 3717         stli_comstats.txxon = stli_cdkstats.txstart;
 3718         stli_comstats.txxoff = stli_cdkstats.txstop;
 3719         stli_comstats.rxxon = stli_cdkstats.rxstart;
 3720         stli_comstats.rxxoff = stli_cdkstats.rxstop;
 3721         stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
 3722         stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
 3723         stli_comstats.modem = stli_cdkstats.dcdcnt;
 3724         stli_comstats.hwid = stli_cdkstats.hwid;
 3725         stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
 3726 
 3727         *((comstats_t *) data) = stli_comstats;;
 3728         return(0);
 3729 }
 3730 
 3731 /*****************************************************************************/
 3732 
 3733 /*
 3734  *      Clear the port stats structure. We also return it zeroed out...
 3735  */
 3736 
 3737 static int stli_clrportstats(stliport_t *portp, caddr_t data)
 3738 {
 3739         stlibrd_t       *brdp;
 3740         int             rc;
 3741 
 3742         if (portp == (stliport_t *) NULL) {
 3743                 stli_comstats = *((comstats_t *) data);
 3744                 portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 3745                         stli_comstats.port);
 3746                 if (portp == (stliport_t *) NULL)
 3747                         return(-ENODEV);
 3748         }
 3749 
 3750         brdp = stli_brds[portp->brdnr];
 3751         if (brdp == (stlibrd_t *) NULL)
 3752                 return(-ENODEV);
 3753 
 3754         if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, 0, 0, 0)) < 0)
 3755                 return(rc);
 3756 
 3757         portp->rxlost = 0;
 3758         bzero(&stli_comstats, sizeof(comstats_t));
 3759         stli_comstats.brd = portp->brdnr;
 3760         stli_comstats.panel = portp->panelnr;
 3761         stli_comstats.port = portp->portnr;
 3762 
 3763         *((comstats_t *) data) = stli_comstats;;
 3764         return(0);
 3765 }
 3766 
 3767 /*****************************************************************************/
 3768 
 3769 /*
 3770  *      Code to handle an "staliomem" read and write operations. This device
 3771  *      is the contents of the board shared memory. It is used for down
 3772  *      loading the slave image (and debugging :-)
 3773  */
 3774 
 3775 STATIC int stli_memrw(dev_t dev, struct uio *uiop, int flag)
 3776 {
 3777         stlibrd_t       *brdp;
 3778         void            *memptr;
 3779         int             brdnr, size, n, error;
 3780 
 3781 #if DEBUG
 3782         printf("stli_memrw(dev=%x,uiop=%x,flag=%x)\n", (int) dev,
 3783                 (int) uiop, flag);
 3784 #endif
 3785 
 3786         brdnr = dev & 0x7;
 3787         brdp = stli_brds[brdnr];
 3788         if (brdp == (stlibrd_t *) NULL)
 3789                 return(ENODEV);
 3790         if (brdp->state == 0)
 3791                 return(ENODEV);
 3792 
 3793         if (uiop->uio_offset >= brdp->memsize)
 3794                 return(0);
 3795 
 3796         error = 0;
 3797         size = brdp->memsize - uiop->uio_offset;
 3798 
 3799         disable_intr();
 3800         EBRDENABLE(brdp);
 3801         while (size > 0) {
 3802                 memptr = (void *) EBRDGETMEMPTR(brdp, uiop->uio_offset);
 3803                 n = MIN(size, (brdp->pagesize -
 3804                         (((unsigned long) uiop->uio_offset) % brdp->pagesize)));
 3805                 error = uiomove(memptr, n, uiop);
 3806                 if ((uiop->uio_resid == 0) || error)
 3807                         break;
 3808         }
 3809         EBRDDISABLE(brdp);
 3810         enable_intr();
 3811 
 3812         return(error);
 3813 }
 3814 
 3815 /*****************************************************************************/
 3816 
 3817 /*
 3818  *      The "staliomem" device is also required to do some special operations
 3819  *      on the board. We need to be able to send an interrupt to the board,
 3820  *      reset it, and start/stop it.
 3821  */
 3822 
 3823 static int stli_memioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 3824 {
 3825         stlibrd_t       *brdp;
 3826         int             brdnr, rc;
 3827 
 3828 #if DEBUG
 3829         printf("stli_memioctl(dev=%x,cmd=%x,data=%x,flag=%x)\n", (int) dev,
 3830                 cmd, (int) data, flag);
 3831 #endif
 3832 
 3833         brdnr = dev & 0x7;
 3834         brdp = stli_brds[brdnr];
 3835         if (brdp == (stlibrd_t *) NULL)
 3836                 return(ENODEV);
 3837         if (brdp->state == 0)
 3838                 return(ENODEV);
 3839 
 3840         rc = 0;
 3841 
 3842         switch (cmd) {
 3843         case STL_BINTR:
 3844                 EBRDINTR(brdp);
 3845                 break;
 3846         case STL_BSTART:
 3847                 rc = stli_startbrd(brdp);
 3848                 break;
 3849         case STL_BSTOP:
 3850                 brdp->state &= ~BST_STARTED;
 3851                 break;
 3852         case STL_BRESET:
 3853                 brdp->state &= ~BST_STARTED;
 3854                 EBRDRESET(brdp);
 3855                 if (stli_shared == 0) {
 3856                         if (brdp->reenable != NULL)
 3857                                 (* brdp->reenable)(brdp);
 3858                 }
 3859                 break;
 3860         case COM_GETPORTSTATS:
 3861                 rc = stli_getportstats((stliport_t *) NULL, data);
 3862                 break;
 3863         case COM_CLRPORTSTATS:
 3864                 rc = stli_clrportstats((stliport_t *) NULL, data);
 3865                 break;
 3866         case COM_GETBRDSTATS:
 3867                 rc = stli_getbrdstats(data);
 3868                 break;
 3869         default:
 3870                 rc = ENOTTY;
 3871                 break;
 3872         }
 3873 
 3874         return(rc);
 3875 }
 3876 
 3877 /*****************************************************************************/

Cache object: db59d048177bcdf731bdfc3322b3125b


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