s3c2440 tty驱动

1、tty驱动的总体调用过程

s3c2440 tty驱动_第1张图片


2、底层串口的驱动

static struct uart_driver s3c24xx_uart_drv = {
    .owner        = THIS_MODULE,
    .driver_name    = "ttyS",           /*Modified by guowenxue, 2011.08.30*/
    .nr        = CONFIG_SERIAL_SAMSUNG_UARTS,
    .cons        = S3C24XX_SERIAL_CONSOLE,
    .dev_name    = S3C24XX_SERIAL_NAME,  /
    .major        = S3C24XX_SERIAL_MAJOR,
    .minor        = S3C24XX_SERIAL_MINOR,
};

3、底层串口的操作函数

static struct uart_ops s3c24xx_serial_ops = {
    .pm        = s3c24xx_serial_pm,
    .tx_empty    = s3c24xx_serial_tx_empty,
    .get_mctrl    = s3c24xx_serial_get_mctrl,
    .set_mctrl    = s3c24xx_serial_set_mctrl,
    .stop_tx    = s3c24xx_serial_stop_tx,
    .start_tx    = s3c24xx_serial_start_tx,
    .stop_rx    = s3c24xx_serial_stop_rx,
    .enable_ms    = s3c24xx_serial_enable_ms,
    .break_ctl    = s3c24xx_serial_break_ctl,
    .startup    = s3c24xx_serial_startup,
    .shutdown    = s3c24xx_serial_shutdown,
    .set_termios    = s3c24xx_serial_set_termios,
    .type        = s3c24xx_serial_type,
    .release_port    = s3c24xx_serial_release_port,
    .request_port    = s3c24xx_serial_request_port,
    .config_port    = s3c24xx_serial_config_port,
    .verify_port    = s3c24xx_serial_verify_port,
}


4、tty层串口操作函数

static const struct tty_operations uart_ops = {
    .open        = uart_open,
    .close        = uart_close,
    .write        = uart_write,
    .put_char    = uart_put_char,
    .flush_chars    = uart_flush_chars,
    .write_room    = uart_write_room,
    .chars_in_buffer= uart_chars_in_buffer,
    .flush_buffer    = uart_flush_buffer,
    .ioctl        = uart_ioctl,
    .throttle    = uart_throttle,
    .unthrottle    = uart_unthrottle,
    .send_xchar    = uart_send_xchar,
    .set_termios    = uart_set_termios,
    .set_ldisc    = uart_set_ldisc,
    .stop        = uart_stop,
    .start        = uart_start,
    .hangup        = uart_hangup,
    .break_ctl    = uart_break_ctl,
    .wait_until_sent= uart_wait_until_sent,
#ifdef CONFIG_PROC_FS
    .proc_fops    = &uart_proc_fops,
#endif
    .tiocmget    = uart_tiocmget,
    .tiocmset    = uart_tiocmset,
    .get_icount    = uart_get_icount,
#ifdef CONFIG_CONSOLE_POLL
    .poll_init    = uart_poll_init,
    .poll_get_char    = uart_poll_get_char,
    .poll_put_char    = uart_poll_put_char,
#endif
};


4、struct ktermios结构

  1. struct ktermios {  
  2.     tcflag_t c_iflag;   /* input mode flags */  //输入模式标志  
  3.     tcflag_t c_oflag;   /* output mode flags */ //输出模式标志  
  4.     tcflag_t c_cflag;   /* control mode flags */    //控制模式标志  
  5.     tcflag_t c_lflag;   /* local mode flags */  //本地模式标志  
  6.     cc_t c_line;    /* line discipline */   //线路规程类型  
  7.     cc_t c_cc[NCCS];    /* control characters */    //控制字符  
  8.     speed_t c_ispeed;   /* input speed */       //输入速度  
  9.     speed_t c_ospeed;   /* output speed */      //输出速度  
  10. }; 

5、tty层struct tty_driver

288 struct tty_driver {
289     int magic;          /* magic number for this structure */
290     struct kref kref;      /* Reference management */
291     struct cdev cdev;      //含有cdev结构
292     struct module   *owner;
293     const char  *driver_name;
294     const char  *name;
295     int name_base;  /* offset of printed name */
296     int major;      /* major device number */
297     int minor_start;    /* start of minor device number */
298     int minor_num;  /* number of *possible* devices */
299     int num;        /* number of devices allocated */
300     short   type;       /* type of tty driver */
301     short   subtype;    /* subtype of tty driver */
302     struct  ktermios  init_termios;    /* Initial termios */
303     int flags;      /* tty driver flags */
304     struct proc_dir_entry *proc_entry; /* /proc fs entry */
305     struct tty_driver *other; /* only used for the PTY driver */
306
307     /*
308      * Pointer to the tty data structures
309      */
310     struct tty_struct **ttys;
311     struct ktermios **termios;
312     struct ktermios **termios_locked;
313     void *driver_state;
314
315     /*
316      * Driver methods
317      */
318
319     const struct tty_operations *ops; //指向tty层的函数
320     struct list_head tty_drivers;   //驱动链表         
321 };


6、struct tty_struct 结构

  1. struct tty_struct {  
  2.     int magic;  //魔数  
  3.     struct kref kref;   //参考计数  
  4.     struct device *dev; //设备文件  
  5.     struct tty_driver *driver;  //tty驱动  
  6.     const struct tty_operations *ops;   //tty操作函数集  
  7.     int index;    
  8.     struct mutex ldisc_mutex;  
  9.     struct tty_ldisc *ldisc;    //线路规程  
  10.     struct mutex termios_mutex;  
  11.     spinlock_t ctrl_lock;  
  12.     struct ktermios *termios, *termios_locked;  
  13.     struct termiox *termiox;  
  14.     char name[64];  //名字  
  15.     struct pid *pgrp;  
  16.     struct pid *session;  
  17.     unsigned long flags;  
  18.     int count;  
  19.     struct winsize winsize;  
  20.     unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;  
  21.     unsigned char low_latency:1, warned:1;  
  22.     unsigned char ctrl_status;  
  23.     unsigned int receive_room;  
  24.     struct tty_struct *link;  
  25.     struct fasync_struct *fasync;  
  26.     struct tty_bufhead buf;  
  27.     int alt_speed;  
  28.     wait_queue_head_t write_wait;  
  29.     wait_queue_head_t read_wait;  
  30.     struct work_struct hangup_work;  
  31.     void *disc_data;  
  32.     void *driver_data;  
  33.     struct list_head tty_files;  
  34. #define N_TTY_BUF_SIZE 4096  
  35.     unsigned int column;  
  36.     unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;  
  37.     unsigned char closing:1;  
  38.     unsigned char echo_overrun:1;  
  39.     unsigned short minimum_to_wake;  
  40.     unsigned long overrun_time;  
  41.     int num_overrun;  
  42.     unsigned long process_char_map[256/(8*sizeof(unsigned long))];  
  43.     char *read_buf;  
  44.     int read_head;  
  45.     int read_tail;  
  46.     int read_cnt;  
  47.     unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];  
  48.     unsigned char *echo_buf;  
  49.     unsigned int echo_pos;  
  50.     unsigned int echo_cnt;  
  51.     int canon_data;  
  52.     unsigned long canon_head;  
  53.     unsigned int canon_column;  
  54.     struct mutex atomic_read_lock;  
  55.     struct mutex atomic_write_lock;  
  56.     struct mutex output_lock;  
  57.     struct mutex echo_lock;  
  58.     unsigned char *write_buf;  
  59.     int write_cnt;  
  60.     spinlock_t read_lock;  
  61.     struct work_struct SAK_work;  
  62.     struct tty_port *port;  
  63. }; 

7、struct file_operations 字符设备操作函数
static const struct file_operations tty_fops = {
    .llseek        = no_llseek,
    .read        = tty_read,
    .write        = tty_write,
    .poll        = tty_poll,
    .unlocked_ioctl    = tty_ioctl,
    .compat_ioctl    = tty_compat_ioctl,
    .open        = tty_open,
    .release    = tty_release,
    .fasync        = tty_fasync,
};


8、注册struct uart_drive底层串口驱动进tty层

int uart_register_driver(struct uart_driver *drv)

int uart_register_driver(struct uart_driver *drv)
{
    struct tty_driver *normal;
    int i, retval;

    BUG_ON(drv->state);    //用于内核调试

    /*
     * Maybe we should be using a slab cache for this, especially if
     * we have a large number of ports to handle.
     */
    drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
    if (!drv->state)
        goto out;

    normal = alloc_tty_driver(drv->nr);    //分配tty_driver结构体
    if (!normal)
        goto out_kfree;

    drv->tty_driver = normal;   //初始化 struct uart_driver的struct tty_driver指针

    normal->owner        = drv->owner;
    normal->driver_name    = drv->driver_name;
    normal->name        = drv->dev_name;
    normal->major        = drv->major;
    normal->minor_start    = drv->minor;
    normal->type        = TTY_DRIVER_TYPE_SERIAL;
    normal->subtype        = SERIAL_TYPE_NORMAL;
    normal->init_termios    = tty_std_termios;   //初始化struct ktermios 结构
    normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
    normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
    normal->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
    normal->driver_state    = drv;     //保存 uart_driver结构信息
    tty_set_operations(normal, &uart_ops);  //tty层操作函数,struct tty_driver中含有
                                                                     // 指向struct tty_operations的指针

    /*
     * Initialise the UART state(s).
     */
    for (i = 0; i < drv->nr; i++) {
        struct uart_state *state = drv->state + i;
        struct tty_port *port = &state->port;

        tty_port_init(port);    //初始化tty_port
        port->ops = &uart_port_ops;   
        port->close_delay     = 500;    /* .5 seconds */
        port->closing_wait    = 30000;    /* 30 seconds */
        tasklet_init(&state->tlet, uart_tasklet_action,
                 (unsigned long)state);
    }

    retval = tty_register_driver(normal);  //注册struct tty_driver结构
    if (retval >= 0)
        return retval;

    put_tty_driver(normal);
out_kfree:
    kfree(drv->state);
out:
    return -ENOMEM;
}


8、注册struct tty_driver结构


int tty_register_driver(struct tty_driver *driver)
{
    int error;
    int i;
    dev_t dev;
    void **p = NULL;
    struct device *d;

    if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
        p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
        if (!p)
            return -ENOMEM;
    }

    if (!driver->major) {
        error = alloc_chrdev_region(&dev, driver->minor_start,
                        driver->num, driver->name);   //如果主设备号为0,采用动态分配方式
        if (!error) {
            driver->major = MAJOR(dev);   //获得新的主设备号
            driver->minor_start = MINOR(dev);//获得新的此设备号
        }
    } else {   //这设备号不为0,生成新的设备号
        dev = MKDEV(driver->major, driver->minor_start);
        error = register_chrdev_region(dev, driver->num, driver->name);
    }
    if (error < 0) {
        kfree(p);
        return error;
    }

    if (p) {
        driver->ttys = (struct tty_struct **)p;
        driver->termios = (struct ktermios **)(p + driver->num);
    } else {
        driver->ttys = NULL;
        driver->termios = NULL;
    }

    cdev_init(&driver->cdev, &tty_fops);   //初始化始化cdev设备
    driver->cdev.owner = driver->owner;
    error = cdev_add(&driver->cdev, dev, driver->num);
    if (error) {
        unregister_chrdev_region(dev, driver->num);
        driver->ttys = NULL;
        driver->termios = NULL;
        kfree(p);
        return error;
    }

    mutex_lock(&tty_mutex);
    list_add(&driver->tty_drivers, &tty_drivers);
    mutex_unlock(&tty_mutex);

    if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
        for (i = 0; i < driver->num; i++) {
            d = tty_register_device(driver, i, NULL);                    //注册设备
            if (IS_ERR(d)) {
                error = PTR_ERR(d);
                goto err;
            }
        }
    }
    proc_tty_register_driver(driver);
    driver->flags |= TTY_DRIVER_INSTALLED;
    return 0;

err:
    for (i--; i >= 0; i--)
        tty_unregister_device(driver, i);

    mutex_lock(&tty_mutex);
    list_del(&driver->tty_drivers);
    mutex_unlock(&tty_mutex);

    unregister_chrdev_region(dev, driver->num);
    driver->ttys = NULL;
    driver->termios = NULL;
    kfree(p);
    return error;
}


9、注册设备函数

struct device *tty_register_device(struct tty_driver *driver, unsigned index,
                   struct device *device)
{
    char name[64];
    dev_t dev = MKDEV(driver->major, driver->minor_start) + index;

    if (index >= driver->num) {
        printk(KERN_ERR "Attempt to register invalid tty line number "
               " (%d).\n", index);
        return ERR_PTR(-EINVAL);
    }

    if (driver->type == TTY_DRIVER_TYPE_PTY)
        pty_line_name(driver, index, name);
    else
        tty_line_name(driver, index, name);

    return device_create(tty_class, device, dev, NULL, name);
}






你可能感兴趣的:(s3c2440 tty驱动)