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