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