diff options
Diffstat (limited to 'drivers/net/arcnet')
-rw-r--r-- | drivers/net/arcnet/Kconfig | 140 | ||||
-rw-r--r-- | drivers/net/arcnet/Makefile | 14 | ||||
-rw-r--r-- | drivers/net/arcnet/arc-rawmode.c | 204 | ||||
-rw-r--r-- | drivers/net/arcnet/arc-rimi.c | 368 | ||||
-rw-r--r-- | drivers/net/arcnet/arcnet.c | 1102 | ||||
-rw-r--r-- | drivers/net/arcnet/capmode.c | 296 | ||||
-rw-r--r-- | drivers/net/arcnet/com20020-isa.c | 219 | ||||
-rw-r--r-- | drivers/net/arcnet/com20020-pci.c | 189 | ||||
-rw-r--r-- | drivers/net/arcnet/com20020.c | 357 | ||||
-rw-r--r-- | drivers/net/arcnet/com90io.c | 435 | ||||
-rw-r--r-- | drivers/net/arcnet/com90xx.c | 646 | ||||
-rw-r--r-- | drivers/net/arcnet/rfc1051.c | 253 | ||||
-rw-r--r-- | drivers/net/arcnet/rfc1201.c | 549 |
13 files changed, 4772 insertions, 0 deletions
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig new file mode 100644 index 000000000000..948de2532a1e --- /dev/null +++ b/drivers/net/arcnet/Kconfig | |||
@@ -0,0 +1,140 @@ | |||
1 | # | ||
2 | # Arcnet configuration | ||
3 | # | ||
4 | |||
5 | menu "ARCnet devices" | ||
6 | depends on NETDEVICES && (ISA || PCI) | ||
7 | |||
8 | config ARCNET | ||
9 | tristate "ARCnet support" | ||
10 | ---help--- | ||
11 | If you have a network card of this type, say Y and check out the | ||
12 | (arguably) beautiful poetry in | ||
13 | <file:Documentation/networking/arcnet.txt>. | ||
14 | |||
15 | You need both this driver, and the driver for the particular ARCnet | ||
16 | chipset of your card. If you don't know, then it's probably a | ||
17 | COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset | ||
18 | support" below. | ||
19 | |||
20 | You might also want to have a look at the Ethernet-HOWTO, available | ||
21 | from <http://www.tldp.org/docs.html#howto>(even though ARCnet | ||
22 | is not really Ethernet). | ||
23 | |||
24 | To compile this driver as a module, choose M here and read | ||
25 | <file:Documentation/networking/net-modules.txt>. The module will | ||
26 | be called arcnet. | ||
27 | |||
28 | config ARCNET_1201 | ||
29 | tristate "Enable standard ARCNet packet format (RFC 1201)" | ||
30 | depends on ARCNET | ||
31 | help | ||
32 | This allows you to use RFC1201 with your ARCnet card via the virtual | ||
33 | arc0 device. You need to say Y here to communicate with | ||
34 | industry-standard RFC1201 implementations, like the arcether.com | ||
35 | packet driver or most DOS/Windows ODI drivers. Please read the | ||
36 | ARCnet documentation in <file:Documentation/networking/arcnet.txt> | ||
37 | for more information about using arc0. | ||
38 | |||
39 | config ARCNET_1051 | ||
40 | tristate "Enable old ARCNet packet format (RFC 1051)" | ||
41 | depends on ARCNET | ||
42 | ---help--- | ||
43 | This allows you to use RFC1051 with your ARCnet card via the virtual | ||
44 | arc0s device. You only need arc0s if you want to talk to ARCnet | ||
45 | software complying with the "old" standard, specifically, the DOS | ||
46 | arcnet.com packet driver, Amigas running AmiTCP, and some variants | ||
47 | of NetBSD. You do not need to say Y here to communicate with | ||
48 | industry-standard RFC1201 implementations, like the arcether.com | ||
49 | packet driver or most DOS/Windows ODI drivers. RFC1201 is included | ||
50 | automatically as the arc0 device. Please read the ARCnet | ||
51 | documentation in <file:Documentation/networking/arcnet.txt> for more | ||
52 | information about using arc0e and arc0s. | ||
53 | |||
54 | config ARCNET_RAW | ||
55 | tristate "Enable raw mode packet interface" | ||
56 | depends on ARCNET | ||
57 | help | ||
58 | ARCnet "raw mode" packet encapsulation, no soft headers. Unlikely | ||
59 | to work unless talking to a copy of the same Linux arcnet driver, | ||
60 | but perhaps marginally faster in that case. | ||
61 | |||
62 | config ARCNET_CAP | ||
63 | tristate "Enable CAP mode packet interface" | ||
64 | depends on ARCNET | ||
65 | help | ||
66 | ARCnet "cap mode" packet encapsulation. Used to get the hardware | ||
67 | acknowledge back to userspace. After the initial protocol byte every | ||
68 | packet is stuffed with an extra 4 byte "cookie" which doesn't | ||
69 | actually appear on the network. After transmit the driver will send | ||
70 | back a packet with protocol byte 0 containing the status of the | ||
71 | transmition: | ||
72 | 0=no hardware acknowledge | ||
73 | 1=excessive nak | ||
74 | 2=transmition accepted by the reciever hardware | ||
75 | |||
76 | Received packets are also stuffed with the extra 4 bytes but it will | ||
77 | be random data. | ||
78 | |||
79 | Cap only listens to protocol 1-8. | ||
80 | |||
81 | config ARCNET_COM90xx | ||
82 | tristate "ARCnet COM90xx (normal) chipset driver" | ||
83 | depends on ARCNET | ||
84 | help | ||
85 | This is the chipset driver for the standard COM90xx cards. If you | ||
86 | have always used the old ARCnet driver without knowing what type of | ||
87 | card you had, this is probably the one for you. | ||
88 | |||
89 | To compile this driver as a module, choose M here and read | ||
90 | <file:Documentation/networking/net-modules.txt>. The module will | ||
91 | be called com90xx. | ||
92 | |||
93 | config ARCNET_COM90xxIO | ||
94 | tristate "ARCnet COM90xx (IO mapped) chipset driver" | ||
95 | depends on ARCNET | ||
96 | ---help--- | ||
97 | This is the chipset driver for the COM90xx cards, using them in | ||
98 | IO-mapped mode instead of memory-mapped mode. This is slower than | ||
99 | the normal driver. Only use it if your card doesn't support shared | ||
100 | memory. | ||
101 | |||
102 | To compile this driver as a module, choose M here and read | ||
103 | <file:Documentation/networking/net-modules.txt>. The module will | ||
104 | be called com90io. | ||
105 | |||
106 | config ARCNET_RIM_I | ||
107 | tristate "ARCnet COM90xx (RIM I) chipset driver" | ||
108 | depends on ARCNET | ||
109 | ---help--- | ||
110 | This is yet another chipset driver for the COM90xx cards, but this | ||
111 | time only using memory-mapped mode, and no IO ports at all. This | ||
112 | driver is completely untested, so if you have one of these cards, | ||
113 | please mail <dwmw2@infradead.org>, especially if it works! | ||
114 | |||
115 | To compile this driver as a module, choose M here and read | ||
116 | <file:Documentation/networking/net-modules.txt>. The module will | ||
117 | be called arc-rimi. | ||
118 | |||
119 | config ARCNET_COM20020 | ||
120 | tristate "ARCnet COM20020 chipset driver" | ||
121 | depends on ARCNET | ||
122 | help | ||
123 | This is the driver for the new COM20020 chipset. It supports such | ||
124 | things as promiscuous mode, so packet sniffing is possible, and | ||
125 | extra diagnostic information. | ||
126 | |||
127 | To compile this driver as a module, choose M here and read | ||
128 | <file:Documentation/networking/net-modules.txt>. The module will | ||
129 | be called com20020. | ||
130 | |||
131 | config ARCNET_COM20020_ISA | ||
132 | tristate "Support for COM20020 on ISA" | ||
133 | depends on ARCNET_COM20020 && ISA | ||
134 | |||
135 | config ARCNET_COM20020_PCI | ||
136 | tristate "Support for COM20020 on PCI" | ||
137 | depends on ARCNET_COM20020 && PCI | ||
138 | |||
139 | endmenu | ||
140 | |||
diff --git a/drivers/net/arcnet/Makefile b/drivers/net/arcnet/Makefile new file mode 100644 index 000000000000..5861af543d42 --- /dev/null +++ b/drivers/net/arcnet/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # Makefile for linux/drivers/net/arcnet | ||
2 | # | ||
3 | |||
4 | obj-$(CONFIG_ARCNET) += arcnet.o | ||
5 | obj-$(CONFIG_ARCNET_1201) += rfc1201.o | ||
6 | obj-$(CONFIG_ARCNET_1051) += rfc1051.o | ||
7 | obj-$(CONFIG_ARCNET_RAW) += arc-rawmode.o | ||
8 | obj-$(CONFIG_ARCNET_CAP) += capmode.o | ||
9 | obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o | ||
10 | obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o | ||
11 | obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o | ||
12 | obj-$(CONFIG_ARCNET_COM20020) += com20020.o | ||
13 | obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o | ||
14 | obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o | ||
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c new file mode 100644 index 000000000000..e1ea29b0cd14 --- /dev/null +++ b/drivers/net/arcnet/arc-rawmode.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers) | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun. | ||
5 | * Derived from skeleton.c by Donald Becker. | ||
6 | * | ||
7 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
8 | * for sponsoring the further development of this driver. | ||
9 | * | ||
10 | * ********************** | ||
11 | * | ||
12 | * The original copyright of skeleton.c was as follows: | ||
13 | * | ||
14 | * skeleton.c Written 1993 by Donald Becker. | ||
15 | * Copyright 1993 United States Government as represented by the | ||
16 | * Director, National Security Agency. This software may only be used | ||
17 | * and distributed according to the terms of the GNU General Public License as | ||
18 | * modified by SRC, incorporated herein by reference. | ||
19 | * | ||
20 | * ********************** | ||
21 | * | ||
22 | * For more details, see drivers/net/arcnet.c | ||
23 | * | ||
24 | * ********************** | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/if_arp.h> | ||
30 | #include <net/arp.h> | ||
31 | #include <linux/netdevice.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | #include <linux/arcdevice.h> | ||
34 | |||
35 | #define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n" | ||
36 | |||
37 | |||
38 | static void rx(struct net_device *dev, int bufnum, | ||
39 | struct archdr *pkthdr, int length); | ||
40 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
41 | unsigned short type, uint8_t daddr); | ||
42 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
43 | int bufnum); | ||
44 | |||
45 | struct ArcProto rawmode_proto = | ||
46 | { | ||
47 | .suffix = 'r', | ||
48 | .mtu = XMTU, | ||
49 | .rx = rx, | ||
50 | .build_header = build_header, | ||
51 | .prepare_tx = prepare_tx, | ||
52 | .continue_tx = NULL, | ||
53 | .ack_tx = NULL | ||
54 | }; | ||
55 | |||
56 | |||
57 | static int __init arcnet_raw_init(void) | ||
58 | { | ||
59 | int count; | ||
60 | |||
61 | printk(VERSION); | ||
62 | |||
63 | for (count = 0; count < 256; count++) | ||
64 | if (arc_proto_map[count] == arc_proto_default) | ||
65 | arc_proto_map[count] = &rawmode_proto; | ||
66 | |||
67 | /* for raw mode, we only set the bcast proto if there's no better one */ | ||
68 | if (arc_bcast_proto == arc_proto_default) | ||
69 | arc_bcast_proto = &rawmode_proto; | ||
70 | |||
71 | arc_proto_default = &rawmode_proto; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static void __exit arcnet_raw_exit(void) | ||
76 | { | ||
77 | arcnet_unregister_proto(&rawmode_proto); | ||
78 | } | ||
79 | |||
80 | module_init(arcnet_raw_init); | ||
81 | module_exit(arcnet_raw_exit); | ||
82 | |||
83 | MODULE_LICENSE("GPL"); | ||
84 | |||
85 | |||
86 | /* packet receiver */ | ||
87 | static void rx(struct net_device *dev, int bufnum, | ||
88 | struct archdr *pkthdr, int length) | ||
89 | { | ||
90 | struct arcnet_local *lp = dev->priv; | ||
91 | struct sk_buff *skb; | ||
92 | struct archdr *pkt = pkthdr; | ||
93 | int ofs; | ||
94 | |||
95 | BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); | ||
96 | |||
97 | if (length >= MinTU) | ||
98 | ofs = 512 - length; | ||
99 | else | ||
100 | ofs = 256 - length; | ||
101 | |||
102 | skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); | ||
103 | if (skb == NULL) { | ||
104 | BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); | ||
105 | lp->stats.rx_dropped++; | ||
106 | return; | ||
107 | } | ||
108 | skb_put(skb, length + ARC_HDR_SIZE); | ||
109 | skb->dev = dev; | ||
110 | |||
111 | pkt = (struct archdr *) skb->data; | ||
112 | |||
113 | skb->mac.raw = skb->data; | ||
114 | skb_pull(skb, ARC_HDR_SIZE); | ||
115 | |||
116 | /* up to sizeof(pkt->soft) has already been copied from the card */ | ||
117 | memcpy(pkt, pkthdr, sizeof(struct archdr)); | ||
118 | if (length > sizeof(pkt->soft)) | ||
119 | lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), | ||
120 | pkt->soft.raw + sizeof(pkt->soft), | ||
121 | length - sizeof(pkt->soft)); | ||
122 | |||
123 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); | ||
124 | |||
125 | skb->protocol = __constant_htons(ETH_P_ARCNET); | ||
126 | ; | ||
127 | netif_rx(skb); | ||
128 | dev->last_rx = jiffies; | ||
129 | } | ||
130 | |||
131 | |||
132 | /* | ||
133 | * Create the ARCnet hard/soft headers for raw mode. | ||
134 | * There aren't any soft headers in raw mode - not even the protocol id. | ||
135 | */ | ||
136 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
137 | unsigned short type, uint8_t daddr) | ||
138 | { | ||
139 | int hdr_size = ARC_HDR_SIZE; | ||
140 | struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); | ||
141 | |||
142 | /* | ||
143 | * Set the source hardware address. | ||
144 | * | ||
145 | * This is pretty pointless for most purposes, but it can help in | ||
146 | * debugging. ARCnet does not allow us to change the source address in | ||
147 | * the actual packet sent) | ||
148 | */ | ||
149 | pkt->hard.source = *dev->dev_addr; | ||
150 | |||
151 | /* see linux/net/ethernet/eth.c to see where I got the following */ | ||
152 | |||
153 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { | ||
154 | /* | ||
155 | * FIXME: fill in the last byte of the dest ipaddr here to better | ||
156 | * comply with RFC1051 in "noarp" mode. | ||
157 | */ | ||
158 | pkt->hard.dest = 0; | ||
159 | return hdr_size; | ||
160 | } | ||
161 | /* otherwise, just fill it in and go! */ | ||
162 | pkt->hard.dest = daddr; | ||
163 | |||
164 | return hdr_size; /* success */ | ||
165 | } | ||
166 | |||
167 | |||
168 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
169 | int bufnum) | ||
170 | { | ||
171 | struct arcnet_local *lp = dev->priv; | ||
172 | struct arc_hardware *hard = &pkt->hard; | ||
173 | int ofs; | ||
174 | |||
175 | BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", | ||
176 | lp->next_tx, lp->cur_tx, bufnum); | ||
177 | |||
178 | length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ | ||
179 | |||
180 | if (length > XMTU) { | ||
181 | /* should never happen! other people already check for this. */ | ||
182 | BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", | ||
183 | length, XMTU); | ||
184 | length = XMTU; | ||
185 | } | ||
186 | if (length > MinTU) { | ||
187 | hard->offset[0] = 0; | ||
188 | hard->offset[1] = ofs = 512 - length; | ||
189 | } else if (length > MTU) { | ||
190 | hard->offset[0] = 0; | ||
191 | hard->offset[1] = ofs = 512 - length - 3; | ||
192 | } else | ||
193 | hard->offset[0] = ofs = 256 - length; | ||
194 | |||
195 | BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", | ||
196 | length,ofs); | ||
197 | |||
198 | lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); | ||
199 | lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); | ||
200 | |||
201 | lp->lastload_dest = hard->dest; | ||
202 | |||
203 | return 1; /* done */ | ||
204 | } | ||
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c new file mode 100644 index 000000000000..38c3f033f739 --- /dev/null +++ b/drivers/net/arcnet/arc-rimi.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun. | ||
5 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
6 | * Derived from skeleton.c by Donald Becker. | ||
7 | * | ||
8 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
9 | * for sponsoring the further development of this driver. | ||
10 | * | ||
11 | * ********************** | ||
12 | * | ||
13 | * The original copyright of skeleton.c was as follows: | ||
14 | * | ||
15 | * skeleton.c Written 1993 by Donald Becker. | ||
16 | * Copyright 1993 United States Government as represented by the | ||
17 | * Director, National Security Agency. This software may only be used | ||
18 | * and distributed according to the terms of the GNU General Public License as | ||
19 | * modified by SRC, incorporated herein by reference. | ||
20 | * | ||
21 | * ********************** | ||
22 | * | ||
23 | * For more details, see drivers/net/arcnet.c | ||
24 | * | ||
25 | * ********************** | ||
26 | */ | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/ioport.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/netdevice.h> | ||
34 | #include <linux/bootmem.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <linux/arcdevice.h> | ||
38 | |||
39 | |||
40 | #define VERSION "arcnet: RIM I (entirely mem-mapped) support\n" | ||
41 | |||
42 | |||
43 | /* Internal function declarations */ | ||
44 | |||
45 | static int arcrimi_probe(struct net_device *dev); | ||
46 | static int arcrimi_found(struct net_device *dev); | ||
47 | static void arcrimi_command(struct net_device *dev, int command); | ||
48 | static int arcrimi_status(struct net_device *dev); | ||
49 | static void arcrimi_setmask(struct net_device *dev, int mask); | ||
50 | static int arcrimi_reset(struct net_device *dev, int really_reset); | ||
51 | static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
52 | void *buf, int count); | ||
53 | static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
54 | void *buf, int count); | ||
55 | |||
56 | /* Handy defines for ARCnet specific stuff */ | ||
57 | |||
58 | /* Amount of I/O memory used by the card */ | ||
59 | #define BUFFER_SIZE (512) | ||
60 | #define MIRROR_SIZE (BUFFER_SIZE*4) | ||
61 | |||
62 | /* COM 9026 controller chip --> ARCnet register addresses */ | ||
63 | #define _INTMASK (ioaddr+0) /* writable */ | ||
64 | #define _STATUS (ioaddr+0) /* readable */ | ||
65 | #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ | ||
66 | #define _RESET (ioaddr+8) /* software reset (on read) */ | ||
67 | #define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ | ||
68 | #define _ADDR_HI (ioaddr+15) /* Control registers for said */ | ||
69 | #define _ADDR_LO (ioaddr+14) | ||
70 | #define _CONFIG (ioaddr+2) /* Configuration register */ | ||
71 | |||
72 | #undef ASTATUS | ||
73 | #undef ACOMMAND | ||
74 | #undef AINTMASK | ||
75 | |||
76 | #define ASTATUS() readb(_STATUS) | ||
77 | #define ACOMMAND(cmd) writeb((cmd),_COMMAND) | ||
78 | #define AINTMASK(msk) writeb((msk),_INTMASK) | ||
79 | #define SETCONF() writeb(lp->config,_CONFIG) | ||
80 | |||
81 | |||
82 | /* | ||
83 | * We cannot probe for a RIM I card; one reason is I don't know how to reset | ||
84 | * them. In fact, we can't even get their node ID automatically. So, we | ||
85 | * need to be passed a specific shmem address, IRQ, and node ID. | ||
86 | */ | ||
87 | static int __init arcrimi_probe(struct net_device *dev) | ||
88 | { | ||
89 | BUGLVL(D_NORMAL) printk(VERSION); | ||
90 | BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); | ||
91 | |||
92 | BUGMSG(D_NORMAL, "Given: node %02Xh, shmem %lXh, irq %d\n", | ||
93 | dev->dev_addr[0], dev->mem_start, dev->irq); | ||
94 | |||
95 | if (dev->mem_start <= 0 || dev->irq <= 0) { | ||
96 | BUGMSG(D_NORMAL, "No autoprobe for RIM I; you " | ||
97 | "must specify the shmem and irq!\n"); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | /* | ||
101 | * Grab the memory region at mem_start for BUFFER_SIZE bytes. | ||
102 | * Later in arcrimi_found() the real size will be determined | ||
103 | * and this reserve will be released and the correct size | ||
104 | * will be taken. | ||
105 | */ | ||
106 | if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) { | ||
107 | BUGMSG(D_NORMAL, "Card memory already allocated\n"); | ||
108 | return -ENODEV; | ||
109 | } | ||
110 | if (dev->dev_addr[0] == 0) { | ||
111 | release_mem_region(dev->mem_start, BUFFER_SIZE); | ||
112 | BUGMSG(D_NORMAL, "You need to specify your card's station " | ||
113 | "ID!\n"); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | return arcrimi_found(dev); | ||
117 | } | ||
118 | |||
119 | |||
120 | /* | ||
121 | * Set up the struct net_device associated with this card. Called after | ||
122 | * probing succeeds. | ||
123 | */ | ||
124 | static int __init arcrimi_found(struct net_device *dev) | ||
125 | { | ||
126 | struct arcnet_local *lp; | ||
127 | unsigned long first_mirror, last_mirror, shmem; | ||
128 | int mirror_size; | ||
129 | int err; | ||
130 | |||
131 | /* reserve the irq */ | ||
132 | if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { | ||
133 | release_mem_region(dev->mem_start, BUFFER_SIZE); | ||
134 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); | ||
135 | return -ENODEV; | ||
136 | } | ||
137 | |||
138 | shmem = dev->mem_start; | ||
139 | isa_writeb(TESTvalue, shmem); | ||
140 | isa_writeb(dev->dev_addr[0], shmem + 1); /* actually the node ID */ | ||
141 | |||
142 | /* find the real shared memory start/end points, including mirrors */ | ||
143 | |||
144 | /* guess the actual size of one "memory mirror" - the number of | ||
145 | * bytes between copies of the shared memory. On most cards, it's | ||
146 | * 2k (or there are no mirrors at all) but on some, it's 4k. | ||
147 | */ | ||
148 | mirror_size = MIRROR_SIZE; | ||
149 | if (isa_readb(shmem) == TESTvalue | ||
150 | && isa_readb(shmem - mirror_size) != TESTvalue | ||
151 | && isa_readb(shmem - 2 * mirror_size) == TESTvalue) | ||
152 | mirror_size *= 2; | ||
153 | |||
154 | first_mirror = last_mirror = shmem; | ||
155 | while (isa_readb(first_mirror) == TESTvalue) | ||
156 | first_mirror -= mirror_size; | ||
157 | first_mirror += mirror_size; | ||
158 | |||
159 | while (isa_readb(last_mirror) == TESTvalue) | ||
160 | last_mirror += mirror_size; | ||
161 | last_mirror -= mirror_size; | ||
162 | |||
163 | dev->mem_start = first_mirror; | ||
164 | dev->mem_end = last_mirror + MIRROR_SIZE - 1; | ||
165 | |||
166 | /* initialize the rest of the device structure. */ | ||
167 | |||
168 | lp = dev->priv; | ||
169 | lp->card_name = "RIM I"; | ||
170 | lp->hw.command = arcrimi_command; | ||
171 | lp->hw.status = arcrimi_status; | ||
172 | lp->hw.intmask = arcrimi_setmask; | ||
173 | lp->hw.reset = arcrimi_reset; | ||
174 | lp->hw.owner = THIS_MODULE; | ||
175 | lp->hw.copy_to_card = arcrimi_copy_to_card; | ||
176 | lp->hw.copy_from_card = arcrimi_copy_from_card; | ||
177 | |||
178 | /* | ||
179 | * re-reserve the memory region - arcrimi_probe() alloced this reqion | ||
180 | * but didn't know the real size. Free that region and then re-get | ||
181 | * with the correct size. There is a VERY slim chance this could | ||
182 | * fail. | ||
183 | */ | ||
184 | release_mem_region(shmem, BUFFER_SIZE); | ||
185 | if (!request_mem_region(dev->mem_start, | ||
186 | dev->mem_end - dev->mem_start + 1, | ||
187 | "arcnet (90xx)")) { | ||
188 | BUGMSG(D_NORMAL, "Card memory already allocated\n"); | ||
189 | goto err_free_irq; | ||
190 | } | ||
191 | |||
192 | lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
193 | if (!lp->mem_start) { | ||
194 | BUGMSG(D_NORMAL, "Can't remap device memory!\n"); | ||
195 | goto err_release_mem; | ||
196 | } | ||
197 | |||
198 | /* get and check the station ID from offset 1 in shmem */ | ||
199 | dev->dev_addr[0] = readb(lp->mem_start + 1); | ||
200 | |||
201 | BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, " | ||
202 | "ShMem %lXh (%ld*%d bytes).\n", | ||
203 | dev->dev_addr[0], | ||
204 | dev->irq, dev->mem_start, | ||
205 | (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); | ||
206 | |||
207 | err = register_netdev(dev); | ||
208 | if (err) | ||
209 | goto err_unmap; | ||
210 | |||
211 | return 0; | ||
212 | |||
213 | err_unmap: | ||
214 | iounmap(lp->mem_start); | ||
215 | err_release_mem: | ||
216 | release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
217 | err_free_irq: | ||
218 | free_irq(dev->irq, dev); | ||
219 | return -EIO; | ||
220 | } | ||
221 | |||
222 | |||
223 | /* | ||
224 | * Do a hardware reset on the card, and set up necessary registers. | ||
225 | * | ||
226 | * This should be called as little as possible, because it disrupts the | ||
227 | * token on the network (causes a RECON) and requires a significant delay. | ||
228 | * | ||
229 | * However, it does make sure the card is in a defined state. | ||
230 | */ | ||
231 | static int arcrimi_reset(struct net_device *dev, int really_reset) | ||
232 | { | ||
233 | struct arcnet_local *lp = dev->priv; | ||
234 | void __iomem *ioaddr = lp->mem_start + 0x800; | ||
235 | |||
236 | BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); | ||
237 | |||
238 | if (really_reset) { | ||
239 | writeb(TESTvalue, ioaddr - 0x800); /* fake reset */ | ||
240 | return 0; | ||
241 | } | ||
242 | ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ | ||
243 | ACOMMAND(CFLAGScmd | CONFIGclear); | ||
244 | |||
245 | /* enable extended (512-byte) packets */ | ||
246 | ACOMMAND(CONFIGcmd | EXTconf); | ||
247 | |||
248 | /* done! return success. */ | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static void arcrimi_setmask(struct net_device *dev, int mask) | ||
253 | { | ||
254 | struct arcnet_local *lp = dev->priv; | ||
255 | void __iomem *ioaddr = lp->mem_start + 0x800; | ||
256 | |||
257 | AINTMASK(mask); | ||
258 | } | ||
259 | |||
260 | static int arcrimi_status(struct net_device *dev) | ||
261 | { | ||
262 | struct arcnet_local *lp = dev->priv; | ||
263 | void __iomem *ioaddr = lp->mem_start + 0x800; | ||
264 | |||
265 | return ASTATUS(); | ||
266 | } | ||
267 | |||
268 | static void arcrimi_command(struct net_device *dev, int cmd) | ||
269 | { | ||
270 | struct arcnet_local *lp = dev->priv; | ||
271 | void __iomem *ioaddr = lp->mem_start + 0x800; | ||
272 | |||
273 | ACOMMAND(cmd); | ||
274 | } | ||
275 | |||
276 | static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
277 | void *buf, int count) | ||
278 | { | ||
279 | struct arcnet_local *lp = dev->priv; | ||
280 | void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; | ||
281 | TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); | ||
282 | } | ||
283 | |||
284 | |||
285 | static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
286 | void *buf, int count) | ||
287 | { | ||
288 | struct arcnet_local *lp = dev->priv; | ||
289 | void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; | ||
290 | TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); | ||
291 | } | ||
292 | |||
293 | static int node; | ||
294 | static int io; /* use the insmod io= irq= node= options */ | ||
295 | static int irq; | ||
296 | static char device[9]; /* use eg. device=arc1 to change name */ | ||
297 | |||
298 | module_param(node, int, 0); | ||
299 | module_param(io, int, 0); | ||
300 | module_param(irq, int, 0); | ||
301 | module_param_string(device, device, sizeof(device), 0); | ||
302 | MODULE_LICENSE("GPL"); | ||
303 | |||
304 | static struct net_device *my_dev; | ||
305 | |||
306 | static int __init arc_rimi_init(void) | ||
307 | { | ||
308 | struct net_device *dev; | ||
309 | |||
310 | dev = alloc_arcdev(device); | ||
311 | if (!dev) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | if (node && node != 0xff) | ||
315 | dev->dev_addr[0] = node; | ||
316 | |||
317 | dev->mem_start = io; | ||
318 | dev->irq = irq; | ||
319 | if (dev->irq == 2) | ||
320 | dev->irq = 9; | ||
321 | |||
322 | if (arcrimi_probe(dev)) { | ||
323 | free_netdev(dev); | ||
324 | return -EIO; | ||
325 | } | ||
326 | |||
327 | my_dev = dev; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static void __exit arc_rimi_exit(void) | ||
332 | { | ||
333 | struct net_device *dev = my_dev; | ||
334 | struct arcnet_local *lp = dev->priv; | ||
335 | |||
336 | unregister_netdev(dev); | ||
337 | iounmap(lp->mem_start); | ||
338 | release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
339 | free_irq(dev->irq, dev); | ||
340 | free_netdev(dev); | ||
341 | } | ||
342 | |||
343 | #ifndef MODULE | ||
344 | static int __init arcrimi_setup(char *s) | ||
345 | { | ||
346 | int ints[8]; | ||
347 | s = get_options(s, 8, ints); | ||
348 | if (!ints[0]) | ||
349 | return 1; | ||
350 | switch (ints[0]) { | ||
351 | default: /* ERROR */ | ||
352 | printk("arcrimi: Too many arguments.\n"); | ||
353 | case 3: /* Node ID */ | ||
354 | node = ints[3]; | ||
355 | case 2: /* IRQ */ | ||
356 | irq = ints[2]; | ||
357 | case 1: /* IO address */ | ||
358 | io = ints[1]; | ||
359 | } | ||
360 | if (*s) | ||
361 | snprintf(device, sizeof(device), "%s", s); | ||
362 | return 1; | ||
363 | } | ||
364 | __setup("arcrimi=", arcrimi_setup); | ||
365 | #endif /* MODULE */ | ||
366 | |||
367 | module_init(arc_rimi_init) | ||
368 | module_exit(arc_rimi_exit) | ||
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c new file mode 100644 index 000000000000..4f9f69e22c1b --- /dev/null +++ b/drivers/net/arcnet/arcnet.c | |||
@@ -0,0 +1,1102 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - device-independent routines | ||
3 | * | ||
4 | * Written 1997 by David Woodhouse. | ||
5 | * Written 1994-1999 by Avery Pennarun. | ||
6 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
7 | * Derived from skeleton.c by Donald Becker. | ||
8 | * | ||
9 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
10 | * for sponsoring the further development of this driver. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * The change log is now in a file called ChangeLog in this directory. | ||
25 | * | ||
26 | * Sources: | ||
27 | * - Crynwr arcnet.com/arcether.com packet drivers. | ||
28 | * - arcnet.c v0.00 dated 1/1/94 and apparently by | ||
29 | * Donald Becker - it didn't work :) | ||
30 | * - skeleton.c v0.05 dated 11/16/93 by Donald Becker | ||
31 | * (from Linux Kernel 1.1.45) | ||
32 | * - RFC's 1201 and 1051 - re: TCP/IP over ARCnet | ||
33 | * - The official ARCnet COM9026 data sheets (!) thanks to | ||
34 | * Ken Cornetet <kcornete@nyx10.cs.du.edu> | ||
35 | * - The official ARCnet COM20020 data sheets. | ||
36 | * - Information on some more obscure ARCnet controller chips, thanks | ||
37 | * to the nice people at SMSC. | ||
38 | * - net/inet/eth.c (from kernel 1.1.50) for header-building info. | ||
39 | * - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su> | ||
40 | * - Textual information and more alternate source from Joachim Koenig | ||
41 | * <jojo@repas.de> | ||
42 | */ | ||
43 | |||
44 | #define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n" | ||
45 | |||
46 | #include <linux/module.h> | ||
47 | #include <linux/config.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/delay.h> | ||
50 | #include <linux/netdevice.h> | ||
51 | #include <linux/if_arp.h> | ||
52 | #include <net/arp.h> | ||
53 | #include <linux/init.h> | ||
54 | #include <linux/arcdevice.h> | ||
55 | |||
56 | /* "do nothing" functions for protocol drivers */ | ||
57 | static void null_rx(struct net_device *dev, int bufnum, | ||
58 | struct archdr *pkthdr, int length); | ||
59 | static int null_build_header(struct sk_buff *skb, struct net_device *dev, | ||
60 | unsigned short type, uint8_t daddr); | ||
61 | static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, | ||
62 | int length, int bufnum); | ||
63 | |||
64 | |||
65 | /* | ||
66 | * one ArcProto per possible proto ID. None of the elements of | ||
67 | * arc_proto_map are allowed to be NULL; they will get set to | ||
68 | * arc_proto_default instead. It also must not be NULL; if you would like | ||
69 | * to set it to NULL, set it to &arc_proto_null instead. | ||
70 | */ | ||
71 | struct ArcProto *arc_proto_map[256], *arc_proto_default, | ||
72 | *arc_bcast_proto, *arc_raw_proto; | ||
73 | |||
74 | struct ArcProto arc_proto_null = | ||
75 | { | ||
76 | .suffix = '?', | ||
77 | .mtu = XMTU, | ||
78 | .is_ip = 0, | ||
79 | .rx = null_rx, | ||
80 | .build_header = null_build_header, | ||
81 | .prepare_tx = null_prepare_tx, | ||
82 | .continue_tx = NULL, | ||
83 | .ack_tx = NULL | ||
84 | }; | ||
85 | |||
86 | /* Exported function prototypes */ | ||
87 | int arcnet_debug = ARCNET_DEBUG; | ||
88 | |||
89 | EXPORT_SYMBOL(arc_proto_map); | ||
90 | EXPORT_SYMBOL(arc_proto_default); | ||
91 | EXPORT_SYMBOL(arc_bcast_proto); | ||
92 | EXPORT_SYMBOL(arc_raw_proto); | ||
93 | EXPORT_SYMBOL(arc_proto_null); | ||
94 | EXPORT_SYMBOL(arcnet_unregister_proto); | ||
95 | EXPORT_SYMBOL(arcnet_debug); | ||
96 | EXPORT_SYMBOL(alloc_arcdev); | ||
97 | EXPORT_SYMBOL(arcnet_interrupt); | ||
98 | |||
99 | /* Internal function prototypes */ | ||
100 | static int arcnet_open(struct net_device *dev); | ||
101 | static int arcnet_close(struct net_device *dev); | ||
102 | static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
103 | static void arcnet_timeout(struct net_device *dev); | ||
104 | static int arcnet_header(struct sk_buff *skb, struct net_device *dev, | ||
105 | unsigned short type, void *daddr, void *saddr, | ||
106 | unsigned len); | ||
107 | static int arcnet_rebuild_header(struct sk_buff *skb); | ||
108 | static struct net_device_stats *arcnet_get_stats(struct net_device *dev); | ||
109 | static int go_tx(struct net_device *dev); | ||
110 | |||
111 | static int debug = ARCNET_DEBUG; | ||
112 | module_param(debug, int, 0); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | |||
115 | static int __init arcnet_init(void) | ||
116 | { | ||
117 | int count; | ||
118 | |||
119 | arcnet_debug = debug; | ||
120 | |||
121 | printk(VERSION); | ||
122 | |||
123 | #ifdef ALPHA_WARNING | ||
124 | BUGLVL(D_EXTRA) { | ||
125 | printk("arcnet: ***\n" | ||
126 | "arcnet: * Read arcnet.txt for important release notes!\n" | ||
127 | "arcnet: *\n" | ||
128 | "arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n" | ||
129 | "arcnet: * me if you have any questions, comments, or bug reports.\n" | ||
130 | "arcnet: ***\n"); | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | /* initialize the protocol map */ | ||
135 | arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null; | ||
136 | for (count = 0; count < 256; count++) | ||
137 | arc_proto_map[count] = arc_proto_default; | ||
138 | |||
139 | BUGLVL(D_DURING) | ||
140 | printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", | ||
141 | sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), | ||
142 | sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), | ||
143 | sizeof(struct archdr)); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit arcnet_exit(void) | ||
149 | { | ||
150 | } | ||
151 | |||
152 | module_init(arcnet_init); | ||
153 | module_exit(arcnet_exit); | ||
154 | |||
155 | /* | ||
156 | * Dump the contents of an sk_buff | ||
157 | */ | ||
158 | #if ARCNET_DEBUG_MAX & D_SKB | ||
159 | void arcnet_dump_skb(struct net_device *dev, | ||
160 | struct sk_buff *skb, char *desc) | ||
161 | { | ||
162 | int i; | ||
163 | |||
164 | printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); | ||
165 | for (i = 0; i < skb->len; i++) { | ||
166 | if (i % 16 == 0) | ||
167 | printk("\n" KERN_DEBUG "[%04X] ", i); | ||
168 | printk("%02X ", ((u_char *) skb->data)[i]); | ||
169 | } | ||
170 | printk("\n"); | ||
171 | } | ||
172 | |||
173 | EXPORT_SYMBOL(arcnet_dump_skb); | ||
174 | #endif | ||
175 | |||
176 | |||
177 | /* | ||
178 | * Dump the contents of an ARCnet buffer | ||
179 | */ | ||
180 | #if (ARCNET_DEBUG_MAX & (D_RX | D_TX)) | ||
181 | void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, | ||
182 | int take_arcnet_lock) | ||
183 | { | ||
184 | struct arcnet_local *lp = dev->priv; | ||
185 | int i, length; | ||
186 | unsigned long flags = 0; | ||
187 | static uint8_t buf[512]; | ||
188 | |||
189 | /* hw.copy_from_card expects IRQ context so take the IRQ lock | ||
190 | to keep it single threaded */ | ||
191 | if(take_arcnet_lock) | ||
192 | spin_lock_irqsave(&lp->lock, flags); | ||
193 | |||
194 | lp->hw.copy_from_card(dev, bufnum, 0, buf, 512); | ||
195 | if(take_arcnet_lock) | ||
196 | spin_unlock_irqrestore(&lp->lock, flags); | ||
197 | |||
198 | /* if the offset[0] byte is nonzero, this is a 256-byte packet */ | ||
199 | length = (buf[2] ? 256 : 512); | ||
200 | |||
201 | printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); | ||
202 | for (i = 0; i < length; i++) { | ||
203 | if (i % 16 == 0) | ||
204 | printk("\n" KERN_DEBUG "[%04X] ", i); | ||
205 | printk("%02X ", buf[i]); | ||
206 | } | ||
207 | printk("\n"); | ||
208 | |||
209 | } | ||
210 | |||
211 | EXPORT_SYMBOL(arcnet_dump_packet); | ||
212 | #endif | ||
213 | |||
214 | |||
215 | /* | ||
216 | * Unregister a protocol driver from the arc_proto_map. Protocol drivers | ||
217 | * are responsible for registering themselves, but the unregister routine | ||
218 | * is pretty generic so we'll do it here. | ||
219 | */ | ||
220 | void arcnet_unregister_proto(struct ArcProto *proto) | ||
221 | { | ||
222 | int count; | ||
223 | |||
224 | if (arc_proto_default == proto) | ||
225 | arc_proto_default = &arc_proto_null; | ||
226 | if (arc_bcast_proto == proto) | ||
227 | arc_bcast_proto = arc_proto_default; | ||
228 | if (arc_raw_proto == proto) | ||
229 | arc_raw_proto = arc_proto_default; | ||
230 | |||
231 | for (count = 0; count < 256; count++) { | ||
232 | if (arc_proto_map[count] == proto) | ||
233 | arc_proto_map[count] = arc_proto_default; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | |||
238 | /* | ||
239 | * Add a buffer to the queue. Only the interrupt handler is allowed to do | ||
240 | * this, unless interrupts are disabled. | ||
241 | * | ||
242 | * Note: we don't check for a full queue, since there aren't enough buffers | ||
243 | * to more than fill it. | ||
244 | */ | ||
245 | static void release_arcbuf(struct net_device *dev, int bufnum) | ||
246 | { | ||
247 | struct arcnet_local *lp = dev->priv; | ||
248 | int i; | ||
249 | |||
250 | lp->buf_queue[lp->first_free_buf++] = bufnum; | ||
251 | lp->first_free_buf %= 5; | ||
252 | |||
253 | BUGLVL(D_DURING) { | ||
254 | BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", | ||
255 | bufnum); | ||
256 | for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) | ||
257 | BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); | ||
258 | BUGMSG2(D_DURING, "\n"); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | /* | ||
264 | * Get a buffer from the queue. If this returns -1, there are no buffers | ||
265 | * available. | ||
266 | */ | ||
267 | static int get_arcbuf(struct net_device *dev) | ||
268 | { | ||
269 | struct arcnet_local *lp = dev->priv; | ||
270 | int buf = -1, i; | ||
271 | |||
272 | if (!atomic_dec_and_test(&lp->buf_lock)) { | ||
273 | /* already in this function */ | ||
274 | BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", | ||
275 | lp->buf_lock.counter); | ||
276 | } | ||
277 | else { /* we can continue */ | ||
278 | if (lp->next_buf >= 5) | ||
279 | lp->next_buf -= 5; | ||
280 | |||
281 | if (lp->next_buf == lp->first_free_buf) | ||
282 | BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n"); | ||
283 | else { | ||
284 | buf = lp->buf_queue[lp->next_buf++]; | ||
285 | lp->next_buf %= 5; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | |||
290 | BUGLVL(D_DURING) { | ||
291 | BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); | ||
292 | for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) | ||
293 | BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); | ||
294 | BUGMSG2(D_DURING, "\n"); | ||
295 | } | ||
296 | |||
297 | atomic_inc(&lp->buf_lock); | ||
298 | return buf; | ||
299 | } | ||
300 | |||
301 | |||
302 | static int choose_mtu(void) | ||
303 | { | ||
304 | int count, mtu = 65535; | ||
305 | |||
306 | /* choose the smallest MTU of all available encaps */ | ||
307 | for (count = 0; count < 256; count++) { | ||
308 | if (arc_proto_map[count] != &arc_proto_null | ||
309 | && arc_proto_map[count]->mtu < mtu) { | ||
310 | mtu = arc_proto_map[count]->mtu; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | return mtu == 65535 ? XMTU : mtu; | ||
315 | } | ||
316 | |||
317 | |||
318 | /* Setup a struct device for ARCnet. */ | ||
319 | static void arcdev_setup(struct net_device *dev) | ||
320 | { | ||
321 | dev->type = ARPHRD_ARCNET; | ||
322 | dev->hard_header_len = sizeof(struct archdr); | ||
323 | dev->mtu = choose_mtu(); | ||
324 | |||
325 | dev->addr_len = ARCNET_ALEN; | ||
326 | dev->tx_queue_len = 100; | ||
327 | dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ | ||
328 | dev->watchdog_timeo = TX_TIMEOUT; | ||
329 | |||
330 | /* New-style flags. */ | ||
331 | dev->flags = IFF_BROADCAST; | ||
332 | |||
333 | /* | ||
334 | * Put in this stuff here, so we don't have to export the symbols to | ||
335 | * the chipset drivers. | ||
336 | */ | ||
337 | dev->open = arcnet_open; | ||
338 | dev->stop = arcnet_close; | ||
339 | dev->hard_start_xmit = arcnet_send_packet; | ||
340 | dev->tx_timeout = arcnet_timeout; | ||
341 | dev->get_stats = arcnet_get_stats; | ||
342 | dev->hard_header = arcnet_header; | ||
343 | dev->rebuild_header = arcnet_rebuild_header; | ||
344 | } | ||
345 | |||
346 | struct net_device *alloc_arcdev(char *name) | ||
347 | { | ||
348 | struct net_device *dev; | ||
349 | |||
350 | dev = alloc_netdev(sizeof(struct arcnet_local), | ||
351 | name && *name ? name : "arc%d", arcdev_setup); | ||
352 | if(dev) { | ||
353 | struct arcnet_local *lp = (struct arcnet_local *) dev->priv; | ||
354 | spin_lock_init(&lp->lock); | ||
355 | } | ||
356 | |||
357 | return dev; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Open/initialize the board. This is called sometime after booting when | ||
362 | * the 'ifconfig' program is run. | ||
363 | * | ||
364 | * This routine should set everything up anew at each open, even registers | ||
365 | * that "should" only need to be set once at boot, so that there is | ||
366 | * non-reboot way to recover if something goes wrong. | ||
367 | */ | ||
368 | static int arcnet_open(struct net_device *dev) | ||
369 | { | ||
370 | struct arcnet_local *lp = dev->priv; | ||
371 | int count, newmtu, error; | ||
372 | |||
373 | BUGMSG(D_INIT,"opened."); | ||
374 | |||
375 | if (!try_module_get(lp->hw.owner)) | ||
376 | return -ENODEV; | ||
377 | |||
378 | BUGLVL(D_PROTO) { | ||
379 | int count; | ||
380 | BUGMSG(D_PROTO, "protocol map (default is '%c'): ", | ||
381 | arc_proto_default->suffix); | ||
382 | for (count = 0; count < 256; count++) | ||
383 | BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix); | ||
384 | BUGMSG2(D_PROTO, "\n"); | ||
385 | } | ||
386 | |||
387 | |||
388 | BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); | ||
389 | |||
390 | /* try to put the card in a defined state - if it fails the first | ||
391 | * time, actually reset it. | ||
392 | */ | ||
393 | error = -ENODEV; | ||
394 | if (ARCRESET(0) && ARCRESET(1)) | ||
395 | goto out_module_put; | ||
396 | |||
397 | newmtu = choose_mtu(); | ||
398 | if (newmtu < dev->mtu) | ||
399 | dev->mtu = newmtu; | ||
400 | |||
401 | BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu); | ||
402 | |||
403 | /* autodetect the encapsulation for each host. */ | ||
404 | memset(lp->default_proto, 0, sizeof(lp->default_proto)); | ||
405 | |||
406 | /* the broadcast address is special - use the 'bcast' protocol */ | ||
407 | for (count = 0; count < 256; count++) { | ||
408 | if (arc_proto_map[count] == arc_bcast_proto) { | ||
409 | lp->default_proto[0] = count; | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | /* initialize buffers */ | ||
415 | atomic_set(&lp->buf_lock, 1); | ||
416 | |||
417 | lp->next_buf = lp->first_free_buf = 0; | ||
418 | release_arcbuf(dev, 0); | ||
419 | release_arcbuf(dev, 1); | ||
420 | release_arcbuf(dev, 2); | ||
421 | release_arcbuf(dev, 3); | ||
422 | lp->cur_tx = lp->next_tx = -1; | ||
423 | lp->cur_rx = -1; | ||
424 | |||
425 | lp->rfc1201.sequence = 1; | ||
426 | |||
427 | /* bring up the hardware driver */ | ||
428 | if (lp->hw.open) | ||
429 | lp->hw.open(dev); | ||
430 | |||
431 | if (dev->dev_addr[0] == 0) | ||
432 | BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " | ||
433 | "for broadcasts!\n"); | ||
434 | else if (dev->dev_addr[0] == 255) | ||
435 | BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " | ||
436 | "DOS networking programs!\n"); | ||
437 | |||
438 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
439 | if (ASTATUS() & RESETflag) { | ||
440 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
441 | ACOMMAND(CFLAGScmd | RESETclear); | ||
442 | } | ||
443 | |||
444 | |||
445 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
446 | /* make sure we're ready to receive IRQ's. */ | ||
447 | AINTMASK(0); | ||
448 | udelay(1); /* give it time to set the mask before | ||
449 | * we reset it again. (may not even be | ||
450 | * necessary) | ||
451 | */ | ||
452 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
453 | lp->intmask = NORXflag | RECONflag; | ||
454 | AINTMASK(lp->intmask); | ||
455 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
456 | |||
457 | netif_start_queue(dev); | ||
458 | |||
459 | return 0; | ||
460 | |||
461 | out_module_put: | ||
462 | module_put(lp->hw.owner); | ||
463 | return error; | ||
464 | } | ||
465 | |||
466 | |||
467 | /* The inverse routine to arcnet_open - shuts down the card. */ | ||
468 | static int arcnet_close(struct net_device *dev) | ||
469 | { | ||
470 | struct arcnet_local *lp = dev->priv; | ||
471 | |||
472 | netif_stop_queue(dev); | ||
473 | |||
474 | /* flush TX and disable RX */ | ||
475 | AINTMASK(0); | ||
476 | ACOMMAND(NOTXcmd); /* stop transmit */ | ||
477 | ACOMMAND(NORXcmd); /* disable receive */ | ||
478 | mdelay(1); | ||
479 | |||
480 | /* shut down the card */ | ||
481 | lp->hw.close(dev); | ||
482 | module_put(lp->hw.owner); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | |||
487 | static int arcnet_header(struct sk_buff *skb, struct net_device *dev, | ||
488 | unsigned short type, void *daddr, void *saddr, | ||
489 | unsigned len) | ||
490 | { | ||
491 | struct arcnet_local *lp = dev->priv; | ||
492 | uint8_t _daddr, proto_num; | ||
493 | struct ArcProto *proto; | ||
494 | |||
495 | BUGMSG(D_DURING, | ||
496 | "create header from %d to %d; protocol %d (%Xh); size %u.\n", | ||
497 | saddr ? *(uint8_t *) saddr : -1, | ||
498 | daddr ? *(uint8_t *) daddr : -1, | ||
499 | type, type, len); | ||
500 | |||
501 | if (skb->len!=0 && len != skb->len) | ||
502 | BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", | ||
503 | skb->len, len); | ||
504 | |||
505 | |||
506 | /* Type is host order - ? */ | ||
507 | if(type == ETH_P_ARCNET) { | ||
508 | proto = arc_raw_proto; | ||
509 | BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix); | ||
510 | _daddr = daddr ? *(uint8_t *) daddr : 0; | ||
511 | } | ||
512 | else if (!daddr) { | ||
513 | /* | ||
514 | * if the dest addr isn't provided, we can't choose an encapsulation! | ||
515 | * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a | ||
516 | * real header when we do rebuild_header. | ||
517 | */ | ||
518 | *(uint16_t *) skb_push(skb, 2) = type; | ||
519 | if (skb->nh.raw - skb->mac.raw != 2) | ||
520 | BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", | ||
521 | (int)(skb->nh.raw - skb->mac.raw)); | ||
522 | return -2; /* return error -- can't transmit yet! */ | ||
523 | } | ||
524 | else { | ||
525 | /* otherwise, we can just add the header as usual. */ | ||
526 | _daddr = *(uint8_t *) daddr; | ||
527 | proto_num = lp->default_proto[_daddr]; | ||
528 | proto = arc_proto_map[proto_num]; | ||
529 | BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", | ||
530 | proto_num, proto->suffix); | ||
531 | if (proto == &arc_proto_null && arc_bcast_proto != proto) { | ||
532 | BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", | ||
533 | arc_bcast_proto->suffix); | ||
534 | proto = arc_bcast_proto; | ||
535 | } | ||
536 | } | ||
537 | return proto->build_header(skb, dev, type, _daddr); | ||
538 | } | ||
539 | |||
540 | |||
541 | /* | ||
542 | * Rebuild the ARCnet hard header. This is called after an ARP (or in the | ||
543 | * future other address resolution) has completed on this sk_buff. We now | ||
544 | * let ARP fill in the destination field. | ||
545 | */ | ||
546 | static int arcnet_rebuild_header(struct sk_buff *skb) | ||
547 | { | ||
548 | struct net_device *dev = skb->dev; | ||
549 | struct arcnet_local *lp = dev->priv; | ||
550 | int status = 0; /* default is failure */ | ||
551 | unsigned short type; | ||
552 | uint8_t daddr=0; | ||
553 | struct ArcProto *proto; | ||
554 | |||
555 | if (skb->nh.raw - skb->mac.raw != 2) { | ||
556 | BUGMSG(D_NORMAL, | ||
557 | "rebuild_header: shouldn't be here! (hdrsize=%d)\n", | ||
558 | (int)(skb->nh.raw - skb->mac.raw)); | ||
559 | return 0; | ||
560 | } | ||
561 | type = *(uint16_t *) skb_pull(skb, 2); | ||
562 | BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type); | ||
563 | |||
564 | if (type == ETH_P_IP) { | ||
565 | #ifdef CONFIG_INET | ||
566 | BUGMSG(D_DURING, "rebuild header for ethernet protocol %Xh\n", type); | ||
567 | status = arp_find(&daddr, skb) ? 1 : 0; | ||
568 | BUGMSG(D_DURING, " rebuilt: dest is %d; protocol %Xh\n", | ||
569 | daddr, type); | ||
570 | #endif | ||
571 | } else { | ||
572 | BUGMSG(D_NORMAL, | ||
573 | "I don't understand ethernet protocol %Xh addresses!\n", type); | ||
574 | lp->stats.tx_errors++; | ||
575 | lp->stats.tx_aborted_errors++; | ||
576 | } | ||
577 | |||
578 | /* if we couldn't resolve the address... give up. */ | ||
579 | if (!status) | ||
580 | return 0; | ||
581 | |||
582 | /* add the _real_ header this time! */ | ||
583 | proto = arc_proto_map[lp->default_proto[daddr]]; | ||
584 | proto->build_header(skb, dev, type, daddr); | ||
585 | |||
586 | return 1; /* success */ | ||
587 | } | ||
588 | |||
589 | |||
590 | |||
591 | /* Called by the kernel in order to transmit a packet. */ | ||
592 | static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) | ||
593 | { | ||
594 | struct arcnet_local *lp = dev->priv; | ||
595 | struct archdr *pkt; | ||
596 | struct arc_rfc1201 *soft; | ||
597 | struct ArcProto *proto; | ||
598 | int txbuf; | ||
599 | unsigned long flags; | ||
600 | int freeskb = 0; | ||
601 | |||
602 | BUGMSG(D_DURING, | ||
603 | "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", | ||
604 | ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol); | ||
605 | |||
606 | pkt = (struct archdr *) skb->data; | ||
607 | soft = &pkt->soft.rfc1201; | ||
608 | proto = arc_proto_map[soft->proto]; | ||
609 | |||
610 | BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", | ||
611 | skb->len, pkt->hard.dest); | ||
612 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); | ||
613 | |||
614 | /* fits in one packet? */ | ||
615 | if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { | ||
616 | BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n"); | ||
617 | dev_kfree_skb(skb); | ||
618 | return 0; /* don't try again */ | ||
619 | } | ||
620 | |||
621 | /* We're busy transmitting a packet... */ | ||
622 | netif_stop_queue(dev); | ||
623 | |||
624 | spin_lock_irqsave(&lp->lock, flags); | ||
625 | AINTMASK(0); | ||
626 | |||
627 | txbuf = get_arcbuf(dev); | ||
628 | if (txbuf != -1) { | ||
629 | if (proto->prepare_tx(dev, pkt, skb->len, txbuf) && | ||
630 | !proto->ack_tx) { | ||
631 | /* done right away and we don't want to acknowledge | ||
632 | the package later - forget about it now */ | ||
633 | lp->stats.tx_bytes += skb->len; | ||
634 | freeskb = 1; | ||
635 | } else { | ||
636 | /* do it the 'split' way */ | ||
637 | lp->outgoing.proto = proto; | ||
638 | lp->outgoing.skb = skb; | ||
639 | lp->outgoing.pkt = pkt; | ||
640 | |||
641 | if (proto->continue_tx && | ||
642 | proto->continue_tx(dev, txbuf)) { | ||
643 | BUGMSG(D_NORMAL, | ||
644 | "bug! continue_tx finished the first time! " | ||
645 | "(proto='%c')\n", proto->suffix); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | lp->next_tx = txbuf; | ||
650 | } else { | ||
651 | freeskb = 1; | ||
652 | } | ||
653 | |||
654 | BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); | ||
655 | /* make sure we didn't ignore a TX IRQ while we were in here */ | ||
656 | AINTMASK(0); | ||
657 | |||
658 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
659 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
660 | AINTMASK(lp->intmask); | ||
661 | BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); | ||
662 | |||
663 | spin_unlock_irqrestore(&lp->lock, flags); | ||
664 | if (freeskb) { | ||
665 | dev_kfree_skb(skb); | ||
666 | } | ||
667 | return 0; /* no need to try again */ | ||
668 | } | ||
669 | |||
670 | |||
671 | /* | ||
672 | * Actually start transmitting a packet that was loaded into a buffer | ||
673 | * by prepare_tx. This should _only_ be called by the interrupt handler. | ||
674 | */ | ||
675 | static int go_tx(struct net_device *dev) | ||
676 | { | ||
677 | struct arcnet_local *lp = dev->priv; | ||
678 | |||
679 | BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", | ||
680 | ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); | ||
681 | |||
682 | if (lp->cur_tx != -1 || lp->next_tx == -1) | ||
683 | return 0; | ||
684 | |||
685 | BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); | ||
686 | |||
687 | lp->cur_tx = lp->next_tx; | ||
688 | lp->next_tx = -1; | ||
689 | |||
690 | /* start sending */ | ||
691 | ACOMMAND(TXcmd | (lp->cur_tx << 3)); | ||
692 | |||
693 | dev->trans_start = jiffies; | ||
694 | lp->stats.tx_packets++; | ||
695 | lp->lasttrans_dest = lp->lastload_dest; | ||
696 | lp->lastload_dest = 0; | ||
697 | lp->excnak_pending = 0; | ||
698 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
699 | |||
700 | return 1; | ||
701 | } | ||
702 | |||
703 | |||
704 | /* Called by the kernel when transmit times out */ | ||
705 | static void arcnet_timeout(struct net_device *dev) | ||
706 | { | ||
707 | unsigned long flags; | ||
708 | struct arcnet_local *lp = dev->priv; | ||
709 | int status = ASTATUS(); | ||
710 | char *msg; | ||
711 | |||
712 | spin_lock_irqsave(&lp->lock, flags); | ||
713 | if (status & TXFREEflag) { /* transmit _DID_ finish */ | ||
714 | msg = " - missed IRQ?"; | ||
715 | } else { | ||
716 | msg = ""; | ||
717 | lp->stats.tx_aborted_errors++; | ||
718 | lp->timed_out = 1; | ||
719 | ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); | ||
720 | } | ||
721 | lp->stats.tx_errors++; | ||
722 | |||
723 | /* make sure we didn't miss a TX or a EXC NAK IRQ */ | ||
724 | AINTMASK(0); | ||
725 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
726 | AINTMASK(lp->intmask); | ||
727 | |||
728 | spin_unlock_irqrestore(&lp->lock, flags); | ||
729 | |||
730 | if (jiffies - lp->last_timeout > 10*HZ) { | ||
731 | BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", | ||
732 | msg, status, lp->intmask, lp->lasttrans_dest); | ||
733 | lp->last_timeout = jiffies; | ||
734 | } | ||
735 | |||
736 | if (lp->cur_tx == -1) | ||
737 | netif_wake_queue(dev); | ||
738 | } | ||
739 | |||
740 | |||
741 | /* | ||
742 | * The typical workload of the driver: Handle the network interface | ||
743 | * interrupts. Establish which device needs attention, and call the correct | ||
744 | * chipset interrupt handler. | ||
745 | */ | ||
746 | irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
747 | { | ||
748 | struct net_device *dev = dev_id; | ||
749 | struct arcnet_local *lp; | ||
750 | int recbuf, status, diagstatus, didsomething, boguscount; | ||
751 | int retval = IRQ_NONE; | ||
752 | |||
753 | BUGMSG(D_DURING, "\n"); | ||
754 | |||
755 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); | ||
756 | |||
757 | lp = dev->priv; | ||
758 | if (!lp) | ||
759 | BUG(); | ||
760 | |||
761 | spin_lock(&lp->lock); | ||
762 | |||
763 | /* | ||
764 | * RESET flag was enabled - if device is not running, we must clear it right | ||
765 | * away (but nothing else). | ||
766 | */ | ||
767 | if (!netif_running(dev)) { | ||
768 | if (ASTATUS() & RESETflag) | ||
769 | ACOMMAND(CFLAGScmd | RESETclear); | ||
770 | AINTMASK(0); | ||
771 | spin_unlock(&lp->lock); | ||
772 | return IRQ_HANDLED; | ||
773 | } | ||
774 | |||
775 | BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", | ||
776 | ASTATUS(), lp->intmask); | ||
777 | |||
778 | boguscount = 5; | ||
779 | do { | ||
780 | status = ASTATUS(); | ||
781 | diagstatus = (status >> 8) & 0xFF; | ||
782 | |||
783 | BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", | ||
784 | __FILE__,__LINE__,__FUNCTION__,status); | ||
785 | didsomething = 0; | ||
786 | |||
787 | /* | ||
788 | * RESET flag was enabled - card is resetting and if RX is | ||
789 | * disabled, it's NOT because we just got a packet. | ||
790 | * | ||
791 | * The card is in an undefined state. Clear it out and start over. | ||
792 | */ | ||
793 | if (status & RESETflag) { | ||
794 | BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); | ||
795 | arcnet_close(dev); | ||
796 | arcnet_open(dev); | ||
797 | |||
798 | /* get out of the interrupt handler! */ | ||
799 | break; | ||
800 | } | ||
801 | /* | ||
802 | * RX is inhibited - we must have received something. Prepare to | ||
803 | * receive into the next buffer. | ||
804 | * | ||
805 | * We don't actually copy the received packet from the card until | ||
806 | * after the transmit handler runs (and possibly launches the next | ||
807 | * tx); this should improve latency slightly if we get both types | ||
808 | * of interrupts at once. | ||
809 | */ | ||
810 | recbuf = -1; | ||
811 | if (status & lp->intmask & NORXflag) { | ||
812 | recbuf = lp->cur_rx; | ||
813 | BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n", | ||
814 | recbuf, status); | ||
815 | |||
816 | lp->cur_rx = get_arcbuf(dev); | ||
817 | if (lp->cur_rx != -1) { | ||
818 | BUGMSG(D_DURING, "enabling receive to buffer #%d\n", | ||
819 | lp->cur_rx); | ||
820 | ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts); | ||
821 | } | ||
822 | didsomething++; | ||
823 | } | ||
824 | |||
825 | if((diagstatus & EXCNAKflag)) { | ||
826 | BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", | ||
827 | diagstatus); | ||
828 | |||
829 | ACOMMAND(NOTXcmd); /* disable transmit */ | ||
830 | lp->excnak_pending = 1; | ||
831 | |||
832 | ACOMMAND(EXCNAKclear); | ||
833 | lp->intmask &= ~(EXCNAKflag); | ||
834 | didsomething++; | ||
835 | } | ||
836 | |||
837 | |||
838 | /* a transmit finished, and we're interested in it. */ | ||
839 | if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { | ||
840 | lp->intmask &= ~(TXFREEflag|EXCNAKflag); | ||
841 | |||
842 | BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); | ||
843 | |||
844 | if (lp->cur_tx != -1 && !lp->timed_out) { | ||
845 | if(!(status & TXACKflag)) { | ||
846 | if (lp->lasttrans_dest != 0) { | ||
847 | BUGMSG(D_EXTRA, | ||
848 | "transmit was not acknowledged! " | ||
849 | "(status=%Xh, dest=%02Xh)\n", | ||
850 | status, lp->lasttrans_dest); | ||
851 | lp->stats.tx_errors++; | ||
852 | lp->stats.tx_carrier_errors++; | ||
853 | } else { | ||
854 | BUGMSG(D_DURING, | ||
855 | "broadcast was not acknowledged; that's normal " | ||
856 | "(status=%Xh, dest=%02Xh)\n", | ||
857 | status, lp->lasttrans_dest); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | if (lp->outgoing.proto && | ||
862 | lp->outgoing.proto->ack_tx) { | ||
863 | int ackstatus; | ||
864 | if(status & TXACKflag) | ||
865 | ackstatus=2; | ||
866 | else if(lp->excnak_pending) | ||
867 | ackstatus=1; | ||
868 | else | ||
869 | ackstatus=0; | ||
870 | |||
871 | lp->outgoing.proto | ||
872 | ->ack_tx(dev, ackstatus); | ||
873 | } | ||
874 | } | ||
875 | if (lp->cur_tx != -1) | ||
876 | release_arcbuf(dev, lp->cur_tx); | ||
877 | |||
878 | lp->cur_tx = -1; | ||
879 | lp->timed_out = 0; | ||
880 | didsomething++; | ||
881 | |||
882 | /* send another packet if there is one */ | ||
883 | go_tx(dev); | ||
884 | |||
885 | /* continue a split packet, if any */ | ||
886 | if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { | ||
887 | int txbuf = get_arcbuf(dev); | ||
888 | if (txbuf != -1) { | ||
889 | if (lp->outgoing.proto->continue_tx(dev, txbuf)) { | ||
890 | /* that was the last segment */ | ||
891 | lp->stats.tx_bytes += lp->outgoing.skb->len; | ||
892 | if(!lp->outgoing.proto->ack_tx) | ||
893 | { | ||
894 | dev_kfree_skb_irq(lp->outgoing.skb); | ||
895 | lp->outgoing.proto = NULL; | ||
896 | } | ||
897 | } | ||
898 | lp->next_tx = txbuf; | ||
899 | } | ||
900 | } | ||
901 | /* inform upper layers of idleness, if necessary */ | ||
902 | if (lp->cur_tx == -1) | ||
903 | netif_wake_queue(dev); | ||
904 | } | ||
905 | /* now process the received packet, if any */ | ||
906 | if (recbuf != -1) { | ||
907 | BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0); | ||
908 | |||
909 | arcnet_rx(dev, recbuf); | ||
910 | release_arcbuf(dev, recbuf); | ||
911 | |||
912 | didsomething++; | ||
913 | } | ||
914 | if (status & lp->intmask & RECONflag) { | ||
915 | ACOMMAND(CFLAGScmd | CONFIGclear); | ||
916 | lp->stats.tx_carrier_errors++; | ||
917 | |||
918 | BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", | ||
919 | status); | ||
920 | |||
921 | /* is the RECON info empty or old? */ | ||
922 | if (!lp->first_recon || !lp->last_recon || | ||
923 | jiffies - lp->last_recon > HZ * 10) { | ||
924 | if (lp->network_down) | ||
925 | BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n"); | ||
926 | lp->first_recon = lp->last_recon = jiffies; | ||
927 | lp->num_recons = lp->network_down = 0; | ||
928 | |||
929 | BUGMSG(D_DURING, "recon: clearing counters.\n"); | ||
930 | } else { /* add to current RECON counter */ | ||
931 | lp->last_recon = jiffies; | ||
932 | lp->num_recons++; | ||
933 | |||
934 | BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", | ||
935 | lp->num_recons, | ||
936 | (lp->last_recon - lp->first_recon) / HZ, | ||
937 | lp->network_down); | ||
938 | |||
939 | /* if network is marked up; | ||
940 | * and first_recon and last_recon are 60+ apart; | ||
941 | * and the average no. of recons counted is | ||
942 | * > RECON_THRESHOLD/min; | ||
943 | * then print a warning message. | ||
944 | */ | ||
945 | if (!lp->network_down | ||
946 | && (lp->last_recon - lp->first_recon) <= HZ * 60 | ||
947 | && lp->num_recons >= RECON_THRESHOLD) { | ||
948 | lp->network_down = 1; | ||
949 | BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n"); | ||
950 | } else if (!lp->network_down | ||
951 | && lp->last_recon - lp->first_recon > HZ * 60) { | ||
952 | /* reset counters if we've gone for over a minute. */ | ||
953 | lp->first_recon = lp->last_recon; | ||
954 | lp->num_recons = 1; | ||
955 | } | ||
956 | } | ||
957 | } else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) { | ||
958 | if (lp->network_down) | ||
959 | BUGMSG(D_NORMAL, "cabling restored?\n"); | ||
960 | lp->first_recon = lp->last_recon = 0; | ||
961 | lp->num_recons = lp->network_down = 0; | ||
962 | |||
963 | BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); | ||
964 | } | ||
965 | |||
966 | if(didsomething) { | ||
967 | retval |= IRQ_HANDLED; | ||
968 | } | ||
969 | } | ||
970 | while (--boguscount && didsomething); | ||
971 | |||
972 | BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n", | ||
973 | ASTATUS(), boguscount); | ||
974 | BUGMSG(D_DURING, "\n"); | ||
975 | |||
976 | |||
977 | AINTMASK(0); | ||
978 | udelay(1); | ||
979 | AINTMASK(lp->intmask); | ||
980 | |||
981 | spin_unlock(&lp->lock); | ||
982 | return retval; | ||
983 | } | ||
984 | |||
985 | |||
986 | /* | ||
987 | * This is a generic packet receiver that calls arcnet??_rx depending on the | ||
988 | * protocol ID found. | ||
989 | */ | ||
990 | void arcnet_rx(struct net_device *dev, int bufnum) | ||
991 | { | ||
992 | struct arcnet_local *lp = dev->priv; | ||
993 | struct archdr pkt; | ||
994 | struct arc_rfc1201 *soft; | ||
995 | int length, ofs; | ||
996 | |||
997 | soft = &pkt.soft.rfc1201; | ||
998 | |||
999 | lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE)); | ||
1000 | if (pkt.hard.offset[0]) { | ||
1001 | ofs = pkt.hard.offset[0]; | ||
1002 | length = 256 - ofs; | ||
1003 | } else { | ||
1004 | ofs = pkt.hard.offset[1]; | ||
1005 | length = 512 - ofs; | ||
1006 | } | ||
1007 | |||
1008 | /* get the full header, if possible */ | ||
1009 | if (sizeof(pkt.soft) <= length) | ||
1010 | lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); | ||
1011 | else { | ||
1012 | memset(&pkt.soft, 0, sizeof(pkt.soft)); | ||
1013 | lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); | ||
1014 | } | ||
1015 | |||
1016 | BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh " | ||
1017 | "(%d+4 bytes)\n", | ||
1018 | bufnum, pkt.hard.source, pkt.hard.dest, length); | ||
1019 | |||
1020 | lp->stats.rx_packets++; | ||
1021 | lp->stats.rx_bytes += length + ARC_HDR_SIZE; | ||
1022 | |||
1023 | /* call the right receiver for the protocol */ | ||
1024 | if (arc_proto_map[soft->proto]->is_ip) { | ||
1025 | BUGLVL(D_PROTO) { | ||
1026 | struct ArcProto | ||
1027 | *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], | ||
1028 | *newp = arc_proto_map[soft->proto]; | ||
1029 | |||
1030 | if (oldp != newp) { | ||
1031 | BUGMSG(D_PROTO, | ||
1032 | "got protocol %02Xh; encap for host %02Xh is now '%c'" | ||
1033 | " (was '%c')\n", soft->proto, pkt.hard.source, | ||
1034 | newp->suffix, oldp->suffix); | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | /* broadcasts will always be done with the last-used encap. */ | ||
1039 | lp->default_proto[0] = soft->proto; | ||
1040 | |||
1041 | /* in striking contrast, the following isn't a hack. */ | ||
1042 | lp->default_proto[pkt.hard.source] = soft->proto; | ||
1043 | } | ||
1044 | /* call the protocol-specific receiver. */ | ||
1045 | arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | |||
1050 | /* | ||
1051 | * Get the current statistics. This may be called with the card open or | ||
1052 | * closed. | ||
1053 | */ | ||
1054 | static struct net_device_stats *arcnet_get_stats(struct net_device *dev) | ||
1055 | { | ||
1056 | struct arcnet_local *lp = dev->priv; | ||
1057 | return &lp->stats; | ||
1058 | } | ||
1059 | |||
1060 | |||
1061 | static void null_rx(struct net_device *dev, int bufnum, | ||
1062 | struct archdr *pkthdr, int length) | ||
1063 | { | ||
1064 | BUGMSG(D_PROTO, | ||
1065 | "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", | ||
1066 | pkthdr->soft.rfc1201.proto, pkthdr->hard.source); | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | static int null_build_header(struct sk_buff *skb, struct net_device *dev, | ||
1071 | unsigned short type, uint8_t daddr) | ||
1072 | { | ||
1073 | struct arcnet_local *lp = dev->priv; | ||
1074 | |||
1075 | BUGMSG(D_PROTO, | ||
1076 | "tx: can't build header for encap %02Xh; load a protocol driver.\n", | ||
1077 | lp->default_proto[daddr]); | ||
1078 | |||
1079 | /* always fails */ | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | /* the "do nothing" prepare_tx function warns that there's nothing to do. */ | ||
1085 | static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, | ||
1086 | int length, int bufnum) | ||
1087 | { | ||
1088 | struct arcnet_local *lp = dev->priv; | ||
1089 | struct arc_hardware newpkt; | ||
1090 | |||
1091 | BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n"); | ||
1092 | |||
1093 | /* send a packet to myself -- will never get received, of course */ | ||
1094 | newpkt.source = newpkt.dest = dev->dev_addr[0]; | ||
1095 | |||
1096 | /* only one byte of actual data (and it's random) */ | ||
1097 | newpkt.offset[0] = 0xFF; | ||
1098 | |||
1099 | lp->hw.copy_to_card(dev, bufnum, 0, &newpkt, ARC_HDR_SIZE); | ||
1100 | |||
1101 | return 1; /* done */ | ||
1102 | } | ||
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c new file mode 100644 index 000000000000..16e155b04129 --- /dev/null +++ b/drivers/net/arcnet/capmode.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - "cap mode" packet encapsulation. | ||
3 | * It adds sequence numbers to packets for communicating between a user space | ||
4 | * application and the driver. After a transmit it sends a packet with protocol | ||
5 | * byte 0 back up to the userspace containing the sequence number of the packet | ||
6 | * plus the transmit-status on the ArcNet. | ||
7 | * | ||
8 | * Written 2002-4 by Esben Nielsen, Vestas Wind Systems A/S | ||
9 | * Derived from arc-rawmode.c by Avery Pennarun. | ||
10 | * arc-rawmode was in turned based on skeleton.c, see below. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright of skeleton.c was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * For more details, see drivers/net/arcnet.c | ||
25 | * | ||
26 | * ********************** | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/if_arp.h> | ||
32 | #include <net/arp.h> | ||
33 | #include <linux/netdevice.h> | ||
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/arcdevice.h> | ||
36 | |||
37 | #define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n" | ||
38 | |||
39 | |||
40 | static void rx(struct net_device *dev, int bufnum, | ||
41 | struct archdr *pkthdr, int length); | ||
42 | static int build_header(struct sk_buff *skb, | ||
43 | struct net_device *dev, | ||
44 | unsigned short type, | ||
45 | uint8_t daddr); | ||
46 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
47 | int bufnum); | ||
48 | static int ack_tx(struct net_device *dev, int acked); | ||
49 | |||
50 | |||
51 | struct ArcProto capmode_proto = | ||
52 | { | ||
53 | 'r', | ||
54 | XMTU, | ||
55 | 0, | ||
56 | rx, | ||
57 | build_header, | ||
58 | prepare_tx, | ||
59 | NULL, | ||
60 | ack_tx | ||
61 | }; | ||
62 | |||
63 | |||
64 | void arcnet_cap_init(void) | ||
65 | { | ||
66 | int count; | ||
67 | |||
68 | for (count = 1; count <= 8; count++) | ||
69 | if (arc_proto_map[count] == arc_proto_default) | ||
70 | arc_proto_map[count] = &capmode_proto; | ||
71 | |||
72 | /* for cap mode, we only set the bcast proto if there's no better one */ | ||
73 | if (arc_bcast_proto == arc_proto_default) | ||
74 | arc_bcast_proto = &capmode_proto; | ||
75 | |||
76 | arc_proto_default = &capmode_proto; | ||
77 | arc_raw_proto = &capmode_proto; | ||
78 | } | ||
79 | |||
80 | |||
81 | #ifdef MODULE | ||
82 | |||
83 | int __init init_module(void) | ||
84 | { | ||
85 | printk(VERSION); | ||
86 | arcnet_cap_init(); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | void cleanup_module(void) | ||
91 | { | ||
92 | arcnet_unregister_proto(&capmode_proto); | ||
93 | } | ||
94 | |||
95 | MODULE_LICENSE("GPL"); | ||
96 | #endif /* MODULE */ | ||
97 | |||
98 | |||
99 | |||
100 | /* packet receiver */ | ||
101 | static void rx(struct net_device *dev, int bufnum, | ||
102 | struct archdr *pkthdr, int length) | ||
103 | { | ||
104 | struct arcnet_local *lp = (struct arcnet_local *) dev->priv; | ||
105 | struct sk_buff *skb; | ||
106 | struct archdr *pkt = pkthdr; | ||
107 | char *pktbuf, *pkthdrbuf; | ||
108 | int ofs; | ||
109 | |||
110 | BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length); | ||
111 | |||
112 | if (length >= MinTU) | ||
113 | ofs = 512 - length; | ||
114 | else | ||
115 | ofs = 256 - length; | ||
116 | |||
117 | skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); | ||
118 | if (skb == NULL) { | ||
119 | BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); | ||
120 | lp->stats.rx_dropped++; | ||
121 | return; | ||
122 | } | ||
123 | skb_put(skb, length + ARC_HDR_SIZE + sizeof(int)); | ||
124 | skb->dev = dev; | ||
125 | |||
126 | pkt = (struct archdr *) skb->data; | ||
127 | |||
128 | skb->mac.raw = skb->data; | ||
129 | skb_pull(skb, ARC_HDR_SIZE); | ||
130 | |||
131 | /* up to sizeof(pkt->soft) has already been copied from the card */ | ||
132 | /* squeeze in an int for the cap encapsulation */ | ||
133 | |||
134 | /* use these variables to be sure we count in bytes, not in | ||
135 | sizeof(struct archdr) */ | ||
136 | pktbuf=(char*)pkt; | ||
137 | pkthdrbuf=(char*)pkthdr; | ||
138 | memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)); | ||
139 | memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int), | ||
140 | pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto), | ||
141 | sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto)); | ||
142 | |||
143 | if (length > sizeof(pkt->soft)) | ||
144 | lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), | ||
145 | pkt->soft.raw + sizeof(pkt->soft) | ||
146 | + sizeof(int), | ||
147 | length - sizeof(pkt->soft)); | ||
148 | |||
149 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); | ||
150 | |||
151 | skb->protocol = __constant_htons(ETH_P_ARCNET); | ||
152 | ; | ||
153 | netif_rx(skb); | ||
154 | dev->last_rx = jiffies; | ||
155 | } | ||
156 | |||
157 | |||
158 | /* | ||
159 | * Create the ARCnet hard/soft headers for cap mode. | ||
160 | * There aren't any soft headers in cap mode - not even the protocol id. | ||
161 | */ | ||
162 | static int build_header(struct sk_buff *skb, | ||
163 | struct net_device *dev, | ||
164 | unsigned short type, | ||
165 | uint8_t daddr) | ||
166 | { | ||
167 | int hdr_size = ARC_HDR_SIZE; | ||
168 | struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); | ||
169 | |||
170 | BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", | ||
171 | *((int*)&pkt->soft.cap.cookie[0])); | ||
172 | /* | ||
173 | * Set the source hardware address. | ||
174 | * | ||
175 | * This is pretty pointless for most purposes, but it can help in | ||
176 | * debugging. ARCnet does not allow us to change the source address in | ||
177 | * the actual packet sent) | ||
178 | */ | ||
179 | pkt->hard.source = *dev->dev_addr; | ||
180 | |||
181 | /* see linux/net/ethernet/eth.c to see where I got the following */ | ||
182 | |||
183 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { | ||
184 | /* | ||
185 | * FIXME: fill in the last byte of the dest ipaddr here to better | ||
186 | * comply with RFC1051 in "noarp" mode. | ||
187 | */ | ||
188 | pkt->hard.dest = 0; | ||
189 | return hdr_size; | ||
190 | } | ||
191 | /* otherwise, just fill it in and go! */ | ||
192 | pkt->hard.dest = daddr; | ||
193 | |||
194 | return hdr_size; /* success */ | ||
195 | } | ||
196 | |||
197 | |||
198 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
199 | int bufnum) | ||
200 | { | ||
201 | struct arcnet_local *lp = (struct arcnet_local *) dev->priv; | ||
202 | struct arc_hardware *hard = &pkt->hard; | ||
203 | int ofs; | ||
204 | |||
205 | |||
206 | /* hard header is not included in packet length */ | ||
207 | length -= ARC_HDR_SIZE; | ||
208 | /* And neither is the cookie field */ | ||
209 | length -= sizeof(int); | ||
210 | |||
211 | BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", | ||
212 | lp->next_tx, lp->cur_tx, bufnum); | ||
213 | |||
214 | BUGMSG(D_PROTO, "Sending for cap packet %x.\n", | ||
215 | *((int*)&pkt->soft.cap.cookie[0])); | ||
216 | |||
217 | if (length > XMTU) { | ||
218 | /* should never happen! other people already check for this. */ | ||
219 | BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", | ||
220 | length, XMTU); | ||
221 | length = XMTU; | ||
222 | } | ||
223 | if (length > MinTU) { | ||
224 | hard->offset[0] = 0; | ||
225 | hard->offset[1] = ofs = 512 - length; | ||
226 | } else if (length > MTU) { | ||
227 | hard->offset[0] = 0; | ||
228 | hard->offset[1] = ofs = 512 - length - 3; | ||
229 | } else | ||
230 | hard->offset[0] = ofs = 256 - length; | ||
231 | |||
232 | BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", | ||
233 | length,ofs); | ||
234 | |||
235 | // Copy the arcnet-header + the protocol byte down: | ||
236 | lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); | ||
237 | lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft.cap.proto, | ||
238 | sizeof(pkt->soft.cap.proto)); | ||
239 | |||
240 | // Skip the extra integer we have written into it as a cookie | ||
241 | // but write the rest of the message: | ||
242 | lp->hw.copy_to_card(dev, bufnum, ofs+1, | ||
243 | ((unsigned char*)&pkt->soft.cap.mes),length-1); | ||
244 | |||
245 | lp->lastload_dest = hard->dest; | ||
246 | |||
247 | return 1; /* done */ | ||
248 | } | ||
249 | |||
250 | |||
251 | static int ack_tx(struct net_device *dev, int acked) | ||
252 | { | ||
253 | struct arcnet_local *lp = (struct arcnet_local *) dev->priv; | ||
254 | struct sk_buff *ackskb; | ||
255 | struct archdr *ackpkt; | ||
256 | int length=sizeof(struct arc_cap); | ||
257 | |||
258 | BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", | ||
259 | lp->outgoing.skb->protocol, acked); | ||
260 | |||
261 | BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); | ||
262 | |||
263 | /* Now alloc a skb to send back up through the layers: */ | ||
264 | ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); | ||
265 | if (ackskb == NULL) { | ||
266 | BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); | ||
267 | goto free_outskb; | ||
268 | } | ||
269 | |||
270 | skb_put(ackskb, length + ARC_HDR_SIZE ); | ||
271 | ackskb->dev = dev; | ||
272 | |||
273 | ackpkt = (struct archdr *) ackskb->data; | ||
274 | |||
275 | ackskb->mac.raw = ackskb->data; | ||
276 | /* skb_pull(ackskb, ARC_HDR_SIZE); */ | ||
277 | |||
278 | |||
279 | memcpy(ackpkt, lp->outgoing.skb->data, ARC_HDR_SIZE+sizeof(struct arc_cap)); | ||
280 | ackpkt->soft.cap.proto=0; /* using protocol 0 for acknowledge */ | ||
281 | ackpkt->soft.cap.mes.ack=acked; | ||
282 | |||
283 | BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", | ||
284 | *((int*)&ackpkt->soft.cap.cookie[0])); | ||
285 | |||
286 | ackskb->protocol = __constant_htons(ETH_P_ARCNET); | ||
287 | |||
288 | BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); | ||
289 | netif_rx(ackskb); | ||
290 | |||
291 | free_outskb: | ||
292 | dev_kfree_skb_irq(lp->outgoing.skb); | ||
293 | lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ | ||
294 | |||
295 | return 0; | ||
296 | } | ||
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c new file mode 100644 index 000000000000..9289e6103de5 --- /dev/null +++ b/drivers/net/arcnet/com20020-isa.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM20020 chipset support | ||
3 | * | ||
4 | * Written 1997 by David Woodhouse. | ||
5 | * Written 1994-1999 by Avery Pennarun. | ||
6 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
7 | * Derived from skeleton.c by Donald Becker. | ||
8 | * | ||
9 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
10 | * for sponsoring the further development of this driver. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright of skeleton.c was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * For more details, see drivers/net/arcnet.c | ||
25 | * | ||
26 | * ********************** | ||
27 | */ | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/bootmem.h> | ||
39 | #include <linux/arcdevice.h> | ||
40 | #include <linux/com20020.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | |||
44 | #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" | ||
45 | |||
46 | |||
47 | /* | ||
48 | * We cannot (yet) probe for an IO mapped card, although we can check that | ||
49 | * it's where we were told it was, and even do autoirq. | ||
50 | */ | ||
51 | static int __init com20020isa_probe(struct net_device *dev) | ||
52 | { | ||
53 | int ioaddr; | ||
54 | unsigned long airqmask; | ||
55 | struct arcnet_local *lp = dev->priv; | ||
56 | int err; | ||
57 | |||
58 | BUGLVL(D_NORMAL) printk(VERSION); | ||
59 | |||
60 | ioaddr = dev->base_addr; | ||
61 | if (!ioaddr) { | ||
62 | BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you " | ||
63 | "must specify the base address!\n"); | ||
64 | return -ENODEV; | ||
65 | } | ||
66 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { | ||
67 | BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n", | ||
68 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); | ||
69 | return -ENXIO; | ||
70 | } | ||
71 | if (ASTATUS() == 0xFF) { | ||
72 | BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr); | ||
73 | err = -ENODEV; | ||
74 | goto out; | ||
75 | } | ||
76 | if (com20020_check(dev)) { | ||
77 | err = -ENODEV; | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | if (!dev->irq) { | ||
82 | /* if we do this, we're sure to get an IRQ since the | ||
83 | * card has just reset and the NORXflag is on until | ||
84 | * we tell it to start receiving. | ||
85 | */ | ||
86 | BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK)); | ||
87 | outb(0, _INTMASK); | ||
88 | airqmask = probe_irq_on(); | ||
89 | outb(NORXflag, _INTMASK); | ||
90 | udelay(1); | ||
91 | outb(0, _INTMASK); | ||
92 | dev->irq = probe_irq_off(airqmask); | ||
93 | |||
94 | if (dev->irq <= 0) { | ||
95 | BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n"); | ||
96 | airqmask = probe_irq_on(); | ||
97 | outb(NORXflag, _INTMASK); | ||
98 | udelay(5); | ||
99 | outb(0, _INTMASK); | ||
100 | dev->irq = probe_irq_off(airqmask); | ||
101 | if (dev->irq <= 0) { | ||
102 | BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n"); | ||
103 | err = -ENODEV; | ||
104 | goto out; | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | lp->card_name = "ISA COM20020"; | ||
110 | if ((err = com20020_found(dev, 0)) != 0) | ||
111 | goto out; | ||
112 | |||
113 | return 0; | ||
114 | |||
115 | out: | ||
116 | release_region(ioaddr, ARCNET_TOTAL_SIZE); | ||
117 | return err; | ||
118 | } | ||
119 | |||
120 | static int node = 0; | ||
121 | static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ | ||
122 | static int irq = 0; /* or use the insmod io= irq= shmem= options */ | ||
123 | static char device[9]; /* use eg. device="arc1" to change name */ | ||
124 | static int timeout = 3; | ||
125 | static int backplane = 0; | ||
126 | static int clockp = 0; | ||
127 | static int clockm = 0; | ||
128 | |||
129 | module_param(node, int, 0); | ||
130 | module_param(io, int, 0); | ||
131 | module_param(irq, int, 0); | ||
132 | module_param_string(device, device, sizeof(device), 0); | ||
133 | module_param(timeout, int, 0); | ||
134 | module_param(backplane, int, 0); | ||
135 | module_param(clockp, int, 0); | ||
136 | module_param(clockm, int, 0); | ||
137 | |||
138 | MODULE_LICENSE("GPL"); | ||
139 | |||
140 | static struct net_device *my_dev; | ||
141 | |||
142 | static int __init com20020_init(void) | ||
143 | { | ||
144 | struct net_device *dev; | ||
145 | struct arcnet_local *lp; | ||
146 | |||
147 | dev = alloc_arcdev(device); | ||
148 | if (!dev) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | if (node && node != 0xff) | ||
152 | dev->dev_addr[0] = node; | ||
153 | |||
154 | lp = dev->priv; | ||
155 | lp->backplane = backplane; | ||
156 | lp->clockp = clockp & 7; | ||
157 | lp->clockm = clockm & 3; | ||
158 | lp->timeout = timeout & 3; | ||
159 | lp->hw.owner = THIS_MODULE; | ||
160 | |||
161 | dev->base_addr = io; | ||
162 | dev->irq = irq; | ||
163 | |||
164 | if (dev->irq == 2) | ||
165 | dev->irq = 9; | ||
166 | |||
167 | if (com20020isa_probe(dev)) { | ||
168 | free_netdev(dev); | ||
169 | return -EIO; | ||
170 | } | ||
171 | |||
172 | my_dev = dev; | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static void __exit com20020_exit(void) | ||
177 | { | ||
178 | unregister_netdev(my_dev); | ||
179 | free_irq(my_dev->irq, my_dev); | ||
180 | release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE); | ||
181 | free_netdev(my_dev); | ||
182 | } | ||
183 | |||
184 | #ifndef MODULE | ||
185 | static int __init com20020isa_setup(char *s) | ||
186 | { | ||
187 | int ints[8]; | ||
188 | |||
189 | s = get_options(s, 8, ints); | ||
190 | if (!ints[0]) | ||
191 | return 1; | ||
192 | |||
193 | switch (ints[0]) { | ||
194 | default: /* ERROR */ | ||
195 | printk("com90xx: Too many arguments.\n"); | ||
196 | case 6: /* Timeout */ | ||
197 | timeout = ints[6]; | ||
198 | case 5: /* CKP value */ | ||
199 | clockp = ints[5]; | ||
200 | case 4: /* Backplane flag */ | ||
201 | backplane = ints[4]; | ||
202 | case 3: /* Node ID */ | ||
203 | node = ints[3]; | ||
204 | case 2: /* IRQ */ | ||
205 | irq = ints[2]; | ||
206 | case 1: /* IO address */ | ||
207 | io = ints[1]; | ||
208 | } | ||
209 | if (*s) | ||
210 | snprintf(device, sizeof(device), "%s", s); | ||
211 | return 1; | ||
212 | } | ||
213 | |||
214 | __setup("com20020=", com20020isa_setup); | ||
215 | |||
216 | #endif /* MODULE */ | ||
217 | |||
218 | module_init(com20020_init) | ||
219 | module_exit(com20020_exit) | ||
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c new file mode 100644 index 000000000000..96636ca8754e --- /dev/null +++ b/drivers/net/arcnet/com20020-pci.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM20020 PCI support | ||
3 | * Contemporary Controls PCI20 and SOHARD SH-ARC PCI | ||
4 | * | ||
5 | * Written 1994-1999 by Avery Pennarun, | ||
6 | * based on an ISA version by David Woodhouse. | ||
7 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
8 | * Derived from skeleton.c by Donald Becker. | ||
9 | * | ||
10 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
11 | * for sponsoring the further development of this driver. | ||
12 | * | ||
13 | * ********************** | ||
14 | * | ||
15 | * The original copyright of skeleton.c was as follows: | ||
16 | * | ||
17 | * skeleton.c Written 1993 by Donald Becker. | ||
18 | * Copyright 1993 United States Government as represented by the | ||
19 | * Director, National Security Agency. This software may only be used | ||
20 | * and distributed according to the terms of the GNU General Public License as | ||
21 | * modified by SRC, incorporated herein by reference. | ||
22 | * | ||
23 | * ********************** | ||
24 | * | ||
25 | * For more details, see drivers/net/arcnet.c | ||
26 | * | ||
27 | * ********************** | ||
28 | */ | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/ioport.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/pci.h> | ||
39 | #include <linux/arcdevice.h> | ||
40 | #include <linux/com20020.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | |||
44 | |||
45 | #define VERSION "arcnet: COM20020 PCI support\n" | ||
46 | |||
47 | /* Module parameters */ | ||
48 | |||
49 | static int node; | ||
50 | static char device[9]; /* use eg. device="arc1" to change name */ | ||
51 | static int timeout = 3; | ||
52 | static int backplane; | ||
53 | static int clockp; | ||
54 | static int clockm; | ||
55 | |||
56 | module_param(node, int, 0); | ||
57 | module_param_string(device, device, sizeof(device), 0); | ||
58 | module_param(timeout, int, 0); | ||
59 | module_param(backplane, int, 0); | ||
60 | module_param(clockp, int, 0); | ||
61 | module_param(clockm, int, 0); | ||
62 | MODULE_LICENSE("GPL"); | ||
63 | |||
64 | static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
65 | { | ||
66 | struct net_device *dev; | ||
67 | struct arcnet_local *lp; | ||
68 | int ioaddr, err; | ||
69 | |||
70 | if (pci_enable_device(pdev)) | ||
71 | return -EIO; | ||
72 | dev = alloc_arcdev(device); | ||
73 | if (!dev) | ||
74 | return -ENOMEM; | ||
75 | lp = dev->priv; | ||
76 | |||
77 | pci_set_drvdata(pdev, dev); | ||
78 | |||
79 | // SOHARD needs PCI base addr 4 | ||
80 | if (pdev->vendor==0x10B5) { | ||
81 | BUGMSG(D_NORMAL, "SOHARD\n"); | ||
82 | ioaddr = pci_resource_start(pdev, 4); | ||
83 | } | ||
84 | else { | ||
85 | BUGMSG(D_NORMAL, "Contemporary Controls\n"); | ||
86 | ioaddr = pci_resource_start(pdev, 2); | ||
87 | } | ||
88 | |||
89 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) { | ||
90 | BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n", | ||
91 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); | ||
92 | err = -EBUSY; | ||
93 | goto out_dev; | ||
94 | } | ||
95 | |||
96 | // Dummy access after Reset | ||
97 | // ARCNET controller needs this access to detect bustype | ||
98 | outb(0x00,ioaddr+1); | ||
99 | inb(ioaddr+1); | ||
100 | |||
101 | dev->base_addr = ioaddr; | ||
102 | dev->irq = pdev->irq; | ||
103 | dev->dev_addr[0] = node; | ||
104 | lp->card_name = "PCI COM20020"; | ||
105 | lp->card_flags = id->driver_data; | ||
106 | lp->backplane = backplane; | ||
107 | lp->clockp = clockp & 7; | ||
108 | lp->clockm = clockm & 3; | ||
109 | lp->timeout = timeout; | ||
110 | lp->hw.owner = THIS_MODULE; | ||
111 | |||
112 | if (ASTATUS() == 0xFF) { | ||
113 | BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, " | ||
114 | "but seems empty!\n", ioaddr); | ||
115 | err = -EIO; | ||
116 | goto out_port; | ||
117 | } | ||
118 | if (com20020_check(dev)) { | ||
119 | err = -EIO; | ||
120 | goto out_port; | ||
121 | } | ||
122 | |||
123 | if ((err = com20020_found(dev, SA_SHIRQ)) != 0) | ||
124 | goto out_port; | ||
125 | |||
126 | return 0; | ||
127 | |||
128 | out_port: | ||
129 | release_region(ioaddr, ARCNET_TOTAL_SIZE); | ||
130 | out_dev: | ||
131 | free_netdev(dev); | ||
132 | return err; | ||
133 | } | ||
134 | |||
135 | static void __devexit com20020pci_remove(struct pci_dev *pdev) | ||
136 | { | ||
137 | struct net_device *dev = pci_get_drvdata(pdev); | ||
138 | unregister_netdev(dev); | ||
139 | free_irq(dev->irq, dev); | ||
140 | release_region(dev->base_addr, ARCNET_TOTAL_SIZE); | ||
141 | free_netdev(dev); | ||
142 | } | ||
143 | |||
144 | static struct pci_device_id com20020pci_id_table[] = { | ||
145 | { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
146 | { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
147 | { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
148 | { 0x1571, 0xa004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
149 | { 0x1571, 0xa005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
150 | { 0x1571, 0xa006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
151 | { 0x1571, 0xa007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
152 | { 0x1571, 0xa008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
153 | { 0x1571, 0xa009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, | ||
154 | { 0x1571, 0xa00a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, | ||
155 | { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, | ||
156 | { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, | ||
157 | { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, | ||
158 | { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
159 | { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
160 | { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
161 | { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
162 | { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
163 | { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
164 | { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | ||
165 | {0,} | ||
166 | }; | ||
167 | |||
168 | MODULE_DEVICE_TABLE(pci, com20020pci_id_table); | ||
169 | |||
170 | static struct pci_driver com20020pci_driver = { | ||
171 | .name = "com20020", | ||
172 | .id_table = com20020pci_id_table, | ||
173 | .probe = com20020pci_probe, | ||
174 | .remove = __devexit_p(com20020pci_remove), | ||
175 | }; | ||
176 | |||
177 | static int __init com20020pci_init(void) | ||
178 | { | ||
179 | BUGLVL(D_NORMAL) printk(VERSION); | ||
180 | return pci_module_init(&com20020pci_driver); | ||
181 | } | ||
182 | |||
183 | static void __exit com20020pci_cleanup(void) | ||
184 | { | ||
185 | pci_unregister_driver(&com20020pci_driver); | ||
186 | } | ||
187 | |||
188 | module_init(com20020pci_init) | ||
189 | module_exit(com20020pci_cleanup) | ||
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c new file mode 100644 index 000000000000..0dc70c7b7940 --- /dev/null +++ b/drivers/net/arcnet/com20020.c | |||
@@ -0,0 +1,357 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM20020 chipset support | ||
3 | * | ||
4 | * Written 1997 by David Woodhouse. | ||
5 | * Written 1994-1999 by Avery Pennarun. | ||
6 | * Written 1999 by Martin Mares <mj@ucw.cz>. | ||
7 | * Derived from skeleton.c by Donald Becker. | ||
8 | * | ||
9 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
10 | * for sponsoring the further development of this driver. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright of skeleton.c was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * For more details, see drivers/net/arcnet.c | ||
25 | * | ||
26 | * ********************** | ||
27 | */ | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/netdevice.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/arcdevice.h> | ||
38 | #include <linux/com20020.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | |||
42 | #define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n" | ||
43 | |||
44 | static char *clockrates[] = | ||
45 | {"10 Mb/s", "Reserved", "5 Mb/s", | ||
46 | "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", | ||
47 | "156.25 Kb/s", "Reserved", "Reserved", "Reserved"}; | ||
48 | |||
49 | static void com20020_command(struct net_device *dev, int command); | ||
50 | static int com20020_status(struct net_device *dev); | ||
51 | static void com20020_setmask(struct net_device *dev, int mask); | ||
52 | static int com20020_reset(struct net_device *dev, int really_reset); | ||
53 | static void com20020_copy_to_card(struct net_device *dev, int bufnum, | ||
54 | int offset, void *buf, int count); | ||
55 | static void com20020_copy_from_card(struct net_device *dev, int bufnum, | ||
56 | int offset, void *buf, int count); | ||
57 | static void com20020_set_mc_list(struct net_device *dev); | ||
58 | static void com20020_close(struct net_device *); | ||
59 | |||
60 | static void com20020_copy_from_card(struct net_device *dev, int bufnum, | ||
61 | int offset, void *buf, int count) | ||
62 | { | ||
63 | int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; | ||
64 | |||
65 | /* set up the address register */ | ||
66 | outb((ofs >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); | ||
67 | outb(ofs & 0xff, _ADDR_LO); | ||
68 | |||
69 | /* copy the data */ | ||
70 | TIME("insb", count, insb(_MEMDATA, buf, count)); | ||
71 | } | ||
72 | |||
73 | |||
74 | static void com20020_copy_to_card(struct net_device *dev, int bufnum, | ||
75 | int offset, void *buf, int count) | ||
76 | { | ||
77 | int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; | ||
78 | |||
79 | /* set up the address register */ | ||
80 | outb((ofs >> 8) | AUTOINCflag, _ADDR_HI); | ||
81 | outb(ofs & 0xff, _ADDR_LO); | ||
82 | |||
83 | /* copy the data */ | ||
84 | TIME("outsb", count, outsb(_MEMDATA, buf, count)); | ||
85 | } | ||
86 | |||
87 | |||
88 | /* Reset the card and check some basic stuff during the detection stage. */ | ||
89 | int com20020_check(struct net_device *dev) | ||
90 | { | ||
91 | int ioaddr = dev->base_addr, status; | ||
92 | struct arcnet_local *lp = dev->priv; | ||
93 | |||
94 | ARCRESET0; | ||
95 | mdelay(RESETtime); | ||
96 | |||
97 | lp->setup = lp->clockm ? 0 : (lp->clockp << 1); | ||
98 | lp->setup2 = (lp->clockm << 4) | 8; | ||
99 | |||
100 | /* CHECK: should we do this for SOHARD cards ? */ | ||
101 | /* Enable P1Mode for backplane mode */ | ||
102 | lp->setup = lp->setup | P1MODE; | ||
103 | |||
104 | SET_SUBADR(SUB_SETUP1); | ||
105 | outb(lp->setup, _XREG); | ||
106 | |||
107 | if (lp->card_flags & ARC_CAN_10MBIT) | ||
108 | { | ||
109 | SET_SUBADR(SUB_SETUP2); | ||
110 | outb(lp->setup2, _XREG); | ||
111 | |||
112 | /* must now write the magic "restart operation" command */ | ||
113 | mdelay(1); | ||
114 | outb(0x18, _COMMAND); | ||
115 | } | ||
116 | |||
117 | lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); | ||
118 | /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ | ||
119 | SETCONF; | ||
120 | outb(0x42, ioaddr + BUS_ALIGN*7); | ||
121 | |||
122 | status = ASTATUS(); | ||
123 | |||
124 | if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) { | ||
125 | BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status); | ||
126 | return -ENODEV; | ||
127 | } | ||
128 | BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status); | ||
129 | |||
130 | /* Enable TX */ | ||
131 | outb(0x39, _CONFIG); | ||
132 | outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7); | ||
133 | |||
134 | ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); | ||
135 | |||
136 | status = ASTATUS(); | ||
137 | BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n", | ||
138 | status); | ||
139 | |||
140 | /* Read first location of memory */ | ||
141 | outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI); | ||
142 | outb(0, _ADDR_LO); | ||
143 | |||
144 | if ((status = inb(_MEMDATA)) != TESTvalue) { | ||
145 | BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n", | ||
146 | status); | ||
147 | return -ENODEV; | ||
148 | } | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /* Set up the struct net_device associated with this card. Called after | ||
153 | * probing succeeds. | ||
154 | */ | ||
155 | int com20020_found(struct net_device *dev, int shared) | ||
156 | { | ||
157 | struct arcnet_local *lp; | ||
158 | int ioaddr = dev->base_addr; | ||
159 | |||
160 | /* Initialize the rest of the device structure. */ | ||
161 | |||
162 | lp = dev->priv; | ||
163 | |||
164 | lp->hw.owner = THIS_MODULE; | ||
165 | lp->hw.command = com20020_command; | ||
166 | lp->hw.status = com20020_status; | ||
167 | lp->hw.intmask = com20020_setmask; | ||
168 | lp->hw.reset = com20020_reset; | ||
169 | lp->hw.copy_to_card = com20020_copy_to_card; | ||
170 | lp->hw.copy_from_card = com20020_copy_from_card; | ||
171 | lp->hw.close = com20020_close; | ||
172 | |||
173 | dev->set_multicast_list = com20020_set_mc_list; | ||
174 | |||
175 | if (!dev->dev_addr[0]) | ||
176 | dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */ | ||
177 | |||
178 | SET_SUBADR(SUB_SETUP1); | ||
179 | outb(lp->setup, _XREG); | ||
180 | |||
181 | if (lp->card_flags & ARC_CAN_10MBIT) | ||
182 | { | ||
183 | SET_SUBADR(SUB_SETUP2); | ||
184 | outb(lp->setup2, _XREG); | ||
185 | |||
186 | /* must now write the magic "restart operation" command */ | ||
187 | mdelay(1); | ||
188 | outb(0x18, _COMMAND); | ||
189 | } | ||
190 | |||
191 | lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1; | ||
192 | /* Default 0x38 + register: Node ID */ | ||
193 | SETCONF; | ||
194 | outb(dev->dev_addr[0], _XREG); | ||
195 | |||
196 | /* reserve the irq */ | ||
197 | if (request_irq(dev->irq, &arcnet_interrupt, shared, | ||
198 | "arcnet (COM20020)", dev)) { | ||
199 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); | ||
200 | return -ENODEV; | ||
201 | } | ||
202 | |||
203 | dev->base_addr = ioaddr; | ||
204 | |||
205 | BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n", | ||
206 | lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); | ||
207 | |||
208 | if (lp->backplane) | ||
209 | BUGMSG(D_NORMAL, "Using backplane mode.\n"); | ||
210 | |||
211 | if (lp->timeout != 3) | ||
212 | BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout); | ||
213 | |||
214 | BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n", | ||
215 | lp->setup >> 1, | ||
216 | clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); | ||
217 | |||
218 | if (register_netdev(dev)) { | ||
219 | free_irq(dev->irq, dev); | ||
220 | return -EIO; | ||
221 | } | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | /* | ||
227 | * Do a hardware reset on the card, and set up necessary registers. | ||
228 | * | ||
229 | * This should be called as little as possible, because it disrupts the | ||
230 | * token on the network (causes a RECON) and requires a significant delay. | ||
231 | * | ||
232 | * However, it does make sure the card is in a defined state. | ||
233 | */ | ||
234 | static int com20020_reset(struct net_device *dev, int really_reset) | ||
235 | { | ||
236 | struct arcnet_local *lp = dev->priv; | ||
237 | u_int ioaddr = dev->base_addr; | ||
238 | u_char inbyte; | ||
239 | |||
240 | BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", | ||
241 | __FILE__,__LINE__,__FUNCTION__,dev,lp,dev->name); | ||
242 | BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", | ||
243 | dev->name, ASTATUS()); | ||
244 | |||
245 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
246 | lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); | ||
247 | /* power-up defaults */ | ||
248 | SETCONF; | ||
249 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
250 | |||
251 | if (really_reset) { | ||
252 | /* reset the card */ | ||
253 | ARCRESET; | ||
254 | mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ | ||
255 | } | ||
256 | /* clear flags & end reset */ | ||
257 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
258 | ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); | ||
259 | |||
260 | /* verify that the ARCnet signature byte is present */ | ||
261 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
262 | |||
263 | com20020_copy_from_card(dev, 0, 0, &inbyte, 1); | ||
264 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
265 | if (inbyte != TESTvalue) { | ||
266 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
267 | BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); | ||
268 | return 1; | ||
269 | } | ||
270 | /* enable extended (512-byte) packets */ | ||
271 | ACOMMAND(CONFIGcmd | EXTconf); | ||
272 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
273 | |||
274 | /* done! return success. */ | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | |||
279 | static void com20020_setmask(struct net_device *dev, int mask) | ||
280 | { | ||
281 | u_int ioaddr = dev->base_addr; | ||
282 | BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr); | ||
283 | AINTMASK(mask); | ||
284 | } | ||
285 | |||
286 | |||
287 | static void com20020_command(struct net_device *dev, int cmd) | ||
288 | { | ||
289 | u_int ioaddr = dev->base_addr; | ||
290 | ACOMMAND(cmd); | ||
291 | } | ||
292 | |||
293 | |||
294 | static int com20020_status(struct net_device *dev) | ||
295 | { | ||
296 | u_int ioaddr = dev->base_addr; | ||
297 | |||
298 | return ASTATUS() + (ADIAGSTATUS()<<8); | ||
299 | } | ||
300 | |||
301 | static void com20020_close(struct net_device *dev) | ||
302 | { | ||
303 | struct arcnet_local *lp = dev->priv; | ||
304 | int ioaddr = dev->base_addr; | ||
305 | |||
306 | /* disable transmitter */ | ||
307 | lp->config &= ~TXENcfg; | ||
308 | SETCONF; | ||
309 | } | ||
310 | |||
311 | /* Set or clear the multicast filter for this adaptor. | ||
312 | * num_addrs == -1 Promiscuous mode, receive all packets | ||
313 | * num_addrs == 0 Normal mode, clear multicast list | ||
314 | * num_addrs > 0 Multicast mode, receive normal and MC packets, and do | ||
315 | * best-effort filtering. | ||
316 | * FIXME - do multicast stuff, not just promiscuous. | ||
317 | */ | ||
318 | static void com20020_set_mc_list(struct net_device *dev) | ||
319 | { | ||
320 | struct arcnet_local *lp = dev->priv; | ||
321 | int ioaddr = dev->base_addr; | ||
322 | |||
323 | if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ | ||
324 | if (!(lp->setup & PROMISCset)) | ||
325 | BUGMSG(D_NORMAL, "Setting promiscuous flag...\n"); | ||
326 | SET_SUBADR(SUB_SETUP1); | ||
327 | lp->setup |= PROMISCset; | ||
328 | outb(lp->setup, _XREG); | ||
329 | } else | ||
330 | /* Disable promiscuous mode, use normal mode */ | ||
331 | { | ||
332 | if ((lp->setup & PROMISCset)) | ||
333 | BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n"); | ||
334 | SET_SUBADR(SUB_SETUP1); | ||
335 | lp->setup &= ~PROMISCset; | ||
336 | outb(lp->setup, _XREG); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | #ifdef MODULE | ||
341 | |||
342 | EXPORT_SYMBOL(com20020_check); | ||
343 | EXPORT_SYMBOL(com20020_found); | ||
344 | |||
345 | MODULE_LICENSE("GPL"); | ||
346 | |||
347 | int init_module(void) | ||
348 | { | ||
349 | BUGLVL(D_NORMAL) printk(VERSION); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | void cleanup_module(void) | ||
354 | { | ||
355 | } | ||
356 | |||
357 | #endif /* MODULE */ | ||
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c new file mode 100644 index 000000000000..52c77cbe8c62 --- /dev/null +++ b/drivers/net/arcnet/com90io.c | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers) | ||
3 | * | ||
4 | * Written 1997 by David Woodhouse. | ||
5 | * Written 1994-1999 by Avery Pennarun. | ||
6 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
7 | * Derived from skeleton.c by Donald Becker. | ||
8 | * | ||
9 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
10 | * for sponsoring the further development of this driver. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright of skeleton.c was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * For more details, see drivers/net/arcnet.c | ||
25 | * | ||
26 | * ********************** | ||
27 | */ | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/bootmem.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <linux/arcdevice.h> | ||
39 | |||
40 | |||
41 | #define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n" | ||
42 | |||
43 | |||
44 | /* Internal function declarations */ | ||
45 | |||
46 | static int com90io_found(struct net_device *dev); | ||
47 | static void com90io_command(struct net_device *dev, int command); | ||
48 | static int com90io_status(struct net_device *dev); | ||
49 | static void com90io_setmask(struct net_device *dev, int mask); | ||
50 | static int com90io_reset(struct net_device *dev, int really_reset); | ||
51 | static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
52 | void *buf, int count); | ||
53 | static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
54 | void *buf, int count); | ||
55 | |||
56 | |||
57 | /* Handy defines for ARCnet specific stuff */ | ||
58 | |||
59 | /* The number of low I/O ports used by the card. */ | ||
60 | #define ARCNET_TOTAL_SIZE 16 | ||
61 | |||
62 | /* COM 9026 controller chip --> ARCnet register addresses */ | ||
63 | #define _INTMASK (ioaddr+0) /* writable */ | ||
64 | #define _STATUS (ioaddr+0) /* readable */ | ||
65 | #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ | ||
66 | #define _RESET (ioaddr+8) /* software reset (on read) */ | ||
67 | #define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ | ||
68 | #define _ADDR_HI (ioaddr+15) /* Control registers for said */ | ||
69 | #define _ADDR_LO (ioaddr+14) | ||
70 | #define _CONFIG (ioaddr+2) /* Configuration register */ | ||
71 | |||
72 | #undef ASTATUS | ||
73 | #undef ACOMMAND | ||
74 | #undef AINTMASK | ||
75 | |||
76 | #define ASTATUS() inb(_STATUS) | ||
77 | #define ACOMMAND(cmd) outb((cmd),_COMMAND) | ||
78 | #define AINTMASK(msk) outb((msk),_INTMASK) | ||
79 | #define SETCONF() outb((lp->config),_CONFIG) | ||
80 | |||
81 | |||
82 | /**************************************************************************** | ||
83 | * * | ||
84 | * IO-mapped operation routines * | ||
85 | * * | ||
86 | ****************************************************************************/ | ||
87 | |||
88 | #undef ONE_AT_A_TIME_TX | ||
89 | #undef ONE_AT_A_TIME_RX | ||
90 | |||
91 | static u_char get_buffer_byte(struct net_device *dev, unsigned offset) | ||
92 | { | ||
93 | int ioaddr = dev->base_addr; | ||
94 | |||
95 | outb(offset >> 8, _ADDR_HI); | ||
96 | outb(offset & 0xff, _ADDR_LO); | ||
97 | |||
98 | return inb(_MEMDATA); | ||
99 | } | ||
100 | |||
101 | #ifdef ONE_AT_A_TIME_TX | ||
102 | static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum) | ||
103 | { | ||
104 | int ioaddr = dev->base_addr; | ||
105 | |||
106 | outb(offset >> 8, _ADDR_HI); | ||
107 | outb(offset & 0xff, _ADDR_LO); | ||
108 | |||
109 | outb(datum, _MEMDATA); | ||
110 | } | ||
111 | |||
112 | #endif | ||
113 | |||
114 | |||
115 | static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) | ||
116 | { | ||
117 | int ioaddr = dev->base_addr; | ||
118 | |||
119 | outb((offset >> 8) | AUTOINCflag, _ADDR_HI); | ||
120 | outb(offset & 0xff, _ADDR_LO); | ||
121 | |||
122 | while (length--) | ||
123 | #ifdef ONE_AT_A_TIME_RX | ||
124 | *(dest++) = get_buffer_byte(dev, offset++); | ||
125 | #else | ||
126 | *(dest++) = inb(_MEMDATA); | ||
127 | #endif | ||
128 | } | ||
129 | |||
130 | static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) | ||
131 | { | ||
132 | int ioaddr = dev->base_addr; | ||
133 | |||
134 | outb((offset >> 8) | AUTOINCflag, _ADDR_HI); | ||
135 | outb(offset & 0xff, _ADDR_LO); | ||
136 | |||
137 | while (length--) | ||
138 | #ifdef ONE_AT_A_TIME_TX | ||
139 | put_buffer_byte(dev, offset++, *(dest++)); | ||
140 | #else | ||
141 | outb(*(dest++), _MEMDATA); | ||
142 | #endif | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * We cannot probe for an IO mapped card either, although we can check that | ||
147 | * it's where we were told it was, and even autoirq | ||
148 | */ | ||
149 | static int __init com90io_probe(struct net_device *dev) | ||
150 | { | ||
151 | int ioaddr = dev->base_addr, status; | ||
152 | unsigned long airqmask; | ||
153 | |||
154 | BUGLVL(D_NORMAL) printk(VERSION); | ||
155 | BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n"); | ||
156 | |||
157 | if (!ioaddr) { | ||
158 | BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you " | ||
159 | "must specify the base address!\n"); | ||
160 | return -ENODEV; | ||
161 | } | ||
162 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { | ||
163 | BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n", | ||
164 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); | ||
165 | return -ENXIO; | ||
166 | } | ||
167 | if (ASTATUS() == 0xFF) { | ||
168 | BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr); | ||
169 | goto err_out; | ||
170 | } | ||
171 | inb(_RESET); | ||
172 | mdelay(RESETtime); | ||
173 | |||
174 | status = ASTATUS(); | ||
175 | |||
176 | if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { | ||
177 | BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status); | ||
178 | goto err_out; | ||
179 | } | ||
180 | BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status); | ||
181 | |||
182 | ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); | ||
183 | |||
184 | BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status); | ||
185 | |||
186 | status = ASTATUS(); | ||
187 | |||
188 | if (status & RESETflag) { | ||
189 | BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status); | ||
190 | goto err_out; | ||
191 | } | ||
192 | outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG); | ||
193 | |||
194 | /* Read first loc'n of memory */ | ||
195 | |||
196 | outb(AUTOINCflag, _ADDR_HI); | ||
197 | outb(0, _ADDR_LO); | ||
198 | |||
199 | if ((status = inb(_MEMDATA)) != 0xd1) { | ||
200 | BUGMSG(D_INIT_REASONS, "Signature byte not found" | ||
201 | " (%Xh instead).\n", status); | ||
202 | goto err_out; | ||
203 | } | ||
204 | if (!dev->irq) { | ||
205 | /* | ||
206 | * if we do this, we're sure to get an IRQ since the | ||
207 | * card has just reset and the NORXflag is on until | ||
208 | * we tell it to start receiving. | ||
209 | */ | ||
210 | |||
211 | airqmask = probe_irq_on(); | ||
212 | outb(NORXflag, _INTMASK); | ||
213 | udelay(1); | ||
214 | outb(0, _INTMASK); | ||
215 | dev->irq = probe_irq_off(airqmask); | ||
216 | |||
217 | if (dev->irq <= 0) { | ||
218 | BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n"); | ||
219 | goto err_out; | ||
220 | } | ||
221 | } | ||
222 | release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */ | ||
223 | return com90io_found(dev); | ||
224 | |||
225 | err_out: | ||
226 | release_region(ioaddr, ARCNET_TOTAL_SIZE); | ||
227 | return -ENODEV; | ||
228 | } | ||
229 | |||
230 | |||
231 | /* Set up the struct net_device associated with this card. Called after | ||
232 | * probing succeeds. | ||
233 | */ | ||
234 | static int __init com90io_found(struct net_device *dev) | ||
235 | { | ||
236 | struct arcnet_local *lp; | ||
237 | int ioaddr = dev->base_addr; | ||
238 | int err; | ||
239 | |||
240 | /* Reserve the irq */ | ||
241 | if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { | ||
242 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); | ||
243 | return -ENODEV; | ||
244 | } | ||
245 | /* Reserve the I/O region - guaranteed to work by check_region */ | ||
246 | if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { | ||
247 | free_irq(dev->irq, dev); | ||
248 | return -EBUSY; | ||
249 | } | ||
250 | |||
251 | lp = dev->priv; | ||
252 | lp->card_name = "COM90xx I/O"; | ||
253 | lp->hw.command = com90io_command; | ||
254 | lp->hw.status = com90io_status; | ||
255 | lp->hw.intmask = com90io_setmask; | ||
256 | lp->hw.reset = com90io_reset; | ||
257 | lp->hw.owner = THIS_MODULE; | ||
258 | lp->hw.copy_to_card = com90io_copy_to_card; | ||
259 | lp->hw.copy_from_card = com90io_copy_from_card; | ||
260 | |||
261 | lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag; | ||
262 | SETCONF(); | ||
263 | |||
264 | /* get and check the station ID from offset 1 in shmem */ | ||
265 | |||
266 | dev->dev_addr[0] = get_buffer_byte(dev, 1); | ||
267 | |||
268 | err = register_netdev(dev); | ||
269 | if (err) { | ||
270 | outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); | ||
271 | free_irq(dev->irq, dev); | ||
272 | release_region(dev->base_addr, ARCNET_TOTAL_SIZE); | ||
273 | return err; | ||
274 | } | ||
275 | |||
276 | BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", | ||
277 | dev->dev_addr[0], dev->base_addr, dev->irq); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | |||
283 | /* | ||
284 | * Do a hardware reset on the card, and set up necessary registers. | ||
285 | * | ||
286 | * This should be called as little as possible, because it disrupts the | ||
287 | * token on the network (causes a RECON) and requires a significant delay. | ||
288 | * | ||
289 | * However, it does make sure the card is in a defined state. | ||
290 | */ | ||
291 | static int com90io_reset(struct net_device *dev, int really_reset) | ||
292 | { | ||
293 | struct arcnet_local *lp = dev->priv; | ||
294 | short ioaddr = dev->base_addr; | ||
295 | |||
296 | BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); | ||
297 | |||
298 | if (really_reset) { | ||
299 | /* reset the card */ | ||
300 | inb(_RESET); | ||
301 | mdelay(RESETtime); | ||
302 | } | ||
303 | /* Set the thing to IO-mapped, 8-bit mode */ | ||
304 | lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag; | ||
305 | SETCONF(); | ||
306 | |||
307 | ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ | ||
308 | ACOMMAND(CFLAGScmd | CONFIGclear); | ||
309 | |||
310 | /* verify that the ARCnet signature byte is present */ | ||
311 | if (get_buffer_byte(dev, 0) != TESTvalue) { | ||
312 | BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); | ||
313 | return 1; | ||
314 | } | ||
315 | /* enable extended (512-byte) packets */ | ||
316 | ACOMMAND(CONFIGcmd | EXTconf); | ||
317 | |||
318 | /* done! return success. */ | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | |||
323 | static void com90io_command(struct net_device *dev, int cmd) | ||
324 | { | ||
325 | short ioaddr = dev->base_addr; | ||
326 | |||
327 | ACOMMAND(cmd); | ||
328 | } | ||
329 | |||
330 | |||
331 | static int com90io_status(struct net_device *dev) | ||
332 | { | ||
333 | short ioaddr = dev->base_addr; | ||
334 | |||
335 | return ASTATUS(); | ||
336 | } | ||
337 | |||
338 | |||
339 | static void com90io_setmask(struct net_device *dev, int mask) | ||
340 | { | ||
341 | short ioaddr = dev->base_addr; | ||
342 | |||
343 | AINTMASK(mask); | ||
344 | } | ||
345 | |||
346 | static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
347 | void *buf, int count) | ||
348 | { | ||
349 | TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); | ||
350 | } | ||
351 | |||
352 | |||
353 | static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
354 | void *buf, int count) | ||
355 | { | ||
356 | TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); | ||
357 | } | ||
358 | |||
359 | static int io; /* use the insmod io= irq= shmem= options */ | ||
360 | static int irq; | ||
361 | static char device[9]; /* use eg. device=arc1 to change name */ | ||
362 | |||
363 | module_param(io, int, 0); | ||
364 | module_param(irq, int, 0); | ||
365 | module_param_string(device, device, sizeof(device), 0); | ||
366 | MODULE_LICENSE("GPL"); | ||
367 | |||
368 | #ifndef MODULE | ||
369 | static int __init com90io_setup(char *s) | ||
370 | { | ||
371 | int ints[4]; | ||
372 | s = get_options(s, 4, ints); | ||
373 | if (!ints[0]) | ||
374 | return 0; | ||
375 | switch (ints[0]) { | ||
376 | default: /* ERROR */ | ||
377 | printk("com90io: Too many arguments.\n"); | ||
378 | case 2: /* IRQ */ | ||
379 | irq = ints[2]; | ||
380 | case 1: /* IO address */ | ||
381 | io = ints[1]; | ||
382 | } | ||
383 | if (*s) | ||
384 | snprintf(device, sizeof(device), "%s", s); | ||
385 | return 1; | ||
386 | } | ||
387 | __setup("com90io=", com90io_setup); | ||
388 | #endif | ||
389 | |||
390 | static struct net_device *my_dev; | ||
391 | |||
392 | static int __init com90io_init(void) | ||
393 | { | ||
394 | struct net_device *dev; | ||
395 | int err; | ||
396 | |||
397 | dev = alloc_arcdev(device); | ||
398 | if (!dev) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | SET_MODULE_OWNER(dev); | ||
402 | |||
403 | dev->base_addr = io; | ||
404 | dev->irq = irq; | ||
405 | if (dev->irq == 2) | ||
406 | dev->irq = 9; | ||
407 | |||
408 | err = com90io_probe(dev); | ||
409 | |||
410 | if (err) { | ||
411 | free_netdev(dev); | ||
412 | return err; | ||
413 | } | ||
414 | |||
415 | my_dev = dev; | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static void __exit com90io_exit(void) | ||
420 | { | ||
421 | struct net_device *dev = my_dev; | ||
422 | int ioaddr = dev->base_addr; | ||
423 | |||
424 | unregister_netdev(dev); | ||
425 | |||
426 | /* Set the thing back to MMAP mode, in case the old driver is loaded later */ | ||
427 | outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); | ||
428 | |||
429 | free_irq(dev->irq, dev); | ||
430 | release_region(dev->base_addr, ARCNET_TOTAL_SIZE); | ||
431 | free_netdev(dev); | ||
432 | } | ||
433 | |||
434 | module_init(com90io_init) | ||
435 | module_exit(com90io_exit) | ||
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c new file mode 100644 index 000000000000..6c2c9b9ac6db --- /dev/null +++ b/drivers/net/arcnet/com90xx.c | |||
@@ -0,0 +1,646 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM90xx chipset (memory-mapped buffers) | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun. | ||
5 | * Written 1999 by Martin Mares <mj@ucw.cz>. | ||
6 | * Derived from skeleton.c by Donald Becker. | ||
7 | * | ||
8 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
9 | * for sponsoring the further development of this driver. | ||
10 | * | ||
11 | * ********************** | ||
12 | * | ||
13 | * The original copyright of skeleton.c was as follows: | ||
14 | * | ||
15 | * skeleton.c Written 1993 by Donald Becker. | ||
16 | * Copyright 1993 United States Government as represented by the | ||
17 | * Director, National Security Agency. This software may only be used | ||
18 | * and distributed according to the terms of the GNU General Public License as | ||
19 | * modified by SRC, incorporated herein by reference. | ||
20 | * | ||
21 | * ********************** | ||
22 | * | ||
23 | * For more details, see drivers/net/arcnet.c | ||
24 | * | ||
25 | * ********************** | ||
26 | */ | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/ioport.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/netdevice.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <linux/arcdevice.h> | ||
35 | |||
36 | |||
37 | #define VERSION "arcnet: COM90xx chipset support\n" | ||
38 | |||
39 | |||
40 | /* Define this to speed up the autoprobe by assuming if only one io port and | ||
41 | * shmem are left in the list at Stage 5, they must correspond to each | ||
42 | * other. | ||
43 | * | ||
44 | * This is undefined by default because it might not always be true, and the | ||
45 | * extra check makes the autoprobe even more careful. Speed demons can turn | ||
46 | * it on - I think it should be fine if you only have one ARCnet card | ||
47 | * installed. | ||
48 | * | ||
49 | * If no ARCnet cards are installed, this delay never happens anyway and thus | ||
50 | * the option has no effect. | ||
51 | */ | ||
52 | #undef FAST_PROBE | ||
53 | |||
54 | |||
55 | /* Internal function declarations */ | ||
56 | static int com90xx_found(int ioaddr, int airq, u_long shmem); | ||
57 | static void com90xx_command(struct net_device *dev, int command); | ||
58 | static int com90xx_status(struct net_device *dev); | ||
59 | static void com90xx_setmask(struct net_device *dev, int mask); | ||
60 | static int com90xx_reset(struct net_device *dev, int really_reset); | ||
61 | static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
62 | void *buf, int count); | ||
63 | static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
64 | void *buf, int count); | ||
65 | |||
66 | /* Known ARCnet cards */ | ||
67 | |||
68 | static struct net_device *cards[16]; | ||
69 | static int numcards; | ||
70 | |||
71 | /* Handy defines for ARCnet specific stuff */ | ||
72 | |||
73 | /* The number of low I/O ports used by the card */ | ||
74 | #define ARCNET_TOTAL_SIZE 16 | ||
75 | |||
76 | /* Amount of I/O memory used by the card */ | ||
77 | #define BUFFER_SIZE (512) | ||
78 | #define MIRROR_SIZE (BUFFER_SIZE*4) | ||
79 | |||
80 | /* COM 9026 controller chip --> ARCnet register addresses */ | ||
81 | #define _INTMASK (ioaddr+0) /* writable */ | ||
82 | #define _STATUS (ioaddr+0) /* readable */ | ||
83 | #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ | ||
84 | #define _CONFIG (ioaddr+2) /* Configuration register */ | ||
85 | #define _RESET (ioaddr+8) /* software reset (on read) */ | ||
86 | #define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ | ||
87 | #define _ADDR_HI (ioaddr+15) /* Control registers for said */ | ||
88 | #define _ADDR_LO (ioaddr+14) | ||
89 | |||
90 | #undef ASTATUS | ||
91 | #undef ACOMMAND | ||
92 | #undef AINTMASK | ||
93 | |||
94 | #define ASTATUS() inb(_STATUS) | ||
95 | #define ACOMMAND(cmd) outb((cmd),_COMMAND) | ||
96 | #define AINTMASK(msk) outb((msk),_INTMASK) | ||
97 | |||
98 | |||
99 | static int com90xx_skip_probe __initdata = 0; | ||
100 | |||
101 | /* Module parameters */ | ||
102 | |||
103 | static int io; /* use the insmod io= irq= shmem= options */ | ||
104 | static int irq; | ||
105 | static int shmem; | ||
106 | static char device[9]; /* use eg. device=arc1 to change name */ | ||
107 | |||
108 | module_param(io, int, 0); | ||
109 | module_param(irq, int, 0); | ||
110 | module_param(shmem, int, 0); | ||
111 | module_param_string(device, device, sizeof(device), 0); | ||
112 | |||
113 | static void __init com90xx_probe(void) | ||
114 | { | ||
115 | int count, status, ioaddr, numprint, airq, openparen = 0; | ||
116 | unsigned long airqmask; | ||
117 | int ports[(0x3f0 - 0x200) / 16 + 1] = | ||
118 | {0}; | ||
119 | u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] = | ||
120 | {0}; | ||
121 | int numports, numshmems, *port; | ||
122 | u_long *p; | ||
123 | |||
124 | if (!io && !irq && !shmem && !*device && com90xx_skip_probe) | ||
125 | return; | ||
126 | |||
127 | BUGLVL(D_NORMAL) printk(VERSION); | ||
128 | |||
129 | /* set up the arrays where we'll store the possible probe addresses */ | ||
130 | numports = numshmems = 0; | ||
131 | if (io) | ||
132 | ports[numports++] = io; | ||
133 | else | ||
134 | for (count = 0x200; count <= 0x3f0; count += 16) | ||
135 | ports[numports++] = count; | ||
136 | if (shmem) | ||
137 | shmems[numshmems++] = shmem; | ||
138 | else | ||
139 | for (count = 0xA0000; count <= 0xFF800; count += 2048) | ||
140 | shmems[numshmems++] = count; | ||
141 | |||
142 | /* Stage 1: abandon any reserved ports, or ones with status==0xFF | ||
143 | * (empty), and reset any others by reading the reset port. | ||
144 | */ | ||
145 | numprint = -1; | ||
146 | for (port = &ports[0]; port - ports < numports; port++) { | ||
147 | numprint++; | ||
148 | numprint %= 8; | ||
149 | if (!numprint) { | ||
150 | BUGMSG2(D_INIT, "\n"); | ||
151 | BUGMSG2(D_INIT, "S1: "); | ||
152 | } | ||
153 | BUGMSG2(D_INIT, "%Xh ", *port); | ||
154 | |||
155 | ioaddr = *port; | ||
156 | |||
157 | if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { | ||
158 | BUGMSG2(D_INIT_REASONS, "(request_region)\n"); | ||
159 | BUGMSG2(D_INIT_REASONS, "S1: "); | ||
160 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
161 | *port-- = ports[--numports]; | ||
162 | continue; | ||
163 | } | ||
164 | if (ASTATUS() == 0xFF) { | ||
165 | BUGMSG2(D_INIT_REASONS, "(empty)\n"); | ||
166 | BUGMSG2(D_INIT_REASONS, "S1: "); | ||
167 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
168 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
169 | *port-- = ports[--numports]; | ||
170 | continue; | ||
171 | } | ||
172 | inb(_RESET); /* begin resetting card */ | ||
173 | |||
174 | BUGMSG2(D_INIT_REASONS, "\n"); | ||
175 | BUGMSG2(D_INIT_REASONS, "S1: "); | ||
176 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
177 | } | ||
178 | BUGMSG2(D_INIT, "\n"); | ||
179 | |||
180 | if (!numports) { | ||
181 | BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); | ||
182 | return; | ||
183 | } | ||
184 | /* Stage 2: we have now reset any possible ARCnet cards, so we can't | ||
185 | * do anything until they finish. If D_INIT, print the list of | ||
186 | * cards that are left. | ||
187 | */ | ||
188 | numprint = -1; | ||
189 | for (port = &ports[0]; port < ports + numports; port++) { | ||
190 | numprint++; | ||
191 | numprint %= 8; | ||
192 | if (!numprint) { | ||
193 | BUGMSG2(D_INIT, "\n"); | ||
194 | BUGMSG2(D_INIT, "S2: "); | ||
195 | } | ||
196 | BUGMSG2(D_INIT, "%Xh ", *port); | ||
197 | } | ||
198 | BUGMSG2(D_INIT, "\n"); | ||
199 | mdelay(RESETtime); | ||
200 | |||
201 | /* Stage 3: abandon any shmem addresses that don't have the signature | ||
202 | * 0xD1 byte in the right place, or are read-only. | ||
203 | */ | ||
204 | numprint = -1; | ||
205 | for (p = &shmems[0]; p < shmems + numshmems; p++) { | ||
206 | u_long ptr = *p; | ||
207 | |||
208 | numprint++; | ||
209 | numprint %= 8; | ||
210 | if (!numprint) { | ||
211 | BUGMSG2(D_INIT, "\n"); | ||
212 | BUGMSG2(D_INIT, "S3: "); | ||
213 | } | ||
214 | BUGMSG2(D_INIT, "%lXh ", *p); | ||
215 | |||
216 | if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) { | ||
217 | BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); | ||
218 | BUGMSG2(D_INIT_REASONS, "Stage 3: "); | ||
219 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
220 | *p-- = shmems[--numshmems]; | ||
221 | continue; | ||
222 | } | ||
223 | if (isa_readb(ptr) != TESTvalue) { | ||
224 | BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", | ||
225 | isa_readb(ptr), TESTvalue); | ||
226 | BUGMSG2(D_INIT_REASONS, "S3: "); | ||
227 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
228 | release_mem_region(*p, BUFFER_SIZE); | ||
229 | *p-- = shmems[--numshmems]; | ||
230 | continue; | ||
231 | } | ||
232 | /* By writing 0x42 to the TESTvalue location, we also make | ||
233 | * sure no "mirror" shmem areas show up - if they occur | ||
234 | * in another pass through this loop, they will be discarded | ||
235 | * because *cptr != TESTvalue. | ||
236 | */ | ||
237 | isa_writeb(0x42, ptr); | ||
238 | if (isa_readb(ptr) != 0x42) { | ||
239 | BUGMSG2(D_INIT_REASONS, "(read only)\n"); | ||
240 | BUGMSG2(D_INIT_REASONS, "S3: "); | ||
241 | release_mem_region(*p, BUFFER_SIZE); | ||
242 | *p-- = shmems[--numshmems]; | ||
243 | continue; | ||
244 | } | ||
245 | BUGMSG2(D_INIT_REASONS, "\n"); | ||
246 | BUGMSG2(D_INIT_REASONS, "S3: "); | ||
247 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
248 | } | ||
249 | BUGMSG2(D_INIT, "\n"); | ||
250 | |||
251 | if (!numshmems) { | ||
252 | BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); | ||
253 | for (port = &ports[0]; port < ports + numports; port++) | ||
254 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
255 | return; | ||
256 | } | ||
257 | /* Stage 4: something of a dummy, to report the shmems that are | ||
258 | * still possible after stage 3. | ||
259 | */ | ||
260 | numprint = -1; | ||
261 | for (p = &shmems[0]; p < shmems + numshmems; p++) { | ||
262 | numprint++; | ||
263 | numprint %= 8; | ||
264 | if (!numprint) { | ||
265 | BUGMSG2(D_INIT, "\n"); | ||
266 | BUGMSG2(D_INIT, "S4: "); | ||
267 | } | ||
268 | BUGMSG2(D_INIT, "%lXh ", *p); | ||
269 | } | ||
270 | BUGMSG2(D_INIT, "\n"); | ||
271 | |||
272 | /* Stage 5: for any ports that have the correct status, can disable | ||
273 | * the RESET flag, and (if no irq is given) generate an autoirq, | ||
274 | * register an ARCnet device. | ||
275 | * | ||
276 | * Currently, we can only register one device per probe, so quit | ||
277 | * after the first one is found. | ||
278 | */ | ||
279 | numprint = -1; | ||
280 | for (port = &ports[0]; port < ports + numports; port++) { | ||
281 | int found = 0; | ||
282 | numprint++; | ||
283 | numprint %= 8; | ||
284 | if (!numprint) { | ||
285 | BUGMSG2(D_INIT, "\n"); | ||
286 | BUGMSG2(D_INIT, "S5: "); | ||
287 | } | ||
288 | BUGMSG2(D_INIT, "%Xh ", *port); | ||
289 | |||
290 | ioaddr = *port; | ||
291 | status = ASTATUS(); | ||
292 | |||
293 | if ((status & 0x9D) | ||
294 | != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { | ||
295 | BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); | ||
296 | BUGMSG2(D_INIT_REASONS, "S5: "); | ||
297 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
298 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
299 | *port-- = ports[--numports]; | ||
300 | continue; | ||
301 | } | ||
302 | ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); | ||
303 | status = ASTATUS(); | ||
304 | if (status & RESETflag) { | ||
305 | BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", | ||
306 | status); | ||
307 | BUGMSG2(D_INIT_REASONS, "S5: "); | ||
308 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
309 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
310 | *port-- = ports[--numports]; | ||
311 | continue; | ||
312 | } | ||
313 | /* skip this completely if an IRQ was given, because maybe | ||
314 | * we're on a machine that locks during autoirq! | ||
315 | */ | ||
316 | if (!irq) { | ||
317 | /* if we do this, we're sure to get an IRQ since the | ||
318 | * card has just reset and the NORXflag is on until | ||
319 | * we tell it to start receiving. | ||
320 | */ | ||
321 | airqmask = probe_irq_on(); | ||
322 | AINTMASK(NORXflag); | ||
323 | udelay(1); | ||
324 | AINTMASK(0); | ||
325 | airq = probe_irq_off(airqmask); | ||
326 | |||
327 | if (airq <= 0) { | ||
328 | BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); | ||
329 | BUGMSG2(D_INIT_REASONS, "S5: "); | ||
330 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
331 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
332 | *port-- = ports[--numports]; | ||
333 | continue; | ||
334 | } | ||
335 | } else { | ||
336 | airq = irq; | ||
337 | } | ||
338 | |||
339 | BUGMSG2(D_INIT, "(%d,", airq); | ||
340 | openparen = 1; | ||
341 | |||
342 | /* Everything seems okay. But which shmem, if any, puts | ||
343 | * back its signature byte when the card is reset? | ||
344 | * | ||
345 | * If there are multiple cards installed, there might be | ||
346 | * multiple shmems still in the list. | ||
347 | */ | ||
348 | #ifdef FAST_PROBE | ||
349 | if (numports > 1 || numshmems > 1) { | ||
350 | inb(_RESET); | ||
351 | mdelay(RESETtime); | ||
352 | } else { | ||
353 | /* just one shmem and port, assume they match */ | ||
354 | isa_writeb(TESTvalue, shmems[0]); | ||
355 | } | ||
356 | #else | ||
357 | inb(_RESET); | ||
358 | mdelay(RESETtime); | ||
359 | #endif | ||
360 | |||
361 | for (p = &shmems[0]; p < shmems + numshmems; p++) { | ||
362 | u_long ptr = *p; | ||
363 | |||
364 | if (isa_readb(ptr) == TESTvalue) { /* found one */ | ||
365 | BUGMSG2(D_INIT, "%lXh)\n", *p); | ||
366 | openparen = 0; | ||
367 | |||
368 | /* register the card */ | ||
369 | if (com90xx_found(*port, airq, *p) == 0) | ||
370 | found = 1; | ||
371 | numprint = -1; | ||
372 | |||
373 | /* remove shmem from the list */ | ||
374 | *p = shmems[--numshmems]; | ||
375 | break; /* go to the next I/O port */ | ||
376 | } else { | ||
377 | BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr)); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | if (openparen) { | ||
382 | BUGLVL(D_INIT) printk("no matching shmem)\n"); | ||
383 | BUGLVL(D_INIT_REASONS) printk("S5: "); | ||
384 | BUGLVL(D_INIT_REASONS) numprint = 0; | ||
385 | } | ||
386 | if (!found) | ||
387 | release_region(*port, ARCNET_TOTAL_SIZE); | ||
388 | *port-- = ports[--numports]; | ||
389 | } | ||
390 | |||
391 | BUGLVL(D_INIT_REASONS) printk("\n"); | ||
392 | |||
393 | /* Now put back TESTvalue on all leftover shmems. */ | ||
394 | for (p = &shmems[0]; p < shmems + numshmems; p++) { | ||
395 | isa_writeb(TESTvalue, *p); | ||
396 | release_mem_region(*p, BUFFER_SIZE); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | /* Set up the struct net_device associated with this card. Called after | ||
402 | * probing succeeds. | ||
403 | */ | ||
404 | static int __init com90xx_found(int ioaddr, int airq, u_long shmem) | ||
405 | { | ||
406 | struct net_device *dev = NULL; | ||
407 | struct arcnet_local *lp; | ||
408 | u_long first_mirror, last_mirror; | ||
409 | int mirror_size; | ||
410 | |||
411 | /* allocate struct net_device */ | ||
412 | dev = alloc_arcdev(device); | ||
413 | if (!dev) { | ||
414 | BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); | ||
415 | release_mem_region(shmem, BUFFER_SIZE); | ||
416 | return -ENOMEM; | ||
417 | } | ||
418 | lp = dev->priv; | ||
419 | /* find the real shared memory start/end points, including mirrors */ | ||
420 | |||
421 | /* guess the actual size of one "memory mirror" - the number of | ||
422 | * bytes between copies of the shared memory. On most cards, it's | ||
423 | * 2k (or there are no mirrors at all) but on some, it's 4k. | ||
424 | */ | ||
425 | mirror_size = MIRROR_SIZE; | ||
426 | if (isa_readb(shmem) == TESTvalue | ||
427 | && isa_readb(shmem - mirror_size) != TESTvalue | ||
428 | && isa_readb(shmem - 2 * mirror_size) == TESTvalue) | ||
429 | mirror_size *= 2; | ||
430 | |||
431 | first_mirror = last_mirror = shmem; | ||
432 | while (isa_readb(first_mirror) == TESTvalue) | ||
433 | first_mirror -= mirror_size; | ||
434 | first_mirror += mirror_size; | ||
435 | |||
436 | while (isa_readb(last_mirror) == TESTvalue) | ||
437 | last_mirror += mirror_size; | ||
438 | last_mirror -= mirror_size; | ||
439 | |||
440 | dev->mem_start = first_mirror; | ||
441 | dev->mem_end = last_mirror + MIRROR_SIZE - 1; | ||
442 | |||
443 | release_mem_region(shmem, BUFFER_SIZE); | ||
444 | if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) | ||
445 | goto err_free_dev; | ||
446 | |||
447 | /* reserve the irq */ | ||
448 | if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) { | ||
449 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); | ||
450 | goto err_release_mem; | ||
451 | } | ||
452 | dev->irq = airq; | ||
453 | |||
454 | /* Initialize the rest of the device structure. */ | ||
455 | lp->card_name = "COM90xx"; | ||
456 | lp->hw.command = com90xx_command; | ||
457 | lp->hw.status = com90xx_status; | ||
458 | lp->hw.intmask = com90xx_setmask; | ||
459 | lp->hw.reset = com90xx_reset; | ||
460 | lp->hw.owner = THIS_MODULE; | ||
461 | lp->hw.copy_to_card = com90xx_copy_to_card; | ||
462 | lp->hw.copy_from_card = com90xx_copy_from_card; | ||
463 | lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
464 | if (!lp->mem_start) { | ||
465 | BUGMSG(D_NORMAL, "Can't remap device memory!\n"); | ||
466 | goto err_free_irq; | ||
467 | } | ||
468 | |||
469 | /* get and check the station ID from offset 1 in shmem */ | ||
470 | dev->dev_addr[0] = readb(lp->mem_start + 1); | ||
471 | |||
472 | dev->base_addr = ioaddr; | ||
473 | |||
474 | BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, " | ||
475 | "ShMem %lXh (%ld*%xh).\n", | ||
476 | dev->dev_addr[0], | ||
477 | dev->base_addr, dev->irq, dev->mem_start, | ||
478 | (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); | ||
479 | |||
480 | if (register_netdev(dev)) | ||
481 | goto err_unmap; | ||
482 | |||
483 | cards[numcards++] = dev; | ||
484 | return 0; | ||
485 | |||
486 | err_unmap: | ||
487 | iounmap(lp->mem_start); | ||
488 | err_free_irq: | ||
489 | free_irq(dev->irq, dev); | ||
490 | err_release_mem: | ||
491 | release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
492 | err_free_dev: | ||
493 | free_netdev(dev); | ||
494 | return -EIO; | ||
495 | } | ||
496 | |||
497 | |||
498 | static void com90xx_command(struct net_device *dev, int cmd) | ||
499 | { | ||
500 | short ioaddr = dev->base_addr; | ||
501 | |||
502 | ACOMMAND(cmd); | ||
503 | } | ||
504 | |||
505 | |||
506 | static int com90xx_status(struct net_device *dev) | ||
507 | { | ||
508 | short ioaddr = dev->base_addr; | ||
509 | |||
510 | return ASTATUS(); | ||
511 | } | ||
512 | |||
513 | |||
514 | static void com90xx_setmask(struct net_device *dev, int mask) | ||
515 | { | ||
516 | short ioaddr = dev->base_addr; | ||
517 | |||
518 | AINTMASK(mask); | ||
519 | } | ||
520 | |||
521 | |||
522 | /* | ||
523 | * Do a hardware reset on the card, and set up necessary registers. | ||
524 | * | ||
525 | * This should be called as little as possible, because it disrupts the | ||
526 | * token on the network (causes a RECON) and requires a significant delay. | ||
527 | * | ||
528 | * However, it does make sure the card is in a defined state. | ||
529 | */ | ||
530 | int com90xx_reset(struct net_device *dev, int really_reset) | ||
531 | { | ||
532 | struct arcnet_local *lp = dev->priv; | ||
533 | short ioaddr = dev->base_addr; | ||
534 | |||
535 | BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS()); | ||
536 | |||
537 | if (really_reset) { | ||
538 | /* reset the card */ | ||
539 | inb(_RESET); | ||
540 | mdelay(RESETtime); | ||
541 | } | ||
542 | ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ | ||
543 | ACOMMAND(CFLAGScmd | CONFIGclear); | ||
544 | |||
545 | /* don't do this until we verify that it doesn't hurt older cards! */ | ||
546 | /* outb(inb(_CONFIG) | ENABLE16flag, _CONFIG); */ | ||
547 | |||
548 | /* verify that the ARCnet signature byte is present */ | ||
549 | if (readb(lp->mem_start) != TESTvalue) { | ||
550 | if (really_reset) | ||
551 | BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); | ||
552 | return 1; | ||
553 | } | ||
554 | /* enable extended (512-byte) packets */ | ||
555 | ACOMMAND(CONFIGcmd | EXTconf); | ||
556 | |||
557 | /* clean out all the memory to make debugging make more sense :) */ | ||
558 | BUGLVL(D_DURING) | ||
559 | memset_io(lp->mem_start, 0x42, 2048); | ||
560 | |||
561 | /* done! return success. */ | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, | ||
566 | void *buf, int count) | ||
567 | { | ||
568 | struct arcnet_local *lp = dev->priv; | ||
569 | void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; | ||
570 | TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); | ||
571 | } | ||
572 | |||
573 | |||
574 | static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, | ||
575 | void *buf, int count) | ||
576 | { | ||
577 | struct arcnet_local *lp = dev->priv; | ||
578 | void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; | ||
579 | TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); | ||
580 | } | ||
581 | |||
582 | |||
583 | MODULE_LICENSE("GPL"); | ||
584 | |||
585 | static int __init com90xx_init(void) | ||
586 | { | ||
587 | if (irq == 2) | ||
588 | irq = 9; | ||
589 | com90xx_probe(); | ||
590 | if (!numcards) | ||
591 | return -EIO; | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static void __exit com90xx_exit(void) | ||
596 | { | ||
597 | struct net_device *dev; | ||
598 | struct arcnet_local *lp; | ||
599 | int count; | ||
600 | |||
601 | for (count = 0; count < numcards; count++) { | ||
602 | dev = cards[count]; | ||
603 | lp = dev->priv; | ||
604 | |||
605 | unregister_netdev(dev); | ||
606 | free_irq(dev->irq, dev); | ||
607 | iounmap(lp->mem_start); | ||
608 | release_region(dev->base_addr, ARCNET_TOTAL_SIZE); | ||
609 | release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); | ||
610 | free_netdev(dev); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | module_init(com90xx_init); | ||
615 | module_exit(com90xx_exit); | ||
616 | |||
617 | #ifndef MODULE | ||
618 | static int __init com90xx_setup(char *s) | ||
619 | { | ||
620 | int ints[8]; | ||
621 | |||
622 | s = get_options(s, 8, ints); | ||
623 | if (!ints[0] && !*s) { | ||
624 | printk("com90xx: Disabled.\n"); | ||
625 | return 1; | ||
626 | } | ||
627 | |||
628 | switch (ints[0]) { | ||
629 | default: /* ERROR */ | ||
630 | printk("com90xx: Too many arguments.\n"); | ||
631 | case 3: /* Mem address */ | ||
632 | shmem = ints[3]; | ||
633 | case 2: /* IRQ */ | ||
634 | irq = ints[2]; | ||
635 | case 1: /* IO address */ | ||
636 | io = ints[1]; | ||
637 | } | ||
638 | |||
639 | if (*s) | ||
640 | snprintf(device, sizeof(device), "%s", s); | ||
641 | |||
642 | return 1; | ||
643 | } | ||
644 | |||
645 | __setup("com90xx=", com90xx_setup); | ||
646 | #endif | ||
diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c new file mode 100644 index 000000000000..6d7913704fb5 --- /dev/null +++ b/drivers/net/arcnet/rfc1051.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun. | ||
5 | * Derived from skeleton.c by Donald Becker. | ||
6 | * | ||
7 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
8 | * for sponsoring the further development of this driver. | ||
9 | * | ||
10 | * ********************** | ||
11 | * | ||
12 | * The original copyright of skeleton.c was as follows: | ||
13 | * | ||
14 | * skeleton.c Written 1993 by Donald Becker. | ||
15 | * Copyright 1993 United States Government as represented by the | ||
16 | * Director, National Security Agency. This software may only be used | ||
17 | * and distributed according to the terms of the GNU General Public License as | ||
18 | * modified by SRC, incorporated herein by reference. | ||
19 | * | ||
20 | * ********************** | ||
21 | * | ||
22 | * For more details, see drivers/net/arcnet.c | ||
23 | * | ||
24 | * ********************** | ||
25 | */ | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <net/arp.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/arcdevice.h> | ||
33 | |||
34 | #define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n" | ||
35 | |||
36 | |||
37 | static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev); | ||
38 | static void rx(struct net_device *dev, int bufnum, | ||
39 | struct archdr *pkthdr, int length); | ||
40 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
41 | unsigned short type, uint8_t daddr); | ||
42 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
43 | int bufnum); | ||
44 | |||
45 | |||
46 | struct ArcProto rfc1051_proto = | ||
47 | { | ||
48 | .suffix = 's', | ||
49 | .mtu = XMTU - RFC1051_HDR_SIZE, | ||
50 | .is_ip = 1, | ||
51 | .rx = rx, | ||
52 | .build_header = build_header, | ||
53 | .prepare_tx = prepare_tx, | ||
54 | .continue_tx = NULL, | ||
55 | .ack_tx = NULL | ||
56 | }; | ||
57 | |||
58 | |||
59 | static int __init arcnet_rfc1051_init(void) | ||
60 | { | ||
61 | printk(VERSION); | ||
62 | |||
63 | arc_proto_map[ARC_P_IP_RFC1051] | ||
64 | = arc_proto_map[ARC_P_ARP_RFC1051] | ||
65 | = &rfc1051_proto; | ||
66 | |||
67 | /* if someone else already owns the broadcast, we won't take it */ | ||
68 | if (arc_bcast_proto == arc_proto_default) | ||
69 | arc_bcast_proto = &rfc1051_proto; | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static void __exit arcnet_rfc1051_exit(void) | ||
75 | { | ||
76 | arcnet_unregister_proto(&rfc1051_proto); | ||
77 | } | ||
78 | |||
79 | module_init(arcnet_rfc1051_init); | ||
80 | module_exit(arcnet_rfc1051_exit); | ||
81 | |||
82 | MODULE_LICENSE("GPL"); | ||
83 | |||
84 | /* | ||
85 | * Determine a packet's protocol ID. | ||
86 | * | ||
87 | * With ARCnet we have to convert everything to Ethernet-style stuff. | ||
88 | */ | ||
89 | static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev) | ||
90 | { | ||
91 | struct arcnet_local *lp = dev->priv; | ||
92 | struct archdr *pkt = (struct archdr *) skb->data; | ||
93 | struct arc_rfc1051 *soft = &pkt->soft.rfc1051; | ||
94 | int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; | ||
95 | |||
96 | /* Pull off the arcnet header. */ | ||
97 | skb->mac.raw = skb->data; | ||
98 | skb_pull(skb, hdr_size); | ||
99 | |||
100 | if (pkt->hard.dest == 0) | ||
101 | skb->pkt_type = PACKET_BROADCAST; | ||
102 | else if (dev->flags & IFF_PROMISC) { | ||
103 | /* if we're not sending to ourselves :) */ | ||
104 | if (pkt->hard.dest != dev->dev_addr[0]) | ||
105 | skb->pkt_type = PACKET_OTHERHOST; | ||
106 | } | ||
107 | /* now return the protocol number */ | ||
108 | switch (soft->proto) { | ||
109 | case ARC_P_IP_RFC1051: | ||
110 | return htons(ETH_P_IP); | ||
111 | case ARC_P_ARP_RFC1051: | ||
112 | return htons(ETH_P_ARP); | ||
113 | |||
114 | default: | ||
115 | lp->stats.rx_errors++; | ||
116 | lp->stats.rx_crc_errors++; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | return htons(ETH_P_IP); | ||
121 | } | ||
122 | |||
123 | |||
124 | /* packet receiver */ | ||
125 | static void rx(struct net_device *dev, int bufnum, | ||
126 | struct archdr *pkthdr, int length) | ||
127 | { | ||
128 | struct arcnet_local *lp = dev->priv; | ||
129 | struct sk_buff *skb; | ||
130 | struct archdr *pkt = pkthdr; | ||
131 | int ofs; | ||
132 | |||
133 | BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); | ||
134 | |||
135 | if (length >= MinTU) | ||
136 | ofs = 512 - length; | ||
137 | else | ||
138 | ofs = 256 - length; | ||
139 | |||
140 | skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); | ||
141 | if (skb == NULL) { | ||
142 | BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); | ||
143 | lp->stats.rx_dropped++; | ||
144 | return; | ||
145 | } | ||
146 | skb_put(skb, length + ARC_HDR_SIZE); | ||
147 | skb->dev = dev; | ||
148 | |||
149 | pkt = (struct archdr *) skb->data; | ||
150 | |||
151 | /* up to sizeof(pkt->soft) has already been copied from the card */ | ||
152 | memcpy(pkt, pkthdr, sizeof(struct archdr)); | ||
153 | if (length > sizeof(pkt->soft)) | ||
154 | lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), | ||
155 | pkt->soft.raw + sizeof(pkt->soft), | ||
156 | length - sizeof(pkt->soft)); | ||
157 | |||
158 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); | ||
159 | |||
160 | skb->protocol = type_trans(skb, dev); | ||
161 | netif_rx(skb); | ||
162 | dev->last_rx = jiffies; | ||
163 | } | ||
164 | |||
165 | |||
166 | /* | ||
167 | * Create the ARCnet hard/soft headers for RFC1051. | ||
168 | */ | ||
169 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
170 | unsigned short type, uint8_t daddr) | ||
171 | { | ||
172 | struct arcnet_local *lp = dev->priv; | ||
173 | int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; | ||
174 | struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); | ||
175 | struct arc_rfc1051 *soft = &pkt->soft.rfc1051; | ||
176 | |||
177 | /* set the protocol ID according to RFC1051 */ | ||
178 | switch (type) { | ||
179 | case ETH_P_IP: | ||
180 | soft->proto = ARC_P_IP_RFC1051; | ||
181 | break; | ||
182 | case ETH_P_ARP: | ||
183 | soft->proto = ARC_P_ARP_RFC1051; | ||
184 | break; | ||
185 | default: | ||
186 | BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n", | ||
187 | type, type); | ||
188 | lp->stats.tx_errors++; | ||
189 | lp->stats.tx_aborted_errors++; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* | ||
195 | * Set the source hardware address. | ||
196 | * | ||
197 | * This is pretty pointless for most purposes, but it can help in | ||
198 | * debugging. ARCnet does not allow us to change the source address in | ||
199 | * the actual packet sent) | ||
200 | */ | ||
201 | pkt->hard.source = *dev->dev_addr; | ||
202 | |||
203 | /* see linux/net/ethernet/eth.c to see where I got the following */ | ||
204 | |||
205 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { | ||
206 | /* | ||
207 | * FIXME: fill in the last byte of the dest ipaddr here to better | ||
208 | * comply with RFC1051 in "noarp" mode. | ||
209 | */ | ||
210 | pkt->hard.dest = 0; | ||
211 | return hdr_size; | ||
212 | } | ||
213 | /* otherwise, just fill it in and go! */ | ||
214 | pkt->hard.dest = daddr; | ||
215 | |||
216 | return hdr_size; /* success */ | ||
217 | } | ||
218 | |||
219 | |||
220 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
221 | int bufnum) | ||
222 | { | ||
223 | struct arcnet_local *lp = dev->priv; | ||
224 | struct arc_hardware *hard = &pkt->hard; | ||
225 | int ofs; | ||
226 | |||
227 | BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", | ||
228 | lp->next_tx, lp->cur_tx, bufnum); | ||
229 | |||
230 | length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ | ||
231 | |||
232 | if (length > XMTU) { | ||
233 | /* should never happen! other people already check for this. */ | ||
234 | BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", | ||
235 | length, XMTU); | ||
236 | length = XMTU; | ||
237 | } | ||
238 | if (length > MinTU) { | ||
239 | hard->offset[0] = 0; | ||
240 | hard->offset[1] = ofs = 512 - length; | ||
241 | } else if (length > MTU) { | ||
242 | hard->offset[0] = 0; | ||
243 | hard->offset[1] = ofs = 512 - length - 3; | ||
244 | } else | ||
245 | hard->offset[0] = ofs = 256 - length; | ||
246 | |||
247 | lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); | ||
248 | lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); | ||
249 | |||
250 | lp->lastload_dest = hard->dest; | ||
251 | |||
252 | return 1; /* done */ | ||
253 | } | ||
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c new file mode 100644 index 000000000000..6b6ae4bf3d39 --- /dev/null +++ b/drivers/net/arcnet/rfc1201.c | |||
@@ -0,0 +1,549 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - RFC1201 (standard) packet encapsulation | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun. | ||
5 | * Derived from skeleton.c by Donald Becker. | ||
6 | * | ||
7 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
8 | * for sponsoring the further development of this driver. | ||
9 | * | ||
10 | * ********************** | ||
11 | * | ||
12 | * The original copyright of skeleton.c was as follows: | ||
13 | * | ||
14 | * skeleton.c Written 1993 by Donald Becker. | ||
15 | * Copyright 1993 United States Government as represented by the | ||
16 | * Director, National Security Agency. This software may only be used | ||
17 | * and distributed according to the terms of the GNU General Public License as | ||
18 | * modified by SRC, incorporated herein by reference. | ||
19 | * | ||
20 | * ********************** | ||
21 | * | ||
22 | * For more details, see drivers/net/arcnet.c | ||
23 | * | ||
24 | * ********************** | ||
25 | */ | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/skbuff.h> | ||
31 | #include <linux/arcdevice.h> | ||
32 | |||
33 | MODULE_LICENSE("GPL"); | ||
34 | #define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n" | ||
35 | |||
36 | |||
37 | static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev); | ||
38 | static void rx(struct net_device *dev, int bufnum, | ||
39 | struct archdr *pkthdr, int length); | ||
40 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
41 | unsigned short type, uint8_t daddr); | ||
42 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
43 | int bufnum); | ||
44 | static int continue_tx(struct net_device *dev, int bufnum); | ||
45 | |||
46 | struct ArcProto rfc1201_proto = | ||
47 | { | ||
48 | .suffix = 'a', | ||
49 | .mtu = 1500, /* could be more, but some receivers can't handle it... */ | ||
50 | .is_ip = 1, /* This is for sending IP and ARP packages */ | ||
51 | .rx = rx, | ||
52 | .build_header = build_header, | ||
53 | .prepare_tx = prepare_tx, | ||
54 | .continue_tx = continue_tx, | ||
55 | .ack_tx = NULL | ||
56 | }; | ||
57 | |||
58 | |||
59 | static int __init arcnet_rfc1201_init(void) | ||
60 | { | ||
61 | printk(VERSION); | ||
62 | |||
63 | arc_proto_map[ARC_P_IP] | ||
64 | = arc_proto_map[ARC_P_IPV6] | ||
65 | = arc_proto_map[ARC_P_ARP] | ||
66 | = arc_proto_map[ARC_P_RARP] | ||
67 | = arc_proto_map[ARC_P_IPX] | ||
68 | = arc_proto_map[ARC_P_NOVELL_EC] | ||
69 | = &rfc1201_proto; | ||
70 | |||
71 | /* if someone else already owns the broadcast, we won't take it */ | ||
72 | if (arc_bcast_proto == arc_proto_default) | ||
73 | arc_bcast_proto = &rfc1201_proto; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static void __exit arcnet_rfc1201_exit(void) | ||
79 | { | ||
80 | arcnet_unregister_proto(&rfc1201_proto); | ||
81 | } | ||
82 | |||
83 | module_init(arcnet_rfc1201_init); | ||
84 | module_exit(arcnet_rfc1201_exit); | ||
85 | |||
86 | /* | ||
87 | * Determine a packet's protocol ID. | ||
88 | * | ||
89 | * With ARCnet we have to convert everything to Ethernet-style stuff. | ||
90 | */ | ||
91 | static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev) | ||
92 | { | ||
93 | struct archdr *pkt = (struct archdr *) skb->data; | ||
94 | struct arc_rfc1201 *soft = &pkt->soft.rfc1201; | ||
95 | struct arcnet_local *lp = dev->priv; | ||
96 | int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; | ||
97 | |||
98 | /* Pull off the arcnet header. */ | ||
99 | skb->mac.raw = skb->data; | ||
100 | skb_pull(skb, hdr_size); | ||
101 | |||
102 | if (pkt->hard.dest == 0) | ||
103 | skb->pkt_type = PACKET_BROADCAST; | ||
104 | else if (dev->flags & IFF_PROMISC) { | ||
105 | /* if we're not sending to ourselves :) */ | ||
106 | if (pkt->hard.dest != dev->dev_addr[0]) | ||
107 | skb->pkt_type = PACKET_OTHERHOST; | ||
108 | } | ||
109 | /* now return the protocol number */ | ||
110 | switch (soft->proto) { | ||
111 | case ARC_P_IP: | ||
112 | return htons(ETH_P_IP); | ||
113 | case ARC_P_IPV6: | ||
114 | return htons(ETH_P_IPV6); | ||
115 | case ARC_P_ARP: | ||
116 | return htons(ETH_P_ARP); | ||
117 | case ARC_P_RARP: | ||
118 | return htons(ETH_P_RARP); | ||
119 | |||
120 | case ARC_P_IPX: | ||
121 | case ARC_P_NOVELL_EC: | ||
122 | return htons(ETH_P_802_3); | ||
123 | default: | ||
124 | lp->stats.rx_errors++; | ||
125 | lp->stats.rx_crc_errors++; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | return htons(ETH_P_IP); | ||
130 | } | ||
131 | |||
132 | |||
133 | /* packet receiver */ | ||
134 | static void rx(struct net_device *dev, int bufnum, | ||
135 | struct archdr *pkthdr, int length) | ||
136 | { | ||
137 | struct arcnet_local *lp = dev->priv; | ||
138 | struct sk_buff *skb; | ||
139 | struct archdr *pkt = pkthdr; | ||
140 | struct arc_rfc1201 *soft = &pkthdr->soft.rfc1201; | ||
141 | int saddr = pkt->hard.source, ofs; | ||
142 | struct Incoming *in = &lp->rfc1201.incoming[saddr]; | ||
143 | |||
144 | BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", length); | ||
145 | |||
146 | if (length >= MinTU) | ||
147 | ofs = 512 - length; | ||
148 | else | ||
149 | ofs = 256 - length; | ||
150 | |||
151 | if (soft->split_flag == 0xFF) { /* Exception Packet */ | ||
152 | if (length >= 4 + RFC1201_HDR_SIZE) | ||
153 | BUGMSG(D_DURING, "compensating for exception packet\n"); | ||
154 | else { | ||
155 | BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh", | ||
156 | saddr); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | /* skip over 4-byte junkola */ | ||
161 | length -= 4; | ||
162 | ofs += 4; | ||
163 | lp->hw.copy_from_card(dev, bufnum, 512 - length, | ||
164 | soft, sizeof(pkt->soft)); | ||
165 | } | ||
166 | if (!soft->split_flag) { /* not split */ | ||
167 | BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n", | ||
168 | soft->split_flag); | ||
169 | |||
170 | if (in->skb) { /* already assembling one! */ | ||
171 | BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", | ||
172 | in->sequence, soft->split_flag, soft->sequence); | ||
173 | lp->rfc1201.aborted_seq = soft->sequence; | ||
174 | dev_kfree_skb_irq(in->skb); | ||
175 | lp->stats.rx_errors++; | ||
176 | lp->stats.rx_missed_errors++; | ||
177 | in->skb = NULL; | ||
178 | } | ||
179 | in->sequence = soft->sequence; | ||
180 | |||
181 | skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); | ||
182 | if (skb == NULL) { | ||
183 | BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); | ||
184 | lp->stats.rx_dropped++; | ||
185 | return; | ||
186 | } | ||
187 | skb_put(skb, length + ARC_HDR_SIZE); | ||
188 | skb->dev = dev; | ||
189 | |||
190 | pkt = (struct archdr *) skb->data; | ||
191 | soft = &pkt->soft.rfc1201; | ||
192 | |||
193 | /* up to sizeof(pkt->soft) has already been copied from the card */ | ||
194 | memcpy(pkt, pkthdr, sizeof(struct archdr)); | ||
195 | if (length > sizeof(pkt->soft)) | ||
196 | lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), | ||
197 | pkt->soft.raw + sizeof(pkt->soft), | ||
198 | length - sizeof(pkt->soft)); | ||
199 | |||
200 | /* | ||
201 | * ARP packets have problems when sent from some DOS systems: the | ||
202 | * source address is always 0! So we take the hardware source addr | ||
203 | * (which is impossible to fumble) and insert it ourselves. | ||
204 | */ | ||
205 | if (soft->proto == ARC_P_ARP) { | ||
206 | struct arphdr *arp = (struct arphdr *) soft->payload; | ||
207 | |||
208 | /* make sure addresses are the right length */ | ||
209 | if (arp->ar_hln == 1 && arp->ar_pln == 4) { | ||
210 | uint8_t *cptr = (uint8_t *) arp + sizeof(struct arphdr); | ||
211 | |||
212 | if (!*cptr) { /* is saddr = 00? */ | ||
213 | BUGMSG(D_EXTRA, | ||
214 | "ARP source address was 00h, set to %02Xh.\n", | ||
215 | saddr); | ||
216 | lp->stats.rx_crc_errors++; | ||
217 | *cptr = saddr; | ||
218 | } else { | ||
219 | BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n", | ||
220 | *cptr); | ||
221 | } | ||
222 | } else { | ||
223 | BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n", | ||
224 | arp->ar_hln, arp->ar_pln); | ||
225 | lp->stats.rx_errors++; | ||
226 | lp->stats.rx_crc_errors++; | ||
227 | } | ||
228 | } | ||
229 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); | ||
230 | |||
231 | skb->protocol = type_trans(skb, dev); | ||
232 | netif_rx(skb); | ||
233 | dev->last_rx = jiffies; | ||
234 | } else { /* split packet */ | ||
235 | /* | ||
236 | * NOTE: MSDOS ARP packet correction should only need to apply to | ||
237 | * unsplit packets, since ARP packets are so short. | ||
238 | * | ||
239 | * My interpretation of the RFC1201 document is that if a packet is | ||
240 | * received out of order, the entire assembly process should be | ||
241 | * aborted. | ||
242 | * | ||
243 | * The RFC also mentions "it is possible for successfully received | ||
244 | * packets to be retransmitted." As of 0.40 all previously received | ||
245 | * packets are allowed, not just the most recent one. | ||
246 | * | ||
247 | * We allow multiple assembly processes, one for each ARCnet card | ||
248 | * possible on the network. Seems rather like a waste of memory, | ||
249 | * but there's no other way to be reliable. | ||
250 | */ | ||
251 | |||
252 | BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n", | ||
253 | soft->split_flag, in->sequence); | ||
254 | |||
255 | if (in->skb && in->sequence != soft->sequence) { | ||
256 | BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", | ||
257 | saddr, in->sequence, soft->sequence, | ||
258 | soft->split_flag); | ||
259 | dev_kfree_skb_irq(in->skb); | ||
260 | in->skb = NULL; | ||
261 | lp->stats.rx_errors++; | ||
262 | lp->stats.rx_missed_errors++; | ||
263 | in->lastpacket = in->numpackets = 0; | ||
264 | } | ||
265 | if (soft->split_flag & 1) { /* first packet in split */ | ||
266 | BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n", | ||
267 | soft->split_flag); | ||
268 | if (in->skb) { /* already assembling one! */ | ||
269 | BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly " | ||
270 | "(splitflag=%d, seq=%d)\n", | ||
271 | in->sequence, soft->split_flag, | ||
272 | soft->sequence); | ||
273 | lp->stats.rx_errors++; | ||
274 | lp->stats.rx_missed_errors++; | ||
275 | dev_kfree_skb_irq(in->skb); | ||
276 | } | ||
277 | in->sequence = soft->sequence; | ||
278 | in->numpackets = ((unsigned) soft->split_flag >> 1) + 2; | ||
279 | in->lastpacket = 1; | ||
280 | |||
281 | if (in->numpackets > 16) { | ||
282 | BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", | ||
283 | soft->split_flag); | ||
284 | lp->rfc1201.aborted_seq = soft->sequence; | ||
285 | lp->stats.rx_errors++; | ||
286 | lp->stats.rx_length_errors++; | ||
287 | return; | ||
288 | } | ||
289 | in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE, | ||
290 | GFP_ATOMIC); | ||
291 | if (skb == NULL) { | ||
292 | BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n"); | ||
293 | lp->rfc1201.aborted_seq = soft->sequence; | ||
294 | lp->stats.rx_dropped++; | ||
295 | return; | ||
296 | } | ||
297 | skb->dev = dev; | ||
298 | pkt = (struct archdr *) skb->data; | ||
299 | soft = &pkt->soft.rfc1201; | ||
300 | |||
301 | memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE); | ||
302 | skb_put(skb, ARC_HDR_SIZE + RFC1201_HDR_SIZE); | ||
303 | |||
304 | soft->split_flag = 0; /* end result won't be split */ | ||
305 | } else { /* not first packet */ | ||
306 | int packetnum = ((unsigned) soft->split_flag >> 1) + 1; | ||
307 | |||
308 | /* | ||
309 | * if we're not assembling, there's no point trying to | ||
310 | * continue. | ||
311 | */ | ||
312 | if (!in->skb) { | ||
313 | if (lp->rfc1201.aborted_seq != soft->sequence) { | ||
314 | BUGMSG(D_EXTRA, "can't continue split without starting " | ||
315 | "first! (splitflag=%d, seq=%d, aborted=%d)\n", | ||
316 | soft->split_flag, soft->sequence, | ||
317 | lp->rfc1201.aborted_seq); | ||
318 | lp->stats.rx_errors++; | ||
319 | lp->stats.rx_missed_errors++; | ||
320 | } | ||
321 | return; | ||
322 | } | ||
323 | in->lastpacket++; | ||
324 | if (packetnum != in->lastpacket) { /* not the right flag! */ | ||
325 | /* harmless duplicate? ignore. */ | ||
326 | if (packetnum <= in->lastpacket - 1) { | ||
327 | BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n", | ||
328 | soft->split_flag); | ||
329 | lp->stats.rx_errors++; | ||
330 | lp->stats.rx_frame_errors++; | ||
331 | return; | ||
332 | } | ||
333 | /* "bad" duplicate, kill reassembly */ | ||
334 | BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly " | ||
335 | "(seq=%d) aborted (splitflag=%d, seq=%d)\n", | ||
336 | in->sequence, soft->split_flag, soft->sequence); | ||
337 | lp->rfc1201.aborted_seq = soft->sequence; | ||
338 | dev_kfree_skb_irq(in->skb); | ||
339 | in->skb = NULL; | ||
340 | lp->stats.rx_errors++; | ||
341 | lp->stats.rx_missed_errors++; | ||
342 | in->lastpacket = in->numpackets = 0; | ||
343 | return; | ||
344 | } | ||
345 | pkt = (struct archdr *) in->skb->data; | ||
346 | soft = &pkt->soft.rfc1201; | ||
347 | } | ||
348 | |||
349 | skb = in->skb; | ||
350 | |||
351 | lp->hw.copy_from_card(dev, bufnum, ofs + RFC1201_HDR_SIZE, | ||
352 | skb->data + skb->len, | ||
353 | length - RFC1201_HDR_SIZE); | ||
354 | skb_put(skb, length - RFC1201_HDR_SIZE); | ||
355 | |||
356 | /* are we done? */ | ||
357 | if (in->lastpacket == in->numpackets) { | ||
358 | in->skb = NULL; | ||
359 | in->lastpacket = in->numpackets = 0; | ||
360 | |||
361 | BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", | ||
362 | skb->len, pkt->hard.source); | ||
363 | BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", | ||
364 | skb->len, pkt->hard.source); | ||
365 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); | ||
366 | |||
367 | skb->protocol = type_trans(skb, dev); | ||
368 | netif_rx(skb); | ||
369 | dev->last_rx = jiffies; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | |||
375 | /* Create the ARCnet hard/soft headers for RFC1201. */ | ||
376 | static int build_header(struct sk_buff *skb, struct net_device *dev, | ||
377 | unsigned short type, uint8_t daddr) | ||
378 | { | ||
379 | struct arcnet_local *lp = dev->priv; | ||
380 | int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; | ||
381 | struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); | ||
382 | struct arc_rfc1201 *soft = &pkt->soft.rfc1201; | ||
383 | |||
384 | /* set the protocol ID according to RFC1201 */ | ||
385 | switch (type) { | ||
386 | case ETH_P_IP: | ||
387 | soft->proto = ARC_P_IP; | ||
388 | break; | ||
389 | case ETH_P_IPV6: | ||
390 | soft->proto = ARC_P_IPV6; | ||
391 | break; | ||
392 | case ETH_P_ARP: | ||
393 | soft->proto = ARC_P_ARP; | ||
394 | break; | ||
395 | case ETH_P_RARP: | ||
396 | soft->proto = ARC_P_RARP; | ||
397 | break; | ||
398 | case ETH_P_IPX: | ||
399 | case ETH_P_802_3: | ||
400 | case ETH_P_802_2: | ||
401 | soft->proto = ARC_P_IPX; | ||
402 | break; | ||
403 | case ETH_P_ATALK: | ||
404 | soft->proto = ARC_P_ATALK; | ||
405 | break; | ||
406 | default: | ||
407 | BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n", | ||
408 | type, type); | ||
409 | lp->stats.tx_errors++; | ||
410 | lp->stats.tx_aborted_errors++; | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Set the source hardware address. | ||
416 | * | ||
417 | * This is pretty pointless for most purposes, but it can help in | ||
418 | * debugging. ARCnet does not allow us to change the source address in | ||
419 | * the actual packet sent) | ||
420 | */ | ||
421 | pkt->hard.source = *dev->dev_addr; | ||
422 | |||
423 | soft->sequence = htons(lp->rfc1201.sequence++); | ||
424 | soft->split_flag = 0; /* split packets are done elsewhere */ | ||
425 | |||
426 | /* see linux/net/ethernet/eth.c to see where I got the following */ | ||
427 | |||
428 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { | ||
429 | /* | ||
430 | * FIXME: fill in the last byte of the dest ipaddr here to better | ||
431 | * comply with RFC1051 in "noarp" mode. For now, always broadcasting | ||
432 | * will probably at least get packets sent out :) | ||
433 | */ | ||
434 | pkt->hard.dest = 0; | ||
435 | return hdr_size; | ||
436 | } | ||
437 | /* otherwise, drop in the dest address */ | ||
438 | pkt->hard.dest = daddr; | ||
439 | return hdr_size; | ||
440 | } | ||
441 | |||
442 | |||
443 | static void load_pkt(struct net_device *dev, struct arc_hardware *hard, | ||
444 | struct arc_rfc1201 *soft, int softlen, int bufnum) | ||
445 | { | ||
446 | struct arcnet_local *lp = dev->priv; | ||
447 | int ofs; | ||
448 | |||
449 | /* assume length <= XMTU: someone should have handled that by now. */ | ||
450 | |||
451 | if (softlen > MinTU) { | ||
452 | hard->offset[0] = 0; | ||
453 | hard->offset[1] = ofs = 512 - softlen; | ||
454 | } else if (softlen > MTU) { /* exception packet - add an extra header */ | ||
455 | struct arc_rfc1201 excsoft; | ||
456 | |||
457 | excsoft.proto = soft->proto; | ||
458 | excsoft.split_flag = 0xff; | ||
459 | excsoft.sequence = 0xffff; | ||
460 | |||
461 | hard->offset[0] = 0; | ||
462 | ofs = 512 - softlen; | ||
463 | hard->offset[1] = ofs - RFC1201_HDR_SIZE; | ||
464 | lp->hw.copy_to_card(dev, bufnum, ofs - RFC1201_HDR_SIZE, | ||
465 | &excsoft, RFC1201_HDR_SIZE); | ||
466 | } else | ||
467 | hard->offset[0] = ofs = 256 - softlen; | ||
468 | |||
469 | lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); | ||
470 | lp->hw.copy_to_card(dev, bufnum, ofs, soft, softlen); | ||
471 | |||
472 | lp->lastload_dest = hard->dest; | ||
473 | } | ||
474 | |||
475 | |||
476 | static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, | ||
477 | int bufnum) | ||
478 | { | ||
479 | struct arcnet_local *lp = dev->priv; | ||
480 | const int maxsegsize = XMTU - RFC1201_HDR_SIZE; | ||
481 | struct Outgoing *out; | ||
482 | |||
483 | |||
484 | BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", | ||
485 | lp->next_tx, lp->cur_tx, bufnum); | ||
486 | |||
487 | length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ | ||
488 | pkt->soft.rfc1201.split_flag = 0; | ||
489 | |||
490 | /* need to do a split packet? */ | ||
491 | if (length > XMTU) { | ||
492 | out = &lp->outgoing; | ||
493 | |||
494 | out->length = length - RFC1201_HDR_SIZE; | ||
495 | out->dataleft = lp->outgoing.length; | ||
496 | out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize; | ||
497 | out->segnum = 0; | ||
498 | |||
499 | BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split " | ||
500 | "(%d bytes, seq=%d)\n", out->numsegs, out->length, | ||
501 | pkt->soft.rfc1201.sequence); | ||
502 | |||
503 | return 0; /* not done */ | ||
504 | } | ||
505 | /* just load the packet into the buffers and send it off */ | ||
506 | load_pkt(dev, &pkt->hard, &pkt->soft.rfc1201, length, bufnum); | ||
507 | |||
508 | return 1; /* done */ | ||
509 | } | ||
510 | |||
511 | |||
512 | static int continue_tx(struct net_device *dev, int bufnum) | ||
513 | { | ||
514 | struct arcnet_local *lp = dev->priv; | ||
515 | struct Outgoing *out = &lp->outgoing; | ||
516 | struct arc_hardware *hard = &out->pkt->hard; | ||
517 | struct arc_rfc1201 *soft = &out->pkt->soft.rfc1201, *newsoft; | ||
518 | int maxsegsize = XMTU - RFC1201_HDR_SIZE; | ||
519 | int seglen; | ||
520 | |||
521 | BUGMSG(D_DURING, | ||
522 | "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", | ||
523 | out->segnum, out->numsegs, soft->sequence); | ||
524 | |||
525 | /* the "new" soft header comes right before the data chunk */ | ||
526 | newsoft = (struct arc_rfc1201 *) | ||
527 | (out->pkt->soft.raw + out->length - out->dataleft); | ||
528 | |||
529 | if (!out->segnum) /* first packet; newsoft == soft */ | ||
530 | newsoft->split_flag = ((out->numsegs - 2) << 1) | 1; | ||
531 | else { | ||
532 | newsoft->split_flag = out->segnum << 1; | ||
533 | newsoft->proto = soft->proto; | ||
534 | newsoft->sequence = soft->sequence; | ||
535 | } | ||
536 | |||
537 | seglen = maxsegsize; | ||
538 | if (seglen > out->dataleft) | ||
539 | seglen = out->dataleft; | ||
540 | out->dataleft -= seglen; | ||
541 | |||
542 | load_pkt(dev, hard, newsoft, seglen + RFC1201_HDR_SIZE, bufnum); | ||
543 | |||
544 | out->segnum++; | ||
545 | if (out->segnum >= out->numsegs) | ||
546 | return 1; | ||
547 | else | ||
548 | return 0; | ||
549 | } | ||