1/*
2 *  linux/drivers/char/pcxx.c
3 *
4 *  Written by Troy De Jongh, November, 1994
5 *
6 *  Copyright (C) 1994,1995 Troy De Jongh
7 *  This software may be used and distributed according to the terms
8 *  of the GNU General Public License.
9 *
10 *  This driver is for the DigiBoard PC/Xe and PC/Xi line of products.
11 *
12 *  This driver does NOT support DigiBoard's fastcook FEP option and
13 *  does not support the transparent print (i.e. digiprint) option.
14 *
15 * This Driver is currently maintained by Christoph Lameter (christoph@lameter.com)
16 *
17 * Please contact digi for support issues at digilnux@dgii.com.
18 * Some more information can be found at
19 * http://lameter.com/digi.
20 *
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.
46 *
47 */
48
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/slab.h>
67#include <linux/init.h>
68#include <linux/version.h>
69
70#ifndef MODULE
71#include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
72#endif
73
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>
79
80#define VERSION 	"1.6.3"
81
82#include "digi.h"
83#include "fep.h"
84#include "pcxx.h"
85#include "digi_fep.h"
86#include "digi_bios.h"
87
88/*
89 * Define one default setting if no digi= config line is used.
90 * Default is altpin = disabled, 16 ports, I/O 200h, Memory 0D0000h
91 */
92static 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} };
101
102static int verbose = 0;
103static int debug   = 0;
104
105#ifdef MODULE
106/* Variables for insmod */
107static int io[]           = {0, 0, 0, 0};
108static int membase[]      = {0, 0, 0, 0};
109static int memsize[]      = {0, 0, 0, 0};
110static int altpin[]       = {0, 0, 0, 0};
111static int numports[]     = {0, 0, 0, 0};
112
113# if (LINUX_VERSION_CODE > 0x020111)
114MODULE_AUTHOR("Bernhard Kaindl");
115MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
116MODULE_LICENSE("GPL");
117MODULE_PARM(verbose,     "i");
118MODULE_PARM(debug,       "i");
119MODULE_PARM(io,          "1-4i");
120MODULE_PARM(membase,     "1-4i");
121MODULE_PARM(memsize,     "1-4i");
122MODULE_PARM(altpin,      "1-4i");
123MODULE_PARM(numports,    "1-4i");
124# endif
125
126#endif MODULE
127
128static int numcards = 1;
129static int nbdevs = 0;
130
131static struct channel    *digi_channels;
132static struct tty_struct **pcxe_table;
133static struct termios    **pcxe_termios;
134static struct termios    **pcxe_termios_locked;
135
136int pcxx_ncook=sizeof(pcxx_cook);
137int pcxx_nbios=sizeof(pcxx_bios);
138
139#define MIN(a,b)	((a) < (b) ? (a) : (b))
140#define pcxxassert(x, msg)  if(!(x)) pcxx_error(__LINE__, msg)
141
142#define FEPTIMEOUT 200000
143#define SERIAL_TYPE_NORMAL	1
144#define SERIAL_TYPE_CALLOUT	2
145#define PCXE_EVENT_HANGUP   1
146
147struct tty_driver pcxe_driver;
148struct tty_driver pcxe_callout;
149static int pcxe_refcount;
150
151static struct timer_list pcxx_timer;
152
153DECLARE_TASK_QUEUE(tq_pcxx);
154
155static void pcxxpoll(unsigned long dummy);
156static void fepcmd(struct channel *, int, int, int, int, int);
157static void pcxe_put_char(struct tty_struct *, unsigned char);
158static void pcxe_flush_chars(struct tty_struct *);
159static void pcxx_error(int, char *);
160static void pcxe_close(struct tty_struct *, struct file *);
161static int pcxe_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
162static void pcxe_set_termios(struct tty_struct *, struct termios *);
163static int pcxe_write(struct tty_struct *, int, const unsigned char *, int);
164static int pcxe_write_room(struct tty_struct *);
165static int pcxe_chars_in_buffer(struct tty_struct *);
166static void pcxe_flush_buffer(struct tty_struct *);
167static void doevent(int);
168static void receive_data(struct channel *);
169static void pcxxparam(struct tty_struct *, struct channel *ch);
170static void do_softint(void *);
171static inline void pcxe_sched_event(struct channel *, int);
172static void do_pcxe_bh(void);
173static void pcxe_start(struct tty_struct *);
174static void pcxe_stop(struct tty_struct *);
175static void pcxe_throttle(struct tty_struct *);
176static void pcxe_unthrottle(struct tty_struct *);
177static void digi_send_break(struct channel *ch, int msec);
178static void shutdown(struct channel *);
179static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
180static inline void memwinon(struct board_info *b, unsigned int win);
181static inline void memwinoff(struct board_info *b, unsigned int win);
182static inline void globalwinon(struct channel *ch);
183static inline void rxwinon(struct channel *ch);
184static inline void txwinon(struct channel *ch);
185static inline void memoff(struct channel *ch);
186static inline void assertgwinon(struct channel *ch);
187static inline void assertmemoff(struct channel *ch);
188
189#define TZ_BUFSZ 4096
190
191/* function definitions */
192
193/*****************************************************************************/
194
195static void cleanup_board_resources(void)
196{
197	int crd, i;
198	struct board_info *bd;
199	struct channel *ch;
200
201        for(crd = 0; crd < numcards; crd++) {
202                bd = &boards[crd];
203		ch = digi_channels + bd->first_minor;
204
205		if (bd->region)
206			release_region(bd->port, 4);
207
208		for(i = 0; i < bd->numports; i++, ch++)
209			if (ch->tmp_buf)
210				kfree(ch->tmp_buf);
211	}
212}
213
214/*****************************************************************************/
215
216#ifdef MODULE
217
218/*
219 * pcxe_init() is our init_module():
220 */
221#define pcxe_init init_module
222
223void	cleanup_module(void);
224
225
226/*****************************************************************************/
227
228void cleanup_module()
229{
230
231	unsigned long	flags;
232	int e1, e2;
233
234	printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
235
236	save_flags(flags);
237	cli();
238	del_timer_sync(&pcxx_timer);
239	remove_bh(DIGI_BH);
240
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);
245
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);
252}
253#endif
254
255static inline struct channel *chan(register struct tty_struct *tty)
256{
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;
262		}
263	}
264	return NULL;
265}
266
267/* These inline routines are to turn board memory on and off */
268static inline void memwinon(struct board_info *b, unsigned int win)
269{
270	if(b->type == PCXEVE)
271		outb_p(FEPWIN|win, b->port+1);
272	else
273		outb_p(inb(b->port)|FEPMEM, b->port);
274}
275
276static inline void memwinoff(struct board_info *b, unsigned int win)
277{
278	outb_p(inb(b->port)&~FEPMEM, b->port);
279	if(b->type == PCXEVE)
280		outb_p(0, b->port + 1);
281}
282
283static inline void globalwinon(struct channel *ch)
284{
285	if(ch->board->type == PCXEVE)
286		outb_p(FEPWIN, ch->board->port+1);
287	else
288		outb_p(FEPMEM, ch->board->port);
289}
290
291static inline void rxwinon(struct channel *ch)
292{
293	if(ch->rxwin == 0)
294		outb_p(FEPMEM, ch->board->port);
295	else
296		outb_p(ch->rxwin, ch->board->port+1);
297}
298
299static inline void txwinon(struct channel *ch)
300{
301	if(ch->txwin == 0)
302		outb_p(FEPMEM, ch->board->port);
303	else
304		outb_p(ch->txwin, ch->board->port+1);
305}
306
307static inline void memoff(struct channel *ch)
308{
309	outb_p(0, ch->board->port);
310	if(ch->board->type == PCXEVE)
311		outb_p(0, ch->board->port+1);
312}
313
314static inline void assertgwinon(struct channel *ch)
315{
316	if(ch->board->type != PCXEVE)
317		pcxxassert(inb(ch->board->port) & FEPMEM, "Global memory off");
318}
319
320static inline void assertmemoff(struct channel *ch)
321{
322	if(ch->board->type != PCXEVE)
323		pcxxassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
324}
325
326static inline void pcxe_sched_event(struct channel *info, int event)
327{
328	info->event |= 1 << event;
329	queue_task(&info->tqueue, &tq_pcxx);
330	mark_bh(DIGI_BH);
331}
332
333static void pcxx_error(int line, char *msg)
334{
335	printk("pcxx_error (DigiBoard): line=%d %s\n", line, msg);
336}
337
338static int pcxx_waitcarrier(struct tty_struct *tty,struct file *filp,struct channel *info)
339{
340	DECLARE_WAITQUEUE(wait, current);
341	int	retval = 0;
342	int	do_clocal = 0;
343
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;
350	}
351
352	/*
353	 * Block waiting for the carrier detect and the line to become free
354	 */
355
356	retval = 0;
357	add_wait_queue(&info->open_wait, &wait);
358	info->count--;
359	info->blocked_open++;
360
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);
368		}
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;
377		}
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;
385		}
386		schedule();
387	}
388	current->state = TASK_RUNNING;
389	remove_wait_queue(&info->open_wait, &wait);
390
391	if(!tty_hung_up_p(filp))
392		info->count++;
393	info->blocked_open--;
394
395	return retval;
396}
397
398
399int pcxe_open(struct tty_struct *tty, struct file * filp)
400{
401	volatile struct board_chan *bc;
402	struct channel *ch;
403	unsigned long flags;
404	int line;
405	int boardnum;
406	int retval;
407
408	line = MINOR(tty->device) - tty->driver.minor_start;
409
410	if(line < 0 || line >= nbdevs) {
411		printk("line out of range in pcxe_open\n");
412		tty->driver_data = NULL;
413		return(-ENODEV);
414	}
415
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;
420
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);
425	}
426
427	ch = digi_channels+line;
428
429	if(ch->brdchan == 0) {
430		tty->driver_data = NULL;
431		return(-ENODEV);
432	}
433
434	/* flag the kernel that there is somebody using this guy */
435	MOD_INC_USE_COUNT;
436	/*
437	 * If the device is in the middle of being closed, then block
438	 * until it's done, and then try again.
439	 */
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;
446	}
447
448	save_flags(flags);
449	cli();
450	ch->count++;
451	tty->driver_data = ch;
452	ch->tty = tty;
453
454	if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) {
455		unsigned int head;
456
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;
471	}
472	restore_flags(flags);
473
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;
480	}
481	/*
482	 * If this is a callout device, then just make sure the normal
483	 * device isn't being used.
484	 */
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;
495		}
496		ch->asyncflags |= ASYNC_CALLOUT_ACTIVE;
497	}
498	else {
499		if (filp->f_flags & O_NONBLOCK) {
500			if(ch->asyncflags & ASYNC_CALLOUT_ACTIVE)
501				return -EBUSY;
502		}
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
509			 */
510			ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
511			if ((retval = pcxx_waitcarrier(tty, filp, ch)) != 0)
512				return retval;
513		}
514		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
515	}
516
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);
527	}
528
529	ch->session = current->session;
530	ch->pgrp = current->pgrp;
531	restore_flags(flags);
532	return 0;
533}
534
535static void shutdown(struct channel *info)
536{
537	unsigned long flags;
538	volatile struct board_chan *bc;
539	struct tty_struct *tty;
540
541	if (!(info->asyncflags & ASYNC_INITIALIZED))
542		return;
543
544	save_flags(flags);
545	cli();
546	globalwinon(info);
547
548	bc = info->brdchan;
549	if(bc)
550		bc->idata = 0;
551
552	tty = info->tty;
553
554	/*
555	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
556	 */
557	if(tty->termios->c_cflag & HUPCL) {
558		info->omodem &= ~(RTS|DTR);
559		fepcmd(info, SETMODEM, 0, DTR|RTS, 10, 1);
560	}
561
562	memoff(info);
563	info->asyncflags &= ~ASYNC_INITIALIZED;
564	restore_flags(flags);
565}
566
567
568static void pcxe_close(struct tty_struct * tty, struct file * filp)
569{
570	struct channel *info;
571
572	if ((info=chan(tty))!=NULL) {
573		unsigned long flags;
574		save_flags(flags);
575		cli();
576
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;
582		}
583		/* this check is in serial.c, it won't hurt to do it here too */
584		if ((tty->count == 1) && (info->count != 1)) {
585			/*
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.
591			 */
592			printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info->count);
593			info->count = 1;
594		}
595		if (info->count-- > 1) {
596			restore_flags(flags);
597			MOD_DEC_USE_COUNT;
598			return;
599		}
600		if (info->count < 0) {
601			info->count = 0;
602		}
603
604		info->asyncflags |= ASYNC_CLOSING;
605
606		/*
607		* Save the termios structure, since this port may have
608		* separate termios for callout and dialin.
609		*/
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 */
618		}
619
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.
634*/
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);
642		}
643#endif
644		if(info->blocked_open) {
645			if(info->close_delay) {
646				current->state = TASK_INTERRUPTIBLE;
647				schedule_timeout(info->close_delay);
648			}
649			wake_up_interruptible(&info->open_wait);
650		}
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);
656	}
657}
658
659
660void pcxe_hangup(struct tty_struct *tty)
661{
662	struct channel *ch;
663
664	if ((ch=chan(tty))!=NULL) {
665		unsigned long flags;
666
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);
676	}
677}
678
679
680
681static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
682{
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;
688	/* printk("Entering pcxe_write()\n"); */
689
690	if ((ch=chan(tty))==NULL)
691		return 0;
692
693	bc = ch->brdchan;
694	size = ch->txbufsize;
695
696	if (from_user) {
697
698		down(&ch->tmp_buf_sem);
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. */
705		do
706		{
707			tail = bc->tout;
708		} while (tail != bc->tout);
709
710		tail &= (size - 1);
711		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
712		count = MIN(stlen, count);
713		memoff(ch);
714		restore_flags(flags);
715
716		if (count)
717			if (copy_from_user(ch->tmp_buf, buf, count))
718				count = 0;
719
720		buf = ch->tmp_buf;
721	}
722
723	/*
724	 * All data is now local
725	 */
726
727	total = 0;
728	save_flags(flags);
729	cli();
730	globalwinon(ch);
731	head = bc->tin & (size - 1);
732	tail = bc->tout;
733	if (tail != bc->tout)
734		tail = bc->tout;
735	tail &= (size - 1);
736	if (head >= tail) {
737		remain = size - (head - tail) - 1;
738		stlen = size - head;
739	}
740	else {
741		remain = tail - head - 1;
742		stlen = remain;
743	}
744	count = MIN(remain, count);
745
746	txwinon(ch);
747	while (count > 0) {
748		stlen = MIN(count, stlen);
749		memcpy(ch->txptr + head, buf, stlen);
750		buf += stlen;
751		count -= stlen;
752		total += stlen;
753		head += stlen;
754		if (head >= size) {
755			head = 0;
756			stlen = tail;
757		}
758	}
759	ch->statusflags |= TXBUSY;
760	globalwinon(ch);
761	bc->tin = head;
762	if ((ch->statusflags & LOWWAIT) == 0) {
763		ch->statusflags |= LOWWAIT;
764		bc->ilow = 1;
765	}
766	memoff(ch);
767	restore_flags(flags);
768
769	if(from_user)
770		up(&ch->tmp_buf_sem);
771
772	return(total);
773}
774
775
776static void pcxe_put_char(struct tty_struct *tty, unsigned char c)
777{
778	pcxe_write(tty, 0, &c, 1);
779	return;
780}
781
782
783static int pcxe_write_room(struct tty_struct *tty)
784{
785	struct channel *ch;
786	int remain;
787
788	remain = 0;
789	if ((ch=chan(tty))!=NULL) {
790		volatile struct board_chan *bc;
791		unsigned int head, tail;
792		unsigned long flags;
793
794		save_flags(flags);
795		cli();
796		globalwinon(ch);
797
798		bc = ch->brdchan;
799		head = bc->tin & (ch->txbufsize - 1);
800		tail = bc->tout;
801		if (tail != bc->tout)
802			tail = bc->tout;
803		tail &= (ch->txbufsize - 1);
804
805		if((remain = tail - head - 1) < 0 )
806			remain += ch->txbufsize;
807
808		if (remain && (ch->statusflags & LOWWAIT) == 0) {
809			ch->statusflags |= LOWWAIT;
810			bc->ilow = 1;
811		}
812		memoff(ch);
813		restore_flags(flags);
814	}
815
816	return remain;
817}
818
819
820static int pcxe_chars_in_buffer(struct tty_struct *tty)
821{
822	int chars;
823	unsigned int ctail, head, tail;
824	int remain;
825	unsigned long flags;
826	struct channel *ch;
827	volatile struct board_chan *bc;
828
829	if ((ch=chan(tty))==NULL)
830		return(0);
831
832	save_flags(flags);
833	cli();
834	globalwinon(ch);
835
836	bc = ch->brdchan;
837	tail = bc->tout;
838	head = bc->tin;
839	ctail = ch->mailbox->cout;
840	if(tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
841		chars = 0;
842	else {
843		head = bc->tin & (ch->txbufsize - 1);
844		tail &= (ch->txbufsize - 1);
845		if((remain = tail - head - 1) < 0 )
846			remain += ch->txbufsize;
847
848		chars = (int)(ch->txbufsize - remain);
849
850		/*
851		 * Make it possible to wakeup anything waiting for output
852		 * in tty_ioctl.c, etc.
853		 */
854		if(!(ch->statusflags & EMPTYWAIT))
855			setup_empty_event(tty,ch);
856	}
857
858	memoff(ch);
859	restore_flags(flags);
860
861	return(chars);
862}
863
864
865static void pcxe_flush_buffer(struct tty_struct *tty)
866{
867	unsigned int tail;
868	volatile struct board_chan *bc;
869	struct channel *ch;
870	unsigned long flags;
871
872	if ((ch=chan(tty))==NULL)
873		return;
874
875	save_flags(flags);
876	cli();
877
878	globalwinon(ch);
879	bc = ch->brdchan;
880	tail = bc->tout;
881	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
882
883	memoff(ch);
884	restore_flags(flags);
885
886	wake_up_interruptible(&tty->write_wait);
887	if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
888		(tty->ldisc.write_wakeup)(tty);
889}
890
891static void pcxe_flush_chars(struct tty_struct *tty)
892{
893	struct channel * ch;
894
895	if ((ch=chan(tty))!=NULL) {
896		unsigned long flags;
897
898		save_flags(flags);
899		cli();
900		if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
901			setup_empty_event(tty,ch);
902		restore_flags(flags);
903	}
904}
905
906#ifndef MODULE
907
908/*
909 * Driver setup function when linked into the kernel to optionally parse multible
910 * "digi="-lines and initialize the driver at boot time. No probing.
911 */
912void __init pcxx_setup(char *str, int *ints)
913{
914
915	struct board_info board;
916	int               i, j, last;
917	char              *temp, *t2;
918	unsigned          len;
919
920	numcards=0;
921
922	memset(&board, 0, sizeof(board));
923
924	for(last=0,i=1;i<=ints[0];i++)
925		switch(i)
926		{
927			case 1:
928				board.status = ints[i];
929				last = i;
930				break;
931
932			case 2:
933				board.type = ints[i];
934				last = i;
935				break;
936
937			case 3:
938				board.altpin = ints[i];
939				last = i;
940				break;
941
942			case 4:
943				board.numports = ints[i];
944				last = i;
945				break;
946
947			case 5:
948				board.port = ints[i];
949				last = i;
950				break;
951
952			case 6:
953				board.membase = ints[i];
954				last = i;
955				break;
956
957			default:
958				printk("PC/Xx: Too many integer parms\n");
959				return;
960		}
961
962	while (str && *str)
963	{
964		/* find the next comma or terminator */
965		temp = str;
966		while (*temp && (*temp != ','))
967			temp++;
968
969		if (!*temp)
970			temp = NULL;
971		else
972			*temp++ = 0;
973
974		i = last + 1;
975
976		switch(i)
977		{
978			case 1:
979				len = strlen(str);
980				if (strncmp("Disable", str, len) == 0)
981					board.status = 0;
982				else
983					if (strncmp("Enable", str, len) == 0)
984						board.status = 1;
985					else
986					{
987						printk("PC/Xx: Invalid status %s\n", str);
988						return;
989					}
990				last = i;
991				break;
992
993			case 2:
994				for(j=0;j<PCXX_NUM_TYPES;j++)
995					if (strcmp(board_desc[j], str) == 0)
996						break;
997
998				if (i<PCXX_NUM_TYPES)
999					board.type = j;
1000				else
1001				{
1002					printk("PC/Xx: Invalid board name: %s\n", str);
1003					return;
1004				}
1005				last = i;
1006				break;
1007
1008			case 3:
1009				len = strlen(str);
1010				if (strncmp("Disable", str, len) == 0)
1011					board.altpin = 0;
1012				else
1013					if (strncmp("Enable", str, len) == 0)
1014						board.altpin = 1;
1015					else
1016					{
1017						printk("PC/Xx: Invalid altpin %s\n", str);
1018						return;
1019					}
1020				last = i;
1021				break;
1022
1023			case 4:
1024				t2 = str;
1025				while (isdigit(*t2))
1026					t2++;
1027
1028				if (*t2)
1029				{
1030					printk("PC/Xx: Invalid port count %s\n", str);
1031					return;
1032				}
1033
1034				board.numports = simple_strtoul(str, NULL, 0);
1035				last = i;
1036				break;
1037
1038			case 5:
1039				t2 = str;
1040				while (isxdigit(*t2))
1041					t2++;
1042
1043				if (*t2)
1044				{
1045					printk("PC/Xx: Invalid io port address %s\n", str);
1046					return;
1047				}
1048
1049				board.port = simple_strtoul(str, NULL, 16);
1050				last = i;
1051				break;
1052
1053			case 6:
1054				t2 = str;
1055				while (isxdigit(*t2))
1056					t2++;
1057
1058				if (*t2)
1059				{
1060					printk("PC/Xx: Invalid memory base %s\n", str);
1061					return;
1062				}
1063
1064				board.membase = simple_strtoul(str, NULL, 16);
1065				last = i;
1066				break;
1067
1068			default:
1069				printk("PC/Xx: Too many string parms\n");
1070				return;
1071		}
1072		str = temp;
1073	}
1074
1075	if (last < 6)
1076	{
1077		printk("PC/Xx: Insufficient parms specified\n");
1078		return;
1079	}
1080
1081        /* I should REALLY validate the stuff here */
1082
1083	memcpy(&boards[numcards],&board, sizeof(board));
1084	printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n",
1085		numcards, board_desc[board.type], board_mem[board.type],
1086		board.numports, board.port, (unsigned int) board.membase);
1087
1088	/* keep track of my initial minor number */
1089        if (numcards)
1090		boards[numcards].first_minor = boards[numcards-1].first_minor + boards[numcards-1].numports;
1091	else
1092		boards[numcards].first_minor = 0;
1093
1094	/* yeha!  string parameter was successful! */
1095	numcards++;
1096}
1097#endif
1098
1099/*
1100 * function to initialize the driver with the given parameters, which are either
1101 * the default values from this file or the parameters given at boot.
1102 */
1103int __init pcxe_init(void)
1104{
1105	ulong memory_seg=0, memory_size=0;
1106	int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L;
1107	int ret = -ENOMEM;
1108	unchar *fepos, *memaddr, *bios, v;
1109	volatile struct global_data *gd;
1110	volatile struct board_chan *bc;
1111	struct board_info *bd;
1112	struct channel *ch;
1113
1114	printk(KERN_NOTICE "Digiboard PC/X{i,e,eve} driver v%s\n", VERSION);
1115
1116#ifdef MODULE
1117	for (i = 0; i < MAX_DIGI_BOARDS; i++) {
1118		if (io[i]) {
1119			numcards = 0;
1120			break;
1121		}
1122	}
1123	if (numcards == 0) {
1124		int first_minor = 0;
1125
1126		for (i = 0; i < MAX_DIGI_BOARDS; i++) {
1127			if (io[i] == 0) {
1128				boards[i].port    = 0;
1129				boards[i].status  = DISABLED;
1130			}
1131			else {
1132				boards[i].port         = (ushort)io[i];
1133				boards[i].status       = ENABLED;
1134				boards[i].first_minor  = first_minor;
1135				numcards=i+1;
1136			}
1137			if (membase[i])
1138				boards[i].membase = (ulong)membase[i];
1139			else
1140				boards[i].membase = 0xD0000;
1141
1142			if (memsize[i])
1143				boards[i].memsize = (ulong)(memsize[i] * 1024);
1144			else
1145				boards[i].memsize = 0;
1146
1147			if (altpin[i])
1148				boards[i].altpin  = ON;
1149			else
1150				boards[i].altpin  = OFF;
1151
1152			if (numports[i])
1153				boards[i].numports  = (ushort)numports[i];
1154			else
1155				boards[i].numports  = 16;
1156
1157			boards[i].region = NULL;
1158			first_minor += boards[i].numports;
1159		}
1160	}
1161#endif
1162
1163	if (numcards <= 0)
1164	{
1165		printk("PC/Xx: No cards configured, driver not active.\n");
1166		return -EIO;
1167	}
1168	if (debug)
1169	    for (i = 0; i < numcards; i++) {
1170		    printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",
1171			    i+1,
1172			    boards[i].status,
1173			    boards[i].port,
1174			    boards[i].membase,
1175			    boards[i].memsize,
1176			    boards[i].altpin,
1177			    boards[i].numports,
1178			    boards[i].first_minor);
1179	    }
1180
1181	for (i=0;i<numcards;i++)
1182		nbdevs += boards[i].numports;
1183
1184	if (nbdevs <= 0)
1185	{
1186		printk("PC/Xx: No devices activated, driver not active.\n");
1187		return -EIO;
1188	}
1189
1190	/*
1191	 * this turns out to be more memory efficient, as there are no
1192	 * unused spaces.
1193	 */
1194	digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
1195	if (!digi_channels) {
1196		printk(KERN_ERR "Unable to allocate digi_channel struct\n");
1197		return -ENOMEM;
1198	}
1199	memset(digi_channels, 0, sizeof(struct channel) * nbdevs);
1200
1201	pcxe_table =  kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
1202	if (!pcxe_table) {
1203		printk(KERN_ERR "Unable to allocate pcxe_table struct\n");
1204		goto cleanup_digi_channels;
1205	}
1206	memset(pcxe_table, 0, sizeof(struct tty_struct *) * nbdevs);
1207
1208	pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
1209	if (!pcxe_termios) {
1210		printk(KERN_ERR "Unable to allocate pcxe_termios struct\n");
1211		goto cleanup_pcxe_table;
1212	}
1213	memset(pcxe_termios,0,sizeof(struct termios *)*nbdevs);
1214
1215	pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
1216	if (!pcxe_termios_locked) {
1217		printk(KERN_ERR "Unable to allocate pcxe_termios_locked struct\n");
1218		goto cleanup_pcxe_termios;
1219	}
1220	memset(pcxe_termios_locked,0,sizeof(struct termios *)*nbdevs);
1221
1222	init_bh(DIGI_BH,do_pcxe_bh);
1223
1224	init_timer(&pcxx_timer);
1225	pcxx_timer.function = pcxxpoll;
1226
1227	memset(&pcxe_driver, 0, sizeof(struct tty_driver));
1228	pcxe_driver.magic = TTY_DRIVER_MAGIC;
1229	pcxe_driver.name = "ttyD";
1230	pcxe_driver.major = DIGI_MAJOR;
1231	pcxe_driver.minor_start = 0;
1232
1233	pcxe_driver.num = nbdevs;
1234
1235	pcxe_driver.type = TTY_DRIVER_TYPE_SERIAL;
1236	pcxe_driver.subtype = SERIAL_TYPE_NORMAL;
1237	pcxe_driver.init_termios = tty_std_termios;
1238	pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
1239	pcxe_driver.flags = TTY_DRIVER_REAL_RAW;
1240	pcxe_driver.refcount = &pcxe_refcount;
1241
1242	pcxe_driver.table = pcxe_table;
1243	pcxe_driver.termios = pcxe_termios;
1244	pcxe_driver.termios_locked = pcxe_termios_locked;
1245
1246	pcxe_driver.open = pcxe_open;
1247	pcxe_driver.close = pcxe_close;
1248	pcxe_driver.write = pcxe_write;
1249	pcxe_driver.put_char = pcxe_put_char;
1250	pcxe_driver.flush_chars = pcxe_flush_chars;
1251	pcxe_driver.write_room = pcxe_write_room;
1252	pcxe_driver.chars_in_buffer = pcxe_chars_in_buffer;
1253	pcxe_driver.flush_buffer = pcxe_flush_buffer;
1254	pcxe_driver.ioctl = pcxe_ioctl;
1255	pcxe_driver.throttle = pcxe_throttle;
1256	pcxe_driver.unthrottle = pcxe_unthrottle;
1257	pcxe_driver.set_termios = pcxe_set_termios;
1258	pcxe_driver.stop = pcxe_stop;
1259	pcxe_driver.start = pcxe_start;
1260	pcxe_driver.hangup = pcxe_hangup;
1261
1262	pcxe_callout = pcxe_driver;
1263	pcxe_callout.name = "cud";
1264	pcxe_callout.major = DIGICU_MAJOR;
1265	pcxe_callout.subtype = SERIAL_TYPE_CALLOUT;
1266	pcxe_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1267
1268	for(crd=0; crd < numcards; crd++) {
1269		bd = &boards[crd];
1270		outb(FEPRST, bd->port);
1271		mdelay(1);
1272
1273		for(i=0; (inb(bd->port) & FEPMASK) != FEPRST; i++) {
1274			if(i > 100) {
1275				printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
1276					bd->port);
1277				bd->status = DISABLED;
1278				break;
1279			}
1280#ifdef MODULE
1281			schedule();
1282#endif
1283			mdelay(10);
1284		}
1285		if(bd->status == DISABLED)
1286			continue;
1287
1288		v = inb(bd->port);
1289
1290		if((v & 0x1) == 0x1) {
1291			if((v & 0x30) == 0) {        /* PC/Xi 64K card */
1292				memory_seg = 0xf000;
1293				memory_size = 0x10000;
1294			}
1295
1296			if((v & 0x30) == 0x10) {     /* PC/Xi 128K card */
1297				memory_seg = 0xe000;
1298				memory_size = 0x20000;
1299			}
1300
1301			if((v & 0x30) == 0x20) {     /* PC/Xi 256K card */
1302				memory_seg = 0xc000;
1303				memory_size = 0x40000;
1304			}
1305
1306			if((v & 0x30) == 0x30) {     /* PC/Xi 512K card */
1307				memory_seg = 0x8000;
1308				memory_size = 0x80000;
1309			}
1310			bd->type = PCXI;
1311		} else {
1312			if((v & 0x1) == 0x1) {
1313				bd->status = DISABLED;   /* PC/Xm unsupported card */
1314				printk("PC/Xx: PC/Xm at 0x%x not supported!!\n", bd->port);
1315				continue;
1316			} else {
1317				if(v & 0xC0) {
1318					topwin = 0x1f00L;
1319					outb((((ulong)bd->membase>>8) & 0xe0) | 0x10, bd->port+2);
1320					outb(((ulong)bd->membase>>16) & 0xff, bd->port+3);
1321					bd->type = PCXEVE; /* PC/Xe 8K card */
1322				} else {
1323					bd->type = PCXE;    /* PC/Xe 64K card */
1324				}
1325
1326				memory_seg = 0xf000;
1327				memory_size = 0x10000;
1328			}
1329		}
1330		if (verbose)
1331			printk("Configuring card %d as a %s %ldK card. io=0x%x, mem=%lx-%lx\n",
1332				crd+1, board_desc[bd->type], memory_size/1024,
1333				bd->port,bd->membase,bd->membase+memory_size-1);
1334
1335		if (boards[crd].memsize == 0)
1336			boards[crd].memsize = memory_size;
1337		else
1338			if (boards[crd].memsize != memory_size) {
1339			    printk("PC/Xx: memory size mismatch:supplied=%lx(%ldK) probed=%ld(%ldK)\n",
1340				    boards[crd].memsize, boards[crd].memsize / 1024,
1341				    memory_size, memory_size / 1024);
1342			    continue;
1343			}
1344
1345		memaddr = (unchar *)phys_to_virt(bd->membase);
1346
1347		if (verbose)
1348			printk("Resetting board and testing memory access:");
1349
1350		outb(FEPRST|FEPMEM, bd->port);
1351
1352		for(i=0; (inb(bd->port) & FEPMASK) != (FEPRST|FEPMEM); i++) {
1353			if(i > 1000) {
1354				printk("\nPC/Xx: %s not resetting at port 0x%x! Check switch settings.\n",
1355					board_desc[bd->type], bd->port);
1356				bd->status = DISABLED;
1357				break;
1358			}
1359#ifdef MODULE
1360			schedule();
1361#endif
1362			mdelay(1);
1363		}
1364		if(bd->status == DISABLED)
1365			continue;
1366
1367		memwinon(bd,0);
1368		*(ulong *)(memaddr + botwin) = 0xa55a3cc3;
1369		*(ulong *)(memaddr + topwin) = 0x5aa5c33c;
1370
1371		if(*(ulong *)(memaddr + botwin) != 0xa55a3cc3 ||
1372					*(ulong *)(memaddr + topwin) != 0x5aa5c33c) {
1373			printk("PC/Xx: Failed memory test at %lx for %s at port %x, check switch settings.\n",
1374				bd->membase, board_desc[bd->type], bd->port);
1375			bd->status = DISABLED;
1376			continue;
1377		}
1378		if (verbose)
1379			printk(" done.\n");
1380
1381		for(i=0; i < 16; i++) {
1382			memaddr[MISCGLOBAL+i] = 0;
1383		}
1384
1385		if(bd->type == PCXI || bd->type == PCXE) {
1386			bios = memaddr + BIOSCODE + ((0xf000 - memory_seg) << 4);
1387
1388			if (verbose)
1389				printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios));
1390
1391			memcpy(bios, pcxx_bios, pcxx_nbios);
1392
1393			if (verbose)
1394				printk(" done.\n");
1395
1396			outb(FEPMEM, bd->port);
1397
1398			if (verbose)
1399				printk("Waiting for BIOS to become ready");
1400
1401			for(i=1; i <= 30; i++) {
1402				if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
1403					goto load_fep;
1404				}
1405				if (verbose) {
1406					printk(".");
1407					if (i % 50 == 0)
1408						printk("\n");
1409				}
1410#ifdef MODULE
1411				schedule();
1412#endif
1413				mdelay(50);
1414			}
1415
1416			printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n",
1417							bd->port, bd->membase, bd->membase+bd->memsize);
1418			bd->status = DISABLED;
1419			continue;
1420		}
1421
1422		if(bd->type == PCXEVE) {
1423			bios = memaddr + (BIOSCODE & 0x1fff);
1424			memwinon(bd,0xff);
1425
1426			memcpy(bios, pcxx_bios, pcxx_nbios);
1427
1428			outb(FEPCLR, bd->port);
1429			memwinon(bd,0);
1430
1431			for(i=0; i <= 1000; i++) {
1432				if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
1433					goto load_fep;
1434				}
1435				if (verbose) {
1436					printk(".");
1437					if (i % 50 == 0)
1438						printk("\n");
1439				}
1440#ifdef MODULE
1441				schedule();
1442#endif
1443				mdelay(10);
1444			}
1445
1446			printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n",
1447				board_desc[bd->type], bd->port);
1448			bd->status = DISABLED;
1449			continue;
1450		}
1451
1452load_fep:
1453		fepos = memaddr + FEPCODE;
1454		if(bd->type == PCXEVE)
1455			fepos = memaddr + (FEPCODE & 0x1fff);
1456
1457		if (verbose)
1458			printk(" ok.\nDownloading FEP/OS to 0x%lx:", virt_to_phys(fepos));
1459
1460		memwinon(bd, (FEPCODE >> 13));
1461		memcpy(fepos, pcxx_cook, pcxx_ncook);
1462		memwinon(bd, 0);
1463
1464		if (verbose)
1465			printk(" done.\n");
1466
1467		*(ushort *)((ulong)memaddr + MBOX +  0) = 2;
1468		*(ushort *)((ulong)memaddr + MBOX +  2) = memory_seg + FEPCODESEG;
1469		*(ushort *)((ulong)memaddr + MBOX +  4) = 0;
1470		*(ushort *)((ulong)memaddr + MBOX +  6) = FEPCODESEG;
1471		*(ushort *)((ulong)memaddr + MBOX +  8) = 0;
1472		*(ushort *)((ulong)memaddr + MBOX + 10) = pcxx_ncook;
1473
1474		outb(FEPMEM|FEPINT, bd->port);
1475		outb(FEPMEM, bd->port);
1476
1477		for(i=0; *(ushort *)((ulong)memaddr + MBOX); i++) {
1478			if(i > 2000) {
1479				printk("PC/Xx: Command failed for the %s at 0x%x!\n",
1480					board_desc[bd->type], bd->port);
1481				bd->status = DISABLED;
1482				break;
1483			}
1484#ifdef MODULE
1485			schedule();
1486#endif
1487			mdelay(1);
1488		}
1489
1490		if(bd->status == DISABLED)
1491			continue;
1492
1493		if (verbose)
1494			printk("Waiting for FEP/OS to become ready");
1495
1496		*(ushort *)(memaddr + FEPSTAT) = 0;
1497		*(ushort *)(memaddr + MBOX + 0) = 1;
1498		*(ushort *)(memaddr + MBOX + 2) = FEPCODESEG;
1499		*(ushort *)(memaddr + MBOX + 4) = 0x4L;
1500
1501		outb(FEPINT, bd->port);
1502		outb(FEPCLR, bd->port);
1503		memwinon(bd, 0);
1504
1505		for(i=1; *(ushort *)((ulong)memaddr + FEPSTAT) != *(ushort *)"OS"; i++) {
1506			if(i > 1000) {
1507				printk("\nPC/Xx: FEP/OS download failed on the %s at 0x%x!\n",
1508					board_desc[bd->type], bd->port);
1509				bd->status = DISABLED;
1510				break;
1511			}
1512			if (verbose) {
1513				printk(".");
1514				if (i % 50 == 0)
1515					printk("\n%5d",i/50);
1516			}
1517#ifdef MODULE
1518			schedule();
1519#endif
1520			mdelay(1);
1521		}
1522		if(bd->status == DISABLED)
1523			continue;
1524
1525		if (verbose)
1526			printk(" ok.\n");
1527
1528		ch = digi_channels+bd->first_minor;
1529		pcxxassert(ch < digi_channels+nbdevs, "ch out of range");
1530
1531		bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
1532		gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
1533
1534		if((bd->type == PCXEVE) && (*(ushort *)((ulong)memaddr+NPORT) < 3))
1535			shrinkmem = 1;
1536
1537		bd->region = request_region(bd->port, 4, "PC/Xx");
1538
1539		if (!bd->region) {
1540			printk(KERN_ERR "I/O port 0x%x is already used\n", bd->port);
1541			ret = -EBUSY;
1542			goto cleanup_boards;
1543		}
1544
1545		for(i=0; i < bd->numports; i++, ch++, bc++) {
1546			if(((ushort *)((ulong)memaddr + PORTBASE))[i] == 0) {
1547				ch->brdchan = 0;
1548				continue;
1549			}
1550			ch->brdchan = bc;
1551			ch->mailbox = gd;
1552			ch->tqueue.routine = do_softint;
1553			ch->tqueue.data = ch;
1554			ch->board = &boards[crd];
1555#ifdef DEFAULT_HW_FLOW
1556			ch->digiext.digi_flags = RTSPACE|CTSPACE;
1557#endif
1558			if(boards[crd].altpin) {
1559				ch->dsr = CD;
1560				ch->dcd = DSR;
1561				ch->digiext.digi_flags |= DIGI_ALTPIN;
1562			} else {
1563				ch->dcd = CD;
1564				ch->dsr = DSR;
1565			}
1566
1567			ch->magic = PCXX_MAGIC;
1568			ch->boardnum = crd;
1569			ch->channelnum = i;
1570
1571			ch->dev = bd->first_minor + i;
1572			ch->tty = 0;
1573
1574			if(shrinkmem) {
1575				fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
1576				shrinkmem = 0;
1577			}
1578
1579			if(bd->type != PCXEVE) {
1580				ch->txptr = memaddr+((bc->tseg-memory_seg) << 4);
1581				ch->rxptr = memaddr+((bc->rseg-memory_seg) << 4);
1582				ch->txwin = ch->rxwin = 0;
1583			} else {
1584				ch->txptr = memaddr+(((bc->tseg-memory_seg) << 4) & 0x1fff);
1585				ch->txwin = FEPWIN | ((bc->tseg-memory_seg) >> 9);
1586				ch->rxptr = memaddr+(((bc->rseg-memory_seg) << 4) & 0x1fff);
1587				ch->rxwin = FEPWIN | ((bc->rseg-memory_seg) >>9 );
1588			}
1589
1590			ch->txbufsize = bc->tmax + 1;
1591			ch->rxbufsize = bc->rmax + 1;
1592			ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
1593			init_MUTEX(&ch->tmp_buf_sem);
1594
1595			if (!ch->tmp_buf) {
1596				printk(KERN_ERR "Unable to allocate memory for temp buffers\n");
1597				goto cleanup_boards;
1598			}
1599
1600			lowwater = ch->txbufsize >= 2000 ? 1024 : ch->txbufsize/2;
1601			fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
1602			fepcmd(ch, SRXLWATER, ch->rxbufsize/4, 0, 10, 0);
1603			fepcmd(ch, SRXHWATER, 3 * ch->rxbufsize/4, 0, 10, 0);
1604
1605			bc->edelay = 100;
1606			bc->idata = 1;
1607
1608			ch->startc = bc->startc;
1609			ch->stopc = bc->stopc;
1610			ch->startca = bc->startca;
1611			ch->stopca = bc->stopca;
1612
1613			ch->fepcflag = 0;
1614			ch->fepiflag = 0;
1615			ch->fepoflag = 0;
1616			ch->fepstartc = 0;
1617			ch->fepstopc = 0;
1618			ch->fepstartca = 0;
1619			ch->fepstopca = 0;
1620
1621			ch->close_delay = 50;
1622			ch->count = 0;
1623			ch->blocked_open = 0;
1624			ch->callout_termios = pcxe_callout.init_termios;
1625			ch->normal_termios = pcxe_driver.init_termios;
1626			init_waitqueue_head(&ch->open_wait);
1627			init_waitqueue_head(&ch->close_wait);
1628			ch->asyncflags = 0;
1629		}
1630
1631		if (verbose)
1632		    printk("Card No. %d ready: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1633			    crd+1, board_desc[bd->type], board_mem[bd->type], bd->port,
1634			    bd->membase, bd->numports);
1635		else
1636		    printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
1637			    board_desc[bd->type], board_mem[bd->type], bd->port,
1638			    bd->membase, bd->numports);
1639
1640		memwinoff(bd, 0);
1641		enabled_cards++;
1642	}
1643
1644	if (enabled_cards <= 0) {
1645		printk(KERN_NOTICE "PC/Xx: No cards enabled, no driver.\n");
1646		ret = -EIO;
1647		goto cleanup_boards;
1648	}
1649
1650	ret = tty_register_driver(&pcxe_driver);
1651	if(ret) {
1652		printk(KERN_ERR "Couldn't register PC/Xe driver\n");
1653		goto cleanup_boards;
1654	}
1655
1656	ret = tty_register_driver(&pcxe_callout);
1657	if(ret) {
1658		printk(KERN_ERR "Couldn't register PC/Xe callout\n");
1659		goto cleanup_pcxe_driver;
1660	}
1661
1662	/*
1663	 * Start up the poller to check for events on all enabled boards
1664	 */
1665	mod_timer(&pcxx_timer, HZ/25);
1666
1667	if (verbose)
1668		printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards);
1669
1670	return 0;
1671cleanup_pcxe_driver:	tty_unregister_driver(&pcxe_driver);
1672cleanup_boards:		cleanup_board_resources();
1673			kfree(pcxe_termios_locked);
1674cleanup_pcxe_termios:	kfree(pcxe_termios);
1675cleanup_pcxe_table:	kfree(pcxe_table);
1676cleanup_digi_channels:	kfree(digi_channels);
1677	return ret;
1678}
1679
1680
1681static void pcxxpoll(unsigned long dummy)
1682{
1683	unsigned long flags;
1684	int crd;
1685	volatile unsigned int head, tail;
1686	struct channel *ch;
1687	struct board_info *bd;
1688
1689	save_flags(flags);
1690	cli();
1691
1692	for(crd=0; crd < numcards; crd++) {
1693		bd = &boards[crd];
1694
1695		ch = digi_channels+bd->first_minor;
1696
1697		if(bd->status == DISABLED)
1698			continue;
1699
1700		assertmemoff(ch);
1701
1702		globalwinon(ch);
1703		head = ch->mailbox->ein;
1704		tail = ch->mailbox->eout;
1705
1706		if(head != tail)
1707			doevent(crd);
1708
1709		memoff(ch);
1710	}
1711
1712	mod_timer(&pcxx_timer, jiffies + HZ/25);
1713	restore_flags(flags);
1714}
1715
1716static void doevent(int crd)
1717{
1718	volatile struct board_info *bd;
1719	static struct tty_struct *tty;
1720	volatile struct board_chan *bc;
1721	volatile unchar *eventbuf;
1722	volatile unsigned int head;
1723	volatile unsigned int tail;
1724	struct channel *ch;
1725	struct channel *chan0;
1726	int channel, event, mstat, lstat;
1727
1728	bd = &boards[crd];
1729
1730	chan0 = digi_channels+bd->first_minor;
1731	pcxxassert(chan0 < digi_channels+nbdevs, "ch out of range");
1732
1733
1734	assertgwinon(chan0);
1735
1736	while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) {
1737		assertgwinon(chan0);
1738		eventbuf = (volatile unchar *)phys_to_virt(bd->membase + tail + ISTART);
1739		channel = eventbuf[0];
1740		event = eventbuf[1];
1741		mstat = eventbuf[2];
1742		lstat = eventbuf[3];
1743
1744		ch=chan0+channel;
1745
1746		if ((unsigned)channel >= bd->numports || !ch) {
1747			printk("physmem=%lx, tail=%x, head=%x\n", bd->membase, tail, head);
1748			printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
1749					crd, (unsigned)channel, event, (unsigned)mstat, lstat);
1750			if(channel >= bd->numports)
1751				ch = chan0;
1752			bc = ch->brdchan;
1753			goto next;
1754		}
1755		if ((bc = ch->brdchan) == NULL)
1756			goto next;
1757
1758		if (event & DATA_IND) {
1759			receive_data(ch);
1760			assertgwinon(ch);
1761		}
1762
1763		if (event & MODEMCHG_IND) {
1764			ch->imodem = mstat;
1765			if (ch->asyncflags & (ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE)) {
1766				if (ch->asyncflags & ASYNC_CHECK_CD) {
1767					if (mstat & ch->dcd) {
1768						wake_up_interruptible(&ch->open_wait);
1769					} else {
1770						pcxe_sched_event(ch, PCXE_EVENT_HANGUP);
1771					}
1772				}
1773			}
1774		}
1775
1776		tty = ch->tty;
1777
1778		if (tty) {
1779
1780			if (event & BREAK_IND) {
1781				tty->flip.count++;
1782				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
1783				*tty->flip.char_buf_ptr++ = 0;
1784				tty_schedule_flip(tty);
1785			}
1786
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);
1794				}
1795			}
1796
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);
1805				}
1806			}
1807		}
1808
1809	next:
1810		globalwinon(ch);
1811		if(!bc) printk("bc == NULL in doevent!\n");
1812		else bc->idata = 1;
1813
1814		chan0->mailbox->eout = (tail+4) & (IMAX-ISTART-4);
1815		globalwinon(chan0);
1816	}
1817
1818}
1819
1820
1821static void
1822fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds,
1823						int bytecmd)
1824{
1825	unchar *memaddr;
1826	unsigned int head, tail;
1827	long count;
1828	int n;
1829
1830	if(ch->board->status == DISABLED)
1831		return;
1832
1833	assertgwinon(ch);
1834
1835	memaddr = (unchar *)phys_to_virt(ch->board->membase);
1836	head = ch->mailbox->cin;
1837
1838	if(head >= (CMAX-CSTART) || (head & 03)) {
1839		printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__, cmd, head);
1840		return;
1841	}
1842
1843	if(bytecmd) {
1844		*(unchar *)(memaddr+head+CSTART+0) = cmd;
1845
1846		*(unchar *)(memaddr+head+CSTART+1) = ch->dev - ch->board->first_minor;
1847
1848		*(unchar *)(memaddr+head+CSTART+2) = word_or_byte;
1849		*(unchar *)(memaddr+head+CSTART+3) = byte2;
1850	} else {
1851		*(unchar *)(memaddr+head+CSTART+0) = cmd;
1852
1853		*(unchar *)(memaddr+head+CSTART+1) = ch->dev - ch->board->first_minor;
1854		*(ushort*)(memaddr+head+CSTART+2) = word_or_byte;
1855	}
1856
1857	head = (head+4) & (CMAX-CSTART-4);
1858	ch->mailbox->cin = head;
1859
1860	count = FEPTIMEOUT;
1861
1862	while(1) {
1863		count--;
1864		if(count == 0) {
1865			printk("Fep not responding in fepcmd()\n");
1866			return;
1867		}
1868
1869		head = ch->mailbox->cin;
1870		tail = ch->mailbox->cout;
1871
1872		n = (head-tail) & (CMAX-CSTART-4);
1873
1874		if(n <= ncmds * (sizeof(short)*4))
1875			break;
1876		/* Seems not to be good here: schedule(); */
1877	}
1878}
1879
1880
1881static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
1882{
1883	unsigned res = 0;
1884	if (cflag & CBAUDEX)
1885	{
1886		ch->digiext.digi_flags |= DIGI_FAST;
1887		res |= FEP_HUPCL;
1888		/* This gets strange but if we don't do this we will get 78600
1889		 * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
1890		 * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
1891		 * do 115K
1892		 */
1893		if (cflag & B115200) res|=1;
1894	}
1895	else ch->digiext.digi_flags &= ~DIGI_FAST;
1896	res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE | CLOCAL);
1897	return res;
1898}
1899
1900static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
1901{
1902	unsigned res = iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|IXON|IXANY|IXOFF);
1903
1904	if(ch->digiext.digi_flags & DIGI_AIXON)
1905		res |= IAIXON;
1906	return res;
1907}
1908
1909static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
1910{
1911	unsigned res = 0;
1912
1913	if(cflag & CRTSCTS) {
1914		ch->digiext.digi_flags |= (RTSPACE|CTSPACE);
1915		res |= (CTS | RTS);
1916	}
1917	if(ch->digiext.digi_flags & RTSPACE)
1918		res |= RTS;
1919	if(ch->digiext.digi_flags & DTRPACE)
1920		res |= DTR;
1921	if(ch->digiext.digi_flags & CTSPACE)
1922		res |= CTS;
1923	if(ch->digiext.digi_flags & DSRPACE)
1924		res |= ch->dsr;
1925	if(ch->digiext.digi_flags & DCDPACE)
1926		res |= ch->dcd;
1927
1928	if (res & RTS)
1929		ch->digiext.digi_flags |= RTSPACE;
1930	if (res & CTS)
1931		ch->digiext.digi_flags |= CTSPACE;
1932
1933	return res;
1934}
1935
1936static void pcxxparam(struct tty_struct *tty, struct channel *ch)
1937{
1938	volatile struct board_chan *bc;
1939	unsigned int head;
1940	unsigned mval, hflow, cflag, iflag;
1941	struct termios *ts;
1942
1943	bc = ch->brdchan;
1944	assertgwinon(ch);
1945	ts = tty->termios;
1946
1947	if((ts->c_cflag & CBAUD) == 0) {
1948		head = bc->rin;
1949		bc->rout = head;
1950		head = bc->tin;
1951		fepcmd(ch, STOUT, (unsigned) head, 0, 0, 0);
1952		mval = 0;
1953	} else {
1954
1955		cflag = termios2digi_c(ch, ts->c_cflag);
1956
1957		if(cflag != ch->fepcflag) {
1958			ch->fepcflag = cflag;
1959			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
1960		}
1961
1962		if(cflag & CLOCAL)
1963			ch->asyncflags &= ~ASYNC_CHECK_CD;
1964		else {
1965			ch->asyncflags |= ASYNC_CHECK_CD;
1966		}
1967
1968		mval = DTR | RTS;
1969	}
1970
1971	iflag = termios2digi_i(ch, ts->c_iflag);
1972
1973	if(iflag != ch->fepiflag) {
1974		ch->fepiflag = iflag;
1975		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
1976	}
1977
1978	bc->mint = ch->dcd;
1979	if((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
1980		if(ch->digiext.digi_flags & DIGI_FORCEDCD)
1981			bc->mint = 0;
1982
1983	ch->imodem = bc->mstat;
1984
1985	hflow = termios2digi_h(ch, ts->c_cflag);
1986
1987	if(hflow != ch->hflow) {
1988		ch->hflow = hflow;
1989		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
1990	}
1991
1992	/* mval ^= ch->modemfake & (mval ^ ch->modem); */
1993
1994	if(ch->omodem != mval) {
1995		ch->omodem = mval;
1996		fepcmd(ch, SETMODEM, mval, RTS|DTR, 0, 1);
1997	}
1998
1999	if(ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
2000		ch->fepstartc = ch->startc;
2001		ch->fepstopc = ch->stopc;
2002		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
2003	}
2004
2005	if(ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
2006		ch->fepstartca = ch->startca;
2007		ch->fepstopca = ch->stopca;
2008		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
2009	}
2010}
2011
2012
2013static void receive_data(struct channel *ch)
2014{
2015	volatile struct board_chan *bc;
2016	struct tty_struct *tty;
2017	unsigned int tail, head, wrapmask;
2018	int n;
2019	int piece;
2020	struct termios *ts=0;
2021	unchar *rptr;
2022	int rc;
2023	int wrapgap;
2024
2025    globalwinon(ch);
2026
2027	if (ch->statusflags & RXSTOPPED)
2028		return;
2029
2030	tty = ch->tty;
2031	if(tty)
2032		ts = tty->termios;
2033
2034	bc = ch->brdchan;
2035
2036	if(!bc) {
2037		printk("bc is NULL in receive_data!\n");
2038		return;
2039	}
2040
2041	wrapmask = ch->rxbufsize - 1;
2042
2043	head = bc->rin;
2044	head &= wrapmask;
2045	tail = bc->rout & wrapmask;
2046
2047	n = (head-tail) & wrapmask;
2048
2049	if(n == 0)
2050		return;
2051
2052	/*
2053	 * If CREAD bit is off or device not open, set TX tail to head
2054	 */
2055	if(!tty || !ts || !(ts->c_cflag & CREAD)) {
2056		bc->rout = head;
2057		return;
2058	}
2059
2060	if(tty->flip.count == TTY_FLIPBUF_SIZE) {
2061		/* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
2062		return;
2063	}
2064
2065	if(bc->orun) {
2066		bc->orun = 0;
2067		printk("overrun! DigiBoard device minor=%d\n",MINOR(tty->device));
2068	}
2069
2070	rxwinon(ch);
2071	rptr = tty->flip.char_buf_ptr;
2072	rc = tty->flip.count;
2073	while(n > 0) {
2074		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
2075		piece = (wrapgap < n) ? wrapgap : n;
2076
2077		/*
2078		 * Make sure we don't overflow the buffer
2079		 */
2080
2081		if ((rc + piece) > TTY_FLIPBUF_SIZE)
2082			piece = TTY_FLIPBUF_SIZE - rc;
2083
2084		if (piece == 0)
2085			break;
2086
2087		memcpy(rptr, ch->rxptr + tail, piece);
2088		rptr += piece;
2089		rc += piece;
2090		tail = (tail + piece) & wrapmask;
2091		n -= piece;
2092	}
2093	tty->flip.count = rc;
2094	tty->flip.char_buf_ptr = rptr;
2095    globalwinon(ch);
2096	bc->rout = tail;
2097
2098	/* Must be called with global data */
2099	tty_schedule_flip(ch->tty);
2100	return;
2101}
2102
2103
2104static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
2105		    unsigned int cmd, unsigned long arg)
2106{
2107	struct channel *ch = (struct channel *) tty->driver_data;
2108	volatile struct board_chan *bc;
2109	int retval;
2110	unsigned int mflag, mstat;
2111	unsigned char startc, stopc;
2112	unsigned long flags;
2113	digiflow_t dflow;
2114
2115	if(ch)
2116		bc = ch->brdchan;
2117	else {
2118		printk("ch is NULL in pcxe_ioctl!\n");
2119		return(-EINVAL);
2120	}
2121
2122	save_flags(flags);
2123
2124	switch(cmd) {
2125		case TCSBRK:	/* SVID version: non-zero arg --> no break */
2126			retval = tty_check_change(tty);
2127			if(retval)
2128				return retval;
2129			setup_empty_event(tty,ch);
2130			tty_wait_until_sent(tty, 0);
2131			if(!arg)
2132				digi_send_break(ch, HZ/4);    /* 1/4 second */
2133			return 0;
2134
2135		case TCSBRKP:	/* support for POSIX tcsendbreak() */
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			digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
2142			return 0;
2143
2144		case TIOCGSOFTCAR:
2145			return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *)arg);
2146
2147		case TIOCSSOFTCAR:
2148			{
2149			    unsigned int value;
2150			    if (get_user(value, (unsigned int *) arg))
2151				    return -EFAULT;
2152			    tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (value ? CLOCAL : 0));
2153			}
2154			return 0;
2155
2156		case TIOCMODG:
2157		case TIOCMGET:
2158			mflag = 0;
2159
2160			cli();
2161			globalwinon(ch);
2162			mstat = bc->mstat;
2163			memoff(ch);
2164			restore_flags(flags);
2165
2166			if(mstat & DTR)
2167				mflag |= TIOCM_DTR;
2168			if(mstat & RTS)
2169				mflag |= TIOCM_RTS;
2170			if(mstat & CTS)
2171				mflag |= TIOCM_CTS;
2172			if(mstat & ch->dsr)
2173				mflag |= TIOCM_DSR;
2174			if(mstat & RI)
2175				mflag |= TIOCM_RI;
2176			if(mstat & ch->dcd)
2177				mflag |= TIOCM_CD;
2178
2179			if (put_user(mflag, (unsigned int *) arg))
2180				return -EFAULT;
2181			break;
2182
2183		case TIOCMBIS:
2184		case TIOCMBIC:
2185		case TIOCMODS:
2186		case TIOCMSET:
2187			if (get_user(mstat, (unsigned int *) arg))
2188				return -EFAULT;
2189
2190			mflag = 0;
2191			if(mstat & TIOCM_DTR)
2192				mflag |= DTR;
2193			if(mstat & TIOCM_RTS)
2194				mflag |= RTS;
2195
2196			switch(cmd) {
2197				case TIOCMODS:
2198				case TIOCMSET:
2199					ch->modemfake = DTR|RTS;
2200					ch->modem = mflag;
2201					break;
2202
2203				case TIOCMBIS:
2204					ch->modemfake |= mflag;
2205					ch->modem |= mflag;
2206					break;
2207
2208				case TIOCMBIC:
2209					ch->modemfake &= ~mflag;
2210					ch->modem &= ~mflag;
2211					break;
2212			}
2213
2214			cli();
2215			globalwinon(ch);
2216			pcxxparam(tty,ch);
2217			memoff(ch);
2218			restore_flags(flags);
2219			break;
2220
2221		case TIOCSDTR:
2222			cli();
2223			ch->omodem |= DTR;
2224			globalwinon(ch);
2225			fepcmd(ch, SETMODEM, DTR, 0, 10, 1);
2226			memoff(ch);
2227			restore_flags(flags);
2228			break;
2229
2230		case TIOCCDTR:
2231			ch->omodem &= ~DTR;
2232			cli();
2233			globalwinon(ch);
2234			fepcmd(ch, SETMODEM, 0, DTR, 10, 1);
2235			memoff(ch);
2236			restore_flags(flags);
2237			break;
2238
2239		case DIGI_GETA:
2240			if (copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)))
2241				return -EFAULT;
2242			break;
2243
2244		case DIGI_SETAW:
2245		case DIGI_SETAF:
2246			if(cmd == DIGI_SETAW) {
2247				setup_empty_event(tty,ch);
2248				tty_wait_until_sent(tty, 0);
2249			}
2250			else {
2251				if(tty->ldisc.flush_buffer)
2252					tty->ldisc.flush_buffer(tty);
2253			}
2254
2255			/* Fall Thru */
2256
2257		case DIGI_SETA:
2258			if (copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)))
2259				return -EFAULT;
2260#ifdef DEBUG_IOCTL
2261			printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
2262#endif
2263
2264			if(ch->digiext.digi_flags & DIGI_ALTPIN) {
2265				ch->dcd = DSR;
2266				ch->dsr = CD;
2267			} else {
2268				ch->dcd = CD;
2269				ch->dsr = DSR;
2270			}
2271
2272			cli();
2273			globalwinon(ch);
2274			pcxxparam(tty,ch);
2275			memoff(ch);
2276			restore_flags(flags);
2277			break;
2278
2279		case DIGI_GETFLOW:
2280		case DIGI_GETAFLOW:
2281			cli();
2282			globalwinon(ch);
2283			if(cmd == DIGI_GETFLOW) {
2284				dflow.startc = bc->startc;
2285				dflow.stopc = bc->stopc;
2286			} else {
2287				dflow.startc = bc->startca;
2288				dflow.stopc = bc->stopca;
2289			}
2290			memoff(ch);
2291			restore_flags(flags);
2292
2293			if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
2294				return -EFAULT;
2295			break;
2296
2297		case DIGI_SETAFLOW:
2298		case DIGI_SETFLOW:
2299			if(cmd == DIGI_SETFLOW) {
2300				startc = ch->startc;
2301				stopc = ch->stopc;
2302			} else {
2303				startc = ch->startca;
2304				stopc = ch->stopca;
2305			}
2306
2307			if (copy_from_user(&dflow, (char*)arg, sizeof(dflow)))
2308				return -EFAULT;
2309
2310			if(dflow.startc != startc || dflow.stopc != stopc) {
2311				cli();
2312				globalwinon(ch);
2313
2314				if(cmd == DIGI_SETFLOW) {
2315					ch->fepstartc = ch->startc = dflow.startc;
2316					ch->fepstopc = ch->stopc = dflow.stopc;
2317					fepcmd(ch,SONOFFC,ch->fepstartc,ch->fepstopc,0, 1);
2318				} else {
2319					ch->fepstartca = ch->startca = dflow.startc;
2320					ch->fepstopca  = ch->stopca = dflow.stopc;
2321					fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
2322				}
2323
2324				if(ch->statusflags & TXSTOPPED)
2325					pcxe_start(tty);
2326
2327				memoff(ch);
2328				restore_flags(flags);
2329			}
2330			break;
2331
2332		default:
2333			return -ENOIOCTLCMD;
2334	}
2335
2336	return 0;
2337}
2338
2339static void pcxe_set_termios(struct tty_struct *tty, struct termios *old_termios)
2340{
2341	struct channel *info;
2342
2343	if ((info=chan(tty))!=NULL) {
2344		unsigned long flags;
2345		save_flags(flags);
2346		cli();
2347		globalwinon(info);
2348		pcxxparam(tty,info);
2349		memoff(info);
2350
2351		if ((old_termios->c_cflag & CRTSCTS) &&
2352			((tty->termios->c_cflag & CRTSCTS) == 0))
2353			tty->hw_stopped = 0;
2354		if(!(old_termios->c_cflag & CLOCAL) &&
2355			(tty->termios->c_cflag & CLOCAL))
2356			wake_up_interruptible(&info->open_wait);
2357		restore_flags(flags);
2358	}
2359}
2360
2361
2362static void do_pcxe_bh(void)
2363{
2364	run_task_queue(&tq_pcxx);
2365}
2366
2367
2368static void do_softint(void *private_)
2369{
2370	struct channel *info = (struct channel *) private_;
2371
2372	if(info && info->magic == PCXX_MAGIC) {
2373		struct tty_struct *tty = info->tty;
2374		if (tty && tty->driver_data) {
2375			if(test_and_clear_bit(PCXE_EVENT_HANGUP, &info->event)) {
2376				tty_hangup(tty);
2377				wake_up_interruptible(&info->open_wait);
2378				info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2379			}
2380		}
2381	}
2382}
2383
2384
2385static void pcxe_stop(struct tty_struct *tty)
2386{
2387	struct channel *info;
2388
2389	if ((info=chan(tty))!=NULL) {
2390		unsigned long flags;
2391		save_flags(flags);
2392		cli();
2393		if ((info->statusflags & TXSTOPPED) == 0) {
2394			globalwinon(info);
2395			fepcmd(info, PAUSETX, 0, 0, 0, 0);
2396			info->statusflags |= TXSTOPPED;
2397			memoff(info);
2398		}
2399		restore_flags(flags);
2400	}
2401}
2402
2403static void pcxe_throttle(struct tty_struct * tty)
2404{
2405	struct channel *info;
2406
2407	if ((info=chan(tty))!=NULL) {
2408		unsigned long flags;
2409		save_flags(flags);
2410		cli();
2411		if ((info->statusflags & RXSTOPPED) == 0) {
2412			globalwinon(info);
2413			fepcmd(info, PAUSERX, 0, 0, 0, 0);
2414			info->statusflags |= RXSTOPPED;
2415			memoff(info);
2416		}
2417		restore_flags(flags);
2418	}
2419}
2420
2421static void pcxe_unthrottle(struct tty_struct *tty)
2422{
2423	struct channel *info;
2424
2425	if ((info=chan(tty)) != NULL) {
2426		unsigned long flags;
2427
2428		/* Just in case output was resumed because of a change in Digi-flow */
2429		save_flags(flags);
2430		cli();
2431		if(info->statusflags & RXSTOPPED) {
2432			volatile struct board_chan *bc;
2433			globalwinon(info);
2434			bc = info->brdchan;
2435			fepcmd(info, RESUMERX, 0, 0, 0, 0);
2436			info->statusflags &= ~RXSTOPPED;
2437			memoff(info);
2438		}
2439		restore_flags(flags);
2440	}
2441}
2442
2443
2444static void pcxe_start(struct tty_struct *tty)
2445{
2446	struct channel *info;
2447
2448	if ((info=chan(tty))!=NULL) {
2449		unsigned long flags;
2450
2451		save_flags(flags);
2452		cli();
2453		/* Just in case output was resumed because of a change in Digi-flow */
2454		if(info->statusflags & TXSTOPPED) {
2455			volatile struct board_chan *bc;
2456			globalwinon(info);
2457			bc = info->brdchan;
2458			if(info->statusflags & LOWWAIT)
2459				bc->ilow = 1;
2460			fepcmd(info, RESUMETX, 0, 0, 0, 0);
2461			info->statusflags &= ~TXSTOPPED;
2462			memoff(info);
2463		}
2464		restore_flags(flags);
2465	}
2466}
2467
2468
2469void digi_send_break(struct channel *ch, int msec)
2470{
2471	unsigned long flags;
2472
2473	save_flags(flags);
2474	cli();
2475	globalwinon(ch);
2476
2477	/*
2478	 * Maybe I should send an infinite break here, schedule() for
2479	 * msec amount of time, and then stop the break.  This way,
2480	 * the user can't screw up the FEP by causing digi_send_break()
2481	 * to be called (i.e. via an ioctl()) more than once in msec amount
2482	 * of time.  Try this for now...
2483	 */
2484
2485	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
2486	memoff(ch);
2487
2488	restore_flags(flags);
2489}
2490
2491static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
2492{
2493	volatile struct board_chan *bc;
2494	unsigned long flags;
2495
2496	save_flags(flags);
2497	cli();
2498	globalwinon(ch);
2499	ch->statusflags |= EMPTYWAIT;
2500	bc = ch->brdchan;
2501	bc->iempty = 1;
2502	memoff(ch);
2503	restore_flags(flags);
2504}
2505