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

📄 if_ilac.c

📁 IXP425的BSP代码
💻 C
字号:
/* if_ilac.c - AMD 79C900 ILACC Ethernet network interface driver *//* Copyright 1989-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01e,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler01d,07apr97,spm  code cleanup and upgraded to BSD 4.401c,25nov96,dat  coding standards, documentation01b,09jan95,caf  added intConnect() call to ilacattach().01a,02jan95,kat  written.*//*DESCRIPTION:*//* includes */#include "vxWorks.h"#include "net/mbuf.h"#include "net/protosw.h"#include "sys/ioctl.h"#include "sys/socket.h"#include "errnoLib.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "etherLib.h"#include "vme.h"#include "iv.h"#include "iosLib.h"#include "ioLib.h"#include "memLib.h"#include "net/systm.h"#include "net/if_subr.h"#include "sysLib.h"#include "vxLib.h"#include "stdio.h"#include "intLib.h"#include "logLib.h"#include "string.h"#include "netLib.h"#include "stdlib.h"#include "drv/netif/if_ilac.h"#define MINPKTSIZE   60typedef struct /* SHIFT_BUFFER */    {     char     dummy_space[16];     TM_DESC  shift_tring[XMIT_DES_CNT];     char     shift_xmit_buf[XMIT_DES_CNT * ROUND_BUF_SIZE];     RM_DESC  shift_rring[RECV_DES_CNT];     char     shift_recv_buf[RECV_DES_CNT * ROUND_BUF_SIZE];     INIT_BLK shift_init_blk;    } SHIFT_BUFFER;LOCAL SHIFT_BUFFER shift_buffer;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;IMPORT unsigned char ilacEnetAddr[6];typedef struct /* DRV_CTRL */    {    IDR           idr;          /* interface data record */    int           unit;         /* which unit are we */    ILAC_DEVICE  *addr;        	/* address of physical device */    int           recvIndex;    /* next receive buffer */    int           xmitIndex;    /* next transmit buffer */    TM_DESC      *tranRing;	/* transmit message descriptors */    RM_DESC      *recvRing;	/* receive message descriptors */    INIT_BLK     *initBlk;	/* initialization block */    char         *xmitBuf;	/* transmit buffers */    char         *recvBuf;	/* receive buffers */    volatile BOOL rcvHandling;  /* flag, indicates netTask active */    BOOL          attached;     /* TRUE if attach() has succeeded */    } DRV_CTRL;LOCAL DRV_CTRL drvCtrl[1];LOCAL STATUS ilacInit(int unit, char *eaddr);LOCAL void   ilacInt(int unit);/* ether_attach functions */LOCAL int    ilacIoctl(IDR *pIDR, int cmd, caddr_t data);#ifdef BSD43_DRIVERLOCAL STATUS ilacOutput(IDR *pIDR, MBUF *pMbuf, SOCK *pDest);#endifLOCAL STATUS ilacReset(int unit);LOCAL void   ilacHandleRecvInt (DRV_CTRL *pDrv);#ifdef BSD43_DRIVERLOCAL void   ilacTxStartup(int unit);#elseLOCAL void   ilacTxStartup (DRV_CTRL *pDrv);#endifLOCAL STATUS ilacReceive(DRV_CTRL *pDrv, unsigned char *buf, int *len);LOCAL STATUS ilacTransmit(DRV_CTRL *pDrv, unsigned char *buf, int len);/********************************************************************************* ilacattach - attach ilac driver network system** RETURNS:*/STATUS ilacattach    (    int unit,    char *addrs,    int ivec    )    {    DRV_CTRL *pDrv = &drvCtrl[unit];        if (pDrv->attached)	{        return OK;	}#ifdef BSD43_DRIVER    ether_attach(&pDrv->idr.ac_if, unit, "ilac", (FUNCPTR) NULL,		 (FUNCPTR) ilacIoctl, (FUNCPTR) ilacOutput,		 (FUNCPTR) ilacReset);#else    ether_attach (                 &pDrv->idr.ac_if,                  unit,                  "ilac",                  (FUNCPTR) NULL,		 (FUNCPTR) ilacIoctl,                  (FUNCPTR) ether_output,                 (FUNCPTR) ilacReset                 );    pDrv->idr.ac_if.if_start = (FUNCPTR)ilacTxStartup;#endif    pDrv->addr = (ILAC_DEVICE *)addrs;    /* connect the interrupt handler */    (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec),                       (VOIDFUNCPTR)ilacInt, NULL);    ilacInit(unit, (char *)pDrv->idr.ac_enaddr);        pDrv->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    pDrv->rcvHandling = FALSE;    /* Set our success indicator */    pDrv->attached = TRUE;    return OK;    }/********************************************************************************* ilacInit - initialize an ILAC device ** RETURNS:*/LOCAL STATUS ilacInit    (    int unit,    char *ethernet_num    )    {     int          i;    unsigned int csr0;     unsigned int count;     DRV_CTRL    *pDrv = &drvCtrl[unit];    ILAC_DEVICE *ilac = pDrv->addr;        /* Set init bit in CSR0 register */    ilac->rap = 0;    ilac->rdp = CSR0_STOP;        pDrv->tranRing =	(TM_DESC *) (((unsigned int)&shift_buffer.shift_tring[0]) & 0xFFFFFFF0);    pDrv->recvRing =	(RM_DESC *) (((unsigned int)&shift_buffer.shift_rring[0]) & 0xFFFFFFF0);    pDrv->xmitBuf =	(char *) (((unsigned int)&shift_buffer.shift_xmit_buf[0]) & 0xFFFFFFF0);    pDrv->recvBuf =	(char *) (((unsigned int)&shift_buffer.shift_recv_buf[0]) & 0xFFFFFFF0);    pDrv->initBlk =	(INIT_BLK *)(((unsigned int)&shift_buffer.shift_init_blk) & 0xFFFFFFF0);        /* Setup the transmit descriptors */     for(i = 0; i < XMIT_DES_CNT; i++)	{	pDrv->tranRing[i].addr =			(unsigned long)&pDrv->xmitBuf[i * ROUND_BUF_SIZE];	pDrv->tranRing[i].error = 0;	pDrv->tranRing[i].status = (TST_STP | TST_ENP);	}    /* Setup the receive descriptors */     for(i = 0; i < RECV_DES_CNT; i++)	{	pDrv->recvRing[i].addr = 			(unsigned long)&pDrv->recvBuf[i * ROUND_BUF_SIZE];	pDrv->recvRing[i].bcnt = -(ROUND_BUF_SIZE);	pDrv->recvRing[i].mcnt = 0;	pDrv->recvRing[i].flags = RFLG_OWN; /* give buffer to ilac */	}    /* set up ilac init block */    pDrv->initBlk->mode = 0; /* IBM_PROM; 0 */    pDrv->initBlk->rlen = L2RECV_DES_CNT;        /* Set the receive descriptor ring address */    pDrv->initBlk->rdra = (unsigned long)pDrv->recvRing;        /* Set the transmit descriptor ring length */    pDrv->initBlk->tlen = L2XMIT_DES_CNT;    /* Set the tranmit descriptor ring address */    pDrv->initBlk->tdra = (unsigned long)pDrv->tranRing;        /* grab the hardware enet address */    for (i = 0; i < 6; i++)	{	ethernet_num[i] = ilacEnetAddr[i];	}     pDrv->initBlk->padr[3] = ethernet_num[0];    pDrv->initBlk->padr[2] = ethernet_num[1];    pDrv->initBlk->padr[1] = ethernet_num[2];    pDrv->initBlk->padr[0] = ethernet_num[3];    pDrv->initBlk->padr[7] = ethernet_num[4];    pDrv->initBlk->padr[6] = ethernet_num[5];    /* CSR4 controls selected diagnostic functions, microprocessor bus  */    /* acquisition and DMA signaling */    ilac->rap = 4;    ilac->rdp = CSR4_BACON_68K | CSR4_TXSTRTM | CSR4_LBDM;    ilac->rap = 3;    ilac->rdp = CSR3_ACON | CSR3_IDONM | CSR3_TINTM;     /* CSR2 must contain the high order 16 bits of the first word in */    /* the initialization block */    ilac->rap = 2;    ilac->rdp = (((int)pDrv->initBlk & 0xff0000) >> 16);        /* CSR1 must contain the low order 16 bits of the first word in */    /* the initialization block */    ilac->rap = 1;    ilac->rdp = ((int)pDrv->initBlk & 0xffff);        ilac->rap = 0;    ilac->rdp = CSR0_INIT | CSR0_INEA;        count = 0;      while (!((csr0 = ilac->rdp) & CSR0_IDON) && count < INIT_TMO)	{	count++;	}    if (count >= INIT_TMO)	{	printf ("ilac: INIT timeout: CSR0 = 0x%x\n", (unsigned short)csr0);	return ERROR;	}    else	{	count = 0;	ilac->rdp = CSR0_STRT | CSR0_INEA;	while (!((csr0 = ilac->rdp) & (CSR0_RXON | CSR0_TXON)) &&		count < STRT_TMO)	    {	    count++;	    }	if (count >= STRT_TMO)	    {	    printf ("ilac: STRT timeout: CSR0 = 0x%x\n", (unsigned short)csr0);	    return ERROR;	    }	}        pDrv->recvIndex = 0;     pDrv->xmitIndex = 0;        return OK;    }/********************************************************************************* ilacInt - ILAC interrupt service routine** RETURNS:*/LOCAL void ilacInt    (    int unit    )    {    int       status;    DRV_CTRL *pDrv = (DRV_CTRL *)&drvCtrl[0];    /* get csr0 */    pDrv->addr->rap = 0;    status = pDrv->addr->rdp;        /* ack interrupt and reenable */    pDrv->addr->rap = 0;    pDrv->addr->rdp = CSR0_ACKINT | CSR0_INEA;        if (status & CSR0_RINT)	/* handle receive interrput */	{	if (!(pDrv->rcvHandling))	    {            pDrv->rcvHandling = TRUE;            netJobAdd ( (FUNCPTR)ilacHandleRecvInt, (int)pDrv, 0, 0, 0, 0);	    }	}    else	{	logMsg("ilac0: got unexpected interrupt: 0x%4x\n", status,		0, 0, 0, 0, 0);	}    }/********************************************************************************* ilacIoctl - ILAC control functions** RETURNS:*/LOCAL int ilacIoctl    (    IDR *pIDR,    int cmd,    caddr_t data    )    {    STATUS error = OK;        switch (cmd)	{        case SIOCSIFADDR:           ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;            arpwhohas (pIDR, &IA_SIN (data)->sin_addr);            break;	            case SIOCSIFFLAGS:            break;        default:            error = EINVAL;	}        return error;    }#ifdef BSD43_DRIVER/********************************************************************************* ilacOutput - packet transmit routine** RETURNS:*/LOCAL STATUS ilacOutput    (    IDR *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    return ether_output ((IFNET *)pIDR, pMbuf, pDest, (FUNCPTR) ilacTxStartup,			pIDR);    }#endif/********************************************************************************* ilacReset - ILAC reset device routine*** RETURNS:*/LOCAL STATUS ilacReset    (    int unit    )    {    logMsg ("ilac%d: reset called", unit, 0, 0, 0, 0, 0);        return OK;    }/********************************************************************************* ilacHandleRecvInt - task level portion of packet receive** RETURNS:*/LOCAL void ilacHandleRecvInt    (    DRV_CTRL *pDrv    )    {    MBUF * 		pMbuf;    int 		length;    unsigned char 	packet[ROUND_BUF_SIZE];    ETH_HDR * 		pEh;    unsigned char * 	pData;#ifdef BSD43_DRIVER    unsigned short 	type;#endif    pDrv->rcvHandling = TRUE;    while (ilacReceive (pDrv, packet, &length) != ERROR)	{	++pDrv->idr.ac_if.if_ipackets;	pEh = (ETH_HDR *)packet;		if ( (etherInputHookRtn != NULL) &&	     (*etherInputHookRtn) (&pDrv->idr, (char *)pEh, length))            continue;	        length -= sizeof (ETH_HDR);	pData = (unsigned char *) (packet + sizeof (ETH_HDR));#ifdef BSD43_DRIVER        type = ntohs (pEh->ether_type);#endif        pMbuf = copy_to_mbufs (pData, length, 0, &pDrv->idr);        if (pMbuf != NULL)#ifdef BSD43_DRIVER            do_protocol_with_type(type, pMbuf, &pDrv->idr, length);#else            do_protocol (pEh, pMbuf, &pDrv->idr, length);#endif        }    pDrv->rcvHandling = FALSE;     }/********************************************************************************* ilacTxStartup - startup transmitter*** RETURNS:*/#ifdef BSD43_DRIVERLOCAL void ilacTxStartup    (    int unit    )    {    DRV_CTRL     *pDrv = &drvCtrl[unit];#elseLOCAL void ilacTxStartup    (    DRV_CTRL     *pDrv    )    {#endif    MBUF         *pMbuf;    int           length;    unsigned char packet[ROUND_BUF_SIZE];    STATUS result;    /*     * Loop until there are no more packets ready to send or we     * have insufficient resources left to send another one.     */        while (pDrv->idr.ac_if.if_snd.ifq_head)	{        IF_DEQUEUE (&pDrv->idr.ac_if.if_snd, pMbuf);  /* dequeue a packet */        copy_from_mbufs ( (ETH_HDR *)packet, pMbuf, length);        if ( (etherOutputHookRtn != NULL) &&             (*etherOutputHookRtn) (&pDrv->idr, (ETH_HDR *)packet, length))            continue;	        result = ilacTransmit (pDrv, packet, length);        if (result == ERROR)            pDrv->idr.ac_if.if_oerrors++;#ifndef BSD43_DRIVER    /* BSD 4.4 ether_output doesn't bump statistic. */        else            pDrv->idr.ac_if.if_opackets++; #endif	}    }/********************************************************************************* ilacReceive - receive packet*** RETURNS:*/LOCAL STATUS ilacReceive    (    DRV_CTRL *pDrv,    unsigned char *packet,    int *len    )    {    RM_DESC      *rmd = (RM_DESC *)&pDrv->recvRing[pDrv->recvIndex];         if (rmd->flags & RFLG_OWN)	{	return ERROR;	}     if (rmd->flags & RFLG_ERR)	{ 	pDrv->recvIndex++; 	pDrv->recvIndex %= RECV_DES_CNT;		rmd->flags |= RFLG_OWN;		logMsg("ilac0: recv ERROR: 0x%x\n", rmd->flags, 0, 0, 0, 0, 0); 	return ERROR;  	}        *len = rmd->mcnt;         bcopy((char *)rmd->addr, (char *)packet, *len);    pDrv->recvIndex++;     pDrv->recvIndex %= RECV_DES_CNT;    /* ilac can have this buffer back again */    rmd->mcnt = 0;     rmd->flags |= RFLG_OWN;        return OK;    } /********************************************************************************* ilacTransmit - actual packet transmission*** RETURNS:*/LOCAL STATUS ilacTransmit    (    DRV_CTRL *pDrv,    unsigned char *packet,    int len    )    {    unsigned int   count;    unsigned char  status;        TM_DESC *tmd;    tmd = (TM_DESC *)&pDrv->tranRing[pDrv->xmitIndex]; 	        bcopy ((const char *)packet, (char *)tmd->addr, len);        len = (len < MINPKTSIZE) ? MINPKTSIZE : len;    tmd->bcnt = TBCNT_ONES | -(len);    tmd->error = 0;    tmd->status = TST_XMIT;        count = 0;    while ( (status = tmd->status) & TST_OWN)	if (count++ > XMIT_TMO)	    return ERROR;    if (status & TST_ERR)	{	pDrv->xmitIndex++; 	pDrv->xmitIndex %= XMIT_DES_CNT;		if ( (tmd->error << 10) & TERR_LCAR)	    logMsg ("ilac%d: lost carrier\n", pDrv->idr.ac_if.if_unit,		    0, 0, 0, 0, 0);	else	    logMsg ("ilac%d: ERROR = 0x%x\n", pDrv->idr.ac_if.if_unit,		    tmd->error, 0, 0, 0, 0); 	return ERROR;	}    pDrv->xmitIndex++;     pDrv->xmitIndex %= XMIT_DES_CNT;    return OK;    }

⌨️ 快捷键说明

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