`
dato0123
  • 浏览: 913786 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是UHCI(10)一个函数引发的故事(一)

 
阅读更多

接下来,1632,下一个函数,driver->start被调用.对于咱们的uhci_driver,start指针指向的是uhci_start函数,经过了人间大炮一级准备,二级准备之后,这个函数基本上就算介于三级准备和发射之间了.这个函数算是整个故事中最重要的一个函数,理解它是理解整个uhci的关键.来自drivers/usb/host/uhci-hcd.c:

538 /*

539 * Allocate a frame list, and then setup the skeleton

540 *

541 * The hardware doesn't really know any difference

542 * in the queues, but the order does matter for the

543 * protocols higher up. The order in which the queues

544 * are encountered by the hardware is:

545 *

546 * - All isochronous events are handled before any

547 * of the queues. We don't do that here, because

548 * we'll create the actual TD entries on demand.

549 * - The first queue is the high-period interrupt queue.

550 * - The second queue is the period-1 interrupt and async

551 * (low-speed control, full-speed control, then bulk) queue.

552 * - The third queue is the terminating bandwidth reclamation queue,

553 * which contains no members, loops back to itself, and is present

554 * only when FSBR is on and there are no full-speed control or bulk QHs.

555 */

556 static int uhci_start(struct usb_hcd *hcd)

557 {

558 struct uhci_hcd *uhci = hcd_to_uhci(hcd);

559 int retval = -EBUSY;

560 int i;

561 struct dentry *dentry;

562

563 hcd->uses_new_polling = 1;

564

565 spin_lock_init(&uhci->lock);

566 setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,

567 (unsigned long) uhci);

568 INIT_LIST_HEAD(&uhci->idle_qh_list);

569 init_waitqueue_head(&uhci->waitqh);

570

571 if (DEBUG_CONFIGURED) {

572 dentry = debugfs_create_file(hcd->self.bus_name,

573 S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,

574 uhci, &uhci_debug_operations);

575 if (!dentry) {

576 dev_err(uhci_dev(uhci), "couldn't create uhci "

577 "debugfs entry/n");

578 retval = -ENOMEM;

579 goto err_create_debug_entry;

580 }

581 uhci->dentry = dentry;

582 }

583

584 uhci->frame = dma_alloc_coherent(uhci_dev(uhci),

585 UHCI_NUMFRAMES * sizeof(*uhci->frame),

586 &uhci->frame_dma_handle, 0);

587 if (!uhci->frame) {

588 dev_err(uhci_dev(uhci), "unable to allocate "

589 "consistent memory for frame list/n");

590 goto err_alloc_frame;

591 }

592 memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));

593

594 uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),

595 GFP_KERNEL);

596 if (!uhci->frame_cpu) {

597 dev_err(uhci_dev(uhci), "unable to allocate "

598 "memory for frame pointers/n");

599 goto err_alloc_frame_cpu;

600 }

601

602 uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),

603 sizeof(struct uhci_td), 16, 0);

604 if (!uhci->td_pool) {

605 dev_err(uhci_dev(uhci), "unable to create td dma_pool/n");

606 goto err_create_td_pool;

607 }

608

609 uhci->qh_pool = dma_pool_create("uhci_qh", uhci_dev(uhci),

610 sizeof(struct uhci_qh), 16, 0);

611 if (!uhci->qh_pool) {

612 dev_err(uhci_dev(uhci), "unable to create qh dma_pool/n");

613 goto err_create_qh_pool;

614 }

615

616 uhci->term_td = uhci_alloc_td(uhci);

617 if (!uhci->term_td) {

618 dev_err(uhci_dev(uhci), "unable to allocate terminating TD/n");

619 goto err_alloc_term_td;

620 }

621

622 for (i = 0; i < UHCI_NUM_SKELQH; i++) {

623 uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);

624 if (!uhci->skelqh[i]) {

625 dev_err(uhci_dev(uhci), "unable to allocate QH/n");

626 goto err_alloc_skelqh;

627 }

628 }

629

630 /*

631 * 8 Interrupt queues; link all higher int queues to int1 = async

632 */

633 for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)

634 uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);

635 uhci->skel_async_qh->link = UHCI_PTR_TERM;

636 uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);

637

638 /* This dummy TD is to work around a bug in Intel PIIX controllers */

639 uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |

640 (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);

641 uhci->term_td->link = UHCI_PTR_TERM;

642 uhci->skel_async_qh->element = uhci->skel_term_qh->element =

643 LINK_TO_TD(uhci->term_td);

644

645 /*

646 * Fill the frame list: make all entries point to the proper

647 * interrupt queue.

648 */

649 for (i = 0; i < UHCI_NUMFRAMES; i++) {

650

651 /* Only place we don't use the frame list routines */

652 uhci->frame[i] = uhci_frame_skel_link(uhci, i);

653 }

654

655 /*

656 * Some architectures require a full mb() to enforce completion of

657 * the memory writes above before the I/O transfers in configure_hc().

658 */

659 mb();

660

661 configure_hc(uhci);

662 uhci->is_initialized = 1;

663 start_rh(uhci);

664 return 0;

665

666 /*

667 * error exits:

668 */

669 err_alloc_skelqh:

670 for (i = 0; i < UHCI_NUM_SKELQH; i++) {

671 if (uhci->skelqh[i])

672 uhci_free_qh(uhci, uhci->skelqh[i]);

673 }

674

675 uhci_free_td(uhci, uhci->term_td);

676

677 err_alloc_term_td:

678 dma_pool_destroy(uhci->qh_pool);

679

680 err_create_qh_pool:

681 dma_pool_destroy(uhci->td_pool);

682

683 err_create_td_pool:

684 kfree(uhci->frame_cpu);

685

686 err_alloc_frame_cpu:

687 dma_free_coherent(uhci_dev(uhci),

688 UHCI_NUMFRAMES * sizeof(*uhci->frame),

689 uhci->frame, uhci->frame_dma_handle);

690

691 err_alloc_frame:

692 debugfs_remove(uhci->dentry);

693

694 err_create_debug_entry:

695 return retval;

696 }

这个函数简直就是一个大杂烩,所有变态的代码全都集中在这一个函数里边了.我始终觉得我们看到的这些函数,谈论的这些代码,远比唐笑打武警的话题来得枯燥乏味,但是,天下没有轻松的成功,成功,要付代价.在这个浮躁的社会中,也许很难再有人能够静下心来看代码了.都说现在的程序员是做一天程序撞一天钟,我们这些读程序的又何尝不是这种心态呢?

面对这越来越枯燥的代码,我想我们不能再像过去那样分析了.记得一位泡妞大师曾经教育过我,读懂Linux内核代码和读懂女人的心一样,不是不可能,只是需要你多下点功夫,多用点时间在她们身上,多多沟通,多多了解,增进两个人的感情.这套理论我觉得很有道理,所以我想从现在开始我决定多用点时间多下点功夫来读代码,要和代码多多沟通才能对它有多多了解.所以我决定用出我的杀手锏,kdb.也许你不熟悉kdb,没有关系,我只是通过kdb来展示一些函数调用关系.我主要会使用kdbbp命令来设置一些断点,通过kdbbt命令来显示函数调用堆栈.很显然,了解了函数的调用关系对读懂代码是很有帮助的.

首先我们在加载uhci-hcd的时候设置断点uhci_start.于是我们会在uhci_start被调用的时候进入kdb,bt命令看一下Stacktraceback.

kdb>bt

Stack traceback for pid 3498

0xdd5ac550 3498 3345 1 0 R 0xdd5ac720 *modprobe

esp eip Function (args)

0xd4a89d40 0xc0110000 lapic_resume+0x185

0xd4a89d48 0xe0226e41 [uhci_hcd]uhci_start

0xd4a89d54 0xe0297132 [usbcore]usb_add_hcd+0x3fb

0xd4a89da0 0xe02a0a9b [usbcore]usb_hcd_pci_probe+0x263

其实Stack中还有更多的函数,篇幅原因,跟咱们这里没有太多关系的函数就不列出来了.但是至少从这个traceback中我们可以很清楚的知道我们目前我们的处境,我们在uhci_start,而调用它的函数是usb_add_hcd,后者则是被usb_hcd_pci_probe函数调用,usb_hcd_pci_probe函数正是我们故事的真正开始处.

但单单是kdb还不足以显示我们的决心.有人说,女人如画,不同的画中有不同的风景,代码也是如此,左看右看,上看下看,角度不同风景各异.对于uhci-hcd这样变态的模块,用常规的方法恐怕是很难看明白了,我们必须引入一种新的方法,图解法.uhci_start函数开始,我们将接触到一堆乱七八糟的庞大的复杂的数据结构,这些数据结构的关系如果不能理解,那么我们很难读懂这代码.所以我决定把uhci_start作为实验田,通过图解法把众多复杂的结构众多的链表之间的关系给描绘出来.

分享到:
评论

相关推荐

    Linux那些事儿之我是UHCI

    写一下UHCI吧,也顺便怀念一下Intel,以及Intel的那几个女同事们,好久没联系了,你们可好? UHCI是 Intel提出来的.虽然离开 Intel一年多了,但我总觉得也许有一天我还会回到 Intel.所 以关于 Intel的东西,我多少会关注...

    Linux那些事儿

    Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Block层 Linux那些事儿之我是Sysfs 今天本人将9个单独的文档整理出来,做成了一...

    Linux那些事儿1-9合集

    由复旦fudan_abc写的,风趣的文笔,深入浅...linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Block层 linux那些事儿之我是Sysfs

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    linux那些事儿(EHCI Block SCSI Sysfs PCI USB U 盘 UHCI Hub)

    Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Block层.pdf Linux那些事儿之我是SCSI硬盘.pdf Linux那些事儿之我是Sysfs.pdf Linux那些事儿之我是PCI.pdf ...Linux那些事儿之我是UHCI.pdf

    linux的那些事儿全集

    Linux那些事儿之我是Block层 Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Hub Linux那些事儿之我是PCI ...Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘

    linux那些事全集

    Linux那些事儿之我是UHCI Linux那些事儿之我是Sysfs Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是PCI Linux那些事儿之我是Hub Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Block层

    Linux那些事儿.rar

    Linux那些Linux那些事儿之我是SCSI硬盘,Linux那些事儿之我是Block层,Linux那些事儿之我是EHCI主机控制器,Linux那些事儿之我是HUB,Linux那些事儿之我是PCI,Linux那些事儿之我是Sysfs,Linux那些事儿之我是UHCI,...

    Linux那些事儿系列

    本人整理的fudan_abc的专栏中以完结的文章,在此向原作者表示感谢,给...内容包括:linux那些事儿之我是U盘,linux那些事儿之我是USB,linux那些事儿之我是HUB,linux那些事儿之我是UHCI,linux那些事儿之我是Sysfs。

    Linux那些事儿之我是XXX全集.rar

    Linux那些事儿之我是XXX全集 包含USB core U盘 UHCI PCI SCSI硬盘 Block Hub EHCI 。 想学驱动的童鞋,不妨看看。该书主要是进行源代码的分析

    Linux那些事儿 系列之2 Block+EHCI+PCI+SCSI

    Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是PCI.pdf Linux那些事儿之我是SCSI硬盘.pdf 注: 之前有人已经上传了《Linux那些事儿 系列》,其已经包含了:hub,sysfs...

    linux那些事儿之我是USB.zip

    里面包含Linux那些事的九个文档,Block层,ECHI主机控制,HUB,PCI,SCSI硬盘,Sysfs,UHCI,USB+core,U盘等九个文档,内容详细,而且全面都有书签,适合系统学习!

    Linux那些事系列

    Linux那些事儿之我是Hub Linux那些事儿之我是Sysfs Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘 Linux那些事之我是HUB1

    微信生活缴费商业项目标准版

    Linux那些Linux那些事儿之我是SCSI硬盘,Linux那些事儿之我是Block层,Linux那些事儿之我是EHCI主机控制器,Linux那些事儿之我是HUB,Linux那些事儿之我是PCI,Linux那些事儿之我是Sysfs,Linux那些事儿之我是UHCI,...

    LINUX那些事儿 linux经典之作

    然后是usb core(也就是戏说USB),这一阶段是个承上启下的角色,承的是U盘/HUB,启的是UHCI/EHCI,主要描述一个usb设备连接到hub上之后,在HUB和UHCI/EHCI之间也就是usb core里发生的故事. 再然后可以开始看UHCI/EHCI.这...

    Linux那些事儿[完整版]自己整理

    我是U盘 说的是2.6.10的内核 我是Sysfs 说的是2.6.10的内核 戏说USB 说的是2.6.22的内核 我是Hub/UHCI/EHCI 说的是2.6.22.1的内核

    usb那些事的全集

    usb那些事的全集,包含: 1 Linux那些事儿之我是Block层 2 Linux那些事儿之我是EHCI主机控制器 3 Linux那些事儿之我是HUB ...7 Linux那些事儿之我是UHCI 8 Linux那些事儿之我是USB+core 9 Linux那些事儿之我是U盘

    Linux那些事儿(包括Hub, Sysfs, UHCI, USB, U盘5个部分)

    一个很经典的东东,里面的很多东西都很有启发性,值得看看

    linux那些事儿.rar

    linux那些事儿,Block层,EHCI主机控制器,Hub,PCI,SCSI硬盘,Sysfs,UHCI,USB core,U盘等文档。

Global site tag (gtag.js) - Google Analytics