?? stallion.c
字號:
printk("stl_charsinbuffer(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return(0); portp = tty->driver_data; if (portp == (stlport_t *) NULL) return(0); if (portp->tx.buf == (char *) NULL) return(0); head = portp->tx.head; tail = portp->tx.tail; size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) size = 1; return(size);}/*****************************************************************************//* * Generate the serial struct info. */static void stl_getserial(stlport_t *portp, struct serial_struct *sp){ struct serial_struct sio; stlbrd_t *brdp;#if DEBUG printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);#endif memset(&sio, 0, sizeof(struct serial_struct)); sio.line = portp->portnr; sio.port = portp->ioaddr; sio.flags = portp->flags; sio.baud_base = portp->baud_base; sio.close_delay = portp->close_delay; sio.closing_wait = portp->closing_wait; sio.custom_divisor = portp->custom_divisor; sio.hub6 = 0; if (portp->uartp == &stl_cd1400uart) { sio.type = PORT_CIRRUS; sio.xmit_fifo_size = CD1400_TXFIFOSIZE; } else { sio.type = PORT_UNKNOWN; sio.xmit_fifo_size = SC26198_TXFIFOSIZE; } brdp = stl_brds[portp->brdnr]; if (brdp != (stlbrd_t *) NULL) sio.irq = brdp->irq; copy_to_user(sp, &sio, sizeof(struct serial_struct));}/*****************************************************************************//* * Set port according to the serial struct info. * At this point we do not do any auto-configure stuff, so we will * just quietly ignore any requests to change irq, etc. */static int stl_setserial(stlport_t *portp, struct serial_struct *sp){ struct serial_struct sio;#if DEBUG printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);#endif copy_from_user(&sio, sp, sizeof(struct serial_struct)); if (!capable(CAP_SYS_ADMIN)) { if ((sio.baud_base != portp->baud_base) || (sio.close_delay != portp->close_delay) || ((sio.flags & ~ASYNC_USR_MASK) != (portp->flags & ~ASYNC_USR_MASK))) return(-EPERM); } portp->flags = (portp->flags & ~ASYNC_USR_MASK) | (sio.flags & ASYNC_USR_MASK); portp->baud_base = sio.baud_base; portp->close_delay = sio.close_delay; portp->closing_wait = sio.closing_wait; portp->custom_divisor = sio.custom_divisor; stl_setport(portp, portp->tty->termios); return(0);}/*****************************************************************************/static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){ stlport_t *portp; unsigned int ival; int rc;#if DEBUG printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n", (int) tty, (int) file, cmd, (int) arg);#endif if (tty == (struct tty_struct *) NULL) return(-ENODEV); portp = tty->driver_data; if (portp == (stlport_t *) NULL) return(-ENODEV); if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { if (tty->flags & (1 << TTY_IO_ERROR)) return(-EIO); } rc = 0; switch (cmd) { case TIOCGSOFTCAR: rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; case TIOCSSOFTCAR: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(int))) == 0) { get_user(ival, (unsigned int *) arg); tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); } break; case TIOCMGET: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) { ival = stl_getsignals(portp); put_user(ival, (unsigned int *) arg); } break; case TIOCMBIS: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { get_user(ival, (unsigned int *) arg); stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); } break; case TIOCMBIC: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { get_user(ival, (unsigned int *) arg); stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); } break; case TIOCMSET: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { get_user(ival, (unsigned int *) arg); stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); } break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) stl_getserial(portp, (struct serial_struct *) arg); break; case TIOCSSERIAL: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) == 0) rc = stl_setserial(portp, (struct serial_struct *) arg); break; case COM_GETPORTSTATS: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0) rc = stl_getportstats(portp, (comstats_t *) arg); break; case COM_CLRPORTSTATS: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0) rc = stl_clrportstats(portp, (comstats_t *) arg); break; case TIOCSERCONFIG: case TIOCSERGWILD: case TIOCSERSWILD: case TIOCSERGETLSR: case TIOCSERGSTRUCT: case TIOCSERGETMULTI: case TIOCSERSETMULTI: default: rc = -ENOIOCTLCMD; break; } return(rc);}/*****************************************************************************/static void stl_settermios(struct tty_struct *tty, struct termios *old){ stlport_t *portp; struct termios *tiosp;#if DEBUG printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; tiosp = tty->termios; if ((tiosp->c_cflag == old->c_cflag) && (tiosp->c_iflag == old->c_iflag)) return; stl_setport(portp, tiosp); stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0), -1); if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) { tty->hw_stopped = 0; stl_start(tty); } if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) wake_up_interruptible(&portp->open_wait);}/*****************************************************************************//* * Attempt to flow control who ever is sending us data. Based on termios * settings use software or/and hardware flow control. */static void stl_throttle(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_throttle(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_flowctrl(portp, 0);}/*****************************************************************************//* * Unflow control the device sending us data... */static void stl_unthrottle(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_unthrottle(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_flowctrl(portp, 1);}/*****************************************************************************//* * Stop the transmitter. Basically to do this we will just turn TX * interrupts off. */static void stl_stop(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_stop(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_startrxtx(portp, -1, 0);}/*****************************************************************************//* * Start the transmitter again. Just turn TX interrupts back on. */static void stl_start(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_start(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_startrxtx(portp, -1, 1);}/*****************************************************************************//* * Hangup this port. This is pretty much like closing the port, only * a little more brutal. No waiting for data to drain. Shutdown the * port and maybe drop signals. */static void stl_hangup(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_hangup(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; portp->flags &= ~ASYNC_INITIALIZED; stl_disableintrs(portp); if (tty->termios->c_cflag & HUPCL) stl_setsignals(portp, 0, 0); stl_enablerxtx(portp, 0, 0); stl_flushbuffer(tty); portp->istate = 0; set_bit(TTY_IO_ERROR, &tty->flags); if (portp->tx.buf != (char *) NULL) { kfree_s(portp->tx.buf, STL_TXBUFSIZE); portp->tx.buf = (char *) NULL; portp->tx.head = (char *) NULL; portp->tx.tail = (char *) NULL; } portp->tty = (struct tty_struct *) NULL; portp->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); portp->refcount = 0; wake_up_interruptible(&portp->open_wait);}/*****************************************************************************/static void stl_flushbuffer(struct tty_struct *tty){ stlport_t *portp;#if DEBUG printk("stl_flushbuffer(tty=%x)\n", (int) tty);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_flush(portp); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty);}/*****************************************************************************/static void stl_breakctl(struct tty_struct *tty, int state){ stlport_t *portp;#if DEBUG printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; stl_sendbreak(portp, ((state == -1) ? 1 : 2));}/*****************************************************************************/static void stl_waituntilsent(struct tty_struct *tty, int timeout){ stlport_t *portp; unsigned long tend;#if DEBUG printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; if (timeout == 0) timeout = HZ; tend = jiffies + timeout; while (stl_datastate(portp)) { if (signal_pending(current)) break; stl_delay(2); if (time_after_eq(jiffies, tend)) break; }}/*****************************************************************************/static void stl_sendxchar(struct tty_struct *tty, char ch){ stlport_t *portp;#if DEBUG printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);#endif if (tty == (struct tty_struct *) NULL) return; portp = tty->driver_data; if (portp == (stlport_t *) NULL) return; if (ch == STOP_CHAR(tty)) stl_sendflow(portp, 0); else if (ch == START_CHAR(tty)) stl_sendflow(portp, 1); else stl_putchar(tty, ch);}/*****************************************************************************/#define MAXLINE 80/* * Format info for a specified port. The line is deliberately limited * to 80 characters. (If it is too long it will be truncated, if too * short then padded with spaces). */static int stl_portinfo(stlport_t *portp, int portnr, char *pos){ char *sp; int sigs, cnt; sp = pos; sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d", portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", (int) portp->stats.txtotal, (int) portp->stats.rxtotal); if (portp->stats.rxframing) sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing); if (portp->stats.rxparity) sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity); if (portp->stats.rxbreaks) sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks); if (portp->stats.rxoverrun) sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun); sigs = stl_getsignals(portp); cnt = sprintf(sp, "%s%s%s%s%s ", (sigs & TIOCM_RTS) ? "|RTS" : "", (sigs & TIOCM_CTS) ? "|CTS" : "", (sigs & TIOCM_DTR) ? "|DTR" : "", (sigs & TIOCM_CD) ? "|DCD" : "",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -