via-velocity.c revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
#define EB54 1
/**************************************************************************
* via-velocity.c: Etherboot device driver for the VIA 6120 Gigabit
* Changes for Etherboot port:
* Copyright (c) 2006 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.
*
* This driver is based on:
* via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver
* The changes are (c) Copyright 2004, Red Hat Inc.
* <alan@redhat.com>
* Additional fixes and clean up: Francois Romieu
*
* Original code:
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
* Author: Chuang Liang-Shing, AJ Jiang
*
* Linux Driver Version 2.6.15.4
*
* REVISION HISTORY:
* ================
*
* v1.0 03-06-2006 timlegge Initial port of Linux driver
* v1.1 03-19-2006 timlegge Cleanup and enabled multicast
*
* 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 "via-velocity.h"
//#define EDEBUG
#ifdef EDEBUG
#else
#define dprintf(x)
#endif
typedef int pci_power_t;
#define PCI_D0 ((int) 0)
#define PCI_D1 ((int) 1)
#define PCI_D2 ((int) 2)
#define PCI_D3hot ((int) 3)
#define PCI_D3cold ((int) 4)
#define PCI_POWER_ERROR ((int) -1)
/* Condensed operations for readability. */
//FIXME: Move to pci.c
/* FIXME: Move BASE to the private structure */
/* NIC specific static variables go here */
#define VELOCITY_PARAM(N,D) \
static const int N[MAX_UNITS]=OPTION_DEFAULT;
/* MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
MODULE_PARM_DESC(N, D); */
#define VLAN_ID_MIN 0
#define VLAN_ID_MAX 4095
#define VLAN_ID_DEF 0
/* VID_setting[] is used for setting the VID of NIC.
0: default VID.
1-4094: other VIDs.
*/
#define RX_THRESH_MIN 0
#define RX_THRESH_MAX 3
#define RX_THRESH_DEF 0
/* rx_thresh[] is used for controlling the receive fifo threshold.
0: indicate the rxfifo threshold is 128 bytes.
1: indicate the rxfifo threshold is 512 bytes.
2: indicate the rxfifo threshold is 1024 bytes.
3: indicate the rxfifo threshold is store & forward.
*/
#define DMA_LENGTH_MIN 0
#define DMA_LENGTH_MAX 7
#define DMA_LENGTH_DEF 0
/* DMA_length[] is used for controlling the DMA length
0: 8 DWORDs
1: 16 DWORDs
2: 32 DWORDs
3: 64 DWORDs
4: 128 DWORDs
5: 256 DWORDs
6: SF(flush till emply)
7: SF(flush till emply)
*/
#define TAGGING_DEF 0
/* enable_tagging[] is used for enabling 802.1Q VID tagging.
0: disable VID seeting(default).
1: enable VID setting.
*/
#define IP_ALIG_DEF 0
/* IP_byte_align[] is used for IP header DWORD byte aligned
0: indicate the IP header won't be DWORD byte aligned.(Default) .
1: indicate the IP header will be DWORD byte aligned.
In some enviroment, the IP header should be DWORD byte aligned,
or the packet will be droped when we receive it. (eg: IPVS)
*/
#define TX_CSUM_DEF 1
/* txcsum_offload[] is used for setting the checksum offload ability of NIC.
(We only support RX checksum offload now)
0: disable csum_offload[checksum offload
1: enable checksum offload. (Default)
*/
#define FLOW_CNTL_DEF 1
#define FLOW_CNTL_MIN 1
#define FLOW_CNTL_MAX 5
/* flow_control[] is used for setting the flow control ability of NIC.
1: hardware deafult - AUTO (default). Use Hardware default value in ANAR.
2: enable TX flow control.
3: enable RX flow control.
5: disable
*/
#define MED_LNK_DEF 0
#define MED_LNK_MIN 0
#define MED_LNK_MAX 4
/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
0: indicate autonegotiation for both speed and duplex mode
1: indicate 100Mbps half duplex mode
2: indicate 100Mbps full duplex mode
3: indicate 10Mbps half duplex mode
4: indicate 10Mbps full duplex mode
Note:
if EEPROM have been set to the force mode, this option is ignored
by driver.
*/
#define VAL_PKT_LEN_DEF 0
/* ValPktLen[] is used for setting the checksum offload ability of NIC.
0: Receive frame with invalid layer 2 length (Default)
1: Drop frame with invalid layer 2 length
*/
#define WOL_OPT_DEF 0
#define WOL_OPT_MIN 0
#define WOL_OPT_MAX 7
/* wol_opts[] is used for controlling wake on lan behavior.
0: Wake up if recevied a magic packet. (Default)
2: Wake up if recevied an arp packet.
4: Wake up if recevied any unicast packet.
Those value can be sumed up to support more than one option.
*/
#define INT_WORKS_DEF 20
#define INT_WORKS_MIN 10
#define INT_WORKS_MAX 64
/* The descriptors for this card are required to be aligned on
64 byte boundaries. As the align attribute does not guarantee alignment
greater than the alignment of the start address (which for Etherboot
is 16 bytes of alignment) it requires some extra steps. Add 64 to the
size of the array and the init_ring adjusts the alignment */
/* 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 */
struct velocity_info *vptr,
struct velocity_info_tbl *info);
static int velocity_get_pci_info(struct velocity_info *,
struct pci_device *pdev);
/*
* Internal board variants. At the moment we have only one
*/
static struct velocity_info_tbl chip_info_table[] = {
"VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1,
0x00FFFFFFUL},
{0, NULL, 0, 0, 0}
};
/**
* velocity_set_int_opt - parser for integer options
* @opt: pointer to option value
* @val: value the user requested (or -1 for default)
* @min: lowest value allowed
* @max: highest value allowed
* @def: default value
* @name: property name
* @dev: device name
*
* Set an integer property in the module options. This function does
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
{
if (val == -1) {
dprintf(("%s: set value of parameter %s to %d\n",
("%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",
} else {
dprintf(("%s: set value of parameter %s to %d\n",
}
}
/**
* velocity_set_bool_opt - parser for boolean options
* @opt: pointer to option value
* @val: value the user requested (or -1 for default)
* @flag: numeric value to set for true.
* @name: property name
* @dev: device name
*
* Set a boolean property in the module options. This function does
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
{
if (val == -1) {
dprintf(("%s: set parameter %s to %s\n",
("%s: the value of parameter %s is invalid, the valid range is (0-1)\n",
} else {
dprintf(("%s: set parameter %s to %s\n",
}
}
/**
* velocity_get_options - set options on device
* @opts: option structure for the device
* @index: index of option to use in module options array
* @devname: device name
*
* Turn the module and command options into a single structure
* for the current device
*/
char *devname)
{
/* FIXME Do the options need to be configurable */
devname);
"RxDescriptors", devname);
"TxDescriptors", devname);
devname);
"enable_tagging", devname);
"txcsum_offload", devname);
"flow_control", devname);
"IP_byte_align", devname);
"ValPktLen", devname);
"Media link mode", devname);
"Wake On Lan options", devname);
"Interrupt service works", devname);
}
/**
* velocity_init_cam_filter - initialise CAM
* @vptr: velocity to program
*
* Initialize the content addressable memory used for filters. Load
* appropriately according to the presence of VLAN
*/
{
/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
/* Disable all CAMs */
/* Enable first VCAM */
/* If Tagging option is enabled and VLAN ID is not zero, then
turn on MCFG_RTGOPT also */
} else {
temp = 1;
}
}
{
/*
* RD number must be equal to 4X per hardware spec
* (programming guide rev 1.20, p.13)
*/
return;
wmb();
// dprintf(("return dirty: %d\n", dirty));
}
}
{
// dprintf(("rx_refill - rd_curr = %d, dirty = %d\n", vptr->rd_curr, dirty));
do {
/* Fine for an all zero Rx desc at init time as well */
break;
// dprintf(("rx_refill - after owner %d\n", dirty));
done++;
if (done) {
// dprintf(("\nGive Back Desc\n"));
}
return ret;
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
{
/* Work out whether or not there's an ethernet packet ready to
* read. Return 0 if not.
*/
return 0;
rmb();
if ( ! retrieve )
return 1;
/*
* Don't drop CE or RL error frame although RXOK is off
*/
// ptr->rxb + (rd_curr * PKT_BUF_SZ)
return 1; /* Remove this line once this method is implemented */
}
return 0;
}
#define TX_TIMEOUT (1000);
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
unsigned int type, /* Type */
unsigned int size, /* size */
const char *packet)
{ /* Packet */
unsigned int pktlen;
/* point to the current txb incase multiple tx_rings are used */
// dprintf(("Pad that packet\n"));
cpu_to_le32(0xffff0000L);
} else {
// dprintf(("Correct size packet\n"));
// tdinfo->nskb_dma = 1;
}
}
{
if (prev < 0)
}
printf("TX Time Out");
}
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
{
/* put the card in its initial state */
/* This function serves 3 purposes.
* This disables DMA and interrupts so we don't receive
* unexpected packets or interrupts from the card after
* etherboot has finished.
* This frees resources so etherboot may use
* this driver on another interface
* This allows etherboot to reinitialize the interface
* if something is something goes wrong.
*/
/* Power down the chip */
// pci_set_power_state(vptr->pdev, PCI_D3hot);
}
#ifdef EB54
/**************************************************************************
IRQ - handle interrupts
***************************************************************************/
{
/* This routine is somewhat optional. Etherboot itself
* doesn't use interrupts, but they are required under some
* circumstances when we're acting as a PXE stack.
*
* If you don't implement this routine, the only effect will
* be that your driver cannot be used via Etherboot's UNDI
* API. This won't affect programs that use only the UDP
* portion of the PXE API, such as pxelinux.
*/
switch (action) {
case DISABLE:
case ENABLE:
/*
outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
nic->ioaddr + IntrMaskRegister );
*/
break;
case FORCE:
/* Force NIC to generate a receive interrupt */
/*
outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
*/
break;
}
}
#endif
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
#define board_found 1
#define valid_link 0
{
int ret, i;
printf("Found %s Vendor=0x%hX Device=0x%hX",
/* point to private storage */
//FIXME: pci_enable_device(pci);
//FIXME: pci_set_power_state(pci, PCI_D0);
if (ret < 0) {
printf("Failed to find PCI device.\n");
return 0;
}
printf("Unable to remap io\n");
return 0;
}
// dprintf(("Chip ID: %hX\n", vptr->chip_id));
for (i = 0; i < 6; i++)
/* Print out some hardware info */
/*
* Mask out the options cannot be set to the chip
*/
/*
* Enable the chip specified capbilities
*/
/* and leave the chip powered down */
// FIXME: pci_set_power_state(pci, PCI_D3hot);
/* store NIC parameters */
#ifdef EB54
#endif
return 1;
}
/**
* velocity_init_info - init private data
* @pdev: PCI device
* @vptr: Velocity info
* @info: Board type
*
* Set up the initial velocity_info struct for the device that has been
* discovered.
*/
struct velocity_info *vptr,
struct velocity_info_tbl *info)
{
(("chip_id: 0x%hX, io_size: %d, num_txq %d, multicast_limit: %d\n",
vptr->multicast_limit));
}
#define IORESOURCE_MEM 0x00000200
#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
// #define PCI_BASE_ADDRESS_SPACE_IO 0x01
// #define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
// #define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
// #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
// #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
// #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
// #define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
{
unsigned long flags = 0;
printf("Weird size\n");
if (l == 0xffffffff)
l = 0;
if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
/* sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
if (!sz)
continue;
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
// dprintf(("Memory Resource\n"));
} else {
// sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
/// if (!sz)
/// continue;
// res->start = l & PCI_BASE_ADDRESS_IO_MASK;
flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
// dprintf(("I/O Resource\n"));
}
if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
flags |= IORESOURCE_IO;
} else {
//flags &= ~IORESOURCE_IO;
}
return flags;
}
/**
* velocity_get_pci_info - retrieve PCI info for device
* @vptr: velocity device
* @pdev: PCI device it matches
*
* Retrieve the PCI configuration space data that interests us from
* the kernel PCI layer
*/
struct pci_device *pdev)
{
printf("DEBUG: pci_read_config_byte failed\n");
return -1;
}
dprintf(("Looking for I/O Resource - Found:"));
if (!
{
("DEBUG: region #0 is not an I/O resource, aborting.\n");
return -1;
}
dprintf(("Looking for Memory Resource - Found:"));
printf("DEBUG: region #1 is an I/O resource, aborting.\n");
return -1;
}
printf("DEBUG: region #1 is too small.\n");
return -1;
}
return 0;
}
/**
* velocity_print_link_status - link status reporting
* @vptr: velocity to report on
*
* Turn the link status of the velocity card into a kernel log
* description of the new link state, detailing speed and duplex
* status
*/
{
printf("failed to detect cable link\n");
printf("Link autonegation");
printf(" speed 1000M bps");
printf(" speed 100M bps");
else
printf(" speed 10M bps");
printf(" full duplex\n");
else
printf(" half duplex\n");
} else {
printf("Link forced");
case SPD_DPX_100_HALF:
printf(" speed 100M bps half duplex\n");
break;
case SPD_DPX_100_FULL:
printf(" speed 100M bps full duplex\n");
break;
case SPD_DPX_10_HALF:
printf(" speed 10M bps half duplex\n");
break;
case SPD_DPX_10_FULL:
printf(" speed 10M bps full duplex\n");
break;
default:
break;
}
}
}
/**
* velocity_rx_reset - handle a receive reset
* @vptr: velocity we are resetting
*
* Reset the ownership and status for the receive ring side.
* Hand all the receive queue to the NIC.
*/
{
int i;
/*
* Init state, all RD entries belong to the NIC
*/
}
/**
* velocity_init_registers - initialise MAC registers
* @vptr: velocity to init
* @type: type of initialisation (hot or cold)
*
* Initialise the MAC on a reset or on first set up on the
* hardware.
*/
struct velocity_info *vptr,
enum velocity_init_type type)
{
int i, mii_status;
switch (type) {
case VELOCITY_INIT_RESET:
case VELOCITY_INIT_WOL:
/*
* Reset RX to prevent RX pointer not on the 4X location
*/
printf("Link Failed\n");
}
break;
case VELOCITY_INIT_COLD:
default:
/*
* Do reset
*/
mdelay(5);
for (i = 0; i < 6; i++) {
}
/*
* clear Pre_ACPI bit.
*/
/*
* Back off algorithm use original IEEE standard
*/
/*
* Init CAM filter
*/
/*
* Set packet filter: Receive directed and broadcast address
*/
/*
* Enable Multicast by default
* from velocity_set_multi(nic)
*/
/* Not necessary (no where to set mtu)
if (dev->mtu > 1500)
rx_mode |= RCR_AL;
*/
/*
* Enable MII auto-polling
*/
// for (i = 0; i < vptr->num_txq; i++) {
mac_tx_queue_run(regs, 0);
// }
printf("Link Failed\n");
}
}
}
/**
* velocity_soft_reset - soft reset
* @vptr: velocity to reset
*
* Kick off a soft reset of the velocity adapter and then poll
* until the reset sequence has completed before returning.
*/
{
unsigned int i = 0;
for (i = 0; i < W_MAX_TIMEOUT; i++) {
udelay(5);
break;
}
if (i == W_MAX_TIMEOUT) {
/* FIXME: PCI POSTING */
/* delay 2ms */
mdelay(2);
}
return 0;
}
/**
* velocity_init_rings - set up DMA rings
* @vptr: Velocity to set up
*
* Allocate PCI mapped DMA rings for the receive and transmit layer
* to use.
*/
{
int idx;
// memset(vptr->tx_buffs, 0, TX_DESC_DEF * PKT_BUF_SZ);
}
/* for (i = 0; idx < TX_DESC_DEF; idx++ ) {
vptr->td_rings[idx].tdesc1.TCPLS = TCPLS_NORMAL;
vptr->td_rings[idx].tdesc1.TCR = TCR0_TIC;
vptr->td_rings[idx].td_buf[0].queue = 0;
vptr->td_rings[idx].tdesc0.owner = ~OWNED_BY_NIC;
vptr->td_rings[idx].tdesc0.pktsize = 0;
vptr->td_rings[idx].td_buf[0].pa_low = cpu_to_le32(virt_to_bus(vptr->txb + (idx * PKT_BUF_SZ)));
vptr->td_rings[idx].td_buf[0].pa_high = 0;
vptr->td_rings[idx].td_buf[0].bufsize = 0;
vptr->td_rings[idx].tdesc1.CMDZ = 2;
}
*/
return 0;
}
/**
* velocity_open - interface activation callback
* @dev: network layer device to open
*
* Called when the network layer brings the interface up. Returns
* a negative posix error code on failure, or zero on success.
*
* All the ring allocation and set up is done on open for this
* adapter to minimise memory usage when inactive
*/
#define PCI_BYTE_REG_BITS_ON(x,i,p) do{\
pci_read_config_byte((p), (i), &(byReg));\
(byReg) |= (x);\
pci_write_config_byte((p), (i), (byReg));\
} while (0)
//
// Registers in the PCI configuration space
//
// Bits in the (MODE2, 0x62) register
//
#define MODE2_TXQ16 0x40 // TX write-back Queue control. 0->32 entries available in Tx write-back queue, 1->16 entries
#define MODE2_TCPLSOPT 0x01 // TCP large send field update disable, hardware will not update related fields, leave it to software.
//
// Bits in the MODE3 register
//
// Bits in the (COMMAND, 0x04) register
#define COMMAND_BUSM 0x04
#define COMMAND_WAIT 0x80
{
int ret;
if (vptr->TxDescArrays == 0)
printf("Allot Error");
/* Tx Descriptor needs 64 bytes alignment; */
/* Rx Buffer needs 64 bytes alignment; */
TxBufPhyAddr += diff;
/* Rx Descriptor needs 64 bytes alignment; */
/* Rx Buffer needs 64 bytes alignment; */
RxBufPhyAddr += diff;
printf("Allocate tx_ring or rd_ring failed\n");
return 0;
}
/*
// turn this on to avoid retry forever
PCI_BYTE_REG_BITS_ON(MODE2_PCEROPT, PCI_REG_MODE2, pci);
// for some legacy BIOS and OS don't open BusM
// bit in PCI configuration space. So, turn it on.
PCI_BYTE_REG_BITS_ON(COMMAND_BUSM, PCI_REG_COMMAND, pci);
// turn this on to detect MII coding error
PCI_BYTE_REG_BITS_ON(MODE3_MIION, PCI_REG_MODE3, pci);
*/
/* Ensure chip is running */
//FIXME: pci_set_power_state(vptr->pdev, PCI_D0);
// _int(vptr->mac_regs);
//mac_enable_int(vptr->mac_regs);
return 1;
}
/*
* MII access , media link mode setting functions
*/
/**
* mii_init - set up MII
* @vptr: velocity adapter
* @mii_status: links tatus
*
* Set up the PHY for the current link state.
*/
{
case PHYID_CICADA_CS8201:
/*
* Reset to hardware default
*/
/*
* Turn on ECHODIS bit in NWay-forced full mode and turn it
* off it in NWay-forced half mode for NWay-forced v.s.
* legacy-forced issue.
*/
else
/*
*/
break;
case PHYID_VT3216_32BIT:
case PHYID_VT3216_64BIT:
/*
* Reset to hardware default
*/
/*
* Turn on ECHODIS bit in NWay-forced full mode and turn it
* off it in NWay-forced half mode for NWay-forced v.s.
* legacy-forced issue
*/
else
break;
case PHYID_MARVELL_1000:
case PHYID_MARVELL_1000S:
/*
* Assert CRS on Transmit
*/
/*
* Reset to hardware default
*/
break;
default:
;
}
}
}
/**
* safe_disable_mii_autopoll - autopoll off
* @regs: velocity registers
*
* Turn off the autopoll and wait for it to disable on the chip
*/
{
/* turn off MAUTO */
udelay(1);
break;
}
}
/**
* enable_mii_autopoll - turn on autopolling
* @regs: velocity registers
*
* Enable the MII link status autopoll feature on the Velocity
* hardware. Wait for it to enable.
*/
{
unsigned int ii;
udelay(1);
break;
}
udelay(1);
break;
}
}
/**
* velocity_mii_read - read MII data
* @regs: velocity registers
* @index: MII register index
* @data: buffer for received data
*
* Perform a single read of an MII 16bit register. Returns zero
* on success or -ETIMEDOUT if the PHY did not respond.
*/
{
/*
* Disable MIICR_MAUTO, so that mii addr can be set normally
*/
break;
}
if (ww == W_MAX_TIMEOUT)
return -1;
return 0;
}
/**
* velocity_mii_write - write MII data
* @regs: velocity registers
* @index: MII register index
* @data: 16bit data for the MII register
*
* Perform a single write to an MII 16bit register. Returns zero
* on success or -ETIMEDOUT if the PHY did not respond.
*/
{
/*
* Disable MIICR_MAUTO, so that mii addr can be set normally
*/
/* MII reg offset */
/* set MII data */
/* turn on MIICR_WCMD */
/* W_MAX_TIMEOUT is the timeout period */
udelay(5);
break;
}
if (ww == W_MAX_TIMEOUT)
return -1;
return 0;
}
/**
* velocity_get_opt_media_mode - get media selection
* @vptr: velocity adapter
*
* Get the media mode stored in EEPROM or module options and load
* mii_status accordingly. The requested link state information
* is also returned.
*/
{
case SPD_DPX_AUTO:
break;
case SPD_DPX_100_FULL:
break;
case SPD_DPX_10_FULL:
break;
case SPD_DPX_100_HALF:
break;
case SPD_DPX_10_HALF:
break;
}
return status;
}
/**
* mii_set_auto_on - autonegotiate on
* @vptr: velocity
*
* Enable autonegotation on this interface
*/
{
else
}
/*
static void mii_set_auto_off(struct velocity_info * vptr)
{
MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
}
*/
/**
* set_mii_flow_control - flow control setup
* @vptr: velocity interface
*
* Set up the flow control on this interface according to
*/
{
/*Enable or Disable PAUSE in ANAR */
case FLOW_CNTL_TX:
break;
case FLOW_CNTL_RX:
break;
case FLOW_CNTL_TX_RX:
break;
case FLOW_CNTL_DISABLE:
break;
default:
break;
}
}
/**
* velocity_set_media_mode - set media mode
* @mii_status: old MII link state
*
* Check the media link state and configure the flow control
* PHY and also velocity hardware setup accordingly. In particular
* we need to set up CD polling and frame bursting.
*/
{
/* Set mii link status */
/*
Check if new status is consisent with current status
if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE)
|| (mii_status==curr_status)) {
vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
vptr->mii_status=check_connection_type(vptr->mac_regs);
printf(MSG_LEVEL_INFO, "Velocity link no change\n");
return 0;
}
*/
}
/*
* If connection type is AUTO
*/
if (mii_status & VELOCITY_AUTONEG_ENABLE) {
printf("Velocity is AUTO mode\n");
/* clear force MAC mode bit */
/* set duplex mode of MAC according to duplex mode of MII */
/* enable AUTO-NEGO mode */
} else {
/*
* 1. if it's 3119, disable frame bursting in halfduplex mode
* and enable it in fullduplex mode
* 3. only enable CD heart beat counter in 10HD mode
*/
/* set force MAC mode bit */
CHIPGCR &= ~CHIPGCR_FCGMII;
if (mii_status & VELOCITY_DUPLEX_FULL) {
CHIPGCR |= CHIPGCR_FCFDX;
("DEBUG: set Velocity to forced full mode\n");
} else {
CHIPGCR &= ~CHIPGCR_FCFDX;
("DEBUG: set Velocity to forced half mode\n");
}
if (!(mii_status & VELOCITY_DUPLEX_FULL)
&& (mii_status & VELOCITY_SPEED_10)) {
} else {
}
/* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
if (mii_status & VELOCITY_SPEED_100) {
if (mii_status & VELOCITY_DUPLEX_FULL)
else
} else {
if (mii_status & VELOCITY_DUPLEX_FULL)
else
}
/* enable AUTO-NEGO mode */
/* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
}
/* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
/* vptr->mii_status=check_connection_type(vptr->mac_regs); */
return VELOCITY_LINK_CHANGE;
}
/**
* mii_check_media_mode - check media state
* @regs: velocity registers
*
* Check the current MII status and determine the link status
* accordingly
*/
{
status |= (VELOCITY_SPEED_1000);
else {
status |=
status |=
else
status |= (VELOCITY_SPEED_10);
}
}
}
return status;
}
{
/*
if (!(PHYSR0 & PHYSR0_LINKGD))
status|=VELOCITY_LINK_FAIL;
*/
if (PHYSR0 & PHYSR0_FDPX)
if (PHYSR0 & PHYSR0_SPDG)
if (PHYSR0 & PHYSR0_SPD10)
else
}
}
return status;
}
/**
* enable_flow_control_ability - flow control
* @vptr: veloity to configure
*
* Set up flow control according to the flow control options
* determined by the eeprom/configuration.
*/
{
case FLOW_CNTL_DEFAULT:
else
else
break;
case FLOW_CNTL_TX:
break;
case FLOW_CNTL_RX:
break;
case FLOW_CNTL_TX_RX:
break;
case FLOW_CNTL_DISABLE:
break;
default:
break;
}
}
/* FIXME: Move to pci.c */
/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
* @state: Power state we're entering
*
* Transition a device to a new power state, using the Power Management
* Capabilities in the device's config space.
*
* RETURN VALUE:
* -EINVAL if trying to enter a lower state than we're already in.
* 0 if we're already in the requested state.
* -EIO if device does not support PCI PM.
* 0 if we can successfully change the power state.
*/
{
int pm;
int current_state = 0;
/* bound the state we're entering */
if (state > 3)
state = 3;
/* Validate current state:
* Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state
*/
return -1;
else if (current_state == state)
return 0; /* we're already there */
/* find PCI PM capability in list */
/* abort if the device doesn't support PM capabilities */
if (!pm)
return -2;
/* check if this device supports the desired state */
return -2;
return -2;
}
/* If we're in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
if (current_state >= 3)
pmcsr = 0;
else {
}
/* enter specified state */
/* Mandatory power management transition delays */
/* see PCI PM 1.1 5.6.1 table 18 */
mdelay(10);
udelay(200);
return 0;
}
static struct pci_id velocity_nics[] = {
};
.type = NIC_DRIVER,
.name = "VIA-VELOCITY/PCI",
.probe = velocity_probe,
.ids = velocity_nics,
.class = 0,
};