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

📄 eepro.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
***************************************************************************/static void eepro_reset(struct nic *nic){	int		temp_reg, i;	/* put the card in its initial state */	eepro_sw2bank2(ioaddr);	/* be careful, bank2 now */	temp_reg = inb(ioaddr + eeprom_reg);#ifdef	DEBUG	printf("Stepping %d\n", temp_reg >> 5);#endif	if (temp_reg & 0x10)	/* check the TurnOff Enable bit */		outb(temp_reg & 0xEF, ioaddr + eeprom_reg);	for (i = 0; i < ETH_ALEN; i++)	/* fill the MAC address */		outb(nic->node_addr[i], ioaddr + I_ADD_REG0 + i);	temp_reg = inb(ioaddr + REG1);	/* setup Transmit Chaining and discard bad RCV frames */	outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop		| RCV_Discard_BadFrame, ioaddr + REG1);	temp_reg = inb(ioaddr + REG2);		/* match broadcast */	outb(temp_reg | 0x14, ioaddr + REG2);	temp_reg = inb(ioaddr + REG3);	outb(temp_reg & 0x3F, ioaddr + REG3);	/* clear test mode */	/* set the receiving mode */	eepro_sw2bank1(ioaddr);	/* be careful, bank1 now */	/* initialise the RCV and XMT upper and lower limits */	outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);	outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);	outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg);	outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg);	eepro_sw2bank0(ioaddr);	/* Switch back to bank 0 */	eepro_clear_int(ioaddr);	/* Initialise RCV */	outw(rx_start = (RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR);	outw(((RCV_UPPER_LIMIT << 8) | 0xFE), ioaddr + RCV_STOP);	/* Intialise XMT */	outw((XMT_LOWER_LIMIT << 8), ioaddr + xmt_bar);	eepro_sel_reset(ioaddr);	tx_start = tx_end = (XMT_LOWER_LIMIT << 8);	tx_last = 0;	eepro_en_rx(ioaddr);}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int eepro_poll(struct nic *nic){	int		i;	unsigned int	rcv_car = rx_start;	unsigned int	rcv_event, rcv_status, rcv_next_frame, rcv_size;	/* 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 */#if	0	if ((inb(ioaddr + STATUS_REG) & 0x40) == 0)		return (0);	outb(0x40, ioaddr + STATUS_REG);#endif	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);	rcv_event = inw(ioaddr + IO_PORT);	if (rcv_event != RCV_DONE)		return (0);	rcv_status = inw(ioaddr + IO_PORT);	rcv_next_frame = inw(ioaddr + IO_PORT);	rcv_size = inw(ioaddr + IO_PORT);#if	0	printf("%hX %hX %d %hhX\n", rcv_status, rcv_next_frame, rcv_size,		inb(ioaddr + STATUS_REG));#endif	if ((rcv_status & (RX_OK|RX_ERROR)) != RX_OK) {		printf("Receive error %hX\n", rcv_status);		return (0);	}	rcv_size &= 0x3FFF;	insw(ioaddr + IO_PORT, nic->packet, ((rcv_size + 3) >> 1));#if	0	for (i = 0; i < 48; i++) {		printf("%hhX", nic->packet[i]);		putchar(i % 16 == 15 ? '\n' : ' ');	}#endif	nic->packetlen = rcv_size;	rcv_car = rx_start + RCV_HEADER + rcv_size;	rx_start = rcv_next_frame;	if (rcv_car == 0)		rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);	outw(rcv_car - 1, ioaddr + RCV_STOP);	return (1);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void eepro_transmit(	struct nic *nic,	const char *d,			/* Destination */	unsigned int t,			/* Type */	unsigned int s,			/* size */	const char *p)			/* Packet */{	unsigned int	status, tx_available, last, end, length;	unsigned short	type;	int		boguscount = 20;	length = s + ETH_HLEN;	if (tx_end > tx_start)		tx_available = XMT_RAM - (tx_end - tx_start);	else if (tx_end < tx_start)		tx_available = tx_start - tx_end;	else		tx_available = XMT_RAM;	last = tx_end;	end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;	if (end >= (XMT_UPPER_LIMIT << 8)) {		last = (XMT_LOWER_LIMIT << 8);		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;	}	outw(last, ioaddr + HOST_ADDRESS_REG);	outw(XMT_CMD, ioaddr + IO_PORT);	outw(0, ioaddr + IO_PORT);	outw(end, ioaddr + IO_PORT);	outw(length, ioaddr + IO_PORT);	outsw(ioaddr + IO_PORT, d, ETH_ALEN / 2);	outsw(ioaddr + IO_PORT, nic->node_addr, ETH_ALEN / 2);	type = htons(t);	outsw(ioaddr + IO_PORT, &type, sizeof(type) / 2);	outsw(ioaddr + IO_PORT, p, (s + 3) >> 1);	/* A dummy read to flush the DRAM write pipeline */	status = inw(ioaddr + IO_PORT);	outw(last, ioaddr + xmt_bar);	outb(XMT_CMD, ioaddr);	tx_start = last;	tx_last = last;	tx_end = end;#if	0	printf("%d %d\n", tx_start, tx_end);#endif	while (boguscount > 0) {		if (((status = inw(ioaddr + IO_PORT)) & TX_DONE_BIT) == 0) {			udelay(40);			boguscount--;			continue;		}#if	DEBUG		if ((status & 0x2000) == 0)			printf("Transmit status %hX\n", status);#endif	}}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void eepro_disable(struct nic *nic){	eepro_sw2bank0(ioaddr);	/* Switch to bank 0 */	/* Flush the Tx and disable Rx */	outb(STOP_RCV_CMD, ioaddr);	tx_start = tx_end = (XMT_LOWER_LIMIT << 8);	tx_last = 0;	/* Reset the 82595 */	eepro_full_reset(ioaddr);}static int read_eeprom(int location){	int		i;	unsigned short	retval = 0;	int		ee_addr = ioaddr + eeprom_reg;	int		read_cmd = location | EE_READ_CMD;	int		ctrl_val = EECS;	if (eepro == LAN595FX_10ISA) {		eepro_sw2bank1(ioaddr);		outb(0x00, ioaddr + STATUS_REG);	}	eepro_sw2bank2(ioaddr);	outb(ctrl_val, ee_addr);	/* shift the read command bits out */	for (i = 8; i >= 0; i--) {		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;		outb(outval, ee_addr);		outb(outval | EESK, ee_addr);	/* EEPROM clock tick */		eeprom_delay();		outb(outval, ee_addr);		/* finish EEPROM clock tick */		eeprom_delay();	}	outb(ctrl_val, ee_addr);	for (i = 16; i > 0; i--) {		outb(ctrl_val | EESK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);		outb(ctrl_val, ee_addr);		eeprom_delay();	}	/* terminate the EEPROM access */	ctrl_val &= ~EECS;	outb(ctrl_val | EESK, ee_addr);	eeprom_delay();	outb(ctrl_val, ee_addr);	eeprom_delay();	eepro_sw2bank0(ioaddr);	return (retval);}static int eepro_probe1(struct nic *nic){	int		i, id, counter, l_eepro = 0;	union {		unsigned char	caddr[ETH_ALEN];		unsigned short	saddr[ETH_ALEN/2];	} station_addr;	char		*name;	id = inb(ioaddr + ID_REG);	if ((id & ID_REG_MASK) != ID_REG_SIG)		return (0);	counter = id & R_ROBIN_BITS;	if (((id = inb(ioaddr + ID_REG)) & R_ROBIN_BITS) != (counter + 0x40))		return (0);	/* yes the 82595 has been found */	station_addr.saddr[2] = read_eeprom(2);	if (station_addr.saddr[2] == 0x0000 || station_addr.saddr[2] == 0xFFFF) {		l_eepro = 3;		eepro = LAN595FX_10ISA;		eeprom_reg= EEPROM_REG_10;		rcv_start = RCV_START_10;		xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;		xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;		station_addr.saddr[2] = read_eeprom(2);	}	station_addr.saddr[1] = read_eeprom(3);	station_addr.saddr[0] = read_eeprom(4);	if (l_eepro)		name = "Intel EtherExpress 10 ISA";	else if (read_eeprom(7) == ee_FX_INT2IRQ) {		name = "Intel EtherExpress Pro/10+ ISA";		l_eepro = 2;	} else if (station_addr.saddr[0] == SA_ADDR1) {		name = "Intel EtherExpress Pro/10 ISA";		l_eepro = 1;	} else {		l_eepro = 0;		name = "Intel 82595-based LAN card";	}	station_addr.saddr[0] = swap16(station_addr.saddr[0]);	station_addr.saddr[1] = swap16(station_addr.saddr[1]);	station_addr.saddr[2] = swap16(station_addr.saddr[2]);	for (i = 0; i < ETH_ALEN; i++) {		nic->node_addr[i] = station_addr.caddr[i];	}	printf("\n%s ioaddr %#hX, addr %!", name, ioaddr, nic->node_addr);	mem_start = RCV_LOWER_LIMIT << 8;	if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29)		mem_end = RCV_UPPER_LIMIT << 8;	else {		mem_end = mem_end * 1024 + (RCV_LOWER_LIMIT << 8);		rcv_ram = mem_end - (RCV_LOWER_LIMIT << 8);	}	printf(", Rx mem %dK, if %s\n", (mem_end - mem_start) >> 10,		GetBit(read_eeprom(5), ee_BNC_TPE) ? "BNC" : "TP");	return (1);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/struct nic *eepro_probe(struct nic *nic, unsigned short *probe_addrs){	unsigned short		*p;	/* same probe list as the Linux driver */	static unsigned short	ioaddrs[] = {		0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};	if (probe_addrs == 0 || probe_addrs[0] == 0)		probe_addrs = ioaddrs;	for (p = probe_addrs; (ioaddr = *p) != 0; p++) {		if (eepro_probe1(nic))			break;	}	if (*p == 0)		return (0);	eepro_reset(nic);	/* point to NIC specific routines */	nic->reset = eepro_reset;	nic->poll = eepro_poll;	nic->transmit = eepro_transmit;	nic->disable = eepro_disable;	return (nic);}

⌨️ 快捷键说明

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