diff -urN linux-2.4.33-wt1/drivers/net/velocityget/kcompat.h linux-2.4.33-wt1-via/drivers/net/velocityget/kcompat.h --- linux-2.4.33-wt1/drivers/net/velocityget/kcompat.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/kcompat.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: kcompat.h + * + * Purpose: Header file for Linux kernel version compatibility + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __KCOMPAT_H__ +#define __KCOMPAT_H__ + +#include + +#ifndef __init +#define __init +#endif + +#ifndef __exit +#define __exit +#endif + +#ifndef __devexit +#define __devexit +#endif + +#ifndef __devinitdata +#define __devinitdata +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(license) +#endif + +#ifndef MOD_INC_USE_COUNT +#define MOD_INC_USE_COUNT do {} while (0) +#endif + +#ifndef MOD_DEC_USE_COUNT +#define MOD_DEC_USE_COUNT do {} while (0) +#endif + +#ifndef HAVE_NETDEV_PRIV +#define netdev_priv(dev) (dev->priv) +#endif + +#ifndef IRQ_RETVAL +typedef void irqreturn_t; +#define IRQ_RETVAL(x) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) + +typedef unsigned long dma_addr_t; +typedef struct wait_queue *wait_queue_head_t; +#define init_waitqueue_head(x) *(x)=NULL +#define set_current_state(status) { current->state = (status); mb(); } + +#ifdef MODULE +#define module_init(fn) int init_module(void) { return fn(); } +#define module_exit(fn) void cleanup_module(void) { return fn(); } +#else // MODULE +#define module_init(fn) int velocity_probe(void) { return fn(); } +#define module_exit(fn) // NOTHING +#endif // MODULE + +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + +#ifdef MODVERSIONS +#include +#endif + +#include +#include +#include +#include + +#define pci_resource_start(dev, bar) \ + (((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_SPACE_IO) ? \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_IO_MASK) : \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_MEM_MASK)) + +static inline int pci_enable_device(struct pci_dev *dev) { return 0; } +#define pci_disable_device(dev) /* NOTHING */ +#define __constant_cpu_to_le32 cpu_to_le32 +#define __constant_cpu_to_le16 cpu_to_le16 + +#define PCI_DMA_TODEVICE 1 +#define PCI_DMA_FROMDEVICE 2 + +extern inline void *pci_alloc_consistent (struct pci_dev *dev, + size_t size, + dma_addr_t *dma_handle) { + void *vaddr = kmalloc(size, GFP_ATOMIC); + if(vaddr != NULL) { + *dma_handle = virt_to_bus(vaddr); + } + return vaddr; +} + +#define pci_dma_sync_single(dev,dma_handle,size,direction) do{} while(0) +#define pci_dma_supported(dev, addr_mask) (1) +#define pci_free_consistent(dev, size, cpu_addr, dma_handle) kfree(cpu_addr) +#define pci_map_single(dev, addr, size, direction) virt_to_bus(addr) +#define pci_unmap_single(dev, dma_handle, size, direction) do{} while(0) + + +#define spin_lock_bh spin_lock_irq +#define spin_unlock_bh spin_unlock_irq +#define del_timer_sync(timer) del_timer(timer) +#define net_device device + +#define netif_start_queue(dev) ( clear_bit(0, &(dev)->tbusy)) +#define netif_stop_queue(dev) ( set_bit(0, &(dev)->tbusy)) +#define netif_wake_queue(dev) { clear_bit(0, &(dev)->tbusy); \ + mark_bh(NET_BH); } +#define netif_running(dev) ( test_bit(0, &(dev)->start)) +#define netif_queue_stopped(dev) ( test_bit(0, &(dev)->tbusy)) + +#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb) + +#define netif_carrier_on(dev) do {} while (0) +#define netif_carrier_off(dev) do {} while (0) + + +#define PCI_ANY_ID (~0U) + +struct pci_device_id { + unsigned int vendor, device; + unsigned int subvendor, subdevice; + unsigned int class, classmask; + unsigned long driver_data; +}; + +#define MODULE_DEVICE_TABLE(bus, dev_table) +#define PCI_MAX_NUM_NICS 256 + +struct pci_driver { + char *name; + struct pci_device_id *id_table; + int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); + void (*remove)(struct pci_dev *dev); + void (*suspend)(struct pci_dev *dev); + void (*resume)(struct pci_dev *dev); + struct pci_dev *pcimap[PCI_MAX_NUM_NICS]; +}; + +static inline int pci_module_init(struct pci_driver *drv) +{ + struct pci_dev *pdev; + struct pci_device_id *pcid; + uint16_t subvendor, subdevice; + int board_count = 0; + + /* walk the global pci device list looking for matches */ + for (pdev = pci_devices; pdev && (board_count < PCI_MAX_NUM_NICS); pdev = pdev->next) { + + pcid = &drv->id_table[0]; + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subdevice); + + while (pcid->vendor != 0) { + if (((pcid->vendor == pdev->vendor) || (pcid->vendor == PCI_ANY_ID)) && + ((pcid->device == pdev->device) || (pcid->device == PCI_ANY_ID)) && + ((pcid->subvendor == subvendor) || (pcid->subvendor == PCI_ANY_ID)) && + ((pcid->subdevice == subdevice) || (pcid->subdevice == PCI_ANY_ID))) { + + if (drv->probe(pdev, pcid) == 0) { + drv->pcimap[board_count] = pdev; + board_count++; + } + break; + } + pcid++; + } + } + + if (board_count < PCI_MAX_NUM_NICS) { + drv->pcimap[board_count] = NULL; + } + + return (board_count > 0) ? 0 : -ENODEV; +} + +static inline void pci_unregister_driver(struct pci_driver *drv) +{ + int i; + + for (i = 0; i < PCI_MAX_NUM_NICS; i++) { + if (!drv->pcimap[i]) + break; + + drv->remove(drv->pcimap[i]); + } +} + +#define pci_set_drvdata(pcid, data) + +#define pci_get_drvdata(pcid) ({ \ + PVELOCITY_INFO pInfo; \ + for (pInfo = pVelocity3_Infos; \ + pInfo; pInfo = pInfo->next) { \ + if (pInfo->pcid == pcid) \ + break; \ + } \ + pInfo; }) + +#define pci_set_dma_mask(pdev, mask) (0) + +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) +#if !defined(skb_linearize) +#define skb_linearize(skb, gfp_mask) ({ \ + struct sk_buff *tmp_skb; \ + tmp_skb = skb; \ + skb = skb_copy(tmp_skb, gfp_mask); \ + dev_kfree_skb(tmp_skb); }) +#endif +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) + + +#ifndef MODULE_LICESEN +#define MODULE_LICESEN(x) +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,2) + static inline int pci_set_power_state(struct pci_dev *dev, int state) { return 0; } +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,4,2) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) + +#include +#include + +#define PMCSR 0xe0 +#define PM_ENABLE_BIT 0x0100 +#define PM_CLEAR_BIT 0x8000 +#define PM_STATE_MASK 0xFFFC +#define PM_STATE_D1 0x0001 +static inline int +pci_enable_wake(struct pci_dev *dev, u32 state, int enable) +{ + u16 p_state; + + pci_read_config_word(dev, PMCSR, &p_state); + pci_write_config_word(dev, PMCSR, p_state | PM_CLEAR_BIT); + + if (enable == 0) { + p_state &= ~PM_ENABLE_BIT; + } else { + p_state |= PM_ENABLE_BIT; + } + p_state &= PM_STATE_MASK; + p_state |= state; + + pci_write_config_word(dev, PMCSR, p_state); + + return 0; +} +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) + + +#endif // __KCOMPAT_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/osdep.h linux-2.4.33-wt1-via/drivers/net/velocityget/osdep.h --- linux-2.4.33-wt1/drivers/net/velocityget/osdep.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/osdep.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software is copyrighted by and is the sole property of + * VIA Networking Technologies, Inc. This software may only be used + * in accordance with the corresponding license agreement. Any unauthorized + * use, duplication, transmission, distribution, or disclosure of this + * software is expressly forbidden. + * + * This software is provided by VIA Networking Technologies, Inc. "as is" + * and any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose + * are disclaimed. In no event shall VIA Networking Technologies, Inc. + * be liable for any direct, indirect, incidental, special, exemplary, or + * consequential damages. + * + * + * File: _os_dep.h + * + * Purpose: OS depended function and macro defined, including register accessing. + * + * Author: Guard Kuo + * + * Date: Jan 28, 2005 + * + * + */ +#ifndef ___OS_DEP_H__ +#define ___OS_DEP_H__ +#include +#include +#include +#include +#include +#include +#include + +typedef __u8 UCHAR, *PUCHAR; +typedef __u16 U16, *PU16; +typedef __u8 UINT8, *PUINT8; +typedef __u32 U32, *PU32; +typedef __u32 UINT32, *PUINT32; +typedef __u32 UINT, *PUINT; +typedef __u8 BYTE, *PBYTE; +typedef __u8 U8, *PU8; +typedef __u32 BOOL, *PBOOL; +typedef __u16 WORD, *PWORD; +typedef __u32 DWORD, *PDWORD; +typedef unsigned long ULONG, *PULONG; + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!(FALSE)) +#endif + +// Power status setting +#ifndef PCI_D0 +#define PCI_D0 0 +#endif +#ifndef PCI_D1 +#define PCI_D1 1 +#endif +#ifndef PCI_D2 +#define PCI_D2 2 +#endif +#ifndef PCI_D3hot +#define PCI_D3hot 3 +#endif +#ifndef PCI_D3cold +#define PCI_D3cold 4 +#endif + +/* + little/big endian converting +*/ +#if 0 +#define cpu_to_le32(x) x +#define cpu_to_le16(x) x +#endif + + +/* + delay function +*/ +#if 0 +#ifndef mdelay(x) +#define mdelay(x) x +#endif + +#ifndef udelay(x) +#define udelay(x) x +#endif +#endif + +struct em_osdep +{ + struct net_device* dev; +}; + + +/* + */ +#define VELOCITY_PRT(msglevel, l, p, args...) do {if (l<=msglevel) printk( p ,##args);} while (0) +#define VELOCITY_HW_PRT(hw, l, p, args...) do {if (l<=(hw)->msglevel) printk( "%s: " p , hw->back->dev->name, ##args);} while (0) + + +//#define USE_PIO +#undef USE_PIO + +#ifdef USE_PIO +#define CSR_WRITE_4(hw, val, reg) writel(val, (hw)->ioaddr+reg) +#define CSR_WRITE_2(hw, val, reg) writew(val, (hw)->ioaddr+reg) +#define CSR_WRITE_1(hw, val, reg) writeb(val, (hw)->ioaddr+reg) + +#define CSR_READ_4(hw, reg) readl((hw)->ioaddr+reg) +#define CSR_READ_2(hw, reg) readw((hw)->ioaddr+reg) +#define CSR_READ_1(hw, reg) readb((hw)->ioaddr+reg) + +#else +/* + * register space access macros + */ +#define CSR_WRITE_4(hw, val, reg) writel(val, (hw)->hw_addr+reg) +#define CSR_WRITE_2(hw, val, reg) writew(val, (hw)->hw_addr+reg) +#define CSR_WRITE_1(hw, val, reg) writeb(val, (hw)->hw_addr+reg) + +#define CSR_READ_4(hw, reg) readl((hw)->hw_addr+reg) +#define CSR_READ_2(hw, reg) readw((hw)->hw_addr+reg) +#define CSR_READ_1(hw, reg) readb((hw)->hw_addr+reg) +#endif + +#define _INB(hw, reg) inb((hw)->ioaddr+reg) +#define _OUTB(hw, val, reg) outb(val, (hw)->ioaddr+reg) + +#define TX_QUEUE_NO 4 + +#define MALLOC(x,y) kmalloc((x),(y)) + +#define PKT_BUF_SZ 1540 + + +#endif + diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,295 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity.h + * + * Purpose: Header file to define driver's private structures. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_H__ +#define __VELOCITY_H__ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef SIOCETHTOOL +#define VELOCITY_ETHTOOL_IOCTL_SUPPORT +#include +#else +#undef VELOCITY_ETHTOOL_IOCTL_SUPPORT +#endif + +#ifdef SIOCGMIIPHY +#define VELOCITY_MII_IOCTL_SUPPORT +#include +#else +#undef VELOCITY_MII_IOCTL_SUPPORT +#endif + +#if 0 +// The skb fragments of this version isn't be tested. +#ifdef MAX_SKB_FRAGS +#define VELOCITY_ZERO_COPY_SUPPORT +#else +#undef VELOCITY_ZERO_COPY_SUPPORT +#endif +#endif + +#ifdef NETIF_F_IP_CSUM +#include +#include +#include +#include +#define VELOCITY_TX_CSUM_SUPPORT +#else +#undef VELOCITY_TX_CSUM_SUPPORT +#endif + +#if 0 +#ifdef NETIF_F_TSO +#include +#define VELOCITY_TSO_SUPPORT +#else +#undef VELOCITY_TSO_SUPPORT +#endif +#endif + +#include "velocity_hw.h" + +#include "kcompat.h" +#include "velocity_cfg.h" +#include "velocity_desc.h" +#include "velocity_mac.h" +#include "velocity_proc.h" +#include "velocity_wol.h" +#include "velocity_mii.h" +#include "velocity_dbg.h" + + +// flags for driver status +#define VELOCITY_FLAGS_OPENED 0x00010000UL +#define VELOCITY_FLAGS_WOL_ENABLED 0x00080000UL + +// +// Registers in the PCI configuration space +// +#define PCI_REG_COMMAND 0x04 // +#define PCI_REG_MODE0 0x60 // +#define PCI_REG_MODE1 0x61 // +#define PCI_REG_MODE2 0x62 // +#define PCI_REG_MODE3 0x63 // +#define PCI_REG_DELAY_TIMER 0x64 // + +// +// Registers for power management (offset) +// +#define PCI_REG_PM_BASE 0x50 + +#define PM_CAP_ID 0x00 // 0x50 +#define PM_NEXT_ITEM_PTR 0x01 // 0x51 +#define PM_PMC0 0x02 // 0x52 +#define PM_PMC1 0x03 // 0x53 +#define PM_PMCSR0 0x04 // 0x54 +#define PM_PMCSR1 0x05 // 0x55 +#define PM_CSR_BSE 0x06 // 0x56 +#define PM_DATA 0x07 // 0x57 + +// Bits in the (COMMAND, 0x04) register +#define COMMAND_BUSM 0x04 +#define COMMAND_WAIT 0x80 + +// +// Bits in the (MODE0, 0x60) register +// +#define MODE0_QPKTDIS 0x80 // DISable transmit PacKeT Queuing + +// +// Bits in the (MODE2, 0x62) register +// +#define MODE2_PCEROPT 0x80 // take PCI bus ERror as a fatal and shutdown from software control +#define MODE2_TXQ16 0x40 // TX write-back Queue control. 0->32 entries available in Tx write-back queue, 1->16 entries +#define MODE2_TXPOST 0x08 // (Not support in VT3119) +#define MODE2_AUTOOPT 0x04 // (VT3119 GHCI without such behavior) +#define MODE2_MODE10T 0x02 // used to control tx Threshold for 10M case +#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 +// +#define MODE3_MIION 0x04 // MII symbol codine error detect enable ?? + +// +// Bits in PMCSR0 register +// +#define PMCSR0_PW_STAT1 0x02 // +#define PMCSR0_PW_STAT0 0x01 // + +// +// Bits in PMCSR1 register +// +#define PMCSR1_PME_STATUS 0x80 // +#define PMCSR1_PME_EN 0x01 // + + +typedef enum __velocity_init_type { + VELOCITY_INIT_COLD = 0, // 0 + VELOCITY_INIT_RESET, // 1 + VELOCITY_INIT_WOL // 2 +} VELOCITY_INIT_TYPE, *PVELOCITY_INIT_TYPE; + + +typedef +struct _velocity_rd_info { + struct sk_buff* skb; + dma_addr_t skb_dma; +} VELOCITY_RD_INFO, *PVELOCITY_RD_INFO; + +typedef +struct _velocity_td_info { + struct sk_buff* skb; + PU8 buf; + int nskb_dma; + dma_addr_t skb_dma[7]; + dma_addr_t buf_dma; +} VELOCITY_TD_INFO, *PVELOCITY_TD_INFO; + + + +typedef struct __velocity_info { + struct __velocity_info* next; + struct __velocity_info* prev; + + struct pci_dev* pcid; + struct net_device* dev; + struct net_device_stats stats; + +#if CONFIG_PM + U32 pci_state[16]; +#endif + + void* pool; + PU8 tx_bufs; + + U8 abyIPAddr[4]; + CHIP_TYPE chip_id; + + PVELOCITY_TD_INFO apTDInfos[TX_QUEUE_NO]; + + PVELOCITY_RD_INFO aRDInfo; //it's an array + + U32 adwRMONStats[RMON_TAB_SIZE]; + + + /* define in velocity_hw.h */ + struct velocity_hw hw; + + spinlock_t lock; + spinlock_t xmit_lock; + + int wol_opts; + U8 wol_passwd[6]; + + VELOCITY_CONTEXT mac_context; + U32 pci_context; + +#ifdef CONFIG_PROC_FS + PVELOCITY_PROC_ENTRY pProcDir; +#endif + U32 ticks; + U32 rx_bytes; + + struct em_osdep osdep; + + +} VELOCITY_INFO, *PVELOCITY_INFO; + +inline static BOOL velocity_get_ip(PVELOCITY_INFO pInfo) { + struct in_device* in_dev = (struct in_device*)pInfo->dev->ip_ptr; + struct in_ifaddr* ifa; + + if (in_dev!=NULL) { + ifa=(struct in_ifaddr*) in_dev->ifa_list; + if (ifa!=NULL) { + memcpy(pInfo->abyIPAddr,&ifa->ifa_address,4); + return TRUE; + } + } + return FALSE; +} + + + +#define PCI_BYTE_REG_BITS_ON(x,i,p) do{\ + U8 byReg;\ + pci_read_config_byte((p), (i), &(byReg));\ + (byReg) |= (x);\ + pci_write_config_byte((p), (i), (byReg));\ +} while (0) + +#define PCI_BYTE_REG_BITS_OFF(x,i,p) do{\ + U8 byReg;\ + pci_read_config_byte((p), (i), &(byReg));\ + (byReg) &= (~(x));\ + pci_write_config_byte((p), (i), (byReg));\ +} while (0) + +#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) >= ((uModulo) - 1)) \ + (uVar) = 0; \ + else \ + (uVar)++; \ +} + +#define SUB_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) <= 0) \ + (uVar) = ((uModulo) - 1); \ + else \ + (uVar)--; \ +} + + +#endif // __VELOCITY_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_cfg.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_cfg.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_cfg.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_cfg.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_cfg.h + * + * Purpose: The OS dependent types & constants. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +/* +* Description: This file defined OS dependent macros & defines +*/ + +#ifndef __VELOCITY_CFG_H__ +#define __VELOCITY_CFG_H__ + +#include +#include + +typedef +struct _version { + UINT8 major; + UINT8 minor; + UINT8 build; +} version_t, *pversion_t; + +#define VELOCITY_NAME "velocityget" +#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver" + +#ifndef MAJOR_VERSION +#define MAJOR_VERSION 1 +#endif + +#ifndef MINOR_VERSION +#define MINOR_VERSION 22 +#endif + +#ifndef VELOCITY_VERSION +#define VELOCITY_VERSION "1.22" +#endif + + + +#define MAX_UINTS 8 +#define OPTION_DEFAULT { [0 ... MAX_UINTS-1] = -1} + +#define REV_ID_VT6110 (0) +#define DEVICE_ID (0x3119) + +#define VAR_USED(p) do {(p)=(p);} while (0) + + +#endif // __VELOCITY_CFG_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_dbg.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_dbg.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_dbg.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_dbg.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_dbg.h + * + * Purpose: Hearder file for inline debug routine + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_DBG_H__ +#define __VELOCITY_DBG_H__ + + +#ifdef VELOCITY_DEBUG +#define ASSERT(x) { \ + if (!(x)) { \ + printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\ + __FUNCTION__, __LINE__);\ + *(int*) 0=0;\ + }\ +} +#define VELOCITY_DBG(p,args...) printk(p, ##args) +#else +#define ASSERT(x) +#define VELOCITY_DBG(x) +#endif + + +#define VELOCITY_PRT_CAMMASK(p,t) {\ + int i;\ + if ((t)==VELOCITY_MULTICAST_CAM) {\ + for (i=0;i<(MCAM_SIZE/8);i++)\ + printk("%02X",(p)->abyMCAMMask[i]);\ + }\ + else {\ + for (i=0;i<(VCAM_SIZE/8);i++)\ + printk("%02X",(p)->abyVCAMMask[i]);\ + }\ + printk("\n");\ +} + +#endif // __VELOCITY_DBG_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_desc.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_desc.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_desc.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_desc.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,253 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_desc.h + * + * Purpose: Structures for MAX RX/TX descriptors. + * + * Author: Chuang Liang-Shing, AJ Jiang, Ryan Fu + * + * Date: Jan 24, 2003 + * + * + */ + + +#ifndef __VELOCITY_DESC_H__ +#define __VELOCITY_DESC_H__ + +#include "osdep.h" + +/* +// Bits in the RSR0 register +*/ +#define RSR_DETAG 0x0080 +#define RSR_SNTAG 0x0040 +#define RSR_RXER 0x0020 +#define RSR_RL 0x0010 +#define RSR_CE 0x0008 +#define RSR_FAE 0x0004 +#define RSR_CRC 0x0002 +#define RSR_VIDM 0x0001 +/* +// Bits in the RSR1 register +*/ +#define RSR_RXOK 0x8000 /* rx OK */ +#define RSR_PFT 0x4000 /* Perfect filtering address match */ +#define RSR_MAR 0x2000 /* MAC accept multicast address packet */ +#define RSR_BAR 0x1000 /* MAC accept broadcast address packet */ +#define RSR_PHY 0x0800 /* MAC accept physical address packet */ +#define RSR_VTAG 0x0400 /* 802.1p/1Q tagging packet indicator */ +#define RSR_STP 0x0200 /* start of packet */ +#define RSR_EDP 0x0100 /* end of packet */ +/* +// Bits in the RSR1 register +*/ +#define RSR1_RXOK 0x80 /* rx OK */ +#define RSR1_PFT 0x40 /* Perfect filtering address match */ +#define RSR1_MAR 0x20 /* MAC accept multicast address packet */ +#define RSR1_BAR 0x10 /* MAC accept broadcast address packet */ +#define RSR1_PHY 0x08 /* MAC accept physical address packet */ +#define RSR1_VTAG 0x04 /* 802.1p/1q tagging packet indicator */ +#define RSR1_STP 0x02 /* start of packet */ +#define RSR1_EDP 0x01 /* end of packet */ + +/* +// Bits in the CSM register +*/ +#define CSM_IPOK 0x40 /*IP Checkusm validatiaon ok */ +#define CSM_TUPOK 0x20 /*TCP/UDP Checkusm validatiaon ok */ +#define CSM_FRAG 0x10 /*Fragment IP datagram */ +#define CSM_IPKT 0x04 /*Received an IP packet */ +#define CSM_TCPKT 0x02 /*Received a TCP packet */ +#define CSM_UDPKT 0x01 /*Received a UDP packet */ + +/* +// Bits in the TSR0 register +*/ +#define TSR0_ABT 0x0080 /* Tx abort because of excessive collision */ +#define TSR0_OWT 0x0040 /* Jumbo frame Tx abort */ +#define TSR0_OWC 0x0020 /* Out of window collision */ +#define TSR0_COLS 0x0010 /* experience collision in this transmit event */ +#define TSR0_NCR3 0x0008 /* collision retry counter[3] */ +#define TSR0_NCR2 0x0004 /* collision retry counter[2] */ +#define TSR0_NCR1 0x0002 /* collision retry counter[1] */ +#define TSR0_NCR0 0x0001 /* collision retry counter[0] */ +#define TSR0_TERR 0x8000 /* */ +#define TSR0_FDX 0x4000 /* current transaction is serviced by full duplex mode */ +#define TSR0_GMII 0x2000 /* current transaction is serviced by GMII mode */ +#define TSR0_LNKFL 0x1000 /* packet serviced during link down */ +#define TSR0_SHDN 0x0400 /* shutdown case */ +#define TSR0_CRS 0x0200 /* carrier sense lost */ +#define TSR0_CDH 0x0100 /* AQE test fail (CD heartbeat) */ +#define TSR_TERR 0x00008000 +/* +// Bits in the TSR1 register +*/ +#define TSR1_TERR 0x80 /* */ +#define TSR1_FDX 0x40 /* current transaction is serviced by full duplex mode */ +#define TSR1_GMII 0x20 /* current transaction is serviced by GMII mode */ +#define TSR1_LNKFL 0x10 /* packet serviced during link down */ +#define TSR1_SHDN 0x04 /* shutdown case */ +#define TSR1_CRS 0x02 /* carrier sense lost */ +#define TSR1_CDH 0x01 /* AQE test fail (CD heartbeat) */ + +/* +// Bits in the TCR0 register +*/ +#define TCR0_TIC 0x80 /* assert interrupt immediately while descriptor has been send complete */ +#define TCR0_PIC 0x40 /* priority interrupt request, INA# is issued over adaptive interrupt scheme */ +#define TCR0_VETAG 0x20 /* enable VLAN tag */ +#define TCR0_IPCK 0x10 /* request IP checksum calculation. */ +#define TCR0_UDPCK 0x08 /* request UDP checksum calculation. */ +#define TCR0_TCPCK 0x04 /* request TCP checksum calculation. */ +#define TCR0_JMBO 0x02 /* indicate a jumbo packet in GMAC side */ +#define TCR0_CRC 0x01 /* disable CRC generation */ + +#define TCR_TCPLS_SOF 0x02000000L +#define TCR_TCPLS_EOF 0x01000000L +#define TCR_TIC 0x00800000L +#define TCR_VETAG 0x00200000L /* enable VLAN tag */ +#define TCR_IPCK 0x00100000L /* request IP checksum calculation. */ +#define TCR_UDPCK 0x00080000L /* request UDP checksum calculation. */ +#define TCR_TCPCK 0x00040000L /* request TCP checksum calculation. */ + +#define TCPLS_NORMAL 3 +#define TCPLS_START 2 +#define TCPLS_END 1 +#define TCPLS_MED 0 + +/* max transmit or receive buffer size */ +#define CB_RX_BUF_SIZE 2048UL /* max buffer size */ + /* NOTE: must be multiple of 4 */ + +#define CB_MAX_RD_NUM 512 /* MAX # of RD */ +#define CB_MAX_TD_NUM 256 /* MAX # of TD */ + +#define CB_INIT_RD_NUM_3119 128 /* init # of RD, for setup VT3119 */ +#define CB_INIT_TD_NUM_3119 64 /* init # of TD, for setup VT3119 */ + +#define CB_INIT_RD_NUM 128 /* init # of RD, for setup default */ +#define CB_INIT_TD_NUM 64 /* init # of TD, for setup default */ + +/* for 3119 */ +#define CB_TD_RING_NUM 4 /* # of TD rings. */ +#define CB_MAX_SEG_PER_PKT 7 /* max data seg per packet (Tx) */ + + +/* if collisions excess 15 times , tx will abort, and +// if tx fifo underflow, tx will fail +// we should try to resend it */ +#define CB_MAX_TX_ABORT_RETRY 3 + +/*--------------------- Export Types ------------------------------*/ + +/* +// receive descriptor +*/ + +#define RDESC0_OWN 0x80000000L +#define RDESC3_INTCTL 0x80000000L + +typedef struct __rx_desc { + U32 rdesc0; /* [31]: Owner, [29:16]: RMBC(receive packet length */ + /* [15:0]: RCR */ + U32 rdesc1; /* [31:24]: IPKT, [23:16]: CSM, [15:0]: PQTAG */ + U32 dwBufAddrLo; + U32 rdesc3; /* [31]: Intr control enable, [29:16]: buffer size */ + /* [15:0]: Rx buffer address(48 bit-33 bit) */ +} +__attribute__ ((__packed__)) +RX_DESC, * PRX_DESC; + + +/* +// transmit descriptor +*/ + +#define TDESC0_OWN 0x80000000L +#define TDTXBUF_QUE 0x80000000L +#define TDESC1_CMDZ 0xf0000000L + +typedef struct _td_buf { + U32 dwBufAddrLo; + U32 dwBufaddrHi; /* [31]: Queue bit, [29:16]: buffer size */ + /* [15:0]: Tx data buffer address(48 bit-33 bit). */ +} +__attribute__ ((__packed__)) +TD_BUF, *PTD_BUF; + +typedef struct _tx_desc { + U32 tdesc0; /* [31]: Owner, [29:16]: tx packet size */ + /* [15:0]: TSR */ + U32 tdesc1; /* [31:28]: CMDZ, [27:26]: reserved, [25:24]: TCPLS */ + /* [23:16]: TCR, [15:13]: 802.1p priority bits, */ + /* [12]: CFI(reserved control bit), [11:0]: 802.1Q Virtaul Lan identifier */ + TD_BUF aTdBufs[7]; +} +__attribute__ ((__packed__)) +TX_DESC, *PTX_DESC; + + +typedef +enum { + OWNED_BY_HOST=0, + OWNED_BY_NIC=1 +} VELOCITY_OWNER_TYPE, *PVELOCITY_OWNER_TYPE; + + +/*--------------------- Export Macros ------------------------------*/ + +#define VELOCITY_SET_RD_BUFFER_SIZE(pRD, size) { \ + pRD->rdesc3 &= cpu_to_le32(0xc000ffffL); \ + pRD->rdesc3 |= cpu_to_le32(((U32)size) << 16); \ +} + +#define VELOCITY_SET_TD_BUFFER_SIZE(pTDBuf, size) { \ + pTDBuf.dwBufaddrHi &= cpu_to_le32(0xc000ffffL); \ + pTDBuf.dwBufaddrHi |= cpu_to_le32(((U32)size) << 16); \ +} + +#define VELOCITY_SET_TD_PACKET_SIZE(pTD, size) { \ + pTD->tdesc0 &= cpu_to_le32(0xc000ffffL); \ + pTD->tdesc0 |= cpu_to_le32(((U32)size) << 16); \ +} + +#define VELOCITY_SET_TD_CMDZ(pTD, cmdz) { \ + pTD->tdesc1 &= cpu_to_le32(0x0fffffffL); \ + pTD->tdesc1 |= cpu_to_le32(((U32)cmdz) << 28); \ +} + +#define VELOCITY_SET_TD_TCPLS(pTD, tcpls) { \ + pTD->tdesc1 &= cpu_to_le32(0xfcffffffL); \ + pTD->tdesc1 |= cpu_to_le32(((U32)tcpls) << 24); \ +} + +#define VELOCITY_SET_TD_VLANID(pTD, vlanid) { \ + pTD->tdesc1 &= cpu_to_le32(0xfffff000L); \ + pTD->tdesc1 |= cpu_to_le32((U32)vlanid); \ +} + +#define VELOCITY_SET_TD_PRIORITY(pTD, priority) { \ + pTD->tdesc1 &= cpu_to_le32(0xffff1fffL); \ + pTD->tdesc1 |= cpu_to_le32(((U32)priority) << 13); \ +} + +#define VELOCITY_GET_RD_PACKET_SIZE(pRD) \ + (U16)((cpu_to_le32(pRD->rdesc0) >> 16) & 0x00003fffL); + + + +#endif /* __VELOCITY_DESC_H__ */ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_hw.c linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_hw.c --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_hw.c 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_hw.c 2006-10-23 10:58:14 +0200 @@ -0,0 +1,895 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software is copyrighted by and is the sole property of + * VIA Networking Technologies, Inc. This software may only be used + * in accordance with the corresponding license agreement. Any unauthorized + * use, duplication, transmission, distribution, or disclosure of this + * software is expressly forbidden. + * + * This software is provided by VIA Networking Technologies, Inc. "as is" + * and any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose + * are disclaimed. In no event shall VIA Networking Technologies, Inc. + * be liable for any direct, indirect, incidental, special, exemplary, or + * consequential damages. + * + * + * File: velocity_hw.c + * + * Purpose: Describe what this file is going to do. + * + * Author: Guard Kuo + * + * Date: May 04, 2005 + * + * Functions: + * List all the functions this module provides. + * (This section is omitted in the header of ".h" files) + * + * Revision History: + * mm-dd-yyyy Revisor's Name: Whenever you made some changes, + * leave a record here. + * (This section is omitted in the header of ".h" files) + * + */ + +#include "velocity_hw.h" +#include "velocity_mac.h" +#include "velocity_desc.h" +#include "velocity_mii.h" + + + + +void velocity_shutdown(struct velocity_hw *hw) { + mac_disable_int(hw); + CSR_WRITE_4(hw, CR0_STOP,MAC_REG_CR0_SET); + CSR_WRITE_2(hw, 0xFFFF, MAC_REG_TDCSR_CLR); + CSR_WRITE_1(hw, 0xFF, MAC_REG_RDCSR_CLR); + SafeDisableMiiAutoPoll(hw); + mac_clear_isr(hw); +} + +BOOL velocity_soft_reset(struct velocity_hw *hw) { + + int i=0; + + CSR_WRITE_4(hw, CR0_SFRST, MAC_REG_CR0_SET); + + for (i=0;isOpts.flow_cntl) { + + case FLOW_CNTL_DEFAULT: + if (BYTE_REG_BITS_IS_ON(hw, PHYSR0_RXFLC, MAC_REG_PHYSR0)) + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_SET); + else + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_CLR); + + if (BYTE_REG_BITS_IS_ON(hw, PHYSR0_TXFLC, MAC_REG_PHYSR0)) + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_SET); + else + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_CLR); + break; + + case FLOW_CNTL_TX: + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_SET); + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_CLR); + break; + + case FLOW_CNTL_RX: + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_SET); + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_CLR); + break; + + case FLOW_CNTL_TX_RX: + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_SET); + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_SET); + break; + + case FLOW_CNTL_DISABLE: + CSR_WRITE_4(hw, CR0_FDXRFCEN, MAC_REG_CR0_CLR); + CSR_WRITE_4(hw, CR0_FDXTFCEN, MAC_REG_CR0_CLR); + break; + + default: + break; + } +} + +U32 check_connectiontype(struct velocity_hw *hw) +{ + U32 status = 0; + U8 byPHYSR0; + + byPHYSR0 = CSR_READ_1(hw, MAC_REG_PHYSR0); + + if(!(byPHYSR0 & PHYSR0_LINKGD)) + { + status |= VELOCITY_LINK_FAIL; + return status; + } + + if(hw->sOpts.spd_dpx == SPD_DPX_AUTO){ + status |= VELOCITY_AUTONEG_ENABLE; + if (byPHYSR0 & PHYSR0_FDPX) + status |= VELOCITY_DUPLEX_FULL; + + if (byPHYSR0 & PHYSR0_SPDG) + status |= VELOCITY_SPEED_1000; + + if (byPHYSR0 & PHYSR0_SPD10) + status |= VELOCITY_SPEED_10; + else + status |= VELOCITY_SPEED_100; + } + else{ + switch(hw->sOpts.spd_dpx) + { + case SPD_DPX_100_HALF: + status |= VELOCITY_SPEED_100; + break; + case SPD_DPX_100_FULL: + status |= VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL; + break; + case SPD_DPX_10_HALF: + status |= VELOCITY_SPEED_10; + break; + case SPD_DPX_10_FULL: + status |= VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL; + break; + default: + status = 0; + } + } + + return status; +} + +U32 mii_check_media_mode(struct velocity_hw *hw) +{ + U32 status = 0; + U16 wANAR; + + if (!MII_REG_BITS_IS_ON(BMSR_LNK,MII_REG_BMSR, hw)) + status |= VELOCITY_LINK_FAIL; + + if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, hw)) + status |= (VELOCITY_SPEED_1000|VELOCITY_DUPLEX_FULL); + else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, hw)) + status |= VELOCITY_SPEED_1000; + else { + velocity_mii_read(hw, MII_REG_ANAR, &wANAR); + if (wANAR & ANAR_TXFD) + status |= (VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL); + else if (wANAR & ANAR_TX) + status |= VELOCITY_SPEED_100; + else if (wANAR & ANAR_10FD) + status |= (VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL); + else + status |= (VELOCITY_SPEED_10); + } + + if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, hw)) { + velocity_mii_read(hw, MII_REG_ANAR, &wANAR); + if ((wANAR & (ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)) + ==(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)) { + if (MII_REG_BITS_IS_ON(G1000CR_1000|G1000CR_1000FD, + MII_REG_G1000CR, hw)) + status |= VELOCITY_AUTONEG_ENABLE; + } + } + + return status; +} + + +/************************************************************************ +* MII access , media link mode setting functions +************************************************************************/ +void mii_init(struct velocity_hw *hw, U32 mii_status) { + U16 wBMCR; + + switch (PHYID_GET_PHY_ID(hw->dwPHYId)) { + case PHYID_CICADA_CS8201: + /* Reset to hardware default */ + MII_REG_BITS_OFF((ANAR_ASMDIR|ANAR_PAUSE), MII_REG_ANAR, hw); + + /* turn on ECHODIS bit in NWay-forced full mode and turn off it in + // NWay-forced half mode for NWay-forced v.s. legacy-forced issue */ + if (hw->mii_status & VELOCITY_DUPLEX_FULL) + MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, hw); + else + MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, hw); + + /* Turn on Link/Activity LED enable bit for CIS8201 */ + MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, hw); + + break; + + case PHYID_VT3216_32BIT: + case PHYID_VT3216_64BIT: + /* Reset to hardware default */ + MII_REG_BITS_ON((ANAR_ASMDIR|ANAR_PAUSE), MII_REG_ANAR, hw); + + /* turn on ECHODIS bit in NWay-forced full mode and turn off it in + // NWay-forced half mode for NWay-forced v.s. legacy-forced issue */ + if (hw->mii_status & VELOCITY_DUPLEX_FULL) + MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, hw); + else + MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, hw); + + break; + + case PHYID_MARVELL_1000: + case PHYID_MARVELL_1000S: + /* Assert CRS on Transmit */ + MII_REG_BITS_ON(PSCR_ACRSTX,MII_REG_PSCR, hw); + /*Reset to hardware default*/ + MII_REG_BITS_ON((ANAR_ASMDIR|ANAR_PAUSE),MII_REG_ANAR, hw); + break; + default: + ; + } + + velocity_mii_read(hw, MII_REG_BMCR,&wBMCR); + if (wBMCR & BMCR_ISO) { + wBMCR &=~BMCR_ISO; + velocity_mii_write(hw, MII_REG_BMCR, wBMCR); + } +} + + +U16 set_mii_flow_control(struct velocity_hw *hw) +{ + /* Enable or Disable PAUSE in ANAR */ + switch(hw->sOpts.flow_cntl) { + case FLOW_CNTL_DEFAULT: + if (PHYID_GET_PHY_ID(hw->dwPHYId) == PHYID_CICADA_CS8201) { + /* hardware default PAUSE/ASMDIR value in CIS8201 is (0,0) */ + /*MII_REG_BITS_OFF((ANAR_ASMDIR|ANAR_PAUSE), MII_REG_ANAR, hw);*/ + return ANAR_ASMDIR|ANAR_PAUSE; + + } + else if ((PHYID_GET_PHY_ID(hw->dwPHYId) == PHYID_VT3216_32BIT) || + (PHYID_GET_PHY_ID(hw->dwPHYId) == PHYID_VT3216_64BIT)) { + /* hardware default PAUSE/ASMDIR value in VT3216 is (1,1) */ + /*MII_REG_BITS_ON((ANAR_ASMDIR|ANAR_PAUSE), MII_REG_ANAR, hw);*/ + return ANAR_ASMDIR|ANAR_PAUSE; + } + else { + /* Do nothing */ + } + break; + case FLOW_CNTL_TX: + /*MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, hw);*/ + /*MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, hw);*/ + return ANAR_ASMDIR; + break; + + case FLOW_CNTL_RX: + /*MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, hw); + MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, hw);*/ + return ANAR_PAUSE|ANAR_ASMDIR; + + break; + + case FLOW_CNTL_TX_RX: + /*MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, hw); + MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, hw);*/ + return ANAR_PAUSE|ANAR_ASMDIR; + break; + + case FLOW_CNTL_DISABLE: + MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, hw); + MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, hw); + return 0; + break; + default: + return 0; + break; + } + + return 0; +} + +/* +// Get the media mode stored in EEPROM or module options +*/ +U32 velocity_get_opt_media_mode(struct velocity_hw *hw) +{ + U32 status = 0; + + switch (hw->sOpts.spd_dpx) { + case SPD_DPX_AUTO: + status=VELOCITY_AUTONEG_ENABLE; + break; + case SPD_DPX_100_FULL: + status=VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL; + break; + case SPD_DPX_10_FULL: + status=VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL; + break; + case SPD_DPX_100_HALF: + status=VELOCITY_SPEED_100; + break; + case SPD_DPX_10_HALF: + status=VELOCITY_SPEED_10; + break; + } + hw->mii_status=status; + return status; +} + +BOOL velocity_mii_read(struct velocity_hw *hw, U8 byIdx, PU16 pdata) +{ + WORD ww; + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + SafeDisableMiiAutoPoll(hw); + + CSR_WRITE_1(hw, byIdx, MAC_REG_MIIADR); + + BYTE_REG_BITS_ON(hw, MIICR_RCMD, MAC_REG_MIICR); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(CSR_READ_1(hw, MAC_REG_MIICR) & MIICR_RCMD)) + break; + } + *pdata = CSR_READ_2(hw, MAC_REG_MIIDATA); + + EnableMiiAutoPoll(hw); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +BOOL velocity_mii_write(struct velocity_hw *hw, BYTE byMiiAddr, WORD wData) +{ + WORD ww; + + /* disable MIICR_MAUTO, so that mii addr can be set normally */ + SafeDisableMiiAutoPoll(hw); + + /* MII reg offset */ + CSR_WRITE_1(hw, byMiiAddr, MAC_REG_MIIADR); + /* set MII data */ + CSR_WRITE_2(hw, wData, MAC_REG_MIIDATA); + + /* turn on MIICR_WCMD */ + BYTE_REG_BITS_ON(hw, MIICR_WCMD, MAC_REG_MIICR); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(5); + if (!(CSR_READ_1(hw, MAC_REG_MIICR) & MIICR_WCMD)) + break; + } + + EnableMiiAutoPoll(hw); + + if (ww == W_MAX_TIMEOUT) + return FALSE; + + return TRUE; +} + +void init_flow_control_register(struct velocity_hw *hw) { + + /* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1} + depend on RD=64, and Turn on XNOEN in FlowCR1 */ + CSR_WRITE_4(hw, (CR0_XONEN|CR0_XHITH1|CR0_XLTH1|CR0_XLTH0), MAC_REG_CR0_SET); + CSR_WRITE_4(hw, (CR0_FDXTFCEN|CR0_FDXRFCEN|CR0_HDXFCEN|CR0_XHITH0), MAC_REG_CR0_CLR); + + /* Set TxPauseTimer to 0xFFFF */ + CSR_WRITE_2(hw, 0xFFFF, MAC_REG_PAUSE_TIMER); + + /* Initialize RBRDU to Rx buffer count. */ + CSR_WRITE_2(hw, hw->sOpts.nRxDescs, MAC_REG_RBRDU); +} + +void mac_get_cam_mask(struct velocity_hw *hw, PU8 pbyMask, + VELOCITY_CAM_TYPE cam_type) { + int i; + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_MASK,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + CSR_WRITE_1(hw, CAMADDR_VCAMSL, MAC_REG_CAMADDR); + else + CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); + + /* read mask */ + for (i=0;i<8;i++) + *pbyMask++ = CSR_READ_1(hw, MAC_REG_MAR+i); + + /* disable CAMEN */ + CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); + + /*Select mar*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); + +} + +void mac_set_cam_mask(struct velocity_hw *hw, PU8 pbyMask, + VELOCITY_CAM_TYPE cam_type) { + int i; + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_MASK,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + CSR_WRITE_1(hw, CAMADDR_CAMEN|CAMADDR_VCAMSL, MAC_REG_CAMADDR); + else + CSR_WRITE_1(hw, CAMADDR_CAMEN, MAC_REG_CAMADDR); + + for (i=0;i<8;i++) { + CSR_WRITE_1(hw, *pbyMask++, MAC_REG_MAR+i); + } + /* disable CAMEN */ + CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); + + /*Select CAM mask */ + BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); +} + +void mac_set_cam(struct velocity_hw *hw, int idx, PU8 addr, + VELOCITY_CAM_TYPE cam_type) { + int i; + + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_DATA,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); + + idx&=(64-1); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + CSR_WRITE_1(hw, CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, MAC_REG_CAMADDR); + else + CSR_WRITE_1(hw, CAMADDR_CAMEN|idx, MAC_REG_CAMADDR); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + CSR_WRITE_2(hw, *((PU16) addr), MAC_REG_MAR); + else { + for (i=0;i<6;i++) { + CSR_WRITE_1(hw, *addr++,MAC_REG_MAR+i); + } + } + BYTE_REG_BITS_ON(hw, CAMCR_CAMWR, MAC_REG_CAMCR); + + udelay(10); + + CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); + + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); +} + +void mac_get_cam(struct velocity_hw *hw, int idx, PU8 addr, + VELOCITY_CAM_TYPE cam_type) { + int i; + + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_DATA,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); + + idx&=(64-1); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + CSR_WRITE_1(hw, CAMADDR_CAMEN | CAMADDR_VCAMSL|idx, MAC_REG_CAMADDR); + else + CSR_WRITE_1(hw, CAMADDR_CAMEN |idx, MAC_REG_CAMADDR); + + BYTE_REG_BITS_ON(hw, CAMCR_CAMRD, MAC_REG_CAMCR); + + udelay(10); + + if (cam_type==VELOCITY_VLAN_ID_CAM) + *((PU16) addr)=CSR_READ_2(hw, MAC_REG_MAR); + else + for (i=0;i<6;i++, addr++) + *((PU8)addr)=CSR_READ_1(hw, MAC_REG_MAR+i); + + CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); + + /*Select CAM mask*/ + BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, + MAC_REG_CAMCR); +} + +void mac_wol_reset(struct velocity_hw *hw) { + + /* Turn off SWPTAG right after leaving power mode */ + BYTE_REG_BITS_OFF(hw, STICKHW_SWPTAG,MAC_REG_STICKHW); + /* clear sticky bits */ + BYTE_REG_BITS_OFF(hw, (STICKHW_DS1|STICKHW_DS0), + MAC_REG_STICKHW); + + BYTE_REG_BITS_OFF(hw, CHIPGCR_FCGMII,MAC_REG_CHIPGCR); + BYTE_REG_BITS_OFF(hw, CHIPGCR_FCMODE,MAC_REG_CHIPGCR); + /* disable force PME-enable */ + CSR_WRITE_1(hw, WOLCFG_PMEOVR, MAC_REG_WOLCFG_CLR); + /* disable power-event config bit */ + CSR_WRITE_2(hw, 0xFFFF, MAC_REG_WOLCR0_CLR); + /* clear power status */ + CSR_WRITE_2(hw, 0xFFFF, MAC_REG_WOLSR0_CLR); +} + +void SafeDisableMiiAutoPoll (struct velocity_hw *hw) { + WORD ww; + + /* turn off MAUTO */ + CSR_WRITE_2(hw, 0, MAC_REG_MIICR); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1); + if (BYTE_REG_BITS_IS_ON(hw, MIISR_MIDLE, MAC_REG_MIISR)) + break; + } +} + +void EnableMiiAutoPoll(struct velocity_hw* hw) { + int ii; + + CSR_WRITE_1(hw, 0, MAC_REG_MIICR); + CSR_WRITE_1(hw, MIIADR_SWMPL, MAC_REG_MIIADR); + + for (ii=0; iiabyVCAMMask, 0, sizeof(U8)*8); + memset(hw->abyMCAMMask, 0, sizeof(U8)*8); + mac_set_cam_mask(hw,hw->abyVCAMMask,VELOCITY_VLAN_ID_CAM); + mac_set_cam_mask(hw,hw->abyMCAMMask,VELOCITY_MULTICAST_CAM); + + /* Enable first VCAM */ + if (hw->flags & VELOCITY_FLAGS_TAGGING) { + /* if Tagging option is enabled and VLAN ID is not zero, then turn on MCFG_RTGOPT also */ + if (hw->sOpts.vid != 0) + WORD_REG_BITS_ON(hw, MCFG_RTGOPT, MAC_REG_MCFG0); + + mac_set_cam(hw, 0, (PU8)&(hw->sOpts.vid), VELOCITY_VLAN_ID_CAM); + hw->abyVCAMMask[0] |= 1; + mac_set_cam_mask(hw, hw->abyVCAMMask, VELOCITY_VLAN_ID_CAM); + } + else { + U16 wTemp = 0; + mac_set_cam(hw, 0, (PU8)&wTemp, VELOCITY_VLAN_ID_CAM); + wTemp = 1; + mac_set_cam_mask(hw, (PU8)&(wTemp), VELOCITY_VLAN_ID_CAM); + } +} + +void velocity_update_hw_mibs(struct velocity_hw *hw) { + U32 dwTmp; + int i; + BYTE_REG_BITS_ON(hw, MIBCR_MIBFLSH, MAC_REG_MIBCR); + + while (BYTE_REG_BITS_IS_ON(hw, MIBCR_MIBFLSH, MAC_REG_MIBCR)); + + BYTE_REG_BITS_ON(hw, MIBCR_MPTRINI, MAC_REG_MIBCR); + for (i=0;iadwHWMIBCounters[i]+=dwTmp; + } +} + +void velocity_rx_reset(struct velocity_hw *hw) +{ + int i; + + hw->iCurrRDIdx = 0; + + /* init state, all RD is chip's */ + for(i=0; isOpts.nRxDescs; i++) + hw->aRDRing[i].rdesc0 |= cpu_to_le32(RDESC0_OWN); + + CSR_WRITE_2(hw, hw->sOpts.nRxDescs, MAC_REG_RBRDU); + CSR_WRITE_4(hw, hw->rd_pool_dma, MAC_REG_RDBASE_LO); + CSR_WRITE_2(hw, 0, MAC_REG_RDINDX); + CSR_WRITE_2(hw, hw->sOpts.nRxDescs-1, MAC_REG_RDCSIZE); +} + +void velocity_print_link_status(struct velocity_hw *hw) { + + if (hw->mii_status & VELOCITY_LINK_FAIL) { + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "failed to detect cable link.\n"); + } + else { + if (hw->sOpts.spd_dpx == SPD_DPX_AUTO) { + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Link autonegation"); + + if (hw->mii_status & VELOCITY_SPEED_1000) + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 1000M bps"); + else if (hw->mii_status & VELOCITY_SPEED_100) + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 100M bps"); + else + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 10M bps"); + + if (hw->mii_status & VELOCITY_DUPLEX_FULL) + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " full duplex\n"); + else + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " half duplex\n"); + } + else { + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Link forced"); + switch(hw->sOpts.spd_dpx) { + case SPD_DPX_100_HALF: + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); + break; + case SPD_DPX_100_FULL: + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 100M bps full duplex\n"); + break; + case SPD_DPX_10_HALF: + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 10M bps half duplex\n"); + break; + case SPD_DPX_10_FULL: + VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 10M bps full duplex\n"); + break; + default: + break; + } + } + } +} + +int velocity_set_media_mode(struct velocity_hw *hw, SPD_DPX_OPT spd_dpx) +{ + U16 wANARMask; + U16 wOrigANAR, wOrigG1000CR; + U16 wANAR=0, wG1000CR=0; + U32 status=VELOCITY_LINK_UNCHANGE; + + + velocity_mii_read(hw, MII_REG_ANAR, &wOrigANAR); + velocity_mii_read(hw, MII_REG_G1000CR, &wOrigG1000CR); + wANARMask = wOrigANAR; + wANARMask &= ~(ANLPAR_ASMDIR|ANLPAR_PAUSE|ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); + wOrigANAR &= (ANLPAR_ASMDIR|ANLPAR_PAUSE|ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); + wOrigG1000CR &= (G1000CR_1000FD|G1000CR_1000); + + + + /* Set mii link status */ + wANAR = set_mii_flow_control(hw); + + if (PHYID_GET_PHY_ID(hw->dwPHYId) == PHYID_CICADA_CS8201) { + MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, hw); + } + + /* if connection type is AUTO */ + if (spd_dpx == SPD_DPX_AUTO) { + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Velocity is AUTO mode\n"); + /* auto */ + wANAR |= (ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); + wG1000CR |= (G1000CR_1000FD|G1000CR_1000); + /* clear force MAC mode bit */ + BYTE_REG_BITS_OFF(hw, CHIPGCR_FCMODE, MAC_REG_CHIPGCR); + /* set duplex mode of MAC according to duplex mode of MII */ + MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, hw); + if(wOrigANAR != wANAR || wOrigG1000CR != wG1000CR) { + wANAR |= wANARMask; + velocity_mii_write(hw, MII_REG_ANAR, wANAR); + MII_REG_BITS_ON(G1000CR_1000FD|G1000CR_1000, MII_REG_G1000CR, hw); + /* enable AUTO-NEGO mode */ + MII_REG_BITS_ON((BMCR_AUTO | BMCR_REAUTO), MII_REG_BMCR, hw); + + /* Link changed */ + status = VELOCITY_LINK_CHANGE; + } + } + else { + U8 byCHIPGCR; + + /* 1. if it's 3119, disable frame bursting in halfduplex mode and + // enable it in fullduplex mode + // 2. set correct MII/GMII and half/full duplex mode in CHIPGCR + // 3. only enable CD heart beat counter in 10HD mode + + // set force MAC mode bit */ + BYTE_REG_BITS_ON(hw, CHIPGCR_FCMODE, MAC_REG_CHIPGCR); + + + byCHIPGCR = CSR_READ_1(hw, MAC_REG_CHIPGCR); + byCHIPGCR &= ~CHIPGCR_FCGMII; + + if( spd_dpx == SPD_DPX_100_FULL || spd_dpx == SPD_DPX_10_FULL ){ + byCHIPGCR |= CHIPGCR_FCFDX; + CSR_WRITE_1(hw, byCHIPGCR, MAC_REG_CHIPGCR); + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Set Velocity to forced full mode\n"); + if (hw->byRevId < REV_ID_VT3216_A0) + BYTE_REG_BITS_OFF(hw, TCR_TB2BDIS, MAC_REG_TCR); + } + else { + byCHIPGCR &= ~CHIPGCR_FCFDX; + VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Set Velocity to forced half mode\n"); + CSR_WRITE_1(hw, byCHIPGCR, MAC_REG_CHIPGCR); + if (hw->byRevId < REV_ID_VT3216_A0) + BYTE_REG_BITS_ON(hw, TCR_TB2BDIS, MAC_REG_TCR); + } + + /* No force 1000Mbps */ + wG1000CR=0; + + switch(spd_dpx) + { + case SPD_DPX_100_HALF: + wANAR |= ANLPAR_TX; + break; + case SPD_DPX_100_FULL: + wANAR |= ANLPAR_TXFD; + break; + case SPD_DPX_10_HALF: + wANAR |= ANLPAR_10; + break; + case SPD_DPX_10_FULL: + wANAR |= ANLPAR_10FD; + break; + default: + break; + } + + if(wANAR != wOrigANAR || wG1000CR != wOrigG1000CR) + { + wANAR |= wANARMask; + velocity_mii_write(hw, MII_REG_ANAR, wANAR); + MII_REG_BITS_OFF(G1000CR_1000FD|G1000CR_1000, MII_REG_G1000CR, hw); + /* enable AUTO-NEGO mode */ + MII_REG_BITS_ON((BMCR_AUTO | BMCR_REAUTO), MII_REG_BMCR, hw); + + /* Link changed */ + status = VELOCITY_LINK_CHANGE; + } + } + + return status; +} + + +void velocity_adaptive_init(struct velocity_hw *hw) +{ + hw->IntMask = INT_MASK_DEF; + + /*------------------------------------------------------------ + // [1.18] Adaptive Interrupt + // Set Tx Interrupt Suppression Threshold: 31 (0x001F) */ + CSR_WRITE_1(hw, CAMCR_PS0, MAC_REG_CAMCR); + CSR_WRITE_2(hw, 0x001F, MAC_REG_ISR_CTL); + /*pInfo->IntMask &= ~(ISR_PTXI | ISR_PTX0I | ISR_PTX1I | ISR_PTX2I | ISR_PTX3I);*/ + + /* Set Rx Interrupt Suppression Threshold: 31 (0x001F) */ + CSR_WRITE_1(hw, CAMCR_PS1, MAC_REG_CAMCR); + CSR_WRITE_2(hw, 0x001F, MAC_REG_ISR_CTL); + /*pInfo->IntMask &= ~ISR_PRXI;*/ + + /* Select page to interrupt hold timer */ + CSR_WRITE_1(hw, 0x00, MAC_REG_CAMCR); + + /* Modify IMR */ + hw->IntMask &= ~(ISR_PTXI | ISR_PTX0I | ISR_PTX1I | ISR_PTX2I | ISR_PTX3I | ISR_PRXI); + + /* Enable Memory-Read-Line, both VT3119 and VT3216 + // ==> DCFG1_XMRL = 0 */ + BYTE_REG_BITS_OFF(hw, DCFG1_XMRL, MAC_REG_DCFG1); + +} + +void velocity_init_register_reset( struct velocity_hw *hw) +{ + + /* reset RX to prevent RX pointer not on the 4X location */ + velocity_rx_reset(hw); + mac_rx_queue_run(hw); + mac_rx_queue_wake(hw); + + CSR_WRITE_4(hw, CR0_STOP, MAC_REG_CR0_CLR); + CSR_WRITE_4(hw, (CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT), MAC_REG_CR0_SET); + + + if (velocity_set_media_mode(hw,hw->sOpts.spd_dpx)!=VELOCITY_LINK_CHANGE) { + hw->mii_status = check_connectiontype(hw); + velocity_print_link_status(hw); + } + + enable_flow_control_ability(hw); + + mac_clear_isr(hw); +} + +void velocity_init_register_cold( struct velocity_hw *hw) +{ + int i; + U32 mii_status; + mac_set_rx_thresh(hw, hw->sOpts.rx_thresh); + mac_set_dma_length(hw, hw->sOpts.DMA_length); + + CSR_WRITE_1(hw, (WOLCFG_SAM | WOLCFG_SAB), MAC_REG_WOLCFG_SET); + + /* back off algorithm use original IEEE standard */ + BYTE_REG_BITS_SET(hw, CFGB_OFSET, + (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), + MAC_REG_CFGB); + + + /* enable MII auto-polling */ + EnableMiiAutoPoll(hw); + + velocity_adaptive_init(hw); + + CSR_WRITE_4(hw, hw->rd_pool_dma, MAC_REG_RDBASE_LO); + CSR_WRITE_2(hw, hw->sOpts.nRxDescs-1, MAC_REG_RDCSIZE); + mac_rx_queue_run(hw); + mac_rx_queue_wake(hw); + + CSR_WRITE_2(hw, hw->sOpts.nTxDescs-1, MAC_REG_TDCSIZE); + + for (i=0;inTxQueues;i++) { + CSR_WRITE_4(hw, hw->td_pool_dma[i], (MAC_REG_TDBASE_LO+(i*4)) ); + mac_tx_queue_run(hw,i); + } + + velocity_init_cam_filter(hw); + + init_flow_control_register(hw); + + CSR_WRITE_4(hw, CR0_STOP, MAC_REG_CR0_CLR); + CSR_WRITE_4(hw, (CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT), MAC_REG_CR0_SET); + + mii_status = velocity_get_opt_media_mode(hw); + mac_clear_isr(hw); + + mii_init(hw, mii_status); + + if (velocity_set_media_mode(hw,hw->sOpts.spd_dpx) != VELOCITY_LINK_CHANGE) { + hw->mii_status = check_connectiontype(hw); + velocity_print_link_status(hw); + } + + enable_flow_control_ability(hw); + mac_hw_mibs_init(hw); + mac_write_int_mask(hw->IntMask, hw); + mac_clear_isr(hw); + +} diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_hw.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_hw.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_hw.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_hw.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software is copyrighted by and is the sole property of + * VIA Networking Technologies, Inc. This software may only be used + * in accordance with the corresponding license agreement. Any unauthorized + * use, duplication, transmission, distribution, or disclosure of this + * software is expressly forbidden. + * + * This software is provided by VIA Networking Technologies, Inc. "as is" + * and any express or implied warranties, including, but not limited to, the + * implied warranties of merchantability and fitness for a particular purpose + * are disclaimed. In no event shall VIA Networking Technologies, Inc. + * be liable for any direct, indirect, incidental, special, exemplary, or + * consequential damages. + * + * + * File: velocity_hw.h + * + * Purpose: Describe what this file is going to do. + * + * Author: Guard Kuo + * + * Date: May 2, 2005 + * + * + */ + +#ifndef __VELOCITY_HW_H +#define __VELOCITY_HW_H + +#include "osdep.h" +#include "velocity_desc.h" +#include "velocity_mac.h" + +#define BYTE_REG_BITS_ON(hw,x,p) do { CSR_WRITE_1(hw,(CSR_READ_1(hw,(p))|(x)),(p));} while (0) +#define WORD_REG_BITS_ON(hw,x,p) do { CSR_WRITE_2(hw,(CSR_READ_2(hw,(p))|(x)),(p));} while (0) +#define DWORD_REG_BITS_ON(hw,x,p) do { CSR_WRITE_4(hw,(CSR_READ_4(hw,(p))|(x)),(p));} while (0) + +#define BYTE_REG_BITS_IS_ON(hw,x,p) (CSR_READ_1(hw,(p)) & (x)) +#define WORD_REG_BITS_IS_ON(hw,x,p) (CSR_READ_2(hw,(p)) & (x)) +#define DWORD_REG_BITS_IS_ON(hw,x,p) (CSR_READ_4(hw,(p)) & (x)) + +#define BYTE_REG_BITS_OFF(hw,x,p) do { CSR_WRITE_1(hw,(CSR_READ_1(hw,(p)) & (~(x))),(p));} while (0) +#define WORD_REG_BITS_OFF(hw,x,p) do { CSR_WRITE_2(hw,(CSR_READ_2(hw,(p)) & (~(x))),(p));} while (0) +#define DWORD_REG_BITS_OFF(hw,x,p) do { CSR_WRITE_4(hw,(CSR_READ_4(hw,(p)) & (~(x))),(p));} while (0) + +#define BYTE_REG_BITS_SET(hw,x,m,p) do { CSR_WRITE_1(hw,(CSR_READ_1(hw,(p)) & (~(m))) |(x),(p));} while (0) +#define WORD_REG_BITS_SET(hw,x,m,p) do { CSR_WRITE_2(hw,(CSR_READ_2(hw,(p)) & (~(m))) |(x),(p));} while (0) +#define DWORD_REG_BITS_SET(hw,x,m,p) do { CSR_WRITE_4(hw,(CSR_READ_4(hw,(p)) & (~(m)))|(x),(p));} while (0) + +#define VELOCITY_WOL_MAGIC 0x00000000UL +#define VELOCITY_WOL_PHY 0x00000001UL +#define VELOCITY_WOL_ARP 0x00000002UL +#define VELOCITY_WOL_UCAST 0x00000004UL +#define VELOCITY_WOL_BCAST 0x00000010UL +#define VELOCITY_WOL_MCAST 0x00000020UL +#define VELOCITY_WOL_MAGIC_SEC 0x00000040UL + +/* flags for options */ +#define VELOCITY_FLAGS_TAGGING 0x00000001UL +#define VELOCITY_FLAGS_TX_CSUM 0x00000002UL +#define VELOCITY_FLAGS_RX_CSUM 0x00000004UL +#define VELOCITY_FLAGS_IP_ALIGN 0x00000008UL +#define VELOCITY_FLAGS_VAL_PKT_LEN 0x00000010UL +#define VELOCITY_FLAGS_MRDPL 0x00000020UL +#define VELOCITY_FLAGS_FLOW_CTRL 0x01000000UL + + +/* flags for MII status */ +#define VELOCITY_LINK_FAIL 0x00000001UL +#define VELOCITY_SPEED_10 0x00000002UL +#define VELOCITY_SPEED_100 0x00000004UL +#define VELOCITY_SPEED_1000 0x00000008UL +#define VELOCITY_DUPLEX_FULL 0x00000010UL +#define VELOCITY_AUTONEG_ENABLE 0x00000020UL +#define VELOCITY_FORCED_BY_EEPROM 0x00000040UL +#define VELOCITY_LINK_CHANGE 0x00000001UL /* for velocity_set_media_duplex */ +#define VELOCITY_LINK_UNCHANGE 0x00000002UL /* for velocity_set_media_duplex */ + +typedef enum __velocity_flow_cntl_type { + FLOW_CNTL_DEFAULT = 1, /* 1 */ + FLOW_CNTL_TX, /* 2 */ + FLOW_CNTL_RX, /* 3 */ + FLOW_CNTL_TX_RX, /* 4 */ + FLOW_CNTL_DISABLE /* 5 */ +} +VELOCITY_FLOW_CNTL_TYPE, *PVELOCITY_FLOW_CNTL_TYPE; + + +typedef enum __velocity_msg_level { + MSG_LEVEL_ERR=0, /* Errors that will cause abnormal operation. */ + MSG_LEVEL_NOTICE=1, /* Some errors need users to be notified. */ + MSG_LEVEL_INFO=2, /* Normal message. */ + MSG_LEVEL_VERBOSE=3, /* Will report all trival errors. */ + MSG_LEVEL_DEBUG=4 /* Only for debug purpose. */ +} VELOCITY_MSG_LEVEL, *PVELOCITY_MSG_LEVEL; + + +typedef enum _speed_opt { + SPD_DPX_AUTO = 0, + SPD_DPX_100_HALF = 1, + SPD_DPX_100_FULL = 2, + SPD_DPX_10_HALF = 3, + SPD_DPX_10_FULL = 4 +} SPD_DPX_OPT, *PSPD_DPX_OPT; + + +typedef struct __velocity_opt { + int nRxDescs; /* Number of RX descriptors */ + int nTxDescs; /* Number of TX descriptors */ + SPD_DPX_OPT spd_dpx; /* Media link mode */ + int vid; /* vlan id */ + int DMA_length; /* DMA length */ + int rx_thresh; /* RX_THRESH */ + int flow_cntl; + int wol_opts; /* Wake on lan options */ + int td_int_count; + int int_works; + int rx_bandwidth_hi; + int rx_bandwidth_lo; + int rx_bandwidth_en; + U32 flags; +} OPTIONS, *POPTIONS; + +struct velocity_hw { + long memaddr; + long ioaddr; + U32 io_size; + PU8 hw_addr; + + U32 dwPHYId; + U8 byRevId; + U16 SubSystemID; + U16 SubVendorID; + U32 mii_status; + +#define AVAIL_TD(hw,q) ((hw)->sOpts.nTxDescs-((hw)->iTDUsed[(q)])) + int nTxQueues; + volatile int iTDUsed[TX_QUEUE_NO]; + int aiCurrTDIdx[TX_QUEUE_NO]; + int aiTailTDIdx[TX_QUEUE_NO]; + PTX_DESC apTDRings[TX_QUEUE_NO]; + int iCurrRDIdx; +#define GET_RD_BY_IDX(hw, idx) (hw->aRDRing[idx]) + PRX_DESC aRDRing; + + dma_addr_t pool_dma; + dma_addr_t rd_pool_dma; + dma_addr_t td_pool_dma[TX_QUEUE_NO]; + + dma_addr_t tx_bufs_dma; + + + OPTIONS sOpts; + U32 IntMask; + U32 flags; + + unsigned int rx_buf_sz; + int multicast_limit; + + U32 adwHWMIBCounters[MAX_HW_MIB_COUNTER]; + + U8 abyVCAMMask[(VCAM_SIZE/8)]; + U8 abyMCAMMask[(MCAM_SIZE/8)]; + + int msglevel; /* debug message level */ + + /* operation-system-specific structure */ + struct em_osdep *back; +}; + + +#define velocity_set_all_multi(hw) \ + CSR_WRITE_4(hw, 0xffffffffL, MAC_REG_MAR); \ + CSR_WRITE_4(hw, 0xffffffffL, MAC_REG_MAR+4) + +U32 check_connectiontype(struct velocity_hw *hw); +U32 mii_check_media_mode(struct velocity_hw *hw); +U16 set_mii_flow_control(struct velocity_hw *hw); +void mii_init(struct velocity_hw *hw, U32 mii_status); +void init_flow_control_register(struct velocity_hw *hw); +void enable_flow_control_ability(struct velocity_hw *hw); +BOOL velocity_soft_reset(struct velocity_hw* hw); +void velocity_shutdown(struct velocity_hw *hw); +U32 velocity_get_opt_media_mode(struct velocity_hw *hw); +BOOL velocity_mii_read(struct velocity_hw* hw, U8 byIdx, PU16 pdata); +BOOL velocity_mii_write(struct velocity_hw* hw, BYTE byMiiAddr, WORD wData); +void mac_wol_reset(struct velocity_hw *hw); +void mac_get_cam(struct velocity_hw *hw, int idx, PU8 addr, VELOCITY_CAM_TYPE cam_type); +void mac_set_cam(struct velocity_hw *hw, int idx, PU8 addr, VELOCITY_CAM_TYPE cam_type); +void mac_set_cam_mask(struct velocity_hw *hw, PU8 pbyMask, VELOCITY_CAM_TYPE cam_type); +void mac_get_cam_mask(struct velocity_hw *hw, PU8 pbyMask, VELOCITY_CAM_TYPE cam_type); +void SafeDisableMiiAutoPoll (struct velocity_hw *hw); +void EnableMiiAutoPoll(struct velocity_hw* hw); +void velocity_init_cam_filter(struct velocity_hw *hw); +void velocity_update_hw_mibs(struct velocity_hw *hw); +void velocity_rx_reset(struct velocity_hw *hw); +void velocity_print_link_status(struct velocity_hw *hw); +int velocity_set_media_mode(struct velocity_hw *hw, SPD_DPX_OPT spd_dpx); + + +void velocity_init_register_cold(struct velocity_hw *hw); +void velocity_init_register_reset(struct velocity_hw *hw); + + +#endif /* __VELOCITY_HW_H */ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_mac.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_mac.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_mac.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_mac.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,756 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_mac.h + * + * Purpose: Header file for MAC registers and macros. + * + * Author: Chuang Liang-Shing, AJ Jiang, Ryan Fu + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_MAC_H__ +#define __VELOCITY_MAC_H__ + +#include "osdep.h" + +/*--------------------- Export Definitions -------------------------*/ +#define MCAM_SIZE 64 +#define VCAM_SIZE 64 + +#define MAX_HW_MIB_COUNTER 32 +#define VELOCITY_MIN_MTU (1514-14) +#define VELOCITY_MAX_MTU (9000) + +#define VELOCITY_DMA_ALIGN 64 + + +/* + Registers in the MAC +*/ +#define MAC_REG_PAR 0x00 /* physical address */ +#define MAC_REG_RCR 0x06 +#define MAC_REG_TCR 0x07 +#define MAC_REG_CR0_SET 0x08 +#define MAC_REG_CR1_SET 0x09 +#define MAC_REG_CR2_SET 0x0A +#define MAC_REG_CR3_SET 0x0B +#define MAC_REG_CR0_CLR 0x0C +#define MAC_REG_CR1_CLR 0x0D +#define MAC_REG_CR2_CLR 0x0E +#define MAC_REG_CR3_CLR 0x0F +#define MAC_REG_MAR 0x10 +#define MAC_REG_CAM 0x10 +#define MAC_REG_DEC_BASE_HI 0x18 +#define MAC_REG_DBF_BASE_HI 0x1C +#define MAC_REG_ISR_CTL 0x20 +#define MAC_REG_ISR_HOTMR 0x20 +#define MAC_REG_ISR_TSUPTHR 0x20 +#define MAC_REG_ISR_RSUPTHR 0x20 +#define MAC_REG_ISR_CTL1 0x21 +#define MAC_REG_TXE_SR 0x22 +#define MAC_REG_RXE_SR 0x23 +#define MAC_REG_ISR 0x24 +#define MAC_REG_ISR0 0x24 +#define MAC_REG_ISR1 0x25 +#define MAC_REG_ISR2 0x26 +#define MAC_REG_ISR3 0x27 +#define MAC_REG_IMR 0x28 +#define MAC_REG_IMR0 0x28 +#define MAC_REG_IMR1 0x29 +#define MAC_REG_IMR2 0x2A +#define MAC_REG_IMR3 0x2B +#define MAC_REG_TDCSR_SET 0x30 +#define MAC_REG_RDCSR_SET 0x32 +#define MAC_REG_TDCSR_CLR 0x34 +#define MAC_REG_RDCSR_CLR 0x36 +#define MAC_REG_RDBASE_LO 0x38 +#define MAC_REG_RDINDX 0x3C +#define MAC_REG_TQETMR 0x3E /* VT3216 only */ +#define MAC_REG_RQETMR 0x3F /* VT3216 only */ +#define MAC_REG_TDBASE_LO 0x40 +#define MAC_REG_RDCSIZE 0x50 +#define MAC_REG_TDCSIZE 0x52 +#define MAC_REG_TDINDX 0x54 +#define MAC_REG_TDIDX0 0x54 +#define MAC_REG_TDIDX1 0x56 +#define MAC_REG_TDIDX2 0x58 +#define MAC_REG_TDIDX3 0x5A +#define MAC_REG_PAUSE_TIMER 0x5C +#define MAC_REG_RBRDU 0x5E +#define MAC_REG_FIFO_TEST0 0x60 +#define MAC_REG_FIFO_TEST1 0x64 +#define MAC_REG_CAMADDR 0x68 +#define MAC_REG_CAMCR 0x69 +#define MAC_REG_GFTEST 0x6A +#define MAC_REG_FTSTCMD 0x6B +#define MAC_REG_MIICFG 0x6C +#define MAC_REG_MIISR 0x6D +#define MAC_REG_PHYSR0 0x6E +#define MAC_REG_PHYSR1 0x6F +#define MAC_REG_MIICR 0x70 +#define MAC_REG_MIIADR 0x71 +#define MAC_REG_MIIDATA 0x72 +#define MAC_REG_SOFT_TIMER0 0x74 +#define MAC_REG_SOFT_TIMER1 0x76 +#define MAC_REG_CFGA 0x78 +#define MAC_REG_CFGB 0x79 +#define MAC_REG_CFGC 0x7A +#define MAC_REG_CFGD 0x7B +#define MAC_REG_DCFG0 0x7C +#define MAC_REG_DCFG1 0x7D +#define MAC_REG_MCFG0 0x7E +#define MAC_REG_MCFG1 0x7F + +#define MAC_REG_TBIST 0x80 +#define MAC_REG_RBIST 0x81 +#define MAC_REG_PMCC 0x82 +#define MAC_REG_STICKHW 0x83 +#define MAC_REG_MIBCR 0x84 +#define MAC_REG_EERSV 0x85 +#define MAC_REG_REVID 0x86 +#define MAC_REG_MIBREAD 0x88 +#define MAC_REG_MIBDATA 0x88 +#define MAC_REG_BPMA 0x8C +#define MAC_REG_EEWR_DATA 0x8C +#define MAC_REG_BPMD_WR 0x8F +#define MAC_REG_BPCMD 0x90 +#define MAC_REG_BPMD_RD 0x91 +#define MAC_REG_EECHKSUM 0x92 +#define MAC_REG_EECSR 0x93 +#define MAC_REG_EERD_DATA 0x94 +#define MAC_REG_EADDR 0x96 +#define MAC_REG_EMBCMD 0x97 +#define MAC_REG_JMPSR0 0x98 +#define MAC_REG_JMPSR1 0x99 +#define MAC_REG_JMPSR2 0x9A +#define MAC_REG_JMPSR3 0x9B +#define MAC_REG_CHIPGSR 0x9C +#define MAC_REG_TESTCFG 0x9D +#define MAC_REG_DEBUG 0x9E +#define MAC_REG_CHIPGCR 0x9F +#define MAC_REG_WOLCR0_SET 0xA0 +#define MAC_REG_WOLCR1_SET 0xA1 +#define MAC_REG_PWCFG_SET 0xA2 +#define MAC_REG_WOLCFG_SET 0xA3 +#define MAC_REG_WOLCR0_CLR 0xA4 +#define MAC_REG_WOLCR1_CLR 0xA5 +#define MAC_REG_PWCFG_CLR 0xA6 +#define MAC_REG_WOLCFG_CLR 0xA7 +#define MAC_REG_WOLSR0_SET 0xA8 +#define MAC_REG_WOLSR1_SET 0xA9 +#define MAC_REG_WOLSR0_CLR 0xAC +#define MAC_REG_WOLSR1_CLR 0xAD +#define MAC_REG_PATRN_CRC0 0xB0 +#define MAC_REG_PATRN_CRC1 0xB2 +#define MAC_REG_PATRN_CRC2 0xB4 +#define MAC_REG_PATRN_CRC3 0xB6 +#define MAC_REG_PATRN_CRC4 0xB8 +#define MAC_REG_PATRN_CRC5 0xBA +#define MAC_REG_PATRN_CRC6 0xBC +#define MAC_REG_PATRN_CRC7 0xBE +#define MAC_REG_BYTEMSK0_0 0xC0 +#define MAC_REG_BYTEMSK0_1 0xC4 +#define MAC_REG_BYTEMSK0_2 0xC8 +#define MAC_REG_BYTEMSK0_3 0xCC +#define MAC_REG_BYTEMSK1_0 0xD0 +#define MAC_REG_BYTEMSK1_1 0xD4 +#define MAC_REG_BYTEMSK1_2 0xD8 +#define MAC_REG_BYTEMSK1_3 0xDC +#define MAC_REG_BYTEMSK2_0 0xE0 +#define MAC_REG_BYTEMSK2_1 0xE4 +#define MAC_REG_BYTEMSK2_2 0xE8 +#define MAC_REG_BYTEMSK2_3 0xEC +#define MAC_REG_BYTEMSK3_0 0xF0 +#define MAC_REG_BYTEMSK3_1 0xF4 +#define MAC_REG_BYTEMSK3_2 0xF8 +#define MAC_REG_BYTEMSK3_3 0xFC + + +/* + Bits in the RCR register +*/ +#define RCR_AS 0x80 +#define RCR_AP 0x40 +#define RCR_AL 0x20 +#define RCR_PROM 0x10 +#define RCR_AB 0x08 +#define RCR_AM 0x04 +#define RCR_AR 0x02 +#define RCR_SEP 0x01 + +/* + Bits in the TCR register +*/ +#define TCR_TB2BDIS 0x80 +#define TCR_COLTMC1 0x08 +#define TCR_COLTMC0 0x04 +#define TCR_LB1 0x02 /* loopback[1] */ +#define TCR_LB0 0x01 /* loopback[0] */ + +/* + Bits in the CR0 register +*/ +#define CR0_TXON 0x00000008UL +#define CR0_RXON 0x00000004UL +#define CR0_STOP 0x00000002UL /* stop MAC, default = 1 */ +#define CR0_STRT 0x00000001UL /* start MAC */ +#define CR0_SFRST 0x00008000UL /* software reset */ +#define CR0_TM1EN 0x00004000UL +#define CR0_TM0EN 0x00002000UL +#define CR0_DPOLL 0x00000800UL /* disable rx/tx auto polling */ +#define CR0_DISAU 0x00000100UL +#define CR0_XONEN 0x00800000UL +#define CR0_FDXTFCEN 0x00400000UL /* full-duplex TX flow control enable */ +#define CR0_FDXRFCEN 0x00200000UL /* full-duplex RX flow control enable */ +#define CR0_HDXFCEN 0x00100000UL /* half-duplex flow control enable */ +#define CR0_XHITH1 0x00080000UL /* TX XON high threshold 1 */ +#define CR0_XHITH0 0x00040000UL /* TX XON high threshold 0 */ +#define CR0_XLTH1 0x00020000UL /* TX pause frame low threshold 1 */ +#define CR0_XLTH0 0x00010000UL /* TX pause frame low threshold 0 */ +#define CR0_GSPRST 0x80000000UL +#define CR0_FORSRST 0x40000000UL +#define CR0_FPHYRST 0x20000000UL +#define CR0_DIAG 0x10000000UL +#define CR0_INTPCTL 0x04000000UL +#define CR0_GINTMSK1 0x02000000UL +#define CR0_GINTMSK0 0x01000000UL + +/* + Bits in the CR1 register +*/ +#define CR1_SFRST 0x80 /* software reset */ +#define CR1_TM1EN 0x40 +#define CR1_TM0EN 0x20 +#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */ +#define CR1_DISAU 0x01 + +/* + Bits in the CR2 register +*/ +#define CR2_XONEN 0x80 +#define CR2_FDXTFCEN 0x40 /* full-duplex TX flow control enable */ +#define CR2_FDXRFCEN 0x20 /* full-duplex RX flow control enable */ +#define CR2_HDXFCEN 0x10 /* half-duplex flow control enable */ +#define CR2_XHITH1 0x08 /* TX XON high threshold 1 */ +#define CR2_XHITH0 0x04 /* TX XON high threshold 0 */ +#define CR2_XLTH1 0x02 /* TX pause frame low threshold 1 */ +#define CR2_XLTH0 0x01 /* TX pause frame low threshold 0 */ + +/* + Bits in the CR3 register +*/ +#define CR3_GSPRST 0x80 +#define CR3_FORSRST 0x40 +#define CR3_FPHYRST 0x20 +#define CR3_DIAG 0x10 +#define CR3_INTPCTL 0x04 +#define CR3_GINTMSK1 0x02 +#define CR3_GINTMSK0 0x01 + +#define ISRCTL_UDPINT 0x8000 +#define ISRCTL_TSUPDIS 0x4000 +#define ISRCTL_RSUPDIS 0x2000 +#define ISRCTL_PMSK1 0x1000 +#define ISRCTL_PMSK0 0x0800 +#define ISRCTL_INTPD 0x0400 +#define ISRCTL_HCRLD 0x0200 +#define ISRCTL_SCRLD 0x0100 + +/* + Bits in the ISR_CTL1 register +*/ +#define ISRCTL1_UDPINT 0x80 +#define ISRCTL1_TSUPDIS 0x40 +#define ISRCTL1_RSUPDIS 0x20 +#define ISRCTL1_PMSK1 0x10 +#define ISRCTL1_PMSK0 0x08 +#define ISRCTL1_INTPD 0x04 +#define ISRCTL1_HCRLD 0x02 +#define ISRCTL1_SCRLD 0x01 + +/* + Bits in the TXE_SR register +*/ +#define TXESR_TFDBS 0x08 +#define TXESR_TDWBS 0x04 +#define TXESR_TDRBS 0x02 +#define TXESR_TDSTR 0x01 + +/* + Bits in the RXE_SR register +*/ +#define RXESR_RFDBS 0x08 +#define RXESR_RDWBS 0x04 +#define RXESR_RDRBS 0x02 +#define RXESR_RDSTR 0x01 + +/* + Bits in the ISR register +*/ +#define ISR_ISR3 0x80000000UL +#define ISR_ISR2 0x40000000UL +#define ISR_ISR1 0x20000000UL +#define ISR_ISR0 0x10000000UL +#define ISR_TXSTLI 0x02000000UL +#define ISR_RXSTLI 0x01000000UL +#define ISR_HFLD 0x00800000UL +#define ISR_UDPI 0x00400000UL +#define ISR_MIBFI 0x00200000UL +#define ISR_SHDNI 0x00100000UL +#define ISR_PHYI 0x00080000UL +#define ISR_PWEI 0x00040000UL +#define ISR_TMR1I 0x00020000UL +#define ISR_TMR0I 0x00010000UL +#define ISR_SRCI 0x00008000UL +#define ISR_LSTPEI 0x00004000UL +#define ISR_LSTEI 0x00002000UL +#define ISR_OVFI 0x00001000UL +#define ISR_FLONI 0x00000800UL +#define ISR_RACEI 0x00000400UL +#define ISR_TXWB1I 0x00000200UL +#define ISR_TXWB0I 0x00000100UL +#define ISR_PTX3I 0x00000080UL +#define ISR_PTX2I 0x00000040UL +#define ISR_PTX1I 0x00000020UL +#define ISR_PTX0I 0x00000010UL +#define ISR_PTXI 0x00000008UL +#define ISR_PRXI 0x00000004UL +#define ISR_PPTXI 0x00000002UL +#define ISR_PPRXI 0x00000001UL + +#define INT_MASK_DEF 0x037BFFFFUL + +/* + Bits in the TDCSR0/1, RDCSR0 register +*/ +#define TRDCSR_DEAD 0x0008 +#define TRDCSR_WAK 0x0004 +#define TRDCSR_ACT 0x0002 +#define TRDCSR_RUN 0x0001 + +/* + Bits in the CAMADDR register +*/ +#define CAMADDR_CAMEN 0x80 +#define CAMADDR_VCAMSL 0x40 + +/* + Bits in the CAMCR register +*/ +#define CAMCR_PS1 0x80 +#define CAMCR_PS0 0x40 +#define CAMCR_AITRPKT 0x20 +#define CAMCR_AITR16 0x10 +#define CAMCR_CAMRD 0x08 +#define CAMCR_CAMWR 0x04 +#define CAMCR_PS_CAM_MASK 0x40 +#define CAMCR_PS_CAM_DATA 0x80 +#define CAMCR_PS_MAR 0x00 + +/* + Bits in the MIICFG register +*/ +#define MIICFG_MPO1 0x80 +#define MIICFG_MPO0 0x40 +#define MIICFG_MFDC 0x20 + +/* + Bits in the MIISR register +*/ +#define MIISR_MIDLE 0x80 + +/* + Bits in the PHYSR0 register +*/ +#define PHYSR0_PHYRST 0x80 +#define PHYSR0_LINKGD 0x40 +#define PHYSR0_FDPX 0x10 +#define PHYSR0_SPDG 0x08 +#define PHYSR0_SPD10 0x04 +#define PHYSR0_RXFLC 0x02 +#define PHYSR0_TXFLC 0x01 + +/* + Bits in the PHYSR1 register +*/ +#define PHYSR1_PHYTBI 0x01 + +/* + Bits in the MIICR register +*/ +#define MIICR_MAUTO 0x80 +#define MIICR_RCMD 0x40 +#define MIICR_WCMD 0x20 +#define MIICR_MDPM 0x10 +#define MIICR_MOUT 0x08 +#define MIICR_MDO 0x04 +#define MIICR_MDI 0x02 +#define MIICR_MDC 0x01 + +/* + Bits in the MIIADR register +*/ +#define MIIADR_SWMPL 0x80 + +/* + Bits in the CFGA register +*/ +#define CFGA_PMHCTG 0x08 +#define CFGA_GPIO1PD 0x04 +#define CFGA_ABSHDN 0x02 +#define CFGA_PACPI 0x01 + +/* + Bits in the CFGB register +*/ +#define CFGB_GTCKOPT 0x80 +#define CFGB_MIIOPT 0x40 +#define CFGB_CRSEOPT 0x20 +#define CFGB_OFSET 0x10 +#define CFGB_CRANDOM 0x08 +#define CFGB_CAP 0x04 +#define CFGB_MBA 0x02 +#define CFGB_BAKOPT 0x01 + +/* + Bits in the CFGC register +*/ +#define CFGC_EELOAD 0x80 +#define CFGC_BROPT 0x40 +#define CFGC_DLYEN 0x20 +#define CFGC_DTSEL 0x10 +#define CFGC_BTSEL 0x08 +#define CFGC_BPS2 0x04 /* bootrom select[2] */ +#define CFGC_BPS1 0x02 /* bootrom select[1] */ +#define CFGC_BPS0 0x01 /* bootrom select[0] */ + +/* + Bits in the CFGD register +*/ +#define CFGD_IODIS 0x80 +#define CFGD_MSLVDACEN 0x40 +#define CFGD_CFGDACEN 0x20 +#define CFGD_PCI64EN 0x10 +#define CFGD_HTMRL4 0x08 + +/* + Bits in the DCFG1 register (0x7D) +*/ +#define DCFG1_XMWI 0x80 +#define DCFG1_XMRM 0x40 +#define DCFG1_XMRL 0x20 +#define DCFG1_PERDIS 0x10 +#define DCFG1_MRDPL 0x08 /* Read-Multiple, VT3216 only */ +#define DCFG1_MRWAIT 0x04 +#define DCFG1_MWWAIT 0x02 +#define DCFG1_LATMEN 0x01 + +/* + Bits in the MCFG0 register +*/ +#define MCFG_RXARB 0x0080 +#define MCFG_RFT1 0x0020 +#define MCFG_RFT0 0x0010 +#define MCFG_LOWTHOPT 0x0008 +#define MCFG_PQEN 0x0004 +#define MCFG_RTGOPT 0x0002 +#define MCFG_VIDFR 0x0001 + +/* + Bits in the MCFG1 register +*/ +#define MCFG_TXARB 0x8000 +#define MCFG_TXQBK1 0x0800 +#define MCFG_TXQBK0 0x0400 +#define MCFG_TXQNOBK 0x0200 +#define MCFG_SNAPOPT 0x0100 + +/* + Bits in the PMCC register +*/ +#define PMCC_DSI 0x80 +#define PMCC_D2_DIS 0x40 +#define PMCC_D1_DIS 0x20 +#define PMCC_D3C_EN 0x10 +#define PMCC_D3H_EN 0x08 +#define PMCC_D2_EN 0x04 +#define PMCC_D1_EN 0x02 +#define PMCC_D0_EN 0x01 + +/* + Bits in STICKHW +*/ +#define STICKHW_SWPTAG 0x10 +#define STICKHW_WOLSR 0x08 +#define STICKHW_WOLEN 0x04 +#define STICKHW_DS1 0x02 /* R/W by software/cfg cycle */ +#define STICKHW_DS0 0x01 /* suspend well DS write port */ + +/* + Bits in the MIBCR register +*/ +#define MIBCR_MIBISTOK 0x80 +#define MIBCR_MIBISTGO 0x40 +#define MIBCR_MIBINC 0x20 +#define MIBCR_MIBHI 0x10 +#define MIBCR_MIBFRZ 0x08 +#define MIBCR_MIBFLSH 0x04 +#define MIBCR_MPTRINI 0x02 +#define MIBCR_MIBCLR 0x01 + +/* + Bits in the EERSV register +*/ +#define EERSV_BOOT_RPL 0x01 /* Boot method selection for VT6110 */ + +#define EERSV_BOOT_MASK 0x06 +#define EERSV_BOOT_INT19 0x00 +#define EERSV_BOOT_INT18 0x02 +#define EERSV_BOOT_LOCAL 0x04 +#define EERSV_BOOT_BEV 0x06 + +/* + Bits in BPCMD +*/ +#define BPCMD_BPDNE 0x80 +#define BPCMD_EBPWR 0x02 +#define BPCMD_EBPRD 0x01 + +/* + Bits in the EECSR register +*/ +#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_RELOAD 0x20 /* eeprom content reload */ +#define EECSR_DPM 0x10 /* eeprom direct programming */ +#define EECSR_ECS 0x08 /* eeprom CS pin */ +#define EECSR_ECK 0x04 /* eeprom CK pin */ +#define EECSR_EDI 0x02 /* eeprom DI pin */ +#define EECSR_EDO 0x01 /* eeprom DO pin */ + +/* + Bits in the EMBCMD register +*/ +#define EMBCMD_EDONE 0x80 +#define EMBCMD_EWDIS 0x08 +#define EMBCMD_EWEN 0x04 +#define EMBCMD_EWR 0x02 +#define EMBCMD_ERD 0x01 + +/* + Bits in TESTCFG register +*/ +#define TESTCFG_HBDIS 0x80 + +/* + Bits in CHIPGCR register +*/ +#define CHIPGCR_FCGMII 0x80 +#define CHIPGCR_FCFDX 0x40 +#define CHIPGCR_FCRESV 0x20 +#define CHIPGCR_FCMODE 0x10 +#define CHIPGCR_LPSOPT 0x08 +#define CHIPGCR_TM1US 0x04 +#define CHIPGCR_TM0US 0x02 +#define CHIPGCR_PHYINTEN 0x01 + +/* + Bits in WOLCR0 +*/ +#define WOLCR_MSWOLEN7 0x0080 /* enable pattern match filtering */ +#define WOLCR_MSWOLEN6 0x0040 +#define WOLCR_MSWOLEN5 0x0020 +#define WOLCR_MSWOLEN4 0x0010 +#define WOLCR_MSWOLEN3 0x0008 +#define WOLCR_MSWOLEN2 0x0004 +#define WOLCR_MSWOLEN1 0x0002 +#define WOLCR_MSWOLEN0 0x0001 +#define WOLCR_ARP_EN 0x0001 + +/* + Bits in WOLCR1 +*/ +#define WOLCR_LINKOFF_EN 0x0800 /* link off detected enable */ +#define WOLCR_LINKON_EN 0x0400 /* link on detected enable */ +#define WOLCR_MAGIC_EN 0x0200 /* magic packet filter enable */ +#define WOLCR_UNICAST_EN 0x0100 /* unicast filter enable */ + + +/* + Bits in PWCFG +*/ +#define PWCFG_PHYPWOPT 0x80 /* internal MII I/F timing */ +#define PWCFG_PCISTICK 0x40 /* PCI sticky R/W enable */ +#define PWCFG_WOLTYPE 0x20 /* pulse(1) or button (0) */ +#define PWCFG_LEGCY_WOL 0x10 +#define PWCFG_PMCSR_PME_SR 0x08 +#define PWCFG_PMCSR_PME_EN 0x04 /* control by PCISTICK */ +#define PWCFG_LEGACY_WOLSR 0x02 /* Legacy WOL_SR shadow */ +#define PWCFG_LEGACY_WOLEN 0x01 /* Legacy WOL_EN shadow */ + +/* + Bits in WOLCFG +*/ +#define WOLCFG_PMEOVR 0x80 /* for legacy use, force PMEEN always */ +#define WOLCFG_SAM 0x20 /* accept multicast case reset, default=0 */ +#define WOLCFG_SAB 0x10 /* accept broadcast case reset, default=0 */ +#define WOLCFG_SMIIACC 0x08 /* ?? */ +#define WOLCFG_SGENWH 0x02 +#define WOLCFG_PHYINTEN 0x01 /* 0:PHYINT trigger enable, 1:use internal MII */ + /* to report status change */ +/* + Bits in WOLSR1 +*/ +#define WOLSR_LINKOFF_INT 0x0800 +#define WOLSR_LINKON_INT 0x0400 +#define WOLSR_MAGIC_INT 0x0200 +#define WOLSR_UNICAST_INT 0x0100 + + +/* + revision id +*/ +#define REV_ID_VT3119_A0 0x00 +#define REV_ID_VT3119_A1 0x01 +#define REV_ID_VT3216_A0 0x10 +#define REV_ID_VT3284_A0 0x20 /* [1.18] */ + +/* wait time within loop */ +#define CB_DELAY_LOOP_WAIT 10 /* 10ms */ +#define CB_DELAY_MII_STABLE 660 + +/* max time out delay time */ +#define W_MAX_TIMEOUT 0x0FFFU + +typedef +enum __HW_MIBS { + HW_MIB_ifRxAllPkts=0, + HW_MIB_ifRxOkPkts, + HW_MIB_ifTxOkPkts, + HW_MIB_ifRxErrorPkts, + HW_MIB_ifRxRuntOkPkt, + HW_MIB_ifRxRuntErrPkt, + HW_MIB_ifRx64Pkts, + HW_MIB_ifTx64Pkts, + HW_MIB_ifRx65To127Pkts, + HW_MIB_ifTx65To127Pkts, + HW_MIB_ifRx128To255Pkts, + HW_MIB_ifTx128To255Pkts, + HW_MIB_ifRx256To511Pkts, + HW_MIB_ifTx256To511Pkts, + HW_MIB_ifRx512To1023Pkts, + HW_MIB_ifTx512To1023Pkts, + HW_MIB_ifRx1024To1518Pkts, + HW_MIB_ifTx1024To1518Pkts, + HW_MIB_ifTxEtherCollisions, + HW_MIB_ifRxPktCRCE, + HW_MIB_ifRxJumboPkts, + HW_MIB_ifTxJumboPkts, + HW_MIB_ifRxMacControlFrames, + HW_MIB_ifTxMacControlFrames, + HW_MIB_ifRxPktFAE, + HW_MIB_ifRxLongOkPkt, + HW_MIB_ifRxLongPktErrPkt, + HW_MIB_ifTXSQEErrors, + HW_MIB_ifRxNobuf, + HW_MIB_ifRxSymbolErrors, + HW_MIB_ifInRangeLengthErrors, + HW_MIB_ifLateCollisions, + HW_MIB_SIZE +} HW_MIBS, *PHW_MIBS; + +typedef enum _chip_type{ + CHIP_TYPE_VT6110=1, +} CHIP_TYPE, *PCHIP_TYPE; + +typedef struct __chip_info_tbl{ + CHIP_TYPE chip_id; + char* name; + int io_size; + int nTxQueue; + U32 flags; +} CHIP_INFO, *PCHIP_INFO; + +#define mac_hw_mibs_init(hw) {\ + BYTE_REG_BITS_ON(hw, MIBCR_MIBFRZ, MAC_REG_MIBCR);\ + BYTE_REG_BITS_ON(hw, MIBCR_MIBCLR, MAC_REG_MIBCR);\ + do {}\ + while (BYTE_REG_BITS_IS_ON(hw, MIBCR_MIBCLR, MAC_REG_MIBCR));\ + BYTE_REG_BITS_OFF(hw, MIBCR_MIBFRZ, MAC_REG_MIBCR);\ +} + +#define mac_read_isr(hw) CSR_READ_4(hw, MAC_REG_ISR) +#define mac_write_isr(hw, x) CSR_WRITE_4(hw, (x), MAC_REG_ISR) +#define mac_clear_isr(hw) CSR_WRITE_4(hw, 0xffffffffL, MAC_REG_ISR) + +#define mac_write_int_mask(mask, hw) CSR_WRITE_4(hw, (mask), MAC_REG_IMR); +#define mac_disable_int(hw) CSR_WRITE_4(hw, CR0_GINTMSK1, MAC_REG_CR0_CLR) +#define mac_enable_int(hw) CSR_WRITE_4(hw, CR0_GINTMSK1, MAC_REG_CR0_SET) + +#define mac_hw_mibs_read(hw, adwMIBs) {\ + int i;\ + BYTE_REG_BITS_ON(hw, MIBCR_MPTRINI, MAC_REG_MIBCR);\ + for (i=0;i0x1000) {\ + break;\ + }\ + }while (BYTE_REG_BITS_IS_ON(hw, EECSR_RELOAD,MAC_REG_EECSR));\ +} + +typedef enum { + VELOCITY_VLAN_ID_CAM=0, + VELOCITY_MULTICAST_CAM +} VELOCITY_CAM_TYPE, *PVELOCITY_CAM_TYPE; + + + +#endif /* __VELOCITY_MAC_H__ */ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_main.c linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_main.c --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_main.c 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_main.c 2006-10-23 10:58:14 +0200 @@ -0,0 +1,2081 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_main.c + * + * Purpose: Functions for Linux drver interfaces. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#undef __NO_VERSION__ + +#if !defined(__VELOCITY_H__) +#include "velocity.h" +#endif + +static int velocity_nics = 0; +static PVELOCITY_INFO pVelocity3_Infos = NULL; +static int msglevel = MSG_LEVEL_INFO; + +#ifdef VELOCITY_ETHTOOL_IOCTL_SUPPORT +static int velocity_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr); +#endif + +#ifdef SIOCGMIIPHY +static int velocity_mii_ioctl(struct net_device* dev, struct ifreq* ifr, int cmd); +#endif + + +/* + Define module options +*/ + +MODULE_AUTHOR("VIA Networking Technologies, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"); + +#define VELOCITY_PARAM(N,D) \ + static const int N[MAX_UINTS]=OPTION_DEFAULT;\ + MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\ + MODULE_PARM_DESC(N, D); + +#define RX_DESC_MIN 64 +#define RX_DESC_MAX 255 +#define RX_DESC_DEF 64 +VELOCITY_PARAM(RxDescriptors,"Number of receive descriptors"); + +#define TX_DESC_MIN 16 +#define TX_DESC_MAX 256 +#define TX_DESC_DEF 64 +VELOCITY_PARAM(TxDescriptors,"Number of transmit descriptors"); + +#define VLAN_ID_MIN 0 +#define VLAN_ID_MAX 4094 +#define VLAN_ID_DEF 0 +/* VID_setting[] is used for setting the VID of NIC. + 0: default VID. + 1-4094: other VIDs. +*/ +VELOCITY_PARAM(VID_setting,"802.1Q VLAN ID"); + +#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. +*/ +VELOCITY_PARAM(rx_thresh,"Receive fifo threshold"); + +#define DMA_LENGTH_MIN 0 +#define DMA_LENGTH_MAX 7 +#define DMA_LENGTH_DEF 6 // [1.18] Change DMA default to S&F + +/* 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) +*/ +VELOCITY_PARAM(DMA_length,"DMA length"); + +#define TAGGING_DEF 0 +/* enable_tagging[] is used for enabling 802.1Q VID tagging. + 0: disable VID seeting(default). + 1: enable VID setting. +*/ +VELOCITY_PARAM(enable_tagging,"Enable 802.1Q tagging"); + +#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) +*/ +VELOCITY_PARAM(IP_byte_align,"Enable IP header dword aligned"); + +#ifdef VELOCITY_TX_CSUM_SUPPORT +#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) +*/ +VELOCITY_PARAM(txcsum_offload,"Enable transmit packet checksum offload"); +#endif + +#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. + 4: enable RX/TX flow control. + 5: disable +*/ +VELOCITY_PARAM(flow_control,"Enable flow control ability"); + +#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. +*/ +VELOCITY_PARAM(speed_duplex,"Setting the speed and duplex mode"); + +#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 +*/ +VELOCITY_PARAM(ValPktLen,"Receiving or Drop invalid 802.3 frame"); + +#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) + 1: Wake up if link status is on/off. + 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. +*/ +VELOCITY_PARAM(wol_opts,"Wake On Lan options"); + +#define INT_WORKS_DEF 32 +#define INT_WORKS_MIN 10 +#define INT_WORKS_MAX 64 +VELOCITY_PARAM(int_works,"Number of packets per interrupt services"); + +// EnableMRDPL[] is used for setting the Memory-Read-Multiple ability of NIC +// 0: Disable (default) +// 1: Enable +#define MRDPL_DEF 0 +VELOCITY_PARAM(EnableMRDPL,"Memory-Read-Multiple ability"); + +static int velocity_found1(struct pci_dev *pcid, const struct pci_device_id *ent); +static void velocity_print_info(PVELOCITY_INFO pInfo); +static int velocity_open(struct net_device *dev); +static int velocity_change_mtu(struct net_device *dev,int mtu); +static int velocity_xmit(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t velocity_intr(int irq, void *dev_instance, struct pt_regs *regs); +static void velocity_set_multi(struct net_device *dev); +static struct net_device_stats *velocity_get_stats(struct net_device *dev); +static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int velocity_close(struct net_device *dev); +static int velocity_rx_srv(PVELOCITY_INFO pInfo,int status); +static BOOL velocity_receive_frame(PVELOCITY_INFO ,int idx); +static BOOL velocity_alloc_rx_buf(PVELOCITY_INFO, int idx); +static void velocity_init_adapter(PVELOCITY_INFO pInfo, VELOCITY_INIT_TYPE); +static void velocity_init_pci(PVELOCITY_INFO pInfo); +static void velocity_free_tx_buf(PVELOCITY_INFO pInfo, PVELOCITY_TD_INFO); + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM +static int velocity_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +static int velocity_suspend(struct pci_dev *pcid, pm_message_t state); +#else +static int velocity_suspend(struct pci_dev *pcid, u32 state); +#endif +static int velocity_resume(struct pci_dev *pcid); + +struct notifier_block velocity_notifier = { + notifier_call: velocity_notify_reboot, + next: NULL, + priority: 0 +}; + +static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr); + +static struct notifier_block velocity_inetaddr_notifier = { + notifier_call: velocity_netdev_event, + }; +#endif //CONFIG_PM +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) + + +static CHIP_INFO chip_info_table[] = { + {CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 4, 0x00FFFFFFUL}, + {0, NULL} +}; + +static struct pci_device_id velocity_id_table[] __devinitdata = { + {0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&chip_info_table[0]}, + {0,} +}; + + +static char* get_product_name(int chip_id) +{ + int i; + for (i=0; chip_info_table[i].name!=NULL; i++) + if (chip_info_table[i].chip_id==chip_id) + break; + return chip_info_table[i].name; +} + +static void __devexit velocity_remove1(struct pci_dev *pcid) +{ + PVELOCITY_INFO pInfo = pci_get_drvdata(pcid); + PVELOCITY_INFO ptr; + struct net_device* dev = pInfo->dev; + + if (pInfo == NULL) + return; + + for (ptr=pVelocity3_Infos; ptr && (ptr!=pInfo); ptr=ptr->next) + do {} while (0); + + if (ptr == pInfo) { + if (ptr == pVelocity3_Infos) + pVelocity3_Infos = ptr->next; + else + ptr->prev->next = ptr->next; + } + else { + VELOCITY_PRT(msglevel, MSG_LEVEL_ERR, KERN_ERR "info struct not found\n"); + return; + } + +#ifdef CONFIG_PROC_FS + velocity_free_proc_entry(pInfo); + velocity_free_proc_fs(pInfo); +#endif + + if (dev) + unregister_netdev(dev); + + /*if (pInfo->pMacRegs) + iounmap(pInfo->pMacRegs);*/ + if (pInfo->hw.hw_addr) + iounmap(pInfo->hw.hw_addr); + + pci_disable_device(pcid); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + pci_release_regions(pcid); + free_netdev(dev); +#else + if (pInfo->hw.ioaddr) + release_region(pInfo->hw.ioaddr, pInfo->hw.io_size); + kfree(dev); +#endif + + pci_set_drvdata(pcid, NULL); +} + + +static void +velocity_set_int_opt( + int* opt, + int val, + int min, + int max, + int def, + char* name + ) +{ + if (val == -1) + *opt = def; + else if (valmax) { + VELOCITY_PRT(msglevel, MSG_LEVEL_INFO, KERN_NOTICE "the value of parameter %s is invalid, the valid range is (%d-%d)\n", name, min, max); + *opt = def; + } + else { + VELOCITY_PRT(msglevel, MSG_LEVEL_INFO, KERN_INFO "set value of parameter %s to %d\n", name, val); + *opt = val; + } +} + +static void +velocity_set_bool_opt(PU32 opt, int val, BOOL def, U32 flag, char* name) +{ + (*opt) &= (~flag); + if (val == -1) + *opt |= (def ? flag : 0); + else if (val<0 || val>1) { + printk(KERN_NOTICE "the value of parameter %s is invalid, the valid range is (0-1)\n", name); + *opt |= (def ? flag : 0); + } + else { + printk(KERN_INFO "set parameter %s to %s\n", name , val ? "TRUE" : "FALSE"); + *opt |= (val ? flag : 0); + } +} + +static void +velocity_get_options (POPTIONS pOpts, int index) +{ + velocity_set_int_opt(&pOpts->rx_thresh,rx_thresh[index], + RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF,"rx_thresh"); + + velocity_set_int_opt(&pOpts->DMA_length,DMA_length[index], + DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF,"DMA_length"); + + velocity_set_int_opt(&pOpts->nRxDescs,RxDescriptors[index], + RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors"); + + velocity_set_int_opt(&pOpts->nTxDescs,TxDescriptors[index], + TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors"); + + velocity_set_int_opt(&pOpts->vid,VID_setting[index], + VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_DEF,"VID_setting"); + + velocity_set_bool_opt(&pOpts->flags,enable_tagging[index], + TAGGING_DEF,VELOCITY_FLAGS_TAGGING, "enable_tagging"); + +#ifdef VELOCITY_TX_CSUM_SUPPORT + velocity_set_bool_opt(&pOpts->flags, txcsum_offload[index], + TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, "txcsum_offload"); +#endif + + velocity_set_int_opt(&pOpts->flow_cntl,flow_control[index], + FLOW_CNTL_MIN,FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control"); + + velocity_set_bool_opt(&pOpts->flags,IP_byte_align[index], + IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align"); + + velocity_set_bool_opt(&pOpts->flags,ValPktLen[index], + VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen"); + + velocity_set_int_opt((int*) &pOpts->spd_dpx,speed_duplex[index], + MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF,"Media link mode"); + + velocity_set_int_opt((int*) &pOpts->wol_opts,wol_opts[index], + WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF,"Wake On Lan options"); + + velocity_set_int_opt((int*) &pOpts->int_works,int_works[index], + INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF,"Interrupt service works"); + + velocity_set_bool_opt(&pOpts->flags,EnableMRDPL[index], + MRDPL_DEF, VELOCITY_FLAGS_MRDPL, "EnableMRDPL"); + + pOpts->nRxDescs = (pOpts->nRxDescs & ~3); +} + + + + +// +// Initialiation of adapter +// +static void +velocity_init_adapter ( + PVELOCITY_INFO pInfo, + VELOCITY_INIT_TYPE InitType + ) +{ + struct net_device *dev = pInfo->dev; + int i; + + mac_wol_reset(&pInfo->hw); + + switch (InitType) { + case VELOCITY_INIT_RESET: + case VELOCITY_INIT_WOL: + + netif_stop_queue(dev); + + velocity_init_register_reset(&pInfo->hw); + + if (!(pInfo->hw.mii_status & VELOCITY_LINK_FAIL)) + netif_wake_queue(dev); + + break; + + case VELOCITY_INIT_COLD: + default: + mac_eeprom_reload(&pInfo->hw); + // write dev->dev_addr to MAC address field for MAC address override + for (i = 0; i < 6; i++) + CSR_WRITE_2(&pInfo->hw, dev->dev_addr[i], MAC_REG_PAR+i); + + // clear Pre_ACPI bit. + BYTE_REG_BITS_OFF(&pInfo->hw, CFGA_PACPI, MAC_REG_CFGA); + + // set packet filter + // receive directed and broadcast address + velocity_set_multi(dev); + netif_stop_queue(dev); + + velocity_init_register_cold(&pInfo->hw); + + if (!(pInfo->hw.mii_status & VELOCITY_LINK_FAIL)) + netif_wake_queue(dev); + break; + } // switch (InitType) +} + +static void +velocity_init_pci(PVELOCITY_INFO pInfo) { + + // turn this on to avoid retry forever + PCI_BYTE_REG_BITS_ON(MODE2_PCEROPT, PCI_REG_MODE2, pInfo->pcid); + // 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, pInfo->pcid); + // turn this on to detect MII coding error + PCI_BYTE_REG_BITS_ON(MODE3_MIION, PCI_REG_MODE3, pInfo->pcid); +} + +static int +velocity_found1( + struct pci_dev *pcid, + const struct pci_device_id *ent + ) +{ + static BOOL bFirst = TRUE; + struct net_device* dev = NULL; + int i, rc; + PCHIP_INFO pChip_info = (PCHIP_INFO)ent->driver_data; + PVELOCITY_INFO pInfo, p; + long ioaddr, memaddr; + PU8 hw_addr; + + + if (velocity_nics++ >= MAX_UINTS) { + printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs\n", velocity_nics); + return -ENODEV; + } + + rc = pci_enable_device(pcid); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pcid, 0xffffffffL); + if (rc) { + printk(KERN_ERR VELOCITY_NAME "PCI DMA not supported!\n"); + goto err_out; + } + + ioaddr = pci_resource_start(pcid, 0); + memaddr = pci_resource_start(pcid, 1); + + pci_set_master(pcid); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + dev = alloc_etherdev(sizeof(VELOCITY_INFO)); +#else + dev = init_etherdev(NULL, sizeof(VELOCITY_INFO)); +#endif + + if (dev == NULL) { + rc = -ENOMEM; + printk(KERN_ERR VELOCITY_NAME ": allocate net device failed!\n"); + goto err_out; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + /* Chain it all together */ + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pcid->dev); +#endif + pInfo = netdev_priv(dev); + + if (bFirst) { + printk(KERN_INFO "%s Ver. %s\n",VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION); + printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n"); + bFirst=FALSE; + } + + // init pVelocity3_Infos information + if (pVelocity3_Infos == NULL) { + pVelocity3_Infos = pInfo; + } + else { + for (p=pVelocity3_Infos; p->next!=NULL; p=p->next) + do {} while (0); + p->next = pInfo; + pInfo->prev = p; + } + + // init pInfo information + pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pInfo->hw.SubSystemID); + pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pInfo->hw.SubVendorID); + pci_read_config_byte(pcid, PCI_REVISION_ID, &pInfo->hw.byRevId); + + pInfo->chip_id = pChip_info->chip_id; + pInfo->hw.nTxQueues = 1; + pInfo->hw.multicast_limit = MCAM_SIZE; + pInfo->pcid = pcid; + spin_lock_init(&(pInfo->lock)); + spin_lock_init(&(pInfo->xmit_lock)); + + /* init velocity_hw */ + pInfo->hw.io_size = 256; + pInfo->hw.ioaddr = ioaddr; + pInfo->hw.memaddr = memaddr; + +#ifdef CONFIG_PROC_FS + velocity_init_proc_fs(pInfo); +#endif + + /* assign message level */ + pInfo->hw.msglevel = msglevel; + + pInfo->dev = dev; + pInfo->osdep.dev = dev; + pInfo->hw.back = &pInfo->osdep; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + rc = pci_request_regions(pcid, VELOCITY_NAME); + if (rc) { + printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device\n"); + goto err_out_free_dev; + } +#else + if (check_region(pInfo->hw.ioaddr, pInfo->hw.io_size)) { + printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device\n"); + goto err_out_free_dev; + } + request_region(pInfo->hw.ioaddr, pInfo->hw.io_size, VELOCITY_NAME); +#endif + + + hw_addr = ioremap(pInfo->hw.memaddr & PCI_BASE_ADDRESS_MEM_MASK, pInfo->hw.io_size); + if (!hw_addr) { + rc = -EIO; + printk(KERN_ERR VELOCITY_NAME ": ioremap failed for region 0x%lx\n", pInfo->hw.memaddr); + goto err_out_free_res; + } + + pInfo->hw.hw_addr = hw_addr; + + velocity_create_proc_entry(pInfo); + + + mac_wol_reset(&pInfo->hw); + + // get MII PHY Id + velocity_mii_read(&pInfo->hw, MII_REG_PHYID2, (PU16)&pInfo->hw.dwPHYId); + velocity_mii_read(&pInfo->hw, MII_REG_PHYID1, ((PU16)&pInfo->hw.dwPHYId)+1); + + // software reset + velocity_soft_reset(&pInfo->hw); + mdelay(5); + + // EEPROM reload + mac_eeprom_reload(&pInfo->hw); + + // set net_device related stuffs + dev->base_addr = pInfo->hw.ioaddr; + for (i=0; i<6; i++) + dev->dev_addr[i] = CSR_READ_1(&pInfo->hw, MAC_REG_PAR+i); + dev->irq = pcid->irq; + dev->open = velocity_open; + dev->hard_start_xmit = velocity_xmit; + dev->stop = velocity_close; + dev->get_stats = velocity_get_stats; + dev->set_multicast_list = velocity_set_multi; + dev->do_ioctl = velocity_ioctl; + dev->change_mtu = velocity_change_mtu; + + velocity_get_options(&pInfo->hw.sOpts, velocity_nics-1); + + // Mask out the options cannot be set to the chip + pInfo->hw.sOpts.flags &= pChip_info->flags; + + // Enable the chip specified capbilities + pInfo->hw.flags = pInfo->hw.sOpts.flags | (pChip_info->flags & 0xFF000000L); + + pInfo->wol_opts = pInfo->hw.sOpts.wol_opts; + + pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; + +#ifdef VELOCITY_TX_CSUM_SUPPORT + if (pInfo->hw.flags & VELOCITY_FLAGS_TX_CSUM) { + dev->features |= NETIF_F_HW_CSUM; +#ifdef VELOCITY_ZERO_COPY_SUPPORT + // Checksum function must be enabled, or SG will be dropped + dev->features |= NETIF_F_SG; +#endif + } +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + rc = register_netdev(dev); + if (rc) { + printk(KERN_ERR VELOCITY_NAME ": Failed to register netdev\n"); + goto err_out_unmap; + } +#endif + + velocity_print_info(pInfo); + + pci_set_drvdata(pcid, pInfo); + + return 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +err_out_unmap: + iounmap(pInfo->hw.hw_addr); +err_out_free_res: + pci_release_regions(pcid); +err_out_free_dev: + free_netdev(dev); +#else +err_out_free_res: + if (pInfo->hw.ioaddr) + release_region(pInfo->hw.ioaddr, pInfo->hw.io_size); +err_out_free_dev: + kfree(dev); +#endif + +err_out: + return rc; +} + + +static void velocity_print_info(PVELOCITY_INFO pInfo) +{ + struct net_device* dev = pInfo->dev; + + printk(KERN_INFO "%s: %s\n", dev->name, get_product_name(pInfo->chip_id)); + printk(KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + dev->name, + dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], + dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); + + printk(" IO=0x%lx Mem=0x%lx ", pInfo->hw.ioaddr, pInfo->hw.memaddr); + printk(" IRQ=%d \n", dev->irq); + +} + +static BOOL velocity_init_rings(PVELOCITY_INFO pInfo) +{ + int i; + struct net_device* dev = pInfo->dev; + + /*allocate all RD/TD rings a single pool*/ + pInfo->pool = pci_alloc_consistent(pInfo->pcid, + pInfo->hw.sOpts.nRxDescs * sizeof(RX_DESC) + 64 + + pInfo->hw.sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->hw.nTxQueues, + &pInfo->hw.pool_dma); + + if (pInfo->pool == NULL) { + printk(KERN_ERR "%s : allocate dma memory failed\n", dev->name); + return FALSE; + } + + memset(pInfo->pool,0, pInfo->hw.sOpts.nRxDescs * sizeof(RX_DESC) + + pInfo->hw.sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->hw.nTxQueues); + + pInfo->hw.aRDRing = (PRX_DESC)(((unsigned long)(((PU8) pInfo->pool) + 63)) & ~63); + + pInfo->hw.rd_pool_dma = pInfo->hw.pool_dma; + + pInfo->tx_bufs=pci_alloc_consistent(pInfo->pcid, + pInfo->hw.sOpts.nTxDescs * PKT_BUF_SZ*pInfo->hw.nTxQueues, + &pInfo->hw.tx_bufs_dma); + + if (pInfo->tx_bufs == NULL) { + printk(KERN_ERR "%s: allocate dma memory failed\n", dev->name); + pci_free_consistent(pInfo->pcid, + pInfo->hw.sOpts.nRxDescs * sizeof(RX_DESC) + 64 + + pInfo->hw.sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->hw.nTxQueues, + pInfo->pool, pInfo->hw.pool_dma); + return FALSE; + } + + memset(pInfo->tx_bufs, 0, pInfo->hw.sOpts.nTxDescs * PKT_BUF_SZ * pInfo->hw.nTxQueues); + + for (i=0;ihw.nTxQueues;i++) { + + pInfo->hw.td_pool_dma[i]=pInfo->hw.rd_pool_dma+ + pInfo->hw.sOpts.nRxDescs*sizeof(RX_DESC)+ + pInfo->hw.sOpts.nTxDescs*sizeof(TX_DESC)*i; + + pInfo->hw.apTDRings[i]=(PTX_DESC) (((PU8) pInfo->hw.aRDRing)+ + pInfo->hw.sOpts.nRxDescs*sizeof(RX_DESC)+ + pInfo->hw.sOpts.nTxDescs*sizeof(TX_DESC)*i); + } + + return TRUE; +} + +static void velocity_free_rings(PVELOCITY_INFO pInfo) { + + pci_free_consistent(pInfo->pcid, + pInfo->hw.sOpts.nRxDescs * sizeof(RX_DESC) + 64 + + pInfo->hw.sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->hw.nTxQueues, + pInfo->pool, pInfo->hw.pool_dma); + + if (pInfo->tx_bufs) + pci_free_consistent(pInfo->pcid, + pInfo->hw.sOpts.nTxDescs * PKT_BUF_SZ*pInfo->hw.nTxQueues, + pInfo->tx_bufs, pInfo->hw.tx_bufs_dma); +} + +static BOOL velocity_init_rd_ring(PVELOCITY_INFO pInfo) +{ + int i; + PRX_DESC pDesc; + PVELOCITY_RD_INFO pRDInfo; + struct net_device* dev = pInfo->dev; + + pInfo->aRDInfo=MALLOC(sizeof(VELOCITY_RD_INFO)*pInfo->hw.sOpts.nRxDescs, + GFP_KERNEL); + memset(pInfo->aRDInfo,0,sizeof(VELOCITY_RD_INFO)*pInfo->hw.sOpts.nRxDescs); + + /* Init the RD ring entries */ + for (i = 0; i < pInfo->hw.sOpts.nRxDescs; i++) { + pDesc=&(pInfo->hw.aRDRing[i]); + pRDInfo=&(pInfo->aRDInfo[i]); + + if (!velocity_alloc_rx_buf(pInfo, i)) { + VELOCITY_PRT(msglevel, MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n", + dev->name); + return FALSE; + } + pDesc->rdesc0 |= cpu_to_le32(RDESC0_OWN); + } + + pInfo->hw.iCurrRDIdx = 0; + return TRUE; +} + +static void velocity_free_rd_ring(PVELOCITY_INFO pInfo) { + int i; + PVELOCITY_RD_INFO pRDInfo; + + if (pInfo->aRDInfo == NULL) + return; + + for (i = 0; i < pInfo->hw.sOpts.nRxDescs; i++) { + pRDInfo = &(pInfo->aRDInfo[i]); + + if (pRDInfo->skb_dma) { + pci_unmap_single(pInfo->pcid,pRDInfo->skb_dma, + pInfo->hw.rx_buf_sz, PCI_DMA_FROMDEVICE); + pRDInfo->skb_dma=(dma_addr_t)NULL; + } + if (pRDInfo->skb) { + dev_kfree_skb(pRDInfo->skb); + pRDInfo->skb=NULL; + } + } + + if (pInfo->aRDInfo) + kfree(pInfo->aRDInfo); + pInfo->aRDInfo = NULL; +} + +static BOOL velocity_init_td_ring(PVELOCITY_INFO pInfo) { + int i,j; + dma_addr_t curr; + PTX_DESC pDesc; + PVELOCITY_TD_INFO pTDInfo; + + /* Init the TD ring entries */ + for (j=0;jhw.nTxQueues;j++) { + curr=pInfo->hw.td_pool_dma[j]; + + pInfo->apTDInfos[j]=MALLOC(sizeof(VELOCITY_TD_INFO)*pInfo->hw.sOpts.nTxDescs, + GFP_KERNEL); + + memset(pInfo->apTDInfos[j],0, + sizeof(VELOCITY_TD_INFO)*pInfo->hw.sOpts.nTxDescs); + + for (i = 0; i < pInfo->hw.sOpts.nTxDescs; i++, curr+=sizeof(TX_DESC)) { + pDesc=&(pInfo->hw.apTDRings[j][i]); + pTDInfo=&(pInfo->apTDInfos[j][i]); + pTDInfo->buf=pInfo->tx_bufs+(i+j)*PKT_BUF_SZ; + pTDInfo->buf_dma=pInfo->hw.tx_bufs_dma+(i+j)*PKT_BUF_SZ; + } + pInfo->hw.aiTailTDIdx[j]=pInfo->hw.aiCurrTDIdx[j]=pInfo->hw.iTDUsed[j]=0; + } + return TRUE; +} + +static void velocity_free_td_ring(PVELOCITY_INFO pInfo) { + int i, j, k; + PVELOCITY_TD_INFO pTDInfo; + + for (j=0; jhw.nTxQueues; j++) { + if (pInfo->apTDInfos[j] == NULL) + continue; + + for (i = 0; i < pInfo->hw.sOpts.nTxDescs; i++) { + pTDInfo = &(pInfo->apTDInfos[j][i]); + if (pTDInfo == NULL) + continue; + + for (k=0; knskb_dma; k++) + if (pTDInfo->skb_dma[k] && (pTDInfo->skb_dma[k] != pTDInfo->buf_dma)) { + pci_unmap_single(pInfo->pcid, pTDInfo->skb_dma[k], + pTDInfo->skb->len, PCI_DMA_TODEVICE); + pTDInfo->skb_dma[k] = (dma_addr_t)NULL; + } + + if (pTDInfo->skb) { + dev_kfree_skb(pTDInfo->skb); + pTDInfo->skb = NULL; + } + } + + if (pInfo->apTDInfos[j]) { + kfree(pInfo->apTDInfos[j]); + pInfo->apTDInfos[j] = NULL; + } + } +} + +/*-----------------------------------------------------------------*/ +static int velocity_rx_srv(PVELOCITY_INFO pInfo, int status) +{ + PRX_DESC pRD; + struct net_device_stats* pStats = &pInfo->stats; + //PMAC_REGS pMacRegs = pInfo->pMacRegs; + int iCurrRDIdx = pInfo->hw.iCurrRDIdx; + int works = 0; + U16 wRSR; + + + while (TRUE) { + pRD = &(pInfo->hw.aRDRing[iCurrRDIdx]); + + if ((pInfo->aRDInfo[iCurrRDIdx]).skb == NULL) { + if (!velocity_alloc_rx_buf(pInfo, iCurrRDIdx)) + break; + } + + if (works++ > INT_WORKS_DEF) + break; + + if (pRD->rdesc0 & cpu_to_le32(RDESC0_OWN)) + break; + + pInfo->adwRMONStats[RMON_Octets] += (U16)((cpu_to_le32(pRD->rdesc0) >> 16) & 0x00003fffL); + + wRSR = (U16)(cpu_to_le32(pRD->rdesc0)); + + // don't drop CE or RL error frame although RXOK is off + if( (wRSR & RSR_RXOK) || (!(wRSR & RSR_RXOK) && (wRSR & (RSR_CE | RSR_RL)))) { + if (velocity_receive_frame(pInfo, iCurrRDIdx)) { + if (!velocity_alloc_rx_buf(pInfo, iCurrRDIdx)) { + VELOCITY_PRT(msglevel, MSG_LEVEL_ERR, KERN_ERR + "%s: can not allocate rx buf\n", pInfo->dev->name); + break; + } + } + else { + pStats->rx_dropped++; + } + } + else { + if (wRSR & RSR_CRC) + pStats->rx_crc_errors++; + if (wRSR & RSR_FAE) + pStats->rx_frame_errors++; + + pStats->rx_dropped++; + } + + if ((iCurrRDIdx % 4) == 3) { + int i, iPrevRDIdx = iCurrRDIdx; + for (i=0; i<4; i++) { + pRD = &(pInfo->hw.aRDRing[iPrevRDIdx]); + pRD->rdesc0 |= cpu_to_le32(RDESC0_OWN); + SUB_ONE_WITH_WRAP_AROUND(iPrevRDIdx, pInfo->hw.sOpts.nRxDescs); + } + CSR_WRITE_2(&pInfo->hw, 4, MAC_REG_RBRDU); + } + + pInfo->dev->last_rx = jiffies; + + ADD_ONE_WITH_WRAP_AROUND(iCurrRDIdx, pInfo->hw.sOpts.nRxDescs); + } + + pInfo->hw.iCurrRDIdx = iCurrRDIdx; + VAR_USED(pStats); + return works; +} + +static inline void +velocity_rx_csum(PRX_DESC pRD, struct sk_buff* skb) +{ + U8 byCSM; + + skb->ip_summed = CHECKSUM_NONE; + byCSM = (U8)(cpu_to_le32(pRD->rdesc1) >> 16); + + if ((byCSM & CSM_IPKT) && (byCSM & CSM_IPOK)) { + if ((byCSM & CSM_TCPKT) || (byCSM & CSM_UDPKT)) { + if (!(byCSM & CSM_TUPOK)) + return; + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + } +} + +static BOOL +velocity_receive_frame(PVELOCITY_INFO pInfo, int idx) +{ + PVELOCITY_RD_INFO pRDInfo = &(pInfo->aRDInfo[idx]); + PRX_DESC pRD = &(pInfo->hw.aRDRing[idx]); + struct sk_buff* skb; + U16 wRSR, wLength; + + wRSR = (U16)(cpu_to_le32(pRD->rdesc0)); + //wLength = (U16)((cpu_to_le32(pRD->rdesc0) >> 16) & 0x00003fffL); + wLength = VELOCITY_GET_RD_PACKET_SIZE(pRD); + + if (wRSR & (RSR_STP|RSR_EDP)) { + VELOCITY_PRT(msglevel, MSG_LEVEL_VERBOSE, KERN_NOTICE "%s: the received frame span multple RDs\n", pInfo->dev->name); + pInfo->stats.rx_length_errors++; + return FALSE; + } + + if (wRSR & RSR_MAR) + pInfo->stats.multicast++; + + if (wRSR & RSR_BAR) + pInfo->adwRMONStats[RMON_BroadcastPkts]++; + + skb = pRDInfo->skb; + skb->dev = pInfo->dev; + + pci_unmap_single(pInfo->pcid,pRDInfo->skb_dma, pInfo->hw.rx_buf_sz, PCI_DMA_FROMDEVICE); + pRDInfo->skb_dma = (dma_addr_t)NULL; + pRDInfo->skb = NULL; + + if (pInfo->hw.flags & VELOCITY_FLAGS_IP_ALIGN) { + int i; + for (i = wLength+4; i >= 0; i--) + *(skb->data + i + 2) = *(skb->data + i); + skb->data += 2; + skb->tail += 2; + } + + skb_put(skb, (wLength-4)); + + skb->protocol = eth_type_trans(skb, skb->dev); + + //drop frame not met IEEE 802.3 + if (pInfo->hw.flags & VELOCITY_FLAGS_VAL_PKT_LEN) { + if (wRSR & RSR_RL) { + pInfo->stats.rx_length_errors++; + return FALSE; + } + } + + velocity_rx_csum(pRD, skb); + pInfo->stats.rx_bytes += skb->len; + netif_rx(skb); + + return TRUE; +} + +static BOOL velocity_alloc_rx_buf(PVELOCITY_INFO pInfo, int idx) { + PRX_DESC pRD=&(pInfo->hw.aRDRing[idx]); + PVELOCITY_RD_INFO pRDInfo=&(pInfo->aRDInfo[idx]); + + pRDInfo->skb = dev_alloc_skb(pInfo->hw.rx_buf_sz+64); + + if (pRDInfo->skb == NULL) + return FALSE; + + ASSERT(pRDInfo->skb); + skb_reserve(pRDInfo->skb, 64 - ((unsigned long)pRDInfo->skb->tail & 63)); + pRDInfo->skb->dev = pInfo->dev; + pRDInfo->skb_dma= + pci_map_single(pInfo->pcid, pRDInfo->skb->tail, pInfo->hw.rx_buf_sz, + PCI_DMA_FROMDEVICE); + *((PU32)&(pRD->rdesc0)) = 0; + + VELOCITY_SET_RD_BUFFER_SIZE(pRD, pInfo->hw.rx_buf_sz); + pRD->rdesc3 |= cpu_to_le32(RDESC3_INTCTL); + pRD->dwBufAddrLo = cpu_to_le32(pRDInfo->skb_dma); + // mask off RD data buffer address high to zero + pRD->rdesc3 &= cpu_to_le32(0xffff0000L); + + return TRUE; +} + +static int velocity_tx_srv(PVELOCITY_INFO pInfo, U32 status) +{ + PTX_DESC pTD; + int iQNo; + BOOL bFull = FALSE; + int idx; + int works = 0; + PVELOCITY_TD_INFO pTDInfo; + struct net_device_stats* pStats = &pInfo->stats; + U16 wTSR; + + + for (iQNo=0; iQNohw.nTxQueues; iQNo++) { + for (idx = pInfo->hw.aiTailTDIdx[iQNo]; + pInfo->hw.iTDUsed[iQNo]>0; + idx = (idx+1) % pInfo->hw.sOpts.nTxDescs) + { + // Get Tx Descriptor + pTD = &(pInfo->hw.apTDRings[iQNo][idx]); + pTDInfo = &(pInfo->apTDInfos[iQNo][idx]); + + if (pTD->tdesc0 & cpu_to_le32(TDESC0_OWN)) { + break; + } + + if (works++ > INT_WORKS_DEF) { + break; + } + + wTSR = (U16)cpu_to_le32(pTD->tdesc0); + + if (wTSR & TSR0_TERR) { + pStats->tx_errors++; + pStats->tx_dropped++; + if (wTSR & TSR0_CDH) + pStats->tx_heartbeat_errors++; + if (wTSR & TSR0_CRS) + pStats->tx_carrier_errors++; + if (wTSR & TSR0_ABT) + pStats->tx_aborted_errors++; + if (wTSR & TSR0_OWC) + pStats->tx_window_errors++; + + } + else { + pStats->tx_packets++; + pStats->tx_bytes += pTDInfo->skb->len; + } + + velocity_free_tx_buf(pInfo, pTDInfo); + pInfo->hw.iTDUsed[iQNo]--; + } // for (idx) + + pInfo->hw.aiTailTDIdx[iQNo]=idx; + + if (AVAIL_TD(&pInfo->hw, iQNo) < 1 ) { + bFull = TRUE; + } + } // for (iQNo) + + if (netif_queue_stopped(pInfo->dev) && (bFull==FALSE) + && (!(pInfo->hw.mii_status & VELOCITY_LINK_FAIL))) { + netif_wake_queue(pInfo->dev); + } + return works; +} + + + +static void velocity_error(PVELOCITY_INFO pInfo, int status) { + struct net_device* dev = pInfo->dev; + + // (1) LSTEI + if (status & ISR_TXSTLI) { + printk("TD structure errror TDindex=%X\n", CSR_READ_2(&pInfo->hw, MAC_REG_TDIDX0)); + + BYTE_REG_BITS_ON(&pInfo->hw, TXESR_TDSTR, MAC_REG_TXE_SR); + CSR_WRITE_2(&pInfo->hw, TRDCSR_RUN, MAC_REG_TDCSR_CLR); + netif_stop_queue(dev); + } + + // (2) SRCI + if (status & ISR_SRCI) { + + if (pInfo->hw.sOpts.spd_dpx == SPD_DPX_AUTO) { + pInfo->hw.mii_status = check_connectiontype(&pInfo->hw); + + // if it's 3119, disable frame bursting in halfduplex mode and + // enable it in fullduplex mode + if (pInfo->hw.byRevId < REV_ID_VT3216_A0) { + if (pInfo->hw.mii_status | VELOCITY_DUPLEX_FULL) + BYTE_REG_BITS_ON(&pInfo->hw, TCR_TB2BDIS, MAC_REG_TCR); + else + BYTE_REG_BITS_OFF(&pInfo->hw, TCR_TB2BDIS, MAC_REG_TCR); + } + + // only enable CD heart beat counter in 10HD mode + if (!(pInfo->hw.mii_status & VELOCITY_DUPLEX_FULL) && (pInfo->hw.mii_status & VELOCITY_SPEED_10)) { + BYTE_REG_BITS_OFF(&pInfo->hw, TESTCFG_HBDIS, MAC_REG_TESTCFG); + } + else { + BYTE_REG_BITS_ON(&pInfo->hw, TESTCFG_HBDIS, MAC_REG_TESTCFG); + } + + //-------------------------------------------------------- + // [1.18] Adaptive Interrupt + if (pInfo->hw.byRevId >= REV_ID_VT3216_A0) { + if ( (pInfo->hw.mii_status & VELOCITY_SPEED_1000) || + (pInfo->hw.mii_status & VELOCITY_SPEED_100) ) + { + CSR_WRITE_1(&pInfo->hw, 0x59, MAC_REG_TQETMR); // 100us + CSR_WRITE_1(&pInfo->hw, 0x14, MAC_REG_TQETMR); // 20us + } + else { + CSR_WRITE_1(&pInfo->hw, 0x00, MAC_REG_TQETMR); + CSR_WRITE_1(&pInfo->hw, 0x00, MAC_REG_TQETMR); + } + } + //-------------------------------------------------------- + } + + // get link status from PHYSR0 + + pInfo->hw.mii_status = check_connectiontype(&pInfo->hw); + + velocity_print_link_status(&pInfo->hw); + enable_flow_control_ability(&pInfo->hw); + + // re-enable auto-polling because SRCI will disable auto-polling + EnableMiiAutoPoll(&pInfo->hw); + + if (pInfo->hw.mii_status & VELOCITY_LINK_FAIL) { + netif_carrier_off(dev); + netif_stop_queue(dev); + } + else { + netif_carrier_on(dev); + netif_wake_queue(dev); + } + } // ISR_SRCI + + // (3) MIBFI + if (status & ISR_MIBFI) + velocity_update_hw_mibs(&pInfo->hw); + + // (4) LSTEI: RD used up, re-wake RD ring + if (status & ISR_LSTEI) { + mac_rx_queue_wake(&pInfo->hw); + } +} + +static void velocity_free_tx_buf(PVELOCITY_INFO pInfo, PVELOCITY_TD_INFO pTDInfo) +{ + struct sk_buff* skb = pTDInfo->skb; + int i; + + // Don't unmap the pre-allocaed tx_bufs + if (pTDInfo->skb_dma && (pTDInfo->skb_dma[0] != pTDInfo->buf_dma)) { + for (i=0; inskb_dma; i++) { +#ifdef VELOCITY_ZERO_COPY_SUPPORT + pci_unmap_single(pInfo->pcid, pTDInfo->skb_dma[i], pDesc->tdesc1.f15BufLen, PCI_DMA_TODEVICE); +#else + pci_unmap_single(pInfo->pcid, pTDInfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE); +#endif + } + } + + dev_kfree_skb_irq(skb); + + for (i=0; inskb_dma; i++) + pTDInfo->skb_dma[i] = 0; + + pTDInfo->skb = 0; +} + +static int velocity_open(struct net_device *dev) { + PVELOCITY_INFO pInfo=(PVELOCITY_INFO) dev->priv; + int i; + + pInfo->hw.rx_buf_sz=(dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32); + + if (!velocity_init_rings(pInfo)) + return -ENOMEM; + + if (!velocity_init_rd_ring(pInfo)) + return -ENOMEM; + + if (!velocity_init_td_ring(pInfo)) + return -ENOMEM; + + velocity_init_pci(pInfo); + + velocity_init_adapter(pInfo, VELOCITY_INIT_COLD); + + i=request_irq(pInfo->pcid->irq, &velocity_intr, SA_SHIRQ, dev->name, dev); + + if (i) + return i; + + mac_enable_int(&pInfo->hw); + + netif_start_queue(dev); + + pInfo->hw.flags |=VELOCITY_FLAGS_OPENED; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +static int velocity_change_mtu(struct net_device *dev,int new_mtu) { + PVELOCITY_INFO pInfo = (PVELOCITY_INFO)dev->priv; + unsigned long flags; + int oldmtu = dev->mtu; + + if ((new_mtu(VELOCITY_MAX_MTU)) { + VELOCITY_PRT(msglevel, MSG_LEVEL_ERR, KERN_NOTICE + "%s: Invaild MTU\n",pInfo->dev->name); + return -EINVAL; + } + + if (new_mtu!=oldmtu) { + spin_lock_irqsave(&pInfo->lock, flags); + + netif_stop_queue(dev); + velocity_shutdown(&pInfo->hw); + + velocity_free_td_ring(pInfo); + velocity_free_rd_ring(pInfo); + + dev->mtu=new_mtu; + if (new_mtu>8192) + pInfo->hw.rx_buf_sz=9*1024; + else if (new_mtu>4096) + pInfo->hw.rx_buf_sz=8192; + else + pInfo->hw.rx_buf_sz=4*1024; + + if (!velocity_init_rd_ring(pInfo)) + return -ENOMEM; + + if (!velocity_init_td_ring(pInfo)) + return -ENOMEM; + + velocity_init_adapter(pInfo, VELOCITY_INIT_COLD); + + mac_enable_int(&pInfo->hw); + netif_start_queue(dev); + spin_unlock_irqrestore(&pInfo->lock, flags); + } + + return 0; +} + +static int velocity_close(struct net_device *dev) { + PVELOCITY_INFO pInfo= netdev_priv(dev); + + netif_stop_queue(dev); + + velocity_shutdown(&pInfo->hw); + + if (pInfo->hw.flags & VELOCITY_FLAGS_WOL_ENABLED) + velocity_get_ip(pInfo); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_DEC_USE_COUNT; +#endif + + if (dev->irq!=0) + free_irq(dev->irq, dev); + + velocity_free_td_ring(pInfo); + velocity_free_rd_ring(pInfo); + velocity_free_rings(pInfo); + + pInfo->hw.flags &=(~VELOCITY_FLAGS_OPENED); + return 0; +} + + +static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) +{ + PVELOCITY_INFO pInfo = netdev_priv(dev); + int iQNo = 0; + PTX_DESC pTD; + PVELOCITY_TD_INFO pTDInfo; + unsigned long flags; + int iCurrTDIdx; + int iPrevTDIdx; + +#ifdef VELOCITY_ZERO_COPY_SUPPORT + unsigned int nfrags = 0; +#endif + +#ifdef VELOCITY_TSO_SUPPORT + unsigned int mss = 0; +#endif + + + spin_lock_irqsave(&pInfo->lock, flags); + + iCurrTDIdx = pInfo->hw.aiCurrTDIdx[iQNo]; + pTD = &(pInfo->hw.apTDRings[iQNo][iCurrTDIdx]); + pTDInfo = &(pInfo->apTDInfos[iQNo][iCurrTDIdx]); + +#ifdef VELOCITY_TSO_SUPPORT + mss = skb_shinfo(skb)->tso_size; +#endif + + // Init TDESC0,1 + pTD->tdesc0 = 0x00000000UL; + pTD->tdesc1 = 0x00000000UL; + + VELOCITY_SET_TD_TCPLS(pTD, TCPLS_NORMAL); + pTD->tdesc1 |= cpu_to_le32(TCR_TIC); + pTD->aTdBufs[0].dwBufaddrHi &= cpu_to_le32(~TDTXBUF_QUE); + +#ifdef VELOCITY_ZERO_COPY_SUPPORT + nfrags = skb_shinfo(skb)->nr_frags; +#endif + + if (skb->len < ETH_ZLEN) { + // packet size is less than 60 bytes + skb_linearize(skb, GFP_ATOMIC); + memcpy(pTDInfo->buf, skb->data, skb->len); + VELOCITY_SET_TD_PACKET_SIZE(pTD, ETH_ZLEN); + + // padding zero + memset(pTDInfo->buf+skb->len, 0, ETH_ZLEN-skb->len); + + pTDInfo->skb = skb; + + pTDInfo->skb_dma[0] = pTDInfo->buf_dma; + pTD->aTdBufs[0].dwBufAddrLo = cpu_to_le32(pTDInfo->skb_dma[0]); + // mask off TD data buffer address high to zero + pTD->aTdBufs[0].dwBufaddrHi &= cpu_to_le32(0xffff0000L); + + VELOCITY_SET_TD_BUFFER_SIZE(pTD->aTdBufs[0], ETH_ZLEN); + pTDInfo->nskb_dma = 1; + VELOCITY_SET_TD_CMDZ(pTD, 2); + } + else +#ifdef VELOCITY_ZERO_COPY_SUPPORT + if (skb_shinfo(skb)->nr_frags > 0) { + int nfrags = skb_shinfo(skb)->nr_frags; + + pTDInfo->skb = skb; + if (nfrags > 6) { + // elements > 7 ==> copy to a buffer + skb_linearize(skb, GFP_ATOMIC); + memcpy(pTDInfo->buf, skb->data, skb->len); + VELOCITY_SET_TD_PACKET_SIZE(pTD, skb->len); + + pTDInfo->skb_dma[0] = pTDInfo->buf_dma; + pTD->aTdBufs[0].dwBufAddrLo = cpu_to_le32(pTDInfo->skb_dma[0]); + // mask off TD data buffer address high to zero + pTD->aTdBufs[0].dwBufaddrHi &= cpu_to_le32(0xffff0000L); + + VELOCITY_SET_TD_BUFFER_SIZE(pTD->aTdBufs[0], skb->len); + pTDInfo->nskb_dma = 1; + VELOCITY_SET_TD_CMDZ(pTD, 2); + } + else { + // elements <= 7 + int i = 0; + + pTDInfo->nskb_dma = 0; + VELOCITY_SET_TD_PACKET_SIZE(pTD, skb->len); + + pTDInfo->skb_dma[i] = pci_map_single(pInfo->pcid, skb->data, skb->len - skb->data_len, PCI_DMA_TODEVICE); + pTD->aTdBufs[i].dwBufAddrLo = cpu_to_le32(pTDInfo->skb_dma[i]); + // mask off TD data buffer address high to zero + pTD->aTdBufs[i].dwBufaddrHi &= cpu_to_le32(0xffff0000L); + + VELOCITY_SET_TD_BUFFER_SIZE(pTD->aTdBufs[i], skb->len - skb->data_len); + + for (i=0; ifrags[i]; + addr = ((void *)page_address(frag->page + frag->page_offset)); + + pTDInfo->skb_dma[i+1] = pci_map_single(pInfo->pcid, addr, frag->size, PCI_DMA_TODEVICE); + pTD->aTdBufs[i+1].dwBufAddrLo = cpu_to_le32(pTDInfo->skb_dma[i+1]); + // mask off TD data buffer address high to zero + pTD->aTdBufs[i+1].dwBufaddrHi &= cpu_to_le32(0xffff0000L); + + VELOCITY_SET_TD_BUFFER_SIZE(pTD->aTdBufs[i+1], frag->size); + } + pTDInfo->nskb_dma = i-1; + VELOCITY_SET_TD_CMDZ(pTD, i); + } + } + else +#endif + { + pTDInfo->skb = skb; + pTDInfo->skb_dma[0] = pci_map_single(pInfo->pcid, skb->data, skb->len, PCI_DMA_TODEVICE); + + VELOCITY_SET_TD_PACKET_SIZE(pTD, skb->len); + pTD->aTdBufs[0].dwBufAddrLo = cpu_to_le32(pTDInfo->skb_dma[0]); + // mask off TD data buffer address high to zero + pTD->aTdBufs[0].dwBufaddrHi &= cpu_to_le32(0xffff0000L); + VELOCITY_SET_TD_BUFFER_SIZE(pTD->aTdBufs[0], skb->len); + pTDInfo->nskb_dma = 1; + VELOCITY_SET_TD_CMDZ(pTD, 2); + } + + if (pInfo->hw.flags & VELOCITY_FLAGS_TAGGING) { + // clear CFI and priority + pTD->tdesc1 &= cpu_to_le32(0xffff0000L); + VELOCITY_SET_TD_VLANID(pTD, pInfo->hw.sOpts.vid & 0xfff); + pTD->tdesc1 |= cpu_to_le32(TCR_VETAG); + } + +#ifdef VELOCITY_TX_CSUM_SUPPORT + if ( (pInfo->hw.flags & VELOCITY_FLAGS_TX_CSUM) && + (skb->ip_summed == CHECKSUM_HW) ) + { + struct iphdr* ip = skb->nh.iph; + + if (ip->protocol == IPPROTO_TCP) { + // request TCP checksum calculation + pTD->tdesc1 |= cpu_to_le32(TCR_TCPCK); + } + else if (ip->protocol == IPPROTO_UDP) { + // request UDP checksum calculation + pTD->tdesc1 |= cpu_to_le32(TCR_UDPCK); + } + + // request IP checksum calculation + pTD->tdesc1 |= cpu_to_le32(TCR_IPCK); + } +#endif + + // Set OWN bit of current TD + pTD->tdesc0 |= cpu_to_le32(TDESC0_OWN); + + pInfo->hw.iTDUsed[iQNo]++; + pInfo->hw.aiCurrTDIdx[iQNo] = (iCurrTDIdx + 1) % pInfo->hw.sOpts.nTxDescs; + + if (AVAIL_TD(&pInfo->hw, iQNo) < 1) + netif_stop_queue(dev); + + iPrevTDIdx = (iCurrTDIdx + pInfo->hw.sOpts.nTxDescs - 1) % pInfo->hw.sOpts.nTxDescs; + pTD = &(pInfo->hw.apTDRings[iQNo][iPrevTDIdx]); + pTD->aTdBufs[0].dwBufaddrHi |= cpu_to_le32(TDTXBUF_QUE); + + mac_tx_queue_wake(&pInfo->hw, iQNo); + + dev->trans_start = jiffies; + + spin_unlock_irqrestore(&pInfo->lock, flags); + return 0; +} + +static irqreturn_t velocity_intr(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device* dev = dev_instance; + PVELOCITY_INFO pInfo = netdev_priv(dev); + U32 isr_status; + int max_count = 0; + int handled = 0; + + + if (!spin_trylock(&pInfo->lock)) + return IRQ_RETVAL(handled); + + isr_status = mac_read_isr(&pInfo->hw); + + if (isr_status == 0) { + spin_unlock(&pInfo->lock); + return IRQ_RETVAL(handled); + } + + handled = 1; + mac_disable_int(&pInfo->hw); + + while (isr_status != 0) { + mac_write_isr(&pInfo->hw, isr_status); + + velocity_error(pInfo, isr_status); + + max_count += velocity_rx_srv(pInfo, isr_status); + max_count += velocity_tx_srv(pInfo, isr_status); + + // [1.18], for performance + max_count += velocity_rx_srv(pInfo, isr_status); + max_count += velocity_tx_srv(pInfo, isr_status); + + isr_status = mac_read_isr(&pInfo->hw); + + if (max_count > pInfo->hw.sOpts.int_works) + break; + } + + mac_enable_int(&pInfo->hw); + + spin_unlock(&pInfo->lock); + return IRQ_RETVAL(handled); +} + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) +{ + int crc = -1; + + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) { + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + } + return crc; +} + + +static void velocity_set_multi(struct net_device *dev) +{ + PVELOCITY_INFO pInfo = netdev_priv(dev); + u8 rx_mode; + int i; + struct dev_mc_list *mclist; + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + /* Unconditionally log net taps. */ + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + velocity_set_all_multi(&pInfo->hw); + rx_mode = (RCR_AM|RCR_AB|RCR_PROM); + } + else if ((dev->mc_count > pInfo->hw.multicast_limit) + || (dev->flags & IFF_ALLMULTI)) { + velocity_set_all_multi(&pInfo->hw); + rx_mode = (RCR_AM|RCR_AB); + } + else { + int offset=MCAM_SIZE-pInfo->hw.multicast_limit; + mac_get_cam_mask(&pInfo->hw,pInfo->hw.abyMCAMMask,VELOCITY_MULTICAST_CAM); + + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + mac_set_cam(&pInfo->hw,i+offset,mclist->dmi_addr,VELOCITY_MULTICAST_CAM); + pInfo->hw.abyMCAMMask[(offset+i)/8]|=1<<((offset+i) & 7); + } + + mac_set_cam_mask(&pInfo->hw,pInfo->hw.abyMCAMMask,VELOCITY_MULTICAST_CAM); + + rx_mode=(RCR_AM|RCR_AB); + } + + if (dev->mtu>1500) + rx_mode|=RCR_AL; + + BYTE_REG_BITS_ON(&pInfo->hw, rx_mode, MAC_REG_RCR); +} + + +static struct net_device_stats *velocity_get_stats(struct net_device *dev) +{ + PVELOCITY_INFO pInfo = netdev_priv(dev); + + spin_lock_irq(&pInfo->lock); + velocity_update_hw_mibs(&pInfo->hw); + spin_unlock_irq(&pInfo->lock); + + pInfo->stats.rx_packets=pInfo->hw.adwHWMIBCounters[HW_MIB_ifRxAllPkts]; + pInfo->stats.rx_errors=pInfo->hw.adwHWMIBCounters[HW_MIB_ifRxErrorPkts]; + pInfo->stats.rx_length_errors=pInfo->hw.adwHWMIBCounters[HW_MIB_ifInRangeLengthErrors]; + + pInfo->stats.collisions=pInfo->hw.adwHWMIBCounters[HW_MIB_ifTxEtherCollisions]; + // detailed rx_errors: + pInfo->stats.rx_crc_errors=pInfo->hw.adwHWMIBCounters[HW_MIB_ifRxPktCRCE]; + + // detailed tx_errors + + return &pInfo->stats; +} + + +static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + switch(cmd) { + +#ifdef VELOCITY_ETHTOOL_IOCTL_SUPPORT + case SIOCETHTOOL: + return velocity_ethtool_ioctl(dev, rq); + break; +#endif + +#ifdef VELOCITY_MII_IOCTL_SUPPORT + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCSMIIREG: /* Write to MII PHY register. */ + return velocity_mii_ioctl(dev, rq, cmd); + break; +#endif + + default: + return -EOPNOTSUPP; + } + return 0; +} + + + +/*------------------------------------------------------------------*/ + +MODULE_DEVICE_TABLE(pci, velocity_id_table); + +static struct pci_driver velocity_driver = { + name: VELOCITY_NAME, + id_table: velocity_id_table, + probe: velocity_found1, + remove: velocity_remove1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + suspend: velocity_suspend, + resume: velocity_resume, +#endif +#endif +}; + +static int __init velocity_init_module(void) +{ + int ret; + ret=pci_module_init(&velocity_driver); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + register_inetaddr_notifier(&velocity_inetaddr_notifier); + if(ret >= 0) + register_reboot_notifier(&velocity_notifier); + +#endif +#endif + + return ret; +} + +static void __exit velocity_cleanup_module(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + unregister_reboot_notifier(&velocity_notifier); + unregister_inetaddr_notifier(&velocity_inetaddr_notifier); +#endif +#endif + pci_unregister_driver(&velocity_driver); +} + +module_init(velocity_init_module); +module_exit(velocity_cleanup_module); + + +/*************************************************************************** +* ETHTOOL ioctl support routine +****************************************************************************/ +#ifdef VELOCITY_ETHTOOL_IOCTL_SUPPORT +static int velocity_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr) +{ + struct ethtool_cmd ecmd; + PVELOCITY_INFO pInfo = netdev_priv(dev); + //PMAC_REGS pMacRegs = pInfo->pMacRegs; + + if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd.cmd))) + return -EFAULT; + + switch (ecmd.cmd) { + case ETHTOOL_GSET: { + U32 status=check_connectiontype(&pInfo->hw); + ecmd.supported= + SUPPORTED_TP|SUPPORTED_Autoneg|SUPPORTED_10baseT_Half|SUPPORTED_10baseT_Full + |SUPPORTED_100baseT_Half|SUPPORTED_100baseT_Full|SUPPORTED_1000baseT_Half|SUPPORTED_1000baseT_Full; + + if (status & VELOCITY_SPEED_100) + ecmd.speed=SPEED_100; + else + ecmd.speed=SPEED_10; + + ecmd.autoneg=(status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE; + ecmd.port=PORT_TP; + ecmd.transceiver=XCVR_INTERNAL; + ecmd.phy_address=CSR_READ_1(&pInfo->hw, MAC_REG_MIIADR) & 0x1F; + + if (status & VELOCITY_DUPLEX_FULL) + ecmd.duplex=DUPLEX_FULL; + else + ecmd.duplex=DUPLEX_HALF; + + if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) + return -EFAULT; + + } + break; + + case ETHTOOL_SSET: { + U32 curr_status; + U32 new_status=0; + if (!capable(CAP_NET_ADMIN)){ + return -EPERM; + } + + if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) + return -EFAULT; + + curr_status=check_connectiontype(&pInfo->hw); + curr_status&=(~VELOCITY_LINK_FAIL); + + new_status|=((ecmd.autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); + new_status|=((ecmd.speed==SPEED_100) ? VELOCITY_SPEED_100 : 0); + new_status|=((ecmd.speed==SPEED_10) ? VELOCITY_SPEED_10 : 0); + new_status|=((ecmd.duplex==DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); + + if ((new_status & VELOCITY_AUTONEG_ENABLE) && + (new_status!=(curr_status| VELOCITY_AUTONEG_ENABLE))) + return -EINVAL; + + //------------------------------------------------------------ + // [1.18] Save ConnectionType Info when via Ethertool + if (new_status & VELOCITY_AUTONEG_ENABLE) { + pInfo->hw.sOpts.spd_dpx = SPD_DPX_AUTO; // 0 + } + else { + if (new_status & VELOCITY_SPEED_100) { + if (new_status & VELOCITY_DUPLEX_FULL) { + // 100-Full + pInfo->hw.sOpts.spd_dpx = SPD_DPX_100_FULL; // 2 + } + else { + // 100-Half + pInfo->hw.sOpts.spd_dpx = SPD_DPX_100_HALF; // 1 + } + } + else { + if (new_status & VELOCITY_DUPLEX_FULL) { + // 10-Full + pInfo->hw.sOpts.spd_dpx = SPD_DPX_10_FULL; // 4 + } + else { + // 10-Half + pInfo->hw.sOpts.spd_dpx = SPD_DPX_10_HALF; // 3 + } + } + } + //------------------------------------------------------------ + + velocity_set_media_mode(&pInfo->hw,pInfo->hw.sOpts.spd_dpx); + } + break; + +#ifdef ETHTOOL_GLINK + case ETHTOOL_GLINK: { + struct ethtool_value info; + memset((void *)&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GLINK; + info.data = BYTE_REG_BITS_IS_ON(&pInfo->hw, PHYSR0_LINKGD, MAC_REG_PHYSR0) ? FALSE : TRUE; + + if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) + return -EFAULT; + } + break; +#endif + +#ifdef ETHTOOL_GDRVINFO + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, VELOCITY_NAME); + strcpy(info.version, VELOCITY_VERSION); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) + strcpy(info.bus_info, pci_name(pInfo->pcid)); +#else + strcpy(info.bus_info,pInfo->pcid->slot_name); +#endif + if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) + return -EFAULT; + } + break; +#endif + +#ifdef ETHTOOL_GWOL + case ETHTOOL_GWOL: { + struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; + + memset(&wol, 0, sizeof(wol)); + + wol.supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP; + wol.wolopts |= WAKE_MAGIC; + + if (pInfo->wol_opts & VELOCITY_WOL_UCAST) + wol.wolopts |= WAKE_UCAST; + if (pInfo->wol_opts & VELOCITY_WOL_ARP) + wol.wolopts |= WAKE_ARP; + + memcpy(&wol.sopass, pInfo->wol_passwd, 6); + + if (copy_to_user(ifr->ifr_data, &wol, sizeof(wol))) + return -EFAULT; + } + break; +#endif + +#ifdef ETHTOOL_SWOL + case ETHTOOL_SWOL: { + struct ethtool_wolinfo wol; + + if (copy_from_user(&wol, ifr->ifr_data, sizeof(wol))) + return -EFAULT; + + if (!(wol.wolopts & (WAKE_PHY|WAKE_MAGIC|WAKE_UCAST|WAKE_ARP))) + return -EFAULT; + + pInfo->wol_opts = VELOCITY_WOL_MAGIC; + + if (wol.wolopts & WAKE_MAGIC) { + pInfo->wol_opts |= VELOCITY_WOL_MAGIC; + pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + + if (wol.wolopts & WAKE_UCAST) { + pInfo->wol_opts |= VELOCITY_WOL_UCAST; + pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + + if (wol.wolopts & WAKE_ARP) { + pInfo->wol_opts |= VELOCITY_WOL_ARP; + pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + + memcpy(pInfo->wol_passwd,wol.sopass,6); + + if (copy_to_user(ifr->ifr_data, &wol, sizeof(wol))) + return -EFAULT; + } + break; +#endif + +#ifdef ETHTOOL_GMSGLVL + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = {ETHTOOL_GMSGLVL}; + + edata.data = msglevel; + if (copy_to_user(ifr->ifr_data, &edata, sizeof(edata))) + return -EFAULT; + } + break; +#endif + +#ifdef ETHTOOL_SMSGLVL + case ETHTOOL_SMSGLVL: { + struct ethtool_value edata={ETHTOOL_SMSGLVL}; + + if (copy_from_user(&edata, ifr->ifr_data, sizeof(edata))) + return -EFAULT; + msglevel = edata.data; + } + break; +#endif + + default: + return -EOPNOTSUPP; + } + + return 0; +} +#endif // VELOCITY_ETHTOOL_IOCTL_SUPPORT + + +/*************************************************************************** +* MII ioctl support routine +****************************************************************************/ +#ifdef VELOCITY_MII_IOCTL_SUPPORT +static int velocity_mii_ioctl(struct net_device* dev, struct ifreq* ifr, int cmd) +{ + PVELOCITY_INFO pInfo = netdev_priv(dev); + //PMAC_REGS pMacRegs = pInfo->pMacRegs; + unsigned long flags; + struct mii_ioctl_data* pMiiData = (struct mii_ioctl_data*)&(ifr->ifr_data); + + switch(cmd) { + case SIOCGMIIPHY: + pMiiData->phy_id=CSR_READ_1(&pInfo->hw, MAC_REG_MIIADR) & 0x1f; + break; + + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + velocity_mii_read(&pInfo->hw,pMiiData->reg_num & 0x1f, &(pMiiData->val_out)); + break; + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + spin_lock_irqsave(&pInfo->lock, flags); + velocity_mii_write(&pInfo->hw,pMiiData->reg_num & 0x1f,pMiiData->val_in); + spin_unlock_irqrestore(&pInfo->lock,flags); + pInfo->hw.mii_status = check_connectiontype(&pInfo->hw); + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} +#endif // VELOCITY_MII_IOCTL_SUPPORT + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM +static int +velocity_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) +{ + struct pci_dev *pcid = NULL; + + switch(event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + while ((pcid = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcid)) != NULL) { +#else + pci_for_each_dev(pcid) { +#endif + if(pci_dev_driver(pcid) == &velocity_driver) { + if (pci_get_drvdata(pcid)) + velocity_suspend(pcid, 3); + } + } + } + return NOTIFY_DONE; +} + + +static int +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +velocity_suspend(struct pci_dev *pcid, pm_message_t state) +#else +velocity_suspend(struct pci_dev *pcid, u32 state) +#endif +{ + PVELOCITY_INFO pInfo = pci_get_drvdata(pcid); + struct net_device *dev = pInfo->dev; + unsigned long flags; + int power_status; // to silence the compiler + + netif_stop_queue(dev); + spin_lock_irqsave(&pInfo->lock, flags); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + pci_save_state(pcid); +#else + pci_save_state(pcid, pInfo->pci_state); +#endif + +#ifdef ETHTOOL_GWOL + if (pInfo->hw.flags & VELOCITY_FLAGS_WOL_ENABLED) { + velocity_get_ip(pInfo); + velocity_save_mac_context(&pInfo->hw, &pInfo->mac_context); + velocity_save_pci_context(pInfo, &pInfo->pci_context); + velocity_shutdown(&pInfo->hw); + velocity_set_wol(pInfo); + power_status = pci_enable_wake(pcid, PCI_D3hot, 1); + power_status = pci_set_power_state(pcid, PCI_D3hot); + } + else { + velocity_save_mac_context(&pInfo->hw, &pInfo->mac_context); + velocity_save_pci_context(pInfo, &pInfo->pci_context); + velocity_shutdown(&pInfo->hw); + pci_disable_device(pcid); + power_status = pci_set_power_state(pcid, state); + } +#else + pci_disable_device(pcid); + power_status = pci_set_power_state(pcid, state); +#endif + + spin_unlock_irqrestore(&pInfo->lock, flags); + return 0; +} + + +static int +velocity_resume(struct pci_dev *pcid) +{ + PVELOCITY_INFO pInfo = pci_get_drvdata(pcid); + struct net_device *dev = pInfo->dev; + unsigned long flags; + int power_status; // to silence the compiler + + power_status = pci_set_power_state(pcid, PCI_D0); + power_status = pci_enable_wake(pcid, PCI_D0, 0); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + pci_restore_state(pcid); +#else + pci_restore_state(pcid, pInfo->pci_state); +#endif + + mac_wol_reset(&pInfo->hw); + + if (netif_running(dev)) { + int i; + spin_lock_irqsave(&pInfo->lock, flags); + velocity_restore_mac_context(&pInfo->hw, &pInfo->mac_context); + velocity_restore_pci_context(pInfo, pInfo->pci_context); + velocity_init_adapter(pInfo, VELOCITY_INIT_WOL); + mac_disable_int(&pInfo->hw); + + velocity_tx_srv(pInfo, 0); + + for (i=0;ihw.nTxQueues;i++) { + if (pInfo->hw.iTDUsed[i]) { + mac_tx_queue_wake(&pInfo->hw, i); + } + } + + mac_enable_int(&pInfo->hw); + netif_start_queue(dev); + spin_unlock_irqrestore(&pInfo->lock, flags); + } + + return 0; +} + + +static int +velocity_netdev_event( + struct notifier_block *nb, + unsigned long notification, + void *ptr + ) +{ + struct in_ifaddr* ifa = (struct in_ifaddr*)ptr; + struct net_device* dev; + PVELOCITY_INFO pInfo; + + if (ifa) { + dev = ifa->ifa_dev->dev; + for (pInfo=pVelocity3_Infos; pInfo; pInfo=pInfo->next) { + if (pInfo->dev == dev) + velocity_get_ip(pInfo); + } + } + return NOTIFY_DONE; +} +#endif // CONFIG_PM +#endif // KERNEL_VERSION(2,4,9) diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_mii.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_mii.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_mii.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_mii.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_mii.h + * + * Purpose: Header file for MII registers. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_MII_H__ +#define __VELOCITY_MII_H__ + +#include "osdep.h" + +/* +// Registers in the MII (offset unit is WORD) +*/ +#define MII_REG_BMCR 0x00 /* physical address */ +#define MII_REG_BMSR 0x01 +#define MII_REG_PHYID1 0x02 /* OUI */ +#define MII_REG_PHYID2 0x03 /* OUI + Module ID + REV ID */ +#define MII_REG_ANAR 0x04 +#define MII_REG_ANLPAR 0x05 +#define MII_REG_G1000CR 0x09 +#define MII_REG_G1000SR 0x0A +#define MII_REG_MODCFG 0x10 +#define MII_REG_TCSR 0x16 +#define MII_REG_PLED 0x1B +/* NS, MYSON only */ +#define MII_REG_PCR 0x17 +/* ESI only */ +#define MII_REG_PCSR 0x17 +#define MII_REG_AUXCR 0x1C + +/* Marvell 88E1000/88E1000S */ +#define MII_REG_PSCR 0x10 /* PHY specific control register */ + +/* +// Bits in the BMCR register +*/ +#define BMCR_RESET 0x8000 +#define BMCR_LBK 0x4000 +#define BMCR_SPEED100 0x2000 +#define BMCR_AUTO 0x1000 +#define BMCR_PD 0x0800 +#define BMCR_ISO 0x0400 +#define BMCR_REAUTO 0x0200 +#define BMCR_FDX 0x0100 +#define BMCR_SPEED1G 0x0040 +/* +// Bits in the BMSR register +*/ +#define BMSR_AUTOCM 0x0020 +#define BMSR_LNK 0x0004 + +/* +// Bits in the ANAR register +*/ +#define ANAR_ASMDIR 0x0800 /* Asymmetric PAUSE support */ +#define ANAR_PAUSE 0x0400 /* Symmetric PAUSE Support */ +#define ANAR_T4 0x0200 +#define ANAR_TXFD 0x0100 +#define ANAR_TX 0x0080 +#define ANAR_10FD 0x0040 +#define ANAR_10 0x0020 +/* +// Bits in the ANLPAR register +*/ +#define ANLPAR_ASMDIR 0x0800 /* Asymmetric PAUSE support */ +#define ANLPAR_PAUSE 0x0400 /* Symmetric PAUSE Support */ +#define ANLPAR_T4 0x0200 +#define ANLPAR_TXFD 0x0100 +#define ANLPAR_TX 0x0080 +#define ANLPAR_10FD 0x0040 +#define ANLPAR_10 0x0020 + +/* +// Bits in the G1000CR register +*/ +#define G1000CR_1000FD 0x0200 /* PHY is 1000-T Full-duplex capable */ +#define G1000CR_1000 0x0100 /* PHY is 1000-T Half-duplex capable */ + +/* +// Bits in the G1000SR register +*/ +#define G1000SR_1000FD 0x0800 /* LP PHY is 1000-T Full-duplex capable */ +#define G1000SR_1000 0x0400 /* LP PHY is 1000-T Half-duplex capable */ + +#define TCSR_ECHODIS 0x2000 +#define AUXCR_MDPPS 0x0004 + +/* Bits in the PLED register */ +#define PLED_LALBE 0x0004 + +/* Marvell 88E1000/88E1000S Bits in the PHY specific control register (10h) */ +#define PSCR_ACRSTX 0x0800 /* Assert CRS on Transmit */ + +#define PHYID_CICADA_CS8201 0x000FC410UL +#define PHYID_VT3216_32BIT 0x000FC610UL +#define PHYID_VT3216_64BIT 0x000FC600UL +#define PHYID_MARVELL_1000 0x01410C50UL +#define PHYID_MARVELL_1000S 0x01410C40UL + +#define PHYID_REV_ID_MASK 0x0000000FUL + +#define PHYID_GET_PHY_REV_ID(i) ((i) & PHYID_REV_ID_MASK) +#define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK) + +#define MII_REG_BITS_ON(x,i,hw) do {\ + U16 w;\ + velocity_mii_read((hw),(i),&(w));\ + (w)|=(x);\ + velocity_mii_write((hw),(i),(w));\ +} while (0) + +#define MII_REG_BITS_OFF(x,i,hw) do {\ + U16 w;\ + velocity_mii_read((hw),(i),&(w));\ + (w)&=(~(x));\ + velocity_mii_write((hw),(i),(w));\ +} while (0) + +#define MII_REG_BITS_IS_ON(x,i,hw) ({\ + U16 w;\ + velocity_mii_read((hw),(i),&(w));\ + ((BOOL) ((w) & (x)));}) + +#define MII_GET_PHY_ID(hw) ({\ + U32 id;\ + velocity_mii_read(hw, MII_REG_PHYID2, (PU16)&id);\ + velocity_mii_read(hw, MII_REG_PHYID1, ((PU16)&id)+1);\ + (id);}) + +#endif /* __VELOCITY_MII_H__ */ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_proc.c linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_proc.c --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_proc.c 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_proc.c 2006-10-23 10:58:14 +0200 @@ -0,0 +1,612 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_proc.c + * + * Purpose: proc entry process routines + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + +#include "velocity.h" +#include "velocity_proc.h" + +static const char* VELOCITY_PROC_DIR_NAME = "Velocity_Gigabit_Adapters"; +static struct proc_dir_entry *velocity_dir = NULL; + +static int FunVerRead(char *page, char **start, off_t off, int count, int *eof, void *data); +static int FunStatRead(PVELOCITY_PROC_ENTRY pInfo,char* buf); +static int FunConfRead(PVELOCITY_PROC_ENTRY pInfo,char* buf); +static int FunConfWrite(PVELOCITY_PROC_ENTRY pInfo,const char* buf,unsigned long len); +static int FunRMONRead(PVELOCITY_PROC_ENTRY pInfo,char* buf); + +typedef +enum _proc_conf_type { + CONF_RX_DESC = 0, // 0 + CONF_TX_DESC, // 1 + CONF_RX_THRESH, // 2 + CONF_DMA_LEN, // 3 + CONF_SPD_DPX, // 4 + CONF_FLOW_CTRL, // 5 + CONF_WOL_OPTS, // 6 + CONF_ENABLE_TAG, // 7 + CONF_VID_SETTING, // 8 + CONF_VAL_PKT, // 9 + CONF_ENABLE_MRDPL // 10 +} PROC_CONF_TYPE, *PPROC_CONF_TYPE; + +static const VELOCITY_PROC_ENTRY velocity_proc_tab_conf[] = { +{"RxDescriptors", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_RX_DESC, NULL, 0}, +{"TxDescriptors", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_TX_DESC, NULL, 0}, +{"rx_thresh", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_RX_THRESH, NULL, 0}, +{"speed_duplex", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_SPD_DPX, NULL, 0}, +{"flow_control", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_FLOW_CTRL, NULL, 0}, +{"DMA_length", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_DMA_LEN, NULL, 0}, +{"ValPktLen", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_VAL_PKT, NULL, 0}, +{"wol_opts", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_WOL_OPTS, NULL, 0}, +{"EnableMRDPL", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_ENABLE_MRDPL, NULL, 0}, +{"enable_tagging", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_ENABLE_TAG, NULL, 0}, +{"VID_setting", VELOCITY_PROC_FILE, FunConfRead, FunConfWrite, CONF_VID_SETTING, NULL, 0}, +{"", VELOCITY_PROC_EOT, NULL, NULL, 0, NULL} +}; + + + +static const VELOCITY_PROC_ENTRY velocity_proc_tab_rmon[]={ +{"etherStatsDropEvents", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_DropEvents, NULL}, +{"etherStatsOctets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Octets, NULL}, +{"etherStatsPkts", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts, NULL}, +{"etherStatsBroadcastPkts", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_BroadcastPkts, NULL}, +{"etherStatsMulticastPkts", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_MulticastPkts, NULL}, +{"etherStatsCRCAlignErrors", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_CRCAlignErrors, NULL}, +{"etherStatsUndersizePkts", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_UndersizePkts,NULL}, +{"etherStatsOversizePkts", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_OversizePkts,NULL}, +{"etherStatsFragments", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Fragments,NULL}, +{"etherStatsJabbers", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Jabbers,NULL}, +{"etherStatsCollisions", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Collisions, NULL}, +{"etherStatsPkts64Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts64Octets, NULL}, +{"etherStatsPkts65to127Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts65to127Octets, NULL}, +{"etherStatsPkts128to255Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts128to255Octets, NULL}, +{"etherStatsPkts256to511Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts256to511Octets, NULL}, +{"etherStatsPkts512to1023Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts512to1023Octets, NULL}, +{"etherStatsPkts1024to1518Octets", VELOCITY_PROC_READ, + FunRMONRead, NULL, RMON_Pkts1024to1518Octets, NULL}, +{"", VELOCITY_PROC_EOT, + NULL, NULL, 0, NULL} +}; + +static const VELOCITY_PROC_ENTRY velocity_proc_tab[]={ +{"conf", VELOCITY_PROC_DIR, NULL, NULL, 0, velocity_proc_tab_conf}, +{"rmon", VELOCITY_PROC_DIR, NULL, NULL, 0, velocity_proc_tab_rmon}, +{"statics", VELOCITY_PROC_READ, FunStatRead,NULL, 0, NULL}, +{"", VELOCITY_PROC_EOT, NULL, NULL, 0, NULL} +}; + +static int velocity_proc_read(char *page, char **start, off_t off, int count, + int *eof, void *data) { + PVELOCITY_PROC_ENTRY pEntry=(PVELOCITY_PROC_ENTRY) data; + int len; + + len=pEntry->read_proc(pEntry, page); + + page[len++]='\n'; + + if (len <= off + count) + *eof = 1; + + *start = page + off; + len -= off; + + if (len > count) + len = count; + + if (len < 0) + len = 0; + return len; +} + +static int velocity_proc_write(struct file *filp, const char* buffer, + unsigned long count, void *data) +{ + int res=0; + PVELOCITY_PROC_ENTRY pEntry=(PVELOCITY_PROC_ENTRY) data; + res=pEntry->write_proc(pEntry,buffer,count); + return res; +} + +static void velocity_create_proc_tab(PVELOCITY_INFO pInfo, + PVELOCITY_PROC_ENTRY pParent, const VELOCITY_PROC_ENTRY pTab[]) { + + int i; + struct proc_dir_entry* ptr; + PVELOCITY_PROC_ENTRY pEntry=NULL; + PVELOCITY_PROC_ENTRY pRoot=NULL; + + if (pTab==NULL) + return; + + for (i=0;pTab[i].type!=VELOCITY_PROC_EOT;i++) { + //Skip some entries + + if ((pTab[i].byRevId!=0) && (pInfo->hw.byRevIdsiblings=pRoot; + pRoot=pEntry; + + if (pEntry->type & VELOCITY_PROC_DIR) { + ptr=create_proc_entry(pEntry->name,S_IFDIR, pParent->pOsEntry); + pEntry->pOsParent=pParent->pOsEntry; + pEntry->pOsEntry=ptr; + velocity_create_proc_tab(pInfo,pEntry,pTab[i].childs); + } + else { + int flag=S_IFREG; + if (pEntry->type & VELOCITY_PROC_READ) + flag|=S_IRUGO; + if (pEntry->type & VELOCITY_PROC_WRITE) + flag|=S_IWUSR; + ptr=create_proc_entry(pEntry->name,flag, pParent->pOsEntry); + if (pEntry->type & VELOCITY_PROC_READ) + ptr->read_proc=velocity_proc_read; + if (pEntry->type & VELOCITY_PROC_WRITE) + ptr->write_proc=velocity_proc_write; + ptr->data=pEntry; + pEntry->pOsEntry=ptr; + pEntry->pInfo=pInfo; + pEntry->pOsParent=pParent->pOsEntry; + } + } + pParent->childs=pRoot; +} + +static void velocity_delete_proc_tab(PVELOCITY_INFO pInfo, + const PVELOCITY_PROC_ENTRY pEntry) { + + if (pEntry==NULL) + return; + + if (pEntry->type & VELOCITY_PROC_DIR) + velocity_delete_proc_tab(pInfo,(PVELOCITY_PROC_ENTRY) pEntry->childs); + else + velocity_delete_proc_tab(pInfo,(PVELOCITY_PROC_ENTRY) pEntry->siblings); + + remove_proc_entry(pEntry->name,pEntry->pOsParent); + kfree(pEntry); +} + +BOOL velocity_create_proc_entry(PVELOCITY_INFO pInfo) +{ + struct net_device *dev = pInfo->dev; + + //Create ethX directory as root directory + pInfo->pProcDir=kmalloc(sizeof(VELOCITY_PROC_ENTRY),GFP_KERNEL); + memset(pInfo->pProcDir,0,sizeof(VELOCITY_PROC_ENTRY)); + + pInfo->pProcDir->pOsEntry= + create_proc_entry(dev->name, S_IFDIR, velocity_dir); + pInfo->pProcDir->pOsParent = velocity_dir; + + //Create all other directoires according the defined entries on table + velocity_create_proc_tab(pInfo, pInfo->pProcDir, velocity_proc_tab); + return TRUE; +} + +void velocity_free_proc_entry(PVELOCITY_INFO pInfo) +{ + struct net_device *dev = pInfo->dev; + + velocity_delete_proc_tab(pInfo, (PVELOCITY_PROC_ENTRY) pInfo->pProcDir->childs); + remove_proc_entry(dev->name, velocity_dir); + kfree(pInfo->pProcDir); +} + +BOOL velocity_init_proc_fs(PVELOCITY_INFO pInfo) { + struct proc_dir_entry* ptr; + int len=strlen(VELOCITY_PROC_DIR_NAME); + + if (velocity_dir==NULL) { + for (velocity_dir = proc_net->subdir; velocity_dir;velocity_dir = velocity_dir->next) { + if ((velocity_dir->namelen == len) && + (!memcmp(velocity_dir->name, VELOCITY_PROC_DIR_NAME, len))) + break; + } + + if (velocity_dir==NULL) { + velocity_dir=create_proc_entry(VELOCITY_PROC_DIR_NAME,S_IFDIR,proc_net); + ptr=create_proc_entry("version",S_IFREG|S_IRUGO,velocity_dir); + ptr->data=NULL; + ptr->write_proc=NULL; + ptr->read_proc=FunVerRead; + } + } + + if (velocity_dir==NULL) + return FALSE; + + return TRUE; +} + +void velocity_free_proc_fs(PVELOCITY_INFO pInfo) { + struct proc_dir_entry* ptr; + +// remove_proc_entry(pInfo->pProcDir, velocity_dir); + + if (velocity_dir==NULL) + return; + + //Check if other adapters's entry still exist + for (ptr = velocity_dir->subdir; ptr; ptr = ptr->next) { + if ((*(ptr->name) != '.') && + (strcmp(ptr->name,"version"))) + break; + } + + if (ptr) + return; + + remove_proc_entry("version",velocity_dir); + remove_proc_entry(VELOCITY_PROC_DIR_NAME,proc_net); + + velocity_dir=NULL; +} + +static long atol(const char* ptr,int len) { + unsigned long l=0; + while (*ptr!=0 && *ptr!='\n' && len-->0 ) { + if (*ptr< '0' || *ptr >'9') + return -1; + l*=10; + l+=(*ptr++-'0'); + } + return l; +} + +//---------------------------------- +// +static int FunVerRead(char *page, char **start, off_t off, int count, + int *eof, void *data) { + int len; + + len=sprintf(page,"%s",VELOCITY_VERSION); + + page[len++]='\n'; + + if (len <= off + count) + *eof = 1; + + *start = page + off; + len -= off; + + if (len > count) + len = count; + + if (len < 0) + len = 0; + return len; +} + +static const char* MIB_STRINGS[HW_MIB_SIZE]={ + "RxAllPkts", + "ifRxOkPkts", + "ifTxOkPkts", + "ifRxErrorPkts", + "ifRxRuntOkPkt", + "ifRxRuntErrPkt", + "ifRx64Pkts", + "ifTx64Pkts", + "ifRx65To127Pkts", + "ifTx65To127Pkts", + "ifRx128To255Pkts", + "ifTx128To255Pkts", + "ifRx256To511Pkts", + "ifTx256To511Pkts", + "ifRx512To1023Pkts", + "ifTx512To1023Pkts", + "ifRx1024To1518Pkts", + "ifTx1024To1518Pkts", + "ifTxEtherCollisions", + "ifRxPktCRCE", + "ifRxJumboPkts", + "ifTxJumboPkts", + "ifRxMacControlFrames", + "ifTxMacControlFrames", + "ifRxPktFAE", + "ifRxLongOkPkt", + "ifRxLongPktErrPkt", + "ifTXSQEErrors", + "ifRxNobuf", + "ifRxSymbolErrors", + "ifInRangeLenthErrors", + "ifLateCollisions" +}; + +static int FunStatRead(PVELOCITY_PROC_ENTRY pEntry,char* buf) { + PVELOCITY_INFO pInfo=pEntry->pInfo; + int len=0; + int i; + + spin_lock_irq(&pInfo->lock); + velocity_update_hw_mibs(&pInfo->hw); + spin_unlock_irq(&pInfo->lock); + len+=sprintf(&buf[len],"Hardware MIB Counter:\n"); + for (i=0;ihw.adwHWMIBCounters[i]); + + len=strlen(buf); + + return len; +} + +static int FunConfRead(PVELOCITY_PROC_ENTRY pEntry,char* buf) { + PVELOCITY_INFO pInfo=pEntry->pInfo; + int len=0; + PROC_CONF_TYPE op=pEntry->data; + switch(op) { + case CONF_RX_DESC: + len=sprintf(buf,"%d",pInfo->hw.sOpts.nRxDescs); + break; + + case CONF_TX_DESC: + len=sprintf(buf,"%d",pInfo->hw.sOpts.nTxDescs); + break; + + case CONF_RX_THRESH: + len=sprintf(buf,"%d",pInfo->hw.sOpts.rx_thresh); + break; + case CONF_SPD_DPX: { + int mii_status=mii_check_media_mode(&pInfo->hw); + int r=0; + if (mii_status & VELOCITY_AUTONEG_ENABLE) + r=0; + else if ((mii_status & (VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL)) + ==(VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL)) + r=2; + else if ((mii_status & (VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL)) + ==(VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL)) + r=4; + else if (mii_status & (VELOCITY_SPEED_100)) + r=1; + else if (mii_status & (VELOCITY_SPEED_10)) + r=3; + len=sprintf(buf,"%d",r); + } + break; + case CONF_DMA_LEN: + len=sprintf(buf,"%d",pInfo->hw.sOpts.DMA_length); + break; + case CONF_WOL_OPTS: + len=sprintf(buf,"%d",pInfo->hw.sOpts.wol_opts); + break; + case CONF_FLOW_CTRL: + len=sprintf(buf,"%d",pInfo->hw.sOpts.flow_cntl); + break; + case CONF_VAL_PKT: + len=sprintf(buf,"%d", + (pInfo->hw.flags & VELOCITY_FLAGS_VAL_PKT_LEN) ? 1 : 0); + break; + case CONF_ENABLE_MRDPL: + len=sprintf(buf,"%d", + (pInfo->hw.flags & VELOCITY_FLAGS_MRDPL) ? 1 : 0); + break; + case CONF_ENABLE_TAG: + len=sprintf(buf,"%d", + (pInfo->hw.flags & VELOCITY_FLAGS_TAGGING) ? 1 : 0); + break; + case CONF_VID_SETTING: + len=sprintf(buf,"%d",pInfo->hw.sOpts.vid); + break; + } + return len; +} + +static int FunConfWrite(PVELOCITY_PROC_ENTRY pEntry, const char* buf, + unsigned long len) { + PVELOCITY_INFO pInfo=pEntry->pInfo; + PROC_CONF_TYPE op=pEntry->data; + long l; + + l=atol(buf,len); + if (l<0) + return -EINVAL; + + switch(op) { + case CONF_RX_DESC: + if (pInfo->hw.flags & VELOCITY_FLAGS_OPENED) + return -EACCES; + if ((l<4)||(l>128)) + return -EINVAL; + pInfo->hw.sOpts.nRxDescs=(l +3 ) & ~3 ; + break; + case CONF_TX_DESC: + if (pInfo->hw.flags & VELOCITY_FLAGS_OPENED) + return -EACCES; + if ((l<16)||(l>128)) + return -EINVAL; + pInfo->hw.sOpts.nTxDescs=l; + break; + + case CONF_RX_THRESH: + if ((l<0)||(l>7)) + return -EINVAL; + pInfo->hw.sOpts.rx_thresh=l; + mac_set_rx_thresh(&pInfo->hw,pInfo->hw.sOpts.rx_thresh); + break; + + case CONF_SPD_DPX: { + int new_status=0; + + switch(l) { + case 0: + new_status=VELOCITY_AUTONEG_ENABLE; + break; + case 1: + new_status=VELOCITY_SPEED_100; + break; + case 2: + new_status=VELOCITY_SPEED_100|VELOCITY_DUPLEX_FULL; + break; + case 3: + new_status=VELOCITY_SPEED_10; + break; + case 4: + new_status=VELOCITY_SPEED_10|VELOCITY_DUPLEX_FULL; + break; + } + + velocity_set_media_mode(&pInfo->hw,pInfo->hw.sOpts.spd_dpx); + } + break; + + case CONF_DMA_LEN: + if ((l<0)||(l>7)) + return -EINVAL; + pInfo->hw.sOpts.DMA_length=l; + mac_set_dma_length(&pInfo->hw,pInfo->hw.sOpts.DMA_length); + break; + + case CONF_WOL_OPTS: + if ((l<0)||(l>16)) + return -EINVAL; + pInfo->hw.sOpts.wol_opts=l; + if (l==0) + pInfo->hw.flags &=(~VELOCITY_FLAGS_WOL_ENABLED); + else + pInfo->hw.flags |=VELOCITY_FLAGS_WOL_ENABLED; + break; + + case CONF_FLOW_CTRL: + if (pInfo->hw.flags & VELOCITY_FLAGS_OPENED) + return -EACCES; + if ((l<1)||(l>3)) + return -EINVAL; + pInfo->hw.sOpts.flow_cntl=l; + break; + + case CONF_VAL_PKT: + if (l==0) { + pInfo->hw.flags &=~VELOCITY_FLAGS_VAL_PKT_LEN; + pInfo->hw.sOpts.flags &=~VELOCITY_FLAGS_VAL_PKT_LEN; + } + else if (l==1) { + pInfo->hw.flags |=VELOCITY_FLAGS_VAL_PKT_LEN; + pInfo->hw.sOpts.flags |=VELOCITY_FLAGS_VAL_PKT_LEN; + } + else + return -EINVAL; + break; + + case CONF_ENABLE_MRDPL: + if (l==0) { + pInfo->hw.flags &= ~VELOCITY_FLAGS_MRDPL; + pInfo->hw.sOpts.flags &= ~VELOCITY_FLAGS_VAL_PKT_LEN; + } + else if (l==1) { + pInfo->hw.flags |= VELOCITY_FLAGS_MRDPL; + pInfo->hw.sOpts.flags |= VELOCITY_FLAGS_MRDPL; + } + else + return -EINVAL; + break; + case CONF_ENABLE_TAG: + if (l==0) { + pInfo->hw.flags &=~VELOCITY_FLAGS_TAGGING; + pInfo->hw.sOpts.flags &=~VELOCITY_FLAGS_TAGGING; + } + else if (l==1) { + pInfo->hw.flags |=VELOCITY_FLAGS_TAGGING; + pInfo->hw.sOpts.flags |=VELOCITY_FLAGS_TAGGING; + } + else + return -EINVAL; + break; + case CONF_VID_SETTING: + if ((l<0) || (l>4094)) + return -EINVAL; + pInfo->hw.sOpts.vid=l; + pInfo->hw.flags |=VELOCITY_FLAGS_TAGGING; + pInfo->hw.sOpts.flags |=VELOCITY_FLAGS_TAGGING; + velocity_init_cam_filter(&pInfo->hw); + + break; + } + return 0; +} + +static void velocity_UpdateRMONStats(PVELOCITY_INFO pInfo) { + spin_lock_irq(&pInfo->lock); + velocity_update_hw_mibs(&pInfo->hw); + spin_unlock_irq(&pInfo->lock); +/* + pInfo->adwRMONStats[RMON_DropEvents] + pInfo->adwRMONStats[RMON_CRCAlignErrors] + pInfo->adwRMONStats[RMON_UndersizePkts] + pInfo->adwRMONStats[RMON_OversizePkts] + pInfo->adwRMONStats[RMON_Fragments] + pInfo->adwRMONStats[RMON_Jabbers] + pInfo->adwRMONStats[RMON_Collisions]*/ + + pInfo->adwRMONStats[RMON_MulticastPkts] + =pInfo->stats.multicast; + pInfo->adwRMONStats[RMON_Pkts] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRxAllPkts]; + pInfo->adwRMONStats[RMON_Pkts64Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx64Pkts]; + pInfo->adwRMONStats[RMON_Pkts65to127Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx65To127Pkts]; + pInfo->adwRMONStats[RMON_Pkts128to255Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx128To255Pkts]; + pInfo->adwRMONStats[RMON_Pkts256to511Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx256To511Pkts]; + pInfo->adwRMONStats[RMON_Pkts512to1023Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx512To1023Pkts]; + pInfo->adwRMONStats[RMON_Pkts1024to1518Octets] + =pInfo->hw.adwHWMIBCounters[HW_MIB_ifRx1024To1518Pkts]; + +} + +static int FunRMONRead(PVELOCITY_PROC_ENTRY pEntry,char* buf) { + PVELOCITY_INFO pInfo =pEntry->pInfo; + PROC_RMON_TYPE op =pEntry->data; + int len=0; + + if (op<0 || op>RMON_TAB_SIZE) + return -EINVAL; + + velocity_UpdateRMONStats(pInfo); + len=sprintf(buf,"%d",pInfo->adwRMONStats[op]); + return len; +} diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_proc.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_proc.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_proc.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_proc.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_proc.h + * + * Purpose: Header file for private proc structures. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_PROC_H__ +#define __VELOCITY_PROC_H__ + +#include "velocity.h" + +#define VELOCITY_PROC_READ 0x0001 +#define VELOCITY_PROC_WRITE 0x0002 +#define VELOCITY_PROC_DIR 0x0004 +#define VELOCITY_PROC_EOT 0xFFFF +#define VELOCITY_PROC_FILE (VELOCITY_PROC_READ|VELOCITY_PROC_WRITE) + +struct __velocity_info; +struct __velocity_proc_entry; + +typedef int (*VELOCITY_PROC_READ_FUNC)(struct __velocity_proc_entry*, char* buf); +typedef int (*VELOCITY_PROC_WRITE_FUNC)(struct __velocity_proc_entry*, const char* buf, unsigned long len); + +typedef enum __velocity_proc_rmon_type { + RMON_DropEvents = 0, // 0 + RMON_Octets, // 1 + RMON_Pkts, // 2 + RMON_BroadcastPkts, // 3 + RMON_MulticastPkts, // 4 + RMON_CRCAlignErrors, // 5 + RMON_UndersizePkts, // 6 + RMON_OversizePkts, // 7 + RMON_Fragments, // 8 + RMON_Jabbers, // 9 + RMON_Collisions, // 10 + RMON_Pkts64Octets, // 11 + RMON_Pkts65to127Octets, // 12 + RMON_Pkts128to255Octets, // 13 + RMON_Pkts256to511Octets, // 14 + RMON_Pkts512to1023Octets, // 15 + RMON_Pkts1024to1518Octets, // 16 + RMON_TAB_SIZE +} PROC_RMON_TYPE, *PPROC_RMON_TYPE; + +typedef struct __velocity_proc_entry { + char name[128]; + int type; + VELOCITY_PROC_READ_FUNC read_proc; + VELOCITY_PROC_WRITE_FUNC write_proc; + int data; + const struct __velocity_proc_entry* childs; + U8 byRevId; + struct proc_dir_entry* pOsEntry; + struct proc_dir_entry* pOsParent; + struct __velocity_info* pInfo; + const struct __velocity_proc_entry* siblings; +} VELOCITY_PROC_ENTRY, *PVELOCITY_PROC_ENTRY; + + +BOOL velocity_init_proc_fs(struct __velocity_info* pInfo); +void velocity_free_proc_fs(struct __velocity_info* pInfo); + +BOOL velocity_create_proc_entry(struct __velocity_info* pInfo); +void velocity_free_proc_entry(struct __velocity_info* pInfo); + +#endif // __VELOCITY_PROC_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_stats.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_stats.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_stats.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_stats.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_stats.h + * + * Purpose: Definitions for MAC hardware counters. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#ifndef __VELOCITY_STATS_H__ +#define __VELOCITY_STATS_H__ +/* +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TTCHAR_H__) +#include "ttchar.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif +*/ +typedef struct tagSAdapterInfo + SAdapterInfo, DEF* PSAdapterInfo; + +/*--------------------- Export Definitions -------------------------*/ +// +// Hardware counter +// +#define MAX_HW_MIB_COUNTER 32 + +typedef struct tagSHWMibCounter { + DWORD ifRxAllPkts; + DWORD ifRxOkPkts; + DWORD ifTxOkPkts; + DWORD ifRxErrorPkts; + DWORD ifRxRuntOkPkt; + DWORD ifRxRuntErrPkt; + DWORD ifRx64Pkts; + DWORD ifTx64Pkts; + DWORD ifRx65To127Pkts; + DWORD ifTx65To127Pkts; + DWORD ifRx128To255Pkts; + DWORD ifTx128To255Pkts; + DWORD ifRx256To511Pkts; + DWORD ifTx256To511Pkts; + DWORD ifRx512To1023Pkts; + DWORD ifTx512To1023Pkts; + DWORD ifRx1024To1518Pkts; + DWORD ifTx1024To1518Pkts; + DWORD ifTxEtherCollisions; + DWORD ifRxPktCRCE; + DWORD ifRxJumboPkts; + DWORD ifTxJumboPkts; + DWORD ifRxMacControlFrames; + DWORD ifTxMacControlFrames; + DWORD ifRxPktFAE; + DWORD ifRxLongOkPkt; + DWORD ifRxLongPktErrPkt; + DWORD ifTXSQEErrors; + DWORD ifRxNobuf; + DWORD ifRxSymbolErrors; + DWORD ifInRangeLenthErrors; + DWORD ifLateCollisions; +} SHWMibCounter, DEF* PSHWMibCounter; + +// +// MIB2 counter +// +typedef struct tagSMib2Counter { + LONG ifIndex; + TCHAR ifDescr[256]; // max size 255 plus zero ending + // e.g. "interface 1" + LONG ifType; + LONG ifMtu; + DWORD ifSpeed; + BYTE ifPhysAddress[U_ETHER_ADDR_LEN]; + LONG ifAdminStatus; + LONG ifOperStatus; + DWORD ifLastChange; + DWORD ifInOctets; + DWORD ifInUcastPkts; + DWORD ifInNUcastPkts; + DWORD ifInDiscards; + DWORD ifInErrors; + DWORD ifInUnknownProtos; + DWORD ifOutOctets; + DWORD ifOutUcastPkts; + DWORD ifOutNUcastPkts; + DWORD ifOutDiscards; + DWORD ifOutErrors; + DWORD ifOutQLen; + DWORD ifSpecific; +} SMib2Counter, DEF* PSMib2Counter; + + +// Value in the ifType entry +#define ETHERNETCSMACD 6 // + +// Value in the ifAdminStatus/ifOperStatus entry +#define UP 1 // +#define DOWN 2 // +#define TESTING 3 // + + +// +// RMON counter +// +typedef struct tagSRmonCounter { + LONG etherStatsIndex; + DWORD etherStatsDataSource; + DWORD etherStatsDropEvents; + DWORD etherStatsOctets; + DWORD etherStatsPkts; + DWORD etherStatsBroadcastPkts; + DWORD etherStatsMulticastPkts; + DWORD etherStatsCRCAlignErrors; + DWORD etherStatsLengthErrPkts; + DWORD etherStatsJumbos; + DWORD etherStatsCollisions; + DWORD etherStatsPkt64Octets; + DWORD etherStatsPkt65to127Octets; + DWORD etherStatsPkt128to255Octets; + DWORD etherStatsPkt256to511Octets; + DWORD etherStatsPkt512to1023Octets; + DWORD etherStatsPkt1024to1518Octets; + DWORD etherStatsOwners; + DWORD etherStatsStatus; +} SRmonCounter, DEF* PSRmonCounter; + +// Value in the etherStatsStatus entry +#define VALID 1 // +#define CREATE_REQUEST 2 // +#define UNDER_CREATION 3 // +#define INVALID 4 // + +// +// statistic counter +// +typedef struct tagSStatCounter { + // ISR0,1 status count + // + DWORD dwIsrPRxOK; + DWORD dwIsrPTxOK; + DWORD dwIsrRxOK; + DWORD dwIsrTxOK; + + DWORD dwIsrTxWB0I; + DWORD dwIsrTxWB1I; + + DWORD dwIsrRxPktRace; + DWORD dwIsrRxFifoOvfl; + DWORD dwIsrRxFlowOn; + DWORD dwIsrRxNoBuf; + DWORD dwIsrRxNoBufP; + + DWORD dwIsrLinkStatusChg; + + + // MISR0 + DWORD dwMisrSoftTimer0; + DWORD dwMisrSoftTimer1; + DWORD dwMisrPWE; + DWORD dwMisrPhyStatChg; + DWORD dwMisrShutDown; + DWORD dwMisrMibOvfl; + DWORD dwMisrUserDef; + + // MISR1 + DWORD dwMisrTxDmaErr; + DWORD dwMisrRxDmaErr; + + // TXE_SR/RXE_SR + DWORD dwTxEsrDmaBusErr; + DWORD dwTxEsrTDRBusErr; + DWORD dwTxEsrTDWBusErr; + DWORD dwTxEsrTDStrErr; + DWORD dwRxEsrDmaBusErr; + DWORD dwRxEsrRDRBusErr; + DWORD dwRxEsrRDWBusErr; + DWORD dwRxEsrRDStrErr; + + + DWORD dwIsrUnknown; // unknown interrupt count + + DWORD dwIntLinkUp; + DWORD dwIntLinkDown; + + // RSR0,1 status count + // + DWORD dwRsrCRCErr; + DWORD dwRsrFrmAlgnErr; + DWORD dwRsrCheckSumErr; + DWORD dwRsrLengthErr; + DWORD dwRsrPCSSymErr; + DWORD dwRsrSNTAG; + DWORD dwRsrDETAG; + + DWORD dwRsrVIDMiss; + DWORD dwRsrRxTag; + DWORD dwRsrBroadcast; + DWORD dwRsrMulticast; + DWORD dwRsrDirected; + DWORD dwRsrPerfectMatch; + DWORD dwRsrOK; + + DWORD dwRsrRxFrmLen64; + DWORD dwRsrRxFrmLen65_127; + DWORD dwRsrRxFrmLen128_255; + DWORD dwRsrRxFrmLen256_511; + DWORD dwRsrRxFrmLen512_1023; + DWORD dwRsrRxFrmLen1024_1518; + + DWORD dwRsrRxPacket; + DWORD dwRsrRxOctet; + DWORD dwRsrRxTagFrame; + + // TSR0,1 status count + // + DWORD dwTsrTotalColRetry; // total collision retry count + DWORD dwTsrOnceCollision; // this packet only occur one collision + DWORD dwTsrMoreThanOnceCollision; // this packet occur more than one collision + + DWORD dwTsrCollision; // this packet has ever occur collision, + // that is (dwTsrOnceCollision + dwTsrMoreThanOnceCollision) + DWORD dwTsrHeartBeat; + DWORD dwTsrAbort; + DWORD dwTsrLateCollision; + DWORD dwTsrCarrierLost; + DWORD dwTsrJumboAbort; + DWORD dwTsrLNKFL; + DWORD dwTsrShutDown; + DWORD dwTsrGMII; + DWORD dwTsrFDX; + + DWORD dwTsrErr; // GOWC | OWT | ABT | SHDN + DWORD dwTsrOK; + + DWORD dwTsrTxPacket; + DWORD dwTsrTxOctet; + + DWORD dwTsrBroadcast; + DWORD dwTsrMulticast; + DWORD dwTsrDirected; + + + // RD/TD count + DWORD dwCntRxFrmLength; + DWORD dwCntTxBufLength; + + BYTE abyCntRxPattern[16]; + BYTE abyCntTxPattern[16]; + + // for pingpong + DWORD dwCntNoResponse; + DWORD dwCntSerialNumErr; + + // PATCH.... + DWORD dwCntRxDataErr; // rx buffer data software compare CRC err count + DWORD dwIsrContinuePktRace; // if continueous packet-race happen, should reset + DWORD dwIsrContinueNoBuf; // if continueous no-buffer + +} SStatCounter, DEF* PSStatCounter; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +VOID STAvClearAllCounter(PSStatCounter pStatistic); + +VOID STAvUpdateEsrStatCounter(PSStatCounter pStatistic, BYTE byEsr, BOOL bTx); +VOID STAvUpdateIsrStatCounter(PSStatCounter pStatistic, DWORD dwIsr, WORD wEsr); + +VOID STAvUpdateRDStatCounter(PSStatCounter pStatistic, PSRxDesc prdCurr, + PBYTE pbyBuffer, UINT cbFrameLength); + +VOID STAvUpdateRDStatCounterEx(PSStatCounter pStatistic, PSRxDesc prdCurr, + PBYTE pbyBuffer, UINT cbFrameLength); + +VOID STAvUpdateTDStatCounter(PSStatCounter pStatistic, PSTxDesc ptdCurr, + PBYTE pbyBuffer, UINT cbFrameLength); + +VOID STAvUpdateTDStatCounterEx(PSStatCounter pStatistic, PSTxDesc ptdCurr, + PBYTE pbyBuffer, DWORD cbFrameLength); + +VOID STAvClearHWMIBCounter(DWORD dwIoBase); +VOID STAvEnableHWMIBCounter(DWORD dwIoBase); +VOID STAvUpdateHWMIBCounter(DWORD dwIoBase, PSHWMibCounter pCounter); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __VELOCITY_STATS_H__ diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_wol.c linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_wol.c --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_wol.c 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_wol.c 2006-10-23 10:58:14 +0200 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_wol.c + * + * Purpose: Functions to set WOL. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + + +#include + +#if !defined(__VELOCITY_H__) +#include "velocity.h" +#endif +#if !defined(__VELOCITY_WOL_H__) +#include "velocity_wol.h" +#endif + +const static unsigned short Crc16Tab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + + +static U32 adwMaskPattern[2][4]={ + {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, //ARP + {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} //Magic Packet +}; + +static U16 ether_crc16( int len, PU8 cp , U16 Crc16) { + while(len--) + Crc16 = (Crc16 >> 8) ^ Crc16Tab[(Crc16 ^ *cp++) & 0xff]; + return (Crc16); +} + +static U16 wBitReverseForWord (U16 wData) +{ + U32 dwNewData = 0x00000000; + int ii; + + + for (ii = 0; ii < 16; ii++) { + dwNewData |= ((U32) (wData & 1) << (31 - ii)); + wData>>=1; + } + + return (U16)(dwNewData >> 16); +} + +U16 WOLCalCRC (int size, PU8 pbyPattern, PU8 abyMaskPattern) +{ + U16 wCrc = 0xFFFF; + U8 byMask; + int i, j; + + for (i = 0; i >= 1; + continue; + } + + byMask >>= 1; + wCrc = ether_crc16(1, &(pbyPattern[i * 8 + j]), wCrc); + } + } + + // finally, invert the result once to get the correct data + wCrc = ~wCrc; + + return wBitReverseForWord(wCrc); +} + +BOOL velocity_set_wol(PVELOCITY_INFO pInfo) { + //PMAC_REGS pMacRegs=pInfo->pMacRegs; + static BYTE abyBuf[256]; + int i; + + CSR_WRITE_2(&pInfo->hw, 0xFFFF, MAC_REG_WOLSR0_CLR); + CSR_WRITE_1(&pInfo->hw, WOLCFG_SAB|WOLCFG_SAM, MAC_REG_WOLCFG_SET); + CSR_WRITE_2(&pInfo->hw, WOLCR_MAGIC_EN, MAC_REG_WOLCR0_SET); + + /* + if (pInfo->wol_opts & VELOCITY_WOL_PHY) + writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), &pMacRegs->wWOLCRSet); + */ + + if (pInfo->wol_opts & VELOCITY_WOL_UCAST) { + CSR_WRITE_2(&pInfo->hw, WOLCR_UNICAST_EN, MAC_REG_WOLCR0_SET); + } + + if (pInfo->wol_opts & VELOCITY_WOL_ARP) { + PARP_PACKET pPacket=(PARP_PACKET) abyBuf; + U16 wCRC; + memset(abyBuf,0,sizeof(ARP_PACKET)+7); + + for (i=0;i<4;i++) + CSR_WRITE_4(&pInfo->hw, adwMaskPattern[0][i], (MAC_REG_BYTEMSK0_0+i*4)); + + pPacket->wType=htons(ETH_P_ARP); + pPacket->ar_op=htons(1); + + memcpy(pPacket->ar_tip,pInfo->abyIPAddr,4); + + wCRC=WOLCalCRC((sizeof(ARP_PACKET)+7)/8, + abyBuf,(PU8)&adwMaskPattern[0][0]); + + CSR_WRITE_2(&pInfo->hw, wCRC, MAC_REG_PATRN_CRC0); + CSR_WRITE_2(&pInfo->hw, WOLCR_ARP_EN, MAC_REG_WOLCR0_SET); + } + + + BYTE_REG_BITS_ON(&pInfo->hw, PWCFG_WOLTYPE, MAC_REG_PWCFG_SET); + BYTE_REG_BITS_ON(&pInfo->hw, PWCFG_LEGACY_WOLEN, MAC_REG_PWCFG_SET); + + CSR_WRITE_2(&pInfo->hw, 0x0FFF, MAC_REG_WOLSR0_CLR); + + if (pInfo->hw.mii_status & VELOCITY_AUTONEG_ENABLE) { + if (PHYID_GET_PHY_ID(pInfo->hw.dwPHYId)==PHYID_CICADA_CS8201) + MII_REG_BITS_ON(AUXCR_MDPPS,MII_REG_AUXCR,&pInfo->hw); + + MII_REG_BITS_OFF(G1000CR_1000FD|G1000CR_1000, + MII_REG_G1000CR,&pInfo->hw); + } + + if (pInfo->hw.mii_status & VELOCITY_SPEED_1000) + MII_REG_BITS_ON(BMCR_REAUTO,MII_REG_BMCR,&pInfo->hw); + + BYTE_REG_BITS_ON(&pInfo->hw, CHIPGCR_FCMODE, MAC_REG_CHIPGCR); + + { + U8 byGCR; + byGCR=CSR_READ_1(&pInfo->hw, MAC_REG_CHIPGCR); + byGCR=(byGCR & ~CHIPGCR_FCGMII) |CHIPGCR_FCFDX; + CSR_WRITE_1(&pInfo->hw, byGCR, MAC_REG_CHIPGCR); + } + + BYTE_REG_BITS_OFF(&pInfo->hw, ISR_PWEI, MAC_REG_ISR); + // Turn on SWPTAG just before entering power mode + BYTE_REG_BITS_ON(&pInfo->hw, STICKHW_SWPTAG, MAC_REG_STICKHW); + //Go to bed ..... + BYTE_REG_BITS_ON(&pInfo->hw, (STICKHW_DS1|STICKHW_DS0), + MAC_REG_STICKHW); + + return FALSE; +} + +void velocity_save_mac_context(struct velocity_hw *hw,PVELOCITY_CONTEXT pContext) { + //PMAC_REGS pMacRegs=pInfo->pMacRegs; + U16 i; + + for (i=MAC_REG_PAR;iabyMacRegs+i))=CSR_READ_4(hw, i); + + for (i=MAC_REG_MAR;iabyMacRegs+i))=CSR_READ_4(hw, i); + + for (i=MAC_REG_RDBASE_LO;iabyMacRegs+i))=CSR_READ_4(hw, i); + +} + +void velocity_restore_mac_context(struct velocity_hw *hw, PVELOCITY_CONTEXT pContext) { + //PMAC_REGS pMacRegs=pInfo->pMacRegs; + int i; + + for (i=MAC_REG_PAR;iabyMacRegs+i)),i); + } + + //Just skip cr0 + for (i=MAC_REG_CR1_SET;iabyMacRegs+i))), i+4); + //Set + CSR_WRITE_1(hw, *((PU8)(pContext->abyMacRegs+i)), i); + } + + for (i=MAC_REG_MAR;iabyMacRegs+i)),i); + } + + for (i=MAC_REG_RDBASE_LO;iabyMacRegs+i)), i); + } + + for (i=MAC_REG_TDCSR_SET;i<=MAC_REG_RDCSR_SET;i++) { + CSR_WRITE_1(hw, *((PU8)(pContext->abyMacRegs+i)), i); + } +} + +void +velocity_save_pci_context(PVELOCITY_INFO pInfo, PU32 pContext) { + // save MODE0 ~ MODE3 registers + pci_read_config_dword(pInfo->pcid, PCI_REG_MODE0, pContext); +} + +void +velocity_restore_pci_context(PVELOCITY_INFO pInfo, U32 Context) { + // restore MODE0 ~ MODE3 registers + pci_write_config_dword(pInfo->pcid, PCI_REG_MODE0, Context); +} diff -urN linux-2.4.33-wt1/drivers/net/velocityget/velocity_wol.h linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_wol.h --- linux-2.4.33-wt1/drivers/net/velocityget/velocity_wol.h 1970-01-01 01:00:00 +0100 +++ linux-2.4.33-wt1-via/drivers/net/velocityget/velocity_wol.h 2006-10-23 10:58:13 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * + * File: velocity_wol.h + * + * Purpose: Hearder for WOL definitions. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + */ + +#ifndef __VELOCITY_WOL_H__ +#define __VELOCITY_WOL_H__ + +#include "velocity.h" + +struct __velocity_info; + +typedef U8 MCAM_ADDR[ETH_ALEN]; + +typedef +struct _arp_packet { + U8 abyDMAC[ETH_ALEN]; + U8 abySMAC[ETH_ALEN]; + U16 wType; + U16 ar_hrd; + U16 ar_pro; + U8 ar_hln; + U8 ar_pln; + U16 ar_op; + U8 ar_sha[ETH_ALEN]; + U8 ar_sip[4]; + U8 ar_tha[ETH_ALEN]; + U8 ar_tip[4]; +} __attribute__ ((__packed__)) +ARP_PACKET, *PARP_PACKET; + +typedef +struct _magic_packet { + U8 abyDMAC[6]; + U8 abySMAC[6]; + U16 wType; + U8 abyMAC[16][6]; + U8 abyPassword[6]; +} +__attribute__ ((__packed__)) +MAGIC_PACKET, *PMAGIC_PACKET; + +typedef +struct __velocity_context { + U8 abyMacRegs[256]; + MCAM_ADDR aMcamAddr[MCAM_SIZE]; + U16 awVcam[VCAM_SIZE]; + U32 dwCammask[2]; + U32 dwPatCRC[2]; + U32 dwPattern[8]; +} VELOCITY_CONTEXT, *PVELOCITY_CONTEXT; + + +BOOL velocity_set_wol(struct __velocity_info*); +void velocity_save_mac_context(struct velocity_hw* hw, PVELOCITY_CONTEXT pContext); +void velocity_restore_mac_context(struct velocity_hw* hw, PVELOCITY_CONTEXT pContext); +void velocity_save_pci_context(struct __velocity_info* pInfo, PU32 pContext); +void velocity_restore_pci_context(struct __velocity_info* pInfo, U32 pContext); + +#endif // __VELOCITY_WOL_H__