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