cardbus_map.c revision 1.29 1 /* $NetBSD: cardbus_map.c,v 1.29 2009/03/14 21:04:19 dsl Exp $ */
2
3 /*
4 * Copyright (c) 1999 and 2000
5 * HAYAKAWA Koichi. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by HAYAKAWA Koichi.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: cardbus_map.c,v 1.29 2009/03/14 21:04:19 dsl Exp $");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41
42 #include <sys/bus.h>
43
44 #include <dev/cardbus/cardbusvar.h>
45
46 #include <dev/pci/pcireg.h> /* XXX */
47
48 #if defined DEBUG && !defined CARDBUS_MAP_DEBUG
49 #define CARDBUS_MAP_DEBUG
50 #endif
51
52 #if defined CARDBUS_MAP_DEBUG
53 #define STATIC
54 #define DPRINTF(a) printf a
55 #else
56 #define STATIC static
57 #define DPRINTF(a)
58 #endif
59
60
61 static int cardbus_io_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
62 cardbustag_t, int, cardbusreg_t,
63 bus_addr_t *, bus_size_t *, int *);
64 static int cardbus_mem_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
65 cardbustag_t, int, cardbusreg_t,
66 bus_addr_t *, bus_size_t *, int *);
67
68 /*
69 * static int cardbus_io_find(cardbus_chipset_tag_t cc,
70 * cardbus_function_tag_t cf, cardbustag_t tag,
71 * int reg, cardbusreg_t type, bus_addr_t *basep,
72 * bus_size_t *sizep, int *flagsp)
73 * This code is stolen from sys/dev/pci_map.c.
74 */
75 static int
76 cardbus_io_find(
77 cardbus_chipset_tag_t cc,
78 cardbus_function_tag_t cf,
79 cardbustag_t tag,
80 int reg,
81 cardbusreg_t type,
82 bus_addr_t *basep,
83 bus_size_t *sizep,
84 int *flagsp)
85 {
86 cardbusreg_t address, mask;
87 int s;
88
89 /* EXT ROM is able to map on memory space ONLY. */
90 if (reg == CARDBUS_ROM_REG) {
91 return 1;
92 }
93
94 if(reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
95 panic("cardbus_io_find: bad request");
96 }
97
98 /*
99 * Section 6.2.5.1, `Address Maps', tells us that:
100 *
101 * 1) The builtin software should have already mapped the device in a
102 * reasonable way.
103 *
104 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
105 * n bits of the address to 0. As recommended, we write all 1s and see
106 * what we get back.
107 */
108 s = splhigh();
109 address = cardbus_conf_read(cc, cf, tag, reg);
110 cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
111 mask = cardbus_conf_read(cc, cf, tag, reg);
112 cardbus_conf_write(cc, cf, tag, reg, address);
113 splx(s);
114
115 if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
116 printf("cardbus_io_find: expected type i/o, found mem\n");
117 return 1;
118 }
119
120 if (PCI_MAPREG_IO_SIZE(mask) == 0) {
121 printf("cardbus_io_find: void region\n");
122 return 1;
123 }
124
125 if (basep != 0) {
126 *basep = PCI_MAPREG_IO_ADDR(address);
127 }
128 if (sizep != 0) {
129 *sizep = PCI_MAPREG_IO_SIZE(mask);
130 }
131 if (flagsp != 0) {
132 *flagsp = 0;
133 }
134
135 return 0;
136 }
137
138
139
140 /*
141 * static int cardbus_mem_find(cardbus_chipset_tag_t cc,
142 * cardbus_function_tag_t cf, cardbustag_t tag,
143 * int reg, cardbusreg_t type, bus_addr_t *basep,
144 * bus_size_t *sizep, int *flagsp)
145 * This code is stolen from sys/dev/pci_map.c.
146 */
147 static int
148 cardbus_mem_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, cardbustag_t tag, int reg, cardbusreg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
149 {
150 cardbusreg_t address, mask;
151 int s;
152
153 if (reg != CARDBUS_ROM_REG &&
154 (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) {
155 panic("cardbus_mem_find: bad request");
156 }
157
158 /*
159 * Section 6.2.5.1, `Address Maps', tells us that:
160 *
161 * 1) The builtin software should have already mapped the device in a
162 * reasonable way.
163 *
164 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
165 * n bits of the address to 0. As recommended, we write all 1s and see
166 * what we get back.
167 */
168 s = splhigh();
169 address = cardbus_conf_read(cc, cf, tag, reg);
170 cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
171 mask = cardbus_conf_read(cc, cf, tag, reg);
172 cardbus_conf_write(cc, cf, tag, reg, address);
173 splx(s);
174
175 if (reg != CARDBUS_ROM_REG) {
176 /* memory space BAR */
177
178 if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
179 printf("cardbus_mem_find: expected type mem, found i/o\n");
180 return 1;
181 }
182 if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
183 printf("cardbus_mem_find: expected mem type %08x, found %08x\n",
184 PCI_MAPREG_MEM_TYPE(type),
185 PCI_MAPREG_MEM_TYPE(address));
186 return 1;
187 }
188 }
189
190 if (PCI_MAPREG_MEM_SIZE(mask) == 0) {
191 printf("cardbus_mem_find: void region\n");
192 return 1;
193 }
194
195 switch (PCI_MAPREG_MEM_TYPE(address)) {
196 case PCI_MAPREG_MEM_TYPE_32BIT:
197 case PCI_MAPREG_MEM_TYPE_32BIT_1M:
198 break;
199 case PCI_MAPREG_MEM_TYPE_64BIT:
200 printf("cardbus_mem_find: 64-bit memory mapping register\n");
201 return 1;
202 default:
203 printf("cardbus_mem_find: reserved mapping register type\n");
204 return 1;
205 }
206
207 if (basep != 0) {
208 *basep = PCI_MAPREG_MEM_ADDR(address);
209 }
210 if (sizep != 0) {
211 *sizep = PCI_MAPREG_MEM_SIZE(mask);
212 }
213 if (flagsp != 0) {
214 *flagsp = PCI_MAPREG_MEM_PREFETCHABLE(address) ?
215 BUS_SPACE_MAP_PREFETCHABLE : 0;
216 }
217
218 return 0;
219 }
220
221
222
223
224 /*
225 * int cardbus_mapreg_map(struct cardbus_softc *, int, int, cardbusreg_t,
226 * int bus_space_tag_t *, bus_space_handle_t *,
227 * bus_addr_t *, bus_size_t *)
228 * This function maps bus-space on the value of Base Address
229 * Register (BAR) indexed by the argument `reg' (the second argument).
230 * When the value of the BAR is not valid, such as 0x00000000, a new
231 * address should be allocated for the BAR and new address values is
232 * written on the BAR.
233 */
234 int
235 cardbus_mapreg_map(struct cardbus_softc *sc, int func, int reg, cardbusreg_t type, int busflags, bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
236 {
237 cardbus_chipset_tag_t cc = sc->sc_cc;
238 cardbus_function_tag_t cf = sc->sc_cf;
239 bus_space_tag_t bustag;
240 #if rbus
241 rbus_tag_t rbustag;
242 #endif
243 bus_space_handle_t handle;
244 bus_addr_t base;
245 bus_size_t size;
246 int flags;
247 int status = 0;
248 cardbustag_t tag;
249
250 size = 0; /* XXX gcc */
251 flags = 0; /* XXX gcc */
252
253 tag = cardbus_make_tag(cc, cf, sc->sc_bus, func);
254
255 DPRINTF(("cardbus_mapreg_map called: %s %x\n", device_xname(sc->sc_dev),
256 type));
257
258 if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
259 if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size, &flags)) {
260 status = 1;
261 }
262 bustag = sc->sc_iot;
263 #if rbus
264 rbustag = sc->sc_rbus_iot;
265 #endif
266 } else {
267 if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size, &flags)){
268 status = 1;
269 }
270 bustag = sc->sc_memt;
271 #if rbus
272 rbustag = sc->sc_rbus_memt;
273 #endif
274 }
275 if (status == 0) {
276 #if rbus
277 bus_addr_t mask = size - 1;
278 if (base != 0) {
279 mask = 0xffffffff;
280 }
281 if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask,
282 size, busflags | flags, &base, &handle)) {
283 panic("io alloc");
284 }
285 #else
286 bus_addr_t start = 0x8300;
287 bus_addr_t end = 0x8400;
288 if (base != 0) {
289 bus_addr_t start = base;
290 bus_addr_t end = base + size;
291 }
292 if (bus_space_alloc(bustag, start, end, size, size, 0, 0, &base, &handle)) {
293 panic("io alloc");
294 }
295 #endif
296 }
297 cardbus_conf_write(cc, cf, tag, reg, base);
298
299 DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base));
300
301 if (tagp != 0) {
302 *tagp = bustag;
303 }
304 if (handlep != 0) {
305 *handlep = handle;
306 }
307 if (basep != 0) {
308 *basep = base;
309 }
310 if (sizep != 0) {
311 *sizep = size;
312 }
313 cardbus_free_tag(cc, cf, tag);
314
315 return 0;
316 }
317
318
319
320
321
322 /*
323 * int cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
324 * bus_space_tag_t tag, bus_space_handle_t handle,
325 * bus_size_t size)
326 *
327 * This function releases bus-space region and close memory or io
328 * window on the bridge.
329 *
330 * Arguments:
331 * struct cardbus_softc *sc; the pointer to the device structure of cardbus.
332 * int func; the number of function on the device.
333 * int reg; the offset of BAR register.
334 */
335 int
336 cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg, bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
337 {
338 cardbus_chipset_tag_t cc = sc->sc_cc;
339 cardbus_function_tag_t cf = sc->sc_cf;
340 int st = 1;
341 cardbustag_t cardbustag;
342 #if rbus
343 rbus_tag_t rbustag;
344
345 if (sc->sc_iot == tag) {
346 /* bus space is io space */
347 DPRINTF(("%s: unmap i/o space\n", device_xname(sc->sc_dev)));
348 rbustag = sc->sc_rbus_iot;
349 } else if (sc->sc_memt == tag) {
350 /* bus space is memory space */
351 DPRINTF(("%s: unmap mem space\n", device_xname(sc->sc_dev)));
352 rbustag = sc->sc_rbus_memt;
353 } else {
354 return 1;
355 }
356 #endif
357
358 cardbustag = cardbus_make_tag(cc, cf, sc->sc_bus, func);
359
360 cardbus_conf_write(cc, cf, cardbustag, reg, 0);
361
362 #if rbus
363 (*cf->cardbus_space_free)(cc, rbustag, handle, size);
364 #endif
365
366 cardbus_free_tag(cc, cf, cardbustag);
367
368 return st;
369 }
370
371
372
373
374
375 /*
376 * int cardbus_save_bar(cardbus_devfunc_t);
377 *
378 * This function saves the Base Address Registers at the CardBus
379 * function denoted by the argument.
380 */
381 int cardbus_save_bar(ct)
382 cardbus_devfunc_t ct;
383 {
384 cardbustag_t tag = Cardbus_make_tag(ct);
385 cardbus_chipset_tag_t cc = ct->ct_cc;
386 cardbus_function_tag_t cf = ct->ct_cf;
387
388 ct->ct_bar[0] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE0_REG);
389 ct->ct_bar[1] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE1_REG);
390 ct->ct_bar[2] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE2_REG);
391 ct->ct_bar[3] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE3_REG);
392 ct->ct_bar[4] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE4_REG);
393 ct->ct_bar[5] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE5_REG);
394
395 DPRINTF(("cardbus_save_bar: %x %x\n", ct->ct_bar[0], ct->ct_bar[1]));
396
397 Cardbus_free_tag(ct, tag);
398
399 return 0;
400 }
401
402
403
404 /*
405 * int cardbus_restore_bar(cardbus_devfunc_t);
406 *
407 * This function saves the Base Address Registers at the CardBus
408 * function denoted by the argument.
409 */
410 int cardbus_restore_bar(ct)
411 cardbus_devfunc_t ct;
412 {
413 cardbustag_t tag = Cardbus_make_tag(ct);
414 cardbus_chipset_tag_t cc = ct->ct_cc;
415 cardbus_function_tag_t cf = ct->ct_cf;
416
417 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, ct->ct_bar[0]);
418 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, ct->ct_bar[1]);
419 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, ct->ct_bar[2]);
420 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, ct->ct_bar[3]);
421 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, ct->ct_bar[4]);
422 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, ct->ct_bar[5]);
423
424 Cardbus_free_tag(ct, tag);
425
426 return 0;
427 }
428