comparison 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
comparison
equal deleted inserted replaced
37:9433dec37a52 38:f43900ad7e66
1 # HG changeset patch 1 # HG changeset patch
2 # Parent a109185dcd773ae92b98a8195b7cc91f1c1cee47 2 # Parent b995d8934956b83383c144303178f3eb383d0acf
3 rathaxes: add the PCI/Ethernet part of a Linux Intel e1000 network card driver 3 rathaxes: add the PCI/Ethernet part of a Linux Intel e1000 network card driver
4 4
5 diff --git a/rathaxes/samples/CMakeLists.txt b/rathaxes/samples/CMakeLists.txt
6 --- a/rathaxes/samples/CMakeLists.txt
7 +++ b/rathaxes/samples/CMakeLists.txt
8 @@ -1,2 +1,3 @@
9 ADD_SUBDIRECTORY(helloworld)
10 +ADD_SUBDIRECTORY(lkm)
11 ADD_SUBDIRECTORY(syntax)
12 diff --git a/rathaxes/samples/lkm/CMakeLists.txt b/rathaxes/samples/lkm/CMakeLists.txt
13 new file mode 100644
14 --- /dev/null
15 +++ b/rathaxes/samples/lkm/CMakeLists.txt
16 @@ -0,0 +1,7 @@
17 +ADD_RATHAXES_SOURCES(lkm lkm.rtx
18 + RTI log.rti lkm.rti pci.rti socket.rti ethernet.rti e1000.rti
19 + BLT log.blt lkm.blt pci.blt socket.blt ethernet.blt e1000.blt)
20 +
21 +# We can't name lkm since it's already used as the target name to generate the
22 +# source (with ADD_RATHAXES_SOURCES).
23 +ADD_RATHAXES_LKM(lkm_hello lkm)
5 diff --git a/rathaxes/samples/lkm/e1000.blt b/rathaxes/samples/lkm/e1000.blt 24 diff --git a/rathaxes/samples/lkm/e1000.blt b/rathaxes/samples/lkm/e1000.blt
6 --- a/rathaxes/samples/lkm/e1000.blt 25 new file mode 100644
26 --- /dev/null
7 +++ b/rathaxes/samples/lkm/e1000.blt 27 +++ b/rathaxes/samples/lkm/e1000.blt
8 @@ -5,7 +5,7 @@ 28 @@ -0,0 +1,80 @@
9 chunk LKM::includes() 29 +with e1000, Ethernet, Socket, PCI, LKM, Log
10 { 30 +{
11 /* 31 + template type e1000::Context()
12 - * Force the generation of the structure in the "headers part, we 32 + {
33 + chunk LKM::includes()
34 + {
35 + /*
13 + * Force the generation of the structure in the "headers" part, we 36 + * Force the generation of the structure in the "headers" part, we
14 * have to do this since we do not use the structure in this blt 37 + * have to do this since we do not use the structure in this blt
15 * (we hacked a bit and used it in ethernet.blt directly). 38 + * (we hacked a bit and used it in ethernet.blt directly).
16 */ 39 + */
17 @@ -64,8 +64,10 @@ 40 + typedef int ${e1000::Context}; /* CNorm __std__ workaround */
18 { 41 + ${e1000::Context} force_declaration_in_includes;
19 chunk Ethernet::destroy_device 42 + }
20 { 43 +
21 - // XXX: add a check in order to avoid freeing none allocated 44 + chunk ::decl()
22 - // resources. 45 + {
46 + struct rtx_e1000_ctx
47 + {
48 + int bars;
49 + unsigned char /* __iomem */ *ioaddr;
50 + };
51 + }
52 +
53 + map
54 + {
55 + }
56 + }
57 +
58 + template sequence e1000::create_device()
59 + {
60 + chunk Ethernet::create_device()
61 + {
62 + rtx_ether_ctx->hw_ctx.bars = pci_select_bars(pdev, IORESOURCE_MEM);
63 + if (pci_enable_device_mem(pdev))
64 + {
65 + ${Log::info("e1000::create: pci_enable_device_mem failed")};
66 + }
67 +
68 + if (pci_request_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars, ${config.name}))
69 + {
70 + ${Log::info("e1000::create: pci_request_selected_regions failed")};
71 + }
72 +
73 + if (${config.set_master})
74 + {
75 + pci_set_master(pdev);
76 + }
77 +
78 + /* 0 here is for BAR_0: */
79 + rtx_ether_ctx->hw_ctx.ioaddr = pci_ioremap_bar(pdev, 0);
80 + if (!rtx_ether_ctx->hw_ctx.ioaddr)
81 + {
82 + ${Log::info("e1000::create: pci_ioremap_bar failed")};
83 + }
84 + }
85 +
86 + chunk ::CALL
87 + {
88 + }
89 + }
90 +
91 + template sequence e1000::destroy_device()
92 + {
93 + chunk Ethernet::destroy_device
94 + {
23 + /* 95 + /*
24 + * Here, we should have some checks to avoid to free resources that 96 + * Here, we should have some checks to avoid to free resources that
25 + * haven't been allocated. (e.g: in case of previous errors). 97 + * haven't been allocated. (e.g: in case of previous errors).
26 + */ 98 + */
27 struct rtx_ethernet_dev* rtx_ether_ctx = netdev_priv(net_dev); 99 + struct rtx_ethernet_dev* rtx_ether_ctx = netdev_priv(net_dev);
28 iounmap(rtx_ether_ctx->hw_ctx.ioaddr); 100 + iounmap(rtx_ether_ctx->hw_ctx.ioaddr);
29 pci_release_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars); 101 + pci_release_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars);
102 + }
103 +
104 + chunk ::CALL
105 + {
106 + }
107 + }
108 +}
30 diff --git a/rathaxes/samples/lkm/e1000.rti b/rathaxes/samples/lkm/e1000.rti 109 diff --git a/rathaxes/samples/lkm/e1000.rti b/rathaxes/samples/lkm/e1000.rti
31 --- a/rathaxes/samples/lkm/e1000.rti 110 new file mode 100644
111 --- /dev/null
32 +++ b/rathaxes/samples/lkm/e1000.rti 112 +++ b/rathaxes/samples/lkm/e1000.rti
33 @@ -2,7 +2,14 @@ 113 @@ -0,0 +1,24 @@
34 { 114 +interface e1000 : Socket, Ethernet, PCI, LKM
35 provided type e1000::Context; 115 +{
36 116 + provided type e1000::Context;
37 - /* Not sure if we need the argument */ 117 +
38 + /* 118 + /*
39 + * This sequence should receive an argument like Ethernet::Device, but it is 119 + * This sequence should receive an argument like Ethernet::Device, but it is
40 + * unclear about how this argument should be bound to a variable/argument in 120 + * unclear about how this argument should be bound to a variable/argument in
41 + * the instrumented C code. 121 + * the instrumented C code.
42 + * 122 + *
43 + * Here again, we rely on the fact that *we* wrote the parent context and 123 + * Here again, we rely on the fact that *we* wrote the parent context and
44 + * named the C variables we need/use with the same name everywhere. 124 + * named the C variables we need/use with the same name everywhere.
45 + */ 125 + */
46 provided sequence e1000::create_device() 126 + provided sequence e1000::create_device()
47 { 127 + {
48 provided chunk Ethernet::create_device; 128 + provided chunk Ethernet::create_device;
129 + provided chunk ::CALL;
130 + }
131 +
132 + provided sequence e1000::destroy_device()
133 + {
134 + provided chunk Ethernet::destroy_device;
135 + provided chunk ::CALL;
136 + }
137 +}
49 diff --git a/rathaxes/samples/lkm/ethernet.blt b/rathaxes/samples/lkm/ethernet.blt 138 diff --git a/rathaxes/samples/lkm/ethernet.blt b/rathaxes/samples/lkm/ethernet.blt
50 --- a/rathaxes/samples/lkm/ethernet.blt 139 new file mode 100644
140 --- /dev/null
51 +++ b/rathaxes/samples/lkm/ethernet.blt 141 +++ b/rathaxes/samples/lkm/ethernet.blt
52 @@ -6,8 +6,6 @@ 142 @@ -0,0 +1,207 @@
53 { 143 +with Ethernet, PCI, LKM, Log
54 #include <linux/netdevice.h> 144 +{
55 #include <linux/etherdevice.h> 145 + template type Ethernet::Device()
56 - 146 + {
57 - typedef int include_linux_net_system_stamp; 147 + chunk LKM::includes()
58 } 148 + {
59 149 + #include <linux/netdevice.h>
60 chunk ::decl() 150 + #include <linux/etherdevice.h>
61 @@ -93,10 +91,9 @@ 151 + }
62 template sequence Ethernet::interrupt_handler(Ethernet::Device dev) 152 +
63 { 153 + chunk ::decl()
64 /* 154 + {
65 - * Why we can't use irqreturn_t here? (we are forced to use enum 155 + struct rtx_ethernet_dev
66 - * irqreturn, which is the real type). 156 + {
157 + /*
158 + * I think it's useless to use the ${PCI::Device} "abstraction"
159 + * here, since we are already in a Linux specific context here.
160 + */
161 + struct pci_dev *pci_dev;
162 + struct net_device *net_dev;
163 +
164 + /* while waiting on issue #8 */
165 + struct rtx_e1000_ctx hw_ctx;
166 + };
167 + }
168 +
169 + chunk ::init(net_dev)
170 + {
171 + ${self} = ${net_dev};
172 + }
173 +
174 + map
175 + {
176 + }
177 + }
178 +
179 + template sequence Ethernet::open(Ethernet::Device dev)
180 + {
181 + chunk LKM::prototypes()
182 + {
183 + static int rtx_ethernet_open(struct net_device *);
184 + }
185 +
186 + chunk LKM::code()
187 + {
188 + static int rtx_ethernet_open(struct net_device *dev)
189 + {
190 + ${pointcut ::IMPLEMENTATION};
191 +
192 + return 0;
193 + }
194 + }
195 + }
196 +
197 + template sequence Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
198 + {
199 + chunk LKM::prototypes()
200 + {
201 + static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev);
202 + }
203 +
204 + chunk LKM::code()
205 + {
206 + static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev)
207 + {
208 + ${pointcut ::IMPLEMENTATION};
209 +
210 + return 0;
211 + }
212 + }
213 + }
214 +
215 + template sequence Ethernet::close(Ethernet::Device dev)
216 + {
217 + chunk LKM::prototypes()
218 + {
219 + static int rtx_ethernet_close(struct net_device *);
220 + }
221 +
222 + chunk LKM::code()
223 + {
224 + static int rtx_ethernet_close(struct net_device *dev)
225 + {
226 + ${pointcut ::IMPLEMENTATION};
227 +
228 + return 0;
229 + }
230 + }
231 + }
232 +
233 + template sequence Ethernet::interrupt_handler(Ethernet::Device dev)
234 + {
235 + /*
67 + * We can't use the irqreturn_t type here because CNornm doesn't know 236 + * We can't use the irqreturn_t type here because CNornm doesn't know
68 + * it. 237 + * it.
69 */ 238 + */
70 - 239 + chunk LKM::prototypes()
71 chunk LKM::prototypes() 240 + {
72 { 241 + static enum irqreturn rtx_ethernet_interrupt_handler(int, void *);
73 static enum irqreturn rtx_ethernet_interrupt_handler(int, void *); 242 + }
74 @@ -141,7 +138,12 @@ 243 +
75 if (net_dev == 0) 244 + chunk LKM::code()
76 { 245 + {
77 ${Log::info("Cannot allocate memory")}; 246 + static enum irqreturn rtx_ethernet_interrupt_handler(int irq, void *dev_id)
78 - // is it the thing to do? 247 + {
248 + ${pointcut ::IMPLEMENTATION};
249 +
250 + return IRQ_NONE;
251 + }
252 + }
253 + }
254 +
255 + template sequence Ethernet::init(PCI::Device pdev)
256 + {
257 + chunk LKM::data()
258 + {
259 + static const struct net_device_ops rtx_ether_ops =
260 + {
261 + .ndo_open = rtx_ethernet_open,
262 + .ndo_stop = rtx_ethernet_close,
263 + .ndo_start_xmit = rtx_ethernet_xmit,
264 + };
265 + }
266 +
267 + chunk PCI::pci_probe_hook()
268 + {
269 + /*
270 + * This typedef is needed to workaround a bug in CNorm __std__
271 + * dialect.
272 + */
273 + typedef int ${Ethernet::Device};
274 + ${Ethernet::Device} *rtx_ether_ctx;
275 + struct net_device *net_dev;
276 + int error;
277 +
278 + error = 0;
279 + net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx));
280 + if (net_dev == 0)
281 + {
282 + ${Log::info("Cannot allocate memory")};
79 + /* 283 + /*
80 + * Again, the error should be "raised" in the parent context. 284 + * Again, the error should be "raised" in the parent context.
81 + * 285 + *
82 + * Here we know that we should return ENOMEM because *we* wrote 286 + * Here we know that we should return ENOMEM because *we* wrote
83 + * the parent context. 287 + * the parent context.
84 + */ 288 + */
85 return -ENOMEM; 289 + return -ENOMEM;
86 } 290 + }
87 strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name)); 291 + strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name));
88 @@ -166,13 +168,13 @@ 292 + net_dev->irq = pdev->irq;
89 if ((error = register_netdev(net_dev))) 293 + // Maybe we should try ${rtx_ether_ctx.init()} here:
90 { 294 + rtx_ether_ctx = netdev_priv(net_dev);
91 ${Log::info("Cannot register the driver")}; 295 + //rtx_ether_ctx->pci_dev = ${pdev};
92 - // is it the thing to do? 296 + rtx_ether_ctx->pci_dev = pdev; // In the meantime do it directly
93 return error; 297 + rtx_ether_ctx->net_dev = net_dev;
94 } 298 +
95 299 + /*
96 /* same problem as above with ${pdev} */ 300 + * The substitution of ${pdev} fails here. I also tried to add a
97 //pci_set_drvdata(${pdev}, net_dev); 301 + * "substitute method" to the PCI::Device that was just doing
98 pci_set_drvdata(pdev, net_dev); 302 + * "${self}" but it didn't work either (it was subsituted by a
99 + 303 + * placeholder, e.g: _1).
100 ${pointcut Ethernet::create_device}; 304 + *
101 } 305 + * That's why we cheated a bit and named all the arguments pdev.
102 306 + */
307 + //SET_NETDEV_DEV(net_dev, &${pdev}->dev);
308 + SET_NETDEV_DEV(net_dev, &pdev->dev);
309 + net_dev->netdev_ops = &rtx_ether_ops;
310 + if ((error = register_netdev(net_dev)))
311 + {
312 + ${Log::info("Cannot register the driver")};
313 + return error;
314 + }
315 +
316 + /* same problem as above with ${pdev} */
317 + //pci_set_drvdata(${pdev}, net_dev);
318 + pci_set_drvdata(pdev, net_dev);
319 +
320 + ${pointcut Ethernet::create_device};
321 + }
322 +
323 + chunk ::CALL
324 + {
325 + }
326 + }
327 +
328 + template sequence Ethernet::exit(PCI::Device pdev)
329 + {
330 + chunk PCI::pci_remove_hook()
331 + {
332 + struct net_device *net_dev = pci_get_drvdata(pdev);
333 +
334 + ${pointcut Ethernet::destroy_device};
335 +
336 + unregister_netdev(net_dev);
337 + /*
338 + * If we had some cleanup todo with struct rtx_ether_ctx we would
339 + * do a netdev_priv(net_dev) here and do it.
340 + */
341 + free_netdev(net_dev);
342 + }
343 +
344 + chunk ::CALL
345 + {
346 + }
347 + }
348 +}
349 +
103 diff --git a/rathaxes/samples/lkm/ethernet.rti b/rathaxes/samples/lkm/ethernet.rti 350 diff --git a/rathaxes/samples/lkm/ethernet.rti b/rathaxes/samples/lkm/ethernet.rti
104 --- a/rathaxes/samples/lkm/ethernet.rti 351 new file mode 100644
352 --- /dev/null
105 +++ b/rathaxes/samples/lkm/ethernet.rti 353 +++ b/rathaxes/samples/lkm/ethernet.rti
106 @@ -37,7 +37,6 @@ 354 @@ -0,0 +1,47 @@
107 provided pointcut Ethernet::create_device; 355 +interface Ethernet : Socket, PCI, LKM
108 } 356 +{
109 357 + provided type Ethernet::Device;
110 - /* Likely extends PCI::remove */ 358 +
111 provided sequence Ethernet::exit(PCI::Device) 359 + required variable ::string Ethernet::ifname;
112 { 360 +
113 provided chunk ::CALL; 361 + required sequence Ethernet::open(Ethernet::Device)
362 + {
363 + provided chunk LKM::prototypes;
364 + provided chunk LKM::code;
365 + }
366 +
367 + required sequence Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
368 + {
369 + provided chunk LKM::prototypes;
370 + provided chunk LKM::code;
371 + }
372 +
373 + required sequence Ethernet::close(Ethernet::Device)
374 + {
375 + provided chunk LKM::prototypes;
376 + provided chunk LKM::code;
377 + }
378 +
379 + required sequence Ethernet::interrupt_handler(Ethernet::Device)
380 + {
381 + provided chunk LKM::prototypes;
382 + provided chunk LKM::code;
383 + }
384 +
385 + provided sequence Ethernet::init(PCI::Device)
386 + {
387 + provided chunk LKM::data;
388 + provided chunk PCI::pci_probe_hook;
389 + provided chunk ::CALL;
390 +
391 + provided pointcut Ethernet::create_device;
392 + }
393 +
394 + provided sequence Ethernet::exit(PCI::Device)
395 + {
396 + provided chunk ::CALL;
397 + provided chunk PCI::pci_remove_hook;
398 +
399 + provided pointcut Ethernet::destroy_device;
400 + }
401 +}
114 diff --git a/rathaxes/samples/lkm/lkm.blt b/rathaxes/samples/lkm/lkm.blt 402 diff --git a/rathaxes/samples/lkm/lkm.blt b/rathaxes/samples/lkm/lkm.blt
115 --- a/rathaxes/samples/lkm/lkm.blt 403 new file mode 100644
404 --- /dev/null
116 +++ b/rathaxes/samples/lkm/lkm.blt 405 +++ b/rathaxes/samples/lkm/lkm.blt
117 @@ -12,9 +12,6 @@ 406 @@ -0,0 +1,55 @@
118 { 407 +with LKM
119 #include <linux/module.h> 408 +{
120 #include <linux/kernel.h> 409 + /* Skel of the generated C file: */
121 - 410 + ${pointcut LKM::includes};
122 - typedef int include_linux_module_stamp; 411 + ${pointcut LKM::prototypes};
123 - typedef int include_linux_kernel_stamp; 412 + ${pointcut LKM::data};
124 } 413 + ${pointcut LKM::code};
125 414 +
126 chunk LKM::data() 415 + template sequence LKM::init()
416 + {
417 + chunk LKM::includes()
418 + {
419 + #include <linux/module.h>
420 + #include <linux/kernel.h>
421 + }
422 +
423 + chunk LKM::data()
424 + {
425 + MODULE_DESCRIPTION(${config.description});
426 + MODULE_AUTHOR(${config.author});
427 + MODULE_LICENSE(${config.license});
428 + }
429 +
430 + chunk LKM::code()
431 + {
432 + /*
433 + * Rathaxes doesn't yet support arbitrary "decorators" like __init
434 + * or __exit.
435 + */
436 + static int __attribute__((__section__(".init.text"))) rtx_module_init(void)
437 + {
438 + ${pointcut ::IMPLEMENTATION};
439 + ${pointcut LKM::init_bus_hook};
440 +
441 + return 0;
442 + }
443 +
444 + module_init(rtx_module_init);
445 + }
446 + }
447 +
448 + template sequence LKM::exit()
449 + {
450 + chunk LKM::code()
451 + {
452 + static void __attribute__((__section__(".exit.text"))) rtx_module_exit(void)
453 + {
454 + ${pointcut ::IMPLEMENTATION};
455 + ${pointcut LKM::deinit_bus_hook};
456 + }
457 +
458 + module_exit(rtx_module_exit);
459 + }
460 + }
461 +}
462 diff --git a/rathaxes/samples/lkm/lkm.rti b/rathaxes/samples/lkm/lkm.rti
463 new file mode 100644
464 --- /dev/null
465 +++ b/rathaxes/samples/lkm/lkm.rti
466 @@ -0,0 +1,25 @@
467 +interface LKM
468 +{
469 + provided pointcut LKM::includes;
470 + /* maybe it should be possible to use chunk ::decl in sequence templates? */
471 + provided pointcut LKM::prototypes;
472 + provided pointcut LKM::data;
473 + provided pointcut LKM::code;
474 +
475 + required variable ::string LKM::author;
476 + required variable ::string LKM::description;
477 + required variable ::string LKM::license;
478 +
479 + required sequence LKM::init()
480 + {
481 + provided chunk LKM::includes;
482 + provided chunk LKM::code;
483 + provided pointcut LKM::init_bus_hook;
484 + }
485 +
486 + required sequence LKM::exit()
487 + {
488 + provided chunk LKM::code;
489 + provided pointcut LKM::deinit_bus_hook;
490 + }
491 +}
127 diff --git a/rathaxes/samples/lkm/lkm.rtx b/rathaxes/samples/lkm/lkm.rtx 492 diff --git a/rathaxes/samples/lkm/lkm.rtx b/rathaxes/samples/lkm/lkm.rtx
128 --- a/rathaxes/samples/lkm/lkm.rtx 493 new file mode 100644
494 --- /dev/null
129 +++ b/rathaxes/samples/lkm/lkm.rtx 495 +++ b/rathaxes/samples/lkm/lkm.rtx
130 @@ -1,4 +1,4 @@ 496 @@ -0,0 +1,46 @@
131 -device LKM use LKM, PCI, Log
132 +device LKM use LKM, PCI, Ethernet, Log 497 +device LKM use LKM, PCI, Ethernet, Log
133 { 498 +{
134 Ethernet::open(Ethernet::Device dev) 499 + Ethernet::open(Ethernet::Device dev)
135 { 500 + {
501 + Log::info("Open the device");
502 + }
503 +
504 + Ethernet::close(Ethernet::Device dev)
505 + {
506 + Log::info("Close the device");
507 + }
508 +
509 + Ethernet::interrupt_handler(Ethernet::Device dev)
510 + {
511 + Log::info("Got an interruption");
512 + }
513 +
514 + Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
515 + {
516 + Log::info("We have one packet to transmit!");
517 + }
518 +
519 + LKM::init()
520 + {
521 + Log::info("Hello this is LKM");
522 + }
523 +
524 + LKM::exit()
525 + {
526 + Log::info("Good bye this was LKM");
527 + }
528 +}
529 +
530 +configuration
531 +{
532 + LKM::name = "hello";
533 + LKM::author = "Rathaxes";
534 + LKM::description = "Hello World Loadable Kernel Module (LKM)";
535 + LKM::license = "GPL";
536 +
537 + PCI::vendor_id = 0x8086;
538 + PCI::product_id = 0x100f;
539 + PCI::set_master = true;
540 +
541 + Ethernet::ifname = "rtx%d";
542 +}
543 diff --git a/rathaxes/samples/lkm/log.blt b/rathaxes/samples/lkm/log.blt
544 new file mode 100644
545 --- /dev/null
546 +++ b/rathaxes/samples/lkm/log.blt
547 @@ -0,0 +1,10 @@
548 +with Log
549 +{
550 + template sequence Log::info(::string msg)
551 + {
552 + chunk ::CALL
553 + {
554 + pr_info("%s\n", ${msg});
555 + }
556 + }
557 +}
558 diff --git a/rathaxes/samples/lkm/log.rti b/rathaxes/samples/lkm/log.rti
559 new file mode 100644
560 --- /dev/null
561 +++ b/rathaxes/samples/lkm/log.rti
562 @@ -0,0 +1,7 @@
563 +interface Log
564 +{
565 + provided sequence Log::info(::string)
566 + {
567 + provided chunk ::CALL;
568 + }
569 +}
136 diff --git a/rathaxes/samples/lkm/pci.blt b/rathaxes/samples/lkm/pci.blt 570 diff --git a/rathaxes/samples/lkm/pci.blt b/rathaxes/samples/lkm/pci.blt
137 --- a/rathaxes/samples/lkm/pci.blt 571 new file mode 100644
572 --- /dev/null
138 +++ b/rathaxes/samples/lkm/pci.blt 573 +++ b/rathaxes/samples/lkm/pci.blt
139 @@ -5,8 +5,6 @@ 574 @@ -0,0 +1,143 @@
140 chunk LKM::includes() 575 +with PCI, LKM, Log
141 { 576 +{
142 #include <linux/pci.h> 577 + template type PCI::Device()
143 - 578 + {
144 - typedef int include_linux_pci_stamp; 579 + chunk LKM::includes()
145 } 580 + {
146 581 + #include <linux/pci.h>
147 chunk ::decl() 582 + }
148 @@ -24,16 +22,6 @@ 583 +
149 } 584 + chunk ::decl()
150 } 585 + {
151 586 + struct pci_dev;
152 - /* 587 + }
153 - * The PCI::probe sequence is a "required" sequence which means that its 588 +
154 - * implementation will be done in the .rtx. Here we just define the context 589 + chunk ::init(pci_dev)
155 - * were this implementation will be inserted. The implementation should be 590 + {
156 - * able to access to the struct pci_dev (here marked as the "argument" 591 + ${self} = ${pci_dev};
157 - * PCI::Device). How do we bind this PCI::Device argument with the pdev 592 + }
158 - * struct pci_dev pointer defined in the LKM::code chunk? 593 +
159 - * 594 + map
160 - * The only thing I can imagine is: ${pointcut ::IMPLEMENTATION(pdev)}; 595 + {
161 - */ 596 + }
162 template sequence PCI::probe(PCI::Device pdev) 597 + }
163 { 598 +
164 chunk LKM::prototypes() 599 + template sequence PCI::probe(PCI::Device pdev)
165 @@ -112,22 +100,32 @@ 600 + {
166 601 + chunk LKM::prototypes()
167 chunk LKM::init_bus_hook() 602 + {
168 { 603 + static int /* __devinit */ rtx_pci_probe(struct pci_dev *,
169 - /* 604 + const struct pci_device_id *);
170 - * So how do we use the return value in the parent context? 605 + }
171 - */ 606 +
172 int error; 607 + chunk LKM::code()
173 if ((error = pci_register_driver(&rtx_pci_driver))) 608 + {
174 { 609 + static int /* __devinit */ rtx_pci_probe(struct pci_dev *pdev,
175 ${Log::info("Cannot register pci driver")}; 610 + const struct pci_device_id *pdev_id)
176 - // should we return here. 611 + {
177 - // error managmement procedure has to be determined ASAP. 612 + int err;
613 +
614 + err = pci_enable_device(pdev);
615 + if (err < 0)
616 + goto fail;
617 +
618 + ${pointcut PCI::pci_probe_hook};
619 +
620 + return 0;
621 +
622 + fail:
623 + return err;
624 + }
625 + }
626 +
627 + chunk ::CALL
628 + {
629 + }
630 + }
631 +
632 + template sequence PCI::remove(PCI::Device pdev)
633 + {
634 + chunk LKM::prototypes()
635 + {
636 + static void rtx_pci_remove(struct pci_dev *);
637 + }
638 +
639 + chunk LKM::code()
640 + {
641 + static void rtx_pci_remove(struct pci_dev *pdev)
642 + {
643 + ${pointcut PCI::pci_remove_hook};
644 +
645 + pci_disable_device(pdev);
646 + }
647 + }
648 +
649 + chunk ::CALL()
650 + {
651 + }
652 + }
653 +
654 + template sequence PCI::register()
655 + {
656 + chunk LKM::data()
657 + {
658 + /*
659 + * CNorm doesn't seem to like "dynamic" arrays (i.e: you always
660 + * have to specify the exact size).
661 + */
662 + static struct pci_device_id rtx_pci_device_table[2] = {
663 + { ${config.vendor_id}, ${config.product_id}, PCI_ANY_ID, PCI_ANY_ID },
664 + { 0, }
665 + };
666 +
667 + static struct pci_driver rtx_pci_driver = {
668 + .name = ${config.name},
669 + .id_table = rtx_pci_device_table,
670 + .probe = rtx_pci_probe,
671 + .remove = rtx_pci_remove
672 + };
673 + }
674 +
675 + chunk LKM::init_bus_hook()
676 + {
677 + int error;
678 + if ((error = pci_register_driver(&rtx_pci_driver)))
679 + {
680 + ${Log::info("Cannot register pci driver")};
178 + /* 681 + /*
179 + * So we catched the error but how do we return it to the 682 + * So we catched the error but how do we return it to the
180 + * parent context? 683 + * parent context?
181 + * 684 + *
182 + * Here we know that we can just return error, but that's just 685 + * Here we know that we can just return error, but that's just
183 + * a coincidence (and, in this case, *we* wrote the parent 686 + * a coincidence (and, in this case, *we* wrote the parent
184 + * context). 687 + * context).
185 + */ 688 + */
186 return error; 689 + return error;
187 } 690 + }
188 } 691 + }
189 692 +
190 chunk ::CALL() 693 + chunk ::CALL()
191 { 694 + {
192 - // no implementation, we just need to instrument the lkm::bus_hook
193 + /* 695 + /*
194 + * The implementation of ::CALL is empty. This template sequence is 696 + * The implementation of ::CALL is empty. This template sequence is
195 + * actually not provided nor required. 697 + * actually not provided nor required.
196 + * 698 + *
197 + * This sequence is just "intermediate" code that will just inject 699 + * This sequence is just "intermediate" code that will just inject
198 + * itself in the hook LKM::init_bus_hook for which this sequence 700 + * itself in the hook LKM::init_bus_hook for which this sequence
199 + * has a chunk (see above chunk). 701 + * has a chunk (see above chunk).
200 + */ 702 + */
201 } 703 + }
202 } 704 + }
203 705 +
706 + template sequence PCI::unregister()
707 + {
708 + chunk LKM::deinit_bus_hook()
709 + {
710 + pci_unregister_driver(&rtx_pci_driver);
711 + }
712 +
713 + chunk ::CALL
714 + {
715 + }
716 + }
717 +}
204 diff --git a/rathaxes/samples/lkm/pci.rti b/rathaxes/samples/lkm/pci.rti 718 diff --git a/rathaxes/samples/lkm/pci.rti b/rathaxes/samples/lkm/pci.rti
205 --- a/rathaxes/samples/lkm/pci.rti 719 new file mode 100644
720 --- /dev/null
206 +++ b/rathaxes/samples/lkm/pci.rti 721 +++ b/rathaxes/samples/lkm/pci.rti
207 @@ -7,11 +7,6 @@ 722 @@ -0,0 +1,36 @@
208 723 +interface PCI : LKM
209 provided sequence PCI::register() 724 +{
210 { 725 + provided type PCI::Device;
211 - // it is impossible to provide a "dummy" sequence 726 +
212 - // which just hook itself. The PCI:register juste 727 + required variable ::number PCI::vendor_id;
213 - // inject its code in the module_init function 728 + required variable ::number PCI::product_id;
214 - // in order to load the pci driver. 729 +
215 - // Everything is done with the configuration. 730 + provided sequence PCI::register()
216 provided chunk ::CALL; 731 + {
217 provided chunk LKM::data; 732 + provided chunk ::CALL;
218 provided chunk LKM::init_bus_hook; 733 + provided chunk LKM::data;
734 + provided chunk LKM::init_bus_hook;
735 + }
736 +
737 + provided sequence PCI::unregister()
738 + {
739 + provided chunk ::CALL;
740 + provided chunk LKM::deinit_bus_hook;
741 + }
742 +
743 + provided sequence PCI::probe(PCI::Device)
744 + {
745 + provided chunk LKM::prototypes;
746 + provided chunk LKM::code;
747 +
748 + provided pointcut PCI::pci_probe_hook;
749 + }
750 +
751 + provided sequence PCI::remove(PCI::Device)
752 + {
753 + provided chunk LKM::prototypes;
754 + provided chunk LKM::code;
755 +
756 + provided pointcut PCI::pci_remove_hook;
757 + }
758 +}
759 diff --git a/rathaxes/samples/lkm/socket.blt b/rathaxes/samples/lkm/socket.blt
760 new file mode 100644
761 --- /dev/null
762 +++ b/rathaxes/samples/lkm/socket.blt
763 @@ -0,0 +1,27 @@
764 +with Socket, LKM
765 +{
766 + template type Socket::SKBuff()
767 + {
768 + chunk LKM::includes()
769 + {
770 + #include <linux/skbuff.h>
771 + }
772 +
773 + chunk ::decl()
774 + {
775 + struct sk_buff;
776 + }
777 +
778 + chunk ::init()
779 + {
780 + }
781 +
782 + map
783 + {
784 + // some work may have to be done here in order
785 + // to access to some field of the sk_buff.
786 + // We should determine if all the sk_buff managment
787 + // can be abstracted from the user.
788 + }
789 + }
790 +}
791 diff --git a/rathaxes/samples/lkm/socket.rti b/rathaxes/samples/lkm/socket.rti
792 new file mode 100644
793 --- /dev/null
794 +++ b/rathaxes/samples/lkm/socket.rti
795 @@ -0,0 +1,4 @@
796 +interface Socket : LKM
797 +{
798 + provided type Socket::SKBuff;
799 +}