davicom.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
#ifdef ALLMULTI
#endif
/*
This driver was ported from Marty Connor's Tulip Etherboot driver.
Thanks Marty Connor (mdc@etherboot.org)
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
*/
/*********************************************************************/
/* Revision History */
/*********************************************************************/
/*
19 OCT 2000 Sten 1.00
Different half and full duplex mode
12 OCT 2000 Sten 0.90
This driver was ported from tulip driver and it
has the following difference.
Deleted some code that did not use in this driver.
Used chain-strcture to replace ring structure
Allocated two tx descriptor.
According current media mode to set operating
register(CR6)
*/
/*********************************************************************/
/* Declarations */
/*********************************************************************/
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
/* Register offsets for davicom device */
enum davicom_offsets {
};
/* EEPROM Address width definitions */
#define EEPROM_ADDRLEN 6
/* Used to be 128, but we only need to read enough to get the MAC
address at bytes 20..25 */
/* Data Read from the EEPROM */
static unsigned char ee_data[EEPROM_SIZE];
/* The EEPROM commands include the alway-set leading bit. */
/* EEPROM_Ctrl bits. */
#define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05
/* Sten 10/11 for phyxcer */
#define PHY_DATA_0 0x0
#define PHY_DATA_1 0x20000
#define MDCLKH 0x10000
/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI
implementations don't overrun the EEPROM clock. We add a bus
turn-around to insure that this remains true. */
/* helpful macro if on a big_endian machine for changing byte order.
not strictly needed on Intel
Already defined in Etherboot includes
#define le16_to_cpu(val) (val)
*/
/* transmit and receive descriptor format */
struct txdesc {
volatile unsigned long status; /* owner, status */
const unsigned char *buf1addr; /* buffer 1 address */
const unsigned char *buf2addr; /* buffer 2 address */
};
struct rxdesc {
volatile unsigned long status; /* owner, status */
unsigned char *buf1addr; /* buffer 1 address */
unsigned char *buf2addr; /* buffer 2 address */
};
/* Size of transmit and receive buffers */
#define BUFLEN 1536
/*********************************************************************/
/* Global Storage */
/*********************************************************************/
/* PCI Bus parameters */
static unsigned long ioaddr;
/* Note: transmit and receive buffers must be longword aligned and
longword divisable */
/* transmit descriptor and buffer */
#define NTXD 2
/* receive descriptor(s) and buffer(s) */
#define NRXD 4
static int rxd_tail;
static int TxPtr;
/*********************************************************************/
/* Function Prototypes */
/*********************************************************************/
unsigned int s, const char *p);
#ifdef DAVICOM_DEBUG
static void davicom_more(void);
#endif /* DAVICOM_DEBUG */
static void davicom_wait(unsigned int nticks);
static int phy_read(int);
static int phy_read_1bit(u32);
static void davicom_media_chk(struct nic *);
/*********************************************************************/
/* Utility Routines */
/*********************************************************************/
{
/* sleep(2); */
}
#ifdef DAVICOM_DEBUG
static void davicom_more()
{
printf("\n\n-- more --");
while (!iskey())
/* wait */;
getchar();
printf("\n\n");
}
#endif /* DAVICOM_DEBUG */
static void davicom_wait(unsigned int nticks)
{
/* wait */ ;
}
/*********************************************************************/
/* For DAVICOM phyxcer register by MII interface */
/*********************************************************************/
/*
Read a word data from phy register
*/
{
int i, phy_addr=1;
whereami("phy_read\n");
/* Send 33 synchronization clock to Phy controller */
for (i=0; i<34; i++)
/* Send start command(01) to Phy */
/* Send read command(10) to Phy */
/* Send Phy addres */
for (i=0x10; i>0; i=i>>1)
/* Send register addres */
for (i=0x10; i>0; i=i>>1)
/* Skip transition state */
/* read 16bit data */
for (phy_data=0, i=0; i<16; i++) {
phy_data<<=1;
}
return phy_data;
}
/*
Write a word to Phy register
*/
{
whereami("phy_write\n");
/* Send 33 synchronization clock to Phy controller */
for (i=0; i<34; i++)
/* Send start command(01) to Phy */
/* Send write command(01) to Phy */
/* Send Phy addres */
for (i=0x10; i>0; i=i>>1)
/* Send register addres */
for (i=0x10; i>0; i=i>>1)
/* written trasnition */
/* Write a word data to PHY controller */
for (i=0x8000; i>0; i>>=1)
}
/*
Write one bit data to Phy Controller
*/
{
whereami("phy_write_1bit\n");
eeprom_delay();
eeprom_delay();
eeprom_delay();
}
/*
Read one bit phy data from PHY controller
*/
{
int phy_data;
whereami("phy_read_1bit\n");
eeprom_delay();
eeprom_delay();
return phy_data;
}
/*
*/
static void HPNA_process(void)
{
/* DM9801 present */
else
} else {
/* DM9802 present */
}
}
}
/*
Sense media mode and set CR6
*/
{
/* Set to 10BaseT mode for DM9009 */
phy_write(0, 0);
} else {
/* wait */ ;
} else
}
/* set the chip's operating mode */
if (csr6 & 0x40000)
HPNA_process();
}
/*********************************************************************/
/* EEPROM Reading Code */
/*********************************************************************/
/* EEPROM routines adapted from the Linux Tulip Code */
/* Reading a serial EEPROM is a "bit" grungy, but we work our way
through:->.
*/
{
int i;
unsigned short retval = 0;
whereami("read_eeprom\n");
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
eeprom_delay();
eeprom_delay();
}
for (i = 16; i > 0; i--) {
eeprom_delay();
eeprom_delay();
}
/* Terminate the EEPROM access. */
return retval;
}
/*********************************************************************/
/* davicom_init_chain - setup the tx and rx descriptors */
/* Sten 10/9 */
/*********************************************************************/
{
int i;
/* setup the transmit descriptor */
/* Sten: Set 2 TX descriptor but use one TX buffer because
it transmit a packet and wait complete every time. */
for (i=0; i<NTXD; i++) {
}
/* construct perfect filter frame with mac address as first match
and broadcast address for all others */
/* setup receive descriptor */
for (i=0; i<NRXD; i++) {
}
/* Chain the last descriptor to first */
TxPtr = 0;
rxd_tail = 0;
}
/*********************************************************************/
/* davicom_reset - Reset adapter */
/*********************************************************************/
{
unsigned long to;
whereami("davicom_reset\n");
/* Stop Tx and RX */
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
/* set up transmit and receive descriptors */
/* Point to receive descriptor */
/* According phyxcer media mode to set CR6,
DM9102/A phyxcer can auto-detect media mode */
/* Prepare Setup Frame Sten 10/9 */
/* Start Tx */
/* immediate transmit demand */
/* wait */ ;
printf ("TX Setup Timeout!\n");
}
/* Point to next TX descriptor */
#ifdef DAVICOM_DEBUG
davicom_more();
#endif
/* enable RX */
/* immediate poll demand */
}
/*********************************************************************/
/* eth_transmit - Transmit a frame */
/*********************************************************************/
unsigned int s, const char *p)
{
unsigned long to;
whereami("davicom_transmit\n");
/* Stop Tx */
/* outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6); */
/* setup ethernet header */
/* setup the transmit descriptor */
/* immediate transmit demand */
/* wait */ ;
printf ("TX Timeout!\n");
}
/* Point to next TX descriptor */
}
/*********************************************************************/
/* eth_poll - Wait for a frame */
/*********************************************************************/
{
whereami("davicom_poll\n");
return 0;
if ( ! retrieve ) return 1;
whereami("davicom_poll got one\n");
rxd_tail++;
return 0;
}
/* copy packet to working buffer */
/* XXX - this copy could be avoided with a little more work
but for now we are content with it because the optimised
memcpy is quite fast */
/* return the descriptor and buffer to receive ring */
rxd_tail++;
return 1;
}
/*********************************************************************/
/* eth_disable - Disable the interface */
/*********************************************************************/
{
whereami("davicom_disable\n");
/* disable interrupts */
/* Stop the chip's Tx and Rx processes. */
/* Clear the missed-packet counter. */
}
/*********************************************************************/
/* eth_irq - enable, disable and force interrupts */
/*********************************************************************/
{
switch ( action ) {
case DISABLE :
break;
case ENABLE :
break;
case FORCE :
break;
}
}
/*********************************************************************/
/* eth_probe - Look for an adapter */
/*********************************************************************/
{
unsigned int i;
whereami("davicom_probe\n");
return 0;
/* wakeup chip */
/* Stop the chip's Tx and Rx processes. */
/* Clear the missed-packet counter. */
/* Get MAC Address */
/* read EEPROM data */
for (i = 0; i < sizeof(ee_data)/2; i++)
((unsigned short *)ee_data)[i] =
/* extract MAC address from EEPROM buffer */
for (i=0; i<ETH_ALEN; i++)
/* initialize device */
return 1;
}
static struct pci_id davicom_nics[] = {
};
struct pci_driver davicom_driver = {
.type = NIC_DRIVER,
.name = "DAVICOM",
.probe = davicom_probe,
.ids = davicom_nics,
.class = 0,
};