amd8111e.c revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
* Copyright (C) 2004 Advanced Micro Devices
* Copyright (C) 2005 Liu Tao <liutao1980@gmail.com> [etherboot port]
*
* Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
* Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
* Derived from the lance driver written 1993,1994,1995 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency.[ pcnet32.c ]
* Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "etherboot.h"
#include "nic.h"
#include "mii.h"
#include "pci.h"
#include "timer.h"
#include "string.h"
#include "stdint.h"
#include "amd8111e.h"
/* driver definitions */
#define NUM_TX_SLOTS 2
#define NUM_RX_SLOTS 4
#define TX_SLOTS_MASK 1
#define RX_SLOTS_MASK 3
#define TX_BUF_LEN 1536
#define RX_BUF_LEN 1536
#define RX_PKT_LEN_MIN 60
#define RX_PKT_LEN_MAX ETH_FRAME_LEN
#define TX_TIMEOUT 3000
#define TX_PROCESS_TIME 10
#define PHY_RW_RETRY 10
struct amd8111e_tx_desc {
};
struct amd8111e_rx_desc {
};
struct eth_frame {
} __attribute__((packed));
struct amd8111e_priv {
int tx_consistent;
char opened;
char link;
char speed;
char duplex;
int ext_phy_addr;
struct pci_device *pdev;
void *mmio;
};
static struct amd8111e_priv amd8111e;
/********************************************************
* locale functions *
********************************************************/
#if 0
#endif
/*
* This function clears necessary the device registers.
*/
{
unsigned int reg_val;
unsigned int logic_filter[2] = {0,};
/* stop the chip */
/* Clear RCV_RING_BASE_ADDR */
/* Clear XMT_RING_BASE_ADDR */
/* Clear CMD0 */
/* Clear CMD2 */
/* Clear CMD7 */
/* Clear DLY_INT_A and DLY_INT_B */
/* Clear FLOW_CONTROL */
/* Clear INT0 write 1 to clear register */
/* Clear STVAL */
/* Clear INTEN0 */
/* Clear LADRF */
/* Set SRAM_SIZE & SRAM_BOUNDARY registers */
/* Clear RCV_RING0_LEN */
/* Clear XMT_RING0/1/2/3_LEN */
/* Clear XMT_RING_LIMIT */
/* Clear MIB */
/* Clear LARF */
/* SRAM_SIZE register */
/* Set default value to CTRL1 Register */
/* To avoid PCI posting bug */
}
/*
* This function initializes the device registers and starts the device.
*/
{
int i, reg_val;
/* stop the chip */
/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
/* enable the port manager and set auto negotiation always */
/* set control registers */
reg_val &= ~XMTSP_MASK;
/* initialize tx and rx ring base addresses */
/* set default IPG to 96 */
/* AutoPAD transmit, Retransmit on Underflow */
/* JUMBO disabled */
/* Setting the MAC address to the device */
for(i = 0; i < ETH_ALEN; i++)
/* set RUN bit to start the chip, interrupt not enabled */
/* To avoid PCI posting bug */
return 0;
}
/*
This function will read the PHY registers.
*/
{
unsigned int reg_val;
unsigned int retry = PHY_RW_RETRY;
while (reg_val & PHY_CMD_ACTIVE)
mmio + PHY_ACCESS);
do {
if (reg_val & PHY_RD_ERR) {
*val = 0;
return -1;
}
return 0;
}
/*
This function will write into PHY registers.
*/
#if 0
{
unsigned int reg_val;
unsigned int retry = PHY_RW_RETRY;
while (reg_val & PHY_CMD_ACTIVE)
mmio + PHY_ACCESS);
do {
if(reg_val & PHY_RD_ERR)
return -1;
return 0;
}
#endif
{
int i;
lp->ext_phy_id = 0;
for (i = 0x1e; i >= 0; i--) {
continue;
continue;
lp->ext_phy_addr = i;
break;
}
if (lp->ext_phy_id)
printf("Found MII PHY ID 0x%08x at address 0x%02x\n",
else
printf("Couldn't detect MII PHY, assuming address 0x01\n");
}
{
unsigned int int0;
}
{
}
{
}
{
int i;
/* BIOS should have set mac address to PADR register,
* so we read PADR to get it.
*/
for (i = 0; i < ETH_ALEN; i++)
return 0;
}
{
int i;
/* Initilaizing receive descriptors */
for (i = 0; i < NUM_RX_SLOTS; i++) {
wmb();
}
return 0;
}
{
int i;
/* Initializing transmit descriptors */
for (i = 0; i < NUM_TX_SLOTS; i++) {
}
return 0;
}
{
}
return -1;
}
return 0;
}
{
unsigned int status;
do {
/* read phy to update STAT0 register */
}
{
/* read phy to update STAT0 register */
if (status & LINK_STATS) {
if (speed == PHY_SPEED_100)
else
else
printf("Link is up: %s Mbps %s duplex\n",
}
} else {
if (!(status & LINK_STATS)) {
printf("Link is down\n");
}
}
}
{
printf("\nStarting nic...\n");
printf("Waiting link up...\n");
}
/********************************************************
* Interface Functions *
********************************************************/
{
unsigned int index;
/* check packet size */
if (size > TX_PKT_LEN_MAX) {
printf("amd8111e_transmit(): too large packet, drop\n");
return;
}
/* get tx slot */
return;
/* fill frame */
/* start xmit */
wmb();
/* update slot pointer */
}
{
/* return true if there's an ethernet packet ready to read */
/* nic->packet should contain data on return */
/* nic->packetlen should contain length of data */
return 0;
pkt_ok = 0;
pkt_ok = 0;
pkt_ok = 0;
else if (pkt_len < RX_PKT_LEN_MIN)
pkt_ok = 0;
else if (pkt_len > RX_PKT_LEN_MAX)
pkt_ok = 0;
else
pkt_ok = 1;
if (pkt_ok) {
if (!retrieve)
return 1;
}
wmb();
return pkt_ok;
}
{
/* disable interrupt */
/* stop chip */
/* unmap mmio */
/* update status */
}
{
switch (action) {
case DISABLE:
break;
case ENABLE:
break;
case FORCE:
break;
}
}
{
unsigned long mmio_start, mmio_len;
if (pdev == 0)
return 0;
return 1;
}
static struct pci_id amd8111e_nics[] = {
};
.type = NIC_DRIVER,
.name = "AMD8111E",
.probe = amd8111e_probe,
.ids = amd8111e_nics,
.class = 0,
};