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