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

📄 3c90x.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 3 页
字号:
    }/*** a3c90x_internal_WriteEepromWord - write a physical word of *** data to the onboard serial eeprom (not the BIOS prom, but the *** nvram in the card that stores, among other things, the MAC *** address). ***/static inta3c90x_internal_WriteEepromWord(int ioaddr, int address, unsigned short value)    {	/** Select register window **/        a3c90x_internal_SetWindow(ioaddr, winEepromBios0);	/** Verify Eeprom not busy **/	while((1<<15) & inw(ioaddr + regEepromCommand_0_w));	/** Issue WriteEnable, and wait for completion. **/	outw(0x30, ioaddr + regEepromCommand_0_w);	while((1<<15) & inw(ioaddr + regEepromCommand_0_w));	/** Issue EraseRegister, and wait for completion. **/	outw(address + ((0x03)<<6), ioaddr + regEepromCommand_0_w);	while((1<<15) & inw(ioaddr + regEepromCommand_0_w));	/** Send the new data to the eeprom, and wait for completion. **/	outw(value, ioaddr + regEepromData_0_w);	outw(0x30, ioaddr + regEepromCommand_0_w);	while((1<<15) & inw(ioaddr + regEepromCommand_0_w));	/** Burn the new data into the eeprom, and wait for completion. **/	outw(address + ((0x01)<<6), ioaddr + regEepromCommand_0_w);	while((1<<15) & inw(ioaddr + regEepromCommand_0_w));    return 0;    }/*** a3c90x_internal_WriteEeprom - write data to the serial eeprom, *** and re-compute the eeprom checksum. ***/static inta3c90x_internal_WriteEeprom(int 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;    }/*** 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 voida3c90x_reset(struct nic *nic)    {    int cfg;#ifdef	CFG_3C90X_PRESERVE_XCVR    /** Read the current InternalConfig value. **/    a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);    cfg = inl(INF_3C90X.IOAddr + regInternalConfig_3_l);#endif    /** Send the reset command to the card **/    printf("Issuing RESET:\n");    a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdGlobalReset, 0);    /** wait for reset command to complete **/    while (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);    outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+0);    outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+2);    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);    outl(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 (inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS)	;    if (! INF_3C90X.isBrev)	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 (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 voida3c90x_transmit(struct nic *nic, const char *d, unsigned int t,                unsigned int 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 **/	inw(INF_3C90X.IOAddr + regCommandIntStatus_w);	inw(INF_3C90X.IOAddr + regCommandIntStatus_w);	while (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 **/	outl(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(inl(INF_3C90X.IOAddr + regDnListPtr_l) != 0)	    ;	/** Wait for NIC Transmit to Complete **/	load_timer2(10*TICKS_PER_MS);	/* Give it 10 ms */	while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) &&		timer2_running())		;	if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))	    {	    printf("3C90X: Tx Timeout\n");	    continue;	    }	status = inb(INF_3C90X.IOAddr + regTxStatus_b);	/** acknowledge transmit interrupt by writing status **/	outb(0x00, INF_3C90X.IOAddr + regTxStatus_b);	/** successful completion (sans "interrupt Requested" bit) **/	if ((status & 0xbf) == 0x80)	    return;	   printf("3C90X: Status (%hhX)\n", status);	/** check error codes **/	if (status & 0x02)	    {	    printf("3C90X: Tx Reclaim Error (%hhX)\n", status);	    a3c90x_reset(NULL);	    }	else if (status & 0x04)	    {	    printf("3C90X: Tx Status Overflow (%hhX)\n", status);	    for (i=0; i<32; i++)		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)	    {	    printf("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)	    {	    printf("3C90X: Tx Underrun (%hhX)\n", status);	    a3c90x_reset(NULL);	    }	else if (status & 0x20)	    {	    printf("3C90X: Tx Jabber (%hhX)\n", status);	    a3c90x_reset(NULL);	    }	else if ((status & 0x80) != 0x80)	    {	    printf("3C90X: Internal Error - Incomplete Transmission (%hhX)\n",	           status);	    a3c90x_reset(NULL);	    }	}    /** failed after RETRY attempts **/    printf("Failed to send after %d retries\n", retries);    return;    }/*** 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 inta3c90x_poll(struct nic *nic)    {    int i, errcode;    if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0010))	{	return 0;	}    /** we don't need to acknowledge rxComplete -- the upload engine     ** does it for us.     **/    /** Build the up-load descriptor **/    INF_3C90X.ReceiveUPD.UpNextPtr = 0;    INF_3C90X.ReceiveUPD.UpPktStatus = 0;    INF_3C90X.ReceiveUPD.DataAddr = virt_to_bus(nic->packet);

⌨️ 快捷键说明

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