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

📄 3c59x.c

📁 开源的BIOS启动软件
💻 C
字号:
#include <bios/netdev.h>#include <bios/pci.h>#include <bios/stdio.h>#include <bios/malloc.h>#include <bios/timer.h>#include <bios/string.h>#include <bios/debug.h>#include <bios/if_ether.h>#define virt_to_bus(x)	((int)(x) + 0x10000000)struct netdev net_dev_3com_3c59x;extern const struct trans_ops eth_trans_ops;#define inb(x)		pci_io_read_byte(nd->io_base + (x))#define outb(w,x)	pci_io_write_byte((w), nd->io_base + (x))#define inw(x)		pci_io_read_word(nd->io_base + (x))#define outw(w,x)	pci_io_write_word((w), nd->io_base + (x))#define inl(x)		pci_io_read_long(nd->io_base + (x))#define outl(w,x)	pci_io_write_long((w), nd->io_base + (x))#define Command				14#define Command_SelectRegisterWindow(x)	(0x0800 | (x))#define Command_EnableDcConverter	(0x1000)#define Command_RxDisable		(0x1800)#define Command_RxEnable		(0x2000)#define Command_RxReset(mask)		(0x2800|(mask))#define Command_UpStall			(0x3000)#define Command_UpUnstall		(0x3001)#define Command_DownStall		(0x3002)#define Command_DownUnstall		(0x3003)#define Command_TxDone			(0x3800)#define Command_RxDiscard		(0x4000)#define Command_TxEnable		(0x4800)#define Command_TxDisable		(0x5000)#define Command_TxReset(mask)		(0x5800|(mask))#define Command_RequestInterrupt	(0x6000)#define Command_AcknowledgeInterrupt(m)	(0x6800|(m))#define Command_SetInterruptEnable(m)	(0x7000|(m))#define Command_SetIndicationEnable(m)	(0x7800|(m))#define Command_SetRxFilter(m)		(0x8000|(m))#define Command_SetRxEarlyThresh(t)	(0x8800|(t))#define Command_SetTxAvailableThresh(t)	(0x9000|(t))#define Command_SetTxStartThresh(t)	(0x9800|(t))#define Command_StartDma(mode)		(0xa000|(mode))#define Command_StatisticsEnable	(0xa800)#define Command_StatisticsDisable	(0xb000)#define Command_DisableDcConverter	(0xb800)#define IntStatus			14#define IntStatus_interruptLatch	(1 << 0)#define IntStatus_hostError		(1 << 1)#define IntStatus_txComplete		(1 << 2)#define IntStatus_txAvailable		(1 << 3)#define IntStatus_rxComplete		(1 << 4)#define IntStatus_rxEarly		(1 << 5)#define IntStatus_intRequested		(1 << 6)#define IntStatus_updateStats		(1 << 7)#define IntStatus_transferInt		(1 << 8)#define IntStatus_busMasterInProgress	(1 << 11)#define IntStatus_commandInProgress	(1 << 12)#define IntStatus_windowNumber		(7 << 13)/* Bank 1 (at +0x10) */#define RxData				0x10 + 0#define TxData				0x10 + 0#define RxStatus			0x10 + 8#define RxStatus_rxBytes		(0x1fff)#define RxStatus_rxError		(1 << 14)#define RxStatus_rxIncomplete		(1 << 15)#define TxFree				0x10 + 12/* Bank 3 */#define InternalConfig			0#define InternalConfig_autoSelect	(1 << 24)#define InternalConfig_xcvrSelect(x)	((x) << 20)#define InternalConfig_xcvr10bt		InternalConfig_xcvrSelect(0)#define InternalConfig_xcvr10b5		InternalConfig_xcvrSelect(1)#define InternalConfig_xcvr10b2		InternalConfig_xcvrSelect(3)#define InternalConfig_xcvr100btx	InternalConfig_xcvrSelect(4)#define InternalConfig_xcvr100bfx	InternalConfig_xcvrSelect(5)#define InternalConfig_xcvrmii		InternalConfig_xcvrSelect(6)#define InternalConfig_xcvrnway		InternalConfig_xcvrSelect(8)#define MacControl			6#define MacControl_fullDuplexEnable	(1 << 5)#define ResetOptions			8#define ResetOptions_100bT4available	(1 << 0)#define ResetOptions_100bTXavailable	(1 << 1)#define ResetOptions_100bFXavailable	(1 << 2)#define ResetOptions_10bTavailable	(1 << 3)#define ResetOptions_10b2available	(1 << 4)#define ResetOptions_10b5available	(1 << 5)#define ResetOptions_miiavailable	(1 << 6)/* Bank 4 */#define MediaStatus			10#define MediaStatus_dataRate100		(1 << 1)	/* ro */#define MediaStatus_crcStripDisable	(1 << 2)	/* rw */#define MediaStatus_enableSqeStats	(1 << 3)	/* ro */#define MediaStatus_collisionDetect	(1 << 4)	/* ro */#define MediaStatus_carrierSense	(1 << 5)	/* ro */#define MediaStatus_jabberGuardEnable	(1 << 6)	/* rw */#define MediaStatus_linkBeatEnable	(1 << 7)	/* rw */#define MediaStatus_jabberDetect	(1 << 9)	/* ro */#define MediaStatus_polarityReversed	(1 << 10)	/* ro */#define MediaStatus_linkBeatDetect	(1 << 11)	/* ro */#define MediaStatus_txInProg		(1 << 12)	/* ro */#define MediaStatus_dcConverterEnabled	(1 << 14)	/* ro */#define MediaStatus_auiDisable		(1 << 15)	/* ro */#define PhysicalMgmt			8#define PhysicalMgmt_clk		(1 << 0)#define PhysicalMgmt_data		(1 << 1)#define PhysicalMgmt_dir		(1 << 2)/* Boomerang BM regs */#define PacketStatus			0x20#define TxDownListPtr			0x24#define TxFreeThreshold			0x2f#define RxUpPacketStatus		0x30#define RxUpListPtr			0x38struct tx_desc {	volatile u32	next;	volatile u32	status;#define DownComplete	0x00010000	volatile u32	addr;	volatile u32	length;#define LastFrag	0x80000000};struct rx_desc {	volatile u32	next;	volatile u32	status;#define RxComplete	0x00008000#define RxError		0x00004000	volatile u32	addr;	volatile u32	length;};static int eeprom_read(struct netdev *nd, int offset){	outw(Command_SelectRegisterWindow(0), Command);	while ((inw(10) & 1 << 15) != 0);	outw(0x0080 | (offset & 0x3f), 10);	while ((inw(10) & 1 << 15) != 0);	return inw(12);}#if 0static int mdio_sync(struct netdev *nd){	int i;	outw(Command_SelectRegisterWindow(4), Command);	// reg window 4	for (i = 0; i < 32; i++) {		outw(PhysicalMgmt_dir | PhysicalMgmt_data, PhysicalMgmt);		inw(PhysicalMgmt);		outw(PhysicalMgmt_dir | PhysicalMgmt_data | PhysicalMgmt_clk, PhysicalMgmt);		inw(PhysicalMgmt);	}}static int mdio_read(struct netdev *nd, int id, int loc){	int cmd = 0x3d800 | id << 5 | loc;	int i, ret = 0;	/*	 * 14-10 = cmd	 *  9-5  = id	 *  4-0  = loc	 */	mdio_sync(nd);	for (i = 14; i >= 0; i--) {		int data;		data = cmd & 1 << i ? PhysicalMgmt_data : 0;		outw(PhysicalMgmt_dir | data, PhysicalMgmt);		inw(PhysicalMgmt);		outw(PhysicalMgmt_dir | data | PhysicalMgmt_clk, PhysicalMgmt);		inw(PhysicalMgmt);	}	for (i = 19; i > 0; i--) {		outw(0, PhysicalMgmt);		inw(PhysicalMgmt);		ret <<= 1;		ret |= inw(PhysicalMgmt) & PhysicalMgmt_data ? 1 : 0;		outw(PhysicalMgmt_clk, PhysicalMgmt);		inw(PhysicalMgmt);	}	return ret & 0x0000 ? 0xffff : (ret >> 1 & 0xffff);}static void mdio_write(struct netdev *nd, int id, int loc, int val){	int cmd = 0x50020000 | id << 23 | loc << 18 | val;	int i;	/*	 * 31-29 = cmd	 * 28-23 = id	 * 22-18 = loc	 * 17-0  = val	 */	mdio_sync(nd);	for (i = 31; i >= 0; i--) {		int data;		data = cmd & 1 << i ? PhysicalMgmt_data : 0;		outw(PhysicalMgmt_dir | data, PhysicalMgmt);		inw(PhysicalMgmt);		outw(PhysicalMgmt_dir | data | PhysicalMgmt_clk, PhysicalMgmt);		inw(PhysicalMgmt);	}	for (i = 1; i > 0; i--) {		outw(0, PhysicalMgmt);		inw(PhysicalMgmt);		outw(PhysicalMgmt_clk, PhysicalMgmt);		inw(PhysicalMgmt);	}}#endifstatic inline void wait_cmd(struct netdev *nd){	while ((inw(IntStatus) & IntStatus_commandInProgress) != 0);}static void send_and_wait_cmd(struct netdev *nd, int cmd){	outw(cmd, Command);	wait_cmd(nd);}static struct id {	unsigned int	id;	const char	*name;	int		flags;#define TXDMA	1#define RXDMA	2} nd_3c59x_ids[] = {	{ 0x5900,	"3c590 10Combo",	0		},	{ 0x5950,	"3c595 Vortex 100TX",	0		},	{ 0x5951,	"3c595 Vortex 100T4",	0		},	{ 0x5952,	"3c595 Vortex 100MII",	0		},	{ 0x9200,	"3c905C Tornado",	TXDMA|RXDMA	},	{ 0x0000,	NULL,			0		}};static int nd_3c59x_probe(void){	struct netdev *nd = &net_dev_3com_3c59x;	struct pci_dev *dev = NULL;	struct id *id;	int i;	int resetoptions, intcfg;	char *def_media;	for (i = 0, id = nd_3c59x_ids; id->id; i++, id++) {		dev = pci_lookup_vendor_device(NULL, 0x10b7, id->id);		if (dev)			break;	}	if (!dev)		return -1;	if (pci_enable(dev))		return -1;	if (id->flags & (TXDMA | RXDMA) && pci_set_master(dev))		return -1;	/*	 * Ok, we have a 3c59x card.  Now, read the base register.	 */	nd->io_base = dev->bar[0] & ~3;	if (!nd->io_base)		return -1;	nd->driver = id->flags;	printf(" net: %s at 0x%04x, ether address", id->name, nd->io_base);	/*	 * and the EEPROM	 */	for (i = 0; i < 3; i++) {		int addr;		/*		 * Note that the ether address is stored in		 * eeprom offset 0x10		 */		addr = eeprom_read(nd, i + 10);		nd->hw_addr[i * 2] = addr >> 8;		nd->hw_addr[i * 2 + 1] = addr;		printf("%c%02x:%02x", i == 0 ? ' ' : ':',			addr >> 8, addr & 255);	}	outw(Command_SelectRegisterWindow(3), Command);	// Reg window 3	resetoptions = inw(ResetOptions);	intcfg = inl(InternalConfig);	switch (intcfg & (15 << 20)) {	case InternalConfig_xcvr10bt:		nd->default_media = media_10bt;		def_media = "10baseT";		break;	case InternalConfig_xcvr10b5:		nd->default_media = media_aui;		def_media = "AUI";		break;	case InternalConfig_xcvr10b2:		nd->default_media = media_10b2;		def_media = "10base2";		break;	case InternalConfig_xcvr100btx:		nd->default_media = media_100btx;		def_media = "100baseTX";		break;	case InternalConfig_xcvr100bfx:		nd->default_media = media_100bfx;		def_media = "100baseFX";		break;	case InternalConfig_xcvrmii:		nd->default_media = media_mii;		def_media = "MII";		break;	case InternalConfig_xcvrnway:		nd->default_media = media_nway;		def_media = "NWAY";		break;	default:		nd->default_media = media_10bt;		def_media = "?";		break;	}	printf(", media %s\n  Supported media: ", def_media);	if (resetoptions & ResetOptions_100bT4available)		printf("100baseT4 ");	if (resetoptions & ResetOptions_100bTXavailable)		printf("100baseTX ");	if (resetoptions & ResetOptions_100bFXavailable)		printf("100baseFX ");	if (resetoptions & ResetOptions_10bTavailable)		printf("10baseT ");	if (resetoptions & ResetOptions_10b2available)		printf("10base2 ");	if (resetoptions & ResetOptions_10b5available)		printf("AUI ");	if (resetoptions & ResetOptions_miiavailable)		printf("MII");	printf("\n");	nd->media = nd->default_media;	/*	 * Setup the net device	 */	eth_setup(nd);	return 0;}static int nd_3c59x_setmedia(struct netdev *nd, media_t media){	unsigned int intcfg, medstat, macctrl;	/*	 * Read internal config and media status registers	 */	outw(Command_SelectRegisterWindow(3), Command);	intcfg  = inl(InternalConfig);	macctrl = inw(MacControl);	outw(Command_SelectRegisterWindow(4), Command);	medstat = inw(MediaStatus);	intcfg  &= ~InternalConfig_xcvrSelect(15);	medstat &= ~(MediaStatus_jabberGuardEnable |		     MediaStatus_linkBeatEnable |		     MediaStatus_enableSqeStats);	macctrl = 0;	switch (media) {	case media_10bt:		medstat |= MediaStatus_jabberGuardEnable | MediaStatus_linkBeatEnable;//		macctrl = MacControl_fullDuplexEnable;		break;	case media_100btx:		intcfg  |= InternalConfig_xcvr100btx;		medstat |= MediaStatus_linkBeatEnable;		break;	case media_100bfx:		intcfg  |= InternalConfig_xcvr100bfx;		medstat |= MediaStatus_linkBeatEnable;		break;	case media_nway:		intcfg  |= InternalConfig_xcvrnway;		break;	case media_mii:		intcfg  |= InternalConfig_xcvrmii;		break;	case media_10b2:		intcfg  |= InternalConfig_xcvr10b2;		break;	case media_aui:		intcfg  |= InternalConfig_xcvr10b5;		medstat |= MediaStatus_enableSqeStats;		break;	default:		return -1;	}	/*	 * Write internal config and media status registers back	 */	outw(Command_SelectRegisterWindow(3), Command);	outw(macctrl, MacControl);	outl(intcfg, InternalConfig);	send_and_wait_cmd(nd, Command_TxReset(0));	// Tx Reset	send_and_wait_cmd(nd, Command_RxReset(0));	// Rx Reset	/*	 * Don't write the mediastatus register	 * when we are using NWAY	 */	if (media != media_nway) {		outw(Command_SelectRegisterWindow(4), Command);		outw(medstat, MediaStatus);	}	return 0;}static int nd_3c59x_checkmedia(struct netdev *nd){	return 0;}static int nd_3c59x_open(struct netdev *nd){	nd_3c59x_setmedia(nd, nd->media);	outw(Command_SetRxFilter(5), Command);		// SetRxFilter	outw(Command_SelectRegisterWindow(2), Command);	// Reg window 2	outw(nd->hw_addr[0] | nd->hw_addr[1] << 8, 0);	outw(nd->hw_addr[2] | nd->hw_addr[3] << 8, 2);	outw(nd->hw_addr[4] | nd->hw_addr[5] << 8, 4);	outw(0, 6);					// StationMask	outw(0, 8);	outw(0, 10);	if (nd->driver & TXDMA) {		nd->ptr1 = malloc(sizeof(struct tx_desc));		memset(nd->ptr1, 0, sizeof(struct tx_desc));		outb(1536 >> 8, TxFreeThreshold);		outl(0, TxDownListPtr);	}	if (nd->driver & RXDMA) {		struct rx_desc *rx;		rx = nd->ptr2 = malloc(sizeof(struct rx_desc) + 1536);		memset(rx, 0, sizeof(struct rx_desc));		rx->next   = virt_to_bus((u32)rx);		rx->addr   = virt_to_bus((u32)(rx + 1));		rx->length = 1536 | LastFrag;		outw(Command_SetRxEarlyThresh(1536 >> 2), Command);		outl(0x0020, PacketStatus);		outl(virt_to_bus((u32)rx), RxUpListPtr);	}	outw(Command_TxEnable, Command);		// TxEnable	outw(Command_RxEnable, Command);		// RxEnable	outw(Command_SetIndicationEnable(0x7ff), Command);// SetIndicationEnable	outw(Command_StatisticsEnable, Command);	// StatisticsEnable	return 0;}static int nd_3c59x_close(struct netdev *nd){	outw(Command_TxDisable, Command);	outw(Command_RxDisable, Command);	return 0;}static int nd_3c59x_status(struct netdev *nd){	return 0;}static int nd_3c59x_send(struct netdev *nd, void *buffer, int size){	if (nd->driver & TXDMA) {		struct tx_desc *tx = nd->ptr1;		int count;		tx->next = 0;		tx->addr = virt_to_bus((u32)buffer);		tx->length = size | LastFrag;		tx->status = size;		send_and_wait_cmd(nd, Command_DownStall);		outl(virt_to_bus((u32)tx), TxDownListPtr);		send_and_wait_cmd(nd, Command_DownUnstall);		count = 0;		while ((tx->status & DownComplete) == 0) {			count++;			wait_cs(1);			if (count > 500) {				printf("tx timed out: status %04x\n", inw(IntStatus));				break;			}		}	} else {		unsigned long *frame = (unsigned long *)buffer;		while (inw(TxFree) < size);		outl(size, TxData);		while (size > 0) {			outl(*frame++, TxData);			size -= 4;		}	}	return 0;}static int nd_3c59x_recv(struct netdev *nd, void *buf){	int length = 0;	if (nd->driver & RXDMA) {		struct rx_desc *rx = nd->ptr2;		if (!(rx->status & RxComplete))			goto no_packet;		if (!(rx->status & RxError)) {			length = rx->status & 0x1fff;			memcpy(buf, rx + 1, length);		}		rx->status = 0;		outw(Command_UpUnstall, Command);	} else {		unsigned long *frame = (unsigned long *)buf;		int rxstat;		if (!(inw(IntStatus) & IntStatus_rxComplete))			goto no_packet;		rxstat = inw(RxStatus);		if (!(rxstat & RxStatus_rxError)) {			int i = length = rxstat & RxStatus_rxBytes;			while (i > 0) {				i -= 4;				*frame++ = inl(RxData);			}		}		outw(Command_RxDiscard, Command);	}	return length;no_packet:	return 0;}static const struct netdev_ops nd_3c59x_ops = {	nd_3c59x_probe,	nd_3c59x_open,	nd_3c59x_close,	nd_3c59x_status,	nd_3c59x_setmedia,	nd_3c59x_checkmedia,	nd_3c59x_send,	nd_3c59x_recv,};struct netdev net_dev_3com_3c59x = {	&nd_3c59x_ops,	&eth_trans_ops,};

⌨️ 快捷键说明

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