⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial167.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  struct serial_struct tmp;/* CP('g'); */    if (!retinfo)            return -EFAULT;    memset(&tmp, 0, sizeof(tmp));    tmp.type = info->type;    tmp.line = info->line;    tmp.port = info->line;    tmp.irq = 0;    tmp.flags = info->flags;    tmp.baud_base = 0;          /*!!!*/    tmp.close_delay = info->close_delay;    tmp.custom_divisor = 0;     /*!!!*/    tmp.hub6 = 0;               /*!!!*/    return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;} /* get_serial_info */static intset_serial_info(struct cyclades_port * info,                           struct serial_struct * new_info){  struct serial_struct new_serial;  struct cyclades_port old_info;/* CP('s'); */    if (!new_info)	    return -EFAULT;    if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))	    return -EFAULT;    old_info = *info;    if (!suser()) {	    if ((new_serial.close_delay != info->close_delay) ||		((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=		 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))		    return -EPERM;	    info->flags = ((info->flags & ~ASYNC_USR_MASK) |			   (new_serial.flags & ASYNC_USR_MASK));	    goto check_and_exit;    }    /*     * OK, past this point, all the error checking has been done.     * At this point, we start making changes.....     */    info->flags = ((info->flags & ~ASYNC_FLAGS) |		    (new_serial.flags & ASYNC_FLAGS));    info->close_delay = new_serial.close_delay;check_and_exit:    if (info->flags & ASYNC_INITIALIZED){	config_setup(info);	return 0;    }else{        return startup(info);    }} /* set_serial_info */static intget_modem_info(struct cyclades_port * info, unsigned int *value){  int channel;  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;  unsigned long flags;  unsigned char status;  unsigned int result;    channel = info->line;    save_flags(flags); cli();        base_addr[CyCAR] = (u_char)channel;        status = base_addr[CyMSVR1] | base_addr[CyMSVR2];    restore_flags(flags);    result =  ((status  & CyRTS) ? TIOCM_RTS : 0)            | ((status  & CyDTR) ? TIOCM_DTR : 0)            | ((status  & CyDCD) ? TIOCM_CAR : 0)            | ((status  & CyDSR) ? TIOCM_DSR : 0)            | ((status  & CyCTS) ? TIOCM_CTS : 0);    return put_user(result,(unsigned int *) value);} /* get_modem_info */static intset_modem_info(struct cyclades_port * info, unsigned int cmd,                          unsigned int *value){  int channel;  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;  unsigned long flags;  unsigned int arg;	      if (get_user(arg, (unsigned long *) value))	return -EFAULT;    channel = info->line;    switch (cmd) {    case TIOCMBIS:	if (arg & TIOCM_RTS){	    save_flags(flags); cli();		base_addr[CyCAR] = (u_char)channel;		base_addr[CyMSVR1] = CyRTS;	    restore_flags(flags);	}	if (arg & TIOCM_DTR){	    save_flags(flags); cli();	    base_addr[CyCAR] = (u_char)channel;/* CP('S');CP('2'); */	    base_addr[CyMSVR2] = CyDTR;#ifdef SERIAL_DEBUG_DTR            printk("cyc: %d: raising DTR\n", __LINE__);            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif	    restore_flags(flags);	}	break;    case TIOCMBIC:	if (arg & TIOCM_RTS){	    save_flags(flags); cli();		base_addr[CyCAR] = (u_char)channel;		base_addr[CyMSVR1] = 0;	    restore_flags(flags);	}	if (arg & TIOCM_DTR){	    save_flags(flags); cli();	    base_addr[CyCAR] = (u_char)channel;/* CP('C');CP('2'); */	    base_addr[CyMSVR2] = 0;#ifdef SERIAL_DEBUG_DTR            printk("cyc: %d: dropping DTR\n", __LINE__);            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif	    restore_flags(flags);	}	break;    case TIOCMSET:	if (arg & TIOCM_RTS){	    save_flags(flags); cli();		base_addr[CyCAR] = (u_char)channel;		base_addr[CyMSVR1] = CyRTS;	    restore_flags(flags);	}else{	    save_flags(flags); cli();		base_addr[CyCAR] = (u_char)channel;		base_addr[CyMSVR1] = 0;	    restore_flags(flags);	}	if (arg & TIOCM_DTR){	    save_flags(flags); cli();	    base_addr[CyCAR] = (u_char)channel;/* CP('S');CP('3'); */	    base_addr[CyMSVR2] = CyDTR;#ifdef SERIAL_DEBUG_DTR            printk("cyc: %d: raising DTR\n", __LINE__);            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif	    restore_flags(flags);	}else{	    save_flags(flags); cli();	    base_addr[CyCAR] = (u_char)channel;/* CP('C');CP('3'); */	    base_addr[CyMSVR2] = 0;#ifdef SERIAL_DEBUG_DTR            printk("cyc: %d: dropping DTR\n", __LINE__);            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif	    restore_flags(flags);	}	break;    default:		return -EINVAL;        }    return 0;} /* set_modem_info */static voidsend_break( struct cyclades_port * info, int duration){ /* Let the transmit ISR take care of this (since it     requires stuffing characters into the output stream).   */    info->x_break = duration;    if (!info->xmit_cnt ) {	start_xmit(info);    }} /* send_break */static intget_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon){   if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))	   return -EFAULT;   info->mon.int_count  = 0;   info->mon.char_count = 0;   info->mon.char_max   = 0;   info->mon.char_last  = 0;   return 0;}static intset_threshold(struct cyclades_port * info, unsigned long *arg){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   unsigned long value;   int channel;      if (get_user(value, arg))	   return -EFAULT;   channel = info->line;   info->cor4 &= ~CyREC_FIFO;   info->cor4 |= value & CyREC_FIFO;   base_addr[CyCOR4] = info->cor4;   return 0;}static intget_threshold(struct cyclades_port * info, unsigned long *value){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   int channel;   unsigned long tmp;      channel = info->line;   tmp = base_addr[CyCOR4] & CyREC_FIFO;   return put_user(tmp,value);}static intset_default_threshold(struct cyclades_port * info, unsigned long *arg){   unsigned long value;   if (get_user(value, arg))	return -EFAULT;   info->default_threshold = value & 0x0f;   return 0;}static intget_default_threshold(struct cyclades_port * info, unsigned long *value){   return put_user(info->default_threshold,value);}static intset_timeout(struct cyclades_port * info, unsigned long *arg){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   int channel;   unsigned long value;   if (get_user(value, arg))	   return -EFAULT;      channel = info->line;   base_addr[CyRTPRL] = value & 0xff;   base_addr[CyRTPRH] = (value >> 8) & 0xff;   return 0;}static intget_timeout(struct cyclades_port * info, unsigned long *value){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   int channel;   unsigned long tmp;      channel = info->line;   tmp = base_addr[CyRTPRL];   return put_user(tmp,value);}static intset_default_timeout(struct cyclades_port * info, unsigned long value){   info->default_timeout = value & 0xff;   return 0;}static intget_default_timeout(struct cyclades_port * info, unsigned long *value){   return put_user(info->default_timeout,value);}static intcy_ioctl(struct tty_struct *tty, struct file * file,            unsigned int cmd, unsigned long arg){  unsigned long val;  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;  int ret_val = 0;#ifdef SERIAL_DEBUG_OTHER    printk("cy_ioctl ttyS%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */#endif    switch (cmd) {        case CYGETMON:            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);	    break;        case CYGETTHRESH:	    ret_val = get_threshold(info, (unsigned long *)arg); 	    break;        case CYSETTHRESH:            ret_val = set_threshold(info, (unsigned long *)arg);	    break;        case CYGETDEFTHRESH:	    ret_val = get_default_threshold(info, (unsigned long *)arg); 	    break;        case CYSETDEFTHRESH:            ret_val = set_default_threshold(info, (unsigned long *)arg);	    break;        case CYGETTIMEOUT:	    ret_val = get_timeout(info, (unsigned long *)arg); 	    break;        case CYSETTIMEOUT:            ret_val = set_timeout(info, (unsigned long *)arg);	    break;        case CYGETDEFTIMEOUT:	    ret_val = get_default_timeout(info, (unsigned long *)arg); 	    break;        case CYSETDEFTIMEOUT:            ret_val = set_default_timeout(info, (unsigned long)arg);	    break;        case TCSBRK:    /* SVID version: non-zero arg --> no break */	    ret_val = tty_check_change(tty);	    if (ret_val)		    break;            tty_wait_until_sent(tty,0);            if (!arg)                send_break(info, HZ/4); /* 1/4 second */            break;        case TCSBRKP:   /* support for POSIX tcsendbreak() */	    ret_val = tty_check_change(tty);	    if (ret_val)		break;            tty_wait_until_sent(tty,0);            send_break(info, arg ? arg*(HZ/10) : HZ/4);            break;        case TIOCMBIS:        case TIOCMBIC:        case TIOCMSET:            ret_val = set_modem_info(info, cmd, (unsigned int *) arg);            break;/* The following commands are incompletely implemented!!! */        case TIOCGSOFTCAR:            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);            break;        case TIOCSSOFTCAR:            ret_val = get_user(val, (unsigned long *) arg);	    if (ret_val)		    break;            tty->termios->c_cflag =                    ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));            break;        case TIOCMGET:            ret_val = get_modem_info(info, (unsigned int *) arg);            break;        case TIOCGSERIAL:            ret_val = get_serial_info(info, (struct serial_struct *) arg);            break;        case TIOCSSERIAL:            ret_val = set_serial_info(info,                                   (struct serial_struct *) arg);            break;        default:	    ret_val = -ENOIOCTLCMD;    }#ifdef SERIAL_DEBUG_OTHER    printk("cy_ioctl done\n");#endif    return ret_val;} /* cy_ioctl */static voidcy_set_termios(struct tty_struct *tty, struct termios * old_termios){  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;#ifdef SERIAL_DEBUG_OTHER    printk("cy_set_termios ttyS%d\n", info->line);#endif    if (tty->termios->c_cflag == old_termios->c_cflag)        return;    config_setup(info);    if ((old_termios->c_cflag & CRTSCTS) &&        !(tty->termios->c_cflag & CRTSCTS)) {            tty->stopped = 0;            cy_start(tty);    }#ifdef tytso_patch_94Nov25_1726    if (!(old_termios->c_cflag & CLOCAL) &&        (tty->termios->c_cflag & CLOCAL))            wake_up_interruptible(&info->open_wait);#endif    return;} /* cy_set_termios */static voidcy_close(struct tty_struct * tty, struct file * filp){  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;/* CP('C'); */#ifdef SERIAL_DEBUG_OTHER    printk("cy_close ttyS%d\n", info->line);#endif    if (!info    || serial_paranoia_check(info, tty->device, "cy_close")){        return;    }#ifdef SERIAL_DEBUG_OPEN    printk("cy_close ttyS%d, count = %d\n", info->line, info->count);#endif    if ((tty->count == 1) && (info->count != 1)) {	/*	 * Uh, oh.  tty->count is 1, which means that the tty	 * structure will be freed.  Info->count should always	 * be one in these conditions.  If it's greater than	 * one, we've got real problems, since it means the	 * serial port won't be shutdown.	 */	printk("cy_close: bad serial port count; tty->count is 1, "	   "info->count is %d\n", info->count);	info->count = 1;    }#ifdef SERIAL_DEBUG_COUNT    printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);#endif    if (--info->count < 0) {	printk("cy_close: bad serial port count for ttys%d: %d\n",	       info->line, info->count);#ifdef SERIAL_DEBUG_COUNT    printk("cyc: %d: setting count to 0\n", __LINE__);#endif	info->count = 0;    }    if (info->count)	return;    info->flags |= ASYNC_CLOSING;    /*     * Save the termios structure, since this port may have     * separate termios for callout and dialin.     */    if (info->flags & ASYNC_NORMAL_ACTIVE)	info->normal_termios = *tty->termios;    if (info->flags & ASYNC_CALLOUT_ACTIVE)	info->callout_termios = *tty->termios;    if (info->flags & ASYNC_INITIALIZED)	tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */    shutdown(info);    if (tty->driver.flush_buffer)	tty->driver.flush_buffer(tty);    if (tty->ldisc.flush_buffer)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -