好了,usb_alloc_dev,多麼熟悉啊,在講hub驅動時這就是那個八大函數的第一個.這裡做的就是為Root Hub申請了一個struct usb_device結構體,并且初始化,将傳回值賦給指針rhdev.回顧這個函數我們可以知道,Root Hub的parent指針指向了Controller本身.
1585行,确定rhdev的speed,UHCI和OHCI都是源于曾經的USB1.1,而EHCI才是來自USB2.0.隻有USB2.0才定義了高速的裝置,以前的裝置隻有兩種速度,低速和全速.也隻有EHCI的驅動才定義了一個flag,HCD_USB2.是以咱們這裡記錄的rhdev->speed就是USB_SPEED_FULL.不過我需要再次提醒一下,hcd->driver在咱們的故事裡就是那個hc_driver,即uhci_driver,有且隻有這一個driver.
1593行,device_init_wakeup.也是咱們在hub驅動中見過的.第二個參數是1就意味着我們把Root Hub的Wakeup能力打開了.正如注釋裡說的那樣,你要是看不慣,你可以在自己的driver裡面把它關掉.
1598行,如果hc_driver中有reset函數,就調用它,咱們的uhci_driver裡面顯然是有的.回去看它的定義,知道它就是uhci_init.是以這時候就要調用這個函數了,顯然它的名字告訴我們它的作用是做一些初始化.它來自drivers/usb/host/uhci-hcd.c:
483 static int uhci_init(struct usb_hcd *hcd)
484 {
485 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
486 unsigned io_size = (unsigned) hcd->rsrc_len;
487 int port;
488
489 uhci->io_addr = (unsigned long) hcd->rsrc_start;
490
491
499 for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
500 unsigned int portstatus;
501
502 portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
503 if (!(portstatus & 0x0080) || portstatus == 0xffff)
504 break;
505 }
506 if (debug)
507 dev_info(uhci_dev(uhci), "detected %d ports/n", port);
508
509
510 if (port > UHCI_RH_MAXCHILD) {
511 dev_info(uhci_dev(uhci), "port count misdetected? "
512 "forcing to 2 ports/n");
513 port = 2;
514 }
515 uhci->rh_numports = port;
516
517
520 check_and_reset_hc(uhci);
521 return 0;
522 }
可惡!又出來一個新的結構體.struct uhci_hcd,很顯然,這是uhci特有的.
371 struct uhci_hcd {
372
373
374 struct dentry *dentry;
375
376
377 unsigned long io_addr;
378
379 struct dma_pool *qh_pool;
380 struct dma_pool *td_pool;
381
382 struct uhci_td *term_td;
383 struct uhci_qh *skelqh[UHCI_NUM_SKELQH];
384 struct uhci_qh *next_qh;
385
386 spinlock_t lock;
387
388 dma_addr_t frame_dma_handle;
389 __le32 *frame;
390 void **frame_cpu;
391
392 enum uhci_rh_state rh_state;
393 unsigned long auto_stop_time;
394
395 unsigned int frame_number;
396 unsigned int is_stopped;
397 #define UHCI_IS_STOPPED 9999
398 unsigned int last_iso_frame;
399 unsigned int cur_iso_frame;
400
401 unsigned int scan_in_progress:1;
402 unsigned int need_rescan:1;
403 unsigned int dead:1;
404 unsigned int working_RD:1;
406 unsigned int is_initialized:1;
407 unsigned int fsbr_is_on:1;
408 unsigned int fsbr_is_wanted:1;
409 unsigned int fsbr_expiring:1;
410
411 struct timer_list fsbr_timer;
412
413
414 unsigned long port_c_suspend;
415 unsigned long resuming_ports;
416 unsigned long ports_timeout;
417
418 struct list_head idle_qh_list;
419
420 int rh_numports;
421
422 wait_queue_head_t waitqh;
423 int num_waiting;
424
425 int total_load;
426 short load[MAX_PHASE];
427 };
寫代碼的人永遠都不會體會到我們讀代碼人的痛苦,我真的覺得如果這些變态的資料結構再多出現幾個的話我就不想看了.我的忍耐是有底線的,我甚至懷疑今年那部号稱十足的悲劇的電影<<十分愛>>中女主角之是以說出那句經典的“那些男人隻知道女人的底褲在哪裡,永遠都不知道女人的底線在哪裡,總是想挑戰女人的極限.”是不是因為當時她也在看Linux核心代碼?