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