1 /* $NetBSD: pci_machdep.h,v 1.15 2018/04/19 21:50:07 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2002,2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Klaus Klein and Tim Rightnour
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _PCI_MACHDEP_H_
33 #define _PCI_MACHDEP_H_
34
35 #include <prop/proplib.h>
36
37 /*
38 * Machine-specific definitions for PCI autoconfiguration.
39 */
40
41 #define __HAVE_PCI_CONF_HOOK
42 #define __HAVE_PCI_MSI_MSIX
43
44 /*
45 * Types provided to machine-independent PCI code
46 */
47 typedef struct genppc_pci_chipset *pci_chipset_tag_t;
48 typedef int pcitag_t;
49 typedef int pci_intr_handle_t;
50
51 /*
52 * Forward declarations.
53 */
54 struct pci_attach_args;
55 struct pcibus_attach_args;
56
57 static __inline pci_chipset_tag_t pcibus_attach_args_pc(
58 struct pcibus_attach_args *);
59 static __inline pci_chipset_tag_t pci_attach_args_pc(
60 const struct pci_attach_args *);
61
62 #include <dev/pci/pcireg.h>
63
64 #ifdef _KERNEL
65 extern struct powerpc_bus_dma_tag pci_bus_dma_tag;
66
67 typedef enum {
68 PCI_INTR_TYPE_INTX = 0,
69 PCI_INTR_TYPE_MSI,
70 PCI_INTR_TYPE_MSIX,
71 PCI_INTR_TYPE_SIZE,
72 } pci_intr_type_t;
73 #endif
74
75
76 #if defined(_KERNEL) && (defined(_MODULE) || defined(__PCI_NOINLINE))
77 void pci_attach_hook(device_t, device_t,
78 struct pcibus_attach_args *);
79
80 int pci_bus_maxdevs(pci_chipset_tag_t, int);
81 pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int);
82 pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
83 void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
84 void pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
85 int *, int *, int *);
86
87 const char * pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t,
88 char *, size_t);
89 const struct evcnt *
90 pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t);
91 void * pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
92 int, int (*)(void *), void *);
93 void * pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t,
94 int, int (*)(void *), void *, const char *);
95 void pci_intr_disestablish(pci_chipset_tag_t, void *);
96 int pci_intr_map(const struct pci_attach_args *,
97 pci_intr_handle_t *ihp);
98 int pci_intr_setattr(pci_chipset_tag_t, pci_intr_handle_t *,
99 int, uint64_t);
100
101 pci_intr_type_t pci_intr_type(pci_chipset_tag_t, pci_intr_handle_t);
102 int pci_intr_alloc(const struct pci_attach_args *,
103 pci_intr_handle_t **, int *, pci_intr_type_t);
104 void pci_intr_release(pci_chipset_tag_t, pci_intr_handle_t *, int);
105 int pci_intx_alloc(const struct pci_attach_args *,
106 pci_intr_handle_t **);
107
108 /* experimental MSI support */
109 int pci_msi_alloc(const struct pci_attach_args *,
110 pci_intr_handle_t **, int *);
111 int pci_msi_alloc_exact(const struct pci_attach_args *,
112 pci_intr_handle_t **, int);
113
114 /* experimental MSI-X support */
115 int pci_msix_alloc(const struct pci_attach_args *,
116 pci_intr_handle_t **, int *);
117 int pci_msix_alloc_exact(const struct pci_attach_args *,
118 pci_intr_handle_t **, int);
119 int pci_msix_alloc_map(const struct pci_attach_args *,
120 pci_intr_handle_t **, u_int *, int);
121
122 void pci_conf_interrupt(pci_chipset_tag_t, int, int, int,
123 int, int *);
124 int pci_conf_hook(pci_chipset_tag_t, int, int, int, pcireg_t);
125 #endif /* _KERNEL && (_MODULE || __PCI_NOINLINE) */
126
127 /* Per bus information structure */
128 struct genppc_pci_chipset_businfo {
129 SIMPLEQ_ENTRY(genppc_pci_chipset_businfo) next;
130 prop_dictionary_t pbi_properties; /* chipset properties */
131 };
132
133 #if !defined(_MODULE)
134 /*
135 * Generic PPC PCI structure and type definitions.
136 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
137 */
138 struct genppc_pci_chipset {
139 void *pc_conf_v;
140 void (*pc_attach_hook)(device_t, device_t,
141 struct pcibus_attach_args *);
142 int (*pc_bus_maxdevs)(void *, int);
143 pcitag_t (*pc_make_tag)(void *, int, int, int);
144 pcireg_t (*pc_conf_read)(void *, pcitag_t, int);
145 void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t);
146
147 void *pc_intr_v;
148 int (*pc_intr_map)(const struct pci_attach_args *,
149 pci_intr_handle_t *);
150 const char *(*pc_intr_string)(void *, pci_intr_handle_t, char *,
151 size_t);
152 const struct evcnt *(*pc_intr_evcnt)(void *, pci_intr_handle_t);
153 void *(*pc_intr_establish)(void *, pci_intr_handle_t,
154 int, int (*)(void *), void *, const char *);
155 void (*pc_intr_disestablish)(void *, void *);
156 int (*pc_intr_setattr)(void *, pci_intr_handle_t *,
157 int, uint64_t);
158
159 pci_intr_type_t (*pc_intr_type)(void *, pci_intr_handle_t);
160 int (*pc_intr_alloc)(const struct pci_attach_args *,
161 pci_intr_handle_t **, int *, pci_intr_type_t);
162 void (*pc_intr_release)(void *, pci_intr_handle_t *, int);
163 int (*pc_intx_alloc)(const struct pci_attach_args *,
164 pci_intr_handle_t **);
165
166 /* experimental MSI support */
167 void *pc_msi_v;
168 int (*pc_msi_alloc)(const struct pci_attach_args *,
169 pci_intr_handle_t **, int *, bool);
170
171 /* experimental MSI-X support */
172 void *pc_msix_v;
173 int (*pc_msix_alloc)(const struct pci_attach_args *,
174 pci_intr_handle_t **, u_int *, int *, bool);
175
176 void (*pc_conf_interrupt)(void *, int, int, int, int, int *);
177 void (*pc_decompose_tag)(void *, pcitag_t, int *,
178 int *, int *);
179 int (*pc_conf_hook)(void *, int, int, int, pcireg_t);
180
181 uint32_t *pc_addr;
182 uint32_t *pc_data;
183 int pc_node;
184 int pc_ihandle;
185 int pc_bus;
186 bus_space_tag_t pc_memt;
187 bus_space_tag_t pc_iot;
188
189 SIMPLEQ_HEAD(, genppc_pci_chipset_businfo) pc_pbi;
190 };
191
192 #ifdef _KERNEL
193
194 #ifdef __PCI_NOINLINE
195 #define __pci_inline
196 #else
197 #define __pci_inline static __inline
198 #endif
199
200 /*
201 * Functions provided to machine-independent PCI code.
202 */
203 __pci_inline void
pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)204 pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
205 {
206 (*pcibus_attach_args_pc(pba)->pc_attach_hook)(parent, self, pba);
207 }
208
209 __pci_inline int
pci_bus_maxdevs(pci_chipset_tag_t pc,int busno)210 pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
211 {
212 return (*pc->pc_bus_maxdevs)(pc->pc_conf_v, busno);
213 }
214
215 __pci_inline pcitag_t
pci_make_tag(pci_chipset_tag_t pc,int bus,int device,int function)216 pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
217 {
218 return (*pc->pc_make_tag)(pc->pc_conf_v, bus, device, function);
219 }
220
221 __pci_inline pcireg_t
pci_conf_read(pci_chipset_tag_t pc,pcitag_t tag,int reg)222 pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
223 {
224 return (*pc->pc_conf_read)(pc->pc_conf_v, tag, reg);
225 }
226
227 __pci_inline void
pci_conf_write(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t val)228 pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val)
229 {
230 (*pc->pc_conf_write)(pc->pc_conf_v, tag, reg, val);
231 }
232
233 __pci_inline void
pci_decompose_tag(pci_chipset_tag_t pc,pcitag_t tag,int * bp,int * dp,int * fp)234 pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
235 {
236 (*pc->pc_decompose_tag)(pc->pc_conf_v, tag, bp, dp, fp);
237 }
238
239 __pci_inline int
pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ihp)240 pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
241 {
242 return (*pci_attach_args_pc(pa)->pc_intr_map)(pa, ihp);
243 }
244
245 __pci_inline const char *
pci_intr_string(pci_chipset_tag_t pc,pci_intr_handle_t ih,char * buf,size_t len)246 pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char * buf,
247 size_t len)
248 {
249 return (*pc->pc_intr_string)(pc->pc_intr_v, ih, buf, len);
250 }
251
252 __pci_inline const struct evcnt *
pci_intr_evcnt(pci_chipset_tag_t pc,pci_intr_handle_t ih)253 pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
254 {
255 return (*pc->pc_intr_evcnt)(pc->pc_intr_v, ih);
256 }
257
258 __pci_inline void *
pci_intr_establish(pci_chipset_tag_t pc,pci_intr_handle_t ih,int ipl,int (* handler)(void *),void * arg)259 pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int ipl,
260 int (*handler)(void *), void *arg)
261 {
262 return (*pc->pc_intr_establish)(pc->pc_intr_v, ih, ipl, handler, arg,
263 NULL);
264 }
265
266 __pci_inline void *
pci_intr_establish_xname(pci_chipset_tag_t pc,pci_intr_handle_t ih,int ipl,int (* handler)(void *),void * arg,const char * xname)267 pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih, int ipl,
268 int (*handler)(void *), void *arg, const char *xname)
269 {
270 return (*pc->pc_intr_establish)(pc->pc_intr_v, ih, ipl, handler, arg,
271 xname);
272 }
273
274 __pci_inline void
pci_intr_disestablish(pci_chipset_tag_t pc,void * cookie)275 pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
276 {
277 (*pc->pc_intr_disestablish)(pc->pc_intr_v, cookie);
278 }
279
280 __pci_inline int
pci_intr_setattr(pci_chipset_tag_t pc,pci_intr_handle_t * ihp,int attr,uint64_t data)281 pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ihp, int attr,
282 uint64_t data)
283 {
284 return (*pc->pc_intr_setattr)(pc->pc_intr_v, ihp, attr, data);
285 }
286
287 __pci_inline pci_intr_type_t
pci_intr_type(pci_chipset_tag_t pc,pci_intr_handle_t ih)288 pci_intr_type(pci_chipset_tag_t pc, pci_intr_handle_t ih)
289 {
290 return (*pc->pc_intr_type)(pc->pc_intr_v, ih);
291 }
292
293 __pci_inline int
pci_intr_alloc(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,int * count,pci_intr_type_t max_type)294 pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
295 int *count, pci_intr_type_t max_type)
296 {
297 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
298 return (*pc->pc_intr_alloc)(pa, ihps, count, max_type);
299 }
300
301 __pci_inline void
pci_intr_release(pci_chipset_tag_t pc,pci_intr_handle_t * ihp,int count)302 pci_intr_release(pci_chipset_tag_t pc, pci_intr_handle_t *ihp, int count)
303 {
304 (*pc->pc_intr_release)(pc->pc_intr_v, ihp, count);
305 }
306
307 __pci_inline int
pci_intx_alloc(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps)308 pci_intx_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps)
309 {
310 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
311 return (*pc->pc_intx_alloc)(pa, ihps);
312 }
313
314
315 __pci_inline void
pci_conf_interrupt(pci_chipset_tag_t pc,int bus,int device,int pin,int swiz,int * iline)316 pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int device, int pin,
317 int swiz, int *iline)
318 {
319 (*pc->pc_conf_interrupt)(pc->pc_conf_v, bus, device, pin, swiz, iline);
320 }
321
322 __pci_inline int
pci_conf_hook(pci_chipset_tag_t pc,int bus,int device,int function,pcireg_t id)323 pci_conf_hook(pci_chipset_tag_t pc, int bus, int device, int function,
324 pcireg_t id)
325 {
326 return (*pc->pc_conf_hook)(pc->pc_conf_v, bus, device, function, id);
327 }
328
329
330 /* experimental MSI support */
331 __pci_inline int
pci_msi_alloc(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,int * count)332 pci_msi_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
333 int *count)
334 {
335 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
336 return (*pc->pc_msi_alloc)(pa, ihps, count, false);
337 }
338
339 __pci_inline int
pci_msi_alloc_exact(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,int count)340 pci_msi_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
341 int count)
342 {
343 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
344 return (*pc->pc_msi_alloc)(pa, ihps, &count, true);
345 }
346
347 /* experimental MSI-X support */
348 __pci_inline int
pci_msix_alloc(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,int * count)349 pci_msix_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
350 int *count)
351 {
352 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
353 return (*pc->pc_msix_alloc)(pa, ihps, NULL, count, false);
354 }
355
356 __pci_inline int
pci_msix_alloc_exact(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,int count)357 pci_msix_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
358 int count)
359 {
360 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
361 return (*pc->pc_msix_alloc)(pa, ihps, NULL, &count, true);
362 }
363
364 __pci_inline int
pci_msix_alloc_map(const struct pci_attach_args * pa,pci_intr_handle_t ** ihps,u_int * table_indexes,int count)365 pci_msix_alloc_map(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
366 u_int *table_indexes, int count)
367 {
368 pci_chipset_tag_t pc = pci_attach_args_pc(pa);
369 return (*pc->pc_msix_alloc)(pa, ihps, table_indexes, &count, true);
370 }
371
372 #undef __pci_inline
373
374 /*
375 * Generic PowerPC PCI functions. Override if necc.
376 */
377
378 int genppc_pci_bus_maxdevs(void *, int);
379
380 int genppc_pci_intr_map(const struct pci_attach_args *,
381 pci_intr_handle_t *);
382 const char *genppc_pci_intr_string(void *, pci_intr_handle_t, char *, size_t);
383 const struct evcnt *genppc_pci_intr_evcnt(void *, pci_intr_handle_t);
384 void *genppc_pci_intr_establish(void *, pci_intr_handle_t, int, int (*)(void *),
385 void *, const char *);
386 void genppc_pci_intr_disestablish(void *, void *);
387 int genppc_pci_intr_setattr(void *, pci_intr_handle_t *, int, uint64_t);
388 pci_intr_type_t genppc_pci_intr_type(void *, pci_intr_handle_t);
389 int genppc_pci_intr_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
390 int *, pci_intr_type_t);
391 void genppc_pci_intr_release(void *, pci_intr_handle_t *, int);
392 int genppc_pci_intx_alloc(const struct pci_attach_args *, pci_intr_handle_t **);
393
394 /* experimental MSI support */
395 int genppc_pci_msi_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
396 int *, bool);
397
398 /* experimental MSI-X support */
399 int genppc_pci_msix_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
400 u_int *, int *, bool);
401
402 void genppc_pci_chipset_msi_init(pci_chipset_tag_t pc);
403 void genppc_pci_chipset_msix_init(pci_chipset_tag_t pc);
404
405 #define GENPPC_PCI_MSI_INITIALIZER \
406 .pc_msi_alloc = genppc_pci_msi_alloc
407
408 #define GENPPC_PCI_MSIX_INITIALIZER \
409 .pc_msix_alloc = genppc_pci_msix_alloc
410
411 void genppc_pci_conf_interrupt(void *, int, int, int, int, int *);
412 int genppc_pci_conf_hook(void *, int, int, int, pcireg_t);
413
414 /* generic indirect PCI functions */
415 void genppc_pci_indirect_attach_hook(device_t, device_t,
416 struct pcibus_attach_args *);
417 pcitag_t genppc_pci_indirect_make_tag(void *, int, int, int);
418 pcireg_t genppc_pci_indirect_conf_read(void *, pcitag_t, int);
419 void genppc_pci_indirect_conf_write(void *, pcitag_t, int, pcireg_t);
420 void genppc_pci_indirect_decompose_tag(void *, pcitag_t, int *, int *, int *);
421
422 /* generic OFW method PCI functions */
423 void genppc_pci_ofmethod_attach_hook(device_t, device_t,
424 struct pcibus_attach_args *);
425 pcitag_t genppc_pci_ofmethod_make_tag(void *, int, int, int);
426 pcireg_t genppc_pci_ofmethod_conf_read(void *, pcitag_t, int);
427 void genppc_pci_ofmethod_conf_write(void *, pcitag_t, int, pcireg_t);
428 void genppc_pci_ofmethod_decompose_tag(void *, pcitag_t, int *, int *, int *);
429
430 /* Generic OFW PCI functions */
431
432 int genofw_find_picnode(int);
433 void genofw_find_ofpics(int);
434 void genofw_fixup_picnode_offsets(void);
435 void genofw_setup_pciintr_map(void *, struct genppc_pci_chipset_businfo *, int);
436 int genofw_find_node_by_devfunc(int, int, int, int);
437 int genofw_pci_intr_map(const struct pci_attach_args *, pci_intr_handle_t *);
438 int genofw_pci_conf_hook(void *, int, int, int, pcireg_t);
439
440 /* OFW PCI structures and defines */
441 #define PICNODE_TYPE_OPENPIC 1
442 #define PICNODE_TYPE_8259 2
443 #define PICNODE_TYPE_HEATHROW 3
444 #define PICNODE_TYPE_OHARE 4
445 #define PICNODE_TYPE_IVR 5
446
447 typedef struct _ofw_pic_node_t {
448 int node;
449 int parent;
450 int16_t cells;
451 int16_t intrs;
452 int16_t offset;
453 int16_t type;
454 } ofw_pic_node_t;
455
456 #endif /* _KERNEL */
457
458 #endif /* !_MODULE */
459
460 #endif /* _PCI_MACHDEP_H_ */
461