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

📄 rtl8139.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		outb(EE_ENB | dataval, ee_addr);		eeprom_delay();		outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay();	}	outb(EE_ENB, ee_addr);	eeprom_delay();	for (i = 16; i > 0; i--) {		outb(EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);		outb(EE_ENB, ee_addr);		eeprom_delay();	}	/* Terminate the EEPROM access. */	outb(~EE_CS, ee_addr);	eeprom_delay();	return retval;}static const unsigned int rtl8139_rx_config = 	(RX_BUF_LEN_IDX << 11) |	(RX_FIFO_THRESH << 13) |	(RX_DMA_BURST << 8);	static void set_rx_mode(struct nic *nic) {	unsigned int mc_filter[2];	int rx_mode;	/* !IFF_PROMISC */	rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;	mc_filter[1] = mc_filter[0] = 0xffffffff;	outl(rtl8139_rx_config | rx_mode, ioaddr + RxConfig);	outl(mc_filter[0], ioaddr + MAR0 + 0);	outl(mc_filter[1], ioaddr + MAR0 + 4);}	static void rtl_reset(struct nic* nic){	int i;	outb(CmdReset, ioaddr + ChipCmd);	cur_rx = 0;	cur_tx = 0;	/* Give the chip 10ms to finish the reset. */	load_timer2(10*TICKS_PER_MS);	while ((inb(ioaddr + ChipCmd) & CmdReset) != 0 && timer2_running())		/* wait */;	for (i = 0; i < ETH_ALEN; i++)		outb(nic->node_addr[i], ioaddr + MAC0 + i);	/* Must enable Tx/Rx before setting transfer thresholds! */	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);	outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8),		ioaddr + RxConfig);		/* accept no frames yet!  */	outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);	/* 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.  */#ifdef	DEBUG_RX	printf("rx ring address is %X\n",(unsigned long)rx_ring);#endif	outl((unsigned long)virt_to_bus(rx_ring), ioaddr + RxBuf);	/* 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.  */	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);		outl(rtl8139_rx_config, ioaddr + RxConfig);		/* Start the chip's Tx and Rx process. */	outl(0, ioaddr + RxMissed);	/* set_rx_mode */	set_rx_mode(nic);		/* Disable all known interrupts by setting the interrupt mask. */	outw(0, ioaddr + IntrMask);}static void rtl_transmit(struct nic *nic, const char *destaddr,	unsigned int type, unsigned int len, const char *data){	unsigned int status, to, nstype;	unsigned long txstatus;	/* nstype assignment moved up here to avoid gcc 3.0.3 compiler bug */	nstype = htons(type);	memcpy(tx_buffer, destaddr, ETH_ALEN);	memcpy(tx_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);	memcpy(tx_buffer + 2 * ETH_ALEN, &nstype, 2);	memcpy(tx_buffer + ETH_HLEN, data, len);	len += ETH_HLEN;#ifdef	DEBUG_TX	printf("sending %d bytes ethtype %hX\n", len, type);#endif	/* 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';	}	outl((unsigned long)virt_to_bus(tx_buffer), ioaddr + TxAddr0 + cur_tx*4);	outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len,		ioaddr + TxStatus0 + cur_tx*4);	to = currticks() + RTL_TIMEOUT;	do {		status = inw(ioaddr + IntrStatus);		/* Only acknlowledge interrupt sources we can properly handle		 * here - the RxOverflow/RxFIFOOver MUST be handled in the		 * rtl_poll() function.  */		outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus);		if ((status & (TxOK | TxErr | PCIErr)) != 0) break;	} while (currticks() < to);	txstatus = inl(ioaddr+ TxStatus0 + cur_tx*4);	if (status & TxOK) {		cur_tx = (cur_tx + 1) % NUM_TX_DESC;#ifdef	DEBUG_TX		printf("tx done (%d ticks), status %hX txstatus %X\n",			to-currticks(), status, txstatus);#endif	} else {#ifdef	DEBUG_TX		printf("tx timeout/error (%d ticks), status %hX txstatus %X\n",			currticks()-to, status, txstatus);#endif		rtl_reset(nic);	}}static int rtl_poll(struct nic *nic){	unsigned int status;	unsigned int ring_offs;	unsigned int rx_size, rx_status;	if (inb(ioaddr + ChipCmd) & RxBufEmpty) {		return 0;	}	status = inw(ioaddr + IntrStatus);	/* See below for the rest of the interrupt acknowledges.  */	outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);#ifdef	DEBUG_RX	printf("rtl_poll: int %hX ", status);#endif	ring_offs = cur_rx % RX_BUF_LEN;	rx_status = *(unsigned int*)(rx_ring + ring_offs);	rx_size = rx_status >> 16;	rx_status &= 0xffff;	if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) ||	    (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) {		printf("rx error %hX\n", rx_status);		rtl_reset(nic);	/* this clears all interrupts still pending */		return 0;	}	/* Received a good packet */	nic->packetlen = rx_size - 4;	/* no one cares about the FCS */	if (ring_offs+4+rx_size-4 > RX_BUF_LEN) {		int semi_count = RX_BUF_LEN - ring_offs - 4;		memcpy(nic->packet, rx_ring + ring_offs + 4, semi_count);		memcpy(nic->packet+semi_count, rx_ring, rx_size-4-semi_count);#ifdef	DEBUG_RX		printf("rx packet %d+%d bytes", semi_count,rx_size-4-semi_count);#endif	} else {		memcpy(nic->packet, rx_ring + ring_offs + 4, nic->packetlen);#ifdef	DEBUG_RX		printf("rx packet %d bytes", rx_size-4);#endif	}#ifdef	DEBUG_RX	printf(" at %X type %hhX%hhX rxstatus %hX\n",		(unsigned long)(rx_ring+ring_offs+4),		nic->packet[12], nic->packet[13], rx_status);#endif	cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;	outw(cur_rx - 16, ioaddr + RxBufPtr);	/* See RTL8139 Programming Guide V0.1 for the official handling of	 * Rx overflow situations.  The document itself contains basically no	 * usable information, except for a few exception handling rules.  */	outw(status & (RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);	return 1;}static void rtl_disable(struct dev *dev){	struct nic *nic = (struct nic *)dev;	/* merge reset and disable */	rtl_reset(nic);	/* reset the chip */	outb(CmdReset, ioaddr + ChipCmd);	/* 10 ms timeout */	load_timer2(10*TICKS_PER_MS);	while ((inb(ioaddr + ChipCmd) & CmdReset) != 0 && timer2_running())		/* wait */;}static struct pci_id rtl8139_nics[] = {PCI_ROM(0x10ec, 0x8129, "rtl8129",       "Realtek 8129"),PCI_ROM(0x10ec, 0x8139, "rtl8139",       "Realtek 8139"),PCI_ROM(0x10ec, 0x8138, "rtl8139b",      "Realtek 8139B"),PCI_ROM(0x1186, 0x1300, "dfe538",        "DFE530TX+/DFE538TX"),PCI_ROM(0x1113, 0x1211, "smc1211-1",     "SMC EZ10/100"),PCI_ROM(0x1112, 0x1211, "smc1211",       "SMC EZ10/100"),PCI_ROM(0x1500, 0x1360, "delta8139",     "Delta Electronics 8139"),PCI_ROM(0x4033, 0x1360, "addtron8139",   "Addtron Technology 8139"),PCI_ROM(0x1186, 0x1340, "dfe690txd",     "D-Link DFE690TXD"),PCI_ROM(0x13d1, 0xab06, "fe2000vx",      "AboCom FE2000VX"),PCI_ROM(0x1259, 0xa117, "allied8139",    "Allied Telesyn 8139"),PCI_ROM(0x14ea, 0xab06, "fnw3603tx",     "Planex FNW-3603-TX"),PCI_ROM(0x14ea, 0xab07, "fnw3800tx",     "Planex FNW-3800-TX"),PCI_ROM(0xffff, 0x8139, "clone-rtl8139", "Cloned 8139"),};static struct pci_driver rtl8139_driver __pci_driver = {	.type     = NIC_DRIVER,	.name     = "RTL8139",	.probe    = rtl8139_probe,	.ids      = rtl8139_nics,	.id_count = sizeof(rtl8139_nics)/sizeof(rtl8139_nics[0]),	.class    = 0,};

⌨️ 快捷键说明

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