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

📄 ax88796end.c

📁 操作系统vxworks
💻 C
📖 第 1 页 / 共 5 页
字号:
* ax88796EndLoad - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device specific parameters are passed in the initString.
*
* The string contains the target specific parameters like this:
*
* "unit:register addr:int vector:int level:shmem addr:shmem size:shmem width"
*
* RETURNS: An END object pointer or NULL on error.
*/

END_OBJ* ax88796EndLoad
    (
    char* initString,		/* String to be parsed by the driver. */
    void* pBSP			/* for BSP group */
    )
    {
    AX88796END_DEVICE 	*pDrvCtrl;

#ifdef DEBUG
    printf ("ax88796EndLoad(%s)\n", initString);
    printf ("\tinitString '%s'\n", initString ? initString : "");
    printf ("\tpBSP       '%s'\n", pBSP ? pBSP : "");
#endif
    if (initString == NULL)
        return (NULL);

    if (initString[0] == '\0')
        {
        bcopy((char *)AX88796_DEV_NAME, initString, AX88796_DEV_NAME_LEN);
        return (NULL);
        }

    /* allocate the device structure */

    pDrvCtrl = (AX88796END_DEVICE *) calloc (sizeof(AX88796END_DEVICE), 1);
    if (pDrvCtrl == NULL)
	goto errorExit;

    /* parse the init string, filling in the device structure */

    if (ax88796Parse (pDrvCtrl, initString) == ERROR)
	goto errorExit;
	
    /* stop device */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
    
    /* select 8 bit width */
    
    SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BUS_8);

    /* Ask the BSP to provide the ethernet address. */

    SYS_ENET_ADDR_GET (pDrvCtrl);

    /* initialize the END parts of the structure */

    if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, AX88796_DEV_NAME,
		      pDrvCtrl->unit, &ax88796FuncTable,
		      "ax88796 Enhanced Network Driver") == ERROR)
	goto errorExit;

    /* initialize the MIB2 parts of the structure */

    if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
		      &pDrvCtrl->enetAddr[0], 6, ETHERMTU,
                      END_SPEED) == ERROR)
	goto errorExit;

    /* Perform memory allocation/distribution */

    if (ax88796MemInit (pDrvCtrl) == ERROR)
	goto errorExit;

    /* set the flags to indicate readiness */

    END_OBJ_READY (&pDrvCtrl->endObj,
		    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);

    return (&pDrvCtrl->endObj);

errorExit:
    if (pDrvCtrl != NULL)
	free ((char *)pDrvCtrl);

    return (NULL);
    }

/******************************************************************************
*
* ax88796Parse - parse the init string
*
* Parse the input string.  Fill in values in the driver control structure.
*
* The initialization string format is:
* .CS
*   "unit:adrs:vecnum:intLvl:byteAccess:usePromEnetAddr:offset"
* .CE
*
* .IP <unit>
* Device unit number, a small integer.
* .IP <adrs>
* Base address
* .IP <vecNum>
* Interrupt vector number (used with sysIntConnect)
* .IP <intLvl>
* Interrupt level (used with sysLanIntEnable)
* .IP <byteAccess>
* Use 8-bit access mode.
* .IP <usePromEnetAddr>
* get ethernet address from PROM.
* .IP <offset>
* offset for memory alignment
* Set Configuration Register A. Defaults to reset value. 
* .IP <configRegA>
* Set Configuration Register B. Defaults to reset value. 
* .IP <configRegB>
* .LP
*
* RETURNS: OK or ERROR for invalid arguments.
*/

LOCAL STATUS ax88796Parse
    (
    AX88796END_DEVICE * pDrvCtrl,
    char * initString
    )
    {
    char*	tok;
    char*	holder = NULL;

    /* Parse the initString */

    /* Unit number. */

    tok = strtok_r (initString, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->unit = atoi (tok);

    /* Base address. */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->base = strtoul (tok, NULL, 16);

    /* Interrupt vector. */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->ivec = strtoul (tok, NULL, 16);

    /* Interrupt level. */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->ilevel = strtoul (tok, NULL, 16);

    /* 8-bit access. */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->byteAccess = atoi (tok);

    /* ethernet address from PROM. */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->usePromEnetAddr = atoi (tok);

    /* memory alignment offset */

    tok = strtok_r (NULL, ":", &holder);
    if (tok == NULL)
	return (ERROR);
    pDrvCtrl->offset = strtoul (tok, NULL, 16);

    return (OK);
    }

/*******************************************************************************
*
* ax88796MemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS ax88796MemInit
    (
    AX88796END_DEVICE * pDrvCtrl	/* device to be initialized */
    )
    {
    M_CL_CONFIG	eneMclBlkConfig;
    CL_DESC	clDesc;                      /* cluster description */

    bzero ((char *)&eneMclBlkConfig, sizeof(eneMclBlkConfig));
    bzero ((char *)&clDesc, sizeof(clDesc));

    clDesc.clNum   = 64;
    clDesc.clSize  = AX88796_BUFSIZ;	/* allow for alignment */
    clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 8)) + 4);

    eneMclBlkConfig.mBlkNum  = 16 * 8;
    eneMclBlkConfig.clBlkNum = clDesc.clNum;

    /*
     * mBlk and cluster configuration memory size initialization
     * memory size adjusted to hold the netPool pointer at the head.
     */
    eneMclBlkConfig.memSize =
      (eneMclBlkConfig.mBlkNum * (MSIZE + sizeof (long)))
      + (eneMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));
    eneMclBlkConfig.memArea = (char *) memalign(sizeof (long),
						eneMclBlkConfig.memSize);
    if (eneMclBlkConfig.memArea == NULL)
        return (ERROR);

    clDesc.memArea = (char *) malloc (clDesc.memSize);
    if (clDesc.memArea == NULL)
	return (ERROR);

    pDrvCtrl->endObj.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL));
    if (pDrvCtrl->endObj.pNetPool == NULL)
        return (ERROR);

    /* Initialize the net buffer pool with transmit buffers */
    if (netPoolInit (pDrvCtrl->endObj.pNetPool, &eneMclBlkConfig,
                     &clDesc, 1, NULL) == ERROR)
        return (ERROR);

    /* Save the cluster pool id */
    pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
				      AX88796_BUFSIZ, FALSE);

    return (OK);
    }

/*******************************************************************************
*
* ax88796Ioctl - the driver I/O control routine
*
* Process an ioctl request.
*/

LOCAL int ax88796Ioctl
    (
    void*	pCookie,	/* device ptr */
    int		cmd,
    caddr_t	data
    )
    {
    int error = 0;
    long value;
    AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;

    switch ((UINT) cmd)
        {
        case EIOCSADDR:
	    if (data == NULL)
		return (EINVAL);
            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
		   END_HADDR_LEN(&pDrvCtrl->endObj));
            break;

        case EIOCGADDR:
	    if (data == NULL)
		return (EINVAL);
            bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,
		   END_HADDR_LEN(&pDrvCtrl->endObj));
            break;

        case EIOCSFLAGS:
	    value = (long)data;
	    if (value < 0)
		{
		value = -value;
		value--;
		END_FLAGS_CLR (&pDrvCtrl->endObj, value);
		}
	    else
		END_FLAGS_SET (&pDrvCtrl->endObj, value);

	    ax88796Config (pDrvCtrl, TRUE);
            break;

        case EIOCGFLAGS:
	    *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
            break;

	case EIOCPOLLSTART:
	    ax88796PollStart (pDrvCtrl);
	    break;

	case EIOCPOLLSTOP:
	    ax88796PollStop (pDrvCtrl);
	    break;

        case EIOCGMIB2:
            if (data == NULL)
                return (EINVAL);
            bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
                  sizeof(pDrvCtrl->endObj.mib2Tbl));
            break;

        case EIOCGFBUF:
            if (data == NULL)
                return (EINVAL);
#if 0
	    /* XXX */
            *(int *)data = END_MIN_FBUF;
#endif
            break;

        default:
            error = EINVAL;
        }

    return (error);
    }

/*******************************************************************************
*
* ax88796Start - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/

LOCAL STATUS ax88796Start
    (
    void*	pCookie
    )
    {
    STATUS result;
    AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;

    ENDLOGMSG (("ax88796Start\n", 0, 0, 0, 0, 0, 0));

    SYS_INT_CONNECT (pDrvCtrl, ax88796Int, (int)pDrvCtrl, &result);
    if (result == ERROR)
	return (ERROR);
	
    /* mark the interface as up (SPR #32034) */

    END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));

    /* Enable interrupts */
    
    pDrvCtrl->imask = (pDrvCtrl->flags & END_POLLING) ? 0 : AX88796_ALL_INTS;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
    SYS_INT_ENABLE (pDrvCtrl);

    return (OK);
    }

/******************************************************************************
*
* ax88796Config - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode, and changing the
* multicast interface list.
*
* NOMANUAL
*/
LOCAL void ax88796Config
    (
    AX88796END_DEVICE *pDrvCtrl,
    BOOL	      intEnable		/* TRUE to enable interrupts */
    )
    {
    UCHAR	rxFilter;		/* receiver configuration */
    UCHAR pStart;
#ifdef DEBUG
    static buf [256];
#endif

    ENDLOGMSG (("ax88796Config: enter (intEnable=%d)\n",
		intEnable, 0, 0, 0, 0, 0));

    /* Disable device interrupts */

    pDrvCtrl->imask = 0;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

    /* Set up address filter for multicasting. */

    if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
	ax88796AddrFilterSet (pDrvCtrl);

    /* preserve END_POLLING and OVERWRITE flags */
    pDrvCtrl->flags &= (END_POLLING | END_OVERWRITE | END_OVERWRITE2);

    /* 1. program Command Register for page 0 and for no DMA */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
    
    /* delay at least 1.5 ms */
    
    delay (3000);

    /* 2. initialize Data Configuration Register:
     *    16-bit bus, burst mode, 8-deep FIFO.
     * or
     *    8-bit bus, burst mode, 8-deep FIFO.
     */

//    if (pDrvCtrl->byteAccess)
	SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BUS_8);
//    else
//	SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BUS16);

    SYS_ENET_ADDR_GET (pDrvCtrl);

    /* 3. clear Remote Byte Count Register */

    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);

    /* 4. initialize Receive Configuration Register */

    /* Always accept broadcast packets. */

    rxFilter = RCON_INIT | RCON_BROAD;

    /* Set multicast mode if it's asked for. */

    if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
	{
	rxFilter |= RCON_GROUP;
	}
    ENDLOGMSG (("\tMulticast mode %s\n",
	    (rxFilter & RCON_GROUP) ? "on" : "off",
	    0, 0, 0, 0, 0));


    SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter);

⌨️ 快捷键说明

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