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

Cache object: 1b38645d7460322cd9ef1a01273dd155


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