Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 217 → Rev 218

/shark/trunk/drivers/net/3c59x.c
14,9 → 14,89
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/
 
static char *version =
"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
/*
15Apr00, Andrew Morton <andrewm@uow.edu.au>
- Don't set RxComplete in boomerang interrupt enable reg
- Added standard spinlocking.
- Removed setting/clearing of dev->interrupt
- Removed vp->in_interrupt
- spinlock in vortex_timer to protect mdio functions
- disable local interrupts around call to vortex_interrupt in
vortex_tx_timeout() (So vortex_interrupt can use spin_lock())
- Removed global save/restore_flags() and cli() from get_stats
and vortex_start_xmit()
- Select window 3 in vortex_timer()'s write to Wn3_MAC_Ctrl
- In vortex_start_xmit(), move the lock to _after_ we've altered
vp->cur_tx and vp->tx_full. This defeats the race between
vortex_start_xmit() and vortex_interrupt which was identified
by Bogdan Costescu.
- Merged back support for six new cards from various sources
- Tell it that 3c905C has NWAY
- Fix handling of SetStatusEnd in 'Too much work..' code, as
per 2.3.99's 3c575_cb (Dave Hinds). Added vp->deferred for this.
 
24May00 <2.2.16-pre4> andrewm
- Replace union wn3_config with BFINS/BFEXT manipulation for
sparc64 (Pete Zaitcev, Peter Jones)
- Use insl_ns/outsl_ns for __powerpc__ (Andreas Tobler)
- In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex): clear
tbusy and force a BH rerun to better recover from errors.
 
24Jun00 <2.2.16> andrewm
- Better handling of shared interrupts
- Reset the transmitter in vortex_error() on both maxcollisions and Tx reclaim error
- Split the ISR into vortex_interrupt and boomerang_interrupt. This is
to fix once-and-for-all the dubious testing of vortex status bits on
boomerang/hurricane/cyclone/tornado NICs.
- Fixed crash under OOM during vortex_open() (Mark Hemment)
- Fix Rx cessation problem during OOM (help from Mark Hemment)
 
01Aug00 <2.2.17-pre14> andrewm
- Added 3c556 support (Fred Maciel)
 
16Aug00 <2.2.17-pre17> andrem
- In vortex_error: don't reset the Tx after txReclaim or maxCollisions errors
- In vortex_error(do_tx_reset): only reset dev->tbusy for vortex-style NICs.
- In vortex_open(), set vp->tx_full to zero (else we get errors if the device was
closed with a full Tx ring).
 
17Oct00 <2.2.18-pre16> andrewm
- Added support for the 3c556B Laptop Hurricane (Louis Gerbarg)
- Backported transceiver options handling from 2.4. This changes the semantics
of forcing full duplex in the `options' parm! (It's better to use
`full_duplex' anyway). See Documentation/vortex.txt (Maciej Rozycki).
- Set PCI latency timer to maximum for the 3c590 (From Donald's driver)
- Removed all the CARDBUS code (it's never used).
- Added INVERT_MII_PWR, EEPROM_8BIT, EEPROM_OFFSET. Use them.
- Use EEPROM_8BIT for the 3c555
- Merged ACPI WOL support from Donald's drivers.
- Sort-of backported Donald's new medialock code. Called it duplexlock
and we now prefer to use `full_duplex=[-1,0,1]' to force duplex mode.
- Merged the rx_oom_timer from 2.4. This gives better handling of OOM
conditions. Backed out the previous way of handling this.
- Replace suser() with capable(CAP_NET_ADMIN) in ioctl().
 
07Jan01 <2.2.19-pre6> andrewm
- Add HAS_NWAY to "3c900 Cyclone 10Mbps TPO"
- Added and used wait_for_completion(). 3c905CX problems.
- Removed the code for older kernel versions.
- Add HAS_NWAY to 3cSOHO100-TX (Brett Frankenberger)
- Search for phy 24 first for 3c905CX. (D Becker)
- Don't free skbs we don't own on oom path in vortex_open().
- Added explicit `medialock' flag so we can truly
lock the media type down with `options'.
- In vortex_error(), only reset the up/down load engine, not all the
interface stuff.
- Added and used EEPROM_NORESET for 3c556B PM resumes.
- Enable WOL with the `enable_wol' module parm
- Give the 3c980 HAS_NWAY
 
- See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.2 for more details.
*/
 
static char version[] =
"3c59x.c 18Feb01 Donald Becker and others http://www.scyld.com/network/vortex.html\n";
 
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
31,7 → 111,7
#ifdef VORTEX_DEBUG
static int vortex_debug = VORTEX_DEBUG;
#else
static int vortex_debug = 1;
static int vortex_debug = 0;
#endif
 
/* Some values here only for performance evaluation and path-coverage
49,16 → 129,6
 
#include <linux/config.h>
#include <linux/version.h>
#ifdef MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif
 
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
72,9 → 142,8
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS)
#include <linux/bios32.h>
#endif
#include <linux/delay.h>
#include <linux/module.h>
#include <asm/irq.h> /* For NR_IRQS only. */
#include <asm/bitops.h>
#include <asm/io.h>
84,48 → 153,18
 
#define RUN_AT(x) (jiffies + (x))
 
#include <linux/delay.h>
 
#if (LINUX_VERSION_CODE <= 0x20100)
#ifndef __alpha__
#define ioremap(a,b) \
(((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
#define iounmap(v) \
do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
#endif
#endif
#if LINUX_VERSION_CODE <= 0x20139
#define net_device_stats enet_statistics
#define NETSTATS_VER2
#endif
#if LINUX_VERSION_CODE < 0x20138
#define test_and_set_bit(val, addr) set_bit(val, addr)
#define le32_to_cpu(val) (val)
#define cpu_to_le32(val) (val)
#endif
#if LINUX_VERSION_CODE < 0x20155
#define PCI_SUPPORT_VER1
#else
#define PCI_SUPPORT_VER2
#endif
#if LINUX_VERSION_CODE < 0x20159
#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
#else /* Grrr, unneeded incompatible change. */
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
#endif
 
#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
MODULE_PARM(debug, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(enable_wol, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
MODULE_PARM(compaq_device_id, "i");
#endif
 
/* Operational parameter that usually are not changed. */
 
233,8 → 272,10
long ioaddr, int irq, int chip_idx, int fnd_cnt);
};
 
enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80,
INVERT_MII_PWR=0x100, EEPROM_8BIT=0x200, EEPROM_OFFSET=0x400,
EEPROM_NORESET=0x800};
static struct device *vortex_probe1(int pci_bus, int pci_devfn,
struct device *dev, long ioaddr,
int irq, int dev_id, int card_idx);
241,6 → 282,10
static struct pci_id_info pci_tbl[] = {
{"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
{"3c592 EISA 10mbps Demon/Vortex", 0x10B7, 0x5920, 0xffff, /* AKPM: from Don's 3c59x_cb.c 0.49H */
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
{"3c597 EISA Fast Demon/Vortex", 0x10B7, 0x5970, 0xffff, /* AKPM: from Don's 3c59x_cb.c 0.49H */
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
{"3c595 Vortex 100baseTx", 0x10B7, 0x5950, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
{"3c595 Vortex 100baseT4", 0x10B7, 0x5951, 0xffff,
247,6 → 292,8
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
{"3c595 Vortex 100base-MII", 0x10B7, 0x5952, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
 
#define EISA_TBL_OFFSET 6 /* AKPM: the offset of this entry */
{"3Com Vortex", 0x10B7, 0x5900, 0xff00,
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
{"3c900 Boomerang 10baseT", 0x10B7, 0x9000, 0xffff,
257,6 → 304,10
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
{"3c900B-FL Cyclone 10base-FL", 0x10B7, 0x900A, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
{"3c900 Cyclone 10Mbps TPO", 0x10B7, 0x9004, 0xffff, /* AKPM: from Don's 0.99M */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
{"3c900 Cyclone 10Mbps TPC", 0x10B7, 0x9006, 0xffff, /* AKPM: from Don's 0.99M */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
{"3c905 Boomerang 100baseTx", 0x10B7, 0x9050, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
{"3c905 Boomerang 100baseT4", 0x10B7, 0x9051, 0xffff,
268,13 → 319,17
{"3c905B-FX Cyclone 100baseFx", 0x10B7, 0x905A, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
{"3c905C Tornado", 0x10B7, 0x9200, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, vortex_probe1},
{"3c980 Cyclone", 0x10B7, 0x9800, 0xfff0,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
{"3cSOHO100-TX Hurricane", 0x10B7, 0x7646, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
{"3c555 Laptop Hurricane", 0x10B7, 0x5055, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT, 128, vortex_probe1},
{"3c556 10/100 Mini PCI Adapter", 0x10B7, 0x6055, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, vortex_probe1},
{"3c556B Laptop Hurricane", 0x10B7, 0x6056, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|EEPROM_NORESET, 128, vortex_probe1},
{"3c575 Boomerang CardBus", 0x10B7, 0x5057, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
{"3CCFE575 Cyclone CardBus", 0x10B7, 0x5157, 0xffff,
283,8 → 338,13
{"3CCFE656 Cyclone CardBus", 0x10B7, 0x6560, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
128, vortex_probe1},
{"3CCFEM656 Cyclone CardBus", 0x10B7, 0x6562, 0xffff, /* AKPM: From the 2.3 driver ? */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
128, vortex_probe1},
{"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
{"3c450 HomePNA Tornado", 0x10B7, 0x4500, 0xffff, /* AKPM: from Don's 0.99P */
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, vortex_probe1},
{"3Com Boomerang (unknown version)", 0x10B7, 0x9000, 0xff00,
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
{0,}, /* 0 terminated list. */
363,16 → 423,22
enum Window3 { /* Window 3: MAC/config bits. */
Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
};
union wn3_config {
int i;
struct w3_config_fields {
unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
int pad8:8;
unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
int pad24:7;
} u;
};
 
#define BFEXT(value, offset, bitcount) \
((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1))
 
#define BFINS(lhs, rhs, offset, bitcount) \
(((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \
(((rhs) & ((1 << (bitcount)) - 1)) << (offset)))
 
#define RAM_SIZE(v) BFEXT(v, 0, 3)
#define RAM_WIDTH(v) BFEXT(v, 3, 1)
#define RAM_SPEED(v) BFEXT(v, 4, 2)
#define ROM_SIZE(v) BFEXT(v, 6, 2)
#define RAM_SPLIT(v) BFEXT(v, 16, 2)
#define XCVR(v) BFEXT(v, 20, 4)
#define AUTOSELECT(v) BFEXT(v, 24, 1)
 
enum Window4 { /* Window 4: Xcvr/media bits. */
Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
};
424,7 → 490,7
};
 
/* Chip features we care about in vp->capabilities, read from the EEPROM. */
enum ChipCaps { CapBusMaster=0x20 };
enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
 
struct vortex_private {
/* The Rx and Tx rings should be quad-word-aligned. */
446,16 → 512,19
int chip_id;
 
/* The remainder are related to chip state, mostly media selection. */
unsigned long in_interrupt;
struct timer_list timer; /* Media selection timer. */
struct timer_list rx_oom_timer; /* Rx skb allocation retry timer */
int options; /* User-settable misc. driver options. */
unsigned int media_override:3, /* Passed-in media type. */
unsigned int media_override:4, /* Passed-in media type. */
default_media:4, /* Read from the EEPROM/Wn3_Config. */
full_duplex:1, force_fd:1, autoselect:1,
full_duplex:1, /* User wants FD (or we're running at FD) */
duplexlock:1, /* User has forced duplex */
autoselect:1, /* Can use NWAY negotiation */
bus_master:1, /* Vortex can only do a fragment bus-m. */
full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
hw_csums:1, /* Has hardware checksums. */
tx_full:1;
tx_full:1,
enable_wol:1,
medialock:1;
u16 status_enable;
u16 intr_enable;
u16 available_media; /* From Wn3_Options. */
462,6 → 531,9
u16 capabilities, info1, info2; /* Various, from EEPROM. */
u16 advertising; /* NWay media advertisement */
unsigned char phys[2]; /* MII device addresses. */
u16 deferred; /* Resend these interrupts when we
* bale from the ISR */
spinlock_t lock;
};
 
/* The action to take with a media selection timer tick.
492,130 → 564,51
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
 
#ifndef CARDBUS
static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[]);
#endif
static int vortex_open(struct device *dev);
static void mdio_sync(long ioaddr, int bits);
static int mdio_read(long ioaddr, int phy_id, int location);
static void mdio_write(long ioaddr, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg);
static void rx_oom_timer(unsigned long arg);
static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
static int vortex_rx(struct device *dev);
static int boomerang_rx(struct device *dev);
static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct device *dev);
static void update_stats(long ioaddr, struct device *dev);
static struct net_device_stats *vortex_get_stats(struct device *dev);
static void set_rx_mode(struct device *dev);
static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
static void acpi_wake(int pci_bus, int pci_devfn);
static void acpi_set_WOL(struct device *dev);
 
#if 0
#warning dev_alloc_skb_debug is defined!
#define dev_alloc_skb dev_alloc_skb_debug
#endif
 
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
/* Option count limit only -- unlimited interfaces are supported. */
#define MAX_UNITS 8
static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1};
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* A list of all installed Vortex devices, for removing the driver module. */
static struct device *root_vortex_dev = NULL;
 
#ifdef MODULE
#ifndef CARDBUS
/* Variables to work-around the Compaq PCI BIOS32 problem. */
static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
#endif
 
#ifdef CARDBUS
 
#include <pcmcia/driver_ops.h>
 
static dev_node_t *vortex_attach(dev_locator_t *loc)
{
u16 dev_id, vendor_id;
u32 io;
u8 bus, devfn, irq;
struct device *dev;
int chip_idx;
 
if (loc->bus != LOC_PCI) return NULL;
bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
bus, devfn, dev_id);
io &= ~3;
if (io == 0 || irq == 0) {
printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
"assigned an %s.\n" KERN_ERR " It will not be activated.\n",
io == 0 ? "I/O address" : "IRQ");
return NULL;
}
for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
if (vendor_id == pci_tbl[chip_idx].vendor_id
&& (dev_id & pci_tbl[chip_idx].device_id_mask) ==
pci_tbl[chip_idx].device_id)
break;
if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */
printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
"vortex_attach().\n", vendor_id, dev_id);
return NULL;
}
dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
node->major = node->minor = 0;
node->next = NULL;
MOD_INC_USE_COUNT;
return node;
}
return NULL;
}
 
static void vortex_detach(dev_node_t *node)
{
struct device **devp, **next;
printk(KERN_INFO "vortex_detach(%s)\n", node->dev_name);
for (devp = &root_vortex_dev; *devp; devp = next) {
next = &((struct vortex_private *)(*devp)->priv)->next_module;
if (strcmp((*devp)->name, node->dev_name) == 0) break;
}
if (*devp) {
struct device *dev = *devp;
struct vortex_private *vp = dev->priv;
if (dev->flags & IFF_UP)
vortex_close(dev);
dev->flags &= ~(IFF_UP|IFF_RUNNING);
unregister_netdev(dev);
if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
kfree(dev);
*devp = *next;
kfree(vp);
kfree(node);
MOD_DEC_USE_COUNT;
}
}
 
struct driver_operations vortex_ops = {
"3c575_cb", vortex_attach, NULL, NULL, vortex_detach
};
 
#endif /* Cardbus support */
 
 
int init_module(void)
{
if (vortex_debug)
printk(KERN_INFO "%s", version);
#ifdef CARDBUS
register_driver(&vortex_ops);
return 0;
#else
return vortex_scan(0, pci_tbl);
#endif
}
 
#else
629,7 → 622,30
}
#endif /* not MODULE */
 
#ifndef CARDBUS
static void wait_for_completion(struct device *dev, int cmd)
{
int i;
 
outw(cmd, dev->base_addr + EL3_CMD);
for (i = 0; i < 2000; i++) {
if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
return;
}
 
/* OK, that didn't work. Do it the slow way. One second */
for (i = 0; i < 100000; i++) {
if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
if (vortex_debug > 1)
printk(KERN_INFO "%s: command 0x%04x took %d usecs!\n",
dev->name, cmd, i * 10);
return;
}
udelay(10);
}
printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
}
 
static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[])
{
int cards_found = 0;
650,8 → 666,7
long ioaddr;
 
if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
&pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
&pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL)
break;
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_VENDOR_ID, &vendor);
665,21 → 680,13
if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
continue;
 
/* The Cyclone requires config space re-write if powered down. */
acpi_wake(pci_bus, pci_device_fn);
 
{
#if LINUX_VERSION_CODE >= 0x20155
struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
ioaddr = pdev->base_address[0] & ~3;
irq = pdev->irq;
#else
u32 pci_ioaddr;
u8 pci_irq_line;
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &pci_irq_line);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
ioaddr = pci_ioaddr & ~3;;
irq = pci_irq_line;
#endif
}
 
/* Power-up the card. */
727,21 → 734,21
chip_idx, cards_found);
 
if (dev) {
if ((device & 0xff00) == 0x5900) {
/* Get and check the latency values. On the 3c590 series
the latency timer must be set to the maximum value to avoid
data corruption that occurs when the timer expires during
a transfer -- a bug in the Vortex chip only. */
u8 pci_latency;
u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
u8 new_latency = 248;
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_LATENCY_TIMER, &pci_latency);
pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < new_latency) {
printk(KERN_INFO "%s: Overriding PCI latency"
" timer (CFLT) setting of %d, new value is %d.\n",
dev->name, pci_latency, new_latency);
pcibios_write_config_byte(pci_bus, pci_device_fn,
PCI_LATENCY_TIMER, new_latency);
pcibios_write_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, new_latency);
}
}
dev = 0;
cards_found++;
765,7 → 772,7
if ((device_id & 0xFF00) != 0x5900)
continue;
vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
4, cards_found);
EISA_TBL_OFFSET, cards_found);
dev = 0;
cards_found++;
}
782,7 → 789,6
 
return cards_found ? 0 : -ENODEV;
}
#endif /* ! Cardbus */
 
static struct device *vortex_probe1(int pci_bus, int pci_devfn,
struct device *dev, long ioaddr,
794,6 → 800,10
int i;
 
dev = init_etherdev(dev, 0);
if (dev == NULL) {
printk(KERN_EMERG "3c59x: init_etherdev failed\n");
return NULL;
}
 
printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
dev->name, pci_tbl[chip_idx].name, ioaddr);
805,30 → 815,44
/* Make certain the descriptor lists are aligned. */
{
void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
if (!mem) {
printk(KERN_EMERG "3c59x: out of memory for dev->priv\n");
unregister_netdev(dev);
kfree(dev);
return NULL;
}
vp = (void *)(((long)mem + 15) & ~15);
memset(vp, 0, sizeof(*vp));
vp->priv_addr = mem;
}
memset(vp, 0, sizeof(*vp));
dev->priv = vp;
 
vp->next_module = root_vortex_dev;
root_vortex_dev = dev;
 
spin_lock_init(&vp->lock);
vp->chip_id = chip_idx;
vp->pci_bus = pci_bus;
vp->pci_devfn = pci_devfn;
 
/* The lower four bits are the media type. */
option = -1;
if (dev->mem_start)
option = dev->mem_start;
else if (card_idx < MAX_UNITS)
option = options[card_idx];
else
option = -1;
 
if (option >= 0) {
vp->media_override = ((option & 7) == 2) ? 0 : option & 7;
vp->full_duplex = (option & 8) ? 1 : 0;
vp->media_override = ((option & 7) == 2) ? 0 : option & 15;
if (vp->media_override != 7)
vp->medialock = 1;
if (option & 0x200) {
vp->full_duplex = 1;
vp->duplexlock = 1;
printk( "\n" KERN_WARNING
"%s: forcing duplex via options is deprecated - use `full_duplex'.\n",
dev->name);
}
vp->bus_master = (option & 16) ? 1 : 0;
} else {
vp->media_override = 7;
835,21 → 859,35
vp->full_duplex = 0;
vp->bus_master = 0;
}
if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
if (card_idx < MAX_UNITS) {
if (enable_wol[card_idx] > 0)
vp->enable_wol = 1;
if (full_duplex[card_idx] == 0) { /* full_duplex=0 : force half duplex */
vp->duplexlock = 1;
}
if (full_duplex[card_idx] > 0) { /* full_duplex=1: force full duplex */
vp->duplexlock = 1;
vp->full_duplex = 1;
 
vp->force_fd = vp->full_duplex;
}
/* full_duplex=-1: duplex is not forced */
}
vp->options = option;
 
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
{
int base;
 
if (pci_tbl[chip_idx].drv_flags & EEPROM_8BIT)
base = 0x230;
else if (pci_tbl[chip_idx].drv_flags & EEPROM_OFFSET)
base = EEPROM_Read + 0x30;
else
base = EEPROM_Read;
 
for (i = 0; i < 0x40; i++) {
int timer;
#ifdef CARDBUS
outw(0x230 + i, ioaddr + Wn0EepromCmd);
#else
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
#endif
outw(base + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
for (timer = 10; timer >= 0; timer--) {
udelay(162);
858,6 → 896,8
}
eeprom[i] = inw(ioaddr + Wn0EepromData);
}
}
 
for (i = 0; i < 0x18; i++)
checksum ^= eeprom[i];
checksum = (checksum ^ (checksum >> 8)) & 0xff;
866,7 → 906,7
checksum ^= eeprom[i++];
checksum = (checksum ^ (checksum >> 8)) & 0xff;
}
if (checksum != 0x00)
if (checksum != 0x00 && !(pci_tbl[chip_idx].drv_flags & IS_TORNADO))
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
 
for (i = 0; i < 3; i++)
885,6 → 925,7
 
if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
u16 n;
pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
&fn_st_addr);
if (fn_st_addr)
892,7 → 933,12
printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
" brain-damage).\n", dev->name, fn_st_addr, vp->cb_fn_base);
EL3WINDOW(2);
outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
 
n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
n |= 0x10;
if (pci_tbl[chip_idx].drv_flags & INVERT_MII_PWR)
n |= 0x4000;
outw(n, ioaddr + Wn2_ResetOptions);
}
 
/* Extract our information from the EEPROM data. */
900,29 → 946,29
vp->info2 = eeprom[15];
vp->capabilities = eeprom[16];
 
if (vp->info1 & 0x8000)
if (!vp->duplexlock && (vp->info1 & 0x8000))
vp->full_duplex = 1;
 
{
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
union wn3_config config;
unsigned int config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */
vp->available_media = 0x40;
config.i = inl(ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);
if (vortex_debug > 1)
printk(KERN_DEBUG " Internal config register is %4.4x, "
"transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options));
"transceivers %#x.\n", config, inw(ioaddr + Wn3_Options));
printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
8 << config.u.ram_size,
config.u.ram_width ? "word" : "byte",
ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect/" : "",
config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
media_tbl[config.u.xcvr].name);
vp->default_media = config.u.xcvr;
vp->autoselect = config.u.autoselect;
8 << RAM_SIZE(config),
RAM_WIDTH(config) ? "word" : "byte",
ram_split[RAM_SPLIT(config)],
AUTOSELECT(config) ? "autoselect/" : "",
XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" :
media_tbl[XCVR(config)].name);
vp->default_media = XCVR(config);
vp->autoselect = AUTOSELECT(config);
}
 
if (vp->media_override != 7) {
938,8 → 984,19
mii_preamble_required++;
mii_preamble_required++;
mdio_read(ioaddr, 24, 1);
for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
int mii_status, phyx = phy & 0x1f;
for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
int mii_status, phyx;
 
/*
* For the 3c905CX we look at index 24 first, because it bogusly
* reports an external PHY at all indices
*/
if (phy == 0)
phyx = 24;
else if (phy <= 24)
phyx = phy - 1;
else
phyx = phy;
mii_status = mdio_read(ioaddr, phyx, 1);
if (mii_status && mii_status != 0xffff) {
vp->phys[phy_idx++] = phyx;
963,6 → 1020,9
}
}
 
if (vp->enable_wol && (vp->capabilities & CapPwrMgmt))
acpi_set_WOL(dev);
 
if (vp->capabilities & CapBusMaster) {
vp->full_bus_master_tx = 1;
printk(KERN_INFO" Enabling bus-master transmits and %s receives.\n",
974,12 → 1034,13
request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
 
/* The 3c59x-specific entries in the device structure. */
dev->open = &vortex_open;
dev->hard_start_xmit = &vortex_start_xmit;
dev->stop = &vortex_close;
dev->get_stats = &vortex_get_stats;
dev->do_ioctl = &vortex_ioctl;
dev->set_multicast_list = &set_rx_mode;
dev->open = vortex_open;
dev->hard_start_xmit = vp->full_bus_master_tx ?
boomerang_start_xmit : vortex_start_xmit;
dev->stop = vortex_close;
dev->get_stats = vortex_get_stats;
dev->do_ioctl = vortex_ioctl;
dev->set_multicast_list = set_rx_mode;
 
return dev;
}
990,12 → 1051,17
{
long ioaddr = dev->base_addr;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
union wn3_config config;
int i;
unsigned int config;
int i, retval;
 
MOD_INC_USE_COUNT;
 
if (vp->enable_wol)
acpi_wake(vp->pci_bus, vp->pci_devfn);
 
/* Before initializing select the active media port. */
EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);
 
if (vp->media_override != 7) {
if (vortex_debug > 1)
1004,6 → 1070,8
media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
} else if (vp->autoselect && pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) {
if (vortex_debug > 1)
printk(KERN_INFO "%s: using NWAY from config\n", dev->name);
dev->if_port = XCVR_NWAY;
} else if (vp->autoselect) {
/* Find first available media type, starting with 100baseTx. */
1013,19 → 1081,13
} else
dev->if_port = vp->default_media;
 
init_timer(&vp->timer);
vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
vp->timer.data = (unsigned long)dev;
vp->timer.function = &vortex_timer; /* timer handler */
add_timer(&vp->timer);
printk(KERN_INFO "%s: Initial media type %s.\n", dev->name, media_tbl[dev->if_port].name);
 
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Initial media type %s.\n",
dev->name, media_tbl[dev->if_port].name);
if (!vp->duplexlock && (vp->info1 & 0x8000))
vp->full_duplex = 1;
 
vp->full_duplex = vp->force_fd;
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
config = BFINS(config, dev->if_port, 20, 4);
outl(config, ioaddr + Wn3_Config);
 
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int mii_reg1, mii_reg5;
1035,10 → 1097,10
mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
if (mii_reg5 == 0xffff || mii_reg5 == 0x0000)
; /* No MII device or no link partner report */
else if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */
|| (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
else if (!vp->duplexlock &&
((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */
|| (mii_reg5 & 0x00C0) == 0x0040)) /* 10T-FD, but not 100-HD */
vp->full_duplex = 1;
if (vortex_debug > 1)
printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
" setting %s-duplex.\n", dev->name, vp->phys[0],
mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half");
1046,30 → 1108,23
}
 
/* Set the full-duplex bit. */
outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
(dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
outb((vp->full_duplex ? 0x20 : 0) | (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
 
if (vortex_debug > 1) {
printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n",
dev->name, config.i);
printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n", dev->name, config);
}
 
outw(TxReset, ioaddr + EL3_CMD);
for (i = 2000; i >= 0 ; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
wait_for_completion(dev, TxReset);
wait_for_completion(dev, RxReset);
 
outw(RxReset, ioaddr + EL3_CMD);
/* Wait a few ticks for the RxReset command to complete. */
for (i = 2000; i >= 0 ; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
 
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
 
/* Use the now-standard shared IRQ implementation. */
if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
return -EAGAIN;
if ((retval = request_irq(dev->irq, vp->full_bus_master_tx ?
&boomerang_interrupt : &vortex_interrupt,
SA_SHIRQ, dev->name, dev))) {
printk(KERN_ERR "%s: Cannot allocate IRQ #%d\n", dev->name, dev->irq);
goto out;
}
 
if (vortex_debug > 1) {
1127,19 → 1182,24
if (skb == NULL)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
#else
vp->rx_ring[i].addr = virt_to_bus(skb->data);
#endif
}
if (i != RX_RING_SIZE) {
int j;
printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name);
for (j = 0; j < i; j++) {
if (vp->rx_skbuff[j])
dev_kfree_skb(vp->rx_skbuff[j]);
}
retval = -ENOMEM;
goto out_free_irq;
}
/* Wrap the ring. */
vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
dev->hard_start_xmit = &boomerang_start_xmit;
vp->cur_tx = vp->dirty_tx = 0;
outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
/* Clear the Tx ring. */
1147,14 → 1207,13
vp->tx_skbuff[i] = 0;
outl(0, ioaddr + DownListPtr);
}
/* Set reciever mode: presumably accept b-case and phys addr only. */
/* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
vp->in_interrupt = 0;
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
vp->tx_full = 0;
 
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
1163,7 → 1222,8
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
(vp->full_bus_master_rx ? UpComplete : RxComplete) |
(vp->bus_master ? DMADone : 0);
vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |
vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable |
(vp->full_bus_master_rx ? 0 : RxComplete) |
StatsFull | HostError | TxComplete | IntReq
| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
outw(vp->status_enable, ioaddr + EL3_CMD);
1174,9 → 1234,22
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
writel(0x8000, vp->cb_fn_base + 4);
 
MOD_INC_USE_COUNT;
init_timer(&vp->timer);
vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
vp->timer.data = (unsigned long)dev;
vp->timer.function = &vortex_timer; /* timer handler */
add_timer(&vp->timer);
 
init_timer(&vp->rx_oom_timer);
vp->rx_oom_timer.data = (unsigned long)dev;
vp->rx_oom_timer.function = rx_oom_timer;
 
return 0;
 
out_free_irq:
free_irq(dev->irq, dev);
out:
return retval;
}
 
static void vortex_timer(unsigned long data)
1184,7 → 1257,7
struct device *dev = (struct device *)data;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
int next_tick = 0;
int next_tick = 60 * HZ;
int ok = 0;
int media_status, mii_status, old_window;
 
1192,6 → 1265,8
printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
dev->name, media_tbl[dev->if_port].name);
 
if (vp->medialock)
goto leave_media_alone;
disable_irq(dev->irq);
old_window = inw(ioaddr + EL3_CMD) >> 13;
EL3WINDOW(4);
1208,6 → 1283,9
dev->name, media_tbl[dev->if_port].name, media_status);
break;
case XCVR_MII: case XCVR_NWAY:
{
unsigned long flags;
spin_lock_irqsave(&vp->lock, flags);
mii_status = mdio_read(ioaddr, vp->phys[0], 1);
ok = 1;
if (debug > 1)
1215,7 → 1293,7
dev->name, mii_status);
if (mii_status & 0x0004) {
int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
if (! vp->force_fd && mii_reg5 != 0xffff) {
if (!vp->duplexlock && mii_reg5 != 0xffff) {
int duplex = (mii_reg5&0x0100) ||
(mii_reg5 & 0x01C0) == 0x0040;
if (vp->full_duplex != duplex) {
1225,6 → 1303,7
dev->name, vp->full_duplex ? "full" : "half",
vp->phys[0], mii_reg5);
/* Set the full-duplex bit. */
EL3WINDOW(3);
outb((vp->full_duplex ? 0x20 : 0) |
(dev->mtu > 1500 ? 0x40 : 0),
ioaddr + Wn3_MAC_Ctrl);
1232,15 → 1311,17
next_tick = 60*HZ;
}
}
spin_unlock_irqrestore(&vp->lock, flags);
}
break;
default: /* Other media types handled by Tx timeouts. */
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
printk(KERN_DEBUG "%s: Media %s has no indication, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
ok = 1;
}
if ( ! ok) {
union wn3_config config;
unsigned int config;
 
do {
dev->if_port = media_tbl[dev->if_port].next;
1262,9 → 1343,9
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
 
EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config);
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);
config = BFINS(config, dev->if_port, 20, 4);
outl(config, ioaddr + Wn3_Config);
 
outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
1272,14 → 1353,15
EL3WINDOW(old_window);
enable_irq(dev->irq);
 
leave_media_alone:
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
 
if (next_tick) {
vp->timer.expires = RUN_AT(next_tick);
add_timer(&vp->timer);
}
if (vp->deferred)
outw(FakeIntr, ioaddr + EL3_CMD);
return;
}
 
1287,7 → 1369,6
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
int j;
 
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
dev->name, inb(ioaddr + TxStatus),
1300,14 → 1381,22
printk(KERN_ERR "%s: Interrupt posted but not delivered --"
" IRQ blocked by another device?\n", dev->name);
/* Bad idea here.. but we might as well handle a few events. */
{
/*
* AKPM: block interrupts because vortex_interrupt
* does a bare spin_lock()
*/
unsigned long flags;
__save_flags(flags);
__cli();
if (vp->full_bus_master_tx)
boomerang_interrupt(dev->irq, dev, 0);
else
vortex_interrupt(dev->irq, dev, 0);
__restore_flags(flags);
}
}
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
 
#if ! defined(final_version) && LINUX_VERSION_CODE >= 0x10300
if (vp->full_bus_master_tx) {
int i;
printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d "
1323,7 → 1412,7
le32_to_cpu(vp->tx_ring[i].status));
}
}
#endif
wait_for_completion(dev, TxReset);
vp->stats.tx_errors++;
if (vp->full_bus_master_tx) {
if (vortex_debug > 0)
1338,8 → 1427,10
}
outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
outw(DownUnstall, ioaddr + EL3_CMD);
} else
} else {
vp->stats.tx_dropped++;
clear_bit(0, (void*)&dev->tbusy);
}
/* Issue Tx Enable */
outw(TxEnable, ioaddr + EL3_CMD);
1359,7 → 1450,6
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
int do_tx_reset = 0;
int i;
 
if (status & TxComplete) { /* Really "TxError" for us. */
unsigned char tx_status = inb(ioaddr + TxStatus);
1371,7 → 1461,7
if (tx_status & 0x14) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
outb(0, ioaddr + TxStatus);
if (tx_status & 0x30)
if (tx_status & 0x30) /* txJabber or txUnderrun */
do_tx_reset = 1;
else /* Merely re-enable the transmitter. */
outw(TxEnable, ioaddr + EL3_CMD);
1410,10 → 1500,7
dev->name, fifo_diag);
/* Adapter failure requires Tx/Rx reset and reinit. */
if (vp->full_bus_master_tx) {
outw(TotalReset | 0xff, ioaddr + EL3_CMD);
for (i = 2000; i >= 0 ; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
wait_for_completion(dev, TotalReset|0xff);
/* Re-enable the receiver. */
outw(RxEnable, ioaddr + EL3_CMD);
outw(TxEnable, ioaddr + EL3_CMD);
1420,10 → 1507,7
} else if (fifo_diag & 0x0400)
do_tx_reset = 1;
if (fifo_diag & 0x3000) {
outw(RxReset, ioaddr + EL3_CMD);
for (i = 2000; i >= 0 ; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
wait_for_completion(dev, RxReset);
/* Set the Rx filter to the current state. */
set_rx_mode(dev);
outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
1431,17 → 1515,16
}
}
if (do_tx_reset) {
int j;
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
if (!vp->full_bus_master_tx) {
clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
}
}
 
}
 
 
static int
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
{
1453,6 → 1536,9
vortex_tx_timeout(dev);
return 1;
}
if (vortex_debug > 3)
printk(KERN_DEBUG "%s: Trying to send a boomerang packet, Tx index %d.\n",
dev->name, vp->cur_tx);
 
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
1465,8 → 1551,12
/* dev->tbusy will be cleared at the DMADone interrupt. */
} else {
/* ... and the packet rounded to a doubleword. */
#ifdef __powerpc__
outsl_ns(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
#else
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
DEV_FREE_SKB(skb);
#endif
dev_kfree_skb(skb);
if (inw(ioaddr + TxFree) > 1536) {
clear_bit(0, (void*)&dev->tbusy);
} else
1488,13 → 1578,8
dev->name, tx_status);
if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
if (tx_status & 0x30) {
int j;
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
}
if (tx_status & 0x30)
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
}
outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
1520,13 → 1605,12
struct boom_tx_desc *prev_entry =
&vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
unsigned long flags;
int i;
 
if (vortex_debug > 3)
printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
printk(KERN_DEBUG "%s: Trying to send a boomerang packet, Tx index %d.\n",
dev->name, vp->cur_tx);
if (vp->tx_full) {
if (vortex_debug >0)
if (vortex_debug > 0)
printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
dev->name);
return 1;
1537,20 → 1621,13
vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 
save_flags(flags);
cli();
outw(DownStall, ioaddr + EL3_CMD);
/* Wait for the stall to complete. */
for (i = 600; i >= 0 ; i--)
if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
break;
spin_lock_irqsave(&vp->lock, flags);
wait_for_completion(dev, DownStall);
prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
if (inl(ioaddr + DownListPtr) == 0) {
outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
queued_packet++;
}
outw(DownUnstall, ioaddr + EL3_CMD);
restore_flags(flags);
 
vp->cur_tx++;
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
1559,6 → 1636,8
prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
clear_bit(0, (void*)&dev->tbusy);
}
outw(DownUnstall, ioaddr + EL3_CMD);
spin_unlock_irqrestore(&vp->lock, flags);
dev->trans_start = jiffies;
vp->stats.tx_bytes += skb->len;
return 0;
1567,48 → 1646,45
 
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
 
/*
* This is the ISR for the vortex series chips.
* full_bus_master_tx == 0 && full_bus_master_rx == 0
*/
 
static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = dev_id;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr;
int latency, status;
int status;
int work_done = max_interrupt_work;
 
#if defined(__i386__)
/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
if (test_and_set_bit(0, (void*)&dev->interrupt)) {
printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
dev->name);
dev->interrupt = 0; /* Avoid halting machine. */
return;
ioaddr = dev->base_addr;
spin_lock(&vp->lock);
status = inw(ioaddr + EL3_STATUS);
if ((status & IntLatch) == 0) {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: no vortex interrupt pending\n", dev->name);
goto no_int; /* Happens during shared interrupts */
}
#else
if (dev->interrupt) {
printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
return;
 
if (status & IntReq) {
status |= vp->deferred;
vp->deferred = 0;
}
dev->interrupt = 1;
#endif
 
dev->interrupt = 1;
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
status = inw(ioaddr + EL3_STATUS);
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: vortex_interrupt, status %4.4x, latency %d ticks.\n",
dev->name, status, inb(ioaddr + Timer));
 
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
dev->name, status, latency);
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
dev->name, status);
 
if (status & RxComplete)
vortex_rx(dev);
if (status & UpComplete) {
outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
boomerang_rx(dev);
}
 
if (status & TxAvailable) {
if (vortex_debug > 5)
1619,6 → 1695,93
mark_bh(NET_BH);
}
 
if (status & DMADone) {
if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
dev_kfree_skb(vp->tx_skb); /* Release the transfered buffer */
if (inw(ioaddr + TxFree) > 1536) {
clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
} else /* Interrupt when FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
}
 
/* Check for all uncommon interrupts at once. */
if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
if (status == 0xffff)
break;
vortex_error(dev, status);
}
 
if (--work_done < 0) {
printk(KERN_WARNING "%s: Too much work in interrupt, status "
"%4.4x.\n", dev->name, status);
/* Disable all pending interrupts. */
do {
vp->deferred |= status;
outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
} while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, RUN_AT(1));
break;
}
 
/* Acknowledge the IRQ. */
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
 
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
dev->name, status);
 
no_int:
spin_unlock(&vp->lock);
}
 
/*
* This is the ISR for the boomerang/cyclone/hurricane/tornado series chips.
* full_bus_master_tx == 1 && full_bus_master_rx == 1
*/
 
static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = dev_id;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr;
int status;
int work_done = max_interrupt_work;
 
ioaddr = dev->base_addr;
spin_lock(&vp->lock);
status = inw(ioaddr + EL3_STATUS);
if ((status & IntLatch) == 0) {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: no boomerang interrupt pending\n", dev->name);
goto no_int; /* Happens during shared interrupts */
}
 
if (status & IntReq) {
status |= vp->deferred;
vp->deferred = 0;
}
 
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: boomerang interrupt, status %04x, latency %d, cur_rx %d, dirty_rx %d\n",
dev->name, status, inb(ioaddr + Timer), vp->cur_rx, vp->dirty_rx);
 
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
dev->name, status);
 
if (status & UpComplete) {
outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
boomerang_rx(dev);
}
 
if (status & DownComplete) {
unsigned int dirty_tx = vp->dirty_tx;
 
1628,7 → 1791,7
virt_to_bus(&vp->tx_ring[entry]))
break; /* It still hasn't been processed. */
if (vp->tx_skbuff[entry]) {
DEV_FREE_SKB(vp->tx_skbuff[entry]);
dev_kfree_skb(vp->tx_skbuff[entry]);
vp->tx_skbuff[entry] = 0;
}
/* vp->stats.tx_packets++; Counted below. */
1637,22 → 1800,12
vp->dirty_tx = dirty_tx;
outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
vp->tx_full= 0;
clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
}
}
if (status & DMADone) {
if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
if (inw(ioaddr + TxFree) > 1536) {
vp->tx_full = 0;
clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
} else /* Interrupt when FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
}
 
/* Check for all uncommon interrupts at once. */
if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
if (status == 0xffff)
1661,37 → 1814,33
}
 
if (--work_done < 0) {
if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
/* Just ack these and return. */
outw(AckIntr | UpComplete | DownComplete, ioaddr + EL3_CMD);
} else {
printk(KERN_WARNING "%s: Too much work in interrupt, status "
"%4.4x. Temporarily disabling functions (%4.4x).\n",
dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
"%4.4x.\n", dev->name, status);
/* Disable all pending interrupts. */
outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
do {
vp->deferred |= status;
outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
} while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, RUN_AT(1));
break;
}
}
 
/* Acknowledge the IRQ. */
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
writel(0x8000, vp->cb_fn_base + 4);
 
} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
} while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch);
 
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
dev->name, status);
 
#if defined(__i386__)
clear_bit(0, (void*)&dev->interrupt);
#else
dev->interrupt = 0;
#endif
return;
no_int:
spin_unlock(&vp->lock);
}
 
static int vortex_rx(struct device *dev)
1702,7 → 1851,7
short rx_status;
 
if (vortex_debug > 5)
printk(KERN_DEBUG" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
printk(KERN_DEBUG" In vortex_rx(), status %4.4x, rx_status %4.4x.\n",
inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */
1737,8 → 1886,13
while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
;
} else {
#ifdef __powerpc__
insl_ns(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
(pkt_len + 3) >> 2);
#else
insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
(pkt_len + 3) >> 2);
#endif
}
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
1755,12 → 1909,8
printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
"size %d.\n", dev->name, pkt_len);
}
outw(RxDiscard, ioaddr + EL3_CMD);
vp->stats.rx_dropped++;
/* Wait a limited time to skip this packet. */
for (i = 200; i >= 0; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
wait_for_completion(dev, RxDiscard);
}
 
return 0;
1844,13 → 1994,21
entry = (++vp->cur_rx) % RX_RING_SIZE;
}
/* Refill the Rx ring buffers. */
for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
struct sk_buff *skb;
entry = vp->dirty_rx % RX_RING_SIZE;
if (vp->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb(PKT_BUF_SZ);
if (skb == NULL)
if (skb == NULL) {
static unsigned long last_jif;
if ((jiffies - last_jif) > 10 * HZ) {
printk(KERN_WARNING "%s: memory shortage\n", dev->name);
last_jif = jiffies;
}
if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)
mod_timer(&vp->rx_oom_timer, RUN_AT(HZ * 1));
break; /* Bad news! */
}
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
1862,6 → 2020,26
return 0;
}
 
/*
* If we've hit a total OOM refilling the Rx ring we poll once a second
* for some memory. Otherwise there is no way to restart the rx process.
*/
static void
rx_oom_timer(unsigned long arg)
{
struct device *dev = (struct device *)arg;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
 
spin_lock_irq(&vp->lock);
if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE) /* This test is redundant, but makes me feel good */
boomerang_rx(dev);
if (vortex_debug > 1) {
printk(KERN_DEBUG "%s: rx_oom_timer %s\n", dev->name,
((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying");
}
spin_unlock_irq(&vp->lock);
}
 
static int
vortex_close(struct device *dev)
{
1881,6 → 2059,7
}
 
del_timer(&vp->timer);
del_timer(&vp->rx_oom_timer);
 
/* Turn off statistics ASAP. We update vp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
1902,10 → 2081,7
outl(0, ioaddr + UpListPtr);
for (i = 0; i < RX_RING_SIZE; i++)
if (vp->rx_skbuff[i]) {
#if LINUX_VERSION_CODE < 0x20100
vp->rx_skbuff[i]->free = 1;
#endif
DEV_FREE_SKB(vp->rx_skbuff[i]);
dev_kfree_skb(vp->rx_skbuff[i]);
vp->rx_skbuff[i] = 0;
}
}
1913,11 → 2089,13
outl(0, ioaddr + DownListPtr);
for (i = 0; i < TX_RING_SIZE; i++)
if (vp->tx_skbuff[i]) {
DEV_FREE_SKB(vp->tx_skbuff[i]);
dev_kfree_skb(vp->tx_skbuff[i]);
vp->tx_skbuff[i] = 0;
}
}
 
if (vp->enable_wol && (vp->capabilities & CapPwrMgmt))
acpi_set_WOL(dev);
MOD_DEC_USE_COUNT;
 
return 0;
1929,10 → 2107,9
unsigned long flags;
 
if (dev->start) {
save_flags(flags);
cli();
spin_lock_irqsave(&vp->lock, flags);
update_stats(dev->base_addr, dev);
restore_flags(flags);
spin_unlock_irqrestore(&vp->lock, flags);
}
return &vp->stats;
}
1981,7 → 2158,11
long ioaddr = dev->base_addr;
u16 *data = (u16 *)&rq->ifr_data;
int phy = vp->phys[0] & 0x1f;
int retval;
unsigned long flags;
 
spin_lock_irqsave(&vp->lock, flags);
 
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = phy;
1988,16 → 2169,23
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
EL3WINDOW(4);
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
return 0;
retval = 0;
break;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!suser())
return -EPERM;
if (!capable(CAP_NET_ADMIN)) {
retval = -EPERM;
} else {
EL3WINDOW(4);
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
retval = 0;
}
break;
default:
return -EOPNOTSUPP;
retval = -EOPNOTSUPP;
}
 
spin_unlock_irqrestore(&vp->lock, flags);
return retval;
}
 
/* Pre-Cyclone chips have no documented multicast filter, so the only
2114,6 → 2302,52
return;
}
 
/* ACPI: Advanced Configuration and Power Interface. */
/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
static void acpi_set_WOL(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
 
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7);
outw(2, ioaddr + 0x0c);
/* The RxFilter must accept the WOL frames. */
outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
outw(RxEnable, ioaddr + EL3_CMD);
/* Change the power state to D3; RxEnable doesn't take effect. */
pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103);
}
 
/* Change from D3 (sleep) to D0 (active).
Problem: The Cyclone forgets all PCI config info during the transition! */
static void acpi_wake(int bus, int devfn)
{
u32 base0, base1, romaddr;
u16 pci_command, pwr_command;
u8 pci_latency, pci_cacheline, irq;
 
pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command);
if ((pwr_command & 3) == 0)
return;
pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command);
pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0);
pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1);
pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr);
pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency);
pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline);
pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq);
 
pcibios_write_config_word( bus, devfn, 0xe0, 0x0000);
pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0);
pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1);
pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr);
pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq);
pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency);
pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline);
pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5);
}
 
#ifdef MODULE
void cleanup_module(void)
2120,16 → 2354,14
{
struct device *next_dev;
 
#ifdef CARDBUS
unregister_driver(&vortex_ops);
#endif
 
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_vortex_dev) {
struct vortex_private *vp=(void *)(root_vortex_dev->priv);
int drv_flags = pci_tbl[vp->chip_id].drv_flags;
next_dev = vp->next_module;
unregister_netdev(root_vortex_dev);
outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
outw((drv_flags & EEPROM_NORESET) ? (TotalReset|0x10) : TotalReset,
root_vortex_dev->base_addr + EL3_CMD);
release_region(root_vortex_dev->base_addr,
pci_tbl[vp->chip_id].io_size);
kfree(root_vortex_dev);
2142,9 → 2374,6
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
* cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
/shark/trunk/drivers/linuxcom/timer.c
22,15 → 22,130
* Linux timer support.
*/
 
 
#include<kernel/kern.h>
#include<time.h>
#include<linux/timer.h>
 
//#define TIMER_DEBUG
 
//#define IANPATCH
#ifndef IANPATCH
 
static inline void
jiffies_to_timespec(unsigned long j, struct timespec *value)
{
value->tv_nsec = (j % HZ) * (1000000000L / HZ);
value->tv_sec = j / HZ;
 
}
 
int add_timer(struct timer_list *timer)
{
 
struct timespec timeout;
 
jiffies_to_timespec(timer->expires, &timeout);
timer->event_timer = kern_event_post(&timeout, (void (*)(void *))timer->function, (void *)timer->data);
 
#ifdef TIMER_DEBUG
cprintf("Set to %ld:%ld\n",timeout.tv_sec,timeout.tv_nsec);
#endif
 
return 0;
 
}
 
 
void del_timer(struct timer_list *timer)
{
 
kern_event_delete(timer->event_timer);
 
}
 
void mod_timer(struct timer_list *timer, unsigned long expires)
{
kern_event_delete(timer->event_timer);
timer->expires = expires;
add_timer(timer);
 
}
 
void init_timer(struct timer_list * timer)
{
}
 
#else
 
#include <pthread.h>
 
/*Needs to have this sort of thing in the initfile
* PTHREAD_register_module(1, 0, 1);
*
* TIMER_register_module();
* PI_register_module();
* PC_register_module();
*/
 
pthread_attr_t task_attr; /* attributtes for the task doing the callback*/
 
static inline void
jiffies_to_timespec(unsigned long j, struct timespec *value)
{
value->tv_nsec = (j % HZ) * (1000000000L / HZ);
value->tv_sec = j / HZ;
}
 
int add_timer(struct timer_list *timer)
{
int err;
struct sigevent ev;
struct sched_param task_param;
struct itimerspec timeout;
 
ev.sigev_notify = SIGEV_THREAD;
ev.sigev_value.sival_int = timer->data;
ev.sigev_notify_function = timer->function;
ev.sigev_notify_attributes = &task_attr;
 
pthread_attr_init(&task_attr);
pthread_attr_setdetachstate(&task_attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setschedpolicy(&task_attr, SCHED_RR);
task_param.sched_priority = 10;
pthread_attr_setschedparam(&task_attr, &task_param);
 
err =timer_create(CLOCK_REALTIME, &ev, &(timer->sharktimer));
if (err !=0 ) { cprintf("timer: unable to create timer\n"); }
timeout.it_interval.tv_sec=0;
timeout.it_interval.tv_nsec=0;
jiffies_to_timespec(timer->expires, &(timeout.it_value));
 
err = timer_settime(timer->sharktimer, 0, &timeout, NULL);
if (err !=0 ) { cprintf("timer: unable to timer_settime\n"); }
cprintf("Set to %ld:%ld\n",timeout.it_value.tv_sec,timeout.it_value.tv_nsec);
return err;
}
 
 
void del_timer(struct timer_list *timer)
{
timer_delete(timer->sharktimer);
}
 
void mod_timer(struct timer_list *timer, unsigned long expires)
{
timer_delete(timer->sharktimer);
timer->expires=expires;
add_timer(timer);
}
 
void init_timer(struct timer_list * timer)
{
}
 
#endif
/shark/trunk/drivers/linuxcom/include/linux/compatib.h
50,8 → 50,8
#define NULL 0
#endif
 
#define jiffies 0 /* Has to be controlled... */
#define HZ 100 /* Has to be controlled... */
#define jiffies (sys_gettime(NULL)*HZ/1000000) /* Has to be controlled... */
extern long unsigned int loops_per_sec; /* ... */
#define EISA_bus 0 /* We do not support EISA buses... */
 
61,6 → 61,11
#define MOD_INC_USE_COUNT /* Do nothing... */
#define MOD_DEC_USE_COUNT /* Do nothing... */
#define MOD_IN_USE 0 /* No module => never in use... */
#define MODULE_AUTHOR(a)
#define MODULE_DESCRIPTION(a)
#define MODULE_LICENSE(a)
#define MODULE_PARM(a,b)
#define MODULE_PARM_DESC(a,b)
 
#define GFP_KERNEL 0x03 /* Don't know what it is... */
#define GFP_ATOMIC 0x01 /* Don't know what it is... */
71,6 → 76,7
//#define printk cprintf I would like to use the kernel printk if possible...
#define check_region(a,b) 0
#define request_region(a,b,c)
#define release_region(a,b);
#define release_region(a,b)
 
/* Linux funcs emulation... */
86,8 → 92,12
#define mark_bh(NET_BH) /* Don't use soft int emulation... */
 
 
#define __cli() kern_cli()
#define __sti() kern_sti()
#define cli() kern_cli()
#define sti() kern_sti()
#define __save_flags(f) f = kern_fsave()
#define __restore_flags(f) kern_frestore(f)
#define save_flags(f) f = kern_fsave()
#define restore_flags(f) kern_frestore(f)
 
122,8 → 132,9
#define spin_unlock_irqrestore(x,y) kern_frestore(y)
#define spin_lock_init(x)
#define SPIN_LOCK_UNLOCKED (spinlock_t) 0
#define spin_lock_irq(lock) kern_cli()
#define spin_unlock_irq(lock) kern_sti()
 
 
extern __inline__ void panic(const char *c)
{
cputs((char *)c);
137,6 → 148,23
/* *** from linux-2.2.17/include/linux/compatmac.h */
#define capable(x) suser()
 
#define __devinitdata
#define __devinit
 
struct pci_device_id {
unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
unsigned long driver_data; /* Data private to the driver */
};
#define PCI_ANY_ID (~0)
#define MODULE_DEVICE_TABLE(a,b)
 
#ifdef CONFIG_HIGHMEM
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif
/* *** from linux-2.2.17/include/linux/capability.h */
#define CAP_NET_ADMIN 12
 
/shark/trunk/drivers/linuxcom/include/linux/timer.h
20,11 → 20,11
 
/**
------------
CVS : $Id: timer.h,v 1.2 2003-03-13 13:48:05 pj Exp $
CVS : $Id: timer.h,v 1.3 2003-09-04 13:34:20 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.2 $
Last update: $Date: 2003-03-13 13:48:05 $
Revision: $Revision: 1.3 $
Last update: $Date: 2003-09-04 13:34:20 $
------------
**/
 
50,6 → 50,7
#define __TIMER__
 
#include <kernel/kern.h>
#include <time.h>
#include <linux/compatib.h>
#include "ll/sys/cdefs.h"
 
76,14 → 77,19
void (*function)(unsigned long);
PID pid;
char Signat;
time_t sharktimer;
int event_timer;
 
};
 
extern inline void init_timer(struct timer_list * timer)
/*extern inline void init_timer(struct timer_list * timer)
{
timer->next = NULL;
timer->prev = NULL;
}
 
*/
void init_timer(struct timer_list * timer);
void mod_timer(struct timer_list *timer, unsigned long expires);
int add_timer(struct timer_list *timer);
void del_timer(struct timer_list *timer);
__END_DECLS
/shark/trunk/drivers/linuxc24/include/linux/compatib.h
60,7 → 60,7
#define inb(p) inp(p)
#define inw(p) inpw(p)
#define inl(p) inpd(p)
#define malloc(a) malloc(a)
/*#define malloc(a) malloc(a)*/
 
#define mark_bh(NET_BH) /* Don't use soft int emulation... */
 
67,8 → 67,12
 
#define cli() kern_cli()
#define sti() kern_sti()
#define __save_flags(f) f = kern_fsave()
#define save_flags(f) f = kern_fsave()
#define __restore_flags(f) kern_frestore(f)
#define restore_flags(f) kern_frestore(f)
#define __cli(f) kern_cli(f)
#define __sti(f) kern_cli(f)
 
 
/* URKA Stubs */
/shark/trunk/drivers/linuxc24/include/linux/delay.h
9,7 → 9,7
 
extern unsigned long loops_per_jiffy;
 
#include <asm/delay.h>
/*#include <asm/delay.h>*/
 
/*
* Using udelay() for intervals greater than a few milliseconds can