免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 987 | 回复: 0
打印 上一主题 下一主题

ldd3 read note Capter 14 下 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-18 12:01 |只看该作者 |倒序浏览

   
   
   
2009.9.15
PCI device 和device model的交互



PCI BUS register

struct bus_type pci_bus_type = {
   .name = "pci",
   .match = pci_bus_match,
   .hotplug = pci_hotplug,
   .suspend = pci_device_suspend,
   .resume = pci_device_resume,
   .dev_attrs = pci_dev_attrs,
};
bus_register 之后,创建 /sys/bus/pci 目录(sub system(kset+sem)),和其下的两个目录(两个kset): device和 driver.
PCI DRIVER 注册
注册PCI driver的时候, PCI core做如下初始化
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type; /*PCI driver ops*/
drv->driver.probe = pci_device_probe;
drv->driver.remove = pci_device_remove;
drv->driver.kobj.ktype = &pci_driver_kobj_type; /*release, attr,show,store*/
/* register with core */
error = driver_register(&drv->driver); /*设置drv 的obj的parent(通过加入bus下的kset:driver)*/

PCI device 注册

PCI 自动搜索并注册设备
struct pci_dev {
  /* ... */
  unsigned int devfn;
  unsigned short vendor;
  unsigned short device;
  unsigned short subsystem_vendor;
  unsigned short subsystem_device;
  unsigned int class;
  /* ... */
  struct pci_driver *driver;
  /* ... */
  struct device dev; /*系统设备,包括一个kobj,对应driver指针,设备parent(和kobj体系有所重叠),bus_type等*/
  /* ... */
};

PCI device和/sys 的交互

pci_scan_single_device   (搜索设置pci特定信息, dev.parent设置为所在bus的bridge设备, kset设置成/sys/device)
pci_bus_add_device-> device_register(&dev->dev);   /*以下是2.6.27的代码*/
1. pci_dev:dev.kobj.kset= /sys/device    其kset作为"系统级别"的分类 (device_initialize)
2. 注册kobjec,触发hotplug事件, 设备出现在/sys/device的某个目录 (kset和parent不同)
4. 如果有class, 在这个设备目录下创建符号连接"subsystem"到对应class (这个..名字重复了)
        有class的情况下,在设备目录下创建符号连接到对应的class
4. 在bus的device kset下创建符号连接到这个设备(pci_bus_type:->bus_type_private)
5. 在这个设备的目录下创建符号连接到PCI subsystem ,(奇怪的是名字也叫"subsystem",这个才是正确的)

PCI device和 PCI BUS 的交互

1. 添加device的kobject, 触发一个hotplug事件, 发送uevent
2. 设备添加到bus的时候(bus_attach_device),触发 match 过程, (drv->probe 匹配返回1, 不匹配返回0, 出错返回负值(继续寻找))
Remove a Device

PCI也可以支持hotplug, 比如cardbus. 如果不支持,需要测试,可以用fakephe. PCI移除设备主要个工作由pci_remove_bus_device完成 :
1. PCI 资源清理
2. device_unregister
     1) 删除sysfs文件
     2) 从各种链表摘除
     3) 调用kobject_del, 产生hotplug事件,通知usr space
3. kobject del 会递减dev的引用计数,如果是最后一个引用,则
     1)调用设备的release
     2) 设备的release函数最后调用pci_release_dev (仅仅释放pci dev占用的内存)
Add driver
1. pci_register_driver -> driver_register
2. -> bus_add_driver
     1) 看看对应bus是否注册,如果没有就立即返回了
     2) 创建driver的对应sysfs目录文件
     3) 遍历设备, 认领对应设备
Remove a Driver

1. driver 调用 pci_unregister_driver
2. -> driver_unregister
3.    sysfs unregister, 然后调用个个device的release函数
4.最后使用下面代码等待所有引用消失
down(&drv->unload_sem);
up(&drv->unload_sem);
Hotplug
Dynamic Devices
USB,
cardbus, PCMCIA, 1394, PCI hotplug controller.  对于PCI,CardBus,or
PCMCIA, 在调用设备的remove之前, 设备就已经被拔掉了. 这是所有读取PCI的操作,返回全f, 要求能正确处理返回值0xFF才成.
类似:
result = readl(ptr);
if (result = = ~(u32)0) /* card removed */
return -ENODEV;
对USB, 来讲, 所有请求的返回 -ENODEV错误.
The /sbin/hotplug Utility
这个程序是钦定的uevent处理函数, 一般简单处理后传递给/etc/hotplug.d/中的对应程序.  比如像下面这样:
DIR="/etc/hotplug.d"
for I in "${DIR}/$1/"*.hotplug "${DIR}/"default/*.hotplug ; do
   if [ -f $I ]; then
      test -x $I && $I $1 ;
   fi
done
exit 1
参考 : hotplug(8) manpage.
内核传递的参数只有一个, 其他的用环境变量来传递. 参数是对应的kset的name函数产生的, 如果没有那个函数,则名字是kset本身. 一些环境变量总是被设置的:
ACTION  : add or remove
DEVPATH: 代表被创建/删除的kobject的目录
SEQNUM : 64bit的序列码, 可以用于保持事件顺序
SUBSYSTEM : 和命令行参数相同
各个bus一般都添加自己的环境变量(kset_hotplug_ops)
IEEE1394 (FireWire)
SUBSYSTEM  => ieee1394.
VENDOR_ID  24-bit vendor ID for the IEEE1394 device
MODEL_ID    The 24-bit model ID for the IEEE1394 device
GUID            The 64-bit GUID for the device
SPECIFIER_ID  The 24-bit value specifying the owner of the protocol spec for this device
VERSION         
Networking
  
SUBSYSTEM => net
INTERFACE  interface name
PCI  
SUBSYSTEM  => pci
PCI_CLASS         The PCI class number for the device, in hex.
PCI_ID               The PCI vendor and device IDs for the device,in hex,combined in the format  vendor:device.
PCI_SUBSYS_ID   subsys_vendor:subsys_device.
PCI_SLOT_NAME   domain:bus:slot:function. An example might be 0000:00:0d.0.
Input
SUBSYSTEM => input
PRODUCT    bustype:vendor:product:version.
NAME
PHYS     input子系统给定的设备物理地址
input 特定环境变量:  EV   KEY   REL   ABS   MSC   LED   SND  FF

USB
SUBSYSTEM =>  usb.
PRODUCT    idVendor/idProduct/bcdDevice
TYPE   bDeviceClass/bDeviceSubClass/bDeviceProtocol
bDeviceClass =0 时
    INTERFACE     bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol
    配置了:CONFIG_USB_DEVICEFS,
        DEVICE :   /proc/bus/usb/USB_BUS_NUMBER/USB_DEVICE_NUMBER
                                            3 位bus号,              3 位设备好
SCSI
SUBSYSTEM => scsi
没有其他的, 考其他途径获取信息
Laptop docking stations
SUBSYSTEM => dock
hotplug scripts 和udev 是两个典想的user space空间程序.

Linux hotplug scripts


组脚本是最早应用/sbin/hotplug的程序了, 它解析参数,
在/lib/module/KERNEL_VERSION/modules.*map  (模块MODULE_DEVICE_TABLE,
depmod生成.) 中寻找合适模块(匹配的都加载,以便寻找最好的), 支持PCI, USB, IEEE1394, INPUT,
ISAPNP, and CCW subsystems.
modporbe也支持这个modules.*map了, 这个脚本可以用modprobe来替换相当部分的代码.
udev
sysfs为了替代devfs而生, devfs的弱点:
1. 需要每个driver都得修改,并且自己在/dev下寻找合适的位置
2. 动态maojor,minor编号支持不好
3. 设备命名规则是在kernel的
4. 无法将一个设备的设备文件名称固定下来(比如重启会变..)
udev 和/sys /sbin/hotplug配合完成这些工作.
*udev 查找/class/下对应目录一个叫dev的文件来确定major,minor
*class_simple_ 借口可以方便的完成这个工作(如果需要自己创建class的话)

Dealing with Firmware

不要用code内嵌代码和从内核打开文件(文件名称被指定了, kernel最好不要有policy).  正确的是:
#include
int request_firmware(const struct firmware **fw, char *name, struct device *device); //name应该是和vendor提供的一样
struct firmware {
   size_t size;
   u8 *data;
};
void release_firmware(struct firmware *fw);
非睡眠版本:
int request_firmware_nowait(struct module *module,char *name, struct device *device, void *context,
                                       void (*cont)(const struct firmware *fw, void *context));
1. request_firmware调用时, 在/sys/class/firmware下用你的设备名字创建一个目录, 并包含三个属性:
loading  :加载数据是置为1, 完成后置为0, 取消写-1
data :  写入数据的二进制属性
device : 符号连接到 /sys/devices 内的设备文件
2. 产生 uevent, 传递FIRMWARE 变量 (名字)
3. 如果10秒钟没有加载就放弃, 这个超时时间/sys/class/firmware/timeout可以设置
3.
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/79526/showart_2124794.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP