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

📄 rtl8139.c

📁 在ucos_ii基础上加上网络功能
💻 C
📖 第 1 页 / 共 2 页
字号:

static void rtl8139_weird_interrupt(struct rtl_private_data *private_data)
{
#ifdef	DEBUG_RTL8139
	debug_print("enter weird_interrupt process \r\n !");
#endif
	return;
}
static void rtl8139_tx_interrupt (struct rtl_private_data *private_data)
{
//	unsigned long txstatus;

	debug_print("rtl_tx_inter() \r\n");

#ifdef	DEBUG_RTL8139
	debug_print("enter tx_interrupt process ! \r\n ");
#endif

//	txstatus = RTL_R32 (TxStatus0);

	/* Clear timeout flag */
#ifdef DEBUG_RTL8139
	debug_print("interrupt from %s \r\n",private_data->nic->name);
#endif
	private_data->nic->timeout = 0;


	return;
}

int rtl_interrupt(void *arg)
{
	struct rtl_private_data *private_data = (struct rtl_private_data *)arg;
	struct nic *nic = private_data->nic;
	int ackstat, status;
	int boguscnt = max_interrupt_work;
	int link_changed = 0; /* avoid bogus "uninit" warning */

	/* Mask the bit that says "this is an io addr" */
	ioaddr = nic->ioaddr;
	
	do {
		status = RTL_R16 (IntrStatus);

		/* h/w no longer present (hotplug?) or major error, bail */
		if (status == 0xFFFF)
			break;

		if ((status &
		     (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
		      RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
			break;
		/* Acknowledge all of the current interrupt sources ASAP, but
		   an first get an additional status bit from CSCR. */
		if (status & RxUnderrun)
			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;


		ackstat = status & ~(RxAckBits | TxErr);
		RTL_W16 (IntrStatus, ackstat);
#ifdef	DEBUG_RTL8139
		debug_print("interrupt  status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\r\n",
			   status,ackstat, RTL_R16 (IntrStatus));
#endif
		if (status & RxAckBits)
			rtl8139_rx_interrupt (private_data);

		/* Check uncommon events with one test. */
		if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
		  	      RxFIFOOver | RxErr))
			rtl8139_weird_interrupt (private_data);

		if (status & (TxOK | TxErr)) {
			rtl8139_tx_interrupt (private_data);
			if (status & TxErr)
				RTL_W16 (IntrStatus, TxErr);
		}

		boguscnt--;
	}while (boguscnt > 0);

	if (boguscnt <= 0) {
#ifdef	DEBUG_RTL8139
		debug_print ("Too much work at interrupt, "
			"IntrStatus=0x%4.4x.\n", status);
#endif
		/* Clear all interrupt sources. */
		RTL_W16 (IntrStatus, 0xffff);
	}
	
	_outp( ICR_A, EOI );
	_outp( ICR_B, EOI );

	return 0;
}



int 
rtl8139_probe(struct nic *nic)
{
	int i;
	struct pci_device *p = NULL;
	int speed10, fullduplex;
	int found = 0;
	p = lookup_pci_device(PCI_VENDOR_ID_REALTEK,PCI_DEVICE_ID_REALTEK_8139);
	while(p&& found < N_RTL8139){
	
		nic->pci_data = p;
#ifdef USE_IO_OPS
		nic->ioaddr = p->ioaddr & ~3;
#else
		nic->ioaddr = p->membase;
#endif

		nic->irq = p->irq;
		nic->device = p->device;
		nic->vendor = p->vendor;
	
	
		/*
		 * This bit below is not necessary at all since the pci.c subsystem
		 * is supposed to find the NIC, but I will leave it in since it
		 * hardly will ever execute this test.
		 */
		if (nic->ioaddr == 0) {
			return -1;
		}

		/* Mask the bit that says "this is an io addr" */
		ioaddr = nic->ioaddr;

		/* Bring the chip out of low-power mode. */
		RTL_W8(Cfg9346,0x00);

		if (read_eeprom(0) != 0xffff) {
			unsigned short *ap = (unsigned short*)nic->node_addr;
			for (i = 0; i < 3; i++)
				*ap++ = read_eeprom(i + 7);
		} else {
			unsigned char *ap = (unsigned char*)nic->node_addr;
			for (i = 0; i < ETH_ALEN; i++)
				*ap++ = RTL_R8(MAC0 + i);
		}

		speed10 = RTL_R8(MediaStatus) & MSRSpeed10;
		fullduplex = RTL_R16(MII_BMCR) & BMCRDuplex;
		debug_print("ioaddr %lX, addr %02x:%02x:%02x:%02x:%02x:%02x  %sMbps %s-duplex\r\n", 
			     ioaddr,
			     nic->node_addr[0],
			     nic->node_addr[1],
			     nic->node_addr[2],
			     nic->node_addr[3],
			     nic->node_addr[4],
			     nic->node_addr[5],
			     speed10 ? "10" : "100",
			     fullduplex ? "full" : "half");


		rtl_reset(nic);

		IRQ_REQUEST(nic->irq,rtl_interrupt,&private_datas[found]);

		private_datas[found].nic = nic;

		nic->watchdog = rtl_reset;
		nic->transmit = rtl_transmit;
		nic->ioctl = rtl_ioctl;
		found ++;
		nic ++;
		p = p->next;

	}

	return found;
}




static void rtl_reset(struct nic* nic)
{
	int i;
	/* Mask the bit that says "this is an io addr" */
	ioaddr = nic->ioaddr;

	RTL_W8(ChipCmd,CmdReset);

	cur_rx = 0;
	cur_tx = 0;

	/* Give the chip 10ms to finish the reset. */
	load_timer2(10*TICKS_PER_MS);
	while ((RTL_R8(ChipCmd) & CmdReset) != 0 && timer2_running())
		/* wait */;

	for (i = 0; i < ETH_ALEN; i++)
		RTL_W8(MAC0 + i,nic->node_addr[i]);

	/* Must enable Tx/Rx before setting transfer thresholds! */
	RTL_W8(ChipCmd,CmdRxEnb | CmdTxEnb);
	RTL_W32(RxConfig,(RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8));		/* accept no frames yet!  */
	RTL_W32(TxConfig,(TX_DMA_BURST<<8)|0x03000000);

	/* The Linux driver changes Config1 here to use a different LED pattern
	 * for half duplex or full/autodetect duplex (for full/autodetect, the
	 * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses
	 * TX/RX, Link100, Link10).  This is messy, because it doesn't match
	 * the inscription on the mounting bracket.  It should not be changed
	 * from the configuration EEPROM default, because the card manufacturer
	 * should have set that to match the card.  */


	RTL_W32(RxBuf,(unsigned long)rx_ring);

	/* Start the chip's Tx and Rx process. */
	RTL_W32(RxMissed,0);
	/* set_rx_mode */
	RTL_W8(RxConfig,AcceptBroadcast|AcceptMyPhys/*|AcceptAllPhys*/);
	/* If we add multicast support, the MAR0 register would have to be
	 * initialized to 0xffffffffffffffff (two 32 bit accesses).  Etherboot
	 * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast.  */
	RTL_W8(ChipCmd,CmdRxEnb | CmdTxEnb);

	/* Disable all known interrupts by setting the interrupt mask. */
	RTL_W16(IntrMask,0);

	RTL_W16(IntrMask,rtl8139_intr_mask);

	/* Clear watchdog timer */
	nic->timeout = 0;
}

static int rtl_transmit(struct nic *nic,  char *data,int len)
{
	/* Mask the bit that says "this is an io addr" */
	ioaddr = nic->ioaddr;
	

	debug_print("rtl_transmit() \r\n");

	/* Wait ... */	
	while(nic->timeout > 0) 
		;

	memcpy(tx_buffer ,data, len);

	/* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4
	 * bytes are sent automatically for the FCS, totalling to 64 bytes). */
	while (len < ETH_ZLEN) {
		tx_buffer[len++] = '\0';
	}

	RTL_W32(TxAddr0 + cur_tx*4,(unsigned long)tx_buffer);
	RTL_W32(TxStatus0 + cur_tx*4,((TX_FIFO_THRESH<<11) & 0x003f0000) | len);


	/* Set a timer just in case we never hear from the board again . */
	nic->timeout = RTL_TIMEOUT;

	return len;
}

int
rtl_ioctl(struct nic *nic,u_long cmd,caddr_t data)
{
	/* Mask the bit that says "this is an io addr" */
	ioaddr = nic->ioaddr;
	return 0;
}




/* 
 * $Log: rtl8139.c,v $
 * Revision 1.10  2002/02/21 08:25:00  linfusheng
 * update
 *
 * Revision 1.9  2002/02/07 10:25:35  linfusheng
 * update
 *
 * Revision 1.8  2002/02/07 01:08:53  linfusheng
 * update
 *
 * Revision 1.7  2002/02/06 07:59:04  linfusheng
 * update
 *
 * Revision 1.6  2002/02/06 07:42:18  linfusheng
 * update
 *
 * Revision 1.5  2002/02/06 07:28:51  linfusheng
 * update
 *
 * Revision 1.4  2002/02/06 02:16:25  linfusheng
 * update
 *
 * Revision 1.3  2002/01/28 01:13:52  linfusheng
 * update
 *
 * Revision 1.2  2002/01/28 00:46:25  linfusheng
 * update
 *
 */

⌨️ 快捷键说明

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