Commit ee4351da authored by Linus Torvalds's avatar Linus Torvalds

Merge

parents d472b9dc 25fbb358
...@@ -1284,7 +1284,7 @@ S: 14059 Berlin ...@@ -1284,7 +1284,7 @@ S: 14059 Berlin
S: Germany S: Germany
N: David Hinds N: David Hinds
E: dhinds@zen.stanford.edu E: dahinds@users.sourceforge.net
W: http://tao.stanford.edu/~dhinds W: http://tao.stanford.edu/~dhinds
D: PCMCIA and CardBus stuff, PCMCIA-HOWTO, PCMCIA client drivers D: PCMCIA and CardBus stuff, PCMCIA-HOWTO, PCMCIA client drivers
S: 2019 W. Middlefield Rd #1 S: 2019 W. Middlefield Rd #1
......
...@@ -1315,7 +1315,7 @@ S: Maintained ...@@ -1315,7 +1315,7 @@ S: Maintained
PCMCIA SUBSYSTEM PCMCIA SUBSYSTEM
P: David Hinds P: David Hinds
M: dhinds@zen.stanford.edu M: dahinds@users.sourceforge.net
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
W: http://pcmcia-cs.sourceforge.net W: http://pcmcia-cs.sourceforge.net
S: Maintained S: Maintained
......
...@@ -550,7 +550,7 @@ Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) ...@@ -550,7 +550,7 @@ Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11)
the StarTech 16650 chip. Treat it as a 16450 for now, the StarTech 16650 chip. Treat it as a 16450 for now,
because of its FIFO bugs. because of its FIFO bugs.
Thu Jan 5 21:21:57 1995 <dhinds@allegro.stanford.edu> Thu Jan 5 21:21:57 1995 <dahinds@users.sourceforge.net>
* serial.c: (receive_char): Added counter to prevent infinite loop * serial.c: (receive_char): Added counter to prevent infinite loop
when a PCMCIA serial device is ejected. when a PCMCIA serial device is ejected.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
A driver for PCMCIA IDE/ATA disk cards A driver for PCMCIA IDE/ATA disk cards
ide_cs.c 1.26 1999/11/16 02:10:49 ide-cs.c 1.3 2002/10/26 05:45:31
The contents of this file are subject to the Mozilla Public The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file License Version 1.1 (the "License"); you may not use this file
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
rights and limitations under the License. rights and limitations under the License.
The initial developer of the original code is David A. Hinds The initial developer of the original code is David A. Hinds
<dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the Alternatively, the contents of this file may be used under the
terms of the GNU General Public License version 2 (the "GPL"), in which terms of the GNU General Public License version 2 (the "GPL"), in
case the provisions of the GPL are applicable instead of the which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision your version of this file under the MPL, indicate your decision
...@@ -40,10 +40,9 @@ ...@@ -40,10 +40,9 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/ide.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/ide.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -53,38 +52,37 @@ ...@@ -53,38 +52,37 @@
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/ds.h> #include <pcmcia/ds.h>
#include <pcmcia/cisreg.h> #include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/ /*====================================================================*/
/* Parameters that can be set with 'insmod' */ /* Module parameters */
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
MODULE_LICENSE("Dual MPL/GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */ /* Bit map of interrupts to choose from */
static u_int irq_mask = 0xdeb8; INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 }; static int irq_list[4] = { -1 };
MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(irq_list, "1-4i");
MODULE_LICENSE("GPL"); #ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/ /*====================================================================*/
static const char ide_major[] = { static const char ide_major[] = {
IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
#ifdef IDE4_MAJOR
IDE4_MAJOR, IDE5_MAJOR IDE4_MAJOR, IDE5_MAJOR
#endif
}; };
typedef struct ide_info_t { typedef struct ide_info_t {
...@@ -94,7 +92,6 @@ typedef struct ide_info_t { ...@@ -94,7 +92,6 @@ typedef struct ide_info_t {
int hd; int hd;
} ide_info_t; } ide_info_t;
static void ide_config(dev_link_t *link);
static void ide_release(u_long arg); static void ide_release(u_long arg);
static int ide_event(event_t event, int priority, static int ide_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
...@@ -227,13 +224,13 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed ...@@ -227,13 +224,13 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
#define CFG_CHECK(fn, args...) \ #define CFG_CHECK(fn, args...) \
if (CardServices(fn, args) != 0) goto next_entry if (CardServices(fn, args) != 0) goto next_entry
int idecs_register (int arg1, int arg2, int irq) static int idecs_register(int io, int ctl, int irq)
{ {
hw_regs_t hw; hw_regs_t hw;
ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); ide_init_hwif_ports(&hw, (ide_ioreg_t)io, (ide_ioreg_t)ctl, NULL);
hw.irq = irq; hw.irq = irq;
hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */ hw.chipset = ide_pci;
return ide_register_hw(&hw, NULL); return ide_register_hw(&hw, NULL);
} }
void ide_config(dev_link_t *link) void ide_config(dev_link_t *link)
...@@ -246,7 +243,7 @@ void ide_config(dev_link_t *link) ...@@ -246,7 +243,7 @@ void ide_config(dev_link_t *link)
config_info_t conf; config_info_t conf;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t dflt = { 0 };
int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base; int i, pass, last_ret, last_fn, hd, io_base, ctl_base, is_kme = 0;
DEBUG(0, "ide_config(0x%p)\n", link); DEBUG(0, "ide_config(0x%p)\n", link);
...@@ -259,7 +256,15 @@ void ide_config(dev_link_t *link) ...@@ -259,7 +256,15 @@ void ide_config(dev_link_t *link)
CS_CHECK(ParseTuple, handle, &tuple, &parse); CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base; link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0]; link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
if (!CardServices(GetFirstTuple, handle, &tuple) &&
!CardServices(GetTupleData, handle, &tuple) &&
!CardServices(ParseTuple, handle, &tuple, &parse))
is_kme = ((parse.manfid.manf == MANFID_KME) &&
((parse.manfid.card == PRODID_KME_KXLC005_A) ||
(parse.manfid.card == PRODID_KME_KXLC005_B)));
/* Configure card */ /* Configure card */
link->state |= DEV_CONFIG; link->state |= DEV_CONFIG;
...@@ -303,7 +308,7 @@ void ide_config(dev_link_t *link) ...@@ -303,7 +308,7 @@ void ide_config(dev_link_t *link)
if (io->nwin == 2) { if (io->nwin == 2) {
link->io.NumPorts1 = 8; link->io.NumPorts1 = 8;
link->io.BasePort2 = io->win[1].base; link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = 1; link->io.NumPorts2 = (is_kme) ? 2 : 1;
CFG_CHECK(RequestIO, link->handle, &link->io); CFG_CHECK(RequestIO, link->handle, &link->io);
io_base = link->io.BasePort1; io_base = link->io.BasePort1;
ctl_base = link->io.BasePort2; ctl_base = link->io.BasePort2;
...@@ -337,17 +342,20 @@ void ide_config(dev_link_t *link) ...@@ -337,17 +342,20 @@ void ide_config(dev_link_t *link)
if (link->io.NumPorts2) if (link->io.NumPorts2)
release_region(link->io.BasePort2, link->io.NumPorts2); release_region(link->io.BasePort2, link->io.NumPorts2);
/* disable drive interrupts during IDE probe */
outb(0x02, ctl_base);
/* special setup for KXLC005 card */
if (is_kme) outb(0x81, ctl_base+1);
/* retry registration in case device is still spinning up */ /* retry registration in case device is still spinning up */
for (i = 0; i < 10; i++) { for (hd = -1, i = 0; i < 10; i++) {
if (ctl_base)
outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */
hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
if (hd >= 0) break; if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) { if (link->io.NumPorts1 == 0x20) {
if (ctl_base) outb(0x02, ctl_base+0x10);
outb(0x02, ctl_base+0x10);
hd = idecs_register(io_base+0x10, ctl_base+0x10, hd = idecs_register(io_base+0x10, ctl_base+0x10,
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
if (hd >= 0) { if (hd >= 0) {
io_base += 0x10; ctl_base += 0x10; io_base += 0x10; ctl_base += 0x10;
break; break;
...@@ -358,7 +366,7 @@ void ide_config(dev_link_t *link) ...@@ -358,7 +366,7 @@ void ide_config(dev_link_t *link)
} }
if (hd < 0) { if (hd < 0) {
printk(KERN_NOTICE "ide_cs: ide_register() at 0x%03x & 0x%03x" printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3x & 0x%3x"
", irq %u failed\n", io_base, ctl_base, ", irq %u failed\n", io_base, ctl_base,
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
goto failed; goto failed;
...@@ -371,7 +379,7 @@ void ide_config(dev_link_t *link) ...@@ -371,7 +379,7 @@ void ide_config(dev_link_t *link)
info->node.minor = 0; info->node.minor = 0;
info->hd = hd; info->hd = hd;
link->dev = &info->node; link->dev = &info->node;
printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10,
link->conf.Vpp1/10, link->conf.Vpp1%10); link->conf.Vpp1/10, link->conf.Vpp1%10);
...@@ -382,6 +390,7 @@ void ide_config(dev_link_t *link) ...@@ -382,6 +390,7 @@ void ide_config(dev_link_t *link)
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
ide_release((u_long)link); ide_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* ide_config */ } /* ide_config */
...@@ -402,13 +411,14 @@ void ide_release(u_long arg) ...@@ -402,13 +411,14 @@ void ide_release(u_long arg)
if (info->ndev) { if (info->ndev) {
ide_unregister(info->hd); ide_unregister(info->hd);
/* deal with brain dead IDE resource management */
request_region(link->io.BasePort1, link->io.NumPorts1,
info->node.dev_name);
if (link->io.NumPorts2)
request_region(link->io.BasePort2, link->io.NumPorts2,
info->node.dev_name);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs");
if (link->io.NumPorts2)
request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs");
info->ndev = 0; info->ndev = 0;
link->dev = NULL; link->dev = NULL;
...@@ -472,9 +482,9 @@ static int __init init_ide_cs(void) ...@@ -472,9 +482,9 @@ static int __init init_ide_cs(void)
DEBUG(0, "%s\n", version); DEBUG(0, "%s\n", version);
CardServices(GetCardServicesInfo, &serv); CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "ide_cs: Card Services release " printk(KERN_NOTICE "ide-cs: Card Services release "
"does not match!\n"); "does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &ide_attach, &ide_detach); register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
return 0; return 0;
...@@ -482,7 +492,7 @@ static int __init init_ide_cs(void) ...@@ -482,7 +492,7 @@ static int __init init_ide_cs(void)
static void __exit exit_ide_cs(void) static void __exit exit_ide_cs(void)
{ {
DEBUG(0, "ide_cs: unloading\n"); DEBUG(0, "ide-cs: unloading\n");
unregister_pccard_driver(&dev_info); unregister_pccard_driver(&dev_info);
while (dev_list != NULL) while (dev_list != NULL)
ide_detach(dev_list); ide_detach(dev_list);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
rights and limitations under the License. rights and limitations under the License.
The initial developer of the original code is David A. Hinds The initial developer of the original code is David A. Hinds
<dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the Alternatively, the contents of this file may be used under the
...@@ -1302,5 +1302,5 @@ module_init(init_ftl); ...@@ -1302,5 +1302,5 @@ module_init(init_ftl);
module_exit(cleanup_ftl); module_exit(cleanup_ftl);
MODULE_LICENSE("Dual MPL/GPL"); MODULE_LICENSE("Dual MPL/GPL");
MODULE_AUTHOR("David Hinds <dhinds@sonic.net>"); MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices and M-Systems DiskOnChip 1000"); MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices and M-Systems DiskOnChip 1000");
/* Generic NS8390 register definitions. */
/* This file is part of Donald Becker's 8390 drivers, and is distributed
under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
Some of these names and comments originated from the Crynwr
packet drivers, which are distributed under the GPL. */
#ifndef _8390_h
#define _8390_h
#include <linux/config.h>
#include <linux/if_ether.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
#define TX_2X_PAGES 12
#define TX_1X_PAGES 6
/* Should always use two Tx slots to get back-to-back transmits. */
#define EI_PINGPONG
#ifdef EI_PINGPONG
#define TX_PAGES TX_2X_PAGES
#else
#define TX_PAGES TX_1X_PAGES
#endif
#define ETHER_ADDR_LEN 6
/* The 8390 specific per-packet-header format. */
struct e8390_pkt_hdr {
unsigned char status; /* status */
unsigned char next; /* pointer to next packet. */
unsigned short count; /* header + packet length in bytes */
};
#ifdef notdef
extern int ei_debug;
#else
#define ei_debug 1
#endif
static int ethdev_init(struct net_device *dev);
static void NS8390_init(struct net_device *dev, int startp);
static int ei_open(struct net_device *dev);
static int ei_close(struct net_device *dev);
static void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/* Most of these entries should be in 'struct net_device' (or most of the
things in there should be here!) */
/* You have one of these per-board */
struct ei_device {
const char *name;
void (*reset_8390)(struct net_device *);
void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
void (*block_output)(struct net_device *, int, const unsigned char *, int);
void (*block_input)(struct net_device *, int, struct sk_buff *, int);
unsigned char mcfilter[8];
unsigned open:1;
unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
unsigned txing:1; /* Transmit Active */
unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
unsigned dmaing:1; /* Remote DMA Active */
unsigned char tx_start_page, rx_start_page, stop_page;
unsigned char current_page; /* Read pointer in buffer */
unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
unsigned char txqueue; /* Tx Packet buffer queue length. */
short tx1, tx2; /* Packet lengths for ping-pong tx. */
short lasttx; /* Alpha version consistency check. */
unsigned char reg0; /* Register '0' in a WD8013 */
unsigned char reg5; /* Register '5' in a WD8013 */
unsigned char saved_irq; /* Original dev->irq value. */
struct net_device_stats stat; /* The new statistics table. */
u32 *reg_offset; /* Register mapping table */
spinlock_t page_lock; /* Page register locks */
unsigned long priv; /* Private field to store bus IDs etc. */
};
/* The maximum number of 8390 interrupt service routines called per IRQ. */
#define MAX_SERVICE 12
/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
#define TX_TIMEOUT (20*HZ/100)
#define ei_status (*(struct ei_device *)(dev->priv))
/* Some generic ethernet register configurations. */
#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
#define E8390_RX_IRQ_MASK 0x5
#define E8390_RXCONFIG 0x44 /* EN0_RXCR: broadcasts, no multicast,errors */
#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
#define E8390_TRANS 0x04 /* Transmit a frame */
#define E8390_RREAD 0x08 /* Remote read */
#define E8390_RWRITE 0x10 /* Remote write */
#define E8390_NODMA 0x20 /* Remote DMA */
#define E8390_PAGE0 0x00 /* Select page chip registers */
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
/*
* Only generate indirect loads given a machine that needs them.
*/
#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) || \
defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
#endif
#define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */
/* Page 0 register offsets. */
#define EN0_CLDALO EI_SHIFT(0x01) /* Low byte of current local dma addr RD */
#define EN0_STARTPG EI_SHIFT(0x01) /* Starting page of ring bfr WR */
#define EN0_CLDAHI EI_SHIFT(0x02) /* High byte of current local dma addr RD */
#define EN0_STOPPG EI_SHIFT(0x02) /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY EI_SHIFT(0x03) /* Boundary page of ring bfr RD WR */
#define EN0_TSR EI_SHIFT(0x04) /* Transmit status reg RD */
#define EN0_TPSR EI_SHIFT(0x04) /* Transmit starting page WR */
#define EN0_NCR EI_SHIFT(0x05) /* Number of collision reg RD */
#define EN0_TCNTLO EI_SHIFT(0x05) /* Low byte of tx byte count WR */
#define EN0_FIFO EI_SHIFT(0x06) /* FIFO RD */
#define EN0_TCNTHI EI_SHIFT(0x06) /* High byte of tx byte count WR */
#define EN0_ISR EI_SHIFT(0x07) /* Interrupt status reg RD WR */
#define EN0_CRDALO EI_SHIFT(0x08) /* low byte of current remote dma address RD */
#define EN0_RSARLO EI_SHIFT(0x08) /* Remote start address reg 0 */
#define EN0_CRDAHI EI_SHIFT(0x09) /* high byte, current remote dma address RD */
#define EN0_RSARHI EI_SHIFT(0x09) /* Remote start address reg 1 */
#define EN0_RCNTLO EI_SHIFT(0x0a) /* Remote byte count reg WR */
#define EN0_RCNTHI EI_SHIFT(0x0b) /* Remote byte count reg WR */
#define EN0_RSR EI_SHIFT(0x0c) /* rx status reg RD */
#define EN0_RXCR EI_SHIFT(0x0c) /* RX configuration reg WR */
#define EN0_TXCR EI_SHIFT(0x0d) /* TX configuration reg WR */
#define EN0_COUNTER0 EI_SHIFT(0x0d) /* Rcv alignment error counter RD */
#define EN0_DCFG EI_SHIFT(0x0e) /* Data configuration reg WR */
#define EN0_COUNTER1 EI_SHIFT(0x0e) /* Rcv CRC error counter RD */
#define EN0_IMR EI_SHIFT(0x0f) /* Interrupt mask reg WR */
#define EN0_COUNTER2 EI_SHIFT(0x0f) /* Rcv missed frame error counter RD */
/* Bits in EN0_ISR - Interrupt status register */
#define ENISR_RX 0x01 /* Receiver, no error */
#define ENISR_TX 0x02 /* Transmitter, no error */
#define ENISR_RX_ERR 0x04 /* Receiver, with error */
#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
#define ENISR_COUNTERS 0x20 /* Counters need emptying */
#define ENISR_RDC 0x40 /* remote dma complete */
#define ENISR_RESET 0x80 /* Reset completed */
#define ENISR_ALL 0x3f /* Interrupts we will enable */
/* Bits in EN0_DCFG - Data config register */
#define ENDCFG_WTS 0x01 /* word transfer mode selection */
/* Page 1 register offsets. */
#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */
#define EN1_PHYS_SHIFT(i) EI_SHIFT(i+1) /* Get and set mac address */
#define EN1_CURPAG EI_SHIFT(0x07) /* Current memory page RD WR */
#define EN1_MULT EI_SHIFT(0x08) /* Multicast filter mask array (8 bytes) RD WR */
#define EN1_MULT_SHIFT(i) EI_SHIFT(8+i) /* Get and set multicast filter */
/* Bits in received packet status byte and EN0_RSR*/
#define ENRSR_RXOK 0x01 /* Received a good packet */
#define ENRSR_CRC 0x02 /* CRC error */
#define ENRSR_FAE 0x04 /* frame alignment error */
#define ENRSR_FO 0x08 /* FIFO overrun */
#define ENRSR_MPA 0x10 /* missed pkt */
#define ENRSR_PHY 0x20 /* physical/multicast address */
#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
#define ENRSR_DEF 0x80 /* deferring */
/* Transmitted packet status, EN0_TSR. */
#define ENTSR_PTX 0x01 /* Packet transmitted without error */
#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
#define ENTSR_COL 0x04 /* The transmit collided at least once. */
#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
#endif /* _8390_h */
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
axnet_cs.c 1.11 2001/06/12 12:42:40 axnet_cs.c 1.28 2002/06/29 06:27:37
The network driver code is based on Donald Becker's NE2000 code: The network driver code is based on Donald Becker's NE2000 code:
Written 1992,1993 by Donald Becker. Written 1992,1993 by Donald Becker.
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
Director, National Security Agency. This software may be used and Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU General Public License, distributed according to the terms of the GNU General Public License,
incorporated herein by reference. incorporated herein by reference.
Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov Donald Becker may be reached at becker@scyld.com
======================================================================*/ ======================================================================*/
...@@ -33,14 +33,15 @@ ...@@ -33,14 +33,15 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include "ax8390.h" #include "../8390.h"
#include <pcmcia/version.h> #include <pcmcia/version.h>
#include <pcmcia/cs_types.h> #include <pcmcia/cs_types.h>
...@@ -53,34 +54,25 @@ ...@@ -53,34 +54,25 @@
#define AXNET_CMD 0x00 #define AXNET_CMD 0x00
#define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ #define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ #define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
#define AXNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
#define AXNET_MII_EEP 0x14 /* Offset of MII access port */ #define AXNET_MII_EEP 0x14 /* Offset of MII access port */
#define AXNET_TEST 0x15 /* Offset of TEST Register port */
#define AXNET_GPIO 0x17 /* Offset of General Purpose Register Port */
#define AXNET_START_PG 0x40 /* First page of TX buffer */ #define AXNET_START_PG 0x40 /* First page of TX buffer */
#define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */ #define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */
#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */ #define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
#ifdef PCMCIA_DEBUG #define IS_AX88190 0x0001
static int pc_debug = PCMCIA_DEBUG; #define IS_AX88790 0x0002
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"axnet_cs.c 1.11 2001/06/12 12:42:40 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
#define skb_tx_check(dev, skb)
#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
#define netif_mark_up(dev) do { } while (0)
#define netif_mark_down(dev) do { } while (0)
/*====================================================================*/ /*====================================================================*/
/* Parameters that can be set with 'insmod' */ /* Module parameters */
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
...@@ -89,9 +81,14 @@ INT_MODULE_PARM(irq_mask, 0xdeb8); ...@@ -89,9 +81,14 @@ INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 }; static int irq_list[4] = { -1 };
MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(irq_list, "1-4i");
/* Ugh! Let the user hardwire the hardware address for queer cards */ #ifdef PCMCIA_DEBUG
static int hw_addr[6] = { 0, /* ... */ }; INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
MODULE_PARM(hw_addr, "6i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"axnet_cs.c 1.28 2002/06/29 06:27:37 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/ /*====================================================================*/
...@@ -122,6 +119,12 @@ static void axnet_detach(dev_link_t *); ...@@ -122,6 +119,12 @@ static void axnet_detach(dev_link_t *);
static dev_info_t dev_info = "axnet_cs"; static dev_info_t dev_info = "axnet_cs";
static dev_link_t *dev_list; static dev_link_t *dev_list;
static int axdev_init(struct net_device *dev);
static void AX88190_init(struct net_device *dev, int startp);
static int ax_open(struct net_device *dev);
static int ax_close(struct net_device *dev);
static void ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*====================================================================*/ /*====================================================================*/
typedef struct axnet_dev_t { typedef struct axnet_dev_t {
...@@ -134,6 +137,7 @@ typedef struct axnet_dev_t { ...@@ -134,6 +137,7 @@ typedef struct axnet_dev_t {
u_short link_status; u_short link_status;
u_char duplex_flag; u_char duplex_flag;
int phy_id; int phy_id;
int flags;
} axnet_dev_t; } axnet_dev_t;
/*====================================================================== /*======================================================================
...@@ -212,7 +216,7 @@ static dev_link_t *axnet_attach(void) ...@@ -212,7 +216,7 @@ static dev_link_t *axnet_attach(void)
link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
ethdev_init(dev); axdev_init(dev);
dev->init = &axnet_init; dev->init = &axnet_init;
dev->open = &axnet_open; dev->open = &axnet_open;
dev->stop = &axnet_close; dev->stop = &axnet_close;
...@@ -304,7 +308,7 @@ static int get_prom(dev_link_t *link) ...@@ -304,7 +308,7 @@ static int get_prom(dev_link_t *link)
{0x00, EN0_RCNTHI}, {0x00, EN0_RCNTHI},
{0x00, EN0_IMR}, /* Mask completion irq. */ {0x00, EN0_IMR}, /* Mask completion irq. */
{0xFF, EN0_ISR}, {0xFF, EN0_ISR},
{E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ {E8390_RXOFF|0x40, EN0_RXCR}, /* 0x60 Set to monitor */
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
{0x10, EN0_RCNTLO}, {0x10, EN0_RCNTLO},
{0x00, EN0_RCNTHI}, {0x00, EN0_RCNTHI},
...@@ -331,30 +335,6 @@ static int get_prom(dev_link_t *link) ...@@ -331,30 +335,6 @@ static int get_prom(dev_link_t *link)
return 1; return 1;
} /* get_prom */ } /* get_prom */
/*======================================================================
This should be totally unnecessary... but when we can't figure
out the hardware address any other way, we'll let the user hard
wire it when the module is initialized.
======================================================================*/
static int get_hwired(dev_link_t *link)
{
struct net_device *dev = link->priv;
int i;
for (i = 0; i < 6; i++)
if (hw_addr[i] != 0) break;
if (i == 6)
return 0;
for (i = 0; i < 6; i++)
dev->dev_addr[i] = hw_addr[i];
return 1;
} /* get_hwired */
/*====================================================================== /*======================================================================
axnet_config() is scheduled to run after a CARD_INSERTION event axnet_config() is scheduled to run after a CARD_INSERTION event
...@@ -421,7 +401,8 @@ static void axnet_config(dev_link_t *link) ...@@ -421,7 +401,8 @@ static void axnet_config(dev_link_t *link)
CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(GetTupleData, handle, &tuple);
CS_CHECK(ParseTuple, handle, &tuple, &parse); CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base; link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0]; /* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
/* Configure card */ /* Configure card */
link->state |= DEV_CONFIG; link->state |= DEV_CONFIG;
...@@ -442,7 +423,7 @@ static void axnet_config(dev_link_t *link) ...@@ -442,7 +423,7 @@ static void axnet_config(dev_link_t *link)
if ((cfg->index == 0) || (cfg->io.nwin == 0)) if ((cfg->index == 0) || (cfg->io.nwin == 0))
goto next_entry; goto next_entry;
link->conf.ConfigIndex = cfg->index; link->conf.ConfigIndex = 0x05;
/* For multifunction cards, by convention, we configure the /* For multifunction cards, by convention, we configure the
network function with window 0, and serial with window 1 */ network function with window 0, and serial with window 1 */
if (io->nwin > 1) { if (io->nwin > 1) {
...@@ -482,9 +463,9 @@ static void axnet_config(dev_link_t *link) ...@@ -482,9 +463,9 @@ static void axnet_config(dev_link_t *link)
goto failed; goto failed;
} }
if (!get_prom(link) && !get_hwired(link)) { if (!get_prom(link)) {
printk(KERN_NOTICE "axnet_cs: unable to read hardware net" printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
" address for io base %#3lx\n", dev->base_addr); printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
unregister_netdev(dev); unregister_netdev(dev);
goto failed; goto failed;
} }
...@@ -501,17 +482,37 @@ static void axnet_config(dev_link_t *link) ...@@ -501,17 +482,37 @@ static void axnet_config(dev_link_t *link)
strcpy(info->node.dev_name, dev->name); strcpy(info->node.dev_name, dev->name);
link->dev = &info->node; link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: Asix AX88190: io %#3lx, irq %d, hw_addr ", if (inb(dev->base_addr + AXNET_TEST) != 0)
dev->name, dev->base_addr, dev->irq); info->flags |= IS_AX88790;
else
info->flags |= IS_AX88190;
printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
dev->base_addr, dev->irq);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
if (info->flags & IS_AX88790)
outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
if ((j != 0) && (j != 0xffff)) break; if ((j != 0) && (j != 0xffff)) break;
} }
/* Maybe PHY is in power down mode. (PPD_SET = 1)
Bit 2 of CCSR is active low. */
if (i == 32) {
conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
CardServices(AccessConfigurationRegister, link->handle, &reg);
for (i = 0; i < 32; i++) {
j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
if ((j != 0) && (j != 0xffff)) break;
}
}
info->phy_id = (i < 32) ? i : -1; info->phy_id = (i < 32) ? i : -1;
if (i < 32) { if (i < 32) {
DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j); DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
...@@ -519,12 +520,14 @@ static void axnet_config(dev_link_t *link) ...@@ -519,12 +520,14 @@ static void axnet_config(dev_link_t *link)
printk(KERN_NOTICE " No MII transceivers found!\n"); printk(KERN_NOTICE " No MII transceivers found!\n");
} }
link->state &= ~DEV_CONFIG_PENDING;
return; return;
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
axnet_release((u_long)link); axnet_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
return; return;
} /* axnet_config */ } /* axnet_config */
...@@ -544,7 +547,7 @@ static void axnet_release(u_long arg) ...@@ -544,7 +547,7 @@ static void axnet_release(u_long arg)
if (link->open) { if (link->open) {
DEBUG(1, "axnet_cs: release postponed, '%s' still open\n", DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
info->node.dev_name); ((axnet_dev_t *)(link->priv))->node.dev_name);
link->state |= DEV_STALE_CONFIG; link->state |= DEV_STALE_CONFIG;
return; return;
} }
...@@ -583,7 +586,7 @@ static int axnet_event(event_t event, int priority, ...@@ -583,7 +586,7 @@ static int axnet_event(event_t event, int priority,
} }
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
axnet_config(link); axnet_config(link);
break; break;
case CS_EVENT_PM_SUSPEND: case CS_EVENT_PM_SUSPEND:
...@@ -604,7 +607,7 @@ static int axnet_event(event_t event, int priority, ...@@ -604,7 +607,7 @@ static int axnet_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf); CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) { if (link->open) {
axnet_reset_8390(&info->dev); axnet_reset_8390(&info->dev);
NS8390_init(&info->dev, 1); AX88190_init(&info->dev, 1);
netif_device_attach(&info->dev); netif_device_attach(&info->dev);
} }
} }
...@@ -695,7 +698,7 @@ static int axnet_open(struct net_device *dev) ...@@ -695,7 +698,7 @@ static int axnet_open(struct net_device *dev)
info->watchdog.expires = jiffies + HZ; info->watchdog.expires = jiffies + HZ;
add_timer(&info->watchdog); add_timer(&info->watchdog);
return ei_open(dev); return ax_open(dev);
} /* axnet_open */ } /* axnet_open */
/*====================================================================*/ /*====================================================================*/
...@@ -707,11 +710,11 @@ static int axnet_close(struct net_device *dev) ...@@ -707,11 +710,11 @@ static int axnet_close(struct net_device *dev)
DEBUG(2, "axnet_close('%s')\n", dev->name); DEBUG(2, "axnet_close('%s')\n", dev->name);
ax_close(dev);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
netif_mark_down(dev);
del_timer(&info->watchdog); del_timer(&info->watchdog);
if (link->state & DEV_STALE_CONFIG) if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20); mod_timer(&link->release, jiffies + HZ/20);
...@@ -758,7 +761,7 @@ static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) ...@@ -758,7 +761,7 @@ static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
{ {
axnet_dev_t *info = dev_id; axnet_dev_t *info = dev_id;
info->stale = 0; info->stale = 0;
ei_interrupt(irq, dev_id, regs); ax_interrupt(irq, dev_id, regs);
} }
static void ei_watchdog(u_long arg) static void ei_watchdog(u_long arg)
...@@ -810,7 +813,7 @@ static void ei_watchdog(u_long arg) ...@@ -810,7 +813,7 @@ static void ei_watchdog(u_long arg)
else else
printk(KERN_INFO "%s: link partner did not autonegotiate\n", printk(KERN_INFO "%s: link partner did not autonegotiate\n",
dev->name); dev->name);
NS8390_init(dev, 1); AX88190_init(dev, 1);
} }
info->link_status = link; info->link_status = link;
} }
...@@ -822,23 +825,22 @@ static void ei_watchdog(u_long arg) ...@@ -822,23 +825,22 @@ static void ei_watchdog(u_long arg)
static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
{ {
u32 ethcmd; u32 ethcmd;
if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd))) if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
return -EFAULT; return -EFAULT;
switch (ethcmd) { switch (ethcmd) {
case ETHTOOL_GDRVINFO: { case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
strncpy(info.driver, "axnet_cs", sizeof(info.driver)-1);
strncpy(info.driver, "axnet_cs", sizeof(info.driver)-1); if (copy_to_user(useraddr, &info, sizeof(info)))
if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT;
return -EFAULT; return 0;
return 0; }
} }
}
return -EOPNOTSUPP;
return -EOPNOTSUPP;
} }
/*====================================================================*/ /*====================================================================*/
...@@ -850,7 +852,7 @@ static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -850,7 +852,7 @@ static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ioaddr_t mii_addr = dev->base_addr + AXNET_MII_EEP; ioaddr_t mii_addr = dev->base_addr + AXNET_MII_EEP;
switch (cmd) { switch (cmd) {
case SIOCETHTOOL: case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCDEVPRIVATE: case SIOCDEVPRIVATE:
data[0] = info->phy_id; data[0] = info->phy_id;
case SIOCDEVPRIVATE+1: case SIOCDEVPRIVATE+1:
...@@ -941,7 +943,7 @@ static int __init init_axnet_cs(void) ...@@ -941,7 +943,7 @@ static int __init init_axnet_cs(void)
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "axnet_cs: Card Services release " printk(KERN_NOTICE "axnet_cs: Card Services release "
"does not match!\n"); "does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach); register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach);
return 0; return 0;
...@@ -970,10 +972,11 @@ module_exit(exit_axnet_cs); ...@@ -970,10 +972,11 @@ module_exit(exit_axnet_cs);
This software may be used and distributed according to the terms This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference. of the GNU General Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O The author may be reached as becker@scyld.com, or C/O
Center of Excellence in Space Data and Information Sciences Scyld Computing Corporation
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 410 Severn Ave., Suite 210
Annapolis MD 21403
This is the chip-specific code for many 8390-based ethernet adaptors. This is the chip-specific code for many 8390-based ethernet adaptors.
This is not a complete driver, it must be combined with board-specific This is not a complete driver, it must be combined with board-specific
code such as ne.c, wd.c, 3c503.c, etc. code such as ne.c, wd.c, 3c503.c, etc.
...@@ -983,7 +986,6 @@ module_exit(exit_axnet_cs); ...@@ -983,7 +986,6 @@ module_exit(exit_axnet_cs);
a simple innocent change. Please contact me or Donald if you think a simple innocent change. Please contact me or Donald if you think
you have found something that needs changing. -- PG you have found something that needs changing. -- PG
Changelog: Changelog:
Paul Gortmaker : remove set_bit lock, other cleanups. Paul Gortmaker : remove set_bit lock, other cleanups.
...@@ -1007,8 +1009,8 @@ module_exit(exit_axnet_cs); ...@@ -1007,8 +1009,8 @@ module_exit(exit_axnet_cs);
*/ */
static const char *version = static const char *version_8390 =
"8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -1088,25 +1090,23 @@ static void do_set_multicast_list(struct net_device *dev); ...@@ -1088,25 +1090,23 @@ static void do_set_multicast_list(struct net_device *dev);
* them. * them.
*/ */
/** /**
* ei_open - Open/initialize the board. * ax_open - Open/initialize the board.
* @dev: network device to initialize * @dev: network device to initialize
* *
* This routine goes all-out, setting everything * This routine goes all-out, setting everything
* up anew at each open, even though many of these registers should only * up anew at each open, even though many of these registers should only
* need to be set once at boot. * need to be set once at boot.
*/ */
static int ei_open(struct net_device *dev) static int ax_open(struct net_device *dev)
{ {
unsigned long flags; unsigned long flags;
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
/* This can't happen unless somebody forgot to call ethdev_init(). */ /* This can't happen unless somebody forgot to call axdev_init(). */
if (ei_local == NULL) if (ei_local == NULL)
{ {
printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); printk(KERN_EMERG "%s: ax_open passed a non-existent device!\n", dev->name);
return -ENXIO; return -ENXIO;
} }
...@@ -1125,16 +1125,38 @@ static int ei_open(struct net_device *dev) ...@@ -1125,16 +1125,38 @@ static int ei_open(struct net_device *dev)
*/ */
spin_lock_irqsave(&ei_local->page_lock, flags); spin_lock_irqsave(&ei_local->page_lock, flags);
NS8390_init(dev, 1); AX88190_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives /* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */ after its set and we get no silly warnings */
netif_mark_up(dev);
netif_start_queue(dev); netif_start_queue(dev);
spin_unlock_irqrestore(&ei_local->page_lock, flags); spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0; ei_local->irqlock = 0;
return 0; return 0;
} }
#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
/**
* ax_close - shut down network device
* @dev: network device to close
*
* Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
*/
int ax_close(struct net_device *dev)
{
unsigned long flags;
/*
* Hold the page lock during close
*/
spin_lock_irqsave(&dev_lock(dev), flags);
AX88190_init(dev, 0);
spin_unlock_irqrestore(&dev_lock(dev), flags);
netif_stop_queue(dev);
return 0;
}
/** /**
* ei_tx_timeout - handle transmit time out condition * ei_tx_timeout - handle transmit time out condition
* @dev: network device which has apparently fallen asleep * @dev: network device which has apparently fallen asleep
...@@ -1174,7 +1196,7 @@ void ei_tx_timeout(struct net_device *dev) ...@@ -1174,7 +1196,7 @@ void ei_tx_timeout(struct net_device *dev)
/* Try to restart the card. Perhaps the user has fixed something. */ /* Try to restart the card. Perhaps the user has fixed something. */
ei_reset_8390(dev); ei_reset_8390(dev);
NS8390_init(dev, 1); AX88190_init(dev, 1);
spin_unlock(&ei_local->page_lock); spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq); enable_irq(dev->irq);
...@@ -1197,7 +1219,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1197,7 +1219,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags; unsigned long flags;
netif_stop_queue(dev); netif_stop_queue(dev);
skb_tx_check(dev, skb);
length = skb->len; length = skb->len;
...@@ -1210,7 +1231,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1210,7 +1231,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
outb_p(0x00, e8390_base + EN0_IMR); outb_p(0x00, e8390_base + EN0_IMR);
spin_unlock_irqrestore(&ei_local->page_lock, flags); spin_unlock_irqrestore(&ei_local->page_lock, flags);
/* /*
* Slow phase with lock held. * Slow phase with lock held.
*/ */
...@@ -1223,8 +1243,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1223,8 +1243,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
send_length = ETH_ZLEN < length ? length : ETH_ZLEN; send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
#ifdef EI_PINGPONG
/* /*
* We have two Tx slots available for use. Find the first free * We have two Tx slots available for use. Find the first free
* slot, and then perform some sanity checks. With two Tx bufs, * slot, and then perform some sanity checks. With two Tx bufs,
...@@ -1293,22 +1311,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1293,22 +1311,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
else else
netif_start_queue(dev); netif_start_queue(dev);
#else /* EI_PINGPONG */
/*
* Only one Tx buffer in use. You need two Tx bufs to come close to
* back-to-back transmits. Expect a 20 -> 25% performance hit on
* reasonable hardware if you only use one Tx buffer.
*/
ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
ei_local->txing = 1;
NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
dev->trans_start = jiffies;
netif_stop_queue(dev);
#endif /* EI_PINGPONG */
/* Turn 8390 interrupts back on. */ /* Turn 8390 interrupts back on. */
ei_local->irqlock = 0; ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR); outb_p(ENISR_ALL, e8390_base + EN0_IMR);
...@@ -1316,14 +1318,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1316,14 +1318,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&ei_local->page_lock); spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq); enable_irq(dev->irq);
DEV_KFREE_SKB (skb); dev_kfree_skb (skb);
add_tx_bytes(&ei_local->stat, send_length); ei_local->stat.tx_bytes += send_length;
return 0; return 0;
} }
/** /**
* ei_interrupt - handle the interrupts from an 8390 * ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number * @irq: interrupt number
* @dev_id: a pointer to the net_device * @dev_id: a pointer to the net_device
* @regs: unused * @regs: unused
...@@ -1335,7 +1337,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1335,7 +1337,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
* needed. * needed.
*/ */
static void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) static void ax_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
long e8390_base; long e8390_base;
...@@ -1502,8 +1504,6 @@ static void ei_tx_intr(struct net_device *dev) ...@@ -1502,8 +1504,6 @@ static void ei_tx_intr(struct net_device *dev)
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
int status = inb(e8390_base + EN0_TSR); int status = inb(e8390_base + EN0_TSR);
#ifdef EI_PINGPONG
/* /*
* There are two Tx buffers, see which one finished, and trigger * There are two Tx buffers, see which one finished, and trigger
* the send of another one if it exists. * the send of another one if it exists.
...@@ -1546,13 +1546,6 @@ static void ei_tx_intr(struct net_device *dev) ...@@ -1546,13 +1546,6 @@ static void ei_tx_intr(struct net_device *dev)
// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", // else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
// dev->name, ei_local->lasttx); // dev->name, ei_local->lasttx);
#else /* EI_PINGPONG */
/*
* Single Tx buffer: mark it free so another packet can be loaded.
*/
ei_local->txing = 0;
#endif
/* Minimize Tx latency: update the statistics after we restart TXing. */ /* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL) if (status & ENTSR_COL)
ei_local->stat.collisions++; ei_local->stat.collisions++;
...@@ -1660,7 +1653,7 @@ static void ei_receive(struct net_device *dev) ...@@ -1660,7 +1653,7 @@ static void ei_receive(struct net_device *dev)
netif_rx(skb); netif_rx(skb);
dev->last_rx = jiffies; dev->last_rx = jiffies;
ei_local->stat.rx_packets++; ei_local->stat.rx_packets++;
add_rx_bytes(&ei_local->stat, pkt_len); ei_local->stat.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY) if (pkt_stat & ENRSR_PHY)
ei_local->stat.multicast++; ei_local->stat.multicast++;
} }
...@@ -1806,11 +1799,11 @@ static void do_set_multicast_list(struct net_device *dev) ...@@ -1806,11 +1799,11 @@ static void do_set_multicast_list(struct net_device *dev)
long e8390_base = dev->base_addr; long e8390_base = dev->base_addr;
if(dev->flags&IFF_PROMISC) if(dev->flags&IFF_PROMISC)
outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR); outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
else if(dev->flags&IFF_ALLMULTI || dev->mc_list) else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR); outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
else else
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
} }
/* /*
...@@ -1818,28 +1811,28 @@ static void do_set_multicast_list(struct net_device *dev) ...@@ -1818,28 +1811,28 @@ static void do_set_multicast_list(struct net_device *dev)
* be parallel to just about everything else. Its also fairly quick and * be parallel to just about everything else. Its also fairly quick and
* not called too often. Must protect against both bh and irq users * not called too often. Must protect against both bh and irq users
*/ */
static void set_multicast_list(struct net_device *dev) static void set_multicast_list(struct net_device *dev)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags); spin_lock_irqsave(&dev_lock(dev), flags);
do_set_multicast_list(dev); do_set_multicast_list(dev);
spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags); spin_unlock_irqrestore(&dev_lock(dev), flags);
} }
/** /**
* ethdev_init - init rest of 8390 device struct * axdev_init - init rest of 8390 device struct
* @dev: network device structure to init * @dev: network device structure to init
* *
* Initialize the rest of the 8390 device structure. Do NOT __init * Initialize the rest of the 8390 device structure. Do NOT __init
* this, as it is used by 8390 based modular drivers too. * this, as it is used by 8390 based modular drivers too.
*/ */
static int ethdev_init(struct net_device *dev) static int axdev_init(struct net_device *dev)
{ {
if (ei_debug > 1) if (ei_debug > 1)
printk(version); printk(version_8390);
if (dev->priv == NULL) if (dev->priv == NULL)
{ {
...@@ -1861,21 +1854,19 @@ static int ethdev_init(struct net_device *dev) ...@@ -1861,21 +1854,19 @@ static int ethdev_init(struct net_device *dev)
return 0; return 0;
} }
/* This page of functions should be 8390 generic */ /* This page of functions should be 8390 generic */
/* Follow National Semi's recommendations for initializing the "NIC". */ /* Follow National Semi's recommendations for initializing the "NIC". */
/** /**
* NS8390_init - initialize 8390 hardware * AX88190_init - initialize 8390 hardware
* @dev: network device to initialize * @dev: network device to initialize
* @startp: boolean. non-zero value to initiate chip processing * @startp: boolean. non-zero value to initiate chip processing
* *
* Must be called with lock held. * Must be called with lock held.
*/ */
static void NS8390_init(struct net_device *dev, int startp) static void AX88190_init(struct net_device *dev, int startp)
{ {
axnet_dev_t *info = (axnet_dev_t *)dev; axnet_dev_t *info = (axnet_dev_t *)dev;
long e8390_base = dev->base_addr; long e8390_base = dev->base_addr;
...@@ -1892,7 +1883,7 @@ static void NS8390_init(struct net_device *dev, int startp) ...@@ -1892,7 +1883,7 @@ static void NS8390_init(struct net_device *dev, int startp)
outb_p(0x00, e8390_base + EN0_RCNTLO); outb_p(0x00, e8390_base + EN0_RCNTLO);
outb_p(0x00, e8390_base + EN0_RCNTHI); outb_p(0x00, e8390_base + EN0_RCNTHI);
/* Set to monitor and loopback mode -- this is vital!. */ /* Set to monitor and loopback mode -- this is vital!. */
outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
/* Set the transmit page and receive ring. */ /* Set the transmit page and receive ring. */
outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
...@@ -1936,7 +1927,7 @@ static void NS8390_init(struct net_device *dev, int startp) ...@@ -1936,7 +1927,7 @@ static void NS8390_init(struct net_device *dev, int startp)
outb_p(E8390_TXCONFIG | info->duplex_flag, outb_p(E8390_TXCONFIG | info->duplex_flag,
e8390_base + EN0_TXCR); /* xmit on. */ e8390_base + EN0_TXCR); /* xmit on. */
/* 3c503 TechMan says rxconfig only after the NIC is started. */ /* 3c503 TechMan says rxconfig only after the NIC is started. */
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
do_set_multicast_list(dev); /* (re)load the mcast table */ do_set_multicast_list(dev); /* (re)load the mcast table */
} }
} }
......
/*====================================================================== /*======================================================================
fmvj18x_cs.c 2.6 2001/09/17 fmvj18x_cs.c 2.8 2002/03/23
A fmvj18x (and its compatibles) PCMCIA client driver A fmvj18x (and its compatibles) PCMCIA client driver
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
======================================================================*/ ======================================================================*/
#define DRV_NAME "fmvj18x_cs" #define DRV_NAME "fmvj18x_cs"
#define DRV_VERSION "2.6" #define DRV_VERSION "2.8"
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -65,6 +65,10 @@ ...@@ -65,6 +65,10 @@
/*====================================================================*/ /*====================================================================*/
/* Module parameters */ /* Module parameters */
MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */ /* Bit map of interrupts to choose from */
...@@ -80,7 +84,7 @@ INT_MODULE_PARM(sram_config, 0); ...@@ -80,7 +84,7 @@ INT_MODULE_PARM(sram_config, 0);
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17"; static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
#else #else
#define DEBUG(n, args...) #define DEBUG(n, args...)
#endif #endif
...@@ -91,6 +95,7 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17"; ...@@ -91,6 +95,7 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17";
*/ */
static void fmvj18x_config(dev_link_t *link); static void fmvj18x_config(dev_link_t *link);
static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
static int fmvj18x_setup_mfc(dev_link_t *link);
static void fmvj18x_release(u_long arg); static void fmvj18x_release(u_long arg);
static int fmvj18x_event(event_t event, int priority, static int fmvj18x_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
...@@ -122,8 +127,6 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, ...@@ -122,8 +127,6 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
XXX10304 XXX10304
} cardtype_t; } cardtype_t;
#define MANFID_UNGERMANN 0x02c0
/* /*
driver specific data structure driver specific data structure
*/ */
...@@ -388,6 +391,45 @@ static void fmvj18x_detach(dev_link_t *link) ...@@ -388,6 +391,45 @@ static void fmvj18x_detach(dev_link_t *link)
#define CS_CHECK(fn, args...) \ #define CS_CHECK(fn, args...) \
while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static int mfc_try_io_port(dev_link_t *link)
{
int i, ret;
static ioaddr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
for (i = 0; i < 5; i++) {
link->io.BasePort2 = serial_base[i];
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
if (link->io.BasePort2 == 0) {
link->io.NumPorts2 = 0;
printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
}
ret = CardServices(RequestIO, link->handle, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
}
static int ungermann_try_io_port(dev_link_t *link)
{
int ret;
ioaddr_t ioaddr;
/*
Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
0x380,0x3c0 only for ioport.
*/
for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
link->io.BasePort1 = ioaddr;
ret = CardServices(RequestIO, link->handle, &link->io);
if (ret == CS_SUCCESS) {
/* calculate ConfigIndex value */
link->conf.ConfigIndex =
((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
return ret;
}
}
return ret; /* RequestIO failed */
}
static void fmvj18x_config(dev_link_t *link) static void fmvj18x_config(dev_link_t *link)
{ {
client_handle_t handle = link->handle; client_handle_t handle = link->handle;
...@@ -401,7 +443,7 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -401,7 +443,7 @@ static void fmvj18x_config(dev_link_t *link)
cardtype_t cardtype; cardtype_t cardtype;
char *card_name = "unknown"; char *card_name = "unknown";
u_char *node_id; u_char *node_id;
DEBUG(0, "fmvj18x_config(0x%p)\n", link); DEBUG(0, "fmvj18x_config(0x%p)\n", link);
/* /*
...@@ -444,6 +486,11 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -444,6 +486,11 @@ static void fmvj18x_config(dev_link_t *link)
CardServices(GetStatus, handle, &status); CardServices(GetStatus, handle, &status);
if (status.CardState & CS_EVENT_3VCARD) if (status.CardState & CS_EVENT_3VCARD)
link->conf.Vcc = 33; /* inserted in 3.3V slot */ link->conf.Vcc = 33; /* inserted in 3.3V slot */
} else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) {
/* MultiFunction Card */
link->conf.ConfigBase = 0x800;
link->conf.ConfigIndex = 0x47;
link->io.NumPorts2 = 8;
} }
break; break;
case MANFID_CONTEC: case MANFID_CONTEC:
...@@ -481,31 +528,22 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -481,31 +528,22 @@ static void fmvj18x_config(dev_link_t *link)
break; break;
case MANFID_UNGERMANN: case MANFID_UNGERMANN:
cardtype = UNGERMANN; cardtype = UNGERMANN;
/* break;
Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
0x380,0x3c0 only for ioport.
*/
for (link->io.BasePort1 = 0x300; link->io.BasePort1 < 0x3e0;
link->io.BasePort1 += 0x20) {
ret = CardServices(RequestIO, link->handle, &link->io);
if (ret == CS_SUCCESS) {
/* calculate ConfigIndex value */
link->conf.ConfigIndex =
((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
goto req_irq;
}
}
/* if ioport allocation is failed, goto failed */
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
goto failed;
default: default:
cardtype = MBH10302; cardtype = MBH10302;
link->conf.ConfigIndex = 1; link->conf.ConfigIndex = 1;
} }
} }
CS_CHECK(RequestIO, link->handle, &link->io); if (link->io.NumPorts2 != 0) {
req_irq: ret = mfc_try_io_port(link);
if (ret != CS_SUCCESS) goto cs_failed;
} else if (cardtype == UNGERMANN) {
ret = ungermann_try_io_port(link);
if (ret != CS_SUCCESS) goto cs_failed;
} else {
CS_CHECK(RequestIO, link->handle, &link->io);
}
CS_CHECK(RequestIRQ, link->handle, &link->irq); CS_CHECK(RequestIRQ, link->handle, &link->irq);
CS_CHECK(RequestConfiguration, link->handle, &link->conf); CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
...@@ -515,19 +553,22 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -515,19 +553,22 @@ static void fmvj18x_config(dev_link_t *link)
goto failed; goto failed;
} }
if (link->io.BasePort2 != 0)
fmvj18x_setup_mfc(link);
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
/* Reset controller */ /* Reset controller */
if( sram_config == 0 ) if (sram_config == 0)
outb(CONFIG0_RST, ioaddr + CONFIG_0); outb(CONFIG0_RST, ioaddr + CONFIG_0);
else else
outb(CONFIG0_RST_1, ioaddr + CONFIG_0); outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
/* Power On chip and select bank 0 */ /* Power On chip and select bank 0 */
if(cardtype == UNGERMANN) if (cardtype == MBH10302)
outb(BANK_0U, ioaddr + CONFIG_1);
else
outb(BANK_0, ioaddr + CONFIG_1); outb(BANK_0, ioaddr + CONFIG_1);
else
outb(BANK_0U, ioaddr + CONFIG_1);
/* Set hardware address */ /* Set hardware address */
switch (cardtype) { switch (cardtype) {
...@@ -591,7 +632,6 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -591,7 +632,6 @@ static void fmvj18x_config(dev_link_t *link)
strcpy(lp->node.dev_name, dev->name); strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node; link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
lp->cardtype = cardtype; lp->cardtype = cardtype;
/* print current configuration */ /* print current configuration */
...@@ -601,6 +641,7 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -601,6 +641,7 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
link->state &= ~DEV_CONFIG_PENDING;
return; return;
cs_failed: cs_failed:
...@@ -608,6 +649,7 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -608,6 +649,7 @@ static void fmvj18x_config(dev_link_t *link)
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
fmvj18x_release((u_long)link); fmvj18x_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* fmvj18x_config */ } /* fmvj18x_config */
/*====================================================================*/ /*====================================================================*/
...@@ -666,6 +708,51 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) ...@@ -666,6 +708,51 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
} /* fmvj18x_get_hwinfo */ } /* fmvj18x_get_hwinfo */
/*====================================================================*/ /*====================================================================*/
static int fmvj18x_setup_mfc(dev_link_t *link)
{
win_req_t req;
memreq_t mem;
u_char *base;
int i, j;
local_info_t *lp = link->priv;
struct net_device *dev = &lp->dev;
ioaddr_t ioaddr;
/* Allocate a small memory window */
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
link->win = (window_handle_t)link->handle;
i = CardServices(RequestWindow, &link->win, &req);
if (i != CS_SUCCESS) {
cs_error(link->handle, RequestWindow, i);
return -1;
}
base = ioremap(req.Base, req.Size);
mem.Page = 0;
mem.CardOffset = 0;
CardServices(MapMemPage, link->win, &mem);
ioaddr = dev->base_addr;
writeb(0x47, base+0x800); /* Config Option Register of LAN */
writeb(0x0, base+0x802); /* Config and Status Register */
writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */
writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */
writeb(0x45, base+0x820); /* Config Option Register of Modem */
writeb(0x8, base+0x822); /* Config and Status Register */
iounmap(base);
j = CardServices(ReleaseWindow, link->win);
if (j != CS_SUCCESS)
cs_error(link->handle, ReleaseWindow, j);
return 0;
}
/*====================================================================*/
static void fmvj18x_release(u_long arg) static void fmvj18x_release(u_long arg)
{ {
dev_link_t *link = (dev_link_t *)arg; dev_link_t *link = (dev_link_t *)arg;
...@@ -752,7 +839,7 @@ static int __init init_fmvj18x_cs(void) ...@@ -752,7 +839,7 @@ static int __init init_fmvj18x_cs(void)
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "fmvj18x: Card Services release " printk(KERN_NOTICE "fmvj18x: Card Services release "
"does not match!\n"); "does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach); register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach);
return 0; return 0;
...@@ -942,10 +1029,10 @@ static void fjn_reset(struct net_device *dev) ...@@ -942,10 +1029,10 @@ static void fjn_reset(struct net_device *dev)
outb(CONFIG0_RST_1, ioaddr + CONFIG_0); outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
/* Power On chip and select bank 0 */ /* Power On chip and select bank 0 */
if( lp->cardtype == UNGERMANN) if (lp->cardtype == MBH10302)
outb(BANK_0U, ioaddr + CONFIG_1);
else
outb(BANK_0, ioaddr + CONFIG_1); outb(BANK_0, ioaddr + CONFIG_1);
else
outb(BANK_0U, ioaddr + CONFIG_1);
/* Set Tx modes */ /* Set Tx modes */
outb(D_TX_MODE, ioaddr + TX_MODE); outb(D_TX_MODE, ioaddr + TX_MODE);
...@@ -957,20 +1044,20 @@ static void fjn_reset(struct net_device *dev) ...@@ -957,20 +1044,20 @@ static void fjn_reset(struct net_device *dev)
outb(dev->dev_addr[i], ioaddr + NODE_ID + i); outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
/* Switch to bank 1 */ /* Switch to bank 1 */
if ( lp->cardtype == UNGERMANN ) if (lp->cardtype == MBH10302)
outb(BANK_1U, ioaddr + CONFIG_1);
else
outb(BANK_1, ioaddr + CONFIG_1); outb(BANK_1, ioaddr + CONFIG_1);
else
outb(BANK_1U, ioaddr + CONFIG_1);
/* set the multicast table to accept none. */ /* set the multicast table to accept none. */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
outb(0x00, ioaddr + MAR_ADR + i); outb(0x00, ioaddr + MAR_ADR + i);
/* Switch to bank 2 (runtime mode) */ /* Switch to bank 2 (runtime mode) */
if ( lp->cardtype == UNGERMANN ) if (lp->cardtype == MBH10302)
outb(BANK_2U, ioaddr + CONFIG_1);
else
outb(BANK_2, ioaddr + CONFIG_1); outb(BANK_2, ioaddr + CONFIG_1);
else
outb(BANK_2U, ioaddr + CONFIG_1);
/* set 16col ctrl bits */ /* set 16col ctrl bits */
if( lp->cardtype == TDK || lp->cardtype == CONTEC) if( lp->cardtype == TDK || lp->cardtype == CONTEC)
...@@ -999,16 +1086,16 @@ static void fjn_reset(struct net_device *dev) ...@@ -999,16 +1086,16 @@ static void fjn_reset(struct net_device *dev)
outb(0xff, ioaddr + TX_STATUS); outb(0xff, ioaddr + TX_STATUS);
outb(0xff, ioaddr + RX_STATUS); outb(0xff, ioaddr + RX_STATUS);
if( lp->cardtype != TDK ) if (lp->cardtype == MBH10302)
outb(INTR_OFF, ioaddr + LAN_CTRL); outb(INTR_OFF, ioaddr + LAN_CTRL);
/* Turn on Rx interrupts */ /* Turn on Rx interrupts */
outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR);
/* Turn on interrupts from LAN card controller */ /* Turn on interrupts from LAN card controller */
if( lp->cardtype != TDK ) if (lp->cardtype == MBH10302)
outb(INTR_ON, ioaddr + LAN_CTRL); outb(INTR_ON, ioaddr + LAN_CTRL);
} /* fjn_reset */ } /* fjn_reset */
/*====================================================================*/ /*====================================================================*/
...@@ -1063,7 +1150,7 @@ static void fjn_rx(struct net_device *dev) ...@@ -1063,7 +1150,7 @@ static void fjn_rx(struct net_device *dev)
skb_reserve(skb, 2); skb_reserve(skb, 2);
insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
(pkt_len + 1) >> 1); (pkt_len + 1) >> 1);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
...@@ -1090,7 +1177,7 @@ static void fjn_rx(struct net_device *dev) ...@@ -1090,7 +1177,7 @@ static void fjn_rx(struct net_device *dev)
has done a netif_wake_queue() for us and will work on them has done a netif_wake_queue() for us and will work on them
when we get to the bottom-half routine. */ when we get to the bottom-half routine. */
/* /*
if( lp->cardtype != TDK ) { if (lp->cardtype != TDK) {
int i; int i;
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {
if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP) if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
...@@ -1223,7 +1310,7 @@ static int fjn_close(struct net_device *dev) ...@@ -1223,7 +1310,7 @@ static int fjn_close(struct net_device *dev)
outb(CHIP_OFF ,ioaddr + CONFIG_1); outb(CHIP_OFF ,ioaddr + CONFIG_1);
/* Set the ethernet adaptor disable IRQ */ /* Set the ethernet adaptor disable IRQ */
if( lp->cardtype != TDK ) if (lp->cardtype == MBH10302)
outb(INTR_OFF, ioaddr + LAN_CTRL); outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--; link->open--;
...@@ -1252,8 +1339,8 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1252,8 +1339,8 @@ static void set_rx_mode(struct net_device *dev)
{ {
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
struct local_info_t *lp = (struct local_info_t *)dev->priv; struct local_info_t *lp = (struct local_info_t *)dev->priv;
unsigned char mc_filter[8]; /* Multicast hash filter */ u_char mc_filter[8]; /* Multicast hash filter */
unsigned long flags; u_long flags;
int i; int i;
if (dev->flags & IFF_PROMISC) { if (dev->flags & IFF_PROMISC) {
...@@ -1293,4 +1380,3 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1293,4 +1380,3 @@ static void set_rx_mode(struct net_device *dev)
} }
restore_flags(flags); restore_flags(flags);
} }
MODULE_LICENSE("GPL");
...@@ -106,6 +106,10 @@ Log: nmclan_cs.c,v ...@@ -106,6 +106,10 @@ Log: nmclan_cs.c,v
---------------------------------------------------------------------------- */ ---------------------------------------------------------------------------- */
#define DRV_NAME "nmclan_cs"
#define DRV_VERSION "0.16"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
Conditional Compilation Options Conditional Compilation Options
---------------------------------------------------------------------------- */ ---------------------------------------------------------------------------- */
...@@ -130,6 +134,9 @@ Include Files ...@@ -130,6 +134,9 @@ Include Files
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -375,7 +382,7 @@ Private Global Variables ...@@ -375,7 +382,7 @@ Private Global Variables
static char rcsid[] = static char rcsid[] =
"nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao"; "nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao";
static char *version = static char *version =
"nmclan_cs 0.16 (Roger C. Pao)"; DRV_NAME " " DRV_VERSION " (Roger C. Pao)";
#endif #endif
static dev_info_t dev_info="nmclan_cs"; static dev_info_t dev_info="nmclan_cs";
...@@ -430,8 +437,8 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); ...@@ -430,8 +437,8 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *mace_get_stats(struct net_device *dev); static struct net_device_stats *mace_get_stats(struct net_device *dev);
static int mace_rx(struct net_device *dev, unsigned char RxCnt); static int mace_rx(struct net_device *dev, unsigned char RxCnt);
static void restore_multicast_list(struct net_device *dev); static void restore_multicast_list(struct net_device *dev);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
static int mace_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static dev_link_t *nmclan_attach(void); static dev_link_t *nmclan_attach(void);
static void nmclan_detach(dev_link_t *); static void nmclan_detach(dev_link_t *);
...@@ -513,6 +520,7 @@ static dev_link_t *nmclan_attach(void) ...@@ -513,6 +520,7 @@ static dev_link_t *nmclan_attach(void)
dev->set_config = &mace_config; dev->set_config = &mace_config;
dev->get_stats = &mace_get_stats; dev->get_stats = &mace_get_stats;
dev->set_multicast_list = &set_multicast_list; dev->set_multicast_list = &set_multicast_list;
dev->do_ioctl = &mace_ioctl;
ether_setup(dev); ether_setup(dev);
dev->open = &mace_open; dev->open = &mace_open;
dev->stop = &mace_close; dev->stop = &mace_close;
...@@ -1002,6 +1010,66 @@ static int mace_close(struct net_device *dev) ...@@ -1002,6 +1010,66 @@ static int mace_close(struct net_device *dev)
return 0; return 0;
} /* mace_close */ } /* mace_close */
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{
u32 ethcmd;
/* dev_ioctl() in ../../net/core/dev.c has already checked
capable(CAP_NET_ADMIN), so don't bother with that here. */
if (get_user(ethcmd, (u32 *)useraddr))
return -EFAULT;
switch (ethcmd) {
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, DRV_NAME);
strcpy (info.version, DRV_VERSION);
sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
#ifdef PCMCIA_DEBUG
/* get message-level */
case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = pc_debug;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof(edata)))
return -EFAULT;
pc_debug = edata.data;
return 0;
}
#endif
default:
break;
}
return -EOPNOTSUPP;
}
static int mace_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
default:
return -EOPNOTSUPP;
}
return 0;
}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
mace_start_xmit mace_start_xmit
This routine begins the packet transmit function. When completed, This routine begins the packet transmit function. When completed,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
pcnet_cs.c 1.144 2001/11/07 04:06:56 pcnet_cs.c 1.149 2002/06/29 06:27:37
The network driver code is based on Donald Becker's NE2000 code: The network driver code is based on Donald Becker's NE2000 code:
...@@ -75,7 +75,7 @@ static int pc_debug = PCMCIA_DEBUG; ...@@ -75,7 +75,7 @@ static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i"); MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version = static char *version =
"pcnet_cs.c 1.144 2001/11/07 04:06:56 (David Hinds)"; "pcnet_cs.c 1.149 2002/06/29 06:27:37 (David Hinds)";
#else #else
#define DEBUG(n, args...) #define DEBUG(n, args...)
#endif #endif
...@@ -765,12 +765,13 @@ static void pcnet_config(dev_link_t *link) ...@@ -765,12 +765,13 @@ static void pcnet_config(dev_link_t *link)
strcpy(info->node.dev_name, dev->name); strcpy(info->node.dev_name, dev->name);
link->dev = &info->node; link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
if (info->flags & (IS_DL10019|IS_DL10022)) { if (info->flags & (IS_DL10019|IS_DL10022)) {
u_char id = inb(dev->base_addr + 0x1a); u_char id = inb(dev->base_addr + 0x1a);
dev->do_ioctl = &ei_ioctl; dev->do_ioctl = &ei_ioctl;
mii_phy_probe(dev); mii_phy_probe(dev);
if ((id == 0x30) && !info->pna_phy && (info->eth_phy == 4))
info->eth_phy = 0;
printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ", printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id); dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id);
if (info->pna_phy) if (info->pna_phy)
...@@ -787,12 +788,14 @@ static void pcnet_config(dev_link_t *link) ...@@ -787,12 +788,14 @@ static void pcnet_config(dev_link_t *link)
printk(" hw_addr "); printk(" hw_addr ");
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
link->state &= ~DEV_CONFIG_PENDING;
return; return;
cs_failed: cs_failed:
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
pcnet_release((u_long)link); pcnet_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
return; return;
} /* pcnet_config */ } /* pcnet_config */
...@@ -856,7 +859,7 @@ static int pcnet_event(event_t event, int priority, ...@@ -856,7 +859,7 @@ static int pcnet_event(event_t event, int priority,
} }
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcnet_config(link); pcnet_config(link);
break; break;
case CS_EVENT_PM_SUSPEND: case CS_EVENT_PM_SUSPEND:
...@@ -1052,6 +1055,7 @@ static int pcnet_close(struct net_device *dev) ...@@ -1052,6 +1055,7 @@ static int pcnet_close(struct net_device *dev)
DEBUG(2, "pcnet_close('%s')\n", dev->name); DEBUG(2, "pcnet_close('%s')\n", dev->name);
ei_close(dev);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
link->open--; link->open--;
...@@ -1621,7 +1625,7 @@ static int __init init_pcnet_cs(void) ...@@ -1621,7 +1625,7 @@ static int __init init_pcnet_cs(void)
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "pcnet_cs: Card Services release " printk(KERN_NOTICE "pcnet_cs: Card Services release "
"does not match!\n"); "does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &pcnet_attach, &pcnet_detach); register_pccard_driver(&dev_info, &pcnet_attach, &pcnet_detach);
return 0; return 0;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* A PCMCIA client driver for the Raylink wireless LAN card. * A PCMCIA client driver for the Raylink wireless LAN card.
* The starting point for this module was the skeleton.c in the * The starting point for this module was the skeleton.c in the
* PCMCIA 2.9.12 package written by David Hinds, dhinds@allegro.stanford.edu * PCMCIA 2.9.12 package written by David Hinds, dahinds@users.sourceforge.net
* *
* *
* Copyright (c) 1998 Corey Thomas (corey@world.std.com) * Copyright (c) 1998 Corey Thomas (corey@world.std.com)
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
smc91c92_cs.c 1.2 2002/09/28 15:00:00 smc91c92_cs.c 1.122 2002/10/25 06:26:39
This driver contains code written by Donald Becker This driver contains code written by Donald Becker
(becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au), (becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au),
David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
incorporated some parts of his driver here. I (Dave) wrote most incorporated some parts of his driver here. I (Dave) wrote most
of the PCMCIA glue code, and the Ositech support code. Kelly of the PCMCIA glue code, and the Ositech support code. Kelly
Stephens (kstephen@holli.com) added support for the Motorola Stephens (kstephen@holli.com) added support for the Motorola
Mariner, with help from Allen Brost. Mariner, with help from Allen Brost.
This software may be used and distributed according to the terms of This software may be used and distributed according to the terms of
the GNU General Public License, incorporated herein by reference. the GNU General Public License, incorporated herein by reference.
...@@ -92,7 +92,7 @@ static const char *version = ...@@ -92,7 +92,7 @@ static const char *version =
#endif #endif
#define DRV_NAME "smc91c92_cs" #define DRV_NAME "smc91c92_cs"
#define DRV_VERSION "1.2" #define DRV_VERSION "1.122"
/*====================================================================*/ /*====================================================================*/
...@@ -130,6 +130,8 @@ struct smc_private { ...@@ -130,6 +130,8 @@ struct smc_private {
u_short fast_poll; u_short fast_poll;
u_short link_status; u_short link_status;
struct mii_if_info mii_if; struct mii_if_info mii_if;
int duplex;
int rx_ovrn;
}; };
/* Special definitions for Megahertz multifunction cards */ /* Special definitions for Megahertz multifunction cards */
...@@ -257,7 +259,7 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, ...@@ -257,7 +259,7 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
#define MULTICAST2 2 #define MULTICAST2 2
#define MULTICAST4 4 #define MULTICAST4 4
#define MULTICAST6 6 #define MULTICAST6 6
#define MGMT 8 #define MGMT 8
#define REVISION 0x0a #define REVISION 0x0a
/* Transmit status bits. */ /* Transmit status bits. */
...@@ -287,22 +289,22 @@ static void smc91c92_release(u_long arg); ...@@ -287,22 +289,22 @@ static void smc91c92_release(u_long arg);
static int smc91c92_event(event_t event, int priority, static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
static int smc91c92_open(struct net_device *dev); static int smc_open(struct net_device *dev);
static int smc91c92_close(struct net_device *dev); static int smc_close(struct net_device *dev);
static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void smc_tx_timeout(struct net_device *dev); static void smc_tx_timeout(struct net_device *dev);
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void smc_rx(struct net_device *dev); static void smc_rx(struct net_device *dev);
static struct net_device_stats *smc91c92_get_stats(struct net_device *dev); static struct net_device_stats *smc_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev); static void set_rx_mode(struct net_device *dev);
static int s9k_config(struct net_device *dev, struct ifmap *map); static int s9k_config(struct net_device *dev, struct ifmap *map);
static void smc_set_xcvr(struct net_device *dev, int if_port); static void smc_set_xcvr(struct net_device *dev, int if_port);
static void smc_reset(struct net_device *dev); static void smc_reset(struct net_device *dev);
static void media_check(u_long arg); static void media_check(u_long arg);
static void smc_mdio_sync(ioaddr_t addr); static void mdio_sync(ioaddr_t addr);
static int smc_mdio_read(struct net_device *dev, int phy_id, int loc); static int mdio_read(struct net_device *dev, int phy_id, int loc);
static void smc_mdio_write(struct net_device *dev, int phy_id, int loc, int value); static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int smc_link_ok(struct net_device *dev); static int smc_link_ok(struct net_device *dev);
/*====================================================================== /*======================================================================
...@@ -310,7 +312,7 @@ static int smc_link_ok(struct net_device *dev); ...@@ -310,7 +312,7 @@ static int smc_link_ok(struct net_device *dev);
This bit of code is used to avoid unregistering network devices This bit of code is used to avoid unregistering network devices
at inappropriate times. 2.2 and later kernels are fairly picky at inappropriate times. 2.2 and later kernels are fairly picky
about when this can happen. about when this can happen.
======================================================================*/ ======================================================================*/
static void flush_stale_links(void) static void flush_stale_links(void)
...@@ -349,7 +351,7 @@ static dev_link_t *smc91c92_attach(void) ...@@ -349,7 +351,7 @@ static dev_link_t *smc91c92_attach(void)
DEBUG(0, "smc91c92_attach()\n"); DEBUG(0, "smc91c92_attach()\n");
flush_stale_links(); flush_stale_links();
/* Create new ethernet device */ /* Create new ethernet device */
smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL); smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
if (!smc) return NULL; if (!smc) return NULL;
...@@ -375,25 +377,25 @@ static dev_link_t *smc91c92_attach(void) ...@@ -375,25 +377,25 @@ static dev_link_t *smc91c92_attach(void)
/* The SMC91c92-specific entries in the device structure. */ /* The SMC91c92-specific entries in the device structure. */
dev->hard_start_xmit = &smc_start_xmit; dev->hard_start_xmit = &smc_start_xmit;
dev->get_stats = &smc91c92_get_stats; dev->get_stats = &smc_get_stats;
dev->set_config = &s9k_config; dev->set_config = &s9k_config;
dev->set_multicast_list = &set_rx_mode; dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &smc_ioctl;
ether_setup(dev); ether_setup(dev);
dev->open = &smc91c92_open; dev->open = &smc_open;
dev->stop = &smc91c92_close; dev->stop = &smc_close;
dev->do_ioctl = &smc_ioctl;
#ifdef HAVE_TX_TIMEOUT #ifdef HAVE_TX_TIMEOUT
dev->tx_timeout = smc_tx_timeout; dev->tx_timeout = smc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#endif #endif
dev->priv = link->priv = link->irq.Instance = smc; dev->priv = link->priv = link->irq.Instance = smc;
smc->mii_if.dev = dev; smc->mii_if.dev = dev;
smc->mii_if.mdio_read = smc_mdio_read; smc->mii_if.mdio_read = mdio_read;
smc->mii_if.mdio_write = smc_mdio_write; smc->mii_if.mdio_write = mdio_write;
smc->mii_if.phy_id_mask = 0x1f; smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f; smc->mii_if.reg_num_mask = 0x1f;
/* Register with Card Services */ /* Register with Card Services */
link->next = dev_list; link->next = dev_list;
dev_list = link; dev_list = link;
...@@ -411,7 +413,7 @@ static dev_link_t *smc91c92_attach(void) ...@@ -411,7 +413,7 @@ static dev_link_t *smc91c92_attach(void)
smc91c92_detach(link); smc91c92_detach(link);
return NULL; return NULL;
} }
return link; return link;
} /* smc91c92_attach */ } /* smc91c92_attach */
...@@ -430,13 +432,13 @@ static void smc91c92_detach(dev_link_t *link) ...@@ -430,13 +432,13 @@ static void smc91c92_detach(dev_link_t *link)
dev_link_t **linkp; dev_link_t **linkp;
DEBUG(0, "smc91c92_detach(0x%p)\n", link); DEBUG(0, "smc91c92_detach(0x%p)\n", link);
/* Locate device structure */ /* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break; if (*linkp == link) break;
if (*linkp == NULL) if (*linkp == NULL)
return; return;
del_timer(&link->release); del_timer(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
smc91c92_release((u_long)link); smc91c92_release((u_long)link);
...@@ -445,16 +447,16 @@ static void smc91c92_detach(dev_link_t *link) ...@@ -445,16 +447,16 @@ static void smc91c92_detach(dev_link_t *link)
return; return;
} }
} }
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
/* Unlink device structure, free bits */ /* Unlink device structure, free bits */
*linkp = link->next; *linkp = link->next;
if (link->dev) if (link->dev)
unregister_netdev(&smc->dev); unregister_netdev(&smc->dev);
kfree(smc); kfree(smc);
} /* smc91c92_detach */ } /* smc91c92_detach */
/*====================================================================*/ /*====================================================================*/
...@@ -502,14 +504,14 @@ static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, ...@@ -502,14 +504,14 @@ static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
mhz_mfc_config() handles socket setup for multifunction (1144 mhz_mfc_config() handles socket setup for multifunction (1144
and 3288) cards. mhz_setup() gets a card's hardware ethernet and 3288) cards. mhz_setup() gets a card's hardware ethernet
address. address.
======================================================================*/ ======================================================================*/
static int mhz_3288_power(dev_link_t *link) static int mhz_3288_power(dev_link_t *link)
{ {
struct smc_private *smc = link->priv; struct smc_private *smc = link->priv;
u_char tmp; u_char tmp;
/* Read the ISR twice... */ /* Read the ISR twice... */
readb(smc->base+MEGAHERTZ_ISR); readb(smc->base+MEGAHERTZ_ISR);
udelay(5); udelay(5);
...@@ -517,7 +519,7 @@ static int mhz_3288_power(dev_link_t *link) ...@@ -517,7 +519,7 @@ static int mhz_3288_power(dev_link_t *link)
/* Pause 200ms... */ /* Pause 200ms... */
mdelay(200); mdelay(200);
/* Now read and write the COR... */ /* Now read and write the COR... */
tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR); tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
udelay(5); udelay(5);
...@@ -569,7 +571,7 @@ static int mhz_mfc_config(dev_link_t *link) ...@@ -569,7 +571,7 @@ static int mhz_mfc_config(dev_link_t *link)
if (i != CS_SUCCESS) if (i != CS_SUCCESS)
return i; return i;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
/* Allocate a memory window, for accessing the ISR */ /* Allocate a memory window, for accessing the ISR */
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0; req.Base = req.Size = 0;
...@@ -583,12 +585,12 @@ static int mhz_mfc_config(dev_link_t *link) ...@@ -583,12 +585,12 @@ static int mhz_mfc_config(dev_link_t *link)
if (smc->manfid == MANFID_MOTOROLA) if (smc->manfid == MANFID_MOTOROLA)
mem.CardOffset = link->conf.ConfigBase; mem.CardOffset = link->conf.ConfigBase;
i = CardServices(MapMemPage, link->win, &mem); i = CardServices(MapMemPage, link->win, &mem);
if ((i == CS_SUCCESS) if ((i == CS_SUCCESS)
&& (smc->manfid == MANFID_MEGAHERTZ) && (smc->manfid == MANFID_MEGAHERTZ)
&& (smc->cardid == PRODID_MEGAHERTZ_EM3288)) && (smc->cardid == PRODID_MEGAHERTZ_EM3288))
mhz_3288_power(link); mhz_3288_power(link);
return i; return i;
} }
...@@ -628,7 +630,7 @@ static int mhz_setup(dev_link_t *link) ...@@ -628,7 +630,7 @@ static int mhz_setup(dev_link_t *link)
buf[12] = '\0'; buf[12] = '\0';
if (cvt_ascii_address(dev, buf) == 0) if (cvt_ascii_address(dev, buf) == 0)
return 0; return 0;
return -1; return -1;
} }
...@@ -638,7 +640,7 @@ static int mhz_setup(dev_link_t *link) ...@@ -638,7 +640,7 @@ static int mhz_setup(dev_link_t *link)
mot_config() writes directly to the Mariner configuration mot_config() writes directly to the Mariner configuration
registers because the CIS is just bogus. registers because the CIS is just bogus.
======================================================================*/ ======================================================================*/
static void mot_config(dev_link_t *link) static void mot_config(dev_link_t *link)
...@@ -647,12 +649,12 @@ static void mot_config(dev_link_t *link) ...@@ -647,12 +649,12 @@ static void mot_config(dev_link_t *link)
struct net_device *dev = &smc->dev; struct net_device *dev = &smc->dev;
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
ioaddr_t iouart = link->io.BasePort2; ioaddr_t iouart = link->io.BasePort2;
/* Set UART base address and force map with COR bit 1 */ /* Set UART base address and force map with COR bit 1 */
writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0); writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0);
writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1); writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);
writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR); writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR);
/* Set SMC base address and force map with COR bit 1 */ /* Set SMC base address and force map with COR bit 1 */
writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0); writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0);
writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1); writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);
...@@ -671,7 +673,7 @@ static int mot_setup(dev_link_t *link) ...@@ -671,7 +673,7 @@ static int mot_setup(dev_link_t *link)
u_int addr; u_int addr;
/* Read Ethernet address from Serial EEPROM */ /* Read Ethernet address from Serial EEPROM */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
outw(MOT_EEPROM + i, ioaddr + POINTER); outw(MOT_EEPROM + i, ioaddr + POINTER);
...@@ -691,7 +693,7 @@ static int mot_setup(dev_link_t *link) ...@@ -691,7 +693,7 @@ static int mot_setup(dev_link_t *link)
dev->dev_addr[2*i] = addr & 0xff; dev->dev_addr[2*i] = addr & 0xff;
dev->dev_addr[2*i+1] = (addr >> 8) & 0xff; dev->dev_addr[2*i+1] = (addr >> 8) & 0xff;
} }
return 0; return 0;
} }
...@@ -743,7 +745,7 @@ static int smc_setup(dev_link_t *link) ...@@ -743,7 +745,7 @@ static int smc_setup(dev_link_t *link)
tuple.Attributes = tuple.TupleOffset = 0; tuple.Attributes = tuple.TupleOffset = 0;
tuple.TupleData = buf; tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf); tuple.TupleDataMax = sizeof(buf);
/* Check for a LAN function extension tuple */ /* Check for a LAN function extension tuple */
tuple.DesiredTuple = CISTPL_FUNCE; tuple.DesiredTuple = CISTPL_FUNCE;
i = first_tuple(handle, &tuple, &parse); i = first_tuple(handle, &tuple, &parse);
...@@ -760,7 +762,7 @@ static int smc_setup(dev_link_t *link) ...@@ -760,7 +762,7 @@ static int smc_setup(dev_link_t *link)
return 0; return 0;
} }
} }
/* Try the third string in the Version 1 Version/ID tuple. */ /* Try the third string in the Version 1 Version/ID tuple. */
tuple.DesiredTuple = CISTPL_VERS_1; tuple.DesiredTuple = CISTPL_VERS_1;
if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
...@@ -780,7 +782,7 @@ static int osi_config(dev_link_t *link) ...@@ -780,7 +782,7 @@ static int osi_config(dev_link_t *link)
struct net_device *dev = &smc->dev; struct net_device *dev = &smc->dev;
static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int i, j; int i, j;
link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA; link->conf.Status = CCSR_AUDIO_ENA;
link->irq.Attributes = link->irq.Attributes =
...@@ -789,10 +791,10 @@ static int osi_config(dev_link_t *link) ...@@ -789,10 +791,10 @@ static int osi_config(dev_link_t *link)
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts2 = 8; link->io.NumPorts2 = 8;
link->io.IOAddrLines = 16; link->io.IOAddrLines = 16;
/* Enable Hard Decode, LAN, Modem */ /* Enable Hard Decode, LAN, Modem */
link->conf.ConfigIndex = 0x23; link->conf.ConfigIndex = 0x23;
for (i = j = 0; j < 4; j++) { for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j]; link->io.BasePort2 = com[j];
i = CardServices(RequestIO, link->handle, &link->io); i = CardServices(RequestIO, link->handle, &link->io);
...@@ -816,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) ...@@ -816,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
tuple_t tuple; tuple_t tuple;
u_char buf[255]; u_char buf[255];
int i; int i;
tuple.Attributes = TUPLE_RETURN_COMMON; tuple.Attributes = TUPLE_RETURN_COMMON;
tuple.TupleData = buf; tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf); tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0; tuple.TupleOffset = 0;
/* Read the station address from tuple 0x90, subtuple 0x04 */ /* Read the station address from tuple 0x90, subtuple 0x04 */
tuple.DesiredTuple = 0x90; tuple.DesiredTuple = 0x90;
i = CardServices(GetFirstTuple, handle, &tuple); i = CardServices(GetFirstTuple, handle, &tuple);
...@@ -862,7 +864,7 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) ...@@ -862,7 +864,7 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
This verifies that the chip is some SMC91cXX variant, and returns This verifies that the chip is some SMC91cXX variant, and returns
the revision code if successful. Otherwise, it returns -ENODEV. the revision code if successful. Otherwise, it returns -ENODEV.
======================================================================*/ ======================================================================*/
static int check_sig(dev_link_t *link) static int check_sig(dev_link_t *link)
...@@ -888,7 +890,7 @@ static int check_sig(dev_link_t *link) ...@@ -888,7 +890,7 @@ static int check_sig(dev_link_t *link)
else else
s &= ~CFG_16BIT; s &= ~CFG_16BIT;
outb(s, ioaddr + CONFIG); outb(s, ioaddr + CONFIG);
/* Check Base Address Register to make sure bus width is OK */ /* Check Base Address Register to make sure bus width is OK */
s = inw(ioaddr + BASE_ADDR); s = inw(ioaddr + BASE_ADDR);
if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) && if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) &&
...@@ -936,7 +938,7 @@ static void smc91c92_config(dev_link_t *link) ...@@ -936,7 +938,7 @@ static void smc91c92_config(dev_link_t *link)
ioaddr_t ioaddr; ioaddr_t ioaddr;
DEBUG(0, "smc91c92_config(0x%p)\n", link); DEBUG(0, "smc91c92_config(0x%p)\n", link);
tuple.Attributes = tuple.TupleOffset = 0; tuple.Attributes = tuple.TupleOffset = 0;
tuple.TupleData = (cisdata_t *)buf; tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf); tuple.TupleDataMax = sizeof(buf);
...@@ -946,14 +948,14 @@ static void smc91c92_config(dev_link_t *link) ...@@ -946,14 +948,14 @@ static void smc91c92_config(dev_link_t *link)
CS_EXIT_TEST(i, ParseTuple, config_failed); CS_EXIT_TEST(i, ParseTuple, config_failed);
link->conf.ConfigBase = parse.config.base; link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0]; link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID; tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON; tuple.Attributes = TUPLE_RETURN_COMMON;
if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
smc->manfid = parse.manfid.manf; smc->manfid = parse.manfid.manf;
smc->cardid = parse.manfid.card; smc->cardid = parse.manfid.card;
} }
/* Configure card */ /* Configure card */
link->state |= DEV_CONFIG; link->state |= DEV_CONFIG;
...@@ -969,12 +971,12 @@ static void smc91c92_config(dev_link_t *link) ...@@ -969,12 +971,12 @@ static void smc91c92_config(dev_link_t *link)
i = smc_config(link); i = smc_config(link);
} }
CS_EXIT_TEST(i, RequestIO, config_failed); CS_EXIT_TEST(i, RequestIO, config_failed);
i = CardServices(RequestIRQ, link->handle, &link->irq); i = CardServices(RequestIRQ, link->handle, &link->irq);
CS_EXIT_TEST(i, RequestIRQ, config_failed); CS_EXIT_TEST(i, RequestIRQ, config_failed);
i = CardServices(RequestConfiguration, link->handle, &link->conf); i = CardServices(RequestConfiguration, link->handle, &link->conf);
CS_EXIT_TEST(i, RequestConfiguration, config_failed); CS_EXIT_TEST(i, RequestConfiguration, config_failed);
if (smc->manfid == MANFID_MOTOROLA) if (smc->manfid == MANFID_MOTOROLA)
mot_config(link); mot_config(link);
...@@ -984,7 +986,7 @@ static void smc91c92_config(dev_link_t *link) ...@@ -984,7 +986,7 @@ static void smc91c92_config(dev_link_t *link)
dev->if_port = if_port; dev->if_port = if_port;
else else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n"); printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
if (register_netdev(dev) != 0) { if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
goto config_undo; goto config_undo;
...@@ -1004,16 +1006,16 @@ static void smc91c92_config(dev_link_t *link) ...@@ -1004,16 +1006,16 @@ static void smc91c92_config(dev_link_t *link)
default: /* get the hw address from EEPROM */ default: /* get the hw address from EEPROM */
i = mot_setup(link); break; i = mot_setup(link); break;
} }
if (i != 0) { if (i != 0) {
printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n"); printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
link->state &= ~DEV_CONFIG_PENDING;
goto config_undo; goto config_undo;
} }
strcpy(smc->node.dev_name, dev->name); strcpy(smc->node.dev_name, dev->name);
link->dev = &smc->node; link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING; smc->duplex = 0;
smc->rx_ovrn = 0;
rev = check_sig(link); rev = check_sig(link);
name = "???"; name = "???";
...@@ -1055,12 +1057,12 @@ static void smc91c92_config(dev_link_t *link) ...@@ -1055,12 +1057,12 @@ static void smc91c92_config(dev_link_t *link)
printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ? printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
"MII" : if_names[dev->if_port]); "MII" : if_names[dev->if_port]);
} }
if (smc->cfg & CFG_MII_SELECT) { if (smc->cfg & CFG_MII_SELECT) {
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
j = smc_mdio_read(dev, i, 1); j = mdio_read(dev, i, 1);
if ((j != 0) && (j != 0xffff)) break; if ((j != 0) && (j != 0xffff)) break;
} }
smc->mii_if.phy_id = (i < 32) ? i : -1; smc->mii_if.phy_id = (i < 32) ? i : -1;
...@@ -1073,13 +1075,15 @@ static void smc91c92_config(dev_link_t *link) ...@@ -1073,13 +1075,15 @@ static void smc91c92_config(dev_link_t *link)
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
} }
link->state &= ~DEV_CONFIG_PENDING;
return; return;
config_undo: config_undo:
unregister_netdev(dev); unregister_netdev(dev);
config_failed: /* CS_EXIT_TEST() calls jump to here... */ config_failed: /* CS_EXIT_TEST() calls jump to here... */
smc91c92_release((u_long)link); smc91c92_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* smc91c92_config */ } /* smc91c92_config */
/*====================================================================== /*======================================================================
...@@ -1096,14 +1100,14 @@ static void smc91c92_release(u_long arg) ...@@ -1096,14 +1100,14 @@ static void smc91c92_release(u_long arg)
struct smc_private *smc = link->priv; struct smc_private *smc = link->priv;
DEBUG(0, "smc91c92_release(0x%p)\n", link); DEBUG(0, "smc91c92_release(0x%p)\n", link);
if (link->open) { if (link->open) {
DEBUG(1, "smc91c92_cs: release postponed, '%s' still open\n", DEBUG(1, "smc91c92_cs: release postponed, '%s' still open\n",
link->dev->dev_name); link->dev->dev_name);
link->state |= DEV_STALE_CONFIG; link->state |= DEV_STALE_CONFIG;
return; return;
} }
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
...@@ -1111,7 +1115,7 @@ static void smc91c92_release(u_long arg) ...@@ -1111,7 +1115,7 @@ static void smc91c92_release(u_long arg)
iounmap(smc->base); iounmap(smc->base);
CardServices(ReleaseWindow, link->win); CardServices(ReleaseWindow, link->win);
} }
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} /* smc91c92_release */ } /* smc91c92_release */
...@@ -1131,8 +1135,8 @@ static int smc91c92_event(event_t event, int priority, ...@@ -1131,8 +1135,8 @@ static int smc91c92_event(event_t event, int priority,
dev_link_t *link = args->client_data; dev_link_t *link = args->client_data;
struct smc_private *smc = link->priv; struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev; struct net_device *dev = &smc->dev;
int i; int i;
DEBUG(1, "smc91c92_event(0x%06x)\n", event); DEBUG(1, "smc91c92_event(0x%06x)\n", event);
switch (event) { switch (event) {
...@@ -1144,7 +1148,7 @@ static int smc91c92_event(event_t event, int priority, ...@@ -1144,7 +1148,7 @@ static int smc91c92_event(event_t event, int priority,
} }
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
smc91c92_config(link); smc91c92_config(link);
break; break;
case CS_EVENT_PM_SUSPEND: case CS_EVENT_PM_SUSPEND:
...@@ -1206,7 +1210,7 @@ static int smc91c92_event(event_t event, int priority, ...@@ -1206,7 +1210,7 @@ static int smc91c92_event(event_t event, int priority,
#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT) #define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
#define MDIO_DATA_READ 0x02 #define MDIO_DATA_READ 0x02
static void smc_mdio_sync(ioaddr_t addr) static void mdio_sync(ioaddr_t addr)
{ {
int bits; int bits;
for (bits = 0; bits < 32; bits++) { for (bits = 0; bits < 32; bits++) {
...@@ -1215,13 +1219,13 @@ static void smc_mdio_sync(ioaddr_t addr) ...@@ -1215,13 +1219,13 @@ static void smc_mdio_sync(ioaddr_t addr)
} }
} }
static int smc_mdio_read(struct net_device *dev, int phy_id, int loc) static int mdio_read(struct net_device *dev, int phy_id, int loc)
{ {
ioaddr_t addr = dev->base_addr + MGMT; ioaddr_t addr = dev->base_addr + MGMT;
u_int cmd = (0x06<<10)|(phy_id<<5)|loc; u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
int i, retval = 0; int i, retval = 0;
smc_mdio_sync(addr); mdio_sync(addr);
for (i = 13; i >= 0; i--) { for (i = 13; i >= 0; i--) {
int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
outb(dat, addr); outb(dat, addr);
...@@ -1235,13 +1239,13 @@ static int smc_mdio_read(struct net_device *dev, int phy_id, int loc) ...@@ -1235,13 +1239,13 @@ static int smc_mdio_read(struct net_device *dev, int phy_id, int loc)
return (retval>>1) & 0xffff; return (retval>>1) & 0xffff;
} }
static void smc_mdio_write(struct net_device *dev, int phy_id, int loc, int value) static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
{ {
ioaddr_t addr = dev->base_addr + MGMT; ioaddr_t addr = dev->base_addr + MGMT;
u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
int i; int i;
smc_mdio_sync(addr); mdio_sync(addr);
for (i = 31; i >= 0; i--) { for (i = 31; i >= 0; i--) {
int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
outb(dat, addr); outb(dat, addr);
...@@ -1254,10 +1258,10 @@ static void smc_mdio_write(struct net_device *dev, int phy_id, int loc, int valu ...@@ -1254,10 +1258,10 @@ static void smc_mdio_write(struct net_device *dev, int phy_id, int loc, int valu
} }
/*====================================================================== /*======================================================================
The driver core code, most of which should be common with a The driver core code, most of which should be common with a
non-PCMCIA implementation. non-PCMCIA implementation.
======================================================================*/ ======================================================================*/
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
...@@ -1277,17 +1281,17 @@ static void smc_dump(struct net_device *dev) ...@@ -1277,17 +1281,17 @@ static void smc_dump(struct net_device *dev)
} }
#endif #endif
static int smc91c92_open(struct net_device *dev) static int smc_open(struct net_device *dev)
{ {
struct smc_private *smc = dev->priv; struct smc_private *smc = dev->priv;
dev_link_t *link = &smc->link; dev_link_t *link = &smc->link;
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
DEBUG(0, "%s: smc91c92_open(%p), ID/Window %4.4x.\n", DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
dev->name, dev, inw(dev->base_addr + BANK_SELECT)); dev->name, dev, inw(dev->base_addr + BANK_SELECT));
if (pc_debug > 1) smc_dump(dev); if (pc_debug > 1) smc_dump(dev);
#endif #endif
/* Check that the PCMCIA card is still here. */ /* Check that the PCMCIA card is still here. */
if (!DEV_OK(link)) if (!DEV_OK(link))
return -ENODEV; return -ENODEV;
...@@ -1302,26 +1306,26 @@ static int smc91c92_open(struct net_device *dev) ...@@ -1302,26 +1306,26 @@ static int smc91c92_open(struct net_device *dev)
netif_start_queue(dev); netif_start_queue(dev);
smc->saved_skb = 0; smc->saved_skb = 0;
smc->packets_waiting = 0; smc->packets_waiting = 0;
smc_reset(dev); smc_reset(dev);
init_timer(&smc->media); init_timer(&smc->media);
smc->media.function = &media_check; smc->media.function = &media_check;
smc->media.data = (u_long)smc; smc->media.data = (u_long)smc;
smc->media.expires = jiffies + HZ; smc->media.expires = jiffies + HZ;
add_timer(&smc->media); add_timer(&smc->media);
return 0; return 0;
} /* smc91c92_open */ } /* smc_open */
/*====================================================================*/ /*====================================================================*/
static int smc91c92_close(struct net_device *dev) static int smc_close(struct net_device *dev)
{ {
struct smc_private *smc = dev->priv; struct smc_private *smc = dev->priv;
dev_link_t *link = &smc->link; dev_link_t *link = &smc->link;
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n", DEBUG(0, "%s: smc_close(), status %4.4x.\n",
dev->name, inw(ioaddr + BANK_SELECT)); dev->name, inw(ioaddr + BANK_SELECT));
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -1333,27 +1337,27 @@ static int smc91c92_close(struct net_device *dev) ...@@ -1333,27 +1337,27 @@ static int smc91c92_close(struct net_device *dev)
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
mask_bits(0xff00, ioaddr + RCR); mask_bits(0xff00, ioaddr + RCR);
mask_bits(0xff00, ioaddr + TCR); mask_bits(0xff00, ioaddr + TCR);
/* Put the chip into power-down mode. */ /* Put the chip into power-down mode. */
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
outw(CTL_POWERDOWN, ioaddr + CONTROL ); outw(CTL_POWERDOWN, ioaddr + CONTROL );
link->open--; link->open--;
del_timer(&smc->media); del_timer(&smc->media);
if (link->state & DEV_STALE_CONFIG) if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20); mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0; return 0;
} /* smc91c92_close */ } /* smc_close */
/*====================================================================== /*======================================================================
Transfer a packet to the hardware and trigger the packet send. Transfer a packet to the hardware and trigger the packet send.
This may be called at either from either the Tx queue code This may be called at either from either the Tx queue code
or the interrupt handler. or the interrupt handler.
======================================================================*/ ======================================================================*/
static void smc_hardware_send_packet(struct net_device * dev) static void smc_hardware_send_packet(struct net_device * dev)
...@@ -1362,12 +1366,12 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1362,12 +1366,12 @@ static void smc_hardware_send_packet(struct net_device * dev)
struct sk_buff *skb = smc->saved_skb; struct sk_buff *skb = smc->saved_skb;
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
u_char packet_no; u_char packet_no;
if (!skb) { if (!skb) {
printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name); printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
return; return;
} }
/* There should be a packet slot waiting. */ /* There should be a packet slot waiting. */
packet_no = inw(ioaddr + PNR_ARR) >> 8; packet_no = inw(ioaddr + PNR_ARR) >> 8;
if (packet_no & 0x80) { if (packet_no & 0x80) {
...@@ -1385,7 +1389,7 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1385,7 +1389,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
outw(packet_no, ioaddr + PNR_ARR); outw(packet_no, ioaddr + PNR_ARR);
/* point to the beginning of the packet */ /* point to the beginning of the packet */
outw(PTR_AUTOINC , ioaddr + POINTER); outw(PTR_AUTOINC , ioaddr + POINTER);
/* Send the packet length (+6 for status, length and ctl byte) /* Send the packet length (+6 for status, length and ctl byte)
and the status word (set to zeros). */ and the status word (set to zeros). */
{ {
...@@ -1403,15 +1407,15 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1403,15 +1407,15 @@ static void smc_hardware_send_packet(struct net_device * dev)
/* The odd last byte, if there is one, goes in the control word. */ /* The odd last byte, if there is one, goes in the control word. */
outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1); outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1);
} }
/* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */ /* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */
outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) | outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) |
(inw(ioaddr + INTERRUPT) & 0xff00), (inw(ioaddr + INTERRUPT) & 0xff00),
ioaddr + INTERRUPT); ioaddr + INTERRUPT);
/* The chip does the rest of the work. */ /* The chip does the rest of the work. */
outw(MC_ENQUEUE , ioaddr + MMU_CMD); outw(MC_ENQUEUE , ioaddr + MMU_CMD);
smc->saved_skb = NULL; smc->saved_skb = NULL;
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
dev->trans_start = jiffies; dev->trans_start = jiffies;
...@@ -1445,9 +1449,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1445,9 +1449,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called," DEBUG(2, "%s: smc_start_xmit(length = %d) called,"
" status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2)); " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
if (smc->saved_skb) { if (smc->saved_skb) {
/* THIS SHOULD NEVER HAPPEN. */ /* THIS SHOULD NEVER HAPPEN. */
smc->stats.tx_aborted_errors++; smc->stats.tx_aborted_errors++;
...@@ -1456,9 +1460,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1456,9 +1460,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1; return 1;
} }
smc->saved_skb = skb; smc->saved_skb = skb;
num_pages = skb->len >> 8; num_pages = skb->len >> 8;
if (num_pages > 7) { if (num_pages > 7) {
printk(KERN_ERR "%s: Far too big packet error.\n", dev->name); printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
dev_kfree_skb (skb); dev_kfree_skb (skb);
...@@ -1468,9 +1472,15 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1468,9 +1472,15 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
} }
/* A packet is now waiting. */ /* A packet is now waiting. */
smc->packets_waiting++; smc->packets_waiting++;
SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */ SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */
/* need MC_RESET to keep the memory consistent. errata? */
if (smc->rx_ovrn) {
outw(MC_RESET, ioaddr + MMU_CMD);
smc->rx_ovrn = 0;
}
/* Allocate the memory; send the packet now if we win. */ /* Allocate the memory; send the packet now if we win. */
outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD); outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD);
for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) { for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) {
...@@ -1482,18 +1492,18 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1482,18 +1492,18 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
} }
/* Otherwise defer until the Tx-space-allocated interrupt. */ /* Otherwise defer until the Tx-space-allocated interrupt. */
DEBUG(2, "%s: memory allocation deferred.\n", dev->name); DEBUG(2, "%s: memory allocation deferred.\n", dev->name);
outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT); outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);
return 0; return 0;
} }
/*====================================================================== /*======================================================================
Handle a Tx anomolous event. Entered while in Window 2. Handle a Tx anomolous event. Entered while in Window 2.
======================================================================*/ ======================================================================*/
static void smc_tx_err(struct net_device * dev) static void smc_tx_err(struct net_device * dev)
...@@ -1503,13 +1513,13 @@ static void smc_tx_err(struct net_device * dev) ...@@ -1503,13 +1513,13 @@ static void smc_tx_err(struct net_device * dev)
int saved_packet = inw(ioaddr + PNR_ARR) & 0xff; int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f; int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
int tx_status; int tx_status;
/* select this as the packet to read from */ /* select this as the packet to read from */
outw(packet_no, ioaddr + PNR_ARR); outw(packet_no, ioaddr + PNR_ARR);
/* read the first word from this packet */ /* read the first word from this packet */
outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER); outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER);
tx_status = inw(ioaddr + DATA_1); tx_status = inw(ioaddr + DATA_1);
smc->stats.tx_errors++; smc->stats.tx_errors++;
...@@ -1519,21 +1529,21 @@ static void smc_tx_err(struct net_device * dev) ...@@ -1519,21 +1529,21 @@ static void smc_tx_err(struct net_device * dev)
smc->stats.tx_aborted_errors++; smc->stats.tx_aborted_errors++;
smc->tx_err++; smc->tx_err++;
} }
if (tx_status & TS_SUCCESS) { if (tx_status & TS_SUCCESS) {
printk(KERN_NOTICE "%s: Successful packet caused error " printk(KERN_NOTICE "%s: Successful packet caused error "
"interrupt?\n", dev->name); "interrupt?\n", dev->name);
} }
/* re-enable transmit */ /* re-enable transmit */
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
outw(inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR); outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */ outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */
/* one less packet waiting for me */ /* one less packet waiting for me */
smc->packets_waiting--; smc->packets_waiting--;
outw(saved_packet, ioaddr + PNR_ARR); outw(saved_packet, ioaddr + PNR_ARR);
return; return;
} }
...@@ -1545,7 +1555,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1545,7 +1555,7 @@ static void smc_eph_irq(struct net_device *dev)
struct smc_private *smc = dev->priv; struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
u_short card_stats, ephs; u_short card_stats, ephs;
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
ephs = inw(ioaddr + EPH); ephs = inw(ioaddr + EPH);
DEBUG(2, "%s: Ethernet protocol handler interrupt, status" DEBUG(2, "%s: Ethernet protocol handler interrupt, status"
...@@ -1562,7 +1572,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1562,7 +1572,7 @@ static void smc_eph_irq(struct net_device *dev)
card_stats >>= 4; /* excess deferred */ card_stats >>= 4; /* excess deferred */
#endif #endif
/* If we had a transmit error we must re-enable the transmitter. */ /* If we had a transmit error we must re-enable the transmitter. */
outw(inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR); outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR);
/* Clear a link error interrupt. */ /* Clear a link error interrupt. */
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
...@@ -1573,7 +1583,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1573,7 +1583,7 @@ static void smc_eph_irq(struct net_device *dev)
} }
/*====================================================================*/ /*====================================================================*/
static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct smc_private *smc = dev_id; struct smc_private *smc = dev_id;
...@@ -1585,10 +1595,10 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1585,10 +1595,10 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return; return;
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
irq, ioaddr); irq, ioaddr);
smc->watchdog = 0; smc->watchdog = 0;
saved_bank = inw(ioaddr + BANK_SELECT); saved_bank = inw(ioaddr + BANK_SELECT);
if ((saved_bank & 0xff00) != 0x3300) { if ((saved_bank & 0xff00) != 0x3300) {
...@@ -1598,13 +1608,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1598,13 +1608,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
"/ejected device.\n", dev->name, irq); "/ejected device.\n", dev->name, irq);
goto irq_done; goto irq_done;
} }
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
saved_pointer = inw(ioaddr + POINTER); saved_pointer = inw(ioaddr + POINTER);
mask = inw(ioaddr + INTERRUPT) >> 8; mask = inw(ioaddr + INTERRUPT) >> 8;
/* clear all interrupts */ /* clear all interrupts */
outw(0, ioaddr + INTERRUPT); outw(0, ioaddr + INTERRUPT);
do { /* read the status flag, and mask it */ do { /* read the status flag, and mask it */
status = inw(ioaddr + INTERRUPT) & 0xff; status = inw(ioaddr + INTERRUPT) & 0xff;
DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,
...@@ -1630,18 +1640,20 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1630,18 +1640,20 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & IM_ALLOC_INT) { if (status & IM_ALLOC_INT) {
/* Clear this interrupt so it doesn't happen again */ /* Clear this interrupt so it doesn't happen again */
mask &= ~IM_ALLOC_INT; mask &= ~IM_ALLOC_INT;
smc_hardware_send_packet(dev); smc_hardware_send_packet(dev);
/* enable xmit interrupts based on this */ /* enable xmit interrupts based on this */
mask |= (IM_TX_EMPTY_INT | IM_TX_INT); mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
/* and let the card send more packets to me */ /* and let the card send more packets to me */
netif_wake_queue(dev); netif_wake_queue(dev);
} }
if (status & IM_RX_OVRN_INT) { if (status & IM_RX_OVRN_INT) {
smc->stats.rx_errors++; smc->stats.rx_errors++;
smc->stats.rx_fifo_errors++; smc->stats.rx_fifo_errors++;
if (smc->duplex)
smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */
outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT); outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT);
} }
if (status & IM_EPH_INT) if (status & IM_EPH_INT)
...@@ -1650,7 +1662,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1650,7 +1662,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x" DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x"
" pointer %4.4x.\n", mask, saved_bank, saved_pointer); " pointer %4.4x.\n", mask, saved_bank, saved_pointer);
/* restore state register */ /* restore state register */
outw((mask<<8), ioaddr + INTERRUPT); outw((mask<<8), ioaddr + INTERRUPT);
outw(saved_pointer, ioaddr + POINTER); outw(saved_pointer, ioaddr + POINTER);
...@@ -1659,7 +1671,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1659,7 +1671,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq); DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
irq_done: irq_done:
if ((smc->manfid == MANFID_OSITECH) && if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) { (smc->cardid != PRODID_OSITECH_SEVEN)) {
/* Retrigger interrupt if needed */ /* Retrigger interrupt if needed */
...@@ -1692,15 +1704,15 @@ static void smc_rx(struct net_device *dev) ...@@ -1692,15 +1704,15 @@ static void smc_rx(struct net_device *dev)
int rx_status; int rx_status;
int packet_length; /* Caution: not frame length, rather words int packet_length; /* Caution: not frame length, rather words
to transfer from the chip. */ to transfer from the chip. */
/* Assertion: we are in Window 2. */ /* Assertion: we are in Window 2. */
if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) { if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n", printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
dev->name); dev->name);
return; return;
} }
/* Reset the read pointer, and read the status and packet length. */ /* Reset the read pointer, and read the status and packet length. */
outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER); outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER);
rx_status = inw(ioaddr + DATA_1); rx_status = inw(ioaddr + DATA_1);
...@@ -1708,7 +1720,7 @@ static void smc_rx(struct net_device *dev) ...@@ -1708,7 +1720,7 @@ static void smc_rx(struct net_device *dev)
DEBUG(2, "%s: Receive status %4.4x length %d.\n", DEBUG(2, "%s: Receive status %4.4x length %d.\n",
dev->name, rx_status, packet_length); dev->name, rx_status, packet_length);
if (!(rx_status & RS_ERRORS)) { if (!(rx_status & RS_ERRORS)) {
/* do stuff to make a new packet */ /* do stuff to make a new packet */
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1726,7 +1738,7 @@ static void smc_rx(struct net_device *dev) ...@@ -1726,7 +1738,7 @@ static void smc_rx(struct net_device *dev)
packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6); packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6);
skb_reserve(skb, 2); skb_reserve(skb, 2);
insw(ioaddr+DATA_1, skb_put(skb, packet_length), insw(ioaddr+DATA_1, skb_put(skb, packet_length),
(packet_length+1)>>1); (packet_length+1)>>1);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
skb->dev = dev; skb->dev = dev;
...@@ -1747,31 +1759,30 @@ static void smc_rx(struct net_device *dev) ...@@ -1747,31 +1759,30 @@ static void smc_rx(struct net_device *dev)
} }
/* Let the MMU free the memory of this packet. */ /* Let the MMU free the memory of this packet. */
outw(MC_RELEASE, ioaddr + MMU_CMD); outw(MC_RELEASE, ioaddr + MMU_CMD);
return; return;
} }
/*====================================================================*/ /*====================================================================*/
static struct net_device_stats *smc91c92_get_stats(struct net_device *dev) static struct net_device_stats *smc_get_stats(struct net_device *dev)
{ {
struct smc_private *smc = (struct smc_private *)dev->priv; struct smc_private *smc = (struct smc_private *)dev->priv;
/* Nothing to update - the 91c92 is a pretty primative chip. */ /* Nothing to update - the 91c92 is a pretty primative chip. */
return &smc->stats; return &smc->stats;
} }
/*====================================================================== /*======================================================================
Calculate values for the hardware multicast filter hash table. Calculate values for the hardware multicast filter hash table.
======================================================================*/ ======================================================================*/
static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
u_char *multicast_table) u_char *multicast_table)
{ {
struct dev_mc_list *mc_addr; struct dev_mc_list *mc_addr;
for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) { for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) {
u_int position = ether_crc(6, mc_addr->dmi_addr); u_int position = ether_crc(6, mc_addr->dmi_addr);
#ifndef final_version /* Verify multicast address. */ #ifndef final_version /* Verify multicast address. */
...@@ -1783,14 +1794,14 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, ...@@ -1783,14 +1794,14 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
} }
/*====================================================================== /*======================================================================
Set the receive mode. Set the receive mode.
This routine is used by both the protocol level to notify us of This routine is used by both the protocol level to notify us of
promiscuous/multicast mode changes, and by the open/reset code to promiscuous/multicast mode changes, and by the open/reset code to
initialize the Rx registers. We always set the multicast list and initialize the Rx registers. We always set the multicast list and
leave the receiver running. leave the receiver running.
======================================================================*/ ======================================================================*/
static void set_rx_mode(struct net_device *dev) static void set_rx_mode(struct net_device *dev)
...@@ -1800,7 +1811,7 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1800,7 +1811,7 @@ static void set_rx_mode(struct net_device *dev)
u_int multicast_table[ 2 ] = { 0, }; u_int multicast_table[ 2 ] = { 0, };
unsigned long flags; unsigned long flags;
u_short rx_cfg_setting; u_short rx_cfg_setting;
if (dev->flags & IFF_PROMISC) { if (dev->flags & IFF_PROMISC) {
printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name); printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name);
rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
...@@ -1813,7 +1824,7 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1813,7 +1824,7 @@ static void set_rx_mode(struct net_device *dev)
} }
rx_cfg_setting = RxStripCRC | RxEnable; rx_cfg_setting = RxStripCRC | RxEnable;
} }
/* Load MC table and Rx setting into the chip without interrupts. */ /* Load MC table and Rx setting into the chip without interrupts. */
spin_lock_irqsave(&smc->lock, flags); spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
...@@ -1823,14 +1834,14 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1823,14 +1834,14 @@ static void set_rx_mode(struct net_device *dev)
outw(rx_cfg_setting, ioaddr + RCR); outw(rx_cfg_setting, ioaddr + RCR);
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
spin_unlock_irqrestore(&smc->lock, flags); spin_unlock_irqrestore(&smc->lock, flags);
return; return;
} }
/*====================================================================== /*======================================================================
Senses when a card's config changes. Here, it's coax or TP. Senses when a card's config changes. Here, it's coax or TP.
======================================================================*/ ======================================================================*/
static int s9k_config(struct net_device *dev, struct ifmap *map) static int s9k_config(struct net_device *dev, struct ifmap *map)
...@@ -1890,18 +1901,18 @@ static void smc_reset(struct net_device *dev) ...@@ -1890,18 +1901,18 @@ static void smc_reset(struct net_device *dev)
int i; int i;
DEBUG(0, "%s: smc91c92 reset called.\n", dev->name); DEBUG(0, "%s: smc91c92 reset called.\n", dev->name);
/* The first interaction must be a write to bring the chip out /* The first interaction must be a write to bring the chip out
of sleep mode. */ of sleep mode. */
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
/* Reset the chip. */ /* Reset the chip. */
outw(RCR_SOFTRESET, ioaddr + RCR); outw(RCR_SOFTRESET, ioaddr + RCR);
udelay(10); udelay(10);
/* Clear the transmit and receive configuration registers. */ /* Clear the transmit and receive configuration registers. */
outw(RCR_CLEAR, ioaddr + RCR); outw(RCR_CLEAR, ioaddr + RCR);
outw(TCR_CLEAR, ioaddr + TCR); outw(TCR_CLEAR, ioaddr + TCR);
/* Set the Window 1 control, configuration and station addr registers. /* Set the Window 1 control, configuration and station addr registers.
No point in writing the I/O base register ;-> */ No point in writing the I/O base register ;-> */
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
...@@ -1915,32 +1926,35 @@ static void smc_reset(struct net_device *dev) ...@@ -1915,32 +1926,35 @@ static void smc_reset(struct net_device *dev)
outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) | outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) |
(inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00), (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00),
ioaddr - 0x10 + OSITECH_AUI_PWR); ioaddr - 0x10 + OSITECH_AUI_PWR);
/* Fill in the physical address. The databook is wrong about the order! */ /* Fill in the physical address. The databook is wrong about the order! */
for (i = 0; i < 6; i += 2) for (i = 0; i < 6; i += 2)
outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i], outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i],
ioaddr + ADDR0 + i); ioaddr + ADDR0 + i);
/* Reset the MMU */ /* Reset the MMU */
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
outw(MC_RESET, ioaddr + MMU_CMD); outw(MC_RESET, ioaddr + MMU_CMD);
outw(0, ioaddr + INTERRUPT); outw(0, ioaddr + INTERRUPT);
/* Re-enable the chip. */ /* Re-enable the chip. */
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) | outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) |
TCR_ENABLE | TCR_PAD_EN, ioaddr + TCR); TCR_ENABLE | TCR_PAD_EN | smc->duplex, ioaddr + TCR);
set_rx_mode(dev); set_rx_mode(dev);
if (smc->cfg & CFG_MII_SELECT) { if (smc->cfg & CFG_MII_SELECT) {
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
/* Reset MII */ /* Reset MII */
smc_mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000); mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000);
/* Advertise 100F, 100H, 10F, 10H */
mdio_write(dev, smc->mii_if.phy_id, 4, 0x01e1);
/* Restart MII autonegotiation */ /* Restart MII autonegotiation */
smc_mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000); mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000);
smc_mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200); mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200);
} }
/* Enable interrupts. */ /* Enable interrupts. */
...@@ -1952,7 +1966,7 @@ static void smc_reset(struct net_device *dev) ...@@ -1952,7 +1966,7 @@ static void smc_reset(struct net_device *dev)
/*====================================================================== /*======================================================================
Media selection timer routine Media selection timer routine
======================================================================*/ ======================================================================*/
static void media_check(u_long arg) static void media_check(u_long arg)
...@@ -1969,12 +1983,18 @@ static void media_check(u_long arg) ...@@ -1969,12 +1983,18 @@ static void media_check(u_long arg)
goto reschedule; goto reschedule;
SMC_SELECT_BANK(2); SMC_SELECT_BANK(2);
/* need MC_RESET to keep the memory consistent. errata? */
if (smc->rx_ovrn) {
outw(MC_RESET, ioaddr + MMU_CMD);
smc->rx_ovrn = 0;
}
i = inw(ioaddr + INTERRUPT); i = inw(ioaddr + INTERRUPT);
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
media = inw(ioaddr + EPH) & EPH_LINK_OK; media = inw(ioaddr + EPH) & EPH_LINK_OK;
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
/* Check for pending interrupt with watchdog flag set: with /* Check for pending interrupt with watchdog flag set: with
this, we can limp along even if the interrupt is blocked */ this, we can limp along even if the interrupt is blocked */
if (smc->watchdog++ && ((i>>8) & i)) { if (smc->watchdog++ && ((i>>8) & i)) {
...@@ -1996,7 +2016,7 @@ static void media_check(u_long arg) ...@@ -1996,7 +2016,7 @@ static void media_check(u_long arg)
goto reschedule; goto reschedule;
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
link = smc_mdio_read(dev, smc->mii_if.phy_id, 1); link = mdio_read(dev, smc->mii_if.phy_id, 1);
if (!link || (link == 0xffff)) { if (!link || (link == 0xffff)) {
printk(KERN_INFO "%s: MII is missing!\n", dev->name); printk(KERN_INFO "%s: MII is missing!\n", dev->name);
smc->mii_if.phy_id = -1; smc->mii_if.phy_id = -1;
...@@ -2005,21 +2025,23 @@ static void media_check(u_long arg) ...@@ -2005,21 +2025,23 @@ static void media_check(u_long arg)
link &= 0x0004; link &= 0x0004;
if (link != smc->link_status) { if (link != smc->link_status) {
u_short p = smc_mdio_read(dev, smc->mii_if.phy_id, 5); u_short p = mdio_read(dev, smc->mii_if.phy_id, 5);
printk(KERN_INFO "%s: %s link beat\n", dev->name, printk(KERN_INFO "%s: %s link beat\n", dev->name,
(link) ? "found" : "lost"); (link) ? "found" : "lost");
smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
? TCR_FDUPLX : 0);
if (link) { if (link) {
printk(KERN_INFO "%s: autonegotiation complete: " printk(KERN_INFO "%s: autonegotiation complete: "
"%sbaseT-%cD selected\n", dev->name, "%sbaseT-%cD selected\n", dev->name,
((p & 0x0180) ? "100" : "10"), ((p & 0x0180) ? "100" : "10"),
(((p & 0x0100) || ((p & 0x1c0) == 0x40)) ? 'F' : 'H')); (smc->duplex ? 'F' : 'H'));
} }
SMC_SELECT_BANK(0);
outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR);
smc->link_status = link; smc->link_status = link;
} }
}
if (smc->cfg & CFG_MII_SELECT)
goto reschedule; goto reschedule;
}
/* Ignore collisions unless we've had no rx's recently */ /* Ignore collisions unless we've had no rx's recently */
if (jiffies - dev->last_rx > HZ) { if (jiffies - dev->last_rx > HZ) {
...@@ -2054,7 +2076,7 @@ static void media_check(u_long arg) ...@@ -2054,7 +2076,7 @@ static void media_check(u_long arg)
} }
smc->media_status = media; smc->media_status = media;
} }
reschedule: reschedule:
smc->media.expires = jiffies + HZ; smc->media.expires = jiffies + HZ;
add_timer(&smc->media); add_timer(&smc->media);
...@@ -2168,7 +2190,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2168,7 +2190,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EFAULT; return -EFAULT;
spin_lock_irq(&smc->lock); spin_lock_irq(&smc->lock);
if (smc->cfg & CFG_MII_SELECT) if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_sset(&smc->mii_if, &ecmd); ret = mii_ethtool_sset(&smc->mii_if, &ecmd);
else else
ret = smc_netdev_set_ecmd(dev, &ecmd); ret = smc_netdev_set_ecmd(dev, &ecmd);
spin_unlock_irq(&smc->lock); spin_unlock_irq(&smc->lock);
...@@ -2195,7 +2217,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2195,7 +2217,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
/* set message-level */ /* set message-level */
case ETHTOOL_SMSGLVL: { case ETHTOOL_SMSGLVL: {
struct ethtool_value edata; struct ethtool_value edata;
...@@ -2212,7 +2234,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2212,7 +2234,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
else else
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
default: default:
break; break;
} }
...@@ -2234,7 +2256,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2234,7 +2256,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCETHTOOL: case SIOCETHTOOL:
rc = smc_ethtool_ioctl(dev, (void *) rq->ifr_data); rc = smc_ethtool_ioctl(dev, (void *) rq->ifr_data);
break; break;
default: default:
spin_lock_irq(&smc->lock); spin_lock_irq(&smc->lock);
rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
...@@ -2256,7 +2278,7 @@ static int __init init_smc91c92_cs(void) ...@@ -2256,7 +2278,7 @@ static int __init init_smc91c92_cs(void)
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_ERR printk(KERN_ERR
"smc91c92_cs: Card Services release does not match!\n"); "smc91c92_cs: Card Services release does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &smc91c92_attach, &smc91c92_detach); register_pccard_driver(&dev_info, &smc91c92_attach, &smc91c92_detach);
return 0; return 0;
...@@ -2272,4 +2294,3 @@ static void __exit exit_smc91c92_cs(void) ...@@ -2272,4 +2294,3 @@ static void __exit exit_smc91c92_cs(void)
module_init(init_smc91c92_cs); module_init(init_smc91c92_cs);
module_exit(exit_smc91c92_cs); module_exit(exit_smc91c92_cs);
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
In addition this module was derived from dummy_cs. In addition this module was derived from dummy_cs.
The initial developer of dummy_cs is David A. Hinds The initial developer of dummy_cs is David A. Hinds
<dhinds@hyper.stanford.edu>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
======================================================================*/ ======================================================================*/
......
...@@ -143,7 +143,7 @@ ...@@ -143,7 +143,7 @@
* Yunzhou Li <yunzhou@strat.iol.unh.edu> finished this work. * Yunzhou Li <yunzhou@strat.iol.unh.edu> finished this work.
* Joe Finney <joe@comp.lancs.ac.uk> patched the driver to start * Joe Finney <joe@comp.lancs.ac.uk> patched the driver to start
* 2.00 cards correctly (2.4 GHz with frequency selection). * 2.00 cards correctly (2.4 GHz with frequency selection).
* David Hinds <dhinds@hyper.stanford.edu> integrated the whole in his * David Hinds <dahinds@users.sourceforge.net> integrated the whole in his
* PCMCIA package (and bug corrections). * PCMCIA package (and bug corrections).
* *
* I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
(specifically, for the Quatech SPP-100 EPP card: other cards will (specifically, for the Quatech SPP-100 EPP card: other cards will
probably require driver tweaks) probably require driver tweaks)
parport_cs.c 1.20 2000/11/02 23:15:05 parport_cs.c 1.29 2002/10/11 06:57:41
The contents of this file are subject to the Mozilla Public The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file License Version 1.1 (the "License"); you may not use this file
...@@ -34,9 +34,7 @@ ...@@ -34,9 +34,7 @@
======================================================================*/ ======================================================================*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -45,7 +43,6 @@ ...@@ -45,7 +43,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/major.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/parport_pc.h> #include <linux/parport_pc.h>
...@@ -58,32 +55,31 @@ ...@@ -58,32 +55,31 @@
#include <pcmcia/cisreg.h> #include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h> #include <pcmcia/ciscode.h>
#ifdef PCMCIA_DEBUG /*====================================================================*/
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"parport_cs.c 1.20 2000/11/02 23:15:05 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
#ifndef VERSION /* Module parameters */
#define VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#endif
/*====================================================================*/ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA parallel port card driver");
MODULE_LICENSE("Dual MPL/GPL");
/* Parameters that can be set with 'insmod' */ #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */ /* Bit map of interrupts to choose from */
static u_int irq_mask = 0xdeb8; INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 }; static int irq_list[4] = { -1 };
static int epp_mode = 1;
MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(irq_list, "1-4i");
MODULE_PARM(epp_mode, "i");
INT_MODULE_PARM(epp_mode, 1);
#ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"parport_cs.c 1.29 2002/10/11 06:57:41 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/ /*====================================================================*/
...@@ -106,8 +102,6 @@ static int parport_event(event_t event, int priority, ...@@ -106,8 +102,6 @@ static int parport_event(event_t event, int priority,
static dev_info_t dev_info = "parport_cs"; static dev_info_t dev_info = "parport_cs";
static dev_link_t *dev_list = NULL; static dev_link_t *dev_list = NULL;
extern struct parport_operations parport_pc_ops;
/*====================================================================*/ /*====================================================================*/
static void cs_error(client_handle_t handle, int func, int ret) static void cs_error(client_handle_t handle, int func, int ret)
...@@ -228,12 +222,6 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed ...@@ -228,12 +222,6 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
#define CFG_CHECK(fn, args...) \ #define CFG_CHECK(fn, args...) \
if (CardServices(fn, args) != 0) goto next_entry if (CardServices(fn, args) != 0) goto next_entry
static struct { u_int flag; char *name; } mode[] = {
{ PARPORT_MODE_TRISTATE, "PS2" },
{ PARPORT_MODE_EPP, "EPP" },
{ PARPORT_MODE_ECP, "ECP" },
};
void parport_config(dev_link_t *link) void parport_config(dev_link_t *link)
{ {
client_handle_t handle = link->handle; client_handle_t handle = link->handle;
...@@ -245,7 +233,7 @@ void parport_config(dev_link_t *link) ...@@ -245,7 +233,7 @@ void parport_config(dev_link_t *link)
cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t dflt = { 0 };
struct parport *p; struct parport *p;
int i, last_ret, last_fn; int last_ret, last_fn;
DEBUG(0, "parport_config(0x%p)\n", link); DEBUG(0, "parport_config(0x%p)\n", link);
...@@ -297,6 +285,9 @@ void parport_config(dev_link_t *link) ...@@ -297,6 +285,9 @@ void parport_config(dev_link_t *link)
CS_CHECK(RequestIRQ, handle, &link->irq); CS_CHECK(RequestIRQ, handle, &link->irq);
CS_CHECK(RequestConfiguration, handle, &link->conf); CS_CHECK(RequestConfiguration, handle, &link->conf);
release_region(link->io.BasePort1, link->io.NumPorts1);
if (link->io.NumPorts2)
release_region(link->io.BasePort2, link->io.NumPorts2);
p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
link->irq.AssignedIRQ, PARPORT_DMA_NONE, link->irq.AssignedIRQ, PARPORT_DMA_NONE,
NULL); NULL);
...@@ -307,19 +298,6 @@ void parport_config(dev_link_t *link) ...@@ -307,19 +298,6 @@ void parport_config(dev_link_t *link)
goto failed; goto failed;
} }
#if (LINUX_VERSION_CODE < VERSION(2,3,6))
#if (LINUX_VERSION_CODE >= VERSION(2,2,8))
p->private_data = kmalloc(sizeof(struct parport_pc_private),
GFP_KERNEL);
((struct parport_pc_private *)(p->private_data))->ctr = 0x0c;
#endif
parport_proc_register(p);
p->flags |= PARPORT_FLAG_COMA;
parport_pc_write_econtrol(p, 0x00);
parport_pc_write_control(p, 0x0c);
parport_pc_write_data(p, 0x00);
#endif
p->modes |= PARPORT_MODE_PCSPP; p->modes |= PARPORT_MODE_PCSPP;
if (epp_mode) if (epp_mode)
p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP; p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
...@@ -329,15 +307,7 @@ void parport_config(dev_link_t *link) ...@@ -329,15 +307,7 @@ void parport_config(dev_link_t *link)
info->port = p; info->port = p;
strcpy(info->node.dev_name, p->name); strcpy(info->node.dev_name, p->name);
link->dev = &info->node; link->dev = &info->node;
printk(KERN_INFO "%s: PC-style PCMCIA at %#x", p->name,
link->io.BasePort1);
if (link->io.NumPorts2)
printk(" & %#x", link->io.BasePort2);
printk(", irq %u [SPP", link->irq.AssignedIRQ);
for (i = 0; i < 5; i++)
if (p->modes & mode[i].flag) printk(",%s", mode[i].name);
printk("]\n");
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
return; return;
...@@ -345,6 +315,7 @@ void parport_config(dev_link_t *link) ...@@ -345,6 +315,7 @@ void parport_config(dev_link_t *link)
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
failed: failed:
parport_cs_release((u_long)link); parport_cs_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* parport_config */ } /* parport_config */
...@@ -365,15 +336,12 @@ void parport_cs_release(u_long arg) ...@@ -365,15 +336,12 @@ void parport_cs_release(u_long arg)
if (info->ndev) { if (info->ndev) {
struct parport *p = info->port; struct parport *p = info->port;
#if (LINUX_VERSION_CODE < VERSION(2,3,6)) parport_pc_unregister_port(p);
if (!(p->flags & PARPORT_FLAG_COMA)) request_region(link->io.BasePort1, link->io.NumPorts1,
parport_quiesce(p); info->node.dev_name);
#endif if (link->io.NumPorts2)
parport_proc_unregister(p); request_region(link->io.BasePort2, link->io.NumPorts2,
#if (LINUX_VERSION_CODE >= VERSION(2,2,8)) info->node.dev_name);
kfree(p->private_data);
#endif
parport_unregister_port(p);
} }
info->ndev = 0; info->ndev = 0;
link->dev = NULL; link->dev = NULL;
...@@ -430,24 +398,6 @@ int parport_event(event_t event, int priority, ...@@ -430,24 +398,6 @@ int parport_event(event_t event, int priority,
/*====================================================================*/ /*====================================================================*/
#if (LINUX_VERSION_CODE < VERSION(2,3,6))
static void inc_use_count(void)
{
MOD_INC_USE_COUNT;
parport_pc_ops.inc_use_count();
}
static void dec_use_count(void)
{
MOD_DEC_USE_COUNT;
parport_pc_ops.dec_use_count();
}
#endif
/*====================================================================*/
static int __init init_parport_cs(void) static int __init init_parport_cs(void)
{ {
servinfo_t serv; servinfo_t serv;
...@@ -456,9 +406,8 @@ static int __init init_parport_cs(void) ...@@ -456,9 +406,8 @@ static int __init init_parport_cs(void)
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "parport_cs: Card Services release " printk(KERN_NOTICE "parport_cs: Card Services release "
"does not match!\n"); "does not match!\n");
return -1; return -EINVAL;
} }
register_pccard_driver(&dev_info, &parport_attach, &parport_detach); register_pccard_driver(&dev_info, &parport_attach, &parport_detach);
return 0; return 0;
} }
...@@ -473,4 +422,3 @@ static void __exit exit_parport_cs(void) ...@@ -473,4 +422,3 @@ static void __exit exit_parport_cs(void)
module_init(init_parport_cs); module_init(init_parport_cs);
module_exit(exit_parport_cs); module_exit(exit_parport_cs);
MODULE_LICENSE("Dual MPL/GPL");
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Cardbus device configuration Cardbus device configuration
cardbus.c 1.63 1999/11/08 20:47:02 cardbus.c 1.87 2002/10/24 06:11:41
The contents of this file are subject to the Mozilla Public The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file License Version 1.1 (the "License"); you may not use this file
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
rights and limitations under the License. rights and limitations under the License.
The initial developer of the original code is David A. Hinds The initial developer of the original code is David A. Hinds
<dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the Alternatively, the contents of this file may be used under the
...@@ -175,8 +175,8 @@ static int cb_setup_cis_mem(socket_info_t * s, struct pci_dev *dev, struct resou ...@@ -175,8 +175,8 @@ static int cb_setup_cis_mem(socket_info_t * s, struct pci_dev *dev, struct resou
=====================================================================*/ =====================================================================*/
void read_cb_mem(socket_info_t * s, u_char fn, int space, int read_cb_mem(socket_info_t * s, u_char fn, int space,
u_int addr, u_int len, void *ptr) u_int addr, u_int len, void *ptr)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct resource *res; struct resource *res;
...@@ -194,7 +194,7 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space, ...@@ -194,7 +194,7 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space,
goto fail; goto fail;
for (; len; addr++, ptr++, len--) for (; len; addr++, ptr++, len--)
pci_readb(dev, addr, (u_char *) ptr); pci_readb(dev, addr, (u_char *) ptr);
return; return 0;
} }
res = dev->resource + space - 1; res = dev->resource + space - 1;
...@@ -214,11 +214,11 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space, ...@@ -214,11 +214,11 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space,
goto fail; goto fail;
memcpy_fromio(ptr, s->cb_cis_virt + addr, len); memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
return; return 0;
fail: fail:
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
return; return -1;
} }
/*===================================================================== /*=====================================================================
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
PCMCIA Card Information Structure parser PCMCIA Card Information Structure parser
cistpl.c 1.97 2001/10/04 03:33:49 cistpl.c 1.99 2002/10/24 06:11:48
The contents of this file are subject to the Mozilla Public The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file License Version 1.1 (the "License"); you may not use this file
...@@ -109,8 +109,8 @@ static void set_cis_map(socket_info_t *s, pccard_mem_map *mem) ...@@ -109,8 +109,8 @@ static void set_cis_map(socket_info_t *s, pccard_mem_map *mem)
} }
} }
void read_cis_mem(socket_info_t *s, int attr, u_int addr, int read_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr) u_int len, void *ptr)
{ {
pccard_mem_map *mem = &s->cis_mem; pccard_mem_map *mem = &s->cis_mem;
u_char *sys, *buf = ptr; u_char *sys, *buf = ptr;
...@@ -118,7 +118,7 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, ...@@ -118,7 +118,7 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr,
DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len); DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) { if (setup_cis_mem(s) != 0) {
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
return; return -1;
} }
mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
...@@ -156,6 +156,7 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, ...@@ -156,6 +156,7 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr,
DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n", DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
*(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+0), *(u_char *)(ptr+1),
*(u_char *)(ptr+2), *(u_char *)(ptr+3)); *(u_char *)(ptr+2), *(u_char *)(ptr+3));
return 0;
} }
void write_cis_mem(socket_info_t *s, int attr, u_int addr, void write_cis_mem(socket_info_t *s, int attr, u_int addr,
...@@ -270,7 +271,7 @@ static int setup_cis_mem(socket_info_t *s) ...@@ -270,7 +271,7 @@ static int setup_cis_mem(socket_info_t *s)
if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size, if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
s->cap.map_size, low, "card services", s)) { s->cap.map_size, low, "card services", s)) {
printk(KERN_NOTICE "cs: unable to map card memory!\n"); printk(KERN_NOTICE "cs: unable to map card memory!\n");
return CS_OUT_OF_RESOURCE; return -1;
} }
s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1; s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1;
s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start, s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start,
...@@ -303,7 +304,7 @@ void release_cis_mem(socket_info_t *s) ...@@ -303,7 +304,7 @@ void release_cis_mem(socket_info_t *s)
static void read_cis_cache(socket_info_t *s, int attr, u_int addr, static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr) u_int len, void *ptr)
{ {
int i; int i, ret;
char *caddr; char *caddr;
if (s->fake_cis) { if (s->fake_cis) {
...@@ -326,12 +327,12 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr, ...@@ -326,12 +327,12 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
} }
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) if (s->state & SOCKET_CARDBUS)
read_cb_mem(s, 0, attr, addr, len, ptr); ret = read_cb_mem(s, 0, attr, addr, len, ptr);
else else
#endif #endif
read_cis_mem(s, attr, addr, len, ptr); ret = read_cis_mem(s, attr, addr, len, ptr);
/* Copy data into the cache, if there is room */ /* Copy data into the cache, if there is room */
if ((i < MAX_CIS_TABLE) && if ((ret == 0) && (i < MAX_CIS_TABLE) &&
(caddr+len < s->cis_cache+MAX_CIS_DATA)) { (caddr+len < s->cis_cache+MAX_CIS_DATA)) {
s->cis_table[i].addr = addr; s->cis_table[i].addr = addr;
s->cis_table[i].len = len; s->cis_table[i].len = len;
......
/* /*
* cs_internal.h 1.54 2000/10/26 20:10:55 * cs_internal.h 1.57 2002/10/24 06:11:43
* *
* The contents of this file are subject to the Mozilla Public License * The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in * Version 1.1 (the "License"); you may not use this file except in
...@@ -202,13 +202,13 @@ int cb_config(socket_info_t *s); ...@@ -202,13 +202,13 @@ int cb_config(socket_info_t *s);
void cb_release(socket_info_t *s); void cb_release(socket_info_t *s);
void cb_enable(socket_info_t *s); void cb_enable(socket_info_t *s);
void cb_disable(socket_info_t *s); void cb_disable(socket_info_t *s);
void read_cb_mem(socket_info_t *s, u_char fn, int space, int read_cb_mem(socket_info_t *s, u_char fn, int space,
u_int addr, u_int len, void *ptr); u_int addr, u_int len, void *ptr);
void cb_release_cis_mem(socket_info_t *s); void cb_release_cis_mem(socket_info_t *s);
/* In cistpl.c */ /* In cistpl.c */
void read_cis_mem(socket_info_t *s, int attr, int read_cis_mem(socket_info_t *s, int attr,
u_int addr, u_int len, void *ptr); u_int addr, u_int len, void *ptr);
void write_cis_mem(socket_info_t *s, int attr, void write_cis_mem(socket_info_t *s, int attr,
u_int addr, u_int len, void *ptr); u_int addr, u_int len, void *ptr);
void release_cis_mem(socket_info_t *s); void release_cis_mem(socket_info_t *s);
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
rights and limitations under the License. rights and limitations under the License.
The initial developer of the original code is David A. Hinds The initial developer of the original code is David A. Hinds
<dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
rights and limitations under the License. rights and limitations under the License.
The initial developer of the original code is David A. Hinds The initial developer of the original code is David A. Hinds
<dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved. are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the Alternatively, the contents of this file may be used under the
...@@ -67,7 +67,7 @@ static const char *version = ...@@ -67,7 +67,7 @@ static const char *version =
#define DEBUG(n, args...) #define DEBUG(n, args...)
#endif #endif
MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>"); MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver"); MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
MODULE_LICENSE("Dual MPL/GPL"); MODULE_LICENSE("Dual MPL/GPL");
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@hyper.stanford.edu>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
* *
* The initial developer of the original code is David A. Hinds * The initial developer of the original code is David A. Hinds
* <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de) * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de)
* PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk> * PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
* Minor reorganizations by David Hinds <dhinds@zen.stanford.edu> * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
......
/* /*
* ciscode.h 1.45 2000/08/12 02:08:23 * ciscode.h 1.56 2002/10/25 06:37:30
* *
* The contents of this file are subject to the Mozilla Public License * The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in * Version 1.1 (the "License"); you may not use this file except in
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
* *
* Alternatively, the contents of this file may be used under the * Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in which * terms of the GNU General Public License version 2 (the "GPL"), in
* case the provisions of the GPL are applicable instead of the * which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file * above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use * only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by * your version of this file under the MPL, indicate your decision by
...@@ -60,6 +60,10 @@ ...@@ -60,6 +60,10 @@
#define PRODID_INTEL_DUAL_RS232 0x0301 #define PRODID_INTEL_DUAL_RS232 0x0301
#define PRODID_INTEL_2PLUS 0x8422 #define PRODID_INTEL_2PLUS 0x8422
#define MANFID_KME 0x0032
#define PRODID_KME_KXLC005_A 0x0704
#define PRODID_KME_KXLC005_B 0x2904
#define MANFID_LINKSYS 0x0143 #define MANFID_LINKSYS 0x0143
#define PRODID_LINKSYS_PCMLM28 0xc0ab #define PRODID_LINKSYS_PCMLM28 0xc0ab
#define PRODID_LINKSYS_3400 0x3341 #define PRODID_LINKSYS_3400 0x3341
...@@ -94,6 +98,8 @@ ...@@ -94,6 +98,8 @@
#define PRODID_OSITECH_JACK_336 0x0007 #define PRODID_OSITECH_JACK_336 0x0007
#define PRODID_OSITECH_SEVEN 0x0008 #define PRODID_OSITECH_SEVEN 0x0008
#define MANFID_OXSEMI 0x0279
#define MANFID_PIONEER 0x000b #define MANFID_PIONEER 0x000b
#define MANFID_PSION 0x016c #define MANFID_PSION 0x016c
...@@ -103,7 +109,10 @@ ...@@ -103,7 +109,10 @@
#define PRODID_QUATECH_SPP100 0x0003 #define PRODID_QUATECH_SPP100 0x0003
#define PRODID_QUATECH_DUAL_RS232 0x0012 #define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007 #define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_DUAL_RS232_D2 0x0052
#define PRODID_QUATECH_QUAD_RS232 0x001b #define PRODID_QUATECH_QUAD_RS232 0x001b
#define PRODID_QUATECH_DUAL_RS422 0x000e
#define PRODID_QUATECH_QUAD_RS422 0x0045
#define MANFID_SMC 0x0108 #define MANFID_SMC 0x0108
#define PRODID_SMC_ETHER 0x0105 #define PRODID_SMC_ETHER 0x0105
...@@ -118,9 +127,12 @@ ...@@ -118,9 +127,12 @@
#define MANFID_TDK 0x0105 #define MANFID_TDK 0x0105
#define PRODID_TDK_CF010 0x0900 #define PRODID_TDK_CF010 0x0900
#define PRODID_TDK_GN3410 0x4815
#define MANFID_TOSHIBA 0x0098 #define MANFID_TOSHIBA 0x0098
#define MANFID_UNGERMANN 0x02c0
#define MANFID_XIRCOM 0x0105 #define MANFID_XIRCOM 0x0105
#endif /* _LINUX_CISCODE_H */ #endif /* _LINUX_CISCODE_H */
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Additional Authors: * Additional Authors:
* Florian la Roche <rzsfl@rz.uni-sb.de> * Florian la Roche <rzsfl@rz.uni-sb.de>
* Alan Cox <gw4pts@gw4pts.ampr.org> * Alan Cox <gw4pts@gw4pts.ampr.org>
* David Hinds <dhinds@allegro.stanford.edu> * David Hinds <dahinds@users.sourceforge.net>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
* Adam Sulmicki <adam@cfar.umd.edu> * Adam Sulmicki <adam@cfar.umd.edu>
* Pekka Riikonen <priikone@poesidon.pspt.fi> * Pekka Riikonen <priikone@poesidon.pspt.fi>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment