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

📄 dm9000end.c

📁 S3C2410的DM9000驱动。在优龙的开发板子上调试成功
💻 C
📖 第 1 页 / 共 5 页
字号:
static void     dm9000_hash_table(END_DEVICE *dev);
static void     program_dm9801( END_DEVICE *dev, UWORD HPNA_rev );
static void     program_dm9802(END_DEVICE *dev);
static UWORD    phy_read( END_DEVICE *dev, int reg );
static void     phy_write( END_DEVICE *dev, int reg, UWORD value);
static UWORD    read_srom_word( END_DEVICE *dev, UCHAR offset);
static void     write_srom_word( END_DEVICE *dev, UCHAR offset, UWORD value );
static unsigned long cal_CRC(unsigned char * Data, unsigned int Len, UCHAR flag);
static void     udelay( int us );
static void     Delay500ns(void);

static void     dm9000Reset(END_DEVICE *pDrvCtrl);
static void     dm9000Config(END_DEVICE *pDrvCtrl);
static void     dm9000Int(END_DEVICE *pDrvCtrl);
static void     dm9000HandleRcvInt(END_DEVICE *pDrvCtrl);
static STATUS   dm9000Recv(END_DEVICE *pDrvCtrl, char* pData);
static UINT     dm9000StatusRead(END_DEVICE *pDrvCtrl);
static void     dm9000needreset( END_DEVICE *pDrvCtrl );

/* END Specific interfaces. */

/* This is the only externally visible interface. */
/* END_OBJ*        dm9000Load (char* initString); */
END_OBJ *   sysEtherEndLoad (char* initString, void *pBSP);

static STATUS   dm9000Start(END_DEVICE* pDrvCtrl);
static STATUS   dm9000Stop(END_DEVICE* pDrvCtrl);
static int      dm9000Ioctl(END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
static STATUS   dm9000Unload(END_DEVICE* pDrvCtrl);
static STATUS   dm9000Send(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);

static STATUS   dm9000MCastAdd(END_DEVICE* pDrvCtrl, char* pAddress);
static STATUS   dm9000MCastDel(END_DEVICE* pDrvCtrl, char* pAddress);
static STATUS   dm9000MCastGet(END_DEVICE* pDrvCtrl, MULTI_TABLE* pTable);
static STATUS   dm9000PollStart(END_DEVICE* pDrvCtrl);
static STATUS   dm9000PollStop(END_DEVICE* pDrvCtrl);
static STATUS   dm9000PollSend(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
static STATUS   dm9000PollRcv(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
static void     dm9000AddrFilterSet(END_DEVICE *pDrvCtrl);

static STATUS   dm9000Parse( END_DEVICE * pDrvCtrl, char * initString );
static STATUS   dm9000MemInit( END_DEVICE * pDrvCtrl);

void dm9000Mode( END_DEVICE *pDrvCtrl, int mode, int reset );
/*
 * Declare our function table.  This is static across all driver
 * instances.
 */

static NET_FUNCS dm9000FuncTable =
{
    (FUNCPTR) dm9000Start,      /* Function to start the device. */
    (FUNCPTR) dm9000Stop,       /* Function to stop the device. */
    (FUNCPTR) dm9000Unload,     /* Unloading function for the driver. */
    (FUNCPTR) dm9000Ioctl,      /* Ioctl function for the driver. */
    (FUNCPTR) dm9000Send,       /* Send function for the driver. */
    (FUNCPTR) dm9000MCastAdd,   /* Multicast add function for the */
                                /* driver. */
    (FUNCPTR) dm9000MCastDel,   /* Multicast delete function for */
                                /* the driver. */
    (FUNCPTR) dm9000MCastGet,   /* Multicast retrieve function for */
                                /* the driver. */
    (FUNCPTR) dm9000PollSend,   /* Polling send function */
    (FUNCPTR) dm9000PollRcv,    /* Polling receive function */

    endEtherAddressForm,        /* put address info into a NET_BUFFER */
    endEtherPacketDataGet,      /* get pointer to data in NET_BUFFER */
    endEtherPacketAddrGet       /* Get packet addresses. */
};

/*static isrLink_t sysEndIsrLink =
{
    (void*)dm9000Int,   /* rtn */
    /*0,                  /* arg */
   /* NULL                /* next */
/*};*/

END_DEVICE *DrvCtrl;


/*****************************************
* Init DM9000 I/O pin
*****************************************/
void InitDM9000()
{
	/*printf("Init DM9000...\n");*/
	IODIR=IODIR|NET_RST0;
	udelay(100);
	IOCLR=NET_RST0;
	udelay(100);
	IOSET=NET_RST0;
	udelay(100);
	IOCLR=NET_RST0;
	udelay(100);
	PINSEL0|=0x03<<18;		/* set P0.9 to EINT3 */
	udelay(100);
	/*printf("Init DM9000 Done...\n");*/
}

UCHAR sysInByte	(ULONG port)
{
	return (REG8(port));
}
void	sysOutByte	(ULONG port, UCHAR data)
{
	(REG8(port))=data;
}

USHORT sysInWord (ULONG port)
{
	return (REG16(port));
}
void	sysOutWord (ULONG port, UINT16 data)
{
	(REG16(port))=data;
}
void dm9000OutChar(UINT8 addr,UINT8 value)
{
	sysOutByte(DM9000_IOADDR,addr);
	/* udelay(BUS_DELAY); */
	sysOutByte(DM9000_IODATA,value);
	/* udelay(BUS_DELAY); */
}
UINT8 dm9000InChar(UINT8 addr)
{
	/* udelay(BUS_DELAY); */
	sysOutByte(DM9000_IOADDR,addr);
	/* udelay(BUS_DELAY); */
	return sysInByte(DM9000_IODATA);
}

/*******************************************************************************
*
* sysEtherEndLoad - 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:
*
* "register addr:int vector:int level:shmem addr:shmem size:shmem width"
*
* RETURNS: An END object pointer or NULL on error.
*/

END_OBJ* sysEtherEndLoad( char* initString, void *pBSP )    /* String to be parsed by the driver. */
{
    END_DEVICE  *pDrvCtrl;
	char tmp;
    DRV_LOG (DRV_DEBUG_LOAD, "Loading dm9000...", 1, 2, 3, 4, 5, 6);
 /*   printf("loading dm9000......\n");
	DM9000_IN_CHAR(0x28,tmp);
	printf("tmp = %x\n",tmp);*/
    if (initString == NULL)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "initString == NULL", 1, 2, 3, 4, 5, 6);
        return (NULL);
    }

    if (initString[0] == '\0')
    {
        DRV_LOG (DRV_DEBUG_LOAD, "initString[0] == 0", 1, 2, 3, 4, 5, 6);
        bcopy((char *)DM9000_DEV_NAME, initString, DM9000_DEV_NAME_LEN);
        return (NULL);
    }

    /*if (sysMedusaPresent == FALSE)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "sysMedusaPresent == FALSE", 1, 2, 3, 4, 5, 6);
        return NULL;
    }*/

    /* allocate the device structure */

    pDrvCtrl = (END_DEVICE *)calloc(sizeof (END_DEVICE), 1);
    
    DrvCtrl = pDrvCtrl;
    if (pDrvCtrl == NULL)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "calloc() == NULL", 1, 2, 3, 4, 5, 6);
        goto errorExit;
        printf("error exit\n");
    }
    memset( (void*)pDrvCtrl, 0, sizeof( END_DEVICE ) );
    (pDrvCtrl->flags) = 0;
    (pDrvCtrl->op_mode) = DM9000_MEDIA_MODE;

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

    if (dm9000Parse(pDrvCtrl, initString) == ERROR)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "Parse() == ERROR", 1, 2, 3, 4, 5, 6);
        goto errorExit;
    }

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

    dm9000Reset (pDrvCtrl);
    /*printf("reset.....\n");*/
    /* initialize the END and MIB2 parts of the structure */

    /*
     * The M2 element must come from m2Lib.h
     * This dm9000 is set up for a DIX type ethernet device.
     */
    if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DM9000_DEV_NAME,
                      pDrvCtrl->unit, &dm9000FuncTable,
                      "END Template Driver.") == ERROR
     || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
                      &pDrvCtrl->enetAddr[0], 6, END_BUFSIZ,
                      END_SPEED)
            == ERROR)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "END_OBJ_INIT() == END_MIB_INIT()==ERROR", 1, 2, 3, 4, 5, 6);
        printf("obj init error\n");
        goto errorExit;
    }

    /* Perform memory allocation/distribution */

    if (dm9000MemInit (pDrvCtrl) == ERROR)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "MemInit() == ERROR", 1, 2, 3, 4, 5, 6);
        goto errorExit;
    }

    /* reset and reconfigure the device */

    dm9000Reset (pDrvCtrl);
    dm9000Config (pDrvCtrl);

    /* set the flags to indicate readiness */

    END_OBJ_READY (&pDrvCtrl->end,
                 IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
		
    DRV_LOG (DRV_DEBUG_LOAD, "Done loading Template...", 1, 2, 3, 4, 5, 6);
    /*printf("Done loading Template...\n");*/
	
    return (&pDrvCtrl->end);

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

    return NULL;
}

/*******************************************************************************
*
* dm9000Parse - parse the init string
*
* Parse the input string.  Fill in values in the driver control structure.
*
* The muxLib.o module automatically prepends the unit number to the user's
* initialization string from the BSP (configNet.h).
*
* .IP <unit>
* Device unit number, a small integer.
* .IP <vecNum>
* Interrupt vector number (used with sysIntConnect)
* .IP <intLvl>
* Interrupt level
* .LP
*
* RETURNS: OK or ERROR for invalid arguments.
*/

static STATUS dm9000Parse( END_DEVICE * pDrvCtrl,  /* device pointer */
                           char * initString )     /* information string */
{
    int               tmp1;
    unsigned long int tmp2, tmp3, tmp4;
    int               tmp5;

    /* Parse the initString */

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Parse()", 1, 2, 3, 4, 5, 6);
    DRV_LOG (DRV_DEBUG_LOAD, initString, 1, 2, 3, 4, 5, 6);
    if (sscanf(initString, "%d:%d:%lx:%lx:%lx:%d",
            &tmp1,
            &(pDrvCtrl->unit),
            &tmp2,
            &tmp3,
            &tmp4,
            &tmp5 ) != 6 /* the number of parameters */ )
        return ERROR;
    pDrvCtrl->ivec =  INT_VEC_EXTINT3;
    pDrvCtrl->ilevel = INT_LVL_EXTINT3;
    /*printf("parm ok\n");*/
    return OK;
}

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

static STATUS dm9000MemInit( END_DEVICE * pDrvCtrl )    /* device to be initialized */
{
     /* This is how we would set up and END netPool using netBufLib(1).
     * This code is pretty generic.
     */

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

    dm9000MclBlkConfig.mBlkNum = 128; /*16;*/
    dm9000ClDescTbl[0].clNum = 128;  /*16;*/
    dm9000MclBlkConfig.clBlkNum = dm9000ClDescTbl[0].clNum;

    /* Calculate the total memory for all the M-Blks and CL-Blks. */

    dm9000MclBlkConfig.memSize = (dm9000MclBlkConfig.mBlkNum *
                                 (MSIZE + sizeof (long))) +
                                 (dm9000MclBlkConfig.clBlkNum *
                                 (CL_BLK_SZ + sizeof(long)));

    if ((dm9000MclBlkConfig.memArea = (char *) memalign (sizeof(long),
                                 dm9000MclBlkConfig.memSize)) == NULL)
        return (ERROR);

    /* Calculate the memory size of all the clusters. */

    dm9000ClDescTbl[0].memSize = (dm9000ClDescTbl[0].clNum *
                                 (END_BUFSIZ + 8)) + sizeof(int);

    /* Allocate the memory for the clusters from cache safe memory. */

    if ((dm9000ClDescTbl[0].memArea = (char *) memalign ( sizeof(long),
                                  dm9000ClDescTbl[0].memSize)) == NULL)
        return (ERROR);

    if ((int)dm9000ClDescTbl[0].memArea == NULL)
    {
        DRV_LOG (DRV_DEBUG_LOAD, "system memory unavailable",
        1, 2, 3, 4, 5, 6);
        return (ERROR);
    }

    /* Initialize the memory pool. */

    if (netPoolInit(pDrvCtrl->end.pNetPool, &dm9000MclBlkConfig,
                    &dm9000ClDescTbl[0], dm9000ClDescTblNumEnt,
            NULL) == ERROR)
        {
        DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering",
        1, 2, 3, 4, 5, 6);
        return (ERROR);
        }

    /*
     * If you need clusters to store received packets into then get them
     * here ahead of time.
     */

    if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool,
        (END_BUFSIZ), FALSE))
        == NULL)
        return (ERROR);
   DRV_LOG (DRV_DEBUG_LOAD, "Memory setup complete", 1, 2, 3, 4, 5, 6);

    return OK;
}

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

static STATUS dm9000Start( END_DEVICE * pDrvCtrl )  /* device ID */
{
    STATUS result;

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Start.", 1, 2, 3, 4, 5, 6);
    /*printf("dm9000 startd\n");*/
   /* sysEndIsrLink.arg = (int)pDrvCtrl;*/
    SYS_INT_CONNECT (pDrvCtrl, dm9000Int, (int)pDrvCtrl, &result);
	VICIntEnable|=1<<17;	/* enable eint3 */
    /*result = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \
			     dm9000Int, 0);*/
    if (result == ERROR)
    {
        printf("interrupt connect error\n");
        return ERROR;
    }
    /*printf("Interrupt connected.\n");*/
    DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.", 1, 2, 3, 4, 5, 6);

    SYS_INT_ENABLE (pDrvCtrl);
    /* sysIntEnablePIC (pDrvCtrl->ilevel); */
    DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.", 1, 2, 3, 4, 5, 6);

    /* TODO - start the device, enabling interrupts */

    /* Activate DM9000 */
    DM9000_OUT_CHAR( 0x05, DM9000_REG05 | 1 );      /* RX enable */
    DM9000_OUT_CHAR( 0xff, DM9000_REGFF );          /* Enable TX/RX interrupt mask */

	pDrvCtrl->tbusy=0;
	/*printf("dm9000Start tbusy=0\n");*/

    return (OK);
}

/*******************************************************************************
*
* dm9000Int - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/

static void dm9000Int( END_DEVICE  *pDrvCtrl  )  /* interrupting device */
{
    UCHAR stat, reg_save, isr_status, nsr_status; /* tx_status, */

⌨️ 快捷键说明

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