vxWorks网络设备驱动开发之-muxDevLoad

muxDevLoad是用来加载一个网络设备的,muxDevLoad成功执行后,我们就可以在shell里调用ifconfig命令来察看load的网卡设备了。

先看一下函数的调用流程,最后大概分析一下muxDevLoad的功能。

1726 /******************************************************************************
1727 *
1728 * usrNetInit - network intialization routine called from usrConfig.c
1729 *
1730 */
1731 STATUS usrNetInit
1732     (
1733     char *bootString
1734     )
1735     {
1736 #ifdef INCLUDE_BOOT_LINE_INIT
1737     usrBootLineParse(NULL);
1738 #endif /* INCLUDE_BOOT_LINE_INIT */
1739     networkinit ();
1740     return (OK);
1741     }

该函数位于"vxworks-6.8/target/src/config/usrNetwork.c", 调用netWorkInit()来初始化整个网络模块。

netWorkInit()

------->usrNetEndLibInit() : "vxworks-6.8/target/src/config/usrNetwork.c"

-------->vxbDevMethodRun((UINT32)&muxDevConnect_desc, NULL); "vxworks-6.8/target/src/config/usrNetwork.c"

通过上述函数流程,可以看到vxbDevMethodRun遍历所有的注册设备,对每个设备调用muxDevConnect_desc函数,看看muxDevConnect_desc函数是哪儿定义的。

下面这段代码是从驱动:vxworks-6.8/target/src/hwif/end/an983VxbEnd.c 摘出来的。

 141 LOCAL struct vxbDeviceMethod anMethods[] =
 142    {
 143    DEVMETHOD(miiRead,       anPhyRead),
 144    DEVMETHOD(miiWrite,      anPhyWrite),
 145    DEVMETHOD(miiMediaUpdate,    anLinkUpdate),
 146    DEVMETHOD(muxDevConnect, anMuxConnect),
 147    DEVMETHOD(vxbDrvUnlink,  anInstUnlink),
 148    { 0, 0 }
 149    }; 

anMethods是一个vxbDeviceMethod结构体数组,struct vxbDeviceMethod结构体定义如下:

266 /*
267  *  An alternative method for bus controllers to provide the
268  *  methods used by downstream devices.  This structure is
269  *  provided so that the controller can provide a null-terminated
270  *  list of method/handler pairs.
271  *
272  *  When a driver fetches the access methods, the standard methods
273  *  are used first.  If the method is not one of the standard
274  *  methods (specified in the vxbAccessList structure), or if the
275  *  method specified is NULL in the controller‘s standard methods,
276  *  then the vxbAccessMethodsGet() routine searches through any
277  *  methods listed in the pMethods field of the vxbAccessList
278  *  structure.
279  *
280  *  In addition, this structure is used by all devices to provide
281  *  services to OS modules such as power management.
282  */
283
284 struct vxbDeviceMethod
285     {
286     UINT32      devMethodId;
287     FUNCPTR     handler;
288     };

宏DEVMETHOD的定义如下:

171 /* method related macros, for driver use and method caller use */
172
173 #define DEVMETHOD(NAME, FUNC)         { (UINT32)&NAME##_desc, (FUNCPTR) FUNC }
174 #define DEVMETHOD_END                 { 0, NULL }
175 #define METHOD_DECL(NAME)             IMPORT char NAME##_desc[];
176 #define DEVMETHOD_DEF(METHOD, STRING) char METHOD##_desc[]=STRING;
177 #define DEVMETHOD_CALL(METHOD)        ((UINT32)(&METHOD##_desc[0]))

从vxbDeviceMethod结构体可以看出,能通过vxbDevMethodRun函数调用的函数必须有一个函数ID,DEVMETHOD可以帮助生成vxDeviceMethod实例。

到这一步,已经可以调到一个具体驱动的muxDevConnect函数了,下面分析一个具体驱动的muxDevConnect函数。还是以an983VxbEnd.c为例,代码如下:

 855 /*****************************************************************************
 856 *
 857 * anMuxConnect - muxConnect method handler
 858 *
 859 * This function handles muxConnect() events, which may be triggered
 860 * manually or (more likely) by the bootstrap code. Most VxBus
 861 * initialization occurs before the MUX has been fully initialized,
 862 * so the usual muxDevLoad()/muxDevStart() sequence must be defered
 863 * until the networking subsystem is ready. This routine will ultimately
 864 * trigger a call to anEndLoad() to create the END interface instance.
 865 *
 866 * RETURNS: N/A
 867 *
 868 * ERRNO: N/A
 869 */
 870
 871 LOCAL void anMuxConnect
 872     (
 873     VXB_DEVICE_ID pDev,
 874     void * unused
 875     )
 876     {
 877     AN_DRV_CTRL *pDrvCtrl;
 878
 879     /*
 880      * Attach our ISR. For PCI, the index value is always
 881      * 0, since the PCI bus controller dynamically sets
 882      * up interrupts for us.
 883      */
 884
 885     vxbIntConnect (pDev, 0, anEndInt, pDev->pDrvCtrl);
 886
 887     pDrvCtrl = pDev->pDrvCtrl;
 888
 889     /* Save the cookie. */
 890
 891     pDrvCtrl->anMuxDevCookie = muxDevLoad (pDev->unitNumber,
 892         anEndLoad, "", TRUE, pDev);
 893
 894     if (pDrvCtrl->anMuxDevCookie != NULL)
 895         muxDevStart (pDrvCtrl->anMuxDevCookie);
 896
 897     if (_func_m2PollStatsIfPoll != NULL)
 898         endPollStatsInit (pDrvCtrl->anMuxDevCookie,
 899             _func_m2PollStatsIfPoll);
 900
 901     return;
 902     }
anMuxConnect首先注册中断,紧接着调用muxDevLoad函数完成网络设备的加载,传入的参数分别为设备的单元号,当同种设备有多个实例时,可以通过pDev->unitNumber区分开来。第二个参数是驱动实现的endLoad函数。最后一个是pDev指向当前网卡的设备实例指针。这三个参数比较重要。下面给出完整的muxDevLoad函数代码,从中可以看出muxDevLoad分两次调用anEndLoad函数,最终完成设备注册,通过muxDevLoad代码,可以更清楚的看到网卡实例的结构体在内核中是如何存放的。
 503 /******************************************************************************
 504 *
 505 * muxDevLoad - load a driver into the MUX
 506 *
 507 * The muxDevLoad() routine loads a network driver into the MUX.  Internally,
 508 * this routine calls the specified <endLoad> routine to initialize the
 509 * software state of the device.  After the device is initialized,
 510 * muxDevStart() must be called to start the device.
 511 * .IP <unit> 15
 512 * Expects the unit number of the device.
 513 * .IP <endLoad>
 514 * Expects a pointer to the network driver‘s endLoad() or nptLoad() entry
 515 * point.
 516 * .IP <pInitString>
 517 * Expects a pointer to an initialization string, typically a colon-delimited
 518 * list of options.  The muxDevLoad() routine passes this along blindly to
 519 * the <endLoad> function.
 520 * .IP <loaning>
 521 * Currently unused. Expects a boolean value that tells the MUX whether the
 522 * driver supports buffer loaning on this device.  If the low-level device
 523 * cannot support buffer loaning, passing in TRUE has no effect.
 524 * .IP <pBSP>
 525 * This argument is passed blindly to the driver, which may or may not use it.
 526 * It is provided so that the BSP can pass in tables of functions that the
 527 * driver can use but that are specific to the particular BSP on which
 528 * it runs.
 529 *
 530 * RETURNS: A cookie representing the new device, or NULL if an error occurred.
 531 *
 532 * ERRNO: S_muxLib_LOAD_FAILED
 533 */
 534     535 DEV_COOKIE muxDevLoad
 536     (
 537     int       unit,                      /* unit number of device */
 538     END_OBJ * (*endLoad) (char*, void*), /* load function of the driver  */
 539     char *    pInitString,       /* init string for this driver  */
 540     BOOL      loaning,               /* we loan buffers  */
 541     void *    pBSP                       /* for BSP group  */
 542     )
 543     {
 544     END_OBJ *     pNew = NULL;
 545     END_TBL_ROW * pNode = NULL;
 546     NODE *    enode;
 547     DEV_OBJ       dev;
 548     char          initString [END_INIT_STR_MAX];
 549     int           endStyle;
 550     MUX_END_STYLE_INFO * style;
 551     int       j;
 552
 553     bzero (initString, END_INIT_STR_MAX);
 554
 555     /* Create a fake END placeholder, mark it as invalid */
 556
 557     bzero ((caddr_t)&dev, sizeof (dev));
 558     dev.unit = unit;
 559     dev.muxFlags = MUX_END_FLAG_LOADING;
 560     dev.refs = 1;
 561
 562     if (snprintf (initString, END_INIT_STR_MAX,
 563           "%d:%s", unit, pInitString) >= END_INIT_STR_MAX)
 564         goto muxDevLoad_errout;
 565
 566     /*
 567      * Loading a device is a two pass algorithm.
 568      *
 569      * This is Pass 1.
 570      *
 571      * In the first pass we ask the device what its name is.
 572      * The END must respect the name length limits of dev.name,
 573      * END_NAME_MAX = 16 characters, including terminating NUL.
 574      * Actually, the network stack imposes tighter limits in
 575      * interface ioctls, for which the name (including unit number &
 576      * terminating NUL) must fit in 16 bytes.
 577      */
 578
 579     if (endLoad (dev.name, NULL) != 0)
 580         goto muxDevLoad_errout;
 581
 582     /*
 583      * Now we verify that the device hasn‘t already been loaded, and
 584      * to protect against concurrent loads of the same device, we
 585      * put a temporary placeholder for the END into the MUX list.
 586      *
 587      * We use the temporary placeholder rather than holding muxLock
 588      * across the END operations since we prefer not to establish
 589      * any mutex ordering between muxLock and any semaphores taken
 590      * by endLoad() or the device ioctl routine.
 591      */
 592
 593     if (semTake (muxLock, WAIT_FOREVER) != OK)
 594     return NULL;
 595
 596     /*
 597      * Consider replacing this data structure with a hash table.
 598      * Consider sorting so that an iterator could be defined that
 599      * traversed through the lists in a well-defined order.
 600      * Consider interface indexes managed by the MUX (& consistent
 601      * with the ipnet & other stacks).
 602      */
 603
 604     for (pNode = (END_TBL_ROW *)lstFirst(&endList); pNode != NULL;
 605     pNode = (END_TBL_ROW *)lstNext(&pNode->node))
 606     {
 607     if (strcmp (pNode->name, dev.name) == 0)
 608             break;
 609     }
 610
 611     if (pNode != NULL) /* there‘s already a row for this driver */
 612         {
 613         /*
 614          * pNew is used temporarily here. We do not create a new END object
 615          * till later.
 616          */
 617
 618         for (enode = lstFirst(&pNode->units); enode != NULL;
 619              enode = lstNext(enode))
 620             {
 621         pNew = member_to_object (enode, END_OBJ, devObject.node);
 622             if (pNew->devObject.unit == unit)
 623                 {
 624         if (_func_logMsg)
 625             _func_logMsg ("muxDevLoad: %s%d already loaded!\n",
 626                   dev.name, unit);
 627
 628         semGive (muxLock);
 629         goto muxDevLoad_errout;
 630                 }
 631             }
 632         }
 633     else  /* There is no row yet for this device; add one. */
 634         {
 635     /* MEM */
 636         pNode = malloc (sizeof(END_TBL_ROW));
 637         if (pNode == NULL)
 638             {
 639         semGive (muxLock);
 640         return NULL;
 641             }
 642
 643         bzero ((char *)pNode, sizeof(END_TBL_ROW));
 644         strncpy (pNode->name, dev.name, END_NAME_MAX - 1);
 645     pNode->name [END_NAME_MAX - 1] = EOS;
 646         lstAdd (&endList, &pNode->node);
 647         }
 648
 649     /*
 650      * Add placeholder to list before unlocking, to protect against
 651      * concurrent loads of the same device.
 652      */
 653
 654     lstAdd (&pNode->units, &dev.node);
 655
 656     taskSafe ();  /* stay delete-safe after unlocking */
 657
 658     semGive (muxLock);
 659
 660     /*
 661      * This is Pass 2.
 662      *
 663      * Now that we can determine a unique number we assign that number to
 664      * the device and actually load it.
 665      */
 666
 667     pNew = (END_OBJ *)endLoad ( (char *)initString, pBSP);
 668
 669     if (pNew == NULL)
 670         goto muxLoadErr;
 671
 672     if (pNew->pFuncTable == NULL || pNew->pFuncTable->ioctl == NULL)
 673         goto muxLoadErr;
 674
 675     /* should this be done by END_OBJ_INIT() ? */
 676
 677     pNew->devObject.dummyBinding = pNew;
 678     pNew->devObject.refs = 1;
 679     pNew->devObject.muxFlags = 0;
 680
 681     pNew->unloadInfo = NULL;
 682
 683     /*
 684      * There used to be stuff here to decide whether to set the
 685      * END_MIB_2233 flag in pNew->flags here; that‘s obsolete in
 686      * more ways than one. Removed it. (TODO: What to do instead?)
 687      */
 688
 689     /*
 690      * Determine if driver uses END or NPT interface. Default is END.
 691      * END_STYLE_END2 (ipnet-native) drivers must support EIOCGSTYLE.
 692      */
 693
 694     endStyle = END_STYLE_END;
 695
 696     if (pNew->pFuncTable->ioctl (pNew, EIOCGSTYLE,
 697                  (caddr_t) &endStyle) != OK &&
 698     pNew->pFuncTable->ioctl (pNew, EIOCGNPT, NULL) == OK)
 699         {
 700     endStyle = END_STYLE_NPT;
 701         }
 702
 703     pNew->endStyle = endStyle;
 704
 705     /*
 706      * Set the native send routine and argument.
 707      *
 708      * TODO: may need a send wrapper to collect statistics for
 709      * ENDs that don‘t set the END_MIB_2233 flag. See the old
 710      * _muxTkSendEnd() and _muxTkSendNpt().
 711      *
 712      * Actually, endM2Init() sets END_MIB_2233 in each END
 713      * depending on whether RFC 2233 support is included in
 714      * the image (pMibRtn != NULL); that‘s independent of
 715      * the driver.  A few older drivers that don‘t call
 716      * endM2Init() might set END_MIB_2233 themselves.
 717      */
 718     pNew->send[endStyle].func = pNew->pFuncTable->send;
 719     pNew->send[endStyle].arg = pNew;
 720
 721     pNew->pollSend[endStyle].func = pNew->pFuncTable->pollSend;
 722     pNew->pollSend[endStyle].arg = pNew;
 723
 724     pNew->pollRecv[endStyle].func = pNew->pFuncTable->pollRcv;
 725     pNew->pollRecv[endStyle].arg = pNew;
 726
 727     style = &muxEndStyles[endStyle];
 728
 729     if ((pNew->receiveRtn = style->rxRtn) == NULL)
 730     {
 731     if (_func_logMsg)
 732         _func_logMsg ("No support for end style %d, required by %s%n\n",
 733               endStyle, pNew->devObject.name, unit);
 734     }
 735     pNew->rxArg = pNew; /* do we need rxArg? */
 736
 737     /*
 738      * Install wrapper send, polled send, and polled receive
 739      * functions for different supported styles
 740      */
 741     for (j = 0; j < NUM_END_STYLES; ++j)
 742     {
 743     if (j == endStyle) /* skip the native style */
 744         continue;
 745
 746     if (style->sendWrappers[j] == NULL)
 747         continue;
 748
 749     pNew->send[j].func = style->sendWrappers[j];
 750     pNew->send[j].arg = pNew;
 751     pNew->pollSend[j].func = style->pollSendWrappers[j];
 752     pNew->pollSend[j].arg = pNew;
 753     pNew->pollRecv[j].func = style->pollReceiveWrappers[j];
 754     pNew->pollRecv[j].arg = pNew;
 755     }
 756
 757     semTake (muxLock, WAIT_FOREVER);
 758
 759     taskUnsafe (); /* remove extra deletion safety count */
 760
 761     /* remove placeholder */
 762
 763     lstDelete (&pNode->units, &dev.node);
 764
 765     lstAdd (&pNode->units, &pNew->devObject.node);
 766
 767     semGive (muxLock);
 768
 769     return (pNew);
 770
 771 muxLoadErr:
 772     semTake (muxLock, WAIT_FOREVER);
 773
 774     taskUnsafe (); /* remove extra deletion safety count */
 775
 776     /* remove placeholder */
 777
 778     lstDelete (&pNode->units, &dev.node);
 779
 780     if (lstCount (&pNode->units) == 0)
 781         {
 782         lstDelete (&endList, &pNode->node);
 783         free (pNode);
 784         }
 785
 786     semGive (muxLock);
 787
 788 muxDevLoad_errout:
 789     errnoSet (S_muxLib_LOAD_FAILED);
 790     return (NULL);
 791     }

//TODO:以后再加详细注释

下面是具体驱动的andLoad函数实现:

1080 /*****************************************************************************
1081 *
1082 * anEndLoad - END driver entry point
1083 *
1084 * This routine initializes the END interface instance associated
1085 * with this device. In traditional END drivers, this function is
1086 * the only public interface, and it‘s typically invoked by a BSP
1087 * driver configuration stub. With VxBus, the BSP stub code is no
1088 * longer needed, and this function is now invoked automatically
1089 * whenever this driver‘s muxConnect() method is called.
1090 *
1091 * For older END drivers, the load string would contain various
1092 * configuration parameters, but with VxBus this use is deprecated.
1093 * The load string should just be an empty string. The second
1094 * argument should be a pointer to the VxBus device instance
1095 * associated with this device. Like older END drivers, this routine
1096 * will still return the device name if the init string is empty,
1097 * since this behavior is still expected by the MUX. The MUX will
1098 * invoke this function twice: once to obtain the device name,
1099 * and then again to create the actual END_OBJ instance.
1100 *
1101 * When this function is called the second time, it will initialize
1102 * the END object, perform MIB2 setup, allocate a buffer pool, and
1103 * initialize the supported END capabilities. The only special
1104 * capability we support is VLAN_MTU, since we can receive slightly
1105 * larger than normal frames.
1106 *
1107 * RETURNS: An END object pointer, or NULL on error, or 0 and the name
1108 * of the device if the <loadStr> was empty.
1109 *
1110 * ERRNO: N/A
1111 */
1112
1113 LOCAL END_OBJ *anEndLoad
1114     (
1115     char * loadStr,
1116     void * pArg
1117     )
1118     {
1119     AN_DRV_CTRL *pDrvCtrl;
1120     VXB_DEVICE_ID pDev;
1121
1122     /* Make the MUX happy. */
1123
1124     if (loadStr == NULL)
1125         return NULL;
1126
1127     if (loadStr[0] == 0)
1128         {
1129         bcopy (AN_NAME, loadStr, sizeof(AN_NAME));
1130         return NULL;
1131         }
1132
1133     pDev = pArg;
1134     pDrvCtrl = pDev->pDrvCtrl;
1135
1136     if (END_OBJ_INIT (&pDrvCtrl->anEndObj, NULL, pDev->pName,
1137         pDev->unitNumber, &anNetFuncs,
1138         "Infineon AN983 VxBus END Driver") == ERROR)
1139         {
1140         logMsg("%s%d: END_OBJ_INIT failed\n", (int)AN_NAME,
1141             pDev->unitNumber, 0, 0, 0, 0);
1142         return (NULL);
1143         }
1144
1145     endM2Init (&pDrvCtrl->anEndObj, M2_ifType_ethernet_csmacd,
1146         pDrvCtrl->anAddr, ETHER_ADDR_LEN, ETHERMTU, 100000000,
1147         IFF_NOTRAILERS | IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST);
1148
1149     /* Allocate a buffer pool */
1150
1151     if (endPoolCreate (256, &pDrvCtrl->anEndObj.pNetPool) == ERROR)
1152         {
1153         logMsg("%s%d: pool creation failed\n", (int)AN_NAME,
1154             pDev->unitNumber, 0, 0, 0, 0);
1155         return (NULL);
1156         }
1157
1158     pDrvCtrl->anPollBuf = netTupleGet(pDrvCtrl->anEndObj.pNetPool,
1159         AN_CLSIZE, M_DONTWAIT, MT_DATA, 0);
1160
1161     /* Set up capabilities. */
1162
1163     pDrvCtrl->anCaps.cap_available = IFCAP_VLAN_MTU;
1164     pDrvCtrl->anCaps.cap_enabled = IFCAP_VLAN_MTU;
1165
1166     return (&pDrvCtrl->anEndObj);
1167     }
时间: 2024-08-03 15:02:12

vxWorks网络设备驱动开发之-muxDevLoad的相关文章

Linux 网络设备驱动开发(一) —— linux内核网络分层结构

Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程,又便于扩展和维护. 一.内核网络结构 在Linux内核中,对网络部分按照网络协议层.网络设备层.设备驱动功能层和网络媒介层的分层体系设计. 网络驱动功能层主要通过网络驱动程序实现. 在Linux内核,所有的网络设备都被抽象为一个接口处理,该接口提供了所有的网络操作. net_device结构表示网络设

浅谈 Linux 内核开发之网络设备驱动

网络设备介绍 网络设备是计算机体系结构中必不可少的一部分,处理器如果想与外界通信,通常都会选择网络设备作为通信接口.众所周知,在 OSI(Open Systems Interconnection,开放网际互连)中,网络被划分为七个层次,从下到上分别是物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.我们所讲的网络设备也包括两个层次,一层叫做 MAC(Media Access Control)层,对应于 OSI 的数据链路层:另一层叫做 PHY(Physical Layer)层,对应于物

《linux设备驱动开发详解》笔记——14 linux网络设备驱动

14.1 网络设备驱动结构 网络协议接口层:硬件无关,标准收发函数dev_queue_xmit()和netif_rx();  注意,netif_rx是将接收到的数据给上层,有时也在驱动收到数据以后调用. 网络设备接口层,net_device,统一接口名称,使上层独立于具体硬件. 设备驱动功能层,实现net_device的各成员 物理层 在整个以太网架构里,有两个数据结构非常重要,即sk_buff和net_device,后面两节有说明. 还有一些与内核交互的函数,需要掌握,如netif_start

Android系统移植与驱动开发概述读书心得

第一章是Android系统移植与驱动开发概述,包含了Android系统架构.Android系统移植的主要工作.查看Linux内核版本.Linux内核版本号的定义规则.如何学习Linux驱动开发以及Linux设备驱动等六方面内容 Android系统架构分为四层,分别是Linux内核.C/C++代码库.Android SDK API和应用程序.Linux内核这一层主要包括Linux的驱动程序以及内存管理.进程管理.电源管理等程序. Android移植可分为两部分:应用移植和系统移植.应用移植是指将应

Android系统移植与驱动开发

Android是基于Linux的操作系统,底层是Linux内核层(Linux2.6, Linux3.4等),android使用了Linux操作系统的内核和驱动,其中驱动部分除了Linux的设备驱动,android还增加了专用驱动(例如Binder实现进程间通信).学习驱动之前,必须先了解linux内核,然后针对其运行方式进行探究. Android系统移植是在某一个特定的平台上运行特定的Android操作系统,因此需要特定的linux驱动促使linux内核支持Android识别不同的硬件平台. L

Android驱动移植与驱动开发概述

本书的第一章主要是对Android系统进行介绍,对Android系统移植前的准备工作进行了解,还有是对Linux内核及驱动进行讲解. Android是已经形成了非常完善的嵌入式操作系统.Android的系统架构分为4层:第一层Linux内核,主要包括驱动程序以及管理内存.进程.电源等资源的程序:第二层C/C++代码库,主要包括Linux的.so文件以及嵌入到APK程序中的NDK代码:第三层Android SDK API,直接面向应用程序的Java APK:第四层应用程序,直接面向最终用户的Jav

驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长.首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多

《Linux设备驱动开发详解(第3版)》海量更新总结

本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 2015.2.26 几乎完成初稿. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]添加关于QEMU模拟vexpress板的描述 第2章 <驱动设计的硬件基础> [N]增加关于SoC的介绍:[N]增加关于eFuse的内容:[D]删除ISA总线的内容了:[N]增加关于SP

Android系统移植与驱动开发概述 第一章

Android系统移植与驱动开发概述 1. Android的系统架构分为Linux内核.C/C++代码库.Android SDK API.应用程序四层. 2. Android移植可分为应用移植和系统移植.应用移植是指将应用程序移植到特定的硬件平台.系统移植指的是让Android操作系统在某一特定硬件平台上运行(首要条件是该操作系统支持硬件平台的CPU架构).系统移植的主要任务是移植Linux驱动和HAL(Hardware Abstraction Layer:硬件抽象层,位于应用程序与驱动之间).