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

📄 cs89x0.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. *//*  Permission is granted to distribute the enclosed cs89x0.[ch] driver  only in conjunction with the Etherboot package.  The code is  ordinarily distributed under the GPL.    Russ Nelson, January 2000  ChangeLog:  Thu Dec 6 22:40:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * disabled all "advanced" features; this should make the code more reliable  * reorganized the reset function  * always reset the address port, so that autoprobing will continue working  * some cosmetic changes  * 2.5  Thu Dec 5 21:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * tested the code against a CS8900 card  * lots of minor bug fixes and adjustments  * this is the first release, that actually works! it still requires some    changes in order to be more tolerant to different environments  * 4  Fri Nov 22 23:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * read the manuals for the CS89x0 chipsets and took note of all the    changes that will be neccessary in order to adapt Russel Nelson's code    to the requirements of a BOOT-Prom  * 6  Thu Nov 19 22:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * Synched with Russel Nelson's current code (v1.00)  * 2  Thu Nov 12 18:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * Cleaned up some of the code and tried to optimize the code size.  * 1.5  Sun Nov 10 16:30:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>  * First experimental release. This code compiles fine, but I  have no way of testing whether it actually works.  * I did not (yet) bother to make the code 16bit aware, so for  the time being, it will only work for Etherboot/32.  * 12  */#include "etherboot.h"#include "nic.h"#include "cards.h"#include "cs89x0.h"static unsigned short	eth_nic_base;static unsigned long    eth_mem_start;static unsigned short   eth_irq;static unsigned short   eth_cs_type;	/* one of: CS8900, CS8920, CS8920M  */static unsigned short   eth_auto_neg_cnf;static unsigned short   eth_adapter_cnf;static unsigned short	eth_linectl;/*************************************************************************	CS89x0 - specific routines**************************************************************************/static inline int readreg(int portno){	outw(portno, eth_nic_base + ADD_PORT);	return inw(eth_nic_base + DATA_PORT);}static inline void writereg(int portno, int value){	outw(portno, eth_nic_base + ADD_PORT);	outw(value, eth_nic_base + DATA_PORT);	return;}/*************************************************************************EEPROM access**************************************************************************/static int wait_eeprom_ready(void){	unsigned long tmo = currticks() + 4*TICKS_PER_SEC;	/* check to see if the EEPROM is ready, a timeout is used -	   just in case EEPROM is ready when SI_BUSY in the	   PP_SelfST is clear */	while(readreg(PP_SelfST) & SI_BUSY) {		if (currticks() >= tmo)			return -1; }	return 0;}static int get_eeprom_data(int off, int len, unsigned short *buffer){	int i;#ifdef	EDEBUG	printf("\ncs: EEPROM data from %hX for %hX:",off,len);#endif	for (i = 0; i < len; i++) {		if (wait_eeprom_ready() < 0)			return -1;		/* Now send the EEPROM read command and EEPROM location		   to read */		writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD);		if (wait_eeprom_ready() < 0)			return -1;		buffer[i] = readreg(PP_EEData);#ifdef	EDEBUG		if (!(i%10))			printf("\ncs: ");		printf("%hX ", buffer[i]);#endif	}#ifdef	EDEBUG	putchar('\n');#endif	return(0);}static int get_eeprom_chksum(int off, int len, unsigned short *buffer){	int  i, cksum;	cksum = 0;	for (i = 0; i < len; i++)		cksum += buffer[i];	cksum &= 0xffff;	if (cksum == 0)		return 0;	return -1;}/*************************************************************************Activate all of the available media and probe for network**************************************************************************/static void clrline(void){	int i;	putchar('\r');	for (i = 79; i--; ) putchar(' ');	printf("\rcs: ");	return;}static void control_dc_dc(int on_not_off){	unsigned int selfcontrol;	unsigned long tmo = currticks() + TICKS_PER_SEC;	/* control the DC to DC convertor in the SelfControl register.  */	selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */	if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)		selfcontrol |= HCB1;	else		selfcontrol &= ~HCB1;	writereg(PP_SelfCTL, selfcontrol);	/* Wait for the DC/DC converter to power up - 1000ms */	while (currticks() < tmo);	return;}static int detect_tp(void){	unsigned long tmo;	/* Turn on the chip auto detection of 10BT/ AUI */	clrline(); printf("attempting %s:","TP");        /* If connected to another full duplex capable 10-Base-T card	   the link pulses seem to be lost when the auto detect bit in	   the LineCTL is set.  To overcome this the auto detect bit	   will be cleared whilst testing the 10-Base-T interface.	   This would not be necessary for the sparrow chip but is	   simpler to do it anyway. */	writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY);	control_dc_dc(0);        /* Delay for the hardware to work out if the TP cable is	   present - 150ms */	for (tmo = currticks() + 4; currticks() < tmo; );	if ((readreg(PP_LineST) & LINK_OK) == 0)		return 0;	if (eth_cs_type != CS8900) {		writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK);		if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {			printf(" negotiating duplex... ");			while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) {				if (currticks() - tmo > 40*TICKS_PER_SEC) {					printf("time out ");					break;				}			}		}		if (readreg(PP_AutoNegST) & FDX_ACTIVE)			printf("using full duplex");		else			printf("using half duplex");	}	return A_CNF_MEDIA_10B_T;}/* send a test packet - return true if carrier bits are ok */static int send_test_pkt(struct nic *nic){	static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,				     0, 46, /*A 46 in network order       */				     0, 0,  /*DSAP=0 & SSAP=0 fields      */				     0xf3,0 /*Control (Test Req+P bit set)*/ };	unsigned long tmo;	writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);	memcpy(testpacket, nic->node_addr, ETH_ALEN);	memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN);	outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);	outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT);	/* Test to see if the chip has allocated memory for the packet */	for (tmo = currticks() + 2;	     (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; )		if (currticks() >= tmo)			return(0);	/* Write the contents of the packet */	outsw(eth_nic_base + TX_FRAME_PORT, testpacket,	      (ETH_ZLEN+1)>>1);	printf(" sending test packet ");	/* wait a couple of timer ticks for packet to be received */	for (tmo = currticks() + 2; currticks() < tmo; );	if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {			printf("succeeded");			return 1;	}	printf("failed");	return 0;}static int detect_aui(struct nic *nic){	clrline(); printf("attempting %s:","AUI");	control_dc_dc(0);	writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);	if (send_test_pkt(nic)) {		return A_CNF_MEDIA_AUI; }	else		return 0;}static int detect_bnc(struct nic *nic){	clrline(); printf("attempting %s:","BNC");	control_dc_dc(1);	writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);	if (send_test_pkt(nic)) {		return A_CNF_MEDIA_10B_2; }	else		return 0;}/**************************************************************************ETH_RESET - Reset adapter***************************************************************************/static void cs89x0_reset(struct nic *nic){	int  i;	unsigned long reset_tmo;	writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);	/* wait for two ticks; that is 2*55ms */	for (reset_tmo = currticks() + 2; currticks() < reset_tmo; );	if (eth_cs_type != CS8900) {		/* Hardware problem requires PNP registers to be reconfigured		   after a reset */		if (eth_irq != 0xFFFF) {			outw(PP_CS8920_ISAINT, eth_nic_base + ADD_PORT);			outb(eth_irq, eth_nic_base + DATA_PORT);			outb(0, eth_nic_base + DATA_PORT + 1); }		if (eth_mem_start) {			outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT);			outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT);			outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } }	/* Wait until the chip is reset */	for (reset_tmo = currticks() + 2;	     (readreg(PP_SelfST) & INIT_DONE) == 0 &&		     currticks() < reset_tmo; );

⌨️ 快捷键说明

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