// copyright 2007 john crispin <blogic@openwrt.org>
// copyright 2007 felix fietkau <nbd@openwrt.org>
+// copyright 2009 hauke mehrtens <hauke@hauke-m.de>
// TODO
#include <linux/ethtool.h>
#include <asm/checksum.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
#include <asm/amazon/amazon.h>
#include <asm/amazon/amazon_dma.h>
int switch_init(struct net_device *dev);
void switch_tx_timeout(struct net_device *dev);
-struct net_device switch_devs[2] = {
- {init:switch_init,},
- {init:switch_init,}
-};
+static struct net_device *switch_devs[2];
int add_mac_table_entry(u64 entry_value)
{
if (line)
line = (*ep) ? ep + 1 : ep;
}
- printk("mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
+ printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
return 0;
}
static void open_rx_dma(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
int i;
#ifdef CONFIG_NET_HW_FLOWCONTROL
static void close_rx_dma(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
int i;
int switch_open(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
if (!strcmp(dev->name, "eth1")) {
priv->mdio_phy_addr = PHY0_ADDR;
}
#ifdef CONFIG_NET_HW_FLOWCONTROL
if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) {
- printk("Hardware Flow Control register fails\n");
+ printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n");
}
#endif
int switch_release(struct net_device *dev)
{
int i;
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
for (i = 0; i < dma_dev->num_tx_chan; i++)
void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
#ifdef CONFIG_NET_HW_FLOWCONTROL
int mit_sel = 0;
#endif
int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
{
- struct switch_priv *priv = dev->priv;
+ struct switch_priv *priv = netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
dma_dev->current_tx_chan = 0;
{
int len;
char *data;
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
data = skb->data;
void switch_tx_timeout(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
priv->stats.tx_errors++;
netif_wake_queue(dev);
return;
void negotiate(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
unsigned short data = get_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG);
data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
void set_duplex(struct net_device *dev, enum duplex new_duplex)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
if (new_duplex != priv->current_duplex) {
priv->current_duplex = new_duplex;
negotiate(dev);
void set_speed(struct net_device *dev, unsigned long speed)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
priv->current_speed_selection = speed;
negotiate(dev);
}
static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
struct net_device_stats *switch_stats(struct net_device *dev)
{
- struct switch_priv *priv = (struct switch_priv *) dev->priv;
+ struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
return &priv->stats;
}
len = dma_device_read(dma_dev, &buf, (void **) &skb);
if (len >= 0x600) {
- printk("packet too large %d\n", len);
+ printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len);
goto switch_hw_receive_err_exit;
}
/* remove CRC */
len -= 4;
if (skb == NULL) {
- printk("cannot restore pointer\n");
+ printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n");
goto switch_hw_receive_err_exit;
}
if (len > (skb->end - skb->tail)) {
- printk("BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
+ printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
goto switch_hw_receive_err_exit;
}
skb_put(skb, len);
{
struct net_device *dev;
- dev = switch_devs + (u32) dma_dev->priv;
+ dev = dma_dev->priv;
switch (status) {
case RCV_INT:
switch_hw_receive(dev, dma_dev);
return OK;
}
-int init_dma_device(_dma_device_info * dma_dev)
+int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
{
int i;
int num_tx_chan, num_rx_chan;
if (strcmp(dma_dev->device_name, "switch1") == 0) {
num_tx_chan = 1;
num_rx_chan = 2;
- dma_dev->priv = (void *) 0;
} else {
num_tx_chan = 1;
num_rx_chan = 2;
- dma_dev->priv = (void *) 1;
}
+ dma_dev->priv = dev;
dma_dev->weight = 1;
dma_dev->num_tx_chan = num_tx_chan;
return OK;
}
+static const struct net_device_ops amazon_mii_ops = {
+ .ndo_init = switch_init,
+ .ndo_open = switch_open,
+ .ndo_stop = switch_release,
+ .ndo_start_xmit = switch_tx,
+ .ndo_do_ioctl = switch_ioctl,
+ .ndo_get_stats = switch_stats,
+ .ndo_change_mtu = switch_change_mtu,
+ .ndo_set_mac_address = switch_set_mac_address,
+ .ndo_tx_timeout = switch_tx_timeout,
+};
int switch_init(struct net_device *dev)
{
int result;
struct switch_priv *priv;
ether_setup(dev); /* assign some of the fields */
- printk("%s up using ", dev->name);
- dev->open = switch_open;
- dev->stop = switch_release;
- dev->hard_start_xmit = switch_tx;
- dev->do_ioctl = switch_ioctl;
- dev->get_stats = switch_stats;
- dev->change_mtu = switch_change_mtu;
- dev->set_mac_address = switch_set_mac_address;
- dev->tx_timeout = switch_tx_timeout;
+ printk(KERN_INFO "amazon_mii0: %s up using ", dev->name);
dev->watchdog_timeo = timeout;
- SET_MODULE_OWNER(dev);
-
- dev->priv = kmalloc(sizeof(struct switch_priv), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct switch_priv));
- priv = dev->priv;
+ priv = netdev_priv(dev);
priv->dma_device = (struct dma_device_info *) kmalloc(sizeof(struct dma_device_info), GFP_KERNEL);
- if ((dev - switch_devs) == 0) {
+ if (priv->num == 0) {
sprintf(priv->dma_device->device_name, "switch1");
- } else if ((dev - switch_devs) == 1) {
+ } else if (priv->num == 1) {
sprintf(priv->dma_device->device_name, "switch2");
}
printk("\"%s\"\n", priv->dma_device->device_name);
- init_dma_device(priv->dma_device);
+ init_dma_device(priv->dma_device, dev);
result = dma_device_register(priv->dma_device);
/* read the mac address from the mac table and put them into the mac table. */
dev->dev_addr[2] = 0xda;
dev->dev_addr[3] = 0x86;
dev->dev_addr[4] = 0x23;
- dev->dev_addr[5] = 0x74 + (unsigned char) (dev - switch_devs);
+ dev->dev_addr[5] = 0x74 + (unsigned char) priv->num;
} else {
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = my_ethaddr[i];
}
- dev->dev_addr[5] += +(unsigned char) (dev - switch_devs);
+ dev->dev_addr[5] += +(unsigned char) priv->num;
}
return OK;
}
-int switch_init_module(void)
+static int amazon_mii_probe(struct platform_device *dev)
{
int i = 0, result, device_present = 0;
+ struct switch_priv *priv;
for (i = 0; i < AMAZON_SW_INT_NO; i++) {
- sprintf(switch_devs[i].name, "eth%d", i);
-
- if ((result = register_netdev(switch_devs + i)))
- printk("error %i registering device \"%s\"\n", result, switch_devs[i].name);
+ switch_devs[i] = alloc_etherdev(sizeof(struct switch_priv));
+ switch_devs[i]->netdev_ops = &amazon_mii_ops;
+ strcpy(switch_devs[i]->name, "eth%d");
+ priv = (struct switch_priv *) netdev_priv(switch_devs[i]);
+ priv->num = i;
+ if ((result = register_netdev(switch_devs[i])))
+ printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name);
else
device_present++;
}
return device_present ? 0 : -ENODEV;
}
-void switch_cleanup(void)
+static int amazon_mii_remove(struct platform_device *dev)
{
int i;
struct switch_priv *priv;
for (i = 0; i < AMAZON_SW_INT_NO; i++) {
- priv = switch_devs[i].priv;
+ priv = netdev_priv(switch_devs[i]);
if (priv->dma_device) {
dma_device_unregister(priv->dma_device);
kfree(priv->dma_device);
}
- kfree(switch_devs[i].priv);
- unregister_netdev(switch_devs + i);
+ kfree(netdev_priv(switch_devs[i]));
+ unregister_netdev(switch_devs[i]);
}
- return;
+ return 0;
+}
+
+static struct platform_driver amazon_mii_driver = {
+ .probe = amazon_mii_probe,
+ .remove = amazon_mii_remove,
+ .driver = {
+ .name = "amazon_mii0",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init amazon_mii_init(void)
+{
+ int ret = platform_driver_register(&amazon_mii_driver);
+ if (ret)
+ printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n");
+ return ret;
}
-module_init(switch_init_module);
-module_exit(switch_cleanup);
+static void __exit amazon_mii_cleanup(void)
+{
+ platform_driver_unregister(&amazon_mii_driver);
+}
+
+module_init(amazon_mii_init);
+module_exit(amazon_mii_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wu Qi Ming");
+MODULE_DESCRIPTION("ethernet driver for AMAZON boards");
+