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

📄 3c90x.c

📁 ucos_ii基础上加上网络功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	/** Burn the new data into the eeprom, and wait for completion. **/
	NETCARD_OUTW(address + ((0x01)<<6), ioaddr + regEepromCommand_0_w);
	while((1<<15) & NETCARD_INW(ioaddr + regEepromCommand_0_w));

    return 0;
    }


/*** a3c90x_internal_WriteEeprom - write data to the serial eeprom,
 *** and re-compute the eeprom checksum.
 ***/
static int
a3c90x_internal_WriteEeprom(unsigned short ioaddr, int address, unsigned short value)
    {
    int cksum = 0,v;
    int i;
    int maxAddress, cksumAddress;

	if (INF_3C90X.isBrev)
	    {
	    maxAddress=0x1f;
	    cksumAddress=0x20;
	    }
	else
	    {
	    maxAddress=0x16;
	    cksumAddress=0x17;
	    }

	/** Write the value. **/
	if (a3c90x_internal_WriteEepromWord(ioaddr, address, value) == -1)
	    return -1;

	/** Recompute the checksum. **/
	for(i=0;i<=maxAddress;i++)
	    {
	    v = a3c90x_internal_ReadEeprom(ioaddr, i);
	    cksum ^= (v & 0xFF);
	    cksum ^= ((v>>8) & 0xFF);
	    }
	/** Write the checksum to the location in the eeprom **/
	if (a3c90x_internal_WriteEepromWord(ioaddr, cksumAddress, cksum) == -1)
	    return -1;

    return 0;
    }

#if 0


/*** a3c90x_reset: exported function that resets the card to its default
 *** state.  This is so the Linux driver can re-set the card up the way
 *** it wants to.  If CFG_3C90X_PRESERVE_XCVR is defined, then the reset will
 *** not alter the selected transceiver that we used to download the boot
 *** image.
 ***/
static void
a3c90x_reset(struct nic *nic)
    {
    int cfg;

#ifdef	CFG_3C90X_PRESERVE_XCVR
    /** Read the current InternalConfig value. **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
    cfg = NETCARD_IND(INF_3C90X.IOAddr + regInternalConfig_3_l);
#endif

    /** Send the reset command to the card **/
    debug_print("Issuing RESET:\n");
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdGlobalReset, 0);

    /** wait for reset command to complete **/
    while (NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS);

    /** global reset command resets station mask, non-B revision cards
     ** require explicit reset of values
     **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2);
    NETCARD_OUTW(0, INF_3C90X.IOAddr + regStationMask_2_3w+0);
    NETCARD_OUTW(0, INF_3C90X.IOAddr + regStationMask_2_3w+2);
    NETCARD_OUTW(0, INF_3C90X.IOAddr + regStationMask_2_3w+4);

#ifdef	CFG_3C90X_PRESERVE_XCVR
    /** Re-set the original InternalConfig value from before reset **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
    NETCARD_OUTD(cfg, INF_3C90X.IOAddr + regInternalConfig_3_l);

    /** enable DC converter for 10-Base-T **/
    if ((cfg&0x0300) == 0x0300)
	{
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdEnableDcConverter, 0);
	}
#endif

    /** Issue transmit reset, wait for command completion **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxReset, 0);
    while (NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS)
	;
    if (! INF_3C90X.isBrev)
	NETCARD_OUTB(0x01, INF_3C90X.IOAddr + regTxFreeThresh_b);
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0);

    /**
     ** reset of the receiver on B-revision cards re-negotiates the link
     ** takes several seconds (a computer eternity)
     **/
    if (INF_3C90X.isBrev)
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxReset, 0x04);
    else
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxReset, 0x00);
    while (NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS);
	;
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxEnable, 0);

    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
                                 cmdSetInterruptEnable, 0);
    /** enable rxComplete and txComplete **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
                                 cmdSetIndicationEnable, 0x0014);
    /** acknowledge any pending status flags **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
                                 cmdAcknowledgeInterrupt, 0x661);

    return;
    }



/*** a3c90x_transmit: exported function that transmits a packet.  Does not
 *** return any particular status.  Parameters are:
 *** d[6] - destination address, ethernet;
 *** t - protocol type (ARP, IP, etc);
 *** s - size of the non-header part of the packet that needs transmitted;
 *** p - the pointer to the packet data itself.
 ***/
static void
a3c90x_transmit(struct nic *nic, const char *d, unsigned long t,
		unsigned long s, const char *p)
    {

    struct eth_hdr
	{
	unsigned char dst_addr[ETH_ALEN];
	unsigned char src_addr[ETH_ALEN];
	unsigned short type;
	} hdr;

    unsigned char status;
    unsigned i, retries;

    for (retries=0; retries < XMIT_RETRIES ; retries++)
	{
	/** Stall the download engine **/
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdStallCtl, 2);

	/** Make sure the card is not waiting on us **/
	NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w);
	NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w);

	while (NETCARD_INW(INF_3C90X.IOAddr+regCommandIntStatus_w) &
	       INT_CMDINPROGRESS)
	    ;

	/** Set the ethernet packet type **/
	hdr.type = htons(t);

	/** Copy the destination address **/
	memcpy(hdr.dst_addr, d, ETH_ALEN);

	/** Copy our MAC address **/
	memcpy(hdr.src_addr, INF_3C90X.HWAddr, ETH_ALEN);

	/** Setup the DPD (download descriptor) **/
	INF_3C90X.TransmitDPD.DnNextPtr = 0;
	/** set notification for transmission completion (bit 15) **/
	INF_3C90X.TransmitDPD.FrameStartHeader = (s + sizeof(hdr)) | 0x8000;
	INF_3C90X.TransmitDPD.HdrAddr = virt_to_bus(&hdr);
	INF_3C90X.TransmitDPD.HdrLength = sizeof(hdr);
	INF_3C90X.TransmitDPD.DataAddr = virt_to_bus(p);
	INF_3C90X.TransmitDPD.DataLength = s + (1<<31);

	/** Send the packet **/
	NETCARD_OUTD(virt_to_bus(&(INF_3C90X.TransmitDPD)),
	     INF_3C90X.IOAddr + regDnListPtr_l);

	/** End Stall and Wait for upload to complete. **/
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdStallCtl, 3);
	while(NETCARD_IND(INF_3C90X.IOAddr + regDnListPtr_l) != 0)
	    ;

	/** Wait for NIC Transmit to Complete **/
	load_timer2(10*TICKS_PER_MS);	/* Give it 10 ms */
	while (!(NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) &&
		timer2_running())
		;

	if (!(NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))
	    {
	    debug_print("3C90X: Tx Timeout\n");
	    continue;
	    }

	status = NETCARD_INB(INF_3C90X.IOAddr + regTxStatus_b);

	/** acknowledge transmit interrupt by writing status **/
	NETCARD_OUTB(0x00, INF_3C90X.IOAddr + regTxStatus_b);

	/** successful completion (sans "interrupt Requested" bit) **/
	if ((status & 0xbf) == 0x80)
	    return;

	   debug_print("3C90X: Status (%hhX)\n", status);
	/** check error codes **/
	if (status & 0x02)
	    {
	    debug_print("3C90X: Tx Reclaim Error (%hhX)\n", status);
	    a3c90x_reset(NULL);
	    }
	else if (status & 0x04)
	    {
	    debug_print("3C90X: Tx Status Overflow (%hhX)\n", status);
	    for (i=0; i<32; i++)
		NETCARD_OUTB(0x00, INF_3C90X.IOAddr + regTxStatus_b);
	    /** must re-enable after max collisions before re-issuing tx **/
	    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0);
	    }
	else if (status & 0x08)
	    {
	    debug_print("3C90X: Tx Max Collisions (%hhX)\n", status);
	    /** must re-enable after max collisions before re-issuing tx **/
	    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0);
	    }
	else if (status & 0x10)
	    {
	    debug_print("3C90X: Tx Underrun (%hhX)\n", status);
	    a3c90x_reset(NULL);
	    }
	else if (status & 0x20)
	    {
	    debug_print("3C90X: Tx Jabber (%hhX)\n", status);
	    a3c90x_reset(NULL);
	    }
	else if ((status & 0x80) != 0x80)
	    {
	    debug_print("3C90X: Internal Error - Incomplete Transmission (%hhX)\n",
	           status);
	    a3c90x_reset(NULL);
	    }
	}

    /** failed after RETRY attempts **/
    debug_print("Failed to send after %d retries\n", retries);
    return;

    }

#endif



/*** a3c90x_poll: exported routine that waits for a certain length of time
 *** for a packet, and if it sees none, returns 0.  This routine should
 *** copy the packet to nic->packet if it gets a packet and set the size
 *** in nic->packetlen.  Return 1 if a packet was found.
 ***/
static int
a3c90x_poll(struct nic *nic,unsigned char *buf,int *buflen)
    {
    unsigned long i;
    int  errcode;

    if (!(NETCARD_INW(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0010))
    {
	return 0;
    }

    /** we don't need to acknowledge rxComplete -- the upload engine
     ** does it for us.
     **/
    printf("step 1 \n");

    /** Build the up-load descriptor **/
    INF_3C90X.ReceiveUPD.UpNextPtr = 0;
    INF_3C90X.ReceiveUPD.UpPktStatus = 0;
    INF_3C90X.ReceiveUPD.DataAddr = virt_to_bus(buf);
    INF_3C90X.ReceiveUPD.DataLength = 1536 + (1<<31);

    printf("step 2 . \n");
    /** Submit the upload descriptor to the NIC **/
    NETCARD_OUTD(virt_to_bus(&(INF_3C90X.ReceiveUPD)),
	 INF_3C90X.IOAddr + regUpListPtr_l);

    printf("step . \n");

    /** Wait for upload completion (upComplete(15) or upError (14)) **/
    for(i=0;i<40000;i++);
    while((INF_3C90X.ReceiveUPD.UpPktStatus & ((1<<14) | (1<<15))) == 0)
	for(i=0;i<40000;i++);

	printf("step 4 \n");
    /** Check for Error (else we have good packet) **/
    if (INF_3C90X.ReceiveUPD.UpPktStatus & (1<<14))
	{
	errcode = INF_3C90X.ReceiveUPD.UpPktStatus;
	if (errcode & (1<<16))
	    debug_print("3C90X: Rx Overrun (%hX)\n",errcode>>16);
	else if (errcode & (1<<17))

⌨️ 快捷键说明

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