1/* 2 * linux/drivers/char/pdc_console.c 3 * 4 * 2001, Christoph Plattner 5 * 6 * Driver template was linux's serial.c 7 * 8 */ 9 10static char *pdc_drv_version = "0.3"; 11static char *pdc_drv_revdate = "2001-11-17"; 12#define AUTHOR "christoph.plattner@gmx.at" 13#include <linux/config.h> 14#include <linux/version.h> 15 16#undef PDC_DRV_DEBUG 17 18#undef SERIAL_PARANOIA_CHECK 19#define CONFIG_SERIAL_NOPAUSE_IO 20#define SERIAL_DO_RESTART 21 22#define PDC_POLL_DELAY (30 * HZ / 1000) 23 24/* 25 * End of serial driver configuration section. 26 */ 27 28#include <linux/module.h> 29 30#include <linux/types.h> 31#include <linux/serial.h> 32#include <linux/serialP.h> 33#include <linux/serial_reg.h> 34#include <asm/serial.h> 35#define LOCAL_VERSTRING "" 36 37#include <linux/errno.h> 38#include <linux/signal.h> 39#include <linux/sched.h> 40#include <linux/timer.h> 41#include <linux/interrupt.h> 42#include <linux/tty.h> 43#include <linux/tty_flip.h> 44#include <linux/major.h> 45#include <linux/string.h> 46#include <linux/fcntl.h> 47#include <linux/ptrace.h> 48#include <linux/ioport.h> 49#include <linux/mm.h> 50#include <linux/slab.h> 51#include <linux/init.h> 52#include <asm/uaccess.h> 53#include <linux/delay.h> 54 55#include <asm/system.h> 56#include <asm/io.h> 57#include <asm/irq.h> 58#include <asm/bitops.h> 59 60#ifdef CONFIG_GSC 61#include <asm/gsc.h> 62#endif 63 64extern int pdc_console_poll_key(void *); 65extern void pdc_outc(unsigned char); 66 67static char *pdc_drv_name = "PDC Software Console"; 68 69static struct tty_driver pdc_drv_driver; 70static int pdc_drv_refcount = 0; 71static struct async_struct *pdc_drv_info; 72 73static struct timer_list pdc_drv_timer; 74 75/* serial subtype definitions */ 76#ifndef SERIAL_TYPE_NORMAL 77#define SERIAL_TYPE_NORMAL 1 78#define SERIAL_TYPE_CALLOUT 2 79#endif 80 81#define NR_PORTS 1 82#define PDC_DUMMY_BUF 2048 83 84static struct tty_struct *pdc_drv_table[NR_PORTS]; 85static struct termios *pdc_drv_termios[NR_PORTS]; 86static struct termios *pdc_drv_termios_locked[NR_PORTS]; 87 88/* 89 * tmp_buf is used as a temporary buffer by serial_write. We need to 90 * lock it in case the copy_from_user blocks while swapping in a page, 91 * and some other program tries to do a serial write at the same time. 92 * Since the lock will only come under contention when the system is 93 * swapping and available memory is low, it makes sense to share one 94 * buffer across all the serial ports, since it significantly saves 95 * memory if large numbers of serial ports are open. 96 */ 97static unsigned char *tmp_buf; 98#ifdef DECLARE_MUTEX 99static DECLARE_MUTEX(tmp_buf_sem); 100#else 101static struct semaphore tmp_buf_sem = MUTEX; 102#endif 103 104/* 105 * ------------------------------------------------------------ 106 * pdc_stop() and pdc_start() 107 * 108 * This routines are called before setting or resetting tty->stopped. 109 * They enable or disable transmitter interrupts, as necessary. 110 * ------------------------------------------------------------ 111 */ 112static void 113pdc_stop(struct tty_struct *tty) 114{ 115} 116 117static void 118pdc_start(struct tty_struct *tty) 119{ 120} 121 122/* 123 * ---------------------------------------------------------------------- 124 * 125 * Here starts the interrupt handling routines. All of the following 126 * subroutines are declared as inline and are folded into 127 * rs_interrupt(). They were separated out for readability's sake. 128 * 129 * Note: rs_interrupt() is a "fast" interrupt, which means that it 130 * runs with interrupts turned off. People who may want to modify 131 * rs_interrupt() should try to keep the interrupt handler as fast as 132 * possible. After you are done making modifications, it is not a bad 133 * idea to do: 134 * 135 * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c 136 * 137 * and look at the resulting assemble code in serial.s. 138 * 139 * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 140 * ----------------------------------------------------------------------- 141 */ 142 143static void 144receive_chars(struct async_struct *info, int *status, struct pt_regs *regs) 145{ 146 struct tty_struct *tty = info->tty; 147 unsigned char ch; 148 int __ch; 149 150 while (1) { 151 __ch = pdc_console_poll_key(NULL); 152 153 if (__ch == -1) /* no character available */ 154 break; 155 156 ch = (unsigned char) ((unsigned) __ch & 0x000000ffu); 157 158 if (tty->flip.count >= TTY_FLIPBUF_SIZE) 159 continue; 160 161 *tty->flip.char_buf_ptr = ch; 162 *tty->flip.flag_buf_ptr = 0; 163 164 tty->flip.flag_buf_ptr++; 165 tty->flip.char_buf_ptr++; 166 tty->flip.count++; 167 } 168 169 tty_flip_buffer_push(tty); 170} 171 172static void 173pdc_drv_poll(unsigned long dummy) 174{ 175 struct async_struct *info; 176 int status = 0; 177 178 info = pdc_drv_info; 179 180 if (!info || !info->tty || (pdc_drv_refcount == 0)) { 181 /* do nothing */ 182 } else { 183 receive_chars(info, &status, NULL); 184 info->last_active = jiffies; 185 } 186 187 mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY); 188} 189 190static void 191pdc_put_char(struct tty_struct *tty, unsigned char ch) 192{ 193#ifdef PDC_DRV_DEBUG 194 printk(KERN_NOTICE "[%s] %c return\n", __FUNCTION__, ch); 195#endif 196 pdc_outc(ch); 197} 198 199static void 200pdc_flush_chars(struct tty_struct *tty) 201{ 202 /* PCD console always flushed all characters */ 203 204#ifdef PDC_DRV_DEBUG 205 printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); 206#endif 207 208 /* nothing to do */ 209} 210 211static int 212pdc_write(struct tty_struct *tty, int from_user, 213 const unsigned char *buf, int count) 214{ 215 char pdc_tmp_buf[PDC_DUMMY_BUF]; 216 char *pdc_tmp_buf_ptr; 217 int len; 218 int ret = 0; 219 220#ifdef PDC_DRV_DEBUG 221 printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); 222#endif 223 while (count) { 224 if (count < PDC_DUMMY_BUF) 225 len = count; 226 else 227 len = PDC_DUMMY_BUF; 228 229 if (from_user) { 230 copy_from_user(pdc_tmp_buf, buf, len); 231 pdc_tmp_buf_ptr = pdc_tmp_buf; 232 } else 233 pdc_tmp_buf_ptr = (char *) buf; 234 235 while (len) { 236 pdc_outc(*pdc_tmp_buf_ptr); 237 buf++; 238 pdc_tmp_buf_ptr++; 239 ret++; 240 count--; 241 len--; 242 } 243 } 244#ifdef PDC_DRV_DEBUG 245 printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); 246#endif 247 return ret; 248} 249 250static int 251pdc_write_room(struct tty_struct *tty) 252{ 253#ifdef PDC_DRV_DEBUG 254 printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); 255#endif 256 return PDC_DUMMY_BUF; 257} 258 259static int 260pdc_chars_in_buffer(struct tty_struct *tty) 261{ 262#ifdef PDC_DRV_DEBUG 263 printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); 264#endif 265 return 0; /* no characters in buffer, always flushed ! */ 266} 267 268static void 269pdc_flush_buffer(struct tty_struct *tty) 270{ 271#ifdef PDC_DRV_DEBUG 272 printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); 273#endif 274} 275 276/* 277 * This function is used to send a high-priority XON/XOFF character to 278 * the device 279 */ 280static void 281pdc_send_xchar(struct tty_struct *tty, char ch) 282{ 283} 284 285/* 286 * ------------------------------------------------------------ 287 * pdc_throttle() 288 * 289 * This routine is called by the upper-layer tty layer to signal that 290 * incoming characters should be throttled. 291 * ------------------------------------------------------------ 292 */ 293static void 294pdc_throttle(struct tty_struct *tty) 295{ 296} 297 298static void 299pdc_unthrottle(struct tty_struct *tty) 300{ 301} 302 303/* 304 * ------------------------------------------------------------ 305 * pdc_ioctl() and friends 306 * ------------------------------------------------------------ 307 */ 308 309static void 310pdc_break(struct tty_struct *tty, int break_state) 311{ 312} 313 314static int 315get_serial_info(struct async_struct * info, 316 struct serial_struct * retinfo) 317{ 318 struct serial_struct tmp; 319 320 if (!retinfo) 321 return -EFAULT; 322 memset(&tmp, 0, sizeof(tmp)); 323 tmp.line = info->line; 324 tmp.port = info->line; 325 tmp.flags = info->flags; 326 tmp.close_delay = info->close_delay; 327 return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; 328} 329 330static int get_modem_info(struct async_struct * info, unsigned int *value) 331{ 332 unsigned int result = TIOCM_DTR|TIOCM_CAR|TIOCM_CTS|TIOCM_RTS; 333 334 return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0; 335} 336 337static int get_lsr_info(struct async_struct * info, unsigned int *value) 338{ 339 unsigned int result = TIOCSER_TEMT; 340 341 return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0; 342} 343 344static int 345pdc_ioctl(struct tty_struct *tty, struct file *file, 346 unsigned int cmd, unsigned long arg) 347{ 348 struct async_struct *info = (struct async_struct *) tty->driver_data; 349 350 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 351 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && 352 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 353 if (tty->flags & (1 << TTY_IO_ERROR)) 354 return -EIO; 355 } 356 357 switch (cmd) { 358 case TIOCMGET: 359 return get_modem_info(info, (unsigned int *) arg); 360 case TIOCMBIS: 361 case TIOCMBIC: 362 case TIOCMSET: 363 return 0; 364 case TIOCGSERIAL: 365 return get_serial_info(info, (struct serial_struct *) arg); 366 case TIOCSSERIAL: 367 return 0; 368 case TIOCSERCONFIG: 369 return 0; 370 371 case TIOCSERGETLSR: /* Get line status register */ 372 return get_lsr_info(info, (unsigned int *) arg); 373 374 case TIOCSERGSTRUCT: 375 if (copy_to_user((struct async_struct *) arg, 376 info, sizeof (struct async_struct))) 377 return -EFAULT; 378 return 0; 379 380 case TIOCMIWAIT: 381 return 0; 382 383 case TIOCGICOUNT: 384 return 0; 385 case TIOCSERGWILD: 386 case TIOCSERSWILD: 387 /* "setserial -W" is called in Debian boot */ 388 printk("TIOCSER?WILD ioctl obsolete, ignored.\n"); 389 return 0; 390 391 default: 392 return -ENOIOCTLCMD; 393 } 394 return 0; 395} 396 397static void 398pdc_set_termios(struct tty_struct *tty, struct termios *old_termios) 399{ 400 401} 402 403/* 404 * ------------------------------------------------------------ 405 * pdc_close() 406 * 407 * This routine is called when the serial port gets closed. First, we 408 * wait for the last remaining data to be sent. Then, we unlink its 409 * async structure from the interrupt chain if necessary, and we free 410 * that IRQ if nothing is left in the chain. 411 * ------------------------------------------------------------ 412 */ 413static void 414pdc_close(struct tty_struct *tty, struct file *filp) 415{ 416 struct async_struct *info = (struct async_struct *) tty->driver_data; 417 418#ifdef PDC_DEBUG_OPEN 419 printk("pdc_close ttyB%d, count = %d\n", info->line, state->count); 420#endif 421 pdc_drv_refcount--; 422 if (pdc_drv_refcount > 0) 423 return; 424 425 info->flags |= ASYNC_CLOSING; 426 427 /* 428 * Save the termios structure, since this port may have 429 * separate termios for callout and dialin. 430 */ 431 if (info->flags & ASYNC_NORMAL_ACTIVE) 432 info->state->normal_termios = *tty->termios; 433 if (info->flags & ASYNC_CALLOUT_ACTIVE) 434 info->state->callout_termios = *tty->termios; 435 436 /* 437 * At this point we stop accepting input. To do this, we 438 * disable the receive line status interrupts, and tell the 439 * interrupt driver to stop checking the data ready bit in the 440 * line status register. 441 */ 442 443 444 if (tty->driver.flush_buffer) 445 tty->driver.flush_buffer(tty); 446 if (tty->ldisc.flush_buffer) 447 tty->ldisc.flush_buffer(tty); 448 tty->closing = 0; 449 info->event = 0; 450 info->tty = 0; 451 pdc_drv_info = NULL; 452 if (info->blocked_open) { 453 if (info->close_delay) { 454 set_current_state(TASK_INTERRUPTIBLE); 455 schedule_timeout(info->close_delay); 456 } 457 wake_up_interruptible(&info->open_wait); 458 } 459 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | 460 ASYNC_CLOSING); 461 wake_up_interruptible(&info->close_wait); 462 MOD_DEC_USE_COUNT; 463} 464 465/* 466 * pdc_wait_until_sent() --- wait until the transmitter is empty 467 */ 468static void 469pdc_wait_until_sent(struct tty_struct *tty, int timeout) 470{ 471 /* we always send immideate */ 472} 473 474/* 475 * pdc_hangup() --- called by tty_hangup() when a hangup is signaled. 476 */ 477static void 478pdc_hangup(struct tty_struct *tty) 479{ 480} 481 482/* 483 * ------------------------------------------------------------ 484 * pdc_open() and friends 485 * ------------------------------------------------------------ 486 */ 487 488static int 489get_async_struct(int line, struct async_struct **ret_info) 490{ 491 struct async_struct *info; 492 493 info = kmalloc(sizeof (struct async_struct), GFP_KERNEL); 494 if (!info) { 495 return -ENOMEM; 496 } 497 memset(info, 0, sizeof (struct async_struct)); 498 init_waitqueue_head(&info->open_wait); 499 init_waitqueue_head(&info->close_wait); 500 init_waitqueue_head(&info->delta_msr_wait); 501 info->magic = SERIAL_MAGIC; 502 info->port = 0; 503 info->flags = 0; 504 info->io_type = 0; 505 info->iomem_base = 0; 506 info->iomem_reg_shift = 0; 507 info->xmit_fifo_size = PDC_DUMMY_BUF; 508 info->line = line; 509 info->tqueue.routine = NULL; 510 info->tqueue.data = info; 511 info->state = NULL; 512 *ret_info = info; 513 return 0; 514} 515 516/* 517 * This routine is called whenever a serial port is opened. It 518 * enables interrupts for a serial port, linking in its async structure into 519 * the IRQ chain. It also performs the serial-specific 520 * initialization for the tty structure. 521 */ 522static int 523pdc_open(struct tty_struct *tty, struct file *filp) 524{ 525 struct async_struct *info; 526 int retval, line; 527 unsigned long page; 528 529 MOD_INC_USE_COUNT; 530 line = MINOR(tty->device) - tty->driver.minor_start; 531 if ((line < 0) || (line >= NR_PORTS)) { 532 MOD_DEC_USE_COUNT; 533 return -ENODEV; 534 } 535 retval = get_async_struct(line, &info); 536 if (retval) { 537 MOD_DEC_USE_COUNT; 538 return retval; 539 } 540 tty->driver_data = info; 541 info->tty = tty; 542 pdc_drv_info = info; 543 544#ifdef PDC_DEBUG_OPEN 545 printk("pdc_open %s%d, count = %d\n", tty->driver.name, info->line, 546 info->state->count); 547#endif 548 info->tty->low_latency = 0; 549 if (!tmp_buf) { 550 page = get_zeroed_page(GFP_KERNEL); 551 if (!page) { 552 MOD_DEC_USE_COUNT; 553 return -ENOMEM; 554 } 555 if (tmp_buf) 556 free_page(page); 557 else 558 tmp_buf = (unsigned char *) page; 559 } 560 561 info->session = current->session; 562 info->pgrp = current->pgrp; 563 564#ifdef PDC_DEBUG_OPEN 565 printk("pdc_open ttyB%d successful...", info->line); 566#endif 567 pdc_drv_refcount++; 568 return 0; 569} 570 571/* 572 * --------------------------------------------------------------------- 573 * pdc_init() and friends 574 * 575 * pdc_init() is called at boot-time to initialize the pdc driver. 576 * --------------------------------------------------------------------- 577 */ 578 579static void 580show_pdc_drv_version(void) 581{ 582 printk(KERN_INFO "%s version %s%s (%s), %s\n", pdc_drv_name, 583 pdc_drv_version, LOCAL_VERSTRING, pdc_drv_revdate, AUTHOR); 584} 585 586/* 587 * The serial driver boot-time initialization code! 588 */ 589static int __init 590pdc_drv_init(void) 591{ 592 init_timer(&pdc_drv_timer); 593 pdc_drv_timer.function = pdc_drv_poll; 594 mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY); 595 596 show_pdc_drv_version(); 597 598 /* Initialize the tty_driver structure */ 599 600 memset(&pdc_drv_driver, 0, sizeof (struct tty_driver)); 601 pdc_drv_driver.magic = TTY_DRIVER_MAGIC; 602 pdc_drv_driver.driver_name = "pdc_console"; 603#ifdef CONFIG_DEVFS_FS 604 pdc_drv_driver.name = "ttb/%d"; 605#else 606 pdc_drv_driver.name = "ttyB"; 607#endif 608 pdc_drv_driver.major = PDCCONS_MAJOR; 609 pdc_drv_driver.minor_start = 0; 610 pdc_drv_driver.num = NR_PORTS; 611 pdc_drv_driver.type = TTY_DRIVER_TYPE_SERIAL; 612 pdc_drv_driver.subtype = SERIAL_TYPE_NORMAL; 613 pdc_drv_driver.init_termios = tty_std_termios; 614 pdc_drv_driver.init_termios.c_cflag = 615 B9600 | CS8 | CREAD | HUPCL | CLOCAL; 616 pdc_drv_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; 617 pdc_drv_driver.refcount = &pdc_drv_refcount; 618 pdc_drv_driver.table = pdc_drv_table; 619 pdc_drv_driver.termios = pdc_drv_termios; 620 pdc_drv_driver.termios_locked = pdc_drv_termios_locked; 621 622 pdc_drv_driver.open = pdc_open; 623 pdc_drv_driver.close = pdc_close; 624 pdc_drv_driver.write = pdc_write; 625 pdc_drv_driver.put_char = pdc_put_char; 626 pdc_drv_driver.flush_chars = pdc_flush_chars; 627 pdc_drv_driver.write_room = pdc_write_room; 628 pdc_drv_driver.chars_in_buffer = pdc_chars_in_buffer; 629 pdc_drv_driver.flush_buffer = pdc_flush_buffer; 630 pdc_drv_driver.ioctl = pdc_ioctl; 631 pdc_drv_driver.throttle = pdc_throttle; 632 pdc_drv_driver.unthrottle = pdc_unthrottle; 633 pdc_drv_driver.set_termios = pdc_set_termios; 634 pdc_drv_driver.stop = pdc_stop; 635 pdc_drv_driver.start = pdc_start; 636 pdc_drv_driver.hangup = pdc_hangup; 637 pdc_drv_driver.break_ctl = pdc_break; 638 pdc_drv_driver.send_xchar = pdc_send_xchar; 639 pdc_drv_driver.wait_until_sent = pdc_wait_until_sent; 640 pdc_drv_driver.read_proc = NULL; 641 642 if (tty_register_driver(&pdc_drv_driver)) 643 panic("Couldn't register pdc_console driver\n"); 644 645 return 0; 646} 647 648static void __exit 649pdc_fini(void) 650{ 651 int e1; 652 653 if ((e1 = tty_unregister_driver(&pdc_drv_driver))) 654 printk("pdc_console: failed to unregister pdc_drv driver (%d)\n", 655 e1); 656} 657 658module_init(pdc_drv_init); 659module_exit(pdc_fini); 660MODULE_DESCRIPTION("PDC Software Console"); 661MODULE_AUTHOR(AUTHOR); 662