Mercurial > archived > louis > epitech > mq > rathaxes
view rathaxes_start_to_implement_the_ethernet_subsystem_in_the_lkm.patch @ 16:41a434b0676b
WIP on the ethernet part of the LKM sample: set ifname + the irq in the net_device struct
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Sat, 07 Jan 2012 11:22:10 +0100 |
parents | 74d9d18d4732 |
children | efe054f0989b |
line wrap: on
line source
# HG changeset patch # Parent dd0e6d18bdef3c6ef7df3b0ed8bdbbea00406508 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,164 @@ +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 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; + + net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx)); + //if (net_dev == NULL) + // How should we raise the error in the parent context? + strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name)); + 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 (*/register_netdev(net_dev);/*)*/ + // Handle the 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 --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,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 --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,25 @@ 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) { - + Ethernet::exit(dev); } LKM::init() @@ -32,4 +44,6 @@ PCI::vendor_id = 0x8086; PCI::product_id = 0x100f; + + Ethernet::ifname = "rtx"; } 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 @@ -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) /* `if' doesn't work */ @@ -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}; } } } @@ -88,9 +89,10 @@ * 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}, 0, PCI_ANY_ID, PCI_ANY_ID }, - { 0, } + static struct pci_device_id rtx_pci_device_table[2] = + { + { ${config.vendor_id}, ${config.product_id}, PCI_ANY_ID, PCI_ANY_ID }, + { 0, } /* Doesn't work with just { } */ }; static struct pci_driver rtx_pci_driver = {