📄 aurora.c
字号:
if (clear & TIOCM_RTS) port->MSVR &= ~bp->RTS; if (clear & TIOCM_DTR) port->MSVR &= ~bp->DTR; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_set_modem_info: end\n");#endif return 0;}static void aurora_send_break(struct Aurora_port * port, unsigned long length){ struct Aurora_board *bp = port_Board(port); unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG printk("aurora_send_break: start\n");#endif chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->break_length = AURORA_TPS / HZ * length; port->COR2 |= COR2_ETC; port->SRER |= SRER_TXRDY; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_send_break: end\n");#endif}static int aurora_set_serial_info(struct Aurora_port * port, struct serial_struct * newinfo){ struct serial_struct tmp; struct Aurora_board *bp = port_Board(port); int change_speed; unsigned long flags;#ifdef AURORA_DEBUG printk("aurora_set_serial_info: start\n");#endif if (copy_from_user(&tmp, newinfo, sizeof(tmp))) return -EFAULT;#if 0 if ((tmp.irq != bp->irq) || (tmp.port != bp->base) || (tmp.type != PORT_CIRRUS) || (tmp.baud_base != (bp->oscfreq + CD180_TPC/2) / CD180_TPC) || (tmp.custom_divisor != 0) || (tmp.xmit_fifo_size != CD180_NFIFO) || (tmp.flags & ~AURORA_LEGAL_FLAGS)) return -EINVAL;#endif change_speed = ((port->flags & ASYNC_SPD_MASK) != (tmp.flags & ASYNC_SPD_MASK)); if (!capable(CAP_SYS_ADMIN)) { if ((tmp.close_delay != port->close_delay) || (tmp.closing_wait != port->closing_wait) || ((tmp.flags & ~ASYNC_USR_MASK) != (port->flags & ~ASYNC_USR_MASK))) return -EPERM; port->flags = ((port->flags & ~ASYNC_USR_MASK) | (tmp.flags & ASYNC_USR_MASK)); } else { port->flags = ((port->flags & ~ASYNC_FLAGS) | (tmp.flags & ASYNC_FLAGS)); port->close_delay = tmp.close_delay; port->closing_wait = tmp.closing_wait; } if (change_speed) { save_flags(flags); cli(); aurora_change_speed(bp, port); restore_flags(flags); }#ifdef AURORA_DEBUG printk("aurora_set_serial_info: end\n");#endif return 0;}extern int aurora_get_serial_info(struct Aurora_port * port, struct serial_struct * retinfo){ struct serial_struct tmp; struct Aurora_board *bp = port_Board(port); #ifdef AURORA_DEBUG printk("aurora_get_serial_info: start\n");#endif if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp))) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tmp.type = PORT_CIRRUS; tmp.line = port - aurora_port; tmp.port = 0; tmp.irq = bp->irq; tmp.flags = port->flags; tmp.baud_base = (bp->oscfreq + CD180_TPC/2) / CD180_TPC; tmp.close_delay = port->close_delay * HZ/100; tmp.closing_wait = port->closing_wait * HZ/100; tmp.xmit_fifo_size = CD180_NFIFO; copy_to_user(retinfo, &tmp, sizeof(tmp));#ifdef AURORA_DEBUGprintk("aurora_get_serial_info: end\n");#endif return 0;}static int aurora_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; int retval;#ifdef AURORA_DEBUG printk("aurora_ioctl: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_ioctl")) return -ENODEV; switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) aurora_send_break(port, HZ/4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); case TIOCSSOFTCAR: if (get_user(arg,(unsigned long *)arg)) return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCGSERIAL: return aurora_get_serial_info(port, (struct serial_struct *) arg); case TIOCSSERIAL: return aurora_set_serial_info(port, (struct serial_struct *) arg); default: return -ENOIOCTLCMD; };#ifdef AURORA_DEBUG printk("aurora_ioctl: end\n");#endif return 0;}static void aurora_throttle(struct tty_struct * tty){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip;#ifdef AURORA_DEBUG printk("aurora_throttle: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_throttle")) return; bp = port_Board(port); chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->MSVR &= ~bp->RTS; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); if (I_IXOFF(tty)) { aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_SSCH2, &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); } sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_throttle: end\n");#endif}static void aurora_unthrottle(struct tty_struct * tty){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip;#ifdef AURORA_DEBUG printk("aurora_unthrottle: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_unthrottle")) return; bp = port_Board(port); chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->MSVR |= bp->RTS; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); if (I_IXOFF(tty)) { aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_SSCH1, &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); } sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_unthrottle: end\n");#endif}static void aurora_stop(struct tty_struct * tty){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip;#ifdef AURORA_DEBUG printk("aurora_stop: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_stop")) return; bp = port_Board(port); chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->SRER &= ~SRER_TXRDY; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_stop: end\n");#endif}static void aurora_start(struct tty_struct * tty){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip;#ifdef AURORA_DEBUG printk("aurora_start: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_start")) return; bp = port_Board(port); chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); if (port->xmit_cnt && port->xmit_buf && !(port->SRER & SRER_TXRDY)) { port->SRER |= SRER_TXRDY; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_start: end\n");#endif}/* * This routine is called from the scheduler tqueue when the interrupt * routine has signalled that a hangup has occurred. The path of * hangup processing is: * * serial interrupt routine -> (scheduler tqueue) -> * do_aurora_hangup() -> tty->hangup() -> aurora_hangup() * */static void do_aurora_hangup(void *private_){ struct Aurora_port *port = (struct Aurora_port *) private_; struct tty_struct *tty;#ifdef AURORA_DEBUG printk("do_aurora_hangup: start\n");#endif tty = port->tty; if (tty != NULL) { tty_hangup(tty); /* FIXME: module removal race - AKPM */#ifdef AURORA_DEBUG printk("do_aurora_hangup: end\n");#endif }}static void aurora_hangup(struct tty_struct * tty){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; #ifdef AURORA_DEBUG printk("aurora_hangup: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_hangup")) return; bp = port_Board(port); aurora_shutdown_port(bp, port); port->event = 0; port->count = 0; port->flags &= ~ASYNC_NORMAL_ACTIVE; port->tty = 0; wake_up_interruptible(&port->open_wait);#ifdef AURORA_DEBUG printk("aurora_hangup: end\n");#endif}static void aurora_set_termios(struct tty_struct * tty, struct termios * old_termios){ struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned long flags;#ifdef AURORA_DEBUG printk("aurora_set_termios: start\n");#endif if ((aurora_paranoia_check(port, tty->name, "aurora_set_termios")) return; if (tty->termios->c_cflag == old_termios->c_cflag && tty->termios->c_iflag == old_termios->c_iflag) return; save_flags(flags); cli(); aurora_change_speed(port_Board(port), port); restore_flags(flags); if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; aurora_start(tty); }#ifdef AURORA_DEBUG printk("aurora_set_termios: end\n");#endif}static void do_aurora_bh(void){ run_task_queue(&tq_aurora);}static void do_softint(void *private_){ struct Aurora_port *port = (struct Aurora_port *) private_; struct tty_struct *tty;#ifdef AURORA_DEBUG printk("do_softint: start\n");#endif tty = port->tty; if (tty == NULL) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { tty_wakeup(tty); }#ifdef AURORA_DEBUG printk("do_softint: end\n");#endif}static struct tty_operations aurora_ops = { .open = aurora_open, .close = aurora_close, .write = aurora_write, .put_char = aurora_put_char, .flush_chars = aurora_flush_chars, .write_room = aurora_write_room, .chars_in_buffer = aurora_chars_in_buffer, .flush_buffer = aurora_flush_buffer, .ioctl = aurora_ioctl, .throttle = aurora_throttle, .unthrottle = aurora_unthrottle, .set_termios = aurora_set_termios, .stop = aurora_stop, .start = aurora_start, .hangup = aurora_hangup, .tiocmget = aurora_tiocmget, .tiocmset = aurora_tiocmset,};static int aurora_init_drivers(void){ int error; int i;#ifdef AURORA_DEBUG printk("aurora_init_drivers: start\n");#endif tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL); if (tmp_buf == NULL) { printk(KERN_ERR "aurora: Couldn't get free page.\n"); return 1; } init_bh(AURORA_BH, do_aurora_bh); aurora_driver = alloc_tty_driver(AURORA_INPORTS); if (!aurora_driver) { printk(KERN_ERR "aurora: Couldn't allocate tty driver.\n"); free_page((unsigned long) tmp_buf); return 1; } aurora_driver->owner = THIS_MODULE; aurora_driver->name = "ttyA"; aurora_driver->major = AURORA_MAJOR; aurora_driver->type = TTY_DRIVER_TYPE_SERIAL; aurora_driver->subtype = SERIAL_TYPE_NORMAL; aurora_driver->init_termios = tty_std_termios; aurora_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; aurora_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(aurora_driver, &aurora_ops); error = tty_register_driver(aurora_driver); if (error) { put_tty_driver(aurora_driver); free_page((unsigned long) tmp_buf); printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n", error); return 1; } memset(aurora_port, 0, sizeof(aurora_port)); for (i = 0; i < AURORA_TNPORTS; i++) { aurora_port[i].magic = AURORA_MAGIC; aurora_port[i].tqueue.routine = do_softint; aurora_port[i].tqueue.data = &aurora_port[i]; aurora_port[i].tqueue_hangup.routine = do_aurora_hangup; aurora_port[i].tqueue_hangup.data = &aurora_port[i]; aurora_port[i].close_delay = 50 * HZ/100; aurora_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&aurora_port[i].open_wait); init_waitqueue_head(&aurora_port[i].close_wait); }#ifdef AURORA_DEBUG printk("aurora_init_drivers: end\n");#endif return 0;}static void aurora_release_drivers(void){#ifdef AURORA_DEBUG printk("aurora_release_drivers: start\n");#endif free_page((unsigned long)tmp_buf); tty_unregister_driver(aurora_driver); put_tty_driver(aurora_driver);#ifdef AURORA_DEBUG printk("aurora_release_drivers: end\n");#endif}/* * Called at boot time. * * You can specify IO base for up to RC_NBOARD cards, * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. * Note that there will be no probing at default * addresses in this case. * */void __init aurora_setup(char *str, int *ints){ int i; for(i=0;(i<ints[0])&&(i<4);i++) { if (ints[i+1]) irqs[i]=ints[i+1]; }}static int __init aurora_real_init(void){ int found; int i; printk(KERN_INFO "aurora: Driver starting.\n"); if(aurora_init_drivers()) return -EIO; found = aurora_probe(); if(!found) { aurora_release_drivers(); printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n"); return -EIO; } else { printk(KERN_INFO "aurora: %d boards found.\n", found); } for (i = 0; i < found; i++) { int ret = aurora_setup_board(&aurora_board[i]); if (ret) {#ifdef AURORA_DEBUG printk(KERN_ERR "aurora_init: error aurora_setup_board ret %d\n", ret);#endif return ret; } } return 0;}int irq = 0;int irq1 = 0;int irq2 = 0;int irq3 = 0;module_param(irq , int, 0);module_param(irq1, int, 0);module_param(irq2, int, 0);module_param(irq3, int, 0);static int __init aurora_init(void) { if (irq ) irqs[0]=irq ; if (irq1) irqs[1]=irq1; if (irq2) irqs[2]=irq2; if (irq3) irqs[3]=irq3; return aurora_real_init();} static void __exit aurora_cleanup(void){ int i; #ifdef AURORA_DEBUGprintk("cleanup_module: aurora_release_drivers\n");#endif aurora_release_drivers(); for (i = 0; i < AURORA_NBOARD; i++) if (aurora_board[i].flags & AURORA_BOARD_PRESENT) { aurora_shutdown_board(&aurora_board[i]); aurora_release_io_range(&aurora_board[i]); }}module_init(aurora_init);module_exit(aurora_cleanup);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -