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

📄 forcedeth.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
	writel(NVREG_TXRXCTL_BIT2, base + NvRegTxRxControl);	pci_push(base);}/* * alloc_rx: fill rx ring entries. * Return 1 if the allocations for the skbs failed and the * rx engine is without Available descriptors */static int alloc_rx(struct nic *nic __unused){	unsigned int refill_rx = np->refill_rx;	int i;	//while (np->cur_rx != refill_rx) {	for (i = 0; i < RX_RING; i++) {		//int nr = refill_rx % RX_RING;		rx_ring[i].PacketBuffer =		    virt_to_le32desc(&rxb[i * RX_NIC_BUFSIZE]);		rx_ring[i].Length = cpu_to_le16(RX_NIC_BUFSIZE);		wmb();		rx_ring[i].Flags = cpu_to_le16(NV_RX_AVAIL);		/*      printf("alloc_rx: Packet  %d marked as Available\n",		   refill_rx); */		refill_rx++;	}	np->refill_rx = refill_rx;	if (np->cur_rx - refill_rx == RX_RING)		return 1;	return 0;}static int update_linkspeed(struct nic *nic){	int adv, lpa, newdup;	u32 newls;	adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);	lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);	dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n",		 adv, lpa));	/* FIXME: handle parallel detection properly, handle gigabit ethernet */	lpa = lpa & adv;	if (lpa & LPA_100FULL) {		newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;		newdup = 1;	} else if (lpa & LPA_100HALF) {		newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;		newdup = 0;	} else if (lpa & LPA_10FULL) {		newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;		newdup = 1;	} else if (lpa & LPA_10HALF) {		newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;		newdup = 0;	} else {		printf("bad ability %hX - falling back to 10HD.\n", lpa);		newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;		newdup = 0;	}	if (np->duplex != newdup || np->linkspeed != newls) {		np->duplex = newdup;		np->linkspeed = newls;		return 1;	}	return 0;}static int init_ring(struct nic *nic){	int i;	np->next_tx = np->nic_tx = 0;	for (i = 0; i < TX_RING; i++) {		tx_ring[i].Flags = 0;	}	np->cur_rx = 0;	np->refill_rx = 0;	for (i = 0; i < RX_RING; i++) {		rx_ring[i].Flags = 0;	}	return alloc_rx(nic);}static void set_multicast(struct nic *nic){	u8 *base = (u8 *) BASE;	u32 addr[2];	u32 mask[2];	u32 pff;	u32 alwaysOff[2];	u32 alwaysOn[2];	memset(addr, 0, sizeof(addr));	memset(mask, 0, sizeof(mask));	pff = NVREG_PFF_MYADDR;	alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;	addr[0] = alwaysOn[0];	addr[1] = alwaysOn[1];	mask[0] = alwaysOn[0] | alwaysOff[0];	mask[1] = alwaysOn[1] | alwaysOff[1];	addr[0] |= NVREG_MCASTADDRA_FORCE;	pff |= NVREG_PFF_ALWAYS;	stop_rx();	writel(addr[0], base + NvRegMulticastAddrA);	writel(addr[1], base + NvRegMulticastAddrB);	writel(mask[0], base + NvRegMulticastMaskA);	writel(mask[1], base + NvRegMulticastMaskB);	writel(pff, base + NvRegPacketFilterFlags);	start_rx(nic);}/**************************************************************************RESET - Reset the NIC to prepare for use***************************************************************************/static int forcedeth_reset(struct nic *nic){	u8 *base = (u8 *) BASE;	int ret, oom, i;	ret = 0;	dprintf(("forcedeth: open\n"));	/* 1) erase previous misconfiguration */	/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);	writel(0, base + NvRegMulticastAddrB);	writel(0, base + NvRegMulticastMaskA);	writel(0, base + NvRegMulticastMaskB);	writel(0, base + NvRegPacketFilterFlags);	writel(0, base + NvRegAdapterControl);	writel(0, base + NvRegLinkSpeed);	writel(0, base + NvRegUnknownTransmitterReg);	txrx_reset(nic);	writel(0, base + NvRegUnknownSetupReg6);	/* 2) initialize descriptor rings */	np->in_shutdown = 0;	oom = init_ring(nic);	/* 3) set mac address */	{		u32 mac[2];		mac[0] =		    (nic->node_addr[0] << 0) + (nic->node_addr[1] << 8) +		    (nic->node_addr[2] << 16) + (nic->node_addr[3] << 24);		mac[1] =		    (nic->node_addr[4] << 0) + (nic->node_addr[5] << 8);		writel(mac[0], base + NvRegMacAddrA);		writel(mac[1], base + NvRegMacAddrB);	}	/* 4) continue setup */	np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;	np->duplex = 0;	writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);	writel(0, base + NvRegTxRxControl);	pci_push(base);	writel(NVREG_TXRXCTL_BIT1, base + NvRegTxRxControl);	reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31,		  NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY,		  NV_SETUP5_DELAYMAX,		  "open: SetupReg5, Bit 31 remained off\n");	writel(0, base + NvRegUnknownSetupReg4);	/* 5) Find a suitable PHY */	writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed);	for (i = 1; i < 32; i++) {		int id1, id2;		id1 = mii_rw(nic, i, MII_PHYSID1, MII_READ);		if (id1 < 0)			continue;		id2 = mii_rw(nic, i, MII_PHYSID2, MII_READ);		if (id2 < 0)			continue;		dprintf(("open: Found PHY %04x:%04x at address %d.\n",			 id1, id2, i));		np->phyaddr = i;		update_linkspeed(nic);		break;	}	if (i == 32) {		printf("open: failing due to lack of suitable PHY.\n");		ret = -1;		goto out_drain;	}	printf("%d-Mbs Link, %s-Duplex\n",	       np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100,	       np->duplex ? "Full" : "Half");	/* 6) continue setup */	writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD),	       base + NvRegMisc1);	writel(readl(base + NvRegTransmitterStatus),	       base + NvRegTransmitterStatus);	writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);	writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);	writel(readl(base + NvRegReceiverStatus),	       base + NvRegReceiverStatus);	/* FIXME: I cheated and used the calculator to get a random number */	i = 75963081;	writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK),	       base + NvRegRandomSeed);	writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);	writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);	writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);	writel((np->		phyaddr << NVREG_ADAPTCTL_PHYSHIFT) |	       NVREG_ADAPTCTL_PHYVALID, base + NvRegAdapterControl);	writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);	writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);	/* 7) start packet processing */	writel((u32) virt_to_le32desc(&rx_ring[0]),	       base + NvRegRxRingPhysAddr);	writel((u32) virt_to_le32desc(&tx_ring[0]),	       base + NvRegTxRingPhysAddr);	writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) +	       ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT),	       base + NvRegRingSizes);	i = readl(base + NvRegPowerState);	if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) {		writel(NVREG_POWERSTATE_POWEREDUP | i,		       base + NvRegPowerState);	}	pci_push(base);	udelay(10);	writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID,	       base + NvRegPowerState);	writel(NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);	writel(0, base + NvRegIrqMask);	pci_push(base);	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);	pci_push(base);	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);	pci_push(base);/*	writel(np->irqmask, base + NvRegIrqMask);*/	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);	writel(0, base + NvRegMulticastAddrB);	writel(0, base + NvRegMulticastMaskA);	writel(0, base + NvRegMulticastMaskB);	writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR,	       base + NvRegPacketFilterFlags);	set_multicast(nic);	//start_rx(nic);	start_tx(nic);	if (!	    (mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) &	     BMSR_ANEGCOMPLETE)) {		printf("no link during initialization.\n");	}	udelay(10000);      out_drain:	return ret;}//extern void hex_dump(const char *data, const unsigned int len);/**************************************************************************POLL - Wait for a frame***************************************************************************/static int forcedeth_poll(struct nic *nic){	/* return true if there's an ethernet packet ready to read */	/* nic->packet should contain data on return */	/* nic->packetlen should contain length of data */	struct ring_desc *prd;	int len;	int i;	i = np->cur_rx % RX_RING;	prd = &rx_ring[i];	if (prd->Flags & cpu_to_le16(NV_RX_DESCRIPTORVALID)) {		/* got a valid packet - forward it to the network core */		len = cpu_to_le16(prd->Length);		nic->packetlen = len;		//hex_dump(rxb + (i * RX_NIC_BUFSIZE), len);		memcpy(nic->packet, rxb +		       (i * RX_NIC_BUFSIZE), nic->packetlen);		wmb();		np->cur_rx++;		alloc_rx(nic);		return 1;	}	return 0;		/* initially as this is called to flush the input */}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void forcedeth_transmit(struct nic *nic, const char *d,	/* Destination */			       unsigned int t,	/* Type */			       unsigned int s,	/* size */			       const char *p){				/* Packet */	/* send the packet to destination */	u8 *ptxb;	u16 nstype;	//u16 status;	u8 *base = (u8 *) BASE;	int nr = np->next_tx % TX_RING;	/* point to the current txb incase multiple tx_rings are used */	ptxb = txb + (nr * RX_NIC_BUFSIZE);	//np->tx_skbuff[nr] = ptxb;	/* copy the packet to ring buffer */	memcpy(ptxb, d, ETH_ALEN);	/* dst */	memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);	/* src */	nstype = htons((u16) t);	/* type */	memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);	/* type */	memcpy(ptxb + ETH_HLEN, p, s);	s += ETH_HLEN;	while (s < ETH_ZLEN)	/* pad to min length */		ptxb[s++] = '\0';	tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);	tx_ring[nr].Length = cpu_to_le16(s - 1);	wmb();	tx_ring[nr].Flags = np->tx_flags;	writel(NVREG_TXRXCTL_KICK, base + NvRegTxRxControl);	pci_push(base);	tx_ring[nr].Flags = np->tx_flags;	np->next_tx++;}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void forcedeth_disable(struct dev *dev __unused){	/* put the card in its initial state */	/* This function serves 3 purposes.	 * This disables DMA and interrupts so we don't receive	 *  unexpected packets or interrupts from the card after	 *  etherboot has finished. 	 * This frees resources so etherboot may use	 *  this driver on another interface	 * This allows etherboot to reinitialize the interface	 *  if something is something goes wrong.	 */	u8 *base = (u8 *) BASE;	np->in_shutdown = 1;	stop_tx();	stop_rx();	/* disable interrupts on the nic or we will lock up */	writel(0, base + NvRegIrqMask);	pci_push(base);	dprintf(("Irqmask is zero again\n"));	/* specia op:o write back the misordered MAC address - otherwise	 * the next probe_nic would see a wrong address.	 */	writel(np->orig_mac[0], base + NvRegMacAddrA);	writel(np->orig_mac[1], base + NvRegMacAddrB);}/** * is_valid_ether_addr - Determine if the given Ethernet address is valid * @addr: Pointer to a six-byte array containing the Ethernet address * * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not * a multicast address, and is not FF:FF:FF:FF:FF:FF.  The multicast * and FF:FF:... tests are combined into the single test "!(addr[0]&1)". * * Return true if the address is valid. */static inline int is_valid_ether_addr( u8 *addr ) {        const char zaddr[6] = {0,};                                                                                        return !(addr[0]&1) && memcmp( addr, zaddr, 6);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/#define IORESOURCE_MEM 0x00000200#define board_found 1#define valid_link 0static int forcedeth_probe(struct dev *dev, struct pci_device *pci){	struct nic *nic = (struct nic *) dev;	unsigned long addr;	int sz;	u8 *base;	if (pci->ioaddr == 0)		return 0;	printf("forcedeth.c: Found %s, vendor=0x%hX, device=0x%hX\n",	       pci->name, pci->vendor, pci->dev_id);	/* point to private storage */	np = &npx;	adjust_pci_device(pci);	addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0);	sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0);	/* BASE is used throughout to address the card */	BASE = (unsigned long) ioremap(addr, sz);	if (!BASE)		return 0;	//rx_ring[0] = rx_ring;	//tx_ring[0] = tx_ring; 	/* read the mac address */	base = (u8 *) BASE;	np->orig_mac[0] = readl(base + NvRegMacAddrA);	np->orig_mac[1] = readl(base + NvRegMacAddrB);	nic->node_addr[0] = (np->orig_mac[1] >> 8) & 0xff;	nic->node_addr[1] = (np->orig_mac[1] >> 0) & 0xff;	nic->node_addr[2] = (np->orig_mac[0] >> 24) & 0xff;	nic->node_addr[3] = (np->orig_mac[0] >> 16) & 0xff;	nic->node_addr[4] = (np->orig_mac[0] >> 8) & 0xff;	nic->node_addr[5] = (np->orig_mac[0] >> 0) & 0xff;	if (!is_valid_ether_addr(nic->node_addr)) {		/*		 * Bad mac address. At least one bios sets the mac address		 * to 01:23:45:67:89:ab		 */		printf("Invalid Mac address detected: %!\n",		       nic->node_addr);		printf("Please complain to your hardware vendor.\n");		return 0;	}	printf("%s: MAC Address %!, ", pci->name, nic->node_addr);	np->tx_flags =	    cpu_to_le16(NV_TX_LASTPACKET | NV_TX_LASTPACKET1 |			NV_TX_VALID);	switch (pci->dev_id) {	case 0x01C3:		// nforce		np->irqmask = NVREG_IRQMASK_WANTED_2;		np->irqmask |= NVREG_IRQ_TIMER;		break;	case 0x0066:		// nforce2		np->tx_flags |= cpu_to_le16(NV_TX_LASTPACKET1);		np->irqmask = NVREG_IRQMASK_WANTED_2;		np->irqmask |= NVREG_IRQ_TIMER;		break;	case 0x00D6:		// nforce3		np->tx_flags |= cpu_to_le16(NV_TX_LASTPACKET1);		np->irqmask = NVREG_IRQMASK_WANTED_2;		np->irqmask |= NVREG_IRQ_TIMER;	}	dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",		 pci->name, pci->vendor, pci->dev_id, pci->name));	forcedeth_reset(nic);//      if (board_found && valid_link)	/* point to NIC specific routines */	dev->disable = forcedeth_disable;	nic->poll = forcedeth_poll;	nic->transmit = forcedeth_transmit;	return 1;//      }	/* else */}static struct pci_id forcedeth_nics[] = {	PCI_ROM(0x10de, 0x01C3, "nforce", "nForce Ethernet Controller"),	PCI_ROM(0x10de, 0x0066, "nforce2", "nForce2 Ethernet Controller"),	PCI_ROM(0x10de, 0x00D6, "nforce3", "nForce3 Ethernet Controller"),};static struct pci_driver forcedeth_driver __pci_driver = {	.type = NIC_DRIVER,	.name = "forcedeth",	.probe = forcedeth_probe,	.ids = forcedeth_nics,	.id_count = sizeof(forcedeth_nics) / sizeof(forcedeth_nics[0]),	.class = 0,};

⌨️ 快捷键说明

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