1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2010-2016 Solarflare Communications Inc.
5 * All rights reserved.
6 *
7 * This software was developed in part by Philip Paeps under contract for
8 * Solarflare Communications, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * The views and conclusions contained in the software and documentation are
32 * those of the authors and should not be interpreted as representing official
33 * policies, either expressed or implied, of the FreeBSD Project.
34 *
35 * $FreeBSD$
36 */
37
38 #ifndef _SYS_EFSYS_H
39 #define _SYS_EFSYS_H
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 #include <sys/param.h>
46 #include <sys/bus.h>
47 #include <sys/endian.h>
48 #include <sys/lock.h>
49 #include <sys/malloc.h>
50 #include <sys/mbuf.h>
51 #include <sys/mutex.h>
52 #include <sys/rwlock.h>
53 #include <sys/sdt.h>
54 #include <sys/systm.h>
55
56 #include <machine/bus.h>
57 #include <machine/endian.h>
58
59 #define EFSYS_HAS_UINT64 1
60 #if defined(__x86_64__)
61 #define EFSYS_USE_UINT64 1
62 #else
63 #define EFSYS_USE_UINT64 0
64 #endif
65 #define EFSYS_HAS_SSE2_M128 0
66 #if _BYTE_ORDER == _BIG_ENDIAN
67 #define EFSYS_IS_BIG_ENDIAN 1
68 #define EFSYS_IS_LITTLE_ENDIAN 0
69 #elif _BYTE_ORDER == _LITTLE_ENDIAN
70 #define EFSYS_IS_BIG_ENDIAN 0
71 #define EFSYS_IS_LITTLE_ENDIAN 1
72 #endif
73 #include "efx_types.h"
74
75 #ifndef B_FALSE
76 #define B_FALSE FALSE
77 #endif
78 #ifndef B_TRUE
79 #define B_TRUE TRUE
80 #endif
81
82 #ifndef IS2P
83 #define ISP2(x) (((x) & ((x) - 1)) == 0)
84 #endif
85
86 #if defined(__x86_64__)
87
88 #define SFXGE_USE_BUS_SPACE_8 1
89
90 #if !defined(bus_space_read_stream_8)
91
92 #define bus_space_read_stream_8(t, h, o) \
93 bus_space_read_8((t), (h), (o))
94
95 #define bus_space_write_stream_8(t, h, o, v) \
96 bus_space_write_8((t), (h), (o), (v))
97
98 #endif
99
100 #endif
101
102 #define ENOTACTIVE EINVAL
103
104 /* Memory type to use on FreeBSD */
105 MALLOC_DECLARE(M_SFXGE);
106
107 /* Machine dependend prefetch wrappers */
108 #if defined(__i386__) || defined(__amd64__)
109 static __inline void
110 prefetch_read_many(void *addr)
111 {
112
113 __asm__(
114 "prefetcht0 (%0)"
115 :
116 : "r" (addr));
117 }
118
119 static __inline void
120 prefetch_read_once(void *addr)
121 {
122
123 __asm__(
124 "prefetchnta (%0)"
125 :
126 : "r" (addr));
127 }
128 #else
129 static __inline void
130 prefetch_read_many(void *addr)
131 {
132
133 }
134
135 static __inline void
136 prefetch_read_once(void *addr)
137 {
138
139 }
140 #endif
141
142 #if defined(__i386__) || defined(__amd64__)
143 #include <vm/vm.h>
144 #include <vm/pmap.h>
145 #endif
146 static __inline void
147 sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
148 struct mbuf *m, bus_dma_segment_t *seg)
149 {
150 #if defined(__i386__) || defined(__amd64__)
151 seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
152 seg->ds_len = m->m_len;
153 #else
154 int nsegstmp;
155
156 bus_dmamap_load_mbuf_sg(tag, map, m, seg, &nsegstmp, 0);
157 #endif
158 }
159
160 /* Code inclusion options */
161
162 #define EFSYS_OPT_NAMES 1
163
164 #define EFSYS_OPT_SIENA 1
165 #define EFSYS_OPT_HUNTINGTON 1
166 #define EFSYS_OPT_MEDFORD 1
167 #define EFSYS_OPT_MEDFORD2 1
168 #ifdef DEBUG
169 #define EFSYS_OPT_CHECK_REG 1
170 #else
171 #define EFSYS_OPT_CHECK_REG 0
172 #endif
173
174 #define EFSYS_OPT_MCDI 1
175 #define EFSYS_OPT_MCDI_LOGGING 0
176 #define EFSYS_OPT_MCDI_PROXY_AUTH 0
177
178 #define EFSYS_OPT_MAC_STATS 1
179
180 #define EFSYS_OPT_LOOPBACK 0
181
182 #define EFSYS_OPT_MON_MCDI 0
183 #define EFSYS_OPT_MON_STATS 0
184
185 #define EFSYS_OPT_PHY_STATS 1
186 #define EFSYS_OPT_BIST 1
187 #define EFSYS_OPT_PHY_LED_CONTROL 1
188 #define EFSYS_OPT_PHY_FLAGS 0
189
190 #define EFSYS_OPT_VPD 1
191 #define EFSYS_OPT_NVRAM 1
192 #define EFSYS_OPT_BOOTCFG 0
193 #define EFSYS_OPT_IMAGE_LAYOUT 0
194
195 #define EFSYS_OPT_DIAG 0
196 #define EFSYS_OPT_RX_SCALE 1
197 #define EFSYS_OPT_QSTATS 1
198 #define EFSYS_OPT_FILTER 1
199 #define EFSYS_OPT_RX_SCATTER 0
200
201 #define EFSYS_OPT_EV_PREFETCH 0
202
203 #define EFSYS_OPT_DECODE_INTR_FATAL 1
204
205 #define EFSYS_OPT_LICENSING 0
206
207 #define EFSYS_OPT_ALLOW_UNCONFIGURED_NIC 0
208
209 #define EFSYS_OPT_RX_PACKED_STREAM 0
210
211 #define EFSYS_OPT_RX_ES_SUPER_BUFFER 0
212
213 #define EFSYS_OPT_TUNNEL 0
214
215 #define EFSYS_OPT_FW_SUBVARIANT_AWARE 0
216
217 /* ID */
218
219 typedef struct __efsys_identifier_s efsys_identifier_t;
220
221 /* PROBE */
222
223 #ifndef DTRACE_PROBE
224
225 #define EFSYS_PROBE(_name)
226
227 #define EFSYS_PROBE1(_name, _type1, _arg1)
228
229 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
230
231 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
232 _type3, _arg3)
233
234 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
235 _type3, _arg3, _type4, _arg4)
236
237 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
238 _type3, _arg3, _type4, _arg4, _type5, _arg5)
239
240 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
241 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
242 _type6, _arg6)
243
244 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
245 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
246 _type6, _arg6, _type7, _arg7)
247
248 #else /* DTRACE_PROBE */
249
250 #define EFSYS_PROBE(_name) \
251 DTRACE_PROBE(_name)
252
253 #define EFSYS_PROBE1(_name, _type1, _arg1) \
254 DTRACE_PROBE1(_name, _type1, _arg1)
255
256 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2) \
257 DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
258
259 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
260 _type3, _arg3) \
261 DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
262 _type3, _arg3)
263
264 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
265 _type3, _arg3, _type4, _arg4) \
266 DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
267 _type3, _arg3, _type4, _arg4)
268
269 #ifdef DTRACE_PROBE5
270 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
271 _type3, _arg3, _type4, _arg4, _type5, _arg5) \
272 DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
273 _type3, _arg3, _type4, _arg4, _type5, _arg5)
274 #else
275 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
276 _type3, _arg3, _type4, _arg4, _type5, _arg5) \
277 DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
278 _type3, _arg3, _type4, _arg4)
279 #endif
280
281 #ifdef DTRACE_PROBE6
282 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
283 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
284 _type6, _arg6) \
285 DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
286 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
287 _type6, _arg6)
288 #else
289 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
290 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
291 _type6, _arg6) \
292 EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
293 _type3, _arg3, _type4, _arg4, _type5, _arg5)
294 #endif
295
296 #ifdef DTRACE_PROBE7
297 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
298 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
299 _type6, _arg6, _type7, _arg7) \
300 DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
301 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
302 _type6, _arg6, _type7, _arg7)
303 #else
304 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
305 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
306 _type6, _arg6, _type7, _arg7) \
307 EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
308 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
309 _type6, _arg6)
310 #endif
311
312 #endif /* DTRACE_PROBE */
313
314 /* DMA */
315
316 typedef uint64_t efsys_dma_addr_t;
317
318 typedef struct efsys_mem_s {
319 bus_dma_tag_t esm_tag;
320 bus_dmamap_t esm_map;
321 caddr_t esm_base;
322 efsys_dma_addr_t esm_addr;
323 size_t esm_size;
324 } efsys_mem_t;
325
326 #define EFSYS_MEM_SIZE(_esmp) \
327 ((_esmp)->esm_size)
328
329 #define EFSYS_MEM_ADDR(_esmp) \
330 ((_esmp)->esm_addr)
331
332 #define EFSYS_MEM_IS_NULL(_esmp) \
333 ((_esmp)->esm_base == NULL)
334
335 #define EFSYS_MEM_ZERO(_esmp, _size) \
336 do { \
337 (void) memset((_esmp)->esm_base, 0, (_size)); \
338 \
339 _NOTE(CONSTANTCONDITION) \
340 } while (B_FALSE)
341
342 #define EFSYS_MEM_READD(_esmp, _offset, _edp) \
343 do { \
344 uint32_t *addr; \
345 \
346 _NOTE(CONSTANTCONDITION) \
347 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
348 sizeof (efx_dword_t)), \
349 ("not power of 2 aligned")); \
350 \
351 addr = (void *)((_esmp)->esm_base + (_offset)); \
352 \
353 (_edp)->ed_u32[0] = *addr; \
354 \
355 EFSYS_PROBE2(mem_readd, unsigned int, (_offset), \
356 uint32_t, (_edp)->ed_u32[0]); \
357 \
358 _NOTE(CONSTANTCONDITION) \
359 } while (B_FALSE)
360
361 #if defined(__x86_64__)
362 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
363 do { \
364 uint64_t *addr; \
365 \
366 _NOTE(CONSTANTCONDITION) \
367 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
368 sizeof (efx_qword_t)), \
369 ("not power of 2 aligned")); \
370 \
371 addr = (void *)((_esmp)->esm_base + (_offset)); \
372 \
373 (_eqp)->eq_u64[0] = *addr; \
374 \
375 EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
376 uint32_t, (_eqp)->eq_u32[1], \
377 uint32_t, (_eqp)->eq_u32[0]); \
378 \
379 _NOTE(CONSTANTCONDITION) \
380 } while (B_FALSE)
381 #else
382 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
383 do { \
384 uint32_t *addr; \
385 \
386 _NOTE(CONSTANTCONDITION) \
387 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
388 sizeof (efx_qword_t)), \
389 ("not power of 2 aligned")); \
390 \
391 addr = (void *)((_esmp)->esm_base + (_offset)); \
392 \
393 (_eqp)->eq_u32[0] = *addr++; \
394 (_eqp)->eq_u32[1] = *addr; \
395 \
396 EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
397 uint32_t, (_eqp)->eq_u32[1], \
398 uint32_t, (_eqp)->eq_u32[0]); \
399 \
400 _NOTE(CONSTANTCONDITION) \
401 } while (B_FALSE)
402 #endif
403
404 #if defined(__x86_64__)
405 #define EFSYS_MEM_READO(_esmp, _offset, _eop) \
406 do { \
407 uint64_t *addr; \
408 \
409 _NOTE(CONSTANTCONDITION) \
410 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
411 sizeof (efx_oword_t)), \
412 ("not power of 2 aligned")); \
413 \
414 addr = (void *)((_esmp)->esm_base + (_offset)); \
415 \
416 (_eop)->eo_u64[0] = *addr++; \
417 (_eop)->eo_u64[1] = *addr; \
418 \
419 EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
420 uint32_t, (_eop)->eo_u32[3], \
421 uint32_t, (_eop)->eo_u32[2], \
422 uint32_t, (_eop)->eo_u32[1], \
423 uint32_t, (_eop)->eo_u32[0]); \
424 \
425 _NOTE(CONSTANTCONDITION) \
426 } while (B_FALSE)
427 #else
428 #define EFSYS_MEM_READO(_esmp, _offset, _eop) \
429 do { \
430 uint32_t *addr; \
431 \
432 _NOTE(CONSTANTCONDITION) \
433 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
434 sizeof (efx_oword_t)), \
435 ("not power of 2 aligned")); \
436 \
437 addr = (void *)((_esmp)->esm_base + (_offset)); \
438 \
439 (_eop)->eo_u32[0] = *addr++; \
440 (_eop)->eo_u32[1] = *addr++; \
441 (_eop)->eo_u32[2] = *addr++; \
442 (_eop)->eo_u32[3] = *addr; \
443 \
444 EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
445 uint32_t, (_eop)->eo_u32[3], \
446 uint32_t, (_eop)->eo_u32[2], \
447 uint32_t, (_eop)->eo_u32[1], \
448 uint32_t, (_eop)->eo_u32[0]); \
449 \
450 _NOTE(CONSTANTCONDITION) \
451 } while (B_FALSE)
452 #endif
453
454 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp) \
455 do { \
456 uint32_t *addr; \
457 \
458 _NOTE(CONSTANTCONDITION) \
459 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
460 sizeof (efx_dword_t)), \
461 ("not power of 2 aligned")); \
462 \
463 EFSYS_PROBE2(mem_writed, unsigned int, (_offset), \
464 uint32_t, (_edp)->ed_u32[0]); \
465 \
466 addr = (void *)((_esmp)->esm_base + (_offset)); \
467 \
468 *addr = (_edp)->ed_u32[0]; \
469 \
470 _NOTE(CONSTANTCONDITION) \
471 } while (B_FALSE)
472
473 #if defined(__x86_64__)
474 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
475 do { \
476 uint64_t *addr; \
477 \
478 _NOTE(CONSTANTCONDITION) \
479 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
480 sizeof (efx_qword_t)), \
481 ("not power of 2 aligned")); \
482 \
483 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
484 uint32_t, (_eqp)->eq_u32[1], \
485 uint32_t, (_eqp)->eq_u32[0]); \
486 \
487 addr = (void *)((_esmp)->esm_base + (_offset)); \
488 \
489 *addr = (_eqp)->eq_u64[0]; \
490 \
491 _NOTE(CONSTANTCONDITION) \
492 } while (B_FALSE)
493
494 #else
495 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
496 do { \
497 uint32_t *addr; \
498 \
499 _NOTE(CONSTANTCONDITION) \
500 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
501 sizeof (efx_qword_t)), \
502 ("not power of 2 aligned")); \
503 \
504 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
505 uint32_t, (_eqp)->eq_u32[1], \
506 uint32_t, (_eqp)->eq_u32[0]); \
507 \
508 addr = (void *)((_esmp)->esm_base + (_offset)); \
509 \
510 *addr++ = (_eqp)->eq_u32[0]; \
511 *addr = (_eqp)->eq_u32[1]; \
512 \
513 _NOTE(CONSTANTCONDITION) \
514 } while (B_FALSE)
515 #endif
516
517 #if defined(__x86_64__)
518 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
519 do { \
520 uint64_t *addr; \
521 \
522 _NOTE(CONSTANTCONDITION) \
523 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
524 sizeof (efx_oword_t)), \
525 ("not power of 2 aligned")); \
526 \
527 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
528 uint32_t, (_eop)->eo_u32[3], \
529 uint32_t, (_eop)->eo_u32[2], \
530 uint32_t, (_eop)->eo_u32[1], \
531 uint32_t, (_eop)->eo_u32[0]); \
532 \
533 addr = (void *)((_esmp)->esm_base + (_offset)); \
534 \
535 *addr++ = (_eop)->eo_u64[0]; \
536 *addr = (_eop)->eo_u64[1]; \
537 \
538 _NOTE(CONSTANTCONDITION) \
539 } while (B_FALSE)
540 #else
541 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
542 do { \
543 uint32_t *addr; \
544 \
545 _NOTE(CONSTANTCONDITION) \
546 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
547 sizeof (efx_oword_t)), \
548 ("not power of 2 aligned")); \
549 \
550 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
551 uint32_t, (_eop)->eo_u32[3], \
552 uint32_t, (_eop)->eo_u32[2], \
553 uint32_t, (_eop)->eo_u32[1], \
554 uint32_t, (_eop)->eo_u32[0]); \
555 \
556 addr = (void *)((_esmp)->esm_base + (_offset)); \
557 \
558 *addr++ = (_eop)->eo_u32[0]; \
559 *addr++ = (_eop)->eo_u32[1]; \
560 *addr++ = (_eop)->eo_u32[2]; \
561 *addr = (_eop)->eo_u32[3]; \
562 \
563 _NOTE(CONSTANTCONDITION) \
564 } while (B_FALSE)
565 #endif
566
567 /* BAR */
568
569 #define SFXGE_LOCK_NAME_MAX 16
570
571 typedef struct efsys_bar_s {
572 struct mtx esb_lock;
573 char esb_lock_name[SFXGE_LOCK_NAME_MAX];
574 bus_space_tag_t esb_tag;
575 bus_space_handle_t esb_handle;
576 int esb_rid;
577 struct resource *esb_res;
578 } efsys_bar_t;
579
580 #define SFXGE_BAR_LOCK_INIT(_esbp, _ifname) \
581 do { \
582 snprintf((_esbp)->esb_lock_name, \
583 sizeof((_esbp)->esb_lock_name), \
584 "%s:bar", (_ifname)); \
585 mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name, \
586 NULL, MTX_DEF); \
587 _NOTE(CONSTANTCONDITION) \
588 } while (B_FALSE)
589 #define SFXGE_BAR_LOCK_DESTROY(_esbp) \
590 mtx_destroy(&(_esbp)->esb_lock)
591 #define SFXGE_BAR_LOCK(_esbp) \
592 mtx_lock(&(_esbp)->esb_lock)
593 #define SFXGE_BAR_UNLOCK(_esbp) \
594 mtx_unlock(&(_esbp)->esb_lock)
595
596 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock) \
597 do { \
598 _NOTE(CONSTANTCONDITION) \
599 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
600 sizeof (efx_dword_t)), \
601 ("not power of 2 aligned")); \
602 \
603 _NOTE(CONSTANTCONDITION) \
604 if (_lock) \
605 SFXGE_BAR_LOCK(_esbp); \
606 \
607 (_edp)->ed_u32[0] = bus_space_read_stream_4( \
608 (_esbp)->esb_tag, (_esbp)->esb_handle, \
609 (_offset)); \
610 \
611 EFSYS_PROBE2(bar_readd, unsigned int, (_offset), \
612 uint32_t, (_edp)->ed_u32[0]); \
613 \
614 _NOTE(CONSTANTCONDITION) \
615 if (_lock) \
616 SFXGE_BAR_UNLOCK(_esbp); \
617 _NOTE(CONSTANTCONDITION) \
618 } while (B_FALSE)
619
620 #if defined(SFXGE_USE_BUS_SPACE_8)
621 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
622 do { \
623 _NOTE(CONSTANTCONDITION) \
624 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
625 sizeof (efx_qword_t)), \
626 ("not power of 2 aligned")); \
627 \
628 SFXGE_BAR_LOCK(_esbp); \
629 \
630 (_eqp)->eq_u64[0] = bus_space_read_stream_8( \
631 (_esbp)->esb_tag, (_esbp)->esb_handle, \
632 (_offset)); \
633 \
634 EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
635 uint32_t, (_eqp)->eq_u32[1], \
636 uint32_t, (_eqp)->eq_u32[0]); \
637 \
638 SFXGE_BAR_UNLOCK(_esbp); \
639 _NOTE(CONSTANTCONDITION) \
640 } while (B_FALSE)
641
642 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
643 do { \
644 _NOTE(CONSTANTCONDITION) \
645 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
646 sizeof (efx_oword_t)), \
647 ("not power of 2 aligned")); \
648 \
649 _NOTE(CONSTANTCONDITION) \
650 if (_lock) \
651 SFXGE_BAR_LOCK(_esbp); \
652 \
653 (_eop)->eo_u64[0] = bus_space_read_stream_8( \
654 (_esbp)->esb_tag, (_esbp)->esb_handle, \
655 (_offset)); \
656 (_eop)->eo_u64[1] = bus_space_read_stream_8( \
657 (_esbp)->esb_tag, (_esbp)->esb_handle, \
658 (_offset) + 8); \
659 \
660 EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
661 uint32_t, (_eop)->eo_u32[3], \
662 uint32_t, (_eop)->eo_u32[2], \
663 uint32_t, (_eop)->eo_u32[1], \
664 uint32_t, (_eop)->eo_u32[0]); \
665 \
666 _NOTE(CONSTANTCONDITION) \
667 if (_lock) \
668 SFXGE_BAR_UNLOCK(_esbp); \
669 _NOTE(CONSTANTCONDITION) \
670 } while (B_FALSE)
671
672 #else
673 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
674 do { \
675 _NOTE(CONSTANTCONDITION) \
676 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
677 sizeof (efx_qword_t)), \
678 ("not power of 2 aligned")); \
679 \
680 SFXGE_BAR_LOCK(_esbp); \
681 \
682 (_eqp)->eq_u32[0] = bus_space_read_stream_4( \
683 (_esbp)->esb_tag, (_esbp)->esb_handle, \
684 (_offset)); \
685 (_eqp)->eq_u32[1] = bus_space_read_stream_4( \
686 (_esbp)->esb_tag, (_esbp)->esb_handle, \
687 (_offset) + 4); \
688 \
689 EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
690 uint32_t, (_eqp)->eq_u32[1], \
691 uint32_t, (_eqp)->eq_u32[0]); \
692 \
693 SFXGE_BAR_UNLOCK(_esbp); \
694 _NOTE(CONSTANTCONDITION) \
695 } while (B_FALSE)
696
697 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
698 do { \
699 _NOTE(CONSTANTCONDITION) \
700 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
701 sizeof (efx_oword_t)), \
702 ("not power of 2 aligned")); \
703 \
704 _NOTE(CONSTANTCONDITION) \
705 if (_lock) \
706 SFXGE_BAR_LOCK(_esbp); \
707 \
708 (_eop)->eo_u32[0] = bus_space_read_stream_4( \
709 (_esbp)->esb_tag, (_esbp)->esb_handle, \
710 (_offset)); \
711 (_eop)->eo_u32[1] = bus_space_read_stream_4( \
712 (_esbp)->esb_tag, (_esbp)->esb_handle, \
713 (_offset) + 4); \
714 (_eop)->eo_u32[2] = bus_space_read_stream_4( \
715 (_esbp)->esb_tag, (_esbp)->esb_handle, \
716 (_offset) + 8); \
717 (_eop)->eo_u32[3] = bus_space_read_stream_4( \
718 (_esbp)->esb_tag, (_esbp)->esb_handle, \
719 (_offset) + 12); \
720 \
721 EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
722 uint32_t, (_eop)->eo_u32[3], \
723 uint32_t, (_eop)->eo_u32[2], \
724 uint32_t, (_eop)->eo_u32[1], \
725 uint32_t, (_eop)->eo_u32[0]); \
726 \
727 _NOTE(CONSTANTCONDITION) \
728 if (_lock) \
729 SFXGE_BAR_UNLOCK(_esbp); \
730 _NOTE(CONSTANTCONDITION) \
731 } while (B_FALSE)
732 #endif
733
734 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock) \
735 do { \
736 _NOTE(CONSTANTCONDITION) \
737 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
738 sizeof (efx_dword_t)), \
739 ("not power of 2 aligned")); \
740 \
741 _NOTE(CONSTANTCONDITION) \
742 if (_lock) \
743 SFXGE_BAR_LOCK(_esbp); \
744 \
745 EFSYS_PROBE2(bar_writed, unsigned int, (_offset), \
746 uint32_t, (_edp)->ed_u32[0]); \
747 \
748 /* \
749 * Make sure that previous writes to the dword have \
750 * been done. It should be cheaper than barrier just \
751 * after the write below. \
752 */ \
753 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
754 (_offset), sizeof (efx_dword_t), \
755 BUS_SPACE_BARRIER_WRITE); \
756 bus_space_write_stream_4((_esbp)->esb_tag, \
757 (_esbp)->esb_handle, \
758 (_offset), (_edp)->ed_u32[0]); \
759 \
760 _NOTE(CONSTANTCONDITION) \
761 if (_lock) \
762 SFXGE_BAR_UNLOCK(_esbp); \
763 _NOTE(CONSTANTCONDITION) \
764 } while (B_FALSE)
765
766 #if defined(SFXGE_USE_BUS_SPACE_8)
767 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
768 do { \
769 _NOTE(CONSTANTCONDITION) \
770 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
771 sizeof (efx_qword_t)), \
772 ("not power of 2 aligned")); \
773 \
774 SFXGE_BAR_LOCK(_esbp); \
775 \
776 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
777 uint32_t, (_eqp)->eq_u32[1], \
778 uint32_t, (_eqp)->eq_u32[0]); \
779 \
780 /* \
781 * Make sure that previous writes to the qword have \
782 * been done. It should be cheaper than barrier just \
783 * after the write below. \
784 */ \
785 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
786 (_offset), sizeof (efx_qword_t), \
787 BUS_SPACE_BARRIER_WRITE); \
788 bus_space_write_stream_8((_esbp)->esb_tag, \
789 (_esbp)->esb_handle, \
790 (_offset), (_eqp)->eq_u64[0]); \
791 \
792 SFXGE_BAR_UNLOCK(_esbp); \
793 _NOTE(CONSTANTCONDITION) \
794 } while (B_FALSE)
795 #else
796 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
797 do { \
798 _NOTE(CONSTANTCONDITION) \
799 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
800 sizeof (efx_qword_t)), \
801 ("not power of 2 aligned")); \
802 \
803 SFXGE_BAR_LOCK(_esbp); \
804 \
805 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
806 uint32_t, (_eqp)->eq_u32[1], \
807 uint32_t, (_eqp)->eq_u32[0]); \
808 \
809 /* \
810 * Make sure that previous writes to the qword have \
811 * been done. It should be cheaper than barrier just \
812 * after the last write below. \
813 */ \
814 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
815 (_offset), sizeof (efx_qword_t), \
816 BUS_SPACE_BARRIER_WRITE); \
817 bus_space_write_stream_4((_esbp)->esb_tag, \
818 (_esbp)->esb_handle, \
819 (_offset), (_eqp)->eq_u32[0]); \
820 /* \
821 * It should be guaranteed that the last dword comes \
822 * the last, so barrier entire qword to be sure that \
823 * neither above nor below writes are reordered. \
824 */ \
825 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
826 (_offset), sizeof (efx_qword_t), \
827 BUS_SPACE_BARRIER_WRITE); \
828 bus_space_write_stream_4((_esbp)->esb_tag, \
829 (_esbp)->esb_handle, \
830 (_offset) + 4, (_eqp)->eq_u32[1]); \
831 \
832 SFXGE_BAR_UNLOCK(_esbp); \
833 _NOTE(CONSTANTCONDITION) \
834 } while (B_FALSE)
835 #endif
836
837 /*
838 * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
839 * (required by PIO hardware)
840 */
841 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp) \
842 do { \
843 _NOTE(CONSTANTCONDITION) \
844 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
845 sizeof (efx_qword_t)), \
846 ("not power of 2 aligned")); \
847 \
848 (void) (_esbp); \
849 (void) (_eqp); \
850 \
851 /* FIXME: Perform a 64-bit write */ \
852 KASSERT(0, ("not implemented")); \
853 \
854 _NOTE(CONSTANTCONDITION) \
855 } while (B_FALSE)
856
857 #if defined(SFXGE_USE_BUS_SPACE_8)
858 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
859 do { \
860 _NOTE(CONSTANTCONDITION) \
861 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
862 sizeof (efx_oword_t)), \
863 ("not power of 2 aligned")); \
864 \
865 _NOTE(CONSTANTCONDITION) \
866 if (_lock) \
867 SFXGE_BAR_LOCK(_esbp); \
868 \
869 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
870 uint32_t, (_eop)->eo_u32[3], \
871 uint32_t, (_eop)->eo_u32[2], \
872 uint32_t, (_eop)->eo_u32[1], \
873 uint32_t, (_eop)->eo_u32[0]); \
874 \
875 /* \
876 * Make sure that previous writes to the oword have \
877 * been done. It should be cheaper than barrier just \
878 * after the last write below. \
879 */ \
880 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
881 (_offset), sizeof (efx_oword_t), \
882 BUS_SPACE_BARRIER_WRITE); \
883 bus_space_write_stream_8((_esbp)->esb_tag, \
884 (_esbp)->esb_handle, \
885 (_offset), (_eop)->eo_u64[0]); \
886 /* \
887 * It should be guaranteed that the last qword comes \
888 * the last, so barrier entire oword to be sure that \
889 * neither above nor below writes are reordered. \
890 */ \
891 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
892 (_offset), sizeof (efx_oword_t), \
893 BUS_SPACE_BARRIER_WRITE); \
894 bus_space_write_stream_8((_esbp)->esb_tag, \
895 (_esbp)->esb_handle, \
896 (_offset) + 8, (_eop)->eo_u64[1]); \
897 \
898 _NOTE(CONSTANTCONDITION) \
899 if (_lock) \
900 SFXGE_BAR_UNLOCK(_esbp); \
901 _NOTE(CONSTANTCONDITION) \
902 } while (B_FALSE)
903
904 #else
905 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
906 do { \
907 _NOTE(CONSTANTCONDITION) \
908 KASSERT(EFX_IS_P2ALIGNED(size_t, _offset, \
909 sizeof (efx_oword_t)), \
910 ("not power of 2 aligned")); \
911 \
912 _NOTE(CONSTANTCONDITION) \
913 if (_lock) \
914 SFXGE_BAR_LOCK(_esbp); \
915 \
916 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
917 uint32_t, (_eop)->eo_u32[3], \
918 uint32_t, (_eop)->eo_u32[2], \
919 uint32_t, (_eop)->eo_u32[1], \
920 uint32_t, (_eop)->eo_u32[0]); \
921 \
922 /* \
923 * Make sure that previous writes to the oword have \
924 * been done. It should be cheaper than barrier just \
925 * after the last write below. \
926 */ \
927 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
928 (_offset), sizeof (efx_oword_t), \
929 BUS_SPACE_BARRIER_WRITE); \
930 bus_space_write_stream_4((_esbp)->esb_tag, \
931 (_esbp)->esb_handle, \
932 (_offset), (_eop)->eo_u32[0]); \
933 bus_space_write_stream_4((_esbp)->esb_tag, \
934 (_esbp)->esb_handle, \
935 (_offset) + 4, (_eop)->eo_u32[1]); \
936 bus_space_write_stream_4((_esbp)->esb_tag, \
937 (_esbp)->esb_handle, \
938 (_offset) + 8, (_eop)->eo_u32[2]); \
939 /* \
940 * It should be guaranteed that the last dword comes \
941 * the last, so barrier entire oword to be sure that \
942 * neither above nor below writes are reordered. \
943 */ \
944 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
945 (_offset), sizeof (efx_oword_t), \
946 BUS_SPACE_BARRIER_WRITE); \
947 bus_space_write_stream_4((_esbp)->esb_tag, \
948 (_esbp)->esb_handle, \
949 (_offset) + 12, (_eop)->eo_u32[3]); \
950 \
951 _NOTE(CONSTANTCONDITION) \
952 if (_lock) \
953 SFXGE_BAR_UNLOCK(_esbp); \
954 _NOTE(CONSTANTCONDITION) \
955 } while (B_FALSE)
956 #endif
957
958 /* Use the standard octo-word write for doorbell writes */
959 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop) \
960 do { \
961 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE); \
962 _NOTE(CONSTANTCONDITION) \
963 } while (B_FALSE)
964
965 /* SPIN */
966
967 #define EFSYS_SPIN(_us) \
968 do { \
969 DELAY(_us); \
970 _NOTE(CONSTANTCONDITION) \
971 } while (B_FALSE)
972
973 #define EFSYS_SLEEP EFSYS_SPIN
974
975 /* BARRIERS */
976
977 #define EFSYS_MEM_READ_BARRIER() rmb()
978 #define EFSYS_PIO_WRITE_BARRIER()
979
980 /* DMA SYNC */
981 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size) \
982 do { \
983 bus_dmamap_sync((_esmp)->esm_tag, \
984 (_esmp)->esm_map, \
985 BUS_DMASYNC_POSTREAD); \
986 _NOTE(CONSTANTCONDITION) \
987 } while (B_FALSE)
988
989 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size) \
990 do { \
991 bus_dmamap_sync((_esmp)->esm_tag, \
992 (_esmp)->esm_map, \
993 BUS_DMASYNC_PREWRITE); \
994 _NOTE(CONSTANTCONDITION) \
995 } while (B_FALSE)
996
997 /* TIMESTAMP */
998
999 typedef clock_t efsys_timestamp_t;
1000
1001 #define EFSYS_TIMESTAMP(_usp) \
1002 do { \
1003 clock_t now; \
1004 \
1005 now = ticks; \
1006 *(_usp) = now * hz / 1000000; \
1007 _NOTE(CONSTANTCONDITION) \
1008 } while (B_FALSE)
1009
1010 /* KMEM */
1011
1012 #define EFSYS_KMEM_ALLOC(_esip, _size, _p) \
1013 do { \
1014 (_esip) = (_esip); \
1015 /* \
1016 * The macro is used in non-sleepable contexts, for \
1017 * example, holding a mutex. \
1018 */ \
1019 (_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO); \
1020 _NOTE(CONSTANTCONDITION) \
1021 } while (B_FALSE)
1022
1023 #define EFSYS_KMEM_FREE(_esip, _size, _p) \
1024 do { \
1025 (void) (_esip); \
1026 (void) (_size); \
1027 free((_p), M_SFXGE); \
1028 _NOTE(CONSTANTCONDITION) \
1029 } while (B_FALSE)
1030
1031 /* LOCK */
1032
1033 typedef struct efsys_lock_s {
1034 struct mtx lock;
1035 char lock_name[SFXGE_LOCK_NAME_MAX];
1036 } efsys_lock_t;
1037
1038 #define SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label) \
1039 do { \
1040 efsys_lock_t *__eslp = (_eslp); \
1041 \
1042 snprintf((__eslp)->lock_name, \
1043 sizeof((__eslp)->lock_name), \
1044 "%s:%s", (_ifname), (_label)); \
1045 mtx_init(&(__eslp)->lock, (__eslp)->lock_name, \
1046 NULL, MTX_DEF); \
1047 } while (B_FALSE)
1048 #define SFXGE_EFSYS_LOCK_DESTROY(_eslp) \
1049 mtx_destroy(&(_eslp)->lock)
1050 #define SFXGE_EFSYS_LOCK(_eslp) \
1051 mtx_lock(&(_eslp)->lock)
1052 #define SFXGE_EFSYS_UNLOCK(_eslp) \
1053 mtx_unlock(&(_eslp)->lock)
1054 #define SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp) \
1055 mtx_assert(&(_eslp)->lock, MA_OWNED)
1056
1057 typedef int efsys_lock_state_t;
1058
1059 #define EFSYS_LOCK_MAGIC 0x000010c4
1060
1061 #define EFSYS_LOCK(_lockp, _state) \
1062 do { \
1063 SFXGE_EFSYS_LOCK(_lockp); \
1064 (_state) = EFSYS_LOCK_MAGIC; \
1065 _NOTE(CONSTANTCONDITION) \
1066 } while (B_FALSE)
1067
1068 #define EFSYS_UNLOCK(_lockp, _state) \
1069 do { \
1070 if ((_state) != EFSYS_LOCK_MAGIC) \
1071 KASSERT(B_FALSE, ("not locked")); \
1072 SFXGE_EFSYS_UNLOCK(_lockp); \
1073 _NOTE(CONSTANTCONDITION) \
1074 } while (B_FALSE)
1075
1076 /* STAT */
1077
1078 typedef uint64_t efsys_stat_t;
1079
1080 #define EFSYS_STAT_INCR(_knp, _delta) \
1081 do { \
1082 *(_knp) += (_delta); \
1083 _NOTE(CONSTANTCONDITION) \
1084 } while (B_FALSE)
1085
1086 #define EFSYS_STAT_DECR(_knp, _delta) \
1087 do { \
1088 *(_knp) -= (_delta); \
1089 _NOTE(CONSTANTCONDITION) \
1090 } while (B_FALSE)
1091
1092 #define EFSYS_STAT_SET(_knp, _val) \
1093 do { \
1094 *(_knp) = (_val); \
1095 _NOTE(CONSTANTCONDITION) \
1096 } while (B_FALSE)
1097
1098 #define EFSYS_STAT_SET_QWORD(_knp, _valp) \
1099 do { \
1100 *(_knp) = le64toh((_valp)->eq_u64[0]); \
1101 _NOTE(CONSTANTCONDITION) \
1102 } while (B_FALSE)
1103
1104 #define EFSYS_STAT_SET_DWORD(_knp, _valp) \
1105 do { \
1106 *(_knp) = le32toh((_valp)->ed_u32[0]); \
1107 _NOTE(CONSTANTCONDITION) \
1108 } while (B_FALSE)
1109
1110 #define EFSYS_STAT_INCR_QWORD(_knp, _valp) \
1111 do { \
1112 *(_knp) += le64toh((_valp)->eq_u64[0]); \
1113 _NOTE(CONSTANTCONDITION) \
1114 } while (B_FALSE)
1115
1116 #define EFSYS_STAT_SUBR_QWORD(_knp, _valp) \
1117 do { \
1118 *(_knp) -= le64toh((_valp)->eq_u64[0]); \
1119 _NOTE(CONSTANTCONDITION) \
1120 } while (B_FALSE)
1121
1122 /* ERR */
1123
1124 extern void sfxge_err(efsys_identifier_t *, unsigned int,
1125 uint32_t, uint32_t);
1126
1127 #if EFSYS_OPT_DECODE_INTR_FATAL
1128 #define EFSYS_ERR(_esip, _code, _dword0, _dword1) \
1129 do { \
1130 sfxge_err((_esip), (_code), (_dword0), (_dword1)); \
1131 _NOTE(CONSTANTCONDITION) \
1132 } while (B_FALSE)
1133 #endif
1134
1135 /* ASSERT */
1136
1137 #define EFSYS_ASSERT(_exp) do { \
1138 if (!(_exp)) \
1139 panic("%s", #_exp); \
1140 } while (0)
1141
1142 #define EFSYS_ASSERT3(_x, _op, _y, _t) do { \
1143 const _t __x = (_t)(_x); \
1144 const _t __y = (_t)(_y); \
1145 if (!(__x _op __y)) \
1146 panic("assertion failed at %s:%u", __FILE__, __LINE__); \
1147 } while(0)
1148
1149 #define EFSYS_ASSERT3U(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uint64_t)
1150 #define EFSYS_ASSERT3S(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, int64_t)
1151 #define EFSYS_ASSERT3P(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
1152
1153 /* ROTATE */
1154
1155 #define EFSYS_HAS_ROTL_DWORD 0
1156
1157 #ifdef __cplusplus
1158 }
1159 #endif
1160
1161 #endif /* _SYS_EFSYS_H */
Cache object: b37d3eeb83ab448abec4f0e161ea11d6
|