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

📄 ns83820.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
static void ns83820_set_multicast(struct nic *nic __unused);static void ns83820_setup_rx(struct nic *nic){	unsigned i;	ns->idle = 1;	ns->next_rx = 0;	ns->next_rx_desc = ns->descs;	ns->next_empty = 0;	ns->cur_rx = 0;	for (i = 0; i < NR_RX_DESC; i++) {		rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);		rx_ring[i].bufptr =		    virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]);		rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);		rx_ring[i].extsts = cpu_to_le32(0);	}//      No need to wrap the ring //      rx_ring[i].link = virt_to_le32desc(&rx_ring[0]);	writel(0, ns->base + RXDP_HI);	writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP);	dprintf(("starting receiver\n"));	writel(0x0001, ns->base + CCSR);	writel(0, ns->base + RFCR);	writel(0x7fc00000, ns->base + RFCR);	writel(0xffc00000, ns->base + RFCR);	ns->up = 1;	phy_intr(nic);	/* Okay, let it rip */	ns->IMR_cache |= ISR_PHY;	ns->IMR_cache |= ISR_RXRCMP;	//dev->IMR_cache |= ISR_RXERR;	//dev->IMR_cache |= ISR_RXOK;	ns->IMR_cache |= ISR_RXORN;	ns->IMR_cache |= ISR_RXSOVR;	ns->IMR_cache |= ISR_RXDESC;	ns->IMR_cache |= ISR_RXIDLE;	ns->IMR_cache |= ISR_TXDESC;	ns->IMR_cache |= ISR_TXIDLE;	// No reason to enable interupts...	// writel(ns->IMR_cache, ns->base + IMR);	// writel(1, ns->base + IER);	ns83820_set_multicast(nic);	kick_rx();}static void ns83820_do_reset(struct nic *nic __unused, u32 which){	dprintf(("resetting chip...\n"));	writel(which, ns->base + CR);	do {	} while (readl(ns->base + CR) & which);	dprintf(("okay!\n"));}static void ns83820_reset(struct nic *nic){	unsigned i;	dprintf(("ns83820_reset\n"));	writel(0, ns->base + PQCR);	ns83820_setup_rx(nic);	for (i = 0; i < NR_TX_DESC; i++) {		tx_ring[i].link = 0;		tx_ring[i].bufptr = 0;		tx_ring[i].cmdsts = cpu_to_le32(0);		tx_ring[i].extsts = cpu_to_le32(0);	}	ns->tx_idx = 0;	ns->tx_done_idx = 0;	writel(0, ns->base + TXDP_HI);	return;}static void ns83820_getmac(struct nic *nic __unused, u8 * mac){	unsigned i;	for (i = 0; i < 3; i++) {		u32 data;		/* Read from the perfect match memory: this is loaded by		 * the chip from the EEPROM via the EELOAD self test.		 */		writel(i * 2, ns->base + RFCR);		data = readl(ns->base + RFDR);		*mac++ = data;		*mac++ = data >> 8;	}}static void ns83820_set_multicast(struct nic *nic __unused){	u8 *rfcr = ns->base + RFCR;	u32 and_mask = 0xffffffff;	u32 or_mask = 0;	u32 val;	/* Support Multicast */	and_mask &= ~(RFCR_AAU | RFCR_AAM);	or_mask |= RFCR_AAM;	val = (readl(rfcr) & and_mask) | or_mask;	/* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */	writel(val & ~RFCR_RFEN, rfcr);	writel(val, rfcr);}static void ns83820_run_bist(struct nic *nic __unused, const char *name,			     u32 enable, u32 done, u32 fail){	int timed_out = 0;	long start;	u32 status;	int loops = 0;	dprintf(("start %s\n", name))	    start = currticks();	writel(enable, ns->base + PTSCR);	for (;;) {		loops++;		status = readl(ns->base + PTSCR);		if (!(status & enable))			break;		if (status & done)			break;		if (status & fail)			break;		if ((currticks() - start) >= HZ) {			timed_out = 1;			break;		}	}	if (status & fail)		printf("%s failed! (0x%hX & 0x%hX)\n", name, status, fail);	else if (timed_out)		printf("run_bist %s timed out! (%hX)\n", name, status);	dprintf(("done %s in %d loops\n", name, loops));}/*************************************Check Link*************************************/static void ns83820_check_intr(struct nic *nic) {	int i;	u32 isr = readl(ns->base + ISR);	if(ISR_PHY & isr)		phy_intr(nic);	if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr)		kick_rx();	for (i = 0; i < NR_RX_DESC; i++) {		if (rx_ring[i].cmdsts == CMDSTS_OWN) {//			rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);			rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);		}	}}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int ns83820_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 */	u32 cmdsts;	int entry = ns->cur_rx;	ns83820_check_intr(nic);	cmdsts = le32_to_cpu(rx_ring[entry].cmdsts);	if ((CMDSTS_OWN & (cmdsts)) && (cmdsts != CMDSTS_OWN)) {		if (CMDSTS_OK & cmdsts) {			int len = cmdsts & 0xffff;			nic->packetlen = len;			memcpy(nic->packet,			       rxb + (entry * REAL_RX_BUF_SIZE),			       nic->packetlen);//			rx_ring[entry].link = 0;			rx_ring[entry].cmdsts =			    cpu_to_le32(CMDSTS_OWN);			ns->cur_rx = ++ns->cur_rx % NR_RX_DESC;			if (ns->cur_rx == 0)	/* We have wrapped the ring */				kick_rx();			return 1;		}	}	return 0;		/* initially as this is called to flush the input */}static inline void kick_tx(struct nic *nic __unused){	dprintf(("kick_tx\n"));	writel(CR_TXE, ns->base + CR);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void ns83820_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 */	u16 nstype;	u32 cmdsts, extsts;	int cur_tx = 0;	u32 isr = readl(ns->base + ISR);	if (ISR_TXIDLE & isr)		kick_tx(nic);	/* point to the current txb incase multiple tx_rings are used */	memcpy(txb, d, ETH_ALEN);	memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);	nstype = htons((u16) t);	memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);	memcpy(txb + ETH_HLEN, p, s);	s += ETH_HLEN;	s &= 0x0FFF;	while (s < ETH_ZLEN)		txb[s++] = '\0';	/* Setup the transmit descriptor */	extsts = 0;	extsts |= EXTSTS_UDPPKT;	tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb);	tx_ring[cur_tx].extsts = cpu_to_le32(extsts);	cmdsts = cpu_to_le32(0);	cmdsts |= cpu_to_le32(CMDSTS_OWN | s);	tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts);	writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP);	kick_tx(nic);}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void ns83820_disable(struct dev *dev){	/* 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.	 */	/* disable interrupts */	writel(0, ns->base + IMR);	writel(0, ns->base + IER);	readl(ns->base + IER);	ns->up = 0;	ns83820_do_reset((struct nic *) dev, CR_RST);	ns->IMR_cache &=	    ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY |	      ISR_RXIDLE);	writel(ns->IMR_cache, ns->base + IMR);	/* touch the pci bus... */	readl(ns->base + IMR);	/* assumes the transmitter is already disabled and reset */	writel(0, ns->base + RXDP_HI);	writel(0, ns->base + RXDP);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/#define board_found 1#define valid_link 0static int ns83820_probe(struct dev *dev, struct pci_device *pci){	struct nic *nic = (struct nic *) dev;	int sz;	long addr;	int using_dac = 0;	if (pci->ioaddr == 0)		return 0;	printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n",	       pci->name, pci->vendor, pci->dev_id);	/* point to private storage */	ns = &nsx;	adjust_pci_device(pci);	addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1);	sz = pci_bar_size(pci, PCI_BASE_ADDRESS_1);	ns->base = ioremap(addr, (1UL << 12));//      ns->base = ioremap(addr, sz);	if (!ns->base)		return 0;	/* disable interrupts */	writel(0, ns->base + IMR);	writel(0, ns->base + IER);	readl(ns->base + IER);	ns->IMR_cache = 0;	ns83820_do_reset(nic, CR_RST);	/* Must reset the ram bist before running it */	writel(PTSCR_RBIST_RST, ns->base + PTSCR);	ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN,			 PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL);	ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0,			 PTSCR_EEBIST_FAIL);	ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0);	/* I love config registers */	ns->CFG_cache = readl(ns->base + CFG);	if ((ns->CFG_cache & CFG_PCI64_DET)) {		printf("%s: detected 64 bit PCI data bus.\n", pci->name);		/*dev->CFG_cache |= CFG_DATA64_EN; */		if (!(ns->CFG_cache & CFG_DATA64_EN))			printf			    ("%s: EEPROM did not enable 64 bit bus.  Disabled.\n",			     pci->name);	} else		ns->CFG_cache &= ~(CFG_DATA64_EN);	ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS |			  CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 |			  CFG_M64ADDR);	ns->CFG_cache |=	    CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS |	    CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL;	ns->CFG_cache |= CFG_REQALG;	ns->CFG_cache |= CFG_POW;	ns->CFG_cache |= CFG_TMRTEST;	/* When compiled with 64 bit addressing, we must always enable	 * the 64 bit descriptor format.	 */#ifdef USE_64BIT_ADDR	ns->CFG_cache |= CFG_M64ADDR;#endif//FIXME: Enable section on dac or remove this	if (using_dac)		ns->CFG_cache |= CFG_T64ADDR;	/* Big endian mode does not seem to do what the docs suggest */	ns->CFG_cache &= ~CFG_BEM;	/* setup optical transceiver if we have one */	if (ns->CFG_cache & CFG_TBI_EN) {		dprintf(("%s: enabling optical transceiver\n", pci->name));		writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR);		/* setup auto negotiation feature advertisement */		writel(readl(ns->base + TANAR)		       | TANAR_HALF_DUP | TANAR_FULL_DUP,		       ns->base + TANAR);		/* start auto negotiation */		writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,		       ns->base + TBICR);		writel(TBICR_MR_AN_ENABLE, ns->base + TBICR);		ns->linkstate = LINK_AUTONEGOTIATE;		ns->CFG_cache |= CFG_MODE_1000;	}	writel(ns->CFG_cache, ns->base + CFG);	dprintf(("CFG: %hX\n", ns->CFG_cache));	/* FIXME: reset_phy is defaulted to 0, should we reset anyway? */	if (reset_phy) {		dprintf(("%s: resetting phy\n", pci->name));		writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG);		writel(ns->CFG_cache, ns->base + CFG);	}#if 0				/* Huh?  This sets the PCI latency register.  Should be done via 				 * the PCI layer.  FIXME.				 */	if (readl(dev->base + SRR))		writel(readl(dev->base + 0x20c) | 0xfe00,		       dev->base + 0x20c);#endif	/* Note!  The DMA burst size interacts with packet	 * transmission, such that the largest packet that	 * can be transmitted is 8192 - FLTH - burst size.	 * If only the transmit fifo was larger...	 */	/* Ramit : 1024 DMA is not a good idea, it ends up banging 	 * some DELL and COMPAQ SMP systems */	writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512	       | ((1600 / 32) * 0x100), ns->base + TXCFG);	/* Set Rx to full duplex, don't accept runt, errored, long or length	 * range errored packets.  Use 512 byte DMA.	 */	/* Ramit : 1024 DMA is not a good idea, it ends up banging 	 * some DELL and COMPAQ SMP systems 	 * Turn on ALP, only we are accpeting Jumbo Packets */	writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD	       | RXCFG_STRIPCRC	       //| RXCFG_ALP	       | (RXCFG_MXDMA512) | 0, ns->base + RXCFG);	/* Disable priority queueing */	writel(0, ns->base + PQCR);	/* Enable IP checksum validation and detetion of VLAN headers.	 * Note: do not set the reject options as at least the 0x102	 * revision of the chip does not properly accept IP fragments	 * at least for UDP.	 */	/* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since	 * the MAC it calculates the packetsize AFTER stripping the VLAN	 * header, and if a VLAN Tagged packet of 64 bytes is received (like	 * a ping with a VLAN header) then the card, strips the 4 byte VLAN	 * tag and then checks the packet size, so if RXCFG_ARP is not enabled,	 * it discrards it!.  These guys......	 */	writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR);	/* Enable per-packet TCP/UDP/IP checksumming */	writel(VTCR_PPCHK, ns->base + VTCR);	/* Ramit : Enable async and sync pause frames *///      writel(0, ns->base + PCR); 	writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K |		PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT),	       ns->base + PCR);	/* Disable Wake On Lan */	writel(0, ns->base + WCSR);	ns83820_getmac(nic, nic->node_addr);	printf("%! at ioaddr 0x%hX, ", nic->node_addr, ns->base);	if (using_dac) {		dprintf(("%s: using 64 bit addressing.\n", pci->name));	}	dprintf(("%s: DP83820 %d.%d: %! io=0x%hX\n",		 pci->name,		 (unsigned) readl(ns->base + SRR) >> 8,		 (unsigned) readl(ns->base + SRR) & 0xff,		 nic->node_addr, pci->ioaddr));#ifdef PHY_CODE_IS_FINISHED	ns83820_probe_phy(dev);#endif	ns83820_reset(nic);	/* point to NIC specific routines */	dev->disable = ns83820_disable;	nic->poll = ns83820_poll;	nic->transmit = ns83820_transmit;	return 1;}static struct pci_id ns83820_nics[] = {	PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820"),};static struct pci_driver ns83820_driver __pci_driver = {	.type = NIC_DRIVER,	.name = "NS83820/PCI",	.probe = ns83820_probe,	.ids = ns83820_nics,	.id_count = sizeof(ns83820_nics) / sizeof(ns83820_nics[0]),	.class = 0,};

⌨️ 快捷键说明

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