1/*-
2 *   BSD LICENSE
3 *
4 *   Copyright (c) 2015 - 2016 CESNET
5 *   All rights reserved.
6 *
7 *   Redistribution and use in source and binary forms, with or without
8 *   modification, are permitted provided that the following conditions
9 *   are met:
10 *
11 *     * Redistributions of source code must retain the above copyright
12 *       notice, this list of conditions and the following disclaimer.
13 *     * Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *     * Neither the name of CESNET nor the names of its
18 *       contributors may be used to endorse or promote products derived
19 *       from this software without specific prior written permission.
20 *
21 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#ifndef RTE_PMD_SZEDATA2_H_
35#define RTE_PMD_SZEDATA2_H_
36
37#include <stdbool.h>
38
39#include <rte_byteorder.h>
40
41/* PCI Vendor ID */
42#define PCI_VENDOR_ID_NETCOPE 0x1b26
43
44/* PCI Device IDs */
45#define PCI_DEVICE_ID_NETCOPE_COMBO80G 0xcb80
46#define PCI_DEVICE_ID_NETCOPE_COMBO100G 0xc1c1
47#define PCI_DEVICE_ID_NETCOPE_COMBO100G2 0xc2c1
48
49/* number of PCI resource used by COMBO card */
50#define PCI_RESOURCE_NUMBER 0
51
52/* szedata2_packet header length == 4 bytes == 2B segment size + 2B hw size */
53#define RTE_SZE2_PACKET_HEADER_SIZE 4
54
55#define RTE_SZE2_MMIO_MAX 10
56
57/*!
58 * Round 'what' to the nearest larger (or equal) multiple of '8'
59 * (szedata2 packet is aligned to 8 bytes)
60 */
61#define RTE_SZE2_ALIGN8(what) (((what) + ((8) - 1)) & (~((8) - 1)))
62
63/*! main handle structure */
64struct szedata {
65	int fd;
66	struct sze2_instance_info *info;
67	uint32_t *write_size;
68	void *space[RTE_SZE2_MMIO_MAX];
69	struct szedata_lock lock[2][2];
70
71	__u32 *rx_asize, *tx_asize;
72
73	/* szedata_read_next variables - to keep context (ct) */
74
75	/*
76	 * rx
77	 */
78	/** initial sze lock ptr */
79	const struct szedata_lock   *ct_rx_lck_orig;
80	/** current sze lock ptr (initial or next) */
81	const struct szedata_lock   *ct_rx_lck;
82	/** remaining bytes (not read) within current lock */
83	unsigned int                ct_rx_rem_bytes;
84	/** current pointer to locked memory */
85	unsigned char               *ct_rx_cur_ptr;
86	/**
87	 * allocated buffer to store RX packet if it was split
88	 * into 2 buffers
89	 */
90	unsigned char               *ct_rx_buffer;
91	/** registered function to provide filtering based on hwdata */
92	int (*ct_rx_filter)(u_int16_t hwdata_len, u_char *hwdata);
93
94	/*
95	 * tx
96	 */
97	/**
98	 * buffer for tx - packet is prepared here
99	 * (in future for burst write)
100	 */
101	unsigned char               *ct_tx_buffer;
102	/** initial sze TX lock ptrs - number according to TX interfaces */
103	const struct szedata_lock   **ct_tx_lck_orig;
104	/** current sze TX lock ptrs - number according to TX interfaces */
105	const struct szedata_lock   **ct_tx_lck;
106	/** already written bytes in both locks */
107	unsigned int                *ct_tx_written_bytes;
108	/** remaining bytes (not written) within current lock */
109	unsigned int                *ct_tx_rem_bytes;
110	/** current pointers to locked memory */
111	unsigned char               **ct_tx_cur_ptr;
112	/** NUMA node closest to PCIe device, or -1 */
113	int                         numa_node;
114};
115
116/*
117 * @return Byte from PCI resource at offset "offset".
118 */
119static inline uint8_t
120pci_resource_read8(struct rte_mem_resource *rsc, uint32_t offset)
121{
122	return *((uint8_t *)((uint8_t *)rsc->addr + offset));
123}
124
125/*
126 * @return Two bytes from PCI resource starting at offset "offset".
127 */
128static inline uint16_t
129pci_resource_read16(struct rte_mem_resource *rsc, uint32_t offset)
130{
131	return rte_le_to_cpu_16(*((uint16_t *)((uint8_t *)rsc->addr +
132					       offset)));
133}
134
135/*
136 * @return Four bytes from PCI resource starting at offset "offset".
137 */
138static inline uint32_t
139pci_resource_read32(struct rte_mem_resource *rsc, uint32_t offset)
140{
141	return rte_le_to_cpu_32(*((uint32_t *)((uint8_t *)rsc->addr +
142					       offset)));
143}
144
145/*
146 * @return Eight bytes from PCI resource starting at offset "offset".
147 */
148static inline uint64_t
149pci_resource_read64(struct rte_mem_resource *rsc, uint32_t offset)
150{
151	return rte_le_to_cpu_64(*((uint64_t *)((uint8_t *)rsc->addr +
152					       offset)));
153}
154
155/*
156 * Write one byte to PCI resource address space at offset "offset".
157 */
158static inline void
159pci_resource_write8(struct rte_mem_resource *rsc, uint32_t offset, uint8_t val)
160{
161	*((uint8_t *)((uint8_t *)rsc->addr + offset)) = val;
162}
163
164/*
165 * Write two bytes to PCI resource address space at offset "offset".
166 */
167static inline void
168pci_resource_write16(struct rte_mem_resource *rsc, uint32_t offset,
169		     uint16_t val)
170{
171	*((uint16_t *)((uint8_t *)rsc->addr + offset)) = rte_cpu_to_le_16(val);
172}
173
174/*
175 * Write four bytes to PCI resource address space at offset "offset".
176 */
177static inline void
178pci_resource_write32(struct rte_mem_resource *rsc, uint32_t offset,
179		     uint32_t val)
180{
181	*((uint32_t *)((uint8_t *)rsc->addr + offset)) = rte_cpu_to_le_32(val);
182}
183
184/*
185 * Write eight bytes to PCI resource address space at offset "offset".
186 */
187static inline void
188pci_resource_write64(struct rte_mem_resource *rsc, uint32_t offset,
189		     uint64_t val)
190{
191	*((uint64_t *)((uint8_t *)rsc->addr + offset)) = rte_cpu_to_le_64(val);
192}
193
194#define SZEDATA2_PCI_RESOURCE_PTR(rsc, offset, type) \
195	((type)(((uint8_t *)(rsc)->addr) + (offset)))
196
197enum szedata2_link_speed {
198	SZEDATA2_LINK_SPEED_DEFAULT = 0,
199	SZEDATA2_LINK_SPEED_10G,
200	SZEDATA2_LINK_SPEED_40G,
201	SZEDATA2_LINK_SPEED_100G,
202};
203
204enum szedata2_mac_check_mode {
205	SZEDATA2_MAC_CHMODE_PROMISC       = 0x0,
206	SZEDATA2_MAC_CHMODE_ONLY_VALID    = 0x1,
207	SZEDATA2_MAC_CHMODE_ALL_BROADCAST = 0x2,
208	SZEDATA2_MAC_CHMODE_ALL_MULTICAST = 0x3,
209};
210
211/*
212 * Structure describes CGMII IBUF address space
213 */
214struct szedata2_cgmii_ibuf {
215	/** Total Received Frames Counter low part */
216	uint32_t trfcl;
217	/** Correct Frames Counter low part */
218	uint32_t cfcl;
219	/** Discarded Frames Counter low part */
220	uint32_t dfcl;
221	/** Counter of frames discarded due to buffer overflow low part */
222	uint32_t bodfcl;
223	/** Total Received Frames Counter high part */
224	uint32_t trfch;
225	/** Correct Frames Counter high part */
226	uint32_t cfch;
227	/** Discarded Frames Counter high part */
228	uint32_t dfch;
229	/** Counter of frames discarded due to buffer overflow high part */
230	uint32_t bodfch;
231	/** IBUF enable register */
232	uint32_t ibuf_en;
233	/** Error mask register */
234	uint32_t err_mask;
235	/** IBUF status register */
236	uint32_t ibuf_st;
237	/** IBUF command register */
238	uint32_t ibuf_cmd;
239	/** Minimum frame length allowed */
240	uint32_t mfla;
241	/** Frame MTU */
242	uint32_t mtu;
243	/** MAC address check mode */
244	uint32_t mac_chmode;
245	/** Octets Received OK Counter low part */
246	uint32_t orocl;
247	/** Octets Received OK Counter high part */
248	uint32_t oroch;
249} __rte_packed;
250
251/* Offset of CGMII IBUF memory for MAC addresses */
252#define SZEDATA2_CGMII_IBUF_MAC_MEM_OFF 0x80
253
254/*
255 * @return
256 *     true if IBUF is enabled
257 *     false if IBUF is disabled
258 */
259static inline bool
260cgmii_ibuf_is_enabled(volatile struct szedata2_cgmii_ibuf *ibuf)
261{
262	return ((rte_le_to_cpu_32(ibuf->ibuf_en) & 0x1) != 0) ? true : false;
263}
264
265/*
266 * Enables IBUF.
267 */
268static inline void
269cgmii_ibuf_enable(volatile struct szedata2_cgmii_ibuf *ibuf)
270{
271	ibuf->ibuf_en =
272		rte_cpu_to_le_32(rte_le_to_cpu_32(ibuf->ibuf_en) | 0x1);
273}
274
275/*
276 * Disables IBUF.
277 */
278static inline void
279cgmii_ibuf_disable(volatile struct szedata2_cgmii_ibuf *ibuf)
280{
281	ibuf->ibuf_en =
282		rte_cpu_to_le_32(rte_le_to_cpu_32(ibuf->ibuf_en) & ~0x1);
283}
284
285/*
286 * @return
287 *     true if ibuf link is up
288 *     false if ibuf link is down
289 */
290static inline bool
291cgmii_ibuf_is_link_up(volatile struct szedata2_cgmii_ibuf *ibuf)
292{
293	return ((rte_le_to_cpu_32(ibuf->ibuf_st) & 0x80) != 0) ? true : false;
294}
295
296/*
297 * @return
298 *     MAC address check mode
299 */
300static inline enum szedata2_mac_check_mode
301cgmii_ibuf_mac_mode_read(volatile struct szedata2_cgmii_ibuf *ibuf)
302{
303	switch (rte_le_to_cpu_32(ibuf->mac_chmode) & 0x3) {
304	case 0x0:
305		return SZEDATA2_MAC_CHMODE_PROMISC;
306	case 0x1:
307		return SZEDATA2_MAC_CHMODE_ONLY_VALID;
308	case 0x2:
309		return SZEDATA2_MAC_CHMODE_ALL_BROADCAST;
310	case 0x3:
311		return SZEDATA2_MAC_CHMODE_ALL_MULTICAST;
312	default:
313		return SZEDATA2_MAC_CHMODE_PROMISC;
314	}
315}
316
317/*
318 * Writes "mode" in MAC address check mode register.
319 */
320static inline void
321cgmii_ibuf_mac_mode_write(volatile struct szedata2_cgmii_ibuf *ibuf,
322		enum szedata2_mac_check_mode mode)
323{
324	ibuf->mac_chmode = rte_cpu_to_le_32(
325			(rte_le_to_cpu_32(ibuf->mac_chmode) & ~0x3) | mode);
326}
327
328/*
329 * Structure describes CGMII OBUF address space
330 */
331struct szedata2_cgmii_obuf {
332	/** Total Sent Frames Counter low part */
333	uint32_t tsfcl;
334	/** Octets Sent Counter low part */
335	uint32_t oscl;
336	/** Total Discarded Frames Counter low part */
337	uint32_t tdfcl;
338	/** reserved */
339	uint32_t reserved1;
340	/** Total Sent Frames Counter high part */
341	uint32_t tsfch;
342	/** Octets Sent Counter high part */
343	uint32_t osch;
344	/** Total Discarded Frames Counter high part */
345	uint32_t tdfch;
346	/** reserved */
347	uint32_t reserved2;
348	/** OBUF enable register */
349	uint32_t obuf_en;
350	/** reserved */
351	uint64_t reserved3;
352	/** OBUF control register */
353	uint32_t ctrl;
354	/** OBUF status register */
355	uint32_t obuf_st;
356} __rte_packed;
357
358/*
359 * @return
360 *     true if OBUF is enabled
361 *     false if OBUF is disabled
362 */
363static inline bool
364cgmii_obuf_is_enabled(volatile struct szedata2_cgmii_obuf *obuf)
365{
366	return ((rte_le_to_cpu_32(obuf->obuf_en) & 0x1) != 0) ? true : false;
367}
368
369/*
370 * Enables OBUF.
371 */
372static inline void
373cgmii_obuf_enable(volatile struct szedata2_cgmii_obuf *obuf)
374{
375	obuf->obuf_en =
376		rte_cpu_to_le_32(rte_le_to_cpu_32(obuf->obuf_en) | 0x1);
377}
378
379/*
380 * Disables OBUF.
381 */
382static inline void
383cgmii_obuf_disable(volatile struct szedata2_cgmii_obuf *obuf)
384{
385	obuf->obuf_en =
386		rte_cpu_to_le_32(rte_le_to_cpu_32(obuf->obuf_en) & ~0x1);
387}
388
389/*
390 * Function takes value from IBUF status register. Values in IBUF and OBUF
391 * should be same.
392 *
393 * @return Link speed constant.
394 */
395static inline enum szedata2_link_speed
396cgmii_link_speed(volatile struct szedata2_cgmii_ibuf *ibuf)
397{
398	uint32_t speed = (rte_le_to_cpu_32(ibuf->ibuf_st) & 0x70) >> 4;
399	switch (speed) {
400	case 0x03:
401		return SZEDATA2_LINK_SPEED_10G;
402	case 0x04:
403		return SZEDATA2_LINK_SPEED_40G;
404	case 0x05:
405		return SZEDATA2_LINK_SPEED_100G;
406	default:
407		return SZEDATA2_LINK_SPEED_DEFAULT;
408	}
409}
410
411/*
412 * IBUFs and OBUFs can generally be located at different offsets in different
413 * firmwares.
414 * This part defines base offsets of IBUFs and OBUFs through various firmwares.
415 * Currently one firmware type is supported.
416 * Type of firmware is set through configuration option
417 * CONFIG_RTE_LIBRTE_PMD_SZEDATA_AS.
418 * Possible values are:
419 * 0 - for firmwares:
420 *     NIC_100G1_LR4
421 *     HANIC_100G1_LR4
422 *     HANIC_100G1_SR10
423 */
424#if !defined(RTE_LIBRTE_PMD_SZEDATA2_AS)
425#error "RTE_LIBRTE_PMD_SZEDATA2_AS has to be defined"
426#elif RTE_LIBRTE_PMD_SZEDATA2_AS == 0
427
428/*
429 * CGMII IBUF offset from the beginning of PCI resource address space.
430 */
431#define SZEDATA2_CGMII_IBUF_BASE_OFF 0x8000
432/*
433 * Size of CGMII IBUF.
434 */
435#define SZEDATA2_CGMII_IBUF_SIZE 0x200
436
437/*
438 * GCMII OBUF offset from the beginning of PCI resource address space.
439 */
440#define SZEDATA2_CGMII_OBUF_BASE_OFF 0x9000
441/*
442 * Size of CGMII OBUF.
443 */
444#define SZEDATA2_CGMII_OBUF_SIZE 0x100
445
446#else
447#error "RTE_LIBRTE_PMD_SZEDATA2_AS has wrong value, see comments in config file"
448#endif
449
450#endif
451