1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_PX_DMA_H
#define _SYS_PX_DMA_H
#ifdef __cplusplus
extern "C" {
#endif
typedef pfn_t px_iopfn_t;
#define MAKE_DMA_COOKIE(cp, address, size) \
{ \
(cp)->dmac_notused = 0; \
(cp)->dmac_type = 0; \
(cp)->dmac_laddress = (address); \
(cp)->dmac_size = (size); \
}
#define PX_HAS_REDZONE(mp) \
(((mp)->dmai_flags & PX_DMAI_FLAGS_REDZONE) ? 1 : 0)
#define PX_MAP_BUFZONE(mp) \
(((mp)->dmai_flags & PX_DMAI_FLAGS_MAP_BUFZONE) ? 1 :0)
typedef struct px_dma_hdl {
ddi_dma_impl_t pdh_ddi_hdl;
ddi_dma_attr_t pdh_attr_dev;
} px_dma_hdl_t;
struct px_dma_impl { /* forthdebug only, keep in sync with ddi_dma_impl_t */
ulong_t dmai_mapping;
uint_t dmai_size;
off_t dmai_offset;
uint_t dmai_minxfer;
uint_t dmai_burstsizes;
uint_t dmai_ndvmapages;
uint_t dmai_roffset;
uint_t dmai_rflags;
uint_t dmai_flags;
uint_t dmai_nwin;
uint_t dmai_winsize;
caddr_t dmai_tte;
void *dmai_pfnlst;
uint_t *dmai_pfn0;
void *dmai_winlst;
dev_info_t *dmai_rdip;
ddi_dma_obj_t dmai_object;
ddi_dma_attr_t dmai_attr_aug;
ddi_dma_cookie_t *dmai_cookie;
int (*dmai_fault_check)(struct ddi_dma_impl *handle);
void (*dmai_fault_notify)(struct ddi_dma_impl *handle);
int dmai_fault;
ddi_dma_attr_t dmai_attr_dev;
};
/* Included in case other px-specific flags are added later. */
#define PX_DMA_SYNC_DDI_FLAGS ((1 << 16) - 1) /* Look for only DDI flags */
/*
* flags for overloading dmai_inuse field of the dma request
* structure:
*/
#define dmai_flags dmai_inuse
#define dmai_tte dmai_nexus_private
#define dmai_fdvma dmai_nexus_private
#define dmai_pfnlst dmai_iopte
#define dmai_winlst dmai_minfo
#define dmai_pfn0 dmai_sbi
#define dmai_roffset dmai_pool
#define dmai_bdf dmai_minxfer
#define PX_MP_PFN0(mp) ((px_iopfn_t)(mp)->dmai_pfn0)
#define PX_WINLST(mp) ((px_dma_win_t *)(mp)->dmai_winlst)
#define PX_DEV_ATTR(mp) ((ddi_dma_attr_t *)(mp + 1))
#define SET_DMAATTR(p, lo, hi, nocross, cntmax) \
(p)->dma_attr_addr_lo = (lo); \
(p)->dma_attr_addr_hi = (hi); \
(p)->dma_attr_seg = (nocross); \
(p)->dma_attr_count_max = (cntmax);
#define SET_DMAALIGN(p, align) \
(p)->dma_attr_align = (align);
#define PX_DMAI_FLAGS_INUSE 0x1
#define PX_DMAI_FLAGS_BYPASSREQ 0x2
#define PX_DMAI_FLAGS_PEER_ONLY 0x4
#define PX_DMAI_FLAGS_NOCTX 0x8
#define PX_DMAI_FLAGS_DVMA 0x10
#define PX_DMAI_FLAGS_BYPASS 0x20
#define PX_DMAI_FLAGS_PTP 0x40
#define PX_DMAI_FLAGS_DMA (PX_DMAI_FLAGS_BYPASS | PX_DMAI_FLAGS_PTP)
#define PX_DMAI_FLAGS_DMA_TYPE (PX_DMAI_FLAGS_DMA | PX_DMAI_FLAGS_DVMA)
#define PX_DMAI_FLAGS_CONTEXT 0x100
#define PX_DMAI_FLAGS_FASTTRACK 0x200
#define PX_DMAI_FLAGS_VMEMCACHE 0x400
#define PX_DMAI_FLAGS_PGPFN 0x800
#define PX_DMAI_FLAGS_NOSYSLIMIT 0x1000
#define PX_DMAI_FLAGS_NOFASTLIMIT 0x2000
#define PX_DMAI_FLAGS_NOSYNC 0x4000
#define PX_DMAI_FLAGS_PTP32 0x10000
#define PX_DMAI_FLAGS_PTP64 0x20000
/*
* #define PX_DMAI_FLAGS_MAP_BUFZONE 0x40000
* See pcie_impl.h
*/
#define PX_DMAI_FLAGS_REDZONE 0x80000
#define PX_DMAI_FLAGS_PRESERVE (PX_DMAI_FLAGS_PEER_ONLY | \
PX_DMAI_FLAGS_BYPASSREQ | PX_DMAI_FLAGS_NOSYSLIMIT | \
PX_DMAI_FLAGS_NOFASTLIMIT | PX_DMAI_FLAGS_NOCTX | \
PX_DMAI_FLAGS_MAP_BUFZONE | PX_DMAI_FLAGS_REDZONE)
#define PX_HAS_NOFASTLIMIT(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_NOFASTLIMIT)
#define PX_HAS_NOSYSLIMIT(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_NOSYSLIMIT)
#define PX_DMA_ISPEERONLY(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_PEER_ONLY)
#define PX_DMA_ISPGPFN(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_PGPFN)
#define PX_DMA_TYPE(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_DMA_TYPE)
#define PX_DMA_ISDVMA(mp) (PX_DMA_TYPE(mp) == PX_DMAI_FLAGS_DVMA)
#define PX_DMA_ISBYPASS(mp) (PX_DMA_TYPE(mp) == PX_DMAI_FLAGS_BYPASS)
#define PX_DMA_ISPTP(mp) (PX_DMA_TYPE(mp) == PX_DMAI_FLAGS_PTP)
#define PX_DMA_ISPTP32(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_PTP32)
#define PX_DMA_ISPTP64(mp) ((mp)->dmai_flags & PX_DMAI_FLAGS_PTP64)
#define PX_DMA_CANFAST(mp) (((mp)->dmai_ndvmapages + PX_HAS_REDZONE(mp) \
<= px_dvma_page_cache_clustsz) && PX_HAS_NOFASTLIMIT(mp))
#define PX_DMA_WINNPGS(mp) MMU_BTOP((mp)->dmai_winsize)
#define PX_DMA_CANCACHE(mp) (!PX_HAS_REDZONE(mp) && \
(PX_DMA_WINNPGS(mp) == 1) && PX_HAS_NOSYSLIMIT(mp))
#define PX_DEV_NOFASTLIMIT(lo, hi, fastlo, fasthi, align_pg) \
(((lo) <= (fastlo)) && ((hi) >= (fasthi)) && \
((align_pg) <= px_dvma_page_cache_clustsz))
#define PX_DEV_NOSYSLIMIT(lo, hi, syslo, syshi, align_pg) \
(((lo) <= (syslo)) && ((hi) >= (syshi)) && (align_pg == 1))
#define PX_DMA_NOCTX(rdip) (!px_use_contexts || (px_ctx_no_active_flush && \
ddi_prop_exists(DDI_DEV_T_ANY, rdip, \
DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "active-dma-flush")))
#define PX_DMA_USECTX(mp) (!(mp->dmai_flags & DMAI_FLAGS_NOCTX))
#define PX_DMA_BADPTP(pfn, attrp) \
((IOMMU_PTOB(pfn) < attrp->dma_attr_addr_lo) || \
(IOMMU_PTOB(pfn) > attrp->dma_attr_addr_hi))
#define PX_DMA_CURWIN(mp) \
(((mp)->dmai_offset + (mp)->dmai_roffset) / (mp)->dmai_winsize)
#ifdef PX_DMA_PROF
/* collect fast track failure statistics */
#define PX_DVMA_FASTTRAK_PROF(mp) { \
if ((mp->dmai_ndvmapages + PX_HAS_REDZONE(mp)) > px_dvma_page_cache_clustsz) \
px_dvmaft_npages++; \
else if (!PX_HAS_NOFASTLIMIT(mp)) \
px_dvmaft_limit++; \
}
#else /* !PX_DMA_PROF */
#define PX_DVMA_FASTTRAK_PROF(mp)
#endif /* PX_DMA_PROF */
typedef struct px_dma_win {
struct px_dma_win *win_next;
uint32_t win_ncookies;
uint32_t win_curseg;
uint64_t win_size;
uint64_t win_offset;
/* cookie table: sizeof (ddi_dma_cookie_t) * win_ncookies */
} px_dma_win_t;
/* dvma debug records */
struct px_dvma_rec {
char *dvma_addr;
uint_t len;
ddi_dma_impl_t *mp;
struct px_dvma_rec *next;
};
extern int px_dma_attach(px_t *px_p);
extern int px_dma_win(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_handle_t handle, uint_t win, off_t *offp,
size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp);
extern ddi_dma_impl_t *px_dma_allocmp(dev_info_t *dip, dev_info_t *rdip,
int (*waitfp)(caddr_t), caddr_t arg);
extern void px_dma_freemp(ddi_dma_impl_t *mp);
extern void px_dma_freepfn(ddi_dma_impl_t *mp);
extern ddi_dma_impl_t *px_dma_lmts2hdl(dev_info_t *dip, dev_info_t *rdip,
px_mmu_t *mmu_p, ddi_dma_req_t *dmareq);
extern int px_dma_attr2hdl(px_t *px_p, ddi_dma_impl_t *mp);
extern int px_dma_type(px_t *px_p, ddi_dma_req_t *req, ddi_dma_impl_t *mp);
extern int px_dma_pfn(px_t *px_p, ddi_dma_req_t *req, ddi_dma_impl_t *mp);
extern int px_dvma_win(px_t *px_p, ddi_dma_req_t *r, ddi_dma_impl_t *mp);
extern void px_dma_freewin(ddi_dma_impl_t *mp);
extern int px_dvma_map_fast(px_mmu_t *mmu_p, ddi_dma_impl_t *mp);
extern int px_dvma_map(ddi_dma_impl_t *mp, ddi_dma_req_t *dmareq,
px_mmu_t *mmu_p);
extern void px_dvma_unmap(px_mmu_t *mmu_p, ddi_dma_impl_t *mp);
extern int px_dma_physwin(px_t *px_p, ddi_dma_req_t *dmareq,
ddi_dma_impl_t *mp);
extern int px_dvma_ctl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_impl_t *mp, enum ddi_dma_ctlops cmd, off_t *offp,
size_t *lenp, caddr_t *objp, uint_t cache_flags);
extern int px_dma_ctl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_impl_t *mp, enum ddi_dma_ctlops cmd, off_t *offp,
size_t *lenp, caddr_t *objp, uint_t cache_flags);
#define PX_GET_MP_NCOOKIES(mp) ((mp)->dmai_ncookies)
#define PX_SET_MP_NCOOKIES(mp, nc) ((mp)->dmai_ncookies = (nc))
#define PX_GET_MP_PFN1_ADDR(mp) (((px_iopfn_t *)(mp)->dmai_pfnlst) + 1)
#define PX_GET_MP_TTE(tte) \
(((uint64_t)(uintptr_t)(tte) >> 5) << (32 + 5) | \
((uint32_t)(uintptr_t)(tte)) & (PCI_MAP_ATTR_READ | \
PCI_MAP_ATTR_WRITE | PCI_MAP_ATTR_RO | \
PCI_MAP_ATTR_PHFUN_MASK))
#define PX_SAVE_MP_TTE(mp, tte) \
(mp)->dmai_tte = (caddr_t)((uintptr_t)HI32(tte) | ((tte) & \
(PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE | \
PCI_MAP_ATTR_RO | PCI_MAP_ATTR_PHFUN_MASK)))
#define PX_GET_MP_PFN1(mp, page_no) \
(((px_iopfn_t *)(mp)->dmai_pfnlst)[page_no])
#define PX_GET_MP_PFN(mp, page_no) ((mp)->dmai_ndvmapages == 1 ? \
(px_iopfn_t)(mp)->dmai_pfnlst : PX_GET_MP_PFN1(mp, page_no))
#define PX_SET_MP_PFN(mp, page_no, pfn) { \
if ((mp)->dmai_ndvmapages == 1) { \
ASSERT(!((page_no) || (mp)->dmai_pfnlst)); \
(mp)->dmai_pfnlst = (void *)(pfn); \
} else \
((px_iopfn_t *)(mp)->dmai_pfnlst)[page_no] = \
(px_iopfn_t)(pfn); \
}
#define PX_SET_MP_PFN1(mp, page_no, pfn) { \
((px_iopfn_t *)(mp)->dmai_pfnlst)[page_no] = (pfn); \
}
extern int px_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_handle_t handle);
#if defined(DEBUG)
extern void px_dump_dma_handle(uint64_t flag, dev_info_t *dip,
ddi_dma_impl_t *hp);
#else
#define px_dump_dma_handle(flag, dip, hp)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _SYS_PX_DMA_H */
|