xref: /freebsd/sys/dev/ioat/ioat_internal.h (revision 8e269d996ab3e809809e17199d8bfacdfcdbc461)
1e974f91cSConrad Meyer /*-
2e974f91cSConrad Meyer  * Copyright (C) 2012 Intel Corporation
3e974f91cSConrad Meyer  * All rights reserved.
4e974f91cSConrad Meyer  *
5e974f91cSConrad Meyer  * Redistribution and use in source and binary forms, with or without
6e974f91cSConrad Meyer  * modification, are permitted provided that the following conditions
7e974f91cSConrad Meyer  * are met:
8e974f91cSConrad Meyer  * 1. Redistributions of source code must retain the above copyright
9e974f91cSConrad Meyer  *    notice, this list of conditions and the following disclaimer.
10e974f91cSConrad Meyer  * 2. Redistributions in binary form must reproduce the above copyright
11e974f91cSConrad Meyer  *    notice, this list of conditions and the following disclaimer in the
12e974f91cSConrad Meyer  *    documentation and/or other materials provided with the distribution.
13e974f91cSConrad Meyer  *
14e974f91cSConrad Meyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15e974f91cSConrad Meyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16e974f91cSConrad Meyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17e974f91cSConrad Meyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18e974f91cSConrad Meyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19e974f91cSConrad Meyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20e974f91cSConrad Meyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21e974f91cSConrad Meyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22e974f91cSConrad Meyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23e974f91cSConrad Meyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24e974f91cSConrad Meyer  * SUCH DAMAGE.
25e974f91cSConrad Meyer  */
26e974f91cSConrad Meyer 
27e974f91cSConrad Meyer __FBSDID("$FreeBSD$");
28e974f91cSConrad Meyer 
29e974f91cSConrad Meyer #ifndef __IOAT_INTERNAL_H__
30e974f91cSConrad Meyer #define __IOAT_INTERNAL_H__
31e974f91cSConrad Meyer 
32374b05e1SConrad Meyer #include <sys/_task.h>
33374b05e1SConrad Meyer 
34e974f91cSConrad Meyer #define	DEVICE2SOFTC(dev)	((struct ioat_softc *) device_get_softc(dev))
3543fc1847SConrad Meyer #define	KTR_IOAT		KTR_SPARE3
36e974f91cSConrad Meyer 
37e974f91cSConrad Meyer #define	ioat_read_chancnt(ioat) \
38e974f91cSConrad Meyer 	ioat_read_1((ioat), IOAT_CHANCNT_OFFSET)
39e974f91cSConrad Meyer 
40e974f91cSConrad Meyer #define	ioat_read_xfercap(ioat) \
41b81eee4aSConrad Meyer 	(ioat_read_1((ioat), IOAT_XFERCAP_OFFSET) & IOAT_XFERCAP_VALID_MASK)
42e974f91cSConrad Meyer 
43e974f91cSConrad Meyer #define	ioat_write_intrctrl(ioat, value) \
44e974f91cSConrad Meyer 	ioat_write_1((ioat), IOAT_INTRCTRL_OFFSET, (value))
45e974f91cSConrad Meyer 
46e974f91cSConrad Meyer #define	ioat_read_cbver(ioat) \
47e974f91cSConrad Meyer 	(ioat_read_1((ioat), IOAT_CBVER_OFFSET) & 0xFF)
48e974f91cSConrad Meyer 
49e974f91cSConrad Meyer #define	ioat_read_dmacapability(ioat) \
50e974f91cSConrad Meyer 	ioat_read_4((ioat), IOAT_DMACAPABILITY_OFFSET)
51e974f91cSConrad Meyer 
52e974f91cSConrad Meyer #define	ioat_write_chanctrl(ioat, value) \
53e974f91cSConrad Meyer 	ioat_write_2((ioat), IOAT_CHANCTRL_OFFSET, (value))
54e974f91cSConrad Meyer 
55e974f91cSConrad Meyer static __inline uint64_t
56e974f91cSConrad Meyer ioat_bus_space_read_8_lower_first(bus_space_tag_t tag,
57e974f91cSConrad Meyer     bus_space_handle_t handle, bus_size_t offset)
58e974f91cSConrad Meyer {
59e974f91cSConrad Meyer 	return (bus_space_read_4(tag, handle, offset) |
60e974f91cSConrad Meyer 	    ((uint64_t)bus_space_read_4(tag, handle, offset + 4)) << 32);
61e974f91cSConrad Meyer }
62e974f91cSConrad Meyer 
63e974f91cSConrad Meyer static __inline void
64e974f91cSConrad Meyer ioat_bus_space_write_8_lower_first(bus_space_tag_t tag,
65e974f91cSConrad Meyer     bus_space_handle_t handle, bus_size_t offset, uint64_t val)
66e974f91cSConrad Meyer {
67e974f91cSConrad Meyer 	bus_space_write_4(tag, handle, offset, val);
68e974f91cSConrad Meyer 	bus_space_write_4(tag, handle, offset + 4, val >> 32);
69e974f91cSConrad Meyer }
70e974f91cSConrad Meyer 
71f3e30f97SConrad Meyer #ifdef __i386__
72e974f91cSConrad Meyer #define ioat_bus_space_read_8 ioat_bus_space_read_8_lower_first
73e974f91cSConrad Meyer #define ioat_bus_space_write_8 ioat_bus_space_write_8_lower_first
74e974f91cSConrad Meyer #else
75e974f91cSConrad Meyer #define ioat_bus_space_read_8(tag, handle, offset) \
76e974f91cSConrad Meyer 	bus_space_read_8((tag), (handle), (offset))
77e974f91cSConrad Meyer #define ioat_bus_space_write_8(tag, handle, offset, val) \
78e974f91cSConrad Meyer 	bus_space_write_8((tag), (handle), (offset), (val))
79e974f91cSConrad Meyer #endif
80e974f91cSConrad Meyer 
81e974f91cSConrad Meyer #define ioat_read_1(ioat, offset) \
82e974f91cSConrad Meyer 	bus_space_read_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
83e974f91cSConrad Meyer 	    (offset))
84e974f91cSConrad Meyer 
85e974f91cSConrad Meyer #define ioat_read_2(ioat, offset) \
86e974f91cSConrad Meyer 	bus_space_read_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
87e974f91cSConrad Meyer 	    (offset))
88e974f91cSConrad Meyer 
89e974f91cSConrad Meyer #define ioat_read_4(ioat, offset) \
90e974f91cSConrad Meyer 	bus_space_read_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
91e974f91cSConrad Meyer 	    (offset))
92e974f91cSConrad Meyer 
93e974f91cSConrad Meyer #define ioat_read_8(ioat, offset) \
94e974f91cSConrad Meyer 	ioat_bus_space_read_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
95e974f91cSConrad Meyer 	    (offset))
96e974f91cSConrad Meyer 
97e974f91cSConrad Meyer #define ioat_read_double_4(ioat, offset) \
98e974f91cSConrad Meyer 	ioat_bus_space_read_8_lower_first((ioat)->pci_bus_tag, \
99e974f91cSConrad Meyer 	    (ioat)->pci_bus_handle, (offset))
100e974f91cSConrad Meyer 
101e974f91cSConrad Meyer #define ioat_write_1(ioat, offset, value) \
102e974f91cSConrad Meyer 	bus_space_write_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
103e974f91cSConrad Meyer 	    (offset), (value))
104e974f91cSConrad Meyer 
105e974f91cSConrad Meyer #define ioat_write_2(ioat, offset, value) \
106e974f91cSConrad Meyer 	bus_space_write_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
107e974f91cSConrad Meyer 	    (offset), (value))
108e974f91cSConrad Meyer 
109e974f91cSConrad Meyer #define ioat_write_4(ioat, offset, value) \
110e974f91cSConrad Meyer 	bus_space_write_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
111e974f91cSConrad Meyer 	    (offset), (value))
112e974f91cSConrad Meyer 
113e974f91cSConrad Meyer #define ioat_write_8(ioat, offset, value) \
114e974f91cSConrad Meyer 	ioat_bus_space_write_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
115e974f91cSConrad Meyer 	    (offset), (value))
116e974f91cSConrad Meyer 
117e974f91cSConrad Meyer #define ioat_write_double_4(ioat, offset, value) \
118e974f91cSConrad Meyer 	ioat_bus_space_write_8_lower_first((ioat)->pci_bus_tag, \
119e974f91cSConrad Meyer 	    (ioat)->pci_bus_handle, (offset), (value))
120e974f91cSConrad Meyer 
121e974f91cSConrad Meyer MALLOC_DECLARE(M_IOAT);
122e974f91cSConrad Meyer 
123e974f91cSConrad Meyer SYSCTL_DECL(_hw_ioat);
124e974f91cSConrad Meyer 
1251c25420eSConrad Meyer extern int g_ioat_debug_level;
126e974f91cSConrad Meyer 
1279e3bbf26SConrad Meyer struct generic_dma_control {
1289e3bbf26SConrad Meyer 	uint32_t int_enable:1;
1299e3bbf26SConrad Meyer 	uint32_t src_snoop_disable:1;
1309e3bbf26SConrad Meyer 	uint32_t dest_snoop_disable:1;
1319e3bbf26SConrad Meyer 	uint32_t completion_update:1;
1329e3bbf26SConrad Meyer 	uint32_t fence:1;
1339e3bbf26SConrad Meyer 	uint32_t reserved1:1;
1349e3bbf26SConrad Meyer 	uint32_t src_page_break:1;
1359e3bbf26SConrad Meyer 	uint32_t dest_page_break:1;
1369e3bbf26SConrad Meyer 	uint32_t bundle:1;
1379e3bbf26SConrad Meyer 	uint32_t dest_dca:1;
1389e3bbf26SConrad Meyer 	uint32_t hint:1;
1399e3bbf26SConrad Meyer 	uint32_t reserved2:13;
1409e3bbf26SConrad Meyer 	uint32_t op:8;
1419e3bbf26SConrad Meyer };
1429e3bbf26SConrad Meyer 
1439e3bbf26SConrad Meyer struct ioat_generic_hw_descriptor {
1449e3bbf26SConrad Meyer 	uint32_t size;
1459e3bbf26SConrad Meyer 	union {
1469e3bbf26SConrad Meyer 		uint32_t control_raw;
1479e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
1489e3bbf26SConrad Meyer 	} u;
1499e3bbf26SConrad Meyer 	uint64_t src_addr;
1509e3bbf26SConrad Meyer 	uint64_t dest_addr;
1519e3bbf26SConrad Meyer 	uint64_t next;
1529e3bbf26SConrad Meyer 	uint64_t reserved[4];
1539e3bbf26SConrad Meyer };
1549e3bbf26SConrad Meyer 
155e974f91cSConrad Meyer struct ioat_dma_hw_descriptor {
156e974f91cSConrad Meyer 	uint32_t size;
157e974f91cSConrad Meyer 	union {
158e974f91cSConrad Meyer 		uint32_t control_raw;
1599e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
160e974f91cSConrad Meyer 		struct {
161e974f91cSConrad Meyer 			uint32_t int_enable:1;
162e974f91cSConrad Meyer 			uint32_t src_snoop_disable:1;
163e974f91cSConrad Meyer 			uint32_t dest_snoop_disable:1;
164e974f91cSConrad Meyer 			uint32_t completion_update:1;
165e974f91cSConrad Meyer 			uint32_t fence:1;
166e974f91cSConrad Meyer 			uint32_t null:1;
167e974f91cSConrad Meyer 			uint32_t src_page_break:1;
168e974f91cSConrad Meyer 			uint32_t dest_page_break:1;
169e974f91cSConrad Meyer 			uint32_t bundle:1;
170e974f91cSConrad Meyer 			uint32_t dest_dca:1;
171e974f91cSConrad Meyer 			uint32_t hint:1;
172e974f91cSConrad Meyer 			uint32_t reserved:13;
173e974f91cSConrad Meyer 			#define IOAT_OP_COPY 0x00
174e974f91cSConrad Meyer 			uint32_t op:8;
175e974f91cSConrad Meyer 		} control;
176e974f91cSConrad Meyer 	} u;
177e974f91cSConrad Meyer 	uint64_t src_addr;
178e974f91cSConrad Meyer 	uint64_t dest_addr;
179e974f91cSConrad Meyer 	uint64_t next;
1809950fde0SConrad Meyer 	uint64_t next_src_addr;
1819950fde0SConrad Meyer 	uint64_t next_dest_addr;
182e974f91cSConrad Meyer 	uint64_t user1;
183e974f91cSConrad Meyer 	uint64_t user2;
184e974f91cSConrad Meyer };
185e974f91cSConrad Meyer 
186e974f91cSConrad Meyer struct ioat_fill_hw_descriptor {
187e974f91cSConrad Meyer 	uint32_t size;
188e974f91cSConrad Meyer 	union {
189e974f91cSConrad Meyer 		uint32_t control_raw;
1909e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
191e974f91cSConrad Meyer 		struct {
192e974f91cSConrad Meyer 			uint32_t int_enable:1;
193e974f91cSConrad Meyer 			uint32_t reserved:1;
194e974f91cSConrad Meyer 			uint32_t dest_snoop_disable:1;
195e974f91cSConrad Meyer 			uint32_t completion_update:1;
196e974f91cSConrad Meyer 			uint32_t fence:1;
197e974f91cSConrad Meyer 			uint32_t reserved2:2;
198e974f91cSConrad Meyer 			uint32_t dest_page_break:1;
199e974f91cSConrad Meyer 			uint32_t bundle:1;
200e974f91cSConrad Meyer 			uint32_t reserved3:15;
201e974f91cSConrad Meyer 			#define IOAT_OP_FILL 0x01
202e974f91cSConrad Meyer 			uint32_t op:8;
203e974f91cSConrad Meyer 		} control;
204e974f91cSConrad Meyer 	} u;
205e974f91cSConrad Meyer 	uint64_t src_data;
206e974f91cSConrad Meyer 	uint64_t dest_addr;
207e974f91cSConrad Meyer 	uint64_t next;
208e974f91cSConrad Meyer 	uint64_t reserved;
209e974f91cSConrad Meyer 	uint64_t next_dest_addr;
210e974f91cSConrad Meyer 	uint64_t user1;
211e974f91cSConrad Meyer 	uint64_t user2;
212e974f91cSConrad Meyer };
213e974f91cSConrad Meyer 
214be3cbf60SConrad Meyer struct ioat_crc32_hw_descriptor {
215be3cbf60SConrad Meyer 	uint32_t size;
216be3cbf60SConrad Meyer 	union {
217be3cbf60SConrad Meyer 		uint32_t control_raw;
218be3cbf60SConrad Meyer 		struct generic_dma_control control_generic;
219be3cbf60SConrad Meyer 		struct {
220be3cbf60SConrad Meyer 			uint32_t int_enable:1;
221be3cbf60SConrad Meyer 			uint32_t src_snoop_disable:1;
222be3cbf60SConrad Meyer 			uint32_t dest_snoop_disable:1;
223be3cbf60SConrad Meyer 			uint32_t completion_update:1;
224be3cbf60SConrad Meyer 			uint32_t fence:1;
225be3cbf60SConrad Meyer 			uint32_t reserved1:3;
226be3cbf60SConrad Meyer 			uint32_t bundle:1;
227be3cbf60SConrad Meyer 			uint32_t dest_dca:1;
228be3cbf60SConrad Meyer 			uint32_t hint:1;
229be3cbf60SConrad Meyer 			uint32_t use_seed:1;
230be3cbf60SConrad Meyer 			/*
231be3cbf60SConrad Meyer 			 * crc_location:
232be3cbf60SConrad Meyer 			 * For IOAT_OP_MOVECRC_TEST and IOAT_OP_CRC_TEST:
233be3cbf60SConrad Meyer 			 * 0: comparison value is pointed to by CRC Address
234be3cbf60SConrad Meyer 			 *    field.
235be3cbf60SConrad Meyer 			 * 1: comparison value follows data in wire format
236be3cbf60SConrad Meyer 			 *    ("inverted reflected bit order") in the 4 bytes
237be3cbf60SConrad Meyer 			 *    following the source data.
238be3cbf60SConrad Meyer 			 *
239be3cbf60SConrad Meyer 			 * For IOAT_OP_CRC_STORE:
240be3cbf60SConrad Meyer 			 * 0: Result will be stored at location pointed to by
241be3cbf60SConrad Meyer 			 *    CRC Address field (in wire format).
242be3cbf60SConrad Meyer 			 * 1: Result will be stored directly following the
243be3cbf60SConrad Meyer 			 *    source data.
244be3cbf60SConrad Meyer 			 *
245be3cbf60SConrad Meyer 			 * For IOAT_OP_MOVECRC_STORE:
246be3cbf60SConrad Meyer 			 * 0: Result will be stored at location pointed to by
247be3cbf60SConrad Meyer 			 *    CRC Address field (in wire format).
248be3cbf60SConrad Meyer 			 * 1: Result will be stored directly following the
249be3cbf60SConrad Meyer 			 *    *destination* data.
250be3cbf60SConrad Meyer 			 */
251be3cbf60SConrad Meyer 			uint32_t crc_location:1;
252be3cbf60SConrad Meyer 			uint32_t reserved2:11;
253be3cbf60SConrad Meyer 			/*
254be3cbf60SConrad Meyer 			 * MOVECRC - Move data in the same way as standard copy
255be3cbf60SConrad Meyer 			 * operation, but also compute CRC32.
256be3cbf60SConrad Meyer 			 *
257be3cbf60SConrad Meyer 			 * CRC - Only compute CRC on source data.
258be3cbf60SConrad Meyer 			 *
259be3cbf60SConrad Meyer 			 * There is a CRC accumulator register in the hardware.
260be3cbf60SConrad Meyer 			 * If 'initial' is set, it is initialized to the value
261be3cbf60SConrad Meyer 			 * in 'seed.'
262be3cbf60SConrad Meyer 			 *
263be3cbf60SConrad Meyer 			 * In all modes, these operators accumulate size bytes
264be3cbf60SConrad Meyer 			 * at src_addr into the running CRC32C.
265be3cbf60SConrad Meyer 			 *
266be3cbf60SConrad Meyer 			 * Store mode emits the accumulated CRC, in wire
267be3cbf60SConrad Meyer 			 * format, as specified by the crc_location bit above.
268be3cbf60SConrad Meyer 			 *
269be3cbf60SConrad Meyer 			 * Test mode compares the accumulated CRC against the
270be3cbf60SConrad Meyer 			 * reference CRC, as described in crc_location above.
271be3cbf60SConrad Meyer 			 * On failure, halts the DMA engine with a CRC error
272be3cbf60SConrad Meyer 			 * status.
273be3cbf60SConrad Meyer 			 */
274be3cbf60SConrad Meyer 			#define	IOAT_OP_MOVECRC		0x41
275be3cbf60SConrad Meyer 			#define	IOAT_OP_MOVECRC_TEST	0x42
276be3cbf60SConrad Meyer 			#define	IOAT_OP_MOVECRC_STORE	0x43
277be3cbf60SConrad Meyer 			#define	IOAT_OP_CRC		0x81
278be3cbf60SConrad Meyer 			#define	IOAT_OP_CRC_TEST	0x82
279be3cbf60SConrad Meyer 			#define	IOAT_OP_CRC_STORE	0x83
280be3cbf60SConrad Meyer 			uint32_t op:8;
281be3cbf60SConrad Meyer 		} control;
282be3cbf60SConrad Meyer 	} u;
283be3cbf60SConrad Meyer 	uint64_t src_addr;
284be3cbf60SConrad Meyer 	uint64_t dest_addr;
285be3cbf60SConrad Meyer 	uint64_t next;
286be3cbf60SConrad Meyer 	uint64_t next_src_addr;
287be3cbf60SConrad Meyer 	uint64_t next_dest_addr;
288be3cbf60SConrad Meyer 	uint32_t seed;
289be3cbf60SConrad Meyer 	uint32_t reserved;
290be3cbf60SConrad Meyer 	uint64_t crc_address;
291be3cbf60SConrad Meyer };
292be3cbf60SConrad Meyer 
293e974f91cSConrad Meyer struct ioat_xor_hw_descriptor {
294e974f91cSConrad Meyer 	uint32_t size;
295e974f91cSConrad Meyer 	union {
296e974f91cSConrad Meyer 		uint32_t control_raw;
2979e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
298e974f91cSConrad Meyer 		struct {
299e974f91cSConrad Meyer 			uint32_t int_enable:1;
300e974f91cSConrad Meyer 			uint32_t src_snoop_disable:1;
301e974f91cSConrad Meyer 			uint32_t dest_snoop_disable:1;
302e974f91cSConrad Meyer 			uint32_t completion_update:1;
303e974f91cSConrad Meyer 			uint32_t fence:1;
304e974f91cSConrad Meyer 			uint32_t src_count:3;
305e974f91cSConrad Meyer 			uint32_t bundle:1;
306e974f91cSConrad Meyer 			uint32_t dest_dca:1;
307e974f91cSConrad Meyer 			uint32_t hint:1;
308e974f91cSConrad Meyer 			uint32_t reserved:13;
309e974f91cSConrad Meyer 			#define IOAT_OP_XOR 0x87
310e974f91cSConrad Meyer 			#define IOAT_OP_XOR_VAL 0x88
311e974f91cSConrad Meyer 			uint32_t op:8;
312e974f91cSConrad Meyer 		} control;
313e974f91cSConrad Meyer 	} u;
314e974f91cSConrad Meyer 	uint64_t src_addr;
315e974f91cSConrad Meyer 	uint64_t dest_addr;
316e974f91cSConrad Meyer 	uint64_t next;
317e974f91cSConrad Meyer 	uint64_t src_addr2;
318e974f91cSConrad Meyer 	uint64_t src_addr3;
319e974f91cSConrad Meyer 	uint64_t src_addr4;
320e974f91cSConrad Meyer 	uint64_t src_addr5;
321e974f91cSConrad Meyer };
322e974f91cSConrad Meyer 
323e974f91cSConrad Meyer struct ioat_xor_ext_hw_descriptor {
324e974f91cSConrad Meyer 	uint64_t src_addr6;
325e974f91cSConrad Meyer 	uint64_t src_addr7;
326e974f91cSConrad Meyer 	uint64_t src_addr8;
327e974f91cSConrad Meyer 	uint64_t next;
328e974f91cSConrad Meyer 	uint64_t reserved[4];
329e974f91cSConrad Meyer };
330e974f91cSConrad Meyer 
331e974f91cSConrad Meyer struct ioat_pq_hw_descriptor {
332e974f91cSConrad Meyer 	uint32_t size;
333e974f91cSConrad Meyer 	union {
334e974f91cSConrad Meyer 		uint32_t control_raw;
3359e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
336e974f91cSConrad Meyer 		struct {
337e974f91cSConrad Meyer 			uint32_t int_enable:1;
338e974f91cSConrad Meyer 			uint32_t src_snoop_disable:1;
339e974f91cSConrad Meyer 			uint32_t dest_snoop_disable:1;
340e974f91cSConrad Meyer 			uint32_t completion_update:1;
341e974f91cSConrad Meyer 			uint32_t fence:1;
342e974f91cSConrad Meyer 			uint32_t src_count:3;
343e974f91cSConrad Meyer 			uint32_t bundle:1;
344e974f91cSConrad Meyer 			uint32_t dest_dca:1;
345e974f91cSConrad Meyer 			uint32_t hint:1;
346e974f91cSConrad Meyer 			uint32_t p_disable:1;
347e974f91cSConrad Meyer 			uint32_t q_disable:1;
348e974f91cSConrad Meyer 			uint32_t reserved:11;
349e974f91cSConrad Meyer 			#define IOAT_OP_PQ 0x89
350e974f91cSConrad Meyer 			#define IOAT_OP_PQ_VAL 0x8a
351e974f91cSConrad Meyer 			uint32_t op:8;
352e974f91cSConrad Meyer 		} control;
353e974f91cSConrad Meyer 	} u;
354e974f91cSConrad Meyer 	uint64_t src_addr;
355e974f91cSConrad Meyer 	uint64_t p_addr;
356e974f91cSConrad Meyer 	uint64_t next;
357e974f91cSConrad Meyer 	uint64_t src_addr2;
358e974f91cSConrad Meyer 	uint64_t src_addr3;
359e974f91cSConrad Meyer 	uint8_t  coef[8];
360e974f91cSConrad Meyer 	uint64_t q_addr;
361e974f91cSConrad Meyer };
362e974f91cSConrad Meyer 
363e974f91cSConrad Meyer struct ioat_pq_ext_hw_descriptor {
364e974f91cSConrad Meyer 	uint64_t src_addr4;
365e974f91cSConrad Meyer 	uint64_t src_addr5;
366e974f91cSConrad Meyer 	uint64_t src_addr6;
367e974f91cSConrad Meyer 	uint64_t next;
368e974f91cSConrad Meyer 	uint64_t src_addr7;
369e974f91cSConrad Meyer 	uint64_t src_addr8;
370e974f91cSConrad Meyer 	uint64_t reserved[2];
371e974f91cSConrad Meyer };
372e974f91cSConrad Meyer 
373e974f91cSConrad Meyer struct ioat_pq_update_hw_descriptor {
374e974f91cSConrad Meyer 	uint32_t size;
375e974f91cSConrad Meyer 	union {
376e974f91cSConrad Meyer 		uint32_t control_raw;
3779e3bbf26SConrad Meyer 		struct generic_dma_control control_generic;
378e974f91cSConrad Meyer 		struct {
379e974f91cSConrad Meyer 			uint32_t int_enable:1;
380e974f91cSConrad Meyer 			uint32_t src_snoop_disable:1;
381e974f91cSConrad Meyer 			uint32_t dest_snoop_disable:1;
382e974f91cSConrad Meyer 			uint32_t completion_update:1;
383e974f91cSConrad Meyer 			uint32_t fence:1;
384e974f91cSConrad Meyer 			uint32_t src_cnt:3;
385e974f91cSConrad Meyer 			uint32_t bundle:1;
386e974f91cSConrad Meyer 			uint32_t dest_dca:1;
387e974f91cSConrad Meyer 			uint32_t hint:1;
388e974f91cSConrad Meyer 			uint32_t p_disable:1;
389e974f91cSConrad Meyer 			uint32_t q_disable:1;
390e974f91cSConrad Meyer 			uint32_t reserved:3;
391e974f91cSConrad Meyer 			uint32_t coef:8;
392e974f91cSConrad Meyer 			#define IOAT_OP_PQ_UP 0x8b
393e974f91cSConrad Meyer 			uint32_t op:8;
394e974f91cSConrad Meyer 		} control;
395e974f91cSConrad Meyer 	} u;
396e974f91cSConrad Meyer 	uint64_t src_addr;
397e974f91cSConrad Meyer 	uint64_t p_addr;
398e974f91cSConrad Meyer 	uint64_t next;
399e974f91cSConrad Meyer 	uint64_t src_addr2;
400e974f91cSConrad Meyer 	uint64_t p_src;
401e974f91cSConrad Meyer 	uint64_t q_src;
402e974f91cSConrad Meyer 	uint64_t q_addr;
403e974f91cSConrad Meyer };
404e974f91cSConrad Meyer 
405e974f91cSConrad Meyer struct ioat_raw_hw_descriptor {
406e974f91cSConrad Meyer 	uint64_t field[8];
407e974f91cSConrad Meyer };
408e974f91cSConrad Meyer 
409e974f91cSConrad Meyer struct bus_dmadesc {
410e974f91cSConrad Meyer 	bus_dmaengine_callback_t callback_fn;
411e974f91cSConrad Meyer 	void			 *callback_arg;
412e974f91cSConrad Meyer };
413e974f91cSConrad Meyer 
414e974f91cSConrad Meyer struct ioat_descriptor {
415e974f91cSConrad Meyer 	struct bus_dmadesc	bus_dmadesc;
416e974f91cSConrad Meyer 	uint32_t		id;
417e974f91cSConrad Meyer };
418e974f91cSConrad Meyer 
419be3cbf60SConrad Meyer /* Unused by this driver at this time. */
420564af7a6SConrad Meyer #define	IOAT_OP_MARKER		0x84
421564af7a6SConrad Meyer 
422564af7a6SConrad Meyer /*
423564af7a6SConrad Meyer  * Deprecated OPs -- v3 DMA generates an abort if given these.  And this driver
424564af7a6SConrad Meyer  * doesn't support anything older than v3.
425564af7a6SConrad Meyer  */
426564af7a6SConrad Meyer #define	IOAT_OP_OLD_XOR		0x85
427564af7a6SConrad Meyer #define	IOAT_OP_OLD_XOR_VAL	0x86
428564af7a6SConrad Meyer 
429466b3540SConrad Meyer enum ioat_ref_kind {
430466b3540SConrad Meyer 	IOAT_DMAENGINE_REF = 0,
431466b3540SConrad Meyer 	IOAT_ACTIVE_DESCR_REF,
432466b3540SConrad Meyer 	IOAT_NUM_REF_KINDS
433466b3540SConrad Meyer };
434466b3540SConrad Meyer 
435e974f91cSConrad Meyer /* One of these per allocated PCI device. */
436e974f91cSConrad Meyer struct ioat_softc {
437e974f91cSConrad Meyer 	bus_dmaengine_t		dmaengine;
438e974f91cSConrad Meyer #define	to_ioat_softc(_dmaeng)						\
439e974f91cSConrad Meyer ({									\
440e974f91cSConrad Meyer 	bus_dmaengine_t *_p = (_dmaeng);				\
441e974f91cSConrad Meyer 	(struct ioat_softc *)((char *)_p -				\
442e974f91cSConrad Meyer 	    offsetof(struct ioat_softc, dmaengine));			\
443e974f91cSConrad Meyer })
444e974f91cSConrad Meyer 
445e974f91cSConrad Meyer 	int			version;
446df1928aaSConrad Meyer 	unsigned		chan_idx;
447e974f91cSConrad Meyer 
448e974f91cSConrad Meyer 	struct mtx		submit_lock;
449e974f91cSConrad Meyer 	device_t		device;
450e974f91cSConrad Meyer 	bus_space_tag_t		pci_bus_tag;
451e974f91cSConrad Meyer 	bus_space_handle_t	pci_bus_handle;
452e974f91cSConrad Meyer 	int			pci_resource_id;
453e974f91cSConrad Meyer 	struct resource		*pci_resource;
454e974f91cSConrad Meyer 	uint32_t		max_xfer_size;
4551693d27bSConrad Meyer 	uint32_t		capabilities;
4565ca9fc2aSConrad Meyer 	uint16_t		intrdelay_max;
4575ca9fc2aSConrad Meyer 	uint16_t		cached_intrdelay;
458e974f91cSConrad Meyer 
459e974f91cSConrad Meyer 	struct resource		*res;
460e974f91cSConrad Meyer 	int			rid;
461e974f91cSConrad Meyer 	void			*tag;
462e974f91cSConrad Meyer 
463e974f91cSConrad Meyer 	bus_dma_tag_t		hw_desc_tag;
464e974f91cSConrad Meyer 	bus_dmamap_t		hw_desc_map;
465e974f91cSConrad Meyer 
466e974f91cSConrad Meyer 	bus_dma_tag_t		comp_update_tag;
467e974f91cSConrad Meyer 	bus_dmamap_t		comp_update_map;
468e974f91cSConrad Meyer 	uint64_t		*comp_update;
469e974f91cSConrad Meyer 	bus_addr_t		comp_update_bus_addr;
470e974f91cSConrad Meyer 
4715ac77963SConrad Meyer 	struct callout		poll_timer;
4725ac77963SConrad Meyer 	struct callout		shrink_timer;
473374b05e1SConrad Meyer 	struct task		reset_task;
474e974f91cSConrad Meyer 
4755f77bd3eSConrad Meyer 	boolean_t		quiescing;
4760ff814e8SConrad Meyer 	boolean_t		destroying;
47725ad9585SConrad Meyer 	boolean_t		is_submitter_processing;
4785ac77963SConrad Meyer 	boolean_t		is_completion_pending;	/* submit_lock */
479e974f91cSConrad Meyer 	boolean_t		is_reset_pending;
480e974f91cSConrad Meyer 	boolean_t		is_channel_running;
4815ca9fc2aSConrad Meyer 	boolean_t		intrdelay_supported;
482fe8712f8SConrad Meyer 	boolean_t		resetting;		/* submit_lock */
483fe8712f8SConrad Meyer 	boolean_t		resetting_cleanup;	/* cleanup_lock */
484e974f91cSConrad Meyer 
485e974f91cSConrad Meyer 	uint32_t		head;
486e974f91cSConrad Meyer 	uint32_t		tail;
487bf8553eaSConrad Meyer 	uint32_t		hw_head;
488e974f91cSConrad Meyer 	uint32_t		ring_size_order;
489e974f91cSConrad Meyer 	bus_addr_t		last_seen;
490e974f91cSConrad Meyer 
491*8e269d99SConrad Meyer 	struct ioat_descriptor	*ring;
492*8e269d99SConrad Meyer 
493*8e269d99SConrad Meyer 	union ioat_hw_descriptor {
494*8e269d99SConrad Meyer 		struct ioat_generic_hw_descriptor	generic;
495*8e269d99SConrad Meyer 		struct ioat_dma_hw_descriptor		dma;
496*8e269d99SConrad Meyer 		struct ioat_fill_hw_descriptor		fill;
497*8e269d99SConrad Meyer 		struct ioat_crc32_hw_descriptor		crc32;
498*8e269d99SConrad Meyer 		struct ioat_xor_hw_descriptor		xor;
499*8e269d99SConrad Meyer 		struct ioat_xor_ext_hw_descriptor	xor_ext;
500*8e269d99SConrad Meyer 		struct ioat_pq_hw_descriptor		pq;
501*8e269d99SConrad Meyer 		struct ioat_pq_ext_hw_descriptor	pq_ext;
502*8e269d99SConrad Meyer 		struct ioat_raw_hw_descriptor		raw;
503*8e269d99SConrad Meyer 	} *hw_desc_ring;
504*8e269d99SConrad Meyer 	bus_addr_t		hw_desc_bus_addr;
505*8e269d99SConrad Meyer #define	RING_PHYS_ADDR(sc, i)	(sc)->hw_desc_bus_addr + \
506*8e269d99SConrad Meyer     (((i) % (1 << (sc)->ring_size_order)) * sizeof(struct ioat_dma_hw_descriptor))
507e974f91cSConrad Meyer 
508e974f91cSConrad Meyer 	struct mtx		cleanup_lock;
509466b3540SConrad Meyer 	volatile uint32_t	refcnt;
510466b3540SConrad Meyer #ifdef INVARIANTS
511466b3540SConrad Meyer 	volatile uint32_t	refkinds[IOAT_NUM_REF_KINDS];
512466b3540SConrad Meyer #endif
51301fbbc88SConrad Meyer 
51401fbbc88SConrad Meyer 	struct {
51501fbbc88SConrad Meyer 		uint64_t	interrupts;
51601fbbc88SConrad Meyer 		uint64_t	descriptors_processed;
51701fbbc88SConrad Meyer 		uint64_t	descriptors_error;
51801fbbc88SConrad Meyer 		uint64_t	descriptors_submitted;
51901fbbc88SConrad Meyer 
52001fbbc88SConrad Meyer 		uint32_t	channel_halts;
52101fbbc88SConrad Meyer 		uint32_t	last_halt_chanerr;
52201fbbc88SConrad Meyer 	} stats;
523e974f91cSConrad Meyer };
524e974f91cSConrad Meyer 
5257afbb263SConrad Meyer void ioat_test_attach(void);
5267afbb263SConrad Meyer void ioat_test_detach(void);
5277afbb263SConrad Meyer 
5280d0f2640SConrad Meyer /*
5290d0f2640SConrad Meyer  * XXX DO NOT USE this routine for obtaining the current completed descriptor.
5300d0f2640SConrad Meyer  *
5310d0f2640SConrad Meyer  * The double_4 read on ioat<3.3 appears to result in torn reads.  And v3.2
5320d0f2640SConrad Meyer  * hardware is still commonplace (Broadwell Xeon has it).  Instead, use the
5330d0f2640SConrad Meyer  * device-pushed *comp_update.
5340d0f2640SConrad Meyer  *
5350d0f2640SConrad Meyer  * It is safe to use ioat_get_chansts() for the low status bits.
5360d0f2640SConrad Meyer  */
537e974f91cSConrad Meyer static inline uint64_t
538e974f91cSConrad Meyer ioat_get_chansts(struct ioat_softc *ioat)
539e974f91cSConrad Meyer {
540e974f91cSConrad Meyer 	uint64_t status;
541e974f91cSConrad Meyer 
542e974f91cSConrad Meyer 	if (ioat->version >= IOAT_VER_3_3)
543e974f91cSConrad Meyer 		status = ioat_read_8(ioat, IOAT_CHANSTS_OFFSET);
544e974f91cSConrad Meyer 	else
545e974f91cSConrad Meyer 		/* Must read lower 4 bytes before upper 4 bytes. */
546e974f91cSConrad Meyer 		status = ioat_read_double_4(ioat, IOAT_CHANSTS_OFFSET);
547e974f91cSConrad Meyer 	return (status);
548e974f91cSConrad Meyer }
549e974f91cSConrad Meyer 
550e974f91cSConrad Meyer static inline void
551e974f91cSConrad Meyer ioat_write_chancmp(struct ioat_softc *ioat, uint64_t addr)
552e974f91cSConrad Meyer {
553e974f91cSConrad Meyer 
554e974f91cSConrad Meyer 	if (ioat->version >= IOAT_VER_3_3)
555e974f91cSConrad Meyer 		ioat_write_8(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
556e974f91cSConrad Meyer 	else
557e974f91cSConrad Meyer 		ioat_write_double_4(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
558e974f91cSConrad Meyer }
559e974f91cSConrad Meyer 
560e974f91cSConrad Meyer static inline void
561e974f91cSConrad Meyer ioat_write_chainaddr(struct ioat_softc *ioat, uint64_t addr)
562e974f91cSConrad Meyer {
563e974f91cSConrad Meyer 
564e974f91cSConrad Meyer 	if (ioat->version >= IOAT_VER_3_3)
565e974f91cSConrad Meyer 		ioat_write_8(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
566e974f91cSConrad Meyer 	else
567e974f91cSConrad Meyer 		ioat_write_double_4(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
568e974f91cSConrad Meyer }
569e974f91cSConrad Meyer 
570e974f91cSConrad Meyer static inline boolean_t
571e974f91cSConrad Meyer is_ioat_active(uint64_t status)
572e974f91cSConrad Meyer {
573e974f91cSConrad Meyer 	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_ACTIVE);
574e974f91cSConrad Meyer }
575e974f91cSConrad Meyer 
576e974f91cSConrad Meyer static inline boolean_t
577e974f91cSConrad Meyer is_ioat_idle(uint64_t status)
578e974f91cSConrad Meyer {
579e974f91cSConrad Meyer 	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_IDLE);
580e974f91cSConrad Meyer }
581e974f91cSConrad Meyer 
582e974f91cSConrad Meyer static inline boolean_t
583e974f91cSConrad Meyer is_ioat_halted(uint64_t status)
584e974f91cSConrad Meyer {
585e974f91cSConrad Meyer 	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_HALTED);
586e974f91cSConrad Meyer }
587e974f91cSConrad Meyer 
588e974f91cSConrad Meyer static inline boolean_t
589e974f91cSConrad Meyer is_ioat_suspended(uint64_t status)
590e974f91cSConrad Meyer {
591e974f91cSConrad Meyer 	return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_SUSPENDED);
592e974f91cSConrad Meyer }
593e974f91cSConrad Meyer 
594e974f91cSConrad Meyer static inline void
595e974f91cSConrad Meyer ioat_suspend(struct ioat_softc *ioat)
596e974f91cSConrad Meyer {
597e974f91cSConrad Meyer 	ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_SUSPEND);
598e974f91cSConrad Meyer }
599e974f91cSConrad Meyer 
600e974f91cSConrad Meyer static inline void
601e974f91cSConrad Meyer ioat_reset(struct ioat_softc *ioat)
602e974f91cSConrad Meyer {
603e974f91cSConrad Meyer 	ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
604e974f91cSConrad Meyer }
605e974f91cSConrad Meyer 
606e974f91cSConrad Meyer static inline boolean_t
607e974f91cSConrad Meyer ioat_reset_pending(struct ioat_softc *ioat)
608e974f91cSConrad Meyer {
609e974f91cSConrad Meyer 	uint8_t cmd;
610e974f91cSConrad Meyer 
611e974f91cSConrad Meyer 	cmd = ioat_read_1(ioat, IOAT_CHANCMD_OFFSET);
612e974f91cSConrad Meyer 	return ((cmd & IOAT_CHANCMD_RESET) != 0);
613e974f91cSConrad Meyer }
614e974f91cSConrad Meyer 
615e974f91cSConrad Meyer #endif /* __IOAT_INTERNAL_H__ */
616