📄 ln97xend.c
字号:
/* ln97xEnd.c - END style AMD Am79C97X PCnet-PCI Ethernet driver *//* Copyright 1984-2002 Wind River Systems, Inc., and Cetia Inc. */#include "copyright_wrs.h"/*modification history--------------------01n,30may02,sru Add run-time control of byte-swapping for PCI master operations.01m,25jan02,pai Reworked polled-mode code (SPR #72034). Corrected ln97xConfig() abuse. Removed unused DRV_PRINT(). Removed gratuitous header file inclusions. Replaced most driver macros with inline functions. Reworked logical address support.01l,14jan02,dat Removing warnings from Diab compiler01k,17oct01,pai Added support for custom device description string.01j,27mar01,tlc Add configuration routine to set up the PCI bus endianess and interuppt level expected by the driver.01i,20nov00,jkf SPR#62266 T3 doc update01h,10nov00,mks passing in correct type of pointer in strtok_r. SPR 6222401g,11jun00,ham removed reference to etherLib.01f,19may00,pai Implemented accumulated driver bug fixes (SPR #31349).01e,27jan00,dat fixed use of NULL01d,13oct99,stv Fixed the bug of failing to release the transmit semaphore (SPR #29094).01c,08dec98,snk made architecture independant, by teamF1 Inc. tested with x86 & power Pc architectures.01b,21sep98,dat modified to stand alone01a,01aug98,dmb written from if_lnPci.c, ver 01e*//*DESCRIPTIONThis module implements the Advanced Micro Devices Am79C970A, Am79C971,Am79C972, and Am79C973 PCnet-PCI Ethernet 32-bit network interface driver.The PCnet-PCI ethernet controller is inherently little-endian becausethe chip is designed to operate on a PCI bus which is a little-endianbus. The software interface to the driver is divided into three parts.The first part is the PCI configuration registers and their set up. This part is done at the BSP level in the various BSPs which use thisdriver. The second and third part are dealt with in the driver. The secondpart of the interface is comprised of the I/O control registers and theirprogramming. The third part of the interface is comprised of the descriptorsand the buffers. This driver is designed to be moderately generic, operating unmodifiedacross the range of architectures and targets supported by VxWorks. Toachieve this, the driver must be given several target-specific parameters,and some external support routines must be provided. These target-specificvalues and the external support routines are described below.This driver supports multiple units per CPU. The driver can beconfigured to support big-endian or little-endian architectures. Itcontains error recovery code to handle known device errata related to DMAactivity. Some big-endian processors may be connected to a PCI bus through ahost/PCI bridge which performs byte swapping during data phases. On suchplatforms, the PCnet-PCI controller need not perform byte swapping during aDMA access to memory shared with the host processor.BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.EXTERNAL INTERFACEThe drvier provides one standard external interface, ln97xEndLoad(). Asinput, this routine takes a string of colon-separated parameters. Theparameters should be specified in hexadecimal (optionally preceded by '0x'or a minus sign '-'). The parameter string is parsed using strtok_r().TARGET-SPECIFIC PARAMETERSThe format of the parameter string is:<unit:devMemAddr:devIoAddr:pciMemBase:vecNum:intLvl:memAdrs:memSize:memWidth:csr3b:offset:flags>\is\i <unit>The unit number of the device. Unit numbers start at zero and increase foreach device controlled by the same driver. The driver does not use thisvalue directly. The unit number is passed through the MUX API where it isused to differentiate between multiple instances of a particular driver.\i <devMemAddr>This parameter is the memory mapped I/O base address of the device registersin the memory map of the CPU. The driver will locate device registers asoffsets from this base address.The PCnet presents two registers to the external interface, the RDP (RegisterData Port) and RAP (Register Address Port) registers. This driver assumes that these two registers occupy two unique addresses in a memory spacethat is directly accessible by the CPU executing this driver. The driverassumes that the RDP register is mapped at a lower address than the RAPregister; the RDP register is therefore derived from the "base address."This is a required parameter.\i <devIoAddr>This parameter specifies the I/O base address of the device registers in theI/O map of some CPUs. It indicates to the driver where to find the RDPregister. This parameter is no longer used, but is retained so that theload string format will be compatible with legacy initialization routines.The driver will always use memory mapped I/O registers specified via the<devMemAddr> parameter.\i <pciMemBase>This parameter is the base address of the host processor memory as seenfrom the PCI bus. This parameter is zero for most Intel architectures.\i <vecNum>This parameter is the vector associated with the device interrupt.This driver configures the PCnet device to generate hardware interruptsfor various events within the device; thus it containsan interrupt handler routine. The driver calls pciIntConnect() to connectits interrupt handler to the interrupt vector generated as a result of thePCnet interrupt.\i <intLvl>Some targets use additional interrupt controller devices to help organizeand service the various interrupt sources. This driver avoids allboard-specific knowledge of such devices. During the driver'sinitialization, the external routine sysLan97xIntEnable() is called toperform any board-specific operations required to allow the servicing of aPCnet interrupt. For a description of sysLan97xIntEnable(), see "ExternalSupport Requirements" below.\i <memAdrs>This parameter gives the driver the memory address to carve out itsbuffers and data structures. If this parameter is specified to beNONE then the driver allocates cache coherent memory for buffersand descriptors from the system memory pool.The PCnet device is a DMA type of device and typically shares access tosome region of memory with the CPU. This driver is designed for systemsthat directly share memory between the CPU and the PCnet. Itassumes that this shared memory is directly available to itwithout any arbitration or timing concerns.\i <memSize>This parameter can be used to explicitly limit the amount of sharedmemory (bytes) this driver will use. The constant NONE can be used toindicate no specific size limitation. This parameter is used only ifa specific memory region is provided to the driver.\i <memWidth>Some target hardware that restricts the shared memory region to aspecific location also restricts the access width to this region bythe CPU. On these targets, performing an access of an invalid widthwill cause a bus error.This parameter can be used to specify the number of bytes of accesswidth to be used by the driver during access to the shared memory.The constant NONE can be used to indicate no restrictions.Current internal support for this mechanism is not robust; implementation may not work on all targets requiring these restrictions.\i <csr3b>The PCnet-PCI Control and Status Register 3 (CSR3) controls, amongother things, big-endian and little-endian modes of operation. Whenbig-endian mode is selected, the PCnet-PCI controller will swap theorder of bytes on the AD bus during a data phase on access to the FIFOsonly: AD[31:24] is byte 0, AD[23:16] is byte 1, AD[15:8] is byte 2 andAD[7:0] is byte 3. In order to select the big-endian mode, set thisparameter to (0x0004). Most implementations, including nativelybig-endian host architectures, should set this parameter to (0x0000) inorder to select little-endian access to the FIFOs, as the driver iscurrently designed to perform byte swapping as appropriate to the hostarchitecture.\i <offset>This parameter specifies a memory alignment offset. Normally thisparameter is zero except for architectures which can only access 32-bitwords on 4-byte aligned address boundaries. For these architectures thevalue of this offset should be 2.\i <flags>This is parameter is used for future use. Currently its value should bezero.\ieEXTERNAL SUPPORT REQUIREMENTSThis driver requires five externally defined support functions that canbe customized by modifying global pointers. The function pointer typesand default "bindings" are specified below. To change the defaults, theBSP should create an appropriate routine and set the function pointerbefore first use. This would normally be done within sysHwInit2().Note that all of the pointers to externally defined functions <must> beset to a valid executable code address. Also, note thatsysLan97xIntEnable(), sysLan97xIntDisable(), and sysLan97xEnetAddrGet()must be defined in the BSP. This was done so that the driver would becompatible with initialization code and support routines in existing BSPs.The function pointer convention has been introduced to facilitate futuredriver versions that do not explicitly reference a named BSP-definedfunction. Among other things, this would allow a BSP designer to define,for example, one endIntEnable() routine to support multple END drivers.\is\i 'ln97xIntConnect'\cs IMPORT STATUS (* ln97xIntConnect) ( VOIDFUNCPTR * vector, /@ interrupt vector to attach to @/ VOIDFUNCPTR routine, /@ routine to be called @/ int parameter /@ parameter to be passed to routine @/ ); /@ default setting @/ ln97xIntConnect = pciIntConnect;\ceThe ln97xIntConnect pointer specifies a function used to connect thedriver interrupt handler to the appropriate vector. By default it isthe <pciIntLib> routine pciIntConnect().\i 'ln97xIntDisconnect'\cs IMPORT STATUS (* ln97xIntDisconnect) ( VOIDFUNCPTR * vector, /@ interrupt vector to attach to @/ VOIDFUNCPTR routine, /@ routine to be called @/ int parameter /@ routine parameter @/ ); /@ default setting @/ ln97xIntDisconnect = pciIntDisconnect2;\ceThe ln97xIntDisconnect pointer specifies a function used to disconnectthe interrupt handler prior to unloading the driver. By default it isthe <pciIntLib> routine pciIntDisconnect2().\i 'ln97xIntEnable'\cs IMPORT STATUS (* ln97xIntEnable) ( int level /@ interrupt level to be enabled @/ ); /@ default setting @/ ln97xIntEnable = sysLan97xIntEnable;\ceThe ln97xIntEnable pointer specifies a function used to enable theinterrupt level for the END device. It is called once duringinitialization. By default it is a BSP routine named sysLan97xIntEnable(). The implementation of this routine can vary between architectures, andeven between BSPs for a given architecture family. Generally, theparameter to this routine will specify an interrupt <level> defined for aninterrupt controller on the host platform. For example, MIPS and PowerPCBSPs may implement this routine by invoking the WRS intEnable() libraryroutine. WRS Intel Pentium BSPs may implement this routine viasysIntEnablePIC().\i 'ln97xIntDisable'\cs IMPORT STATUS (* ln97xIntDisable) ( int level /@ interrupt level to be disabled @/ ); /@ default setting @/ ln97xIntDisable = sysLan97xIntDisable;\ceThe ln97xIntDisable pointer specifies a function used to disable theinterrupt level for the END device. It is called during stop. By defaultit is a BSP routine named sysLan97xIntDisable(). The implementation ofthis routine can vary between architectures, and even between BSPs for agiven architecture family. Generally, the parameter to this routine willspecify an interrupt <level> defined for an interrupt controller on thehost platform. For example, MIPS and PowerPC BSPs may implement thisroutine by invoking the WRS intDisable() library routine. WRS IntelPentium BSPs may implement this routine via sysIntDisablePIC().\i 'ln97xEnetAddrGet'\cs IMPORT STATUS (* ln97xEnetAddrGet) (LN_97X_DRV_CTRL * pDrvCtrl, char * pStationAddr); /@ default setting @/ ln97xEnetAddrGet = sysLan97xEnetAddrGet;\ceThe ln97xEnetAddrGet pointer specifies a function used to get the Ethernet(IEEE station) address of the device. By default it is a BSP routinenamed sysLan97xEnetAddrGet().\ieSYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vector - 14240 bytes in text for a PENTIUM3 target - 120 bytes in the initialized data section (data) - 0 bytes in the uninitialized data section (BSS)The driver allocates clusters of size 1520 bytes for receive frames andand transmit frames.SEE ALSO: muxLib, endLib, netBufLib\tb "Network Protocol Toolkit User's Guide"\tb "PCnet-PCI II Single-Chip Full-Duplex Ethernet Controllerfor PCI Local Bus Product"\tb "PCnet-FAST Single-Chip Full-Duplex 10/100 Mbps Ethernet Controllerfor PCI Local Bus Product"*/#include "vxWorks.h"#include "taskLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.h"#include "intLib.h"#include "iv.h"#include "netLib.h"#define END_MACROS#include "etherMultiLib.h"#include "endLib.h"#include "drv/end/ln97xEnd.h"/* defines *//* * If LN_KICKSTART_TX is TRUE the transmitter is kick-started to force a * read of the transmit descriptors, otherwise the internal polling (1.6msec) * will initiate a read of the descriptors. This should be FALSE if there * is any chance of memory latency or chip accesses detaining the PCnet DMA, * which results in a transmitter UFLO error. This can be changed with the * global lnKickStartTx below. */#define LN_KICKSTART_TX TRUE/* Cache macros */#define LN_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))#define LN_CACHE_VIRT_TO_PHYS(address) \ CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))#define LN_CACHE_PHYS_TO_VIRT(address) \ CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))/* memory to PCI address translation macros */#define PCI_TO_MEM_PHYS(pciAdrs) \ ((UINT)(pciAdrs) - (pDrvCtrl->pciMemBase))#define MEM_TO_PCI_PHYS(memAdrs) \ ((UINT)(memAdrs) + (pDrvCtrl->pciMemBase)) #define SYS_OUT_LONG(pDrvCtrl, addr, value) \ if (pDrvCtrl->flags & LS_MODE_MEM_IO_MAP) \ *((volatile UINT32 *)(addr)) = (value); \ else \ sysOutLong ((int)(addr), (value)); \#define SYS_IN_LONG(pDrvCtrl, addr, data) \ if (pDrvCtrl->flags & LS_MODE_MEM_IO_MAP) \ ((data) = *((volatile UINT32 *)(addr)));\ else \ ((data) = sysInLong ((int) (addr))); \/* A shortcut for getting the hardware address from the MIB II stuff. *//* RFC 1213 (old) */#define END_HADDR(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define END_HADDR_LEN(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)/* RFC 2233 (new - not implemented in this driver yet) * * #define END_HADDR(pEnd) \ * ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress) * * #define END_HADDR_LEN(pEnd) \ * ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength) *//* imports */IMPORT int endMultiLstCnt (END_OBJ *);/* bind external support interface to default BSP implementation */IMPORT STATUS pciIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR, int);IMPORT STATUS pciIntDisconnect2 (VOIDFUNCPTR *, VOIDFUNCPTR, int);IMPORT STATUS sysLan97xIntEnable (int);IMPORT STATUS sysLan97xIntDisable (int);IMPORT STATUS sysLan97xEnetAddrGet (LN_97X_DRV_CTRL *, char *);STATUS (* ln97xIntConnect) (VOIDFUNCPTR *, VOIDFUNCPTR, int) = pciIntConnect;STATUS (* ln97xIntDisconnect) (VOIDFUNCPTR *, VOIDFUNCPTR, int) = pciIntDisconnect2;STATUS (* ln97xIntEnable)(int) = sysLan97xIntEnable;STATUS (* ln97xIntDisable)(int) = sysLan97xIntDisable;STATUS (* ln97xEnetAddrGet) (LN_97X_DRV_CTRL *, char *) = sysLan97xEnetAddrGet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -