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)
return 0;
}
/**
* ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number
......@@ -1853,7 +1853,7 @@ static int axdev_init(struct net_device *dev)
return 0;
}
/* This page of functions should be 8390 generic */
/* 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
......@@ -29,7 +29,7 @@
======================================================================*/
#define DRV_NAME "fmvj18x_cs"
#define DRV_VERSION "2.6"
#define DRV_VERSION "2.8"
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -65,6 +65,10 @@
/*====================================================================*/
/* 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")
/* Bit map of interrupts to choose from */
......@@ -80,7 +84,7 @@ INT_MODULE_PARM(sram_config, 0);
#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 = DRV_NAME ".c " DRV_VERSION " 2001/09/17";
static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
#else
#define DEBUG(n, args...)
#endif
......@@ -91,6 +95,7 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17";
*/
static void fmvj18x_config(dev_link_t *link);
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 int fmvj18x_event(event_t event, int priority,
event_callback_args_t *args);
......@@ -122,8 +127,6 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
XXX10304
} cardtype_t;
#define MANFID_UNGERMANN 0x02c0
/*
driver specific data structure
*/
......@@ -388,6 +391,45 @@ static void fmvj18x_detach(dev_link_t *link)
#define CS_CHECK(fn, args...) \
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)
{
client_handle_t handle = link->handle;
......@@ -444,6 +486,11 @@ static void fmvj18x_config(dev_link_t *link)
CardServices(GetStatus, handle, &status);
if (status.CardState & CS_EVENT_3VCARD)
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;
case MANFID_CONTEC:
......@@ -481,31 +528,22 @@ static void fmvj18x_config(dev_link_t *link)
break;
case MANFID_UNGERMANN:
cardtype = UNGERMANN;
/*
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;
break;
default:
cardtype = MBH10302;
link->conf.ConfigIndex = 1;
}
}
if (link->io.NumPorts2 != 0) {
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);
req_irq:
}
CS_CHECK(RequestIRQ, link->handle, &link->irq);
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
......@@ -515,19 +553,22 @@ static void fmvj18x_config(dev_link_t *link)
goto failed;
}
if (link->io.BasePort2 != 0)
fmvj18x_setup_mfc(link);
ioaddr = dev->base_addr;
/* Reset controller */
if( sram_config == 0 )
if (sram_config == 0)
outb(CONFIG0_RST, ioaddr + CONFIG_0);
else
outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
/* Power On chip and select bank 0 */
if(cardtype == UNGERMANN)
outb(BANK_0U, ioaddr + CONFIG_1);
else
if (cardtype == MBH10302)
outb(BANK_0, ioaddr + CONFIG_1);
else
outb(BANK_0U, ioaddr + CONFIG_1);
/* Set hardware address */
switch (cardtype) {
......@@ -592,7 +633,6 @@ static void fmvj18x_config(dev_link_t *link)
strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
lp->cardtype = cardtype;
/* print current configuration */
......@@ -602,6 +642,7 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
link->state &= ~DEV_CONFIG_PENDING;
return;
cs_failed:
......@@ -609,6 +650,7 @@ static void fmvj18x_config(dev_link_t *link)
cs_error(link->handle, last_fn, last_ret);
failed:
fmvj18x_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* fmvj18x_config */
/*====================================================================*/
......@@ -667,6 +709,51 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
} /* 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)
{
dev_link_t *link = (dev_link_t *)arg;
......@@ -753,7 +840,7 @@ static int __init init_fmvj18x_cs(void)
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "fmvj18x: Card Services release "
"does not match!\n");
return -1;
return -EINVAL;
}
register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach);
return 0;
......@@ -943,10 +1030,10 @@ static void fjn_reset(struct net_device *dev)
outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
/* Power On chip and select bank 0 */
if( lp->cardtype == UNGERMANN)
outb(BANK_0U, ioaddr + CONFIG_1);
else
if (lp->cardtype == MBH10302)
outb(BANK_0, ioaddr + CONFIG_1);
else
outb(BANK_0U, ioaddr + CONFIG_1);
/* Set Tx modes */
outb(D_TX_MODE, ioaddr + TX_MODE);
......@@ -958,20 +1045,20 @@ static void fjn_reset(struct net_device *dev)
outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
/* Switch to bank 1 */
if ( lp->cardtype == UNGERMANN )
outb(BANK_1U, ioaddr + CONFIG_1);
else
if (lp->cardtype == MBH10302)
outb(BANK_1, ioaddr + CONFIG_1);
else
outb(BANK_1U, ioaddr + CONFIG_1);
/* set the multicast table to accept none. */
for (i = 0; i < 6; i++)
outb(0x00, ioaddr + MAR_ADR + i);
/* Switch to bank 2 (runtime mode) */
if ( lp->cardtype == UNGERMANN )
outb(BANK_2U, ioaddr + CONFIG_1);
else
if (lp->cardtype == MBH10302)
outb(BANK_2, ioaddr + CONFIG_1);
else
outb(BANK_2U, ioaddr + CONFIG_1);
/* set 16col ctrl bits */
if( lp->cardtype == TDK || lp->cardtype == CONTEC)
......@@ -1000,7 +1087,7 @@ static void fjn_reset(struct net_device *dev)
outb(0xff, ioaddr + TX_STATUS);
outb(0xff, ioaddr + RX_STATUS);
if( lp->cardtype != TDK )
if (lp->cardtype == MBH10302)
outb(INTR_OFF, ioaddr + LAN_CTRL);
/* Turn on Rx interrupts */
......@@ -1008,7 +1095,7 @@ static void fjn_reset(struct net_device *dev)
outb(D_RX_INTR, ioaddr + RX_INTR);
/* Turn on interrupts from LAN card controller */
if( lp->cardtype != TDK )
if (lp->cardtype == MBH10302)
outb(INTR_ON, ioaddr + LAN_CTRL);
} /* fjn_reset */
......@@ -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
when we get to the bottom-half routine. */
/*
if( lp->cardtype != TDK ) {
if (lp->cardtype != TDK) {
int i;
for (i = 0; i < 20; i++) {
if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
......@@ -1224,7 +1311,7 @@ static int fjn_close(struct net_device *dev)
outb(CHIP_OFF ,ioaddr + CONFIG_1);
/* Set the ethernet adaptor disable IRQ */
if( lp->cardtype != TDK )
if (lp->cardtype == MBH10302)
outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--;
......@@ -1253,8 +1340,8 @@ static void set_rx_mode(struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
struct local_info_t *lp = (struct local_info_t *)dev->priv;
unsigned char mc_filter[8]; /* Multicast hash filter */
unsigned long flags;
u_char mc_filter[8]; /* Multicast hash filter */
u_long flags;
int i;
if (dev->flags & IFF_PROMISC) {
......@@ -1294,4 +1381,3 @@ static void set_rx_mode(struct net_device *dev)
}
restore_flags(flags);
}
MODULE_LICENSE("GPL");
......@@ -8,7 +8,7 @@
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
(becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au),
......@@ -92,7 +92,7 @@ static const char *version =
#endif
#define DRV_NAME "smc91c92_cs"
#define DRV_VERSION "1.2"
#define DRV_VERSION "1.122"
/*====================================================================*/
......@@ -130,6 +130,8 @@ struct smc_private {
u_short fast_poll;
u_short link_status;
struct mii_if_info mii_if;
int duplex;
int rx_ovrn;
};
/* Special definitions for Megahertz multifunction cards */
......@@ -287,22 +289,22 @@ static void smc91c92_release(u_long arg);
static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args);
static int smc91c92_open(struct net_device *dev);
static int smc91c92_close(struct net_device *dev);
static int smc_open(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 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_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 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_reset(struct net_device *dev);
static void media_check(u_long arg);
static void smc_mdio_sync(ioaddr_t addr);
static int smc_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 int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void mdio_sync(ioaddr_t addr);
static int mdio_read(struct net_device *dev, int phy_id, int loc);
static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
static int smc_link_ok(struct net_device *dev);
/*======================================================================
......@@ -375,13 +377,13 @@ static dev_link_t *smc91c92_attach(void)
/* The SMC91c92-specific entries in the device structure. */
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_multicast_list = &set_rx_mode;
dev->do_ioctl = &smc_ioctl;
ether_setup(dev);
dev->open = &smc91c92_open;
dev->stop = &smc91c92_close;
dev->open = &smc_open;
dev->stop = &smc_close;
dev->do_ioctl = &smc_ioctl;
#ifdef HAVE_TX_TIMEOUT
dev->tx_timeout = smc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
......@@ -389,8 +391,8 @@ static dev_link_t *smc91c92_attach(void)
dev->priv = link->priv = link->irq.Instance = smc;
smc->mii_if.dev = dev;
smc->mii_if.mdio_read = smc_mdio_read;
smc->mii_if.mdio_write = smc_mdio_write;
smc->mii_if.mdio_read = mdio_read;
smc->mii_if.mdio_write = mdio_write;
smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f;
......@@ -1007,13 +1009,13 @@ static void smc91c92_config(dev_link_t *link)
if (i != 0) {
printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
link->state &= ~DEV_CONFIG_PENDING;
goto config_undo;
}
strcpy(smc->node.dev_name, dev->name);
link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING;
smc->duplex = 0;
smc->rx_ovrn = 0;
rev = check_sig(link);
name = "???";
......@@ -1060,7 +1062,7 @@ static void smc91c92_config(dev_link_t *link)
SMC_SELECT_BANK(3);
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;
}
smc->mii_if.phy_id = (i < 32) ? i : -1;
......@@ -1073,12 +1075,14 @@ static void smc91c92_config(dev_link_t *link)
SMC_SELECT_BANK(0);
}
link->state &= ~DEV_CONFIG_PENDING;
return;
config_undo:
unregister_netdev(dev);
config_failed: /* CS_EXIT_TEST() calls jump to here... */
smc91c92_release((u_long)link);
link->state &= ~DEV_CONFIG_PENDING;
} /* smc91c92_config */
......@@ -1144,7 +1148,7 @@ static int smc91c92_event(event_t event, int priority,
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
smc91c92_config(link);
break;
case CS_EVENT_PM_SUSPEND:
......@@ -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_READ 0x02
static void smc_mdio_sync(ioaddr_t addr)
static void mdio_sync(ioaddr_t addr)
{
int bits;
for (bits = 0; bits < 32; bits++) {
......@@ -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;
u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
int i, retval = 0;
smc_mdio_sync(addr);
mdio_sync(addr);
for (i = 13; i >= 0; i--) {
int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
outb(dat, addr);
......@@ -1235,13 +1239,13 @@ static int smc_mdio_read(struct net_device *dev, int phy_id, int loc)
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;
u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
int i;
smc_mdio_sync(addr);
mdio_sync(addr);
for (i = 31; i >= 0; i--) {
int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
outb(dat, addr);
......@@ -1277,13 +1281,13 @@ static void smc_dump(struct net_device *dev)
}
#endif
static int smc91c92_open(struct net_device *dev)
static int smc_open(struct net_device *dev)
{
struct smc_private *smc = dev->priv;
dev_link_t *link = &smc->link;
#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));
if (pc_debug > 1) smc_dump(dev);
#endif
......@@ -1310,17 +1314,17 @@ static int smc91c92_open(struct net_device *dev)
add_timer(&smc->media);
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;
dev_link_t *link = &smc->link;
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));
netif_stop_queue(dev);
......@@ -1345,7 +1349,7 @@ static int smc91c92_close(struct net_device *dev)
MOD_DEC_USE_COUNT;
return 0;
} /* smc91c92_close */
} /* smc_close */
/*======================================================================
......@@ -1444,7 +1448,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *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));
if (smc->saved_skb) {
......@@ -1470,6 +1474,12 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
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. */
outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD);
for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) {
......@@ -1525,7 +1535,7 @@ static void smc_tx_err(struct net_device * dev)
}
/* re-enable transmit */
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);
outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */
......@@ -1561,7 +1571,7 @@ static void smc_eph_irq(struct net_device *dev)
card_stats >>= 4; /* excess deferred */
#endif
/* 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. */
SMC_SELECT_BANK(1);
......@@ -1641,6 +1651,8 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & IM_RX_OVRN_INT) {
smc->stats.rx_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);
}
if (status & IM_EPH_INT)
......@@ -1752,14 +1764,13 @@ 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)
{
struct smc_private *smc = (struct smc_private *)dev->priv;
/* Nothing to update - the 91c92 is a pretty primative chip. */
return &smc->stats;
}
/*======================================================================
Calculate values for the hardware multicast filter hash table.
......@@ -1928,18 +1939,21 @@ static void smc_reset(struct net_device *dev)
/* Re-enable the chip. */
SMC_SELECT_BANK(0);
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);
if (smc->cfg & CFG_MII_SELECT) {
SMC_SELECT_BANK(3);
/* 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 */
smc_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, 0x0000);
mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200);
}
/* Enable interrupts. */
......@@ -1968,6 +1982,12 @@ static void media_check(u_long arg)
goto reschedule;
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);
SMC_SELECT_BANK(0);
media = inw(ioaddr + EPH) & EPH_LINK_OK;
......@@ -1995,7 +2015,7 @@ static void media_check(u_long arg)
goto reschedule;
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)) {
printk(KERN_INFO "%s: MII is missing!\n", dev->name);
smc->mii_if.phy_id = -1;
......@@ -2004,21 +2024,23 @@ static void media_check(u_long arg)
link &= 0x0004;
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,
(link) ? "found" : "lost");
smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
? TCR_FDUPLX : 0);
if (link) {
printk(KERN_INFO "%s: autonegotiation complete: "
"%sbaseT-%cD selected\n", dev->name,
((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;
}
}
if (smc->cfg & CFG_MII_SELECT)
goto reschedule;
}
/* Ignore collisions unless we've had no rx's recently */
if (jiffies - dev->last_rx > HZ) {
......@@ -2255,7 +2277,7 @@ static int __init init_smc91c92_cs(void)
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_ERR
"smc91c92_cs: Card Services release does not match!\n");
return -1;
return -EINVAL;
}
register_pccard_driver(&dev_info, &smc91c92_attach, &smc91c92_detach);
return 0;
......@@ -2271,4 +2293,3 @@ static void __exit exit_smc91c92_cs(void)
module_init(init_smc91c92_cs);
module_exit(exit_smc91c92_cs);
......@@ -2,7 +2,7 @@
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
License Version 1.1 (the "License"); you may not use this file
......@@ -175,7 +175,7 @@ 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)
{
struct pci_dev *dev;
......@@ -194,7 +194,7 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space,
goto fail;
for (; len; addr++, ptr++, len--)
pci_readb(dev, addr, (u_char *) ptr);
return;
return 0;
}
res = dev->resource + space - 1;
......@@ -214,11 +214,11 @@ void read_cb_mem(socket_info_t * s, u_char fn, int space,
goto fail;
memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
return;
return 0;
fail:
memset(ptr, 0xff, len);
return;
return -1;
}
/*=====================================================================
......
......@@ -2,7 +2,7 @@
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
License Version 1.1 (the "License"); you may not use this file
......@@ -109,7 +109,7 @@ 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)
{
pccard_mem_map *mem = &s->cis_mem;
......@@ -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);
if (setup_cis_mem(s) != 0) {
memset(ptr, 0xff, len);
return;
return -1;
}
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,
DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
*(u_char *)(ptr+0), *(u_char *)(ptr+1),
*(u_char *)(ptr+2), *(u_char *)(ptr+3));
return 0;
}
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)
if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
s->cap.map_size, low, "card services", s)) {
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_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start,
......@@ -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,
u_int len, void *ptr)
{
int i;
int i, ret;
char *caddr;
if (s->fake_cis) {
......@@ -326,12 +327,12 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
}
#ifdef CONFIG_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
#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 */
if ((i < MAX_CIS_TABLE) &&
if ((ret == 0) && (i < MAX_CIS_TABLE) &&
(caddr+len < s->cis_cache+MAX_CIS_DATA)) {
s->cis_table[i].addr = addr;
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
* Version 1.1 (the "License"); you may not use this file except in
......@@ -202,12 +202,12 @@ int cb_config(socket_info_t *s);
void cb_release(socket_info_t *s);
void cb_enable(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);
void cb_release_cis_mem(socket_info_t *s);
/* 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);
void write_cis_mem(socket_info_t *s, int attr,
u_int addr, u_int len, void *ptr);
......
/*
* 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
* Version 1.1 (the "License"); you may not use this file except in
......@@ -16,8 +16,8 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in which
* case the provisions of the GPL are applicable instead of the
* terms of the GNU General Public License version 2 (the "GPL"), in
* 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
* 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
......@@ -60,6 +60,10 @@
#define PRODID_INTEL_DUAL_RS232 0x0301
#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 PRODID_LINKSYS_PCMLM28 0xc0ab
#define PRODID_LINKSYS_3400 0x3341
......@@ -94,6 +98,8 @@
#define PRODID_OSITECH_JACK_336 0x0007
#define PRODID_OSITECH_SEVEN 0x0008
#define MANFID_OXSEMI 0x0279
#define MANFID_PIONEER 0x000b
#define MANFID_PSION 0x016c
......@@ -103,7 +109,10 @@
#define PRODID_QUATECH_SPP100 0x0003
#define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_DUAL_RS232_D2 0x0052
#define PRODID_QUATECH_QUAD_RS232 0x001b
#define PRODID_QUATECH_DUAL_RS422 0x000e
#define PRODID_QUATECH_QUAD_RS422 0x0045
#define MANFID_SMC 0x0108
#define PRODID_SMC_ETHER 0x0105
......@@ -118,9 +127,12 @@
#define MANFID_TDK 0x0105
#define PRODID_TDK_CF010 0x0900
#define PRODID_TDK_GN3410 0x4815
#define MANFID_TOSHIBA 0x0098
#define MANFID_UNGERMANN 0x02c0
#define MANFID_XIRCOM 0x0105
#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