1/*
2 * Copyright 2022, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _OBSD_COMPAT_DEV_PCI_PCIVAR_H_
6#define _OBSD_COMPAT_DEV_PCI_PCIVAR_H_
7
8
9#include_next <dev/pci/pcivar.h>
10#include <dev/pci/pcireg.h>
11
12#include <sys/rman.h>
13
14
15typedef u_int32_t pcireg_t;
16
17
18struct pci_matchid {
19	pci_vendor_id_t		pm_vid;
20	pci_product_id_t	pm_pid;
21};
22
23typedef struct {
24	int rid;
25} pci_intr_handle_t;
26
27
28#define pci_conf_read(pct, pcitag, reg) \
29	pci_read_config(SC_DEV_FOR_PCI, reg, sizeof(pcireg_t))
30#define pci_conf_write(pct, pcitag, reg, val) \
31	pci_write_config(SC_DEV_FOR_PCI, reg, val, sizeof(pcireg_t))
32#define pci_get_capability(pct, pcitag, capability, offset, value) \
33	pci_get_capability_openbsd(SC_DEV_FOR_PCI, capability, offset, value)
34#define pci_mapreg_type(pct, pcitag, reg) \
35	pci_mapreg_type_openbsd(SC_DEV_FOR_PCI, reg)
36#define pci_mapreg_map(pa, reg, type, flags, tagp, handlep, basep, sizep, maxsize) \
37	pci_mapreg_map_openbsd(SC_DEV_FOR_PCI, reg, type, flags, tagp, handlep, basep, sizep, maxsize)
38#define pci_intr_establish(pa, ih, level, func, arg, what) \
39	pci_intr_establish_openbsd(SC_DEV_FOR_PCI, ih, level, func, arg, what)
40
41#define pci_intr_string(...) NULL
42
43static int
44pci_get_capability_openbsd(device_t dev, int capability, int* offset, pcireg_t* value)
45{
46	int res = pci_find_cap(dev, capability, offset);
47	if (res != 0)
48		return 0;
49
50	if (value)
51		*value = pci_read_config(dev, *offset, sizeof(pcireg_t));
52	return 1;
53}
54
55static pcireg_t
56pci_mapreg_type_openbsd(device_t dev, int reg)
57{
58	return (_PCI_MAPREG_TYPEBITS(pci_read_config(dev, reg, sizeof(pcireg_t))));
59}
60
61static int
62pci_mapreg_map_openbsd(device_t dev, int reg, pcireg_t type, int flags,
63	bus_space_tag_t* tagp, bus_space_handle_t* handlep, bus_addr_t* basep,
64	bus_size_t* sizep, bus_size_t maxsize)
65{
66	struct resource* res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &reg, RF_ACTIVE);
67	if (res == NULL)
68		return -1;
69
70	*tagp = rman_get_bustag(res);
71	*handlep = rman_get_bushandle(res);
72	if (basep != NULL)
73		*basep = rman_get_start(res);
74	if (sizep != NULL)
75		*sizep = rman_get_size(res);
76	return 0;
77}
78
79static int
80pci_intr_map_msix(device_t dev, int vec, pci_intr_handle_t* ihp)
81{
82	if (vec != 0)
83		return -1;
84
85	int count = 1;
86	ihp->rid = 1;
87	return pci_alloc_msix(dev, &count);
88}
89
90static int
91pci_intr_map_msi(device_t dev, pci_intr_handle_t* ihp)
92{
93	int count = 1;
94	ihp->rid = 1;
95	return pci_alloc_msi(dev, &count);
96}
97
98static int
99pci_intr_map(device_t dev, pci_intr_handle_t* ihp)
100{
101	// No need to map legacy interrupts.
102	ihp->rid = 0;
103	return 0;
104}
105
106static void*
107pci_intr_establish_openbsd(device_t dev, pci_intr_handle_t ih, int level,
108	int(*func)(void*), void* arg, const char* what)
109{
110	struct resource* irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &ih.rid,
111		RF_ACTIVE | (ih.rid != 0 ? 0 : RF_SHAREABLE));
112	if (irq == NULL)
113		return NULL;
114
115	int flags = INTR_TYPE_NET;
116	if ((level & IPL_MPSAFE) != 0)
117		flags |= INTR_MPSAFE;
118
119	void* ihp = NULL;
120	bus_setup_intr(dev, irq, flags, NULL, func, arg, &ihp);
121	return ihp;
122}
123
124
125#endif	/* _OBSD_COMPAT_DEV_PCI_PCIVAR_H_ */
126