www.pudn.com > vxworks0108.rar > dec21143.c


/*
modification history
--------------------
2003-4-14,deng xindong   dxd-2000@163.net
*/


#include "type.h"
#include "config.h"
#include "vxWorks.h"
#include "ivppc.h"
#include "vg4.h"
#include "pciConfigLib.h"
#include "pciIntLib.h"
#include "pciAutoConfigLib.h"
#include "lwip/debug.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/cc.h"
#include "netif/arp.h"
#include "decif.h"


#define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_21143 0x0019

#define NUM_RX_DESC             32
#define NUM_TX_DESC             32
#define DE_RX_RING_SIZE		64
#define DE_TX_RING_SIZE		64

#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/

static int csr0 = 0x01A00000 | 0x8000;
const struct eth_addr ethbroadcast = {0x0,0x20,0xce,0xc5,0x43,0x1d};


struct DEC21143if {
	struct eth_addr *ethaddr;
	unsigned		tx_head;
	unsigned		tx_tail;
	unsigned		rx_tail;
	struct de_desc	*rx_ring;
	struct de_desc	*tx_ring;
	u32_t      iobaseCsr;              /* Base Address Register 0 */
	u32_t      membaseCsr;             /* Base Address Register 1 */
	char        irq;                    /* Interrupt Request Level */
	u32_t      irqvec;                 /* Interrupt Request vector */
	u32_t      configType;             /* type of configuration */
	u32_t      boardType;              /* type of LAN board this unit is */
	u32_t      pciBus;                 /* PCI Bus number */
	u32_t      pciDevice;              /* PCI Device number */
	u32_t      pciFunc;                /* PCI Function number */
	/* Add whatever per-interface state that is needed here. */
};


enum {
	/* NIC registers */
	        BusMode			= 0x00,  /* bus mode register */
		TxPoll			= 0x08,  /* transmit poll demand */                 
		RxPoll			= 0x10,  /* receive poll demand */
		RxRingAddr		= 0x18,  /* receive list base address */
		TxRingAddr		= 0x20,  /* transmit list base address */
		MacStatus		= 0x28,  /* status register */
		MacMode			= 0x30,  /* operation mode register */
		IntrMask		= 0x38,  /* interrupt mask register */
		RxMissed		= 0x40,  /* missed frame counter */
		ROMCmd			= 0x48,  /* Ethernet ROM register */
		CSR11			= 0x58,  /* full-duplex register */
		SIAStatus		= 0x60,  /* SIA status register */
		CSR13			= 0x68,
		CSR14			= 0x70,
		CSR15			= 0x78,
		PCIPM			= 0x40,
		
		/* BusMode bits */
		CmdReset		= (1 << 0),
		CacheAlign16		= 0x00008000,
		BurstLen4		= 0x00000400,
		
		/* Rx/TxPoll bits */
		NormalTxPoll		= (1 << 0),
		NormalRxPoll		= (1 << 0),
		
		/* Tx/Rx descriptor status bits */
		DescOwn			= (1 << 31),
		RxError			= (1 << 15),
		RxErrLong		= (1 << 7),
		RxErrCRC		= (1 << 1),
		RxErrFIFO		= (1 << 0),
		RxErrRunt		= (1 << 11),
		RxErrFrame		= (1 << 14),
		RingEnd			= (1 << 25),
		FirstFrag		= (1 << 29),
		LastFrag		= (1 << 30),
		TxError			= (1 << 15),
		TxFIFOUnder		= (1 << 1),
		TxLinkFail		= (1 << 2) | (1 << 10) | (1 << 11),
		TxMaxCol		= (1 << 8),
		TxOWC			= (1 << 9),
		TxJabber		= (1 << 14),
		SetupFrame		= (1 << 27),
		TxSwInt			= (1 << 31),
		
		/* MacStatus bits */
		IntrOK			= (1 << 16),
		IntrErr			= (1 << 15),
		RxIntr			= (1 << 6),
		RxEmpty			= (1 << 7),
		TxIntr			= (1 << 0),
		TxEmpty			= (1 << 2),
		PciErr			= (1 << 13),
		TxState			= (1 << 22) | (1 << 21) | (1 << 20),
		RxState			= (1 << 19) | (1 << 18) | (1 << 17),
		LinkFail		= (1 << 12),
		LinkPass		= (1 << 4),
		RxStopped		= (1 << 8),
		TxStopped		= (1 << 1),
		
		/* MacMode bits */
		TxEnable		= (1 << 13),
		RxEnable		= (1 << 1),
		RxTx			= TxEnable | RxEnable,
		FullDuplex		= (1 << 9),
		AcceptAllMulticast	= (1 << 7),
		AcceptAllPhys		= (1 << 6),
		BOCnt			= (1 << 5),
		MacModeClear		= (1<<12) | (1<<11) | (1<<10) | (1<<8) | (1<<3) |
		RxTx | BOCnt | AcceptAllPhys | AcceptAllMulticast,
		
		/* ROMCmd bits */
		EE_SHIFT_CLK		= 0x02,	/* EEPROM shift clock. */
		EE_CS			= 0x01,	/* EEPROM chip select. */
		EE_DATA_WRITE		= 0x04,	/* Data from the Tulip to EEPROM. */
		EE_WRITE_0		= 0x01,
		EE_WRITE_1		= 0x05,
		EE_DATA_READ		= 0x08,	/* Data from the EEPROM chip. */
		EE_ENB			= (0x4800 | EE_CS),
		
		/* The EEPROM commands include the alway-set leading bit. */
		EE_READ_CMD		= 6,
		
		/* RxMissed bits */
		RxMissedOver		= (1 << 16),
		RxMissedMask		= 0xffff,
		
		/* SROM-related bits */
		SROMC0InfoLeaf		= 27,
		MediaBlockMask		= 0x3f,
		MediaCustomCSRs		= (1 << 6),
		
		/* PCIPM bits */
		PM_Sleep		= (1 << 31),
		PM_Snooze		= (1 << 30),
		PM_Mask			= PM_Sleep | PM_Snooze,
		
		/* SIAStatus bits */
		NWayState		= (1 << 14) | (1 << 13) | (1 << 12),
		NWayRestart		= (1 << 12),
		NonselPortActive	= (1 << 9),
		LinkFailStatus		= (1 << 2),
		NetCxnErr		= (1 << 1),
};

static const u32_t de_intr_mask =
IntrOK | IntrErr | RxIntr | RxEmpty | TxIntr | TxEmpty |
LinkPass | LinkFail | PciErr;

static const u32_t de_bus_mode = /*0x02e000f8;*/  CacheAlign16 | BurstLen4;
static const u32_t de_MacStatus   = 0x66f0;  /* status register */
static const u32_t de_MacMode     = 0x03e04432;  /* operation mode register */
static const u32_t de_IntrMask    =0xc5a0fff3;

static struct de_desc rx_ring[NUM_RX_DESC];
static struct de_desc tx_ring[NUM_TX_DESC];	

#define dr32(reg)		readl(de->membaseCsr + (reg))
#define dw32(reg,val)		writel(de->membaseCsr + (reg),(val))

#define mdelay                  sysMsDelay

void dec_recv_packet(struct netif *netif);
err_t dec_send_packet(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
int dec_pci_init(struct DEC21143if *deif);
static void de_interrupt (struct DEC21143if *de);
static int de_is_running (struct DEC21143if *de);
static void de_reset_mac (struct DEC21143if *de);

unsigned long cpu_to_le32(unsigned long x)
{
	return (((x & 0x000000ffU) << 24) |
		((x & 0x0000ff00U) <<  8) |
		((x & 0x00ff0000U) >>  8) |
		((x & 0xff000000U) >> 24));
}


static unsigned short tulip_read_eeprom(int regs, int location, int addr_len)
{
	int i;
	unsigned short retval = 0;
	unsigned int ee_addr = (unsigned int)(regs + ROMCmd);
	int read_cmd = location | (EE_READ_CMD << addr_len);
	
	writel(ee_addr,EE_ENB & ~EE_CS);
	writel(ee_addr,EE_ENB);
	
	/* Shift the read command bits out. */
	for (i = 4 + addr_len; i >= 0; i--) {
		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
		writel(ee_addr,EE_ENB | dataval);
		readl(ee_addr);
		writel(ee_addr,EE_ENB | dataval | EE_SHIFT_CLK);
		readl(ee_addr);
		retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
	}
	writel(ee_addr,EE_ENB);
	readl(ee_addr);
	
	for (i = 16; i > 0; i--) {
		writel(ee_addr,EE_ENB | EE_SHIFT_CLK);
		readl(ee_addr);
		retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
		writel(ee_addr,EE_ENB);
		readl(ee_addr);
	}
	
	/* Terminate the EEPROM access. */
	writel( ee_addr,EE_ENB & ~EE_CS);
	return (((retval<<8)&0xff00) | ((retval>>8)&0xff) );
}


static void de_reset_mac (struct DEC21143if *de)
{
	u32_t tmp;
	u32_t status;
	
	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
	if (dr32(BusMode) == 0xffffffff)
	{
		printf("dec busy\n");
	}
	
	dw32 (BusMode, CmdReset);
	mdelay (1);
	
	dw32 (BusMode, de_bus_mode);
	mdelay (1);
	
	for (tmp = 0; tmp < 5; tmp++) {
		dr32 (BusMode);
		mdelay (1);
	}	
	mdelay (1);
	
	status = dr32(MacStatus);
	if (status & (RxState | TxState))
	{
		printf("dec busy\n");
	}		
	if (status == 0xffffffff)
	{
		printf("no dec \n");
	}
	
        printf("dec reset\n");
}

static void de_adapter_wake (struct DEC21143if *de)
{
	u32_t pmctl;

	pciConfigInLong(de->pciBus, de->pciDevice, de->pciFunc, PCIPM, &pmctl);
	if (pmctl & PM_Mask) {
		pmctl &= ~PM_Mask;
		pciConfigOutLong(de->pciBus, de->pciDevice, de->pciFunc, PCIPM, pmctl);

	}
}


static void de_stop_rxtx (struct DEC21143if *de)
{
	u32_t macmode;
	unsigned int work = 1000;

	macmode = dr32(MacMode);
	if (macmode & RxTx) {
		dw32(MacMode, macmode & ~RxTx);
		dr32(MacMode);
	}

	while (--work > 0) {
		if (!de_is_running(de))
			return;		
	}
	
	printf("timeout expired stopping DMA\n");
}

static void de_set_rx_mode (struct DEC21143if *de)
{	
	u32_t macmode;	

	macmode = dr32(MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);
	macmode |= AcceptAllMulticast | AcceptAllPhys;
	
	if (macmode != dr32(MacMode))
		dw32(MacMode, macmode);
}


static void de_start_rxtx (struct DEC21143if *de)
{
	u32_t macmode;

	macmode = dr32(MacMode);
	if ((macmode & RxTx) != RxTx) {
		dw32(MacMode, macmode | RxTx);
		dr32(MacMode);
	}
}

static void de_stop_hw (struct DEC21143if *de)
{
	
	mdelay(5);
	dw32(IntrMask, 0);
	
	de_stop_rxtx(de);
	
	dw32(MacStatus, dr32(MacStatus));
	
	mdelay(10);
	
	de->rx_tail = 0;
	de->tx_head = de->tx_tail = 0;
}



static int de_is_running (struct DEC21143if *de)
{
	return (dr32(MacStatus) & (RxState | TxState)) ? 1 : 0;
}


static void de_set_media (struct DEC21143if *de)
{
	
	u32_t macmode = dr32(MacMode);
	if (de_is_running(de))
	{
		printf("dec21143 is running\n");
		return ;
	}
	
	
	dw32(CSR13, 0); /* Reset phy */
	
			/* must delay 10ms before writing to other registers,
			* especially CSR6
	*/
	mdelay(10);
	
	macmode |= FullDuplex;	
	
	if (macmode != dr32(MacMode))
		dw32(MacMode, macmode);
}


static int de_init_hw (struct netif *netif)
{
	struct DEC21143if *de;
	unsigned int  macmode;	
	
	de = (struct DEC21143if *)netif->state;
	
	de_adapter_wake(de);
	macmode = dr32(MacMode) & ~MacModeClear;
	
	de_reset_mac(de);        
       
	de_set_media(de); /* reset phy */	
	
	dw32(RxRingAddr, (int)rx_ring);
	dw32(TxRingAddr, (int)tx_ring);       
        
        intConnect(INUM_TO_IVEC(de->irqvec),(VOIDFUNCPTR)de_interrupt,(int)de);        
	dw32(MacMode, RxTx | macmode);	
	dr32(RxMissed); /* self-clearing */
	
	printf("de_intr_mask=%x  ",de_intr_mask);
	
	dw32(IntrMask, de_intr_mask);        
	de_start_rxtx(de);
		
        printf("BusMode= %x   ", dr32(BusMode)); 
        printf("TxPoll= %x   ", dr32(TxPoll)); 
        printf("RxPoll= %x    ", dr32(RxPoll)); 
        printf("RxRingAddr= %x   ", dr32(RxRingAddr)); 
        printf("TxRingAddr= %x   ", dr32(TxRingAddr)); 
        printf("MacStatus= %x   ", dr32(MacStatus)); 
        printf("MacMode= %x   ", dr32(MacMode)); 
        printf("IntrMask= %x    ", dr32(IntrMask)); 
        printf("RxMissed= %x    ", dr32(RxMissed)); 
        printf("ROMCmd= %x    ", dr32(ROMCmd)); 
        printf("CSR11= %x    ", dr32(CSR11)); 
        printf("SIAStatus= %x    ", dr32(SIAStatus)); 
        printf("CSR13= %x    ", dr32(CSR13)); 
        printf("CSR14= %x    ", dr32(CSR14)); 
        printf("CSR15= %x    ", dr32(CSR15)); 
        printf("de_init_hw ok\n");
        intEnable(de->irqvec);
	return 0;
	
}

static void de_rx (struct DEC21143if *de)
{
	printf("de_receive\n");
}


static void de_tx (struct DEC21143if *de)
{
	printf("de_tricve\n");
}



static void de_interrupt (struct DEC21143if *de)
{	
	u32_t status;
        printf("de_int\n");
	status = dr32(MacStatus);
	
	if ((!(status & (IntrOK|IntrErr))) || (status == 0xFFFF))
	{
		dw32(MacStatus, status);
		printf("status=%x,error\n",status);
		return ;
	}
	
	dw32(MacStatus, status);
	
	if (status & (RxIntr | RxEmpty)) {
		de_rx(de);
		if (status & RxEmpty)
			dw32(RxPoll, NormalRxPoll);
	}	
	
	if (status & (TxIntr | TxEmpty))
		de_tx(de);
		
	if (status & PciErr) {
		u16_t pci_status;

		pciConfigInWord(de->pciBus, de->pciDevice, de->pciFunc, PCI_CFG_STATUS, &pci_status);
		pciConfigOutWord(de->pciBus, de->pciDevice, de->pciFunc, PCI_CFG_STATUS, pci_status);
		printf("PCI bus error, status=%08x, PCI status=%04x\n",
		       status, pci_status);
	}
	
}

static int de_refill_rx (struct DEC21143if *de)
{
	unsigned i;
	
	for (i = 0; i < DE_RX_RING_SIZE; i++) {		
		
		de->rx_ring[i].status = cpu_to_le32(DescOwn);
		if (i == (DE_RX_RING_SIZE - 1))
			de->rx_ring[i].length =
			cpu_to_le32(RingEnd | PKT_BUF_SZ);
		else
			de->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
		de->rx_ring[i].buffer1 = 0;
		de->rx_ring[i].buffer2 = 0;
	}
	
	return 0;
}


static int de_init_rings (struct DEC21143if *de)
{
	memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE);
	de->tx_ring[DE_TX_RING_SIZE - 1].length = cpu_to_le32(RingEnd);
	
	de->rx_tail = 0;
	de->tx_head = de->tx_tail = 0;
	
	return de_refill_rx (de);
}


/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* WARNING: must close all interrupts during init!!!!
/*-----------------------------------------------------------------------------------*/
void dec_init(struct netif *netif)
{
	struct DEC21143if *dec21143if;
	
	dec21143if = mem_malloc(sizeof(struct DEC21143if));
	netif->state = dec21143if;
	netif->name[0] = 'd';
	netif->name[1] = 'e';
	netif->output = dec_send_packet;
	if(dec_pci_init(dec21143if) == OK)
	{
		printf("dec_pci_init ok\n");
	}
	de_init_hw(netif);
	arp_init();
}

static err_t low_level_send(struct DEC21143if *de,struct pbuf *p)
{
	
}

static struct pbuf * low_level_receive(struct DEC21143if *de)
{
	
}

/**
* Send a packet to the RTK8019as from a series of pbuf buffers.
*/
err_t dec_send_packet(struct netif *netif, struct pbuf *p,
		      struct ip_addr *ipaddr)
{
	struct DEC21143if *dec21143if;
	struct pbuf *q;
	struct eth_hdr *ethhdr;
	struct eth_addr *dest, mcastaddr;
	struct ip_addr *queryaddr;
	err_t err = 0;
	u8_t i;
	
	dec21143if = netif->state;
	
	/* Make room for Ethernet header. */
	if(pbuf_header(p, 14) != 0) {
	/* The pbuf_header() call shouldn't fail, but we allocate an extra
		pbuf just in case. */
		q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
		if(q == NULL) {
			return ERR_MEM;
		}
		pbuf_chain(q, p);
		p = q;
	}
	
	/* Construct Ethernet header. Start with looking up deciding which
	MAC address to use as a destination address. Broadcasts and
	multicasts are special, all other addresses are looked up in the
	ARP table. */
	queryaddr = ipaddr;
	if(ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
		dest = (struct eth_addr *)ðbroadcast;
	} 
	else if(ip_addr_ismulticast(ipaddr)) {
		/* Hash IP multicast address to MAC address. */
		mcastaddr.addr[0] = 0x01;
		mcastaddr.addr[1] = 0x0;
		mcastaddr.addr[2] = 0x5e;
		mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
		mcastaddr.addr[4] = ip4_addr3(ipaddr);
		mcastaddr.addr[5] = ip4_addr4(ipaddr);
		dest = &mcastaddr;
	} else {
		
		if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
		/* Use destination IP address if the destination is on the same
			subnet as we are. */
			queryaddr = ipaddr;
		} else {
		/* Otherwise we use the default router as the address to send
			the Ethernet frame to. */
			queryaddr = &(netif->gw);
		}
		dest = arp_lookup(queryaddr);
	}
	
	
	/* If the arp_lookup() didn't find an address, we send out an ARP
	query for the IP address. */
	if(dest == NULL) {
		q = arp_query(netif, dec21143if->ethaddr, queryaddr);
		if(q != NULL) {
			low_level_send(dec21143if, q);
			pbuf_free(q);
			return err;
		}
		
		return ERR_MEM;
	}
	ethhdr = p->payload;
	
	for(i = 0; i < 6; i++) {
		ethhdr->dest.addr[i] = dest->addr[i];
		ethhdr->src.addr[i] = dec21143if->ethaddr->addr[i];
	}
	
	ethhdr->type = htons(ETHTYPE_IP);
	
	return low_level_send(dec21143if, p);
	
}


/**
* Read a packet, clearing overflows.
*/
void dec_recv_packet(struct netif *netif)
{
	struct DEC21143if *dec21143if;
	struct eth_hdr *ethhdr;
	struct pbuf *p = NULL;
	
	dec21143if = netif->state;  
	p = low_level_receive(dec21143if); 
	
	if(p == NULL) {
		return;
	}
	ethhdr = p->payload;
	
	switch(htons(ethhdr->type)) {
	case ETHTYPE_IP:
		arp_ip_input(netif, p);
		pbuf_header(p, -14);
		netif->input(p, netif);
		break;
	case ETHTYPE_ARP:
		p = arp_arp_input(netif, dec21143if->ethaddr, p);
		if(p != NULL) {
			low_level_send(dec21143if, p);
			pbuf_free(p);
		}
		break;
	default:
		pbuf_free(p);
		break;
	}
}

int dec_pci_init(struct DEC21143if *deif)
{	
	u32_t              pciBus;         /* PCI Bus number */
	u32_t              pciDevice;      /* PCI Device number */
	u32_t              pciFunc;        /* PCI Function number */
	u32_t              membaseCsr;     /* Base Address Register 1 */
	u32_t              iobaseCsr;      /* Base Address Register 0 */
	char               irq;            /* Interrupt Request Level */    
	
	int                i;
        unsigned char     temp[600];
        int sa_offset=0;
        
	if (pciFindDevice (PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21143,
		0, &pciBus, &pciDevice, &pciFunc) == ERROR)                             
	{
		return ERROR;          
	}     
	
	deif->pciBus    = pciBus;
	deif->pciDevice = pciDevice;
	deif->pciFunc   = pciFunc;
	
	/* get memory base address and IO base address */
	
	pciConfigInLong (deif->pciBus, deif->pciDevice, deif->pciFunc,
		PCI_CFG_BASE_ADDRESS_0, &iobaseCsr);
	pciConfigInLong (deif->pciBus, deif->pciDevice, deif->pciFunc,
		PCI_CFG_BASE_ADDRESS_1, &membaseCsr);
	pciConfigInByte (deif->pciBus, deif->pciDevice, deif->pciFunc,
		PCI_CFG_DEV_INT_LINE, &irq);
	
	membaseCsr   &= PCI_MEMBASE_MASK;
	iobaseCsr    &= PCI_IOBASE_MASK ;
	
	/* overwrite the resource table with read value */
	deif->membaseCsr   = membaseCsr ;
	deif->iobaseCsr    = iobaseCsr ;
	deif->irq          = irq;
	deif->irqvec       = IVEC_TO_INUM(irq);
	
	pciConfigOutWord (pciBus, pciDevice, pciFunc, PCI_CFG_COMMAND,
		PCI_CMD_MEM_ENABLE  |
		PCI_CMD_MASTER_ENABLE);
	pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_MODE, SLEEP_MODE_DIS);
	pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_LATENCY_TIMER, 0x30);
	
	temp[0] = tulip_read_eeprom(deif->membaseCsr, 0xff, 8) & 0x40000 ? 8 : 6;
        printf("ee_addr_size=%08x\n",temp[0]);
        printf("deif->membaseCsr=%08x  ",deif->membaseCsr);
        printf("deif->iobaseCsr=%08x   ",deif->iobaseCsr);
        printf("deif->irq=%d   ",deif->irq);
        
	for(i=0; i<256; i++)
	{
		((u16_t*)temp)[i] = tulip_read_eeprom(deif->membaseCsr, i,6);		
		
	}	
	
	for (i = 0; i < 8; i ++)
		if (temp[i] != temp[16+i])
			sa_offset = 20;			
	
/*	ethbroadcast = *(struct eth_addr*)&temp[sa_offset];*/
	
	printf("dec %x:%x:%x:%x:%x:%x\n",ethbroadcast.addr[0],ethbroadcast.addr[1],ethbroadcast.addr[2],ethbroadcast.addr[3],ethbroadcast.addr[4],ethbroadcast.addr[5]);
	      
	return (OK);
}