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