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