net: arcnet: remove ISA and PCMCIA support; modernize documentation

While ARCnet is still used in industrial environments, and cards are
still manufactured, it is unlikely anyone is still using it with ISA
and PCMCIA cards. Reduce future maintenance burden by removing all ISA
and PCMCIA ARCnet drivers and documentation related to them. Update
instructions for loading modules and passing parameters to work on
modern kernels and with the com20020_pci driver. Also take the
opportunity to document the rest of the module parameters, correct a
file path in Documentation/networking/arcnet.rst, and change a
reference to /etc/rc.inet1, which no longer exists, to refer to
ifconfig.

Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Link: https://patch.msgid.link/20260521001631.45434-4-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Ethan Nelson-Moore 2026-05-20 17:16:15 -07:00 committed by Jakub Kicinski
parent 5bc0c090bc
commit 910394c74c
12 changed files with 37 additions and 5240 deletions

View File

@ -558,9 +558,6 @@ Kernel parameters
1 -- enable.
Default value is set via kernel config option.
arcrimi= [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
Format: <io>,<irq>,<nodeID>
arm64.no32bit_el0 [ARM64] Unconditionally disable the execution of
32 bit applications.
@ -911,17 +908,6 @@ Kernel parameters
Sets the size of memory pool for coherent, atomic dma
allocations, by default set to 256K.
com20020= [HW,NET] ARCnet - COM20020 chipset
Format:
<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
com90io= [HW,NET] ARCnet - COM90xx chipset (IO-mapped buffers)
Format: <io>[,<irq>]
com90xx= [HW,NET]
ARCnet - COM90xx chipset (memory-mapped buffers)
Format: <io>[,<irq>[,<memstart>]]
condev= [HW,S390] console device
conmode=

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ ARCnet
.. note::
See also arcnet-hardware.txt in this directory for jumper-setting
See also arcnet-hardware.rst in this directory for jumper-setting
and cabling information if you're like many of us and didn't happen to get a
manual with your ARCnet card.
@ -88,157 +88,43 @@ versions are available on my WWW page, or via e-mail if you don't have WWW
access.
Installing the Driver
---------------------
All you will need to do in order to install the driver is::
Supported Hardware
------------------
make config
(be sure to choose ARCnet in the network devices
and at least one chipset driver.)
make clean
make zImage
Only PCI and PCI Express devices based on the COM20020 chipset are supported.
This is the newest chipset from SMC with support for promiscuous mode (packet
sniffing), extra diagnostic information, etc. These devices use the com20020_pci
driver.
If you obtained this ARCnet package as an upgrade to the ARCnet driver in
your current kernel, you will need to first copy arcnet.c over the one in
the linux/drivers/net directory.
Support for older chipsets and ISA and PCMCIA devices was previously available
but has been removed.
You will know the driver is installed properly if you get some ARCnet
messages when you reboot into the new Linux kernel.
There are four chipset options:
Configuring the Driver
----------------------
1. Standard ARCnet COM90xx chipset.
The COM20020 driver will be loaded automatically at boot if a supported card is
detected.
This is the normal ARCnet card, which you've probably got. This is the only
chipset driver which will autoprobe if not told where the card is.
It following options on the command line::
If the com20020_pci driver was compiled as a loadable module, the options are::
com90xx=[<io>[,<irq>[,<shmem>]]][,<name>] | <name>
node=<node_ID> backplane=<backplane> clockp=<CKP> clockm=<CKM>
timeout=<timeout> device=<interface_name>
If you load the chipset support as a module, the options are::
If the driver was compiled into the kernel, the same options can be specified on
the kernel command line by prefixing them with `com20020_pci.`, as in the
following example::
io=<io> irq=<irq> shmem=<shmem> device=<name>
To disable the autoprobe, just specify "com90xx=" on the kernel command line.
To specify the name alone, but allow autoprobe, just put "com90xx=<name>"
2. ARCnet COM20020 chipset.
This is the new chipset from SMC with support for promiscuous mode (packet
sniffing), extra diagnostic information, etc. Unfortunately, there is no
sensible method of autoprobing for these cards. You must specify the I/O
address on the kernel command line.
The command line options are::
com20020=<io>[,<irq>[,<node_ID>[,backplane[,CKP[,timeout]]]]][,name]
If you load the chipset support as a module, the options are::
io=<io> irq=<irq> node=<node_ID> backplane=<backplane> clock=<CKP>
timeout=<timeout> device=<name>
com20020_pci.device=eth1
The COM20020 chipset allows you to set the node ID in software, overriding the
default which is still set in DIP switches on the card. If you don't have the
COM20020 data sheets, and you don't know what the other three options refer
COM20020 data sheets, and you don't know what the other options refer
to, then they won't interest you - forget them.
3. ARCnet COM90xx chipset in IO-mapped mode.
This will also work with the normal ARCnet cards, but doesn't use the shared
memory. It performs less well than the above driver, but is provided in case
you have a card which doesn't support shared memory, or (strangely) in case
you have so many ARCnet cards in your machine that you run out of shmem slots.
If you don't give the IO address on the kernel command line, then the driver
will not find the card.
The command line options are::
com90io=<io>[,<irq>][,<name>]
If you load the chipset support as a module, the options are:
io=<io> irq=<irq> device=<name>
4. ARCnet RIM I cards.
These are COM90xx chips which are _completely_ memory mapped. The support for
these is not tested. If you have one, please mail the author with a success
report. All options must be specified, except the device name.
Command line options::
arcrimi=<shmem>,<irq>,<node_ID>[,<name>]
If you load the chipset support as a module, the options are::
shmem=<shmem> irq=<irq> node=<node_ID> device=<name>
Loadable Module Support
-----------------------
Configure and rebuild Linux. When asked, answer 'm' to "Generic ARCnet
support" and to support for your ARCnet chipset if you want to use the
loadable module. You can also say 'y' to "Generic ARCnet support" and 'm'
to the chipset support if you wish.
::
make config
make clean
make zImage
make modules
If you're using a loadable module, you need to use insmod to load it, and
you can specify various characteristics of your card on the command
line. (In recent versions of the driver, autoprobing is much more reliable
and works as a module, so most of this is now unnecessary.)
For example::
cd /usr/src/linux/modules
insmod arcnet.o
insmod com90xx.o
insmod com20020.o io=0x2e0 device=eth1
Using the Driver
----------------
If you build your kernel with ARCnet COM90xx support included, it should
probe for your card automatically when you boot. If you use a different
chipset driver complied into the kernel, you must give the necessary options
on the kernel command line, as detailed above.
Go read the NET-2-HOWTO and ETHERNET-HOWTO for Linux; they should be
available where you picked up this driver. Think of your ARCnet as a
souped-up (or down, as the case may be) Ethernet card.
By the way, be sure to change all references from "eth0" to "arc0" in the
HOWTOs. Remember that ARCnet isn't a "true" Ethernet, and the device name
is DIFFERENT.
Multiple Cards in One Computer
------------------------------
Linux has pretty good support for this now, but since I've been busy, the
ARCnet driver has somewhat suffered in this respect. COM90xx support, if
compiled into the kernel, will (try to) autodetect all the installed cards.
If you have other cards, with support compiled into the kernel, then you can
just repeat the options on the kernel command line, e.g.::
LILO: linux com20020=0x2e0 com20020=0x380 com90io=0x260
If you have the chipset support built as a loadable module, then you need to
do something like this::
insmod -o arc0 com90xx
insmod -o arc1 com20020 io=0x2e0
insmod -o arc2 com90xx
The ARCnet drivers will now sort out their names automatically.
Otherwise, ARCnet can be configured in a similar way to Ethernet, with the
exception that ARCnet interface names begin with `arc`.
How do I get it to work with...?
@ -524,10 +410,6 @@ first! D_DURING displays 4-5 lines for each packet sent or received. D_TX,
D_RX, and D_SKB actually DISPLAY each packet as it is sent or received,
which is obviously quite big.
Starting with v2.40 ALPHA, the autoprobe routines have changed
significantly. In particular, they won't tell you why the card was not
found unless you turn on the D_INIT_REASONS debugging flag.
Once the driver is running, you can run the arcdump shell script (available
from me or in the full ARCnet package, if you have it) as root to list the
contents of the arcnet buffers at any time. To make any sense at all out of
@ -548,7 +430,7 @@ out which bytes are being used by a packet.
You can change the debug level without recompiling the kernel by typing::
ifconfig arc0 down metric 1xxx
/etc/rc.d/rc.inet1
ifconfig arc0 up
where "xxx" is the debug level you want. For example, "metric 1015" would put
you at debug level 15. Debug level 7 is currently the default.

View File

@ -221,12 +221,8 @@ CONFIG_ARCNET_1201=m
CONFIG_ARCNET_1051=m
CONFIG_ARCNET_RAW=m
CONFIG_ARCNET_CAP=m
CONFIG_ARCNET_COM90xx=m
CONFIG_ARCNET_COM90xxIO=m
CONFIG_ARCNET_RIM_I=m
CONFIG_ARCNET_COM20020=m
CONFIG_ARCNET_COM20020_PCI=m
CONFIG_ARCNET_COM20020_CS=m
CONFIG_VORTEX=m
CONFIG_TYPHOON=m
CONFIG_ADAPTEC_STARFIRE=m

View File

@ -4,7 +4,7 @@
#
menuconfig ARCNET
depends on NETDEVICES && (ISA || PCI || PCMCIA) && HAS_IOPORT
depends on NETDEVICES && PCI && HAS_IOPORT
tristate "ARCnet support"
help
If you have a network card of this type, say Y and check out the
@ -12,9 +12,7 @@ menuconfig ARCNET
<file:Documentation/networking/arcnet.rst>.
You need both this driver, and the driver for the particular ARCnet
chipset of your card. If you don't know, then it's probably a
COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset
support" below.
chipset of your card.
To compile this driver as a module, choose M here. The module will
be called arcnet.
@ -70,38 +68,6 @@ config ARCNET_CAP
Cap only listens to protocol 1-8.
config ARCNET_COM90xx
tristate "ARCnet COM90xx (normal) chipset driver"
help
This is the chipset driver for the standard COM90xx cards. If you
have always used the old ARCnet driver without knowing what type of
card you had, this is probably the one for you.
To compile this driver as a module, choose M here. The module will
be called com90xx.
config ARCNET_COM90xxIO
tristate "ARCnet COM90xx (IO mapped) chipset driver"
help
This is the chipset driver for the COM90xx cards, using them in
IO-mapped mode instead of memory-mapped mode. This is slower than
the normal driver. Only use it if your card doesn't support shared
memory.
To compile this driver as a module, choose M here. The module will
be called com90io.
config ARCNET_RIM_I
tristate "ARCnet COM90xx (RIM I) chipset driver"
help
This is yet another chipset driver for the COM90xx cards, but this
time only using memory-mapped mode, and no IO ports at all. This
driver is completely untested, so if you have one of these cards,
please mail <dwmw2@infradead.org>, especially if it works!
To compile this driver as a module, choose M here. The module will
be called arc-rimi.
config ARCNET_COM20020
tristate "ARCnet COM20020 chipset driver"
depends on LEDS_CLASS
@ -113,22 +79,8 @@ config ARCNET_COM20020
To compile this driver as a module, choose M here. The module will
be called com20020.
config ARCNET_COM20020_ISA
tristate "Support for COM20020 on ISA"
depends on ARCNET_COM20020 && ISA
config ARCNET_COM20020_PCI
tristate "Support for COM20020 on PCI"
depends on ARCNET_COM20020 && PCI
config ARCNET_COM20020_CS
tristate "COM20020 ARCnet PCMCIA support"
depends on ARCNET_COM20020 && PCMCIA
help
Say Y here if you intend to attach this type of ARCnet PCMCIA card
to your computer.
To compile this driver as a module, choose M here: the module will be
called com20020_cs. If unsure, say N.
endif # ARCNET

View File

@ -7,10 +7,5 @@ obj-$(CONFIG_ARCNET_1201) += rfc1201.o
obj-$(CONFIG_ARCNET_1051) += rfc1051.o
obj-$(CONFIG_ARCNET_RAW) += arc-rawmode.o
obj-$(CONFIG_ARCNET_CAP) += capmode.o
obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o
obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o
obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
obj-$(CONFIG_ARCNET_COM20020) += com20020.o
obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o

View File

@ -1,386 +0,0 @@
/*
* Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
*
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
* for sponsoring the further development of this driver.
*
* **********************
*
* The original copyright of skeleton.c was as follows:
*
* skeleton.c Written 1993 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
*
* **********************
*
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/memblock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include "arcdevice.h"
#include "com9026.h"
/* Internal function declarations */
static int arcrimi_probe(struct net_device *dev);
static int arcrimi_found(struct net_device *dev);
static void arcrimi_command(struct net_device *dev, int command);
static int arcrimi_status(struct net_device *dev);
static void arcrimi_setmask(struct net_device *dev, int mask);
static int arcrimi_reset(struct net_device *dev, int really_reset);
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count);
/* Handy defines for ARCnet specific stuff */
/* Amount of I/O memory used by the card */
#define BUFFER_SIZE (512)
#define MIRROR_SIZE (BUFFER_SIZE * 4)
/* We cannot probe for a RIM I card; one reason is I don't know how to reset
* them. In fact, we can't even get their node ID automatically. So, we
* need to be passed a specific shmem address, IRQ, and node ID.
*/
static int __init arcrimi_probe(struct net_device *dev)
{
if (BUGLVL(D_NORMAL)) {
pr_info("%s\n", "RIM I (entirely mem-mapped) support");
pr_info("E-mail me if you actually test the RIM I driver, please!\n");
pr_info("Given: node %02Xh, shmem %lXh, irq %d\n",
dev->dev_addr[0], dev->mem_start, dev->irq);
}
if (dev->mem_start <= 0 || dev->irq <= 0) {
if (BUGLVL(D_NORMAL))
pr_err("No autoprobe for RIM I; you must specify the shmem and irq!\n");
return -ENODEV;
}
if (dev->dev_addr[0] == 0) {
if (BUGLVL(D_NORMAL))
pr_err("You need to specify your card's station ID!\n");
return -ENODEV;
}
/* Grab the memory region at mem_start for MIRROR_SIZE bytes.
* Later in arcrimi_found() the real size will be determined
* and this reserve will be released and the correct size
* will be taken.
*/
if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
if (BUGLVL(D_NORMAL))
pr_notice("Card memory already allocated\n");
return -ENODEV;
}
return arcrimi_found(dev);
}
static int check_mirror(unsigned long addr, size_t size)
{
void __iomem *p;
int res = -1;
if (!request_mem_region(addr, size, "arcnet (90xx)"))
return -1;
p = ioremap(addr, size);
if (p) {
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
res = 1;
else
res = 0;
iounmap(p);
}
release_mem_region(addr, size);
return res;
}
/* Set up the struct net_device associated with this card.
* Called after probing succeeds.
*/
static int __init arcrimi_found(struct net_device *dev)
{
struct arcnet_local *lp;
unsigned long first_mirror, last_mirror, shmem;
void __iomem *p;
int mirror_size;
int err;
p = ioremap(dev->mem_start, MIRROR_SIZE);
if (!p) {
release_mem_region(dev->mem_start, MIRROR_SIZE);
arc_printk(D_NORMAL, dev, "Can't ioremap\n");
return -ENODEV;
}
/* reserve the irq */
if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
iounmap(p);
release_mem_region(dev->mem_start, MIRROR_SIZE);
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
shmem = dev->mem_start;
arcnet_writeb(TESTvalue, p, COM9026_REG_W_INTMASK);
arcnet_writeb(TESTvalue, p, COM9026_REG_W_COMMAND);
/* actually the station/node ID */
/* find the real shared memory start/end points, including mirrors */
/* guess the actual size of one "memory mirror" - the number of
* bytes between copies of the shared memory. On most cards, it's
* 2k (or there are no mirrors at all) but on some, it's 4k.
*/
mirror_size = MIRROR_SIZE;
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue &&
check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size = 2 * MIRROR_SIZE;
first_mirror = shmem - mirror_size;
while (check_mirror(first_mirror, mirror_size) == 1)
first_mirror -= mirror_size;
first_mirror += mirror_size;
last_mirror = shmem + mirror_size;
while (check_mirror(last_mirror, mirror_size) == 1)
last_mirror += mirror_size;
last_mirror -= mirror_size;
dev->mem_start = first_mirror;
dev->mem_end = last_mirror + MIRROR_SIZE - 1;
/* initialize the rest of the device structure. */
lp = netdev_priv(dev);
lp->card_name = "RIM I";
lp->hw.command = arcrimi_command;
lp->hw.status = arcrimi_status;
lp->hw.intmask = arcrimi_setmask;
lp->hw.reset = arcrimi_reset;
lp->hw.owner = THIS_MODULE;
lp->hw.copy_to_card = arcrimi_copy_to_card;
lp->hw.copy_from_card = arcrimi_copy_from_card;
/* re-reserve the memory region - arcrimi_probe() allocated this reqion
* but didn't know the real size. Free that region and then re-get
* with the correct size. There is a VERY slim chance this could
* fail.
*/
iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
if (!request_mem_region(dev->mem_start,
dev->mem_end - dev->mem_start + 1,
"arcnet (90xx)")) {
arc_printk(D_NORMAL, dev, "Card memory already allocated\n");
goto err_free_irq;
}
lp->mem_start = ioremap(dev->mem_start,
dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
arc_printk(D_NORMAL, dev, "Can't remap device memory!\n");
goto err_release_mem;
}
/* get and check the station ID from offset 1 in shmem */
arcnet_set_addr(dev, arcnet_readb(lp->mem_start,
COM9026_REG_R_STATION));
arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n",
dev->dev_addr[0],
dev->irq, dev->mem_start,
(dev->mem_end - dev->mem_start + 1) / mirror_size,
mirror_size);
err = register_netdev(dev);
if (err)
goto err_unmap;
return 0;
err_unmap:
iounmap(lp->mem_start);
err_release_mem:
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
err_free_irq:
free_irq(dev->irq, dev);
return -EIO;
}
/* Do a hardware reset on the card, and set up necessary registers.
*
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
*
* However, it does make sure the card is in a defined state.
*/
static int arcrimi_reset(struct net_device *dev, int really_reset)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
dev->name, arcnet_readb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
arcnet_writeb(TESTvalue, ioaddr, -0x800); /* fake reset */
return 0;
}
/* clear flags & end reset */
arcnet_writeb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
arcnet_writeb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
/* enable extended (512-byte) packets */
arcnet_writeb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* done! return success. */
return 0;
}
static void arcrimi_setmask(struct net_device *dev, int mask)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
arcnet_writeb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
static int arcrimi_status(struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
return arcnet_readb(ioaddr, COM9026_REG_R_STATUS);
}
static void arcrimi_command(struct net_device *dev, int cmd)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
arcnet_writeb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
static int node;
static int io; /* use the insmod io= irq= node= options */
static int irq;
static char device[9]; /* use eg. device=arc1 to change name */
module_param(node, int, 0);
module_param(io, int, 0);
module_param(irq, int, 0);
module_param_string(device, device, sizeof(device), 0);
MODULE_DESCRIPTION("ARCnet COM90xx RIM I chipset driver");
MODULE_LICENSE("GPL");
static struct net_device *my_dev;
static int __init arc_rimi_init(void)
{
struct net_device *dev;
dev = alloc_arcdev(device);
if (!dev)
return -ENOMEM;
if (node && node != 0xff)
arcnet_set_addr(dev, node);
dev->mem_start = io;
dev->irq = irq;
if (dev->irq == 2)
dev->irq = 9;
if (arcrimi_probe(dev)) {
free_arcdev(dev);
return -EIO;
}
my_dev = dev;
return 0;
}
static void __exit arc_rimi_exit(void)
{
struct net_device *dev = my_dev;
struct arcnet_local *lp = netdev_priv(dev);
unregister_netdev(dev);
iounmap(lp->mem_start);
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
free_irq(dev->irq, dev);
free_arcdev(dev);
}
#ifndef MODULE
static int __init arcrimi_setup(char *s)
{
int ints[8];
s = get_options(s, 8, ints);
if (!ints[0])
return 1;
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
fallthrough;
case 3: /* Node ID */
node = ints[3];
fallthrough;
case 2: /* IRQ */
irq = ints[2];
fallthrough;
case 1: /* IO address */
io = ints[1];
}
if (*s)
snprintf(device, sizeof(device), "%s", s);
return 1;
}
__setup("arcrimi=", arcrimi_setup);
#endif /* MODULE */
module_init(arc_rimi_init)
module_exit(arc_rimi_exit)

View File

@ -1,230 +0,0 @@
/*
* Linux ARCnet driver - COM20020 chipset support
*
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
* for sponsoring the further development of this driver.
*
* **********************
*
* The original copyright of skeleton.c was as follows:
*
* skeleton.c Written 1993 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
*
* **********************
*
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/memblock.h>
#include <linux/io.h>
#include "arcdevice.h"
#include "com20020.h"
/* We cannot (yet) probe for an IO mapped card, although we can check that
* it's where we were told it was, and even do autoirq.
*/
static int __init com20020isa_probe(struct net_device *dev)
{
int ioaddr;
unsigned long airqmask;
struct arcnet_local *lp = netdev_priv(dev);
int err;
if (BUGLVL(D_NORMAL))
pr_info("%s\n", "COM20020 ISA support (by David Woodhouse et al.)");
ioaddr = dev->base_addr;
if (!ioaddr) {
arc_printk(D_NORMAL, dev, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n");
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr);
err = -ENODEV;
goto out;
}
if (com20020_check(dev)) {
err = -ENODEV;
goto out;
}
if (!dev->irq) {
/* if we do this, we're sure to get an IRQ since the
* card has just reset and the NORXflag is on until
* we tell it to start receiving.
*/
arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n",
arcnet_inb(ioaddr, COM20020_REG_R_STATUS));
arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
airqmask = probe_irq_on();
arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
udelay(1);
arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n");
airqmask = probe_irq_on();
arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
udelay(5);
arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n");
err = -ENODEV;
goto out;
}
}
}
lp->card_name = "ISA COM20020";
err = com20020_found(dev, 0);
if (err != 0)
goto out;
return 0;
out:
release_region(ioaddr, ARCNET_TOTAL_SIZE);
return err;
}
static int node = 0;
static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
static int irq = 0; /* or use the insmod io= irq= shmem= options */
static char device[9]; /* use eg. device="arc1" to change name */
static int timeout = 3;
static int backplane = 0;
static int clockp = 0;
static int clockm = 0;
module_param(node, int, 0);
module_param_hw(io, int, ioport, 0);
module_param_hw(irq, int, irq, 0);
module_param_string(device, device, sizeof(device), 0);
module_param(timeout, int, 0);
module_param(backplane, int, 0);
module_param(clockp, int, 0);
module_param(clockm, int, 0);
MODULE_DESCRIPTION("ARCnet COM20020 chipset ISA driver");
MODULE_LICENSE("GPL");
static struct net_device *my_dev;
static int __init com20020_init(void)
{
struct net_device *dev;
struct arcnet_local *lp;
dev = alloc_arcdev(device);
if (!dev)
return -ENOMEM;
if (node && node != 0xff)
arcnet_set_addr(dev, node);
dev->netdev_ops = &com20020_netdev_ops;
lp = netdev_priv(dev);
lp->backplane = backplane;
lp->clockp = clockp & 7;
lp->clockm = clockm & 3;
lp->timeout = timeout & 3;
lp->hw.owner = THIS_MODULE;
dev->base_addr = io;
dev->irq = irq;
if (dev->irq == 2)
dev->irq = 9;
if (com20020isa_probe(dev)) {
free_arcdev(dev);
return -EIO;
}
my_dev = dev;
return 0;
}
static void __exit com20020_exit(void)
{
unregister_netdev(my_dev);
free_irq(my_dev->irq, my_dev);
release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
free_arcdev(my_dev);
}
#ifndef MODULE
static int __init com20020isa_setup(char *s)
{
int ints[8];
s = get_options(s, 8, ints);
if (!ints[0])
return 1;
switch (ints[0]) {
default: /* ERROR */
pr_info("Too many arguments\n");
fallthrough;
case 6: /* Timeout */
timeout = ints[6];
fallthrough;
case 5: /* CKP value */
clockp = ints[5];
fallthrough;
case 4: /* Backplane flag */
backplane = ints[4];
fallthrough;
case 3: /* Node ID */
node = ints[3];
fallthrough;
case 2: /* IRQ */
irq = ints[2];
fallthrough;
case 1: /* IO address */
io = ints[1];
}
if (*s)
snprintf(device, sizeof(device), "%s", s);
return 1;
}
__setup("com20020=", com20020isa_setup);
#endif /* MODULE */
module_init(com20020_init)
module_exit(com20020_exit)

View File

@ -385,9 +385,7 @@ static void com20020_set_rx_mode(struct net_device *dev)
}
}
#if defined(CONFIG_ARCNET_COM20020_PCI_MODULE) || \
defined(CONFIG_ARCNET_COM20020_ISA_MODULE) || \
defined(CONFIG_ARCNET_COM20020_CS_MODULE)
#ifdef CONFIG_ARCNET_COM20020_PCI_MODULE
EXPORT_SYMBOL(com20020_check);
EXPORT_SYMBOL(com20020_found);
EXPORT_SYMBOL(com20020_netdev_ops);

View File

@ -1,330 +0,0 @@
/*
* Linux ARCnet driver - COM20020 PCMCIA support
*
* Written 1994-1999 by Avery Pennarun,
* based on an ISA version by David Woodhouse.
* Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
* which was derived from pcnet_cs.c by David Hinds.
* Some additional portions derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
* for sponsoring the further development of this driver.
*
* **********************
*
* The original copyright of skeleton.c was as follows:
*
* skeleton.c Written 1993 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
*
* **********************
* Changes:
* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
* - reorganize kmallocs in com20020_attach, checking all for failure
* and releasing the previous allocations if one fails
* **********************
*
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/io.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "arcdevice.h"
#include "com20020.h"
static void regdump(struct net_device *dev)
{
#ifdef DEBUG
int ioaddr = dev->base_addr;
int count;
netdev_dbg(dev, "register dump:\n");
for (count = 0; count < 16; count++) {
if (!(count % 16))
pr_cont("%04X:", ioaddr + count);
pr_cont(" %02X", arcnet_inb(ioaddr, count));
}
pr_cont("\n");
netdev_dbg(dev, "buffer0 dump:\n");
/* set up the address register */
count = 0;
arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag,
ioaddr, COM20020_REG_W_ADDR_HI);
arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
for (count = 0; count < 256 + 32; count++) {
if (!(count % 16))
pr_cont("%04X:", count);
/* copy the data */
pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA));
}
pr_cont("\n");
#endif
}
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
static int node;
static int timeout = 3;
static int backplane;
static int clockp;
static int clockm;
module_param(node, int, 0);
module_param(timeout, int, 0);
module_param(backplane, int, 0);
module_param(clockp, int, 0);
module_param(clockm, int, 0);
MODULE_DESCRIPTION("ARCnet COM20020 chipset PCMCIA driver");
MODULE_LICENSE("GPL");
/*====================================================================*/
static int com20020_config(struct pcmcia_device *link);
static void com20020_release(struct pcmcia_device *link);
static void com20020_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
static int com20020_probe(struct pcmcia_device *p_dev)
{
struct com20020_dev *info;
struct net_device *dev;
struct arcnet_local *lp;
int ret = -ENOMEM;
dev_dbg(&p_dev->dev, "com20020_attach()\n");
/* Create new network device */
info = kzalloc_obj(*info);
if (!info)
goto fail_alloc_info;
dev = alloc_arcdev("");
if (!dev)
goto fail_alloc_dev;
lp = netdev_priv(dev);
lp->timeout = timeout;
lp->backplane = backplane;
lp->clockp = clockp;
lp->clockm = clockm & 3;
lp->hw.owner = THIS_MODULE;
/* fill in our module parameters as defaults */
arcnet_set_addr(dev, node);
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 16;
p_dev->config_flags |= CONF_ENABLE_IRQ;
info->dev = dev;
p_dev->priv = info;
ret = com20020_config(p_dev);
if (ret)
goto fail_config;
return 0;
fail_config:
free_arcdev(dev);
fail_alloc_dev:
kfree(info);
fail_alloc_info:
return ret;
} /* com20020_attach */
static void com20020_detach(struct pcmcia_device *link)
{
struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
dev_dbg(&link->dev, "detach...\n");
dev_dbg(&link->dev, "com20020_detach\n");
dev_dbg(&link->dev, "unregister...\n");
unregister_netdev(dev);
/* this is necessary because we register our IRQ separately
* from card services.
*/
if (dev->irq)
free_irq(dev->irq, dev);
com20020_release(link);
/* Unlink device structure, free bits */
dev_dbg(&link->dev, "unlinking...\n");
if (link->priv) {
dev = info->dev;
if (dev) {
dev_dbg(&link->dev, "kfree...\n");
free_arcdev(dev);
}
dev_dbg(&link->dev, "kfree2...\n");
kfree(info);
}
} /* com20020_detach */
static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
struct com20020_dev *info;
struct net_device *dev;
int i, ret;
int ioaddr;
info = link->priv;
dev = info->dev;
dev_dbg(&link->dev, "config...\n");
dev_dbg(&link->dev, "com20020_config\n");
dev_dbg(&link->dev, "baseport1 is %Xh\n",
(unsigned int)link->resource[0]->start);
i = -ENODEV;
link->io_lines = 16;
if (!link->resource[0]->start) {
for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) {
link->resource[0]->start = ioaddr;
i = pcmcia_request_io(link);
if (i == 0)
break;
}
} else {
i = pcmcia_request_io(link);
}
if (i != 0) {
dev_dbg(&link->dev, "requestIO failed totally!\n");
goto failed;
}
ioaddr = dev->base_addr = link->resource[0]->start;
dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
dev_dbg(&link->dev, "request IRQ %d\n",
link->irq);
if (!link->irq) {
dev_dbg(&link->dev, "requestIRQ failed totally!\n");
goto failed;
}
dev->irq = link->irq;
ret = pcmcia_enable_device(link);
if (ret)
goto failed;
if (com20020_check(dev)) {
regdump(dev);
goto failed;
}
lp = netdev_priv(dev);
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
SET_NETDEV_DEV(dev, &link->dev);
i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
dev_notice(&link->dev,
"com20020_found() failed\n");
goto failed;
}
netdev_dbg(dev, "port %#3lx, irq %d\n",
dev->base_addr, dev->irq);
return 0;
failed:
dev_dbg(&link->dev, "com20020_config failed...\n");
com20020_release(link);
return -ENODEV;
} /* com20020_config */
static void com20020_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "com20020_release\n");
pcmcia_disable_device(link);
}
static int com20020_suspend(struct pcmcia_device *link)
{
struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
if (link->open)
netif_device_detach(dev);
return 0;
}
static int com20020_resume(struct pcmcia_device *link)
{
struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
if (link->open) {
int ioaddr = dev->base_addr;
struct arcnet_local *lp = netdev_priv(dev);
arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
udelay(5);
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
}
return 0;
}
static const struct pcmcia_device_id com20020_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
PCMCIA_DEVICE_PROD_ID12("SoHard AG",
"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
static struct pcmcia_driver com20020_cs_driver = {
.owner = THIS_MODULE,
.name = "com20020_cs",
.probe = com20020_probe,
.remove = com20020_detach,
.id_table = com20020_ids,
.suspend = com20020_suspend,
.resume = com20020_resume,
};
module_pcmcia_driver(com20020_cs_driver);

View File

@ -1,427 +0,0 @@
/*
* Linux ARCnet driver - COM90xx chipset (IO-mapped buffers)
*
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
* for sponsoring the further development of this driver.
*
* **********************
*
* The original copyright of skeleton.c was as follows:
*
* skeleton.c Written 1993 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
*
* **********************
*
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/memblock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include "arcdevice.h"
#include "com9026.h"
/* Internal function declarations */
static int com90io_found(struct net_device *dev);
static void com90io_command(struct net_device *dev, int command);
static int com90io_status(struct net_device *dev);
static void com90io_setmask(struct net_device *dev, int mask);
static int com90io_reset(struct net_device *dev, int really_reset);
static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
static void com90io_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count);
/* Handy defines for ARCnet specific stuff */
/* The number of low I/O ports used by the card. */
#define ARCNET_TOTAL_SIZE 16
/****************************************************************************
* *
* IO-mapped operation routines *
* *
****************************************************************************/
#undef ONE_AT_A_TIME_TX
#undef ONE_AT_A_TIME_RX
static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
{
int ioaddr = dev->base_addr;
arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
}
#ifdef ONE_AT_A_TIME_TX
static void put_buffer_byte(struct net_device *dev, unsigned offset,
u_char datum)
{
int ioaddr = dev->base_addr;
arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA);
}
#endif
static void get_whole_buffer(struct net_device *dev, unsigned offset,
unsigned length, char *dest)
{
int ioaddr = dev->base_addr;
arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
while (length--)
#ifdef ONE_AT_A_TIME_RX
*(dest++) = get_buffer_byte(dev, offset++);
#else
*(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
#endif
}
static void put_whole_buffer(struct net_device *dev, unsigned offset,
unsigned length, char *dest)
{
int ioaddr = dev->base_addr;
arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO);
while (length--)
#ifdef ONE_AT_A_TIME_TX
put_buffer_byte(dev, offset++, *(dest++));
#else
arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA);
#endif
}
/* We cannot probe for an IO mapped card either, although we can check that
* it's where we were told it was, and even autoirq
*/
static int __init com90io_probe(struct net_device *dev)
{
int ioaddr = dev->base_addr, status;
unsigned long airqmask;
if (BUGLVL(D_NORMAL)) {
pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)");
pr_info("E-mail me if you actually test this driver, please!\n");
}
if (!ioaddr) {
arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n");
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n",
ioaddr);
goto err_out;
}
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n",
status);
goto err_out;
}
arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status);
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
ioaddr, COM9026_REG_W_COMMAND);
arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n",
status);
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if (status & RESETflag) {
arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n",
status);
goto err_out;
}
arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag,
ioaddr, COM9026_REG_RW_CONFIG);
/* Read first loc'n of memory */
arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
arcnet_outb(0, ioaddr, COM9026_REG_W_ADDR_LO);
status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
if (status != 0xd1) {
arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n",
status);
goto err_out;
}
if (!dev->irq) {
/* if we do this, we're sure to get an IRQ since the
* card has just reset and the NORXflag is on until
* we tell it to start receiving.
*/
airqmask = probe_irq_on();
arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
udelay(1);
arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
dev->irq = probe_irq_off(airqmask);
if ((int)dev->irq <= 0) {
arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n");
goto err_out;
}
}
release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */
return com90io_found(dev);
err_out:
release_region(ioaddr, ARCNET_TOTAL_SIZE);
return -ENODEV;
}
/* Set up the struct net_device associated with this card. Called after
* probing succeeds.
*/
static int __init com90io_found(struct net_device *dev)
{
struct arcnet_local *lp;
int ioaddr = dev->base_addr;
int err;
/* Reserve the irq */
if (request_irq(dev->irq, arcnet_interrupt, 0,
"arcnet (COM90xx-IO)", dev)) {
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
/* Reserve the I/O region */
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE,
"arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
}
lp = netdev_priv(dev);
lp->card_name = "COM90xx I/O";
lp->hw.command = com90io_command;
lp->hw.status = com90io_status;
lp->hw.intmask = com90io_setmask;
lp->hw.reset = com90io_reset;
lp->hw.owner = THIS_MODULE;
lp->hw.copy_to_card = com90io_copy_to_card;
lp->hw.copy_from_card = com90io_copy_from_card;
lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
/* get and check the station ID from offset 1 in shmem */
arcnet_set_addr(dev, get_buffer_byte(dev, 1));
err = register_netdev(dev);
if (err) {
arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
ioaddr, COM9026_REG_RW_CONFIG);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
return err;
}
arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
dev->dev_addr[0], dev->base_addr, dev->irq);
return 0;
}
/* Do a hardware reset on the card, and set up necessary registers.
*
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
*
* However, it does make sure the card is in a defined state.
*/
static int com90io_reset(struct net_device *dev, int really_reset)
{
struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
/* reset the card */
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
}
/* Set the thing to IO-mapped, 8-bit mode */
lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
/* clear flags & end reset */
arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
/* verify that the ARCnet signature byte is present */
if (get_buffer_byte(dev, 0) != TESTvalue) {
arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* done! return success. */
return 0;
}
static void com90io_command(struct net_device *dev, int cmd)
{
short ioaddr = dev->base_addr;
arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
static int com90io_status(struct net_device *dev)
{
short ioaddr = dev->base_addr;
return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
}
static void com90io_setmask(struct net_device *dev, int mask)
{
short ioaddr = dev->base_addr;
arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
static void com90io_copy_to_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
TIME(dev, "put_whole_buffer", count,
put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
}
static void com90io_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
TIME(dev, "get_whole_buffer", count,
get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
}
static int io; /* use the insmod io= irq= shmem= options */
static int irq;
static char device[9]; /* use eg. device=arc1 to change name */
module_param_hw(io, int, ioport, 0);
module_param_hw(irq, int, irq, 0);
module_param_string(device, device, sizeof(device), 0);
MODULE_DESCRIPTION("ARCnet COM90xx IO mapped chipset driver");
MODULE_LICENSE("GPL");
#ifndef MODULE
static int __init com90io_setup(char *s)
{
int ints[4];
s = get_options(s, 4, ints);
if (!ints[0])
return 0;
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
fallthrough;
case 2: /* IRQ */
irq = ints[2];
fallthrough;
case 1: /* IO address */
io = ints[1];
}
if (*s)
snprintf(device, sizeof(device), "%s", s);
return 1;
}
__setup("com90io=", com90io_setup);
#endif
static struct net_device *my_dev;
static int __init com90io_init(void)
{
struct net_device *dev;
int err;
dev = alloc_arcdev(device);
if (!dev)
return -ENOMEM;
dev->base_addr = io;
dev->irq = irq;
if (dev->irq == 2)
dev->irq = 9;
err = com90io_probe(dev);
if (err) {
free_arcdev(dev);
return err;
}
my_dev = dev;
return 0;
}
static void __exit com90io_exit(void)
{
struct net_device *dev = my_dev;
int ioaddr = dev->base_addr;
unregister_netdev(dev);
/* In case the old driver is loaded later,
* set the thing back to MMAP mode
*/
arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
ioaddr, COM9026_REG_RW_CONFIG);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
free_arcdev(dev);
}
module_init(com90io_init)
module_exit(com90io_exit)

View File

@ -1,716 +0,0 @@
/*
* Linux ARCnet driver - COM90xx chipset (memory-mapped buffers)
*
* Written 1994-1999 by Avery Pennarun.
* Written 1999 by Martin Mares <mj@ucw.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
* for sponsoring the further development of this driver.
*
* **********************
*
* The original copyright of skeleton.c was as follows:
*
* skeleton.c Written 1993 by Donald Becker.
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency. This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC, incorporated herein by reference.
*
* **********************
*
* For more details, see drivers/net/arcnet.c
*
* **********************
*/
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/io.h>
#include "arcdevice.h"
#include "com9026.h"
/* Define this to speed up the autoprobe by assuming if only one io port and
* shmem are left in the list at Stage 5, they must correspond to each
* other.
*
* This is undefined by default because it might not always be true, and the
* extra check makes the autoprobe even more careful. Speed demons can turn
* it on - I think it should be fine if you only have one ARCnet card
* installed.
*
* If no ARCnet cards are installed, this delay never happens anyway and thus
* the option has no effect.
*/
#undef FAST_PROBE
/* Internal function declarations */
static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *);
static void com90xx_command(struct net_device *dev, int command);
static int com90xx_status(struct net_device *dev);
static void com90xx_setmask(struct net_device *dev, int mask);
static int com90xx_reset(struct net_device *dev, int really_reset);
static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count);
static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count);
/* Known ARCnet cards */
static struct net_device *cards[16];
static int numcards;
/* Handy defines for ARCnet specific stuff */
/* The number of low I/O ports used by the card */
#define ARCNET_TOTAL_SIZE 16
/* Amount of I/O memory used by the card */
#define BUFFER_SIZE (512)
#define MIRROR_SIZE (BUFFER_SIZE * 4)
static int com90xx_skip_probe __initdata = 0;
/* Module parameters */
static int io; /* use the insmod io= irq= shmem= options */
static int irq;
static int shmem;
static char device[9]; /* use eg. device=arc1 to change name */
module_param_hw(io, int, ioport, 0);
module_param_hw(irq, int, irq, 0);
module_param(shmem, int, 0);
module_param_string(device, device, sizeof(device), 0);
static void __init com90xx_probe(void)
{
int count, status, ioaddr, numprint, airq, openparen = 0;
unsigned long airqmask;
int ports[(0x3f0 - 0x200) / 16 + 1] = { 0 };
unsigned long *shmems;
void __iomem **iomem;
int numports, numshmems, *port;
u_long *p;
int index;
if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
return;
shmems = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long),
GFP_KERNEL);
if (!shmems)
return;
iomem = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *),
GFP_KERNEL);
if (!iomem) {
kfree(shmems);
return;
}
if (BUGLVL(D_NORMAL))
pr_info("%s\n", "COM90xx chipset support");
/* set up the arrays where we'll store the possible probe addresses */
numports = numshmems = 0;
if (io)
ports[numports++] = io;
else
for (count = 0x200; count <= 0x3f0; count += 16)
ports[numports++] = count;
if (shmem)
shmems[numshmems++] = shmem;
else
for (count = 0xA0000; count <= 0xFF800; count += 2048)
shmems[numshmems++] = count;
/* Stage 1: abandon any reserved ports, or ones with status==0xFF
* (empty), and reset any others by reading the reset port.
*/
numprint = -1;
for (port = &ports[0]; port - ports < numports; port++) {
numprint++;
numprint %= 8;
if (!numprint) {
arc_cont(D_INIT, "\n");
arc_cont(D_INIT, "S1: ");
}
arc_cont(D_INIT, "%Xh ", *port);
ioaddr = *port;
if (!request_region(*port, ARCNET_TOTAL_SIZE,
"arcnet (90xx)")) {
arc_cont(D_INIT_REASONS, "(request_region)\n");
arc_cont(D_INIT_REASONS, "S1: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
*port-- = ports[--numports];
continue;
}
if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
arc_cont(D_INIT_REASONS, "(empty)\n");
arc_cont(D_INIT_REASONS, "S1: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
/* begin resetting card */
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
arc_cont(D_INIT_REASONS, "\n");
arc_cont(D_INIT_REASONS, "S1: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
}
arc_cont(D_INIT, "\n");
if (!numports) {
arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n");
kfree(shmems);
kfree(iomem);
return;
}
/* Stage 2: we have now reset any possible ARCnet cards, so we can't
* do anything until they finish. If D_INIT, print the list of
* cards that are left.
*/
numprint = -1;
for (port = &ports[0]; port < ports + numports; port++) {
numprint++;
numprint %= 8;
if (!numprint) {
arc_cont(D_INIT, "\n");
arc_cont(D_INIT, "S2: ");
}
arc_cont(D_INIT, "%Xh ", *port);
}
arc_cont(D_INIT, "\n");
mdelay(RESETtime);
/* Stage 3: abandon any shmem addresses that don't have the signature
* 0xD1 byte in the right place, or are read-only.
*/
numprint = -1;
for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) {
void __iomem *base;
numprint++;
numprint %= 8;
if (!numprint) {
arc_cont(D_INIT, "\n");
arc_cont(D_INIT, "S3: ");
}
arc_cont(D_INIT, "%lXh ", *p);
if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) {
arc_cont(D_INIT_REASONS, "(request_mem_region)\n");
arc_cont(D_INIT_REASONS, "Stage 3: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
goto out;
}
base = ioremap(*p, MIRROR_SIZE);
if (!base) {
arc_cont(D_INIT_REASONS, "(ioremap)\n");
arc_cont(D_INIT_REASONS, "Stage 3: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
goto out1;
}
if (arcnet_readb(base, COM9026_REG_R_STATUS) != TESTvalue) {
arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
arcnet_readb(base, COM9026_REG_R_STATUS),
TESTvalue);
arc_cont(D_INIT_REASONS, "S3: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
goto out2;
}
/* By writing 0x42 to the TESTvalue location, we also make
* sure no "mirror" shmem areas show up - if they occur
* in another pass through this loop, they will be discarded
* because *cptr != TESTvalue.
*/
arcnet_writeb(0x42, base, COM9026_REG_W_INTMASK);
if (arcnet_readb(base, COM9026_REG_R_STATUS) != 0x42) {
arc_cont(D_INIT_REASONS, "(read only)\n");
arc_cont(D_INIT_REASONS, "S3: ");
goto out2;
}
arc_cont(D_INIT_REASONS, "\n");
arc_cont(D_INIT_REASONS, "S3: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
iomem[index] = base;
continue;
out2:
iounmap(base);
out1:
release_mem_region(*p, MIRROR_SIZE);
out:
*p-- = shmems[--numshmems];
index--;
}
arc_cont(D_INIT, "\n");
if (!numshmems) {
arc_cont(D_NORMAL, "S3: No ARCnet cards found.\n");
for (port = &ports[0]; port < ports + numports; port++)
release_region(*port, ARCNET_TOTAL_SIZE);
kfree(shmems);
kfree(iomem);
return;
}
/* Stage 4: something of a dummy, to report the shmems that are
* still possible after stage 3.
*/
numprint = -1;
for (p = &shmems[0]; p < shmems + numshmems; p++) {
numprint++;
numprint %= 8;
if (!numprint) {
arc_cont(D_INIT, "\n");
arc_cont(D_INIT, "S4: ");
}
arc_cont(D_INIT, "%lXh ", *p);
}
arc_cont(D_INIT, "\n");
/* Stage 5: for any ports that have the correct status, can disable
* the RESET flag, and (if no irq is given) generate an autoirq,
* register an ARCnet device.
*
* Currently, we can only register one device per probe, so quit
* after the first one is found.
*/
numprint = -1;
for (port = &ports[0]; port < ports + numports; port++) {
int found = 0;
numprint++;
numprint %= 8;
if (!numprint) {
arc_cont(D_INIT, "\n");
arc_cont(D_INIT, "S5: ");
}
arc_cont(D_INIT, "%Xh ", *port);
ioaddr = *port;
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if ((status & 0x9D)
!= (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
arc_cont(D_INIT_REASONS, "(status=%Xh)\n", status);
arc_cont(D_INIT_REASONS, "S5: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
ioaddr, COM9026_REG_W_COMMAND);
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
if (status & RESETflag) {
arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
status);
arc_cont(D_INIT_REASONS, "S5: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
/* skip this completely if an IRQ was given, because maybe
* we're on a machine that locks during autoirq!
*/
if (!irq) {
/* if we do this, we're sure to get an IRQ since the
* card has just reset and the NORXflag is on until
* we tell it to start receiving.
*/
airqmask = probe_irq_on();
arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
udelay(1);
arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
airq = probe_irq_off(airqmask);
if (airq <= 0) {
arc_cont(D_INIT_REASONS, "(airq=%d)\n", airq);
arc_cont(D_INIT_REASONS, "S5: ");
if (BUGLVL(D_INIT_REASONS))
numprint = 0;
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
continue;
}
} else {
airq = irq;
}
arc_cont(D_INIT, "(%d,", airq);
openparen = 1;
/* Everything seems okay. But which shmem, if any, puts
* back its signature byte when the card is reset?
*
* If there are multiple cards installed, there might be
* multiple shmems still in the list.
*/
#ifdef FAST_PROBE
if (numports > 1 || numshmems > 1) {
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
} else {
/* just one shmem and port, assume they match */
arcnet_writeb(TESTvalue, iomem[0],
COM9026_REG_W_INTMASK);
}
#else
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
#endif
for (index = 0; index < numshmems; index++) {
u_long ptr = shmems[index];
void __iomem *base = iomem[index];
if (arcnet_readb(base, COM9026_REG_R_STATUS) == TESTvalue) { /* found one */
arc_cont(D_INIT, "%lXh)\n", *p);
openparen = 0;
/* register the card */
if (com90xx_found(*port, airq, ptr, base) == 0)
found = 1;
numprint = -1;
/* remove shmem from the list */
shmems[index] = shmems[--numshmems];
iomem[index] = iomem[numshmems];
break; /* go to the next I/O port */
} else {
arc_cont(D_INIT_REASONS, "%Xh-",
arcnet_readb(base, COM9026_REG_R_STATUS));
}
}
if (openparen) {
if (BUGLVL(D_INIT))
pr_cont("no matching shmem)\n");
if (BUGLVL(D_INIT_REASONS)) {
pr_cont("S5: ");
numprint = 0;
}
}
if (!found)
release_region(*port, ARCNET_TOTAL_SIZE);
*port-- = ports[--numports];
}
if (BUGLVL(D_INIT_REASONS))
pr_cont("\n");
/* Now put back TESTvalue on all leftover shmems. */
for (index = 0; index < numshmems; index++) {
arcnet_writeb(TESTvalue, iomem[index], COM9026_REG_W_INTMASK);
iounmap(iomem[index]);
release_mem_region(shmems[index], MIRROR_SIZE);
}
kfree(shmems);
kfree(iomem);
}
static int __init check_mirror(unsigned long addr, size_t size)
{
void __iomem *p;
int res = -1;
if (!request_mem_region(addr, size, "arcnet (90xx)"))
return -1;
p = ioremap(addr, size);
if (p) {
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
res = 1;
else
res = 0;
iounmap(p);
}
release_mem_region(addr, size);
return res;
}
/* Set up the struct net_device associated with this card. Called after
* probing succeeds.
*/
static int __init com90xx_found(int ioaddr, int airq, u_long shmem,
void __iomem *p)
{
struct net_device *dev = NULL;
struct arcnet_local *lp;
u_long first_mirror, last_mirror;
int mirror_size;
/* allocate struct net_device */
dev = alloc_arcdev(device);
if (!dev) {
arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n");
iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
return -ENOMEM;
}
lp = netdev_priv(dev);
/* find the real shared memory start/end points, including mirrors */
/* guess the actual size of one "memory mirror" - the number of
* bytes between copies of the shared memory. On most cards, it's
* 2k (or there are no mirrors at all) but on some, it's 4k.
*/
mirror_size = MIRROR_SIZE;
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue &&
check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size = 2 * MIRROR_SIZE;
first_mirror = shmem - mirror_size;
while (check_mirror(first_mirror, mirror_size) == 1)
first_mirror -= mirror_size;
first_mirror += mirror_size;
last_mirror = shmem + mirror_size;
while (check_mirror(last_mirror, mirror_size) == 1)
last_mirror += mirror_size;
last_mirror -= mirror_size;
dev->mem_start = first_mirror;
dev->mem_end = last_mirror + MIRROR_SIZE - 1;
iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
if (!request_mem_region(dev->mem_start,
dev->mem_end - dev->mem_start + 1,
"arcnet (90xx)"))
goto err_free_dev;
/* reserve the irq */
if (request_irq(airq, arcnet_interrupt, 0, "arcnet (90xx)", dev)) {
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", airq);
goto err_release_mem;
}
dev->irq = airq;
/* Initialize the rest of the device structure. */
lp->card_name = "COM90xx";
lp->hw.command = com90xx_command;
lp->hw.status = com90xx_status;
lp->hw.intmask = com90xx_setmask;
lp->hw.reset = com90xx_reset;
lp->hw.owner = THIS_MODULE;
lp->hw.copy_to_card = com90xx_copy_to_card;
lp->hw.copy_from_card = com90xx_copy_from_card;
lp->mem_start = ioremap(dev->mem_start,
dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
arc_printk(D_NORMAL, dev, "Can't remap device memory!\n");
goto err_free_irq;
}
/* get and check the station ID from offset 1 in shmem */
arcnet_set_addr(dev, arcnet_readb(lp->mem_start,
COM9026_REG_R_STATION));
dev->base_addr = ioaddr;
arc_printk(D_NORMAL, dev, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n",
dev->dev_addr[0],
dev->base_addr, dev->irq, dev->mem_start,
(dev->mem_end - dev->mem_start + 1) / mirror_size,
mirror_size);
if (register_netdev(dev))
goto err_unmap;
cards[numcards++] = dev;
return 0;
err_unmap:
iounmap(lp->mem_start);
err_free_irq:
free_irq(dev->irq, dev);
err_release_mem:
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
err_free_dev:
free_arcdev(dev);
return -EIO;
}
static void com90xx_command(struct net_device *dev, int cmd)
{
short ioaddr = dev->base_addr;
arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
}
static int com90xx_status(struct net_device *dev)
{
short ioaddr = dev->base_addr;
return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
}
static void com90xx_setmask(struct net_device *dev, int mask)
{
short ioaddr = dev->base_addr;
arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
}
/* Do a hardware reset on the card, and set up necessary registers.
*
* This should be called as little as possible, because it disrupts the
* token on the network (causes a RECON) and requires a significant delay.
*
* However, it does make sure the card is in a defined state.
*/
static int com90xx_reset(struct net_device *dev, int really_reset)
{
struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n",
arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
if (really_reset) {
/* reset the card */
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
mdelay(RESETtime);
}
/* clear flags & end reset */
arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
#if 0
/* don't do this until we verify that it doesn't hurt older cards! */
arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) | ENABLE16flag,
ioaddr, COM9026_REG_RW_CONFIG);
#endif
/* verify that the ARCnet signature byte is present */
if (arcnet_readb(lp->mem_start, COM9026_REG_R_STATUS) != TESTvalue) {
if (really_reset)
arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
/* clean out all the memory to make debugging make more sense :) */
if (BUGLVL(D_DURING))
memset_io(lp->mem_start, 0x42, 2048);
/* done! return success. */
return 0;
}
static void com90xx_copy_to_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
int offset, void *buf, int count)
{
struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
MODULE_DESCRIPTION("ARCnet COM90xx normal chipset driver");
MODULE_LICENSE("GPL");
static int __init com90xx_init(void)
{
if (irq == 2)
irq = 9;
com90xx_probe();
if (!numcards)
return -EIO;
return 0;
}
static void __exit com90xx_exit(void)
{
struct net_device *dev;
struct arcnet_local *lp;
int count;
for (count = 0; count < numcards; count++) {
dev = cards[count];
lp = netdev_priv(dev);
unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(lp->mem_start);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
release_mem_region(dev->mem_start,
dev->mem_end - dev->mem_start + 1);
free_arcdev(dev);
}
}
module_init(com90xx_init);
module_exit(com90xx_exit);
#ifndef MODULE
static int __init com90xx_setup(char *s)
{
int ints[8];
s = get_options(s, 8, ints);
if (!ints[0] && !*s) {
pr_notice("Disabled\n");
return 1;
}
switch (ints[0]) {
default: /* ERROR */
pr_err("Too many arguments\n");
fallthrough;
case 3: /* Mem address */
shmem = ints[3];
fallthrough;
case 2: /* IRQ */
irq = ints[2];
fallthrough;
case 1: /* IO address */
io = ints[1];
}
if (*s)
snprintf(device, sizeof(device), "%s", s);
return 1;
}
__setup("com90xx=", com90xx_setup);
#endif