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;
......@@ -401,7 +443,7 @@ static void fmvj18x_config(dev_link_t *link)
cardtype_t cardtype;
char *card_name = "unknown";
u_char *node_id;
DEBUG(0, "fmvj18x_config(0x%p)\n", link);
/*
......@@ -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;
}
}
CS_CHECK(RequestIO, link->handle, &link->io);
req_irq:
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);
}
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,16 +1087,16 @@ static void fjn_reset(struct net_device *dev)
outb(0xff, ioaddr + TX_STATUS);
outb(0xff, ioaddr + RX_STATUS);
if( lp->cardtype != TDK )
outb(INTR_OFF, ioaddr + LAN_CTRL);
if (lp->cardtype == MBH10302)
outb(INTR_OFF, ioaddr + LAN_CTRL);
/* Turn on Rx interrupts */
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
/* Turn on interrupts from LAN card controller */
if( lp->cardtype != TDK )
outb(INTR_ON, ioaddr + LAN_CTRL);
if (lp->cardtype == MBH10302)
outb(INTR_ON, ioaddr + LAN_CTRL);
} /* fjn_reset */
/*====================================================================*/
......@@ -1064,7 +1151,7 @@ static void fjn_rx(struct net_device *dev)
skb_reserve(skb, 2);
insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
(pkt_len + 1) >> 1);
(pkt_len + 1) >> 1);
skb->protocol = eth_type_trans(skb, dev);
#ifdef PCMCIA_DEBUG
......@@ -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,8 +8,8 @@
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),
David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman
......@@ -18,7 +18,7 @@
incorporated some parts of his driver here. I (Dave) wrote most
of the PCMCIA glue code, and the Ositech support code. Kelly
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
the GNU General Public License, incorporated herein by reference.
......@@ -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 */
......@@ -257,7 +259,7 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
#define MULTICAST2 2
#define MULTICAST4 4
#define MULTICAST6 6
#define MGMT 8
#define MGMT 8
#define REVISION 0x0a
/* Transmit status bits. */
......@@ -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);
/*======================================================================
......@@ -310,7 +312,7 @@ static int smc_link_ok(struct net_device *dev);
This bit of code is used to avoid unregistering network devices
at inappropriate times. 2.2 and later kernels are fairly picky
about when this can happen.
======================================================================*/
static void flush_stale_links(void)
......@@ -349,7 +351,7 @@ static dev_link_t *smc91c92_attach(void)
DEBUG(0, "smc91c92_attach()\n");
flush_stale_links();
/* Create new ethernet device */
smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
if (!smc) return NULL;
......@@ -375,25 +377,25 @@ 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;
#endif
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;
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
......@@ -411,7 +413,7 @@ static dev_link_t *smc91c92_attach(void)
smc91c92_detach(link);
return NULL;
}
return link;
} /* smc91c92_attach */
......@@ -430,13 +432,13 @@ static void smc91c92_detach(dev_link_t *link)
dev_link_t **linkp;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
del_timer(&link->release);
if (link->state & DEV_CONFIG) {
smc91c92_release((u_long)link);
......@@ -445,16 +447,16 @@ static void smc91c92_detach(dev_link_t *link)
return;
}
}
if (link->handle)
CardServices(DeregisterClient, link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
if (link->dev)
unregister_netdev(&smc->dev);
kfree(smc);
} /* smc91c92_detach */
/*====================================================================*/
......@@ -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
and 3288) cards. mhz_setup() gets a card's hardware ethernet
address.
======================================================================*/
static int mhz_3288_power(dev_link_t *link)
{
struct smc_private *smc = link->priv;
u_char tmp;
/* Read the ISR twice... */
readb(smc->base+MEGAHERTZ_ISR);
udelay(5);
......@@ -517,7 +519,7 @@ static int mhz_3288_power(dev_link_t *link)
/* Pause 200ms... */
mdelay(200);
/* Now read and write the COR... */
tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
udelay(5);
......@@ -569,7 +571,7 @@ static int mhz_mfc_config(dev_link_t *link)
if (i != CS_SUCCESS)
return i;
dev->base_addr = link->io.BasePort1;
/* Allocate a memory window, for accessing the ISR */
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
......@@ -583,12 +585,12 @@ static int mhz_mfc_config(dev_link_t *link)
if (smc->manfid == MANFID_MOTOROLA)
mem.CardOffset = link->conf.ConfigBase;
i = CardServices(MapMemPage, link->win, &mem);
if ((i == CS_SUCCESS)
&& (smc->manfid == MANFID_MEGAHERTZ)
&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))
mhz_3288_power(link);
return i;
}
......@@ -628,7 +630,7 @@ static int mhz_setup(dev_link_t *link)
buf[12] = '\0';
if (cvt_ascii_address(dev, buf) == 0)
return 0;
return -1;
}
......@@ -638,7 +640,7 @@ static int mhz_setup(dev_link_t *link)
mot_config() writes directly to the Mariner configuration
registers because the CIS is just bogus.
======================================================================*/
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;
ioaddr_t ioaddr = dev->base_addr;
ioaddr_t iouart = link->io.BasePort2;
/* Set UART base address and force map with COR bit 1 */
writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0);
writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);
writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR);
/* Set SMC base address and force map with COR bit 1 */
writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0);
writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);
......@@ -671,7 +673,7 @@ static int mot_setup(dev_link_t *link)
u_int addr;
/* Read Ethernet address from Serial EEPROM */
for (i = 0; i < 3; i++) {
SMC_SELECT_BANK(2);
outw(MOT_EEPROM + i, ioaddr + POINTER);
......@@ -691,7 +693,7 @@ static int mot_setup(dev_link_t *link)
dev->dev_addr[2*i] = addr & 0xff;
dev->dev_addr[2*i+1] = (addr >> 8) & 0xff;
}
return 0;
}
......@@ -743,7 +745,7 @@ static int smc_setup(dev_link_t *link)
tuple.Attributes = tuple.TupleOffset = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
/* Check for a LAN function extension tuple */
tuple.DesiredTuple = CISTPL_FUNCE;
i = first_tuple(handle, &tuple, &parse);
......@@ -760,7 +762,7 @@ static int smc_setup(dev_link_t *link)
return 0;
}
}
/* Try the third string in the Version 1 Version/ID tuple. */
tuple.DesiredTuple = CISTPL_VERS_1;
if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
......@@ -780,7 +782,7 @@ static int osi_config(dev_link_t *link)
struct net_device *dev = &smc->dev;
static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int i, j;
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
link->irq.Attributes =
......@@ -789,10 +791,10 @@ static int osi_config(dev_link_t *link)
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts2 = 8;
link->io.IOAddrLines = 16;
/* Enable Hard Decode, LAN, Modem */
link->conf.ConfigIndex = 0x23;
for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j];
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)
tuple_t tuple;
u_char buf[255];
int i;
tuple.Attributes = TUPLE_RETURN_COMMON;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
/* Read the station address from tuple 0x90, subtuple 0x04 */
tuple.DesiredTuple = 0x90;
i = CardServices(GetFirstTuple, handle, &tuple);
......@@ -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
the revision code if successful. Otherwise, it returns -ENODEV.
======================================================================*/
static int check_sig(dev_link_t *link)
......@@ -888,7 +890,7 @@ static int check_sig(dev_link_t *link)
else
s &= ~CFG_16BIT;
outb(s, ioaddr + CONFIG);
/* Check Base Address Register to make sure bus width is OK */
s = inw(ioaddr + BASE_ADDR);
if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) &&
......@@ -936,7 +938,7 @@ static void smc91c92_config(dev_link_t *link)
ioaddr_t ioaddr;
DEBUG(0, "smc91c92_config(0x%p)\n", link);
tuple.Attributes = tuple.TupleOffset = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
......@@ -946,14 +948,14 @@ static void smc91c92_config(dev_link_t *link)
CS_EXIT_TEST(i, ParseTuple, config_failed);
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
smc->manfid = parse.manfid.manf;
smc->cardid = parse.manfid.card;
}
/* Configure card */
link->state |= DEV_CONFIG;
......@@ -969,12 +971,12 @@ static void smc91c92_config(dev_link_t *link)
i = smc_config(link);
}
CS_EXIT_TEST(i, RequestIO, config_failed);
i = CardServices(RequestIRQ, link->handle, &link->irq);
CS_EXIT_TEST(i, RequestIRQ, config_failed);
i = CardServices(RequestConfiguration, link->handle, &link->conf);
CS_EXIT_TEST(i, RequestConfiguration, config_failed);
if (smc->manfid == MANFID_MOTOROLA)
mot_config(link);
......@@ -984,7 +986,7 @@ static void smc91c92_config(dev_link_t *link)
dev->if_port = if_port;
else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
goto config_undo;
......@@ -1004,16 +1006,16 @@ static void smc91c92_config(dev_link_t *link)
default: /* get the hw address from EEPROM */
i = mot_setup(link); break;
}
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 = "???";
......@@ -1055,12 +1057,12 @@ static void smc91c92_config(dev_link_t *link)
printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
"MII" : if_names[dev->if_port]);
}
if (smc->cfg & CFG_MII_SELECT) {
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,13 +1075,15 @@ 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 */
/*======================================================================
......@@ -1096,14 +1100,14 @@ static void smc91c92_release(u_long arg)
struct smc_private *smc = link->priv;
DEBUG(0, "smc91c92_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "smc91c92_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
......@@ -1111,7 +1115,7 @@ static void smc91c92_release(u_long arg)
iounmap(smc->base);
CardServices(ReleaseWindow, link->win);
}
link->state &= ~DEV_CONFIG;
} /* smc91c92_release */
......@@ -1131,8 +1135,8 @@ static int smc91c92_event(event_t event, int priority,
dev_link_t *link = args->client_data;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
int i;
int i;
DEBUG(1, "smc91c92_event(0x%06x)\n", event);
switch (event) {
......@@ -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);
......@@ -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
non-PCMCIA implementation.
======================================================================*/
#ifdef PCMCIA_DEBUG
......@@ -1277,17 +1281,17 @@ 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
/* Check that the PCMCIA card is still here. */
if (!DEV_OK(link))
return -ENODEV;
......@@ -1302,25 +1306,25 @@ static int smc91c92_open(struct net_device *dev)
netif_start_queue(dev);
smc->saved_skb = 0;
smc->packets_waiting = 0;
smc_reset(dev);
smc->media.function = &media_check;
smc->media.data = (u_long)smc;
smc->media.expires = jiffies + HZ;
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);
......@@ -1332,27 +1336,27 @@ static int smc91c92_close(struct net_device *dev)
SMC_SELECT_BANK(0);
mask_bits(0xff00, ioaddr + RCR);
mask_bits(0xff00, ioaddr + TCR);
/* Put the chip into power-down mode. */
SMC_SELECT_BANK(1);
outw(CTL_POWERDOWN, ioaddr + CONTROL );
link->open--;
del_timer(&smc->media);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
return 0;
} /* smc91c92_close */
} /* smc_close */
/*======================================================================
Transfer a packet to the hardware and trigger the packet send.
This may be called at either from either the Tx queue code
or the interrupt handler.
======================================================================*/
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;
ioaddr_t ioaddr = dev->base_addr;
u_char packet_no;
if (!skb) {
printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
return;
}
/* There should be a packet slot waiting. */
packet_no = inw(ioaddr + PNR_ARR) >> 8;
if (packet_no & 0x80) {
......@@ -1384,7 +1388,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
outw(packet_no, ioaddr + PNR_ARR);
/* point to the beginning of the packet */
outw(PTR_AUTOINC , ioaddr + POINTER);
/* Send the packet length (+6 for status, length and ctl byte)
and the status word (set to zeros). */
{
......@@ -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. */
outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1);
}
/* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */
outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) |
(inw(ioaddr + INTERRUPT) & 0xff00),
ioaddr + INTERRUPT);
/* The chip does the rest of the work. */
outw(MC_ENQUEUE , ioaddr + MMU_CMD);
smc->saved_skb = NULL;
dev_kfree_skb_irq(skb);
dev->trans_start = jiffies;
......@@ -1444,9 +1448,9 @@ 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) {
/* THIS SHOULD NEVER HAPPEN. */
smc->stats.tx_aborted_errors++;
......@@ -1455,9 +1459,9 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
smc->saved_skb = skb;
num_pages = skb->len >> 8;
if (num_pages > 7) {
printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
dev_kfree_skb (skb);
......@@ -1467,9 +1471,15 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* A packet is now waiting. */
smc->packets_waiting++;
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--) {
......@@ -1481,18 +1491,18 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
}
/* Otherwise defer until the Tx-space-allocated interrupt. */
DEBUG(2, "%s: memory allocation deferred.\n", dev->name);
outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);
return 0;
}
/*======================================================================
Handle a Tx anomolous event. Entered while in Window 2.
======================================================================*/
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 packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
int tx_status;
/* select this as the packet to read from */
outw(packet_no, ioaddr + PNR_ARR);
/* read the first word from this packet */
outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER);
tx_status = inw(ioaddr + DATA_1);
smc->stats.tx_errors++;
......@@ -1518,21 +1528,21 @@ static void smc_tx_err(struct net_device * dev)
smc->stats.tx_aborted_errors++;
smc->tx_err++;
}
if (tx_status & TS_SUCCESS) {
printk(KERN_NOTICE "%s: Successful packet caused error "
"interrupt?\n", dev->name);
}
/* 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. */
/* one less packet waiting for me */
smc->packets_waiting--;
outw(saved_packet, ioaddr + PNR_ARR);
return;
}
......@@ -1544,7 +1554,7 @@ static void smc_eph_irq(struct net_device *dev)
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
u_short card_stats, ephs;
SMC_SELECT_BANK(0);
ephs = inw(ioaddr + EPH);
DEBUG(2, "%s: Ethernet protocol handler interrupt, status"
......@@ -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);
......@@ -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)
{
struct smc_private *smc = dev_id;
......@@ -1584,10 +1594,10 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!netif_device_present(dev))
return;
ioaddr = dev->base_addr;
DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
irq, ioaddr);
smc->watchdog = 0;
saved_bank = inw(ioaddr + BANK_SELECT);
if ((saved_bank & 0xff00) != 0x3300) {
......@@ -1597,13 +1607,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
"/ejected device.\n", dev->name, irq);
goto irq_done;
}
SMC_SELECT_BANK(2);
saved_pointer = inw(ioaddr + POINTER);
mask = inw(ioaddr + INTERRUPT) >> 8;
/* clear all interrupts */
outw(0, ioaddr + INTERRUPT);
do { /* read the status flag, and mask it */
status = inw(ioaddr + INTERRUPT) & 0xff;
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)
if (status & IM_ALLOC_INT) {
/* Clear this interrupt so it doesn't happen again */
mask &= ~IM_ALLOC_INT;
smc_hardware_send_packet(dev);
/* enable xmit interrupts based on this */
mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
/* and let the card send more packets to me */
netif_wake_queue(dev);
}
if (status & IM_RX_OVRN_INT) {
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);
}
if (status & IM_EPH_INT)
......@@ -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"
" pointer %4.4x.\n", mask, saved_bank, saved_pointer);
/* restore state register */
outw((mask<<8), ioaddr + INTERRUPT);
outw(saved_pointer, ioaddr + POINTER);
......@@ -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);
irq_done:
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
/* Retrigger interrupt if needed */
......@@ -1691,15 +1703,15 @@ static void smc_rx(struct net_device *dev)
int rx_status;
int packet_length; /* Caution: not frame length, rather words
to transfer from the chip. */
/* Assertion: we are in Window 2. */
if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
dev->name);
return;
}
/* Reset the read pointer, and read the status and packet length. */
outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER);
rx_status = inw(ioaddr + DATA_1);
......@@ -1707,7 +1719,7 @@ static void smc_rx(struct net_device *dev)
DEBUG(2, "%s: Receive status %4.4x length %d.\n",
dev->name, rx_status, packet_length);
if (!(rx_status & RS_ERRORS)) {
/* do stuff to make a new packet */
struct sk_buff *skb;
......@@ -1725,7 +1737,7 @@ static void smc_rx(struct net_device *dev)
packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6);
skb_reserve(skb, 2);
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->dev = dev;
......@@ -1746,31 +1758,30 @@ static void smc_rx(struct net_device *dev)
}
/* Let the MMU free the memory of this packet. */
outw(MC_RELEASE, ioaddr + MMU_CMD);
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;
/* Nothing to update - the 91c92 is a pretty primative chip. */
return &smc->stats;
}
/*======================================================================
Calculate values for the hardware multicast filter hash table.
======================================================================*/
static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
u_char *multicast_table)
{
struct dev_mc_list *mc_addr;
for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) {
u_int position = ether_crc(6, mc_addr->dmi_addr);
#ifndef final_version /* Verify multicast address. */
......@@ -1782,14 +1793,14 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
}
/*======================================================================
Set the receive mode.
This routine is used by both the protocol level to notify us of
promiscuous/multicast mode changes, and by the open/reset code to
initialize the Rx registers. We always set the multicast list and
leave the receiver running.
======================================================================*/
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, };
unsigned long flags;
u_short rx_cfg_setting;
if (dev->flags & IFF_PROMISC) {
printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name);
rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
......@@ -1812,7 +1823,7 @@ static void set_rx_mode(struct net_device *dev)
}
rx_cfg_setting = RxStripCRC | RxEnable;
}
/* Load MC table and Rx setting into the chip without interrupts. */
spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3);
......@@ -1822,14 +1833,14 @@ static void set_rx_mode(struct net_device *dev)
outw(rx_cfg_setting, ioaddr + RCR);
SMC_SELECT_BANK(2);
spin_unlock_irqrestore(&smc->lock, flags);
return;
}
/*======================================================================
Senses when a card's config changes. Here, it's coax or TP.
======================================================================*/
static int s9k_config(struct net_device *dev, struct ifmap *map)
......@@ -1889,18 +1900,18 @@ static void smc_reset(struct net_device *dev)
int i;
DEBUG(0, "%s: smc91c92 reset called.\n", dev->name);
/* The first interaction must be a write to bring the chip out
of sleep mode. */
SMC_SELECT_BANK(0);
/* Reset the chip. */
outw(RCR_SOFTRESET, ioaddr + RCR);
udelay(10);
/* Clear the transmit and receive configuration registers. */
outw(RCR_CLEAR, ioaddr + RCR);
outw(TCR_CLEAR, ioaddr + TCR);
/* Set the Window 1 control, configuration and station addr registers.
No point in writing the I/O base register ;-> */
SMC_SELECT_BANK(1);
......@@ -1914,32 +1925,35 @@ static void smc_reset(struct net_device *dev)
outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) |
(inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00),
ioaddr - 0x10 + OSITECH_AUI_PWR);
/* Fill in the physical address. The databook is wrong about the order! */
for (i = 0; i < 6; i += 2)
outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i],
ioaddr + ADDR0 + i);
/* Reset the MMU */
SMC_SELECT_BANK(2);
outw(MC_RESET, ioaddr + MMU_CMD);
outw(0, ioaddr + INTERRUPT);
/* 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. */
......@@ -1951,7 +1965,7 @@ static void smc_reset(struct net_device *dev)
/*======================================================================
Media selection timer routine
======================================================================*/
static void media_check(u_long arg)
......@@ -1968,12 +1982,18 @@ 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;
SMC_SELECT_BANK(1);
media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
/* Check for pending interrupt with watchdog flag set: with
this, we can limp along even if the interrupt is blocked */
if (smc->watchdog++ && ((i>>8) & i)) {
......@@ -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'));
"%sbaseT-%cD selected\n", dev->name,
((p & 0x0180) ? "100" : "10"),
(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) {
......@@ -2053,7 +2075,7 @@ static void media_check(u_long arg)
}
smc->media_status = media;
}
reschedule:
smc->media.expires = jiffies + HZ;
add_timer(&smc->media);
......@@ -2167,7 +2189,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EFAULT;
spin_lock_irq(&smc->lock);
if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_sset(&smc->mii_if, &ecmd);
ret = mii_ethtool_sset(&smc->mii_if, &ecmd);
else
ret = smc_netdev_set_ecmd(dev, &ecmd);
spin_unlock_irq(&smc->lock);
......@@ -2194,7 +2216,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
......@@ -2211,7 +2233,7 @@ static int smc_ethtool_ioctl (struct net_device *dev, void *useraddr)
else
return -EOPNOTSUPP;
}
default:
break;
}
......@@ -2233,7 +2255,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCETHTOOL:
rc = smc_ethtool_ioctl(dev, (void *) rq->ifr_data);
break;
default:
spin_lock_irq(&smc->lock);
rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
......@@ -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,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,
u_int addr, u_int len, void *ptr)
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;
struct resource *res;
......@@ -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,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,
u_int len, void *ptr)
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;
u_char *sys, *buf = ptr;
......@@ -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,13 +202,13 @@ 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,
u_int addr, u_int len, void *ptr);
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,
u_int addr, u_int len, void *ptr);
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);
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
* 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