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