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

📄 rtl8139c.c

📁 newos is new operation system
💻 C
字号:
/* $Id: //depot/dcdev/netboot/rtl8139c.c#1 $**** Copyright 2001 Brian J. Swetland** All rights reserved.**** Redistribution and use in source and binary forms, with or without** modification, are permitted provided that the following conditions** are met:** 1. Redistributions of source code must retain the above copyright**    notice, this list of conditions, and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright**    notice, this list of conditions, and the following disclaimer in the**    documentation and/or other materials provided with the distribution.** 3. The name of the author may not be used to endorse or promote products**    derived from this software without specific prior written permission.**** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*//***  PCI GAPS & Original 8139C Code:****  Naive RealTek 8139C driver for the DC Broadband Adapter. Some **  assistance on names of things from the NetBSD-DC sources.**  **  (c)2001 Dan Potter**  License: X11***/#include "defs.h"#include <kernel/debug.h>#include <string.h>#include <stdarg.h>#include "rtl8139c.h"/* Convienence macros */#define REGL(a) (volatile unsigned long *)(a)#define vul volatile unsigned long#define REGS(a) (volatile unsigned short *)(a)#define vus volatile unsigned short#define REGC(a) (volatile unsigned char *)(a)#define vuc volatile unsigned char/* Configuration definitions */#define RX_BUFFER_LEN		8192#define ADDR_RXBUF 0x01840000#define ADDR_TXBUF0 0x01846000/* Mac address of card */u1 rtl_mac[6];/* 8, 16, and 32 bit access to the PCI I/O space (configured by GAPS) */static vuc * const nic8 = REGC(0xa1001700);static vus * const nic16 = REGS(0xa1001700);static vul * const nic32 = REGL(0xa1001700);/* 8 and 32 bit access to the PCI MEMMAP space (configured by GAPS) */static vuc * const mem8 = REGC(0xa1840000);static vul * const mem32 = REGL(0xa1840000);/*  Detect the presence of a Broadband Adapter  This really detects a "GAPS PCI" bridge chip, but the only device  for the Dreamcast that uses it is the net card.    Returns 0 if one is present, -1 if one is not. */int rtl8139_detect() {	const char *str = (char*)REGC(0xa1001400);	const char *chk = "GAPSPCI_BRIDGE_2";	int i;		for(i = 0; i < 16; i++){		if(str[i] != chk[i]) return -1;	}	return 0;}int bb_exit(){	int i;	dprintf("rtl8139c: shutdown\n");	/* Soft-reset the chip */	nic8[RT_CHIPCMD] = RT_CMD_RESET;		/* Wait for it to come back */	i = 1000000;	while ((nic8[RT_CHIPCMD] & RT_CMD_RESET) && i > 0)		i--;	if(i == 0) {		dprintf("rtl8139: CANNOT RESET\n");	} else {		dprintf("rtl8139: RESET OKAY\n");	}	return 0;}/*  Initializes the BBA    Returns 0 for success or -1 for failure. */int rtl8139_init() {	vuc * const g28 = REGC(0xa1000000);	vus * const g216 = REGS(0xa1000000);	vul * const g232 = REGL(0xa1000000);	int i;	u4 tmp;			/* Initialize the "GAPS" PCI glue controller.	   It ain't pretty but it works. */	g232[0x1418/4] = 0x5a14a501;		/* M */	i = 10000;	while (!(g232[0x1418/4] & 1) && i > 0)		i--;	if (!(g232[0x1418/4] & 1)) {		dprintf("rtl8139: GAPS PCI controller not responding; giving up!\n");		return -1;	}	g232[0x1420/4] = 0x01000000;	g232[0x1424/4] = 0x01000000;	g232[0x1428/4] = 0x01840000;		/* DMA Base */	g232[0x142c/4] = 0x01840000 + 32*1024;	/* DMA End */	g232[0x1414/4] = 0x00000001;	g232[0x1434/4] = 0x00000001;	/* Configure PCI bridge (very very hacky). If we wanted to be proper,	   we ought to implement a full PCI subsystem. In this case that is	   ridiculous for accessing a single card that will probably never	   change. Considering that the DC is now out of production officially,	   there is a VERY good chance it will never change. */	g216[0x1606/2] = 0xf900;	g232[0x1630/4] = 0x00000000;	g28[0x163c] = 0x00;	g28[0x160d] = 0xf0;	(void)g216[0x04/2];	g216[0x1604/2] = 0x0006;	g232[0x1614/4] = 0x01000000;	(void)g28[0x1650];		memset((void *)PHYS_ADDR_TO_P1(ADDR_RXBUF), 0, 32*1024);	/* Soft-reset the chip */	nic8[RT_CHIPCMD] = RT_CMD_RESET;		/* Wait for it to come back */	i = 1000000;	while ((nic8[RT_CHIPCMD] & RT_CMD_RESET) && i > 0)		i--;	if(i == 0) {		dprintf("rtl8139: CANNOT RESET\n");		return -1;	} else {		dprintf("rtl8139: RESET OKAY\n");	}	dprintf("0x%x\n", nic16[RT_RXBUFHEAD/2]);	/* Reset CONFIG1 */	nic8[RT_CONFIG1] = 0;		/* Enable auto-negotiation and restart that process */	nic16[RT_MII_BMCR/2] = 0x1200;	for(i = 0; i < 100000; i++);		/* Do another reset */#if 0	nic8[RT_CHIPCMD] = RT_CMD_RESET;		/* Wait for it to come back */	i = 1000;	while ((nic8[RT_CHIPCMD] & RT_CMD_RESET) && i > 0)		i--;#endif		/* Enable writing to the config registers *///	nic8[RT_CFG9346] = 0xc0;		/* Read MAC address */	tmp = nic32[RT_IDR0];	rtl_mac[0] = tmp & 0xff;	rtl_mac[1] = (tmp >> 8) & 0xff;	rtl_mac[2] = (tmp >> 16) & 0xff;	rtl_mac[3] = (tmp >> 24) & 0xff;	tmp = nic32[RT_IDR0+1];	rtl_mac[4] = tmp & 0xff;	rtl_mac[5] = (tmp >> 8) & 0xff;	dprintf("rtl8139: MAC ADDR %X:%X:%X:%X:%X:%X\n",		rtl_mac[0], rtl_mac[1], rtl_mac[2],		rtl_mac[3], rtl_mac[4], rtl_mac[5]);	/* Enable receive and transmit functions */	nic8[RT_CHIPCMD] = RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE;	/* Set Rx FIFO threashold to 1K, Rx size to 8k+16, 1024 byte DMA burst, WRAP mode */	nic32[RT_RXCONFIG/4] = 0x0000c680;		/* Set Tx 1024 byte DMA burst */	nic32[RT_TXCONFIG/4] = 0x03000600;	/* Turn off lan-wake and set the driver-loaded bit */	nic8[RT_CONFIG1] = (nic8[RT_CONFIG1] & ~0x30) | 0x20;		/* Enable FIFO auto-clear */	nic8[RT_CONFIG4] |= 0x80;		/* Switch back to normal operation mode */	nic8[RT_CFG9346] = 0;		/* Setup Rx buffers */	nic32[RT_RXBUF/4] = ADDR_RXBUF;	nic32[RT_TXADDR0/4 + 0] = ADDR_TXBUF0;	nic32[RT_TXADDR0/4 + 1] = 0x01846800;	nic32[RT_TXADDR0/4 + 2] = 0x01847000;	nic32[RT_TXADDR0/4 + 3] = 0x01847800;		/* Reset RXMISSED counter */	nic32[RT_RXMISSED/4] = 0;		/* Enable receiving broadcast and physical match packets *///	nic32[RT_RXCONFIG/4] |= 0x0000000a;	nic32[RT_RXCONFIG/4] |= 0x0000000f;		/* Filter out all multicast packets */	nic32[RT_MAR0/4 + 0] = 0;	nic32[RT_MAR0/4 + 1] = 0;		/* Disable all multi-interrupts */	nic16[RT_MULTIINTR/2] = 0;//	nic16[RT_INTRMASK/2] = 0x807f;	nic16[RT_INTRMASK/2] = 0;		/* Enable RX/TX once more */	nic8[RT_CHIPCMD] = RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE;	nic8[RT_CFG9346] = 0;	dprintf("rtl8139: ready.\n");		return 0;}typedef struct {	volatile u2 status;	volatile u2 len;	volatile u1 data[1];} rx_entry;#define RXSIZE (8192)u1 *rxend = (u1*) (PHYS_ADDR_TO_P1(ADDR_RXBUF + RXSIZE));u1 *rxptr = (u1*) (PHYS_ADDR_TO_P1(ADDR_RXBUF));u1 *rxstart = (u1*) (PHYS_ADDR_TO_P1(ADDR_RXBUF));static int txbn = 0;void rtl8139_xmit(const char *ptr, int len){	int i;		dprintf("XMIT(%d) %x (%d)\n",txbn,ptr,len);		/* wait for clear-to-send */	while(!(nic32[txbn + RT_TXSTATUS0/4] & 0x2000)) {		if(nic32[txbn + RT_TXSTATUS0/4] & 0x40000000){			dprintf("rtl8139: XMIT STATUS ABORT!?\n");			nic32[txbn + RT_TXCONFIG/4] = 0x03000601;		}		for(i = 0; i < 1000; i++);	}		memcpy((void*) ((txbn * 0x800) + PHYS_ADDR_TO_P1(ADDR_TXBUF0)), ptr, len);	if(len < 64) len = 64;		nic32[txbn + RT_TXADDR0/4] = (txbn * 0x800) + ADDR_TXBUF0;	nic32[txbn + RT_TXSTATUS0/4] = len | 0x80000;#if 0		/* wait for clear-to-send */	while(!(nic32[txbn + RT_TXSTATUS0/4] & (0x20000 | 0x4000))) {		for(i = 0; i < 100; i++);	}#endif		dprintf("XMIT DONE %x\n",nic32[txbn + RT_TXSTATUS0/4]);	txbn = (txbn + 1) & 3;	}int rtl8139_rx(char *buf, int buf_len){	int len, status, i, crx;	int processed = 0;	rx_entry *rxe;//	if(1) {	dprintf("0x%x\n", nic8[RT_CHIPCMD]);	if (!(nic8[RT_CHIPCMD] & 1)) {		rxe = (rx_entry*) rxptr;		len = rxe->len;		status = rxe->status;		crx = nic16[RT_RXBUFTAIL/2];#if 1		dprintf("RX: @%x L:%x S:%x CRX:%x\n",rxptr,len,status,crx);#endif				if(len > 1500) {			panic("rtl8139_rx: frame too large 0x%x\n", len);		}		if(status & 1){			memcpy(buf, (char *)rxe->data, len - 4);			processed++;		} else {				/* error */		}			/* advance to next packet */		rxptr += ((len + 4 + 3) & ~3);		if(rxptr >= rxend){			rxptr = rxstart + (rxptr - rxend);		}			/* tell the 8139 where we are */		nic16[RT_RXBUFTAIL/2] = ((u4) (rxptr - rxstart)) - 16;	}	return processed;}int chatter = 1;int rtl8139_foo(){	for(;;) {		dprintf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 			(int)nic8[RT_CHIPCMD], (int)nic32[RT_RXCONFIG/4], 			(int)nic8[RT_MEDIASTATUS],			(int)nic16[RT_INTRSTATUS/2],			(int)nic32[RT_RXBUF/4], 			(int)nic16[RT_RXBUFHEAD/2],			(int)nic32[RT_RXMISSED/4]			);//		nic16[RT_RXBUFHEAD] = 0;//		if(nic16[RT_INTRSTATUS/2] == 0x20) //			panic("y0\n");	}	return 0;}

⌨️ 快捷键说明

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