2 * linux/drivers/char/pcxx.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 (christoph@lameter.com)
17 * Please contact digi for support issues at digilnux@dgii.com.
18 * Some more information can be found at
19 * http://lameter.com/digi.
21 * 1.5.2 Fall 1995 Bug fixes by David Nugent
22 * 1.5.3 March 9, 1996 Christoph Lameter: Fixed 115.2K Support. Memory
23 * allocation harmonized with 1.3.X Series.
24 * 1.5.4 March 30, 1996 Christoph Lameter: Fixup for 1.3.81. Use init_bh
25 * instead of direct assignment to kernel arrays.
26 * 1.5.5 April 5, 1996 Major device numbers corrected.
27 * Mike McLagan<mike.mclagan@linux.org>: Add setup
28 * variable handling, instead of using the old pcxxconfig.h
29 * 1.5.6 April 16, 1996 Christoph Lameter: Pointer cleanup, macro cleanup.
30 * Call out devices changed to /dev/cudxx.
31 * 1.5.7 July 22, 1996 Martin Mares: CLOCAL fix, pcxe_table clearing.
32 * David Nugent: Bug in pcxe_open.
33 * Brian J. Murrell: Modem Control fixes, Majors correctly assigned
34 * 1.6.1 April 6, 1997 Bernhard Kaindl: fixed virtual memory access for 2.1
35 * i386-kernels and use on other archtitectures, Allowing use
36 * as module, added module parameters, added switch to enable
37 * verbose messages to assist user during card configuration.
38 * Currently only tested on a PC/Xi card, but should work on Xe
40 * 1.6.2 August, 7, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
41 * get rid of panics, release previously allocated resources
42 * 1.6.3 August, 23, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
43 * cleaned up wrt verify_area.
44 * Christoph Lameter: Update documentation, email addresses
45 * and URLs. Remove some obsolete code.
49 #include <linux/module.h>
51 #include <linux/ioport.h>
52 #include <linux/errno.h>
53 #include <linux/signal.h>
54 #include <linux/sched.h>
55 #include <linux/timer.h>
56 #include <linux/interrupt.h>
57 #include <linux/tty.h>
58 #include <linux/tty_flip.h>
59 #include <linux/major.h>
60 #include <linux/string.h>
61 #include <linux/fcntl.h>
62 #include <linux/ptrace.h>
63 #include <linux/delay.h>
64 #include <linux/serial.h>
65 #include <linux/tty_driver.h>
66 #include <linux/malloc.h>
67 #include <linux/init.h>
68 #include <linux/version.h>
71 #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
74 #include <asm/system.h>
76 #include <asm/uaccess.h>
77 #include <asm/bitops.h>
78 #include <asm/semaphore.h>
80 #define VERSION "1.6.3"
86 #include "digi_bios.h"
89 * Define one default setting if no digi= config line is used.
90 * Default is altpin = disabled, 16 ports, I/O 200h, Memory 0D0000h
92 static struct board_info boards
[MAX_DIGI_BOARDS
] = { {
93 /* Board is enabled */ ENABLED
,
94 /* Type is auto-detected */ 0,
95 /* altping is disabled */ DISABLED
,
96 /* number of ports = 16 */ 16,
97 /* io address is 0x200 */ 0x200,
98 /* card memory at 0xd0000 */ 0xd0000,
99 /* first minor device no. */ 0
102 static int verbose
= 0;
103 static int debug
= 0;
106 /* Variables for insmod */
107 static int io
[] = {0, 0, 0, 0};
108 static int membase
[] = {0, 0, 0, 0};
109 static int memsize
[] = {0, 0, 0, 0};
110 static int altpin
[] = {0, 0, 0, 0};
111 static int numports
[] = {0, 0, 0, 0};
113 # if (LINUX_VERSION_CODE > 0x020111)
114 MODULE_AUTHOR("Bernhard Kaindl");
115 MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
116 MODULE_PARM(verbose
, "i");
117 MODULE_PARM(debug
, "i");
118 MODULE_PARM(io
, "1-4i");
119 MODULE_PARM(membase
, "1-4i");
120 MODULE_PARM(memsize
, "1-4i");
121 MODULE_PARM(altpin
, "1-4i");
122 MODULE_PARM(numports
, "1-4i");
127 static int numcards
= 1;
128 static int nbdevs
= 0;
130 static struct channel
*digi_channels
;
131 static struct tty_struct
**pcxe_table
;
132 static struct termios
**pcxe_termios
;
133 static struct termios
**pcxe_termios_locked
;
135 int pcxx_ncook
=sizeof(pcxx_cook
);
136 int pcxx_nbios
=sizeof(pcxx_bios
);
138 #define MIN(a,b) ((a) < (b) ? (a) : (b))
139 #define pcxxassert(x, msg) if(!(x)) pcxx_error(__LINE__, msg)
141 #define FEPTIMEOUT 200000
142 #define SERIAL_TYPE_NORMAL 1
143 #define SERIAL_TYPE_CALLOUT 2
144 #define PCXE_EVENT_HANGUP 1
146 struct tty_driver pcxe_driver
;
147 struct tty_driver pcxe_callout
;
148 static int pcxe_refcount
;
150 static struct timer_list pcxx_timer
;
152 DECLARE_TASK_QUEUE(tq_pcxx
);
154 static void pcxxpoll(unsigned long dummy
);
155 static void pcxxdelay(int);
156 static void fepcmd(struct channel
*, int, int, int, int, int);
157 static void pcxe_put_char(struct tty_struct
*, unsigned char);
158 static void pcxe_flush_chars(struct tty_struct
*);
159 static void pcxx_error(int, char *);
160 static void pcxe_close(struct tty_struct
*, struct file
*);
161 static int pcxe_ioctl(struct tty_struct
*, struct file
*, unsigned int, unsigned long);
162 static void pcxe_set_termios(struct tty_struct
*, struct termios
*);
163 static int pcxe_write(struct tty_struct
*, int, const unsigned char *, int);
164 static int pcxe_write_room(struct tty_struct
*);
165 static int pcxe_chars_in_buffer(struct tty_struct
*);
166 static void pcxe_flush_buffer(struct tty_struct
*);
167 static void doevent(int);
168 static void receive_data(struct channel
*);
169 static void pcxxparam(struct tty_struct
*, struct channel
*ch
);
170 static void do_softint(void *);
171 static inline void pcxe_sched_event(struct channel
*, int);
172 static void do_pcxe_bh(void);
173 static void pcxe_start(struct tty_struct
*);
174 static void pcxe_stop(struct tty_struct
*);
175 static void pcxe_throttle(struct tty_struct
*);
176 static void pcxe_unthrottle(struct tty_struct
*);
177 static void digi_send_break(struct channel
*ch
, int msec
);
178 static void shutdown(struct channel
*);
179 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
);
180 static inline void memwinon(struct board_info
*b
, unsigned int win
);
181 static inline void memwinoff(struct board_info
*b
, unsigned int win
);
182 static inline void globalwinon(struct channel
*ch
);
183 static inline void rxwinon(struct channel
*ch
);
184 static inline void txwinon(struct channel
*ch
);
185 static inline void memoff(struct channel
*ch
);
186 static inline void assertgwinon(struct channel
*ch
);
187 static inline void assertmemoff(struct channel
*ch
);
189 #define TZ_BUFSZ 4096
191 /* function definitions */
193 /*****************************************************************************/
195 static void cleanup_board_resources(void)
198 struct board_info
*bd
;
201 for(crd
= 0; crd
< numcards
; crd
++) {
203 ch
= digi_channels
+ bd
->first_minor
;
206 release_region(bd
->port
, 4);
208 for(i
= 0; i
< bd
->numports
; i
++, ch
++)
214 /*****************************************************************************/
219 * pcxe_init() is our init_module():
221 #define pcxe_init init_module
223 void cleanup_module(void);
226 /*****************************************************************************/
228 void cleanup_module()
234 printk(KERN_NOTICE
"Unloading PC/Xx version %s\n", VERSION
);
238 del_timer_sync(&pcxx_timer
);
241 if ((e1
= tty_unregister_driver(&pcxe_driver
)))
242 printk("SERIAL: failed to unregister serial driver (%d)\n", e1
);
243 if ((e2
= tty_unregister_driver(&pcxe_callout
)))
244 printk("SERIAL: failed to unregister callout driver (%d)\n",e2
);
246 cleanup_board_resources();
247 kfree(digi_channels
);
248 kfree(pcxe_termios_locked
);
251 restore_flags(flags
);
255 static inline struct channel
*chan(register struct tty_struct
*tty
)
258 register struct channel
*ch
=(struct channel
*)tty
->driver_data
;
259 if (ch
>= digi_channels
&& ch
< digi_channels
+nbdevs
) {
260 if (ch
->magic
==PCXX_MAGIC
)
267 /* These inline routines are to turn board memory on and off */
268 static inline void memwinon(struct board_info
*b
, unsigned int win
)
270 if(b
->type
== PCXEVE
)
271 outb_p(FEPWIN
|win
, b
->port
+1);
273 outb_p(inb(b
->port
)|FEPMEM
, b
->port
);
276 static inline void memwinoff(struct board_info
*b
, unsigned int win
)
278 outb_p(inb(b
->port
)&~FEPMEM
, b
->port
);
279 if(b
->type
== PCXEVE
)
280 outb_p(0, b
->port
+ 1);
283 static inline void globalwinon(struct channel
*ch
)
285 if(ch
->board
->type
== PCXEVE
)
286 outb_p(FEPWIN
, ch
->board
->port
+1);
288 outb_p(FEPMEM
, ch
->board
->port
);
291 static inline void rxwinon(struct channel
*ch
)
294 outb_p(FEPMEM
, ch
->board
->port
);
296 outb_p(ch
->rxwin
, ch
->board
->port
+1);
299 static inline void txwinon(struct channel
*ch
)
302 outb_p(FEPMEM
, ch
->board
->port
);
304 outb_p(ch
->txwin
, ch
->board
->port
+1);
307 static inline void memoff(struct channel
*ch
)
309 outb_p(0, ch
->board
->port
);
310 if(ch
->board
->type
== PCXEVE
)
311 outb_p(0, ch
->board
->port
+1);
314 static inline void assertgwinon(struct channel
*ch
)
316 if(ch
->board
->type
!= PCXEVE
)
317 pcxxassert(inb(ch
->board
->port
) & FEPMEM
, "Global memory off");
320 static inline void assertmemoff(struct channel
*ch
)
322 if(ch
->board
->type
!= PCXEVE
)
323 pcxxassert(!(inb(ch
->board
->port
) & FEPMEM
), "Memory on");
326 static inline void pcxe_sched_event(struct channel
*info
, int event
)
328 info
->event
|= 1 << event
;
329 queue_task(&info
->tqueue
, &tq_pcxx
);
333 static void pcxx_error(int line
, char *msg
)
335 printk("pcxx_error (DigiBoard): line=%d %s\n", line
, msg
);
338 static int pcxx_waitcarrier(struct tty_struct
*tty
,struct file
*filp
,struct channel
*info
)
340 DECLARE_WAITQUEUE(wait
, current
);
344 if (info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
345 if (info
->normal_termios
.c_cflag
& CLOCAL
)
348 if (tty
->termios
->c_cflag
& CLOCAL
)
353 * Block waiting for the carrier detect and the line to become free
357 add_wait_queue(&info
->open_wait
, &wait
);
359 info
->blocked_open
++;
363 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0) {
365 info
->omodem
|= DTR
|RTS
;
366 fepcmd(info
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
370 set_current_state(TASK_INTERRUPTIBLE
);
371 if(tty_hung_up_p(filp
) || (info
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
372 if(info
->asyncflags
& ASYNC_HUP_NOTIFY
)
375 retval
= -ERESTARTSYS
;
378 if ((info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) == 0 &&
379 (info
->asyncflags
& ASYNC_CLOSING
) == 0 &&
380 (do_clocal
|| (info
->imodem
& info
->dcd
)))
382 if(signal_pending(current
)) {
383 retval
= -ERESTARTSYS
;
388 current
->state
= TASK_RUNNING
;
389 remove_wait_queue(&info
->open_wait
, &wait
);
391 if(!tty_hung_up_p(filp
))
393 info
->blocked_open
--;
399 int pcxe_open(struct tty_struct
*tty
, struct file
* filp
)
401 volatile struct board_chan
*bc
;
408 line
= MINOR(tty
->device
) - tty
->driver
.minor_start
;
410 if(line
< 0 || line
>= nbdevs
) {
411 printk("line out of range in pcxe_open\n");
412 tty
->driver_data
= NULL
;
416 for(boardnum
=0;boardnum
<numcards
;boardnum
++)
417 if ((line
>= boards
[boardnum
].first_minor
) &&
418 (line
< boards
[boardnum
].first_minor
+ boards
[boardnum
].numports
))
421 if(boardnum
>= numcards
|| boards
[boardnum
].status
== DISABLED
||
422 (line
- boards
[boardnum
].first_minor
) >= boards
[boardnum
].numports
) {
423 tty
->driver_data
= NULL
; /* Mark this device as 'down' */
427 ch
= digi_channels
+line
;
429 if(ch
->brdchan
== 0) {
430 tty
->driver_data
= NULL
;
434 /* flag the kernel that there is somebody using this guy */
437 * If the device is in the middle of being closed, then block
438 * until it's done, and then try again.
440 if(ch
->asyncflags
& ASYNC_CLOSING
) {
441 interruptible_sleep_on(&ch
->close_wait
);
442 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
451 tty
->driver_data
= ch
;
454 if ((ch
->asyncflags
& ASYNC_INITIALIZED
) == 0) {
460 ch
->imodem
= bc
->mstat
;
465 ch
->imodem
= bc
->mstat
;
467 ch
->omodem
= DTR
|RTS
;
468 fepcmd(ch
, SETMODEM
, DTR
|RTS
, 0, 10, 1);
470 ch
->asyncflags
|= ASYNC_INITIALIZED
;
472 restore_flags(flags
);
474 if(ch
->asyncflags
& ASYNC_CLOSING
) {
475 interruptible_sleep_on(&ch
->close_wait
);
476 if(ch
->asyncflags
& ASYNC_HUP_NOTIFY
)
482 * If this is a callout device, then just make sure the normal
483 * device isn't being used.
485 if (tty
->driver
.subtype
== SERIAL_TYPE_CALLOUT
) {
486 if (ch
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
488 if (ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
) {
489 if ((ch
->asyncflags
& ASYNC_SESSION_LOCKOUT
) &&
490 (ch
->session
!= current
->session
))
492 if((ch
->asyncflags
& ASYNC_PGRP_LOCKOUT
) &&
493 (ch
->pgrp
!= current
->pgrp
))
496 ch
->asyncflags
|= ASYNC_CALLOUT_ACTIVE
;
499 if (filp
->f_flags
& O_NONBLOCK
) {
500 if(ch
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
504 /* this has to be set in order for the "block until
505 * CD" code to work correctly. i'm not sure under
506 * what circumstances asyncflags should be set to
507 * ASYNC_NORMAL_ACTIVE though
510 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
511 if ((retval
= pcxx_waitcarrier(tty
, filp
, ch
)) != 0)
514 ch
->asyncflags
|= ASYNC_NORMAL_ACTIVE
;
519 if((ch
->count
== 1) && (ch
->asyncflags
& ASYNC_SPLIT_TERMIOS
)) {
520 if(tty
->driver
.subtype
== SERIAL_TYPE_NORMAL
)
521 *tty
->termios
= ch
->normal_termios
;
523 *tty
->termios
= ch
->callout_termios
;
529 ch
->session
= current
->session
;
530 ch
->pgrp
= current
->pgrp
;
531 restore_flags(flags
);
535 static void shutdown(struct channel
*info
)
538 volatile struct board_chan
*bc
;
539 struct tty_struct
*tty
;
541 if (!(info
->asyncflags
& ASYNC_INITIALIZED
))
555 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
557 if(tty
->termios
->c_cflag
& HUPCL
) {
558 info
->omodem
&= ~(RTS
|DTR
);
559 fepcmd(info
, SETMODEM
, 0, DTR
|RTS
, 10, 1);
563 info
->asyncflags
&= ~ASYNC_INITIALIZED
;
564 restore_flags(flags
);
568 static void pcxe_close(struct tty_struct
* tty
, struct file
* filp
)
570 struct channel
*info
;
572 if ((info
=chan(tty
))!=NULL
) {
577 if(tty_hung_up_p(filp
)) {
578 /* flag that somebody is done with this module */
580 restore_flags(flags
);
583 /* this check is in serial.c, it won't hurt to do it here too */
584 if ((tty
->count
== 1) && (info
->count
!= 1)) {
586 * Uh, oh. tty->count is 1, which means that the tty
587 * structure will be freed. Info->count should always
588 * be one in these conditions. If it's greater than
589 * one, we've got real problems, since it means the
590 * serial port won't be shutdown.
592 printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info
->count
);
595 if (info
->count
-- > 1) {
596 restore_flags(flags
);
600 if (info
->count
< 0) {
604 info
->asyncflags
|= ASYNC_CLOSING
;
607 * Save the termios structure, since this port may have
608 * separate termios for callout and dialin.
610 if(info
->asyncflags
& ASYNC_NORMAL_ACTIVE
)
611 info
->normal_termios
= *tty
->termios
;
612 if(info
->asyncflags
& ASYNC_CALLOUT_ACTIVE
)
613 info
->callout_termios
= *tty
->termios
;
615 if(info
->asyncflags
& ASYNC_INITIALIZED
) {
616 setup_empty_event(tty
,info
);
617 tty_wait_until_sent(tty
, 3000); /* 30 seconds timeout */
620 if(tty
->driver
.flush_buffer
)
621 tty
->driver
.flush_buffer(tty
);
622 if(tty
->ldisc
.flush_buffer
)
623 tty
->ldisc
.flush_buffer(tty
);
629 /* ldiscs[] is not available in a MODULE
630 ** worth noting that while I'm not sure what this hunk of code is supposed
631 ** to do, it is not present in the serial.c driver. Hmmm. If you know,
632 ** please send me a note. brian@ilinx.com
633 ** Don't know either what this is supposed to do christoph@lameter.com.
635 if(tty
->ldisc
.num
!= ldiscs
[N_TTY
].num
) {
637 (tty
->ldisc
.close
)(tty
);
638 tty
->ldisc
= ldiscs
[N_TTY
];
639 tty
->termios
->c_line
= N_TTY
;
641 (tty
->ldisc
.open
)(tty
);
644 if(info
->blocked_open
) {
645 if(info
->close_delay
) {
646 current
->state
= TASK_INTERRUPTIBLE
;
647 schedule_timeout(info
->close_delay
);
649 wake_up_interruptible(&info
->open_wait
);
651 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|
652 ASYNC_CALLOUT_ACTIVE
|ASYNC_CLOSING
);
653 wake_up_interruptible(&info
->close_wait
);
655 restore_flags(flags
);
660 void pcxe_hangup(struct tty_struct
*tty
)
664 if ((ch
=chan(tty
))!=NULL
) {
673 ch
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
674 wake_up_interruptible(&ch
->open_wait
);
675 restore_flags(flags
);
681 static int pcxe_write(struct tty_struct
* tty
, int from_user
, const unsigned char *buf
, int count
)
684 volatile struct board_chan
*bc
;
685 int total
, remain
, size
, stlen
;
686 unsigned int head
, tail
;
689 /* printk("Entering pcxe_write()\n"); */
691 if ((ch
=chan(tty
))==NULL
)
695 size
= ch
->txbufsize
;
702 head
= bc
->tin
& (size
- 1);
703 /* It seems to be necessary to make sure that the value is stable here somehow
704 This is a rather odd pice of code here. */
707 } while (tail
!= bc
->tout
);
710 stlen
= (head
>= tail
) ? (size
- (head
- tail
) - 1) : (tail
- head
- 1);
711 count
= MIN(stlen
, count
);
713 if (copy_from_user(ch
->tmp_buf
, buf
, count
))
718 restore_flags(flags
);
722 * All data is now local
729 head
= bc
->tin
& (size
- 1);
731 if (tail
!= bc
->tout
)
735 remain
= size
- (head
- tail
) - 1;
739 remain
= tail
- head
- 1;
742 count
= MIN(remain
, count
);
746 stlen
= MIN(count
, stlen
);
747 memcpy(ch
->txptr
+ head
, buf
, stlen
);
757 ch
->statusflags
|= TXBUSY
;
760 if ((ch
->statusflags
& LOWWAIT
) == 0) {
761 ch
->statusflags
|= LOWWAIT
;
765 restore_flags(flags
);
771 static void pcxe_put_char(struct tty_struct
*tty
, unsigned char c
)
773 pcxe_write(tty
, 0, &c
, 1);
778 static int pcxe_write_room(struct tty_struct
*tty
)
784 if ((ch
=chan(tty
))!=NULL
) {
785 volatile struct board_chan
*bc
;
786 unsigned int head
, tail
;
794 head
= bc
->tin
& (ch
->txbufsize
- 1);
796 if (tail
!= bc
->tout
)
798 tail
&= (ch
->txbufsize
- 1);
800 if((remain
= tail
- head
- 1) < 0 )
801 remain
+= ch
->txbufsize
;
803 if (remain
&& (ch
->statusflags
& LOWWAIT
) == 0) {
804 ch
->statusflags
|= LOWWAIT
;
808 restore_flags(flags
);
815 static int pcxe_chars_in_buffer(struct tty_struct
*tty
)
818 unsigned int ctail
, head
, tail
;
822 volatile struct board_chan
*bc
;
824 if ((ch
=chan(tty
))==NULL
)
834 ctail
= ch
->mailbox
->cout
;
835 if(tail
== head
&& ch
->mailbox
->cin
== ctail
&& bc
->tbusy
== 0)
838 head
= bc
->tin
& (ch
->txbufsize
- 1);
839 tail
&= (ch
->txbufsize
- 1);
840 if((remain
= tail
- head
- 1) < 0 )
841 remain
+= ch
->txbufsize
;
843 chars
= (int)(ch
->txbufsize
- remain
);
846 * Make it possible to wakeup anything waiting for output
847 * in tty_ioctl.c, etc.
849 if(!(ch
->statusflags
& EMPTYWAIT
))
850 setup_empty_event(tty
,ch
);
854 restore_flags(flags
);
860 static void pcxe_flush_buffer(struct tty_struct
*tty
)
863 volatile struct board_chan
*bc
;
867 if ((ch
=chan(tty
))==NULL
)
876 fepcmd(ch
, STOUT
, (unsigned) tail
, 0, 0, 0);
879 restore_flags(flags
);
881 wake_up_interruptible(&tty
->write_wait
);
882 if((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) && tty
->ldisc
.write_wakeup
)
883 (tty
->ldisc
.write_wakeup
)(tty
);
886 static void pcxe_flush_chars(struct tty_struct
*tty
)
890 if ((ch
=chan(tty
))!=NULL
) {
895 if ((ch
->statusflags
& TXBUSY
) && !(ch
->statusflags
& EMPTYWAIT
))
896 setup_empty_event(tty
,ch
);
897 restore_flags(flags
);
904 * Driver setup function when linked into the kernel to optionally parse multible
905 * "digi="-lines and initialize the driver at boot time. No probing.
907 void __init
pcxx_setup(char *str
, int *ints
)
910 struct board_info board
;
917 memset(&board
, 0, sizeof(board
));
919 for(last
=0,i
=1;i
<=ints
[0];i
++)
923 board
.status
= ints
[i
];
928 board
.type
= ints
[i
];
933 board
.altpin
= ints
[i
];
938 board
.numports
= ints
[i
];
943 board
.port
= ints
[i
];
948 board
.membase
= ints
[i
];
953 printk("PC/Xx: Too many integer parms\n");
959 /* find the next comma or terminator */
961 while (*temp
&& (*temp
!= ','))
975 if (strncmp("Disable", str
, len
) == 0)
978 if (strncmp("Enable", str
, len
) == 0)
982 printk("PC/Xx: Invalid status %s\n", str
);
989 for(j
=0;j
<PCXX_NUM_TYPES
;j
++)
990 if (strcmp(board_desc
[j
], str
) == 0)
993 if (i
<PCXX_NUM_TYPES
)
997 printk("PC/Xx: Invalid board name: %s\n", str
);
1005 if (strncmp("Disable", str
, len
) == 0)
1008 if (strncmp("Enable", str
, len
) == 0)
1012 printk("PC/Xx: Invalid altpin %s\n", str
);
1020 while (isdigit(*t2
))
1025 printk("PC/Xx: Invalid port count %s\n", str
);
1029 board
.numports
= simple_strtoul(str
, NULL
, 0);
1035 while (isxdigit(*t2
))
1040 printk("PC/Xx: Invalid io port address %s\n", str
);
1044 board
.port
= simple_strtoul(str
, NULL
, 16);
1050 while (isxdigit(*t2
))
1055 printk("PC/Xx: Invalid memory base %s\n", str
);
1059 board
.membase
= simple_strtoul(str
, NULL
, 16);
1064 printk("PC/Xx: Too many string parms\n");
1072 printk("PC/Xx: Insufficient parms specified\n");
1076 /* I should REALLY validate the stuff here */
1078 memcpy(&boards
[numcards
],&board
, sizeof(board
));
1079 printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n",
1080 numcards
, board_desc
[board
.type
], board_mem
[board
.type
],
1081 board
.numports
, board
.port
, (unsigned int) board
.membase
);
1083 /* keep track of my initial minor number */
1085 boards
[numcards
].first_minor
= boards
[numcards
-1].first_minor
+ boards
[numcards
-1].numports
;
1087 boards
[numcards
].first_minor
= 0;
1089 /* yeha! string parameter was successful! */
1095 * function to initialize the driver with the given parameters, which are either
1096 * the default values from this file or the parameters given at boot.
1098 int __init
pcxe_init(void)
1100 ulong memory_seg
=0, memory_size
=0;
1101 int lowwater
, enabled_cards
=0, i
, crd
, shrinkmem
=0, topwin
= 0xff00L
, botwin
=0x100L
;
1103 unchar
*fepos
, *memaddr
, *bios
, v
;
1104 volatile struct global_data
*gd
;
1105 volatile struct board_chan
*bc
;
1106 struct board_info
*bd
;
1109 printk(KERN_NOTICE
"Digiboard PC/X{i,e,eve} driver v%s\n", VERSION
);
1112 for (i
= 0; i
< MAX_DIGI_BOARDS
; i
++) {
1118 if (numcards
== 0) {
1119 int first_minor
= 0;
1121 for (i
= 0; i
< MAX_DIGI_BOARDS
; i
++) {
1124 boards
[i
].status
= DISABLED
;
1127 boards
[i
].port
= (ushort
)io
[i
];
1128 boards
[i
].status
= ENABLED
;
1129 boards
[i
].first_minor
= first_minor
;
1133 boards
[i
].membase
= (ulong
)membase
[i
];
1135 boards
[i
].membase
= 0xD0000;
1138 boards
[i
].memsize
= (ulong
)(memsize
[i
] * 1024);
1140 boards
[i
].memsize
= 0;
1143 boards
[i
].altpin
= ON
;
1145 boards
[i
].altpin
= OFF
;
1148 boards
[i
].numports
= (ushort
)numports
[i
];
1150 boards
[i
].numports
= 16;
1152 boards
[i
].region
= NULL
;
1153 first_minor
+= boards
[i
].numports
;
1160 printk("PC/Xx: No cards configured, driver not active.\n");
1165 for (i
= 0; i
< numcards
; i
++) {
1166 printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",
1174 boards
[i
].first_minor
);
1178 for (i
=0;i
<numcards
;i
++)
1179 nbdevs
+= boards
[i
].numports
;
1183 printk("PC/Xx: No devices activated, driver not active.\n");
1188 * this turns out to be more memory efficient, as there are no
1191 digi_channels
= kmalloc(sizeof(struct channel
) * nbdevs
, GFP_KERNEL
);
1192 if (!digi_channels
) {
1193 printk(KERN_ERR
"Unable to allocate digi_channel struct\n");
1196 memset(digi_channels
, 0, sizeof(struct channel
) * nbdevs
);
1198 pcxe_table
= kmalloc(sizeof(struct tty_struct
*) * nbdevs
, GFP_KERNEL
);
1200 printk(KERN_ERR
"Unable to allocate pcxe_table struct\n");
1201 goto cleanup_digi_channels
;
1203 memset(pcxe_table
, 0, sizeof(struct tty_struct
*) * nbdevs
);
1205 pcxe_termios
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1206 if (!pcxe_termios
) {
1207 printk(KERN_ERR
"Unable to allocate pcxe_termios struct\n");
1208 goto cleanup_pcxe_table
;
1210 memset(pcxe_termios
,0,sizeof(struct termios
*)*nbdevs
);
1212 pcxe_termios_locked
= kmalloc(sizeof(struct termios
*) * nbdevs
, GFP_KERNEL
);
1213 if (!pcxe_termios_locked
) {
1214 printk(KERN_ERR
"Unable to allocate pcxe_termios_locked struct\n");
1215 goto cleanup_pcxe_termios
;
1217 memset(pcxe_termios_locked
,0,sizeof(struct termios
*)*nbdevs
);
1219 init_bh(DIGI_BH
,do_pcxe_bh
);
1221 init_timer(&pcxx_timer
);
1222 pcxx_timer
.function
= pcxxpoll
;
1224 memset(&pcxe_driver
, 0, sizeof(struct tty_driver
));
1225 pcxe_driver
.magic
= TTY_DRIVER_MAGIC
;
1226 pcxe_driver
.name
= "ttyD";
1227 pcxe_driver
.major
= DIGI_MAJOR
;
1228 pcxe_driver
.minor_start
= 0;
1230 pcxe_driver
.num
= nbdevs
;
1232 pcxe_driver
.type
= TTY_DRIVER_TYPE_SERIAL
;
1233 pcxe_driver
.subtype
= SERIAL_TYPE_NORMAL
;
1234 pcxe_driver
.init_termios
= tty_std_termios
;
1235 pcxe_driver
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
;
1236 pcxe_driver
.flags
= TTY_DRIVER_REAL_RAW
;
1237 pcxe_driver
.refcount
= &pcxe_refcount
;
1239 pcxe_driver
.table
= pcxe_table
;
1240 pcxe_driver
.termios
= pcxe_termios
;
1241 pcxe_driver
.termios_locked
= pcxe_termios_locked
;
1243 pcxe_driver
.open
= pcxe_open
;
1244 pcxe_driver
.close
= pcxe_close
;
1245 pcxe_driver
.write
= pcxe_write
;
1246 pcxe_driver
.put_char
= pcxe_put_char
;
1247 pcxe_driver
.flush_chars
= pcxe_flush_chars
;
1248 pcxe_driver
.write_room
= pcxe_write_room
;
1249 pcxe_driver
.chars_in_buffer
= pcxe_chars_in_buffer
;
1250 pcxe_driver
.flush_buffer
= pcxe_flush_buffer
;
1251 pcxe_driver
.ioctl
= pcxe_ioctl
;
1252 pcxe_driver
.throttle
= pcxe_throttle
;
1253 pcxe_driver
.unthrottle
= pcxe_unthrottle
;
1254 pcxe_driver
.set_termios
= pcxe_set_termios
;
1255 pcxe_driver
.stop
= pcxe_stop
;
1256 pcxe_driver
.start
= pcxe_start
;
1257 pcxe_driver
.hangup
= pcxe_hangup
;
1259 pcxe_callout
= pcxe_driver
;
1260 pcxe_callout
.name
= "cud";
1261 pcxe_callout
.major
= DIGICU_MAJOR
;
1262 pcxe_callout
.subtype
= SERIAL_TYPE_CALLOUT
;
1263 pcxe_callout
.init_termios
.c_cflag
= B9600
| CS8
| CREAD
| HUPCL
| CLOCAL
;
1265 for(crd
=0; crd
< numcards
; crd
++) {
1267 outb(FEPRST
, bd
->port
);
1270 for(i
=0; (inb(bd
->port
) & FEPMASK
) != FEPRST
; i
++) {
1272 printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
1274 bd
->status
= DISABLED
;
1282 if(bd
->status
== DISABLED
)
1287 if((v
& 0x1) == 0x1) {
1288 if((v
& 0x30) == 0) { /* PC/Xi 64K card */
1289 memory_seg
= 0xf000;
1290 memory_size
= 0x10000;
1293 if((v
& 0x30) == 0x10) { /* PC/Xi 128K card */
1294 memory_seg
= 0xe000;
1295 memory_size
= 0x20000;
1298 if((v
& 0x30) == 0x20) { /* PC/Xi 256K card */
1299 memory_seg
= 0xc000;
1300 memory_size
= 0x40000;
1303 if((v
& 0x30) == 0x30) { /* PC/Xi 512K card */
1304 memory_seg
= 0x8000;
1305 memory_size
= 0x80000;
1309 if((v
& 0x1) == 0x1) {
1310 bd
->status
= DISABLED
; /* PC/Xm unsupported card */
1311 printk("PC/Xx: PC/Xm at 0x%x not supported!!\n", bd
->port
);
1316 outb((((ulong
)bd
->membase
>>8) & 0xe0) | 0x10, bd
->port
+2);
1317 outb(((ulong
)bd
->membase
>>16) & 0xff, bd
->port
+3);
1318 bd
->type
= PCXEVE
; /* PC/Xe 8K card */
1320 bd
->type
= PCXE
; /* PC/Xe 64K card */
1323 memory_seg
= 0xf000;
1324 memory_size
= 0x10000;
1328 printk("Configuring card %d as a %s %ldK card. io=0x%x, mem=%lx-%lx\n",
1329 crd
+1, board_desc
[bd
->type
], memory_size
/1024,
1330 bd
->port
,bd
->membase
,bd
->membase
+memory_size
-1);
1332 if (boards
[crd
].memsize
== 0)
1333 boards
[crd
].memsize
= memory_size
;
1335 if (boards
[crd
].memsize
!= memory_size
) {
1336 printk("PC/Xx: memory size mismatch:supplied=%lx(%ldK) probed=%ld(%ldK)\n",
1337 boards
[crd
].memsize
, boards
[crd
].memsize
/ 1024,
1338 memory_size
, memory_size
/ 1024);
1342 memaddr
= (unchar
*)phys_to_virt(bd
->membase
);
1345 printk("Resetting board and testing memory access:");
1347 outb(FEPRST
|FEPMEM
, bd
->port
);
1349 for(i
=0; (inb(bd
->port
) & FEPMASK
) != (FEPRST
|FEPMEM
); i
++) {
1351 printk("\nPC/Xx: %s not resetting at port 0x%x! Check switch settings.\n",
1352 board_desc
[bd
->type
], bd
->port
);
1353 bd
->status
= DISABLED
;
1361 if(bd
->status
== DISABLED
)
1365 *(ulong
*)(memaddr
+ botwin
) = 0xa55a3cc3;
1366 *(ulong
*)(memaddr
+ topwin
) = 0x5aa5c33c;
1368 if(*(ulong
*)(memaddr
+ botwin
) != 0xa55a3cc3 ||
1369 *(ulong
*)(memaddr
+ topwin
) != 0x5aa5c33c) {
1370 printk("PC/Xx: Failed memory test at %lx for %s at port %x, check switch settings.\n",
1371 bd
->membase
, board_desc
[bd
->type
], bd
->port
);
1372 bd
->status
= DISABLED
;
1378 for(i
=0; i
< 16; i
++) {
1379 memaddr
[MISCGLOBAL
+i
] = 0;
1382 if(bd
->type
== PCXI
|| bd
->type
== PCXE
) {
1383 bios
= memaddr
+ BIOSCODE
+ ((0xf000 - memory_seg
) << 4);
1386 printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios
));
1388 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1393 outb(FEPMEM
, bd
->port
);
1396 printk("Waiting for BIOS to become ready");
1398 for(i
=1; i
<= 30; i
++) {
1399 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1413 printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n",
1414 bd
->port
, bd
->membase
, bd
->membase
+bd
->memsize
);
1415 bd
->status
= DISABLED
;
1419 if(bd
->type
== PCXEVE
) {
1420 bios
= memaddr
+ (BIOSCODE
& 0x1fff);
1423 memcpy(bios
, pcxx_bios
, pcxx_nbios
);
1425 outb(FEPCLR
, bd
->port
);
1428 for(i
=0; i
<= 1000; i
++) {
1429 if(*(ushort
*)((ulong
)memaddr
+ MISCGLOBAL
) == *(ushort
*)"GD" ) {
1443 printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n",
1444 board_desc
[bd
->type
], bd
->port
);
1445 bd
->status
= DISABLED
;
1450 fepos
= memaddr
+ FEPCODE
;
1451 if(bd
->type
== PCXEVE
)
1452 fepos
= memaddr
+ (FEPCODE
& 0x1fff);
1455 printk(" ok.\nDownloading FEP/OS to 0x%lx:", virt_to_phys(fepos
));
1457 memwinon(bd
, (FEPCODE
>> 13));
1458 memcpy(fepos
, pcxx_cook
, pcxx_ncook
);
1464 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 0) = 2;
1465 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 2) = memory_seg
+ FEPCODESEG
;
1466 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 4) = 0;
1467 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 6) = FEPCODESEG
;
1468 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 8) = 0;
1469 *(ushort
*)((ulong
)memaddr
+ MBOX
+ 10) = pcxx_ncook
;
1471 outb(FEPMEM
|FEPINT
, bd
->port
);
1472 outb(FEPMEM
, bd
->port
);
1474 for(i
=0; *(ushort
*)((ulong
)memaddr
+ MBOX
); i
++) {
1476 printk("PC/Xx: Command failed for the %s at 0x%x!\n",
1477 board_desc
[bd
->type
], bd
->port
);
1478 bd
->status
= DISABLED
;
1487 if(bd
->status
== DISABLED
)
1491 printk("Waiting for FEP/OS to become ready");
1493 *(ushort
*)(memaddr
+ FEPSTAT
) = 0;
1494 *(ushort
*)(memaddr
+ MBOX
+ 0) = 1;
1495 *(ushort
*)(memaddr
+ MBOX
+ 2) = FEPCODESEG
;
1496 *(ushort
*)(memaddr
+ MBOX
+ 4) = 0x4L
;
1498 outb(FEPINT
, bd
->port
);
1499 outb(FEPCLR
, bd
->port
);
1502 for(i
=1; *(ushort
*)((ulong
)memaddr
+ FEPSTAT
) != *(ushort
*)"OS"; i
++) {
1504 printk("\nPC/Xx: FEP/OS download failed on the %s at 0x%x!\n",
1505 board_desc
[bd
->type
], bd
->port
);
1506 bd
->status
= DISABLED
;
1512 printk("\n%5d",i
/50);
1519 if(bd
->status
== DISABLED
)
1525 ch
= digi_channels
+bd
->first_minor
;
1526 pcxxassert(ch
< digi_channels
+nbdevs
, "ch out of range");
1528 bc
= (volatile struct board_chan
*)((ulong
)memaddr
+ CHANSTRUCT
);
1529 gd
= (volatile struct global_data
*)((ulong
)memaddr
+ GLOBAL
);
1531 if((bd
->type
== PCXEVE
) && (*(ushort
*)((ulong
)memaddr
+NPORT
) < 3))
1534 bd
->region
= request_region(bd
->port
, 4, "PC/Xx");
1537 printk(KERN_ERR
"I/O port 0x%x is already used\n", bd
->port
);
1539 goto cleanup_boards
;
1542 for(i
=0; i
< bd
->numports
; i
++, ch
++, bc
++) {
1543 if(((ushort
*)((ulong
)memaddr
+ PORTBASE
))[i
] == 0) {
1549 ch
->tqueue
.routine
= do_softint
;
1550 ch
->tqueue
.data
= ch
;
1551 ch
->board
= &boards
[crd
];
1552 #ifdef DEFAULT_HW_FLOW
1553 ch
->digiext
.digi_flags
= RTSPACE
|CTSPACE
;
1555 if(boards
[crd
].altpin
) {
1558 ch
->digiext
.digi_flags
|= DIGI_ALTPIN
;
1564 ch
->magic
= PCXX_MAGIC
;
1568 ch
->dev
= bd
->first_minor
+ i
;
1572 fepcmd(ch
, SETBUFFER
, 32, 0, 0, 0);
1576 if(bd
->type
!= PCXEVE
) {
1577 ch
->txptr
= memaddr
+((bc
->tseg
-memory_seg
) << 4);
1578 ch
->rxptr
= memaddr
+((bc
->rseg
-memory_seg
) << 4);
1579 ch
->txwin
= ch
->rxwin
= 0;
1581 ch
->txptr
= memaddr
+(((bc
->tseg
-memory_seg
) << 4) & 0x1fff);
1582 ch
->txwin
= FEPWIN
| ((bc
->tseg
-memory_seg
) >> 9);
1583 ch
->rxptr
= memaddr
+(((bc
->rseg
-memory_seg
) << 4) & 0x1fff);
1584 ch
->rxwin
= FEPWIN
| ((bc
->rseg
-memory_seg
) >>9 );
1587 ch
->txbufsize
= bc
->tmax
+ 1;
1588 ch
->rxbufsize
= bc
->rmax
+ 1;
1589 ch
->tmp_buf
= kmalloc(ch
->txbufsize
,GFP_KERNEL
);
1592 printk(KERN_ERR
"Unable to allocate memory for temp buffers\n");
1593 goto cleanup_boards
;
1596 lowwater
= ch
->txbufsize
>= 2000 ? 1024 : ch
->txbufsize
/2;
1597 fepcmd(ch
, STXLWATER
, lowwater
, 0, 10, 0);
1598 fepcmd(ch
, SRXLWATER
, ch
->rxbufsize
/4, 0, 10, 0);
1599 fepcmd(ch
, SRXHWATER
, 3 * ch
->rxbufsize
/4, 0, 10, 0);
1604 ch
->startc
= bc
->startc
;
1605 ch
->stopc
= bc
->stopc
;
1606 ch
->startca
= bc
->startca
;
1607 ch
->stopca
= bc
->stopca
;
1617 ch
->close_delay
= 50;
1619 ch
->blocked_open
= 0;
1620 ch
->callout_termios
= pcxe_callout
.init_termios
;
1621 ch
->normal_termios
= pcxe_driver
.init_termios
;
1622 init_waitqueue_head(&ch
->open_wait
);
1623 init_waitqueue_head(&ch
->close_wait
);
1628 printk("Card No. %d ready: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1629 crd
+1, board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1630 bd
->membase
, bd
->numports
);
1632 printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1633 board_desc
[bd
->type
], board_mem
[bd
->type
], bd
->port
,
1634 bd
->membase
, bd
->numports
);
1640 if (enabled_cards
<= 0) {
1641 printk(KERN_NOTICE
"PC/Xx: No cards enabled, no driver.\n");
1643 goto cleanup_boards
;
1646 ret
= tty_register_driver(&pcxe_driver
);
1648 printk(KERN_ERR
"Couldn't register PC/Xe driver\n");
1649 goto cleanup_boards
;
1652 ret
= tty_register_driver(&pcxe_callout
);
1654 printk(KERN_ERR
"Couldn't register PC/Xe callout\n");
1655 goto cleanup_pcxe_driver
;
1659 * Start up the poller to check for events on all enabled boards
1661 mod_timer(&pcxx_timer
, HZ
/25);
1664 printk(KERN_NOTICE
"PC/Xx: Driver with %d card(s) ready.\n", enabled_cards
);
1667 cleanup_pcxe_driver
: tty_unregister_driver(&pcxe_driver
);
1668 cleanup_boards
: cleanup_board_resources();
1669 kfree(pcxe_termios_locked
);
1670 cleanup_pcxe_termios
: kfree(pcxe_termios
);
1671 cleanup_pcxe_table
: kfree(pcxe_table
);
1672 cleanup_digi_channels
: kfree(digi_channels
);
1677 static void pcxxpoll(unsigned long dummy
)
1679 unsigned long flags
;
1681 volatile unsigned int head
, tail
;
1683 struct board_info
*bd
;
1688 for(crd
=0; crd
< numcards
; crd
++) {
1691 ch
= digi_channels
+bd
->first_minor
;
1693 if(bd
->status
== DISABLED
)
1699 head
= ch
->mailbox
->ein
;
1700 tail
= ch
->mailbox
->eout
;
1708 mod_timer(&pcxx_timer
, jiffies
+ HZ
/25);
1709 restore_flags(flags
);
1712 static void doevent(int crd
)
1714 volatile struct board_info
*bd
;
1715 static struct tty_struct
*tty
;
1716 volatile struct board_chan
*bc
;
1717 volatile unchar
*eventbuf
;
1718 volatile unsigned int head
;
1719 volatile unsigned int tail
;
1721 struct channel
*chan0
;
1722 int channel
, event
, mstat
, lstat
;
1726 chan0
= digi_channels
+bd
->first_minor
;
1727 pcxxassert(chan0
< digi_channels
+nbdevs
, "ch out of range");
1730 assertgwinon(chan0
);
1732 while ((tail
= chan0
->mailbox
->eout
) != (head
= chan0
->mailbox
->ein
)) {
1733 assertgwinon(chan0
);
1734 eventbuf
= (volatile unchar
*)phys_to_virt(bd
->membase
+ tail
+ ISTART
);
1735 channel
= eventbuf
[0];
1736 event
= eventbuf
[1];
1737 mstat
= eventbuf
[2];
1738 lstat
= eventbuf
[3];
1742 if ((unsigned)channel
>= bd
->numports
|| !ch
) {
1743 printk("physmem=%lx, tail=%x, head=%x\n", bd
->membase
, tail
, head
);
1744 printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
1745 crd
, (unsigned)channel
, event
, (unsigned)mstat
, lstat
);
1746 if(channel
>= bd
->numports
)
1751 if ((bc
= ch
->brdchan
) == NULL
)
1754 if (event
& DATA_IND
) {
1759 if (event
& MODEMCHG_IND
) {
1761 if (ch
->asyncflags
& (ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
)) {
1762 if (ch
->asyncflags
& ASYNC_CHECK_CD
) {
1763 if (mstat
& ch
->dcd
) {
1764 wake_up_interruptible(&ch
->open_wait
);
1766 pcxe_sched_event(ch
, PCXE_EVENT_HANGUP
);
1776 if (event
& BREAK_IND
) {
1778 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
1779 *tty
->flip
.char_buf_ptr
++ = 0;
1781 if (ch
->asyncflags
& ASYNC_SAK
)
1784 tty_schedule_flip(tty
);
1787 if (event
& LOWTX_IND
) {
1788 if (ch
->statusflags
& LOWWAIT
) {
1789 ch
->statusflags
&= ~LOWWAIT
;
1790 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1791 tty
->ldisc
.write_wakeup
)
1792 (tty
->ldisc
.write_wakeup
)(tty
);
1793 wake_up_interruptible(&tty
->write_wait
);
1797 if (event
& EMPTYTX_IND
) {
1798 ch
->statusflags
&= ~TXBUSY
;
1799 if (ch
->statusflags
& EMPTYWAIT
) {
1800 ch
->statusflags
&= ~EMPTYWAIT
;
1801 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1802 tty
->ldisc
.write_wakeup
)
1803 (tty
->ldisc
.write_wakeup
)(tty
);
1804 wake_up_interruptible(&tty
->write_wait
);
1811 if(!bc
) printk("bc == NULL in doevent!\n");
1814 chan0
->mailbox
->eout
= (tail
+4) & (IMAX
-ISTART
-4);
1822 * pcxxdelay - delays a specified number of milliseconds
1824 static void pcxxdelay(int msec
)
1827 __delay(loops_per_sec
/1000);
1832 fepcmd(struct channel
*ch
, int cmd
, int word_or_byte
, int byte2
, int ncmds
,
1836 unsigned int head
, tail
;
1840 if(ch
->board
->status
== DISABLED
)
1845 memaddr
= (unchar
*)phys_to_virt(ch
->board
->membase
);
1846 head
= ch
->mailbox
->cin
;
1848 if(head
>= (CMAX
-CSTART
) || (head
& 03)) {
1849 printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__
, cmd
, head
);
1854 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1856 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1858 *(unchar
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1859 *(unchar
*)(memaddr
+head
+CSTART
+3) = byte2
;
1861 *(unchar
*)(memaddr
+head
+CSTART
+0) = cmd
;
1863 *(unchar
*)(memaddr
+head
+CSTART
+1) = ch
->dev
- ch
->board
->first_minor
;
1864 *(ushort
*)(memaddr
+head
+CSTART
+2) = word_or_byte
;
1867 head
= (head
+4) & (CMAX
-CSTART
-4);
1868 ch
->mailbox
->cin
= head
;
1875 printk("Fep not responding in fepcmd()\n");
1879 head
= ch
->mailbox
->cin
;
1880 tail
= ch
->mailbox
->cout
;
1882 n
= (head
-tail
) & (CMAX
-CSTART
-4);
1884 if(n
<= ncmds
* (sizeof(short)*4))
1886 /* Seems not to be good here: schedule(); */
1891 static unsigned termios2digi_c(struct channel
*ch
, unsigned cflag
)
1894 if (cflag
& CBAUDEX
)
1896 ch
->digiext
.digi_flags
|= DIGI_FAST
;
1898 /* This gets strange but if we don't do this we will get 78600
1899 * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
1900 * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
1903 if (cflag
& B115200
) res
|=1;
1905 else ch
->digiext
.digi_flags
&= ~DIGI_FAST
;
1906 res
|= cflag
& (CBAUD
| PARODD
| PARENB
| CSTOPB
| CSIZE
| CLOCAL
);
1910 static unsigned termios2digi_i(struct channel
*ch
, unsigned iflag
)
1912 unsigned res
= iflag
& (IGNBRK
|BRKINT
|IGNPAR
|PARMRK
|INPCK
|ISTRIP
|IXON
|IXANY
|IXOFF
);
1914 if(ch
->digiext
.digi_flags
& DIGI_AIXON
)
1919 static unsigned termios2digi_h(struct channel
*ch
, unsigned cflag
)
1923 if(cflag
& CRTSCTS
) {
1924 ch
->digiext
.digi_flags
|= (RTSPACE
|CTSPACE
);
1927 if(ch
->digiext
.digi_flags
& RTSPACE
)
1929 if(ch
->digiext
.digi_flags
& DTRPACE
)
1931 if(ch
->digiext
.digi_flags
& CTSPACE
)
1933 if(ch
->digiext
.digi_flags
& DSRPACE
)
1935 if(ch
->digiext
.digi_flags
& DCDPACE
)
1939 ch
->digiext
.digi_flags
|= RTSPACE
;
1941 ch
->digiext
.digi_flags
|= CTSPACE
;
1946 static void pcxxparam(struct tty_struct
*tty
, struct channel
*ch
)
1948 volatile struct board_chan
*bc
;
1950 unsigned mval
, hflow
, cflag
, iflag
;
1957 if((ts
->c_cflag
& CBAUD
) == 0) {
1961 fepcmd(ch
, STOUT
, (unsigned) head
, 0, 0, 0);
1965 cflag
= termios2digi_c(ch
, ts
->c_cflag
);
1967 if(cflag
!= ch
->fepcflag
) {
1968 ch
->fepcflag
= cflag
;
1969 fepcmd(ch
, SETCTRLFLAGS
, (unsigned) cflag
, 0, 0, 0);
1973 ch
->asyncflags
&= ~ASYNC_CHECK_CD
;
1975 ch
->asyncflags
|= ASYNC_CHECK_CD
;
1981 iflag
= termios2digi_i(ch
, ts
->c_iflag
);
1983 if(iflag
!= ch
->fepiflag
) {
1984 ch
->fepiflag
= iflag
;
1985 fepcmd(ch
, SETIFLAGS
, (unsigned int) ch
->fepiflag
, 0, 0, 0);
1989 if((ts
->c_cflag
& CLOCAL
) || (ch
->digiext
.digi_flags
& DIGI_FORCEDCD
))
1990 if(ch
->digiext
.digi_flags
& DIGI_FORCEDCD
)
1993 ch
->imodem
= bc
->mstat
;
1995 hflow
= termios2digi_h(ch
, ts
->c_cflag
);
1997 if(hflow
!= ch
->hflow
) {
1999 fepcmd(ch
, SETHFLOW
, hflow
, 0xff, 0, 1);
2002 /* mval ^= ch->modemfake & (mval ^ ch->modem); */
2004 if(ch
->omodem
!= mval
) {
2006 fepcmd(ch
, SETMODEM
, mval
, RTS
|DTR
, 0, 1);
2009 if(ch
->startc
!= ch
->fepstartc
|| ch
->stopc
!= ch
->fepstopc
) {
2010 ch
->fepstartc
= ch
->startc
;
2011 ch
->fepstopc
= ch
->stopc
;
2012 fepcmd(ch
, SONOFFC
, ch
->fepstartc
, ch
->fepstopc
, 0, 1);
2015 if(ch
->startca
!= ch
->fepstartca
|| ch
->stopca
!= ch
->fepstopca
) {
2016 ch
->fepstartca
= ch
->startca
;
2017 ch
->fepstopca
= ch
->stopca
;
2018 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
2023 static void receive_data(struct channel
*ch
)
2025 volatile struct board_chan
*bc
;
2026 struct tty_struct
*tty
;
2027 unsigned int tail
, head
, wrapmask
;
2030 struct termios
*ts
=0;
2037 if (ch
->statusflags
& RXSTOPPED
)
2047 printk("bc is NULL in receive_data!\n");
2051 wrapmask
= ch
->rxbufsize
- 1;
2055 tail
= bc
->rout
& wrapmask
;
2057 n
= (head
-tail
) & wrapmask
;
2063 * If CREAD bit is off or device not open, set TX tail to head
2065 if(!tty
|| !ts
|| !(ts
->c_cflag
& CREAD
)) {
2070 if(tty
->flip
.count
== TTY_FLIPBUF_SIZE
) {
2071 /* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
2077 printk("overrun! DigiBoard device minor=%d\n",MINOR(tty
->device
));
2081 rptr
= tty
->flip
.char_buf_ptr
;
2082 rc
= tty
->flip
.count
;
2084 wrapgap
= (head
>= tail
) ? head
- tail
: ch
->rxbufsize
- tail
;
2085 piece
= (wrapgap
< n
) ? wrapgap
: n
;
2088 * Make sure we don't overflow the buffer
2091 if ((rc
+ piece
) > TTY_FLIPBUF_SIZE
)
2092 piece
= TTY_FLIPBUF_SIZE
- rc
;
2097 memcpy(rptr
, ch
->rxptr
+ tail
, piece
);
2100 tail
= (tail
+ piece
) & wrapmask
;
2103 tty
->flip
.count
= rc
;
2104 tty
->flip
.char_buf_ptr
= rptr
;
2108 /* Must be called with global data */
2109 tty_schedule_flip(ch
->tty
);
2114 static int pcxe_ioctl(struct tty_struct
*tty
, struct file
* file
,
2115 unsigned int cmd
, unsigned long arg
)
2117 struct channel
*ch
= (struct channel
*) tty
->driver_data
;
2118 volatile struct board_chan
*bc
;
2120 unsigned int mflag
, mstat
;
2121 unsigned char startc
, stopc
;
2122 unsigned long flags
;
2128 printk("ch is NULL in pcxe_ioctl!\n");
2135 case TCSBRK
: /* SVID version: non-zero arg --> no break */
2136 retval
= tty_check_change(tty
);
2139 setup_empty_event(tty
,ch
);
2140 tty_wait_until_sent(tty
, 0);
2142 digi_send_break(ch
, HZ
/4); /* 1/4 second */
2145 case TCSBRKP
: /* support for POSIX tcsendbreak() */
2146 retval
= tty_check_change(tty
);
2149 setup_empty_event(tty
,ch
);
2150 tty_wait_until_sent(tty
, 0);
2151 digi_send_break(ch
, arg
? arg
*(HZ
/10) : HZ
/4);
2155 return put_user(C_CLOCAL(tty
) ? 1 : 0, (unsigned int *)arg
);
2160 if (get_user(value
, (unsigned int *) arg
))
2162 tty
->termios
->c_cflag
= ((tty
->termios
->c_cflag
& ~CLOCAL
) | (value
? CLOCAL
: 0));
2174 restore_flags(flags
);
2189 if (put_user(mflag
, (unsigned int *) arg
))
2197 if (get_user(mstat
, (unsigned int *) arg
))
2201 if(mstat
& TIOCM_DTR
)
2203 if(mstat
& TIOCM_RTS
)
2209 ch
->modemfake
= DTR
|RTS
;
2214 ch
->modemfake
|= mflag
;
2219 ch
->modemfake
&= ~mflag
;
2220 ch
->modem
&= ~mflag
;
2228 restore_flags(flags
);
2235 fepcmd(ch
, SETMODEM
, DTR
, 0, 10, 1);
2237 restore_flags(flags
);
2244 fepcmd(ch
, SETMODEM
, 0, DTR
, 10, 1);
2246 restore_flags(flags
);
2250 if (copy_to_user((char*)arg
, &ch
->digiext
, sizeof(digi_t
)))
2256 if(cmd
== DIGI_SETAW
) {
2257 setup_empty_event(tty
,ch
);
2258 tty_wait_until_sent(tty
, 0);
2261 if(tty
->ldisc
.flush_buffer
)
2262 tty
->ldisc
.flush_buffer(tty
);
2268 if (copy_from_user(&ch
->digiext
, (char*)arg
, sizeof(digi_t
)))
2271 printk("ioctl(DIGI_SETA): flags = %x\n", ch
->digiext
.digi_flags
);
2274 if(ch
->digiext
.digi_flags
& DIGI_ALTPIN
) {
2286 restore_flags(flags
);
2293 if(cmd
== DIGI_GETFLOW
) {
2294 dflow
.startc
= bc
->startc
;
2295 dflow
.stopc
= bc
->stopc
;
2297 dflow
.startc
= bc
->startca
;
2298 dflow
.stopc
= bc
->stopca
;
2301 restore_flags(flags
);
2303 if (copy_to_user((char*)arg
, &dflow
, sizeof(dflow
)))
2309 if(cmd
== DIGI_SETFLOW
) {
2310 startc
= ch
->startc
;
2313 startc
= ch
->startca
;
2317 if (copy_from_user(&dflow
, (char*)arg
, sizeof(dflow
)))
2320 if(dflow
.startc
!= startc
|| dflow
.stopc
!= stopc
) {
2324 if(cmd
== DIGI_SETFLOW
) {
2325 ch
->fepstartc
= ch
->startc
= dflow
.startc
;
2326 ch
->fepstopc
= ch
->stopc
= dflow
.stopc
;
2327 fepcmd(ch
,SONOFFC
,ch
->fepstartc
,ch
->fepstopc
,0, 1);
2329 ch
->fepstartca
= ch
->startca
= dflow
.startc
;
2330 ch
->fepstopca
= ch
->stopca
= dflow
.stopc
;
2331 fepcmd(ch
, SAUXONOFFC
, ch
->fepstartca
, ch
->fepstopca
, 0, 1);
2334 if(ch
->statusflags
& TXSTOPPED
)
2338 restore_flags(flags
);
2343 return -ENOIOCTLCMD
;
2349 static void pcxe_set_termios(struct tty_struct
*tty
, struct termios
*old_termios
)
2351 struct channel
*info
;
2353 if ((info
=chan(tty
))!=NULL
) {
2354 unsigned long flags
;
2358 pcxxparam(tty
,info
);
2361 if ((old_termios
->c_cflag
& CRTSCTS
) &&
2362 ((tty
->termios
->c_cflag
& CRTSCTS
) == 0))
2363 tty
->hw_stopped
= 0;
2364 if(!(old_termios
->c_cflag
& CLOCAL
) &&
2365 (tty
->termios
->c_cflag
& CLOCAL
))
2366 wake_up_interruptible(&info
->open_wait
);
2367 restore_flags(flags
);
2372 static void do_pcxe_bh(void)
2374 run_task_queue(&tq_pcxx
);
2378 static void do_softint(void *private_
)
2380 struct channel
*info
= (struct channel
*) private_
;
2382 if(info
&& info
->magic
== PCXX_MAGIC
) {
2383 struct tty_struct
*tty
= info
->tty
;
2384 if (tty
&& tty
->driver_data
) {
2385 if(test_and_clear_bit(PCXE_EVENT_HANGUP
, &info
->event
)) {
2387 wake_up_interruptible(&info
->open_wait
);
2388 info
->asyncflags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2395 static void pcxe_stop(struct tty_struct
*tty
)
2397 struct channel
*info
;
2399 if ((info
=chan(tty
))!=NULL
) {
2400 unsigned long flags
;
2403 if ((info
->statusflags
& TXSTOPPED
) == 0) {
2405 fepcmd(info
, PAUSETX
, 0, 0, 0, 0);
2406 info
->statusflags
|= TXSTOPPED
;
2409 restore_flags(flags
);
2413 static void pcxe_throttle(struct tty_struct
* tty
)
2415 struct channel
*info
;
2417 if ((info
=chan(tty
))!=NULL
) {
2418 unsigned long flags
;
2421 if ((info
->statusflags
& RXSTOPPED
) == 0) {
2423 fepcmd(info
, PAUSERX
, 0, 0, 0, 0);
2424 info
->statusflags
|= RXSTOPPED
;
2427 restore_flags(flags
);
2431 static void pcxe_unthrottle(struct tty_struct
*tty
)
2433 struct channel
*info
;
2435 if ((info
=chan(tty
)) != NULL
) {
2436 unsigned long flags
;
2438 /* Just in case output was resumed because of a change in Digi-flow */
2441 if(info
->statusflags
& RXSTOPPED
) {
2442 volatile struct board_chan
*bc
;
2445 fepcmd(info
, RESUMERX
, 0, 0, 0, 0);
2446 info
->statusflags
&= ~RXSTOPPED
;
2449 restore_flags(flags
);
2454 static void pcxe_start(struct tty_struct
*tty
)
2456 struct channel
*info
;
2458 if ((info
=chan(tty
))!=NULL
) {
2459 unsigned long flags
;
2463 /* Just in case output was resumed because of a change in Digi-flow */
2464 if(info
->statusflags
& TXSTOPPED
) {
2465 volatile struct board_chan
*bc
;
2468 if(info
->statusflags
& LOWWAIT
)
2470 fepcmd(info
, RESUMETX
, 0, 0, 0, 0);
2471 info
->statusflags
&= ~TXSTOPPED
;
2474 restore_flags(flags
);
2479 void digi_send_break(struct channel
*ch
, int msec
)
2481 unsigned long flags
;
2488 * Maybe I should send an infinite break here, schedule() for
2489 * msec amount of time, and then stop the break. This way,
2490 * the user can't screw up the FEP by causing digi_send_break()
2491 * to be called (i.e. via an ioctl()) more than once in msec amount
2492 * of time. Try this for now...
2495 fepcmd(ch
, SENDBREAK
, msec
, 0, 10, 0);
2498 restore_flags(flags
);
2501 static void setup_empty_event(struct tty_struct
*tty
, struct channel
*ch
)
2503 volatile struct board_chan
*bc
;
2504 unsigned long flags
;
2509 ch
->statusflags
|= EMPTYWAIT
;
2513 restore_flags(flags
);