天天看點

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;  

    151         const char      *product_desc; 

    152         size_t          hcd_priv_size; 

    153

    154        

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

    156

    157         int     flags;

    158 #define HCD_MEMORY      0x0001         

    159 #define HCD_USB11       0x0010         

    160 #define HCD_USB2        0x0020         

    161

    162        

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

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

    165

    166        

    169        

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

    171

    172        

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

    174

    175        

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

    177

    178        

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

    180

    181        

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

    183

    184        

    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        

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

    193                         struct usb_host_endpoint *ep);

    194

    195        

    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                

    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        

    870         .irq =                  uhci_irq,

    871         .flags =                HCD_USB11,

    872

    873        

    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_driver是usb這邊的接口,這兩概念咋扯到一塊去了呢?呵呵, 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

     55

     56

     57

     58 struct usb_hcd {

     59

     60        

     63         struct usb_bus          self;          

     64         struct kref             kref;          

     65

     66         const char              *product_desc; 

     67         char                    irq_descr[24]; 

     68

     69         struct timer_list       rh_timer;      

     70         struct urb              *status_urb;   

     71 #ifdef CONFIG_PM

     72         struct work_struct      wakeup_work;   

     73 #endif

     74

     75        

     78         const struct hc_driver  *driver;       

     79

     80        

     81         unsigned long           flags;

     82 #define HCD_FLAG_HW_ACCESSIBLE  0x00000001

     83 #define HCD_FLAG_SAW_IRQ        0x00000002

     84

     85         unsigned                rh_registered:1;

     86

     87        

     89         unsigned                uses_new_polling:1;

     90         unsigned                poll_rh:1;     

     91         unsigned                poll_pending:1;

     92         unsigned                wireless:1;    

     93

     94         int                     irq;           

     95         void __iomem            *regs;         

     96         u64                     rsrc_start;    

     97         u64                     rsrc_len;      

     98         unsigned                power_budget;  

     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        

    122

    123        

    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中的dev是struct 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

    276 struct usb_bus {

    277         struct device *controller;     

    278         int busnum;                    

    279         char *bus_name;                 

    280         u8 uses_dma;                   

    281         u8 otg_port;                   

    282         unsigned is_b_host:1;           

    283         unsigned b_hnp_enable:1;       

    284

    285         int devnum_next;               

    287

    288         struct usb_devmap devmap;      

    289         struct usb_device *root_hub;   

    290         struct list_head bus_list;     

    291

    292         int bandwidth_allocated;       

    299         int bandwidth_int_reqs;        

    300         int bandwidth_isoc_reqs;       

    301

    302 #ifdef CONFIG_USB_DEVICEFS

    303         struct dentry *usbfs_dentry;   

    304 #endif

    305         struct class_device *class_dev;

    306

    307 #if defined(CONFIG_USB_MON)

    308         struct mon_bus *mon_bus;       

    309         int monitored;                 

    310 #endif

    311 };

有時候我真的很困惑,難道定義的結構體越多說明寫代碼的人腕兒越大?真的,我算是看明白了,這些人的思路是,一定得選最變态的資料結構,行數至少也得30行,什麼int型呀,char型呀,unsinged型呀,能給它用的全給它用上,結構體前邊有說明,裡邊有嵌套的結構體,結構體内寫一堆注釋,跨行,特長的那種,一套道地的gcc文法,倍兒有面子,再用上ANSI C的struct結構體初始化形式,一個結構體光指針就得十來個,再添加一些宏定義,編譯開關,就是一個字兒--帥!寫個子產品就得定義十個八個的結構體,你要是隻定義兩三個啊,你都不好意思在開源社群裡跟人家打招呼,你說這樣的代碼,一個子產品得賣多少錢?我覺得怎麼着也得兩千美金吧,兩千美金?!那是人力成本,四千美金起,你别嫌貴,還不打折,你得研究使用者的購買心理,願意掏兩千美金買源程式的使用者,根本不在乎再多掏兩千,什麼叫成功人士你知道嗎?成功人士就是,買什麼都買最複雜的,不買最好的,是以我們寫代碼的口号就是,不求最好,但求最複雜.

繼續閱讀