This source file includes following definitions.
- obsd_pci_io_find
- obsd_pci_mem_find
- pci_io_find
- pci_mem_find
- pci_mapreg_type
- pci_mapreg_probe
- pci_mapreg_info
- pci_mapreg_map
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 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50
51
52 int obsd_pci_io_find(pci_chipset_tag_t, pcitag_t, int, pcireg_t,
53 bus_addr_t *, bus_size_t *, int *);
54 int obsd_pci_mem_find(pci_chipset_tag_t, pcitag_t, int, pcireg_t,
55 bus_addr_t *, bus_size_t *, int *);
56
57 int
58 obsd_pci_io_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
59 bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
60 {
61 pcireg_t address, mask, csr;
62 int s;
63
64 if (reg < PCI_MAPREG_START ||
65 #if 0
66
67
68
69
70 reg >= PCI_MAPREG_END ||
71 #endif
72 (reg & 3))
73 panic("pci_io_find: bad request");
74
75
76
77
78
79
80
81
82
83
84
85 s = splhigh();
86 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
87 if (csr & PCI_COMMAND_IO_ENABLE)
88 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
89 csr & ~PCI_COMMAND_IO_ENABLE);
90 address = pci_conf_read(pc, tag, reg);
91 pci_conf_write(pc, tag, reg, 0xffffffff);
92 mask = pci_conf_read(pc, tag, reg);
93 pci_conf_write(pc, tag, reg, address);
94 if (csr & PCI_COMMAND_IO_ENABLE)
95 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
96 splx(s);
97
98 if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
99 #ifdef DEBUG
100 printf("pci_io_find: expected type i/o, found mem\n");
101 #endif
102 return (EINVAL);
103 }
104
105 if (PCI_MAPREG_IO_SIZE(mask) == 0) {
106 #ifdef DEBUG
107 printf("pci_io_find: void region\n");
108 #endif
109 return (ENOENT);
110 }
111
112 if (basep != 0)
113 *basep = PCI_MAPREG_IO_ADDR(address);
114 if (sizep != 0)
115 *sizep = PCI_MAPREG_IO_SIZE(mask);
116 if (flagsp != 0)
117 *flagsp = 0;
118
119 return (0);
120 }
121
122 int
123 obsd_pci_mem_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
124 bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
125 {
126 pcireg_t address, mask, address1 = 0, mask1 = 0xffffffff, csr;
127 u_int64_t waddress, wmask;
128 int s, is64bit;
129
130 is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT);
131
132 if (reg < PCI_MAPREG_START ||
133 #if 0
134
135
136
137
138 reg >= PCI_MAPREG_END ||
139 #endif
140 (reg & 3))
141 panic("pci_mem_find: bad request");
142
143 if (is64bit && (reg + 4) >= PCI_MAPREG_END)
144 panic("pci_mem_find: bad 64-bit request");
145
146
147
148
149
150
151
152
153
154
155
156 s = splhigh();
157 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
158 if (csr & PCI_COMMAND_MEM_ENABLE)
159 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
160 csr & ~PCI_COMMAND_MEM_ENABLE);
161 address = pci_conf_read(pc, tag, reg);
162 pci_conf_write(pc, tag, reg, 0xffffffff);
163 mask = pci_conf_read(pc, tag, reg);
164 pci_conf_write(pc, tag, reg, address);
165 if (is64bit) {
166 address1 = pci_conf_read(pc, tag, reg + 4);
167 pci_conf_write(pc, tag, reg + 4, 0xffffffff);
168 mask1 = pci_conf_read(pc, tag, reg + 4);
169 pci_conf_write(pc, tag, reg + 4, address1);
170 }
171 if (csr & PCI_COMMAND_MEM_ENABLE)
172 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
173 splx(s);
174
175 if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
176 #ifdef DEBUG
177 printf("pci_mem_find: expected type mem, found i/o\n");
178 #endif
179 return (EINVAL);
180 }
181 if (type != -1 &&
182 PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
183 #ifdef DEBUG
184 printf("pci_mem_find: expected mem type %08x, found %08x\n",
185 PCI_MAPREG_MEM_TYPE(type),
186 PCI_MAPREG_MEM_TYPE(address));
187 #endif
188 return (EINVAL);
189 }
190
191 waddress = (u_int64_t)address1 << 32UL | address;
192 wmask = (u_int64_t)mask1 << 32UL | mask;
193
194 if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) ||
195 (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) {
196 #ifdef DEBUG
197 printf("pci_mem_find: void region\n");
198 #endif
199 return (ENOENT);
200 }
201
202 switch (PCI_MAPREG_MEM_TYPE(address)) {
203 case PCI_MAPREG_MEM_TYPE_32BIT:
204 case PCI_MAPREG_MEM_TYPE_32BIT_1M:
205 break;
206 case PCI_MAPREG_MEM_TYPE_64BIT:
207
208
209
210
211
212
213
214 if (sizeof(u_int64_t) > sizeof(bus_addr_t) &&
215 (address1 != 0 || mask1 != 0xffffffff)) {
216 #ifdef DEBUG
217 printf("pci_mem_find: 64-bit memory map which is "
218 "inaccessible on a 32-bit platform\n");
219 #endif
220 return (EINVAL);
221 }
222 break;
223 default:
224 #ifdef DEBUG
225 printf("pci_mem_find: reserved mapping register type\n");
226 #endif
227 return (EINVAL);
228 }
229
230 if (sizeof(u_int64_t) > sizeof(bus_addr_t)) {
231 if (basep != 0)
232 *basep = PCI_MAPREG_MEM_ADDR(address);
233 if (sizep != 0)
234 *sizep = PCI_MAPREG_MEM_SIZE(mask);
235 } else {
236 if (basep != 0)
237 *basep = PCI_MAPREG_MEM64_ADDR(waddress);
238 if (sizep != 0)
239 *sizep = PCI_MAPREG_MEM64_SIZE(wmask);
240 }
241 if (flagsp != 0)
242 *flagsp =
243 #ifdef BUS_SPACE_MAP_PREFETCHABLE
244 PCI_MAPREG_MEM_PREFETCHABLE(address) ?
245 BUS_SPACE_MAP_PREFETCHABLE :
246 #endif
247 0;
248
249 return (0);
250 }
251
252 int
253 pci_io_find(pci_chipset_tag_t pc, pcitag_t pcitag, int reg,
254 bus_addr_t *iobasep, bus_size_t *iosizep)
255 {
256 return (obsd_pci_io_find(pc, pcitag, reg, 0, iobasep, iosizep, 0));
257 }
258
259 int
260 pci_mem_find(pci_chipset_tag_t pc, pcitag_t pcitag, int reg,
261 bus_addr_t *membasep, bus_size_t *memsizep, int *cacheablep)
262 {
263 return (obsd_pci_mem_find(pc, pcitag, reg, -1, membasep, memsizep,
264 cacheablep));
265 }
266
267 pcireg_t
268 pci_mapreg_type(pci_chipset_tag_t pc, pcitag_t tag, int reg)
269 {
270 return (_PCI_MAPREG_TYPEBITS(pci_conf_read(pc, tag, reg)));
271 }
272
273 int
274 pci_mapreg_probe(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *typep)
275 {
276 pcireg_t address, mask, csr;
277 int s;
278
279 s = splhigh();
280 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
281 if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
282 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr &
283 ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE));
284 address = pci_conf_read(pc, tag, reg);
285 pci_conf_write(pc, tag, reg, 0xffffffff);
286 mask = pci_conf_read(pc, tag, reg);
287 pci_conf_write(pc, tag, reg, address);
288 if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
289 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
290 splx(s);
291
292 if (mask == 0)
293 return (0);
294
295 if (typep)
296 *typep = _PCI_MAPREG_TYPEBITS(address);
297 return (1);
298 }
299
300 int
301 pci_mapreg_info(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
302 bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
303 {
304
305 if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
306 return (obsd_pci_io_find(pc, tag, reg, type, basep, sizep,
307 flagsp));
308 else
309 return (obsd_pci_mem_find(pc, tag, reg, type, basep, sizep,
310 flagsp));
311 }
312
313 int
314 pci_mapreg_map(struct pci_attach_args *pa, int reg, pcireg_t type, int busflags,
315 bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep,
316 bus_size_t *sizep, bus_size_t maxsize)
317 {
318 bus_space_tag_t tag;
319 bus_space_handle_t handle;
320 bus_addr_t base;
321 bus_size_t size;
322 pcireg_t csr;
323 int flags;
324 int rv;
325
326 if ((rv = pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg, type,
327 &base, &size, &flags)) != 0)
328 return (rv);
329 if (base == 0)
330 return (EINVAL);
331
332 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
333 if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
334 csr |= PCI_COMMAND_IO_ENABLE;
335 else
336 csr |= PCI_COMMAND_MEM_ENABLE;
337
338 csr |= PCI_COMMAND_MASTER_ENABLE;
339 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);
340
341 if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
342 if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0)
343 return (EINVAL);
344 tag = pa->pa_iot;
345 } else {
346 if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0)
347 return (EINVAL);
348 tag = pa->pa_memt;
349 }
350
351
352 if (maxsize != 0 && size > maxsize) {
353 #ifdef DEBUG
354 printf("pci_mapreg_map: limited PCI mapping from %lx to %lx\n",
355 (u_long)size, (u_long)maxsize);
356 #endif
357 size = maxsize;
358 }
359
360 if (bus_space_map(tag, base, size, busflags | flags, &handle))
361 return (1);
362
363 if (tagp != NULL)
364 *tagp = tag;
365 if (handlep != NULL)
366 *handlep = handle;
367 if (basep != NULL)
368 *basep = base;
369 if (sizep != NULL)
370 *sizep = size;
371
372 return (0);
373 }