Commit 87ebb81d authored by David Hinds's avatar David Hinds Committed by Linus Torvalds

[PATCH] PATCH: more PCMCIA fixes for 2.5

include/pcmcia/ciscode.h
o added product ID's for a few more cards

drivers/net/pcmcia/fmvj18x_cs.c
o Added MODULE_DESCRIPTION
o Added support for RATOC cards
o Added support for Nextcom NC5310B cards
o Added support for SSi 78Q8370 chipset
o Added support for TDK GN3410 multifunction cards
o Better errno for failed module initialization
o Cleaned up whitespace

drivers/net/pcmcia/smc91c92_cs.c
o Added full duplex support for smc91c100 based cards
o Better errno for failed module initialization
o Synced up naming of stuff to match pcmcia-cs version
o Cleaned up whitespace

drivers/pcmcia/cardbus.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs_internal.c
o Fixed card identification bug triggered by invoking certain PCMCIA
  tools when cardmgr is not running.
parent 4546ef0b
...@@ -1322,7 +1322,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1322,7 +1322,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
/** /**
* ax_interrupt - handle the interrupts from an 8390 * ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number * @irq: interrupt number
...@@ -1853,7 +1853,7 @@ static int axdev_init(struct net_device *dev) ...@@ -1853,7 +1853,7 @@ static int axdev_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". */
......
/*====================================================================== /*======================================================================
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) {
...@@ -592,7 +633,6 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -592,7 +633,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 */
...@@ -602,6 +642,7 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -602,6 +642,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:
...@@ -609,6 +650,7 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -609,6 +650,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 */
/*====================================================================*/ /*====================================================================*/
...@@ -667,6 +709,51 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) ...@@ -667,6 +709,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;
...@@ -753,7 +840,7 @@ static int __init init_fmvj18x_cs(void) ...@@ -753,7 +840,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;
...@@ -943,10 +1030,10 @@ static void fjn_reset(struct net_device *dev) ...@@ -943,10 +1030,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);
...@@ -958,20 +1045,20 @@ static void fjn_reset(struct net_device *dev) ...@@ -958,20 +1045,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)
...@@ -1000,16 +1087,16 @@ static void fjn_reset(struct net_device *dev) ...@@ -1000,16 +1087,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 */
/*====================================================================*/ /*====================================================================*/
...@@ -1064,7 +1151,7 @@ static void fjn_rx(struct net_device *dev) ...@@ -1064,7 +1151,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
...@@ -1091,7 +1178,7 @@ static void fjn_rx(struct net_device *dev) ...@@ -1091,7 +1178,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)
...@@ -1224,7 +1311,7 @@ static int fjn_close(struct net_device *dev) ...@@ -1224,7 +1311,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--;
...@@ -1253,8 +1340,8 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1253,8 +1340,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) {
...@@ -1294,4 +1381,3 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1294,4 +1381,3 @@ static void set_rx_mode(struct net_device *dev)
} }
restore_flags(flags); restore_flags(flags);
} }
MODULE_LICENSE("GPL");
...@@ -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,25 +1306,25 @@ static int smc91c92_open(struct net_device *dev) ...@@ -1302,25 +1306,25 @@ 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);
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);
...@@ -1332,27 +1336,27 @@ static int smc91c92_close(struct net_device *dev) ...@@ -1332,27 +1336,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)
...@@ -1361,12 +1365,12 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1361,12 +1365,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) {
...@@ -1384,7 +1388,7 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1384,7 +1388,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). */
{ {
...@@ -1402,15 +1406,15 @@ static void smc_hardware_send_packet(struct net_device * dev) ...@@ -1402,15 +1406,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;
...@@ -1444,9 +1448,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1444,9 +1448,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++;
...@@ -1455,9 +1459,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1455,9 +1459,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);
...@@ -1467,9 +1471,15 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1467,9 +1471,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--) {
...@@ -1481,18 +1491,18 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1481,18 +1491,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)
...@@ -1502,13 +1512,13 @@ static void smc_tx_err(struct net_device * dev) ...@@ -1502,13 +1512,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++;
...@@ -1518,21 +1528,21 @@ static void smc_tx_err(struct net_device * dev) ...@@ -1518,21 +1528,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;
} }
...@@ -1544,7 +1554,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1544,7 +1554,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"
...@@ -1561,7 +1571,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1561,7 +1571,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);
...@@ -1572,7 +1582,7 @@ static void smc_eph_irq(struct net_device *dev) ...@@ -1572,7 +1582,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;
...@@ -1584,10 +1594,10 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1584,10 +1594,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) {
...@@ -1597,13 +1607,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1597,13 +1607,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,
...@@ -1629,18 +1639,20 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1629,18 +1639,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)
...@@ -1649,7 +1661,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1649,7 +1661,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);
...@@ -1658,7 +1670,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1658,7 +1670,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 */
...@@ -1691,15 +1703,15 @@ static void smc_rx(struct net_device *dev) ...@@ -1691,15 +1703,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);
...@@ -1707,7 +1719,7 @@ static void smc_rx(struct net_device *dev) ...@@ -1707,7 +1719,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;
...@@ -1725,7 +1737,7 @@ static void smc_rx(struct net_device *dev) ...@@ -1725,7 +1737,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;
...@@ -1746,31 +1758,30 @@ static void smc_rx(struct net_device *dev) ...@@ -1746,31 +1758,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. */
...@@ -1782,14 +1793,14 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, ...@@ -1782,14 +1793,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)
...@@ -1799,7 +1810,7 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1799,7 +1810,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;
...@@ -1812,7 +1823,7 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1812,7 +1823,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);
...@@ -1822,14 +1833,14 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1822,14 +1833,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)
...@@ -1889,18 +1900,18 @@ static void smc_reset(struct net_device *dev) ...@@ -1889,18 +1900,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);
...@@ -1914,32 +1925,35 @@ static void smc_reset(struct net_device *dev) ...@@ -1914,32 +1925,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. */
...@@ -1951,7 +1965,7 @@ static void smc_reset(struct net_device *dev) ...@@ -1951,7 +1965,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)
...@@ -1968,12 +1982,18 @@ static void media_check(u_long arg) ...@@ -1968,12 +1982,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)) {
...@@ -1995,7 +2015,7 @@ static void media_check(u_long arg) ...@@ -1995,7 +2015,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;
...@@ -2004,21 +2024,23 @@ static void media_check(u_long arg) ...@@ -2004,21 +2024,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) {
...@@ -2053,7 +2075,7 @@ static void media_check(u_long arg) ...@@ -2053,7 +2075,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);
...@@ -2167,7 +2189,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2167,7 +2189,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);
...@@ -2194,7 +2216,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2194,7 +2216,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;
...@@ -2211,7 +2233,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2211,7 +2233,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
else else
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
default: default:
break; break;
} }
...@@ -2233,7 +2255,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2233,7 +2255,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);
...@@ -2255,7 +2277,7 @@ static int __init init_smc91c92_cs(void) ...@@ -2255,7 +2277,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;
...@@ -2271,4 +2293,3 @@ static void __exit exit_smc91c92_cs(void) ...@@ -2271,4 +2293,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);
...@@ -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
...@@ -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;
} }
/*===================================================================== /*=====================================================================
......
...@@ -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);
......
/* /*
* 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 */
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