📄 8253xtty.c
字号:
{ port->tty = tty; /* may be a standard tty waiting on a call out device */ tty->flip.tqueue.routine = sab8253x_flush_to_ldisc; } tty->driver_data = port; /* but the tty devices are unique for each type of open */ if(port->function == FUNCTION_NA) { /* port 2 on 1020s and 1520s */ ++(port->count); restore_flags(flags); return -ENODEV; } /* Check whether or not the port is open in SYNC mode */ if(port->open_type == OPEN_SYNC_NET) { if(port->dev && netif_carrier_ok(port->dev)); { port->tty= NULL; /* Don't bother with open counting here but make sure the tty field is NULL*/ restore_flags(flags); return -EBUSY; } sab8253x_flush_buffer(tty); /* don't restore flags here */ sab8253x_shutdownN(port); } else if (port->open_type > OPEN_ASYNC) /* can't have a callout or async line * if already open in some sync mode */ { ++(port->count); restore_flags(flags); return -EBUSY; } restore_flags(flags); if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_open")) { ++(port->count); return -ENODEV; } #ifdef DEBUG_OPEN printk("sab8253x_open %s%d, count = %d\n", tty->driver.name, port->line, port->count);#endif /* * If the port is in the middle of closing, bail out now. */ if (tty_hung_up_p(filp) || (port->flags & FLAG8253X_CLOSING)) { if (port->flags & FLAG8253X_CLOSING) { interruptible_sleep_on(&port->close_wait); }#ifdef SERIAL_DO_RESTART ++(port->count); return ((port->flags & FLAG8253X_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);#else ++(port->count); return -EAGAIN;#endif } if(Sab8253xSetUpLists(port)) { ++(port->count); return -ENODEV; } if(Sab8253xInitDescriptors2(port, sab8253xt_listsize, sab8253xt_rbufsize)) { ++(port->count); return -ENODEV; } retval = sab8253x_startup(port); if (retval) { ++(port->count); return retval; } retval = sab8253x_block_til_ready(tty, filp, port); ++(port->count); if (retval) { return retval; } port->tty = tty; /* may change here once through the block */ /* because now the port belongs to an new tty */ tty->flip.tqueue.routine = sab8253x_flush_to_ldisc; /* in case it was changed */ if(Sab8253xSetUpLists(port)) { return -ENODEV; } if(Sab8253xInitDescriptors2(port, sab8253xt_listsize, sab8253xt_rbufsize)) { Sab8253xCleanUpTransceiveN(port); /* the network functions should be okay -- only difference */ /* is the crc32 that is appended */ return -ENODEV; } /* * Start up serial port */ retval = sab8253x_startup(port); /* just in case closing the cu dev * shutdown the port (but left CD) */ if (retval) { return retval; } if ((port->count == 1) && /* first open */ (port->flags & FLAG8253X_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) { *tty->termios = port->normal_termios; } else { *tty->termios = port->callout_termios; } sab8253x_change_speed(port); } #ifdef XCONFIG_SERIAL_CONSOLE if (sab8253x_console.cflag && sab8253x_console.index == line) { tty->termios->c_cflag = sab8253x_console.cflag; sab8253x_console.cflag = 0; sab8253x_change_speed(port); }#endif port->session = current->session; port->pgrp = current->pgrp; port->open_type = OPEN_ASYNC; return 0;}static char *signaling[] ={ "OFF ", "RS232", "RS422", "RS485", "RS449", "RS530", "V.35 "};static int sab8253x_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ extern struct sab_port * AuraPortRoot; struct sab_port *port = AuraPortRoot; extern char *board_type[]; off_t begin = 0; int len = 0; int portno; unsigned int typeno; extern int sab8253x_rebootflag; #ifdef FREEININTERRUPT len += sprintf(page, "serinfo:2.01I driver:%s\n", sab8253x_serial_version);#else len += sprintf(page, "serinfo:2.01N driver:%s\n", sab8253x_serial_version);#endif if(sab8253x_rebootflag) { len += sprintf(page+len, "WARNING: Found %d cards that required reprogramming. Reboot machine!.\n", sab8253x_rebootflag); } len += sprintf(page+len, "TTY MAJOR = %d, CUA MAJOR = %d, STTY MAJOR = %d.\n", sab8253x_serial_driver.major, sab8253x_callout_driver.major, sync_sab8253x_serial_driver.major); for (portno = 0; port != NULL; port = port->next, ++portno) { typeno = port->board->b_type; if(typeno > BD_8520P) { typeno = 0; } len += sprintf(page+len, "%d: port %d: %s: v%d: chip %d: ATI %s: bus %d: slot %d: %s: ", sab8253x_serial_driver.minor_start + portno, port->portno, (port->chip->chip_type == ESCC2) ? "sab82532" : "sab82538", port->type, port->chip->c_chipno, board_type[port->board->b_type], port->board->b_dev.bus->number, PCI_SLOT(port->board->b_dev.devfn), aura_functionality[((port->function > FUNCTION_UN) ? FUNCTION_UN : port->function)]); switch(port->open_type) { case OPEN_ASYNC: len += sprintf(page+len, "openA"); break; case OPEN_SYNC: len += sprintf(page+len, "openS"); break; case OPEN_SYNC_NET: len += sprintf(page+len, "openN"); break; case OPEN_SYNC_CHAR: len += sprintf(page+len, "openC"); break; case OPEN_NOT: len += sprintf(page+len, "close"); break; default: len += sprintf(page+len, "open?"); break; } if(port->chip->c_cim) { if(port->chip->c_cim->ci_type == CIM_SP502) { len += sprintf(page+len, ": %s\n", signaling[port->sigmode]); } else { len += sprintf(page+len, ": NOPRG\n"); } } else { len += sprintf(page+len, ": NOPRG\n"); } if (len+begin > off+count) { goto done; } if (len+begin < off) { begin += len; len = 0; } } *eof = 1; done: if (off >= len+begin) { return 0; } *start = page + (off-begin); return ((count < begin+len-off) ? count : begin+len-off);}/* * --------------------------------------------------------------------- * sab8253x_init() and friends * * sab8253x_init() is called at boot-time to initialize the serial driver. * --------------------------------------------------------------------- */static void inline show_aurora_version(void){ char *revision = "$Revision: 1.23 $"; char *version, *p; version = strchr(revision, ' '); strcpy(sab8253x_serial_version, ++version); p = strchr(sab8253x_serial_version, ' '); *p = '\0'; printk("Aurora serial driver version %s\n", sab8253x_serial_version);}#ifndef MODULEstatic int GetMinorStart(void){ struct tty_driver *ttydriver; int minor_start = 0; kdev_t device; device = MKDEV(TTY_MAJOR, minor_start); while(ttydriver = get_tty_driver(device), ttydriver != NULL) { minor_start += ttydriver->num; device = MKDEV(TTY_MAJOR, minor_start); } return minor_start; }#endifint finish_sab8253x_setup_ttydriver(void) { extern unsigned int NumSab8253xPorts; sab8253x_tableASY = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL); if(sab8253x_tableASY == NULL) { printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableASY.\n"); return -1; } memset(sab8253x_tableASY, 0, NumSab8253xPorts*sizeof(struct tty_struct *)); sab8253x_tableCUA = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL); if(sab8253x_tableCUA == NULL) { printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableCUA.\n"); return -1; } memset(sab8253x_tableCUA, 0, NumSab8253xPorts*sizeof(struct tty_struct *)); sab8253x_tableSYN = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL); if(sab8253x_tableSYN == NULL) { printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableSYN.\n"); return -1; } memset(sab8253x_tableSYN, 0, NumSab8253xPorts*sizeof(struct tty_struct *)); sab8253x_termios = (struct termios **) kmalloc(NumSab8253xPorts*sizeof(struct termios *), GFP_KERNEL); if(sab8253x_termios == NULL) { printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_termios.\n"); return -1; } memset(sab8253x_termios, 0, NumSab8253xPorts*sizeof(struct termios *)); sab8253x_termios_locked = (struct termios **) kmalloc(NumSab8253xPorts*sizeof(struct termios *), GFP_KERNEL); if(sab8253x_termios_locked == NULL) { printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_termios_locked.\n"); return -1; } memset(sab8253x_termios_locked, 0, NumSab8253xPorts*sizeof(struct termios *)); sync_sab8253x_serial_driver.num = sab8253x_callout_driver.num = sab8253x_serial_driver.num = NumSab8253xPorts; sab8253x_serial_driver.table = sab8253x_tableASY; sab8253x_callout_driver.table = sab8253x_tableCUA; sync_sab8253x_serial_driver.table = sab8253x_tableSYN; sync_sab8253x_serial_driver.termios = sab8253x_callout_driver.termios = sab8253x_serial_driver.termios = sab8253x_termios; sync_sab8253x_serial_driver.termios_locked = sab8253x_callout_driver.termios_locked = sab8253x_serial_driver.termios_locked = sab8253x_termios_locked; if (tty_register_driver(&sab8253x_serial_driver) < 0) { printk(KERN_ALERT "auraXX20: Could not register serial driver.\n"); return -1; } if (tty_register_driver(&sab8253x_callout_driver) < 0) { printk(KERN_ALERT "auraXX20: Could not register call out device.\n"); return -1; } if (tty_register_driver(&sync_sab8253x_serial_driver) < 0) { printk(KERN_ALERT "auraXX20: Could not register sync serial device.\n"); return -1; } return 0; }void sab8253x_setup_ttydriver(void) {#ifdef MODULE extern int xx20_minorstart;#endif init_bh(AURORA_BH, sab8253x_do_serial_bh); show_aurora_version(); /* Initialize the tty_driver structure */ memset(&sab8253x_serial_driver, 0, sizeof(struct tty_driver)); sab8253x_serial_driver.magic = TTY_DRIVER_MAGIC; sab8253x_serial_driver.driver_name = "auraserial"; sab8253x_serial_driver.name = "ttyS"; sab8253x_serial_driver.major = TTY_MAJOR;#ifdef MODULE sab8253x_serial_driver.minor_start = xx20_minorstart;#else sab8253x_serial_driver.minor_start = GetMinorStart();#endif sab8253x_serial_driver.type = TTY_DRIVER_TYPE_SERIAL; sab8253x_serial_driver.subtype = SERIAL_TYPE_NORMAL; sab8253x_serial_driver.init_termios = tty_std_termios; sab8253x_serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; sab8253x_serial_driver.flags = TTY_DRIVER_REAL_RAW; sab8253x_serial_driver.refcount = &sab8253x_refcount; sab8253x_serial_driver.open = sab8253x_open; sab8253x_serial_driver.close = sab8253x_close; sab8253x_serial_driver.write = sab8253x_write; sab8253x_serial_driver.put_char = NULL; /*sab8253x_put_char is evil.*/ sab8253x_serial_driver.flush_chars = sab8253x_flush_chars; sab8253x_serial_driver.write_room = sab8253x_write_room; sab8253x_serial_driver.chars_in_buffer = sab8253x_chars_in_buffer; sab8253x_serial_driver.flush_buffer = sab8253x_flush_buffer; sab8253x_serial_driver.ioctl = sab8253x_ioctl; sab8253x_serial_driver.throttle = sab8253x_throttle; sab8253x_serial_driver.unthrottle = sab8253x_unthrottle; sab8253x_serial_driver.send_xchar = sab8253x_send_xchar; sab8253x_serial_driver.set_termios = sab8253x_set_termios; sab8253x_serial_driver.stop = sab8253x_stop; sab8253x_serial_driver.start = sab8253x_start; sab8253x_serial_driver.hangup = sab8253x_hangup; sab8253x_serial_driver.break_ctl = sab8253x_break; sab8253x_serial_driver.wait_until_sent = sab8253x_wait_until_sent; sab8253x_serial_driver.read_proc = sab8253x_read_proc; /* * The callout device is just like normal device except for * major number and the subtype code. */ sab8253x_callout_driver = sab8253x_serial_driver; sab8253x_callout_driver.name = "cua"; sab8253x_callout_driver.major = TTYAUX_MAJOR; sab8253x_callout_driver.subtype = SERIAL_TYPE_CALLOUT; sab8253x_callout_driver.read_proc = 0; sab8253x_callout_driver.proc_entry = 0; sync_sab8253x_serial_driver = sab8253x_serial_driver; sync_sab8253x_serial_driver.name = "sttyS"; sync_sab8253x_serial_driver.major = 0; sync_sab8253x_serial_driver.subtype = SERIAL_TYPE_SYNCTTY; sync_sab8253x_serial_driver.open = sab8253x_openS; sync_sab8253x_serial_driver.close = sab8253x_closeS; sync_sab8253x_serial_driver.write = sab8253x_writeS; sync_sab8253x_serial_driver.put_char = NULL; /*sab8253x_put_char logic is evil*/ sync_sab8253x_serial_driver.flush_chars = sab8253x_flush_charsS; sync_sab8253x_serial_driver.write_room = sab8253x_write_room; sync_sab8253x_serial_driver.chars_in_buffer = sab8253x_chars_in_buffer; sync_sab8253x_serial_driver.flush_buffer = sab8253x_flush_buffer; sync_sab8253x_serial_driver.ioctl = sab8253x_ioctl; sync_sab8253x_serial_driver.throttle = sab8253x_throttleS; sync_sab8253x_serial_driver.unthrottle = sab8253x_unthrottleS; sync_sab8253x_serial_driver.send_xchar = sab8253x_send_xcharS; sync_sab8253x_serial_driver.set_termios = sab8253x_set_termiosS; sync_sab8253x_serial_driver.stop = sab8253x_stopS; sync_sab8253x_serial_driver.start = sab8253x_startS; sync_sab8253x_serial_driver.hangup = sab8253x_hangupS; sync_sab8253x_serial_driver.break_ctl = sab8253x_breakS; sync_sab8253x_serial_driver.wait_until_sent = sab8253x_wait_until_sent; sync_sab8253x_serial_driver.read_proc = 0; sync_sab8253x_serial_driver.proc_entry = 0;}void sab8253x_setup_ttyport(struct sab_port *p_port) { p_port->magic = SAB_MAGIC; p_port->custom_divisor = 16; p_port->close_delay = 5*HZ/10; p_port->closing_wait = 30*HZ; p_port->tec_timeout = SAB8253X_MAX_TEC_DELAY; p_port->cec_timeout = SAB8253X_MAX_CEC_DELAY; p_port->x_char = 0; p_port->event = 0; p_port->flags= FLAG8253X_BOOT_AUTOCONF | FLAG8253X_SKIP_TEST; p_port->blocked_open = 0; p_port->all_sent = 1; /* probably not needed */ p_port->tqueue.sync = 0; /* for later */ p_port->tqueue.routine = sab8253x_do_softint; p_port->tqueue.data = p_port; p_port->tqueue_hangup.sync = 0; /* for later */ p_port->tqueue_hangup.routine = sab8253x_do_serial_hangup; p_port->tqueue_hangup.data = p_port; p_port->callout_termios = sab8253x_callout_driver.init_termios; p_port->normal_termios = sab8253x_serial_driver.init_termios; /* these are being shared */ /* between asynchronous and */ /* asynchronous ttys */ init_waitqueue_head(&p_port->open_wait); init_waitqueue_head(&p_port->close_wait); init_waitqueue_head(&p_port->delta_msr_wait); init_waitqueue_head(&p_port->write_wait); init_waitqueue_head(&p_port->read_wait); p_port->count = 0; /* maybe not needed */ p_port->icount.cts = p_port->icount.dsr = p_port->icount.rng = p_port->icount.dcd = 0; p_port->cts.val = p_port->dsr.val = p_port->dcd.val = 0; p_port->icount.rx = p_port->icount.tx = 0; p_port->icount.frame = p_port->icount.parity = 0; p_port->icount.overrun = p_port->icount.brk = 0; p_port->xmit_fifo_size = 32; p_port->recv_fifo_size = 32; p_port->xmit_buf = NULL; p_port->receive_chars = sab8253x_receive_chars; p_port->transmit_chars = sab8253x_transmit_chars; p_port->check_status = sab8253x_check_status; p_port->receive_test = (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF); p_port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR); p_port->check_status_test = SAB82532_ISR1_BRK; /* put in default sync control channel values * not needed for async -- I think these work * for bisync*/ p_port->ccontrol.ccr0 = DEFAULT_CCR0; p_port->ccontrol.ccr1 = DEFAULT_CCR1; p_port->ccontrol.ccr2 = DEFAULT_CCR2; p_port->ccontrol.ccr3 = DEFAULT_CCR3; p_port->ccontrol.ccr4 = DEFAULT_CCR4; p_port->ccontrol.mode = DEFAULT_MODE; p_port->ccontrol.rlcr = DEFAULT_RLCR;}void sab8253x_cleanup_ttydriver(void){ unsigned long flags; int e1, e2; save_flags(flags); cli(); if(sab8253x_tableASY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -