📄 mxser.c
字号:
info->mon_data.rxcnt = 0; info->mon_data.txcnt = 0; return(0); }// (above) added by James. case MOXA_ASPP_SETBAUD:{ long baud; error = verify_area(VERIFY_READ, (void *)arg, sizeof(long)); if ( error ) return(error); get_from_user(baud, (long *)arg); mxser_set_baud(info, baud); return (0); } case MOXA_ASPP_GETBAUD: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long)); if ( error ) return(error); if (copy_to_user((long *)arg, &info->realbaud, sizeof(long))) return -EFAULT; return (0); case MOXA_ASPP_OQUEUE:{ int len, lsr; error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); if ( error ) return(error); len = mxser_chars_in_buffer(tty); lsr = inb(info->base+ UART_LSR) & UART_LSR_TEMT; len += (lsr ? 0: 1); if (copy_to_user((int *)arg, &len, sizeof(int))) return -EFAULT; return (0); } case MOXA_ASPP_MON:{ int mcr, status; error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon)); if ( error ) return(error);// info->mon_data.ser_param = tty->termios->c_cflag; status = mxser_get_msr(info->base, 1, info->port, info); mxser_check_modem_status(info, status); mcr = inb(info->base + UART_MCR); if(mcr & MOXA_MUST_MCR_XON_FLAG) info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; else info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; if(mcr & MOXA_MUST_MCR_TX_XON) info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; else info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; if(info->tty->hw_stopped) info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; else info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; if (copy_to_user((struct mxser_mon *)arg, &(info->mon_data), sizeof(struct mxser_mon))) return -EFAULT; return (0); } case MOXA_ASPP_LSTATUS:{ error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon)); if ( error ) return(error); if (copy_to_user((struct mxser_mon *)arg, &(info->err_shadow), sizeof(unsigned char))) return -EFAULT; info->err_shadow = 0; return (0); } case MOXA_SET_BAUD_METHOD:{ int method; error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); if ( error ) return(error); get_from_user(method,(int *)arg); mxser_set_baud_method[info->port] = method; if (copy_to_user((int *)arg, &method, sizeof(int))) return -EFAULT; return (0); } default: return(-ENOIOCTLCMD); } return(0);}static int mxser_ioctl_special(unsigned int cmd, unsigned long arg){ int error, i, result, status; switch ( cmd ) { case MOXA_GET_CONF: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_hwconf)*4); if ( error ) return(error); if(copy_to_user((struct mxser_hwconf *)arg, mxsercfg, sizeof(struct mxser_hwconf)*4)) return -EFAULT; return 0; case MOXA_GET_MAJOR: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); if ( error ) return(error); if(copy_to_user((int*)arg, &ttymajor, sizeof(int))) return -EFAULT; return 0; case MOXA_GET_CUMAJOR: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); if ( error ) return(error); if(copy_to_user((int*)arg, &calloutmajor, sizeof(int))) return -EFAULT; return 0; case MOXA_CHKPORTENABLE: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long)); if ( error ) return(error); result = 0; for ( i=0; i<MXSER_PORTS; i++ ) { if ( mxvar_table[i].base ) result |= (1 << i); } put_to_user(result, (unsigned long *)arg); return(0); case MOXA_GETDATACOUNT: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_log)); if ( error ) return(error); if(copy_to_user((struct mxser_log *)arg, &mxvar_log, sizeof(mxvar_log))) return -EFAULT; return(0); case MOXA_GETMSTATUS: error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mstatus) * MXSER_PORTS); if ( error ) return(error); for(i=0; i<MXSER_PORTS; i++){ GMStatus[i].ri = 0; if ( !mxvar_table[i].base ){ GMStatus[i].dcd = 0; GMStatus[i].dsr = 0; GMStatus[i].cts = 0; continue; } if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios ) GMStatus[i].cflag=mxvar_table[i].normal_termios.c_cflag; else GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag; status = inb(mxvar_table[i].base + UART_MSR); if(status & 0x80/*UART_MSR_DCD*/) GMStatus[i].dcd = 1; else GMStatus[i].dcd = 0; if(status & 0x20/*UART_MSR_DSR*/) GMStatus[i].dsr = 1; else GMStatus[i].dsr = 0; if(status & 0x10/*UART_MSR_CTS*/) GMStatus[i].cts = 1; else GMStatus[i].cts = 0; } if(copy_to_user((struct mxser_mstatus *)arg, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS)) return -EFAULT; return 0; case MOXA_ASPP_MON_EXT:{ int status; int opmode, p; int shiftbit; unsigned cflag, iflag; error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mxser_mon_ext)); if ( error ) return(error); for(i=0; i<MXSER_PORTS; i++) { if ( !mxvar_table[i].base ) continue; status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i]));// mxser_check_modem_status(&mxvar_table[i], status); if ( status & UART_MSR_TERI ) mxvar_table[i].icount.rng++; if ( status & UART_MSR_DDSR ) mxvar_table[i].icount.dsr++; if ( status & UART_MSR_DDCD ) mxvar_table[i].icount.dcd++; if ( status & UART_MSR_DCTS ) mxvar_table[i].icount.cts++; mxvar_table[i].mon_data.modem_status = status; mon_data_ext.rx_cnt[i] = mxvar_table[i].mon_data.rxcnt; mon_data_ext.tx_cnt[i] = mxvar_table[i].mon_data.txcnt; mon_data_ext.up_rxcnt[i] = mxvar_table[i].mon_data.up_rxcnt; mon_data_ext.up_txcnt[i] = mxvar_table[i].mon_data.up_txcnt; mon_data_ext.modem_status[i] = mxvar_table[i].mon_data.modem_status; mon_data_ext.baudrate[i] = mxvar_table[i].realbaud; if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios ) { cflag = mxvar_table[i].normal_termios.c_cflag; iflag = mxvar_table[i].normal_termios.c_iflag; } else { cflag = mxvar_table[i].tty->termios->c_cflag; iflag = mxvar_table[i].tty->termios->c_iflag; } mon_data_ext.databits[i] = cflag & CSIZE; mon_data_ext.stopbits[i] = cflag & CSTOPB; mon_data_ext.parity[i] = cflag & (PARENB | PARODD | CMSPAR); mon_data_ext.flowctrl[i] = 0x00; if( cflag & CRTSCTS ) mon_data_ext.flowctrl[i] |= 0x03; if( iflag & (IXON | IXOFF) ) mon_data_ext.flowctrl[i] |= 0x0C; if( mxvar_table[i].type == PORT_16550A) mon_data_ext.fifo[i] = 1; else mon_data_ext.fifo[i] = 0; p = i % 4; shiftbit = p * 2; opmode = inb(mxvar_table[i].opmode_ioaddr) >> shiftbit; opmode &= OP_MODE_MASK; mon_data_ext.iftype[i] = opmode; } if (copy_to_user((struct mxser_mon_ext *)arg, &mon_data_ext, sizeof(struct mxser_mon_ext))) return -EFAULT; return (0); } default: return(-ENOIOCTLCMD); } return(0);}static void mxser_stoprx(struct tty_struct * tty){ struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; //MX_LOCK_INIT(); info->ldisc_stop_rx = 1; if ( I_IXOFF(tty) ) { //MX_LOCK(&info->slock); // following add by Victor Yu. 09-02-2002 if ( info->IsMoxaMustChipFlag ) { info->IER &= ~MOXA_MUST_RECV_ISR; outb(info->IER, info->base+UART_IER); } else { // above add by Victor Yu. 09-02-2002 info->x_char = STOP_CHAR(tty); // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 outb(0, info->base+UART_IER); info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); /* force Tx interrupt */ } // add by Victor Yu. 09-02-2002 //MX_UNLOCK(&info->slock); } if ( info->tty->termios->c_cflag & CRTSCTS ) { //MX_LOCK(&info->slock); info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->base + UART_MCR); //MX_UNLOCK(&info->slock); }}static void mxser_startrx(struct tty_struct * tty){ struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; //MX_LOCK_INIT(); info->ldisc_stop_rx = 0; if ( I_IXOFF(tty) ) { if ( info->x_char ) info->x_char = 0; else { //MX_LOCK(&info->slock); // following add by Victor Yu. 09-02-2002 if ( info->IsMoxaMustChipFlag ) { info->IER |= MOXA_MUST_RECV_ISR; outb(info->IER, info->base+UART_IER); } else { // above add by Victor Yu. 09-02-2002 info->x_char = START_CHAR(tty); // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 outb(0, info->base+UART_IER); // add by Victor Yu. 09-02-2002 info->IER |= UART_IER_THRI; /* force Tx interrupt */ outb(info->IER, info->base + UART_IER); } // add by Victor Yu. 09-02-2002 //MX_UNLOCK(&info->slock); } } if ( info->tty->termios->c_cflag & CRTSCTS ) { //MX_LOCK(&info->slock); info->MCR |= UART_MCR_RTS; outb(info->MCR, info->base + UART_MCR); //MX_UNLOCK(&info->slock); }}/* * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. */static void mxser_throttle(struct tty_struct * tty){ //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; //MX_LOCK_INIT(); //MX_LOCK(&info->slock); mxser_stoprx(tty); //MX_UNLOCK(&info->slock);}static void mxser_unthrottle(struct tty_struct * tty){ //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; //MX_LOCK_INIT(); //MX_LOCK(&info->slock); mxser_startrx(tty); //MX_UNLOCK(&info->slock);}static void mxser_set_termios(struct tty_struct * tty, struct termios * old_termios){ struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; MX_LOCK_INIT(); if ( (tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag)) ) { mxser_change_speed(info, old_termios); if ( (old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS) ) { tty->hw_stopped = 0; mxser_start(tty); } }/* Handle sw stopped */ if ( (old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON) ) { tty->stopped = 0; // following add by Victor Yu. 09-02-2002 if ( info->IsMoxaMustChipFlag ) { MX_LOCK(&info->slock); DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); MX_UNLOCK(&info->slock); } // above add by Victor Yu. 09-02-2002 mxser_start(tty); }}/* * mxser_stop() and mxser_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. */static void mxser_stop(struct tty_struct * tty){ struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; MX_LOCK_INIT(); MX_LOCK(&info->slock); if ( info->IER & UART_IER_THRI ) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); } MX_UNLOCK(&info->slock);}static void mxser_start(struct tty_struct * tty){ struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; MX_LOCK_INIT(); MX_LOCK(&info->slock); if ( info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI) ) { info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); } MX_UNLOCK(&info->slock);}#if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))/* * mxser_wait_until_sent() --- wait until the transmitter is empty */static void mxser_wait_until_sent(struct tty_struct *tty, int timeout){ struct mxser_struct * info = (struct mxser_struct *)tty->driver_data; unsigned long orig_jiffies, char_time; int lsr; if (info->type == PORT_UNKNOWN) return; if (info->xmit_fifo_size == 0) return; /* Just in case.... */ orig_jiffies = jiffies; /* * Set the check interval to be 1/5 of the estimated time to * send a single cha
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -