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


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

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/istallion.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a293212e9cac25105bedb2338e612e07


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