1 | /** |
---|
2 | * @file |
---|
3 | */ |
---|
4 | |
---|
5 | /* |
---|
6 | * Copyright (c) 2013 embedded brains GmbH. All rights reserved. |
---|
7 | * |
---|
8 | * embedded brains GmbH |
---|
9 | * Dornierstr. 4 |
---|
10 | * 82178 Puchheim |
---|
11 | * Germany |
---|
12 | * <rtems@embedded-brains.de> |
---|
13 | * |
---|
14 | * The license and distribution terms for this file may be |
---|
15 | * found in the file LICENSE in this distribution or at |
---|
16 | * http://www.rtems./license/LICENSE. |
---|
17 | */ |
---|
18 | |
---|
19 | #ifndef DWMAC_COMMON_H_ |
---|
20 | #define DWMAC_COMMON_H_ |
---|
21 | |
---|
22 | #define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1 |
---|
23 | #define __BSD_VISIBLE 1 |
---|
24 | |
---|
25 | #include <stdint.h> |
---|
26 | #include <rtems.h> |
---|
27 | #include <rtems/rtems_bsdnet.h> |
---|
28 | #include <rtems/rtems_mii_ioctl.h> |
---|
29 | |
---|
30 | #include <sys/param.h> |
---|
31 | #include <sys/socket.h> |
---|
32 | #include <sys/sockio.h> |
---|
33 | #include <sys/mbuf.h> |
---|
34 | |
---|
35 | #include <net/if.h> |
---|
36 | #include <net/if_arp.h> |
---|
37 | #include <netinet/in.h> |
---|
38 | #include <netinet/if_ether.h> |
---|
39 | #include <netinet/in_systm.h> |
---|
40 | #include <netinet/ip.h> |
---|
41 | |
---|
42 | #include <libchip/dwmac.h> |
---|
43 | #include "dwmac-desc.h" |
---|
44 | #include "dwmac-regs.h" |
---|
45 | |
---|
46 | #ifdef __cplusplus |
---|
47 | extern "C" { |
---|
48 | #endif /* __cplusplus */ |
---|
49 | |
---|
50 | #define DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD 1 /* DMA STORE-AND-FORWARD Operation Mode */ |
---|
51 | |
---|
52 | /* Events */ |
---|
53 | /* Common task events */ |
---|
54 | #define DWMAC_COMMON_EVENT_TASK_INIT RTEMS_EVENT_1 |
---|
55 | #define DWMAC_COMMON_EVENT_TASK_STOP RTEMS_EVENT_2 |
---|
56 | |
---|
57 | /* Events for the transmit task */ |
---|
58 | #define DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME RTEMS_EVENT_3 |
---|
59 | #define DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED RTEMS_EVENT_4 |
---|
60 | #define DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD RTEMS_EVENT_5 |
---|
61 | #define DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE RTEMS_EVENT_6 |
---|
62 | |
---|
63 | /* Events for the receive task */ |
---|
64 | #define DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED RTEMS_EVENT_3 |
---|
65 | |
---|
66 | #ifdef __ARM_ARCH_7A__ |
---|
67 | #define DWMAC_COMMON_DSB() _ARM_Data_synchronization_barrier() |
---|
68 | #else /* __ARM_ARCH_7A__ */ |
---|
69 | #define DWMAC_COMMON_DSB() |
---|
70 | #endif /* __ARM_ARCH_7A__ */ |
---|
71 | |
---|
72 | /* Foreward declarations */ |
---|
73 | typedef struct dwmac_common_core_ops dwmac_common_core_ops; |
---|
74 | typedef struct dwmac_common_dma_ops dwmac_common_dma_ops; |
---|
75 | typedef struct dwmac_common_desc_ops dwmac_common_desc_ops; |
---|
76 | |
---|
77 | typedef enum { /* IPC status */ |
---|
78 | DWMAC_COMMON_RX_FRAME_STATUS_GOOD, |
---|
79 | DWMAC_COMMON_RX_FRAME_STATUS_DISCARD, |
---|
80 | DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE, |
---|
81 | DWMAC_COMMON_RX_FRAME_STATUS_LLC_SNAP |
---|
82 | } dwmac_common_rx_frame_status; |
---|
83 | |
---|
84 | typedef enum { |
---|
85 | DWMAC_COMMON_STATE_DOWN, |
---|
86 | DWMAC_COMMON_STATE_UP, |
---|
87 | |
---|
88 | DWMAC_COMMON_STATE_COUNT |
---|
89 | } dwmac_common_state; |
---|
90 | |
---|
91 | typedef struct { |
---|
92 | uint32_t link_down; |
---|
93 | uint32_t link_up; |
---|
94 | } dwmac_common_phy_status_counts; |
---|
95 | |
---|
96 | typedef struct { |
---|
97 | uint32_t receive; |
---|
98 | uint32_t transmit; |
---|
99 | uint32_t tx_underflow; |
---|
100 | uint32_t tx_jabber; |
---|
101 | uint32_t rx_overflow; |
---|
102 | uint32_t rx_early; |
---|
103 | uint32_t rx_buf_unav; |
---|
104 | uint32_t rx_process_stopped; |
---|
105 | uint32_t rx_watchdog; |
---|
106 | uint32_t tx_early; |
---|
107 | uint32_t tx_buf_unav; |
---|
108 | uint32_t tx_process_stopped; |
---|
109 | uint32_t fatal_bus_error; |
---|
110 | uint32_t unhandled; |
---|
111 | } dwmac_common_dma_irq_counts; |
---|
112 | |
---|
113 | typedef struct { |
---|
114 | uint32_t dest_addr_fail; /* When set, this bit indicates a frame that failed in the DA Filter in the MAC. */ |
---|
115 | uint32_t crc_error; /* When set, this bit indicates that a CRC error occurred on the received frame. This field is valid only when the Last |
---|
116 | Descriptor (RDES0[8]) is set. */ |
---|
117 | uint32_t receive_error; /* When set, this bit indicates that the gmii_rxer_i signal is asserted while gmii_rxdv_i is asserted during frame |
---|
118 | reception. Error can be of less or no extension, or error (rxd !=0xf) during extension. */ |
---|
119 | uint32_t watchdog_timeout; /* When set, this bit indicates that the receive Watchdog Timer has expired while receiving the current frame and the |
---|
120 | current frame is truncated after the Watchdog Timeout. */ |
---|
121 | uint32_t late_collision; /* When set, this bit indicates that a late collision has occurred while receiving the frame in the half-duplex mode. */ |
---|
122 | uint32_t giant_frame; /* When advanced timestamp feature is present, when set, this bit indicates that a snapshot of the Timestamp is |
---|
123 | written in descriptor words 6 (RDES6) and 7 (RDES7). This is valid only when the Last Descriptor bit (RDES0[8]) is |
---|
124 | set. |
---|
125 | When IP Checksum Engine (Type 1) is selected, this bit, when set, indicates that the 16-bit IPv4 Header checksum |
---|
126 | calculated by the EMAC did not match the received checksum bytes. |
---|
127 | Otherwise, this bit, when set, indicates the Giant frame Status. Giant frames are larger than 1,518-byte (or |
---|
128 | 1,522-byte for VLAN or 2,000-byte when Bit 27 (2KPE) of MAC Configuration register is set) normal frames and |
---|
129 | larger than 9,018-byte (9,022-byte for VLAN) frame when Jumbo frame processing is enabled. */ |
---|
130 | uint32_t overflow_error; /* When set, this bit indicates that the received frame was damaged because of buffer overflow in MTL. |
---|
131 | Note: This bit is set only when the DMA transfers a partial frame to the application. This happens only when the RX |
---|
132 | FIFO buffer is operating in the threshold mode. In the store-and-forward mode, all partial frames are dropped |
---|
133 | completely in RX FIFO buffer. */ |
---|
134 | uint32_t descriptor_error; /* When set, this bit indicates a frame truncation caused by a frame that does not fit within the current descriptor |
---|
135 | buffers, and that the DMA does not own the Next descriptor. The frame is truncated. This field is valid only when the |
---|
136 | Last Descriptor (RDES0[8]) is set. */ |
---|
137 | uint32_t source_addr_fail; /* When set, this bit indicates that the SA field of frame failed the SA Filter in the MAC. */ |
---|
138 | uint32_t length_error; /* When set, this bit indicates that the actual length of the frame received and that the Length/ Type field does not |
---|
139 | match. This bit is valid only when the Frame Type (RDES0[5]) bit is reset. */ |
---|
140 | uint32_t vlan_tag; /* When set, this bit indicates that the frame to which this descriptor is pointing is a VLAN frame tagged by the MAC. |
---|
141 | The VLAN tagging depends on checking the VLAN fields of received frame based on the Register 7 (VLAN Tag |
---|
142 | Register) setting. */ |
---|
143 | uint32_t ethernet_frames; /* When set, this bit indicates that the receive frame is an Ethernet-type frame (the LT field is greater than or equal to |
---|
144 | 0x0600). When this bit is reset, it indicates that the received frame is an IEEE802.3 frame. This bit is not valid for |
---|
145 | Runt frames less than 14 bytes. */ |
---|
146 | uint32_t dribble_bit_error; /* When set, this bit indicates that the received frame has a non-integer multiple of bytes (odd nibbles). This bit is valid |
---|
147 | only in the MII Mode. */ |
---|
148 | } dwmac_common_desc_status_counts_rx; |
---|
149 | |
---|
150 | typedef struct { |
---|
151 | uint32_t jabber; /* When set, this bit indicates the MAC transmitter has experienced a jabber time-out. This bit is only set when Bit 22 |
---|
152 | (Jabber Disable) of Register 0 (MAC Configuration Register) is not set. */ |
---|
153 | uint32_t frame_flushed; /* When set, this bit indicates that the DMA or MTL flushed the frame because of a software Flush command given by |
---|
154 | the CPU. */ |
---|
155 | uint32_t losscarrier; /* When set, this bit indicates that a loss of carrier occurred during frame transmission (that is, the gmii_crs_i |
---|
156 | signal was inactive for one or more transmit clock periods during frame transmission). This is valid only for the |
---|
157 | frames transmitted without collision when the MAC operates in the half-duplex mode. */ |
---|
158 | uint32_t no_carrier; /* When set, this bit indicates that the Carrier Sense signal form the PHY was not asserted during transmission. */ |
---|
159 | uint32_t excessive_collisions; /* When set, this bit indicates that the transmission was aborted after 16 successive collisions while attempting to |
---|
160 | transmit the current frame. If Bit 9 (Disable Retry) bit in the Register 0 (MAC Configuration Register) is set, this bit |
---|
161 | is set after the first collision, and the transmission of the frame is aborted. */ |
---|
162 | uint32_t excessive_deferral; /* When set, this bit indicates that the transmission has ended because of excessive deferral of over 24,288 bit times |
---|
163 | (155,680 bits times in 1,000-Mbps mode or if Jumbo frame is enabled) if Bit 4 (Deferral Check) bit in Register 0 |
---|
164 | (MAC Configuration Register) is set high. */ |
---|
165 | uint32_t underflow; /* When set, this bit indicates that the MAC aborted the frame because the data arrived late from the Host memory. |
---|
166 | Underflow Error indicates that the DMA encountered an empty transmit buffer while transmitting the frame. The |
---|
167 | transmission process enters the Suspended state and sets both Transmit Underflow (Register 5[5]) and Transmit |
---|
168 | Interrupt (Register 5[0]). */ |
---|
169 | uint32_t ip_header_error; /* When set, this bit indicates that the MAC transmitter detected an error in the IP datagram header. The transmitter |
---|
170 | checks the header length in the IPv4 packet against the number of header bytes received from the application and |
---|
171 | indicates an error status if there is a mismatch. For IPv6 frames, a header error is reported if the main header length |
---|
172 | is not 40 bytes. Furthermore, the Ethernet Length/Type field value for an IPv4 or IPv6 frame must match the IP |
---|
173 | header version received with the packet. For IPv4 frames, an error status is also indicated if the Header Length field |
---|
174 | has a value less than 0x5. */ |
---|
175 | uint32_t payload_error; /* When set, this bit indicates that MAC transmitter detected an error in the TCP, UDP, or ICMP IP datagram payload. |
---|
176 | The transmitter checks the payload length received in the IPv4 or IPv6 header against the actual number of TCP, |
---|
177 | UDP, or ICMP packet bytes received from the application and issues an error status in case of a mismatch. */ |
---|
178 | uint32_t deferred; /* When set, this bit indicates that the MAC defers before transmission because of the presence of carrier. This bit is |
---|
179 | valid only in the half-duplex mode. */ |
---|
180 | uint32_t vlan; /* When set, this bit indicates that the transmitted frame is a VLAN-type frame. */ |
---|
181 | } dwmac_common_desc_status_counts_tx; |
---|
182 | |
---|
183 | typedef struct { |
---|
184 | uint32_t errors; /* Frames with errors */ |
---|
185 | uint32_t dropped; /* Frames dropped */ |
---|
186 | uint32_t frames_good; /* Frames passed to the network stack */ |
---|
187 | uint32_t bytes_good; /* Sum of bytes passed to the network stack */ |
---|
188 | uint32_t frames; /* Frames handled (good or bad) */ |
---|
189 | uint32_t dma_suspended; /* The receive DMA was supended due to lack of descriptors */ |
---|
190 | } dwmac_common_rx_frame_counts; |
---|
191 | |
---|
192 | typedef struct { |
---|
193 | uint32_t frames_from_stack; /* Frames received from the network stack fro tranmission */ |
---|
194 | uint32_t frames_to_dma; /* Number of frames transmitted to DMA */ |
---|
195 | uint32_t packets_to_dma; /* Number of packets transmitted to DMA*/ |
---|
196 | uint32_t bytes_to_dma; /* Number of bytes transmitted */ |
---|
197 | uint32_t packet_errors; /* Packets with errors */ |
---|
198 | uint32_t packets_tranmitted_by_DMA; /* Packets tranmitted by the DMA */ |
---|
199 | } dwmac_common_tx_frame_counts; |
---|
200 | |
---|
201 | typedef struct { |
---|
202 | dwmac_common_phy_status_counts phy_status_counts; |
---|
203 | dwmac_common_dma_irq_counts dma_irq_counts; |
---|
204 | dwmac_common_desc_status_counts_rx desc_status_counts_rx; |
---|
205 | dwmac_common_desc_status_counts_tx desc_status_counts_tx; |
---|
206 | dwmac_common_rx_frame_counts frame_counts_rx; |
---|
207 | dwmac_common_tx_frame_counts frame_counts_tx; |
---|
208 | } dwmac_common_stats; |
---|
209 | |
---|
210 | typedef struct { |
---|
211 | struct arpcom arpcom; |
---|
212 | struct rtems_bsdnet_ifconfig *bsd_config; |
---|
213 | struct rtems_mdio_info mdio; |
---|
214 | rtems_id task_id_rx; |
---|
215 | rtems_id task_id_tx; |
---|
216 | rtems_id task_id_control; |
---|
217 | void *arg; |
---|
218 | volatile macgrp *macgrp; |
---|
219 | volatile dmagrp *dmagrp; |
---|
220 | unsigned int csr_clock; |
---|
221 | dwmac_common_state state; |
---|
222 | dwmac_common_stats stats; |
---|
223 | unsigned int dma_threshold_control; |
---|
224 | volatile dwmac_desc *dma_tx; |
---|
225 | volatile dwmac_desc *dma_rx; |
---|
226 | unsigned int idx_rx; |
---|
227 | struct mbuf **mbuf_addr_rx; |
---|
228 | struct mbuf **mbuf_addr_tx; |
---|
229 | const dwmac_cfg *CFG; |
---|
230 | int MDIO_BUS_ADDR; |
---|
231 | } dwmac_common_context; |
---|
232 | |
---|
233 | struct dwmac_common_core_ops { |
---|
234 | /* MAC core initialization */ |
---|
235 | void (*core_init) ( dwmac_common_context *self ); |
---|
236 | |
---|
237 | /* Multicast filter setting */ |
---|
238 | void (*set_hash_filter) ( |
---|
239 | dwmac_common_context *self, |
---|
240 | const bool add, |
---|
241 | struct ifreq *ifr ); |
---|
242 | |
---|
243 | /* Set/Get Unicast MAC addresses */ |
---|
244 | void (*set_umac_addr) ( |
---|
245 | dwmac_common_context *ioaddr, |
---|
246 | const unsigned char *addr, |
---|
247 | const unsigned int reg_n ); |
---|
248 | }; |
---|
249 | |
---|
250 | struct dwmac_common_dma_ops { |
---|
251 | /* DMA core initialization */ |
---|
252 | int (*init) ( |
---|
253 | dwmac_common_context *self, |
---|
254 | const uint32_t pbl, |
---|
255 | const uint32_t fb, |
---|
256 | const uint32_t mb, |
---|
257 | const bool use_enhanced_desc, |
---|
258 | const uint32_t burst_len_4_support, |
---|
259 | const uint32_t burst_len_8_support, |
---|
260 | const uint32_t burst_len_16_support, |
---|
261 | const uint32_t burst_boundary, |
---|
262 | volatile dwmac_desc *dma_tx, |
---|
263 | volatile dwmac_desc *dma_rx ); |
---|
264 | |
---|
265 | /* Set tx/rx threshold in the csr6 register |
---|
266 | * An invalid value enables the store-and-forward mode */ |
---|
267 | void (*dma_mode) ( |
---|
268 | dwmac_common_context *self, |
---|
269 | const unsigned int txmode, |
---|
270 | const unsigned int rxmode ); |
---|
271 | }; |
---|
272 | |
---|
273 | struct dwmac_common_desc_ops { |
---|
274 | /* Verify that it is OK to use the selected descriptor operations */ |
---|
275 | int (*validate) ( dwmac_common_context *self ); |
---|
276 | bool (*use_enhanced_descs) ( dwmac_common_context *self ); |
---|
277 | |
---|
278 | /* DMA RX descriptor ring allocation */ |
---|
279 | int (*create_rx_desc) ( dwmac_common_context *self ); |
---|
280 | |
---|
281 | /* DMA TX descriptor ring allocation */ |
---|
282 | int (*create_tx_desc) ( dwmac_common_context *self ); |
---|
283 | |
---|
284 | /* Free DMA RX descriptor ring */ |
---|
285 | int (*destroy_rx_desc) ( dwmac_common_context *self ); |
---|
286 | |
---|
287 | /* Free DMA TX descriptor ring */ |
---|
288 | int (*destroy_tx_desc) ( dwmac_common_context *self ); |
---|
289 | |
---|
290 | /* DMA RX descriptor initialization */ |
---|
291 | void (*init_rx_desc) ( |
---|
292 | dwmac_common_context *self, |
---|
293 | const unsigned int index ); |
---|
294 | |
---|
295 | /* DMA TX descriptor ring initialization */ |
---|
296 | void (*init_tx_desc) ( dwmac_common_context *self ); |
---|
297 | |
---|
298 | /* Free rx data buffers */ |
---|
299 | void (*release_rx_bufs) ( dwmac_common_context *self ); |
---|
300 | |
---|
301 | /* Allocate a data buffer */ |
---|
302 | struct mbuf *(*alloc_data_buf)( dwmac_common_context *self ); |
---|
303 | |
---|
304 | /* Free tx data buffers */ |
---|
305 | void (*release_tx_bufs) ( dwmac_common_context *self ); |
---|
306 | |
---|
307 | /* Invoked by the xmit function to prepare the tx descriptor */ |
---|
308 | void (*prepare_tx_desc) ( |
---|
309 | dwmac_common_context *self, |
---|
310 | const unsigned int idx, |
---|
311 | const bool is_first, |
---|
312 | const size_t len, |
---|
313 | const void *pdata ); |
---|
314 | |
---|
315 | /* Set/get the owner of the descriptor */ |
---|
316 | void (*release_tx_ownership) ( |
---|
317 | dwmac_common_context *self, |
---|
318 | const unsigned int idx_tx ); |
---|
319 | bool (*am_i_tx_owner) ( |
---|
320 | dwmac_common_context *self, |
---|
321 | const unsigned int idx_tx ); |
---|
322 | |
---|
323 | /* Invoked by the xmit function to close the tx descriptor */ |
---|
324 | void (*close_tx_desc) ( |
---|
325 | dwmac_common_context *self, |
---|
326 | const unsigned int idx_tx ); |
---|
327 | |
---|
328 | /* Clean the tx descriptor as soon as the tx irq is received */ |
---|
329 | void (*release_tx_desc) ( |
---|
330 | dwmac_common_context *self, |
---|
331 | const unsigned int idx_tx ); |
---|
332 | |
---|
333 | /* Last tx segment reports the transmit status */ |
---|
334 | int (*get_tx_ls) ( |
---|
335 | dwmac_common_context *self, |
---|
336 | const unsigned int idx_tx ); |
---|
337 | |
---|
338 | /* Return the transmit status looking at the TDES1 */ |
---|
339 | int (*tx_status) ( |
---|
340 | dwmac_common_context *self, |
---|
341 | const unsigned int idx_tx ); |
---|
342 | |
---|
343 | /* Handle extra events on specific interrupts hw dependent */ |
---|
344 | bool (*am_i_rx_owner) ( |
---|
345 | dwmac_common_context *self, |
---|
346 | const unsigned int desc_idx ); |
---|
347 | |
---|
348 | /* Get the receive frame size */ |
---|
349 | size_t (*get_rx_frame_len) ( |
---|
350 | dwmac_common_context *self, |
---|
351 | const unsigned int desc_idx ); |
---|
352 | |
---|
353 | /* Return the reception status looking at the RDES1 */ |
---|
354 | dwmac_common_rx_frame_status (*rx_status) ( |
---|
355 | dwmac_common_context *self, |
---|
356 | const unsigned int desc_idx ); |
---|
357 | bool (*is_first_rx_segment) ( |
---|
358 | dwmac_common_context *self, |
---|
359 | const unsigned int descriptor_index ); |
---|
360 | bool (*is_last_rx_segment) ( |
---|
361 | dwmac_common_context *self, |
---|
362 | const unsigned int descriptor_index ); |
---|
363 | void (*print_tx_desc) ( |
---|
364 | volatile dwmac_desc *p, |
---|
365 | const unsigned int count ); |
---|
366 | void (*print_rx_desc) ( |
---|
367 | volatile dwmac_desc *p, |
---|
368 | const unsigned int count ); |
---|
369 | }; |
---|
370 | |
---|
371 | #ifdef __cplusplus |
---|
372 | } |
---|
373 | #endif /* __cplusplus */ |
---|
374 | |
---|
375 | #endif /* DWMAC_COMMON_H_ */ |
---|