⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_nic.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* if_nic.c - National Semiconductor SNIC Chip (for HKV30) network interface driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02b,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler02a,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.401z,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h01y,19feb93,jdi  documentation cleanup.01x,15oct92,rfs  Added documentation.01w,02oct92,rfs  Made multiple attach calls per unit return OK.01v,09sep92,gae  documentation tweaks.01u,02sep92,ajm  added conditional compilation for __STDC__ (DEC)01t,18aug92,rfs  Revised to follow style of other drivers.                 Added cache support.  Reworked OVW error recovery.01s,23jun92,ajm  fixed ansi warnings for pktBufRead calls                 went back and fixed all 68k ansi warnings01r,26may92,rrr  the tree shuffle                 -changed includes to have absolute path from h/01q,26may92,ajm  got rid of HOST_DEC def's (new compiler)                 updated copyright01p,10oct91,rfs  modified pktBufRead() & pktBufWrite() to return if len is zero01o,04oct91,rrr  passed through the ansification filter                 -changed functions to ansi style                 -changed includes to have absolute path from h/                 -changed VOID to void                 -changed copyright notice01n,28sep91,ajm  ifdef'd HOST_DEC for compiler problem01m,02Aug91,rfs  cleanup of transmit design, int handler, NIC command register                 was being handled incorrectly, DMA operations required                 semaphoring and error checking, changed names, deleted                 nicdelay(), deleted excessive include files. Provided correct                 OVW recovery.  Your basic rewrite.01l,01may91,elh  fixed transmit buffering problems, added changes from                 heurikon, removed DMAState, XmtByteCount.01k,20sep90,dab  made nicInit() return int.01j,10aug90,dnw  added forward declarations of void routines.                 added include of if_subr.h.01i,11jul90,hjb  removed code that uses gotIp.  made nicRead() a void function.                 changed references to do_protocol() to use                 do_protocol_with_type().01h,19apr90,hjb  deleted param.h, de-linted.01g,18mar90,hjb  reduction of redundant code and addition of cluster support.                 added error recording (TXE, RXE), removed unnecessary                 error handler which didn't do anything.  delinted.01f,18sep89,cwp  added multiple transmit buffer support01e,14sep89,dab  changed iv68k.h to iv.h.01d,15jun89,cwp  fixed ring buffer overflow and transmit errors.01c,04apr89,cwp  first working version.01b,25feb89,cwp  added changes from unix driver.01a,12jan89,cwp  written.*//*This module implements the National Semiconductor 83901 SNIC Ethernet network interface driver.This driver is non-generic and is for use on the Heurikon HKV30 board.  Only unit number zero is supported.  The driver must be given several target-specific parameters.  These parameters, and the mechanisms used to communicate them to the driver, are detailed below.BOARD LAYOUTThis device is on-board.  No jumpering diagram is necessary.EXTERNAL INTERFACEThis driver provides the standard external interface with the followingexceptions.  All initialization is performed within the attach routine; thereis no separate initialization routine.  Therefore, in the global interfacestructure, the function pointer to the initialization routine is NULL.The only user-callable routine is nicattach(), which publishes the `nic'interface and initializes the driver and device.TARGET-SPECIFIC PARAMETERS.iP "device I/O address"This parameter is passed to the driver by nicattach().It specifies the base address of the device's I/O registerset..iP "interrupt vector"This parameter is passed to the driver by nicattach().It specifies the interrupt vector to be used by the driverto service an interrupt from the SNIC device.  The driver will connectthe interrupt handler to this vector by calling intConnect()..LPSYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources:    - one mutual exclusion semaphore    - one interrupt vector    - 0 bytes in the initialized data section (data)    - 1702 bytes in the uninitialized data section (BSS)The above data and BSS requirements are for the MC68020 architecture and may vary for other architectures.  Code size (text) varies greatly betweenarchitectures and is therefore not quoted here.The HKV30 provides a private buffer for all packets transmitted and received.Thus, the driver does not require any system memory to share with thedevice.  This also eliminates all data cache coherency issues.SEE ALSO: ifLib*/#include "vxWorks.h"#include "iv.h"#include "stdlib.h"#include "intLib.h"#include "netLib.h"#include "net/mbuf.h"#include "sys/ioctl.h"#include "errno.h"#include "net/if.h"#include "net/unixLib.h"#include "net/if_subr.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "etherLib.h"#include "semLib.h"#include "cacheLib.h"#include "drv/netif/if_nic.h"#include "drv/dma/we32104.h"/***** LOCAL DEFINITIONS *****/#define MAX_UNITS      1                     /* max number of units supported */#define NIC_DCR_CS      DCR_CS_2                /* device #2 on DMAC PBUS */#define NIC_DCR_PA      0x60                    /* device addr on DMAC PBUS *//* 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 ether_header ETH_HDR;#ifdef BSD43_DRIVER#define ENET_HDR_REAL_SIZ   14#endiftypedef struct rx_hdr    {    u_char status;                              /* status of packet */    u_char nextRxPage;                          /* page next pkt starts at */    u_char cntL;                                /* low byte of frame length */    u_char cntH;                                /* high byte of frame length */    } RX_HDR;#define RX_HDR_SIZ      sizeof(RX_HDR)typedef struct rx_frame    {    RX_HDR rxHdr;                               /* the receive status header */    ETH_HDR enetHdr;                            /* the Ethernet header */    u_char data [ETHERMTU];                     /* the data */    u_long fcs;    } RX_FRAME;#define RX_FRAME_SIZ        sizeof(RX_FRAME)typedef struct tx_desc    {    volatile BOOL ready;                        /* ready for transmission */    unsigned short addr;                        /* addr in NIC buffer */    unsigned short len;                         /* length of packet */    struct tx_desc *next;                       /* link to next descriptor */    } TX_DESC;#define TX_DESC_SIZ     sizeof(TX_DESC)/* The driver control structure. */typedef struct drv_ctrl    {    IDR                 idr;                /* interface data record */    BOOL                attached;           /* indicates unit is attached */    int                 nicIntVec;          /* interrupt vector */    SEM_ID              dmaSem;             /* exclusive use of DMA units */    u_char              NextPkt;            /* NIC buf page for next pkt */    volatile BOOL       dmaWait;            /* waiting for DMA completion */    volatile BOOL       taskRcvActive;      /* indicates netTask in use */    NIC_DEVICE          *nicAddr;           /* address of NIC chip */    volatile TX_DESC    *pTxActive;         /* ptr to Tx desc in use */    TX_DESC             *pTxNext;           /* ptr to next Tx desc to use */    TX_DESC             txDesc [MAXXMT];    /* array of Tx descriptors */    RX_FRAME            rxFrame;            /* storage for one Rx frame */    } DRV_CTRL;#define DRV_CTRL_SIZ       sizeof(DRV_CTRL)/* array of driver control structs, one per unit supported */LOCAL DRV_CTRL drvCtrl [MAX_UNITS];/* forward static functions */static void nicReset (int unit);static void nicIntr (int unit);static void nicRestart (int unit);static void nicHandleInt (DRV_CTRL *pDrvCtrl);static BOOL nicRead (DRV_CTRL *pDrvCtrl);#ifdef BSD43_DRIVERstatic int nicOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDest);#elsestatic int nicTxStartup (DRV_CTRL *pDrvCtrl);#endifstatic int nicIoctl (IDR *pIDR, int cmd, caddr_t data);static void nicEnetAddrGet (int unit);static void nicConfig (int unit);static STATUS pktBufWrite (DRV_CTRL *pDrvCtrl, u_long nicBufAddr,                           u_long len, char *pData);static STATUS pktBufRead (DRV_CTRL *pDrvCtrl, u_long nicBufAddr,                          u_long len, char *pData);#ifdef BSD43_DRIVERstatic BOOL convertDestAddr (IDR *pIDR, SOCK *pDestSktAddr,                             char *pDestEnetAddr, u_short *pPacketType,                             MBUF *pMbuf);#endif/********************************************************************************* nicattach - publish the `nic' network interface and initialize the driver and device** This routine publishes the `nic' interface by filling in a network interface* record and adding this record to the system list.  It also* initializes the driver and the device to the operational state.** RETURNS: OK or ERROR.*/STATUS nicattach    (    int unit,                                 /* unit number */    NIC_DEVICE *pNic,                         /* address of NIC chip */    int ivec                                  /* interrupt vector to use */    )    {    int         temp;    int         loopy;    WE32104     *pDmac;    DRV_CTRL    *pDrvCtrl;    /* Sanity check the unit number */    if (unit < 0 || unit >= MAX_UNITS)        return (ERROR);    /* Ensure single invocation per system life */    pDrvCtrl = & drvCtrl [unit];    if (pDrvCtrl->attached)        return (OK);    pDrvCtrl->dmaSem = semBCreate(SEM_Q_FIFO, SEM_FULL);    pDrvCtrl->nicAddr = pNic;    pDrvCtrl->nicIntVec = ivec;    /* Publish the interface data record */#ifdef BSD43_DRIVER    ether_attach    (                    &pDrvCtrl->idr.ac_if,                    unit,                    "nic",                    (FUNCPTR) NULL,                    (FUNCPTR) nicIoctl,                    (FUNCPTR) nicOutput,                    (FUNCPTR) nicReset                    );#else    ether_attach (                 &pDrvCtrl->idr.ac_if,                 unit,                 "nic",                 (FUNCPTR) NULL,                 (FUNCPTR) nicIoctl,                 (FUNCPTR) ether_output,                  (FUNCPTR) nicReset                 );    pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)nicTxStartup;#endif    /*     * Fill in the Tx descriptors.     * Note that the address in the NIC buffer must be on a 256 byte boundary,     * since only the upper 8 bits are fed to the device when telling it     * to transmit.     */    for (loopy = 0; loopy < MAXXMT; loopy++)        {        /* addr in NIC buf */        pDrvCtrl->txDesc[loopy].addr = XMTBUF + (loopy * 0x600);        /* point to next */        pDrvCtrl->txDesc[loopy].next = & pDrvCtrl->txDesc [loopy+1];        pDrvCtrl->txDesc[loopy].ready = FALSE;        }    pDrvCtrl->txDesc[MAXXMT-1].next = pDrvCtrl->txDesc;    /* point to first */    /* Connect the interrupt handler */    (void) intConnect (INUM_TO_IVEC (ivec), nicIntr, 0);    pDrvCtrl->pTxNext = pDrvCtrl->txDesc;          /* reset "next Tx" ptr */    pDrvCtrl->pTxActive = NULL;                    /* no active Tx desc */    pDrvCtrl->taskRcvActive = FALSE;               /* reset flag */    pDrvCtrl->NextPkt = CURR;                      /* reset to initial value */    /* The WE32104 controls all access to the peripheral buss. It allows the     * CPU "transparent" access to the devices on that buss. Before this     * access is allowed, the WE32104 must be told device control info. The     * following line sets up the channel 2 device control register to     * correctly access the NIC. These values are obtained from the HKV30     * manual.     */    pDmac = (WE32104 *) DMA_BASE;    pDmac->Ch2.DevControl = NIC_DCR_CS | NIC_DCR_PA;    pDmac->Mask = pDmac->Mask & ~MASK_CH2;      /* allow channel 2 requests */    temp = RESET_ON;                            /* Issue a hardware reset */    temp = RESET_OFF;                           /* release the reset */    temp = LED_OFF;                             /* the 'U' LED on XE module */    while (!(pNic->Isr & RST))                  /* wait for reset done */        ;    nicConfig (unit);                              /* configure the device */    /* Raise the interface flags */    pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    /* Set our flag */    pDrvCtrl->attached = TRUE;    temp = LED_ON;                      /* turn XE module LED on */    return (OK);    }/********************************************************************************* nicReset - reset of interface*/LOCAL void nicReset    (    int unit    )    {    int         temp;    DRV_CTRL    *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    pDrvCtrl->idr.ac_if.if_flags = 0;    temp = RESET_ON;                            /* Issue a hardware reset */    temp = LED_OFF;                             /* the 'U' LED on XE module */    }/********************************************************************************* nicIntr - The driver's interrupt handler** This function clears the cause of the device interrupt(s) and then acts* on the individual possible causes.  The primary goal of this routine is to* minimize the time spent in it.  This is accomplished by deferring processing* to the netTask via the netJobAdd() function.** A secondary goal is to keep the transmitter working, if there are more* frames ready to be sent.  This is done examining flags set by the task level* code that indicates ready frames.  The transmitter is flagged as "idle" if* it appears that there are no frames ready to send.** Note that in case the receiver overruns, we promptly mark the interface as* "down" and then leave only the RDC interrupt enabled.  This is in case netTask* is in the midst of DMA activity, we must allow it to complete.  The receive* handler will give up when it discovers the interface is down, which will* then allow netTask to run our OVW handler.  This provides a nice orderly* error recovery, even though the crummy NIC requires complete re-init.*/LOCAL void nicIntr    (    int unit    )    {    DRV_CTRL *pDrvCtrl;    NIC_DEVICE *pNic;    TX_DESC *pTxDesc;    unsigned char isr;                            /* copy of ISR */    unsigned char tsr;                            /* copy of TSR */    pDrvCtrl = & drvCtrl [unit];    pNic = pDrvCtrl->nicAddr;    isr = pNic->Isr;                              /* copy the ISR */    pNic->Isr = isr;                              /* ACK all the ints */    /* handle receiver overrun */    if  (        (isr & OVW) &&        (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING))        )        {        pNic->Imr = RDCE;                       /* disable all but RDC intrs */        pDrvCtrl->idr.ac_if.if_flags &=                 /* flag as down */            ~(IFF_UP | IFF_RUNNING | IFF_PROMISC);        /* Place our restart routine on the netTask queue */        netJobAdd ((FUNCPTR) nicRestart, unit, 0, 0, 0, 0);        return;                     /* no sense continuing */        }    /* handle packet Tx error */    if (isr & TXE)        {        pDrvCtrl->idr.ac_if.if_opackets--;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -