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