Linux那些事儿之我是UHCI(3)-物以类聚

这年头情侣一多,黄瓜就不好卖了. –- 北大门口卖水果的小贩回忆2005

开源社区的家伙大概都是光棍,因为他们展现给我们的不是情侣多,而是变态的数据结构多.尤其我们这一节里要经历的变态数据结构更是多,基本上这些变态的数据结构都聚集到了这一节,所谓物以类聚吧.这么一堆变态的数据结构,要是写博客的是谭浩强,估计你看了就崩溃了,也亏了是我在写.平心而论,经历了毕业这两年来的种种挫折之后,尤其是两次求职的那冷暖自知的种种辛酸之后,有些东西我也算是看得比较透了,写代码的这群混蛋们就是唯恐天下不乱,每写一个模块就给我们引进一堆复杂的数据结构,仿佛他们的理念就是,男人,就是要对别人狠一点.没办法,哥们儿也是因为没钱,迫于生计才学Linux,有钱了我才不会来看这无聊的代码呢,如果我要中500,除了爹妈不换,剩下全换!

usb_create_hcd的第一个参数struct hc_driver,这个结构体掀开了我们对usb host controller driver的认识,它来自drivers/usb/core/hcd.h:

    149 struct hc_driver {

    150         const char      *description;   /* "ehci-hcd" etc */

    151         const char      *product_desc;  /* product/vendor string */

    152         size_t          hcd_priv_size;  /* size of private data */

    153

    154         /* irq handler */

    155         irqreturn_t     (*irq) (struct usb_hcd *hcd);

    156

    157         int     flags;

    158 #define HCD_MEMORY      0x0001          /* HC regs use memory (else I/O) */

    159 #define HCD_USB11       0x0010          /* USB 1.1 */

    160 #define HCD_USB2        0x0020          /* USB 2.0 */

    161

    162         /* called to init HCD and root hub */

    163         int     (*reset) (struct usb_hcd *hcd);

    164         int     (*start) (struct usb_hcd *hcd);

    165

    166         /* NOTE:  these suspend/resume calls relate to the HC as

    167          * a whole, not just the root hub; they're for PCI bus glue.

    168          */

    169         /* called after suspending the hub, before entering D3 etc */

    170         int     (*suspend) (struct usb_hcd *hcd, pm_message_t message);

    171

    172         /* called after entering D0 (etc), before resuming the hub */

    173         int     (*resume) (struct usb_hcd *hcd);

    174

    175         /* cleanly make HCD stop writing memory and doing I/O */

    176         void    (*stop) (struct usb_hcd *hcd);

    177

    178         /* shutdown HCD */

    179         void    (*shutdown) (struct usb_hcd *hcd);

    180

    181         /* return current frame number */

    182         int     (*get_frame_number) (struct usb_hcd *hcd);

    183

    184         /* manage i/o requests, device state */

    185         int     (*urb_enqueue) (struct usb_hcd *hcd,

    186                                         struct usb_host_endpoint *ep,

187                                         struct urb *urb,

    188                                         gfp_t mem_flags);

    189         int     (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);

    190

    191         /* hw synch, freeing endpoint resources that urb_dequeue can't */

    192         void    (*endpoint_disable)(struct usb_hcd *hcd,

    193                         struct usb_host_endpoint *ep);

    194

    195         /* root hub support */

    196         int             (*hub_status_data) (struct usb_hcd *hcd, char *buf);

    197         int             (*hub_control) (struct usb_hcd *hcd,

    198                                 u16 typeReq, u16 wValue, u16 wIndex,

    199                                 char *buf, u16 wLength);

    200         int             (*bus_suspend)(struct usb_hcd *);

    201         int             (*bus_resume)(struct usb_hcd *);

    202         int             (*start_port_reset)(struct usb_hcd *, unsigned port_num);

    203         void            (*hub_irq_enable)(struct usb_hcd *);

    204                 /* Needed only if port-change IRQs are level-triggered */

    205 };

说句良心话,你说这么长的一个结构体你要我怎么看?现在制药的都知道要制良心药,你们这些写代码的就不能写良心代码?算了,先不看这个结构体的细节了,反正吧,每个hcd都得对应这么一个结构体变量.比如咱们的uhci,drivers/usb/host/uhci-hcd中就有这么一段:

    862 static const char hcd_name[] = "uhci_hcd";

    863

    864 static const struct hc_driver uhci_driver = {

    865         .description =          hcd_name,

    866         .product_desc =         "UHCI Host Controller",

    867         .hcd_priv_size =        sizeof(struct uhci_hcd),

    868

    869         /* Generic hardware linkage */

    870         .irq =                  uhci_irq,

    871         .flags =                HCD_USB11,

    872

    873         /* Basic lifecycle operations */

    874         .reset =                uhci_init,

    875         .start =                uhci_start,

    876 #ifdef CONFIG_PM

    877         .suspend =              uhci_suspend,

    878         .resume =               uhci_resume,

    879         .bus_suspend =          uhci_rh_suspend,

    880         .bus_resume =           uhci_rh_resume,

    881 #endif

    882         .stop =                 uhci_stop,

    883

    884         .urb_enqueue =          uhci_urb_enqueue,

    885         .urb_dequeue =          uhci_urb_dequeue,

    886

    887         .endpoint_disable =     uhci_hcd_endpoint_disable,

    888         .get_frame_number =     uhci_hcd_get_frame_number,

    889

    890         .hub_status_data =      uhci_hub_status_data,

    891         .hub_control =          uhci_hub_control,

    892 };

其实就是一堆乱七八糟的指针,也没什么了不起.不过我得提醒你了,在咱们整个故事中也就只有一个struct hc_driver变量,就是这一个uhci_driver,以后凡是提到hc_driver,指的就是uhci_driver.不过你说这个probe函数咋知道的?probe函数是pci那边的接口,hc_driverusb这边的接口,这两概念咋扯到一块去了呢?呵呵, usb_hcd_pci_probe函数67,看见没有,driver在这里被赋值了,而等号右边那个id->driver_data又是什么?继续回去看,uhci_pci_ids这张表里写得很清楚,driver_data就是被赋值为&uhci_driver,所以说一切都是有因才有果的,不会无缘无故的出现一个变量.说到因果,就好比你问我没房没老婆是什么关系,我就只能告诉你三十岁以前是并列关系,三十岁以后是因果关系.

继续看,1496,一个变态的数据结构还不够,还得来一个更变态的.struct usb_hcd,这意思很明确,有一个hcd就得有这么一个结构体,也是来自drivers/usb/core/hcd.h:

     47 /*-------------------------------------------------------------------------*/

     48

     49 /*

     50  * USB Host Controller Driver (usb_hcd) framework

     51  *

     52  * Since "struct usb_bus" is so thin, you can't share much code in it.

     53  * This framework is a layer over that, and should be more sharable.

     54  */

     55

     56 /*-------------------------------------------------------------------------*/

     57

     58 struct usb_hcd {

     59

     60         /*

     61          * housekeeping

     62          */

     63         struct usb_bus          self;           /* hcd is-a bus */

     64         struct kref             kref;           /* reference counter */

     65

     66         const char              *product_desc;  /* product/vendor string */

     67         char                    irq_descr[24];  /* driver + bus # */

     68

     69         struct timer_list       rh_timer;       /* drives root-hub polling */

     70         struct urb              *status_urb;    /* the current status urb */

     71 #ifdef CONFIG_PM

     72         struct work_struct      wakeup_work;    /* for remote wakeup */

     73 #endif

     74

     75         /*

     76          * hardware info/state

     77          */

     78         const struct hc_driver  *driver;        /* hw-specific hooks */

     79

     80         /* Flags that need to be manipulated atomically */

     81         unsigned long           flags;

     82 #define HCD_FLAG_HW_ACCESSIBLE  0x00000001

     83 #define HCD_FLAG_SAW_IRQ        0x00000002

     84

     85         unsigned                rh_registered:1;/* is root hub registered? */

     86

     87         /* The next flag is a stopgap, to be removed when all the HCDs

     88          * support the new root-hub polling mechanism. */

     89         unsigned                uses_new_polling:1;

     90         unsigned                poll_rh:1;      /* poll for rh status? */

     91         unsigned                poll_pending:1; /* status has changed? */

     92         unsigned                wireless:1;     /* Wireless USB HCD */

     93

     94         int                     irq;            /* irq allocated */

     95         void __iomem            *regs;          /* device memory/io */

     96         u64                     rsrc_start;     /* memory/io resource start */

     97         u64                     rsrc_len;       /* memory/io resource length */

     98         unsigned                power_budget;   /* in mA, 0 = no limit */

     99

    100 #define HCD_BUFFER_POOLS        4

    101         struct dma_pool         *pool [HCD_BUFFER_POOLS];

    102

    103         int                     state;

    104 #       define  __ACTIVE                0x01

    105 #       define  __SUSPEND               0x04

    106 #       define  __TRANSIENT             0x80

    107

    108 #       define  HC_STATE_HALT           0

    109 #       define  HC_STATE_RUNNING        (__ACTIVE)

    110 #       define  HC_STATE_QUIESCING      (__SUSPEND|__TRANSIENT|__ACTIVE)

    111 #       define  HC_STATE_RESUMING       (__SUSPEND|__TRANSIENT)

    112 #       define  HC_STATE_SUSPENDED      (__SUSPEND)

    113

    114 #define HC_IS_RUNNING(state) ((state) & __ACTIVE)

    115 #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)

    116

    117         /* more shared queuing code would be good; it should support

    118          * smarter scheduling, handle transaction translators, etc;

119          * input size of periodic table to an interrupt scheduler.

    120          * (ohci 32, uhci 1024, ehci 256/512/1024).

    121          */

    122

    123         /* The HC driver's private data is stored at the end of

    124          * this structure.

    125          */

    126         unsigned long hcd_priv[0]

    127                         __attribute__ ((aligned (sizeof(unsigned long))));

    128 };

所以usb_create_hcd这个函数就是为struct usb_hcd申请内存空间,并且初始化.我们来看它具体如何初始化的.

1498行是申请内存,并且初值为0.

接下来你得注意了,usb_create_hcd中的dev可是struct device结构体指针,而刚才的usb_hcd_pci_probe中的devstruct pci_dev结构体指针,struct pci_dev虽然我们没说,但也该知道,表示的就是一个pci设备,它有一个成员struct device dev,所以实际上我们看到我们在调用usb_create_hcd的时候第二个参数是&dev->dev.而这里1503行这个dev_set_drvdata就是一简单的内联函数,来自include/linux/device.h:

    491 static inline void

    492 dev_set_drvdata (struct device *dev, void *data)

    493 {

    494         dev->driver_data = data;

    495 }

struct device这个结构体中有一个成员void *driver_data,所以在我们这里,其效果就是令dev->driver_data等于咱们这里申请好的hcd.

1504行就是初始化一个引用计数,struct usb_hcd也不是白贴出来了,至少我们可以看到它有一个成员struct kref kref,这玩艺说白了就是一个引用计数的变量.

1506,我不知道该说什么了,反正我也贴出来了,你也看到了,struct usb_hcd中有一个成员struct usb_bus self,我们说了一个主机控制器就意味着一条总线,所以这里又出来另一个结构体,struct usb_bus,

    273 /*

    274  * Allocated per bus (tree of devices) we have:

    275  */

    276 struct usb_bus {

    277         struct device *controller;      /* host/master side hardware */

    278         int busnum;                     /* Bus number (in order of reg) */

    279         char *bus_name;                 /* stable id (PCI slot_name etc) */

    280         u8 uses_dma;                    /* Does the host controller use DMA? */

    281         u8 otg_port;                    /* 0, or number of OTG/HNP port */

    282         unsigned is_b_host:1;           /* true during some HNP roleswitches */

    283         unsigned b_hnp_enable:1;        /* OTG: did A-Host enable HNP? */

    284

    285         int devnum_next;                /* Next open device number in

    286                                          * round-robin allocation */

    287

    288         struct usb_devmap devmap;       /* device address allocation map */

    289         struct usb_device *root_hub;    /* Root hub */

    290         struct list_head bus_list;      /* list of busses */

    291

    292         int bandwidth_allocated;        /* on this bus: how much of the time

    293                                          * reserved for periodic (intr/iso)

    294                                          * requests is used, on average?

    295                                          * Units: microseconds/frame.

    296                                          * Limits: Full/low speed reserve 90%,

    297                                          * while high speed reserves 80%.

    298                                          */

    299         int bandwidth_int_reqs;         /* number of Interrupt requests */

    300         int bandwidth_isoc_reqs;        /* number of Isoc. requests */

    301

    302 #ifdef CONFIG_USB_DEVICEFS

    303         struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */

    304 #endif

    305         struct class_device *class_dev; /* class device for this bus */

    306

    307 #if defined(CONFIG_USB_MON)

    308         struct mon_bus *mon_bus;        /* non-null when associated */

    309         int monitored;                  /* non-zero when monitored */

    310 #endif

    311 };

有时候我真的很困惑,难道定义的结构体越多说明写代码的人腕儿越大?真的,我算是看明白了,这些人的思路是,一定得选最变态的数据结构,行数至少也得30,什么int型呀,char型呀,unsinged型呀,能给它用的全给它用上,结构体前边有说明,里边有嵌套的结构体,结构体内写一堆注释,跨行,特长的那种,一套地道的gcc语法,倍儿有面子,再用上ANSI Cstruct结构体初始化形式,一个结构体光指针就得十来个,再添加一些宏定义,编译开关,就是一个字儿--!写个模块就得定义十个八个的结构体,你要是只定义两三个啊,你都不好意思在开源社区里跟人家打招呼,你说这样的代码,一个模块得卖多少钱?我觉得怎么着也得两千美金吧,两千美金?!那是人力成本,四千美金起,你别嫌贵,还不打折,你得研究用户的购买心理,愿意掏两千美金买源程序的用户,根本不在乎再多掏两千,什么叫成功人士你知道吗?成功人士就是,买什么都买最复杂的,不买最好的,所以我们写代码的口号就是,不求最好,但求最复杂.

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值