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 #ifndef __IOAT_INTERNAL_H__
27e974f91cSConrad Meyer #define __IOAT_INTERNAL_H__
28e974f91cSConrad Meyer
29374b05e1SConrad Meyer #include <sys/_task.h>
30374b05e1SConrad Meyer
31e974f91cSConrad Meyer #define DEVICE2SOFTC(dev) ((struct ioat_softc *) device_get_softc(dev))
3243fc1847SConrad Meyer #define KTR_IOAT KTR_SPARE3
33e974f91cSConrad Meyer
34e974f91cSConrad Meyer #define ioat_read_chancnt(ioat) \
35e974f91cSConrad Meyer ioat_read_1((ioat), IOAT_CHANCNT_OFFSET)
36e974f91cSConrad Meyer
37e974f91cSConrad Meyer #define ioat_read_xfercap(ioat) \
38b81eee4aSConrad Meyer (ioat_read_1((ioat), IOAT_XFERCAP_OFFSET) & IOAT_XFERCAP_VALID_MASK)
39e974f91cSConrad Meyer
40e974f91cSConrad Meyer #define ioat_write_intrctrl(ioat, value) \
41e974f91cSConrad Meyer ioat_write_1((ioat), IOAT_INTRCTRL_OFFSET, (value))
42e974f91cSConrad Meyer
43e974f91cSConrad Meyer #define ioat_read_cbver(ioat) \
44e974f91cSConrad Meyer (ioat_read_1((ioat), IOAT_CBVER_OFFSET) & 0xFF)
45e974f91cSConrad Meyer
46e974f91cSConrad Meyer #define ioat_read_dmacapability(ioat) \
47e974f91cSConrad Meyer ioat_read_4((ioat), IOAT_DMACAPABILITY_OFFSET)
48e974f91cSConrad Meyer
49e974f91cSConrad Meyer #define ioat_write_chanctrl(ioat, value) \
50e974f91cSConrad Meyer ioat_write_2((ioat), IOAT_CHANCTRL_OFFSET, (value))
51e974f91cSConrad Meyer
52e974f91cSConrad Meyer static __inline uint64_t
ioat_bus_space_read_8_lower_first(bus_space_tag_t tag,bus_space_handle_t handle,bus_size_t offset)53e974f91cSConrad Meyer ioat_bus_space_read_8_lower_first(bus_space_tag_t tag,
54e974f91cSConrad Meyer bus_space_handle_t handle, bus_size_t offset)
55e974f91cSConrad Meyer {
56e974f91cSConrad Meyer return (bus_space_read_4(tag, handle, offset) |
57e974f91cSConrad Meyer ((uint64_t)bus_space_read_4(tag, handle, offset + 4)) << 32);
58e974f91cSConrad Meyer }
59e974f91cSConrad Meyer
60e974f91cSConrad Meyer static __inline void
ioat_bus_space_write_8_lower_first(bus_space_tag_t tag,bus_space_handle_t handle,bus_size_t offset,uint64_t val)61e974f91cSConrad Meyer ioat_bus_space_write_8_lower_first(bus_space_tag_t tag,
62e974f91cSConrad Meyer bus_space_handle_t handle, bus_size_t offset, uint64_t val)
63e974f91cSConrad Meyer {
64e974f91cSConrad Meyer bus_space_write_4(tag, handle, offset, val);
65e974f91cSConrad Meyer bus_space_write_4(tag, handle, offset + 4, val >> 32);
66e974f91cSConrad Meyer }
67e974f91cSConrad Meyer
68f3e30f97SConrad Meyer #ifdef __i386__
69e974f91cSConrad Meyer #define ioat_bus_space_read_8 ioat_bus_space_read_8_lower_first
70e974f91cSConrad Meyer #define ioat_bus_space_write_8 ioat_bus_space_write_8_lower_first
71e974f91cSConrad Meyer #else
72e974f91cSConrad Meyer #define ioat_bus_space_read_8(tag, handle, offset) \
73e974f91cSConrad Meyer bus_space_read_8((tag), (handle), (offset))
74e974f91cSConrad Meyer #define ioat_bus_space_write_8(tag, handle, offset, val) \
75e974f91cSConrad Meyer bus_space_write_8((tag), (handle), (offset), (val))
76e974f91cSConrad Meyer #endif
77e974f91cSConrad Meyer
78e974f91cSConrad Meyer #define ioat_read_1(ioat, offset) \
79e974f91cSConrad Meyer bus_space_read_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
80e974f91cSConrad Meyer (offset))
81e974f91cSConrad Meyer
82e974f91cSConrad Meyer #define ioat_read_2(ioat, offset) \
83e974f91cSConrad Meyer bus_space_read_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
84e974f91cSConrad Meyer (offset))
85e974f91cSConrad Meyer
86e974f91cSConrad Meyer #define ioat_read_4(ioat, offset) \
87e974f91cSConrad Meyer bus_space_read_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
88e974f91cSConrad Meyer (offset))
89e974f91cSConrad Meyer
90e974f91cSConrad Meyer #define ioat_read_8(ioat, offset) \
91e974f91cSConrad Meyer ioat_bus_space_read_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
92e974f91cSConrad Meyer (offset))
93e974f91cSConrad Meyer
94e974f91cSConrad Meyer #define ioat_read_double_4(ioat, offset) \
95e974f91cSConrad Meyer ioat_bus_space_read_8_lower_first((ioat)->pci_bus_tag, \
96e974f91cSConrad Meyer (ioat)->pci_bus_handle, (offset))
97e974f91cSConrad Meyer
98e974f91cSConrad Meyer #define ioat_write_1(ioat, offset, value) \
99e974f91cSConrad Meyer bus_space_write_1((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
100e974f91cSConrad Meyer (offset), (value))
101e974f91cSConrad Meyer
102e974f91cSConrad Meyer #define ioat_write_2(ioat, offset, value) \
103e974f91cSConrad Meyer bus_space_write_2((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
104e974f91cSConrad Meyer (offset), (value))
105e974f91cSConrad Meyer
106e974f91cSConrad Meyer #define ioat_write_4(ioat, offset, value) \
107e974f91cSConrad Meyer bus_space_write_4((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
108e974f91cSConrad Meyer (offset), (value))
109e974f91cSConrad Meyer
110e974f91cSConrad Meyer #define ioat_write_8(ioat, offset, value) \
111e974f91cSConrad Meyer ioat_bus_space_write_8((ioat)->pci_bus_tag, (ioat)->pci_bus_handle, \
112e974f91cSConrad Meyer (offset), (value))
113e974f91cSConrad Meyer
114e974f91cSConrad Meyer #define ioat_write_double_4(ioat, offset, value) \
115e974f91cSConrad Meyer ioat_bus_space_write_8_lower_first((ioat)->pci_bus_tag, \
116e974f91cSConrad Meyer (ioat)->pci_bus_handle, (offset), (value))
117e974f91cSConrad Meyer
118e974f91cSConrad Meyer MALLOC_DECLARE(M_IOAT);
119e974f91cSConrad Meyer
120e974f91cSConrad Meyer SYSCTL_DECL(_hw_ioat);
121e974f91cSConrad Meyer
1221c25420eSConrad Meyer extern int g_ioat_debug_level;
123e974f91cSConrad Meyer
1249e3bbf26SConrad Meyer struct generic_dma_control {
1259e3bbf26SConrad Meyer uint32_t int_enable:1;
1269e3bbf26SConrad Meyer uint32_t src_snoop_disable:1;
1279e3bbf26SConrad Meyer uint32_t dest_snoop_disable:1;
1289e3bbf26SConrad Meyer uint32_t completion_update:1;
1299e3bbf26SConrad Meyer uint32_t fence:1;
1309e3bbf26SConrad Meyer uint32_t reserved1:1;
1319e3bbf26SConrad Meyer uint32_t src_page_break:1;
1329e3bbf26SConrad Meyer uint32_t dest_page_break:1;
1339e3bbf26SConrad Meyer uint32_t bundle:1;
1349e3bbf26SConrad Meyer uint32_t dest_dca:1;
1359e3bbf26SConrad Meyer uint32_t hint:1;
1369e3bbf26SConrad Meyer uint32_t reserved2:13;
1379e3bbf26SConrad Meyer uint32_t op:8;
1389e3bbf26SConrad Meyer };
1399e3bbf26SConrad Meyer
1409e3bbf26SConrad Meyer struct ioat_generic_hw_descriptor {
1419e3bbf26SConrad Meyer uint32_t size;
1429e3bbf26SConrad Meyer union {
1439e3bbf26SConrad Meyer uint32_t control_raw;
1449e3bbf26SConrad Meyer struct generic_dma_control control_generic;
1459e3bbf26SConrad Meyer } u;
1469e3bbf26SConrad Meyer uint64_t src_addr;
1479e3bbf26SConrad Meyer uint64_t dest_addr;
1489e3bbf26SConrad Meyer uint64_t next;
1499e3bbf26SConrad Meyer uint64_t reserved[4];
1509e3bbf26SConrad Meyer };
1519e3bbf26SConrad Meyer
152e974f91cSConrad Meyer struct ioat_dma_hw_descriptor {
153e974f91cSConrad Meyer uint32_t size;
154e974f91cSConrad Meyer union {
155e974f91cSConrad Meyer uint32_t control_raw;
1569e3bbf26SConrad Meyer struct generic_dma_control control_generic;
157e974f91cSConrad Meyer struct {
158e974f91cSConrad Meyer uint32_t int_enable:1;
159e974f91cSConrad Meyer uint32_t src_snoop_disable:1;
160e974f91cSConrad Meyer uint32_t dest_snoop_disable:1;
161e974f91cSConrad Meyer uint32_t completion_update:1;
162e974f91cSConrad Meyer uint32_t fence:1;
163e974f91cSConrad Meyer uint32_t null:1;
164e974f91cSConrad Meyer uint32_t src_page_break:1;
165e974f91cSConrad Meyer uint32_t dest_page_break:1;
166e974f91cSConrad Meyer uint32_t bundle:1;
167e974f91cSConrad Meyer uint32_t dest_dca:1;
168e974f91cSConrad Meyer uint32_t hint:1;
169e974f91cSConrad Meyer uint32_t reserved:13;
170e974f91cSConrad Meyer #define IOAT_OP_COPY 0x00
171e974f91cSConrad Meyer uint32_t op:8;
172e974f91cSConrad Meyer } control;
173e974f91cSConrad Meyer } u;
174e974f91cSConrad Meyer uint64_t src_addr;
175e974f91cSConrad Meyer uint64_t dest_addr;
176e974f91cSConrad Meyer uint64_t next;
1779950fde0SConrad Meyer uint64_t next_src_addr;
1789950fde0SConrad Meyer uint64_t next_dest_addr;
179e974f91cSConrad Meyer uint64_t user1;
180e974f91cSConrad Meyer uint64_t user2;
181e974f91cSConrad Meyer };
182e974f91cSConrad Meyer
183e974f91cSConrad Meyer struct ioat_fill_hw_descriptor {
184e974f91cSConrad Meyer uint32_t size;
185e974f91cSConrad Meyer union {
186e974f91cSConrad Meyer uint32_t control_raw;
1879e3bbf26SConrad Meyer struct generic_dma_control control_generic;
188e974f91cSConrad Meyer struct {
189e974f91cSConrad Meyer uint32_t int_enable:1;
190e974f91cSConrad Meyer uint32_t reserved:1;
191e974f91cSConrad Meyer uint32_t dest_snoop_disable:1;
192e974f91cSConrad Meyer uint32_t completion_update:1;
193e974f91cSConrad Meyer uint32_t fence:1;
194e974f91cSConrad Meyer uint32_t reserved2:2;
195e974f91cSConrad Meyer uint32_t dest_page_break:1;
196e974f91cSConrad Meyer uint32_t bundle:1;
197e974f91cSConrad Meyer uint32_t reserved3:15;
198e974f91cSConrad Meyer #define IOAT_OP_FILL 0x01
199e974f91cSConrad Meyer uint32_t op:8;
200e974f91cSConrad Meyer } control;
201e974f91cSConrad Meyer } u;
202e974f91cSConrad Meyer uint64_t src_data;
203e974f91cSConrad Meyer uint64_t dest_addr;
204e974f91cSConrad Meyer uint64_t next;
205e974f91cSConrad Meyer uint64_t reserved;
206e974f91cSConrad Meyer uint64_t next_dest_addr;
207e974f91cSConrad Meyer uint64_t user1;
208e974f91cSConrad Meyer uint64_t user2;
209e974f91cSConrad Meyer };
210e974f91cSConrad Meyer
211be3cbf60SConrad Meyer struct ioat_crc32_hw_descriptor {
212be3cbf60SConrad Meyer uint32_t size;
213be3cbf60SConrad Meyer union {
214be3cbf60SConrad Meyer uint32_t control_raw;
215be3cbf60SConrad Meyer struct generic_dma_control control_generic;
216be3cbf60SConrad Meyer struct {
217be3cbf60SConrad Meyer uint32_t int_enable:1;
218be3cbf60SConrad Meyer uint32_t src_snoop_disable:1;
219be3cbf60SConrad Meyer uint32_t dest_snoop_disable:1;
220be3cbf60SConrad Meyer uint32_t completion_update:1;
221be3cbf60SConrad Meyer uint32_t fence:1;
222be3cbf60SConrad Meyer uint32_t reserved1:3;
223be3cbf60SConrad Meyer uint32_t bundle:1;
224be3cbf60SConrad Meyer uint32_t dest_dca:1;
225be3cbf60SConrad Meyer uint32_t hint:1;
226be3cbf60SConrad Meyer uint32_t use_seed:1;
227be3cbf60SConrad Meyer /*
228be3cbf60SConrad Meyer * crc_location:
229be3cbf60SConrad Meyer * For IOAT_OP_MOVECRC_TEST and IOAT_OP_CRC_TEST:
230be3cbf60SConrad Meyer * 0: comparison value is pointed to by CRC Address
231be3cbf60SConrad Meyer * field.
232be3cbf60SConrad Meyer * 1: comparison value follows data in wire format
233be3cbf60SConrad Meyer * ("inverted reflected bit order") in the 4 bytes
234be3cbf60SConrad Meyer * following the source data.
235be3cbf60SConrad Meyer *
236be3cbf60SConrad Meyer * For IOAT_OP_CRC_STORE:
237be3cbf60SConrad Meyer * 0: Result will be stored at location pointed to by
238be3cbf60SConrad Meyer * CRC Address field (in wire format).
239be3cbf60SConrad Meyer * 1: Result will be stored directly following the
240be3cbf60SConrad Meyer * source data.
241be3cbf60SConrad Meyer *
242be3cbf60SConrad Meyer * For IOAT_OP_MOVECRC_STORE:
243be3cbf60SConrad Meyer * 0: Result will be stored at location pointed to by
244be3cbf60SConrad Meyer * CRC Address field (in wire format).
245be3cbf60SConrad Meyer * 1: Result will be stored directly following the
246be3cbf60SConrad Meyer * *destination* data.
247be3cbf60SConrad Meyer */
248be3cbf60SConrad Meyer uint32_t crc_location:1;
249be3cbf60SConrad Meyer uint32_t reserved2:11;
250be3cbf60SConrad Meyer /*
251be3cbf60SConrad Meyer * MOVECRC - Move data in the same way as standard copy
252be3cbf60SConrad Meyer * operation, but also compute CRC32.
253be3cbf60SConrad Meyer *
254be3cbf60SConrad Meyer * CRC - Only compute CRC on source data.
255be3cbf60SConrad Meyer *
256be3cbf60SConrad Meyer * There is a CRC accumulator register in the hardware.
257be3cbf60SConrad Meyer * If 'initial' is set, it is initialized to the value
258be3cbf60SConrad Meyer * in 'seed.'
259be3cbf60SConrad Meyer *
260be3cbf60SConrad Meyer * In all modes, these operators accumulate size bytes
261be3cbf60SConrad Meyer * at src_addr into the running CRC32C.
262be3cbf60SConrad Meyer *
263be3cbf60SConrad Meyer * Store mode emits the accumulated CRC, in wire
264be3cbf60SConrad Meyer * format, as specified by the crc_location bit above.
265be3cbf60SConrad Meyer *
266be3cbf60SConrad Meyer * Test mode compares the accumulated CRC against the
267be3cbf60SConrad Meyer * reference CRC, as described in crc_location above.
268be3cbf60SConrad Meyer * On failure, halts the DMA engine with a CRC error
269be3cbf60SConrad Meyer * status.
270be3cbf60SConrad Meyer */
271be3cbf60SConrad Meyer #define IOAT_OP_MOVECRC 0x41
272be3cbf60SConrad Meyer #define IOAT_OP_MOVECRC_TEST 0x42
273be3cbf60SConrad Meyer #define IOAT_OP_MOVECRC_STORE 0x43
274be3cbf60SConrad Meyer #define IOAT_OP_CRC 0x81
275be3cbf60SConrad Meyer #define IOAT_OP_CRC_TEST 0x82
276be3cbf60SConrad Meyer #define IOAT_OP_CRC_STORE 0x83
277be3cbf60SConrad Meyer uint32_t op:8;
278be3cbf60SConrad Meyer } control;
279be3cbf60SConrad Meyer } u;
280be3cbf60SConrad Meyer uint64_t src_addr;
281be3cbf60SConrad Meyer uint64_t dest_addr;
282be3cbf60SConrad Meyer uint64_t next;
283be3cbf60SConrad Meyer uint64_t next_src_addr;
284be3cbf60SConrad Meyer uint64_t next_dest_addr;
285be3cbf60SConrad Meyer uint32_t seed;
286be3cbf60SConrad Meyer uint32_t reserved;
287be3cbf60SConrad Meyer uint64_t crc_address;
288be3cbf60SConrad Meyer };
289be3cbf60SConrad Meyer
290e974f91cSConrad Meyer struct ioat_xor_hw_descriptor {
291e974f91cSConrad Meyer uint32_t size;
292e974f91cSConrad Meyer union {
293e974f91cSConrad Meyer uint32_t control_raw;
2949e3bbf26SConrad Meyer struct generic_dma_control control_generic;
295e974f91cSConrad Meyer struct {
296e974f91cSConrad Meyer uint32_t int_enable:1;
297e974f91cSConrad Meyer uint32_t src_snoop_disable:1;
298e974f91cSConrad Meyer uint32_t dest_snoop_disable:1;
299e974f91cSConrad Meyer uint32_t completion_update:1;
300e974f91cSConrad Meyer uint32_t fence:1;
301e974f91cSConrad Meyer uint32_t src_count:3;
302e974f91cSConrad Meyer uint32_t bundle:1;
303e974f91cSConrad Meyer uint32_t dest_dca:1;
304e974f91cSConrad Meyer uint32_t hint:1;
305e974f91cSConrad Meyer uint32_t reserved:13;
306e974f91cSConrad Meyer #define IOAT_OP_XOR 0x87
307e974f91cSConrad Meyer #define IOAT_OP_XOR_VAL 0x88
308e974f91cSConrad Meyer uint32_t op:8;
309e974f91cSConrad Meyer } control;
310e974f91cSConrad Meyer } u;
311e974f91cSConrad Meyer uint64_t src_addr;
312e974f91cSConrad Meyer uint64_t dest_addr;
313e974f91cSConrad Meyer uint64_t next;
314e974f91cSConrad Meyer uint64_t src_addr2;
315e974f91cSConrad Meyer uint64_t src_addr3;
316e974f91cSConrad Meyer uint64_t src_addr4;
317e974f91cSConrad Meyer uint64_t src_addr5;
318e974f91cSConrad Meyer };
319e974f91cSConrad Meyer
320e974f91cSConrad Meyer struct ioat_xor_ext_hw_descriptor {
321e974f91cSConrad Meyer uint64_t src_addr6;
322e974f91cSConrad Meyer uint64_t src_addr7;
323e974f91cSConrad Meyer uint64_t src_addr8;
324e974f91cSConrad Meyer uint64_t next;
325e974f91cSConrad Meyer uint64_t reserved[4];
326e974f91cSConrad Meyer };
327e974f91cSConrad Meyer
328e974f91cSConrad Meyer struct ioat_pq_hw_descriptor {
329e974f91cSConrad Meyer uint32_t size;
330e974f91cSConrad Meyer union {
331e974f91cSConrad Meyer uint32_t control_raw;
3329e3bbf26SConrad Meyer struct generic_dma_control control_generic;
333e974f91cSConrad Meyer struct {
334e974f91cSConrad Meyer uint32_t int_enable:1;
335e974f91cSConrad Meyer uint32_t src_snoop_disable:1;
336e974f91cSConrad Meyer uint32_t dest_snoop_disable:1;
337e974f91cSConrad Meyer uint32_t completion_update:1;
338e974f91cSConrad Meyer uint32_t fence:1;
339e974f91cSConrad Meyer uint32_t src_count:3;
340e974f91cSConrad Meyer uint32_t bundle:1;
341e974f91cSConrad Meyer uint32_t dest_dca:1;
342e974f91cSConrad Meyer uint32_t hint:1;
343e974f91cSConrad Meyer uint32_t p_disable:1;
344e974f91cSConrad Meyer uint32_t q_disable:1;
345e974f91cSConrad Meyer uint32_t reserved:11;
346e974f91cSConrad Meyer #define IOAT_OP_PQ 0x89
347e974f91cSConrad Meyer #define IOAT_OP_PQ_VAL 0x8a
348e974f91cSConrad Meyer uint32_t op:8;
349e974f91cSConrad Meyer } control;
350e974f91cSConrad Meyer } u;
351e974f91cSConrad Meyer uint64_t src_addr;
352e974f91cSConrad Meyer uint64_t p_addr;
353e974f91cSConrad Meyer uint64_t next;
354e974f91cSConrad Meyer uint64_t src_addr2;
355e974f91cSConrad Meyer uint64_t src_addr3;
356e974f91cSConrad Meyer uint8_t coef[8];
357e974f91cSConrad Meyer uint64_t q_addr;
358e974f91cSConrad Meyer };
359e974f91cSConrad Meyer
360e974f91cSConrad Meyer struct ioat_pq_ext_hw_descriptor {
361e974f91cSConrad Meyer uint64_t src_addr4;
362e974f91cSConrad Meyer uint64_t src_addr5;
363e974f91cSConrad Meyer uint64_t src_addr6;
364e974f91cSConrad Meyer uint64_t next;
365e974f91cSConrad Meyer uint64_t src_addr7;
366e974f91cSConrad Meyer uint64_t src_addr8;
367e974f91cSConrad Meyer uint64_t reserved[2];
368e974f91cSConrad Meyer };
369e974f91cSConrad Meyer
370e974f91cSConrad Meyer struct ioat_pq_update_hw_descriptor {
371e974f91cSConrad Meyer uint32_t size;
372e974f91cSConrad Meyer union {
373e974f91cSConrad Meyer uint32_t control_raw;
3749e3bbf26SConrad Meyer struct generic_dma_control control_generic;
375e974f91cSConrad Meyer struct {
376e974f91cSConrad Meyer uint32_t int_enable:1;
377e974f91cSConrad Meyer uint32_t src_snoop_disable:1;
378e974f91cSConrad Meyer uint32_t dest_snoop_disable:1;
379e974f91cSConrad Meyer uint32_t completion_update:1;
380e974f91cSConrad Meyer uint32_t fence:1;
381e974f91cSConrad Meyer uint32_t src_cnt:3;
382e974f91cSConrad Meyer uint32_t bundle:1;
383e974f91cSConrad Meyer uint32_t dest_dca:1;
384e974f91cSConrad Meyer uint32_t hint:1;
385e974f91cSConrad Meyer uint32_t p_disable:1;
386e974f91cSConrad Meyer uint32_t q_disable:1;
387e974f91cSConrad Meyer uint32_t reserved:3;
388e974f91cSConrad Meyer uint32_t coef:8;
389e974f91cSConrad Meyer #define IOAT_OP_PQ_UP 0x8b
390e974f91cSConrad Meyer uint32_t op:8;
391e974f91cSConrad Meyer } control;
392e974f91cSConrad Meyer } u;
393e974f91cSConrad Meyer uint64_t src_addr;
394e974f91cSConrad Meyer uint64_t p_addr;
395e974f91cSConrad Meyer uint64_t next;
396e974f91cSConrad Meyer uint64_t src_addr2;
397e974f91cSConrad Meyer uint64_t p_src;
398e974f91cSConrad Meyer uint64_t q_src;
399e974f91cSConrad Meyer uint64_t q_addr;
400e974f91cSConrad Meyer };
401e974f91cSConrad Meyer
402e974f91cSConrad Meyer struct ioat_raw_hw_descriptor {
403e974f91cSConrad Meyer uint64_t field[8];
404e974f91cSConrad Meyer };
405e974f91cSConrad Meyer
406e974f91cSConrad Meyer struct bus_dmadesc {
407e974f91cSConrad Meyer bus_dmaengine_callback_t callback_fn;
408e974f91cSConrad Meyer void *callback_arg;
409e974f91cSConrad Meyer };
410e974f91cSConrad Meyer
411e974f91cSConrad Meyer struct ioat_descriptor {
412e974f91cSConrad Meyer struct bus_dmadesc bus_dmadesc;
413e974f91cSConrad Meyer uint32_t id;
414b80b32a2STycho Nightingale bus_dmamap_t src_dmamap;
415b80b32a2STycho Nightingale bus_dmamap_t dst_dmamap;
416b80b32a2STycho Nightingale bus_dmamap_t src2_dmamap;
417b80b32a2STycho Nightingale bus_dmamap_t dst2_dmamap;
418e974f91cSConrad Meyer };
419e974f91cSConrad Meyer
420be3cbf60SConrad Meyer /* Unused by this driver at this time. */
421564af7a6SConrad Meyer #define IOAT_OP_MARKER 0x84
422564af7a6SConrad Meyer
423564af7a6SConrad Meyer /*
424564af7a6SConrad Meyer * Deprecated OPs -- v3 DMA generates an abort if given these. And this driver
425564af7a6SConrad Meyer * doesn't support anything older than v3.
426564af7a6SConrad Meyer */
427564af7a6SConrad Meyer #define IOAT_OP_OLD_XOR 0x85
428564af7a6SConrad Meyer #define IOAT_OP_OLD_XOR_VAL 0x86
429564af7a6SConrad Meyer
430e974f91cSConrad Meyer /* One of these per allocated PCI device. */
431e974f91cSConrad Meyer struct ioat_softc {
432e974f91cSConrad Meyer bus_dmaengine_t dmaengine;
433e974f91cSConrad Meyer #define to_ioat_softc(_dmaeng) \
434e974f91cSConrad Meyer ({ \
435e974f91cSConrad Meyer bus_dmaengine_t *_p = (_dmaeng); \
436e974f91cSConrad Meyer (struct ioat_softc *)((char *)_p - \
437e974f91cSConrad Meyer offsetof(struct ioat_softc, dmaengine)); \
438e974f91cSConrad Meyer })
439e974f91cSConrad Meyer
4402f03a95fSAlexander Motin device_t device;
441*657dc81dSAlexander Motin int domain;
442*657dc81dSAlexander Motin int cpu;
443e974f91cSConrad Meyer int version;
444df1928aaSConrad Meyer unsigned chan_idx;
445e974f91cSConrad Meyer
446e974f91cSConrad Meyer bus_space_tag_t pci_bus_tag;
447e974f91cSConrad Meyer bus_space_handle_t pci_bus_handle;
448e974f91cSConrad Meyer struct resource *pci_resource;
4492f03a95fSAlexander Motin int pci_resource_id;
450e974f91cSConrad Meyer uint32_t max_xfer_size;
4511693d27bSConrad Meyer uint32_t capabilities;
4522f03a95fSAlexander Motin uint32_t ring_size_order;
4535ca9fc2aSConrad Meyer uint16_t intrdelay_max;
4545ca9fc2aSConrad Meyer uint16_t cached_intrdelay;
455e974f91cSConrad Meyer
456e974f91cSConrad Meyer int rid;
4572f03a95fSAlexander Motin struct resource *res;
458e974f91cSConrad Meyer void *tag;
459e974f91cSConrad Meyer
460e974f91cSConrad Meyer bus_dma_tag_t hw_desc_tag;
461e974f91cSConrad Meyer bus_dmamap_t hw_desc_map;
462e974f91cSConrad Meyer
463b80b32a2STycho Nightingale bus_dma_tag_t data_tag;
464b80b32a2STycho Nightingale
465e974f91cSConrad Meyer bus_dma_tag_t comp_update_tag;
466e974f91cSConrad Meyer bus_dmamap_t comp_update_map;
467e974f91cSConrad Meyer uint64_t *comp_update;
468e974f91cSConrad Meyer bus_addr_t comp_update_bus_addr;
469e974f91cSConrad Meyer
4705f77bd3eSConrad Meyer boolean_t quiescing;
4710ff814e8SConrad Meyer boolean_t destroying;
47225ad9585SConrad Meyer boolean_t is_submitter_processing;
4735ca9fc2aSConrad Meyer boolean_t intrdelay_supported;
474fe8712f8SConrad Meyer boolean_t resetting; /* submit_lock */
475fe8712f8SConrad Meyer boolean_t resetting_cleanup; /* cleanup_lock */
476e974f91cSConrad Meyer
4778e269d99SConrad Meyer struct ioat_descriptor *ring;
4788e269d99SConrad Meyer
4798e269d99SConrad Meyer union ioat_hw_descriptor {
4808e269d99SConrad Meyer struct ioat_generic_hw_descriptor generic;
4818e269d99SConrad Meyer struct ioat_dma_hw_descriptor dma;
4828e269d99SConrad Meyer struct ioat_fill_hw_descriptor fill;
4838e269d99SConrad Meyer struct ioat_crc32_hw_descriptor crc32;
4848e269d99SConrad Meyer struct ioat_xor_hw_descriptor xor;
4858e269d99SConrad Meyer struct ioat_xor_ext_hw_descriptor xor_ext;
4868e269d99SConrad Meyer struct ioat_pq_hw_descriptor pq;
4878e269d99SConrad Meyer struct ioat_pq_ext_hw_descriptor pq_ext;
4888e269d99SConrad Meyer struct ioat_raw_hw_descriptor raw;
4898e269d99SConrad Meyer } *hw_desc_ring;
4908e269d99SConrad Meyer bus_addr_t hw_desc_bus_addr;
4918e269d99SConrad Meyer #define RING_PHYS_ADDR(sc, i) (sc)->hw_desc_bus_addr + \
4928e269d99SConrad Meyer (((i) % (1 << (sc)->ring_size_order)) * sizeof(struct ioat_dma_hw_descriptor))
493e974f91cSConrad Meyer
4942f03a95fSAlexander Motin struct mtx_padalign submit_lock;
4952f03a95fSAlexander Motin struct callout poll_timer;
4962f03a95fSAlexander Motin struct task reset_task;
4972f03a95fSAlexander Motin struct mtx_padalign cleanup_lock;
4982f03a95fSAlexander Motin
4992f03a95fSAlexander Motin uint32_t refcnt;
5002f03a95fSAlexander Motin uint32_t head;
5012f03a95fSAlexander Motin uint32_t acq_head;
5022f03a95fSAlexander Motin uint32_t tail;
5032f03a95fSAlexander Motin bus_addr_t last_seen;
50401fbbc88SConrad Meyer
50501fbbc88SConrad Meyer struct {
50601fbbc88SConrad Meyer uint64_t interrupts;
50701fbbc88SConrad Meyer uint64_t descriptors_processed;
50801fbbc88SConrad Meyer uint64_t descriptors_error;
50901fbbc88SConrad Meyer uint64_t descriptors_submitted;
51001fbbc88SConrad Meyer
51101fbbc88SConrad Meyer uint32_t channel_halts;
51201fbbc88SConrad Meyer uint32_t last_halt_chanerr;
51301fbbc88SConrad Meyer } stats;
514e974f91cSConrad Meyer };
515e974f91cSConrad Meyer
5167afbb263SConrad Meyer void ioat_test_attach(void);
5177afbb263SConrad Meyer void ioat_test_detach(void);
5187afbb263SConrad Meyer
5190d0f2640SConrad Meyer /*
5200d0f2640SConrad Meyer * XXX DO NOT USE this routine for obtaining the current completed descriptor.
5210d0f2640SConrad Meyer *
5220d0f2640SConrad Meyer * The double_4 read on ioat<3.3 appears to result in torn reads. And v3.2
5230d0f2640SConrad Meyer * hardware is still commonplace (Broadwell Xeon has it). Instead, use the
5240d0f2640SConrad Meyer * device-pushed *comp_update.
5250d0f2640SConrad Meyer *
5260d0f2640SConrad Meyer * It is safe to use ioat_get_chansts() for the low status bits.
5270d0f2640SConrad Meyer */
528e974f91cSConrad Meyer static inline uint64_t
ioat_get_chansts(struct ioat_softc * ioat)529e974f91cSConrad Meyer ioat_get_chansts(struct ioat_softc *ioat)
530e974f91cSConrad Meyer {
531e974f91cSConrad Meyer uint64_t status;
532e974f91cSConrad Meyer
533e974f91cSConrad Meyer if (ioat->version >= IOAT_VER_3_3)
534e974f91cSConrad Meyer status = ioat_read_8(ioat, IOAT_CHANSTS_OFFSET);
535e974f91cSConrad Meyer else
536e974f91cSConrad Meyer /* Must read lower 4 bytes before upper 4 bytes. */
537e974f91cSConrad Meyer status = ioat_read_double_4(ioat, IOAT_CHANSTS_OFFSET);
538e974f91cSConrad Meyer return (status);
539e974f91cSConrad Meyer }
540e974f91cSConrad Meyer
541e974f91cSConrad Meyer static inline void
ioat_write_chancmp(struct ioat_softc * ioat,uint64_t addr)542e974f91cSConrad Meyer ioat_write_chancmp(struct ioat_softc *ioat, uint64_t addr)
543e974f91cSConrad Meyer {
544e974f91cSConrad Meyer
545e974f91cSConrad Meyer if (ioat->version >= IOAT_VER_3_3)
546e974f91cSConrad Meyer ioat_write_8(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
547e974f91cSConrad Meyer else
548e974f91cSConrad Meyer ioat_write_double_4(ioat, IOAT_CHANCMP_OFFSET_LOW, addr);
549e974f91cSConrad Meyer }
550e974f91cSConrad Meyer
551e974f91cSConrad Meyer static inline void
ioat_write_chainaddr(struct ioat_softc * ioat,uint64_t addr)552e974f91cSConrad Meyer ioat_write_chainaddr(struct ioat_softc *ioat, uint64_t addr)
553e974f91cSConrad Meyer {
554e974f91cSConrad Meyer
555e974f91cSConrad Meyer if (ioat->version >= IOAT_VER_3_3)
556e974f91cSConrad Meyer ioat_write_8(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
557e974f91cSConrad Meyer else
558e974f91cSConrad Meyer ioat_write_double_4(ioat, IOAT_CHAINADDR_OFFSET_LOW, addr);
559e974f91cSConrad Meyer }
560e974f91cSConrad Meyer
561e974f91cSConrad Meyer static inline boolean_t
is_ioat_active(uint64_t status)562e974f91cSConrad Meyer is_ioat_active(uint64_t status)
563e974f91cSConrad Meyer {
564e974f91cSConrad Meyer return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_ACTIVE);
565e974f91cSConrad Meyer }
566e974f91cSConrad Meyer
567e974f91cSConrad Meyer static inline boolean_t
is_ioat_idle(uint64_t status)568e974f91cSConrad Meyer is_ioat_idle(uint64_t status)
569e974f91cSConrad Meyer {
570e974f91cSConrad Meyer return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_IDLE);
571e974f91cSConrad Meyer }
572e974f91cSConrad Meyer
573e974f91cSConrad Meyer static inline boolean_t
is_ioat_halted(uint64_t status)574e974f91cSConrad Meyer is_ioat_halted(uint64_t status)
575e974f91cSConrad Meyer {
576e974f91cSConrad Meyer return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_HALTED);
577e974f91cSConrad Meyer }
578e974f91cSConrad Meyer
579e974f91cSConrad Meyer static inline boolean_t
is_ioat_suspended(uint64_t status)580e974f91cSConrad Meyer is_ioat_suspended(uint64_t status)
581e974f91cSConrad Meyer {
582e974f91cSConrad Meyer return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_SUSPENDED);
583e974f91cSConrad Meyer }
584e974f91cSConrad Meyer
585e974f91cSConrad Meyer static inline void
ioat_suspend(struct ioat_softc * ioat)586e974f91cSConrad Meyer ioat_suspend(struct ioat_softc *ioat)
587e974f91cSConrad Meyer {
588e974f91cSConrad Meyer ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_SUSPEND);
589e974f91cSConrad Meyer }
590e974f91cSConrad Meyer
591e974f91cSConrad Meyer static inline void
ioat_reset(struct ioat_softc * ioat)592e974f91cSConrad Meyer ioat_reset(struct ioat_softc *ioat)
593e974f91cSConrad Meyer {
594e974f91cSConrad Meyer ioat_write_1(ioat, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
595e974f91cSConrad Meyer }
596e974f91cSConrad Meyer
597e974f91cSConrad Meyer static inline boolean_t
ioat_reset_pending(struct ioat_softc * ioat)598e974f91cSConrad Meyer ioat_reset_pending(struct ioat_softc *ioat)
599e974f91cSConrad Meyer {
600e974f91cSConrad Meyer uint8_t cmd;
601e974f91cSConrad Meyer
602e974f91cSConrad Meyer cmd = ioat_read_1(ioat, IOAT_CHANCMD_OFFSET);
603e974f91cSConrad Meyer return ((cmd & IOAT_CHANCMD_RESET) != 0);
604e974f91cSConrad Meyer }
605e974f91cSConrad Meyer
606e974f91cSConrad Meyer #endif /* __IOAT_INTERNAL_H__ */
607