1 /*
2  * Copyright (c) 2009 Corey Tabaka
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #ifndef __PCI_H
24 #define __PCI_H
25 
26 #include <sys/types.h>
27 #include <compiler.h>
28 
29 /*
30  * PCI access return codes
31  */
32 #define _PCI_SUCCESSFUL             0x00
33 #define _PCI_FUNC_NOT_SUPPORTED     0x81
34 #define _PCI_BAD_VENDOR_ID          0x83
35 #define _PCI_DEVICE_NOT_FOUND       0x86
36 #define _PCI_BAD_REGISTER_NUMBER    0x87
37 #define _PCI_SET_FAILED             0x88
38 #define _PCI_BUFFER_TOO_SMALL       0x89
39 
40 /*
41  * PCI configuration space offsets
42  */
43 #define PCI_CONFIG_VENDOR_ID        0x00
44 #define PCI_CONFIG_DEVICE_ID        0x02
45 #define PCI_CONFIG_COMMAND          0x04
46 #define PCI_CONFIG_STATUS           0x06
47 #define PCI_CONFIG_REVISION_ID      0x08
48 #define PCI_CONFIG_CLASS_CODE       0x09
49 #define PCI_CONFIG_CLASS_CODE_INTR  0x09
50 #define PCI_CONFIG_CLASS_CODE_SUB   0x0a
51 #define PCI_CONFIG_CLASS_CODE_BASE  0x0b
52 #define PCI_CONFIG_CACHE_LINE_SIZE  0x0c
53 #define PCI_CONFIG_LATENCY_TIMER    0x0d
54 #define PCI_CONFIG_HEADER_TYPE      0x0e
55 #define PCI_CONFIG_BIST             0x0f
56 #define PCI_CONFIG_BASE_ADDRESSES   0x10
57 #define PCI_CONFIG_CARDBUS_CIS_PTR  0x28
58 #define PCI_CONFIG_SUBSYS_VENDOR_ID 0x2c
59 #define PCI_CONFIG_SUBSYS_ID        0x2e
60 #define PCI_CONFIG_EXP_ROM_ADDRESS  0x30
61 #define PCI_CONFIG_CAPABILITIES     0x34
62 #define PCI_CONFIG_INTERRUPT_LINE   0x3c
63 #define PCI_CONFIG_INTERRUPT_PIN    0x3d
64 #define PCI_CONFIG_MIN_GRANT        0x3e
65 #define PCI_CONFIG_MAX_LATENCY      0x3f
66 
67 /*
68  * PCI header type register bits
69  */
70 #define PCI_HEADER_TYPE_MASK        0x7f
71 #define PCI_HEADER_TYPE_MULTI_FN    0x80
72 
73 /*
74  * PCI header types
75  */
76 #define PCI_HEADER_TYPE_STANDARD    0x00
77 #define PCI_HEADER_TYPE_PCI_BRIDGE  0x01
78 #define PCI_HEADER_TYPE_CARD_BUS    0x02
79 
80 /*
81  * PCI command register bits
82  */
83 #define PCI_COMMAND_IO_EN           0x0001
84 #define PCI_COMMAND_MEM_EN          0x0002
85 #define PCI_COMMAND_BUS_MASTER_EN   0x0004
86 #define PCI_COMMAND_SPECIAL_EN      0x0008
87 #define PCI_COMMAND_MEM_WR_INV_EN   0x0010
88 #define PCI_COMMAND_PAL_SNOOP_EN    0x0020
89 #define PCI_COMMAND_PERR_RESP_EN    0x0040
90 #define PCI_COMMAND_AD_STEP_EN      0x0080
91 #define PCI_COMMAND_SERR_EN         0x0100
92 #define PCI_COMMAND_FAST_B2B_EN     0x0200
93 
94 /*
95  * PCI status register bits
96  */
97 #define PCI_STATUS_NEW_CAPS         0x0010
98 #define PCI_STATUS_66_MHZ           0x0020
99 #define PCI_STATUS_FAST_B2B         0x0080
100 #define PCI_STATUS_MSTR_PERR        0x0100
101 #define PCI_STATUS_DEVSEL_MASK      0x0600
102 #define PCI_STATUS_TARG_ABORT_SIG   0x0800
103 #define PCI_STATUS_TARG_ABORT_RCV   0x1000
104 #define PCI_STATUS_MSTR_ABORT_RCV   0x2000
105 #define PCI_STATUS_SERR_SIG         0x4000
106 #define PCI_STATUS_PERR             0x8000
107 
108 typedef struct {
109     uint16_t vendor_id;
110     uint16_t device_id;
111     uint16_t command;
112     uint16_t status;
113     uint8_t revision_id_0;
114     uint8_t program_interface;
115     uint8_t sub_class;
116     uint8_t base_class;
117     uint8_t cache_line_size;
118     uint8_t latency_timer;
119     uint8_t header_type;
120     uint8_t bist;
121     uint32_t base_addresses[6];
122     uint32_t cardbus_cis_ptr;
123     uint16_t subsystem_vendor_id;
124     uint16_t subsystem_id;
125     uint32_t expansion_rom_address;
126     uint8_t capabilities_ptr;
127     uint8_t reserved_0[3];
128     uint32_t reserved_1;
129     uint8_t interrupt_line;
130     uint8_t interrupt_pin;
131     uint8_t min_grant;
132     uint8_t max_latency;
133 } __PACKED pci_config_t;
134 
135 /*
136  * PCI address structure
137  */
138 typedef struct {
139     uint8_t bus;
140     uint8_t dev_fn;
141 } pci_location_t;
142 
143 typedef struct {
144     uint8_t id;
145     uint8_t next;
146 } __PACKED pci_capability_t;
147 
148 typedef struct {
149     uint8_t bus;
150     uint8_t device;
151     uint8_t link_int_a;
152     uint16_t irq_int_a;
153     uint8_t link_int_b;
154     uint16_t irq_int_b;
155     uint8_t link_int_c;
156     uint16_t irq_int_c;
157     uint8_t link_int_d;
158     uint16_t irq_int_d;
159     uint8_t slot;
160     uint8_t reserved;
161 } __PACKED irq_routing_entry;
162 
163 void pci_init(void);
164 
165 int pci_get_last_bus(void);
166 
167 int pci_find_pci_device(pci_location_t *state, uint16_t device_id, uint16_t vendor_id, uint16_t index);
168 int pci_find_pci_class_code(pci_location_t *state, uint32_t class_code, uint16_t index);
169 
170 int pci_read_config_byte(const pci_location_t *state, uint32_t reg, uint8_t *value);
171 int pci_read_config_half(const pci_location_t *state, uint32_t reg, uint16_t *value);
172 int pci_read_config_word(const pci_location_t *state, uint32_t reg, uint32_t *value);
173 
174 int pci_write_config_byte(const pci_location_t *state, uint32_t reg, uint8_t value);
175 int pci_write_config_half(const pci_location_t *state, uint32_t reg, uint16_t value);
176 int pci_write_config_word(const pci_location_t *state, uint32_t reg, uint32_t value);
177 
178 int pci_get_irq_routing_options(irq_routing_entry *entries, uint16_t *count, uint16_t *pci_irqs);
179 int pci_set_irq_hw_int(const pci_location_t *state, uint8_t int_pin, uint8_t irq);
180 
181 #endif
182