Mercurial > archived > louis > epitech > mq > rathaxes
view rathaxes_start_to_implement_the_ethernet_subsystem_in_the_lkm.patch @ 30:b4ca25b88690
Finish patches on the CMake library and on #includes
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Sat, 07 Jan 2012 21:11:13 +0100 |
parents | 65523c345b40 |
children |
line wrap: on
line source
# HG changeset patch # Parent 53c073d05449cc4cd6130bd79eb02c07239dd8d8 rathaxes: start to implement the Ethernet subsystem in linux LKM sample diff -r 53c073d05449 rathaxes/samples/lkm/CMakeLists.txt --- a/rathaxes/samples/lkm/CMakeLists.txt Sat Jan 07 19:10:21 2012 +0100 +++ b/rathaxes/samples/lkm/CMakeLists.txt Sat Jan 07 19:18:24 2012 +0100 @@ -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 -r 53c073d05449 rathaxes/samples/lkm/ethernet.blt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rathaxes/samples/lkm/ethernet.blt Sat Jan 07 19:18:24 2012 +0100 @@ -0,0 +1,173 @@ +with Ethernet, PCI, LKM, Log +{ + 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 rtx_ethernet_dev + { + /* + * I think it's useless to use the ${PCI::Device} "abstraction" + * here, since we are already in a Linux specific context here. + */ + struct pci_dev *pci_dev; + struct net_device *net_dev; + }; + } + + 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}; + + return 0; + } + } + } + + 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}; + + return 0; + } + } + } + + 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}; + + return IRQ_NONE; + } + } + } + + template sequence Ethernet::init(PCI::Device pdev) + { + chunk LKM::data() + { + static const struct net_device_ops rtx_ether_ops = + { + .ndo_open = rtx_ethernet_open, + .ndo_stop = rtx_ethernet_close, + .ndo_start_xmit = NULL, + }; + } + + chunk ::CALL + { + /* + * This typedef is needed to workaround a bug in CNorm __std__ + * dialect. + */ + typedef int ${Ethernet::Device}; + ${Ethernet::Device} *rtx_ether_ctx; + struct net_device *net_dev; + int error; + + error = 0; + net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx)); + if (net_dev == 0) + { + ${Log::info("Cannot allocate memory")}; + // is it the thing to do? + return -ENOMEM; + } + strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name)); + net_dev->irq = pdev->irq; + // Maybe we should try ${rtx_ether_ctx.init()} here: + rtx_ether_ctx = netdev_priv(net_dev); + //rtx_ether_ctx->pci_dev = ${pdev}; + rtx_ether_ctx->pci_dev = pdev; // In the meantime do it directly + rtx_ether_ctx->net_dev = net_dev; + + /* + * The substitution of ${pdev} fails here. I also tried to add a + * "substitute method" to the PCI::Device that was just doing + * "${self}" but it didn't work either (it was subsituted by a + * placeholder, e.g: _1). + * + * That's why we cheated a bit and named all the arguments pdev. + */ + //SET_NETDEV_DEV(net_dev, &${pdev}->dev); + SET_NETDEV_DEV(net_dev, &pdev->dev); + net_dev->netdev_ops = &rtx_ether_ops; + if ((error = register_netdev(net_dev))) + { + ${Log::info("Cannot register the driver")}; + // is it the thing to do? + return error; + } + + /* same problem as above with ${pdev} */ + //pci_set_drvdata(${pdev}, net_dev); + pci_set_drvdata(pdev, net_dev); + } + } + + template sequence Ethernet::exit(PCI::Device pdev) + { + chunk ::CALL + { + struct net_device *net_dev; + + net_dev = pci_get_drvdata(pdev); // should be ${pdev}, see above + unregister_netdev(net_dev); + /* + * If we had some cleanup todo with struct rtx_ether_ctx we would + * do a netdev_priv(net_dev) here and do it. + */ + free_netdev(net_dev); + } + } +} diff -r 53c073d05449 rathaxes/samples/lkm/ethernet.rti --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rathaxes/samples/lkm/ethernet.rti Sat Jan 07 19:18:24 2012 +0100 @@ -0,0 +1,37 @@ +interface Ethernet : PCI, LKM +{ + provided type Ethernet::Device; + + required variable ::string Ethernet::ifname; + + 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; + } + + /* Kinda extends PCI::probe */ + provided sequence Ethernet::init(PCI::Device) + { + provided chunk LKM::data; + provided chunk ::CALL; + } + + /* Likely extends PCI::remove */ + provided sequence Ethernet::exit(PCI::Device) + { + provided chunk ::CALL; + } +} diff -r 53c073d05449 rathaxes/samples/lkm/lkm.rtx --- a/rathaxes/samples/lkm/lkm.rtx Sat Jan 07 19:10:21 2012 +0100 +++ b/rathaxes/samples/lkm/lkm.rtx Sat Jan 07 19:18:24 2012 +0100 @@ -1,13 +1,30 @@ device LKM use LKM, PCI, Log { + Ethernet::open(Ethernet::Device dev) + { + Log::info("Open the device"); + } + + Ethernet::close(Ethernet::Device dev) + { + Log::info("Close the device"); + } + + Ethernet::interrupt_handler(Ethernet::Device dev) + { + Log::info("Got an interruption"); + } + PCI::probe(PCI::Device dev) { - + Log::info("Probe the device"); + Ethernet::init(dev); } PCI::remove(PCI::Device dev) { - + Log::info("Remove the pci device"); + Ethernet::exit(dev); } LKM::init() @@ -32,4 +49,6 @@ PCI::vendor_id = 0x8086; PCI::product_id = 0x100f; + + Ethernet::ifname = "rtx%d"; } diff -r 53c073d05449 rathaxes/samples/lkm/pci.blt --- a/rathaxes/samples/lkm/pci.blt Sat Jan 07 19:10:21 2012 +0100 +++ b/rathaxes/samples/lkm/pci.blt Sat Jan 07 19:18:24 2012 +0100 @@ -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 @@ -27,7 +24,17 @@ } } - template sequence PCI::probe(PCI::Device dev) + /* + * The PCI::probe sequence is a "required" sequence which means that its + * implementation will be done in the .rtx. Here we just define the context + * were this implementation will be inserted. The implementation should be + * able to access to the struct pci_dev (here marked as the "argument" + * PCI::Device). How do we bind this PCI::Device argument with the pdev + * struct pci_dev pointer defined in the LKM::code chunk? + * + * The only thing I can imagine is: ${pointcut ::IMPLEMENTATION(pdev)}; + */ + template sequence PCI::probe(PCI::Device pdev) { chunk LKM::prototypes() { @@ -40,11 +47,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) @@ -52,8 +55,6 @@ ${pointcut ::IMPLEMENTATION}; - pci_set_drvdata(pdev, dev); - return 0; fail: @@ -62,7 +63,7 @@ } } - template sequence PCI::remove(PCI::Device dev) + template sequence PCI::remove(PCI::Device pdev) { chunk LKM::prototypes() { @@ -73,9 +74,9 @@ { static void rtx_pci_remove(struct pci_dev *pdev) { + ${pointcut ::IMPLEMENTATION}; + pci_disable_device(pdev); - - ${pointcut ::IMPLEMENTATION}; } } } @@ -89,7 +90,7 @@ * have to specify the exact size). */ static struct pci_device_id rtx_pci_device_table[2] = { - { ${config.vendor_id}, ${config.product_id}, 0, PCI_ANY_ID, PCI_ANY_ID }, + { ${config.vendor_id}, ${config.product_id}, PCI_ANY_ID, PCI_ANY_ID }, { 0, } };