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);