Mercurial > archived > louis > epitech > mq > rathaxes
comparison e1000_initialize_transmission.patch @ 83:27f0e70df342
Wip on the transmission, tx init done, and tx hooked from Ethernet send
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Sun, 08 Jul 2012 10:00:25 +0200 |
parents | 71f76c0f235f |
children |
comparison
equal
deleted
inserted
replaced
82:71f76c0f235f | 83:27f0e70df342 |
---|---|
1 # HG changeset patch | 1 # HG changeset patch |
2 # Parent 1328cb41b1bb4d39588c1934c841b3e4362f7413 | 2 # Parent e2e48ad161482555c5e87550e76cf15ef7fdbd3e |
3 rathaxes: initialize transmission on the e1000 sample: | 3 rathaxes: initialize transmission on the e1000 sample: |
4 | 4 |
5 - This is documented in details in the sections 14.5 and 3.3 of the | 5 - This is documented in details in the sections 14.5 and 3.3 of the |
6 Intel Gigabit Controller Software Developer manual. | 6 Intel Gigabit Controller Software Developer manual. |
7 | 7 |
8 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt | 8 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt |
9 --- a/rathaxes/samples/e1000/e1000.blt | 9 --- a/rathaxes/samples/e1000/e1000.blt |
10 +++ b/rathaxes/samples/e1000/e1000.blt | 10 +++ b/rathaxes/samples/e1000/e1000.blt |
11 @@ -34,6 +34,24 @@ | 11 @@ -34,6 +34,59 @@ |
12 } | |
13 } | 12 } |
14 | 13 |
15 + template type e1000:TxDescriptor() | 14 /* |
15 + * This is a generic tx descriptor for the e1000. When you use TCP | |
16 + * Segmentation Offload (TSO) the hardware actually uses two types of | |
17 + * tx descriptors in its tx ring: | |
18 + * - context descriptors: this descriptor doesn't actually point to data to | |
19 + * send but initialize the offloading engine for the data descriptor that | |
20 + * follow; | |
21 + * - data descriptors: this descriptor points to data from the skbuffs. | |
22 + */ | |
23 + template type e1000::TxDescriptor() | |
16 + { | 24 + { |
17 + chunk LKM:includes() | 25 + chunk LKM::includes() |
18 + { | 26 + { |
19 + typedef int ${e1000:TxDescriptor}; | 27 + static const ${e1000::TxDescriptor} force_rtx_e1000_tx_descriptor_decl; |
20 + | |
21 + static const ${e1000:TxDescriptor} force_rtx_e1000_tx_descriptor_decl; | |
22 + } | 28 + } |
23 + | 29 + |
24 + chunk ::decl() | 30 + chunk ::decl() |
25 + { | 31 + { |
26 + typedef struct rtx_e1000_tx_descriptor | 32 + typedef struct rtx_e1000_tx_descriptor |
27 + { | 33 + { |
28 + | 34 + unsigned long int /* __le64 */ buff_addr; |
29 + } | 35 + union |
36 + { | |
37 + unsigned int /* __le32 */ data; | |
38 + struct | |
39 + { | |
40 + unsigned short /* __le16 */ length; | |
41 + unsigned char csum_offset; /* CSO */ | |
42 + unsigned char cmd; | |
43 + } fields; | |
44 + } lower; | |
45 + union | |
46 + { | |
47 + unsigned int /* __le32 */ data; | |
48 + struct | |
49 + { | |
50 + unsigned char status; | |
51 + unsigned char csum_start; /* CSS */ | |
52 + unsigned short /* __le16 */ special; | |
53 + } fields; | |
54 + } upper; | |
55 + } *rtx_e1000_tx_descriptor_p; | |
56 + } | |
57 + | |
58 + chunk ::init() | |
59 + { | |
60 + } | |
61 + | |
62 + map | |
63 + { | |
30 + } | 64 + } |
31 + } | 65 + } |
32 + | 66 + |
33 /* | 67 + /* |
34 * Ring of e1000::RxDescriptors and their corresponding skbuffs. | 68 * Ring of e1000::RxDescriptors and their corresponding skbuffs. |
35 * | 69 * |
36 @@ -103,6 +121,7 @@ | 70 * - size: total size of the ring in bytes. |
71 @@ -73,6 +126,43 @@ | |
72 } | |
73 } | |
74 | |
75 + /* | |
76 + * Ring of e1000::TxDescriptors, this is a bit similar to the Rx ring except | |
77 + * that we don't really have to manage the skbuffs themselves (they are | |
78 + * given to use by the kernel). | |
79 + * | |
80 + * - size: total size of the ring in bytes. | |
81 + * - base: address of the ring (we can't use the typedef here until we get | |
82 + * CNorm unstrict); | |
83 + * - dma_base: (physical) address of the ring where the device can access | |
84 + * the different descriptors. | |
85 + */ | |
86 + template type e1000::TxRing() | |
87 + { | |
88 + chunk LKM::includes() | |
89 + { | |
90 + static const ${e1000::TxRing} force_rtx_e1000_tx_ring_decl; | |
91 + } | |
92 + | |
93 + chunk ::decl() | |
94 + { | |
95 + struct rtx_e1000_tx_ring | |
96 + { | |
97 + unsigned int size; | |
98 + struct rtx_e1000_tx_descriptor *base; | |
99 + void* /* dma_addr_t */ dma_base; | |
100 + }; | |
101 + } | |
102 + | |
103 + chunk ::init() | |
104 + { | |
105 + } | |
106 + | |
107 + map | |
108 + { | |
109 + } | |
110 + } | |
111 + | |
112 template type e1000::Context() | |
113 { | |
114 chunk LKM::includes() | |
115 @@ -99,6 +189,7 @@ | |
37 | 116 |
38 /* we can't use the Rathaxes type here (#8) */ | 117 /* we can't use the Rathaxes type here (#8) */ |
39 struct rtx_e1000_rx_ring rx_ring; | 118 struct rtx_e1000_rx_ring rx_ring; |
40 + struct rtx_e1000_tx_ring tx_ring; | 119 + struct rtx_e1000_tx_ring tx_ring; |
41 } *rtx_e1000_ctx_p; | 120 } *rtx_e1000_ctx_p; |
42 } | 121 } |
43 | 122 |
44 @@ -736,6 +755,20 @@ | 123 @@ -139,6 +230,7 @@ |
124 E1000_FCT = 0x00030, /* Flow Control Type */ | |
125 E1000_RCTL = 0x00100, /* Receive Control */ | |
126 E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value */ | |
127 + E1000_TCTL = 0x00400, /* Transmit Control */ | |
128 E1000_CRCERRS = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */ | |
129 E1000_RAL = 0x05400, /* Receive Address Low */ | |
130 E1000_RAH = 0x05404, /* Receive Address High */ | |
131 @@ -148,6 +240,11 @@ | |
132 E1000_RDLEN = 0x02808, /* Receive Descriptor Length */ | |
133 E1000_RDH = 0x02810, /* Receive Descriptor Head */ | |
134 E1000_RDT = 0x02818, /* Receive Descriptor Tail */ | |
135 + E1000_TDBAL = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */ | |
136 + E1000_TDBAH = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */ | |
137 + E1000_TDLEN = 0x03808, /* Transmit Descriptor Length */ | |
138 + E1000_TDH = 0x03810, /* Transmit Descriptor Head */ | |
139 + E1000_TDT = 0x03818, /* Transmit Descriptor Tail */ | |
140 }; | |
141 } | |
142 | |
143 @@ -226,6 +323,8 @@ | |
144 E1000_RCTL_BSIZE_4096 = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)), | |
145 E1000_RCTL_BSIZE_8192 = (E1000_RCTL_BSEX | (1 << 17)), | |
146 E1000_RCTL_BSIZE_16384 = (E1000_RCTL_BSEX | (1 << 16)), | |
147 + E1000_TCTL_EN = (1 << 1), /* Transmitter Enable */ | |
148 + E1000_TCTL_PSP = (1 << 3), /* Pad Short Packet */ | |
149 }; | |
150 } | |
151 | |
152 @@ -728,11 +827,64 @@ | |
45 } | 153 } |
46 | 154 |
47 /* | 155 /* |
48 + * Transmission initialization (section 14.5): | 156 + * Transmission initialization (section 14.5): |
49 + * | 157 + * |
54 + * 3. Set the TDH/TDT indexes to the beginning and end of the ring; | 162 + * 3. Set the TDH/TDT indexes to the beginning and end of the ring; |
55 + * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the | 163 + * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the |
56 + * transmitter. | 164 + * transmitter. |
57 + */ | 165 + */ |
58 + | 166 + |
167 + /* | |
168 + * XXX: at this point we must be careful to not fuck up with i, or | |
169 + * we are going go have surprises in `err_skbuffs_alloc`. Maybe it's | |
170 + * time to separate the rx and tx initialization in two functions. | |
171 + */ | |
172 + | |
59 + /* 1. Allocate the tx ring */ | 173 + /* 1. Allocate the tx ring */ |
174 + hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base); | |
175 + hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096); | |
176 + hw_ctx->tx_ring.base = dma_alloc_coherent( | |
177 + &${ctx}->pci_dev->dev, | |
178 + hw_ctx->tx_ring.size, | |
179 + (dma_addr_t *)&hw_ctx->tx_ring.dma_base, | |
180 + GFP_KERNEL); | |
181 + if (!hw_ctx->rx_ring.base) | |
182 + { | |
183 + ${Log::info("cannot allocate the descriptors for the tx ring")}; | |
184 + goto err_tx_ring_alloc; | |
185 + } | |
186 + | |
187 + { | |
188 + ${Log::info("setup_device: tx descriptors allocated")}; | |
189 + } | |
190 + | |
191 + /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ | |
192 + rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, (dma_addr_t)hw_ctx->tx_ring.dma_base & 0xffffffff); | |
193 + rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, (dma_addr_t)hw_ctx->tx_ring.dma_base >> 32); | |
194 + rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size); | |
195 + | |
196 + /* 3. Setup TDH/TDT to zero: the queue is empty */ | |
197 + rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); | |
198 + rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); | |
199 + | |
200 + /* 4. Set TCTL.PSP and enable the transmitter */ | |
201 + rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_PSP); | |
202 + | |
203 + { | |
204 + ${Log::info("transmit registers configured and transmitter enabled")}; | |
205 + } | |
60 + | 206 + |
61 + /* | 207 + /* |
62 * XXX: We can't return here since we are not in a function but in | 208 * XXX: We can't return here since we are not in a function but in |
63 * a chunk of code (injected in a function). | 209 * a chunk of code (injected in a function). |
64 */ | 210 */ |
211 goto ok; | |
212 | |
213 + err_tx_ring_alloc: | |
214 /* | |
215 * Likewise, always the same problem with error handling, we don't | |
216 * know where we are at in the "parent context": | |
217 @@ -788,6 +940,15 @@ | |
218 ${Log::info("free_rx_tx: rx ring free'ed")}; | |
219 } | |
220 | |
221 + /* | |
222 + * Free the tx ring: | |
223 + * - Free the descriptors array. | |
224 + */ | |
225 + dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->tx_ring.size, | |
226 + hw_ctx->tx_ring.base, (dma_addr_t)hw_ctx->tx_ring.dma_base); | |
227 + { | |
228 + ${Log::info("free_rx_tx: tx ring free'ed")}; | |
229 + } | |
230 } | |
231 } | |
232 | |
233 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti | |
234 --- a/rathaxes/samples/e1000/e1000.rti | |
235 +++ b/rathaxes/samples/e1000/e1000.rti | |
236 @@ -2,7 +2,9 @@ | |
237 { | |
238 provided type e1000::Context; | |
239 provided type e1000::RxDescriptor; | |
240 + provided type e1000::TxDescriptor; | |
241 provided type e1000::RxRing; | |
242 + provided type e1000::TxRing; | |
243 | |
244 /* | |
245 * These two types should actually be registers definitions in the frontend: | |
246 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx | |
247 --- a/rathaxes/samples/e1000/lkm.rtx | |
248 +++ b/rathaxes/samples/e1000/lkm.rtx | |
249 @@ -73,6 +73,7 @@ | |
250 Ethernet::ifname = "rtx%d"; | |
251 | |
252 e1000::rx_ring_size = 256; /* Number of incoming packets we can buffer */ | |
253 + e1000::tx_ring_size = 256; /* Mumber of buffers we can have in the tx queue */ | |
254 /* | |
255 * The e1000 supports seven receive buffer sizes: 256, 512, 1024, 2048, | |
256 * 4096, 8192 and 16384 bytes: |