mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
Merge branch 'arcnet-remove-outdated-drivers-and-information-and-unused-code-small-cleanups-and-documentation-improvements'
Ethan Nelson-Moore says: ==================== ARCnet: remove outdated drivers and information and unused code; small cleanups and documentation improvements This patch series mainly removes the ISA and PCMCIA ARCnet drivers and documentation for them and hardware they supported. 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. Removing these drivers reduces future maintenance burden. While updating the ARCnet documentation to remove references to the removed drivers, I noticed that it contained thousands of lines of outdated and irrelevant information (much of it so outdated that it would not even work on modern kernels). I took the opportunity to remove this information and improve the writing style slightly. I noticed that the BUS_ALIGN macro was always defined to 1, which meant that the custom arcnet_in/out/read/write* I/O macros were unnecessary. I expanded and removed them to make the code more straightforwards. I also corrected some typos and comments. ==================== Link: https://patch.msgid.link/20260521001631.45434-1-enelsonmoore@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
a482b63085
|
|
@ -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
|
|
@ -8,30 +8,10 @@ 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.
|
||||
|
||||
Since no one seems to listen to me otherwise, perhaps a poem will get your
|
||||
attention::
|
||||
|
||||
This driver's getting fat and beefy,
|
||||
But my cat is still named Fifi.
|
||||
|
||||
Hmm, I think I'm allowed to call that a poem, even though it's only two
|
||||
lines. Hey, I'm in Computer Science, not English. Give me a break.
|
||||
|
||||
The point is: I REALLY REALLY REALLY REALLY REALLY want to hear from you if
|
||||
you test this and get it working. Or if you don't. Or anything.
|
||||
|
||||
ARCnet 0.32 ALPHA first made it into the Linux kernel 1.1.80 - this was
|
||||
nice, but after that even FEWER people started writing to me because they
|
||||
didn't even have to install the patch. <sigh>
|
||||
|
||||
Come on, be a sport! Send me a success report!
|
||||
|
||||
(hey, that was even better than my original poem... this is getting bad!)
|
||||
|
||||
----
|
||||
|
||||
These are the ARCnet drivers for Linux.
|
||||
|
|
@ -62,183 +42,47 @@ netdev@vger.kernel.org and make sure to Cc: maintainer listed in
|
|||
Other Drivers and Info
|
||||
----------------------
|
||||
|
||||
You can try my ARCNET page on the World Wide Web at:
|
||||
You can try JoAnne Schmitz's ARCNET page on the World Wide Web at:
|
||||
|
||||
http://www.qis.net/~jschmitz/arcnet/
|
||||
|
||||
Also, SMC (one of the companies that makes ARCnet cards) has a WWW site you
|
||||
might be interested in, which includes several drivers for various cards
|
||||
including ARCnet. Try:
|
||||
|
||||
http://www.smc.com/
|
||||
|
||||
Performance Technologies makes various network software that supports
|
||||
ARCnet:
|
||||
|
||||
http://www.perftech.com/ or ftp to ftp.perftech.com.
|
||||
|
||||
Novell makes a networking stack for DOS which includes ARCnet drivers. Try
|
||||
FTPing to ftp.novell.com.
|
||||
|
||||
You can get the Crynwr packet driver collection (including arcether.com, the
|
||||
one you'll want to use with ARCnet cards) from
|
||||
oak.oakland.edu:/simtel/msdos/pktdrvr. It won't work perfectly on a 386+
|
||||
without patches, though, and also doesn't like several cards. Fixed
|
||||
versions are available on my WWW page, or via e-mail if you don't have WWW
|
||||
access.
|
||||
https://www.qis.net/~jschmitz/arcnet/
|
||||
|
||||
|
||||
Installing the Driver
|
||||
---------------------
|
||||
Supported Hardware
|
||||
------------------
|
||||
|
||||
All you will need to do in order to install the driver is::
|
||||
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.
|
||||
|
||||
make config
|
||||
(be sure to choose ARCnet in the network devices
|
||||
and at least one chipset driver.)
|
||||
make clean
|
||||
make zImage
|
||||
Support for older chipsets and ISA and PCMCIA devices was previously available
|
||||
but has been removed.
|
||||
|
||||
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.
|
||||
|
||||
You will know the driver is installed properly if you get some ARCnet
|
||||
messages when you reboot into the new Linux kernel.
|
||||
Configuring the Driver
|
||||
----------------------
|
||||
|
||||
There are four chipset options:
|
||||
The COM20020 driver will be loaded automatically at boot if a supported card is
|
||||
detected.
|
||||
|
||||
1. Standard ARCnet COM90xx chipset.
|
||||
If the com20020_pci driver was compiled as a loadable module, the options are::
|
||||
|
||||
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::
|
||||
node=<node_ID> backplane=<backplane> clockp=<CKP> clockm=<CKM>
|
||||
timeout=<timeout> device=<interface_name>
|
||||
|
||||
com90xx=[<io>[,<irq>[,<shmem>]]][,<name>] | <name>
|
||||
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::
|
||||
|
||||
If you load the chipset support as a module, the options are::
|
||||
|
||||
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...?
|
||||
|
|
@ -276,9 +120,8 @@ LAN Manager and Windows for Workgroups:
|
|||
are incompatible with the Internet standard. They try to pretend
|
||||
the cards are Ethernet, and confuse everyone else on the network.
|
||||
|
||||
However, v2.00 and higher of the Linux ARCnet driver supports this
|
||||
protocol via the 'arc0e' device. See the section on "Multiprotocol
|
||||
Support" for more information.
|
||||
The Linux ARCnet driver supports this protocol via the 'arc0e' device.
|
||||
See the section on "Multiprotocol Support" for more information.
|
||||
|
||||
Using the freeware Samba server and clients for Linux, you can now
|
||||
interface quite nicely with TCP/IP-based WfWg or Lan Manager
|
||||
|
|
@ -313,7 +156,7 @@ NetBSD/AmiTCP:
|
|||
Using Multiprotocol ARCnet
|
||||
--------------------------
|
||||
|
||||
The ARCnet driver v2.10 ALPHA supports three protocols, each on its own
|
||||
The ARCnet driver supports three protocols, each on its own
|
||||
"virtual network device":
|
||||
|
||||
====== ===============================================================
|
||||
|
|
@ -505,7 +348,7 @@ can set up your network then:
|
|||
It works: what now?
|
||||
-------------------
|
||||
|
||||
Send mail following :ref:`arcnet-netdev`. Describe your setup, preferably
|
||||
:ref:`Send an email to netdev <arcnet-netdev>`. Describe your setup, preferably
|
||||
including driver version, kernel version, ARCnet card model, CPU type, number
|
||||
of systems on your network, and list of software in use.
|
||||
|
||||
|
|
@ -524,10 +367,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,21 +387,13 @@ 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.
|
||||
|
||||
Note that the debug level is (starting with v1.90 ALPHA) a binary
|
||||
combination of different debug flags; so debug level 7 is really 1+2+4 or
|
||||
D_NORMAL+D_EXTRA+D_INIT. To include D_DURING, you would add 16 to this,
|
||||
resulting in debug level 23.
|
||||
Note that the debug level is a binary combination of different debug flags;
|
||||
debug level 7 is really 1+2+4 or D_NORMAL+D_EXTRA+D_INIT. To include D_DURING,
|
||||
you would add 16 to this, resulting in debug level 23.
|
||||
|
||||
If you don't understand that, you probably don't want to know anyway.
|
||||
E-mail me about your problem.
|
||||
|
||||
|
||||
I want to send money: what now?
|
||||
-------------------------------
|
||||
|
||||
Go take a nap or something. You'll feel better in the morning.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() alloced 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)
|
||||
|
|
@ -137,7 +137,7 @@ do { \
|
|||
#define TXACKflag 0x02 /* transmitted msg. ackd */
|
||||
#define RECONflag 0x04 /* network reconfigured */
|
||||
#define TESTflag 0x08 /* test flag */
|
||||
#define EXCNAKflag 0x08 /* excesive nak flag */
|
||||
#define EXCNAKflag 0x08 /* excessive nak flag */
|
||||
#define RESETflag 0x10 /* power-on-reset */
|
||||
#define RES1flag 0x20 /* reserved - usually set by jumper */
|
||||
#define RES2flag 0x40 /* reserved - usually set by jumper */
|
||||
|
|
@ -166,7 +166,7 @@ do { \
|
|||
#define RESETclear 0x08 /* power-on-reset */
|
||||
#define CONFIGclear 0x10 /* system reconfigured */
|
||||
|
||||
#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */
|
||||
#define EXCNAKclear 0x0E /* Clear and acknowledge the excessive nak bit */
|
||||
|
||||
/* flags for "load test flags" command */
|
||||
#define TESTload 0x08 /* test flag (diagnostic) */
|
||||
|
|
@ -194,7 +194,7 @@ do { \
|
|||
struct ArcProto {
|
||||
char suffix; /* a for RFC1201, e for ether-encap, etc. */
|
||||
int mtu; /* largest possible packet */
|
||||
int is_ip; /* This is a ip plugin - not a raw thing */
|
||||
int is_ip; /* This is an ip plugin - not a raw thing */
|
||||
|
||||
void (*rx)(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length);
|
||||
|
|
@ -257,7 +257,7 @@ struct arcnet_local {
|
|||
char *card_name; /* card ident string */
|
||||
int card_flags; /* special card features */
|
||||
|
||||
/* On preemtive and SMB a lock is needed */
|
||||
/* On preemptive and SMP a lock is needed */
|
||||
spinlock_t lock;
|
||||
|
||||
struct led_trigger *tx_led_trig;
|
||||
|
|
@ -299,7 +299,7 @@ struct arcnet_local {
|
|||
int num_recons; /* number of RECONs between first and last. */
|
||||
int network_down; /* do we think the network is down? */
|
||||
|
||||
int excnak_pending; /* We just got an excesive nak interrupt */
|
||||
int excnak_pending; /* We just got an excessive nak interrupt */
|
||||
|
||||
/* RESET flag handling */
|
||||
int reset_in_progress;
|
||||
|
|
@ -372,31 +372,5 @@ static inline void arcnet_set_addr(struct net_device *dev, u8 addr)
|
|||
dev_addr_set(dev, &addr);
|
||||
}
|
||||
|
||||
/* I/O equivalents */
|
||||
|
||||
#ifdef CONFIG_SA1100_CT6001
|
||||
#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */
|
||||
#else
|
||||
#define BUS_ALIGN 1
|
||||
#endif
|
||||
|
||||
/* addr and offset allow register like names to define the actual IO address.
|
||||
* A configuration option multiplies the offset for alignment.
|
||||
*/
|
||||
#define arcnet_inb(addr, offset) \
|
||||
inb((addr) + BUS_ALIGN * (offset))
|
||||
#define arcnet_outb(value, addr, offset) \
|
||||
outb(value, (addr) + BUS_ALIGN * (offset))
|
||||
|
||||
#define arcnet_insb(addr, offset, buffer, count) \
|
||||
insb((addr) + BUS_ALIGN * (offset), buffer, count)
|
||||
#define arcnet_outsb(addr, offset, buffer, count) \
|
||||
outsb((addr) + BUS_ALIGN * (offset), buffer, count)
|
||||
|
||||
#define arcnet_readb(addr, offset) \
|
||||
readb((addr) + (offset))
|
||||
#define arcnet_writeb(value, addr, offset) \
|
||||
writeb(value, (addr) + (offset))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_ARCDEVICE_H */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -127,7 +127,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
struct net_device *dev;
|
||||
struct arcnet_local *lp;
|
||||
struct com20020_priv *priv;
|
||||
int i, ioaddr, ret;
|
||||
int ioaddr, ret;
|
||||
u8 i;
|
||||
struct resource *r;
|
||||
|
||||
ret = 0;
|
||||
|
|
@ -195,8 +196,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
* ARCNET controller needs
|
||||
* this access to detect bustype
|
||||
*/
|
||||
arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
|
||||
arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
|
||||
outb(0x00, ioaddr + COM20020_REG_W_COMMAND);
|
||||
inb(ioaddr + COM20020_REG_R_DIAGSTAT);
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
dev->base_addr = ioaddr;
|
||||
|
|
@ -224,7 +225,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
|
||||
}
|
||||
|
||||
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
|
||||
if (inb(ioaddr + COM20020_REG_R_STATUS) == 0xFF) {
|
||||
pr_err("IO address %Xh is empty!\n", ioaddr);
|
||||
ret = -EIO;
|
||||
goto err_free_arcdev;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum,
|
|||
int offset, void *buf, int count);
|
||||
static void com20020_copy_from_card(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count);
|
||||
static void com20020_set_mc_list(struct net_device *dev);
|
||||
static void com20020_set_rx_mode(struct net_device *dev);
|
||||
static void com20020_close(struct net_device *);
|
||||
|
||||
static void com20020_copy_from_card(struct net_device *dev, int bufnum,
|
||||
|
|
@ -65,13 +65,13 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum,
|
|||
int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
|
||||
|
||||
/* set up the address register */
|
||||
arcnet_outb((ofs >> 8) | RDDATAflag | AUTOINCflag,
|
||||
ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
outb((ofs >> 8) | RDDATAflag | AUTOINCflag,
|
||||
ioaddr + COM20020_REG_W_ADDR_HI);
|
||||
outb(ofs & 0xff, ioaddr + COM20020_REG_W_ADDR_LO);
|
||||
|
||||
/* copy the data */
|
||||
TIME(dev, "insb", count,
|
||||
arcnet_insb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
|
||||
insb(ioaddr + COM20020_REG_RW_MEMDATA, buf, count));
|
||||
}
|
||||
|
||||
static void com20020_copy_to_card(struct net_device *dev, int bufnum,
|
||||
|
|
@ -80,12 +80,12 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum,
|
|||
int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
|
||||
|
||||
/* set up the address register */
|
||||
arcnet_outb((ofs >> 8) | AUTOINCflag, ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
outb((ofs >> 8) | AUTOINCflag, ioaddr + COM20020_REG_W_ADDR_HI);
|
||||
outb(ofs & 0xff, ioaddr + COM20020_REG_W_ADDR_LO);
|
||||
|
||||
/* copy the data */
|
||||
TIME(dev, "outsb", count,
|
||||
arcnet_outsb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
|
||||
outsb(ioaddr + COM20020_REG_RW_MEMDATA, buf, count));
|
||||
}
|
||||
|
||||
/* Reset the card and check some basic stuff during the detection stage. */
|
||||
|
|
@ -94,9 +94,9 @@ int com20020_check(struct net_device *dev)
|
|||
int ioaddr = dev->base_addr, status;
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
|
||||
arcnet_outb(XTOcfg(3) | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(XTOcfg(3) | RESETcfg, ioaddr + COM20020_REG_W_CONFIG);
|
||||
udelay(5);
|
||||
arcnet_outb(XTOcfg(3), ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(XTOcfg(3), ioaddr + COM20020_REG_W_CONFIG);
|
||||
mdelay(RESETtime);
|
||||
|
||||
lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
|
||||
|
|
@ -107,23 +107,23 @@ int com20020_check(struct net_device *dev)
|
|||
lp->setup = lp->setup | P1MODE;
|
||||
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup, ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
if (lp->clockm != 0) {
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP2);
|
||||
arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup2, ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
/* must now write the magic "restart operation" command */
|
||||
mdelay(1);
|
||||
arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
outb(STARTIOcmd, ioaddr + COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
|
||||
/* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
outb(0x42, ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
|
||||
status = inb(ioaddr + COM20020_REG_R_STATUS);
|
||||
|
||||
if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) {
|
||||
arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status);
|
||||
|
|
@ -131,18 +131,17 @@ int com20020_check(struct net_device *dev)
|
|||
}
|
||||
arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status);
|
||||
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM20020_REG_W_COMMAND);
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
|
||||
outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr + COM20020_REG_W_COMMAND);
|
||||
status = inb(ioaddr + COM20020_REG_R_STATUS);
|
||||
arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n",
|
||||
status);
|
||||
|
||||
/* Read first location of memory */
|
||||
arcnet_outb(0 | RDDATAflag | AUTOINCflag,
|
||||
ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(0, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
outb(0 | RDDATAflag | AUTOINCflag, ioaddr + COM20020_REG_W_ADDR_HI);
|
||||
outb(0, ioaddr + COM20020_REG_W_ADDR_LO);
|
||||
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA);
|
||||
status = inb(ioaddr + COM20020_REG_RW_MEMDATA);
|
||||
if (status != TESTvalue) {
|
||||
arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n",
|
||||
status);
|
||||
|
|
@ -159,7 +158,7 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr)
|
|||
|
||||
dev_addr_set(dev, hwaddr->sa_data);
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_NODE);
|
||||
arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
|
||||
outb(dev->dev_addr[0], ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -170,7 +169,7 @@ static int com20020_netdev_open(struct net_device *dev)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
|
||||
lp->config |= TXENcfg;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
|
||||
return arcnet_open(dev);
|
||||
}
|
||||
|
|
@ -184,7 +183,7 @@ static int com20020_netdev_close(struct net_device *dev)
|
|||
|
||||
/* disable transmitter */
|
||||
lp->config &= ~TXENcfg;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -194,7 +193,7 @@ const struct net_device_ops com20020_netdev_ops = {
|
|||
.ndo_start_xmit = arcnet_send_packet,
|
||||
.ndo_tx_timeout = arcnet_timeout,
|
||||
.ndo_set_mac_address = com20020_set_hwaddr,
|
||||
.ndo_set_rx_mode = com20020_set_mc_list,
|
||||
.ndo_set_rx_mode = com20020_set_rx_mode,
|
||||
};
|
||||
|
||||
/* Set up the struct net_device associated with this card. Called after
|
||||
|
|
@ -220,24 +219,24 @@ int com20020_found(struct net_device *dev, int shared)
|
|||
|
||||
/* FIXME: do this some other way! */
|
||||
if (!dev->dev_addr[0])
|
||||
arcnet_set_addr(dev, arcnet_inb(ioaddr, 8));
|
||||
arcnet_set_addr(dev, inb(ioaddr + 8));
|
||||
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup, ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
if (lp->card_flags & ARC_CAN_10MBIT) {
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP2);
|
||||
arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup2, ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
/* must now write the magic "restart operation" command */
|
||||
mdelay(1);
|
||||
arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
outb(STARTIOcmd, ioaddr + COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
|
||||
/* Default 0x38 + register: Node ID */
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
outb(dev->dev_addr[0], ioaddr + COM20020_REG_W_XREG);
|
||||
|
||||
/* reserve the irq */
|
||||
if (request_irq(dev->irq, arcnet_interrupt, shared,
|
||||
|
|
@ -288,26 +287,26 @@ static int com20020_reset(struct net_device *dev, int really_reset)
|
|||
arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n",
|
||||
__FILE__, __LINE__, __func__, dev, lp, dev->name);
|
||||
arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
|
||||
dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS));
|
||||
dev->name, inb(ioaddr + COM20020_REG_R_STATUS));
|
||||
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
lp->config |= (lp->timeout << 3) | (lp->backplane << 2);
|
||||
/* power-up defaults */
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
|
||||
if (really_reset) {
|
||||
/* reset the card */
|
||||
arcnet_outb(lp->config | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config | RESETcfg, ioaddr + COM20020_REG_W_CONFIG);
|
||||
udelay(5);
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
mdelay(RESETtime * 2);
|
||||
/* COM20020 seems to be slower sometimes */
|
||||
}
|
||||
/* clear flags & end reset */
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM20020_REG_W_COMMAND);
|
||||
outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr + COM20020_REG_W_COMMAND);
|
||||
|
||||
/* verify that the ARCnet signature byte is present */
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
|
|
@ -321,7 +320,7 @@ static int com20020_reset(struct net_device *dev, int really_reset)
|
|||
return 1;
|
||||
}
|
||||
/* enable extended (512-byte) packets */
|
||||
arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM20020_REG_W_COMMAND);
|
||||
outb(CONFIGcmd | EXTconf, ioaddr + COM20020_REG_W_COMMAND);
|
||||
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
|
||||
|
|
@ -334,22 +333,22 @@ static void com20020_setmask(struct net_device *dev, int mask)
|
|||
u_int ioaddr = dev->base_addr;
|
||||
|
||||
arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr);
|
||||
arcnet_outb(mask, ioaddr, COM20020_REG_W_INTMASK);
|
||||
outb(mask, ioaddr + COM20020_REG_W_INTMASK);
|
||||
}
|
||||
|
||||
static void com20020_command(struct net_device *dev, int cmd)
|
||||
{
|
||||
u_int ioaddr = dev->base_addr;
|
||||
|
||||
arcnet_outb(cmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
outb(cmd, ioaddr + COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
static int com20020_status(struct net_device *dev)
|
||||
{
|
||||
u_int ioaddr = dev->base_addr;
|
||||
|
||||
return arcnet_inb(ioaddr, COM20020_REG_R_STATUS) +
|
||||
(arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT) << 8);
|
||||
return inb(ioaddr + COM20020_REG_R_STATUS) +
|
||||
(inb(ioaddr + COM20020_REG_R_DIAGSTAT) << 8);
|
||||
}
|
||||
|
||||
static void com20020_close(struct net_device *dev)
|
||||
|
|
@ -359,17 +358,11 @@ static void com20020_close(struct net_device *dev)
|
|||
|
||||
/* disable transmitter */
|
||||
lp->config &= ~TXENcfg;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
}
|
||||
|
||||
/* Set or clear the multicast filter for this adaptor.
|
||||
* num_addrs == -1 Promiscuous mode, receive all packets
|
||||
* num_addrs == 0 Normal mode, clear multicast list
|
||||
* num_addrs > 0 Multicast mode, receive normal and MC packets, and do
|
||||
* best-effort filtering.
|
||||
* FIXME - do multicast stuff, not just promiscuous.
|
||||
*/
|
||||
static void com20020_set_mc_list(struct net_device *dev)
|
||||
/* ARCnet does not support multicast, only unicast and broadcast */
|
||||
static void com20020_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
int ioaddr = dev->base_addr;
|
||||
|
|
@ -380,20 +373,18 @@ static void com20020_set_mc_list(struct net_device *dev)
|
|||
arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n");
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
lp->setup |= PROMISCset;
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup, ioaddr + COM20020_REG_W_XREG);
|
||||
} else {
|
||||
/* Disable promiscuous mode, use normal mode */
|
||||
if ((lp->setup & PROMISCset))
|
||||
arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n");
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
lp->setup &= ~PROMISCset;
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
outb(lp->setup, ioaddr + COM20020_REG_W_XREG);
|
||||
}
|
||||
}
|
||||
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct com20020_pci_channel_map {
|
|||
|
||||
struct com20020_pci_card_info {
|
||||
const char *name;
|
||||
int devcount;
|
||||
u8 devcount;
|
||||
|
||||
struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS];
|
||||
struct com20020_pci_channel_map misc_map;
|
||||
|
|
@ -123,9 +123,9 @@ static inline void com20020_set_subaddress(struct arcnet_local *lp,
|
|||
{
|
||||
if (val < 4) {
|
||||
lp->config = (lp->config & ~0x03) | val;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
|
||||
} else {
|
||||
arcnet_outb(val, ioaddr, COM20020_REG_W_SUBADR);
|
||||
outb(val, ioaddr + COM20020_REG_W_SUBADR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -235,7 +235,7 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
skb->protocol = type_trans(skb, dev);
|
||||
netif_rx(skb);
|
||||
} else { /* split packet */
|
||||
/* NOTE: MSDOS ARP packet correction should only need to
|
||||
/* NOTE: MS-DOS ARP packet correction should only need to
|
||||
* apply to unsplit packets, since ARP packets are so short.
|
||||
*
|
||||
* My interpretation of the RFC1201 document is that if a
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user