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
|
/*
* Copyright (c) 2025 Ian Marco Moffett and L5 engineers
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PCI_PCI_H_
#define _PCI_PCI_H_ 1
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/cdefs.h>
/*
* Use for making instances of the pci_adv
* structure.
*/
#define PCI_CS_ID(CLASS, SUBCLASS) \
{ \
.class = (CLASS), \
.subclass = (SUBCLASS) \
}
#define PCI_DV_ID(DEVICE, VENDOR) \
{ \
.device = (DEVICE), \
.vendor = (VENDOR) \
}
/* PCI specific types */
typedef uint32_t pcireg_t;
typedef uint32_t pcival_t;
/*
* Represents a device attached to the PCI
* bus
*
* @bus: Bus number of device
* @slot: Slot number of device
* @func: Function number of device
* @vendor: Vendor ID
* @device: Device ID
* @bar: Base address registers
*/
struct pci_device {
uint16_t bus;
uint8_t slot;
uint8_t func;
uint8_t class;
uint8_t subclass;
uint16_t vendor;
uint16_t device;
uint32_t bar[6];
TAILQ_ENTRY(pci_device) link;
};
/*
* Structure that allows a device driver of a PCI
* bus node to advocate for its workings. In other words,
* it registers itself to be the driver of the device.
*
* @lookup: Lookup arguments
* @attach: Attach the driver
* @classrev: IF 1, identified by class/subclass
*
* XXX: The `lookup` field is used for both input arguments
* as well as output results
*/
struct pci_adv {
struct pci_device lookup;
int(*attach)(struct pci_adv *ap);
uint8_t classrev : 1;
TAILQ_ENTRY(pci_adv) link;
};
typedef enum {
PCI_LU_VENDEV, /* Vendor / device */
PCI_LU_CLASSREV, /* Class / subclass */
} lookup_type_t;
/*
* Lookup a device on the PCI(e) bus by using the pci_descriptor
* as a lookup key.
*
* @lookup: Lookup descriptor that must match a device
* @type: Lookup type
*/
int pci_bus_lookup(struct pci_device *lookup, lookup_type_t type);
/*
* Advocate for a specific device as its driver.
*
* @advp: Advocation descriptor
*
* Returns zero on success, otherwise a less than
* zero value on failure.
*/
int pci_advoc(struct pci_adv *advp);
/*
* Read from a specific register on a specific PCI
* enabled device.
*
* @dp: Device to read from
* @reg: Offset of desired register
*
* Returns the 32-bit register value on success
*/
pcireg_t pci_readl(struct pci_device *dp, pcireg_t reg);
/*
* Write a value to a specific register on a specific
* PCI enabled device.
*
* @dp: Device to write to
* @reg: Offset of the desired register
* @v: 32-bit value to be written
*/
void pci_writel(struct pci_device *dp, pcireg_t reg, pcival_t v);
/*
* Initialize the root bus and enumerate attached
* devices.
*/
void pci_init_bus(void);
#endif /* !PCI_PCI_H_ */
|