📄 if_lnisa.c
字号:
/* if_lnIsa.c - AMD Am79C961 PCnet-ISA+ Ethernet network interface driver *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01a,1sep96,joes written from 01a of if_lnPci.c.*//*This module implements the Advanced Micro Devices Am79C961 PCnet-ISA+Ethernet network interface driver.This driver is designed to be moderately generic, operating unmodifiedon any i386 or above PC architecture which supports the ISA bus. Toachieve this, the driver must be given several target-specific parameters,and some external support routines must be provided. These parameters,and the mechanisms used to communicate them to the driver, are detailedbelow. If any of the assumptions stated below are not true for yourparticular hardware, this driver will probably not function correctly withit.Plug And PlayThis device is compatible with the Microsoft Plug N' Play resource allocationspecification (http://www.microsoft.com, the P n' P spec is available for download from the microsoft site.). This device driver does not implement the Plug N' Play protocol, but expects the device to power up on the ISA busbased on Data in the Plug N' Play EEPROM. Included are utilities for programming the EEPROM if it is detected as invalid or if you wish to changethe IEEE Ethernet address (Warning: This is not a bright thing to do if you do not know what you are doing. It is included as a development/manufacturingtool only).If the EEPROM is invalid, the device is enabled onto the ISA Bus using the device specific software relocatable key (A backdoor mechanism). This allowsthe EEPROM to be accessible and programmed with valid data. To enable theLANCE after programming the EEPROM, the pack must be rebooted.Little EndianIt is assumed that the device is on a Intel X86 based platform, which supportssysInWord, sysOutWord, etc and is Little Endian.BOARD LAYOUTThis device is jumperless. No jumpering diagram is necessary.EXTERNAL INTERFACEThis driver provides the standard external interface with the followingexceptions. All initialization is performed within the attach routine;there is no separate initialization routine. Therefore, in the global interface structure, the function pointer to the initialization routine is NULL.The only user-callable routine is lnIsaattach(), which publishes the `lnIsa'interface and initializes the driver and device.TARGET-SPECIFIC PARAMETERS.iP "base address of device registers"This parameter is passed to the driver by lnIsaattach(). It indicates to the driver where to find the device's register block. It is assumed that the Plug N' Play registers are already setup with data from the EEPROMand the device is enabled on the Bus. If the EEPROM is invalid, it may be reprogrammed using lnIsa_eeprog() which takes the IEEE ethernet address and (optionally) the IP address of the pack as parameters. It loads the Plug N' Play EEPROM data area with values defined in config.h (See diagram in lnIsa_eeprom.c). The pack can then be rebooted and the device will be enabledcorrectly. By defining IP_ADDR_STORED_IN_EEPROM The enabled LANCE presents two registers to the external interface, the RDP (register data port) and RAP (register address port) registers. This driver assumes that these two registers occupy two unique addresses in IO spacethat is directly accessible by the CPU executing this driver through the PC IORead/Write functions sysInByte(), sysOutByte(), sysOutWord(), sysInWord().The register map is as follows: Offset #Bytes Register 0x0 16 IEEE Address 0x10 2 RDP 0x12 2 RAP 0x14 2 Reset 0x16 2 IDP.iP "interrupt vector"This parameter is passed to the driver by lnIsaattach().This driver configures the LANCE device to generate hardware interruptsfor various events within the device; thus it containsan interrupt handler routine. The driver calls intConnect() to connect its interrupt handler to the interrupt vector generated as a result of the LANCE interrupt..iP "interrupt level"This parameter is passed to the driver by lnIsaattach().Since this is an ISA device (i.e. PC based, an 8259 PIC is the expected interrupt controller. Therefore sysIntEnablePIC() is explicitly referencedto enable the interrupts. This parameter is used to set up Edge or Level triggered interrupts in the ISA brige chip..iP "shared memory address"This parameter is passed to the driver by lnIsaattach().The LANCE 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 LANCE. Itassumes that this shared memory is directly available to itwithout any arbitration or timing concerns.This parameter can be used to specify an explicit memory region for useby the LANCE. This should be done on hardware that restricts the LANCEto a particular memory region. The constant NONE can be used to indicatethat there are no memory limitations, in which case, the driver attempts to allocate the shared memory from the system space..iP "shared memory size"This parameter is passed to the driver by lnIsaattach().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..iP "shared memory width"This parameter is passed to the driver by lnIsaattach().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..iP "shared memory buffer size"This parameter is passed to the driver by lnIsaattach().The driver and LANCE device exchange network data in buffers. Thisparameter permits the size of these individual buffers to be limited.A value of zero indicates that the default buffer size should be used.The default buffer size is large enough to hold a maximum-size Ethernetpacket.Use of this parameter should be rare. Network performancewill be affected, since the target will no longer be able to receiveall valid packet sizes..iP "Ethernet address"This parameter is obtained directly from the EEPROM connected to the device.During initialization, the driver needs to know the Ethernet address forthe LANCE device. The driver assumes that this address is available ina global, six-byte character array, lnEnetAddr[]. This array isstuffed from EEPROM by lnIsaattach()..iP "DMA Channel"This parameter is defined in config.h by the MACRO DMA_CHAN_LNISA.The DMA channel selected must be a 16 bit channel. lnIsaattach() places this channel in Cascade mode, which allows DMA requests to be passed though theDMA controller to the CPU..LPEXTERNAL SUPPORT REQUIREMENTSThis driver requires one external support function:.iP "void sysIntEnablePIC (int level)" "" 9 -1This routine provides a PC specific enable of the interrupt forthe LANCE device. This routine is called once, from the lnIsaattach() routine..LPSYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vector - 24 bytes in the initialized data section (data) - 208 bytes in the uninitialized data section (BSS)The above data and BSS requirements are for the I80386 architecture and may vary for other architectures. Code size (text) varies greatly betweenarchitectures and is therefore not quoted here.If the driver is not given a specific region of memory via the lnIsaattach()routine, then it calls cacheDmaMalloc() to allocate the memory to be shared with the LANCE. The size requested is 80,542 bytes. If a memory regionis provided to the driver, the size of this region is adjustable to suituser needs.The LANCE can only be operated if the shared memory region is write-coherentwith the data cache. The driver cannot maintain cache coherencyfor the device for data that is written by the driver because fieldswithin the shared structures are asynchronously modified by both the driverand the device, and these fields may share the same cache line.SEE ALSO: ifLib, .I "Advanced Micro Devices PCnet-ISA+ Ethernet Controller for ISA."*/#include "vxWorks.h"#include "sysLib.h"#include "stdlib.h"#include "taskLib.h"#include "logLib.h"#include "intLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.h"#include "iv.h"#include "memLib.h"#include "cacheLib.h"#include "sys/ioctl.h"#include "etherLib.h"#ifndef DOC /* don't include when building documentation */#include "net/mbuf.h"#endif /* DOC */#include "net/protosw.h"#include "sys/socket.h"#include "errno.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#include "net/if_subr.h"#include "semLib.h"#include "bootLib.h"#include "drv/netif/if_lnIsa.h" /* device description header *//***** LOCAL DEFINITIONS *****//* descriptor size */#define RMD_SIZ sizeof(ln_rmd)#define TMD_SIZ sizeof(ln_tmd)/* Configuration items */#define LN_MIN_FIRST_DATA_CHAIN 96 /* min size of 1st buf in data-chain */#define LN_MAX_MDS 128 /* max number of [r|t]md's for LANCE */#define LN_BUFSIZ (ETHERMTU + ENET_HDR_REAL_SIZ + 6)#define LN_RMD_RLEN 5 /* ring size as a power of 2 -- 32 RMD's */#define LN_TMD_TLEN 5 /* same for transmit ring -- 32 TMD's */#define MAX_UNITS 1 /* maximum units supported *//* * 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 is there * is any chance of memory latency or chip accesses detaining the LANCE 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))/* Typedefs for external structures that are not typedef'd in their .h files */typedef struct mbuf MBUF;typedef struct arpcom IDR; /* Interface Data Record wrapper */typedef struct ifnet IFNET; /* real Interface Data Record */typedef struct sockaddr SOCK;/* The Ethernet header */typedef struct enet_hdr { char dst [6]; char src [6]; u_short type; } ENET_HDR;#define ENET_HDR_SIZ sizeof(ENET_HDR)#define ENET_HDR_REAL_SIZ 14/* The definition of the driver control structure */typedef struct drv_ctrl { IDR idr; /* Interface Data Record */ ln_ib *ib; /* ptr to Initialization Block */ struct { int r_po2; /* RMD ring size as a power of 2! */ int r_size; /* RMD ring size (power of 2!) */ int r_index; /* index into RMD ring */ ln_rmd *r_ring; /* RMD ring */ char *r_bufs; /* receive buffers base */ } rmd_ring; struct { int t_po2; /* TMD ring size as a power of 2! */ int t_size; /* TMD ring size (power of 2!) */ int t_index; /* index into TMD ring */ int d_index; /* index into TMD ring */ ln_tmd *t_ring; /* TMD ring */ char *t_bufs; /* transmit buffers base */ } tmd_ring; BOOL attached; /* indicates unit is attached */ SEM_ID TxSem; /* transmitter semaphore */ u_char flags; /* misc control flags */ int ivec; /* interrupt vector */ int ilevel; /* interrupt level */ LN_DEVICE *devAdrs; /* device structure address */ char *memBase; /* LANCE memory pool base */ int memWidth; /* width of data port */ int bufSize; /* size of buffer in the LANCE ring */ CACHE_FUNCS cacheFuncs; /* cache function pointers */ } DRV_CTRL;#define DRV_CTRL_SIZ sizeof(DRV_CTRL)/* Definitions for the flags field */#define LS_PROMISCUOUS_FLAG 0x1#define LS_MEM_ALLOC_FLAG 0x2#define LS_PAD_USED_FLAG 0x4#define LS_RCV_HANDLING_FLAG 0x8#define LS_START_OUTPUT_FLAG 0x10/* Shorthand structure references */#define rpo2 rmd_ring.r_po2#define rsize rmd_ring.r_size#define rindex rmd_ring.r_index#define rring rmd_ring.r_ring#define tpo2 tmd_ring.t_po2#define tsize tmd_ring.t_size#define tindex tmd_ring.t_index#define dindex tmd_ring.d_index#define tring tmd_ring.t_ring/***** GLOBALS *****/IMPORT STATUS sysIntDisablePIC (int intLevel);IMPORT STATUS sysIntEnablePIC(int intLevel);IMPORT USHORT sysInWord (int address);IMPORT void sysOutWord (int address, USHORT data);IMPORT void sysOutByte (int address, UINT8 data);void panic ();void ether_attach ();BOOL arpresolve ();/***** LOCALS *****/static int lnTsize = LN_TMD_TLEN; /* deflt xmit ring size as power of 2 */static int lnRsize = LN_RMD_RLEN; /* deflt recv ring size as power of 2 */static BOOL lnKickStartTx = LN_KICKSTART_TX;#define LNISA_DEBUG/* The array of driver control structures */static DRV_CTRL drvCtrl [MAX_UNITS];/* initial word offsets from LANCE base address to access these registers */static u_int CSROffset = 0x10;static u_int RAPOffset = 0x12;static u_int IDPOffset = 0x16;/* forward static functions */static void lnReset (int unit);static void lnInt (DRV_CTRL *pDrvCtrl);static void lnHandleRecvInt (DRV_CTRL *pDrvCtrl);static STATUS lnRecv (DRV_CTRL *pDrvCtrl, ln_rmd *rmd);static int lnOutput (IDR *ifp, MBUF *m0, SOCK *dst);static int lnIoctl (IDR *ifp, int cmd, caddr_t data);static int lnChipReset (DRV_CTRL *pDrvCtrl);static ln_rmd * lnGetFullRMD (DRV_CTRL *pDrvCtrl);void lnCsrWrite (DRV_CTRL * pDrvCtrl, int reg, USHORT value);USHORT lnCsrRead (DRV_CTRL * pDrvCtrl, int reg);void lnIdpWrite (DRV_CTRL * pDrvCtrl, int reg, USHORT value);USHORT lnIdpRead (DRV_CTRL * pDrvCtrl, int reg);static void lnRestart (int unit,int loc,int stat);static BOOL convertDestAddr ( IDR *pIDR, SOCK *pDestSktAddr, char *pDestEnetAddr, u_short *pPacketType, MBUF *pMbuf );UINT8 lnEnetAddr [6];#include "lnIsa_eeprom.c" /* EEPROM and PnP control functions for AMD961 *//********************************************************************************* lnIsaattach - publish the `lnIsa' network interface and initialize the driver and device** This routine publishes the `lnIsa' interface by filling in a network * interface record and adding this record to the system list. This routine * also initializes the driver and the device to the operational state.** The <memAdrs> parameter can be used to specify the location of the* memory that will be shared between the driver and the device. The value* NONE is used to indicate that the driver should obtain the memory.** The <memSize> parameter is valid only if the <memAdrs> parameter is not* set to NONE, in which case <memSize> indicates the size of the* provided memory region.** The <memWidth> parameter sets the memory pool's data port width (in bytes);* if it is NONE, any data width is used.** BUGS* To zero out LANCE data structures, this routine uses bzero(), which* ignores the <memWidth> specification and uses any size data access to* write to memory.** RETURNS: OK or ERROR.*/STATUS lnIsaattach( int unit, /* unit number */ char * devAdrs, /* LANCE I/O address */ int ivec, /* interrupt vector */ int ilevel, /* interrupt level */ char * memAdrs, /* address of memory pool (-1 = malloc it) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -