2 * linux/drivers/char/pcxe.c
4 * Written by Troy De Jongh, November, 1994
6 * Copyright (C) 1994,1995 Troy De Jongh
7 * This software may be used and distributed according to the terms
8 * of the GNU Public License.
10 * This driver is for the DigiBoard PC/Xe and PC/Xi line of products.
12 * This driver does NOT support DigiBoard's fastcook FEP option and
13 * does not support the transparent print (i.e. digiprint) option.
15 * This Driver is currently maintained by Christoph Lameter (clameter@fuller.edu)
16 * Please contact the mailing list for problems first.
18 * Sources of Information:
19 * 1. The Linux Digiboard Page at http://private.fuller.edu/clameter/digi.html
20 * 2. The Linux Digiboard Mailing list at digiboard@list.fuller.edu
21 * (Simply write a message to introduce yourself to subscribe)
23 * 1.5.2 Fall 1995 Bug fixes by David Nugent
24 * 1.5.3 March 9, 1996 Christoph Lameter: Fixed 115.2K Support. Memory
25 * allocation harmonized with 1.3.X Series.
26 * 1.5.4 March 30, 1996 Christoph Lameter: Fixup for 1.3.81. Use init_bh
27 * instead of direct assignment to kernel arrays.
28 * 1.5.5 April 5, 1996 Major device numbers corrected.
29 * Mike McLagan<mike.mclagan@linux.org>: Add setup
30 * variable handling, instead of using the old pcxxconfig.h
31 * 1.5.6 April 16, 1996 Christoph Lameter: Pointer cleanup, macro cleanup.
32 * Call out devices changed to /dev/cudxx.
33 * 1.5.7 July 22, 1996 Martin Mares: CLOCAL fix, pcxe_table clearing.
34 * David Nugent: Bug in pcxe_open.
35 * Brian J. Murrell: Modem Control fixes, Majors correctly assigned
36 * 1.6.1 April 6, 1997 Bernhard Kaindl: fixed virtual memory access for 2.1
37 * i386-kernels and use on other archtitectures, Allowing use
38 * as module, added module parameters, added switch to enable
39 * verbose messages to assist user during card configuration.
40 * Currently only tested on a PC/Xi card, but should work on Xe
46 /* If you define SPEED_HACK then you get the following Baudrate translation
49 The driver supports the native 57.6K and 115K Baudrates under Linux, but
50 some distributions like Slackware 3.0 don't like these high baudrates.
53 #include <linux/module.h>
55 #include <linux/ioport.h>
56 #include <linux/errno.h>
57 #include <linux/signal.h>
58 #include <linux/sched.h>
59 #include <linux/timer.h>
60 #include <linux/interrupt.h>
61 #include <linux/tty.h>
62 #include <linux/tty_flip.h>
63 #include <linux/major.h>
64 #include <linux/string.h>
65 #include <linux/fcntl.h>
66 #include <linux/ptrace.h>
67 #include <linux/delay.h>
68 #include <linux/serial.h>
69 #include <linux/tty_driver.h>
70 #include <linux/malloc.h>
71 #include <linux/init.h>
72 #include <linux/version.h>
75 #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
78 #include <asm/system.h>
80 #include <asm/uaccess.h>
81 #include <asm/bitops.h>
82 #include <asm/semaphore.h>
84 #define VERSION "1.6.1"
90 #include "digi_bios.h"
93 * Define one default setting if no digi= config line is used.
94 * Default is altpin = disabled, 16 ports, I/O 200h, Memory 0D0000h
96 static struct board_info boards
[MAX_DIGI_BOARDS
] = { {
97 /* Board is enabled */ ENABLED
,
98 /* Type is auto-detected */ 0,
99 /* altping is disabled */ DISABLED
,
100 /* number of ports = 16 */ 16,
101 /* io address is 0x200 */ 0x200,
102 /* card memory at 0xd0000 */ 0xd0000,
103 /* first minor device no. */ 0
106 static int verbose
= 0;
107 static int debug
= 0;
110 /* Variables for insmod */
111 static int io
[] = {0, 0, 0, 0};
112 static int membase
[] = {0, 0, 0, 0};
113 static int memsize
[] = {0, 0, 0, 0};
114 static int altpin
[] = {0, 0, 0, 0};
115 static int numports
[] = {0, 0, 0, 0};
117 # if (LINUX_VERSION_CODE > 0x020111)
118 MODULE_AUTHOR("Bernhard Kaindl");
119 MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
120 MODULE_PARM(verbose
, "i");
121 MODULE_PARM(debug
, "i");
122 MODULE_PARM(io
, "1-4i");
123 MODULE_PARM(membase
, "1-4i");
124 MODULE_PARM(memsize
, "1-4i");
125 MODULE_PARM(altpin
, "1-4i");
126 MODULE_PARM(numports
, "1-4i");
131 static int numcards
= 1;
132 static int nbdevs
= 0;
134 static struct channel
*digi_channels
;
135 static struct tty_struct
**pcxe_table
;
136 static struct termios
**pcxe_termios
;
137 static struct termios
**pcxe_termios_locked
;
139 int pcxx_ncook
=sizeof(pcxx_cook
);
140 int pcxx_nbios
=sizeof(pcxx_bios
);
142 #define MIN(a,b) ((a) < (b) ? (a) : (b))
143 #define pcxxassert(x, msg) if(!(x)) pcxx_error(__LINE__, msg)
145 #define FEPTIMEOUT 200000
146 #define SERIAL_TYPE_NORMAL 1
147 #define SERIAL_TYPE_CALLOUT 2
148 #define PCXE_EVENT_HANGUP 1
150 struct tty_driver pcxe_driver
;
151 struct tty_driver pcxe_callout
;
152 static int pcxe_refcount
;
154 DECLARE_TASK_QUEUE(tq_pcxx
);
156 static void pcxxpoll(void);
157 static void pcxxdelay(int);
158 static void fepcmd(struct channel
*, int, int, int, int, int);
159 static void pcxe_put_char(struct tty_struct
*, unsigned char);
160 static void pcxe_flush_chars(struct tty_struct
*);
161 static void pcxx_error(int, char *);
162 static void pcxe_close(struct tty_struct
*, struct file
*);
163 static int pcxe_ioctl(struct tty_struct
*, struct file
*, unsigned int, unsigned long);
164 static void pcxe_set_termios(struct tty_struct
*, struct termios
*);
165 static int pcxe_write(struct tty_struct
*, int, const unsigned char *, int);
166 static int pcxe_write_room(struct tty_struct
*);
167 static int pcxe_chars_in_buffer(struct tty_struct
*);
168 static void pcxe_flush_buffer(struct tty_struct
*);
169 static void doevent(int);
170 static void receive_data(struct channel
*);
171 static void pcxxparam(struct tty_struct
*, struct channel
*ch
);
172 static void do_softint(void *);
173 static inline void pcxe_sched_event(struct channel
*, int);
174 static void do_pcxe_bh(void);
175 static void pcxe_start(struct tty_struct
*);
176 static void pcxe_stop(struct tty_struct
*);
177 static void pcxe_throttle(struct tty_struct
*);
178 static void pcxe_unthrottle(struct tty_struct
*);
179 static void digi_send_break(struct channel
*ch
, int msec
);
180 static void shutdown(struct channel
*);
181 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
);
182 static inline void memwinon(struct board_info
*b
, unsigned int win
);
183 static inline void memwinoff(struct board_info
*b
, unsigned int win
);
184 static inline void globalwinon(struct channel
*ch
);
185 static inline void rxwinon(struct channel
*ch
);
186 static inline void txwinon(struct channel
*ch
);
187 static inline void memoff(struct channel
*ch
);
188 static inline void assertgwinon(struct channel
*ch
);
189 static inline void assertmemoff(struct channel
*ch
);
191 #define TZ_BUFSZ 4096
193 /* function definitions */
197 * pcxe_init() is our init_module():
199 #define pcxe_init init_module
201 void cleanup_module(void);
204 /*****************************************************************************/
206 void cleanup_module()
212 struct board_info
*bd
;
215 printk(KERN_NOTICE
"Unloading PC/Xx version %s\n", VERSION
);
219 timer_active
&= ~(1 << DIGI_TIMER
);
220 timer_table
[DIGI_TIMER
].fn
= NULL
;
221 timer_table
[DIGI_TIMER
].expires
= 0;
224 if ((e1
= tty_unregister_driver(&pcxe_driver
)))
225 printk("SERIAL: failed to unregister serial driver (%d)\n", e1
);
226 if ((e2
= tty_unregister_driver(&pcxe_callout
)))
227 printk("SERIAL: failed to unregister callout driver (%d)\n",e2
);
229 for(crd
=0; crd
< numcards
; crd
++) {
231 ch
= digi_channels
+bd
->first_minor
;
232 for(i
=0; i
< bd
->numports
; i
++, ch
++) {
235 release_region(bd
->port
, 4);
237 kfree(digi_channels
);
238 kfree(pcxe_termios_locked
);
241 restore_flags(flags
);
245 static inline struct channel
*chan(register struct tty_struct
*tty
)
248 register struct channel
*ch
=(struct channel
*)tty
->driver_data
;
249 if (ch
>= digi_channels
&& ch
< digi_channels
+nbdevs
) {
250 if (ch
->magic
==PCXX_MAGIC
)
257 /* These inline routines are to turn board memory on and off */
258 static inline void memwinon(struct board_info
*b
, unsigned int win
)
260 if(b
->type
== PCXEVE
)
261 outb_p(FEPWIN
|win
, b
->port
+1);
263 outb_p(inb(b
->port
)|FEPMEM
, b
->port
);
266 static inline void memwinoff(struct board_info
*b
, unsigned int win
)
268 outb_p(inb(b
->port
)&~FEPMEM
, b
->port
);
269 if(b
->type
== PCXEVE
)
270 outb_p(0, b
->port
+ 1);
273 static inline void globalwinon(struct channel
*ch
)
275 if(ch
->board
->type
== PCXEVE
)
276 outb_p(FEPWIN
, ch
->board
->port
+1);
278 outb_p(FEPMEM
, ch
->board
->port
);
281 static inline void rxwinon(struct channel
*ch
)
284 outb_p(FEPMEM
, ch
->board
->port
);
286 outb_p(ch
->rxwin
, ch
->board
->port
+1);
289 static inline void txwinon(struct channel
*ch
)
292 outb_p(FEPMEM
, ch
->board
->port
);
294 outb_p(ch
->txwin
, ch
->board
->port
+1);
297 static inline void memoff(struct channel
*ch
)
299 outb_p(0, ch
->board
->port
);
300 if(ch
->board
->type
== PCXEVE
)
301 outb_p(0, ch
->board
->port
+1);
304 static inline void assertgwinon(struct channel
*ch
)
306 if(ch
->board
->type
!= PCXEVE
)
307 pcxxassert(inb(ch
->board
->port
) & FEPMEM
, "Global memory off");
310 static inline void assertmemoff(struct channel
*ch
)
312 if(ch
->board
->type
!= PCXEVE
)
313 pcxxassert(!(inb(ch
->board
->port
) & FEPMEM
), "Memory on");
316 static inline void pcxe_sched_event(struct channel
*info
, int event
)
318 info
->event
|= 1 << event
;
319 queue_task(&info
->tqueue
, &tq_pcxx
);
323 static void pcxx_error(int line
, char *msg
)
325 printk("pcxx_error (DigiBoard): line=%d %s\n", line
, msg
);
328 static int pcxx_waitcarrier(struct tty_struct
*tty
,struct file
*filp
,struct channel
*info
)
330 DECLARE_WAITQUEUE(wait
, current
);
334 if (info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
335 if (info
->normal_termios
.c_cflag
& CLOCAL
)
338 if (tty
->termios
->c_cflag
& CLOCAL
)
343 * Block waiting for the carrier detect and the line to become free
347 add_wait_queue(&info
->open_wait
, &wait
);
349 info
->blocked_open
++;
353 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0) {
355 info
->omodem
|= DTR
|RTS
;
356 fepcmd(info
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
360 set_current_state(TASK_INTERRUPTIBLE
);
361 if(tty_hung_up_p(filp
) || (info
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
362 if(info
->asyncflags
& ASYNC_HUP_NOTIFY
)
365 retval
= -ERESTARTSYS
;
368 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0 &&
369 (info
->asyncflags
& ASYNC_CLOSING
) == 0 &&
370 (do_clocal
|| (info
->imodem
& info
->dcd
)))
372 if(signal_pending(current
)) {
373 retval
= -ERESTARTSYS
;
378 current
->state
= TASK_RUNNING
;
379 remove_wait_queue(&info
->open_wait
, &wait
);
381 if(!tty_hung_up_p(filp
))
383 info
->blocked_open
--;
389 int pcxe_open(struct tty_struct
*tty
, struct file
* filp
)
391 volatile struct board_chan
*bc
;
398 line
= MINOR(tty
->device
) - tty
->driver
.minor_start
;
400 if(line
< 0 || line
>= nbdevs
) {
401 printk("line out of range in pcxe_open\n");
402 tty
->driver_data
= NULL
;
406 for(boardnum
=0;boardnum
<numcards
;boardnum
++)
407 if ((line
>= boards
[boardnum
].first_minor
) &&
408 (line
< boards
[boardnum
].first_minor
+ boards
[boardnum
].numports
))
411 if(boardnum
>= numcards
|| boards
[boardnum
].status
== DISABLED
||
412 (line
- boards
[boardnum
].first_minor
) >= boards
[boardnum
].numports
) {
413 tty
->driver_data
= NULL
; /* Mark this device as 'down' */
417 ch
= digi_channels
+line
;
419 if(ch
->brdchan
== 0) {
420 tty
->driver_data
= NULL
;
424 /* flag the kernel that there is somebody using this guy */
427 * If the device is in the middle of being closed, then block
428 * until it's done, and then try again.
430 if(ch
->asyncflags
& ASYNC_CLOSING
) {
431 interruptible_sleep_on(&ch
->close_wait
);
432 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
441 tty
->driver_data
= ch
;
444 if ((ch
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
450 ch
->imodem
= bc
->mstat
;
455 ch
->imodem
= bc
->mstat
;
457 ch
->omodem
= DTR
|RTS
;
458 fepcmd(ch
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
460 ch
->asyncflags
|= ASYNC_INITIALIZED
;
462 restore_flags(flags
);
464 if(ch
->asyncflags
& ASYNC_CLOSING
) {
465 interruptible_sleep_on(&ch
->close_wait
);
466 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
472 * If this is a callout device, then just make sure the normal
473 * device isn't being used.
475 if (tty
->driver
.subtype
== SERIAL_TYPE_CALLOUT
) {
476 if (ch
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
478 if (ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
479 if ((ch
->asyncflags
& ASYNC_SESSION_LOCKOUT
) &&
480 (ch
->session
!= current
->session
))
482 if((ch
->asyncflags
& ASYNC_PGRP_LOCKOUT
) &&
483 (ch
->pgrp
!= current
->pgrp
))
486 ch
->asyncflags
|= ASYNC_CALLOUT_ACTIVE
;
489 if (filp
->f_flags
& O_NONBLOCK
) {
490 if(ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
494 /* this has to be set in order for the "block until
495 * CD" code to work correctly. i'm not sure under
496 * what circumstances asyncflags should be set to
497 * ASYNC_NORMAL_ACTIVE though
500 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
501 if ((retval
= pcxx_waitcarrier(tty
, filp
, ch
)) != 0)
504 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
509 if((ch
->count
== 1) && (ch
->asyncflags
& ASYNC_SPLIT_TERMIOS
)) {
510 if(tty
->driver
.subtype
== SERIAL_TYPE_NORMAL
)
511 *tty
->termios
= ch
->normal_termios
;
513 *tty
->termios
= ch
->callout_termios
;
519 ch
->session
= current
->session
;
520 ch
->pgrp
= current
->pgrp
;
521 restore_flags(flags
);
525 static void shutdown(struct channel
*info
)
528 volatile struct board_chan
*bc
;
529 struct tty_struct
*tty
;
531 if (!(info
->asyncflags
& ASYNC_INITIALIZED
))
545 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
547 if(tty
->termios
->c_cflag
& HUPCL
) {
548 info
->omodem
&= ~(RTS
|DTR
);
549 fepcmd(info
, SETMODEM
, 0, DTR
|RTS
, 10, 1);
553 info
->asyncflags
&= ~ASYNC_INITIALIZED
;
554 restore_flags(flags
);
558 static void pcxe_close(struct tty_struct
* tty
, struct file
* filp
)
560 struct channel
*info
;
562 if ((info
=chan(tty
))!=NULL
) {
567 if(tty_hung_up_p(filp
)) {
568 /* flag that somebody is done with this module */
570 restore_flags(flags
);
573 /* this check is in serial.c, it won't hurt to do it here too */
574 if ((tty
->count
== 1) && (info
->count
!= 1)) {
576 * Uh, oh. tty->count is 1, which means that the tty
577 * structure will be freed. Info->count should always
578 * be one in these conditions. If it's greater than
579 * one, we've got real problems, since it means the
580 * serial port won't be shutdown.
582 printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info
->count
);
585 if (info
->count
-- > 1) {
586 restore_flags(flags
);
590 if (info
->count
< 0) {
594 info
->asyncflags
|= ASYNC_CLOSING
;
597 * Save the termios structure, since this port may have
598 * separate termios for callout and dialin.
600 if(info
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
601 info
->normal_termios
= *tty
->termios
;
602 if(info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
603 info
->callout_termios
= *tty
->termios
;
605 if(info
->asyncflags
& ASYNC_INITIALIZED
) {
606 setup_empty_event(tty
,info
);
607 tty_wait_until_sent(tty
, 3000); /* 30 seconds timeout */
610 if(tty
->driver
.flush_buffer
)
611 tty
->driver
.flush_buffer(tty
);
612 if(tty
->ldisc
.flush_buffer
)
613 tty
->ldisc
.flush_buffer(tty
);
619 /* ldiscs[] is not available in a MODULE
620 ** worth noting that while I'm not sure what this hunk of code is supposed
621 ** to do, it is not present in the serial.c driver. Hmmm. If you know,
622 ** please send me a note. brian@ilinx.com
623 ** Don't know either what this is supposed to do clameter@waterf.org.
625 if(tty
->ldisc
.num
!= ldiscs
[N_TTY
].num
) {
627 (tty
->ldisc
.close
)(tty
);
628 tty
->ldisc
= ldiscs
[N_TTY
];
629 tty
->termios
->c_line
= N_TTY
;
631 (tty
->ldisc
.open
)(tty
);
634 if(info
->blocked_open
) {
635 if(info
->close_delay
) {
636 current
->state
= TASK_INTERRUPTIBLE
;
637 schedule_timeout(info
->close_delay
);
639 wake_up_interruptible(&info
->open_wait
);
641 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|
642 ASYNC_CALLOUT_ACTIVE
|ASYNC_CLOSING
);
643 wake_up_interruptible(&info
->close_wait
);
645 restore_flags(flags
);
650 void pcxe_hangup(struct tty_struct
*tty
)
654 if ((ch
=chan(tty
))!=NULL
) {
663 ch
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
664 wake_up_interruptible(&ch
->open_wait
);
665 restore_flags(flags
);
671 static int pcxe_write(struct tty_struct
* tty
, int from_user
, const unsigned char *buf
, int count
)
674 volatile struct board_chan
*bc
;
675 int total
, remain
, size
, stlen
;
676 unsigned int head
, tail
;
679 /* printk("Entering pcxe_write()\n"); */
681 if ((ch
=chan(tty
))==NULL
)
685 size
= ch
->txbufsize
;
692 head
= bc
->tin
& (size
- 1);
693 /* It seems to be necessary to make sure that the value is stable here somehow
694 This is a rather odd pice of code here. */
697 } while (tail
!= bc
->tout
);
700 stlen
= (head
>= tail
) ? (size
- (head
- tail
) - 1) : (tail
- head
- 1);
701 count
= MIN(stlen
, count
);
703 if (verify_area(VERIFY_READ
, (char*)buf
, count
))
705 else copy_from_user(ch
->tmp_buf
, buf
, count
);
709 restore_flags(flags
);
713 * All data is now local
720 head
= bc
->tin
& (size
- 1);
722 if (tail
!= bc
->tout
)
726 remain
= size
- (head
- tail
) - 1;
730 remain
= tail
- head
- 1;
733 count
= MIN(remain
, count
);
737 stlen
= MIN(count
, stlen
);
738 memcpy(ch
->txptr
+ head
, buf
, stlen
);
748 ch
->statusflags
|= TXBUSY
;
751 if ((ch
->statusflags
& LOWWAIT
) == 0) {
752 ch
->statusflags
|= LOWWAIT
;
756 restore_flags(flags
);
762 static void pcxe_put_char(struct tty_struct
*tty
, unsigned char c
)
764 pcxe_write(tty
, 0, &c
, 1);
769 static int pcxe_write_room(struct tty_struct
*tty
)
775 if ((ch
=chan(tty
))!=NULL
) {
776 volatile struct board_chan
*bc
;
777 unsigned int head
, tail
;
785 head
= bc
->tin
& (ch
->txbufsize
- 1);
787 if (tail
!= bc
->tout
)
789 tail
&= (ch
->txbufsize
- 1);
791 if((remain
= tail
- head
- 1) < 0 )
792 remain
+= ch
->txbufsize
;
794 if (remain
&& (ch
->statusflags
& LOWWAIT
) == 0) {
795 ch
->statusflags
|= LOWWAIT
;
799 restore_flags(flags
);
806 static int pcxe_chars_in_buffer(struct tty_struct
*tty
)
809 unsigned int ctail
, head
, tail
;
813 volatile struct board_chan
*bc
;
815 if ((ch
=chan(tty
))==NULL
)
825 ctail
= ch
->mailbox
->cout
;
826 if(tail
== head
&& ch
->mailbox
->cin
== ctail
&& bc
->tbusy
== 0)
829 head
= bc
->tin
& (ch
->txbufsize
- 1);
830 tail
&= (ch
->txbufsize
- 1);
831 if((remain
= tail
- head
- 1) < 0 )
832 remain
+= ch
->txbufsize
;
834 chars
= (int)(ch
->txbufsize
- remain
);
837 * Make it possible to wakeup anything waiting for output
838 * in tty_ioctl.c, etc.
840 if(!(ch
->statusflags
& EMPTYWAIT
))
841 setup_empty_event(tty
,ch
);
845 restore_flags(flags
);
851 static void pcxe_flush_buffer(struct tty_struct
*tty
)
854 volatile struct board_chan
*bc
;
858 if ((ch
=chan(tty
))==NULL
)
867 fepcmd(ch
, STOUT
, (unsigned) tail
, 0, 0, 0);
870 restore_flags(flags
);
872 wake_up_interruptible(&tty
->write_wait
);
873 if((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) && tty
->ldisc
.write_wakeup
)
874 (tty
->ldisc
.write_wakeup
)(tty
);
877 static void pcxe_flush_chars(struct tty_struct
*tty
)
881 if ((ch
=chan(tty
))!=NULL
) {
886 if ((ch
->statusflags
& TXBUSY
) && !(ch
->statusflags
& EMPTYWAIT
))
887 setup_empty_event(tty
,ch
);
888 restore_flags(flags
);
895 * Driver setup function when linked into the kernel to optionally parse multible
896 * "digi="-lines and initialize the driver at boot time. No probing.
898 void __init
pcxx_setup(char *str
, int *ints
)
901 struct board_info board
;
908 memset(&board
, 0, sizeof(board
));
910 for(last
=0,i
=1;i
<=ints
[0];i
++)
914 board
.status
= ints
[i
];
919 board
.type
= ints
[i
];
924 board
.altpin
= ints
[i
];
929 board
.numports
= ints
[i
];
934 board
.port
= ints
[i
];
939 board
.membase
= ints
[i
];
944 printk("PC/Xx: Too many integer parms\n");
950 /* find the next comma or terminator */
952 while (*temp
&& (*temp
!= ','))
966 if (strncmp("Disable", str
, len
) == 0)
969 if (strncmp("Enable", str
, len
) == 0)
973 printk("PC/Xx: Invalid status %s\n", str
);
980 for(j
=0;j
<PCXX_NUM_TYPES
;j
++)
981 if (strcmp(board_desc
[j
], str
) == 0)
984 if (i
<PCXX_NUM_TYPES
)
988 printk("PC/Xx: Invalid board name: %s\n", str
);
996 if (strncmp("Disable", str
, len
) == 0)
999 if (strncmp("Enable", str
, len
) == 0)
1003 printk("PC/Xx: Invalid altpin %s\n", str
);
1011 while (isdigit(*t2
))
1016 printk("PC/Xx: Invalid port count %s\n", str
);
1020 board
.numports
= simple_strtoul(str
, NULL
, 0);
1026 while (isxdigit(*t2
))
1031 printk("PC/Xx: Invalid io port address %s\n", str
);
1035 board
.port
= simple_strtoul(str
, NULL
, 16);
1041 while (isxdigit(*t2
))
1046 printk("PC/Xx: Invalid memory base %s\n", str
);
1050 board
.membase
= simple_strtoul(str
, NULL
, 16);
1055 printk("PC/Xx: Too many string parms\n");
1063 printk("PC/Xx: Insufficient parms specified\n");
1067 /* I should REALLY validate the stuff here */
1069 memcpy(&boards
[numcards
],&board
, sizeof(board
));
1070 printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n",
1071 numcards
, board_desc
[board
.type
], board_mem
[board
.type
],
1072 board
.numports
, board
.port
, (unsigned int) board
.membase
);
1074 /* keep track of my initial minor number */
1076 boards
[numcards
].first_minor
= boards
[numcards
-1].first_minor
+ boards
[numcards
-1].numports
;
1078 boards
[numcards
].first_minor
= 0;
1080 /* yeha! string parameter was successful! */
1086 * function to initialize the driver with the given parameters, which are either
1087 * the default values from this file or the parameters given at boot.
1089 int __init
pcxe_init(void)
1091 ulong memory_seg
=0, memory_size
=0;
1092 int lowwater
, enabled_cards
=0, i
, crd
, shrinkmem
=0, topwin
= 0xff00L
, botwin
=0x100L
;
1093 unchar
*fepos
, *memaddr
, *bios
, v
;
1094 volatile struct global_data
*gd
;
1095 volatile struct board_chan
*bc
;
1096 struct board_info
*bd
;
1099 printk(KERN_NOTICE
"Digiboard PC/X{i,e,eve} driver v%s\n", VERSION
);
1102 for (i
= 0; i
< 4; i
++) {
1108 if (numcards
== 0) {
1109 int first_minor
= 0;
1111 for (i
= 0; i
< 4; i
++) {
1114 boards
[i
].status
= DISABLED
;
1117 boards
[i
].port
= (ushort
)io
[i
];
1118 boards
[i
].status
= ENABLED
;
1119 boards
[i
].first_minor
= first_minor
;
1123 boards
[i
].membase
= (ulong
)membase
[i
];
1125 boards
[i
].membase
= 0xD0000;
1128 boards
[i
].memsize
= (ulong
)(memsize
[i
] * 1024);
1130 boards
[i
].memsize
= 0;
1133 boards
[i
].altpin
= ON
;
1135 boards
[i
].altpin
= OFF
;
1138 boards
[i
].numports
= (ushort
)numports
[i
];
1140 boards
[i
].numports
= 16;
1142 first_minor
+= boards
[i
].numports
;
1149 printk("PC/Xx: No cards configured, driver not active.\n");
1154 for (i
= 0; i
< numcards
; i
++) {
1155 printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",
1163 boards
[i
].first_minor
);
1167 for (i
=0;i
<numcards
;i
++)
1168 nbdevs
+= boards
[i
].numports
;
1172 printk("PC/Xx: No devices activated, driver not active.\n");
1177 * this turns out to be more memory efficient, as there are no
1180 digi_channels
= kmalloc(sizeof(struct channel
) * nbdevs
, GFP_KERNEL
);
1182 panic("Unable to allocate digi_channel struct");
1183 memset(digi_channels
, 0, sizeof(struct channel
) * nbdevs
);
1185 pcxe_table
= kmalloc(sizeof(struct tty_struct
*) * nbdevs
, GFP_KERNEL
);
1187 panic("Unable to allocate pcxe_table struct");
1188 memset(pcxe_table
, 0, sizeof(struct tty_struct
*) * nbdevs
);
1190 pcxe_termios
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1192 panic("Unable to allocate pcxe_termios struct");
1193 memset(pcxe_termios
,0,sizeof(struct termios
*)*nbdevs
);
1195 pcxe_termios_locked
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1196 if (!pcxe_termios_locked
)
1197 panic("Unable to allocate pcxe_termios_locked struct");
1198 memset(pcxe_termios_locked
,0,sizeof(struct termios
*)*nbdevs
);
1200 init_bh(DIGI_BH
,do_pcxe_bh
);
1203 timer_table
[DIGI_TIMER
].fn
= pcxxpoll
;
1204 timer_table
[DIGI_TIMER
].expires
= 0;
1206 memset(&pcxe_driver
, 0, sizeof(struct tty_driver
));
1207 pcxe_driver
.magic
= TTY_DRIVER_MAGIC
;
1208 pcxe_driver
.name
= "ttyD";
1209 pcxe_driver
.major
= DIGI_MAJOR
;
1210 pcxe_driver
.minor_start
= 0;
1212 pcxe_driver
.num
= nbdevs
;
1214 pcxe_driver
.type
= TTY_DRIVER_TYPE_SERIAL
;
1215 pcxe_driver
.subtype
= SERIAL_TYPE_NORMAL
;
1216 pcxe_driver
.init_termios
= tty_std_termios
;
1217 pcxe_driver
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
;
1218 pcxe_driver
.flags
= TTY_DRIVER_REAL_RAW
;
1219 pcxe_driver
.refcount
= &pcxe_refcount
;
1221 pcxe_driver
.table
= pcxe_table
;
1222 pcxe_driver
.termios
= pcxe_termios
;
1223 pcxe_driver
.termios_locked
= pcxe_termios_locked
;
1225 pcxe_driver
.open
= pcxe_open
;
1226 pcxe_driver
.close
= pcxe_close
;
1227 pcxe_driver
.write
= pcxe_write
;
1228 pcxe_driver
.put_char
= pcxe_put_char
;
1229 pcxe_driver
.flush_chars
= pcxe_flush_chars
;
1230 pcxe_driver
.write_room
= pcxe_write_room
;
1231 pcxe_driver
.chars_in_buffer
= pcxe_chars_in_buffer
;
1232 pcxe_driver
.flush_buffer
= pcxe_flush_buffer
;
1233 pcxe_driver
.ioctl
= pcxe_ioctl
;
1234 pcxe_driver
.throttle
= pcxe_throttle
;
1235 pcxe_driver
.unthrottle
= pcxe_unthrottle
;
1236 pcxe_driver
.set_termios
= pcxe_set_termios
;
1237 pcxe_driver
.stop
= pcxe_stop
;
1238 pcxe_driver
.start
= pcxe_start
;
1239 pcxe_driver
.hangup
= pcxe_hangup
;
1241 pcxe_callout
= pcxe_driver
;
1242 pcxe_callout
.name
= "cud";
1243 pcxe_callout
.major
= DIGICU_MAJOR
;
1244 pcxe_callout
.subtype
= SERIAL_TYPE_CALLOUT
;
1245 pcxe_callout
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
| CLOCAL
;
1247 for(crd
=0; crd
< numcards
; crd
++) {
1249 outb(FEPRST
, bd
->port
);
1252 for(i
=0; (inb(bd
->port
) & FEPMASK
) != FEPRST
; i
++) {
1254 printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
1256 bd
->status
= DISABLED
;
1264 if(bd
->status
== DISABLED
)
1269 if((v
& 0x1) == 0x1) {
1270 if((v
& 0x30) == 0) { /* PC/Xi 64K card */
1271 memory_seg
= 0xf000;
1272 memory_size
= 0x10000;
1275 if((v
& 0x30) == 0x10) { /* PC/Xi 128K card */
1276 memory_seg
= 0xe000;
1277 memory_size
= 0x20000;
1280 if((v
& 0x30) == 0x20) { /* PC/Xi 256K card */
1281 memory_seg
= 0xc000;
1282 memory_size
= 0x40000;
1285 if((v
& 0x30) == 0x30) { /* PC/Xi 512K card */
1286 memory_seg
= 0x8000;
1287 memory_size
= 0x80000;
1291 if((v
& 0x1) == 0x1) {
1292 bd
->status
= DISABLED
; /* PC/Xm unsupported card */
1293 printk("PC/Xx: PC/Xm at 0x%x not supported!!\n", bd
->port
);
1298 outb((((ulong
)bd
->membase
>>8) & 0xe0) | 0x10, bd
->port
+2);
1299 outb(((ulong
)bd
->membase
>>16) & 0xff, bd
->port
+3);
1300 bd
->type
= PCXEVE
; /* PC/Xe 8K card */
1302 bd
->type
= PCXE
; /* PC/Xe 64K card */
1305 memory_seg
= 0xf000;
1306 memory_size
= 0x10000;
1310 printk("Configuring card %d as a %s %ldK card. io=0x%x, mem=%lx-%lx\n",
1311 crd
+1, board_desc
[bd
->type
], memory_size
/1024,
1312 bd
->port
,bd
->membase
,bd
->membase
+memory_size
-1);
1314 if (boards
[crd
].memsize
== 0)
1315 boards
[crd
].memsize
= memory_size
;
1317 if (boards
[crd
].memsize
!= memory_size
) {
1318 printk("PC/Xx: memory size mismatch:supplied=%lx(%ldK) probed=%ld(%ldK)\n",
1319 boards
[crd
].memsize
, boards
[crd
].memsize
/ 1024,
1320 memory_size
, memory_size
/ 1024);
1324 memaddr
= (unchar
*)phys_to_virt(bd
->membase
);
1327 printk("Resetting board and testing memory access:");
1329 outb(FEPRST
|FEPMEM
, bd
->port
);
1331 for(i
=0; (inb(bd
->port
) & FEPMASK
) != (FEPRST
|FEPMEM
); i
++) {
1333 printk("\nPC/Xx: %s not resetting at port 0x%x! Check switch settings.\n",
1334 board_desc
[bd
->type
], bd
->port
);
1335 bd
->status
= DISABLED
;
1343 if(bd
->status
== DISABLED
)
1347 *(ulong
*)(memaddr
+ botwin
) = 0xa55a3cc3;
1348 *(ulong
*)(memaddr
+ topwin
) = 0x5aa5c33c;
1350 if(*(ulong
*)(memaddr
+ botwin
) != 0xa55a3cc3 ||
1351 *(ulong
*)(memaddr
+ topwin
) != 0x5aa5c33c) {
1352 printk("PC/Xx: Failed memory test at %lx for %s at port %x, check switch settings.\n",
1353 bd
->membase
, board_desc
[bd
->type
], bd
->port
);
1354 bd
->status
= DISABLED
;
1360 for(i
=0; i
< 16; i
++) {
1361 memaddr
[MISCGLOBAL
+i
] = 0;
1364 if(bd
->type
== PCXI
|| bd
->type
== PCXE
) {
1365 bios
= memaddr
+ BIOSCODE
+ ((0xf000 - memory_seg
) << 4);
1368 printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios
));
1370 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1375 outb(FEPMEM
, bd
->port
);
1378 printk("Waiting for BIOS to become ready");
1380 for(i
=1; i
<= 30; i
++) {
1381 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1395 printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n",
1396 bd
->port
, bd
->membase
, bd
->membase
+bd
->memsize
);
1397 bd
->status
= DISABLED
;
1401 if(bd
->type
== PCXEVE
) {
1402 bios
= memaddr
+ (BIOSCODE
& 0x1fff);
1405 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1407 outb(FEPCLR
, bd
->port
);
1410 for(i
=0; i
<= 1000; i
++) {
1411 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1425 printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n",
1426 board_desc
[bd
->type
], bd
->port
);
1427 bd
->status
= DISABLED
;
1432 fepos
= memaddr
+ FEPCODE
;
1433 if(bd
->type
== PCXEVE
)
1434 fepos
= memaddr
+ (FEPCODE
& 0x1fff);
1437 printk(" ok.\nDownloading FEP/OS to 0x%lx:", virt_to_phys(fepos
));
1439 memwinon(bd
, (FEPCODE
>> 13));
1440 memcpy(fepos
, pcxx_cook
, pcxx_ncook
);
1446 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 0) = 2;
1447 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 2) = memory_seg
+ FEPCODESEG
;
1448 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 4) = 0;
1449 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 6) = FEPCODESEG
;
1450 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 8) = 0;
1451 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 10) = pcxx_ncook
;
1453 outb(FEPMEM
|FEPINT
, bd
->port
);
1454 outb(FEPMEM
, bd
->port
);
1456 for(i
=0; *(ushort
*)((ulong
)memaddr
+ MBOX
); i
++) {
1458 printk("PC/Xx: Command failed for the %s at 0x%x!\n",
1459 board_desc
[bd
->type
], bd
->port
);
1460 bd
->status
= DISABLED
;
1469 if(bd
->status
== DISABLED
)
1473 printk("Waiting for FEP/OS to become ready");
1475 *(ushort
*)(memaddr
+ FEPSTAT
) = 0;
1476 *(ushort
*)(memaddr
+ MBOX
+ 0) = 1;
1477 *(ushort
*)(memaddr
+ MBOX
+ 2) = FEPCODESEG
;
1478 *(ushort
*)(memaddr
+ MBOX
+ 4) = 0x4L
;
1480 outb(FEPINT
, bd
->port
);
1481 outb(FEPCLR
, bd
->port
);
1484 for(i
=1; *(ushort
*)((ulong
)memaddr
+ FEPSTAT
) != *(ushort
*)"OS"; i
++) {
1486 printk("\nPC/Xx: FEP/OS download failed on the %s at 0x%x!\n",
1487 board_desc
[bd
->type
], bd
->port
);
1488 bd
->status
= DISABLED
;
1494 printk("\n%5d",i
/50);
1501 if(bd
->status
== DISABLED
)
1507 ch
= digi_channels
+bd
->first_minor
;
1508 pcxxassert(ch
< digi_channels
+nbdevs
, "ch out of range");
1510 bc
= (volatile struct board_chan
*)((ulong
)memaddr
+ CHANSTRUCT
);
1511 gd
= (volatile struct global_data
*)((ulong
)memaddr
+ GLOBAL
);
1513 if((bd
->type
== PCXEVE
) && (*(ushort
*)((ulong
)memaddr
+NPORT
) < 3))
1516 request_region(bd
->port
, 4, "PC/Xx");
1518 for(i
=0; i
< bd
->numports
; i
++, ch
++, bc
++) {
1519 if(((ushort
*)((ulong
)memaddr
+ PORTBASE
))[i
] == 0) {
1525 ch
->tqueue
.routine
= do_softint
;
1526 ch
->tqueue
.data
= ch
;
1527 ch
->board
= &boards
[crd
];
1528 #ifdef DEFAULT_HW_FLOW
1529 ch
->digiext
.digi_flags
= RTSPACE
|CTSPACE
;
1531 if(boards
[crd
].altpin
) {
1534 ch
->digiext
.digi_flags
|= DIGI_ALTPIN
;
1540 ch
->magic
= PCXX_MAGIC
;
1544 ch
->dev
= bd
->first_minor
+ i
;
1548 fepcmd(ch
, SETBUFFER
, 32, 0, 0, 0);
1552 if(bd
->type
!= PCXEVE
) {
1553 ch
->txptr
= memaddr
+((bc
->tseg
-memory_seg
) << 4);
1554 ch
->rxptr
= memaddr
+((bc
->rseg
-memory_seg
) << 4);
1555 ch
->txwin
= ch
->rxwin
= 0;
1557 ch
->txptr
= memaddr
+(((bc
->tseg
-memory_seg
) << 4) & 0x1fff);
1558 ch
->txwin
= FEPWIN
| ((bc
->tseg
-memory_seg
) >> 9);
1559 ch
->rxptr
= memaddr
+(((bc
->rseg
-memory_seg
) << 4) & 0x1fff);
1560 ch
->rxwin
= FEPWIN
| ((bc
->rseg
-memory_seg
) >>9 );
1563 ch
->txbufsize
= bc
->tmax
+ 1;
1564 ch
->rxbufsize
= bc
->rmax
+ 1;
1565 ch
->tmp_buf
= kmalloc(ch
->txbufsize
,GFP_KERNEL
);
1566 lowwater
= ch
->txbufsize
>= 2000 ? 1024 : ch
->txbufsize
/2;
1567 fepcmd(ch
, STXLWATER
, lowwater
, 0, 10, 0);
1568 fepcmd(ch
, SRXLWATER
, ch
->rxbufsize
/4, 0, 10, 0);
1569 fepcmd(ch
, SRXHWATER
, 3 * ch
->rxbufsize
/4, 0, 10, 0);
1574 ch
->startc
= bc
->startc
;
1575 ch
->stopc
= bc
->stopc
;
1576 ch
->startca
= bc
->startca
;
1577 ch
->stopca
= bc
->stopca
;
1587 ch
->close_delay
= 50;
1589 ch
->blocked_open
= 0;
1590 ch
->callout_termios
= pcxe_callout
.init_termios
;
1591 ch
->normal_termios
= pcxe_driver
.init_termios
;
1592 init_waitqueue_head(ch
->open_wait
);
1593 init_waitqueue_head(ch
->close_wait
);
1598 printk("Card No. %d ready: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1599 crd
+1, board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1600 bd
->membase
, bd
->numports
);
1602 printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1603 board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1604 bd
->membase
, bd
->numports
);
1610 if (enabled_cards
<= 0) {
1611 printk(KERN_NOTICE
"PC/Xx: No cards enabled, no driver.\n");
1615 if(tty_register_driver(&pcxe_driver
))
1616 panic("Couldn't register PC/Xe driver");
1618 if(tty_register_driver(&pcxe_callout
))
1619 panic("Couldn't register PC/Xe callout");
1622 * Start up the poller to check for events on all enabled boards
1624 timer_active
|= 1 << DIGI_TIMER
;
1627 printk(KERN_NOTICE
"PC/Xx: Driver with %d card(s) ready.\n", enabled_cards
);
1633 static void pcxxpoll(void)
1635 unsigned long flags
;
1637 volatile unsigned int head
, tail
;
1639 struct board_info
*bd
;
1644 for(crd
=0; crd
< numcards
; crd
++) {
1647 ch
= digi_channels
+bd
->first_minor
;
1649 if(bd
->status
== DISABLED
)
1655 head
= ch
->mailbox
->ein
;
1656 tail
= ch
->mailbox
->eout
;
1664 timer_table
[DIGI_TIMER
].fn
= pcxxpoll
;
1665 timer_table
[DIGI_TIMER
].expires
= jiffies
+ HZ
/25;
1666 timer_active
|= 1 << DIGI_TIMER
;
1667 restore_flags(flags
);
1670 static void doevent(int crd
)
1672 volatile struct board_info
*bd
;
1673 static struct tty_struct
*tty
;
1674 volatile struct board_chan
*bc
;
1675 volatile unchar
*eventbuf
;
1676 volatile unsigned int head
;
1677 volatile unsigned int tail
;
1679 struct channel
*chan0
;
1680 int channel
, event
, mstat
, lstat
;
1684 chan0
= digi_channels
+bd
->first_minor
;
1685 pcxxassert(chan0
< digi_channels
+nbdevs
, "ch out of range");
1688 assertgwinon(chan0
);
1690 while ((tail
= chan0
->mailbox
->eout
) != (head
= chan0
->mailbox
->ein
)) {
1691 assertgwinon(chan0
);
1692 eventbuf
= (volatile unchar
*)phys_to_virt(bd
->membase
+ tail
+ ISTART
);
1693 channel
= eventbuf
[0];
1694 event
= eventbuf
[1];
1695 mstat
= eventbuf
[2];
1696 lstat
= eventbuf
[3];
1700 if ((unsigned)channel
>= bd
->numports
|| !ch
) {
1701 printk("physmem=%lx, tail=%x, head=%x\n", bd
->membase
, tail
, head
);
1702 printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
1703 crd
, (unsigned)channel
, event
, (unsigned)mstat
, lstat
);
1704 if(channel
>= bd
->numports
)
1709 if ((bc
= ch
->brdchan
) == NULL
)
1712 if (event
& DATA_IND
) {
1717 if (event
& MODEMCHG_IND
) {
1719 if (ch
->asyncflags
& (ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
)) {
1720 if (ch
->asyncflags
& ASYNC_CHECK_CD
) {
1721 if (mstat
& ch
->dcd
) {
1722 wake_up_interruptible(&ch
->open_wait
);
1724 pcxe_sched_event(ch
, PCXE_EVENT_HANGUP
);
1734 if (event
& BREAK_IND
) {
1736 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
1737 *tty
->flip
.char_buf_ptr
++ = 0;
1739 if (ch
->asyncflags
& ASYNC_SAK
)
1742 tty_schedule_flip(tty
);
1745 if (event
& LOWTX_IND
) {
1746 if (ch
->statusflags
& LOWWAIT
) {
1747 ch
->statusflags
&= ~LOWWAIT
;
1748 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1749 tty
->ldisc
.write_wakeup
)
1750 (tty
->ldisc
.write_wakeup
)(tty
);
1751 wake_up_interruptible(&tty
->write_wait
);
1755 if (event
& EMPTYTX_IND
) {
1756 ch
->statusflags
&= ~TXBUSY
;
1757 if (ch
->statusflags
& EMPTYWAIT
) {
1758 ch
->statusflags
&= ~EMPTYWAIT
;
1759 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1760 tty
->ldisc
.write_wakeup
)
1761 (tty
->ldisc
.write_wakeup
)(tty
);
1762 wake_up_interruptible(&tty
->write_wait
);
1769 if(!bc
) printk("bc == NULL in doevent!\n");
1772 chan0
->mailbox
->eout
= (tail
+4) & (IMAX
-ISTART
-4);
1780 * pcxxdelay - delays a specified number of milliseconds
1782 static void pcxxdelay(int msec
)
1785 __delay(loops_per_sec
/1000);
1790 fepcmd(struct channel
*ch
, int cmd
, int word_or_byte
, int byte2
, int ncmds
,
1794 unsigned int head
, tail
;
1798 if(ch
->board
->status
== DISABLED
)
1803 memaddr
= (unchar
*)phys_to_virt(ch
->board
->membase
);
1804 head
= ch
->mailbox
->cin
;
1806 if(head
>= (CMAX
-CSTART
) || (head
& 03)) {
1807 printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__
, cmd
, head
);
1812 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1814 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1816 *(unchar
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1817 *(unchar
*)(memaddr
+head
+CSTART
+3) = byte2
;
1819 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1821 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1822 *(ushort
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1825 head
= (head
+4) & (CMAX
-CSTART
-4);
1826 ch
->mailbox
->cin
= head
;
1833 printk("Fep not responding in fepcmd()\n");
1837 head
= ch
->mailbox
->cin
;
1838 tail
= ch
->mailbox
->cout
;
1840 n
= (head
-tail
) & (CMAX
-CSTART
-4);
1842 if(n
<= ncmds
* (sizeof(short)*4))
1844 /* Seems not to be good here: schedule(); */
1849 static unsigned termios2digi_c(struct channel
*ch
, unsigned cflag
)
1853 /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
1854 if ((cflag
& CBAUD
)== B38400
) cflag
=cflag
- B38400
+ B115200
;
1855 if ((cflag
& CBAUD
)== B19200
) cflag
=cflag
- B19200
+ B57600
;
1857 if (cflag
& CBAUDEX
)
1859 ch
->digiext
.digi_flags
|= DIGI_FAST
;
1861 /* This gets strange but if we don't do this we will get 78600
1862 * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
1863 * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
1866 if (cflag
& B115200
) res
|=1;
1868 else ch
->digiext
.digi_flags
&= ~DIGI_FAST
;
1869 res
|= cflag
& (CBAUD
| PARODD
| PARENB
| CSTOPB
| CSIZE
| CLOCAL
);
1873 static unsigned termios2digi_i(struct channel
*ch
, unsigned iflag
)
1875 unsigned res
= iflag
& (IGNBRK
|BRKINT
|IGNPAR
|PARMRK
|INPCK
|ISTRIP
|IXON
|IXANY
|IXOFF
);
1877 if(ch
->digiext
.digi_flags
& DIGI_AIXON
)
1882 static unsigned termios2digi_h(struct channel
*ch
, unsigned cflag
)
1886 if(cflag
& CRTSCTS
) {
1887 ch
->digiext
.digi_flags
|= (RTSPACE
|CTSPACE
);
1890 if(ch
->digiext
.digi_flags
& RTSPACE
)
1892 if(ch
->digiext
.digi_flags
& DTRPACE
)
1894 if(ch
->digiext
.digi_flags
& CTSPACE
)
1896 if(ch
->digiext
.digi_flags
& DSRPACE
)
1898 if(ch
->digiext
.digi_flags
& DCDPACE
)
1902 ch
->digiext
.digi_flags
|= RTSPACE
;
1904 ch
->digiext
.digi_flags
|= CTSPACE
;
1909 static void pcxxparam(struct tty_struct
*tty
, struct channel
*ch
)
1911 volatile struct board_chan
*bc
;
1913 unsigned mval
, hflow
, cflag
, iflag
;
1920 if((ts
->c_cflag
& CBAUD
) == 0) {
1924 fepcmd(ch
, STOUT
, (unsigned) head
, 0, 0, 0);
1928 cflag
= termios2digi_c(ch
, ts
->c_cflag
);
1930 if(cflag
!= ch
->fepcflag
) {
1931 ch
->fepcflag
= cflag
;
1932 fepcmd(ch
, SETCTRLFLAGS
, (unsigned) cflag
, 0, 0, 0);
1936 ch
->asyncflags
&= ~ASYNC_CHECK_CD
;
1938 ch
->asyncflags
|= ASYNC_CHECK_CD
;
1944 iflag
= termios2digi_i(ch
, ts
->c_iflag
);
1946 if(iflag
!= ch
->fepiflag
) {
1947 ch
->fepiflag
= iflag
;
1948 fepcmd(ch
, SETIFLAGS
, (unsigned int) ch
->fepiflag
, 0, 0, 0);
1952 if((ts
->c_cflag
& CLOCAL
) || (ch
->digiext
.digi_flags
& DIGI_FORCEDCD
))
1953 if(ch
->digiext
.digi_flags
& DIGI_FORCEDCD
)
1956 ch
->imodem
= bc
->mstat
;
1958 hflow
= termios2digi_h(ch
, ts
->c_cflag
);
1960 if(hflow
!= ch
->hflow
) {
1962 fepcmd(ch
, SETHFLOW
, hflow
, 0xff, 0, 1);
1965 /* mval ^= ch->modemfake & (mval ^ ch->modem); */
1967 if(ch
->omodem
!= mval
) {
1969 fepcmd(ch
, SETMODEM
, mval
, RTS
|DTR
, 0, 1);
1972 if(ch
->startc
!= ch
->fepstartc
|| ch
->stopc
!= ch
->fepstopc
) {
1973 ch
->fepstartc
= ch
->startc
;
1974 ch
->fepstopc
= ch
->stopc
;
1975 fepcmd(ch
, SONOFFC
, ch
->fepstartc
, ch
->fepstopc
, 0, 1);
1978 if(ch
->startca
!= ch
->fepstartca
|| ch
->stopca
!= ch
->fepstopca
) {
1979 ch
->fepstartca
= ch
->startca
;
1980 ch
->fepstopca
= ch
->stopca
;
1981 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
1986 static void receive_data(struct channel
*ch
)
1988 volatile struct board_chan
*bc
;
1989 struct tty_struct
*tty
;
1990 unsigned int tail
, head
, wrapmask
;
1993 struct termios
*ts
=0;
2000 if (ch
->statusflags
& RXSTOPPED
)
2010 printk("bc is NULL in receive_data!\n");
2014 wrapmask
= ch
->rxbufsize
- 1;
2018 tail
= bc
->rout
& wrapmask
;
2020 n
= (head
-tail
) & wrapmask
;
2026 * If CREAD bit is off or device not open, set TX tail to head
2028 if(!tty
|| !ts
|| !(ts
->c_cflag
& CREAD
)) {
2033 if(tty
->flip
.count
== TTY_FLIPBUF_SIZE
) {
2034 /* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
2040 printk("overrun! DigiBoard device minor=%d\n",MINOR(tty
->device
));
2044 rptr
= tty
->flip
.char_buf_ptr
;
2045 rc
= tty
->flip
.count
;
2047 wrapgap
= (head
>= tail
) ? head
- tail
: ch
->rxbufsize
- tail
;
2048 piece
= (wrapgap
< n
) ? wrapgap
: n
;
2051 * Make sure we don't overflow the buffer
2054 if ((rc
+ piece
) > TTY_FLIPBUF_SIZE
)
2055 piece
= TTY_FLIPBUF_SIZE
- rc
;
2060 memcpy(rptr
, ch
->rxptr
+ tail
, piece
);
2063 tail
= (tail
+ piece
) & wrapmask
;
2066 tty
->flip
.count
= rc
;
2067 tty
->flip
.char_buf_ptr
= rptr
;
2071 /* Must be called with global data */
2072 tty_schedule_flip(ch
->tty
);
2077 static int pcxe_ioctl(struct tty_struct
*tty
, struct file
* file
,
2078 unsigned int cmd
, unsigned long arg
)
2081 struct channel
*ch
= (struct channel
*) tty
->driver_data
;
2082 volatile struct board_chan
*bc
;
2084 unsigned int mflag
, mstat
;
2085 unsigned char startc
, stopc
;
2086 unsigned long flags
;
2092 printk("ch is NULL in pcxe_ioctl!\n");
2099 case TCSBRK
: /* SVID version: non-zero arg --> no break */
2100 retval
= tty_check_change(tty
);
2103 setup_empty_event(tty
,ch
);
2104 tty_wait_until_sent(tty
, 0);
2106 digi_send_break(ch
, HZ
/4); /* 1/4 second */
2109 case TCSBRKP
: /* support for POSIX tcsendbreak() */
2110 retval
= tty_check_change(tty
);
2113 setup_empty_event(tty
,ch
);
2114 tty_wait_until_sent(tty
, 0);
2115 digi_send_break(ch
, arg
? arg
*(HZ
/10) : HZ
/4);
2119 return put_user(C_CLOCAL(tty
) ? 1 : 0,
2120 (unsigned int *) arg
);
2125 error
= get_user( value
, (unsigned int *) arg
);
2128 tty
->termios
->c_cflag
= ((tty
->termios
->c_cflag
& ~CLOCAL
) | (value
? CLOCAL
: 0));
2140 restore_flags(flags
);
2155 error
= put_user(mflag
, (unsigned int *) arg
);
2164 error
= get_user(mstat
, (unsigned int *) arg
);
2169 if(mstat
& TIOCM_DTR
)
2171 if(mstat
& TIOCM_RTS
)
2177 ch
->modemfake
= DTR
|RTS
;
2182 ch
->modemfake
|= mflag
;
2187 ch
->modemfake
&= ~mflag
;
2188 ch
->modem
&= ~mflag
;
2196 restore_flags(flags
);
2203 fepcmd(ch
, SETMODEM
, DTR
, 0, 10, 1);
2205 restore_flags(flags
);
2212 fepcmd(ch
, SETMODEM
, 0, DTR
, 10, 1);
2214 restore_flags(flags
);
2218 if((error
=verify_area(VERIFY_WRITE
, (char*)arg
, sizeof(digi_t
))))
2221 copy_to_user((char*)arg
, &ch
->digiext
, sizeof(digi_t
));
2226 if(cmd
== DIGI_SETAW
) {
2227 setup_empty_event(tty
,ch
);
2228 tty_wait_until_sent(tty
, 0);
2231 if(tty
->ldisc
.flush_buffer
)
2232 tty
->ldisc
.flush_buffer(tty
);
2238 if((error
=verify_area(VERIFY_READ
, (char*)arg
,sizeof(digi_t
))))
2241 copy_from_user(&ch
->digiext
, (char*)arg
, sizeof(digi_t
));
2243 printk("ioctl(DIGI_SETA): flags = %x\n", ch
->digiext
.digi_flags
);
2246 if(ch
->digiext
.digi_flags
& DIGI_ALTPIN
) {
2258 restore_flags(flags
);
2265 if(cmd
== DIGI_GETFLOW
) {
2266 dflow
.startc
= bc
->startc
;
2267 dflow
.stopc
= bc
->stopc
;
2269 dflow
.startc
= bc
->startca
;
2270 dflow
.stopc
= bc
->stopca
;
2273 restore_flags(flags
);
2275 if((error
=verify_area(VERIFY_WRITE
, (char*)arg
,sizeof(dflow
))))
2278 copy_to_user((char*)arg
, &dflow
, sizeof(dflow
));
2283 if(cmd
== DIGI_SETFLOW
) {
2284 startc
= ch
->startc
;
2287 startc
= ch
->startca
;
2291 if((error
=verify_area(VERIFY_READ
, (char*)arg
,sizeof(dflow
))))
2294 copy_from_user(&dflow
, (char*)arg
, sizeof(dflow
));
2296 if(dflow
.startc
!= startc
|| dflow
.stopc
!= stopc
) {
2300 if(cmd
== DIGI_SETFLOW
) {
2301 ch
->fepstartc
= ch
->startc
= dflow
.startc
;
2302 ch
->fepstopc
= ch
->stopc
= dflow
.stopc
;
2303 fepcmd(ch
,SONOFFC
,ch
->fepstartc
,ch
->fepstopc
,0, 1);
2305 ch
->fepstartca
= ch
->startca
= dflow
.startc
;
2306 ch
->fepstopca
= ch
->stopca
= dflow
.stopc
;
2307 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
2310 if(ch
->statusflags
& TXSTOPPED
)
2314 restore_flags(flags
);
2319 return -ENOIOCTLCMD
;
2325 static void pcxe_set_termios(struct tty_struct
*tty
, struct termios
*old_termios
)
2327 struct channel
*info
;
2329 if ((info
=chan(tty
))!=NULL
) {
2330 unsigned long flags
;
2334 pcxxparam(tty
,info
);
2337 if ((old_termios
->c_cflag
& CRTSCTS
) &&
2338 ((tty
->termios
->c_cflag
& CRTSCTS
) == 0))
2339 tty
->hw_stopped
= 0;
2340 if(!(old_termios
->c_cflag
& CLOCAL
) &&
2341 (tty
->termios
->c_cflag
& CLOCAL
))
2342 wake_up_interruptible(&info
->open_wait
);
2343 restore_flags(flags
);
2348 static void do_pcxe_bh(void)
2350 run_task_queue(&tq_pcxx
);
2354 static void do_softint(void *private_
)
2356 struct channel
*info
= (struct channel
*) private_
;
2358 if(info
&& info
->magic
== PCXX_MAGIC
) {
2359 struct tty_struct
*tty
= info
->tty
;
2360 if (tty
&& tty
->driver_data
) {
2361 if(test_and_clear_bit(PCXE_EVENT_HANGUP
, &info
->event
)) {
2363 wake_up_interruptible(&info
->open_wait
);
2364 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2371 static void pcxe_stop(struct tty_struct
*tty
)
2373 struct channel
*info
;
2375 if ((info
=chan(tty
))!=NULL
) {
2376 unsigned long flags
;
2379 if ((info
->statusflags
& TXSTOPPED
) == 0) {
2381 fepcmd(info
, PAUSETX
, 0, 0, 0, 0);
2382 info
->statusflags
|= TXSTOPPED
;
2385 restore_flags(flags
);
2389 static void pcxe_throttle(struct tty_struct
* tty
)
2391 struct channel
*info
;
2393 if ((info
=chan(tty
))!=NULL
) {
2394 unsigned long flags
;
2397 if ((info
->statusflags
& RXSTOPPED
) == 0) {
2399 fepcmd(info
, PAUSERX
, 0, 0, 0, 0);
2400 info
->statusflags
|= RXSTOPPED
;
2403 restore_flags(flags
);
2407 static void pcxe_unthrottle(struct tty_struct
*tty
)
2409 struct channel
*info
;
2411 if ((info
=chan(tty
)) != NULL
) {
2412 unsigned long flags
;
2414 /* Just in case output was resumed because of a change in Digi-flow */
2417 if(info
->statusflags
& RXSTOPPED
) {
2418 volatile struct board_chan
*bc
;
2421 fepcmd(info
, RESUMERX
, 0, 0, 0, 0);
2422 info
->statusflags
&= ~RXSTOPPED
;
2425 restore_flags(flags
);
2430 static void pcxe_start(struct tty_struct
*tty
)
2432 struct channel
*info
;
2434 if ((info
=chan(tty
))!=NULL
) {
2435 unsigned long flags
;
2439 /* Just in case output was resumed because of a change in Digi-flow */
2440 if(info
->statusflags
& TXSTOPPED
) {
2441 volatile struct board_chan
*bc
;
2444 if(info
->statusflags
& LOWWAIT
)
2446 fepcmd(info
, RESUMETX
, 0, 0, 0, 0);
2447 info
->statusflags
&= ~TXSTOPPED
;
2450 restore_flags(flags
);
2455 void digi_send_break(struct channel
*ch
, int msec
)
2457 unsigned long flags
;
2464 * Maybe I should send an infinite break here, schedule() for
2465 * msec amount of time, and then stop the break. This way,
2466 * the user can't screw up the FEP by causing digi_send_break()
2467 * to be called (i.e. via an ioctl()) more than once in msec amount
2468 * of time. Try this for now...
2471 fepcmd(ch
, SENDBREAK
, msec
, 0, 10, 0);
2474 restore_flags(flags
);
2477 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
)
2479 volatile struct board_chan
*bc
;
2480 unsigned long flags
;
2485 ch
->statusflags
|= EMPTYWAIT
;
2489 restore_flags(flags
);