mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-06 14:45:14 +00:00
ARCNET: refactoring and cleanup
This series cleans up the code in drivers/net/arcnet and include/uapi/linux/if_arcnet.h . It doesn't change the runtime behaviour of the code. Its only purpose is to improve the code maintenance and readability. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWAm/HAAoJEAvp4xV6HixkFlEQALJwQxtcI3nze7H4weWEGq5W +gpwifVXvR4qqdXH11UesbHmeYPMcnr3kV3zX5+ht/4f3qcEK5Iic7uoEwTFHiQA 4j04YpjCyl3uK4RURwFyAU7u2tK9vPy+DMEgb2xKqUZjKp6aKu8A0jVyT1ozEuRL r9EYwa9GaOYolvL5OMBZqS3QaLyjptk//Of5LKPNBMYXoQ0cM1rO5CX3mU3FuIxR +ob87cKxmCB5PKArOy8eNEBXya5QTCBBo+PPLcqn11HBeEVQ3a6V4H/swUgDu3jw vDVC4Y5+9AWa8ZsdqVkjAyOw0Mj2M5S839gm5+fv1BumjYC/jcWvoKXJ0F1NicBv NZli8YkYf/N8wdEF0eU+zRA4vr8ZvSwGQVtHZM4/X6tGpJ6HfskrlAbneW46qPZR UsqtVsnKv5pMgan12z5gwSsu912DyKpsBgJaZJI8x4bB7Y20UsMTy7amD7O4XH25 p53Ztr/cTyPBjnNa1WHQBXX1NQId1Ml+Rgz3U1Z0bXqNXREQYwb9U9hE6+/pmfPv h0s6D1XfbA4ov3Nxdmn/+qMuKi8WtDvWwLN05OX3Y1xYeG0yD8pixdEO7ACxpaYz x7jtSqSVu76H0alNez4edtZRTKp1NbjqAPaeMmDmzGJbdTFFRXDVgUXPABDHF7vr ldLMco+ILLtQ32YOLdbM =QEr5 -----END PGP SIGNATURE----- Merge tag 'arcnet-cleanup-v4.3-rc2' of git://git.pengutronix.de/git/mgr/linux Michael Grzeschik says: ==================== ARCNET: refactoring and cleanup This series cleans up the code in drivers/net/arcnet and include/uapi/linux/if_arcnet.h . It doesn't change the runtime behaviour of the code. Its only purpose is to improve the code maintenance and readability. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e1ffc0cd2c
17 changed files with 1452 additions and 1488 deletions
|
@ -7292,7 +7292,6 @@ S: Odd Fixes
|
|||
F: drivers/net/
|
||||
F: include/linux/if_*
|
||||
F: include/linux/netdevice.h
|
||||
F: include/linux/arcdevice.h
|
||||
F: include/linux/etherdevice.h
|
||||
F: include/linux/fcdevice.h
|
||||
F: include/linux/fddidevice.h
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers)
|
||||
*
|
||||
*
|
||||
* Written 1994-1999 by Avery Pennarun.
|
||||
* Derived from skeleton.c by Donald Becker.
|
||||
*
|
||||
|
@ -24,6 +24,8 @@
|
|||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -31,20 +33,124 @@
|
|||
#include <net/arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
#define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n"
|
||||
|
||||
#include "arcdevice.h"
|
||||
|
||||
/* packet receiver */
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length);
|
||||
static int build_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, uint8_t daddr);
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum);
|
||||
|
||||
static struct ArcProto rawmode_proto =
|
||||
struct archdr *pkthdr, int length)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct sk_buff *skb;
|
||||
struct archdr *pkt = pkthdr;
|
||||
int ofs;
|
||||
|
||||
arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length);
|
||||
|
||||
if (length > MTU)
|
||||
ofs = 512 - length;
|
||||
else
|
||||
ofs = 256 - length;
|
||||
|
||||
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb_put(skb, length + ARC_HDR_SIZE);
|
||||
skb->dev = dev;
|
||||
|
||||
pkt = (struct archdr *)skb->data;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, ARC_HDR_SIZE);
|
||||
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card */
|
||||
memcpy(pkt, pkthdr, sizeof(struct archdr));
|
||||
if (length > sizeof(pkt->soft))
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
|
||||
pkt->soft.raw + sizeof(pkt->soft),
|
||||
length - sizeof(pkt->soft));
|
||||
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = cpu_to_be16(ETH_P_ARCNET);
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
/* Create the ARCnet hard/soft headers for raw mode.
|
||||
* There aren't any soft headers in raw mode - not even the protocol id.
|
||||
*/
|
||||
static int build_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, uint8_t daddr)
|
||||
{
|
||||
int hdr_size = ARC_HDR_SIZE;
|
||||
struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
|
||||
|
||||
/* Set the source hardware address.
|
||||
*
|
||||
* This is pretty pointless for most purposes, but it can help in
|
||||
* debugging. ARCnet does not allow us to change the source address
|
||||
* in the actual packet sent.
|
||||
*/
|
||||
pkt->hard.source = *dev->dev_addr;
|
||||
|
||||
/* see linux/net/ethernet/eth.c to see where I got the following */
|
||||
|
||||
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
|
||||
/* FIXME: fill in the last byte of the dest ipaddr here
|
||||
* to better comply with RFC1051 in "noarp" mode.
|
||||
*/
|
||||
pkt->hard.dest = 0;
|
||||
return hdr_size;
|
||||
}
|
||||
/* otherwise, just fill it in and go! */
|
||||
pkt->hard.dest = daddr;
|
||||
|
||||
return hdr_size; /* success */
|
||||
}
|
||||
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct arc_hardware *hard = &pkt->hard;
|
||||
int ofs;
|
||||
|
||||
arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
/* hard header is not included in packet length */
|
||||
length -= ARC_HDR_SIZE;
|
||||
|
||||
if (length > XMTU) {
|
||||
/* should never happen! other people already check for this. */
|
||||
arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
length = XMTU;
|
||||
}
|
||||
if (length >= MinTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length;
|
||||
} else if (length > MTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length - 3;
|
||||
} else {
|
||||
hard->offset[0] = ofs = 256 - length;
|
||||
}
|
||||
|
||||
arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n",
|
||||
length, ofs);
|
||||
|
||||
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
|
||||
|
||||
lp->lastload_dest = hard->dest;
|
||||
|
||||
return 1; /* done */
|
||||
}
|
||||
|
||||
static struct ArcProto rawmode_proto = {
|
||||
.suffix = 'r',
|
||||
.mtu = XMTU,
|
||||
.rx = rx,
|
||||
|
@ -54,12 +160,11 @@ static struct ArcProto rawmode_proto =
|
|||
.ack_tx = NULL
|
||||
};
|
||||
|
||||
|
||||
static int __init arcnet_raw_init(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
printk(VERSION);
|
||||
pr_info("raw mode (`r') encapsulation support loaded\n");
|
||||
|
||||
for (count = 0; count < 256; count++)
|
||||
if (arc_proto_map[count] == arc_proto_default)
|
||||
|
@ -82,122 +187,3 @@ module_init(arcnet_raw_init);
|
|||
module_exit(arcnet_raw_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
/* packet receiver */
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct sk_buff *skb;
|
||||
struct archdr *pkt = pkthdr;
|
||||
int ofs;
|
||||
|
||||
BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
|
||||
|
||||
if (length > MTU)
|
||||
ofs = 512 - length;
|
||||
else
|
||||
ofs = 256 - length;
|
||||
|
||||
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb_put(skb, length + ARC_HDR_SIZE);
|
||||
skb->dev = dev;
|
||||
|
||||
pkt = (struct archdr *) skb->data;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, ARC_HDR_SIZE);
|
||||
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card */
|
||||
memcpy(pkt, pkthdr, sizeof(struct archdr));
|
||||
if (length > sizeof(pkt->soft))
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
|
||||
pkt->soft.raw + sizeof(pkt->soft),
|
||||
length - sizeof(pkt->soft));
|
||||
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = cpu_to_be16(ETH_P_ARCNET);
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create the ARCnet hard/soft headers for raw mode.
|
||||
* There aren't any soft headers in raw mode - not even the protocol id.
|
||||
*/
|
||||
static int build_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, uint8_t daddr)
|
||||
{
|
||||
int hdr_size = ARC_HDR_SIZE;
|
||||
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
|
||||
|
||||
/*
|
||||
* Set the source hardware address.
|
||||
*
|
||||
* This is pretty pointless for most purposes, but it can help in
|
||||
* debugging. ARCnet does not allow us to change the source address in
|
||||
* the actual packet sent)
|
||||
*/
|
||||
pkt->hard.source = *dev->dev_addr;
|
||||
|
||||
/* see linux/net/ethernet/eth.c to see where I got the following */
|
||||
|
||||
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
|
||||
/*
|
||||
* FIXME: fill in the last byte of the dest ipaddr here to better
|
||||
* comply with RFC1051 in "noarp" mode.
|
||||
*/
|
||||
pkt->hard.dest = 0;
|
||||
return hdr_size;
|
||||
}
|
||||
/* otherwise, just fill it in and go! */
|
||||
pkt->hard.dest = daddr;
|
||||
|
||||
return hdr_size; /* success */
|
||||
}
|
||||
|
||||
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct arc_hardware *hard = &pkt->hard;
|
||||
int ofs;
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
|
||||
|
||||
if (length > XMTU) {
|
||||
/* should never happen! other people already check for this. */
|
||||
BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
length = XMTU;
|
||||
}
|
||||
if (length >= MinTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length;
|
||||
} else if (length > MTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length - 3;
|
||||
} else
|
||||
hard->offset[0] = ofs = 256 - length;
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n",
|
||||
length,ofs);
|
||||
|
||||
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
|
||||
|
||||
lp->lastload_dest = hard->dest;
|
||||
|
||||
return 1; /* done */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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.
|
||||
|
@ -24,6 +24,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -33,12 +36,10 @@
|
|||
#include <linux/bootmem.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
|
||||
#define VERSION "arcnet: RIM I (entirely mem-mapped) support\n"
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "arcdevice.h"
|
||||
#include "com9026.h"
|
||||
|
||||
/* Internal function declarations */
|
||||
|
||||
|
@ -50,66 +51,46 @@ 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);
|
||||
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)
|
||||
#define BUFFER_SIZE (512)
|
||||
#define MIRROR_SIZE (BUFFER_SIZE * 4)
|
||||
|
||||
/* COM 9026 controller chip --> ARCnet register addresses */
|
||||
#define _INTMASK (ioaddr+0) /* writable */
|
||||
#define _STATUS (ioaddr+0) /* readable */
|
||||
#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
|
||||
#define _RESET (ioaddr+8) /* software reset (on read) */
|
||||
#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
|
||||
#define _ADDR_HI (ioaddr+15) /* Control registers for said */
|
||||
#define _ADDR_LO (ioaddr+14)
|
||||
#define _CONFIG (ioaddr+2) /* Configuration register */
|
||||
|
||||
#undef ASTATUS
|
||||
#undef ACOMMAND
|
||||
#undef AINTMASK
|
||||
|
||||
#define ASTATUS() readb(_STATUS)
|
||||
#define ACOMMAND(cmd) writeb((cmd),_COMMAND)
|
||||
#define AINTMASK(msk) writeb((msk),_INTMASK)
|
||||
#define SETCONF() writeb(lp->config,_CONFIG)
|
||||
|
||||
|
||||
/*
|
||||
* We cannot probe for a RIM I card; one reason is I don't know how to reset
|
||||
/* 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)
|
||||
{
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
|
||||
|
||||
BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n",
|
||||
dev->dev_addr[0], dev->mem_start, dev->irq);
|
||||
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) {
|
||||
BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you "
|
||||
"must specify the shmem and irq!\n");
|
||||
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) {
|
||||
BUGLVL(D_NORMAL) printk("You need to specify your card's station "
|
||||
"ID!\n");
|
||||
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.
|
||||
/* 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)")) {
|
||||
BUGLVL(D_NORMAL) printk("Card memory already allocated\n");
|
||||
if (BUGLVL(D_NORMAL))
|
||||
pr_notice("Card memory already allocated\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return arcrimi_found(dev);
|
||||
|
@ -125,7 +106,7 @@ static int check_mirror(unsigned long addr, size_t size)
|
|||
|
||||
p = ioremap(addr, size);
|
||||
if (p) {
|
||||
if (readb(p) == TESTvalue)
|
||||
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
|
||||
res = 1;
|
||||
else
|
||||
res = 0;
|
||||
|
@ -136,9 +117,8 @@ static int check_mirror(unsigned long addr, size_t size)
|
|||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the struct net_device associated with this card. Called after
|
||||
* probing succeeds.
|
||||
/* Set up the struct net_device associated with this card.
|
||||
* Called after probing succeeds.
|
||||
*/
|
||||
static int __init arcrimi_found(struct net_device *dev)
|
||||
{
|
||||
|
@ -151,7 +131,7 @@ static int __init arcrimi_found(struct net_device *dev)
|
|||
p = ioremap(dev->mem_start, MIRROR_SIZE);
|
||||
if (!p) {
|
||||
release_mem_region(dev->mem_start, MIRROR_SIZE);
|
||||
BUGMSG(D_NORMAL, "Can't ioremap\n");
|
||||
arc_printk(D_NORMAL, dev, "Can't ioremap\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -159,13 +139,14 @@ static int __init arcrimi_found(struct net_device *dev)
|
|||
if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
|
||||
iounmap(p);
|
||||
release_mem_region(dev->mem_start, MIRROR_SIZE);
|
||||
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
|
||||
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
shmem = dev->mem_start;
|
||||
writeb(TESTvalue, p);
|
||||
writeb(dev->dev_addr[0], p + 1); /* actually the node ID */
|
||||
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 */
|
||||
|
||||
|
@ -174,7 +155,7 @@ static int __init arcrimi_found(struct net_device *dev)
|
|||
* 2k (or there are no mirrors at all) but on some, it's 4k.
|
||||
*/
|
||||
mirror_size = MIRROR_SIZE;
|
||||
if (readb(p) == TESTvalue &&
|
||||
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;
|
||||
|
@ -204,8 +185,7 @@ static int __init arcrimi_found(struct net_device *dev)
|
|||
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
|
||||
/* 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.
|
||||
|
@ -215,24 +195,25 @@ static int __init arcrimi_found(struct net_device *dev)
|
|||
if (!request_mem_region(dev->mem_start,
|
||||
dev->mem_end - dev->mem_start + 1,
|
||||
"arcnet (90xx)")) {
|
||||
BUGMSG(D_NORMAL, "Card memory already allocated\n");
|
||||
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);
|
||||
lp->mem_start = ioremap(dev->mem_start,
|
||||
dev->mem_end - dev->mem_start + 1);
|
||||
if (!lp->mem_start) {
|
||||
BUGMSG(D_NORMAL, "Can't remap device memory!\n");
|
||||
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 */
|
||||
dev->dev_addr[0] = readb(lp->mem_start + 1);
|
||||
dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
|
||||
|
||||
BUGMSG(D_NORMAL, "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);
|
||||
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)
|
||||
|
@ -249,9 +230,7 @@ err_free_irq:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do a hardware reset on the card, and set up necessary registers.
|
||||
/* 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.
|
||||
|
@ -263,17 +242,19 @@ 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;
|
||||
|
||||
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
|
||||
arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
|
||||
dev->name, arcnet_readb(ioaddr, COM9026_REG_R_STATUS));
|
||||
|
||||
if (really_reset) {
|
||||
writeb(TESTvalue, ioaddr - 0x800); /* fake reset */
|
||||
arcnet_writeb(TESTvalue, ioaddr, -0x800); /* fake reset */
|
||||
return 0;
|
||||
}
|
||||
ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
|
||||
ACOMMAND(CFLAGScmd | CONFIGclear);
|
||||
/* 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 */
|
||||
ACOMMAND(CONFIGcmd | EXTconf);
|
||||
arcnet_writeb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
|
||||
|
||||
/* done! return success. */
|
||||
return 0;
|
||||
|
@ -284,7 +265,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->mem_start + 0x800;
|
||||
|
||||
AINTMASK(mask);
|
||||
arcnet_writeb(mask, ioaddr, COM9026_REG_W_INTMASK);
|
||||
}
|
||||
|
||||
static int arcrimi_status(struct net_device *dev)
|
||||
|
@ -292,7 +273,7 @@ static int arcrimi_status(struct net_device *dev)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->mem_start + 0x800;
|
||||
|
||||
return ASTATUS();
|
||||
return arcnet_readb(ioaddr, COM9026_REG_R_STATUS);
|
||||
}
|
||||
|
||||
static void arcrimi_command(struct net_device *dev, int cmd)
|
||||
|
@ -300,7 +281,7 @@ static void arcrimi_command(struct net_device *dev, int cmd)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->mem_start + 0x800;
|
||||
|
||||
ACOMMAND(cmd);
|
||||
arcnet_writeb(cmd, ioaddr, COM9026_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
|
||||
|
@ -308,16 +289,17 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
|
|||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
|
||||
TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
|
||||
|
||||
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)
|
||||
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("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
|
||||
|
||||
TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
|
||||
}
|
||||
|
||||
static int node;
|
||||
|
@ -374,12 +356,13 @@ static void __exit arc_rimi_exit(void)
|
|||
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 */
|
||||
printk("arcrimi: Too many arguments.\n");
|
||||
pr_err("Too many arguments\n");
|
||||
case 3: /* Node ID */
|
||||
node = ints[3];
|
||||
case 2: /* IRQ */
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
*/
|
||||
#define RECON_THRESHOLD 30
|
||||
|
||||
|
||||
/*
|
||||
* Define this to the minimum "timeout" value. If a transmit takes longer
|
||||
* than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large
|
||||
|
@ -44,14 +43,12 @@
|
|||
*/
|
||||
#define TX_TIMEOUT (HZ * 200 / 1000)
|
||||
|
||||
|
||||
/* Display warnings about the driver being an ALPHA version. */
|
||||
#undef ALPHA_WARNING
|
||||
|
||||
|
||||
/*
|
||||
* Debugging bitflags: each option can be enabled individually.
|
||||
*
|
||||
*
|
||||
* Note: only debug flags included in the ARCNET_DEBUG_MAX define will
|
||||
* actually be available. GCC will (at least, GCC 2.7.0 will) notice
|
||||
* lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
|
||||
|
@ -77,35 +74,47 @@
|
|||
#endif
|
||||
|
||||
#ifndef ARCNET_DEBUG
|
||||
#define ARCNET_DEBUG (D_NORMAL|D_EXTRA)
|
||||
#define ARCNET_DEBUG (D_NORMAL | D_EXTRA)
|
||||
#endif
|
||||
extern int arcnet_debug;
|
||||
|
||||
#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug)
|
||||
|
||||
/* macros to simplify debug checking */
|
||||
#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
|
||||
#define BUGMSG2(x,msg,args...) do { BUGLVL(x) printk(msg, ## args); } while (0)
|
||||
#define BUGMSG(x,msg,args...) \
|
||||
BUGMSG2(x, "%s%6s: " msg, \
|
||||
x==D_NORMAL ? KERN_WARNING \
|
||||
: x < D_DURING ? KERN_INFO : KERN_DEBUG, \
|
||||
dev->name , ## args)
|
||||
#define arc_printk(x, dev, fmt, ...) \
|
||||
do { \
|
||||
if (BUGLVL(x)) { \
|
||||
if ((x) == D_NORMAL) \
|
||||
netdev_warn(dev, fmt, ##__VA_ARGS__); \
|
||||
else if ((x) < D_DURING) \
|
||||
netdev_info(dev, fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
netdev_dbg(dev, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define arc_cont(x, fmt, ...) \
|
||||
do { \
|
||||
if (BUGLVL(x)) \
|
||||
pr_cont(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* see how long a function call takes to run, expressed in CPU cycles */
|
||||
#define TIME(name, bytes, call) BUGLVL(D_TIMING) { \
|
||||
unsigned long _x, _y; \
|
||||
_x = get_cycles(); \
|
||||
call; \
|
||||
_y = get_cycles(); \
|
||||
BUGMSG(D_TIMING, \
|
||||
"%s: %d bytes in %lu cycles == " \
|
||||
"%lu Kbytes/100Mcycle\n",\
|
||||
name, bytes, _y - _x, \
|
||||
100000000 / 1024 * bytes / (_y - _x + 1));\
|
||||
} \
|
||||
else { \
|
||||
call;\
|
||||
}
|
||||
|
||||
#define TIME(dev, name, bytes, call) \
|
||||
do { \
|
||||
if (BUGLVL(D_TIMING)) { \
|
||||
unsigned long _x, _y; \
|
||||
_x = get_cycles(); \
|
||||
call; \
|
||||
_y = get_cycles(); \
|
||||
arc_printk(D_TIMING, dev, \
|
||||
"%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \
|
||||
name, bytes, _y - _x, \
|
||||
100000000 / 1024 * bytes / (_y - _x + 1)); \
|
||||
} else { \
|
||||
call; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Time needed to reset the card - in ms (milliseconds). This works on my
|
||||
|
@ -155,6 +164,7 @@ extern int arcnet_debug;
|
|||
#define CONFIGcmd 0x05 /* define configuration */
|
||||
#define CFLAGScmd 0x06 /* clear flags */
|
||||
#define TESTcmd 0x07 /* load test flags */
|
||||
#define STARTIOcmd 0x18 /* start internal operation */
|
||||
|
||||
/* flags for "clear flags" command */
|
||||
#define RESETclear 0x08 /* power-on-reset */
|
||||
|
@ -182,29 +192,27 @@ extern int arcnet_debug;
|
|||
#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit,
|
||||
but default is 2.5MBit. */
|
||||
|
||||
|
||||
/* information needed to define an encapsulation driver */
|
||||
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 */
|
||||
|
||||
void (*rx) (struct net_device * dev, int bufnum,
|
||||
struct archdr * pkthdr, int length);
|
||||
int (*build_header) (struct sk_buff * skb, struct net_device *dev,
|
||||
unsigned short ethproto, uint8_t daddr);
|
||||
void (*rx)(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length);
|
||||
int (*build_header)(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short ethproto, uint8_t daddr);
|
||||
|
||||
/* these functions return '1' if the skb can now be freed */
|
||||
int (*prepare_tx) (struct net_device * dev, struct archdr * pkt, int length,
|
||||
int bufnum);
|
||||
int (*continue_tx) (struct net_device * dev, int bufnum);
|
||||
int (*ack_tx) (struct net_device * dev, int acked);
|
||||
int (*prepare_tx)(struct net_device *dev, struct archdr *pkt,
|
||||
int length, int bufnum);
|
||||
int (*continue_tx)(struct net_device *dev, int bufnum);
|
||||
int (*ack_tx)(struct net_device *dev, int acked);
|
||||
};
|
||||
|
||||
extern struct ArcProto *arc_proto_map[256], *arc_proto_default,
|
||||
*arc_bcast_proto, *arc_raw_proto;
|
||||
|
||||
|
||||
/*
|
||||
* "Incoming" is information needed for each address that could be sending
|
||||
* to us. Mostly for partially-received split packets.
|
||||
|
@ -216,7 +224,6 @@ struct Incoming {
|
|||
numpackets; /* number of packets in split */
|
||||
};
|
||||
|
||||
|
||||
/* only needed for RFC1201 */
|
||||
struct Outgoing {
|
||||
struct ArcProto *proto; /* protocol driver that owns this:
|
||||
|
@ -230,7 +237,6 @@ struct Outgoing {
|
|||
numsegs; /* number of segments */
|
||||
};
|
||||
|
||||
|
||||
struct arcnet_local {
|
||||
uint8_t config, /* current value of CONFIG register */
|
||||
timeout, /* Extended timeout for COM20020 */
|
||||
|
@ -251,7 +257,6 @@ struct arcnet_local {
|
|||
char *card_name; /* card ident string */
|
||||
int card_flags; /* special card features */
|
||||
|
||||
|
||||
/* On preemtive and SMB a lock is needed */
|
||||
spinlock_t lock;
|
||||
|
||||
|
@ -263,13 +268,13 @@ struct arcnet_local {
|
|||
* situations in which we (for example) want to pre-load a transmit
|
||||
* buffer, or start receiving while we copy a received packet to
|
||||
* memory.
|
||||
*
|
||||
*
|
||||
* The rules: only the interrupt handler is allowed to _add_ buffers to
|
||||
* the queue; thus, this doesn't require a lock. Both the interrupt
|
||||
* handler and the transmit function will want to _remove_ buffers, so
|
||||
* we need to handle the situation where they try to do it at the same
|
||||
* time.
|
||||
*
|
||||
*
|
||||
* If next_buf == first_free_buf, the queue is empty. Since there are
|
||||
* only four possible buffers, the queue should never be full.
|
||||
*/
|
||||
|
@ -298,34 +303,29 @@ struct arcnet_local {
|
|||
/* hardware-specific functions */
|
||||
struct {
|
||||
struct module *owner;
|
||||
void (*command) (struct net_device * dev, int cmd);
|
||||
int (*status) (struct net_device * dev);
|
||||
void (*intmask) (struct net_device * dev, int mask);
|
||||
int (*reset) (struct net_device * dev, int really_reset);
|
||||
void (*open) (struct net_device * dev);
|
||||
void (*close) (struct net_device * dev);
|
||||
void (*command)(struct net_device *dev, int cmd);
|
||||
int (*status)(struct net_device *dev);
|
||||
void (*intmask)(struct net_device *dev, int mask);
|
||||
int (*reset)(struct net_device *dev, int really_reset);
|
||||
void (*open)(struct net_device *dev);
|
||||
void (*close)(struct net_device *dev);
|
||||
|
||||
void (*copy_to_card) (struct net_device * dev, int bufnum, int offset,
|
||||
void *buf, int count);
|
||||
void (*copy_from_card) (struct net_device * dev, int bufnum, int offset,
|
||||
void *buf, int count);
|
||||
void (*copy_to_card)(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count);
|
||||
void (*copy_from_card)(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count);
|
||||
} hw;
|
||||
|
||||
void __iomem *mem_start; /* pointer to ioremap'ed MMIO */
|
||||
};
|
||||
|
||||
|
||||
#define ARCRESET(x) (lp->hw.reset(dev, (x)))
|
||||
#define ACOMMAND(x) (lp->hw.command(dev, (x)))
|
||||
#define ASTATUS() (lp->hw.status(dev))
|
||||
#define AINTMASK(x) (lp->hw.intmask(dev, (x)))
|
||||
|
||||
|
||||
|
||||
#if ARCNET_DEBUG_MAX & D_SKB
|
||||
void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
|
||||
#else
|
||||
#define arcnet_dump_skb(dev,skb,desc) ;
|
||||
static inline
|
||||
void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void arcnet_unregister_proto(struct ArcProto *proto);
|
||||
|
@ -335,8 +335,34 @@ struct net_device *alloc_arcdev(const char *name);
|
|||
int arcnet_open(struct net_device *dev);
|
||||
int arcnet_close(struct net_device *dev);
|
||||
netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
struct net_device *dev);
|
||||
void arcnet_timeout(struct net_device *dev);
|
||||
|
||||
/* 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 */
|
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,8 @@
|
|||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -33,9 +35,8 @@
|
|||
#include <net/arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
#define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n"
|
||||
#include "arcdevice.h"
|
||||
|
||||
/* packet receiver */
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
|
@ -47,7 +48,8 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
char *pktbuf, *pkthdrbuf;
|
||||
int ofs;
|
||||
|
||||
BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length);
|
||||
arc_printk(D_DURING, dev, "it's a raw(cap) packet (length=%d)\n",
|
||||
length);
|
||||
|
||||
if (length >= MinTU)
|
||||
ofs = 512 - length;
|
||||
|
@ -55,8 +57,7 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
ofs = 256 - length;
|
||||
|
||||
skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
|
||||
if (!skb) {
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
|
@ -66,17 +67,17 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
pkt = (struct archdr *)skb_mac_header(skb);
|
||||
skb_pull(skb, ARC_HDR_SIZE);
|
||||
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card */
|
||||
/* squeeze in an int for the cap encapsulation */
|
||||
|
||||
/* use these variables to be sure we count in bytes, not in
|
||||
sizeof(struct archdr) */
|
||||
pktbuf=(char*)pkt;
|
||||
pkthdrbuf=(char*)pkthdr;
|
||||
memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto));
|
||||
memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int),
|
||||
pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto),
|
||||
sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto));
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card
|
||||
* squeeze in an int for the cap encapsulation
|
||||
* use these variables to be sure we count in bytes, not in
|
||||
* sizeof(struct archdr)
|
||||
*/
|
||||
pktbuf = (char *)pkt;
|
||||
pkthdrbuf = (char *)pkthdr;
|
||||
memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto));
|
||||
memcpy(pktbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto) + sizeof(int),
|
||||
pkthdrbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto),
|
||||
sizeof(struct archdr) - ARC_HDR_SIZE - sizeof(pkt->soft.cap.proto));
|
||||
|
||||
if (length > sizeof(pkt->soft))
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
|
||||
|
@ -84,15 +85,14 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
+ sizeof(int),
|
||||
length - sizeof(pkt->soft));
|
||||
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = cpu_to_be16(ETH_P_ARCNET);
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create the ARCnet hard/soft headers for cap mode.
|
||||
/* Create the ARCnet hard/soft headers for cap mode.
|
||||
* There aren't any soft headers in cap mode - not even the protocol id.
|
||||
*/
|
||||
static int build_header(struct sk_buff *skb,
|
||||
|
@ -101,12 +101,12 @@ static int build_header(struct sk_buff *skb,
|
|||
uint8_t daddr)
|
||||
{
|
||||
int hdr_size = ARC_HDR_SIZE;
|
||||
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
|
||||
struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
|
||||
|
||||
BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n",
|
||||
*((int*)&pkt->soft.cap.cookie[0]));
|
||||
/*
|
||||
* Set the source hardware address.
|
||||
arc_printk(D_PROTO, dev, "Preparing header for cap packet %x.\n",
|
||||
*((int *)&pkt->soft.cap.cookie[0]));
|
||||
|
||||
/* Set the source hardware address.
|
||||
*
|
||||
* This is pretty pointless for most purposes, but it can help in
|
||||
* debugging. ARCnet does not allow us to change the source address in
|
||||
|
@ -117,9 +117,8 @@ static int build_header(struct sk_buff *skb,
|
|||
/* see linux/net/ethernet/eth.c to see where I got the following */
|
||||
|
||||
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
|
||||
/*
|
||||
* FIXME: fill in the last byte of the dest ipaddr here to better
|
||||
* comply with RFC1051 in "noarp" mode.
|
||||
/* FIXME: fill in the last byte of the dest ipaddr here to
|
||||
* better comply with RFC1051 in "noarp" mode.
|
||||
*/
|
||||
pkt->hard.dest = 0;
|
||||
return hdr_size;
|
||||
|
@ -130,7 +129,6 @@ static int build_header(struct sk_buff *skb,
|
|||
return hdr_size; /* success */
|
||||
}
|
||||
|
||||
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum)
|
||||
{
|
||||
|
@ -138,22 +136,21 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
struct arc_hardware *hard = &pkt->hard;
|
||||
int ofs;
|
||||
|
||||
|
||||
/* hard header is not included in packet length */
|
||||
length -= ARC_HDR_SIZE;
|
||||
/* And neither is the cookie field */
|
||||
length -= sizeof(int);
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
BUGMSG(D_PROTO, "Sending for cap packet %x.\n",
|
||||
*((int*)&pkt->soft.cap.cookie[0]));
|
||||
arc_printk(D_PROTO, dev, "Sending for cap packet %x.\n",
|
||||
*((int *)&pkt->soft.cap.cookie[0]));
|
||||
|
||||
if (length > XMTU) {
|
||||
/* should never happen! other people already check for this. */
|
||||
BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
length = XMTU;
|
||||
}
|
||||
if (length > MinTU) {
|
||||
|
@ -162,11 +159,12 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
} else if (length > MTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length - 3;
|
||||
} else
|
||||
} else {
|
||||
hard->offset[0] = ofs = 256 - length;
|
||||
}
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n",
|
||||
length,ofs);
|
||||
arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n",
|
||||
length, ofs);
|
||||
|
||||
/* Copy the arcnet-header + the protocol byte down: */
|
||||
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
|
||||
|
@ -174,9 +172,10 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
sizeof(pkt->soft.cap.proto));
|
||||
|
||||
/* Skip the extra integer we have written into it as a cookie
|
||||
but write the rest of the message: */
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs+1,
|
||||
((unsigned char*)&pkt->soft.cap.mes),length-1);
|
||||
* but write the rest of the message:
|
||||
*/
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs + 1,
|
||||
((unsigned char *)&pkt->soft.cap.mes), length - 1);
|
||||
|
||||
lp->lastload_dest = hard->dest;
|
||||
|
||||
|
@ -188,21 +187,20 @@ static int ack_tx(struct net_device *dev, int acked)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct sk_buff *ackskb;
|
||||
struct archdr *ackpkt;
|
||||
int length=sizeof(struct arc_cap);
|
||||
int length = sizeof(struct arc_cap);
|
||||
|
||||
BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n",
|
||||
lp->outgoing.skb->protocol, acked);
|
||||
arc_printk(D_DURING, dev, "capmode: ack_tx: protocol: %x: result: %d\n",
|
||||
lp->outgoing.skb->protocol, acked);
|
||||
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx");
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx");
|
||||
|
||||
/* Now alloc a skb to send back up through the layers: */
|
||||
ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC);
|
||||
if (ackskb == NULL) {
|
||||
BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n");
|
||||
ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
|
||||
if (!ackskb)
|
||||
goto free_outskb;
|
||||
}
|
||||
|
||||
skb_put(ackskb, length + ARC_HDR_SIZE );
|
||||
skb_put(ackskb, length + ARC_HDR_SIZE);
|
||||
ackskb->dev = dev;
|
||||
|
||||
skb_reset_mac_header(ackskb);
|
||||
|
@ -212,39 +210,40 @@ static int ack_tx(struct net_device *dev, int acked)
|
|||
skb_copy_from_linear_data(lp->outgoing.skb, ackpkt,
|
||||
ARC_HDR_SIZE + sizeof(struct arc_cap));
|
||||
ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */
|
||||
ackpkt->soft.cap.mes.ack=acked;
|
||||
ackpkt->soft.cap.mes.ack = acked;
|
||||
|
||||
BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n",
|
||||
*((int*)&ackpkt->soft.cap.cookie[0]));
|
||||
arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n",
|
||||
*((int *)&ackpkt->soft.cap.cookie[0]));
|
||||
|
||||
ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
|
||||
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, ackskb, "ack_tx_recv");
|
||||
netif_rx(ackskb);
|
||||
|
||||
free_outskb:
|
||||
dev_kfree_skb_irq(lp->outgoing.skb);
|
||||
lp->outgoing.proto = NULL; /* We are always finished when in this protocol */
|
||||
lp->outgoing.proto = NULL;
|
||||
/* We are always finished when in this protocol */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ArcProto capmode_proto =
|
||||
{
|
||||
'r',
|
||||
XMTU,
|
||||
0,
|
||||
rx,
|
||||
build_header,
|
||||
prepare_tx,
|
||||
NULL,
|
||||
ack_tx
|
||||
static struct ArcProto capmode_proto = {
|
||||
.suffix = 'r',
|
||||
.mtu = XMTU,
|
||||
.rx = rx,
|
||||
.build_header = build_header,
|
||||
.prepare_tx = prepare_tx,
|
||||
.ack_tx = ack_tx
|
||||
};
|
||||
|
||||
static void arcnet_cap_init(void)
|
||||
static int __init capmode_module_init(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
pr_info("cap mode (`c') encapsulation support loaded\n");
|
||||
|
||||
for (count = 1; count <= 8; count++)
|
||||
if (arc_proto_map[count] == arc_proto_default)
|
||||
arc_proto_map[count] = &capmode_proto;
|
||||
|
@ -255,12 +254,7 @@ static void arcnet_cap_init(void)
|
|||
|
||||
arc_proto_default = &capmode_proto;
|
||||
arc_raw_proto = &capmode_proto;
|
||||
}
|
||||
|
||||
static int __init capmode_module_init(void)
|
||||
{
|
||||
printk(VERSION);
|
||||
arcnet_cap_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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>.
|
||||
|
@ -25,6 +25,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -36,16 +39,12 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/arcdevice.h>
|
||||
#include <linux/com20020.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include "arcdevice.h"
|
||||
#include "com20020.h"
|
||||
|
||||
#define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n"
|
||||
|
||||
|
||||
/*
|
||||
* We cannot (yet) probe for an IO mapped card, although we can check that
|
||||
/* 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)
|
||||
|
@ -55,21 +54,21 @@ static int __init com20020isa_probe(struct net_device *dev)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
if (BUGLVL(D_NORMAL))
|
||||
pr_info("%s\n", "COM20020 ISA support (by David Woodhouse et al.)");
|
||||
|
||||
ioaddr = dev->base_addr;
|
||||
if (!ioaddr) {
|
||||
BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you "
|
||||
"must specify the base address!\n");
|
||||
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)")) {
|
||||
BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n",
|
||||
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
|
||||
arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n",
|
||||
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
|
||||
return -ENXIO;
|
||||
}
|
||||
if (ASTATUS() == 0xFF) {
|
||||
BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr);
|
||||
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
|
||||
arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr);
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
@ -83,23 +82,24 @@ static int __init com20020isa_probe(struct net_device *dev)
|
|||
* card has just reset and the NORXflag is on until
|
||||
* we tell it to start receiving.
|
||||
*/
|
||||
BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK));
|
||||
outb(0, _INTMASK);
|
||||
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();
|
||||
outb(NORXflag, _INTMASK);
|
||||
arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
|
||||
udelay(1);
|
||||
outb(0, _INTMASK);
|
||||
arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
|
||||
dev->irq = probe_irq_off(airqmask);
|
||||
|
||||
if ((int)dev->irq <= 0) {
|
||||
BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n");
|
||||
arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n");
|
||||
airqmask = probe_irq_on();
|
||||
outb(NORXflag, _INTMASK);
|
||||
arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK);
|
||||
udelay(5);
|
||||
outb(0, _INTMASK);
|
||||
arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK);
|
||||
dev->irq = probe_irq_off(airqmask);
|
||||
if ((int)dev->irq <= 0) {
|
||||
BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n");
|
||||
arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n");
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
@ -107,7 +107,9 @@ static int __init com20020isa_probe(struct net_device *dev)
|
|||
}
|
||||
|
||||
lp->card_name = "ISA COM20020";
|
||||
if ((err = com20020_found(dev, 0)) != 0)
|
||||
|
||||
err = com20020_found(dev, 0);
|
||||
if (err != 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
@ -194,7 +196,7 @@ static int __init com20020isa_setup(char *s)
|
|||
|
||||
switch (ints[0]) {
|
||||
default: /* ERROR */
|
||||
printk("com90xx: Too many arguments.\n");
|
||||
pr_info("Too many arguments\n");
|
||||
case 6: /* Timeout */
|
||||
timeout = ints[6];
|
||||
case 5: /* CKP value */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Linux ARCnet driver - COM20020 PCI support
|
||||
* Contemporary Controls PCI20 and SOHARD SH-ARC PCI
|
||||
*
|
||||
*
|
||||
* Written 1994-1999 by Avery Pennarun,
|
||||
* based on an ISA version by David Woodhouse.
|
||||
* Written 1999-2000 by Martin Mares <mj@ucw.cz>.
|
||||
|
@ -26,6 +26,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -36,14 +39,11 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/arcdevice.h>
|
||||
#include <linux/com20020.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
|
||||
#define VERSION "arcnet: COM20020 PCI support\n"
|
||||
#include "arcdevice.h"
|
||||
#include "com20020.h"
|
||||
|
||||
/* Module parameters */
|
||||
|
||||
|
@ -64,7 +64,8 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static void com20020pci_remove(struct pci_dev *pdev);
|
||||
|
||||
static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
static int com20020pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct com20020_pci_card_info *ci;
|
||||
struct net_device *dev;
|
||||
|
@ -86,7 +87,6 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||
|
||||
INIT_LIST_HEAD(&priv->list_dev);
|
||||
|
||||
|
||||
for (i = 0; i < ci->devcount; i++) {
|
||||
struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
|
||||
struct com20020_dev *card;
|
||||
|
@ -101,13 +101,13 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||
|
||||
lp = netdev_priv(dev);
|
||||
|
||||
BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
|
||||
arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
|
||||
ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
|
||||
|
||||
r = devm_request_region(&pdev->dev, ioaddr, cm->size,
|
||||
"com20020-pci");
|
||||
if (!r) {
|
||||
pr_err("IO region %xh-%xh already allocated.\n",
|
||||
pr_err("IO region %xh-%xh already allocated\n",
|
||||
ioaddr, ioaddr + cm->size - 1);
|
||||
ret = -EBUSY;
|
||||
goto out_port;
|
||||
|
@ -117,8 +117,8 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||
* ARCNET controller needs
|
||||
* this access to detect bustype
|
||||
*/
|
||||
outb(0x00, ioaddr + 1);
|
||||
inb(ioaddr + 1);
|
||||
arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
|
||||
arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
dev->dev_addr[0] = node;
|
||||
|
@ -131,7 +131,7 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||
lp->timeout = timeout;
|
||||
lp->hw.owner = THIS_MODULE;
|
||||
|
||||
if (ASTATUS() == 0xFF) {
|
||||
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
|
||||
pr_err("IO address %Xh is empty!\n", ioaddr);
|
||||
ret = -EIO;
|
||||
goto out_port;
|
||||
|
@ -143,10 +143,8 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
|||
|
||||
card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
|
||||
GFP_KERNEL);
|
||||
if (!card) {
|
||||
pr_err("%s out of memory!\n", __func__);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
card->index = i;
|
||||
card->pci_priv = priv;
|
||||
|
@ -190,7 +188,11 @@ static struct com20020_pci_card_info card_info_10mbit = {
|
|||
.name = "ARC-PCI",
|
||||
.devcount = 1,
|
||||
.chan_map_tbl = {
|
||||
{ 2, 0x00, 0x08 },
|
||||
{
|
||||
.bar = 2,
|
||||
.offset = 0x00,
|
||||
.size = 0x08,
|
||||
},
|
||||
},
|
||||
.flags = ARC_CAN_10MBIT,
|
||||
};
|
||||
|
@ -199,7 +201,11 @@ static struct com20020_pci_card_info card_info_5mbit = {
|
|||
.name = "ARC-PCI",
|
||||
.devcount = 1,
|
||||
.chan_map_tbl = {
|
||||
{ 2, 0x00, 0x08 },
|
||||
{
|
||||
.bar = 2,
|
||||
.offset = 0x00,
|
||||
.size = 0x08,
|
||||
},
|
||||
},
|
||||
.flags = ARC_IS_5MBIT,
|
||||
};
|
||||
|
@ -209,7 +215,11 @@ static struct com20020_pci_card_info card_info_sohard = {
|
|||
.devcount = 1,
|
||||
/* SOHARD needs PCI base addr 4 */
|
||||
.chan_map_tbl = {
|
||||
{4, 0x00, 0x08},
|
||||
{
|
||||
.bar = 4,
|
||||
.offset = 0x00,
|
||||
.size = 0x08
|
||||
},
|
||||
},
|
||||
.flags = ARC_CAN_10MBIT,
|
||||
};
|
||||
|
@ -218,7 +228,11 @@ static struct com20020_pci_card_info card_info_eae_arc1 = {
|
|||
.name = "EAE PLX-PCI ARC1",
|
||||
.devcount = 1,
|
||||
.chan_map_tbl = {
|
||||
{ 2, 0x00, 0x08 },
|
||||
{
|
||||
.bar = 2,
|
||||
.offset = 0x00,
|
||||
.size = 0x08,
|
||||
},
|
||||
},
|
||||
.flags = ARC_CAN_10MBIT,
|
||||
};
|
||||
|
@ -227,8 +241,15 @@ static struct com20020_pci_card_info card_info_eae_ma1 = {
|
|||
.name = "EAE PLX-PCI MA1",
|
||||
.devcount = 2,
|
||||
.chan_map_tbl = {
|
||||
{ 2, 0x00, 0x08 },
|
||||
{ 2, 0x08, 0x08 }
|
||||
{
|
||||
.bar = 2,
|
||||
.offset = 0x00,
|
||||
.size = 0x08,
|
||||
}, {
|
||||
.bar = 2,
|
||||
.offset = 0x08,
|
||||
.size = 0x08,
|
||||
}
|
||||
},
|
||||
.flags = ARC_CAN_10MBIT,
|
||||
};
|
||||
|
@ -404,7 +425,8 @@ static struct pci_driver com20020pci_driver = {
|
|||
|
||||
static int __init com20020pci_init(void)
|
||||
{
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
if (BUGLVL(D_NORMAL))
|
||||
pr_info("%s\n", "COM20020 PCI support");
|
||||
return pci_register_driver(&com20020pci_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux ARCnet driver - COM20020 chipset support
|
||||
*
|
||||
*
|
||||
* Written 1997 by David Woodhouse.
|
||||
* Written 1994-1999 by Avery Pennarun.
|
||||
* Written 1999 by Martin Mares <mj@ucw.cz>.
|
||||
|
@ -25,6 +25,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -34,17 +37,16 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/arcdevice.h>
|
||||
#include <linux/com20020.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include "arcdevice.h"
|
||||
#include "com20020.h"
|
||||
|
||||
#define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n"
|
||||
|
||||
static char *clockrates[] =
|
||||
{"10 Mb/s", "Reserved", "5 Mb/s",
|
||||
"2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s",
|
||||
"156.25 Kb/s", "Reserved", "Reserved", "Reserved"};
|
||||
static const char * const clockrates[] = {
|
||||
"XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s",
|
||||
"1.25Mb/s", "625 Kb/s", "312.5 Kb/s", "156.25 Kb/s",
|
||||
"Reserved", "Reserved", "Reserved"
|
||||
};
|
||||
|
||||
static void com20020_command(struct net_device *dev, int command);
|
||||
static int com20020_status(struct net_device *dev);
|
||||
|
@ -63,35 +65,38 @@ 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 */
|
||||
outb((ofs >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
|
||||
outb(ofs & 0xff, _ADDR_LO);
|
||||
arcnet_outb((ofs >> 8) | RDDATAflag | AUTOINCflag,
|
||||
ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
|
||||
/* copy the data */
|
||||
TIME("insb", count, insb(_MEMDATA, buf, count));
|
||||
TIME(dev, "insb", count,
|
||||
arcnet_insb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
|
||||
}
|
||||
|
||||
|
||||
static void com20020_copy_to_card(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count)
|
||||
{
|
||||
int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
|
||||
|
||||
/* set up the address register */
|
||||
outb((ofs >> 8) | AUTOINCflag, _ADDR_HI);
|
||||
outb(ofs & 0xff, _ADDR_LO);
|
||||
arcnet_outb((ofs >> 8) | AUTOINCflag, ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
|
||||
/* copy the data */
|
||||
TIME("outsb", count, outsb(_MEMDATA, buf, count));
|
||||
TIME(dev, "outsb", count,
|
||||
arcnet_outsb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count));
|
||||
}
|
||||
|
||||
|
||||
/* Reset the card and check some basic stuff during the detection stage. */
|
||||
int com20020_check(struct net_device *dev)
|
||||
{
|
||||
int ioaddr = dev->base_addr, status;
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
|
||||
ARCRESET0;
|
||||
arcnet_outb(XTOcfg(3) | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
|
||||
udelay(5);
|
||||
arcnet_outb(XTOcfg(3), ioaddr, COM20020_REG_W_CONFIG);
|
||||
mdelay(RESETtime);
|
||||
|
||||
lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
|
||||
|
@ -101,49 +106,51 @@ int com20020_check(struct net_device *dev)
|
|||
/* Enable P1Mode for backplane mode */
|
||||
lp->setup = lp->setup | P1MODE;
|
||||
|
||||
SET_SUBADR(SUB_SETUP1);
|
||||
outb(lp->setup, _XREG);
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
arcnet_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);
|
||||
|
||||
if (lp->clockm != 0)
|
||||
{
|
||||
SET_SUBADR(SUB_SETUP2);
|
||||
outb(lp->setup2, _XREG);
|
||||
|
||||
/* must now write the magic "restart operation" command */
|
||||
mdelay(1);
|
||||
outb(0x18, _COMMAND);
|
||||
arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2);
|
||||
lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
|
||||
/* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
|
||||
SETCONF;
|
||||
outb(0x42, ioaddr + BUS_ALIGN*7);
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
status = ASTATUS();
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
|
||||
|
||||
if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) {
|
||||
BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status);
|
||||
arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status);
|
||||
return -ENODEV;
|
||||
}
|
||||
BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status);
|
||||
arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status);
|
||||
|
||||
/* Enable TX */
|
||||
outb(0x39, _CONFIG);
|
||||
outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7);
|
||||
lp->config |= TXENcfg;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
arcnet_outb(arcnet_inb(ioaddr, 8), ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
|
||||
|
||||
status = ASTATUS();
|
||||
BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n",
|
||||
status);
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM20020_REG_W_COMMAND);
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
|
||||
arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n",
|
||||
status);
|
||||
|
||||
/* Read first location of memory */
|
||||
outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI);
|
||||
outb(0, _ADDR_LO);
|
||||
arcnet_outb(0 | RDDATAflag | AUTOINCflag,
|
||||
ioaddr, COM20020_REG_W_ADDR_HI);
|
||||
arcnet_outb(0, ioaddr, COM20020_REG_W_ADDR_LO);
|
||||
|
||||
if ((status = inb(_MEMDATA)) != TESTvalue) {
|
||||
BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n",
|
||||
status);
|
||||
status = arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA);
|
||||
if (status != TESTvalue) {
|
||||
arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n",
|
||||
status);
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
|
@ -156,8 +163,8 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr)
|
|||
struct sockaddr *hwaddr = addr;
|
||||
|
||||
memcpy(dev->dev_addr, hwaddr->sa_data, 1);
|
||||
SET_SUBADR(SUB_NODE);
|
||||
outb(dev->dev_addr[0], _XREG);
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_NODE);
|
||||
arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -192,48 +199,54 @@ int com20020_found(struct net_device *dev, int shared)
|
|||
lp->hw.copy_from_card = com20020_copy_from_card;
|
||||
lp->hw.close = com20020_close;
|
||||
|
||||
/* FIXME: do this some other way! */
|
||||
if (!dev->dev_addr[0])
|
||||
dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */
|
||||
dev->dev_addr[0] = arcnet_inb(ioaddr, 8);
|
||||
|
||||
SET_SUBADR(SUB_SETUP1);
|
||||
outb(lp->setup, _XREG);
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
arcnet_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);
|
||||
|
||||
if (lp->card_flags & ARC_CAN_10MBIT)
|
||||
{
|
||||
SET_SUBADR(SUB_SETUP2);
|
||||
outb(lp->setup2, _XREG);
|
||||
|
||||
/* must now write the magic "restart operation" command */
|
||||
mdelay(1);
|
||||
outb(0x18, _COMMAND);
|
||||
arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1;
|
||||
lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
|
||||
/* Default 0x38 + register: Node ID */
|
||||
SETCONF;
|
||||
outb(dev->dev_addr[0], _XREG);
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
/* reserve the irq */
|
||||
if (request_irq(dev->irq, arcnet_interrupt, shared,
|
||||
"arcnet (COM20020)", dev)) {
|
||||
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
|
||||
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
|
||||
BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
|
||||
lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
|
||||
arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
|
||||
lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
|
||||
|
||||
if (lp->backplane)
|
||||
BUGMSG(D_NORMAL, "Using backplane mode.\n");
|
||||
arc_printk(D_NORMAL, dev, "Using backplane mode.\n");
|
||||
|
||||
if (lp->timeout != 3)
|
||||
BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout);
|
||||
arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n",
|
||||
lp->timeout);
|
||||
|
||||
BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
|
||||
lp->setup >> 1,
|
||||
clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
|
||||
arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n",
|
||||
lp->setup >> 1,
|
||||
clockrates[3 -
|
||||
((lp->setup2 & 0xF0) >> 4) +
|
||||
((lp->setup & 0x0F) >> 1)]);
|
||||
/* The clockrates array index looks very fragile.
|
||||
* It seems like it could have negative indexing.
|
||||
*/
|
||||
|
||||
if (register_netdev(dev)) {
|
||||
free_irq(dev->irq, dev);
|
||||
|
@ -242,10 +255,8 @@ int com20020_found(struct net_device *dev, int shared)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do a hardware reset on the card, and set up necessary registers.
|
||||
*
|
||||
/* 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.
|
||||
*
|
||||
|
@ -257,65 +268,71 @@ static int com20020_reset(struct net_device *dev, int really_reset)
|
|||
u_int ioaddr = dev->base_addr;
|
||||
u_char inbyte;
|
||||
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n",
|
||||
__FILE__,__LINE__,__func__,dev,lp,dev->name);
|
||||
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
|
||||
dev->name, ASTATUS());
|
||||
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));
|
||||
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
|
||||
/* power-up defaults */
|
||||
SETCONF;
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
arcnet_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 */
|
||||
ARCRESET;
|
||||
mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */
|
||||
arcnet_outb(lp->config | RESETcfg, ioaddr, COM20020_REG_W_CONFIG);
|
||||
udelay(5);
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
mdelay(RESETtime * 2);
|
||||
/* COM20020 seems to be slower sometimes */
|
||||
}
|
||||
/* clear flags & end reset */
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM20020_REG_W_COMMAND);
|
||||
|
||||
/* verify that the ARCnet signature byte is present */
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
|
||||
com20020_copy_from_card(dev, 0, 0, &inbyte, 1);
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
if (inbyte != TESTvalue) {
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
|
||||
return 1;
|
||||
}
|
||||
/* enable extended (512-byte) packets */
|
||||
ACOMMAND(CONFIGcmd | EXTconf);
|
||||
BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
|
||||
arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM20020_REG_W_COMMAND);
|
||||
|
||||
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
|
||||
|
||||
/* done! return success. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void com20020_setmask(struct net_device *dev, int mask)
|
||||
{
|
||||
u_int ioaddr = dev->base_addr;
|
||||
BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr);
|
||||
AINTMASK(mask);
|
||||
}
|
||||
|
||||
arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr);
|
||||
arcnet_outb(mask, ioaddr, COM20020_REG_W_INTMASK);
|
||||
}
|
||||
|
||||
static void com20020_command(struct net_device *dev, int cmd)
|
||||
{
|
||||
u_int ioaddr = dev->base_addr;
|
||||
ACOMMAND(cmd);
|
||||
}
|
||||
|
||||
arcnet_outb(cmd, ioaddr, COM20020_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
static int com20020_status(struct net_device *dev)
|
||||
{
|
||||
u_int ioaddr = dev->base_addr;
|
||||
|
||||
return ASTATUS() + (ADIAGSTATUS()<<8);
|
||||
return arcnet_inb(ioaddr, COM20020_REG_R_STATUS) +
|
||||
(arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT) << 8);
|
||||
}
|
||||
|
||||
static void com20020_close(struct net_device *dev)
|
||||
|
@ -325,7 +342,7 @@ static void com20020_close(struct net_device *dev)
|
|||
|
||||
/* disable transmitter */
|
||||
lp->config &= ~TXENcfg;
|
||||
SETCONF;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
}
|
||||
|
||||
/* Set or clear the multicast filter for this adaptor.
|
||||
|
@ -340,20 +357,20 @@ static void com20020_set_mc_list(struct net_device *dev)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */
|
||||
if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) {
|
||||
/* Enable promiscuous mode */
|
||||
if (!(lp->setup & PROMISCset))
|
||||
BUGMSG(D_NORMAL, "Setting promiscuous flag...\n");
|
||||
SET_SUBADR(SUB_SETUP1);
|
||||
arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n");
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
lp->setup |= PROMISCset;
|
||||
outb(lp->setup, _XREG);
|
||||
} else
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
} else {
|
||||
/* Disable promiscuous mode, use normal mode */
|
||||
{
|
||||
if ((lp->setup & PROMISCset))
|
||||
BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n");
|
||||
SET_SUBADR(SUB_SETUP1);
|
||||
arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n");
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
lp->setup &= ~PROMISCset;
|
||||
outb(lp->setup, _XREG);
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,7 +388,8 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init com20020_module_init(void)
|
||||
{
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
if (BUGLVL(D_NORMAL))
|
||||
pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux ARCnet driver - COM20020 chipset support - function declarations
|
||||
*
|
||||
*
|
||||
* Written 1997 by David Woodhouse.
|
||||
* Written 1994-1999 by Avery Pennarun.
|
||||
* Derived from skeleton.c by Donald Becker.
|
||||
|
@ -34,13 +34,6 @@ extern const struct net_device_ops com20020_netdev_ops;
|
|||
/* The number of low I/O ports used by the card. */
|
||||
#define ARCNET_TOTAL_SIZE 8
|
||||
|
||||
/* various register addresses */
|
||||
#ifdef CONFIG_SA1100_CT6001
|
||||
#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */
|
||||
#else
|
||||
#define BUS_ALIGN 1
|
||||
#endif
|
||||
|
||||
#define PLX_PCI_MAX_CARDS 2
|
||||
|
||||
struct com20020_pci_channel_map {
|
||||
|
@ -71,17 +64,18 @@ struct com20020_dev {
|
|||
int index;
|
||||
};
|
||||
|
||||
#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */
|
||||
#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */
|
||||
#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */
|
||||
#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */
|
||||
#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */
|
||||
#define _ADDR_LO (ioaddr+BUS_ALIGN*3)
|
||||
#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */
|
||||
#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */
|
||||
#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */
|
||||
#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG
|
||||
or _SUBADR) */
|
||||
#define COM20020_REG_W_INTMASK 0 /* writable */
|
||||
#define COM20020_REG_R_STATUS 0 /* readable */
|
||||
#define COM20020_REG_W_COMMAND 1 /* standard arcnet commands */
|
||||
#define COM20020_REG_R_DIAGSTAT 1 /* diagnostic status */
|
||||
#define COM20020_REG_W_ADDR_HI 2 /* control for IO-mapped memory */
|
||||
#define COM20020_REG_W_ADDR_LO 3
|
||||
#define COM20020_REG_RW_MEMDATA 4 /* data port for IO-mapped memory */
|
||||
#define COM20020_REG_W_SUBADR 5 /* the extended port _XREG refers to */
|
||||
#define COM20020_REG_W_CONFIG 6 /* configuration */
|
||||
#define COM20020_REG_W_XREG 7 /* extra
|
||||
* (indexed by _CONFIG or _SUBADDR)
|
||||
*/
|
||||
|
||||
/* in the ADDR_HI register */
|
||||
#define RDDATAflag 0x80 /* next access is a read (not a write) */
|
||||
|
@ -92,6 +86,7 @@ struct com20020_dev {
|
|||
/* in the CONFIG register */
|
||||
#define RESETcfg 0x80 /* put card in reset state */
|
||||
#define TXENcfg 0x20 /* enable TX */
|
||||
#define XTOcfg(x) ((x) << 3) /* extended timeout */
|
||||
|
||||
/* in SETUP register */
|
||||
#define PROMISCset 0x10 /* enable RCV_ALL */
|
||||
|
@ -109,37 +104,15 @@ struct com20020_dev {
|
|||
#define SUB_BUSCTL 5 /* bus control options */
|
||||
#define SUB_DMACOUNT 6 /* DMA count options */
|
||||
|
||||
#define SET_SUBADR(x) do { \
|
||||
if ((x) < 4) \
|
||||
{ \
|
||||
lp->config = (lp->config & ~0x03) | (x); \
|
||||
SETCONF; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
outb(x, _SUBADR); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#undef ARCRESET
|
||||
#undef ASTATUS
|
||||
#undef ACOMMAND
|
||||
#undef AINTMASK
|
||||
|
||||
#define ARCRESET { outb(lp->config | 0x80, _CONFIG); \
|
||||
udelay(5); \
|
||||
outb(lp->config , _CONFIG); \
|
||||
}
|
||||
#define ARCRESET0 { outb(0x18 | 0x80, _CONFIG); \
|
||||
udelay(5); \
|
||||
outb(0x18 , _CONFIG); \
|
||||
}
|
||||
|
||||
#define ASTATUS() inb(_STATUS)
|
||||
#define ADIAGSTATUS() inb(_DIAGSTAT)
|
||||
#define ACOMMAND(cmd) outb((cmd),_COMMAND)
|
||||
#define AINTMASK(msk) outb((msk),_INTMASK)
|
||||
|
||||
#define SETCONF outb(lp->config, _CONFIG)
|
||||
static inline void com20020_set_subaddress(struct arcnet_local *lp,
|
||||
int ioaddr, int val)
|
||||
{
|
||||
if (val < 4) {
|
||||
lp->config = (lp->config & ~0x03) | val;
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
} else {
|
||||
arcnet_outb(val, ioaddr, COM20020_REG_W_SUBADR);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __COM20020_H */
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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)
|
||||
|
@ -19,18 +19,21 @@
|
|||
* 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>
|
||||
|
@ -39,52 +42,45 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/arcdevice.h>
|
||||
#include <linux/com20020.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
|
||||
|
||||
#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 = ioaddr; count < ioaddr + 16; count++)
|
||||
{
|
||||
if (!(count % 16))
|
||||
pr_cont("%04X:", count);
|
||||
pr_cont(" %02X", inb(count));
|
||||
}
|
||||
pr_cont("\n");
|
||||
|
||||
netdev_dbg(dev, "buffer0 dump:\n");
|
||||
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;
|
||||
outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
|
||||
outb(count & 0xff, _ADDR_LO);
|
||||
|
||||
for (count = 0; count < 256+32; count++)
|
||||
{
|
||||
if (!(count % 16))
|
||||
pr_cont("%04X:", count);
|
||||
|
||||
/* copy the data */
|
||||
pr_cont(" %02X", inb(_MEMDATA));
|
||||
}
|
||||
pr_cont("\n");
|
||||
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' */
|
||||
|
@ -114,169 +110,161 @@ 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;
|
||||
struct com20020_dev *info;
|
||||
struct net_device *dev;
|
||||
struct arcnet_local *lp;
|
||||
|
||||
dev_dbg(&p_dev->dev, "com20020_attach()\n");
|
||||
dev_dbg(&p_dev->dev, "com20020_attach()\n");
|
||||
|
||||
/* Create new network device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto fail_alloc_info;
|
||||
/* Create new network device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto fail_alloc_info;
|
||||
|
||||
dev = alloc_arcdev("");
|
||||
if (!dev)
|
||||
goto fail_alloc_dev;
|
||||
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;
|
||||
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 */
|
||||
dev->dev_addr[0] = node;
|
||||
/* fill in our module parameters as defaults */
|
||||
dev->dev_addr[0] = node;
|
||||
|
||||
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
p_dev->resource[0]->end = 16;
|
||||
p_dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
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;
|
||||
info->dev = dev;
|
||||
p_dev->priv = info;
|
||||
|
||||
return com20020_config(p_dev);
|
||||
return com20020_config(p_dev);
|
||||
|
||||
fail_alloc_dev:
|
||||
kfree(info);
|
||||
kfree(info);
|
||||
fail_alloc_info:
|
||||
return -ENOMEM;
|
||||
return -ENOMEM;
|
||||
} /* com20020_attach */
|
||||
|
||||
static void com20020_detach(struct pcmcia_device *link)
|
||||
{
|
||||
struct com20020_dev *info = link->priv;
|
||||
struct net_device *dev = info->dev;
|
||||
struct com20020_dev *info = link->priv;
|
||||
struct net_device *dev = info->dev;
|
||||
|
||||
dev_dbg(&link->dev, "detach...\n");
|
||||
dev_dbg(&link->dev, "detach...\n");
|
||||
|
||||
dev_dbg(&link->dev, "com20020_detach\n");
|
||||
dev_dbg(&link->dev, "com20020_detach\n");
|
||||
|
||||
dev_dbg(&link->dev, "unregister...\n");
|
||||
dev_dbg(&link->dev, "unregister...\n");
|
||||
|
||||
unregister_netdev(dev);
|
||||
unregister_netdev(dev);
|
||||
|
||||
/*
|
||||
* this is necessary because we register our IRQ separately
|
||||
* from card services.
|
||||
*/
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
/* this is necessary because we register our IRQ separately
|
||||
* from card services.
|
||||
*/
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
com20020_release(link);
|
||||
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_netdev(dev);
|
||||
/* 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_netdev(dev);
|
||||
}
|
||||
dev_dbg(&link->dev, "kfree2...\n");
|
||||
kfree(info);
|
||||
}
|
||||
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;
|
||||
struct arcnet_local *lp;
|
||||
struct com20020_dev *info;
|
||||
struct net_device *dev;
|
||||
int i, ret;
|
||||
int ioaddr;
|
||||
|
||||
info = link->priv;
|
||||
dev = info->dev;
|
||||
info = link->priv;
|
||||
dev = info->dev;
|
||||
|
||||
dev_dbg(&link->dev, "config...\n");
|
||||
dev_dbg(&link->dev, "config...\n");
|
||||
|
||||
dev_dbg(&link->dev, "com20020_config\n");
|
||||
dev_dbg(&link->dev, "com20020_config\n");
|
||||
|
||||
dev_dbg(&link->dev, "baseport1 is %Xh\n",
|
||||
(unsigned int) link->resource[0]->start);
|
||||
dev_dbg(&link->dev, "baseport1 is %Xh\n",
|
||||
(unsigned int)link->resource[0]->start);
|
||||
|
||||
i = -ENODEV;
|
||||
link->io_lines = 16;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (i != 0) {
|
||||
dev_dbg(&link->dev, "requestIO failed totally!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
dev->irq = link->irq;
|
||||
ioaddr = dev->base_addr = link->resource[0]->start;
|
||||
dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
|
||||
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret)
|
||||
goto failed;
|
||||
dev_dbg(&link->dev, "request IRQ %d\n",
|
||||
link->irq);
|
||||
if (!link->irq) {
|
||||
dev_dbg(&link->dev, "requestIRQ failed totally!\n");
|
||||
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 */
|
||||
dev->irq = link->irq;
|
||||
|
||||
SET_NETDEV_DEV(dev, &link->dev);
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
i = com20020_found(dev, 0); /* calls register_netdev */
|
||||
|
||||
if (i != 0) {
|
||||
dev_notice(&link->dev,
|
||||
"com20020_found() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
if (com20020_check(dev)) {
|
||||
regdump(dev);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
netdev_dbg(dev, "port %#3lx, irq %d\n",
|
||||
dev->base_addr, dev->irq);
|
||||
return 0;
|
||||
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;
|
||||
dev_dbg(&link->dev, "com20020_config failed...\n");
|
||||
com20020_release(link);
|
||||
return -ENODEV;
|
||||
} /* com20020_config */
|
||||
|
||||
static void com20020_release(struct pcmcia_device *link)
|
||||
|
@ -304,7 +292,10 @@ static int com20020_resume(struct pcmcia_device *link)
|
|||
if (link->open) {
|
||||
int ioaddr = dev->base_addr;
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
ARCRESET;
|
||||
|
||||
arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
|
||||
udelay(5);
|
||||
arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -312,9 +303,9 @@ static int com20020_resume(struct pcmcia_device *link)
|
|||
|
||||
static const struct pcmcia_device_id com20020_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
|
||||
"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
|
||||
"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
|
||||
PCMCIA_DEVICE_PROD_ID12("SoHard AG",
|
||||
"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
|
||||
"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
|
||||
PCMCIA_DEVICE_NULL
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
|
||||
|
|
17
drivers/net/arcnet/com9026.h
Normal file
17
drivers/net/arcnet/com9026.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef __COM9026_H
|
||||
#define __COM9026_H
|
||||
|
||||
/* COM 9026 controller chip --> ARCnet register addresses */
|
||||
|
||||
#define COM9026_REG_W_INTMASK 0 /* writable */
|
||||
#define COM9026_REG_R_STATUS 0 /* readable */
|
||||
#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */
|
||||
#define COM9026_REG_RW_CONFIG 2 /* Configuration register */
|
||||
#define COM9026_REG_R_RESET 8 /* software reset (on read) */
|
||||
#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */
|
||||
#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */
|
||||
#define COM9026_REG_W_ADDR_HI 15
|
||||
|
||||
#define COM9026_REG_R_STATION 1 /* Station ID */
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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>.
|
||||
|
@ -25,6 +25,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -34,12 +37,10 @@
|
|||
#include <linux/bootmem.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
|
||||
#define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n"
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "arcdevice.h"
|
||||
#include "com9026.h"
|
||||
|
||||
/* Internal function declarations */
|
||||
|
||||
|
@ -50,35 +51,14 @@ 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);
|
||||
|
||||
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
|
||||
|
||||
/* COM 9026 controller chip --> ARCnet register addresses */
|
||||
#define _INTMASK (ioaddr+0) /* writable */
|
||||
#define _STATUS (ioaddr+0) /* readable */
|
||||
#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
|
||||
#define _RESET (ioaddr+8) /* software reset (on read) */
|
||||
#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
|
||||
#define _ADDR_HI (ioaddr+15) /* Control registers for said */
|
||||
#define _ADDR_LO (ioaddr+14)
|
||||
#define _CONFIG (ioaddr+2) /* Configuration register */
|
||||
|
||||
#undef ASTATUS
|
||||
#undef ACOMMAND
|
||||
#undef AINTMASK
|
||||
|
||||
#define ASTATUS() inb(_STATUS)
|
||||
#define ACOMMAND(cmd) outb((cmd),_COMMAND)
|
||||
#define AINTMASK(msk) outb((msk),_INTMASK)
|
||||
#define SETCONF() outb((lp->config),_CONFIG)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* *
|
||||
* IO-mapped operation routines *
|
||||
|
@ -92,58 +72,59 @@ static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
|
|||
{
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
outb(offset >> 8, _ADDR_HI);
|
||||
outb(offset & 0xff, _ADDR_LO);
|
||||
arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
|
||||
arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
|
||||
|
||||
return inb(_MEMDATA);
|
||||
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)
|
||||
static void put_buffer_byte(struct net_device *dev, unsigned offset,
|
||||
u_char datum)
|
||||
{
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
outb(offset >> 8, _ADDR_HI);
|
||||
outb(offset & 0xff, _ADDR_LO);
|
||||
arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
|
||||
arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
|
||||
|
||||
outb(datum, _MEMDATA);
|
||||
arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
|
||||
static void get_whole_buffer(struct net_device *dev, unsigned offset,
|
||||
unsigned length, char *dest)
|
||||
{
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
|
||||
outb(offset & 0xff, _ADDR_LO);
|
||||
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++) = inb(_MEMDATA);
|
||||
*(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
|
||||
static void put_whole_buffer(struct net_device *dev, unsigned offset,
|
||||
unsigned length, char *dest)
|
||||
{
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
|
||||
outb(offset & 0xff, _ADDR_LO);
|
||||
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
|
||||
outb(*(dest++), _MEMDATA);
|
||||
arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We cannot probe for an IO mapped card either, although we can check that
|
||||
/* 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)
|
||||
|
@ -151,71 +132,78 @@ static int __init com90io_probe(struct net_device *dev)
|
|||
int ioaddr = dev->base_addr, status;
|
||||
unsigned long airqmask;
|
||||
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n");
|
||||
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) {
|
||||
BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you "
|
||||
"must specify the base address!\n");
|
||||
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")) {
|
||||
BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
|
||||
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
|
||||
arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n",
|
||||
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
|
||||
return -ENXIO;
|
||||
}
|
||||
if (ASTATUS() == 0xFF) {
|
||||
BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr);
|
||||
if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
|
||||
arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n",
|
||||
ioaddr);
|
||||
goto err_out;
|
||||
}
|
||||
inb(_RESET);
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
mdelay(RESETtime);
|
||||
|
||||
status = ASTATUS();
|
||||
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
|
||||
if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
|
||||
BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status);
|
||||
arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n",
|
||||
status);
|
||||
goto err_out;
|
||||
}
|
||||
BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status);
|
||||
arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status);
|
||||
|
||||
ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM9026_REG_W_COMMAND);
|
||||
|
||||
BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status);
|
||||
arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n",
|
||||
status);
|
||||
|
||||
status = ASTATUS();
|
||||
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
|
||||
if (status & RESETflag) {
|
||||
BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status);
|
||||
arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n",
|
||||
status);
|
||||
goto err_out;
|
||||
}
|
||||
outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG);
|
||||
arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag,
|
||||
ioaddr, COM9026_REG_RW_CONFIG);
|
||||
|
||||
/* Read first loc'n of memory */
|
||||
|
||||
outb(AUTOINCflag, _ADDR_HI);
|
||||
outb(0, _ADDR_LO);
|
||||
arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
|
||||
arcnet_outb(0, ioaddr, COM9026_REG_W_ADDR_LO);
|
||||
|
||||
if ((status = inb(_MEMDATA)) != 0xd1) {
|
||||
BUGMSG(D_INIT_REASONS, "Signature byte not found"
|
||||
" (%Xh instead).\n", status);
|
||||
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
|
||||
/* 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();
|
||||
outb(NORXflag, _INTMASK);
|
||||
arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
|
||||
udelay(1);
|
||||
outb(0, _INTMASK);
|
||||
arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
|
||||
dev->irq = probe_irq_off(airqmask);
|
||||
|
||||
if ((int)dev->irq <= 0) {
|
||||
BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n");
|
||||
arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +215,6 @@ err_out:
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/* Set up the struct net_device associated with this card. Called after
|
||||
* probing succeeds.
|
||||
*/
|
||||
|
@ -238,12 +225,14 @@ static int __init com90io_found(struct net_device *dev)
|
|||
int err;
|
||||
|
||||
/* Reserve the irq */
|
||||
if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) {
|
||||
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->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)")) {
|
||||
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE,
|
||||
"arcnet (COM90xx-IO)")) {
|
||||
free_irq(dev->irq, dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -259,7 +248,7 @@ static int __init com90io_found(struct net_device *dev)
|
|||
lp->hw.copy_from_card = com90io_copy_from_card;
|
||||
|
||||
lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
|
||||
SETCONF();
|
||||
arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
|
||||
|
||||
/* get and check the station ID from offset 1 in shmem */
|
||||
|
||||
|
@ -267,21 +256,20 @@ static int __init com90io_found(struct net_device *dev)
|
|||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
|
||||
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;
|
||||
}
|
||||
|
||||
BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
|
||||
dev->dev_addr[0], dev->base_addr, dev->irq);
|
||||
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.
|
||||
/* 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.
|
||||
|
@ -293,67 +281,66 @@ static int com90io_reset(struct net_device *dev, int really_reset)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
|
||||
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 */
|
||||
inb(_RESET);
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
mdelay(RESETtime);
|
||||
}
|
||||
/* Set the thing to IO-mapped, 8-bit mode */
|
||||
lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
|
||||
SETCONF();
|
||||
arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
|
||||
|
||||
ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
|
||||
ACOMMAND(CFLAGScmd | CONFIGclear);
|
||||
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) {
|
||||
BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
|
||||
arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
|
||||
return 1;
|
||||
}
|
||||
/* enable extended (512-byte) packets */
|
||||
ACOMMAND(CONFIGcmd | EXTconf);
|
||||
|
||||
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;
|
||||
|
||||
ACOMMAND(cmd);
|
||||
arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
static int com90io_status(struct net_device *dev)
|
||||
{
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
return ASTATUS();
|
||||
return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
}
|
||||
|
||||
|
||||
static void com90io_setmask(struct net_device *dev, int mask)
|
||||
{
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
AINTMASK(mask);
|
||||
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)
|
||||
static void com90io_copy_to_card(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count)
|
||||
{
|
||||
TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
|
||||
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)
|
||||
static void com90io_copy_from_card(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count)
|
||||
{
|
||||
TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
|
||||
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 */
|
||||
|
@ -369,12 +356,13 @@ MODULE_LICENSE("GPL");
|
|||
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 */
|
||||
printk("com90io: Too many arguments.\n");
|
||||
pr_err("Too many arguments\n");
|
||||
case 2: /* IRQ */
|
||||
irq = ints[2];
|
||||
case 1: /* IO address */
|
||||
|
@ -421,8 +409,11 @@ static void __exit com90io_exit(void)
|
|||
|
||||
unregister_netdev(dev);
|
||||
|
||||
/* Set the thing back to MMAP mode, in case the old driver is loaded later */
|
||||
outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
|
||||
/* 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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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.
|
||||
|
@ -24,6 +24,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -32,12 +35,10 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
|
||||
#define VERSION "arcnet: COM90xx chipset support\n"
|
||||
#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
|
||||
|
@ -53,7 +54,6 @@
|
|||
*/
|
||||
#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);
|
||||
|
@ -62,8 +62,8 @@ 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);
|
||||
static void com90xx_copy_from_card(struct net_device *dev, int bufnum,
|
||||
int offset, void *buf, int count);
|
||||
|
||||
/* Known ARCnet cards */
|
||||
|
||||
|
@ -77,26 +77,7 @@ static int numcards;
|
|||
|
||||
/* Amount of I/O memory used by the card */
|
||||
#define BUFFER_SIZE (512)
|
||||
#define MIRROR_SIZE (BUFFER_SIZE*4)
|
||||
|
||||
/* COM 9026 controller chip --> ARCnet register addresses */
|
||||
#define _INTMASK (ioaddr+0) /* writable */
|
||||
#define _STATUS (ioaddr+0) /* readable */
|
||||
#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
|
||||
#define _CONFIG (ioaddr+2) /* Configuration register */
|
||||
#define _RESET (ioaddr+8) /* software reset (on read) */
|
||||
#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */
|
||||
#define _ADDR_HI (ioaddr+15) /* Control registers for said */
|
||||
#define _ADDR_LO (ioaddr+14)
|
||||
|
||||
#undef ASTATUS
|
||||
#undef ACOMMAND
|
||||
#undef AINTMASK
|
||||
|
||||
#define ASTATUS() inb(_STATUS)
|
||||
#define ACOMMAND(cmd) outb((cmd),_COMMAND)
|
||||
#define AINTMASK(msk) outb((msk),_INTMASK)
|
||||
|
||||
#define MIRROR_SIZE (BUFFER_SIZE * 4)
|
||||
|
||||
static int com90xx_skip_probe __initdata = 0;
|
||||
|
||||
|
@ -116,8 +97,7 @@ static void __init com90xx_probe(void)
|
|||
{
|
||||
int count, status, ioaddr, numprint, airq, openparen = 0;
|
||||
unsigned long airqmask;
|
||||
int ports[(0x3f0 - 0x200) / 16 + 1] =
|
||||
{0};
|
||||
int ports[(0x3f0 - 0x200) / 16 + 1] = { 0 };
|
||||
unsigned long *shmems;
|
||||
void __iomem **iomem;
|
||||
int numports, numshmems, *port;
|
||||
|
@ -127,18 +107,19 @@ static void __init com90xx_probe(void)
|
|||
if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
|
||||
return;
|
||||
|
||||
shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
|
||||
shmems = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
if (!shmems)
|
||||
return;
|
||||
iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
|
||||
GFP_KERNEL);
|
||||
iomem = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *),
|
||||
GFP_KERNEL);
|
||||
if (!iomem) {
|
||||
kfree(shmems);
|
||||
return;
|
||||
}
|
||||
|
||||
BUGLVL(D_NORMAL) printk(VERSION);
|
||||
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;
|
||||
|
@ -161,38 +142,43 @@ static void __init com90xx_probe(void)
|
|||
numprint++;
|
||||
numprint %= 8;
|
||||
if (!numprint) {
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
BUGMSG2(D_INIT, "S1: ");
|
||||
arc_cont(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "S1: ");
|
||||
}
|
||||
BUGMSG2(D_INIT, "%Xh ", *port);
|
||||
arc_cont(D_INIT, "%Xh ", *port);
|
||||
|
||||
ioaddr = *port;
|
||||
|
||||
if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) {
|
||||
BUGMSG2(D_INIT_REASONS, "(request_region)\n");
|
||||
BUGMSG2(D_INIT_REASONS, "S1: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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 (ASTATUS() == 0xFF) {
|
||||
BUGMSG2(D_INIT_REASONS, "(empty)\n");
|
||||
BUGMSG2(D_INIT_REASONS, "S1: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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;
|
||||
}
|
||||
inb(_RESET); /* begin resetting card */
|
||||
/* begin resetting card */
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
|
||||
BUGMSG2(D_INIT_REASONS, "\n");
|
||||
BUGMSG2(D_INIT_REASONS, "S1: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
arc_cont(D_INIT_REASONS, "\n");
|
||||
arc_cont(D_INIT_REASONS, "S1: ");
|
||||
if (BUGLVL(D_INIT_REASONS))
|
||||
numprint = 0;
|
||||
}
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "\n");
|
||||
|
||||
if (!numports) {
|
||||
BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
|
||||
arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n");
|
||||
kfree(shmems);
|
||||
kfree(iomem);
|
||||
return;
|
||||
|
@ -206,12 +192,12 @@ static void __init com90xx_probe(void)
|
|||
numprint++;
|
||||
numprint %= 8;
|
||||
if (!numprint) {
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
BUGMSG2(D_INIT, "S2: ");
|
||||
arc_cont(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "S2: ");
|
||||
}
|
||||
BUGMSG2(D_INIT, "%Xh ", *port);
|
||||
arc_cont(D_INIT, "%Xh ", *port);
|
||||
}
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "\n");
|
||||
mdelay(RESETtime);
|
||||
|
||||
/* Stage 3: abandon any shmem addresses that don't have the signature
|
||||
|
@ -224,29 +210,33 @@ static void __init com90xx_probe(void)
|
|||
numprint++;
|
||||
numprint %= 8;
|
||||
if (!numprint) {
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
BUGMSG2(D_INIT, "S3: ");
|
||||
arc_cont(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "S3: ");
|
||||
}
|
||||
BUGMSG2(D_INIT, "%lXh ", *p);
|
||||
arc_cont(D_INIT, "%lXh ", *p);
|
||||
|
||||
if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) {
|
||||
BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n");
|
||||
BUGMSG2(D_INIT_REASONS, "Stage 3: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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) {
|
||||
BUGMSG2(D_INIT_REASONS, "(ioremap)\n");
|
||||
BUGMSG2(D_INIT_REASONS, "Stage 3: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
arc_cont(D_INIT_REASONS, "(ioremap)\n");
|
||||
arc_cont(D_INIT_REASONS, "Stage 3: ");
|
||||
if (BUGLVL(D_INIT_REASONS))
|
||||
numprint = 0;
|
||||
goto out1;
|
||||
}
|
||||
if (readb(base) != TESTvalue) {
|
||||
BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
|
||||
readb(base), TESTvalue);
|
||||
BUGMSG2(D_INIT_REASONS, "S3: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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
|
||||
|
@ -254,15 +244,16 @@ static void __init com90xx_probe(void)
|
|||
* in another pass through this loop, they will be discarded
|
||||
* because *cptr != TESTvalue.
|
||||
*/
|
||||
writeb(0x42, base);
|
||||
if (readb(base) != 0x42) {
|
||||
BUGMSG2(D_INIT_REASONS, "(read only)\n");
|
||||
BUGMSG2(D_INIT_REASONS, "S3: ");
|
||||
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;
|
||||
}
|
||||
BUGMSG2(D_INIT_REASONS, "\n");
|
||||
BUGMSG2(D_INIT_REASONS, "S3: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
arc_cont(D_INIT_REASONS, "\n");
|
||||
arc_cont(D_INIT_REASONS, "S3: ");
|
||||
if (BUGLVL(D_INIT_REASONS))
|
||||
numprint = 0;
|
||||
iomem[index] = base;
|
||||
continue;
|
||||
out2:
|
||||
|
@ -273,10 +264,10 @@ static void __init com90xx_probe(void)
|
|||
*p-- = shmems[--numshmems];
|
||||
index--;
|
||||
}
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "\n");
|
||||
|
||||
if (!numshmems) {
|
||||
BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
|
||||
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);
|
||||
|
@ -291,12 +282,12 @@ static void __init com90xx_probe(void)
|
|||
numprint++;
|
||||
numprint %= 8;
|
||||
if (!numprint) {
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
BUGMSG2(D_INIT, "S4: ");
|
||||
arc_cont(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "S4: ");
|
||||
}
|
||||
BUGMSG2(D_INIT, "%lXh ", *p);
|
||||
arc_cont(D_INIT, "%lXh ", *p);
|
||||
}
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
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,
|
||||
|
@ -308,33 +299,37 @@ static void __init com90xx_probe(void)
|
|||
numprint = -1;
|
||||
for (port = &ports[0]; port < ports + numports; port++) {
|
||||
int found = 0;
|
||||
|
||||
numprint++;
|
||||
numprint %= 8;
|
||||
if (!numprint) {
|
||||
BUGMSG2(D_INIT, "\n");
|
||||
BUGMSG2(D_INIT, "S5: ");
|
||||
arc_cont(D_INIT, "\n");
|
||||
arc_cont(D_INIT, "S5: ");
|
||||
}
|
||||
BUGMSG2(D_INIT, "%Xh ", *port);
|
||||
arc_cont(D_INIT, "%Xh ", *port);
|
||||
|
||||
ioaddr = *port;
|
||||
status = ASTATUS();
|
||||
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
|
||||
if ((status & 0x9D)
|
||||
!= (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
|
||||
BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
|
||||
BUGMSG2(D_INIT_REASONS, "S5: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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;
|
||||
}
|
||||
ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
|
||||
status = ASTATUS();
|
||||
arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
|
||||
ioaddr, COM9026_REG_W_COMMAND);
|
||||
status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
if (status & RESETflag) {
|
||||
BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
|
||||
status);
|
||||
BUGMSG2(D_INIT_REASONS, "S5: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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;
|
||||
|
@ -348,15 +343,16 @@ static void __init com90xx_probe(void)
|
|||
* we tell it to start receiving.
|
||||
*/
|
||||
airqmask = probe_irq_on();
|
||||
AINTMASK(NORXflag);
|
||||
arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
|
||||
udelay(1);
|
||||
AINTMASK(0);
|
||||
arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
|
||||
airq = probe_irq_off(airqmask);
|
||||
|
||||
if (airq <= 0) {
|
||||
BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
|
||||
BUGMSG2(D_INIT_REASONS, "S5: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 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;
|
||||
|
@ -365,7 +361,7 @@ static void __init com90xx_probe(void)
|
|||
airq = irq;
|
||||
}
|
||||
|
||||
BUGMSG2(D_INIT, "(%d,", airq);
|
||||
arc_cont(D_INIT, "(%d,", airq);
|
||||
openparen = 1;
|
||||
|
||||
/* Everything seems okay. But which shmem, if any, puts
|
||||
|
@ -376,14 +372,15 @@ static void __init com90xx_probe(void)
|
|||
*/
|
||||
#ifdef FAST_PROBE
|
||||
if (numports > 1 || numshmems > 1) {
|
||||
inb(_RESET);
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
mdelay(RESETtime);
|
||||
} else {
|
||||
/* just one shmem and port, assume they match */
|
||||
writeb(TESTvalue, iomem[0]);
|
||||
arcnet_writeb(TESTvalue, iomem[0],
|
||||
COM9026_REG_W_INTMASK);
|
||||
}
|
||||
#else
|
||||
inb(_RESET);
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
mdelay(RESETtime);
|
||||
#endif
|
||||
|
||||
|
@ -391,8 +388,8 @@ static void __init com90xx_probe(void)
|
|||
u_long ptr = shmems[index];
|
||||
void __iomem *base = iomem[index];
|
||||
|
||||
if (readb(base) == TESTvalue) { /* found one */
|
||||
BUGMSG2(D_INIT, "%lXh)\n", *p);
|
||||
if (arcnet_readb(base, COM9026_REG_R_STATUS) == TESTvalue) { /* found one */
|
||||
arc_cont(D_INIT, "%lXh)\n", *p);
|
||||
openparen = 0;
|
||||
|
||||
/* register the card */
|
||||
|
@ -405,25 +402,30 @@ static void __init com90xx_probe(void)
|
|||
iomem[index] = iomem[numshmems];
|
||||
break; /* go to the next I/O port */
|
||||
} else {
|
||||
BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base));
|
||||
arc_cont(D_INIT_REASONS, "%Xh-",
|
||||
arcnet_readb(base, COM9026_REG_R_STATUS));
|
||||
}
|
||||
}
|
||||
|
||||
if (openparen) {
|
||||
BUGLVL(D_INIT) printk("no matching shmem)\n");
|
||||
BUGLVL(D_INIT_REASONS) printk("S5: ");
|
||||
BUGLVL(D_INIT_REASONS) numprint = 0;
|
||||
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];
|
||||
}
|
||||
|
||||
BUGLVL(D_INIT_REASONS) printk("\n");
|
||||
if (BUGLVL(D_INIT_REASONS))
|
||||
pr_cont("\n");
|
||||
|
||||
/* Now put back TESTvalue on all leftover shmems. */
|
||||
for (index = 0; index < numshmems; index++) {
|
||||
writeb(TESTvalue, iomem[index]);
|
||||
arcnet_writeb(TESTvalue, iomem[index], COM9026_REG_W_INTMASK);
|
||||
iounmap(iomem[index]);
|
||||
release_mem_region(shmems[index], MIRROR_SIZE);
|
||||
}
|
||||
|
@ -441,7 +443,7 @@ static int check_mirror(unsigned long addr, size_t size)
|
|||
|
||||
p = ioremap(addr, size);
|
||||
if (p) {
|
||||
if (readb(p) == TESTvalue)
|
||||
if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
|
||||
res = 1;
|
||||
else
|
||||
res = 0;
|
||||
|
@ -455,7 +457,8 @@ static int check_mirror(unsigned long addr, size_t size)
|
|||
/* 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)
|
||||
static int __init com90xx_found(int ioaddr, int airq, u_long shmem,
|
||||
void __iomem *p)
|
||||
{
|
||||
struct net_device *dev = NULL;
|
||||
struct arcnet_local *lp;
|
||||
|
@ -465,7 +468,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
|
|||
/* allocate struct net_device */
|
||||
dev = alloc_arcdev(device);
|
||||
if (!dev) {
|
||||
BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
|
||||
arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n");
|
||||
iounmap(p);
|
||||
release_mem_region(shmem, MIRROR_SIZE);
|
||||
return -ENOMEM;
|
||||
|
@ -478,7 +481,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
|
|||
* 2k (or there are no mirrors at all) but on some, it's 4k.
|
||||
*/
|
||||
mirror_size = MIRROR_SIZE;
|
||||
if (readb(p) == TESTvalue &&
|
||||
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;
|
||||
|
@ -499,12 +502,14 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
|
|||
iounmap(p);
|
||||
release_mem_region(shmem, MIRROR_SIZE);
|
||||
|
||||
if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)"))
|
||||
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)) {
|
||||
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq);
|
||||
arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", airq);
|
||||
goto err_release_mem;
|
||||
}
|
||||
dev->irq = airq;
|
||||
|
@ -518,22 +523,23 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
|
|||
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);
|
||||
lp->mem_start = ioremap(dev->mem_start,
|
||||
dev->mem_end - dev->mem_start + 1);
|
||||
if (!lp->mem_start) {
|
||||
BUGMSG(D_NORMAL, "Can't remap device memory!\n");
|
||||
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 */
|
||||
dev->dev_addr[0] = readb(lp->mem_start + 1);
|
||||
dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
|
||||
BUGMSG(D_NORMAL, "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);
|
||||
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;
|
||||
|
@ -552,34 +558,29 @@ err_free_dev:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
static void com90xx_command(struct net_device *dev, int cmd)
|
||||
{
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
ACOMMAND(cmd);
|
||||
arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
static int com90xx_status(struct net_device *dev)
|
||||
{
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
return ASTATUS();
|
||||
return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
|
||||
}
|
||||
|
||||
|
||||
static void com90xx_setmask(struct net_device *dev, int mask)
|
||||
{
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
AINTMASK(mask);
|
||||
arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do a hardware reset on the card, and set up necessary registers.
|
||||
*
|
||||
/* 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.
|
||||
*
|
||||
|
@ -590,53 +591,58 @@ static int com90xx_reset(struct net_device *dev, int really_reset)
|
|||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
short ioaddr = dev->base_addr;
|
||||
|
||||
BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
|
||||
arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n",
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
|
||||
|
||||
if (really_reset) {
|
||||
/* reset the card */
|
||||
inb(_RESET);
|
||||
arcnet_inb(ioaddr, COM9026_REG_R_RESET);
|
||||
mdelay(RESETtime);
|
||||
}
|
||||
ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */
|
||||
ACOMMAND(CFLAGScmd | CONFIGclear);
|
||||
/* 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! */
|
||||
/* outb(inb(_CONFIG) | ENABLE16flag, _CONFIG); */
|
||||
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 (readb(lp->mem_start) != TESTvalue) {
|
||||
if (arcnet_readb(lp->mem_start, COM9026_REG_R_STATUS) != TESTvalue) {
|
||||
if (really_reset)
|
||||
BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
|
||||
arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
|
||||
return 1;
|
||||
}
|
||||
/* enable extended (512-byte) packets */
|
||||
ACOMMAND(CONFIGcmd | EXTconf);
|
||||
arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
|
||||
|
||||
/* clean out all the memory to make debugging make more sense :) */
|
||||
BUGLVL(D_DURING)
|
||||
memset_io(lp->mem_start, 0x42, 2048);
|
||||
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)
|
||||
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("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
|
||||
|
||||
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)
|
||||
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("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
|
||||
}
|
||||
|
||||
TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@ -664,7 +670,8 @@ static void __exit com90xx_exit(void)
|
|||
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);
|
||||
release_mem_region(dev->mem_start,
|
||||
dev->mem_end - dev->mem_start + 1);
|
||||
free_netdev(dev);
|
||||
}
|
||||
}
|
||||
|
@ -679,13 +686,13 @@ static int __init com90xx_setup(char *s)
|
|||
|
||||
s = get_options(s, 8, ints);
|
||||
if (!ints[0] && !*s) {
|
||||
printk("com90xx: Disabled.\n");
|
||||
pr_notice("Disabled\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (ints[0]) {
|
||||
default: /* ERROR */
|
||||
printk("com90xx: Too many arguments.\n");
|
||||
pr_err("Too many arguments\n");
|
||||
case 3: /* Mem address */
|
||||
shmem = ints[3];
|
||||
case 2: /* IRQ */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation
|
||||
*
|
||||
*
|
||||
* Written 1994-1999 by Avery Pennarun.
|
||||
* Derived from skeleton.c by Donald Becker.
|
||||
*
|
||||
|
@ -23,6 +23,9 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -30,10 +33,8 @@
|
|||
#include <net/arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
#define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n"
|
||||
|
||||
#include "arcdevice.h"
|
||||
|
||||
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
|
@ -43,9 +44,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum);
|
||||
|
||||
|
||||
static struct ArcProto rfc1051_proto =
|
||||
{
|
||||
static struct ArcProto rfc1051_proto = {
|
||||
.suffix = 's',
|
||||
.mtu = XMTU - RFC1051_HDR_SIZE,
|
||||
.is_ip = 1,
|
||||
|
@ -56,10 +55,9 @@ static struct ArcProto rfc1051_proto =
|
|||
.ack_tx = NULL
|
||||
};
|
||||
|
||||
|
||||
static int __init arcnet_rfc1051_init(void)
|
||||
{
|
||||
printk(VERSION);
|
||||
pr_info("%s\n", "RFC1051 \"simple standard\" (`s') encapsulation support loaded");
|
||||
|
||||
arc_proto_map[ARC_P_IP_RFC1051]
|
||||
= arc_proto_map[ARC_P_ARP_RFC1051]
|
||||
|
@ -82,14 +80,13 @@ module_exit(arcnet_rfc1051_exit);
|
|||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Determine a packet's protocol ID.
|
||||
*
|
||||
/* Determine a packet's protocol ID.
|
||||
*
|
||||
* With ARCnet we have to convert everything to Ethernet-style stuff.
|
||||
*/
|
||||
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct archdr *pkt = (struct archdr *) skb->data;
|
||||
struct archdr *pkt = (struct archdr *)skb->data;
|
||||
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
|
||||
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
|
||||
|
||||
|
@ -97,9 +94,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, hdr_size);
|
||||
|
||||
if (pkt->hard.dest == 0)
|
||||
if (pkt->hard.dest == 0) {
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
else if (dev->flags & IFF_PROMISC) {
|
||||
} else if (dev->flags & IFF_PROMISC) {
|
||||
/* if we're not sending to ourselves :) */
|
||||
if (pkt->hard.dest != dev->dev_addr[0])
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
|
@ -120,7 +117,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
return htons(ETH_P_IP);
|
||||
}
|
||||
|
||||
|
||||
/* packet receiver */
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length)
|
||||
|
@ -130,7 +126,7 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
struct archdr *pkt = pkthdr;
|
||||
int ofs;
|
||||
|
||||
BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
|
||||
arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length);
|
||||
|
||||
if (length >= MinTU)
|
||||
ofs = 512 - length;
|
||||
|
@ -138,15 +134,14 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
ofs = 256 - length;
|
||||
|
||||
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
|
||||
if (!skb) {
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb_put(skb, length + ARC_HDR_SIZE);
|
||||
skb->dev = dev;
|
||||
|
||||
pkt = (struct archdr *) skb->data;
|
||||
pkt = (struct archdr *)skb->data;
|
||||
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card */
|
||||
memcpy(pkt, pkthdr, sizeof(struct archdr));
|
||||
|
@ -155,21 +150,19 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
pkt->soft.raw + sizeof(pkt->soft),
|
||||
length - sizeof(pkt->soft));
|
||||
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = type_trans(skb, dev);
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create the ARCnet hard/soft headers for RFC1051.
|
||||
*/
|
||||
/* Create the ARCnet hard/soft headers for RFC1051 */
|
||||
static int build_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, uint8_t daddr)
|
||||
{
|
||||
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
|
||||
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
|
||||
struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
|
||||
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
|
||||
|
||||
/* set the protocol ID according to RFC1051 */
|
||||
|
@ -181,29 +174,26 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
soft->proto = ARC_P_ARP_RFC1051;
|
||||
break;
|
||||
default:
|
||||
BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
|
||||
type, type);
|
||||
arc_printk(D_NORMAL, dev, "RFC1051: I don't understand protocol %d (%Xh)\n",
|
||||
type, type);
|
||||
dev->stats.tx_errors++;
|
||||
dev->stats.tx_aborted_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the source hardware address.
|
||||
/* Set the source hardware address.
|
||||
*
|
||||
* This is pretty pointless for most purposes, but it can help in
|
||||
* debugging. ARCnet does not allow us to change the source address in
|
||||
* the actual packet sent)
|
||||
* debugging. ARCnet does not allow us to change the source address
|
||||
* in the actual packet sent.
|
||||
*/
|
||||
pkt->hard.source = *dev->dev_addr;
|
||||
|
||||
/* see linux/net/ethernet/eth.c to see where I got the following */
|
||||
|
||||
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
|
||||
/*
|
||||
* FIXME: fill in the last byte of the dest ipaddr here to better
|
||||
* comply with RFC1051 in "noarp" mode.
|
||||
/* FIXME: fill in the last byte of the dest ipaddr here to
|
||||
* better comply with RFC1051 in "noarp" mode.
|
||||
*/
|
||||
pkt->hard.dest = 0;
|
||||
return hdr_size;
|
||||
|
@ -214,7 +204,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
return hdr_size; /* success */
|
||||
}
|
||||
|
||||
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum)
|
||||
{
|
||||
|
@ -222,15 +211,16 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
struct arc_hardware *hard = &pkt->hard;
|
||||
int ofs;
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
|
||||
/* hard header is not included in packet length */
|
||||
length -= ARC_HDR_SIZE;
|
||||
|
||||
if (length > XMTU) {
|
||||
/* should never happen! other people already check for this. */
|
||||
BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n",
|
||||
length, XMTU);
|
||||
length = XMTU;
|
||||
}
|
||||
if (length > MinTU) {
|
||||
|
@ -239,8 +229,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
} else if (length > MTU) {
|
||||
hard->offset[0] = 0;
|
||||
hard->offset[1] = ofs = 512 - length - 3;
|
||||
} else
|
||||
} else {
|
||||
hard->offset[0] = ofs = 256 - length;
|
||||
}
|
||||
|
||||
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux ARCnet driver - RFC1201 (standard) packet encapsulation
|
||||
*
|
||||
*
|
||||
* Written 1994-1999 by Avery Pennarun.
|
||||
* Derived from skeleton.c by Donald Becker.
|
||||
*
|
||||
|
@ -23,17 +23,19 @@
|
|||
*
|
||||
* **********************
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/arcdevice.h>
|
||||
|
||||
#include "arcdevice.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
#define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n"
|
||||
|
||||
|
||||
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
|
@ -44,8 +46,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
int bufnum);
|
||||
static int continue_tx(struct net_device *dev, int bufnum);
|
||||
|
||||
static struct ArcProto rfc1201_proto =
|
||||
{
|
||||
static struct ArcProto rfc1201_proto = {
|
||||
.suffix = 'a',
|
||||
.mtu = 1500, /* could be more, but some receivers can't handle it... */
|
||||
.is_ip = 1, /* This is for sending IP and ARP packages */
|
||||
|
@ -56,10 +57,9 @@ static struct ArcProto rfc1201_proto =
|
|||
.ack_tx = NULL
|
||||
};
|
||||
|
||||
|
||||
static int __init arcnet_rfc1201_init(void)
|
||||
{
|
||||
printk(VERSION);
|
||||
pr_info("%s\n", "RFC1201 \"standard\" (`a') encapsulation support loaded");
|
||||
|
||||
arc_proto_map[ARC_P_IP]
|
||||
= arc_proto_map[ARC_P_IPV6]
|
||||
|
@ -84,14 +84,13 @@ static void __exit arcnet_rfc1201_exit(void)
|
|||
module_init(arcnet_rfc1201_init);
|
||||
module_exit(arcnet_rfc1201_exit);
|
||||
|
||||
/*
|
||||
* Determine a packet's protocol ID.
|
||||
*
|
||||
/* Determine a packet's protocol ID.
|
||||
*
|
||||
* With ARCnet we have to convert everything to Ethernet-style stuff.
|
||||
*/
|
||||
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct archdr *pkt = (struct archdr *) skb->data;
|
||||
struct archdr *pkt = (struct archdr *)skb->data;
|
||||
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
|
||||
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
|
||||
|
||||
|
@ -99,9 +98,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, hdr_size);
|
||||
|
||||
if (pkt->hard.dest == 0)
|
||||
if (pkt->hard.dest == 0) {
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
else if (dev->flags & IFF_PROMISC) {
|
||||
} else if (dev->flags & IFF_PROMISC) {
|
||||
/* if we're not sending to ourselves :) */
|
||||
if (pkt->hard.dest != dev->dev_addr[0])
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
|
@ -129,7 +128,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
return htons(ETH_P_IP);
|
||||
}
|
||||
|
||||
|
||||
/* packet receiver */
|
||||
static void rx(struct net_device *dev, int bufnum,
|
||||
struct archdr *pkthdr, int length)
|
||||
|
@ -141,7 +139,8 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
int saddr = pkt->hard.source, ofs;
|
||||
struct Incoming *in = &lp->rfc1201.incoming[saddr];
|
||||
|
||||
BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", length);
|
||||
arc_printk(D_DURING, dev, "it's an RFC1201 packet (length=%d)\n",
|
||||
length);
|
||||
|
||||
if (length >= MinTU)
|
||||
ofs = 512 - length;
|
||||
|
@ -149,11 +148,11 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
ofs = 256 - length;
|
||||
|
||||
if (soft->split_flag == 0xFF) { /* Exception Packet */
|
||||
if (length >= 4 + RFC1201_HDR_SIZE)
|
||||
BUGMSG(D_DURING, "compensating for exception packet\n");
|
||||
else {
|
||||
BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh",
|
||||
saddr);
|
||||
if (length >= 4 + RFC1201_HDR_SIZE) {
|
||||
arc_printk(D_DURING, dev, "compensating for exception packet\n");
|
||||
} else {
|
||||
arc_printk(D_EXTRA, dev, "short RFC1201 exception packet from %02Xh",
|
||||
saddr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -164,12 +163,13 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
soft, sizeof(pkt->soft));
|
||||
}
|
||||
if (!soft->split_flag) { /* not split */
|
||||
BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
arc_printk(D_RX, dev, "incoming is not split (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
|
||||
if (in->skb) { /* already assembling one! */
|
||||
BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag, soft->sequence);
|
||||
arc_printk(D_EXTRA, dev, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag,
|
||||
soft->sequence);
|
||||
lp->rfc1201.aborted_seq = soft->sequence;
|
||||
dev_kfree_skb_irq(in->skb);
|
||||
dev->stats.rx_errors++;
|
||||
|
@ -179,82 +179,86 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
in->sequence = soft->sequence;
|
||||
|
||||
skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
|
||||
if (!skb) {
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb_put(skb, length + ARC_HDR_SIZE);
|
||||
skb->dev = dev;
|
||||
|
||||
pkt = (struct archdr *) skb->data;
|
||||
pkt = (struct archdr *)skb->data;
|
||||
soft = &pkt->soft.rfc1201;
|
||||
|
||||
/* up to sizeof(pkt->soft) has already been copied from the card */
|
||||
/* up to sizeof(pkt->soft) has already
|
||||
* been copied from the card
|
||||
*/
|
||||
memcpy(pkt, pkthdr, sizeof(struct archdr));
|
||||
if (length > sizeof(pkt->soft))
|
||||
lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
|
||||
pkt->soft.raw + sizeof(pkt->soft),
|
||||
lp->hw.copy_from_card(dev, bufnum,
|
||||
ofs + sizeof(pkt->soft),
|
||||
pkt->soft.raw + sizeof(pkt->soft),
|
||||
length - sizeof(pkt->soft));
|
||||
|
||||
/*
|
||||
* ARP packets have problems when sent from some DOS systems: the
|
||||
* source address is always 0! So we take the hardware source addr
|
||||
* (which is impossible to fumble) and insert it ourselves.
|
||||
/* ARP packets have problems when sent from some DOS systems:
|
||||
* the source address is always 0!
|
||||
* So we take the hardware source addr (which is impossible
|
||||
* to fumble) and insert it ourselves.
|
||||
*/
|
||||
if (soft->proto == ARC_P_ARP) {
|
||||
struct arphdr *arp = (struct arphdr *) soft->payload;
|
||||
struct arphdr *arp = (struct arphdr *)soft->payload;
|
||||
|
||||
/* make sure addresses are the right length */
|
||||
if (arp->ar_hln == 1 && arp->ar_pln == 4) {
|
||||
uint8_t *cptr = (uint8_t *) arp + sizeof(struct arphdr);
|
||||
uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr);
|
||||
|
||||
if (!*cptr) { /* is saddr = 00? */
|
||||
BUGMSG(D_EXTRA,
|
||||
"ARP source address was 00h, set to %02Xh.\n",
|
||||
saddr);
|
||||
arc_printk(D_EXTRA, dev,
|
||||
"ARP source address was 00h, set to %02Xh\n",
|
||||
saddr);
|
||||
dev->stats.rx_crc_errors++;
|
||||
*cptr = saddr;
|
||||
} else {
|
||||
BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n",
|
||||
*cptr);
|
||||
arc_printk(D_DURING, dev, "ARP source address (%Xh) is fine.\n",
|
||||
*cptr);
|
||||
}
|
||||
} else {
|
||||
BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n",
|
||||
arp->ar_hln, arp->ar_pln);
|
||||
arc_printk(D_NORMAL, dev, "funny-shaped ARP packet. (%Xh, %Xh)\n",
|
||||
arp->ar_hln, arp->ar_pln);
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_crc_errors++;
|
||||
}
|
||||
}
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = type_trans(skb, dev);
|
||||
netif_rx(skb);
|
||||
} else { /* split packet */
|
||||
/*
|
||||
* NOTE: MSDOS ARP packet correction should only need to apply to
|
||||
* unsplit packets, since ARP packets are so short.
|
||||
/* NOTE: MSDOS 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 packet is
|
||||
* received out of order, the entire assembly process should be
|
||||
* aborted.
|
||||
* My interpretation of the RFC1201 document is that if a
|
||||
* packet is received out of order, the entire assembly
|
||||
* process should be aborted.
|
||||
*
|
||||
* The RFC also mentions "it is possible for successfully received
|
||||
* packets to be retransmitted." As of 0.40 all previously received
|
||||
* packets are allowed, not just the most recent one.
|
||||
* The RFC also mentions "it is possible for successfully
|
||||
* received packets to be retransmitted." As of 0.40 all
|
||||
* previously received packets are allowed, not just the
|
||||
* most recent one.
|
||||
*
|
||||
* We allow multiple assembly processes, one for each ARCnet card
|
||||
* possible on the network. Seems rather like a waste of memory,
|
||||
* but there's no other way to be reliable.
|
||||
* We allow multiple assembly processes, one for each
|
||||
* ARCnet card possible on the network.
|
||||
* Seems rather like a waste of memory, but there's no
|
||||
* other way to be reliable.
|
||||
*/
|
||||
|
||||
BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n",
|
||||
soft->split_flag, in->sequence);
|
||||
arc_printk(D_RX, dev, "packet is split (splitflag=%d, seq=%d)\n",
|
||||
soft->split_flag, in->sequence);
|
||||
|
||||
if (in->skb && in->sequence != soft->sequence) {
|
||||
BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
|
||||
saddr, in->sequence, soft->sequence,
|
||||
soft->split_flag);
|
||||
arc_printk(D_EXTRA, dev, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
|
||||
saddr, in->sequence, soft->sequence,
|
||||
soft->split_flag);
|
||||
dev_kfree_skb_irq(in->skb);
|
||||
in->skb = NULL;
|
||||
dev->stats.rx_errors++;
|
||||
|
@ -262,24 +266,23 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
in->lastpacket = in->numpackets = 0;
|
||||
}
|
||||
if (soft->split_flag & 1) { /* first packet in split */
|
||||
BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
arc_printk(D_RX, dev, "brand new splitpacket (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
if (in->skb) { /* already assembling one! */
|
||||
BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly "
|
||||
"(splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag,
|
||||
soft->sequence);
|
||||
arc_printk(D_EXTRA, dev, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag,
|
||||
soft->sequence);
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_missed_errors++;
|
||||
dev_kfree_skb_irq(in->skb);
|
||||
}
|
||||
in->sequence = soft->sequence;
|
||||
in->numpackets = ((unsigned) soft->split_flag >> 1) + 2;
|
||||
in->numpackets = ((unsigned)soft->split_flag >> 1) + 2;
|
||||
in->lastpacket = 1;
|
||||
|
||||
if (in->numpackets > 16) {
|
||||
BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
arc_printk(D_EXTRA, dev, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
lp->rfc1201.aborted_seq = soft->sequence;
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_length_errors++;
|
||||
|
@ -287,14 +290,14 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
}
|
||||
in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE,
|
||||
GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
|
||||
if (!skb) {
|
||||
arc_printk(D_NORMAL, dev, "(split) memory squeeze, dropping packet.\n");
|
||||
lp->rfc1201.aborted_seq = soft->sequence;
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
skb->dev = dev;
|
||||
pkt = (struct archdr *) skb->data;
|
||||
pkt = (struct archdr *)skb->data;
|
||||
soft = &pkt->soft.rfc1201;
|
||||
|
||||
memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE);
|
||||
|
@ -302,37 +305,37 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
|
||||
soft->split_flag = 0; /* end result won't be split */
|
||||
} else { /* not first packet */
|
||||
int packetnum = ((unsigned) soft->split_flag >> 1) + 1;
|
||||
int packetnum = ((unsigned)soft->split_flag >> 1) + 1;
|
||||
|
||||
/*
|
||||
* if we're not assembling, there's no point trying to
|
||||
/* if we're not assembling, there's no point trying to
|
||||
* continue.
|
||||
*/
|
||||
if (!in->skb) {
|
||||
if (lp->rfc1201.aborted_seq != soft->sequence) {
|
||||
BUGMSG(D_EXTRA, "can't continue split without starting "
|
||||
"first! (splitflag=%d, seq=%d, aborted=%d)\n",
|
||||
soft->split_flag, soft->sequence,
|
||||
lp->rfc1201.aborted_seq);
|
||||
arc_printk(D_EXTRA, dev, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
|
||||
soft->split_flag,
|
||||
soft->sequence,
|
||||
lp->rfc1201.aborted_seq);
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_missed_errors++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
in->lastpacket++;
|
||||
if (packetnum != in->lastpacket) { /* not the right flag! */
|
||||
/* if not the right flag */
|
||||
if (packetnum != in->lastpacket) {
|
||||
/* harmless duplicate? ignore. */
|
||||
if (packetnum <= in->lastpacket - 1) {
|
||||
BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n",
|
||||
soft->split_flag);
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_frame_errors++;
|
||||
return;
|
||||
}
|
||||
/* "bad" duplicate, kill reassembly */
|
||||
BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly "
|
||||
"(seq=%d) aborted (splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag, soft->sequence);
|
||||
arc_printk(D_EXTRA, dev, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
|
||||
in->sequence, soft->split_flag,
|
||||
soft->sequence);
|
||||
lp->rfc1201.aborted_seq = soft->sequence;
|
||||
dev_kfree_skb_irq(in->skb);
|
||||
in->skb = NULL;
|
||||
|
@ -341,7 +344,7 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
in->lastpacket = in->numpackets = 0;
|
||||
return;
|
||||
}
|
||||
pkt = (struct archdr *) in->skb->data;
|
||||
pkt = (struct archdr *)in->skb->data;
|
||||
soft = &pkt->soft.rfc1201;
|
||||
}
|
||||
|
||||
|
@ -357,11 +360,12 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
in->skb = NULL;
|
||||
in->lastpacket = in->numpackets = 0;
|
||||
|
||||
BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n",
|
||||
skb->len, pkt->hard.source);
|
||||
BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n",
|
||||
skb->len, pkt->hard.source);
|
||||
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
|
||||
arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (unsplit)\n",
|
||||
skb->len, pkt->hard.source);
|
||||
arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (split)\n",
|
||||
skb->len, pkt->hard.source);
|
||||
if (BUGLVL(D_SKB))
|
||||
arcnet_dump_skb(dev, skb, "rx");
|
||||
|
||||
skb->protocol = type_trans(skb, dev);
|
||||
netif_rx(skb);
|
||||
|
@ -369,14 +373,13 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create the ARCnet hard/soft headers for RFC1201. */
|
||||
static int build_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, uint8_t daddr)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
|
||||
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
|
||||
struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size);
|
||||
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
|
||||
|
||||
/* set the protocol ID according to RFC1201 */
|
||||
|
@ -402,19 +405,18 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
soft->proto = ARC_P_ATALK;
|
||||
break;
|
||||
default:
|
||||
BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n",
|
||||
type, type);
|
||||
arc_printk(D_NORMAL, dev, "RFC1201: I don't understand protocol %d (%Xh)\n",
|
||||
type, type);
|
||||
dev->stats.tx_errors++;
|
||||
dev->stats.tx_aborted_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the source hardware address.
|
||||
/* Set the source hardware address.
|
||||
*
|
||||
* This is pretty pointless for most purposes, but it can help in
|
||||
* debugging. ARCnet does not allow us to change the source address in
|
||||
* the actual packet sent)
|
||||
* debugging. ARCnet does not allow us to change the source address
|
||||
* in the actual packet sent.
|
||||
*/
|
||||
pkt->hard.source = *dev->dev_addr;
|
||||
|
||||
|
@ -424,10 +426,10 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
/* see linux/net/ethernet/eth.c to see where I got the following */
|
||||
|
||||
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
|
||||
/*
|
||||
* FIXME: fill in the last byte of the dest ipaddr here to better
|
||||
* comply with RFC1051 in "noarp" mode. For now, always broadcasting
|
||||
* will probably at least get packets sent out :)
|
||||
/* FIXME: fill in the last byte of the dest ipaddr here
|
||||
* to better comply with RFC1051 in "noarp" mode.
|
||||
* For now, always broadcasting will probably at least get
|
||||
* packets sent out :)
|
||||
*/
|
||||
pkt->hard.dest = 0;
|
||||
return hdr_size;
|
||||
|
@ -437,7 +439,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
|
|||
return hdr_size;
|
||||
}
|
||||
|
||||
|
||||
static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
|
||||
struct arc_rfc1201 *soft, int softlen, int bufnum)
|
||||
{
|
||||
|
@ -461,8 +462,9 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
|
|||
hard->offset[1] = ofs - RFC1201_HDR_SIZE;
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs - RFC1201_HDR_SIZE,
|
||||
&excsoft, RFC1201_HDR_SIZE);
|
||||
} else
|
||||
} else {
|
||||
hard->offset[0] = ofs = 256 - softlen;
|
||||
}
|
||||
|
||||
lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
|
||||
lp->hw.copy_to_card(dev, bufnum, ofs, soft, softlen);
|
||||
|
@ -470,7 +472,6 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
|
|||
lp->lastload_dest = hard->dest;
|
||||
}
|
||||
|
||||
|
||||
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
||||
int bufnum)
|
||||
{
|
||||
|
@ -478,11 +479,11 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
const int maxsegsize = XMTU - RFC1201_HDR_SIZE;
|
||||
struct Outgoing *out;
|
||||
|
||||
arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
|
||||
lp->next_tx, lp->cur_tx, bufnum);
|
||||
|
||||
length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
|
||||
/* hard header is not included in packet length */
|
||||
length -= ARC_HDR_SIZE;
|
||||
pkt->soft.rfc1201.split_flag = 0;
|
||||
|
||||
/* need to do a split packet? */
|
||||
|
@ -494,9 +495,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize;
|
||||
out->segnum = 0;
|
||||
|
||||
BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split "
|
||||
"(%d bytes, seq=%d)\n", out->numsegs, out->length,
|
||||
pkt->soft.rfc1201.sequence);
|
||||
arc_printk(D_DURING, dev, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n",
|
||||
out->numsegs, out->length,
|
||||
pkt->soft.rfc1201.sequence);
|
||||
|
||||
return 0; /* not done */
|
||||
}
|
||||
|
@ -506,7 +507,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
|
|||
return 1; /* done */
|
||||
}
|
||||
|
||||
|
||||
static int continue_tx(struct net_device *dev, int bufnum)
|
||||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
|
@ -516,9 +516,9 @@ static int continue_tx(struct net_device *dev, int bufnum)
|
|||
int maxsegsize = XMTU - RFC1201_HDR_SIZE;
|
||||
int seglen;
|
||||
|
||||
BUGMSG(D_DURING,
|
||||
"rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n",
|
||||
out->segnum, out->numsegs, soft->sequence);
|
||||
arc_printk(D_DURING, dev,
|
||||
"rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n",
|
||||
out->segnum, out->numsegs, soft->sequence);
|
||||
|
||||
/* the "new" soft header comes right before the data chunk */
|
||||
newsoft = (struct arc_rfc1201 *)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
||||
/*
|
||||
* These are the defined ARCnet Protocol ID's.
|
||||
*/
|
||||
|
@ -57,42 +56,40 @@
|
|||
* The RFC1201-specific components of an arcnet packet header.
|
||||
*/
|
||||
struct arc_rfc1201 {
|
||||
__u8 proto; /* protocol ID field - varies */
|
||||
__u8 split_flag; /* for use with split packets */
|
||||
__be16 sequence; /* sequence number */
|
||||
__u8 payload[0]; /* space remaining in packet (504 bytes)*/
|
||||
__u8 proto; /* protocol ID field - varies */
|
||||
__u8 split_flag; /* for use with split packets */
|
||||
__be16 sequence; /* sequence number */
|
||||
__u8 payload[0]; /* space remaining in packet (504 bytes)*/
|
||||
};
|
||||
#define RFC1201_HDR_SIZE 4
|
||||
|
||||
|
||||
/*
|
||||
* The RFC1051-specific components.
|
||||
*/
|
||||
struct arc_rfc1051 {
|
||||
__u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */
|
||||
__u8 payload[0]; /* 507 bytes */
|
||||
__u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */
|
||||
__u8 payload[0]; /* 507 bytes */
|
||||
};
|
||||
#define RFC1051_HDR_SIZE 1
|
||||
|
||||
|
||||
/*
|
||||
* The ethernet-encap-specific components. We have a real ethernet header
|
||||
* and some data.
|
||||
*/
|
||||
struct arc_eth_encap {
|
||||
__u8 proto; /* Always ARC_P_ETHER */
|
||||
struct ethhdr eth; /* standard ethernet header (yuck!) */
|
||||
__u8 payload[0]; /* 493 bytes */
|
||||
__u8 proto; /* Always ARC_P_ETHER */
|
||||
struct ethhdr eth; /* standard ethernet header (yuck!) */
|
||||
__u8 payload[0]; /* 493 bytes */
|
||||
};
|
||||
#define ETH_ENCAP_HDR_SIZE 14
|
||||
|
||||
|
||||
struct arc_cap {
|
||||
__u8 proto;
|
||||
__u8 cookie[sizeof(int)]; /* Actually NOT sent over the network */
|
||||
__u8 cookie[sizeof(int)];
|
||||
/* Actually NOT sent over the network */
|
||||
union {
|
||||
__u8 ack;
|
||||
__u8 raw[0]; /* 507 bytes */
|
||||
__u8 raw[0]; /* 507 bytes */
|
||||
} mes;
|
||||
};
|
||||
|
||||
|
@ -105,9 +102,9 @@ struct arc_cap {
|
|||
* driver.
|
||||
*/
|
||||
struct arc_hardware {
|
||||
__u8 source, /* source ARCnet - filled in automagically */
|
||||
dest, /* destination ARCnet - 0 for broadcast */
|
||||
offset[2]; /* offset bytes (some weird semantics) */
|
||||
__u8 source; /* source ARCnet - filled in automagically */
|
||||
__u8 dest; /* destination ARCnet - 0 for broadcast */
|
||||
__u8 offset[2]; /* offset bytes (some weird semantics) */
|
||||
};
|
||||
#define ARC_HDR_SIZE 4
|
||||
|
||||
|
@ -116,17 +113,17 @@ struct arc_hardware {
|
|||
* when you do a raw packet capture).
|
||||
*/
|
||||
struct archdr {
|
||||
/* hardware requirements */
|
||||
struct arc_hardware hard;
|
||||
|
||||
/* arcnet encapsulation-specific bits */
|
||||
union {
|
||||
struct arc_rfc1201 rfc1201;
|
||||
struct arc_rfc1051 rfc1051;
|
||||
struct arc_eth_encap eth_encap;
|
||||
struct arc_cap cap;
|
||||
__u8 raw[0]; /* 508 bytes */
|
||||
} soft;
|
||||
/* hardware requirements */
|
||||
struct arc_hardware hard;
|
||||
|
||||
/* arcnet encapsulation-specific bits */
|
||||
union {
|
||||
struct arc_rfc1201 rfc1201;
|
||||
struct arc_rfc1051 rfc1051;
|
||||
struct arc_eth_encap eth_encap;
|
||||
struct arc_cap cap;
|
||||
__u8 raw[0]; /* 508 bytes */
|
||||
} soft;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_IF_ARCNET_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue