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

📄 if_ex.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    int                 shMemSize;      /* size of shared memory area */    caddr_t             pShMem;         /* pointer to shared memory area */    DEV_CTRL            *pDev;          /* device address */    EX_MSG              *pH2XNext;      /* host pointer to request queue */    EX_MSG              *pX2HNext;      /* host pointer to reply queue */    /* Pointers to shared memory members.     * These are static after initialization.     */    CFG_MSG             *pCfgMsg;       /* configuration message */    STAT_ARRAY          *pStatArray;    /* EXOS writes stats here */    u_short             *pH2XHdr;       /* ptr to EXOS' host outgoing header */    u_short             *pX2HHdr;       /* ptr toEXOS' host incoming header */    EX_MSG              *pH2XQueue;     /* request msg buffers */    EX_MSG              *pX2HQueue;     /* reply msg buffers */    caddr_t             pWriteBuf;      /* pointer to write buffer */    caddr_t             pReadBuf;       /* pointer to read buffer */    } DRV_CTRL;/* Some values for the flags */#define EX_XPENDING     1                   /* xmit rqst pending on EXOS */#define EX_STATPENDING  (1<<1)              /* stats rqst pending on EXOS */#define EX_RUNNING      (1<<2)              /* board is running */#define EX_SETADDR      (1<<3)              /* physaddr has been changed *//***** GLOBALS *****//***** LOCALS *****//* The array of driver control structures, one per unit supported */LOCAL DRV_CTRL drvCtrl [MAX_UNITS];#undef EX_RESETLOCAL int EX_RESET = 0; /* because using constant causes "clr" inst. */LOCAL BOOL exBit32 = FALSE;     /* TRUE = in VME extended address space *//* * VME address space that the EXOS should use to access host buffers, etc. * This is normally standard space but can be changed through the exattach * argument (exDmaAm). */LOCAL int exBusAdrsSpace;/* forward static functions */static void exReset (int unit);static STATUS exConfig (int unit, int itype);#ifdef BSD43_DRIVERstatic void exStart (int unit);#elsestatic void exStart (DRV_CTRL *pDrvCtrl);#endifstatic void exIntr (int unit);static EX_MSG *exMsgBlkGet (DRV_CTRL *pDrvCtrl);static void exRecvAndHang (int unit, int len, int status);static void exRecv (int unit, int len, int status);static void exRxRqst (int unit);#ifdef BSD43_DRIVERstatic int exOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDest);#endifstatic int exIoctl (IDR *pIDR, int cmd, caddr_t data);static char *exHostAdrs (char *localAdrs);static void exGiveRequest (EX_MSG *pMsg, DEV_CTRL *pDev);/********************************************************************************* exattach - publish the `ex' network interface and initialize the driver and device** This routine publishes the `ex' 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 exattach    (    int unit,           /* logical number of this interface */    char *pDev,         /* bus address of EXOS device ports */    int ivec,           /* interrupt vector */    int ilevel,         /* interrupt level */    int exDmaAm,        /* VME addr modifier to access CPU memory */    int exAdrsAm        /* VME addr modifier to access EXOS ports */    )    {    int             loopy;    STATUS          ret;                /* return value of called funcs */    EX_MSG          *pMsg;    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);    /* Save some parms */    pDrvCtrl->ivec  = ivec;    pDrvCtrl->ilevel= ilevel;    /* Convert the buss address of the EXOS board's registers to the local     * address to use for the specified address space.     */    if  (        sysBusToLocalAdrs (exAdrsAm, pDev, (char **) & pDrvCtrl->pDev)        == ERROR        )        return (ERROR);    /* Publish the interface data record */#ifdef BSD43_DRIVER    ether_attach (&pDrvCtrl->idr.ac_if, unit, "ex", (FUNCPTR) NULL,                  (FUNCPTR) exIoctl, (FUNCPTR) exOutput, (FUNCPTR) exReset);#else    ether_attach (                 &pDrvCtrl->idr.ac_if,                  unit,                  "ex",                  (FUNCPTR) NULL,                 (FUNCPTR) exIoctl,                  ether_output,                  (FUNCPTR) exReset                 );    pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)exStart;#endif    /* setup address modifier */    if  (        (VME_AM_EXT_USR_DATA <= exDmaAm) &&        (exDmaAm <= VME_AM_STD_SUP_ASCENDING)        )        exBusAdrsSpace = exDmaAm;    else        exBusAdrsSpace = VME_AM_STD_SUP_DATA;    exBit32 = VME_AM_IS_EXT(exBusAdrsSpace);    { /***** Obtain memory area that will be shared with the EXOS board *****/    /* this driver can't handle incoherent caches */    if ( !CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT () )        {        printErr ( "\nex%d: requires cache coherent memory\n", unit );        return (ERROR);        }    pDrvCtrl->shMemSize =                CFG_MSG_SIZ +               /* the config message */                STAT_ARRAY_SIZ +            /* the status array */                                            /* the EXOS firmware headers */                sizeof (*pDrvCtrl->pH2XHdr) +                sizeof (*pDrvCtrl->pX2HHdr) +                (EX_MSG_SIZ * NH2X) +       /* outbound message queue */                (EX_MSG_SIZ * NX2H) +       /*  inbound message queue */                EXMAXRBUF +                 /* one packet write buffer */                EXMAXRBUF +                 /* one packet read buffer */                16;                         /* to allow alignment */    /* Attempt to get cache coherent memory */    pDrvCtrl->pShMem = cacheDmaMalloc (pDrvCtrl->shMemSize);    if ( pDrvCtrl->pShMem == NULL )        {#ifdef EX_DEBUG        printErr ( "\nex%d: no memory available\n", unit );#endif        return ( ERROR );        }    /* Clear the whole block */    bzero (pDrvCtrl->pShMem, pDrvCtrl->shMemSize);    } /* Block end */    { /***** Carve up the shared memory *****/    caddr_t pCur;                   /* pointer to current location */    pCur = pDrvCtrl->pShMem;        /* start at location assigned above */    pCur = (caddr_t) ((int)pCur + 15);   /* bump up to next 16 byte page */    pCur = (caddr_t) ((int) pCur & ~0xf);    /* This 16-byte-page aligned address is used as the base address of the     * shared memory area.  This base address is used in offset calculations     * for various values communicated to the EXOS firmware.  The config     * message starts at this base address, and can therefore be used as an     * alias.     */    pDrvCtrl->pCfgMsg = (CFG_MSG *) pCur;    pCur = (caddr_t)((int)pCur + CFG_MSG_SIZ);    pDrvCtrl->pStatArray = (STAT_ARRAY *) pCur;    pCur = (caddr_t)((int)pCur + STAT_ARRAY_SIZ);    pDrvCtrl->pH2XHdr = (u_short *) pCur;    pCur = (caddr_t)((int)pCur + sizeof (*pDrvCtrl->pH2XHdr));    pDrvCtrl->pX2HHdr = (u_short *) pCur;    pCur = (caddr_t)((int)pCur + sizeof (*pDrvCtrl->pX2HHdr));    pDrvCtrl->pH2XQueue = (EX_MSG *) pCur;    pCur = (caddr_t)((int)pCur + (EX_MSG_SIZ * NH2X));    pDrvCtrl->pX2HQueue = (EX_MSG *) pCur;    pCur = (caddr_t)((int)pCur + (EX_MSG_SIZ * NX2H));    pDrvCtrl->pWriteBuf = pCur;    pCur = (caddr_t)((int)pCur + EXMAXRBUF);    pDrvCtrl->pReadBuf = pCur;    } /* Block end */    { /***** Initialize the message queues and headers *****/    int     base;    u_short offset;    /* The offset of certain objects from a base address is a common theme     * in the shared data.  The config message happens to start at the base     * address of the shared memory region, so we cast it and store it as an     * integer once, to make the multiple uses easier to read.     */    base = (int) pDrvCtrl->pCfgMsg;    /* First the request queue (host-to-EXOS) */    pMsg = pDrvCtrl->pH2XQueue;    for ( loopy = NH2X; loopy--; )        {        /* The link is the offset of the next message from the base of         * the shared memory area.         */        offset          = (u_short) ((int)(pMsg+1) - base);        pMsg->mb_link     = offset;        pMsg->mb_rsrv     = 0;        pMsg->mb_length   = MBDATALEN;        pMsg->mb_status   = MH_HOST;            /* we own it */        pMsg->mb_next     = pMsg+1;             /* our ptr to next */        pMsg++;        }    /* Fix up the last message to point back at first message */    pMsg--;    offset = (u_short) ((int)pDrvCtrl->pH2XQueue - base);    pMsg->mb_link = offset;    pMsg->mb_next = pDrvCtrl->pH2XQueue;    /* Initialize the variables that indicate the next message.     * Ours is a direct pointer, while the EXOS firmware uses an offset.     */    *pDrvCtrl->pH2XHdr = offset;    pDrvCtrl->pH2XNext = pDrvCtrl->pH2XQueue;    /* Now the reply queue (EXOS-to-host) */    pMsg = pDrvCtrl->pX2HQueue;    for ( loopy = NX2H; loopy--; )        {        /* The link is the offset of the next message from the base of         * the shared memory area.         */        offset            = (u_short) ((int)(pMsg+1) - base);        pMsg->mb_link     = offset;        pMsg->mb_rsrv     = 0;        pMsg->mb_length   = MBDATALEN;        pMsg->mb_status   = MH_EXOS;            /* EXOS owns it */        pMsg->mb_next     = pMsg+1;             /* our ptr to next */        pMsg++;        }    /* Fix up the last message to point back at first message */    pMsg--;    offset = (u_short) ((int)pDrvCtrl->pX2HQueue - base);    pMsg->mb_link = offset;    pMsg->mb_next = pDrvCtrl->pX2HQueue;    /* Initialize the variables that indicate the next message.     * Ours is a direct pointer, while the EXOS firmware uses an offset.     */    *pDrvCtrl->pX2HHdr = offset;    pDrvCtrl->pX2HNext = pDrvCtrl->pX2HQueue;    } /* Block end */    /* Configure the board */    if (sysBus == VME_BUS)        ret = exConfig (unit, 4);              /* with vectored interrupts */    else        ret = exConfig (unit, 3);              /* with level interrupts */    if (ret != OK)        return (ERROR);    /* Connect interrupt handler, enable interrupt */    (void) intConnect (INUM_TO_IVEC (ivec), exIntr, unit);    (void) sysIntEnable (ilevel);    /* Ask the board for its physical Ethernet address.  The reply will be     * processed by the interrupt handler.  We wait for the handler to complete     * by using the ethernet address field as a sync flag: it will be zero     * until filled in by the reply processing.     */

⌨️ 快捷键说明

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