--- a/devices/generic.c Tue Oct 13 17:56:32 2009 +0200
+++ b/devices/generic.c Thu Oct 15 17:38:53 2009 +0200
@@ -45,6 +45,8 @@
#define PFX "ec_generic: "
+#define ETH_P_ETHERCAT 0x88A4
+
/*****************************************************************************/
int __init ec_gen_init_module(void);
@@ -66,9 +68,7 @@
typedef struct {
struct list_head list;
struct net_device *netdev;
-#if 0
- struct net_device *real_netdev;
-#endif
+ struct socket *socket;
ec_device_t *ecdev;
} ec_gen_device_t;
@@ -130,9 +130,7 @@
char null = 0x00;
dev->ecdev = NULL;
-#if 0
- dev->real_netdev = real_netdev;
-#endif
+ dev->socket = NULL;
dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
if (!dev->netdev) {
@@ -158,25 +156,69 @@
ecdev_close(dev->ecdev);
ecdev_withdraw(dev->ecdev);
}
+ if (dev->socket) {
+ sock_release(dev->socket);
+ }
free_netdev(dev->netdev);
}
/*****************************************************************************/
+/** Creates a network socket.
+ */
+int ec_gen_device_create_socket(
+ ec_gen_device_t *dev,
+ struct net_device *real_netdev
+ )
+{
+ int ret;
+ struct sockaddr_ll sa;
+
+ ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT), &dev->socket);
+ if (ret) {
+ printk(KERN_ERR PFX "Failed to create socket.\n");
+ return ret;
+ }
+
+ printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n",
+ real_netdev->ifindex, real_netdev->name);
+
+ memset(&sa, 0x00, sizeof(sa));
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = htons(ETH_P_ETHERCAT);
+ sa.sll_ifindex = real_netdev->ifindex;
+ ret = kernel_bind(dev->socket, (struct sockaddr *) &sa, sizeof(sa));
+ if (ret) {
+ printk(KERN_ERR PFX "Failed to bind() socket to interface.\n");
+ sock_release(dev->socket);
+ dev->socket = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
/** Offer generic device to master.
*/
int ec_gen_device_offer(
- ec_gen_device_t *dev
+ ec_gen_device_t *dev,
+ struct net_device *real_netdev
)
{
int ret = 0;
dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE);
if (dev->ecdev) {
- if (ecdev_open(dev->ecdev)) {
+ if (ec_gen_device_create_socket(dev, real_netdev)) {
+ ecdev_withdraw(dev->ecdev);
+ dev->ecdev = NULL;
+ } else if (ecdev_open(dev->ecdev)) {
ecdev_withdraw(dev->ecdev);
dev->ecdev = NULL;
} else {
+ ecdev_set_link(dev->ecdev, 1); // FIXME
ret = 1;
}
}
@@ -192,17 +234,7 @@
ec_gen_device_t *dev
)
{
- int ret = 0;
-
-#if 0
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
- ret = dev->real_netdev->netdev_ops->ndo_open(dev->real_netdev);
-#else
- ret = dev->real_netdev->open(dev->real_netdev);
-#endif
-#endif
-
- return ret;
+ return 0;
}
/*****************************************************************************/
@@ -213,17 +245,7 @@
ec_gen_device_t *dev
)
{
- int ret = 0;
-
-#if 0
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
- ret = dev->real_netdev->netdev_ops->ndo_stop(dev->real_netdev);
-#else
- ret = dev->real_netdev->stop(dev->real_netdev);
-#endif
-#endif
-
- return ret;
+ return 0;
}
/*****************************************************************************/
@@ -233,7 +255,18 @@
struct sk_buff *skb
)
{
- return 0;
+ struct msghdr msg;
+ struct kvec iov;
+ size_t len = skb->len;
+ int ret;
+
+ iov.iov_base = skb->data;
+ iov.iov_len = len;
+ memset(&msg, 0, sizeof(msg));
+
+ ret = kernel_sendmsg(dev->socket, &msg, &iov, 1, len);
+
+ return ret == len ? NETDEV_TX_OK : NETDEV_TX_BUSY;
}
/*****************************************************************************/
@@ -258,7 +291,7 @@
return ret;
}
- if (ec_gen_device_offer(gendev)) {
+ if (ec_gen_device_offer(gendev, netdev)) {
list_add_tail(&gendev->list, &generic_devices);
} else {
ec_gen_device_clear(gendev);