patch-2.4.21 linux-2.4.21/drivers/net/pcmcia/fmvj18x_cs.c
Next file: linux-2.4.21/drivers/net/pcmcia/ray_cs.c
Previous file: linux-2.4.21/drivers/net/pcmcia/axnet_cs.c
Back to the patch index
Back to the overall index
- Lines: 400
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/net/pcmcia/fmvj18x_cs.c
- Orig date:
2002-11-28 15:53:14.000000000 -0800
diff -urN linux-2.4.20/drivers/net/pcmcia/fmvj18x_cs.c linux-2.4.21/drivers/net/pcmcia/fmvj18x_cs.c
@@ -1,5 +1,5 @@
/*======================================================================
- 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 @@
#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 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 @@
XXX10304
} cardtype_t;
-#define MANFID_UNGERMANN 0x02c0
-
/*
driver specific data structure
*/
@@ -388,6 +391,45 @@
#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 @@
cardtype_t cardtype;
char *card_name = "unknown";
u_char *node_id;
-
+
DEBUG(0, "fmvj18x_config(0x%p)\n", link);
/*
@@ -444,6 +486,11 @@
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 @@
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 @@
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) {
@@ -591,7 +632,6 @@
strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
lp->cardtype = cardtype;
/* print current configuration */
@@ -601,6 +641,7 @@
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+ link->state &= ~DEV_CONFIG_PENDING;
return;
cs_failed:
@@ -608,6 +649,7 @@
cs_error(link->handle, last_fn, last_ret);
failed:
fmvj18x_release((u_long)link);
+ link->state &= ~DEV_CONFIG_PENDING;
} /* fmvj18x_config */
/*====================================================================*/
@@ -666,6 +708,51 @@
} /* 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;
@@ -752,7 +839,7 @@
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;
@@ -865,11 +952,19 @@
{
struct local_info_t *lp = (struct local_info_t *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
+ short length = skb->len;
+
+ if(length < ETH_ZLEN)
+ {
+ skb = skb_padto(skb, ETH_ZLEN);
+ if(skb == NULL)
+ return 0;
+ length = ETH_ZLEN;
+ }
netif_stop_queue(dev);
{
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
if (length > ETH_FRAME_LEN) {
@@ -942,10 +1037,10 @@
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);
@@ -957,20 +1052,20 @@
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)
@@ -999,16 +1094,16 @@
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 */
/*====================================================================*/
@@ -1063,7 +1158,7 @@
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
@@ -1090,7 +1185,7 @@
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)
@@ -1223,7 +1318,7 @@
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--;
@@ -1252,8 +1347,8 @@
{
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) {
@@ -1293,4 +1388,3 @@
}
restore_flags(flags);
}
-MODULE_LICENSE("GPL");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)