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

Cache object: 178d15ef89c2818f68819be41fdf93bb


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