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

📄 depca.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
#endifstatic enum {	DEPCA, DE100, DE101, DE200, DE201, DE202, DE210, DE212, DE422, unknown} adapter = DEPCA_MODEL;/*** Name <-> Adapter mapping*/static char *adapter_name[] = {	"DEPCA",	"DE100","DE101",	"DE200","DE201","DE202",	"DE210","DE212",	"DE422",	""};#ifndef	DEPCA_RAM_BASE#define DEPCA_RAM_BASE	0xd0000#endif/*** Memory Alignment. Each descriptor is 4 longwords long. To force a** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and** DESC_ALIGN. ALIGN aligns the start address of the private memory area** and hence the RX descriptor ring's first entry. */#define ALIGN4      ((u32)4 - 1)       /* 1 longword align */#define ALIGN8      ((u32)8 - 1)       /* 2 longword (quadword) align */#define ALIGN         ALIGN8              /* Keep the LANCE happy... */typedef	long		s32;typedef	unsigned long	u32;typedef	short		s16;typedef	unsigned short	u16;typedef	char		s8;typedef	unsigned char	u8;/*** The DEPCA Rx and Tx ring descriptors. */struct depca_rx_desc {    volatile s32 base;    s16 buf_length;		/* This length is negative 2's complement! */    s16 msg_length;		/* This length is "normal". */};struct depca_tx_desc {    volatile s32 base;    s16 length;		        /* This length is negative 2's complement! */    s16 misc;                   /* Errors and TDR info */};#define LA_MASK 0x0000ffff      /* LANCE address mask for mapping network RAM				   to LANCE memory address space *//*** The Lance initialization block, described in databook, in common memory.*/struct depca_init {    u16 mode;	                /* Mode register */    u8  phys_addr[ETH_ALEN];	/* Physical ethernet address */    u8  mcast_table[8];	        /* Multicast Hash Table. */    u32 rx_ring;     	        /* Rx ring base pointer & ring length */    u32 tx_ring;	        /* Tx ring base pointer & ring length */};struct depca_private {	struct depca_rx_desc	*rx_ring;	struct depca_tx_desc	*tx_ring;	struct depca_init	init_block;	/* Shadow init block */	char			*rx_memcpy[NUM_RX_DESC];	char			*tx_memcpy[NUM_TX_DESC];	u32			bus_offset;	/* ISA bus address offset */	u32			sh_mem;		/* address of shared mem */	u32			dma_buffs;	/* Rx & Tx buffer start */	int			rx_cur, tx_cur;	/* Next free ring entry */	int			txRingMask, rxRingMask;	s32			rx_rlen, tx_rlen;	/* log2([rt]xRingMask+1) for the descriptors */};static Address		mem_start = DEPCA_RAM_BASE;static Address		mem_len, offset;static unsigned short	ioaddr = 0;static struct depca_private	lp;/*** Miscellaneous defines...*/#define STOP_DEPCA \    outw(CSR0, DEPCA_ADDR);\    outw(STOP, DEPCA_DATA)/* Initialize the lance Rx and Tx descriptor rings. */static void depca_init_ring(struct nic *nic){	int	i;	u32	p;	lp.rx_cur = lp.tx_cur = 0;	/* Initialize the base addresses and length of each buffer in the ring */	for (i = 0; i <= lp.rxRingMask; i++) {		writel((p = lp.dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp.rx_ring[i].base);		writew(-RX_BUFF_SZ, &lp.rx_ring[i].buf_length);		lp.rx_memcpy[i] = (char *) (p + lp.bus_offset);	}	for (i = 0; i <= lp.txRingMask; i++) {		writel((p = lp.dma_buffs + (i + lp.txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, &lp.tx_ring[i].base);		lp.tx_memcpy[i] = (char *) (p + lp.bus_offset);	}	/* Set up the initialization block */	lp.init_block.rx_ring = ((u32) ((u32) lp.rx_ring) & LA_MASK) | lp.rx_rlen;	lp.init_block.tx_ring = ((u32) ((u32) lp.tx_ring) & LA_MASK) | lp.tx_rlen;	for (i = 0; i < ETH_ALEN; i++)		lp.init_block.phys_addr[i] = nic->node_addr[i];	lp.init_block.mode = 0x0000;	/* Enable the Tx and Rx */	memset(lp.init_block.mcast_table, 0, sizeof(lp.init_block.mcast_table));}static void LoadCSRs(void){	outw(CSR1, DEPCA_ADDR);	/* initialisation block address LSW */	outw((u16) (lp.sh_mem & LA_MASK), DEPCA_DATA);	outw(CSR2, DEPCA_ADDR);	/* initialisation block address MSW */	outw((u16) ((lp.sh_mem & LA_MASK) >> 16), DEPCA_DATA);	outw(CSR3, DEPCA_ADDR);	/* ALE control */	outw(ACON, DEPCA_DATA);	outw(CSR0, DEPCA_ADDR);	/* Point back to CSR0 */}static int InitRestartDepca(void){	int		i;	/* Copy the shadow init_block to shared memory */	memcpy_toio((char *)lp.sh_mem, &lp.init_block, sizeof(struct depca_init));	outw(CSR0, DEPCA_ADDR);		/* point back to CSR0 */	outw(INIT, DEPCA_DATA);		/* initialise DEPCA */	for (i = 0; i < 100 && !(inw(DEPCA_DATA) & IDON); i++)		;	if (i < 100) {		/* clear IDON by writing a 1, and start LANCE */		outw(IDON | STRT, DEPCA_DATA);	} else {		printf("DEPCA not initialised\n");		return (1);	}	return (0);}/**************************************************************************RESET - Reset adapter***************************************************************************/static void depca_reset(struct nic *nic){	s16	nicsr;	int	i, j;	STOP_DEPCA;	nicsr = inb(DEPCA_NICSR);	nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);	outb(nicsr, DEPCA_NICSR);	if (inw(DEPCA_DATA) != STOP)	{		printf("depca: Cannot stop NIC\n");		return;	}	/* Initialisation block */	lp.sh_mem = mem_start;	mem_start += sizeof(struct depca_init);	/* Tx & Rx descriptors (aligned to a quadword boundary) */	mem_start = (mem_start + ALIGN) & ~ALIGN;	lp.rx_ring = (struct depca_rx_desc *) mem_start;	mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);	lp.tx_ring = (struct depca_tx_desc *) mem_start;	mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);	lp.bus_offset = mem_start & 0x00ff0000;	/* LANCE re-mapped start address */	lp.dma_buffs = mem_start & LA_MASK;	/* Finish initialising the ring information. */	lp.rxRingMask = NUM_RX_DESC - 1;	lp.txRingMask = NUM_TX_DESC - 1;	/* Calculate Tx/Rx RLEN size for the descriptors. */	for (i = 0, j = lp.rxRingMask; j > 0; i++) {		j >>= 1;	}	lp.rx_rlen = (s32) (i << 29);	for (i = 0, j = lp.txRingMask; j > 0; i++) {		j >>= 1;	}	lp.tx_rlen = (s32) (i << 29);	/* Load the initialisation block */	depca_init_ring(nic);	LoadCSRs();	InitRestartDepca();}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int depca_poll(struct nic *nic){	int		entry;	u32		status;	entry = lp.rx_cur;	if ((status = readl(&lp.rx_ring[entry].base) & R_OWN))		return (0);	memcpy(nic->packet, lp.rx_memcpy[entry], nic->packetlen = lp.rx_ring[entry].msg_length);	lp.rx_ring[entry].base |= R_OWN;	lp.rx_cur = (++lp.rx_cur) & lp.rxRingMask;	return (1);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void depca_transmit(	struct nic *nic,	const char *d,			/* Destination */	unsigned int t,			/* Type */	unsigned int s,			/* size */	const char *p)			/* Packet */{	int		entry, len;	char		*mem;	/* send the packet to destination */	/*	** Caution: the right order is important here... dont	** setup the ownership rights until all the other	** information is in place	*/	mem = lp.tx_memcpy[entry = lp.tx_cur];	memcpy_toio(mem, d, ETH_ALEN);	memcpy_toio(mem + ETH_ALEN, nic->node_addr, ETH_ALEN);	mem[ETH_ALEN * 2] = t >> 8;	mem[ETH_ALEN * 2 + 1] = t;	memcpy_toio(mem + ETH_HLEN, p, s);	s += ETH_HLEN;	len = (s < ETH_ZLEN ? ETH_ZLEN : s);	/* clean out flags */	writel(readl(&lp.tx_ring[entry].base) & ~T_FLAGS, &lp.tx_ring[entry].base);	/* clears other error flags */	writew(0x0000, &lp.tx_ring[entry].misc);	/* packet length in buffer */	writew(-len, &lp.tx_ring[entry].length);	/* start and end of packet, ownership */	writel(readl(&lp.tx_ring[entry].base) | (T_STP|T_ENP|T_OWN), &lp.tx_ring[entry].base);	/* update current pointers */	lp.tx_cur = (++lp.tx_cur) & lp.txRingMask;}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void depca_disable(struct nic *nic){	STOP_DEPCA;}/*** Look for a special sequence in the Ethernet station address PROM that** is common across all DEPCA products. Note that the original DEPCA needs** its ROM address counter to be initialized and enabled. Only enable** if the first address octet is a 0x08 - this minimises the chances of** messing around with some other hardware, but it assumes that this DEPCA** card initialized itself correctly.**** Search the Ethernet address ROM for the signature. Since the ROM address** counter can start at an arbitrary point, the search must include the entire** probe sequence length plus the (length_of_the_signature - 1).** Stop the search IMMEDIATELY after the signature is found so that the** PROM address counter is correctly positioned at the start of the** ethernet address for later read out.*/static int depca_probe1(struct nic *nic){	u8	data, nicsr;	/* This is only correct for little endian machines, but then	   Etherboot doesn't work on anything but a PC */	u8	sig[] = { 0xFF, 0x00, 0x55, 0xAA, 0xFF, 0x00, 0x55, 0xAA };	int	i, j;	long	sum, chksum;	data = inb(DEPCA_PROM);		/* clear counter on DEPCA */	data = inb(DEPCA_PROM);		/* read data */	if (data == 0x8) {		nicsr = inb(DEPCA_NICSR);		nicsr |= AAC;		outb(nicsr, DEPCA_NICSR);	}	for (i = 0, j = 0; j < (int)sizeof(sig) && i < PROBE_LENGTH+((int)sizeof(sig))-1; ++i) {		data = inb(DEPCA_PROM);		if (data == sig[j])		/* track signature */			++j;		else			j = (data == sig[0]) ? 1 : 0;	}	if (j != sizeof(sig))		return (0);	/* put the card in its initial state */	STOP_DEPCA;	nicsr = ((inb(DEPCA_NICSR) & ~SHE & ~RBE & ~IEN) | IM);	outb(nicsr, DEPCA_NICSR);	if (inw(DEPCA_DATA) != STOP)		return (0);	memcpy((char *)mem_start, sig, sizeof(sig));	if (memcmp((char *)mem_start, sig, sizeof(sig)) != 0)		return (0);	for (i = 0, j = 0, sum = 0; j < 3; j++) {		sum <<= 1;		if (sum > 0xFFFF)			sum -= 0xFFFF;		sum += (u8)(nic->node_addr[i++] = inb(DEPCA_PROM));		sum += (u16)((nic->node_addr[i++] = inb(DEPCA_PROM)) << 8);		if (sum > 0xFFFF)			sum -= 0xFFFF;	}	if (sum == 0xFFFF)		sum = 0;	chksum = (u8)inb(DEPCA_PROM);	chksum |= (u16)(inb(DEPCA_PROM) << 8);	mem_len = (adapter == DEPCA) ? (48 << 10) : (64 << 10);	offset = 0;	if (nicsr & BUF) {		offset = 0x8000;		nicsr &= ~BS;		mem_len -= (32 << 10);	}	if (adapter != DEPCA)	/* enable shadow RAM */		outb(nicsr |= SHE, DEPCA_NICSR);	printf("%s base %#hX, memory [%#hX-%#hX], addr %!",		adapter_name[adapter], ioaddr, mem_start, mem_start + mem_len,		nic->node_addr);	if (sum != chksum)		printf(" (bad checksum)");	putchar('\n');	return (1);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/struct nic *depca_probe(struct nic *nic, unsigned short *probe_addrs){	static unsigned short	base[] = DEPCA_IO_PORTS;	int			i;	if (probe_addrs == 0 || probe_addrs[0] == 0)		probe_addrs = base;	/* Use defaults */	for (i = 0; (ioaddr = base[i]) != 0; ++i) {		if (depca_probe1(nic))			break;	}	if (ioaddr == 0)		return (0);	depca_reset(nic);	/* point to NIC specific routines */	nic->reset = depca_reset;	nic->poll = depca_poll;	nic->transmit = depca_transmit;	nic->disable = depca_disable;	return (nic);}

⌨️ 快捷键说明

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