📄 8253xtty.c
字号:
/* Determine EBRG values based on the "encoded"baud rate */ i = cflag & CBAUD; switch(i) { case B0: baud=0; break; case B50: baud=100; break; case B75: baud=150; break; case B110: baud=220; break; case B134: baud=269; break; case B150: baud=300; break; case B200: baud=400; break; case B300: baud=600; break; case B600: baud=1200; break; case B1200: baud=2400; break; case B1800: baud=3600; break; case B2400: baud=4800; break; case B4800: baud=9600; break; case B9600: baud=19200; break; case B19200: baud=38400; break; case B38400: if(port->custspeed) { baud=port->custspeed<<1; } else { baud=76800; } break; case B57600: baud=115200; break;#ifdef SKIPTHIS case B76800: baud=153600; break; case B153600: baud=307200; break;#endif case B230400: baud=460800; break; case B460800: baud=921600; break; case B115200: default: baud=230400; break; } if(!sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud))) { printk("Aurora Warning. baudrate %ld could not be set! Using 115200",baud); baud=230400; sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud)); } if (port->baud) port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud; else port->timeout = 0; port->timeout += HZ / 50; /* Add .02 seconds of slop */ /* CTS flow control flags */ if (cflag & CRTSCTS) port->flags |= FLAG8253X_CTS_FLOW; else port->flags &= ~(FLAG8253X_CTS_FLOW); if (cflag & CLOCAL) port->flags &= ~(FLAG8253X_CHECK_CD); else port->flags |= FLAG8253X_CHECK_CD; if (port->tty) port->tty->hw_stopped = 0; /* * Set up parity check flag * XXX: not implemented, yet. */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) /* * Characters to ignore * XXX: not implemented, yet. */ /* * !!! ignore all characters if CREAD is not set * XXX: not implemented, yet. */ if ((cflag & CREAD) == 0) port->ignore_status_mask |= SAB82532_ISR0_RPF | /* SAB82532_ISR0_TIME |*/ SAB82532_ISR0_TCD ; save_flags(flags); cli(); sab8253x_cec_wait(port); sab8253x_tec_wait(port); WRITEB(port,dafo,dafo); WRITEB(port,bgr,ebrg); ccr2 |= READB(port,ccr2) & ~(0xc0); WRITEB(port,ccr2,ccr2); ccr4 |= READB(port,ccr4) & ~(SAB82532_CCR4_EBRG); WRITEB(port,ccr4,ccr4); if (port->flags & FLAG8253X_CTS_FLOW) { mode = READB(port,mode) & ~(SAB82532_MODE_RTS); mode |= SAB82532_MODE_FRTS; mode &= ~(SAB82532_MODE_FCTS); } else { mode = READB(port,mode) & ~(SAB82532_MODE_FRTS); mode |= SAB82532_MODE_RTS; mode |= SAB82532_MODE_FCTS; } WRITEB(port,mode,mode); mode |= SAB82532_MODE_RAC; WRITEB(port,mode,mode); restore_flags(flags);}static void sab8253x_flush_chars(struct tty_struct *tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_chars")) { return; } if ((Sab8253xCountTransmit(port) <= 0) || tty->stopped || tty->hw_stopped) { return; } sab8253x_start_tx(port);}static int sab8253x_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ struct sab_port *port = (struct sab_port *)tty->driver_data; struct sk_buff *skb = NULL; int truelength = 0; int do_queue = 1; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write")) { return 0; } if(count == 0) { return 0; } if(port->active2.transmit == NULL) { return 0; } if((port->active2.transmit->Count & OWNER) == OWN_SAB) { sab8253x_start_tx(port); return 0; } #ifndef FREEININTERRUPT skb = port->active2.transmit->HostVaddr; /* current slot value */ if(port->buffergreedy == 0) /* are we avoiding buffer free's */ { /* no */ if((skb != NULL) || /* not OWN_SAB from above */ (port->active2.transmit->crcindex != 0)) { register RING_DESCRIPTOR *freeme; freeme = port->active2.transmit; do { if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL)) { break; } if(freeme->HostVaddr) { skb_unlink((struct sk_buff*)freeme->HostVaddr); dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr); freeme->HostVaddr = NULL; } freeme->sendcrc = 0; freeme->crcindex = 0; freeme = (RING_DESCRIPTOR*) freeme->VNext; } while((freeme->Count & OWNER) != OWN_SAB); } skb = NULL; /* buffer was freed */ } if(skb != NULL) /* potentially useful */ { truelength = (skb->end - skb->head); if(truelength >= count) { skb->data = skb->head; /* this buffer is already queued */ skb->tail = skb->head; do_queue = 0; } else { skb_unlink(skb); dev_kfree_skb_any(skb); skb = NULL; port->active2.transmit->HostVaddr = NULL; } } /* in all cases the following is allowed */ port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0;#endif if(skb == NULL) { if(port->DoingInterrupt) { skb = alloc_skb(count, GFP_ATOMIC); } else { skb = alloc_skb(count, GFP_KERNEL); } } if(skb == NULL) { printk(KERN_ALERT "sab8253xt: no skbuffs available.\n"); return 0; } if(from_user) { copy_from_user(skb->data, buf, count); } else { memcpy(skb->data, buf, count); } skb->tail = (skb->data + count); skb->data_len = count; skb->len = count; if(do_queue) { skb_queue_head(port->sab8253xbuflist, skb); } port->active2.transmit->HostVaddr = skb; port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0; port->active2.transmit->Count = (OWN_SAB|count); port->active2.transmit = port->active2.transmit->VNext; sab8253x_start_tx(port); return count;}static int sab8253x_write_room(struct tty_struct *tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if(sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write_room")) { return 0; } if(port->active2.transmit == NULL) { return 0; } if((port->active2.transmit->Count & OWNER) == OWN_SAB) { return 0; } return ((sab8253xt_rbufsize) * /* really should not send buffs bigger than 32 I guess */ (sab8253xt_listsize - Sab8253xCountTransmitDescriptors(port)));}static int sab8253x_chars_in_buffer(struct tty_struct *tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_chars_in_bufferS")) { return 0; } return Sab8253xCountTransmit(port);}/* * This function is used to send a high-priority XON/XOFF character to * the device */static void sab8253x_send_xchar(struct tty_struct *tty, char ch){ struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xchar")) { return; } save_flags(flags); cli(); sab8253x_tec_wait(port); WRITEB(port, tic, ch); restore_flags(flags);}/* * ------------------------------------------------------------ * sab8253x_throttle() * * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void sab8253x_throttle(struct tty_struct * tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_throttle")) { return; } if (I_IXOFF(tty)) { sab8253x_send_xchar(tty, STOP_CHAR(tty)); }}static void sab8253x_unthrottle(struct tty_struct * tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_unthrottle")) { return; } if (I_IXOFF(tty)) { if (port->x_char) { port->x_char = 0; } else { sab8253x_send_xchar(tty, START_CHAR(tty)); } }}/* * ------------------------------------------------------------ * sab8253x_ioctl() and friends * ------------------------------------------------------------ */static int sab8253x_get_serial_info(struct sab_port *port, struct serial_struct *retinfo){ struct serial_struct tmp; if (!retinfo) { return -EFAULT; } memset(&tmp, 0, sizeof(tmp)); tmp.type = port->type; tmp.line = port->line; tmp.port = (unsigned long)port->regs; tmp.irq = port->irq; tmp.flags = port->flags; tmp.xmit_fifo_size = port->xmit_fifo_size; tmp.baud_base = 0; tmp.close_delay = port->close_delay; tmp.closing_wait = port->closing_wait; tmp.custom_divisor = port->custom_divisor; tmp.hub6 = 0; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) { return -EFAULT; } return 0;}static int sab8253x_set_serial_info(struct sab_port *port, struct serial_struct *new_info){ return 0;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically * is emptied. On bus types like RS485, the transmitter must * release the bus after transmitting. This must be done when * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */static int sab8253x_get_lsr_info(struct sab_port * port, unsigned int *value){ unsigned int result; result = (((Sab8253xCountTransmit(port) <= 0) && port->all_sent) ? TIOCSER_TEMT : 0); return put_user(result, value);}static int sab8253x_get_modem_info(struct sab_port * port, unsigned int *value){ unsigned int result; /* Using the cached values !! After all when changed int occurs and the cache is updated */ result= ((port->dtr.val) ? TIOCM_DTR : 0) | ((port->rts.val) ? TIOCM_RTS : 0) | ((port->cts.val) ? TIOCM_CTS : 0) | ((port->dsr.val) ? TIOCM_DSR : 0) | ((port->dcd.val) ? TIOCM_CAR : 0); return put_user(result,value);}static int sab8253x_set_modem_info(struct sab_port * port, unsigned int cmd, unsigned int *value){ int error; unsigned int arg; unsigned long flags; error = get_user(arg, value); if (error) { return error; } save_flags(flags); cli(); switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) { RAISE(port, rts); } if (arg & TIOCM_DTR) { RAISE(port, dtr); } break; case TIOCMBIC: if (arg & TIOCM_RTS) { LOWER(port,rts); } if (arg & TIOCM_DTR) { LOWER(port,dtr); } break; case TIOCMSET: if (arg & TIOCM_RTS) { RAISE(port, rts); } else { LOWER(port,rts); } if (arg & TIOCM_DTR) { RAISE(port, dtr); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -