dmfe.c revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/**************************************************************************
*
* dmfe.c -- Etherboot device driver for the Davicom
*
* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Portions of this code based on:
*
* NIC fast ethernet driver for Linux.
* Copyright (C) 1997 Sten Wang
* (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
*
*
* REVISION HISTORY:
* ================
* v1.0 10-02-2004 timlegge Boots ltsp needs cleanup
*
* Indent Options: indent -kr -i8
*
*
***************************************************************************/
/* to get some global routines like printf */
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
/* to get the PCI support functions, if this is a PCI NIC */
#include "pci.h"
#include "timer.h"
/* #define EDEBUG 1 */
#ifdef EDEBUG
#else
#define dprintf(x)
#endif
/* Condensed operations for readability. */
/* Board/System/Debug information/definition ---------------- */
#define DM9102_IO_SIZE 0x80
#define DM9102A_IO_SIZE 0x100
#define TX_BUF_ALLOC 0x600
#define RX_ALLOC_SIZE 0x620
#define DM910X_RESET 1
#define CR7_DEFAULT 0x180c1
#define MAX_PACKET_SIZE 1514
#define DMFE_MAX_MULTICAST 14
#define RX_COPY_SIZE 100
#define MAX_CHECK_PACKET 0x8000
#define DM9801_NOISE_FLOOR 8
#define DM9802_NOISE_FLOOR 5
#define DMFE_10MHF 0
#define DMFE_100MHF 1
#define DMFE_10MFD 4
#define DMFE_100MFD 5
#define DMFE_AUTO 8
#define DMFE_1M_HPNA 0x10
#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
#define CR9_SROM_READ 0x4800
#define CR9_SRCS 0x1
#define CR9_SRCLK 0x2
#define CR9_CRDOUT 0x8
#define SROM_DATA_0 0x0
#define SROM_DATA_1 0x4
#define PHY_DATA_1 0x20000
#define PHY_DATA_0 0x00000
#define MDCLKH 0x10000
#define PHY_POWER_DOWN 0x800
#define SROM_V41_CODE 0x14
#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
/* Sten Check */
#define DEVICE net_device
struct tx_desc {
struct rx_desc {
struct dmfe_private {
// u32 cr5_data;
/* NIC SROM data */
unsigned char srom[128];
/* Etherboot Only */
} dfx;
static struct dmfe_private *db;
enum dmfe_offsets {
0x70,
DCR15 = 0x78
};
enum dmfe_CR6_bits {
};
/* Global variable declaration ----------------------------- */
static int dmfe_debug;
static unsigned char dmfe_media_mode = DMFE_AUTO;
static u32 dmfe_cr6_user_set;
/* For module input parameter */
static int debug;
4: TX pause packet */
/**********************************************
* Descriptor Ring and Buffer defination
***********************************************/
/* Define the TX Descriptor */
/* Create a static buffer of size PKT_BUF_SZ for each TX Descriptor.
All descriptors point to a part of this buffer */
/* Define the RX Descriptor */
/* Create a static buffer of size PKT_BUF_SZ for each RX Descriptor.
All descriptors point to a part of this buffer */
/* NIC specific static variables go here */
long int BASE;
static void update_cr6(u32, unsigned long);
static void phy_write_1bit(unsigned long, u32);
static u16 phy_read_1bit(unsigned long);
{
/* system variable init */
/* CR6 operation mode decision */
} else {
}
/* Initilize DM910X board */
return;
}
/* Initilize DM910X board
* Reset DM910X board
* Send the set-up frame
*/
{
/* Reset DM910x MAC controller */
udelay(100);
udelay(5);
/* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
/* Parser SROM and media mode */
/* RESET Phyxcer Chip by GPR port bit 7 */
}
/* Process Phyxcer Media Mode */
/* Media Mode Process */
/* tx descriptor start pointer */
/* rx descriptor start pointer */
/* Init CR6 to program DM910x operation */
/* Send setup frame */
} else {
}
/* Init CR7, interrupt active bit */
/* Init CR15, Tx jabber and Rx watchdog timer */
}
#ifdef EDEBUG
#endif
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
{
int rxlen;
if (rdes0 & 0x80000000)
return 0;
if (!retrieve)
return 1;
printf("strange Packet\n");
return 0;
} else {
/* error summary bit check */
if (rdes0 & 0x8000) {
printf("Error\n");
return 0;
}
if (!(rdes0 & 0x8000) ||
printf("Silly check mode\n");
}
}
return 1;
}
{
switch ( action ) {
case DISABLE :
break;
case ENABLE :
break;
case FORCE :
break;
}
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
const char *dest, /* Destination */
unsigned int type, /* Type */
unsigned int size, /* size */
const char *packet) /* Packet */
{
/* Stop Tx */
/* setup the transmit descriptor */
/* immediate transmit demand */
/* Point to next TX descriptor */
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
{
/* Reset & stop DM910X board */
udelay(5);
}
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
#define board_found 1
#define valid_link 0
{
int i;
return 0;
/* Read Chip revision */
/* point to private storage */
pci_pmr &= 0x70000;
else
/* read 64 word srom data */
for (i = 0; i < 64; i++)
/* Set Node address */
for (i = 0; i < 6; i++)
/* Print out some hardware info */
/* Set the card as PCI Bus Master */
/* point to NIC specific routines */
return 1;
}
/*
*/
{
int i;
/* tx descriptor start pointer */
/* rx descriptor start pointer */
/* Init Transmit chain */
for (i = 0; i < TX_DESC_CNT; i++) {
}
/* Mark the last entry as wrapping the ring */
/* receive descriptor chain */
for (i = 0; i < RX_DESC_CNT; i++) {
}
/* Mark the last entry as wrapping the ring */
}
/*
* Update CR6 value
* Firstly stop DM910X , then written value and start
*/
{
udelay(5);
udelay(5);
}
/*
* Send a setup frame for DM9132
* This setup frame initilize DM910X addres filter mode
*/
{
#ifdef LINUX
#endif
dprintf(("dm9132_id_table\n"));
printf("FIXME: This function is broken. If you have this card contact "
"Timothy Legge at the etherboot-user list\n");
#ifdef LINUX
//DMFE_DBUG(0, "dm9132_id_table()", 0);
/* Node address */
ioaddr += 4;
ioaddr += 4;
ioaddr += 4;
/* Clear Hash Table */
for (i = 0; i < 4; i++)
hash_table[i] = 0x0;
/* broadcast address */
/* the multicast address in Hash Table : 64 bits */
}
/* Write the hash table to MAC MD table */
#endif
}
/*
* This setup frame initilize DM910X addres filter mode
*/
{
int i;
dprintf(("send_filter_frame\n"));
/* point to the current txb incase multiple tx_rings are used */
/* construct perfect filter frame with mac address as first match
and broadcast address for all others */
for (i = 0; i < 192; i++)
ptxb[i] = 0xFF;
/* prepare the setup frame */
}
/*
* Read one word data from the serial ROM
*/
{
int i;
/* Send the Read Command 110b */
/* Send the offset */
for (i = 5; i >= 0; i--) {
}
for (i = 16; i > 0; i--) {
udelay(5);
: 0);
udelay(5);
}
return srom_data;
}
/*
* Auto sense the media mode
*/
{
/* CR6 bit18=0, select 10/100M */
phy_mode =
phy_mode =
/* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
switch (phy_mode) {
case 0x1000:
break;
case 0x2000:
break;
case 0x4000:
break;
case 0x8000:
break;
default:
ErrFlag = 1;
break;
}
} else {
//DMFE_DBUG(0, "Link Failed :", phy_mode);
ErrFlag = 1;
}
return ErrFlag;
}
/*
* Set 10/100 phyxcer capability
* AUTO mode : phyxcer register4 is NIC capability
* Force mode: phyxcer register4 is the force media
*/
{
/* Select 10/100M phyxcer */
/* DM9009 Chip: Phyxcer reg18 bit12=0 */
phy_reg =
}
/* Phyxcer capability setting */
/* AUTO Mode */
} else {
/* Force Mode */
switch (db->media_mode) {
case DMFE_10MHF:
phy_reg |= 0x20;
break;
case DMFE_10MFD:
phy_reg |= 0x40;
break;
case DMFE_100MHF:
phy_reg |= 0x80;
break;
case DMFE_100MFD:
phy_reg |= 0x100;
break;
}
phy_reg &= 0x61;
}
/* Write new capability to Phyxcer Reg4 */
if (!(phy_reg & 0x01e0)) {
}
/* Restart Auto-Negotiation */
}
/*
* Process op-mode
* AUTO mode : PHY controller in Auto-negotiation Mode
* Force mode: PHY controller in force mode with HUB
* N-way force capability with SWITCH
*/
{
/* Full Duplex Mode Check */
else
/* Transciver Selection */
else
/* 10/100M phyxcer force mode need */
/* Forece Mode */
if (!(phy_reg & 0x1)) {
/* parter without N-Way capability */
phy_reg = 0x0;
case DMFE_10MHF:
phy_reg = 0x0;
break;
case DMFE_10MFD:
phy_reg = 0x100;
break;
case DMFE_100MHF:
phy_reg = 0x2000;
break;
case DMFE_100MFD:
phy_reg = 0x2100;
break;
}
mdelay(20);
}
}
}
/*
* Write a word to Phy register
*/
{
u16 i;
unsigned long ioaddr;
if (chip_id == PCI_DM9132_ID) {
} else {
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
/* Send start command(01) to Phy */
/* Send write command(01) to Phy */
/* Send Phy addres */
for (i = 0x10; i > 0; i = i >> 1)
phy_addr & i ? PHY_DATA_1 :
/* Send register addres */
for (i = 0x10; i > 0; i = i >> 1)
offset & i ? PHY_DATA_1 :
/* written trasnition */
/* Write a word data to PHY controller */
for (i = 0x8000; i > 0; i >>= 1)
phy_data & i ? PHY_DATA_1 :
}
}
/*
* Read a word data from phy register
*/
{
int i;
unsigned long ioaddr;
if (chip_id == PCI_DM9132_ID) {
/* DM9132 Chip */
} else {
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
/* Send start command(01) to Phy */
/* Send read command(10) to Phy */
/* Send Phy addres */
for (i = 0x10; i > 0; i = i >> 1)
phy_addr & i ? PHY_DATA_1 :
/* Send register addres */
for (i = 0x10; i > 0; i = i >> 1)
offset & i ? PHY_DATA_1 :
/* Skip transition state */
/* read 16bit data */
for (phy_data = 0, i = 0; i < 16; i++) {
phy_data <<= 1;
}
}
return phy_data;
}
/*
* Write one bit data to Phy Controller
*/
{
udelay(1);
udelay(1);
udelay(1);
}
/*
* Read one bit phy data from PHY controller
*/
{
udelay(1);
udelay(1);
return phy_data;
}
/*
* Parser SROM and media mode
*/
{
/* Init CR15 */
/* Check SROM Version */
/* SROM V4.01 */
/* Get NIC support media mode */
case 0x1:
break;
case 0x2:
break;
case 0x4:
break;
case 0x8:
break;
}
}
/* Media Mode Force or not check */
switch (dmfe_mode) {
case 0x4:
break; /* 100MHF */
case 0x2:
break; /* 10MFD */
case 0x8:
break; /* 100MFD */
case 0x100:
case 0x200:
break; /* HomePNA */
}
/* Special Function setting */
/* VLAN function */
/* Flow Control */
/* TX pause packet */
}
/* Parse HPNA parameter */
/* Accept remote command or not */
if (HPNA_rx_cmd == 0)
/* Issue remote command & operation mode */
if (HPNA_tx_cmd == 1)
switch (HPNA_mode) { /* Issue Remote Command */
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
} else
switch (HPNA_mode) { /* Don't Issue */
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
/* Check DM9801 or DM9802 present or not */
db->HPNA_present = 0;
/* DM9801 or DM9802 present */
0x4404) {
/* DM9801 HomeRun */
} else {
/* DM9802 LongRun */
}
}
}
/*
* Init HomeRun DM9801
*/
{
if (!HPNA_NoiseFloor)
switch (HPNA_rev) {
case 0xb900: /* DM9801 E3 */
break;
case 0xb901: /* DM9801 E4 */
break;
case 0xb902: /* DM9801 E5 */
case 0xb903: /* DM9801 E6 */
default:
break;
}
}
/*
* Init HomeRun DM9802
*/
{
if (!HPNA_NoiseFloor)
}
};
.type = NIC_DRIVER,
.probe = dmfe_probe,
.class = 0,
};