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

📄 3c90x.c

📁 在ucos_ii基础上加上网络功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	    debug_print("3C90X: Runt Frame (%hX)\n",errcode>>16);
	else if (errcode & (1<<18))
	    debug_print("3C90X: Alignment Error (%hX)\n",errcode>>16);
	else if (errcode & (1<<19))
	    debug_print("3C90X: CRC Error (%hX)\n",errcode>>16);
	else if (errcode & (1<<20))
	    debug_print("3C90X: Oversized Frame (%hX)\n",errcode>>16);
	else
	    debug_print("3C90X: Packet error (%hX)\n",errcode>>16);
	return 0;
	}

    /** Ok, got packet.  Set length in nic->packetlen. **/
    *buflen = (INF_3C90X.ReceiveUPD.UpPktStatus & 0x1FFF);

    return 1;
    }


/*** a3c90x_disable: exported routine to disable the card.  What's this for?
 *** the eepro100.c driver didn't have one, so I just left this one empty too.
 *** Ideas anyone?
 *** Must turn off receiver at least so stray packets will not corrupt memory
 *** [Ken]
 ***/
static void
a3c90x_disable(struct nic *nic)
    {
	/* Disable the receiver and transmitter. */
	NETCARD_OUTW(cmdRxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);
	NETCARD_OUTW(cmdTxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);
    }


/*** a3c90x_probe: exported routine to probe for the 3c905 card and perform
 *** initialization.  If this routine is called, the pci functions did find the
 *** card.  We just have to init it here.
 ***/
int
a3c90x_probe(struct nic *nic)
    {
    int i, c;
    struct pci_device *pci = nic->pci_data;
    unsigned short eeprom[0x21];
    unsigned long cfg;
    unsigned long mopt;
    unsigned short linktype;

    unsigned short pci_command;
    unsigned short new_command;
    unsigned char pci_latency;

    if (nic->ioaddr == 0)
	  return -1;
    if (pci == NULL)
	  return -1;

    /* Make certain the card is properly set up as a bus master. */
    pcibios_read_config_word(pci->bus, pci->devfn, PCI_COMMAND, &pci_command);
    new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
    if (pci_command != new_command) {
	    debug_print("\nThe PCI BIOS has not enabled this device!\nUpdating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n",
		    pci_command, new_command, pci->bus, pci->devfn);
	    pcibios_write_config_word(pci->bus, pci->devfn, PCI_COMMAND, new_command);
    }
    pcibios_read_config_byte(pci->bus, pci->devfn, PCI_LATENCY_TIMER, &pci_latency);
    if (pci_latency < 32) {
	    debug_print("\nPCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", pci_latency);
	    pcibios_write_config_byte(pci->bus, pci->devfn, PCI_LATENCY_TIMER, 32);
    }

    INF_3C90X.IOAddr = nic->ioaddr;
    INF_3C90X.CurrentWindow = 255;
    switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03))
	{
	case 0x9000: /** 10 Base TPO             **/
	case 0x9001: /** 10/100 T4               **/
	case 0x9050: /** 10/100 TPO              **/
	case 0x9051: /** 10 Base Combo           **/
		INF_3C90X.isBrev = 0;
		break;

	case 0x9004: /** 10 Base TPO             **/
	case 0x9005: /** 10 Base Combo           **/
	case 0x9006: /** 10 Base TPO and Base2   **/
	case 0x900A: /** 10 Base FL              **/
	case 0x9055: /** 10/100 TPO              **/
	case 0x9056: /** 10/100 T4               **/
	case 0x905A: /** 10 Base FX              **/
	default:
		INF_3C90X.isBrev = 1;
		break;
	}

    /** Load the EEPROM contents **/
    if (INF_3C90X.isBrev)
	{
	for(i=0;i<=0x20;i++)
	    {
	    eeprom[i] = a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, i);
	    }

#ifdef	CFG_3C90X_BOOTROM_FIX
	/** Set xcvrSelect in InternalConfig in eeprom. **/
	/* only necessary for 3c905b revision cards with boot PROM bug!!! */
	a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x13, 0x0160);
#endif

#ifdef	CFG_3C90X_XCVR
	if (CFG_3C90X_XCVR == 255)
	    {
	    /** Clear the LanWorks register **/
	    a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x16, 0);
	    }
	else
	    {
	    /** Set the selected permanent-xcvrSelect in the
	     ** LanWorks register
	     **/
	    a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x16,
	                    XCVR_MAGIC + ((CFG_3C90X_XCVR) & 0x000F));
	    }
#endif
	}
    else
	{
	for(i=0;i<=0x17;i++)
	    {
	    eeprom[i] = a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, i);
	    }
	}

    /** Print identification message **/
    debug_print("\n\n3C90X Driver 2.00 "
	   "Copyright 1999 LightSys Technology Services, Inc.\n"
	   "Portions Copyright 1999 Steve Smith\n");
    debug_print("Provided with ABSOLUTELY NO WARRANTY.\n");
    debug_print("-------------------------------------------------------"
           "------------------------\n");

    /** Retrieve the Hardware address and print it on the screen. **/
    INF_3C90X.HWAddr[0] = eeprom[0]>>8;
    INF_3C90X.HWAddr[1] = eeprom[0]&0xFF;
    INF_3C90X.HWAddr[2] = eeprom[1]>>8;
    INF_3C90X.HWAddr[3] = eeprom[1]&0xFF;
    INF_3C90X.HWAddr[4] = eeprom[2]>>8;
    INF_3C90X.HWAddr[5] = eeprom[2]&0xFF;
    debug_print_buf("MAC Address:", INF_3C90X.HWAddr,ETH_ALEN);

    /** Program the MAC address into the station address registers **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2);
    NETCARD_OUTW(htons(eeprom[0]), INF_3C90X.IOAddr + regStationAddress_2_3w);
    NETCARD_OUTW(htons(eeprom[1]), INF_3C90X.IOAddr + regStationAddress_2_3w+2);
    NETCARD_OUTW(htons(eeprom[2]), INF_3C90X.IOAddr + regStationAddress_2_3w+4);
    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);

    /** Fill in our entry in the etherboot arp table **/
    for(i=0;i<ETH_ALEN;i++)
	nic->node_addr[i] = (eeprom[i/2] >> (8*((i&1)^1))) & 0xff;

    /** Read the media options register, print a message and set default
     ** xcvr.
     **
     ** Uses Media Option command on B revision, Reset Option on non-B
     ** revision cards -- same register address
     **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
    mopt = NETCARD_INW(INF_3C90X.IOAddr + regResetMediaOptions_3_w);

    /** mask out VCO bit that is defined as 10baseFL bit on B-rev cards **/
    if (! INF_3C90X.isBrev)
	{
	mopt &= 0x7F;
	}

    debug_print("Connectors present: ");
    c = 0;
    linktype = 0x0008;
    if (mopt & 0x01)
	{
	debug_print("%s100Base-T4",(c++)?", ":"");
	linktype = 0x0006;
	}
    if (mopt & 0x04)
	{
	debug_print("%s100Base-FX",(c++)?", ":"");
	linktype = 0x0005;
	}
    if (mopt & 0x10)
	{
	debug_print("%s10Base-2",(c++)?", ":"");
	linktype = 0x0003;
	}
    if (mopt & 0x20)
	{
	debug_print("%sAUI",(c++)?", ":"");
	linktype = 0x0001;
	}
    if (mopt & 0x40)
	{
	debug_print("%sMII",(c++)?", ":"");
	linktype = 0x0006;
	}
    if ((mopt & 0xA) == 0xA)
	{
	debug_print("%s10Base-T / 100Base-TX",(c++)?", ":"");
	linktype = 0x0008;
	}
    else if ((mopt & 0xA) == 0x2)
	{
	debug_print("%s100Base-TX",(c++)?", ":"");
	linktype = 0x0008;
	}
    else if ((mopt & 0xA) == 0x8)
	{
	debug_print("%s10Base-T",(c++)?", ":"");
	linktype = 0x0008;
	}
    debug_print(".\n");

    /** Determine transceiver type to use, depending on value stored in
     ** eeprom 0x16
     **/
    if (INF_3C90X.isBrev)
	{
	if ((eeprom[0x16] & 0xFF00) == XCVR_MAGIC)
	    {
	    /** User-defined **/
	    linktype = eeprom[0x16] & 0x000F;
	    }
	}
    else
	{
#ifdef	CFG_3C90X_XCVR
	    if (CFG_3C90X_XCVR != 255)
		linktype = CFG_3C90X_XCVR;
#endif	/* CFG_3C90X_XCVR */

	    /** I don't know what MII MAC only mode is!!! **/
	    if (linktype == 0x0009)
		{
		if (INF_3C90X.isBrev)
			debug_print("WARNING: MII External MAC Mode only supported on B-revision "
			       "cards!!!!\nFalling Back to MII Mode\n");
		linktype = 0x0006;
		}
	}

    /** enable DC converter for 10-Base-T **/
    if (linktype == 0x0003)
	{
	a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdEnableDcConverter, 0);
	}

    /** Set the link to the type we just determined. **/
    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
    cfg = NETCARD_IND(INF_3C90X.IOAddr + regInternalConfig_3_l);
    cfg &= ~(0xF<<20);
    cfg |= (linktype<<20);
    NETCARD_OUTD(cfg, INF_3C90X.IOAddr + regInternalConfig_3_l);

    /** Now that we set the xcvr type, reset the Tx and Rx, re-enable. **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxReset, 0x00);
    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)
	;

    /** Set the RX filter = receive only individual pkts & bcast. **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdSetRxFilter, 0x01 + 0x04);
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxEnable, 0);


    /**
     ** set Indication and Interrupt flags , acknowledge any IRQ's
     **/
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdSetInterruptEnable, 0);
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
				 cmdSetIndicationEnable, 0x0014);
    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
				 cmdAcknowledgeInterrupt, 0x661);

    nic->disable = a3c90x_disable;
    nic->poll = a3c90x_poll;
    return 0;
    }


⌨️ 快捷键说明

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