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

📄 serial167.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;               /*!!!*/    copy_to_user(retinfo,&tmp,sizeof(*retinfo));    return 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;    copy_from_user(&new_serial,new_info,sizeof(new_serial));    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);    cy_put_user(result,(unsigned long *) value);    return 0;} /* 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 = cy_get_user((unsigned long *) value);    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){   copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor));   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 value){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   int channel;      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;   cy_put_user(tmp,value);   return 0;}static intset_default_threshold(struct cyclades_port * info, unsigned long value){   info->default_threshold = value & 0x0f;   return 0;}static intget_default_threshold(struct cyclades_port * info, unsigned long *value){   cy_put_user(info->default_threshold,value);   return 0;}static intset_timeout(struct cyclades_port * info, unsigned long value){   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;   int channel;      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];   cy_put_user(tmp,value);   return 0;}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){   cy_put_user(info->default_timeout,value);   return 0;}static intcy_ioctl(struct tty_struct *tty, struct file * file,            unsigned int cmd, unsigned long arg){  int error;  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:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(struct cyclades_monitor));            if (error){                ret_val = error;                break;            }            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);	    break;        case CYGETTHRESH:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned long));            if (error){                ret_val = error;                break;            }	    ret_val = get_threshold(info, (unsigned long *)arg); 	    break;        case CYSETTHRESH:            ret_val = set_threshold(info, (unsigned long)arg);	    break;        case CYGETDEFTHRESH:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned long));            if (error){                ret_val = error;                break;            }	    ret_val = get_default_threshold(info, (unsigned long *)arg); 	    break;        case CYSETDEFTHRESH:            ret_val = set_default_threshold(info, (unsigned long)arg);	    break;        case CYGETTIMEOUT:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned long));            if (error){                ret_val = error;                break;            }	    ret_val = get_timeout(info, (unsigned long *)arg); 	    break;        case CYSETTIMEOUT:            ret_val = set_timeout(info, (unsigned long)arg);	    break;        case CYGETDEFTIMEOUT:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned long));            if (error){                ret_val = error;                break;            }	    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)		return ret_val;            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)		return ret_val;            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:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned int *));            if (error){                ret_val = error;                break;            }            cy_put_user(C_CLOCAL(tty) ? 1 : 0,                        (unsigned long *) arg);            break;        case TIOCSSOFTCAR:	    error = verify_area(VERIFY_READ, (void *) arg				,sizeof(unsigned long *));            if (error){                ret_val = error;                break;            }            arg = cy_get_user((unsigned long *) arg);            tty->termios->c_cflag =                    ((tty->termios->c_cflag & ~CLOCAL) |                     (arg ? CLOCAL : 0));            break;        case TIOCMGET:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(unsigned int *));            if (error){                ret_val = error;                break;            }            ret_val = get_modem_info(info, (unsigned int *) arg);            break;        case TIOCGSERIAL:            error = verify_area(VERIFY_WRITE, (void *) arg                                ,sizeof(struct serial_struct));            if (error){                ret_val = error;                break;            }            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;    }

⌨️ 快捷键说明

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