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