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>
83 #define VERSION "1.6.1"
89 #include "digi_bios.h"
92 * Define one default setting if no digi= config line is used.
93 * Default is altpin = disabled, 16 ports, I/O 200h, Memory 0D0000h
95 static struct board_info boards
[MAX_DIGI_BOARDS
] = { {
96 /* Board is enabled */ ENABLED
,
97 /* Type is auto-detected */ 0,
98 /* altping is disabled */ DISABLED
,
99 /* number of ports = 16 */ 16,
100 /* io address is 0x200 */ 0x200,
101 /* card memory at 0xd0000 */ 0xd0000,
102 /* first minor device no. */ 0
105 static int verbose
= 0;
106 static int debug
= 0;
109 /* Variables for insmod */
110 static int io
[] = {0, 0, 0, 0};
111 static int membase
[] = {0, 0, 0, 0};
112 static int memsize
[] = {0, 0, 0, 0};
113 static int altpin
[] = {0, 0, 0, 0};
114 static int numports
[] = {0, 0, 0, 0};
116 # if (LINUX_VERSION_CODE > 0x020111)
117 MODULE_AUTHOR("Bernhard Kaindl");
118 MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
119 MODULE_PARM(verbose
, "i");
120 MODULE_PARM(debug
, "i");
121 MODULE_PARM(io
, "1-4i");
122 MODULE_PARM(membase
, "1-4i");
123 MODULE_PARM(memsize
, "1-4i");
124 MODULE_PARM(altpin
, "1-4i");
125 MODULE_PARM(numports
, "1-4i");
130 static int numcards
= 1;
131 static int nbdevs
= 0;
133 static struct channel
*digi_channels
;
134 static struct tty_struct
**pcxe_table
;
135 static struct termios
**pcxe_termios
;
136 static struct termios
**pcxe_termios_locked
;
138 int pcxx_ncook
=sizeof(pcxx_cook
);
139 int pcxx_nbios
=sizeof(pcxx_bios
);
141 #define MIN(a,b) ((a) < (b) ? (a) : (b))
142 #define pcxxassert(x, msg) if(!(x)) pcxx_error(__LINE__, msg)
144 #define FEPTIMEOUT 200000
145 #define SERIAL_TYPE_NORMAL 1
146 #define SERIAL_TYPE_CALLOUT 2
147 #define PCXE_EVENT_HANGUP 1
149 struct tty_driver pcxe_driver
;
150 struct tty_driver pcxe_callout
;
151 static int pcxe_refcount
;
153 DECLARE_TASK_QUEUE(tq_pcxx
);
155 static void pcxxpoll(void);
156 static void pcxxdelay(int);
157 static void fepcmd(struct channel
*, int, int, int, int, int);
158 static void pcxe_put_char(struct tty_struct
*, unsigned char);
159 static void pcxe_flush_chars(struct tty_struct
*);
160 static void pcxx_error(int, char *);
161 static void pcxe_close(struct tty_struct
*, struct file
*);
162 static int pcxe_ioctl(struct tty_struct
*, struct file
*, unsigned int, unsigned long);
163 static void pcxe_set_termios(struct tty_struct
*, struct termios
*);
164 static int pcxe_write(struct tty_struct
*, int, const unsigned char *, int);
165 static int pcxe_write_room(struct tty_struct
*);
166 static int pcxe_chars_in_buffer(struct tty_struct
*);
167 static void pcxe_flush_buffer(struct tty_struct
*);
168 static void doevent(int);
169 static void receive_data(struct channel
*);
170 static void pcxxparam(struct tty_struct
*, struct channel
*ch
);
171 static void do_softint(void *);
172 static inline void pcxe_sched_event(struct channel
*, int);
173 static void do_pcxe_bh(void);
174 static void pcxe_start(struct tty_struct
*);
175 static void pcxe_stop(struct tty_struct
*);
176 static void pcxe_throttle(struct tty_struct
*);
177 static void pcxe_unthrottle(struct tty_struct
*);
178 static void digi_send_break(struct channel
*ch
, int msec
);
179 static void shutdown(struct channel
*);
180 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
);
181 static inline void memwinon(struct board_info
*b
, unsigned int win
);
182 static inline void memwinoff(struct board_info
*b
, unsigned int win
);
183 static inline void globalwinon(struct channel
*ch
);
184 static inline void rxwinon(struct channel
*ch
);
185 static inline void txwinon(struct channel
*ch
);
186 static inline void memoff(struct channel
*ch
);
187 static inline void assertgwinon(struct channel
*ch
);
188 static inline void assertmemoff(struct channel
*ch
);
190 #define TZ_BUFSZ 4096
192 /* function definitions */
196 * pcxe_init() is our init_module():
198 #define pcxe_init init_module
200 void cleanup_module(void);
203 /*****************************************************************************/
205 void cleanup_module()
211 struct board_info
*bd
;
214 printk(KERN_NOTICE
"Unloading PC/Xx version %s\n", VERSION
);
218 timer_active
&= ~(1 << DIGI_TIMER
);
219 timer_table
[DIGI_TIMER
].fn
= NULL
;
220 timer_table
[DIGI_TIMER
].expires
= 0;
223 if ((e1
= tty_unregister_driver(&pcxe_driver
)))
224 printk("SERIAL: failed to unregister serial driver (%d)\n", e1
);
225 if ((e2
= tty_unregister_driver(&pcxe_callout
)))
226 printk("SERIAL: failed to unregister callout driver (%d)\n",e2
);
228 for(crd
=0; crd
< numcards
; crd
++) {
230 ch
= digi_channels
+bd
->first_minor
;
231 for(i
=0; i
< bd
->numports
; i
++, ch
++) {
234 release_region(bd
->port
, 4);
236 kfree(digi_channels
);
237 kfree(pcxe_termios_locked
);
240 restore_flags(flags
);
244 static inline struct channel
*chan(register struct tty_struct
*tty
)
247 register struct channel
*ch
=(struct channel
*)tty
->driver_data
;
248 if (ch
>= digi_channels
&& ch
< digi_channels
+nbdevs
) {
249 if (ch
->magic
==PCXX_MAGIC
)
256 /* These inline routines are to turn board memory on and off */
257 static inline void memwinon(struct board_info
*b
, unsigned int win
)
259 if(b
->type
== PCXEVE
)
260 outb_p(FEPWIN
|win
, b
->port
+1);
262 outb_p(inb(b
->port
)|FEPMEM
, b
->port
);
265 static inline void memwinoff(struct board_info
*b
, unsigned int win
)
267 outb_p(inb(b
->port
)&~FEPMEM
, b
->port
);
268 if(b
->type
== PCXEVE
)
269 outb_p(0, b
->port
+ 1);
272 static inline void globalwinon(struct channel
*ch
)
274 if(ch
->board
->type
== PCXEVE
)
275 outb_p(FEPWIN
, ch
->board
->port
+1);
277 outb_p(FEPMEM
, ch
->board
->port
);
280 static inline void rxwinon(struct channel
*ch
)
283 outb_p(FEPMEM
, ch
->board
->port
);
285 outb_p(ch
->rxwin
, ch
->board
->port
+1);
288 static inline void txwinon(struct channel
*ch
)
291 outb_p(FEPMEM
, ch
->board
->port
);
293 outb_p(ch
->txwin
, ch
->board
->port
+1);
296 static inline void memoff(struct channel
*ch
)
298 outb_p(0, ch
->board
->port
);
299 if(ch
->board
->type
== PCXEVE
)
300 outb_p(0, ch
->board
->port
+1);
303 static inline void assertgwinon(struct channel
*ch
)
305 if(ch
->board
->type
!= PCXEVE
)
306 pcxxassert(inb(ch
->board
->port
) & FEPMEM
, "Global memory off");
309 static inline void assertmemoff(struct channel
*ch
)
311 if(ch
->board
->type
!= PCXEVE
)
312 pcxxassert(!(inb(ch
->board
->port
) & FEPMEM
), "Memory on");
315 static inline void pcxe_sched_event(struct channel
*info
, int event
)
317 info
->event
|= 1 << event
;
318 queue_task(&info
->tqueue
, &tq_pcxx
);
322 static void pcxx_error(int line
, char *msg
)
324 printk("pcxx_error (DigiBoard): line=%d %s\n", line
, msg
);
327 static int pcxx_waitcarrier(struct tty_struct
*tty
,struct file
*filp
,struct channel
*info
)
329 DECLARE_WAITQUEUE(wait
, current
);
333 if (info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
334 if (info
->normal_termios
.c_cflag
& CLOCAL
)
337 if (tty
->termios
->c_cflag
& CLOCAL
)
342 * Block waiting for the carrier detect and the line to become free
346 add_wait_queue(&info
->open_wait
, &wait
);
348 info
->blocked_open
++;
352 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0) {
354 info
->omodem
|= DTR
|RTS
;
355 fepcmd(info
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
359 set_current_state(TASK_INTERRUPTIBLE
);
360 if(tty_hung_up_p(filp
) || (info
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
361 if(info
->asyncflags
& ASYNC_HUP_NOTIFY
)
364 retval
= -ERESTARTSYS
;
367 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0 &&
368 (info
->asyncflags
& ASYNC_CLOSING
) == 0 &&
369 (do_clocal
|| (info
->imodem
& info
->dcd
)))
371 if(signal_pending(current
)) {
372 retval
= -ERESTARTSYS
;
377 current
->state
= TASK_RUNNING
;
378 remove_wait_queue(&info
->open_wait
, &wait
);
380 if(!tty_hung_up_p(filp
))
382 info
->blocked_open
--;
388 int pcxe_open(struct tty_struct
*tty
, struct file
* filp
)
390 volatile struct board_chan
*bc
;
397 line
= MINOR(tty
->device
) - tty
->driver
.minor_start
;
399 if(line
< 0 || line
>= nbdevs
) {
400 printk("line out of range in pcxe_open\n");
401 tty
->driver_data
= NULL
;
405 for(boardnum
=0;boardnum
<numcards
;boardnum
++)
406 if ((line
>= boards
[boardnum
].first_minor
) &&
407 (line
< boards
[boardnum
].first_minor
+ boards
[boardnum
].numports
))
410 if(boardnum
>= numcards
|| boards
[boardnum
].status
== DISABLED
||
411 (line
- boards
[boardnum
].first_minor
) >= boards
[boardnum
].numports
) {
412 tty
->driver_data
= NULL
; /* Mark this device as 'down' */
416 ch
= digi_channels
+line
;
418 if(ch
->brdchan
== 0) {
419 tty
->driver_data
= NULL
;
423 /* flag the kernel that there is somebody using this guy */
426 * If the device is in the middle of being closed, then block
427 * until it's done, and then try again.
429 if(ch
->asyncflags
& ASYNC_CLOSING
) {
430 interruptible_sleep_on(&ch
->close_wait
);
431 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
440 tty
->driver_data
= ch
;
443 if ((ch
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
449 ch
->imodem
= bc
->mstat
;
454 ch
->imodem
= bc
->mstat
;
456 ch
->omodem
= DTR
|RTS
;
457 fepcmd(ch
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
459 ch
->asyncflags
|= ASYNC_INITIALIZED
;
461 restore_flags(flags
);
463 if(ch
->asyncflags
& ASYNC_CLOSING
) {
464 interruptible_sleep_on(&ch
->close_wait
);
465 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
471 * If this is a callout device, then just make sure the normal
472 * device isn't being used.
474 if (tty
->driver
.subtype
== SERIAL_TYPE_CALLOUT
) {
475 if (ch
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
477 if (ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
478 if ((ch
->asyncflags
& ASYNC_SESSION_LOCKOUT
) &&
479 (ch
->session
!= current
->session
))
481 if((ch
->asyncflags
& ASYNC_PGRP_LOCKOUT
) &&
482 (ch
->pgrp
!= current
->pgrp
))
485 ch
->asyncflags
|= ASYNC_CALLOUT_ACTIVE
;
488 if (filp
->f_flags
& O_NONBLOCK
) {
489 if(ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
493 /* this has to be set in order for the "block until
494 * CD" code to work correctly. i'm not sure under
495 * what circumstances asyncflags should be set to
496 * ASYNC_NORMAL_ACTIVE though
499 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
500 if ((retval
= pcxx_waitcarrier(tty
, filp
, ch
)) != 0)
503 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
508 if((ch
->count
== 1) && (ch
->asyncflags
& ASYNC_SPLIT_TERMIOS
)) {
509 if(tty
->driver
.subtype
== SERIAL_TYPE_NORMAL
)
510 *tty
->termios
= ch
->normal_termios
;
512 *tty
->termios
= ch
->callout_termios
;
518 ch
->session
= current
->session
;
519 ch
->pgrp
= current
->pgrp
;
520 restore_flags(flags
);
524 static void shutdown(struct channel
*info
)
527 volatile struct board_chan
*bc
;
528 struct tty_struct
*tty
;
530 if (!(info
->asyncflags
& ASYNC_INITIALIZED
))
544 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
546 if(tty
->termios
->c_cflag
& HUPCL
) {
547 info
->omodem
&= ~(RTS
|DTR
);
548 fepcmd(info
, SETMODEM
, 0, DTR
|RTS
, 10, 1);
552 info
->asyncflags
&= ~ASYNC_INITIALIZED
;
553 restore_flags(flags
);
557 static void pcxe_close(struct tty_struct
* tty
, struct file
* filp
)
559 struct channel
*info
;
561 if ((info
=chan(tty
))!=NULL
) {
566 if(tty_hung_up_p(filp
)) {
567 /* flag that somebody is done with this module */
569 restore_flags(flags
);
572 /* this check is in serial.c, it won't hurt to do it here too */
573 if ((tty
->count
== 1) && (info
->count
!= 1)) {
575 * Uh, oh. tty->count is 1, which means that the tty
576 * structure will be freed. Info->count should always
577 * be one in these conditions. If it's greater than
578 * one, we've got real problems, since it means the
579 * serial port won't be shutdown.
581 printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info
->count
);
584 if (info
->count
-- > 1) {
585 restore_flags(flags
);
589 if (info
->count
< 0) {
593 info
->asyncflags
|= ASYNC_CLOSING
;
596 * Save the termios structure, since this port may have
597 * separate termios for callout and dialin.
599 if(info
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
600 info
->normal_termios
= *tty
->termios
;
601 if(info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
602 info
->callout_termios
= *tty
->termios
;
604 if(info
->asyncflags
& ASYNC_INITIALIZED
) {
605 setup_empty_event(tty
,info
);
606 tty_wait_until_sent(tty
, 3000); /* 30 seconds timeout */
609 if(tty
->driver
.flush_buffer
)
610 tty
->driver
.flush_buffer(tty
);
611 if(tty
->ldisc
.flush_buffer
)
612 tty
->ldisc
.flush_buffer(tty
);
618 /* ldiscs[] is not available in a MODULE
619 ** worth noting that while I'm not sure what this hunk of code is supposed
620 ** to do, it is not present in the serial.c driver. Hmmm. If you know,
621 ** please send me a note. brian@ilinx.com
622 ** Don't know either what this is supposed to do clameter@waterf.org.
624 if(tty
->ldisc
.num
!= ldiscs
[N_TTY
].num
) {
626 (tty
->ldisc
.close
)(tty
);
627 tty
->ldisc
= ldiscs
[N_TTY
];
628 tty
->termios
->c_line
= N_TTY
;
630 (tty
->ldisc
.open
)(tty
);
633 if(info
->blocked_open
) {
634 if(info
->close_delay
) {
635 current
->state
= TASK_INTERRUPTIBLE
;
636 schedule_timeout(info
->close_delay
);
638 wake_up_interruptible(&info
->open_wait
);
640 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|
641 ASYNC_CALLOUT_ACTIVE
|ASYNC_CLOSING
);
642 wake_up_interruptible(&info
->close_wait
);
644 restore_flags(flags
);
649 void pcxe_hangup(struct tty_struct
*tty
)
653 if ((ch
=chan(tty
))!=NULL
) {
662 ch
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
663 wake_up_interruptible(&ch
->open_wait
);
664 restore_flags(flags
);
670 static int pcxe_write(struct tty_struct
* tty
, int from_user
, const unsigned char *buf
, int count
)
673 volatile struct board_chan
*bc
;
674 int total
, remain
, size
, stlen
;
675 unsigned int head
, tail
;
678 /* printk("Entering pcxe_write()\n"); */
680 if ((ch
=chan(tty
))==NULL
)
684 size
= ch
->txbufsize
;
691 head
= bc
->tin
& (size
- 1);
692 /* It seems to be necessary to make sure that the value is stable here somehow
693 This is a rather odd pice of code here. */
696 } while (tail
!= bc
->tout
);
699 stlen
= (head
>= tail
) ? (size
- (head
- tail
) - 1) : (tail
- head
- 1);
700 count
= MIN(stlen
, count
);
702 if (verify_area(VERIFY_READ
, (char*)buf
, count
))
704 else copy_from_user(ch
->tmp_buf
, buf
, count
);
708 restore_flags(flags
);
712 * All data is now local
719 head
= bc
->tin
& (size
- 1);
721 if (tail
!= bc
->tout
)
725 remain
= size
- (head
- tail
) - 1;
729 remain
= tail
- head
- 1;
732 count
= MIN(remain
, count
);
736 stlen
= MIN(count
, stlen
);
737 memcpy(ch
->txptr
+ head
, buf
, stlen
);
747 ch
->statusflags
|= TXBUSY
;
750 if ((ch
->statusflags
& LOWWAIT
) == 0) {
751 ch
->statusflags
|= LOWWAIT
;
755 restore_flags(flags
);
761 static void pcxe_put_char(struct tty_struct
*tty
, unsigned char c
)
763 pcxe_write(tty
, 0, &c
, 1);
768 static int pcxe_write_room(struct tty_struct
*tty
)
774 if ((ch
=chan(tty
))!=NULL
) {
775 volatile struct board_chan
*bc
;
776 unsigned int head
, tail
;
784 head
= bc
->tin
& (ch
->txbufsize
- 1);
786 if (tail
!= bc
->tout
)
788 tail
&= (ch
->txbufsize
- 1);
790 if((remain
= tail
- head
- 1) < 0 )
791 remain
+= ch
->txbufsize
;
793 if (remain
&& (ch
->statusflags
& LOWWAIT
) == 0) {
794 ch
->statusflags
|= LOWWAIT
;
798 restore_flags(flags
);
805 static int pcxe_chars_in_buffer(struct tty_struct
*tty
)
808 unsigned int ctail
, head
, tail
;
812 volatile struct board_chan
*bc
;
814 if ((ch
=chan(tty
))==NULL
)
824 ctail
= ch
->mailbox
->cout
;
825 if(tail
== head
&& ch
->mailbox
->cin
== ctail
&& bc
->tbusy
== 0)
828 head
= bc
->tin
& (ch
->txbufsize
- 1);
829 tail
&= (ch
->txbufsize
- 1);
830 if((remain
= tail
- head
- 1) < 0 )
831 remain
+= ch
->txbufsize
;
833 chars
= (int)(ch
->txbufsize
- remain
);
836 * Make it possible to wakeup anything waiting for output
837 * in tty_ioctl.c, etc.
839 if(!(ch
->statusflags
& EMPTYWAIT
))
840 setup_empty_event(tty
,ch
);
844 restore_flags(flags
);
850 static void pcxe_flush_buffer(struct tty_struct
*tty
)
853 volatile struct board_chan
*bc
;
857 if ((ch
=chan(tty
))==NULL
)
866 fepcmd(ch
, STOUT
, (unsigned) tail
, 0, 0, 0);
869 restore_flags(flags
);
871 wake_up_interruptible(&tty
->write_wait
);
872 if((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) && tty
->ldisc
.write_wakeup
)
873 (tty
->ldisc
.write_wakeup
)(tty
);
876 static void pcxe_flush_chars(struct tty_struct
*tty
)
880 if ((ch
=chan(tty
))!=NULL
) {
885 if ((ch
->statusflags
& TXBUSY
) && !(ch
->statusflags
& EMPTYWAIT
))
886 setup_empty_event(tty
,ch
);
887 restore_flags(flags
);
894 * Driver setup function when linked into the kernel to optionally parse multible
895 * "digi="-lines and initialize the driver at boot time. No probing.
897 void __init
pcxx_setup(char *str
, int *ints
)
900 struct board_info board
;
907 memset(&board
, 0, sizeof(board
));
909 for(last
=0,i
=1;i
<=ints
[0];i
++)
913 board
.status
= ints
[i
];
918 board
.type
= ints
[i
];
923 board
.altpin
= ints
[i
];
928 board
.numports
= ints
[i
];
933 board
.port
= ints
[i
];
938 board
.membase
= ints
[i
];
943 printk("PC/Xx: Too many integer parms\n");
949 /* find the next comma or terminator */
951 while (*temp
&& (*temp
!= ','))
965 if (strncmp("Disable", str
, len
) == 0)
968 if (strncmp("Enable", str
, len
) == 0)
972 printk("PC/Xx: Invalid status %s\n", str
);
979 for(j
=0;j
<PCXX_NUM_TYPES
;j
++)
980 if (strcmp(board_desc
[j
], str
) == 0)
983 if (i
<PCXX_NUM_TYPES
)
987 printk("PC/Xx: Invalid board name: %s\n", str
);
995 if (strncmp("Disable", str
, len
) == 0)
998 if (strncmp("Enable", str
, len
) == 0)
1002 printk("PC/Xx: Invalid altpin %s\n", str
);
1010 while (isdigit(*t2
))
1015 printk("PC/Xx: Invalid port count %s\n", str
);
1019 board
.numports
= simple_strtoul(str
, NULL
, 0);
1025 while (isxdigit(*t2
))
1030 printk("PC/Xx: Invalid io port address %s\n", str
);
1034 board
.port
= simple_strtoul(str
, NULL
, 16);
1040 while (isxdigit(*t2
))
1045 printk("PC/Xx: Invalid memory base %s\n", str
);
1049 board
.membase
= simple_strtoul(str
, NULL
, 16);
1054 printk("PC/Xx: Too many string parms\n");
1062 printk("PC/Xx: Insufficient parms specified\n");
1066 /* I should REALLY validate the stuff here */
1068 memcpy(&boards
[numcards
],&board
, sizeof(board
));
1069 printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n",
1070 numcards
, board_desc
[board
.type
], board_mem
[board
.type
],
1071 board
.numports
, board
.port
, (unsigned int) board
.membase
);
1073 /* keep track of my initial minor number */
1075 boards
[numcards
].first_minor
= boards
[numcards
-1].first_minor
+ boards
[numcards
-1].numports
;
1077 boards
[numcards
].first_minor
= 0;
1079 /* yeha! string parameter was successful! */
1085 * function to initialize the driver with the given parameters, which are either
1086 * the default values from this file or the parameters given at boot.
1088 int __init
pcxe_init(void)
1090 ulong memory_seg
=0, memory_size
=0;
1091 int lowwater
, enabled_cards
=0, i
, crd
, shrinkmem
=0, topwin
= 0xff00L
, botwin
=0x100L
;
1092 unchar
*fepos
, *memaddr
, *bios
, v
;
1093 volatile struct global_data
*gd
;
1094 volatile struct board_chan
*bc
;
1095 struct board_info
*bd
;
1098 printk(KERN_NOTICE
"Digiboard PC/X{i,e,eve} driver v%s\n", VERSION
);
1101 for (i
= 0; i
< 4; i
++) {
1107 if (numcards
== 0) {
1108 int first_minor
= 0;
1110 for (i
= 0; i
< 4; i
++) {
1113 boards
[i
].status
= DISABLED
;
1116 boards
[i
].port
= (ushort
)io
[i
];
1117 boards
[i
].status
= ENABLED
;
1118 boards
[i
].first_minor
= first_minor
;
1122 boards
[i
].membase
= (ulong
)membase
[i
];
1124 boards
[i
].membase
= 0xD0000;
1127 boards
[i
].memsize
= (ulong
)(memsize
[i
] * 1024);
1129 boards
[i
].memsize
= 0;
1132 boards
[i
].altpin
= ON
;
1134 boards
[i
].altpin
= OFF
;
1137 boards
[i
].numports
= (ushort
)numports
[i
];
1139 boards
[i
].numports
= 16;
1141 first_minor
+= boards
[i
].numports
;
1148 printk("PC/Xx: No cards configured, driver not active.\n");
1153 for (i
= 0; i
< numcards
; i
++) {
1154 printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",
1162 boards
[i
].first_minor
);
1166 for (i
=0;i
<numcards
;i
++)
1167 nbdevs
+= boards
[i
].numports
;
1171 printk("PC/Xx: No devices activated, driver not active.\n");
1176 * this turns out to be more memory efficient, as there are no
1179 digi_channels
= kmalloc(sizeof(struct channel
) * nbdevs
, GFP_KERNEL
);
1181 panic("Unable to allocate digi_channel struct");
1182 memset(digi_channels
, 0, sizeof(struct channel
) * nbdevs
);
1184 pcxe_table
= kmalloc(sizeof(struct tty_struct
*) * nbdevs
, GFP_KERNEL
);
1186 panic("Unable to allocate pcxe_table struct");
1187 memset(pcxe_table
, 0, sizeof(struct tty_struct
*) * nbdevs
);
1189 pcxe_termios
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1191 panic("Unable to allocate pcxe_termios struct");
1192 memset(pcxe_termios
,0,sizeof(struct termios
*)*nbdevs
);
1194 pcxe_termios_locked
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1195 if (!pcxe_termios_locked
)
1196 panic("Unable to allocate pcxe_termios_locked struct");
1197 memset(pcxe_termios_locked
,0,sizeof(struct termios
*)*nbdevs
);
1199 init_bh(DIGI_BH
,do_pcxe_bh
);
1202 timer_table
[DIGI_TIMER
].fn
= pcxxpoll
;
1203 timer_table
[DIGI_TIMER
].expires
= 0;
1205 memset(&pcxe_driver
, 0, sizeof(struct tty_driver
));
1206 pcxe_driver
.magic
= TTY_DRIVER_MAGIC
;
1207 pcxe_driver
.name
= "ttyD";
1208 pcxe_driver
.major
= DIGI_MAJOR
;
1209 pcxe_driver
.minor_start
= 0;
1211 pcxe_driver
.num
= nbdevs
;
1213 pcxe_driver
.type
= TTY_DRIVER_TYPE_SERIAL
;
1214 pcxe_driver
.subtype
= SERIAL_TYPE_NORMAL
;
1215 pcxe_driver
.init_termios
= tty_std_termios
;
1216 pcxe_driver
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
;
1217 pcxe_driver
.flags
= TTY_DRIVER_REAL_RAW
;
1218 pcxe_driver
.refcount
= &pcxe_refcount
;
1220 pcxe_driver
.table
= pcxe_table
;
1221 pcxe_driver
.termios
= pcxe_termios
;
1222 pcxe_driver
.termios_locked
= pcxe_termios_locked
;
1224 pcxe_driver
.open
= pcxe_open
;
1225 pcxe_driver
.close
= pcxe_close
;
1226 pcxe_driver
.write
= pcxe_write
;
1227 pcxe_driver
.put_char
= pcxe_put_char
;
1228 pcxe_driver
.flush_chars
= pcxe_flush_chars
;
1229 pcxe_driver
.write_room
= pcxe_write_room
;
1230 pcxe_driver
.chars_in_buffer
= pcxe_chars_in_buffer
;
1231 pcxe_driver
.flush_buffer
= pcxe_flush_buffer
;
1232 pcxe_driver
.ioctl
= pcxe_ioctl
;
1233 pcxe_driver
.throttle
= pcxe_throttle
;
1234 pcxe_driver
.unthrottle
= pcxe_unthrottle
;
1235 pcxe_driver
.set_termios
= pcxe_set_termios
;
1236 pcxe_driver
.stop
= pcxe_stop
;
1237 pcxe_driver
.start
= pcxe_start
;
1238 pcxe_driver
.hangup
= pcxe_hangup
;
1240 pcxe_callout
= pcxe_driver
;
1241 pcxe_callout
.name
= "cud";
1242 pcxe_callout
.major
= DIGICU_MAJOR
;
1243 pcxe_callout
.subtype
= SERIAL_TYPE_CALLOUT
;
1244 pcxe_callout
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
| CLOCAL
;
1246 for(crd
=0; crd
< numcards
; crd
++) {
1248 outb(FEPRST
, bd
->port
);
1251 for(i
=0; (inb(bd
->port
) & FEPMASK
) != FEPRST
; i
++) {
1253 printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
1255 bd
->status
= DISABLED
;
1263 if(bd
->status
== DISABLED
)
1268 if((v
& 0x1) == 0x1) {
1269 if((v
& 0x30) == 0) { /* PC/Xi 64K card */
1270 memory_seg
= 0xf000;
1271 memory_size
= 0x10000;
1274 if((v
& 0x30) == 0x10) { /* PC/Xi 128K card */
1275 memory_seg
= 0xe000;
1276 memory_size
= 0x20000;
1279 if((v
& 0x30) == 0x20) { /* PC/Xi 256K card */
1280 memory_seg
= 0xc000;
1281 memory_size
= 0x40000;
1284 if((v
& 0x30) == 0x30) { /* PC/Xi 512K card */
1285 memory_seg
= 0x8000;
1286 memory_size
= 0x80000;
1290 if((v
& 0x1) == 0x1) {
1291 bd
->status
= DISABLED
; /* PC/Xm unsupported card */
1292 printk("PC/Xx: PC/Xm at 0x%x not supported!!\n", bd
->port
);
1297 outb((((ulong
)bd
->membase
>>8) & 0xe0) | 0x10, bd
->port
+2);
1298 outb(((ulong
)bd
->membase
>>16) & 0xff, bd
->port
+3);
1299 bd
->type
= PCXEVE
; /* PC/Xe 8K card */
1301 bd
->type
= PCXE
; /* PC/Xe 64K card */
1304 memory_seg
= 0xf000;
1305 memory_size
= 0x10000;
1309 printk("Configuring card %d as a %s %ldK card. io=0x%x, mem=%lx-%lx\n",
1310 crd
+1, board_desc
[bd
->type
], memory_size
/1024,
1311 bd
->port
,bd
->membase
,bd
->membase
+memory_size
-1);
1313 if (boards
[crd
].memsize
== 0)
1314 boards
[crd
].memsize
= memory_size
;
1316 if (boards
[crd
].memsize
!= memory_size
) {
1317 printk("PC/Xx: memory size mismatch:supplied=%lx(%ldK) probed=%ld(%ldK)\n",
1318 boards
[crd
].memsize
, boards
[crd
].memsize
/ 1024,
1319 memory_size
, memory_size
/ 1024);
1323 memaddr
= (unchar
*)phys_to_virt(bd
->membase
);
1326 printk("Resetting board and testing memory access:");
1328 outb(FEPRST
|FEPMEM
, bd
->port
);
1330 for(i
=0; (inb(bd
->port
) & FEPMASK
) != (FEPRST
|FEPMEM
); i
++) {
1332 printk("\nPC/Xx: %s not resetting at port 0x%x! Check switch settings.\n",
1333 board_desc
[bd
->type
], bd
->port
);
1334 bd
->status
= DISABLED
;
1342 if(bd
->status
== DISABLED
)
1346 *(ulong
*)(memaddr
+ botwin
) = 0xa55a3cc3;
1347 *(ulong
*)(memaddr
+ topwin
) = 0x5aa5c33c;
1349 if(*(ulong
*)(memaddr
+ botwin
) != 0xa55a3cc3 ||
1350 *(ulong
*)(memaddr
+ topwin
) != 0x5aa5c33c) {
1351 printk("PC/Xx: Failed memory test at %lx for %s at port %x, check switch settings.\n",
1352 bd
->membase
, board_desc
[bd
->type
], bd
->port
);
1353 bd
->status
= DISABLED
;
1359 for(i
=0; i
< 16; i
++) {
1360 memaddr
[MISCGLOBAL
+i
] = 0;
1363 if(bd
->type
== PCXI
|| bd
->type
== PCXE
) {
1364 bios
= memaddr
+ BIOSCODE
+ ((0xf000 - memory_seg
) << 4);
1367 printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios
));
1369 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1374 outb(FEPMEM
, bd
->port
);
1377 printk("Waiting for BIOS to become ready");
1379 for(i
=1; i
<= 30; i
++) {
1380 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1394 printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n",
1395 bd
->port
, bd
->membase
, bd
->membase
+bd
->memsize
);
1396 bd
->status
= DISABLED
;
1400 if(bd
->type
== PCXEVE
) {
1401 bios
= memaddr
+ (BIOSCODE
& 0x1fff);
1404 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1406 outb(FEPCLR
, bd
->port
);
1409 for(i
=0; i
<= 1000; i
++) {
1410 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1424 printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n",
1425 board_desc
[bd
->type
], bd
->port
);
1426 bd
->status
= DISABLED
;
1431 fepos
= memaddr
+ FEPCODE
;
1432 if(bd
->type
== PCXEVE
)
1433 fepos
= memaddr
+ (FEPCODE
& 0x1fff);
1436 printk(" ok.\nDownloading FEP/OS to 0x%lx:", virt_to_phys(fepos
));
1438 memwinon(bd
, (FEPCODE
>> 13));
1439 memcpy(fepos
, pcxx_cook
, pcxx_ncook
);
1445 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 0) = 2;
1446 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 2) = memory_seg
+ FEPCODESEG
;
1447 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 4) = 0;
1448 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 6) = FEPCODESEG
;
1449 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 8) = 0;
1450 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 10) = pcxx_ncook
;
1452 outb(FEPMEM
|FEPINT
, bd
->port
);
1453 outb(FEPMEM
, bd
->port
);
1455 for(i
=0; *(ushort
*)((ulong
)memaddr
+ MBOX
); i
++) {
1457 printk("PC/Xx: Command failed for the %s at 0x%x!\n",
1458 board_desc
[bd
->type
], bd
->port
);
1459 bd
->status
= DISABLED
;
1468 if(bd
->status
== DISABLED
)
1472 printk("Waiting for FEP/OS to become ready");
1474 *(ushort
*)(memaddr
+ FEPSTAT
) = 0;
1475 *(ushort
*)(memaddr
+ MBOX
+ 0) = 1;
1476 *(ushort
*)(memaddr
+ MBOX
+ 2) = FEPCODESEG
;
1477 *(ushort
*)(memaddr
+ MBOX
+ 4) = 0x4L
;
1479 outb(FEPINT
, bd
->port
);
1480 outb(FEPCLR
, bd
->port
);
1483 for(i
=1; *(ushort
*)((ulong
)memaddr
+ FEPSTAT
) != *(ushort
*)"OS"; i
++) {
1485 printk("\nPC/Xx: FEP/OS download failed on the %s at 0x%x!\n",
1486 board_desc
[bd
->type
], bd
->port
);
1487 bd
->status
= DISABLED
;
1493 printk("\n%5d",i
/50);
1500 if(bd
->status
== DISABLED
)
1506 ch
= digi_channels
+bd
->first_minor
;
1507 pcxxassert(ch
< digi_channels
+nbdevs
, "ch out of range");
1509 bc
= (volatile struct board_chan
*)((ulong
)memaddr
+ CHANSTRUCT
);
1510 gd
= (volatile struct global_data
*)((ulong
)memaddr
+ GLOBAL
);
1512 if((bd
->type
== PCXEVE
) && (*(ushort
*)((ulong
)memaddr
+NPORT
) < 3))
1515 request_region(bd
->port
, 4, "PC/Xx");
1517 for(i
=0; i
< bd
->numports
; i
++, ch
++, bc
++) {
1518 if(((ushort
*)((ulong
)memaddr
+ PORTBASE
))[i
] == 0) {
1524 ch
->tqueue
.routine
= do_softint
;
1525 ch
->tqueue
.data
= ch
;
1526 ch
->board
= &boards
[crd
];
1527 #ifdef DEFAULT_HW_FLOW
1528 ch
->digiext
.digi_flags
= RTSPACE
|CTSPACE
;
1530 if(boards
[crd
].altpin
) {
1533 ch
->digiext
.digi_flags
|= DIGI_ALTPIN
;
1539 ch
->magic
= PCXX_MAGIC
;
1543 ch
->dev
= bd
->first_minor
+ i
;
1547 fepcmd(ch
, SETBUFFER
, 32, 0, 0, 0);
1551 if(bd
->type
!= PCXEVE
) {
1552 ch
->txptr
= memaddr
+((bc
->tseg
-memory_seg
) << 4);
1553 ch
->rxptr
= memaddr
+((bc
->rseg
-memory_seg
) << 4);
1554 ch
->txwin
= ch
->rxwin
= 0;
1556 ch
->txptr
= memaddr
+(((bc
->tseg
-memory_seg
) << 4) & 0x1fff);
1557 ch
->txwin
= FEPWIN
| ((bc
->tseg
-memory_seg
) >> 9);
1558 ch
->rxptr
= memaddr
+(((bc
->rseg
-memory_seg
) << 4) & 0x1fff);
1559 ch
->rxwin
= FEPWIN
| ((bc
->rseg
-memory_seg
) >>9 );
1562 ch
->txbufsize
= bc
->tmax
+ 1;
1563 ch
->rxbufsize
= bc
->rmax
+ 1;
1564 ch
->tmp_buf
= kmalloc(ch
->txbufsize
,GFP_KERNEL
);
1565 lowwater
= ch
->txbufsize
>= 2000 ? 1024 : ch
->txbufsize
/2;
1566 fepcmd(ch
, STXLWATER
, lowwater
, 0, 10, 0);
1567 fepcmd(ch
, SRXLWATER
, ch
->rxbufsize
/4, 0, 10, 0);
1568 fepcmd(ch
, SRXHWATER
, 3 * ch
->rxbufsize
/4, 0, 10, 0);
1573 ch
->startc
= bc
->startc
;
1574 ch
->stopc
= bc
->stopc
;
1575 ch
->startca
= bc
->startca
;
1576 ch
->stopca
= bc
->stopca
;
1586 ch
->close_delay
= 50;
1588 ch
->blocked_open
= 0;
1589 ch
->callout_termios
= pcxe_callout
.init_termios
;
1590 ch
->normal_termios
= pcxe_driver
.init_termios
;
1597 printk("Card No. %d ready: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1598 crd
+1, board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1599 bd
->membase
, bd
->numports
);
1601 printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1602 board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1603 bd
->membase
, bd
->numports
);
1609 if (enabled_cards
<= 0) {
1610 printk(KERN_NOTICE
"PC/Xx: No cards enabled, no driver.\n");
1614 if(tty_register_driver(&pcxe_driver
))
1615 panic("Couldn't register PC/Xe driver");
1617 if(tty_register_driver(&pcxe_callout
))
1618 panic("Couldn't register PC/Xe callout");
1621 * Start up the poller to check for events on all enabled boards
1623 timer_active
|= 1 << DIGI_TIMER
;
1626 printk(KERN_NOTICE
"PC/Xx: Driver with %d card(s) ready.\n", enabled_cards
);
1632 static void pcxxpoll(void)
1634 unsigned long flags
;
1636 volatile unsigned int head
, tail
;
1638 struct board_info
*bd
;
1643 for(crd
=0; crd
< numcards
; crd
++) {
1646 ch
= digi_channels
+bd
->first_minor
;
1648 if(bd
->status
== DISABLED
)
1654 head
= ch
->mailbox
->ein
;
1655 tail
= ch
->mailbox
->eout
;
1663 timer_table
[DIGI_TIMER
].fn
= pcxxpoll
;
1664 timer_table
[DIGI_TIMER
].expires
= jiffies
+ HZ
/25;
1665 timer_active
|= 1 << DIGI_TIMER
;
1666 restore_flags(flags
);
1669 static void doevent(int crd
)
1671 volatile struct board_info
*bd
;
1672 static struct tty_struct
*tty
;
1673 volatile struct board_chan
*bc
;
1674 volatile unchar
*eventbuf
;
1675 volatile unsigned int head
;
1676 volatile unsigned int tail
;
1678 struct channel
*chan0
;
1679 int channel
, event
, mstat
, lstat
;
1683 chan0
= digi_channels
+bd
->first_minor
;
1684 pcxxassert(chan0
< digi_channels
+nbdevs
, "ch out of range");
1687 assertgwinon(chan0
);
1689 while ((tail
= chan0
->mailbox
->eout
) != (head
= chan0
->mailbox
->ein
)) {
1690 assertgwinon(chan0
);
1691 eventbuf
= (volatile unchar
*)phys_to_virt(bd
->membase
+ tail
+ ISTART
);
1692 channel
= eventbuf
[0];
1693 event
= eventbuf
[1];
1694 mstat
= eventbuf
[2];
1695 lstat
= eventbuf
[3];
1699 if ((unsigned)channel
>= bd
->numports
|| !ch
) {
1700 printk("physmem=%lx, tail=%x, head=%x\n", bd
->membase
, tail
, head
);
1701 printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
1702 crd
, (unsigned)channel
, event
, (unsigned)mstat
, lstat
);
1703 if(channel
>= bd
->numports
)
1708 if ((bc
= ch
->brdchan
) == NULL
)
1711 if (event
& DATA_IND
) {
1716 if (event
& MODEMCHG_IND
) {
1718 if (ch
->asyncflags
& (ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
)) {
1719 if (ch
->asyncflags
& ASYNC_CHECK_CD
) {
1720 if (mstat
& ch
->dcd
) {
1721 wake_up_interruptible(&ch
->open_wait
);
1723 pcxe_sched_event(ch
, PCXE_EVENT_HANGUP
);
1733 if (event
& BREAK_IND
) {
1735 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
1736 *tty
->flip
.char_buf_ptr
++ = 0;
1738 if (ch
->asyncflags
& ASYNC_SAK
)
1741 tty_schedule_flip(tty
);
1744 if (event
& LOWTX_IND
) {
1745 if (ch
->statusflags
& LOWWAIT
) {
1746 ch
->statusflags
&= ~LOWWAIT
;
1747 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1748 tty
->ldisc
.write_wakeup
)
1749 (tty
->ldisc
.write_wakeup
)(tty
);
1750 wake_up_interruptible(&tty
->write_wait
);
1754 if (event
& EMPTYTX_IND
) {
1755 ch
->statusflags
&= ~TXBUSY
;
1756 if (ch
->statusflags
& EMPTYWAIT
) {
1757 ch
->statusflags
&= ~EMPTYWAIT
;
1758 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1759 tty
->ldisc
.write_wakeup
)
1760 (tty
->ldisc
.write_wakeup
)(tty
);
1761 wake_up_interruptible(&tty
->write_wait
);
1768 if(!bc
) printk("bc == NULL in doevent!\n");
1771 chan0
->mailbox
->eout
= (tail
+4) & (IMAX
-ISTART
-4);
1779 * pcxxdelay - delays a specified number of milliseconds
1781 static void pcxxdelay(int msec
)
1784 __delay(loops_per_sec
/1000);
1789 fepcmd(struct channel
*ch
, int cmd
, int word_or_byte
, int byte2
, int ncmds
,
1793 unsigned int head
, tail
;
1797 if(ch
->board
->status
== DISABLED
)
1802 memaddr
= (unchar
*)phys_to_virt(ch
->board
->membase
);
1803 head
= ch
->mailbox
->cin
;
1805 if(head
>= (CMAX
-CSTART
) || (head
& 03)) {
1806 printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__
, cmd
, head
);
1811 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1813 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1815 *(unchar
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1816 *(unchar
*)(memaddr
+head
+CSTART
+3) = byte2
;
1818 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1820 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1821 *(ushort
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1824 head
= (head
+4) & (CMAX
-CSTART
-4);
1825 ch
->mailbox
->cin
= head
;
1832 printk("Fep not responding in fepcmd()\n");
1836 head
= ch
->mailbox
->cin
;
1837 tail
= ch
->mailbox
->cout
;
1839 n
= (head
-tail
) & (CMAX
-CSTART
-4);
1841 if(n
<= ncmds
* (sizeof(short)*4))
1843 /* Seems not to be good here: schedule(); */
1848 static unsigned termios2digi_c(struct channel
*ch
, unsigned cflag
)
1852 /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
1853 if ((cflag
& CBAUD
)== B38400
) cflag
=cflag
- B38400
+ B115200
;
1854 if ((cflag
& CBAUD
)== B19200
) cflag
=cflag
- B19200
+ B57600
;
1856 if (cflag
& CBAUDEX
)
1858 ch
->digiext
.digi_flags
|= DIGI_FAST
;
1860 /* This gets strange but if we don't do this we will get 78600
1861 * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
1862 * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
1865 if (cflag
& B115200
) res
|=1;
1867 else ch
->digiext
.digi_flags
&= ~DIGI_FAST
;
1868 res
|= cflag
& (CBAUD
| PARODD
| PARENB
| CSTOPB
| CSIZE
| CLOCAL
);
1872 static unsigned termios2digi_i(struct channel
*ch
, unsigned iflag
)
1874 unsigned res
= iflag
& (IGNBRK
|BRKINT
|IGNPAR
|PARMRK
|INPCK
|ISTRIP
|IXON
|IXANY
|IXOFF
);
1876 if(ch
->digiext
.digi_flags
& DIGI_AIXON
)
1881 static unsigned termios2digi_h(struct channel
*ch
, unsigned cflag
)
1885 if(cflag
& CRTSCTS
) {
1886 ch
->digiext
.digi_flags
|= (RTSPACE
|CTSPACE
);
1889 if(ch
->digiext
.digi_flags
& RTSPACE
)
1891 if(ch
->digiext
.digi_flags
& DTRPACE
)
1893 if(ch
->digiext
.digi_flags
& CTSPACE
)
1895 if(ch
->digiext
.digi_flags
& DSRPACE
)
1897 if(ch
->digiext
.digi_flags
& DCDPACE
)
1901 ch
->digiext
.digi_flags
|= RTSPACE
;
1903 ch
->digiext
.digi_flags
|= CTSPACE
;
1908 static void pcxxparam(struct tty_struct
*tty
, struct channel
*ch
)
1910 volatile struct board_chan
*bc
;
1912 unsigned mval
, hflow
, cflag
, iflag
;
1919 if((ts
->c_cflag
& CBAUD
) == 0) {
1923 fepcmd(ch
, STOUT
, (unsigned) head
, 0, 0, 0);
1927 cflag
= termios2digi_c(ch
, ts
->c_cflag
);
1929 if(cflag
!= ch
->fepcflag
) {
1930 ch
->fepcflag
= cflag
;
1931 fepcmd(ch
, SETCTRLFLAGS
, (unsigned) cflag
, 0, 0, 0);
1935 ch
->asyncflags
&= ~ASYNC_CHECK_CD
;
1937 ch
->asyncflags
|= ASYNC_CHECK_CD
;
1943 iflag
= termios2digi_i(ch
, ts
->c_iflag
);
1945 if(iflag
!= ch
->fepiflag
) {
1946 ch
->fepiflag
= iflag
;
1947 fepcmd(ch
, SETIFLAGS
, (unsigned int) ch
->fepiflag
, 0, 0, 0);
1951 if((ts
->c_cflag
& CLOCAL
) || (ch
->digiext
.digi_flags
& DIGI_FORCEDCD
))
1952 if(ch
->digiext
.digi_flags
& DIGI_FORCEDCD
)
1955 ch
->imodem
= bc
->mstat
;
1957 hflow
= termios2digi_h(ch
, ts
->c_cflag
);
1959 if(hflow
!= ch
->hflow
) {
1961 fepcmd(ch
, SETHFLOW
, hflow
, 0xff, 0, 1);
1964 /* mval ^= ch->modemfake & (mval ^ ch->modem); */
1966 if(ch
->omodem
!= mval
) {
1968 fepcmd(ch
, SETMODEM
, mval
, RTS
|DTR
, 0, 1);
1971 if(ch
->startc
!= ch
->fepstartc
|| ch
->stopc
!= ch
->fepstopc
) {
1972 ch
->fepstartc
= ch
->startc
;
1973 ch
->fepstopc
= ch
->stopc
;
1974 fepcmd(ch
, SONOFFC
, ch
->fepstartc
, ch
->fepstopc
, 0, 1);
1977 if(ch
->startca
!= ch
->fepstartca
|| ch
->stopca
!= ch
->fepstopca
) {
1978 ch
->fepstartca
= ch
->startca
;
1979 ch
->fepstopca
= ch
->stopca
;
1980 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
1985 static void receive_data(struct channel
*ch
)
1987 volatile struct board_chan
*bc
;
1988 struct tty_struct
*tty
;
1989 unsigned int tail
, head
, wrapmask
;
1992 struct termios
*ts
=0;
1999 if (ch
->statusflags
& RXSTOPPED
)
2009 printk("bc is NULL in receive_data!\n");
2013 wrapmask
= ch
->rxbufsize
- 1;
2017 tail
= bc
->rout
& wrapmask
;
2019 n
= (head
-tail
) & wrapmask
;
2025 * If CREAD bit is off or device not open, set TX tail to head
2027 if(!tty
|| !ts
|| !(ts
->c_cflag
& CREAD
)) {
2032 if(tty
->flip
.count
== TTY_FLIPBUF_SIZE
) {
2033 /* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
2039 printk("overrun! DigiBoard device minor=%d\n",MINOR(tty
->device
));
2043 rptr
= tty
->flip
.char_buf_ptr
;
2044 rc
= tty
->flip
.count
;
2046 wrapgap
= (head
>= tail
) ? head
- tail
: ch
->rxbufsize
- tail
;
2047 piece
= (wrapgap
< n
) ? wrapgap
: n
;
2050 * Make sure we don't overflow the buffer
2053 if ((rc
+ piece
) > TTY_FLIPBUF_SIZE
)
2054 piece
= TTY_FLIPBUF_SIZE
- rc
;
2059 memcpy(rptr
, ch
->rxptr
+ tail
, piece
);
2062 tail
= (tail
+ piece
) & wrapmask
;
2065 tty
->flip
.count
= rc
;
2066 tty
->flip
.char_buf_ptr
= rptr
;
2070 /* Must be called with global data */
2071 tty_schedule_flip(ch
->tty
);
2076 static int pcxe_ioctl(struct tty_struct
*tty
, struct file
* file
,
2077 unsigned int cmd
, unsigned long arg
)
2080 struct channel
*ch
= (struct channel
*) tty
->driver_data
;
2081 volatile struct board_chan
*bc
;
2083 unsigned int mflag
, mstat
;
2084 unsigned char startc
, stopc
;
2085 unsigned long flags
;
2091 printk("ch is NULL in pcxe_ioctl!\n");
2098 case TCSBRK
: /* SVID version: non-zero arg --> no break */
2099 retval
= tty_check_change(tty
);
2102 setup_empty_event(tty
,ch
);
2103 tty_wait_until_sent(tty
, 0);
2105 digi_send_break(ch
, HZ
/4); /* 1/4 second */
2108 case TCSBRKP
: /* support for POSIX tcsendbreak() */
2109 retval
= tty_check_change(tty
);
2112 setup_empty_event(tty
,ch
);
2113 tty_wait_until_sent(tty
, 0);
2114 digi_send_break(ch
, arg
? arg
*(HZ
/10) : HZ
/4);
2118 return put_user(C_CLOCAL(tty
) ? 1 : 0,
2119 (unsigned int *) arg
);
2124 error
= get_user( value
, (unsigned int *) arg
);
2127 tty
->termios
->c_cflag
= ((tty
->termios
->c_cflag
& ~CLOCAL
) | (value
? CLOCAL
: 0));
2139 restore_flags(flags
);
2154 error
= put_user(mflag
, (unsigned int *) arg
);
2163 error
= get_user(mstat
, (unsigned int *) arg
);
2168 if(mstat
& TIOCM_DTR
)
2170 if(mstat
& TIOCM_RTS
)
2176 ch
->modemfake
= DTR
|RTS
;
2181 ch
->modemfake
|= mflag
;
2186 ch
->modemfake
&= ~mflag
;
2187 ch
->modem
&= ~mflag
;
2195 restore_flags(flags
);
2202 fepcmd(ch
, SETMODEM
, DTR
, 0, 10, 1);
2204 restore_flags(flags
);
2211 fepcmd(ch
, SETMODEM
, 0, DTR
, 10, 1);
2213 restore_flags(flags
);
2217 if((error
=verify_area(VERIFY_WRITE
, (char*)arg
, sizeof(digi_t
))))
2220 copy_to_user((char*)arg
, &ch
->digiext
, sizeof(digi_t
));
2225 if(cmd
== DIGI_SETAW
) {
2226 setup_empty_event(tty
,ch
);
2227 tty_wait_until_sent(tty
, 0);
2230 if(tty
->ldisc
.flush_buffer
)
2231 tty
->ldisc
.flush_buffer(tty
);
2237 if((error
=verify_area(VERIFY_READ
, (char*)arg
,sizeof(digi_t
))))
2240 copy_from_user(&ch
->digiext
, (char*)arg
, sizeof(digi_t
));
2242 printk("ioctl(DIGI_SETA): flags = %x\n", ch
->digiext
.digi_flags
);
2245 if(ch
->digiext
.digi_flags
& DIGI_ALTPIN
) {
2257 restore_flags(flags
);
2264 if(cmd
== DIGI_GETFLOW
) {
2265 dflow
.startc
= bc
->startc
;
2266 dflow
.stopc
= bc
->stopc
;
2268 dflow
.startc
= bc
->startca
;
2269 dflow
.stopc
= bc
->stopca
;
2272 restore_flags(flags
);
2274 if((error
=verify_area(VERIFY_WRITE
, (char*)arg
,sizeof(dflow
))))
2277 copy_to_user((char*)arg
, &dflow
, sizeof(dflow
));
2282 if(cmd
== DIGI_SETFLOW
) {
2283 startc
= ch
->startc
;
2286 startc
= ch
->startca
;
2290 if((error
=verify_area(VERIFY_READ
, (char*)arg
,sizeof(dflow
))))
2293 copy_from_user(&dflow
, (char*)arg
, sizeof(dflow
));
2295 if(dflow
.startc
!= startc
|| dflow
.stopc
!= stopc
) {
2299 if(cmd
== DIGI_SETFLOW
) {
2300 ch
->fepstartc
= ch
->startc
= dflow
.startc
;
2301 ch
->fepstopc
= ch
->stopc
= dflow
.stopc
;
2302 fepcmd(ch
,SONOFFC
,ch
->fepstartc
,ch
->fepstopc
,0, 1);
2304 ch
->fepstartca
= ch
->startca
= dflow
.startc
;
2305 ch
->fepstopca
= ch
->stopca
= dflow
.stopc
;
2306 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
2309 if(ch
->statusflags
& TXSTOPPED
)
2313 restore_flags(flags
);
2318 return -ENOIOCTLCMD
;
2324 static void pcxe_set_termios(struct tty_struct
*tty
, struct termios
*old_termios
)
2326 struct channel
*info
;
2328 if ((info
=chan(tty
))!=NULL
) {
2329 unsigned long flags
;
2333 pcxxparam(tty
,info
);
2336 if ((old_termios
->c_cflag
& CRTSCTS
) &&
2337 ((tty
->termios
->c_cflag
& CRTSCTS
) == 0))
2338 tty
->hw_stopped
= 0;
2339 if(!(old_termios
->c_cflag
& CLOCAL
) &&
2340 (tty
->termios
->c_cflag
& CLOCAL
))
2341 wake_up_interruptible(&info
->open_wait
);
2342 restore_flags(flags
);
2347 static void do_pcxe_bh(void)
2349 run_task_queue(&tq_pcxx
);
2353 static void do_softint(void *private_
)
2355 struct channel
*info
= (struct channel
*) private_
;
2357 if(info
&& info
->magic
== PCXX_MAGIC
) {
2358 struct tty_struct
*tty
= info
->tty
;
2359 if (tty
&& tty
->driver_data
) {
2360 if(test_and_clear_bit(PCXE_EVENT_HANGUP
, &info
->event
)) {
2362 wake_up_interruptible(&info
->open_wait
);
2363 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2370 static void pcxe_stop(struct tty_struct
*tty
)
2372 struct channel
*info
;
2374 if ((info
=chan(tty
))!=NULL
) {
2375 unsigned long flags
;
2378 if ((info
->statusflags
& TXSTOPPED
) == 0) {
2380 fepcmd(info
, PAUSETX
, 0, 0, 0, 0);
2381 info
->statusflags
|= TXSTOPPED
;
2384 restore_flags(flags
);
2388 static void pcxe_throttle(struct tty_struct
* tty
)
2390 struct channel
*info
;
2392 if ((info
=chan(tty
))!=NULL
) {
2393 unsigned long flags
;
2396 if ((info
->statusflags
& RXSTOPPED
) == 0) {
2398 fepcmd(info
, PAUSERX
, 0, 0, 0, 0);
2399 info
->statusflags
|= RXSTOPPED
;
2402 restore_flags(flags
);
2406 static void pcxe_unthrottle(struct tty_struct
*tty
)
2408 struct channel
*info
;
2410 if ((info
=chan(tty
)) != NULL
) {
2411 unsigned long flags
;
2413 /* Just in case output was resumed because of a change in Digi-flow */
2416 if(info
->statusflags
& RXSTOPPED
) {
2417 volatile struct board_chan
*bc
;
2420 fepcmd(info
, RESUMERX
, 0, 0, 0, 0);
2421 info
->statusflags
&= ~RXSTOPPED
;
2424 restore_flags(flags
);
2429 static void pcxe_start(struct tty_struct
*tty
)
2431 struct channel
*info
;
2433 if ((info
=chan(tty
))!=NULL
) {
2434 unsigned long flags
;
2438 /* Just in case output was resumed because of a change in Digi-flow */
2439 if(info
->statusflags
& TXSTOPPED
) {
2440 volatile struct board_chan
*bc
;
2443 if(info
->statusflags
& LOWWAIT
)
2445 fepcmd(info
, RESUMETX
, 0, 0, 0, 0);
2446 info
->statusflags
&= ~TXSTOPPED
;
2449 restore_flags(flags
);
2454 void digi_send_break(struct channel
*ch
, int msec
)
2456 unsigned long flags
;
2463 * Maybe I should send an infinite break here, schedule() for
2464 * msec amount of time, and then stop the break. This way,
2465 * the user can't screw up the FEP by causing digi_send_break()
2466 * to be called (i.e. via an ioctl()) more than once in msec amount
2467 * of time. Try this for now...
2470 fepcmd(ch
, SENDBREAK
, msec
, 0, 10, 0);
2473 restore_flags(flags
);
2476 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
)
2478 volatile struct board_chan
*bc
;
2479 unsigned long flags
;
2484 ch
->statusflags
|= EMPTYWAIT
;
2488 restore_flags(flags
);