]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/mipsnet.c
Merge Paulus' tree
[karo-tx-linux.git] / drivers / net / mipsnet.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  */
6
7 #define DEBUG
8
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/netdevice.h>
13 #include <linux/sched.h>
14 #include <linux/etherdevice.h>
15 #include <linux/netdevice.h>
16 #include <linux/platform_device.h>
17 #include <asm/io.h>
18 #include <asm/mips-boards/simint.h>
19
20 #include "mipsnet.h"            /* actual device IO mapping */
21
22 #define MIPSNET_VERSION "2005-06-20"
23
24 #define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
25
26 struct mipsnet_priv {
27         struct net_device_stats stats;
28 };
29
30 static struct platform_device *mips_plat_dev;
31
32 static char mipsnet_string[] = "mipsnet";
33
34 /*
35  * Copy data from the MIPSNET rx data port
36  */
37 static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
38                         int len)
39 {
40         uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
41         if (available_len < len)
42                 return -EFAULT;
43
44         for (; len > 0; len--, kdata++) {
45                 *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
46         }
47
48         return inl(mipsnet_reg_address(dev, rxDataCount));
49 }
50
51 static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
52         struct sk_buff *skb)
53 {
54         int count_to_go = skb->len;
55         char *buf_ptr = skb->data;
56         struct mipsnet_priv *mp = netdev_priv(dev);
57
58         pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
59                  dev->name, __FUNCTION__, skb->len);
60
61         outl(skb->len, mipsnet_reg_address(dev, txDataCount));
62
63         pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
64                  dev->name, __FUNCTION__, skb->len);
65
66         for (; count_to_go; buf_ptr++, count_to_go--) {
67                 outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
68         }
69
70         mp->stats.tx_packets++;
71         mp->stats.tx_bytes += skb->len;
72
73         return skb->len;
74 }
75
76 static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
77 {
78         pr_debug("%s:%s(): transmitting %d bytes\n",
79                  dev->name, __FUNCTION__, skb->len);
80
81         /* Only one packet at a time. Once TXDONE interrupt is serviced, the
82          * queue will be restarted.
83          */
84         netif_stop_queue(dev);
85         mipsnet_put_todevice(dev, skb);
86
87         return 0;
88 }
89
90 static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
91 {
92         struct sk_buff *skb;
93         size_t len = count;
94         struct mipsnet_priv *mp = netdev_priv(dev);
95
96         if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
97                 mp->stats.rx_dropped++;
98                 return -ENOMEM;
99         }
100
101         skb_reserve(skb, 2);
102         if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
103                 return -EFAULT;
104
105         skb->dev = dev;
106         skb->protocol = eth_type_trans(skb, dev);
107         skb->ip_summed = CHECKSUM_UNNECESSARY;
108
109         pr_debug("%s:%s(): pushing RXed data to kernel\n",
110                  dev->name, __FUNCTION__);
111         netif_rx(skb);
112
113         mp->stats.rx_packets++;
114         mp->stats.rx_bytes += len;
115
116         return count;
117 }
118
119 static irqreturn_t
120 mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
121 {
122         struct net_device *dev = dev_id;
123
124         irqreturn_t retval = IRQ_NONE;
125         uint64_t interruptFlags;
126
127         if (irq == dev->irq) {
128                 pr_debug("%s:%s(): irq %d for device\n",
129                          dev->name, __FUNCTION__, irq);
130
131                 retval = IRQ_HANDLED;
132
133                 interruptFlags =
134                     inl(mipsnet_reg_address(dev, interruptControl));
135                 pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
136                          __FUNCTION__, interruptFlags);
137
138                 if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
139                         pr_debug("%s:%s(): got TXDone\n",
140                                  dev->name, __FUNCTION__);
141                         outl(MIPSNET_INTCTL_TXDONE,
142                              mipsnet_reg_address(dev, interruptControl));
143                         // only one packet at a time, we are done.
144                         netif_wake_queue(dev);
145                 } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
146                         pr_debug("%s:%s(): got RX data\n",
147                                  dev->name, __FUNCTION__);
148                         mipsnet_get_fromdev(dev,
149                                     inl(mipsnet_reg_address(dev, rxDataCount)));
150                         pr_debug("%s:%s(): clearing RX int\n",
151                                  dev->name, __FUNCTION__);
152                         outl(MIPSNET_INTCTL_RXDONE,
153                              mipsnet_reg_address(dev, interruptControl));
154
155                 } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
156                         pr_debug("%s:%s(): got test interrupt\n",
157                                  dev->name, __FUNCTION__);
158                         // TESTBIT is cleared on read.
159                         //    And takes effect after a write with 0
160                         outl(0, mipsnet_reg_address(dev, interruptControl));
161                 } else {
162                         pr_debug("%s:%s(): no valid fags 0x%016llx\n",
163                                  dev->name, __FUNCTION__, interruptFlags);
164                         // Maybe shared IRQ, just ignore, no clearing.
165                         retval = IRQ_NONE;
166                 }
167
168         } else {
169                 printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
170                        dev->name, __FUNCTION__, irq);
171                 retval = IRQ_NONE;
172         }
173         return retval;
174 }                               //mipsnet_interrupt()
175
176 static int mipsnet_open(struct net_device *dev)
177 {
178         int err;
179         pr_debug("%s: mipsnet_open\n", dev->name);
180
181         err = request_irq(dev->irq, &mipsnet_interrupt,
182                           SA_SHIRQ, dev->name, (void *) dev);
183
184         if (err) {
185                 pr_debug("%s: %s(): can't get irq %d\n",
186                          dev->name, __FUNCTION__, dev->irq);
187                 release_region(dev->base_addr, MIPSNET_IO_EXTENT);
188                 return err;
189         }
190
191         pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
192                  dev->name, __FUNCTION__, dev->base_addr, dev->irq);
193
194
195         netif_start_queue(dev);
196
197         // test interrupt handler
198         outl(MIPSNET_INTCTL_TESTBIT,
199              mipsnet_reg_address(dev, interruptControl));
200
201
202         return 0;
203 }
204
205 static int mipsnet_close(struct net_device *dev)
206 {
207         pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
208         netif_stop_queue(dev);
209         return 0;
210 }
211
212 static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
213 {
214         struct mipsnet_priv *mp = netdev_priv(dev);
215
216         return &mp->stats;
217 }
218
219 static void mipsnet_set_mclist(struct net_device *dev)
220 {
221         // we don't do anything
222         return;
223 }
224
225 static int __init mipsnet_probe(struct device *dev)
226 {
227         struct net_device *netdev;
228         int err;
229
230         netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
231         if (!netdev) {
232                 err = -ENOMEM;
233                 goto out;
234         }
235
236         dev_set_drvdata(dev, netdev);
237
238         netdev->open                    = mipsnet_open;
239         netdev->stop                    = mipsnet_close;
240         netdev->hard_start_xmit         = mipsnet_xmit;
241         netdev->get_stats               = mipsnet_get_stats;
242         netdev->set_multicast_list      = mipsnet_set_mclist;
243
244         /*
245          * TODO: probe for these or load them from PARAM
246          */
247         netdev->base_addr = 0x4200;
248         netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
249                       inl(mipsnet_reg_address(netdev, interruptInfo));
250
251         // Get the io region now, get irq on open()
252         if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
253                 pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
254                          "for dev is not availble.\n", netdev->name,
255                          __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
256                 err = -EBUSY;
257                 goto out_free_netdev;
258         }
259
260         /*
261          * Lacking any better mechanism to allocate a MAC address we use a
262          * random one ...
263          */
264         random_ether_addr(netdev->dev_addr);
265
266         err = register_netdev(netdev);
267         if (err) {
268                 printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
269                 goto out_free_region;
270         }
271
272         return 0;
273
274 out_free_region:
275         release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
276
277 out_free_netdev:
278         free_netdev(netdev);
279
280 out:
281         return err;
282 }
283
284 static int __devexit mipsnet_device_remove(struct device *device)
285 {
286         struct net_device *dev = dev_get_drvdata(device);
287
288         unregister_netdev(dev);
289         release_region(dev->base_addr, MIPSNET_IO_EXTENT);
290         free_netdev(dev);
291         dev_set_drvdata(device, NULL);
292
293         return 0;
294 }
295
296 static struct device_driver mipsnet_driver = {
297         .name   = mipsnet_string,
298         .bus    = &platform_bus_type,
299         .probe  = mipsnet_probe,
300         .remove = __devexit_p(mipsnet_device_remove),
301 };
302
303 static void mipsnet_platform_release(struct device *device)
304 {
305         struct platform_device *pldev;
306
307         /* free device */
308         pldev = to_platform_device(device);
309         kfree(pldev);
310 }
311
312 static int __init mipsnet_init_module(void)
313 {
314         struct platform_device *pldev;
315         int err;
316
317         printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
318                "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
319
320         if (driver_register(&mipsnet_driver)) {
321                 printk(KERN_ERR "Driver registration failed\n");
322                 err = -ENODEV;
323                 goto out;
324         }
325
326         if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
327                 err = -ENOMEM;
328                 goto out_unregister_driver;
329         }
330
331         memset (pldev, 0, sizeof (*pldev));
332         pldev->name             = mipsnet_string;
333         pldev->id               = 0;
334         pldev->dev.release      = mipsnet_platform_release;
335
336         if (platform_device_register(pldev)) {
337                 err = -ENODEV;
338                 goto out_free_pldev;
339         }
340
341         if (!pldev->dev.driver) {
342                 /*
343                  * The driver was not bound to this device, there was
344                  * no hardware at this address. Unregister it, as the
345                  * release fuction will take care of freeing the
346                  * allocated structure
347                  */
348                 platform_device_unregister (pldev);
349         }
350
351         mips_plat_dev           = pldev;
352
353         return 0;
354
355 out_free_pldev:
356         kfree(pldev);
357
358 out_unregister_driver:
359         driver_unregister(&mipsnet_driver);
360 out:
361         return err;
362 }
363
364 static void __exit mipsnet_exit_module(void)
365 {
366         pr_debug("MIPSNet Ethernet driver exiting\n");
367
368         driver_unregister(&mipsnet_driver);
369 }
370
371 module_init(mipsnet_init_module);
372 module_exit(mipsnet_exit_module);