sysfs文件系统

来源:互联网 发布:怎么看淘宝的图片大小 编辑:程序博客网 时间:2024/06/05 13:07

sysfs文件系统

sysfs是一个特殊的文件系统,类似于proc。sysfs不仅像proc一样允许用户空间访问内核的数据,而且它以更结构化的方式向用户提供内核数据信息。sysfs是一种内存文件系统,它与kobject关系非常密切。系统中的每一个kobject对应sysfs中的一个目录。而每一个sysfs中的目录代表一个kobject对象,每个文件代表kobject的属性。

sysfs文件系统非常清晰地展示了设备驱动程序模型中各组件的层次关系。其顶级目录包括block、device、bus、drivers、class、power、firmware等。sysfs文件系统最基本的接口包括:

  1. int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) ;  
  2. int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode);  
  3. void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); 
sysfs文件系统一般是自动加载到/sys下的,也可以通过下面的命令手工加载:
  1. mount -t sysfs sysfs /sys 

/sys的目录结构如表1-1所示。

表1-1  sysfs文件系统的目录

名    称

功    能

Block

块设备

Bus

系统总线

Class

设备组

Devices

系统设备

Firmware

固件

Kernel

内核

Module

内核模块

Power

供电系统

设备模型层次

在kobject等内核对象机制的基础上,Linux的设备模型包括设备结构device、设备驱动结构device_driver、总线结构bus、设备类结构class等几个核心组件。

设备结构device主要用来描述DMA配置以及与体系相关的硬件特性,定义如下:

  1. struct device {  
  2.     struct device*parent;   //父设备  
  3.     struct device_private*p;  
  4.     struct kobject kobj;  
  5.     const char*init_name;   /*初始名称*/  
  6.     struct device_type  *type;  
  7.     struct semaphore    sem;    /* 同步信号量*/  
  8.     struct bus_type *bus;  
  9.     struct device_driver *driver;   /*关联的设备驱动结构 */  
  10.     void        *platform_data;     /* 平台相关的数据 */  
  11.     struct dev_pm_info  power;  
  12. #ifdef CONFIG_NUMA  
  13.     int     numa_node;/* NUMA结点*/  
  14. #endif  
  15.     u64     *dma_mask; /*DMA掩码 */  
  16.     u64     coherent_dma_mask;/ * 连续DMA内存分配掩码*/  
  17.     struct device_dma_parameters *dma_parms;  
  18.     struct list_head    dma_pools;  /*DMA池*/  
  19.     struct dma_coherent_mem *dma_mem;   
  20.     /*体系结构相关的附加信息*/  
  21.     struct dev_archdata archdata;  
  22.     dev_t           devt;     
  23.     spinlock_t      devres_lock;  
  24.     struct list_head    devres_head;  
  25.     struct klist_node   knode_class;  
  26.     struct class        *class;  
  27.     const struct attribute_group **groups;    
  28.     void    (*release)(struct device *dev);  
  29. };  

device的注册与注销函数如下:

  1. int device_register(struct device * dev);  
  2. void device_unregister(struct device * dev);  
  3. int device_add(struct device * dev);   
  4. void device_del(struct device * dev);  

device_driver对象用来描述设备的管理接口,对应的数据结构定义如下:
  1. struct device_driver {  
  2.     const char*name;    //设备驱动程序的名称  
  3.     struct bus_type*bus;    //该驱动程序所管理的设备挂接的总线  
  4.     struct module   *owner;  
  5.     const char*mod_name;        /*模块名*/  
  6.     bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */  
  7.     int (*probe) (struct device *dev);  //指向设备探测函数  
  8.     int (*remove) (struct device *dev);     //用于删除设备的函数  
  9.     void (*shutdown) (struct device *dev);  //停止设备的函数  
  10.     int (*suspend) (struct device *dev, pm_message_t state); //挂起设备的函数  
  11.     int (*resume) (struct device *dev);         //恢复设备的函数  
  12.     const struct attribute_group **groups;  
  13.     const struct dev_pm_ops *pm;  
  14.     struct driver_private *p;  
  15. };  

device_driver的注册与注销函数原型如下:
  1. int driver_register(struct device_driver * drv);  
  2. void driver_unregister(struct device_driver * drv);  

platform的概念

平台概念的引入目的是为了能够更好地描述设备的资源信息。平台设备是系统中自治的实体,包括基于端口的设备、外围总线和集成入片上系统平台的大多数控制器,它们通常直接通过CPU的总线寻址。每个平台设备被赋予一个名称,并分配一定数量的资源。平台设备本质上是device_driver模型的扩展。

平台设备使用platform_device结构描述,该结构定义如下:

  1. struct platform_device {  
  2.     const char* name;           // 平台设备名称  
  3.     int     id;  
  4.     struct device   dev;            //对应的设备结构  
  5.     u32     num_resources;      //资源的数量  
  6.     struct resource * resource;     //资源信息  
  7.     struct platform_device_id*id_entry;   
  8.     struct pdev_archdata    archdata;   /*体系结构相关的附加信息*/  
  9. };  

平台设备的注册接口如下:
  1. int platform_device_register(struct platform_device *);//注册一个平台设备  
  2. void platform_device_unregister(struct platform_device *);//注销一个平台设备  

平台驱动使用platform_driver结构描述:
  1. struct platform_driver {  
  2.     int (*probe)(struct platform_device *);  
  3.     int (*remove)(struct platform_device *);  
  4.     void (*shutdown)(struct platform_device *);  
  5.     int (*suspend)(struct platform_device *, pm_message_t state);  
  6.     int (*resume)(struct platform_device *);  
  7.     struct device_driver driver; //对应的设备驱动结构  
  8.     struct platform_device_id *id_table;  
  9. };  

平台设备驱动必须提供probe和remove方法,并且在probe中确保设备资源的可用性。平台驱动还支持电源管理和设备停止等事件。平台驱动的注册接口如下:
  1. int platform_driver_register(struct platform_driver *drv);  
  2. void platform_driver_unregister(struct platform_driver *drv);  

platform_driver_register和platform_driver_unregister本质上就是调用driver_register和driver_unregister。

resource结构是对平台资源的描述,定义如下:

  1. struct resource {  
  2.     resource_size_t start; //起始地址  
  3.     resource_size_t end; //终止地址  
  4.     const char *name; //名称  
  5.     unsigned long flags;//资源类别  
  6.     struct resource *parent, *sibling, *child;  
  7. };  

在platform_device结构中可以配置多种资源信息。资源的flags标志包括:
  1. #define IORESOURCE_IO       0x00000100  //IO资源  
  2. #define IORESOURCE_MEM  0x00000200  //内存资源  
  3. #define IORESOURCE_IRQ      0x00000400  //中断资源  
  4. #define IORESOURCE_DMA  0x00000800  //DMA资源  

内核提供了一组函数,用来获取设备的资源信息:
  1. //根据资源类型和序号来获取指定的资源  
  2. struct resource * platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);   
  3. //根据序号获取资源中的中断号  
  4. struct int platform_get_irq(struct platform_device *dev, unsigned int num);   
  5. //根据名称和类别获取指定的资源  
  6. struct resource * platform_get_resource_byname(struct platform_device *dev, unsigned int type, char *name);   
  7. //根据名称获取资源中的中断号  
  8. int platform_get_irq_byname(struct platform_device *dev, char *name);  

例1.13  AT91RM9200的MMC平台设备资源实例

本例为AT91RM9200处理器的MMC卡设备的资源实例。核心代码如下所示:

  1. static u64 mmc_dmamask = 0xffffffffUL;  
  2. static struct at91_mmc_data mmc_data;  
  3. static struct resource mmc_resources[] = {  
  4.     [0] = {  
  5.         .start  = AT91RM9200_BASE_MCI,  
  6.         .end    = AT91RM9200_BASE_MCI + SZ_16K - 1,  
  7.         .flags  = IORESOURCE_MEM,//内存资源  
  8.     },  
  9.     [1] = {  
  10.         .start  = AT91RM9200_ID_MCI,  
  11.         .end    = AT91RM9200_ID_MCI,  
  12.         .flags  = IORESOURCE_IRQ,//中断资源  
  13.     },  
  14. };  
  15. //平台设备结构  
  16. static struct platform_device at91rm9200_mmc_device = {  
  17.     .name       = "at91_mci",  
  18.     .id     = -1,  
  19.     .dev        = {  
  20.                 .dma_mask       = &mmc_dmamask,  
  21.                 .coherent_dma_mask  = 0xffffffff,  
  22.                 .platform_data      = &mmc_data,  
  23.     },  
  24.     .resource   = mmc_resources,  
  25.     .num_resources  = ARRAY_SIZE(mmc_resources),  
  26. };  
  27.  

注册MMC设备驱动代码如下:

  1. static struct platform_driver at91_mci_driver = {  
  2.     .remove     = __exit_p(at91_mci_remove),  
  3.     .suspend        = at91_mci_suspend,  
  4.     .resume     = at91_mci_resume,  
  5.     .driver     = {  
  6.         .name   = "at91_mci",  
  7.         .owner  = THIS_MODULE,  
  8.     },  
  9. };  
  10. static int __init at91_mci_init(void)  
  11. {  
  12.     return platform_driver_probe(&at91_mci_driver, at91_mci_probe);  
  13. }  

设备检测过程代码如下:
  1. static int __init at91_mci_probe(struct platform_device *pdev)  
  2. {  
  3.     struct mmc_host *mmc;  
  4.     struct at91mci_host *host;  
  5.     struct resource *res;  
  6.     int ret;  
  7.     pr_debug("Probe MCI devices\n");  
  8.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//获取内存资源  
  9.     if (!res)  
  10.         return -ENXIO;  
  11.     //请求内存区域  
  12.     if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))  
  13.         return -EBUSY;  
  14.     mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);  
  15.     if (!mmc) {  
  16.         pr_debug("Failed to allocate mmc host\n");  
  17.         release_mem_region(res->start, res->end - res->start + 1);  
  18.         return -ENOMEM;  
  19.     }  
  20.     mmc->ops = &at91_mci_ops;  
  21.     mmc->f_min = 375000;  
  22.     mmc->f_max = 25000000;  
  23.     mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;  
  24.     mmc->max_blk_size = 4095;  
  25.     mmc->max_blk_count = mmc->max_req_size;  
  26.     host = mmc_priv(mmc);  
  27.     host->mmcmmc = mmc;  
  28.     host->buffer = NULL;  
  29.     host->bus_mode = 0;  
  30.     host->board = pdev->dev.platform_data;  
  31.     if (host->board->wire4) {  
  32.         if (cpu_is_at91sam9260() || cpu_is_at91sam9263())  
  33.             mmc->caps |= MMC_CAP_4_BIT_DATA;  
  34.         else  
  35.             printk("AT91 MMC: 4 wire bus mode not supported - using 1 wire\n");  
  36.     }  
  37.     //获取控制器时钟信息  
  38.     host->mci_clk = clk_get(&pdev->dev, "mci_clk");  
  39.     if (IS_ERR(host->mci_clk)) {  
  40.         printk(KERN_ERR "AT91 MMC: no clock defined.\n");  
  41.         mmc_free_host(mmc);  
  42.         release_mem_region(res->start, res->end - res->start + 1);  
  43.         return -ENODEV;  
  44.     }  
  45.     host->baseaddr = ioremap(res->start, res->end - res->start + 1);//地址映射  
  46.     if (!host->baseaddr) {  
  47.         clk_put(host->mci_clk);  
  48.         mmc_free_host(mmc);  
  49.         release_mem_region(res->start, res->end - res->start + 1);  
  50.         return -ENOMEM;  
  51.     }  
  52.     clk_enable(host->mci_clk);//允许外设时钟  
  53.     at91_mci_disable(host);  
  54.     at91_mci_enable(host);  
  55.     //获取中断资源  
  56.     host->irq = platform_get_irq(pdev, 0);  
  57.     //申请中断  
  58.     ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);  
  59.     if (ret) {  
  60.         printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");  
  61.         clk_disable(host->mci_clk);  
  62.         clk_put(host->mci_clk);  
  63.         mmc_free_host(mmc);  
  64.         iounmap(host->baseaddr);  
  65.         release_mem_region(res->start, res->end - res->start + 1);  
  66.         return ret;  
  67.     }  
  68.     …  
  69.     return 0;  
  70. }  

0 0
原创粉丝点击