Mercurial > archived > louis > epitech > mq > rathaxes
diff rathaxes_add_lkm_ethernet_sample.patch @ 38:f43900ad7e66
Fold All The Patches on the LKM Sample
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Sun, 08 Jan 2012 01:51:34 +0100 |
parents | rathaxes_add_a_linux_lkm.patch@44a25ffd5c8c |
children | d761c8c625d3 |
line wrap: on
line diff
--- a/rathaxes_add_lkm_ethernet_sample.patch Sun Jan 08 01:45:20 2012 +0100 +++ b/rathaxes_add_lkm_ethernet_sample.patch Sun Jan 08 01:51:34 2012 +0100 @@ -1,40 +1,120 @@ # HG changeset patch -# Parent a109185dcd773ae92b98a8195b7cc91f1c1cee47 +# Parent b995d8934956b83383c144303178f3eb383d0acf rathaxes: add the PCI/Ethernet part of a Linux Intel e1000 network card driver +diff --git a/rathaxes/samples/CMakeLists.txt b/rathaxes/samples/CMakeLists.txt +--- a/rathaxes/samples/CMakeLists.txt ++++ b/rathaxes/samples/CMakeLists.txt +@@ -1,2 +1,3 @@ + ADD_SUBDIRECTORY(helloworld) ++ADD_SUBDIRECTORY(lkm) + ADD_SUBDIRECTORY(syntax) +diff --git a/rathaxes/samples/lkm/CMakeLists.txt b/rathaxes/samples/lkm/CMakeLists.txt +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/CMakeLists.txt +@@ -0,0 +1,7 @@ ++ADD_RATHAXES_SOURCES(lkm lkm.rtx ++ RTI log.rti lkm.rti pci.rti socket.rti ethernet.rti e1000.rti ++ BLT log.blt lkm.blt pci.blt socket.blt ethernet.blt e1000.blt) ++ ++# We can't name lkm since it's already used as the target name to generate the ++# source (with ADD_RATHAXES_SOURCES). ++ADD_RATHAXES_LKM(lkm_hello lkm) diff --git a/rathaxes/samples/lkm/e1000.blt b/rathaxes/samples/lkm/e1000.blt ---- a/rathaxes/samples/lkm/e1000.blt +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/e1000.blt -@@ -5,7 +5,7 @@ - chunk LKM::includes() - { - /* -- * Force the generation of the structure in the "headers part, we +@@ -0,0 +1,80 @@ ++with e1000, Ethernet, Socket, PCI, LKM, Log ++{ ++ template type e1000::Context() ++ { ++ chunk LKM::includes() ++ { ++ /* + * Force the generation of the structure in the "headers" part, we - * have to do this since we do not use the structure in this blt - * (we hacked a bit and used it in ethernet.blt directly). - */ -@@ -64,8 +64,10 @@ - { - chunk Ethernet::destroy_device - { -- // XXX: add a check in order to avoid freeing none allocated -- // resources. ++ * have to do this since we do not use the structure in this blt ++ * (we hacked a bit and used it in ethernet.blt directly). ++ */ ++ typedef int ${e1000::Context}; /* CNorm __std__ workaround */ ++ ${e1000::Context} force_declaration_in_includes; ++ } ++ ++ chunk ::decl() ++ { ++ struct rtx_e1000_ctx ++ { ++ int bars; ++ unsigned char /* __iomem */ *ioaddr; ++ }; ++ } ++ ++ map ++ { ++ } ++ } ++ ++ template sequence e1000::create_device() ++ { ++ chunk Ethernet::create_device() ++ { ++ rtx_ether_ctx->hw_ctx.bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ if (pci_enable_device_mem(pdev)) ++ { ++ ${Log::info("e1000::create: pci_enable_device_mem failed")}; ++ } ++ ++ if (pci_request_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars, ${config.name})) ++ { ++ ${Log::info("e1000::create: pci_request_selected_regions failed")}; ++ } ++ ++ if (${config.set_master}) ++ { ++ pci_set_master(pdev); ++ } ++ ++ /* 0 here is for BAR_0: */ ++ rtx_ether_ctx->hw_ctx.ioaddr = pci_ioremap_bar(pdev, 0); ++ if (!rtx_ether_ctx->hw_ctx.ioaddr) ++ { ++ ${Log::info("e1000::create: pci_ioremap_bar failed")}; ++ } ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++ ++ template sequence e1000::destroy_device() ++ { ++ chunk Ethernet::destroy_device ++ { + /* + * Here, we should have some checks to avoid to free resources that + * haven't been allocated. (e.g: in case of previous errors). + */ - struct rtx_ethernet_dev* rtx_ether_ctx = netdev_priv(net_dev); - iounmap(rtx_ether_ctx->hw_ctx.ioaddr); - pci_release_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars); ++ struct rtx_ethernet_dev* rtx_ether_ctx = netdev_priv(net_dev); ++ iounmap(rtx_ether_ctx->hw_ctx.ioaddr); ++ pci_release_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars); ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++} diff --git a/rathaxes/samples/lkm/e1000.rti b/rathaxes/samples/lkm/e1000.rti ---- a/rathaxes/samples/lkm/e1000.rti +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/e1000.rti -@@ -2,7 +2,14 @@ - { - provided type e1000::Context; - -- /* Not sure if we need the argument */ +@@ -0,0 +1,24 @@ ++interface e1000 : Socket, Ethernet, PCI, LKM ++{ ++ provided type e1000::Context; ++ + /* + * This sequence should receive an argument like Ethernet::Device, but it is + * unclear about how this argument should be bound to a variable/argument in @@ -43,138 +123,561 @@ + * Here again, we rely on the fact that *we* wrote the parent context and + * named the C variables we need/use with the same name everywhere. + */ - provided sequence e1000::create_device() - { - provided chunk Ethernet::create_device; ++ provided sequence e1000::create_device() ++ { ++ provided chunk Ethernet::create_device; ++ provided chunk ::CALL; ++ } ++ ++ provided sequence e1000::destroy_device() ++ { ++ provided chunk Ethernet::destroy_device; ++ provided chunk ::CALL; ++ } ++} diff --git a/rathaxes/samples/lkm/ethernet.blt b/rathaxes/samples/lkm/ethernet.blt ---- a/rathaxes/samples/lkm/ethernet.blt +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/ethernet.blt -@@ -6,8 +6,6 @@ - { - #include <linux/netdevice.h> - #include <linux/etherdevice.h> -- -- typedef int include_linux_net_system_stamp; - } - - chunk ::decl() -@@ -93,10 +91,9 @@ - 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). +@@ -0,0 +1,207 @@ ++with Ethernet, PCI, LKM, Log ++{ ++ template type Ethernet::Device() ++ { ++ chunk LKM::includes() ++ { ++ #include <linux/netdevice.h> ++ #include <linux/etherdevice.h> ++ } ++ ++ 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; ++ ++ /* while waiting on issue #8 */ ++ struct rtx_e1000_ctx hw_ctx; ++ }; ++ } ++ ++ 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::send(Ethernet::Device dev, Socket::SKBuff skb) ++ { ++ chunk LKM::prototypes() ++ { ++ static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev); ++ } ++ ++ chunk LKM::code() ++ { ++ static int rtx_ethernet_xmit(struct sk_buff* skb, 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) ++ { ++ /* + * We can't use the irqreturn_t type here because CNornm doesn't know + * it. - */ -- - chunk LKM::prototypes() - { - static enum irqreturn rtx_ethernet_interrupt_handler(int, void *); -@@ -141,7 +138,12 @@ - if (net_dev == 0) - { - ${Log::info("Cannot allocate memory")}; -- // is it the thing to do? ++ */ ++ 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 = rtx_ethernet_xmit, ++ }; ++ } ++ ++ chunk PCI::pci_probe_hook() ++ { ++ /* ++ * 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")}; + /* + * Again, the error should be "raised" in the parent context. + * + * Here we know that we should return ENOMEM because *we* wrote + * the parent context. + */ - return -ENOMEM; - } - strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name)); -@@ -166,13 +168,13 @@ - 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); ++ 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")}; ++ return error; ++ } ++ ++ /* same problem as above with ${pdev} */ ++ //pci_set_drvdata(${pdev}, net_dev); ++ pci_set_drvdata(pdev, net_dev); + - ${pointcut Ethernet::create_device}; - } - ++ ${pointcut Ethernet::create_device}; ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++ ++ template sequence Ethernet::exit(PCI::Device pdev) ++ { ++ chunk PCI::pci_remove_hook() ++ { ++ struct net_device *net_dev = pci_get_drvdata(pdev); ++ ++ ${pointcut Ethernet::destroy_device}; ++ ++ 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); ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++} ++ diff --git a/rathaxes/samples/lkm/ethernet.rti b/rathaxes/samples/lkm/ethernet.rti ---- a/rathaxes/samples/lkm/ethernet.rti +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/ethernet.rti -@@ -37,7 +37,6 @@ - provided pointcut Ethernet::create_device; - } - -- /* Likely extends PCI::remove */ - provided sequence Ethernet::exit(PCI::Device) - { - provided chunk ::CALL; +@@ -0,0 +1,47 @@ ++interface Ethernet : Socket, 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::send(Ethernet::Device dev, Socket::SKBuff skb) ++ { ++ 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 PCI::pci_probe_hook; ++ provided chunk ::CALL; ++ ++ provided pointcut Ethernet::create_device; ++ } ++ ++ provided sequence Ethernet::exit(PCI::Device) ++ { ++ provided chunk ::CALL; ++ provided chunk PCI::pci_remove_hook; ++ ++ provided pointcut Ethernet::destroy_device; ++ } ++} diff --git a/rathaxes/samples/lkm/lkm.blt b/rathaxes/samples/lkm/lkm.blt ---- a/rathaxes/samples/lkm/lkm.blt +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/lkm.blt -@@ -12,9 +12,6 @@ - { - #include <linux/module.h> - #include <linux/kernel.h> -- -- typedef int include_linux_module_stamp; -- typedef int include_linux_kernel_stamp; - } - - chunk LKM::data() +@@ -0,0 +1,55 @@ ++with LKM ++{ ++ /* Skel of the generated C file: */ ++ ${pointcut LKM::includes}; ++ ${pointcut LKM::prototypes}; ++ ${pointcut LKM::data}; ++ ${pointcut LKM::code}; ++ ++ template sequence LKM::init() ++ { ++ chunk LKM::includes() ++ { ++ #include <linux/module.h> ++ #include <linux/kernel.h> ++ } ++ ++ chunk LKM::data() ++ { ++ MODULE_DESCRIPTION(${config.description}); ++ MODULE_AUTHOR(${config.author}); ++ MODULE_LICENSE(${config.license}); ++ } ++ ++ chunk LKM::code() ++ { ++ /* ++ * Rathaxes doesn't yet support arbitrary "decorators" like __init ++ * or __exit. ++ */ ++ static int __attribute__((__section__(".init.text"))) rtx_module_init(void) ++ { ++ ${pointcut ::IMPLEMENTATION}; ++ ${pointcut LKM::init_bus_hook}; ++ ++ return 0; ++ } ++ ++ module_init(rtx_module_init); ++ } ++ } ++ ++ template sequence LKM::exit() ++ { ++ chunk LKM::code() ++ { ++ static void __attribute__((__section__(".exit.text"))) rtx_module_exit(void) ++ { ++ ${pointcut ::IMPLEMENTATION}; ++ ${pointcut LKM::deinit_bus_hook}; ++ } ++ ++ module_exit(rtx_module_exit); ++ } ++ } ++} +diff --git a/rathaxes/samples/lkm/lkm.rti b/rathaxes/samples/lkm/lkm.rti +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/lkm.rti +@@ -0,0 +1,25 @@ ++interface LKM ++{ ++ provided pointcut LKM::includes; ++ /* maybe it should be possible to use chunk ::decl in sequence templates? */ ++ provided pointcut LKM::prototypes; ++ provided pointcut LKM::data; ++ provided pointcut LKM::code; ++ ++ required variable ::string LKM::author; ++ required variable ::string LKM::description; ++ required variable ::string LKM::license; ++ ++ required sequence LKM::init() ++ { ++ provided chunk LKM::includes; ++ provided chunk LKM::code; ++ provided pointcut LKM::init_bus_hook; ++ } ++ ++ required sequence LKM::exit() ++ { ++ provided chunk LKM::code; ++ provided pointcut LKM::deinit_bus_hook; ++ } ++} diff --git a/rathaxes/samples/lkm/lkm.rtx b/rathaxes/samples/lkm/lkm.rtx ---- a/rathaxes/samples/lkm/lkm.rtx +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/lkm.rtx -@@ -1,4 +1,4 @@ --device LKM use LKM, PCI, Log +@@ -0,0 +1,46 @@ +device LKM use LKM, PCI, Ethernet, Log - { - Ethernet::open(Ethernet::Device dev) - { ++{ ++ 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"); ++ } ++ ++ Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) ++ { ++ Log::info("We have one packet to transmit!"); ++ } ++ ++ LKM::init() ++ { ++ Log::info("Hello this is LKM"); ++ } ++ ++ LKM::exit() ++ { ++ Log::info("Good bye this was LKM"); ++ } ++} ++ ++configuration ++{ ++ LKM::name = "hello"; ++ LKM::author = "Rathaxes"; ++ LKM::description = "Hello World Loadable Kernel Module (LKM)"; ++ LKM::license = "GPL"; ++ ++ PCI::vendor_id = 0x8086; ++ PCI::product_id = 0x100f; ++ PCI::set_master = true; ++ ++ Ethernet::ifname = "rtx%d"; ++} +diff --git a/rathaxes/samples/lkm/log.blt b/rathaxes/samples/lkm/log.blt +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/log.blt +@@ -0,0 +1,10 @@ ++with Log ++{ ++ template sequence Log::info(::string msg) ++ { ++ chunk ::CALL ++ { ++ pr_info("%s\n", ${msg}); ++ } ++ } ++} +diff --git a/rathaxes/samples/lkm/log.rti b/rathaxes/samples/lkm/log.rti +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/log.rti +@@ -0,0 +1,7 @@ ++interface Log ++{ ++ provided sequence Log::info(::string) ++ { ++ provided chunk ::CALL; ++ } ++} diff --git a/rathaxes/samples/lkm/pci.blt b/rathaxes/samples/lkm/pci.blt ---- a/rathaxes/samples/lkm/pci.blt +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/pci.blt -@@ -5,8 +5,6 @@ - chunk LKM::includes() - { - #include <linux/pci.h> -- -- typedef int include_linux_pci_stamp; - } - - chunk ::decl() -@@ -24,16 +22,6 @@ - } - } - -- /* -- * 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() -@@ -112,22 +100,32 @@ - - chunk LKM::init_bus_hook() - { -- /* -- * So how do we use the return value in the parent context? -- */ - int error; - if ((error = pci_register_driver(&rtx_pci_driver))) - { - ${Log::info("Cannot register pci driver")}; -- // should we return here. -- // error managmement procedure has to be determined ASAP. +@@ -0,0 +1,143 @@ ++with PCI, LKM, Log ++{ ++ template type PCI::Device() ++ { ++ chunk LKM::includes() ++ { ++ #include <linux/pci.h> ++ } ++ ++ chunk ::decl() ++ { ++ struct pci_dev; ++ } ++ ++ chunk ::init(pci_dev) ++ { ++ ${self} = ${pci_dev}; ++ } ++ ++ map ++ { ++ } ++ } ++ ++ template sequence PCI::probe(PCI::Device pdev) ++ { ++ chunk LKM::prototypes() ++ { ++ static int /* __devinit */ rtx_pci_probe(struct pci_dev *, ++ const struct pci_device_id *); ++ } ++ ++ chunk LKM::code() ++ { ++ static int /* __devinit */ rtx_pci_probe(struct pci_dev *pdev, ++ const struct pci_device_id *pdev_id) ++ { ++ int err; ++ ++ err = pci_enable_device(pdev); ++ if (err < 0) ++ goto fail; ++ ++ ${pointcut PCI::pci_probe_hook}; ++ ++ return 0; ++ ++ fail: ++ return err; ++ } ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++ ++ template sequence PCI::remove(PCI::Device pdev) ++ { ++ chunk LKM::prototypes() ++ { ++ static void rtx_pci_remove(struct pci_dev *); ++ } ++ ++ chunk LKM::code() ++ { ++ static void rtx_pci_remove(struct pci_dev *pdev) ++ { ++ ${pointcut PCI::pci_remove_hook}; ++ ++ pci_disable_device(pdev); ++ } ++ } ++ ++ chunk ::CALL() ++ { ++ } ++ } ++ ++ template sequence PCI::register() ++ { ++ chunk LKM::data() ++ { ++ /* ++ * CNorm doesn't seem to like "dynamic" arrays (i.e: you always ++ * have to specify the exact size). ++ */ ++ static struct pci_device_id rtx_pci_device_table[2] = { ++ { ${config.vendor_id}, ${config.product_id}, PCI_ANY_ID, PCI_ANY_ID }, ++ { 0, } ++ }; ++ ++ static struct pci_driver rtx_pci_driver = { ++ .name = ${config.name}, ++ .id_table = rtx_pci_device_table, ++ .probe = rtx_pci_probe, ++ .remove = rtx_pci_remove ++ }; ++ } ++ ++ chunk LKM::init_bus_hook() ++ { ++ int error; ++ if ((error = pci_register_driver(&rtx_pci_driver))) ++ { ++ ${Log::info("Cannot register pci driver")}; + /* + * So we catched the error but how do we return it to the + * parent context? @@ -183,13 +686,12 @@ + * a coincidence (and, in this case, *we* wrote the parent + * context). + */ - return error; - } - } - - chunk ::CALL() - { -- // no implementation, we just need to instrument the lkm::bus_hook ++ return error; ++ } ++ } ++ ++ chunk ::CALL() ++ { + /* + * The implementation of ::CALL is empty. This template sequence is + * actually not provided nor required. @@ -198,21 +700,100 @@ + * itself in the hook LKM::init_bus_hook for which this sequence + * has a chunk (see above chunk). + */ - } - } - ++ } ++ } ++ ++ template sequence PCI::unregister() ++ { ++ chunk LKM::deinit_bus_hook() ++ { ++ pci_unregister_driver(&rtx_pci_driver); ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++} diff --git a/rathaxes/samples/lkm/pci.rti b/rathaxes/samples/lkm/pci.rti ---- a/rathaxes/samples/lkm/pci.rti +new file mode 100644 +--- /dev/null +++ b/rathaxes/samples/lkm/pci.rti -@@ -7,11 +7,6 @@ - - provided sequence PCI::register() - { -- // it is impossible to provide a "dummy" sequence -- // which just hook itself. The PCI:register juste -- // inject its code in the module_init function -- // in order to load the pci driver. -- // Everything is done with the configuration. - provided chunk ::CALL; - provided chunk LKM::data; - provided chunk LKM::init_bus_hook; +@@ -0,0 +1,36 @@ ++interface PCI : LKM ++{ ++ provided type PCI::Device; ++ ++ required variable ::number PCI::vendor_id; ++ required variable ::number PCI::product_id; ++ ++ provided sequence PCI::register() ++ { ++ provided chunk ::CALL; ++ provided chunk LKM::data; ++ provided chunk LKM::init_bus_hook; ++ } ++ ++ provided sequence PCI::unregister() ++ { ++ provided chunk ::CALL; ++ provided chunk LKM::deinit_bus_hook; ++ } ++ ++ provided sequence PCI::probe(PCI::Device) ++ { ++ provided chunk LKM::prototypes; ++ provided chunk LKM::code; ++ ++ provided pointcut PCI::pci_probe_hook; ++ } ++ ++ provided sequence PCI::remove(PCI::Device) ++ { ++ provided chunk LKM::prototypes; ++ provided chunk LKM::code; ++ ++ provided pointcut PCI::pci_remove_hook; ++ } ++} +diff --git a/rathaxes/samples/lkm/socket.blt b/rathaxes/samples/lkm/socket.blt +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/socket.blt +@@ -0,0 +1,27 @@ ++with Socket, LKM ++{ ++ template type Socket::SKBuff() ++ { ++ chunk LKM::includes() ++ { ++ #include <linux/skbuff.h> ++ } ++ ++ chunk ::decl() ++ { ++ struct sk_buff; ++ } ++ ++ chunk ::init() ++ { ++ } ++ ++ map ++ { ++ // some work may have to be done here in order ++ // to access to some field of the sk_buff. ++ // We should determine if all the sk_buff managment ++ // can be abstracted from the user. ++ } ++ } ++} +diff --git a/rathaxes/samples/lkm/socket.rti b/rathaxes/samples/lkm/socket.rti +new file mode 100644 +--- /dev/null ++++ b/rathaxes/samples/lkm/socket.rti +@@ -0,0 +1,4 @@ ++interface Socket : LKM ++{ ++ provided type Socket::SKBuff; ++}