patch-2.3.40 linux/drivers/net/pcmcia/xirc2ps_cs.c
Next file: linux/drivers/net/pcnet32.c
Previous file: linux/drivers/net/pcmcia/wavelan_cs.c
Back to the patch index
Back to the overall index
- Lines: 425
- Date:
Tue Jan 18 22:29:17 2000
- Orig file:
v2.3.39/linux/drivers/net/pcmcia/xirc2ps_cs.c
- Orig date:
Thu Nov 11 20:11:41 1999
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1,37 +1,44 @@
-/* [xirc2ps_cs.c wk 14.04.97] (1.31 1998/12/09 19:32:55)
- * Xircom Creditcard Ethernet Adapter IIps driver
- *
- * This driver works for the CE2, CEM28, CEM33, CE3 and CEM56 cards.
- * The CEM56 has some problems, but it works.
- * The CEII card with the 14k4 modem and other old cards do not work.
- *
- * Written by Werner Koch (werner.koch@guug.de),
- * based on David Hinds skeleton driver.
- *
- * You can get the latest driver revision from
- * "http://www.d.shuttle.de/isil/xircom/xirc2ps.html"
- *
- * Please report bugs to: "xircom-bugs@isil.d.shuttle.de"
- *
- * A bug fix for the CEM56 to use modem and ethernet simultaneously
- * was provided by Koen Van Herck (Koen.Van.Herck@xircom.com).
- *
- * If your card locks up you should use the option "lockup_hack=1";
- * this may solve the problem but violates a kernel timing convention
- * (Thanks to David Luyer).
- *
- * Thanks to David Hinds for the PCMCIA package, Donald Becker for some
- * advice, Xircom for providing specs and help, 4PC GmbH Duesseldorf for
- * providing some hardware and last not least to all folks who helped to
- * develop this driver.
- *
- * For those, who are willing to do alpha testing of drivers, I have setup
- * the mailing list "xircom-devel@isil.d.shuttle.de" (To subscribe send a
- * message containing the word "subscribe" in the subject or somewhere at
- * the beginning of a line to "xircom-devel-request@isil.d.shuttle.de").
+/* [xirc2ps_cs.c wk 03.11.99] (1.40 1999/11/18 00:06:03)
+ * Xircom CreditCard Ethernet Adapter IIps driver
+ * Xircom Realport 10/100 (RE-100) driver
+ *
+ * This driver originally was made by Werner Koch. Since the driver was left
+ * unmaintained for some time, there have been some improvements and changes
+ * since. These include supporting some of the "Realport" cards and develop-
+ * ing enhancements to support the new ones.
+ * It is made for CE2, CEM28, CEM33, CE33 and
+ * CEM56 cards. The CEM56 cards work both with their modem and ethernet
+ * interface. The RealPort 10/100 Modem and similar cards are supported but
+ * with some bugs which are being corrected as they are detected.
+ *
+ * Code revised and maintained by Allan Baker Ortegon
+ * al527261@prodigy.net.mx
+ * Written originally by Werner Koch based on David Hinds' skeleton of the
+ * PCMCIA driver. The code has been modified as to make the newer cards
+ * available.
+ *
+ * The latest code for the driver, information on the development project
+ * for the Xircom RealPort and CE cards for the PCMCIA driver, and other
+ * related material, can be found at the following URL, which is underway:
+ *
+ * "http://xirc2ps.linuxbox.com/index.html"
+ *
+ * Any bugs regarding this driver, please send them to:
+ * alanyuu@linuxbox.com
+ *
+ * The driver is still evolving and there are many cards which will benefit
+ * from having alpha testers. If you have a particular card and would like
+ * to be involved in this ongoing effort, please send mail to the maintainer.
+ *
+ * Special thanks to David Hinds, to Xircom for the specifications and their
+ * software development kit, and all others who may have colaborated in the
+ * development of the driver: Koen Van Herck (Koen.Van.Herck@xircom.com),
+ * 4PC GmbH Duesseldorf, David Luger, et al.
+ *
*
************************************************************************
* Copyright (c) 1997,1998 Werner Koch (dd9jn)
+ * Copyright (c) 1999 Allan Baker Ortegon
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -70,7 +77,7 @@
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -388,6 +395,8 @@
*/
typedef struct local_info_t {
+ dev_link_t link;
+ struct net_device dev;
dev_node_t node;
struct enet_statistics stats;
int card_type;
@@ -472,14 +481,18 @@
static void
busy_loop(u_long len)
{
- u_long timeout = jiffies + len;
- u_long flags;
-
- save_flags(flags);
- sti();
- while (timeout >= jiffies)
- ;
- restore_flags(flags);
+ if (in_interrupt()) {
+ u_long timeout = jiffies + len;
+ u_long flags;
+ save_flags(flags);
+ sti();
+ while (timeout >= jiffies)
+ ;
+ restore_flags(flags);
+ } else {
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(len);
+ }
}
/*====== Functions used for debugging =================================*/
@@ -674,9 +687,13 @@
DEBUG(0, "attach()\n");
flush_stale_links();
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- memset(link, 0, sizeof(struct dev_link_t));
+ /* Allocate the device structure */
+ local = kmalloc(sizeof(*local), GFP_KERNEL);
+ if (!local) return NULL;
+ memset(local, 0, sizeof(*local));
+ link = &local->link; dev = &local->dev;
+ link->priv = dev->priv = local;
+
link->release.function = &xirc2ps_release;
link->release.data = (u_long) link;
@@ -686,13 +703,8 @@
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
-
- /* Allocate space for a device structure */
- dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
- memset(dev, 0, sizeof(struct net_device));
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- memset(local, 0, sizeof(local_info_t));
- dev->priv = local;
+ link->irq.Handler = xirc2ps_interrupt;
+ link->irq.Instance = dev;
/* Fill in card specific entries */
dev->hard_start_xmit = &do_start_xmit;
@@ -706,7 +718,6 @@
dev->open = &do_open;
dev->stop = &do_stop;
dev->tbusy = 1;
- link->priv = dev;
/* Register with Card Services */
link->next = dev_list;
@@ -739,6 +750,7 @@
static void
xirc2ps_detach(dev_link_t * link)
{
+ local_info_t *local = link->priv;
dev_link_t **linkp;
long flags;
@@ -778,17 +790,11 @@
if (link->handle)
CardServices(DeregisterClient, link->handle);
- /* Unlink device structure, free pieces */
+ /* Unlink device structure, free it */
*linkp = link->next;
- if (link->priv) {
- struct net_device *dev = link->priv;
- if (link->dev != NULL)
- unregister_netdev(dev);
- if (dev->priv)
- kfree(dev->priv);
- kfree(link->priv);
- }
- kfree(link);
+ if (link->dev)
+ unregister_netdev(&local->dev);
+ kfree(local);
} /* xirc2ps_detach */
@@ -813,8 +819,7 @@
static int
set_card_type(dev_link_t *link, const void *s)
{
- struct net_device *dev = link->priv;
- local_info_t *local = dev->priv;
+ local_info_t *local = link->priv;
#ifdef PCMCIA_DEBUG
unsigned cisrev = ((const unsigned char *)s)[2];
#endif
@@ -907,20 +912,17 @@
static void
xirc2ps_config(dev_link_t * link)
{
- client_handle_t handle;
+ client_handle_t handle = link->handle;
+ local_info_t *local = link->priv;
+ struct net_device *dev = &local->dev;
tuple_t tuple;
cisparse_t parse;
- struct net_device *dev;
- local_info_t *local;
ioaddr_t ioaddr;
int err, i;
u_char buf[64];
cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- handle = link->handle;
- dev = link->priv;
- local = dev->priv;
local->dingo_ccr = 0;
DEBUG(0, "config(0x%p)\n", link);
@@ -1034,8 +1036,6 @@
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
}
- link->irq.Handler = xirc2ps_interrupt;
- link->irq.Instance = dev;
if (local->modem) {
int pass;
@@ -1124,7 +1124,7 @@
* the I/O windows and the interrupt mapping.
*/
if ((err=CardServices(RequestConfiguration,
- link->handle, &link->conf))) {
+ link->handle, &link->conf))) {
cs_error(link->handle, RequestConfiguration, err);
goto config_error;
}
@@ -1146,7 +1146,7 @@
reg.Offset = CISREG_IOBASE_0;
reg.Value = link->io.BasePort2 & 0xff;
if ((err = CardServices(AccessConfigurationRegister, link->handle,
- ®))) {
+ ®))) {
cs_error(link->handle, AccessConfigurationRegister, err);
goto config_error;
}
@@ -1154,7 +1154,7 @@
reg.Offset = CISREG_IOBASE_1;
reg.Value = (link->io.BasePort2 >> 8) & 0xff;
if ((err = CardServices(AccessConfigurationRegister, link->handle,
- ®))) {
+ ®))) {
cs_error(link->handle, AccessConfigurationRegister, err);
goto config_error;
}
@@ -1213,20 +1213,19 @@
}
#endif
- writeb(0x01 , local->dingo_ccr + 0x20);
- writeb(0x0c , local->dingo_ccr + 0x22);
- writeb(0x00 , local->dingo_ccr + 0x24);
- writeb(0x00 , local->dingo_ccr + 0x26);
- writeb(0x00 , local->dingo_ccr + 0x28);
+ writeb(0x01, local->dingo_ccr + 0x20);
+ writeb(0x0c, local->dingo_ccr + 0x22);
+ writeb(0x00, local->dingo_ccr + 0x24);
+ writeb(0x00, local->dingo_ccr + 0x26);
+ writeb(0x00, local->dingo_ccr + 0x28);
}
/* The if_port symbol can be set when the module is loaded */
local->probe_port=0;
if (!if_port) {
- local->probe_port=1;
- dev->if_port = 1;
- }
- else if ((if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4))
+ local->probe_port = dev->if_port = 1;
+ } else if ((if_port >= 1 && if_port <= 2) ||
+ (local->mohawk && if_port==4))
dev->if_port = if_port;
else
printk(KNOT_XIRC "invalid if_port requested\n");
@@ -1275,7 +1274,8 @@
xirc2ps_release(u_long arg)
{
dev_link_t *link = (dev_link_t *) arg;
- struct net_device *dev = link->priv;
+ local_info_t *local = link->priv;
+ struct net_device *dev = &local->dev;
DEBUG(0, "release(0x%p)\n", link);
@@ -1322,8 +1322,8 @@
event_callback_args_t * args)
{
dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
- local_info_t *lp = dev? dev->priv : NULL;
+ local_info_t *lp = link->priv;
+ struct net_device *dev = &lp->dev;
DEBUG(0, "event(%d)\n", (int)event);
@@ -1382,7 +1382,7 @@
xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
- local_info_t *lp;
+ local_info_t *lp = dev->priv;
ioaddr_t ioaddr;
u_char saved_page;
unsigned bytes_rcvd;
@@ -1401,7 +1401,6 @@
return;
}
dev->interrupt = 1;
- lp = dev->priv;
ioaddr = dev->base_addr;
if (lp->mohawk) { /* must disable the interrupt */
PutByte(XIRCREG_CR, 0);
@@ -1441,7 +1440,7 @@
/* too many bytes received during this int, drop the rest of the
* packets */
lp->stats.rx_dropped++;
- printk(KINF_XIRC "%s: RX drop, too much done\n", dev->name);
+ DEBUG(2, "%s: RX drop, too much done\n", dev->name);
PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */
} else if (rsr & PktRxOk) {
struct sk_buff *skb;
@@ -1782,8 +1781,6 @@
DEBUG(0, "do_config(%p)\n", dev);
if (map->port != 255 && map->port != dev->if_port) {
- if (local->new_mii)
- return -EOPNOTSUPP;
if (map->port > 4)
return -EINVAL;
if (!map->port) {
@@ -1813,14 +1810,11 @@
do_open(struct net_device *dev)
{
local_info_t *lp = dev->priv;
- dev_link_t *link;
+ dev_link_t *link = &lp->link;
DEBUG(0, "do_open(%p)\n", dev);
/* Check that the PCMCIA card is still here. */
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
/* Physical device present signature. */
if (!DEV_OK(link))
return -ENODEV;
@@ -1858,7 +1852,7 @@
data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
break;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16);
break;
@@ -2064,7 +2058,7 @@
local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff);
- if (local->new_mii || local->probe_port)
+ if (local->probe_port)
control = 0x1000; /* auto neg */
else if (dev->if_port == 4)
control = 0x2000; /* no auto neg, 100mbs mode */
@@ -2081,8 +2075,8 @@
return 0;
}
- if (local->new_mii || local->probe_port) {
- /* according to the DP83840A specs the auto negotation process
+ if (local->probe_port) {
+ /* according to the DP83840A specs the auto negotiation process
* may take up to 3.5 sec, so we use this also for our ML6692
* Fixme: Better to use a timer here!
*/
@@ -2094,7 +2088,7 @@
}
if (!(status & 0x0020)) {
- printk(KERN_INFO "%s: auto negotation failed;"
+ printk(KERN_INFO "%s: autonegotiation failed;"
" using 10mbs\n", dev->name);
if (!local->new_mii) {
control = 0x0000;
@@ -2112,7 +2106,6 @@
} else
dev->if_port = 1;
}
- local->probe_port = 0;
}
#ifdef PCMCIA_DEBUG
@@ -2140,13 +2133,11 @@
do_stop(struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
- dev_link_t *link;
+ local_info_t *lp = dev->priv;
+ dev_link_t *link = &lp->link;
DEBUG(0, "do_stop(%p)\n", dev);
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
if (!link)
return -ENODEV;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)