# HG changeset patch
# Parent 44a4871708b167b49df10fc6153a73730f08287a
rathaxes: start to implement the Ethernet subsystem in linux LKM sample

diff --git a/rathaxes/samples/lkm/CMakeLists.txt b/rathaxes/samples/lkm/CMakeLists.txt
--- a/rathaxes/samples/lkm/CMakeLists.txt
+++ b/rathaxes/samples/lkm/CMakeLists.txt
@@ -1,6 +1,6 @@
 ADD_RATHAXES_SOURCES(lkm lkm.rtx
-                     RTI log.rti lkm.rti pci.rti
-                     BLT log.blt lkm.blt pci.blt)
+                     RTI log.rti lkm.rti pci.rti ethernet.rti
+                     BLT log.blt lkm.blt pci.blt ethernet.blt)
 
 # We can't name lkm since it's already used as the target name to generate the
 # source (with ADD_RATHAXES_SOURCES).
diff --git a/rathaxes/samples/lkm/ethernet.blt b/rathaxes/samples/lkm/ethernet.blt
new file mode 100644
--- /dev/null
+++ b/rathaxes/samples/lkm/ethernet.blt
@@ -0,0 +1,116 @@
+with Ethernet, PCI, LKM
+{
+    template type   Ethernet::Device()
+    {
+        chunk LKM::includes()
+        {
+            #include <linux/netdevice.h>
+            #include <linux/etherdevice.h>
+
+            typedef int include_linux_net_system_stamp;
+        }
+
+        chunk ::decl()
+        {
+            struct net_device;
+        }
+
+        chunk ::init(net_dev)
+        {
+            ${self} = ${net_dev};
+        }
+
+        map
+        {
+        }
+    }
+
+    template sequence   Ethernet::open(Ethernet::Device dev)
+    {
+        chunk LKM::prototypes()
+        {
+            static int  rtx_ethernet_open(struct net_device *);
+        }
+
+        chunk LKM::code()
+        {
+            static int  rtx_ethernet_open(struct net_device *dev)
+            {
+                ${pointcut ::IMPLEMENTATION};
+            }
+        }
+    }
+
+    template sequence   Ethernet::close(Ethernet::Device dev)
+    {
+        chunk LKM::prototypes()
+        {
+            static int  rtx_ethernet_close(struct net_device );
+        }
+
+        chunk LKM::code()
+        {
+            static int  rtx_ethernet_close(struct net_device dev)
+            {
+                ${pointcut ::IMPLEMENTATION};
+            }
+        }
+    }
+
+    template sequence   Ethernet::interrupt_handler(Ethernet::Device dev)
+    {
+        /*
+         * Why we can't use irqreturn_t here? (we are forced to use enum
+         * irqreturn, which is the real type).
+         */
+
+        chunk LKM::prototypes()
+        {
+            static enum irqreturn   rtx_ethernet_interrupt_handler(int, void *);
+        }
+
+        chunk LKM::code()
+        {
+            static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
+            {
+                ${pointcut ::IMPLEMENTATION};
+            }
+        }
+    }
+
+    template sequence   Ethernet::init(PCI::Device dev)
+    {
+        chunk LKM::data()
+        {
+            /*
+             * This typedef is needed to workaround a bug in CNorm __std__
+             * dialect.
+             */
+            typedef int ${Ethernet::Device};
+
+            static ${Ethernet::Device} *rtx_net_dev = NULL;
+        }
+
+        chunk ::CALL
+        {
+            /*
+             * int should be replaced by the sizeof an hypothetic "context"
+             * structure defined in the front-end.
+             */
+            rtx_net_dev = alloc_etherdev(sizeof(int));
+            /*
+             * if (rtx_net_dev == NULL)
+             *  {
+             *      // What can we do here?
+             *  }
+             */
+        }
+    }
+
+    template sequence   Ethernet::exit(PCI::Device dev)
+    {
+        chunk ::CALL
+        {
+        }
+    }
+}
diff --git a/rathaxes/samples/lkm/ethernet.rti b/rathaxes/samples/lkm/ethernet.rti
new file mode 100644
--- /dev/null
+++ b/rathaxes/samples/lkm/ethernet.rti
@@ -0,0 +1,33 @@
+interface Ethernet : PCI, LKM
+{
+    provided type       Ethernet::Device;
+
+    required sequence   Ethernet::open(Ethernet::Device)
+    {
+        provided chunk  LKM::prototypes;
+        provided chunk  LKM::code;
+    }
+
+    required sequence   Ethernet::close(Ethernet::Device)
+    {
+        provided chunk  LKM::prototypes;
+        provided chunk  LKM::code;
+    }
+
+    required sequence   Ethernet::interrupt_handler(Ethernet::Device)
+    {
+        provided chunk  LKM::prototypes;
+        provided chunk  LKM::code;
+    }
+
+    provided sequence   Ethernet::init(PCI::Device)
+    {
+        provided chunk  LKM::data;
+        provided chunk  ::CALL;
+    }
+
+    provided sequence   Ethernet::exit(PCI::Device)
+    {
+        provided chunk  ::CALL;
+    }
+}
diff --git a/rathaxes/samples/lkm/lkm.rtx b/rathaxes/samples/lkm/lkm.rtx
--- a/rathaxes/samples/lkm/lkm.rtx
+++ b/rathaxes/samples/lkm/lkm.rtx
@@ -1,13 +1,24 @@
 device LKM use LKM, PCI, Log
 {
+    Ethernet::open(Ethernet::Device dev)
+    {
+    }
+
+    Ethernet::close(Ethernet::Device dev)
+    {
+    }
+
+    Ethernet::interrupt_handler(Ethernet::Device dev)
+    {
+    }
+
     PCI::probe(PCI::Device dev)
     {
-
+        Ethernet::init(dev);
     }
 
     PCI::remove(PCI::Device dev)
     {
-
     }
 
     LKM::init()
diff --git a/rathaxes/samples/lkm/pci.blt b/rathaxes/samples/lkm/pci.blt
--- a/rathaxes/samples/lkm/pci.blt
+++ b/rathaxes/samples/lkm/pci.blt
@@ -11,15 +11,12 @@
 
         chunk   ::decl()
         {
-            struct  rtx_pci_device
-            {
-                struct pci_dev  *pci_dev;
-            };
+            struct pci_dev;
         }
 
         chunk   ::init(pci_dev)
         {
-            ${self}.pci_dev = pci_dev;
+            ${self} = ${pci_dev};
         }
 
         map
@@ -40,11 +37,7 @@
             static int /* __devinit */  rtx_pci_probe(struct pci_dev *pdev,
                                                       const struct pci_device_id *pdev_id)
             {
-                /* workaround for CNorm __std__ dialect, shouldn't be here */
-                typedef int ${PCI::Device};
-
                 int             err;
-                ${PCI::Device}  *dev = NULL;
 
                 err = pci_enable_device(pdev);
 //              if (err < 0) /* `if' doesn't work */
@@ -52,8 +45,6 @@
 
                 ${pointcut ::IMPLEMENTATION};
 
-                pci_set_drvdata(pdev, dev);
-
                 return 0;
 
                 fail:
