Mercurial > archived > louis > epitech > mq > rathaxes
comparison rathaxes_samples_e1000_split_set_up_device.patch @ 122:52402232483f
WIP on the split up of e1000::set_up_device
author | Louis Opter <louis@lse.epita.fr> |
---|---|
date | Sun, 28 Jul 2013 02:50:43 -0700 |
parents | 6f600f83a763 |
children | 518d9c8ac70c |
comparison
equal
deleted
inserted
replaced
121:6f600f83a763 | 122:52402232483f |
---|---|
1 # HG changeset patch | 1 # HG changeset patch |
2 # Parent 069883bfa2ec71faaf7ab957bc35db087eacc3cc | 2 # Parent d62a08753da7cec4d44246b747ff79847d9b4238 |
3 rathaxes: split and refactor e1000::set_up_device in {Rx,Tx}Ring methods | 3 rathaxes: split and refactor e1000::set_up_device in {Rx,Tx}Ring methods |
4 | |
5 | 4 |
6 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt | 5 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt |
7 --- a/rathaxes/samples/e1000/e1000.blt | 6 --- a/rathaxes/samples/e1000/e1000.blt |
8 +++ b/rathaxes/samples/e1000/e1000.blt | 7 +++ b/rathaxes/samples/e1000/e1000.blt |
9 @@ -752,8 +752,10 @@ | 8 @@ -1,4 +1,4 @@ |
10 */ | 9 -with e1000, Ethernet, Socket, PCI, LKM, Log, Builtin |
11 for (i = 0; i != ${config.rx_ring_size}; ++i) | 10 +with e1000, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin |
12 { | 11 { |
13 + /* XXX #46: */ | 12 template type e1000::RxDescriptor() |
14 + // hw_ctx->rx_ring.skbuffs[i].skbuff = ${rtx_ether_ctx.net_device.alloc_rx_skb(${config.rx_buffer_len})}; | 13 { |
15 hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb( | 14 @@ -96,8 +96,163 @@ |
15 { | |
16 } | |
17 | |
18 + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) | |
19 + { | |
20 + { | |
21 + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
22 + | |
23 + /* | |
24 + * Receive initialization (section 14.4): | |
25 + * | |
26 + * 1. Program the receive address, in RAL/RAH; | |
27 + * 2. Initialize the Multicast Table Array; | |
28 + * 3. Program the interrupt mask register (done in | |
29 + * e1000::activate_device_interruption); | |
30 + * 4. Allocate the receive descriptor ring and map it to make it | |
31 + * accessible by the device; | |
32 + * 5. Write the start address of the ring in RDBAL/RDBAH and set | |
33 + * RDLEN (Receive Descriptor Length) to the size of the ring; | |
34 + * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the | |
35 + * beginning and end of the ring; | |
36 + * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the | |
37 + * receive buffer size to 2048 bytes (e1000::rx_buffer_len). | |
38 + * 8. Set RCTL.EN to enable the receiver. | |
39 + * | |
40 + * The ugly casts here are caused by the lack of CNorm unstrict. | |
41 + */ | |
42 + | |
43 + int i; | |
44 + | |
45 + /* 1. Program the receive address */ | |
46 + | |
47 + /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */ | |
48 + rtx_e1000_register_write32(hw_ctx, E1000_RAL, | |
49 + *(unsigned int *)(${rtx_ether_ctx.dev_addr})); | |
50 + /* | |
51 + * The 16 upper bits of RAH also store the AS bits (which should be | |
52 + * 0) and the AV bit (should be 1 to set the address as valid). | |
53 + */ | |
54 + rtx_e1000_register_write32(hw_ctx, E1000_RAH, | |
55 + *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4])); | |
56 + rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); | |
57 + | |
58 + ${Log::info("adapter_init_rx: receive address programmed")}; | |
59 + | |
60 + /* 2. Initialize the MTA */ | |
61 + | |
62 + for (i = 0; i != 128; ++i) | |
63 + rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); | |
64 + | |
65 + ${Log::info("adapter_init_rx: MTA init done")}; | |
66 + | |
67 + /* 4. Setup the receive descriptor ring */ | |
68 + | |
69 + /* Allocate the descriptors */ | |
70 + hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base); | |
71 + hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096); | |
72 + hw_ctx->rx_ring.base = dma_alloc_coherent( | |
73 + ${rtx_ether_ctx.device}, | |
74 + hw_ctx->rx_ring.size, | |
75 + &hw_ctx->rx_ring.dma_base, | |
76 + GFP_KERNEL); | |
77 + /* XXX | |
78 + * The first arg is recognized as Ethernet::Device instead of | |
79 + * Device::AbstractDevice. | |
80 + */ | |
81 + hw_ctx->rx_ring.base = ${DMA::alloc_coherent( | |
82 + rtx_ether_ctx.device, local.hw_ctx.rx_ring.size, local.hw_ctx.rx_ring.dma_base.dma_handle | |
83 + )}; | |
84 + if (!hw_ctx->rx_ring.base) | |
85 + { | |
86 + ${Log::info("adapter_init_rx: cannot allocate the descriptors for the rx ring")}; | |
87 + goto err_rx_ring_alloc; | |
88 + } | |
89 + | |
90 + ${Log::info("adapter_init_rx: rx descriptors allocated")}; | |
91 + | |
92 + /* | |
93 + * Allocate the skbuffs, map them for DMA, and write their address | |
94 + * in the corresponding descriptor. | |
95 + */ | |
96 + for (i = 0; i != ${config.rx_ring_size}; ++i) | |
97 + { | |
98 + // XXX #46: ${Socket::SKBuff.ref} skbuff = ${rtx_ether_ctx.net_device.alloc_rx_skbuff(config.rx_buffer_len)}; | |
99 + ${Socket::AbstractSKBuff.ref} k_sk_buff = (${Socket::AbstractSKBuff.ref})netdev_alloc_skb( | |
100 + ${rtx_ether_ctx.net_device.k_net_dev}, ${config.rx_buffer_len} | |
101 + ); | |
102 + if (!k_sk_buff) | |
103 + { | |
104 + ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; | |
105 + goto err_skbuffs_alloc; | |
106 + } | |
107 + ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; | |
108 + // XXX breaks rtxGen: ${local.skbuff.init(local.k_sk_buff)}; | |
109 + skbuff->skbuff = k_sk_buff; | |
110 + skbuff->dma_handle = 0; | |
111 + // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; | |
112 + if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE)) | |
113 + { | |
114 + ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; | |
115 + goto err_skbuffs_map; | |
116 + } | |
117 + hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff}); | |
118 + } | |
119 + | |
120 + ${Log::info("adapter_init_rx: skbuffs allocated")}; | |
121 + | |
122 + /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */ | |
123 + rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff); | |
124 + rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32); | |
125 + rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size); | |
126 + | |
127 + /* 6. Setup RDH/RDT */ | |
128 + rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0); | |
129 + rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1); | |
130 + | |
131 + /* 7. Configure the buffer size, */ | |
132 + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len}); | |
133 + | |
134 + /* 8. Enable the receiver */ | |
135 + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN); | |
136 + | |
137 + ${Log::info("adapter_init_rx: receive registers configured and receiver enabled")}; | |
138 + | |
139 + /* | |
140 + * XXX: We can't return here since we are not in a function but | |
141 + * in a chunk of code (injected in a function). | |
142 + */ | |
143 + goto init_rx_ok; | |
144 + | |
145 + err_skbuffs_alloc: | |
146 + while (i--) | |
147 + { | |
148 + dma_unmap_single( | |
149 + ${rtx_ether_ctx.device}, | |
150 + hw_ctx->rx_ring.skbuffs[i].dma_handle, | |
151 + ${config.rx_buffer_len}, | |
152 + DMA_FROM_DEVICE); | |
153 + err_skbuffs_map: | |
154 + /* XXX leaking cast: */ | |
155 + dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff); | |
156 + } | |
157 + | |
158 + dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size, | |
159 + hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); | |
160 + err_rx_ring_alloc: | |
161 + /* | |
162 + * XXX: Likewise, if there is something else to rollback in the | |
163 + * enclosing function, this won't be done. | |
164 + */ | |
165 + return -ENOMEM; | |
166 + | |
167 + init_rx_ok: (void)0; /* NOP, to make this a valid label. */ | |
168 + } | |
169 + } | |
170 + | |
171 map | |
172 { | |
173 + size: ((${self}).size); | |
174 + dma_base: ((${self}).dma_base); | |
175 } | |
176 } | |
177 | |
178 @@ -208,7 +363,62 @@ | |
179 } | |
180 } | |
181 | |
182 - method clean() | |
183 + chunk Ethernet::adapter_init_tx(Ethernet::Device rtx_ether_ctx) | |
184 + { | |
185 + { | |
186 + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
187 + | |
188 + /* | |
189 + * Transmission initialization (section 14.5): | |
190 + * | |
191 + * 1. Allocate the transmit descriptors ring and map it to make it | |
192 + * accessible by the device; | |
193 + * 2. Write the start address of the ring in TDBAL/TDBAH and set | |
194 + * TDLEN to the size of the ring; | |
195 + * 3. Set the TDH/TDT indexes to the beginning and end of the ring; | |
196 + * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the | |
197 + * transmitter. | |
198 + */ | |
199 + | |
200 + /* 1. Allocate the tx ring */ | |
201 + hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base); | |
202 + hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096); | |
203 + hw_ctx->tx_ring.base = dma_alloc_coherent( | |
204 + ${rtx_ether_ctx.device}, | |
205 + hw_ctx->tx_ring.size, | |
206 + &hw_ctx->tx_ring.dma_base, | |
207 + GFP_KERNEL); | |
208 + if (!hw_ctx->rx_ring.base) | |
209 + { | |
210 + ${Log::info("adapter_init_tx: cannot allocate the descriptors for the tx ring")}; | |
211 + /* | |
212 + * XXX: If there is something else to rollback in the enclosing | |
213 + * function, this won't be done. | |
214 + */ | |
215 + return -ENOMEM; | |
216 + } | |
217 + | |
218 + ${Log::info("adapter_init_tx: tx descriptors allocated")}; | |
219 + | |
220 + /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ | |
221 + rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, hw_ctx->tx_ring.dma_base & 0xffffffff); | |
222 + rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, hw_ctx->tx_ring.dma_base >> 32); | |
223 + rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size); | |
224 + | |
225 + /* 3. Setup TDH/TDT to zero: the queue is empty */ | |
226 + rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); | |
227 + rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); | |
228 + hw_ctx->tx_ring.head = 0; | |
229 + hw_ctx->tx_ring.tail = 0; | |
230 + | |
231 + /* 4. Set TCTL.PSP and enable the transmitter */ | |
232 + rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_EN); | |
233 + | |
234 + ${Log::info("adapter_init_tx: transmit registers configured and transmitter enabled")}; | |
235 + } | |
236 + } | |
237 + | |
238 + method clean() | |
239 { | |
240 rtx_e1000_tx_ring_clean(${self}); | |
241 } | |
242 @@ -247,9 +457,8 @@ | |
243 { | |
244 int bars; | |
245 unsigned char /* __iomem */ *ioaddr; | |
246 - | |
247 - ${e1000::RxRing} rx_ring; | |
248 - ${e1000::TxRing} tx_ring; | |
249 + ${e1000::RxRing.scalar} rx_ring; | |
250 + ${e1000::TxRing.scalar} tx_ring; | |
251 } | |
252 | |
253 chunk Ethernet::HardwareContext() | |
254 @@ -309,10 +518,53 @@ | |
255 } | |
256 } | |
257 | |
258 + chunk Ethernet::adapter_setup(Ethernet::Device rtx_ether_ctx) | |
259 + { | |
260 + { | |
261 + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
262 + | |
263 + /* | |
264 + * "General Configuration" (section 14.3): | |
265 + * | |
266 + * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & | |
267 + * negociation; | |
268 + * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; | |
269 + * - CTRL.PHY_RST: Unset it; | |
270 + * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); | |
271 + * - CTRL.VME: Make sure it's not set to disable VLAN support; | |
272 + * - Set the control flow registers to 0; | |
273 + * - Finally, initialize all the statistic registers from | |
274 + * E1000_CRCERRS to E1000_TSCTFC. | |
275 + */ | |
276 + rtx_e1000_register_set32(hw_ctx, E1000_CTRL, | |
277 + E1000_CMD_ASDE | | |
278 + E1000_CMD_SLU); | |
279 + rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, | |
280 + E1000_CMD_LRST | | |
281 + E1000_CMD_FRCSPD | | |
282 + E1000_CMD_PHY_RST | | |
283 + E1000_CMD_ILOS | | |
284 + E1000_CMD_VME); | |
285 + rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); | |
286 + rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); | |
287 + rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); | |
288 + rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); | |
289 + /* | |
290 + * XXX: Using int i clashes with another int i from the | |
291 + * "parent" chunk: | |
292 + */ | |
293 + for (int j = 0; j != 64; ++j) | |
294 + rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + j * 4, 0); | |
295 + | |
296 + ${Log::info("adapter_setup: general configuration done")}; | |
297 + } | |
298 + } | |
299 + | |
300 map | |
301 { | |
302 + rx_ring: ((${self})->rx_ring); | |
303 + //tx_ring: ((${self})->tx_ring); | |
304 } | |
305 - | |
306 } | |
307 | |
308 template type e1000::Register() | |
309 @@ -615,269 +867,6 @@ | |
310 } | |
311 } | |
312 | |
313 - /* TODO: refactor | |
314 - * | |
315 - * Split into two method methods: | |
316 - * - e1000::RxRing::init_rx() | |
317 - * - e1000::TxRing::init_tx() | |
318 - * | |
319 - * Also it should use the new methods in Socket::SKbuff. | |
320 - */ | |
321 - template sequence set_up_device(Ethernet::Device rtx_ether_ctx) | |
322 - { | |
323 - chunk ::CALL() | |
324 - { | |
325 - /* | |
326 - * This part is documented in the Intel Gigabit Ethernet Controller | |
327 - * Software Developper manual. (You can find it in the doc/hardware | |
328 - * directory). | |
329 - * | |
330 - * Since this part is actually completely device specific it should | |
331 - * not be written here. (but in the front-end). | |
332 - */ | |
333 - | |
334 - /* | |
335 - * shortcut hw_ctx... maybe we should directly take an | |
336 - * e1000::Context? (but we would need to make it point back to | |
337 - * the struct net_device) | |
338 - */ | |
339 - ${e1000::Context.ref} hw_ctx; | |
340 - hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
341 - | |
342 - /* | |
343 - * "General Configuration" (section 14.3): | |
344 - * | |
345 - * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & | |
346 - * negociation; | |
347 - * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; | |
348 - * - CTRL.PHY_RST: Unset it; | |
349 - * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); | |
350 - * - CTRL.VME: Make sure it's not set to disable VLAN support; | |
351 - * - Set the control flow registers to 0; | |
352 - * - Finally, initialize all the statistic registers from | |
353 - * E1000_CRCERRS to E1000_TSCTFC. | |
354 - */ | |
355 - | |
356 - int i; | |
357 - | |
358 - rtx_e1000_register_set32(hw_ctx, E1000_CTRL, | |
359 - E1000_CMD_ASDE | | |
360 - E1000_CMD_SLU); | |
361 - rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, | |
362 - E1000_CMD_LRST | | |
363 - E1000_CMD_FRCSPD | | |
364 - E1000_CMD_PHY_RST | | |
365 - E1000_CMD_ILOS | | |
366 - E1000_CMD_VME); | |
367 - rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); | |
368 - rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); | |
369 - rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); | |
370 - rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); | |
371 - for (i = 0; i != 64; ++i) | |
372 - rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); | |
373 - | |
374 - { | |
375 - ${Log::info("setup_device: general configuration done")}; | |
376 - } | |
377 - | |
378 - /* | |
379 - * Receive initialization (section 14.4): | |
380 - * | |
381 - * 1. Program the receive address, in RAL/RAH; | |
382 - * 2. Initialize the Multicast Table Array; | |
383 - * 3. Program the interrupt mask register (done in | |
384 - * e1000::activate_device_interruption); | |
385 - * 4. Allocate the receive descriptor ring and map it to make it | |
386 - * accessible by the device; | |
387 - * 5. Write the start address of the ring in RDBAL/RDBAH and set | |
388 - * RDLEN (Receive Descriptor Length) to the size of the ring; | |
389 - * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the | |
390 - * beginning and end of the ring; | |
391 - * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the | |
392 - * receive buffer size to 2048 bytes (e1000::rx_buffer_len). | |
393 - * 8. Set RCTL.EN to enable the receiver. | |
394 - * | |
395 - * The ugly casts here are caused by the lack of CNorm unstrict. | |
396 - */ | |
397 - | |
398 - /* 1. Program the receive address */ | |
399 - | |
400 - /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */ | |
401 - rtx_e1000_register_write32(hw_ctx, E1000_RAL, | |
402 - *(unsigned int *)(${rtx_ether_ctx.dev_addr})); | |
403 - /* | |
404 - * The 16 upper bits of RAH also store the AS bits (which should be | |
405 - * 0) and the AV bit (should be 1 to set the address as valid). | |
406 - */ | |
407 - rtx_e1000_register_write32(hw_ctx, E1000_RAH, | |
408 - *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4])); | |
409 - rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); | |
410 - | |
411 - { | |
412 - ${Log::info("setup_device: receive address programmed")}; | |
413 - } | |
414 - | |
415 - /* 2. Initialize the MTA */ | |
416 - | |
417 - for (i = 0; i != 128; ++i) | |
418 - rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); | |
419 - | |
420 - { | |
421 - ${Log::info("setup_device: MTA init done")}; | |
422 - } | |
423 - | |
424 - /* 4. Setup the receive descriptor ring */ | |
425 - | |
426 - /* Allocate the descriptors */ | |
427 - hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base); | |
428 - hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096); | |
429 - hw_ctx->rx_ring.base = dma_alloc_coherent( | |
430 - ${rtx_ether_ctx.device}, | |
431 - hw_ctx->rx_ring.size, | |
432 - &hw_ctx->rx_ring.dma_base, | |
433 - GFP_KERNEL); | |
434 - if (!hw_ctx->rx_ring.base) | |
435 - { | |
436 - ${Log::info("cannot allocate the descriptors for the rx ring")}; | |
437 - goto err_rx_ring_alloc; | |
438 - } | |
439 - | |
440 - { | |
441 - ${Log::info("setup_device: rx descriptors allocated")}; | |
442 - } | |
443 - | |
444 - /* | |
445 - * Allocate the skbuffs, map them for DMA, and write their address | |
446 - * in the corresponding descriptor. | |
447 - */ | |
448 - for (i = 0; i != ${config.rx_ring_size}; ++i) | |
449 - { | |
450 - hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb( | |
16 - ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */ | 451 - ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */ |
17 + ${rtx_ether_ctx.net_device.k_net_dev}, | 452 - ${config.rx_buffer_len}); |
18 ${config.rx_buffer_len}); | 453 - if (!hw_ctx->rx_ring.skbuffs[i].skbuff) |
19 if (!hw_ctx->rx_ring.skbuffs[i].skbuff) | 454 - { |
20 { | 455 - ${Log::info("cannot allocate a skbuff for the rx ring")}; |
456 - goto err_skbuffs_alloc; | |
457 - } | |
458 - hw_ctx->rx_ring.skbuffs[i].dma_handle = dma_map_single( | |
459 - ${rtx_ether_ctx.device}, | |
460 - (struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff, /* XXX leaking cast */ | |
461 - ${config.rx_buffer_len}, | |
462 - DMA_FROM_DEVICE); | |
463 - int dma_error = dma_mapping_error(${rtx_ether_ctx.device}, | |
464 - hw_ctx->rx_ring.skbuffs[i].dma_handle); | |
465 - if (dma_error) | |
466 - { | |
467 - ${Log::info("cannot dma-map a skbuff for the rx ring")}; | |
468 - goto err_skbuffs_map; | |
469 - } | |
470 - hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64( | |
471 - hw_ctx->rx_ring.skbuffs[i].skbuff); | |
472 - } | |
473 - | |
474 - ${Log::info("setup_device: skbuffs allocated")}; | |
475 - | |
476 - /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */ | |
477 - rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff); | |
478 - rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32); | |
479 - rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size); | |
480 - | |
481 - /* 6. Setup RDH/RDT */ | |
482 - rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0); | |
483 - rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1); | |
484 - | |
485 - /* 7. Configure the buffer size, */ | |
486 - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len}); | |
487 - | |
488 - /* 8. Enable the receiver */ | |
489 - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN); | |
490 - | |
491 - ${Log::info("setup_device: receive registers configured and receiver enabled")}; | |
492 - | |
493 - /* | |
494 - * Transmission initialization (section 14.5): | |
495 - * | |
496 - * 1. Allocate the transmit descriptors ring and map it to make it | |
497 - * accessible by the device; | |
498 - * 2. Write the start address of the ring in TDBAL/TDBAH and set | |
499 - * TDLEN to the size of the ring; | |
500 - * 3. Set the TDH/TDT indexes to the beginning and end of the ring; | |
501 - * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the | |
502 - * transmitter. | |
503 - */ | |
504 - | |
505 - /* | |
506 - * XXX: at this point we must be careful to not fuck up with i, or | |
507 - * we are going go have surprises in `err_skbuffs_alloc`. Maybe it's | |
508 - * time to separate the rx and tx initialization in two functions. | |
509 - */ | |
510 - | |
511 - /* 1. Allocate the tx ring */ | |
512 - hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base); | |
513 - hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096); | |
514 - hw_ctx->tx_ring.base = dma_alloc_coherent( | |
515 - ${rtx_ether_ctx.device}, | |
516 - hw_ctx->tx_ring.size, | |
517 - &hw_ctx->tx_ring.dma_base, | |
518 - GFP_KERNEL); | |
519 - if (!hw_ctx->rx_ring.base) | |
520 - { | |
521 - ${Log::info("cannot allocate the descriptors for the tx ring")}; | |
522 - goto err_tx_ring_alloc; | |
523 - } | |
524 - | |
525 - ${Log::info("setup_device: tx descriptors allocated")}; | |
526 - | |
527 - /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ | |
528 - rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, hw_ctx->tx_ring.dma_base & 0xffffffff); | |
529 - rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, hw_ctx->tx_ring.dma_base >> 32); | |
530 - rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size); | |
531 - | |
532 - /* 3. Setup TDH/TDT to zero: the queue is empty */ | |
533 - rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); | |
534 - rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); | |
535 - hw_ctx->tx_ring.head = 0; | |
536 - hw_ctx->tx_ring.tail = 0; | |
537 - | |
538 - /* 4. Set TCTL.PSP and enable the transmitter */ | |
539 - rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_EN); | |
540 - | |
541 - ${Log::info("transmit registers configured and transmitter enabled")}; | |
542 - | |
543 - /* | |
544 - * XXX: We can't return here since we are not in a function but in | |
545 - * a chunk of code (injected in a function). | |
546 - */ | |
547 - goto ok; | |
548 - | |
549 - err_tx_ring_alloc: | |
550 - /* | |
551 - * Likewise, always the same problem with error handling, we don't | |
552 - * know where we are at in the "parent context": | |
553 - */ | |
554 - err_skbuffs_alloc: | |
555 - while (i--) | |
556 - { | |
557 - dma_unmap_single( | |
558 - ${rtx_ether_ctx.device}, | |
559 - hw_ctx->rx_ring.skbuffs[i].dma_handle, | |
560 - ${config.rx_buffer_len}, | |
561 - DMA_FROM_DEVICE); | |
562 - err_skbuffs_map: | |
563 - /* XXX leaking cast: */ | |
564 - dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff); | |
565 - } | |
566 - | |
567 - dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size, | |
568 - hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); | |
569 - err_rx_ring_alloc: | |
570 - return -ENOMEM; | |
571 - | |
572 - ok: | |
573 - } | |
574 - } | |
575 - | |
576 /* TODO: | |
577 * | |
578 * Refactor into two methods (one in RxRing and one in TxRing) and make use | |
579 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti | |
580 --- a/rathaxes/samples/e1000/e1000.rti | |
581 +++ b/rathaxes/samples/e1000/e1000.rti | |
582 @@ -1,23 +1,10 @@ | |
583 -interface e1000 : Socket, Ethernet, PCI, LKM, Builtin | |
584 +interface e1000 : Socket, Ethernet, DMA, PCI, LKM, Builtin | |
585 { | |
586 required variable Builtin::number rx_ring_size; | |
587 required variable Builtin::number tx_ring_size; | |
588 required variable Builtin::number rx_buffer_len; | |
589 required variable Builtin::number tx_max_data_per_desc; | |
590 | |
591 - provided type Context | |
592 - { | |
593 - chunk Ethernet::HardwareContext(); | |
594 - decl data_types(); | |
595 - | |
596 - /* Callbacks/Hooks which should probably be in the front-end: */ | |
597 - chunk Ethernet::adapter_init_context(Ethernet::Device, | |
598 - Builtin::number, | |
599 - Builtin::symbol); | |
600 - chunk Ethernet::adapter_reset(Ethernet::Device); | |
601 - chunk Ethernet::adapter_load_mac_address(Ethernet::Device); | |
602 - } | |
603 - | |
604 provided type RxDescriptor | |
605 { | |
606 chunk LKM::includes(); | |
607 @@ -35,6 +22,32 @@ | |
608 { | |
609 decl data_types(); | |
610 method init(); | |
611 + | |
612 + /* XXX: Callback that should be in the front-end: */ | |
613 + chunk Ethernet::adapter_init_rx(Ethernet::Device); | |
614 + | |
615 + attribute DMA::DMAHandle.scalar dma_base; | |
616 + attribute Builtin::number.scalar size; | |
617 + } | |
618 + | |
619 + provided type Context | |
620 + { | |
621 + chunk Ethernet::HardwareContext(); | |
622 + decl data_types(); | |
623 + | |
624 + /* XXX: | |
625 + * These callbacks/Hooks which should probably be in the front-end. | |
626 + * Also, I'm not too happy about the names, it's difficult to make | |
627 + * the difference between the probe and open parts. | |
628 + */ | |
629 + chunk Ethernet::adapter_init_context(Ethernet::Device, | |
630 + Builtin::number, | |
631 + Builtin::symbol); | |
632 + chunk Ethernet::adapter_reset(Ethernet::Device); | |
633 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device); | |
634 + chunk Ethernet::adapter_setup(Ethernet::Device); | |
635 + | |
636 + attribute RxRing.scalar rx_ring; | |
637 } | |
638 | |
639 provided type TxRing | |
640 @@ -44,6 +57,9 @@ | |
641 decl data_types(); | |
642 method init(); | |
643 | |
644 + /* XXX: Callback that should be in the front-end: */ | |
645 + chunk Ethernet::adapter_init_tx(Ethernet::Device); | |
646 + | |
647 /* Clean the ring (i.e: move the head closer to the tail): */ | |
648 method clean(); | |
649 /* Return the number of clean descriptors left in the ring: */ | |
650 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt | |
651 --- a/rathaxes/samples/e1000/ethernet.blt | |
652 +++ b/rathaxes/samples/e1000/ethernet.blt | |
653 @@ -170,6 +170,9 @@ | |
654 ${Log::info("Cannot register the interrupt handler")}; | |
655 return error; | |
656 } | |
657 + ${pointcut Ethernet::adapter_setup(local.rtx_ether_ctx)}; | |
658 + ${pointcut Ethernet::adapter_init_rx(local.rtx_ether_ctx)}; | |
659 + ${pointcut Ethernet::adapter_init_tx(local.rtx_ether_ctx)}; | |
660 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; | |
661 | |
662 return 0; | |
663 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti | |
664 --- a/rathaxes/samples/e1000/ethernet.rti | |
665 +++ b/rathaxes/samples/e1000/ethernet.rti | |
666 @@ -52,6 +52,15 @@ | |
667 provided chunk LKM::includes(); | |
668 provided chunk LKM::prototypes(); | |
669 provided chunk LKM::code(); | |
670 + | |
671 + /* | |
672 + * For e1000, this part is documented in the Intel Gigabit Ethernet | |
673 + * Controller Software Developper manual. (You can find it in the | |
674 + * doc/hardware directory). | |
675 + */ | |
676 + provided pointcut Ethernet::adapter_setup(Ethernet::Device); | |
677 + provided pointcut Ethernet::adapter_init_rx(Ethernet::Device); | |
678 + provided pointcut Ethernet::adapter_init_tx(Ethernet::Device); | |
679 } | |
680 | |
681 required sequence send(Ethernet::Device, Socket::AbstractSKBuff) | |
682 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx | |
683 --- a/rathaxes/samples/e1000/lkm.rtx | |
684 +++ b/rathaxes/samples/e1000/lkm.rtx | |
685 @@ -4,10 +4,6 @@ | |
686 { | |
687 Log::info("opening the device"); | |
688 | |
689 - | |
690 - e1000::set_up_device(dev); | |
691 - Log::info("device activated"); | |
692 - | |
693 e1000::activate_device_interruption(dev); | |
694 Log::info("interruption enabled"); | |
695 | |
696 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti | |
697 --- a/rathaxes/samples/e1000/socket.rti | |
698 +++ b/rathaxes/samples/e1000/socket.rti | |
699 @@ -15,6 +15,10 @@ | |
700 decl data_types(); | |
701 method init(Socket::AbstractSKBuff); | |
702 method dump_infos(); | |
703 + /* | |
704 + * map_to and map_from return a non-zero value on failure (which | |
705 + * doesn't correspond to an errno value): | |
706 + */ | |
707 method map_to(Device::AbstractDevice); | |
708 method map_from(Device::AbstractDevice); | |
709 method unmap_to_and_free(Device::AbstractDevice); |