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