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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: c5ed29384cf1337a279692c3bd13a8c9


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