📄 templatenetif.c
字号:
/* tempNetif.c - template ethernet network interface driver *//* Copyright 1989-1997 Wind River Systems, Inc. *//*TODO - Remove the template modification history and begin a new history starting with version 01a and growing the history upward with each revision.modification history--------------------01d,24sep97,dat documentation cleanup, added TEMPLATE_NETIF_{READ | WRITE}01c,25aug97,dat removed IFNET references01b,08aug97,dat fixed compilation bugs01a,30jul97,dat written (from if_ei.c, ver 03h)*//*.SH TODOReplace the documentation for this template driver with documentationfor the driver being written. Begin with an overview of the complete device. Indicate if the new driveronly implements a sub-section of the whole device or not.Describe all of the operating modes of the device, and indicate whichones this driver implements.Document the device initialization steps to be used in the BSP to createand initialize the device. Document all the macros thatcan be used to customize the driver to a particular hardware environment.Document anything that will help the user to understand how this deviceworks and interacts with this driver.This template assumes the device uses some type of transmit frame descriptor(tfd) and a similar receive frame descriptor (rfd). There is an array orlist for each. There are dummy declarations for a TFD and an RFD structure.INTERRUPTSThis driver requires the BSP to perform the intConnect function. The BSPshould connect the templateInt() function using a single argument 'unit'to the appropriate vector. This driver will use the TEMPLATE_INT_ENABLE()and TEMPLATE_INT_DISABLE() macros to enable and disable interrupts. Themacro TEMPLATE_INT_INIT() is used to initialize the interrupt system duringdriver initialization time. The macro TEMPLATE_INT_ACK() is used toperform interrupt acknowledge functions external to the driver.HARDWARE The macros TEMPLATE_NETIF_READ() and TEMPLATE_NETIF_WRITE() are used forall accesses to actual chip. These macros can be redefined to createcustom modules for special situations.NOTES:This template driver was abstracted from the Intel 82596 driver, if_ei.c.It is a fairly common device that has its own DMA controller built in.Transmit data is assigned to a TFD (transmit frame descriptor) and the TFDis linked to a command list that the device monitors. Similar incomingpackets are in RFDs (receive frame descriptors). An interrupt occurs whenthere are RFDs ready with incoming data. The RFD is then unlinked from thereceive queue and processed. When the incoming data is no longer needed thebuffer and RFD and returned to the free pool of RFDs, for reuse.WARNINGS:Do not use printf statements within code executed by netTask. A deadlockis possible when the shell is redirected to the network. Use logMsg()instead. (SPR 8954)SEE ALSO: ifLib*/#include "vxWorks.h"#include "wdLib.h"#include "iv.h"#include "vme.h"#include "net/mbuf.h"#include "net/unixLib.h"#include "net/protosw.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "errno.h"#include "memLib.h"#include "intLib.h"#include "net/if.h"#include "net/route.h"#include "iosLib.h"#include "errnoLib.h"#include "cacheLib.h"#include "logLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.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 "etherLib.h"#include "net/systm.h"#include "sys/times.h"#include "net/if_subr.h"/* local definitions */#define EH_SIZE 14#define MAX_UNITS 4 /* maximum units to support */#define MAX_RFDS_LOANED 8 /* max RFDs that can be loaned *//* 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;typedef struct rfd { /* TODO - This is a dummy RFD structure */ ETH_HDR* pEnetHdr; int status; int count; int reserved; int actualCnt; int refCnt; char * enetData; int bufSize; } RFD;typedef RFD TFD; /* TODO - This is a dummy TFD structure *//* The definition of the driver control structure */typedef struct drv_ctrl /* TODO - This is a dummy driver control structure */ { IDR idr; /* interface data record */ BOOL attached; /* indicates attach() called */ volatile UCHAR * pCsr; /* Control status register */ char * memBase; /* memory pool base */ volatile BOOL rcvHandling; /* flag, indicates netTask active */ volatile BOOL txCleaning; /* flag, indicates netTask active */ volatile BOOL txIdle; /* flag, indicates idle transmitter */ volatile int nLoanRfds; /* number of loanable RFDs left */ CACHE_FUNCS cacheFuncs; /* cache descriptor */ int intLevel; /* interrupt level # */ } DRV_CTRL;#define DRV_CTRL_SIZ sizeof(DRV_CTRL)/* hardware abstraction macros */#ifndef TEMPLATE_NETIF_READ#define TEMPLATE_NETIF_READ(pDrvCtrl, reg, result) \ ((result) = (*(pDrvCtrl->reg)))#endif /* TEMPLATE_NETIF_READ */#ifndef TEMPLATE_NETIF_WRITE#define TEMPLATE_NETIF_WRITE(pDrvCtrl, reg, data) \ ((*(pDrvCtrl->reg)) = (data))#endif /* TEMPLATE_NETIF_WRITE *//* Dummy declarations of bits in the CSR register */#define TEMPLATE_CSR_RX_PEND 0x1#define TEMPLATE_CSR_TX_PEND 0x2#define TEMPLATE_CSR_RFD_READY 0x4/* Dummy declarations of CSR commands */#define TEMPLATE_CMD_RESET 0x1#define TEMPLATE_CMD_TX_START 0x2#define TEMPLATE_CMD_RX_START 0x4/* declarations for default macro definitions */IMPORT STATUS sysIntEnable (int);IMPORT STATUS sysIntDisable (int);IMPORT STATUS sysIntAck (int);IMPORT STATUS sysTemplateAddrGet (int, void *);#ifndef TEMPLATE_INT_ENABLE /* enable this interrupt */#define TEMPLATE_INT_ENABLE(pDrv) \ sysIntEnable (pDrv->intLevel);#endif TEMPLATE_INT_ENABLE#ifndef TEMPLATE_INT_DISABLE /* disable this interrupt */#define TEMPLATE_INT_DISABLE(pDrv) \ sysIntEnable (pDrv->intLevel);#endif TEMPLATE_INT_DISABLE#ifndef TEMPLATE_INT_INIT /* initialize interrupts */#define TEMPLATE_INT_INIT(pDrv) \ /* do nothing */#endif TEMPLATE_INT_INIT#ifndef TEMPLATE_INT_ACK /* acknowledge interrupt */#define TEMPLATE_INT_ACK(pDrv) \ sysIntAck (pDrv->intLevel);#endif TEMPLATE_INT_ACK#ifndef TEMPLATE_ENET_GET /* get ethernet MAC address */#define TEMPLATE_ENET_GET(pDrvCtrl, pResult) \ *pResult = sysTemplateAddrGet (pDrvCtrl->idr.ac_if.if_unit, \ (char *)pDrvCtrl->idr.ac_enaddr);#endif TEMPLATE_ENET_GET/* local data */LOCAL DRV_CTRL drvCtrl [MAX_UNITS]; /* array of driver control structs *//* forward function declarations */IMPORT STATUS templateAttach (int unit, UCHAR* pCsr, int iLevel, char* memBase, int nTfds, int nRfds);IMPORT void templateInt (int unit);LOCAL STATUS templateInit (int unit);LOCAL void templateReset (int unit);LOCAL int templateIoctl (IDR *pIDR, int cmd, caddr_t data);LOCAL int templateOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDestAddr);LOCAL void templateTxStart (int unit);LOCAL void templateHandleRecv (DRV_CTRL *pDrvCtrl);LOCAL STATUS templateReceive (DRV_CTRL *pDrvCtrl, RFD *pRfd);LOCAL void templateLoanFree (DRV_CTRL *pDrvCtrl, RFD *pRfd);LOCAL void templateRxStart (DRV_CTRL *pDrvCtrl);LOCAL void templateTfdSend (DRV_CTRL *pDrvCtrl, TFD *pTfd);LOCAL void templateTfdStart (DRV_CTRL *pDrvCtrl);LOCAL void templateRfdReturn (DRV_CTRL *pDrvCtrl, RFD *pRfd);LOCAL RFD *templateRfdGet (DRV_CTRL *pDrvCtrl);LOCAL BOOL templateRfdReady (DRV_CTRL *pDrvCtrl);LOCAL STATUS templateDeviceStart (int unit);/********************************************************************************* templateAttach - publish the network interface and initialize the device** This routine publishes the `template' 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 <memBase> parameter is used to inform the driver about the shared* memory region. If this parameter is set to the constant "NONE," then this* routine will attempt to allocate the shared memory from the system. Any* other value for this parameter is interpreted by this routine as the address* of the shared memory region to be used.** If the caller provides the shared memory region, then the driver assumes* that this region does not require cache coherency operations, nor does it* require conversions between virtual and physical addresses.** If the caller indicates that this routine must allocate the shared memory* region, then this routine will use cacheDmaMalloc() to obtain* some non-cacheable memory. The attributes of this memory will be checked,* and if the memory is not both read and write coherent, this routine will* abort and return ERROR.** RETURNS: OK or ERROR if arguments are invalid or a hardware fault is detected.** SEE ALSO: ifLib*/STATUS templateAttach ( int unit, /* unit number */ UCHAR * pCsr, /* ptr to CSR */ int iLevel, /* interrupt level */ char * memBase, /* address of memory pool or NONE */ int nTfds, /* no. of transmit frames (0 = default) */ int nRfds /* no. of receive frames (0 = default) */ ) { DRV_CTRL *pDrvCtrl; UINT size; /* temporary size holder */ int temp; static char *errMsg1 = "\nattach: could not obtain memory\n"; /* Sanity checks */ if (unit < 0|| unit >= MAX_UNITS || pCsr == NULL) return (ERROR); /* Ensure single invocation per system life */ pDrvCtrl = & drvCtrl [unit]; if (pDrvCtrl->attached) return (OK); /* Publish the interface record */ ether_attach ( &pDrvCtrl->idr.ac_if, unit, "template", (FUNCPTR) NULL, (FUNCPTR) templateIoctl, (FUNCPTR) templateOutput, (FUNCPTR) templateReset ); size = 1024 * 16; /* TODO - calculate the total size of memory pool */ /* * Establish the memory area that we will share with the device. If * the caller has provided an area, then we assume it is non-cacheable * and will not require the use of the special cache routines. * If the caller did not provide an area, then we must obtain it from * the system, using the cache savvy allocation routine. */ switch ((int) memBase) { case NONE : /* we must obtain it */ /* * TODO - if driver needs coherent memory, test for it and * report error if not coherent. */ /* allocate memory */ pDrvCtrl->memBase = cacheDmaMalloc (size); if (pDrvCtrl->memBase == NULL) /* no memory available */ { printf (errMsg1); goto error; } pDrvCtrl->cacheFuncs = cacheDmaFuncs; break; default : /* the user provided an area */ pDrvCtrl->memBase = memBase; /* use the provided address */ pDrvCtrl->cacheFuncs = cacheNullFuncs; break; } /* TODO - Save device specific parameters */ pDrvCtrl->intLevel = iLevel; pDrvCtrl->pCsr = pCsr; /* * TODO - If needed, carve up the shared memory region into * specific sections. */ /* get our enet (MAC) addr */ TEMPLATE_ENET_GET (pDrvCtrl, &temp); if (temp == ERROR) { errnoSet (S_iosLib_INVALID_ETHERNET_ADDRESS); goto error; } /* NOTE: The BSP will connect the ISR to the interrupt vector */ /* reset chip, set flags to indicate device is active */ if (templateInit (unit) == ERROR) goto error; pDrvCtrl->attached = TRUE; pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); return (OK);error: /* TODO - Release allocated objects/memory */ return (ERROR); }/********************************************************************************* templateInit - Initialize the interface.** Initialization of interface; clear recorded pending operations.* Called by templateAttach().** RETURNS: OK or ERROR if a hardware failure is detected.*/LOCAL STATUS templateInit ( int unit /* unit number */ ) { DRV_CTRL *pDrvCtrl = & drvCtrl [unit]; pDrvCtrl->rcvHandling = FALSE; /* netTask not running our receive job */ pDrvCtrl->txCleaning = FALSE; /* netTask not running our clean job */ pDrvCtrl->txIdle = TRUE; /* transmitter idle */ /* Perform device initialization */ TEMPLATE_INT_DISABLE (pDrvCtrl); TEMPLATE_INT_INIT (pDrvCtrl); /* board specific initialization */ /* TODO - configure chip, set up MAC address, etc */ /* TODO - setup TX and RX buffer lists/queues */ /* TODO - Setup free RFD list, and loan count */ pDrvCtrl->nLoanRfds = MAX_RFDS_LOANED; /* Clear and enable interrupts */ TEMPLATE_INT_ACK (pDrvCtrl); /* to clear any pending interrupts */ TEMPLATE_INT_ENABLE (pDrvCtrl); /* Start the device */ if (templateDeviceStart (unit) == ERROR) return (ERROR); return (OK); }/********************************************************************************* templateReset - reset the ei interface** Mark interface as inactive and reset the chip. Called from the interface* layer as needed to shut down the device.** RETURNS: N/A.*/LOCAL void templateReset ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; pDrvCtrl->idr.ac_if.if_flags = 0; TEMPLATE_INT_DISABLE (pDrvCtrl); /* TODO - reset the device */ TEMPLATE_NETIF_WRITE(pDrvCtrl, pCsr, TEMPLATE_CMD_RESET); }/********************************************************************************* templateIoctl - interface ioctl procedure** Process an interface ioctl request.** RETURNS: 0 (OK) always.*/LOCAL int templateIoctl ( IDR *pIDR, int cmd, caddr_t data ) { DRV_CTRL * pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit]; int retVal = OK; int s; s = splimp (); switch (cmd) { case SIOCSIFADDR: retVal = set_if_addr (&pIDR->ac_if, data, pDrvCtrl->idr.ac_enaddr); break; case SIOCSIFFLAGS: /* Flags are set outside this module. No additional work to do. */ break; default: retVal = EINVAL; } splx (s); return (retVal); }/********************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -