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

📄 lance.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************Etherboot -  BOOTP/TFTP Bootstrap ProgramLANCE NIC driver for EtherbootLarge portions borrowed from the Linux LANCE driver by Donald BeckerKen Yap, July 1997***************************************************************************//* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. *//* to get some global routines like printf */#include "etherboot.h"/* to get the interface to the body of the program */#include "nic.h"#ifdef	INCLUDE_LANCE#include "pci.h"#endif#include "cards.h"/* Offsets from base I/O address */#if	defined(INCLUDE_NE2100) || defined(INCLUDE_LANCE)#define	LANCE_ETH_ADDR	0x0#define	LANCE_DATA	0x10#define	LANCE_ADDR	0x12#define	LANCE_RESET	0x14#define	LANCE_BUS_IF	0x16#define	LANCE_TOTAL_SIZE	0x18#endif#ifdef	INCLUDE_NI6510#define	LANCE_ETH_ADDR	0x8#define	LANCE_DATA	0x0#define	LANCE_ADDR	0x2#define	LANCE_RESET	0x4#define	LANCE_BUS_IF	0x6#define	LANCE_TOTAL_SIZE	0x10#endif/* lance_poll() now can use multiple Rx buffers to prevent packet loss. Set * Set LANCE_LOG_RX_BUFFERS to 0..7 for 1, 2, 4, 8, 16, 32, 64 or 128 Rx * buffers. Usually 4 (=16 Rx buffers) is a good value. (Andreas Neuhaus) * Decreased to 2 (=4 Rx buffers) (Ken Yap, 20010305) */#define LANCE_LOG_RX_BUFFERS	2		/* Use 2^2=4 Rx buffers */#define RX_RING_SIZE		(1 << (LANCE_LOG_RX_BUFFERS))#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)#define RX_RING_LEN_BITS	((LANCE_LOG_RX_BUFFERS) << 29)struct lance_init_block{	unsigned short	mode;	unsigned char	phys_addr[ETH_ALEN];	unsigned long	filter[2];	Address		rx_ring;	Address		tx_ring;};struct lance_rx_head{	union {		Address		base;		unsigned char	addr[4];	} u;	short		buf_length;	/* 2s complement */	short		msg_length;};struct lance_tx_head{	union {		Address		base;		unsigned char	addr[4];	} u;	short		buf_length;	/* 2s complement */	short		misc;};struct lance_interface{	struct lance_init_block	init_block;	struct lance_rx_head	rx_ring[RX_RING_SIZE];	struct lance_tx_head	tx_ring;	unsigned char		rbuf[RX_RING_SIZE][ETH_FRAME_LEN+4];	unsigned char		tbuf[ETH_FRAME_LEN];	/*	 * Do not alter the order of the struct members above;	 * the hardware depends on the correct alignment.	 */	int			rx_idx;};#define	LANCE_MUST_PAD		0x00000001#define	LANCE_ENABLE_AUTOSELECT	0x00000002#define	LANCE_SELECT_PHONELINE	0x00000004#define	LANCE_MUST_UNRESET	0x00000008/* A mapping from the chip ID number to the part number and features.   These are from the datasheets -- in real life the '970 version   reportedly has the same ID as the '965. */static const struct lance_chip_type{	int	id_number;	const char	*name;	int	flags;} chip_table[] = {	{0x0000, "LANCE 7990",			/* Ancient lance chip.  */		LANCE_MUST_PAD + LANCE_MUST_UNRESET},	{0x0003, "PCnet/ISA 79C960",		/* 79C960 PCnet/ISA.  */		LANCE_ENABLE_AUTOSELECT},	{0x2260, "PCnet/ISA+ 79C961",		/* 79C961 PCnet/ISA+, Plug-n-Play.  */		LANCE_ENABLE_AUTOSELECT},	{0x2420, "PCnet/PCI 79C970",		/* 79C970 or 79C974 PCnet-SCSI, PCI. */		LANCE_ENABLE_AUTOSELECT},	/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call		it the PCnet32. */	{0x2430, "PCnet32",			/* 79C965 PCnet for VL bus. */		LANCE_ENABLE_AUTOSELECT},        {0x2621, "PCnet/PCI-II 79C970A",        /* 79C970A PCInetPCI II. */                LANCE_ENABLE_AUTOSELECT},	{0x2625, "PCnet-FAST III 79C973",	/* 79C973 PCInet-FAST III. */		LANCE_ENABLE_AUTOSELECT},        {0x2626, "PCnet/HomePNA 79C978",                        LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},	{0x0, "PCnet (unknown)",		LANCE_ENABLE_AUTOSELECT},};/* Define a macro for converting program addresses to real addresses */#undef	virt_to_bus#define	virt_to_bus(x)		((unsigned long)x)static int			chip_version;static int			lance_version;static unsigned short		ioaddr;#ifndef	INCLUDE_LANCEstatic int			dma;#endifstatic struct lance_interface	*lp;/* additional 8 bytes for 8-byte alignment space */#ifdef	USE_LOWMEM_BUFFER#define lance ((char *)0x10000 - (sizeof(struct lance_interface)+8))#elsestatic char			lance[sizeof(struct lance_interface)+8];#endif#ifndef	INCLUDE_LANCE/* DMA defines and helper routines *//* DMA controller registers */#define DMA1_CMD_REG		0x08	/* command register (w) */#define DMA1_STAT_REG		0x08	/* status register (r) */#define DMA1_REQ_REG            0x09    /* request register (w) */#define DMA1_MASK_REG		0x0A	/* single-channel mask (w) */#define DMA1_MODE_REG		0x0B	/* mode register (w) */#define DMA1_CLEAR_FF_REG	0x0C	/* clear pointer flip-flop (w) */#define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */#define DMA1_RESET_REG		0x0D	/* Master Clear (w) */#define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */#define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */#define DMA2_CMD_REG		0xD0	/* command register (w) */#define DMA2_STAT_REG		0xD0	/* status register (r) */#define DMA2_REQ_REG            0xD2    /* request register (w) */#define DMA2_MASK_REG		0xD4	/* single-channel mask (w) */#define DMA2_MODE_REG		0xD6	/* mode register (w) */#define DMA2_CLEAR_FF_REG	0xD8	/* clear pointer flip-flop (w) */#define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */#define DMA2_RESET_REG		0xDA	/* Master Clear (w) */#define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */#define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only *//* enable/disable a specific DMA channel */static void enable_dma(unsigned int dmanr){	if (dmanr <= 3)		outb_p(dmanr, DMA1_MASK_REG);	else		outb_p(dmanr & 3, DMA2_MASK_REG);}static void disable_dma(unsigned int dmanr){	if (dmanr <= 3)		outb_p(dmanr | 4, DMA1_MASK_REG);	else		outb_p((dmanr & 3) | 4, DMA2_MASK_REG);}/* set mode (above) for a specific DMA channel */static void set_dma_mode(unsigned int dmanr, char mode){	if (dmanr <= 3)		outb_p(mode | dmanr, DMA1_MODE_REG);	else		outb_p(mode | (dmanr&3), DMA2_MODE_REG);}#endif	/* !INCLUDE_LANCE *//**************************************************************************RESET - Reset adapter***************************************************************************/static void lance_reset(struct nic *nic){	int		i;	Address		l;	/* Reset the LANCE */	(void)inw(ioaddr+LANCE_RESET);	/* Un-Reset the LANCE, needed only for the NE2100 */	if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)		outw(0, ioaddr+LANCE_RESET);	if (chip_table[lance_version].flags & LANCE_ENABLE_AUTOSELECT)	{		/* This is 79C960 specific; Turn on auto-select of media		   (AUI, BNC). */		outw(0x2, ioaddr+LANCE_ADDR);		/* Don't touch 10base2 power bit. */		outw(inw(ioaddr+LANCE_BUS_IF) | 0x2, ioaddr+LANCE_BUS_IF);	}	/* HomePNA cards need to explicitly pick the phoneline interface.	 * Some of these cards have ethernet interfaces as well, this	 * code might require some modification for those.  	 */        if (chip_table[lance_version].flags & LANCE_SELECT_PHONELINE) {                short media, check ;                /* this is specific to HomePNA cards... */                outw(49, ioaddr+0x12) ;                media = inw(ioaddr+0x16) ;#ifdef DEBUG                printf("media was %d\n", media) ;#endif                media &= ~3 ;                media |= 1 ;#ifdef DEBUG                printf("media changed to %d\n", media) ;#endif                media &= ~3 ;                media |= 1 ;                outw(49, ioaddr+0x12) ;                outw(media, ioaddr+0x16) ;                outw(49, ioaddr+0x12) ;                check = inw(ioaddr+0x16) ;#ifdef DEBUG                printf("check %s, media was set properly\n", 			check ==  media ? "passed" : "FAILED" ) ; #endif	} 	/* Re-initialise the LANCE, and start it when done. */	/* Set station address */	for (i = 0; i < ETH_ALEN; ++i)		lp->init_block.phys_addr[i] = nic->node_addr[i];	/* Preset the receive ring headers */	for (i=0; i<RX_RING_SIZE; i++) {		lp->rx_ring[i].buf_length = -ETH_FRAME_LEN-4;		/* OWN */		lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;		/* we set the top byte as the very last thing */		lp->rx_ring[i].u.addr[3] = 0x80;	}	lp->rx_idx = 0;	lp->init_block.mode = 0x0;	/* enable Rx and Tx */	l = (Address)virt_to_bus(&lp->init_block);	outw(0x1, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw((short)l, ioaddr+LANCE_DATA);	outw(0x2, ioaddr+LANCE_ADDR);	(void)inw(ioaddr+LANCE_ADDR);	outw((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);

⌨️ 快捷键说明

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