- pre2
[davej-history.git] / drivers / char / pcxx.c
blob582503ec3428bfc2efa7f7bc0f23222a8a01ebda
1 /*
2 * linux/drivers/char/pcxx.c
3 *
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
39 * and Xeve also.
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>
50 #include <linux/mm.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>
70 #ifndef MODULE
71 #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
72 #endif
74 #include <asm/system.h>
75 #include <asm/io.h>
76 #include <asm/uaccess.h>
77 #include <asm/bitops.h>
78 #include <asm/semaphore.h>
80 #define VERSION "1.6.3"
82 #include "digi.h"
83 #include "fep.h"
84 #include "pcxx.h"
85 #include "digi_fep.h"
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
100 } };
102 static int verbose = 0;
103 static int debug = 0;
105 #ifdef MODULE
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");
123 # endif
125 #endif MODULE
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)
197 int crd, i;
198 struct board_info *bd;
199 struct channel *ch;
201 for(crd = 0; crd < numcards; crd++) {
202 bd = &boards[crd];
203 ch = digi_channels + bd->first_minor;
205 if (bd->region)
206 release_region(bd->port, 4);
208 for(i = 0; i < bd->numports; i++, ch++)
209 if (ch->tmp_buf)
210 kfree(ch->tmp_buf);
214 /*****************************************************************************/
216 #ifdef MODULE
219 * pcxe_init() is our init_module():
221 #define pcxe_init init_module
223 void cleanup_module(void);
226 /*****************************************************************************/
228 void cleanup_module()
231 unsigned long flags;
232 int e1, e2;
234 printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
236 save_flags(flags);
237 cli();
238 del_timer_sync(&pcxx_timer);
239 remove_bh(DIGI_BH);
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);
249 kfree(pcxe_termios);
250 kfree(pcxe_table);
251 restore_flags(flags);
253 #endif
255 static inline struct channel *chan(register struct tty_struct *tty)
257 if (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)
261 return ch;
264 return NULL;
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);
272 else
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);
287 else
288 outb_p(FEPMEM, ch->board->port);
291 static inline void rxwinon(struct channel *ch)
293 if(ch->rxwin == 0)
294 outb_p(FEPMEM, ch->board->port);
295 else
296 outb_p(ch->rxwin, ch->board->port+1);
299 static inline void txwinon(struct channel *ch)
301 if(ch->txwin == 0)
302 outb_p(FEPMEM, ch->board->port);
303 else
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);
330 mark_bh(DIGI_BH);
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);
341 int retval = 0;
342 int do_clocal = 0;
344 if (info->asyncflags & ASYNC_CALLOUT_ACTIVE) {
345 if (info->normal_termios.c_cflag & CLOCAL)
346 do_clocal = 1;
347 } else {
348 if (tty->termios->c_cflag & CLOCAL)
349 do_clocal = 1;
353 * Block waiting for the carrier detect and the line to become free
356 retval = 0;
357 add_wait_queue(&info->open_wait, &wait);
358 info->count--;
359 info->blocked_open++;
361 for (;;) {
362 cli();
363 if ((info->asyncflags & ASYNC_CALLOUT_ACTIVE) == 0) {
364 globalwinon(info);
365 info->omodem |= DTR|RTS;
366 fepcmd(info, SETMODEM, DTR|RTS, 0, 10, 1);
367 memoff(info);
369 sti();
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)
373 retval = -EAGAIN;
374 else
375 retval = -ERESTARTSYS;
376 break;
378 if ((info->asyncflags & ASYNC_CALLOUT_ACTIVE) == 0 &&
379 (info->asyncflags & ASYNC_CLOSING) == 0 &&
380 (do_clocal || (info->imodem & info->dcd)))
381 break;
382 if(signal_pending(current)) {
383 retval = -ERESTARTSYS;
384 break;
386 schedule();
388 current->state = TASK_RUNNING;
389 remove_wait_queue(&info->open_wait, &wait);
391 if(!tty_hung_up_p(filp))
392 info->count++;
393 info->blocked_open--;
395 return retval;
399 int pcxe_open(struct tty_struct *tty, struct file * filp)
401 volatile struct board_chan *bc;
402 struct channel *ch;
403 unsigned long flags;
404 int line;
405 int boardnum;
406 int retval;
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;
413 return(-ENODEV);
416 for(boardnum=0;boardnum<numcards;boardnum++)
417 if ((line >= boards[boardnum].first_minor) &&
418 (line < boards[boardnum].first_minor + boards[boardnum].numports))
419 break;
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' */
424 return(-ENODEV);
427 ch = digi_channels+line;
429 if(ch->brdchan == 0) {
430 tty->driver_data = NULL;
431 return(-ENODEV);
434 /* flag the kernel that there is somebody using this guy */
435 MOD_INC_USE_COUNT;
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)
443 return -EAGAIN;
444 else
445 return -ERESTARTSYS;
448 save_flags(flags);
449 cli();
450 ch->count++;
451 tty->driver_data = ch;
452 ch->tty = tty;
454 if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) {
455 unsigned int head;
457 globalwinon(ch);
458 ch->statusflags = 0;
459 bc=ch->brdchan;
460 ch->imodem = bc->mstat;
461 head = bc->rin;
462 bc->rout = head;
463 ch->tty = tty;
464 pcxxparam(tty,ch);
465 ch->imodem = bc->mstat;
466 bc->idata = 1;
467 ch->omodem = DTR|RTS;
468 fepcmd(ch, SETMODEM, DTR|RTS, 0, 10, 1);
469 memoff(ch);
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)
477 return -EAGAIN;
478 else
479 return -ERESTARTSYS;
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)
487 return -EBUSY;
488 if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) {
489 if ((ch->asyncflags & ASYNC_SESSION_LOCKOUT) &&
490 (ch->session != current->session))
491 return -EBUSY;
492 if((ch->asyncflags & ASYNC_PGRP_LOCKOUT) &&
493 (ch->pgrp != current->pgrp))
494 return -EBUSY;
496 ch->asyncflags |= ASYNC_CALLOUT_ACTIVE;
498 else {
499 if (filp->f_flags & O_NONBLOCK) {
500 if(ch->asyncflags & ASYNC_CALLOUT_ACTIVE)
501 return -EBUSY;
503 else {
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
508 * brian@ilinx.com
510 ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
511 if ((retval = pcxx_waitcarrier(tty, filp, ch)) != 0)
512 return retval;
514 ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
517 save_flags(flags);
518 cli();
519 if((ch->count == 1) && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {
520 if(tty->driver.subtype == SERIAL_TYPE_NORMAL)
521 *tty->termios = ch->normal_termios;
522 else
523 *tty->termios = ch->callout_termios;
524 globalwinon(ch);
525 pcxxparam(tty,ch);
526 memoff(ch);
529 ch->session = current->session;
530 ch->pgrp = current->pgrp;
531 restore_flags(flags);
532 return 0;
535 static void shutdown(struct channel *info)
537 unsigned long flags;
538 volatile struct board_chan *bc;
539 struct tty_struct *tty;
541 if (!(info->asyncflags & ASYNC_INITIALIZED))
542 return;
544 save_flags(flags);
545 cli();
546 globalwinon(info);
548 bc = info->brdchan;
549 if(bc)
550 bc->idata = 0;
552 tty = info->tty;
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);
562 memoff(info);
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) {
573 unsigned long flags;
574 save_flags(flags);
575 cli();
577 if(tty_hung_up_p(filp)) {
578 /* flag that somebody is done with this module */
579 MOD_DEC_USE_COUNT;
580 restore_flags(flags);
581 return;
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);
593 info->count = 1;
595 if (info->count-- > 1) {
596 restore_flags(flags);
597 MOD_DEC_USE_COUNT;
598 return;
600 if (info->count < 0) {
601 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;
614 tty->closing = 1;
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);
624 shutdown(info);
625 tty->closing = 0;
626 info->event = 0;
627 info->tty = NULL;
628 #ifndef MODULE
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) {
636 if(tty->ldisc.close)
637 (tty->ldisc.close)(tty);
638 tty->ldisc = ldiscs[N_TTY];
639 tty->termios->c_line = N_TTY;
640 if(tty->ldisc.open)
641 (tty->ldisc.open)(tty);
643 #endif
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);
654 MOD_DEC_USE_COUNT;
655 restore_flags(flags);
660 void pcxe_hangup(struct tty_struct *tty)
662 struct channel *ch;
664 if ((ch=chan(tty))!=NULL) {
665 unsigned long flags;
667 save_flags(flags);
668 cli();
669 shutdown(ch);
670 ch->event = 0;
671 ch->count = 0;
672 ch->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)
683 struct channel *ch;
684 volatile struct board_chan *bc;
685 int total, remain, size, stlen;
686 unsigned int head, tail;
687 unsigned long flags;
689 /* printk("Entering pcxe_write()\n"); */
691 if ((ch=chan(tty))==NULL)
692 return 0;
694 bc = ch->brdchan;
695 size = ch->txbufsize;
697 if (from_user) {
699 save_flags(flags);
700 cli();
701 globalwinon(ch);
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. */
706 { tail = bc->tout;
707 } while (tail != bc->tout);
709 tail &= (size - 1);
710 stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
711 count = MIN(stlen, count);
712 if (count)
713 if (copy_from_user(ch->tmp_buf, buf, count))
714 count = 0;
716 buf = ch->tmp_buf;
717 memoff(ch);
718 restore_flags(flags);
722 * All data is now local
725 total = 0;
726 save_flags(flags);
727 cli();
728 globalwinon(ch);
729 head = bc->tin & (size - 1);
730 tail = bc->tout;
731 if (tail != bc->tout)
732 tail = bc->tout;
733 tail &= (size - 1);
734 if (head >= tail) {
735 remain = size - (head - tail) - 1;
736 stlen = size - head;
738 else {
739 remain = tail - head - 1;
740 stlen = remain;
742 count = MIN(remain, count);
744 txwinon(ch);
745 while (count > 0) {
746 stlen = MIN(count, stlen);
747 memcpy(ch->txptr + head, buf, stlen);
748 buf += stlen;
749 count -= stlen;
750 total += stlen;
751 head += stlen;
752 if (head >= size) {
753 head = 0;
754 stlen = tail;
757 ch->statusflags |= TXBUSY;
758 globalwinon(ch);
759 bc->tin = head;
760 if ((ch->statusflags & LOWWAIT) == 0) {
761 ch->statusflags |= LOWWAIT;
762 bc->ilow = 1;
764 memoff(ch);
765 restore_flags(flags);
767 return(total);
771 static void pcxe_put_char(struct tty_struct *tty, unsigned char c)
773 pcxe_write(tty, 0, &c, 1);
774 return;
778 static int pcxe_write_room(struct tty_struct *tty)
780 struct channel *ch;
781 int remain;
783 remain = 0;
784 if ((ch=chan(tty))!=NULL) {
785 volatile struct board_chan *bc;
786 unsigned int head, tail;
787 unsigned long flags;
789 save_flags(flags);
790 cli();
791 globalwinon(ch);
793 bc = ch->brdchan;
794 head = bc->tin & (ch->txbufsize - 1);
795 tail = bc->tout;
796 if (tail != bc->tout)
797 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;
805 bc->ilow = 1;
807 memoff(ch);
808 restore_flags(flags);
811 return remain;
815 static int pcxe_chars_in_buffer(struct tty_struct *tty)
817 int chars;
818 unsigned int ctail, head, tail;
819 int remain;
820 unsigned long flags;
821 struct channel *ch;
822 volatile struct board_chan *bc;
824 if ((ch=chan(tty))==NULL)
825 return(0);
827 save_flags(flags);
828 cli();
829 globalwinon(ch);
831 bc = ch->brdchan;
832 tail = bc->tout;
833 head = bc->tin;
834 ctail = ch->mailbox->cout;
835 if(tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
836 chars = 0;
837 else {
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);
853 memoff(ch);
854 restore_flags(flags);
856 return(chars);
860 static void pcxe_flush_buffer(struct tty_struct *tty)
862 unsigned int tail;
863 volatile struct board_chan *bc;
864 struct channel *ch;
865 unsigned long flags;
867 if ((ch=chan(tty))==NULL)
868 return;
870 save_flags(flags);
871 cli();
873 globalwinon(ch);
874 bc = ch->brdchan;
875 tail = bc->tout;
876 fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
878 memoff(ch);
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)
888 struct channel * ch;
890 if ((ch=chan(tty))!=NULL) {
891 unsigned long flags;
893 save_flags(flags);
894 cli();
895 if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
896 setup_empty_event(tty,ch);
897 restore_flags(flags);
901 #ifndef MODULE
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;
911 int i, j, last;
912 char *temp, *t2;
913 unsigned len;
915 numcards=0;
917 memset(&board, 0, sizeof(board));
919 for(last=0,i=1;i<=ints[0];i++)
920 switch(i)
922 case 1:
923 board.status = ints[i];
924 last = i;
925 break;
927 case 2:
928 board.type = ints[i];
929 last = i;
930 break;
932 case 3:
933 board.altpin = ints[i];
934 last = i;
935 break;
937 case 4:
938 board.numports = ints[i];
939 last = i;
940 break;
942 case 5:
943 board.port = ints[i];
944 last = i;
945 break;
947 case 6:
948 board.membase = ints[i];
949 last = i;
950 break;
952 default:
953 printk("PC/Xx: Too many integer parms\n");
954 return;
957 while (str && *str)
959 /* find the next comma or terminator */
960 temp = str;
961 while (*temp && (*temp != ','))
962 temp++;
964 if (!*temp)
965 temp = NULL;
966 else
967 *temp++ = 0;
969 i = last + 1;
971 switch(i)
973 case 1:
974 len = strlen(str);
975 if (strncmp("Disable", str, len) == 0)
976 board.status = 0;
977 else
978 if (strncmp("Enable", str, len) == 0)
979 board.status = 1;
980 else
982 printk("PC/Xx: Invalid status %s\n", str);
983 return;
985 last = i;
986 break;
988 case 2:
989 for(j=0;j<PCXX_NUM_TYPES;j++)
990 if (strcmp(board_desc[j], str) == 0)
991 break;
993 if (i<PCXX_NUM_TYPES)
994 board.type = j;
995 else
997 printk("PC/Xx: Invalid board name: %s\n", str);
998 return;
1000 last = i;
1001 break;
1003 case 3:
1004 len = strlen(str);
1005 if (strncmp("Disable", str, len) == 0)
1006 board.altpin = 0;
1007 else
1008 if (strncmp("Enable", str, len) == 0)
1009 board.altpin = 1;
1010 else
1012 printk("PC/Xx: Invalid altpin %s\n", str);
1013 return;
1015 last = i;
1016 break;
1018 case 4:
1019 t2 = str;
1020 while (isdigit(*t2))
1021 t2++;
1023 if (*t2)
1025 printk("PC/Xx: Invalid port count %s\n", str);
1026 return;
1029 board.numports = simple_strtoul(str, NULL, 0);
1030 last = i;
1031 break;
1033 case 5:
1034 t2 = str;
1035 while (isxdigit(*t2))
1036 t2++;
1038 if (*t2)
1040 printk("PC/Xx: Invalid io port address %s\n", str);
1041 return;
1044 board.port = simple_strtoul(str, NULL, 16);
1045 last = i;
1046 break;
1048 case 6:
1049 t2 = str;
1050 while (isxdigit(*t2))
1051 t2++;
1053 if (*t2)
1055 printk("PC/Xx: Invalid memory base %s\n", str);
1056 return;
1059 board.membase = simple_strtoul(str, NULL, 16);
1060 last = i;
1061 break;
1063 default:
1064 printk("PC/Xx: Too many string parms\n");
1065 return;
1067 str = temp;
1070 if (last < 6)
1072 printk("PC/Xx: Insufficient parms specified\n");
1073 return;
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 */
1084 if (numcards)
1085 boards[numcards].first_minor = boards[numcards-1].first_minor + boards[numcards-1].numports;
1086 else
1087 boards[numcards].first_minor = 0;
1089 /* yeha! string parameter was successful! */
1090 numcards++;
1092 #endif
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;
1102 int ret = -ENOMEM;
1103 unchar *fepos, *memaddr, *bios, v;
1104 volatile struct global_data *gd;
1105 volatile struct board_chan *bc;
1106 struct board_info *bd;
1107 struct channel *ch;
1109 printk(KERN_NOTICE "Digiboard PC/X{i,e,eve} driver v%s\n", VERSION);
1111 #ifdef MODULE
1112 for (i = 0; i < MAX_DIGI_BOARDS; i++) {
1113 if (io[i]) {
1114 numcards = 0;
1115 break;
1118 if (numcards == 0) {
1119 int first_minor = 0;
1121 for (i = 0; i < MAX_DIGI_BOARDS; i++) {
1122 if (io[i] == 0) {
1123 boards[i].port = 0;
1124 boards[i].status = DISABLED;
1126 else {
1127 boards[i].port = (ushort)io[i];
1128 boards[i].status = ENABLED;
1129 boards[i].first_minor = first_minor;
1130 numcards=i+1;
1132 if (membase[i])
1133 boards[i].membase = (ulong)membase[i];
1134 else
1135 boards[i].membase = 0xD0000;
1137 if (memsize[i])
1138 boards[i].memsize = (ulong)(memsize[i] * 1024);
1139 else
1140 boards[i].memsize = 0;
1142 if (altpin[i])
1143 boards[i].altpin = ON;
1144 else
1145 boards[i].altpin = OFF;
1147 if (numports[i])
1148 boards[i].numports = (ushort)numports[i];
1149 else
1150 boards[i].numports = 16;
1152 boards[i].region = NULL;
1153 first_minor += boards[i].numports;
1156 #endif
1158 if (numcards <= 0)
1160 printk("PC/Xx: No cards configured, driver not active.\n");
1161 return -EIO;
1163 #if 1
1164 if (debug)
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",
1167 i+1,
1168 boards[i].status,
1169 boards[i].port,
1170 boards[i].membase,
1171 boards[i].memsize,
1172 boards[i].altpin,
1173 boards[i].numports,
1174 boards[i].first_minor);
1176 #endif
1178 for (i=0;i<numcards;i++)
1179 nbdevs += boards[i].numports;
1181 if (nbdevs <= 0)
1183 printk("PC/Xx: No devices activated, driver not active.\n");
1184 return -EIO;
1188 * this turns out to be more memory efficient, as there are no
1189 * unused spaces.
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");
1194 return -ENOMEM;
1196 memset(digi_channels, 0, sizeof(struct channel) * nbdevs);
1198 pcxe_table = kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
1199 if (!pcxe_table) {
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++) {
1266 bd = &boards[crd];
1267 outb(FEPRST, bd->port);
1268 pcxxdelay(1);
1270 for(i=0; (inb(bd->port) & FEPMASK) != FEPRST; i++) {
1271 if(i > 100) {
1272 printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
1273 bd->port);
1274 bd->status = DISABLED;
1275 break;
1277 #ifdef MODULE
1278 schedule();
1279 #endif
1280 pcxxdelay(10);
1282 if(bd->status == DISABLED)
1283 continue;
1285 v = inb(bd->port);
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;
1307 bd->type = PCXI;
1308 } else {
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);
1312 continue;
1313 } else {
1314 if(v & 0xC0) {
1315 topwin = 0x1f00L;
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 */
1319 } else {
1320 bd->type = PCXE; /* PC/Xe 64K card */
1323 memory_seg = 0xf000;
1324 memory_size = 0x10000;
1327 if (verbose)
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;
1334 else
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);
1339 continue;
1342 memaddr = (unchar *)phys_to_virt(bd->membase);
1344 if (verbose)
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++) {
1350 if(i > 1000) {
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;
1354 break;
1356 #ifdef MODULE
1357 schedule();
1358 #endif
1359 pcxxdelay(1);
1361 if(bd->status == DISABLED)
1362 continue;
1364 memwinon(bd,0);
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;
1373 continue;
1375 if (verbose)
1376 printk(" done.\n");
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);
1385 if (verbose)
1386 printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios));
1388 memcpy(bios, pcxx_bios, pcxx_nbios);
1390 if (verbose)
1391 printk(" done.\n");
1393 outb(FEPMEM, bd->port);
1395 if (verbose)
1396 printk("Waiting for BIOS to become ready");
1398 for(i=1; i <= 30; i++) {
1399 if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
1400 goto load_fep;
1402 if (verbose) {
1403 printk(".");
1404 if (i % 50 == 0)
1405 printk("\n");
1407 #ifdef MODULE
1408 schedule();
1409 #endif
1410 pcxxdelay(50);
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;
1416 continue;
1419 if(bd->type == PCXEVE) {
1420 bios = memaddr + (BIOSCODE & 0x1fff);
1421 memwinon(bd,0xff);
1423 memcpy(bios, pcxx_bios, pcxx_nbios);
1425 outb(FEPCLR, bd->port);
1426 memwinon(bd,0);
1428 for(i=0; i <= 1000; i++) {
1429 if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
1430 goto load_fep;
1432 if (verbose) {
1433 printk(".");
1434 if (i % 50 == 0)
1435 printk("\n");
1437 #ifdef MODULE
1438 schedule();
1439 #endif
1440 pcxxdelay(10);
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;
1446 continue;
1449 load_fep:
1450 fepos = memaddr + FEPCODE;
1451 if(bd->type == PCXEVE)
1452 fepos = memaddr + (FEPCODE & 0x1fff);
1454 if (verbose)
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);
1459 memwinon(bd, 0);
1461 if (verbose)
1462 printk(" done.\n");
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++) {
1475 if(i > 2000) {
1476 printk("PC/Xx: Command failed for the %s at 0x%x!\n",
1477 board_desc[bd->type], bd->port);
1478 bd->status = DISABLED;
1479 break;
1481 #ifdef MODULE
1482 schedule();
1483 #endif
1484 pcxxdelay(1);
1487 if(bd->status == DISABLED)
1488 continue;
1490 if (verbose)
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);
1500 memwinon(bd, 0);
1502 for(i=1; *(ushort *)((ulong)memaddr + FEPSTAT) != *(ushort *)"OS"; i++) {
1503 if(i > 1000) {
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;
1507 break;
1509 if (verbose) {
1510 printk(".");
1511 if (i % 50 == 0)
1512 printk("\n%5d",i/50);
1514 #ifdef MODULE
1515 schedule();
1516 #endif
1517 pcxxdelay(1);
1519 if(bd->status == DISABLED)
1520 continue;
1522 if (verbose)
1523 printk(" ok.\n");
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))
1532 shrinkmem = 1;
1534 bd->region = request_region(bd->port, 4, "PC/Xx");
1536 if (!bd->region) {
1537 printk(KERN_ERR "I/O port 0x%x is already used\n", bd->port);
1538 ret = -EBUSY;
1539 goto cleanup_boards;
1542 for(i=0; i < bd->numports; i++, ch++, bc++) {
1543 if(((ushort *)((ulong)memaddr + PORTBASE))[i] == 0) {
1544 ch->brdchan = 0;
1545 continue;
1547 ch->brdchan = bc;
1548 ch->mailbox = gd;
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;
1554 #endif
1555 if(boards[crd].altpin) {
1556 ch->dsr = CD;
1557 ch->dcd = DSR;
1558 ch->digiext.digi_flags |= DIGI_ALTPIN;
1559 } else {
1560 ch->dcd = CD;
1561 ch->dsr = DSR;
1564 ch->magic = PCXX_MAGIC;
1565 ch->boardnum = crd;
1566 ch->channelnum = i;
1568 ch->dev = bd->first_minor + i;
1569 ch->tty = 0;
1571 if(shrinkmem) {
1572 fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
1573 shrinkmem = 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;
1580 } else {
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);
1591 if (!ch->tmp_buf) {
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);
1601 bc->edelay = 100;
1602 bc->idata = 1;
1604 ch->startc = bc->startc;
1605 ch->stopc = bc->stopc;
1606 ch->startca = bc->startca;
1607 ch->stopca = bc->stopca;
1609 ch->fepcflag = 0;
1610 ch->fepiflag = 0;
1611 ch->fepoflag = 0;
1612 ch->fepstartc = 0;
1613 ch->fepstopc = 0;
1614 ch->fepstartca = 0;
1615 ch->fepstopca = 0;
1617 ch->close_delay = 50;
1618 ch->count = 0;
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);
1624 ch->asyncflags = 0;
1627 if (verbose)
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);
1631 else
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);
1636 memwinoff(bd, 0);
1637 enabled_cards++;
1640 if (enabled_cards <= 0) {
1641 printk(KERN_NOTICE "PC/Xx: No cards enabled, no driver.\n");
1642 ret = -EIO;
1643 goto cleanup_boards;
1646 ret = tty_register_driver(&pcxe_driver);
1647 if(ret) {
1648 printk(KERN_ERR "Couldn't register PC/Xe driver\n");
1649 goto cleanup_boards;
1652 ret = tty_register_driver(&pcxe_callout);
1653 if(ret) {
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);
1663 if (verbose)
1664 printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards);
1666 return 0;
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);
1673 return ret;
1677 static void pcxxpoll(unsigned long dummy)
1679 unsigned long flags;
1680 int crd;
1681 volatile unsigned int head, tail;
1682 struct channel *ch;
1683 struct board_info *bd;
1685 save_flags(flags);
1686 cli();
1688 for(crd=0; crd < numcards; crd++) {
1689 bd = &boards[crd];
1691 ch = digi_channels+bd->first_minor;
1693 if(bd->status == DISABLED)
1694 continue;
1696 assertmemoff(ch);
1698 globalwinon(ch);
1699 head = ch->mailbox->ein;
1700 tail = ch->mailbox->eout;
1702 if(head != tail)
1703 doevent(crd);
1705 memoff(ch);
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;
1720 struct channel *ch;
1721 struct channel *chan0;
1722 int channel, event, mstat, lstat;
1724 bd = &boards[crd];
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];
1740 ch=chan0+channel;
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)
1747 ch = chan0;
1748 bc = ch->brdchan;
1749 goto next;
1751 if ((bc = ch->brdchan) == NULL)
1752 goto next;
1754 if (event & DATA_IND) {
1755 receive_data(ch);
1756 assertgwinon(ch);
1759 if (event & MODEMCHG_IND) {
1760 ch->imodem = mstat;
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);
1765 } else {
1766 pcxe_sched_event(ch, PCXE_EVENT_HANGUP);
1772 tty = ch->tty;
1774 if (tty) {
1776 if (event & BREAK_IND) {
1777 tty->flip.count++;
1778 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
1779 *tty->flip.char_buf_ptr++ = 0;
1780 #if 0
1781 if (ch->asyncflags & ASYNC_SAK)
1782 do_SAK(tty);
1783 #endif
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);
1809 next:
1810 globalwinon(ch);
1811 if(!bc) printk("bc == NULL in doevent!\n");
1812 else bc->idata = 1;
1814 chan0->mailbox->eout = (tail+4) & (IMAX-ISTART-4);
1815 globalwinon(chan0);
1822 * pcxxdelay - delays a specified number of milliseconds
1824 static void pcxxdelay(int msec)
1826 while(msec-- > 0)
1827 __delay(loops_per_sec/1000);
1831 static void
1832 fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds,
1833 int bytecmd)
1835 unchar *memaddr;
1836 unsigned int head, tail;
1837 long count;
1838 int n;
1840 if(ch->board->status == DISABLED)
1841 return;
1843 assertgwinon(ch);
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);
1850 return;
1853 if(bytecmd) {
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;
1860 } else {
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;
1870 count = FEPTIMEOUT;
1872 while(1) {
1873 count--;
1874 if(count == 0) {
1875 printk("Fep not responding in fepcmd()\n");
1876 return;
1879 head = ch->mailbox->cin;
1880 tail = ch->mailbox->cout;
1882 n = (head-tail) & (CMAX-CSTART-4);
1884 if(n <= ncmds * (sizeof(short)*4))
1885 break;
1886 /* Seems not to be good here: schedule(); */
1891 static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
1893 unsigned res = 0;
1894 if (cflag & CBAUDEX)
1896 ch->digiext.digi_flags |= DIGI_FAST;
1897 res |= FEP_HUPCL;
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
1901 * do 115K
1903 if (cflag & B115200) res|=1;
1905 else ch->digiext.digi_flags &= ~DIGI_FAST;
1906 res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE | CLOCAL);
1907 return res;
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)
1915 res |= IAIXON;
1916 return res;
1919 static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
1921 unsigned res = 0;
1923 if(cflag & CRTSCTS) {
1924 ch->digiext.digi_flags |= (RTSPACE|CTSPACE);
1925 res |= (CTS | RTS);
1927 if(ch->digiext.digi_flags & RTSPACE)
1928 res |= RTS;
1929 if(ch->digiext.digi_flags & DTRPACE)
1930 res |= DTR;
1931 if(ch->digiext.digi_flags & CTSPACE)
1932 res |= CTS;
1933 if(ch->digiext.digi_flags & DSRPACE)
1934 res |= ch->dsr;
1935 if(ch->digiext.digi_flags & DCDPACE)
1936 res |= ch->dcd;
1938 if (res & RTS)
1939 ch->digiext.digi_flags |= RTSPACE;
1940 if (res & CTS)
1941 ch->digiext.digi_flags |= CTSPACE;
1943 return res;
1946 static void pcxxparam(struct tty_struct *tty, struct channel *ch)
1948 volatile struct board_chan *bc;
1949 unsigned int head;
1950 unsigned mval, hflow, cflag, iflag;
1951 struct termios *ts;
1953 bc = ch->brdchan;
1954 assertgwinon(ch);
1955 ts = tty->termios;
1957 if((ts->c_cflag & CBAUD) == 0) {
1958 head = bc->rin;
1959 bc->rout = head;
1960 head = bc->tin;
1961 fepcmd(ch, STOUT, (unsigned) head, 0, 0, 0);
1962 mval = 0;
1963 } else {
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);
1972 if(cflag & CLOCAL)
1973 ch->asyncflags &= ~ASYNC_CHECK_CD;
1974 else {
1975 ch->asyncflags |= ASYNC_CHECK_CD;
1978 mval = DTR | RTS;
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);
1988 bc->mint = ch->dcd;
1989 if((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
1990 if(ch->digiext.digi_flags & DIGI_FORCEDCD)
1991 bc->mint = 0;
1993 ch->imodem = bc->mstat;
1995 hflow = termios2digi_h(ch, ts->c_cflag);
1997 if(hflow != ch->hflow) {
1998 ch->hflow = hflow;
1999 fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
2002 /* mval ^= ch->modemfake & (mval ^ ch->modem); */
2004 if(ch->omodem != mval) {
2005 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;
2028 int n;
2029 int piece;
2030 struct termios *ts=0;
2031 unchar *rptr;
2032 int rc;
2033 int wrapgap;
2035 globalwinon(ch);
2037 if (ch->statusflags & RXSTOPPED)
2038 return;
2040 tty = ch->tty;
2041 if(tty)
2042 ts = tty->termios;
2044 bc = ch->brdchan;
2046 if(!bc) {
2047 printk("bc is NULL in receive_data!\n");
2048 return;
2051 wrapmask = ch->rxbufsize - 1;
2053 head = bc->rin;
2054 head &= wrapmask;
2055 tail = bc->rout & wrapmask;
2057 n = (head-tail) & wrapmask;
2059 if(n == 0)
2060 return;
2063 * If CREAD bit is off or device not open, set TX tail to head
2065 if(!tty || !ts || !(ts->c_cflag & CREAD)) {
2066 bc->rout = head;
2067 return;
2070 if(tty->flip.count == TTY_FLIPBUF_SIZE) {
2071 /* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
2072 return;
2075 if(bc->orun) {
2076 bc->orun = 0;
2077 printk("overrun! DigiBoard device minor=%d\n",MINOR(tty->device));
2080 rxwinon(ch);
2081 rptr = tty->flip.char_buf_ptr;
2082 rc = tty->flip.count;
2083 while(n > 0) {
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;
2094 if (piece == 0)
2095 break;
2097 memcpy(rptr, ch->rxptr + tail, piece);
2098 rptr += piece;
2099 rc += piece;
2100 tail = (tail + piece) & wrapmask;
2101 n -= piece;
2103 tty->flip.count = rc;
2104 tty->flip.char_buf_ptr = rptr;
2105 globalwinon(ch);
2106 bc->rout = tail;
2108 /* Must be called with global data */
2109 tty_schedule_flip(ch->tty);
2110 return;
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;
2119 int retval;
2120 unsigned int mflag, mstat;
2121 unsigned char startc, stopc;
2122 unsigned long flags;
2123 digiflow_t dflow;
2125 if(ch)
2126 bc = ch->brdchan;
2127 else {
2128 printk("ch is NULL in pcxe_ioctl!\n");
2129 return(-EINVAL);
2132 save_flags(flags);
2134 switch(cmd) {
2135 case TCSBRK: /* SVID version: non-zero arg --> no break */
2136 retval = tty_check_change(tty);
2137 if(retval)
2138 return retval;
2139 setup_empty_event(tty,ch);
2140 tty_wait_until_sent(tty, 0);
2141 if(!arg)
2142 digi_send_break(ch, HZ/4); /* 1/4 second */
2143 return 0;
2145 case TCSBRKP: /* support for POSIX tcsendbreak() */
2146 retval = tty_check_change(tty);
2147 if(retval)
2148 return retval;
2149 setup_empty_event(tty,ch);
2150 tty_wait_until_sent(tty, 0);
2151 digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
2152 return 0;
2154 case TIOCGSOFTCAR:
2155 return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *)arg);
2157 case TIOCSSOFTCAR:
2159 unsigned int value;
2160 if (get_user(value, (unsigned int *) arg))
2161 return -EFAULT;
2162 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (value ? CLOCAL : 0));
2164 return 0;
2166 case TIOCMODG:
2167 case TIOCMGET:
2168 mflag = 0;
2170 cli();
2171 globalwinon(ch);
2172 mstat = bc->mstat;
2173 memoff(ch);
2174 restore_flags(flags);
2176 if(mstat & DTR)
2177 mflag |= TIOCM_DTR;
2178 if(mstat & RTS)
2179 mflag |= TIOCM_RTS;
2180 if(mstat & CTS)
2181 mflag |= TIOCM_CTS;
2182 if(mstat & ch->dsr)
2183 mflag |= TIOCM_DSR;
2184 if(mstat & RI)
2185 mflag |= TIOCM_RI;
2186 if(mstat & ch->dcd)
2187 mflag |= TIOCM_CD;
2189 if (put_user(mflag, (unsigned int *) arg))
2190 return -EFAULT;
2191 break;
2193 case TIOCMBIS:
2194 case TIOCMBIC:
2195 case TIOCMODS:
2196 case TIOCMSET:
2197 if (get_user(mstat, (unsigned int *) arg))
2198 return -EFAULT;
2200 mflag = 0;
2201 if(mstat & TIOCM_DTR)
2202 mflag |= DTR;
2203 if(mstat & TIOCM_RTS)
2204 mflag |= RTS;
2206 switch(cmd) {
2207 case TIOCMODS:
2208 case TIOCMSET:
2209 ch->modemfake = DTR|RTS;
2210 ch->modem = mflag;
2211 break;
2213 case TIOCMBIS:
2214 ch->modemfake |= mflag;
2215 ch->modem |= mflag;
2216 break;
2218 case TIOCMBIC:
2219 ch->modemfake &= ~mflag;
2220 ch->modem &= ~mflag;
2221 break;
2224 cli();
2225 globalwinon(ch);
2226 pcxxparam(tty,ch);
2227 memoff(ch);
2228 restore_flags(flags);
2229 break;
2231 case TIOCSDTR:
2232 cli();
2233 ch->omodem |= DTR;
2234 globalwinon(ch);
2235 fepcmd(ch, SETMODEM, DTR, 0, 10, 1);
2236 memoff(ch);
2237 restore_flags(flags);
2238 break;
2240 case TIOCCDTR:
2241 ch->omodem &= ~DTR;
2242 cli();
2243 globalwinon(ch);
2244 fepcmd(ch, SETMODEM, 0, DTR, 10, 1);
2245 memoff(ch);
2246 restore_flags(flags);
2247 break;
2249 case DIGI_GETA:
2250 if (copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)))
2251 return -EFAULT;
2252 break;
2254 case DIGI_SETAW:
2255 case DIGI_SETAF:
2256 if(cmd == DIGI_SETAW) {
2257 setup_empty_event(tty,ch);
2258 tty_wait_until_sent(tty, 0);
2260 else {
2261 if(tty->ldisc.flush_buffer)
2262 tty->ldisc.flush_buffer(tty);
2265 /* Fall Thru */
2267 case DIGI_SETA:
2268 if (copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)))
2269 return -EFAULT;
2270 #ifdef DEBUG_IOCTL
2271 printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
2272 #endif
2274 if(ch->digiext.digi_flags & DIGI_ALTPIN) {
2275 ch->dcd = DSR;
2276 ch->dsr = CD;
2277 } else {
2278 ch->dcd = CD;
2279 ch->dsr = DSR;
2282 cli();
2283 globalwinon(ch);
2284 pcxxparam(tty,ch);
2285 memoff(ch);
2286 restore_flags(flags);
2287 break;
2289 case DIGI_GETFLOW:
2290 case DIGI_GETAFLOW:
2291 cli();
2292 globalwinon(ch);
2293 if(cmd == DIGI_GETFLOW) {
2294 dflow.startc = bc->startc;
2295 dflow.stopc = bc->stopc;
2296 } else {
2297 dflow.startc = bc->startca;
2298 dflow.stopc = bc->stopca;
2300 memoff(ch);
2301 restore_flags(flags);
2303 if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
2304 return -EFAULT;
2305 break;
2307 case DIGI_SETAFLOW:
2308 case DIGI_SETFLOW:
2309 if(cmd == DIGI_SETFLOW) {
2310 startc = ch->startc;
2311 stopc = ch->stopc;
2312 } else {
2313 startc = ch->startca;
2314 stopc = ch->stopca;
2317 if (copy_from_user(&dflow, (char*)arg, sizeof(dflow)))
2318 return -EFAULT;
2320 if(dflow.startc != startc || dflow.stopc != stopc) {
2321 cli();
2322 globalwinon(ch);
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);
2328 } else {
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)
2335 pcxe_start(tty);
2337 memoff(ch);
2338 restore_flags(flags);
2340 break;
2342 default:
2343 return -ENOIOCTLCMD;
2346 return 0;
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;
2355 save_flags(flags);
2356 cli();
2357 globalwinon(info);
2358 pcxxparam(tty,info);
2359 memoff(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)) {
2386 tty_hangup(tty);
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;
2401 save_flags(flags);
2402 cli();
2403 if ((info->statusflags & TXSTOPPED) == 0) {
2404 globalwinon(info);
2405 fepcmd(info, PAUSETX, 0, 0, 0, 0);
2406 info->statusflags |= TXSTOPPED;
2407 memoff(info);
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;
2419 save_flags(flags);
2420 cli();
2421 if ((info->statusflags & RXSTOPPED) == 0) {
2422 globalwinon(info);
2423 fepcmd(info, PAUSERX, 0, 0, 0, 0);
2424 info->statusflags |= RXSTOPPED;
2425 memoff(info);
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 */
2439 save_flags(flags);
2440 cli();
2441 if(info->statusflags & RXSTOPPED) {
2442 volatile struct board_chan *bc;
2443 globalwinon(info);
2444 bc = info->brdchan;
2445 fepcmd(info, RESUMERX, 0, 0, 0, 0);
2446 info->statusflags &= ~RXSTOPPED;
2447 memoff(info);
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;
2461 save_flags(flags);
2462 cli();
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;
2466 globalwinon(info);
2467 bc = info->brdchan;
2468 if(info->statusflags & LOWWAIT)
2469 bc->ilow = 1;
2470 fepcmd(info, RESUMETX, 0, 0, 0, 0);
2471 info->statusflags &= ~TXSTOPPED;
2472 memoff(info);
2474 restore_flags(flags);
2479 void digi_send_break(struct channel *ch, int msec)
2481 unsigned long flags;
2483 save_flags(flags);
2484 cli();
2485 globalwinon(ch);
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);
2496 memoff(ch);
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;
2506 save_flags(flags);
2507 cli();
2508 globalwinon(ch);
2509 ch->statusflags |= EMPTYWAIT;
2510 bc = ch->brdchan;
2511 bc->iempty = 1;
2512 memoff(ch);
2513 restore_flags(flags);