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