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

📄 lance.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
	(void)inw(ioaddr+LANCE_ADDR);	outw(0x4, ioaddr+LANCE_DATA);		/* stop */	outw(0x1, ioaddr+LANCE_DATA);		/* init */	for (i = 10000; i > 0; --i)		if (inw(ioaddr+LANCE_DATA) & 0x100)			break;#ifdef	DEBUG	if (i <= 0)		printf("Init timed out\n");#endif	/* Apparently clearing the InitDone bit here triggers a bug	   in the '974. (Mark Stockton) */	outw(0x2, ioaddr+LANCE_DATA);		/* start */}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int lance_poll(struct nic *nic){	int		status;	status = lp->rx_ring[lp->rx_idx].u.base >> 24;	if (status & 0x80)		return (0);#ifdef	DEBUG	printf("LANCE packet received rx_ring.u.base %X mcnt %hX csr0 %hX\n",		lp->rx_ring[lp->rx_idx].u.base, lp->rx_ring[lp->rx_idx].msg_length,		inw(ioaddr+LANCE_DATA));#endif	if (status == 0x3)		memcpy(nic->packet, lp->rbuf[lp->rx_idx], nic->packetlen = lp->rx_ring[lp->rx_idx].msg_length);	/* Andrew Boyd of QNX reports that some revs of the 79C765	   clear the buffer length */	lp->rx_ring[lp->rx_idx].buf_length = -ETH_FRAME_LEN-4;	lp->rx_ring[lp->rx_idx].u.addr[3] |= 0x80;	/* prime for next receive */	/* I'm not sure if the following is still ok with multiple Rx buffers, but it works */	outw(0x0, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw(0x500, ioaddr+LANCE_DATA);		/* clear receive + InitDone */	/* Switch to the next Rx ring buffer */	lp->rx_idx = (lp->rx_idx + 1) & RX_RING_MOD_MASK;	return (status == 0x3);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void lance_transmit(	struct nic *nic,	const char *d,			/* Destination */	unsigned int t,			/* Type */	unsigned int s,			/* size */	const char *p)			/* Packet */{	unsigned long		time;	/* copy the packet to ring buffer */	memcpy(lp->tbuf, d, ETH_ALEN);	/* dst */	memcpy(&lp->tbuf[ETH_ALEN], nic->node_addr, ETH_ALEN); /* src */	lp->tbuf[ETH_ALEN+ETH_ALEN] = t >> 8;	/* type */	lp->tbuf[ETH_ALEN+ETH_ALEN+1] = t;	/* type */	memcpy(&lp->tbuf[ETH_HLEN], p, s);	s += ETH_HLEN;	if (chip_table[chip_version].flags & LANCE_MUST_PAD)		while (s < ETH_ZLEN)	/* pad to min length */			lp->tbuf[s++] = 0;	lp->tx_ring.buf_length = -s;	lp->tx_ring.misc = 0x0;	/* OWN, STP, ENP */	lp->tx_ring.u.base = virt_to_bus(lp->tbuf) & 0xffffff;	/* we set the top byte as the very last thing */	lp->tx_ring.u.addr[3] = 0x83;	/* Trigger an immediate send poll */	outw(0x0, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	/* as in the datasheets... */	/* Klaus Espenlaub: the value below was 0x48, but that enabled the	 * interrupt line, causing a hang if for some reasone the interrupt	 * controller had the LANCE interrupt enabled.  I have no idea why	 * nobody ran into this before...  */	outw(0x08, ioaddr+LANCE_DATA);	/* wait for transmit complete */	time = currticks() + TICKS_PER_SEC;		/* wait one second */	while (currticks() < time && (lp->tx_ring.u.base & 0x80000000) != 0)		;	if ((lp->tx_ring.u.base & 0x80000000) != 0)		printf("LANCE timed out on transmit\n");	(void)inw(ioaddr+LANCE_ADDR);	outw(0x200, ioaddr+LANCE_DATA);		/* clear transmit + InitDone */#ifdef	DEBUG	printf("tx_ring.u.base %X tx_ring.buf_length %hX tx_ring.misc %hX csr0 %hX\n",		lp->tx_ring.u.base, lp->tx_ring.buf_length, lp->tx_ring.misc,		inw(ioaddr+LANCE_DATA));#endif}static void lance_disable(struct nic *nic){	(void)inw(ioaddr+LANCE_RESET);	if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)		outw(0, ioaddr+LANCE_RESET);	outw(0, ioaddr+LANCE_ADDR);	outw(0x0004, ioaddr+LANCE_DATA);	/* stop the LANCE */#ifndef	INCLUDE_LANCE	disable_dma(dma);#endif}#ifdef	INCLUDE_LANCEstatic int lance_probe1(struct nic *nic, struct pci_device *pci)#elsestatic int lance_probe1(struct nic *nic)#endif{	int			reset_val ;	unsigned int		i;	Address			l;	short			dma_channels;#ifndef	INCLUDE_LANCE	static const char	dmas[] = { 5, 6, 7, 3 };#endif	reset_val = inw(ioaddr+LANCE_RESET);	outw(reset_val, ioaddr+LANCE_RESET);#if	1  /* Klaus Espenlaub -- was #ifdef	INCLUDE_NE2100*/	outw(0x0, ioaddr+LANCE_ADDR);	/* Switch to window 0 */	if (inw(ioaddr+LANCE_DATA) != 0x4)		return (-1);#endif	outw(88, ioaddr+LANCE_ADDR);	/* Get the version of the chip */	if (inw(ioaddr+LANCE_ADDR) != 88)		lance_version = 0;	else	{		chip_version = inw(ioaddr+LANCE_DATA);		outw(89, ioaddr+LANCE_ADDR);		chip_version |= inw(ioaddr+LANCE_DATA) << 16;		if ((chip_version & 0xfff) != 0x3)			return (-1);		chip_version = (chip_version >> 12) & 0xffff;		for (lance_version = 1; chip_table[lance_version].id_number != 0; ++lance_version)			if (chip_table[lance_version].id_number == chip_version)				break;	}	/* make sure data structure is 8-byte aligned */	l = ((Address)lance + 7) & ~7;	lp = (struct lance_interface *)l;	lp->init_block.mode = 0x3;	/* disable Rx and Tx */	lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;	/* using multiple Rx buffer and a single Tx buffer */	lp->init_block.rx_ring = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;	lp->init_block.tx_ring = virt_to_bus(&lp->tx_ring) & 0xffffff;	l = virt_to_bus(&lp->init_block);	outw(0x1, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw((unsigned short)l, ioaddr+LANCE_DATA);	outw(0x2, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw((unsigned short)(l >> 16), ioaddr+LANCE_DATA);	outw(0x4, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw(0x915, ioaddr+LANCE_DATA);	outw(0x0, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	/* Get station address */	for (i = 0; i < ETH_ALEN; ++i) {		nic->node_addr[i] = inb(ioaddr+LANCE_ETH_ADDR+i);	}#ifndef	INCLUDE_LANCE	/* now probe for DMA channel */	dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0xf) |		(inb(DMA2_STAT_REG) & 0xf0);	/* need to fix when PCI provides DMA info */	for (i = 0; i < (sizeof(dmas)/sizeof(dmas[0])); ++i)	{		int		j;		dma = dmas[i];		/* Don't enable a permanently busy DMA channel,		   or the machine will hang */		if (dma_channels & (1 << dma))			continue;		outw(0x7f04, ioaddr+LANCE_DATA);	/* clear memory error bits */		set_dma_mode(dma, DMA_MODE_CASCADE);		enable_dma(dma);		outw(0x1, ioaddr+LANCE_DATA);		/* init */		for (j = 100; j > 0; --j)			if (inw(ioaddr+LANCE_DATA) & 0x900)				break;		if (inw(ioaddr+LANCE_DATA) & 0x100)			break;		else			disable_dma(dma);	}	if (i >= (sizeof(dmas)/sizeof(dmas[0])))		dma = 0;	printf("\n%s base %#X, DMA %d, addr %!\n",		chip_table[lance_version].name, ioaddr, dma, nic->node_addr);#else	printf(" %s base %#hX, addr %!\n", chip_table[lance_version].name, ioaddr, nic->node_addr);#endif	if (chip_table[chip_version].flags & LANCE_ENABLE_AUTOSELECT) {		/* Turn on auto-select of media (10baseT or BNC) so that the		 * user watch the LEDs. */		outw(0x0002, ioaddr+LANCE_ADDR);		/* Don't touch 10base2 power bit. */		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);	}	return (lance_version);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/#ifdef	INCLUDE_LANCEstruct nic *lancepci_probe(struct nic *nic, unsigned short *probe_addrs, struct pci_device *pci)#endif#ifdef	INCLUDE_NE2100struct nic *ne2100_probe(struct nic *nic, unsigned short *probe_addrs)#endif#ifdef	INCLUDE_NI6510struct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)#endif{	unsigned short		*p;#ifndef	INCLUDE_LANCE	static unsigned short	io_addrs[] = { 0x300, 0x320, 0x340, 0x360, 0 };#endif	/* if probe_addrs is 0, then routine can use a hardwired default */	if (probe_addrs == 0) {#ifdef	INCLUDE_LANCE		return 0;#else		probe_addrs = io_addrs;#endif	}	for (p = probe_addrs; (ioaddr = *p) != 0; ++p)	{		char	offset15, offset14 = inb(ioaddr + 14);		unsigned short	pci_cmd;#ifdef	INCLUDE_NE2100		if ((offset14 == 0x52 || offset14 == 0x57) &&		 ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))			if (lance_probe1(nic) >= 0)				break;#endif#ifdef	INCLUDE_NI6510		if ((offset14 == 0x00 || offset14 == 0x52) &&		 ((offset15 = inb(ioaddr + 15)) == 0x55 || offset15 == 0x44))			if (lance_probe1(nic) >= 0)				break;#endif#ifdef	INCLUDE_LANCE		adjust_pci_device(pci);		if (lance_probe1(nic, pci) >= 0)			break;#endif	}	/* if board found */	if (ioaddr != 0)	{		/* point to NIC specific routines */		lance_reset(nic);		nic->reset = lance_reset;		nic->poll = lance_poll;		nic->transmit = lance_transmit;		nic->disable = lance_disable;		return nic;	}	/* no board found */	return 0;}

⌨️ 快捷键说明

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