Mercurial > archived > louis > epitech > mq > rathaxes
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 +} |