Annotation of sys/dev/pci/pccbb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pccbb.c,v 1.47 2006/10/12 16:35:51 grange Exp $ */
2: /* $NetBSD: pccbb.c,v 1.96 2004/03/28 09:49:31 nakayama Exp $ */
3:
4: /*
5: * Copyright (c) 1998, 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: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: #define CBB_DEBUG
36: #define SHOW_REGS
37: #define PCCBB_PCMCIA_POLL
38: */
39:
40: /*
41: #define CB_PCMCIA_POLL
42: #define CB_PCMCIA_POLL_ONLY
43: #define LEVEL2
44: */
45:
46: #include <sys/types.h>
47: #include <sys/param.h>
48: #include <sys/systm.h>
49: #include <sys/kernel.h>
50: #include <sys/errno.h>
51: #include <sys/evcount.h>
52: #include <sys/ioctl.h>
53: #include <sys/syslog.h>
54: #include <sys/device.h>
55: #include <sys/malloc.h>
56:
57: #include <machine/intr.h>
58: #include <machine/bus.h>
59:
60: #include <dev/pci/pcivar.h>
61: #include <dev/pci/pcireg.h>
62: #include <dev/pci/pcidevs.h>
63:
64: #include <dev/pci/pccbbreg.h>
65:
66: #include <dev/cardbus/cardslotvar.h>
67:
68: #include <dev/cardbus/cardbusvar.h>
69:
70: #include <dev/pcmcia/pcmciareg.h>
71: #include <dev/pcmcia/pcmciavar.h>
72:
73: #include <dev/ic/i82365reg.h>
74: #include <dev/ic/i82365var.h>
75: #include <dev/pci/pccbbvar.h>
76:
77: #ifndef __NetBSD_Version__
78: struct cfdriver cbb_cd = {
79: NULL, "cbb", DV_DULL
80: };
81: #endif
82:
83: #if defined CBB_DEBUG
84: #define DPRINTF(x) printf x
85: #else
86: #define DPRINTF(x)
87: #endif
88:
89: int pcicbbmatch(struct device *, void *, void *);
90: void pccbbattach(struct device *, struct device *, void *);
91: int pccbbintr(void *);
92: void pccbb_shutdown(void *);
93: void pci113x_insert(void *);
94: int pccbbintr_function(struct pccbb_softc *);
95:
96: int pccbb_detect_card(struct pccbb_softc *);
97:
98: void pccbb_pcmcia_write(struct pcic_handle *, int, int);
99: u_int8_t pccbb_pcmcia_read(struct pcic_handle *, int);
100: #define Pcic_read(ph, reg) ((ph)->ph_read((ph), (reg)))
101: #define Pcic_write(ph, reg, val) ((ph)->ph_write((ph), (reg), (val)))
102:
103: int cb_reset(struct pccbb_softc *);
104: int cb_detect_voltage(struct pccbb_softc *);
105: int cbbprint(void *, const char *);
106:
107: int cb_chipset(u_int32_t, int *);
108: void pccbb_pcmcia_attach_setup(struct pccbb_softc *,
109: struct pcmciabus_attach_args *);
110: #if 0
111: void pccbb_pcmcia_attach_card(struct pcic_handle *);
112: void pccbb_pcmcia_detach_card(struct pcic_handle *, int);
113: void pccbb_pcmcia_deactivate_card(struct pcic_handle *);
114: #endif
115:
116: int pccbb_ctrl(cardbus_chipset_tag_t, int);
117: int pccbb_power(cardbus_chipset_tag_t, int);
118: int pccbb_cardenable(struct pccbb_softc * sc, int function);
119: void *pccbb_intr_establish(struct pccbb_softc *, int irq, int level,
120: int (*ih) (void *), void *sc, const char *);
121: void pccbb_intr_disestablish(struct pccbb_softc *, void *ih);
122:
123: void *pccbb_cb_intr_establish(cardbus_chipset_tag_t, int irq, int level,
124: int (*ih) (void *), void *sc, const char *);
125: void pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct, void *ih);
126:
127: cardbustag_t pccbb_make_tag(cardbus_chipset_tag_t, int, int, int);
128: void pccbb_free_tag(cardbus_chipset_tag_t, cardbustag_t);
129: cardbusreg_t pccbb_conf_read(cardbus_chipset_tag_t, cardbustag_t, int);
130: void pccbb_conf_write(cardbus_chipset_tag_t, cardbustag_t, int,
131: cardbusreg_t);
132: void pccbb_chipinit(struct pccbb_softc *);
133:
134: int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
135: struct pcmcia_mem_handle *);
136: void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t,
137: struct pcmcia_mem_handle *);
138: int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
139: bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
140: void pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t, int);
141: int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
142: bus_size_t, bus_size_t, struct pcmcia_io_handle *);
143: void pccbb_pcmcia_io_free(pcmcia_chipset_handle_t,
144: struct pcmcia_io_handle *);
145: int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t, int, bus_addr_t,
146: bus_size_t, struct pcmcia_io_handle *, int *);
147: void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t, int);
148: void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t,
149: struct pcmcia_function *, int, int (*)(void *), void *, char *);
150: void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t, void *);
151: const char *pccbb_pcmcia_intr_string(pcmcia_chipset_handle_t, void *);
152: void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t);
153: void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t);
154: int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t pch);
155:
156: void pccbb_pcmcia_do_io_map(struct pcic_handle *, int);
157: void pccbb_pcmcia_wait_ready(struct pcic_handle *);
158: void pccbb_pcmcia_do_mem_map(struct pcic_handle *, int);
159: void pccbb_powerhook(int, void *);
160:
161: /* bus-space allocation and deallocation functions */
162: int pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t, rbus_tag_t,
163: bus_addr_t addr, bus_size_t size, bus_addr_t mask, bus_size_t align,
164: int flags, bus_addr_t * addrp, bus_space_handle_t * bshp);
165: int pccbb_rbus_cb_space_free(cardbus_chipset_tag_t, rbus_tag_t,
166: bus_space_handle_t, bus_size_t);
167:
168: int pccbb_open_win(struct pccbb_softc *, bus_space_tag_t,
169: bus_addr_t, bus_size_t, bus_space_handle_t, int flags);
170: int pccbb_close_win(struct pccbb_softc *, bus_space_tag_t,
171: bus_space_handle_t, bus_size_t);
172: int pccbb_winlist_insert(struct pccbb_win_chain_head *, bus_addr_t,
173: bus_size_t, bus_space_handle_t, int);
174: int pccbb_winlist_delete(struct pccbb_win_chain_head *,
175: bus_space_handle_t, bus_size_t);
176: void pccbb_winset(bus_addr_t align, struct pccbb_softc *,
177: bus_space_tag_t);
178: void pccbb_winlist_show(struct pccbb_win_chain *);
179:
180: /* for config_defer */
181: void pccbb_pci_callback(struct device *);
182:
183: #if defined SHOW_REGS
184: void cb_show_regs(pci_chipset_tag_t, pcitag_t, bus_space_tag_t,
185: bus_space_handle_t memh);
186: #endif
187:
188: struct cfattach cbb_pci_ca = {
189: sizeof(struct pccbb_softc), pcicbbmatch, pccbbattach
190: };
191:
192: static struct pcmcia_chip_functions pccbb_pcmcia_funcs = {
193: pccbb_pcmcia_mem_alloc,
194: pccbb_pcmcia_mem_free,
195: pccbb_pcmcia_mem_map,
196: pccbb_pcmcia_mem_unmap,
197: pccbb_pcmcia_io_alloc,
198: pccbb_pcmcia_io_free,
199: pccbb_pcmcia_io_map,
200: pccbb_pcmcia_io_unmap,
201: pccbb_pcmcia_intr_establish,
202: pccbb_pcmcia_intr_disestablish,
203: pccbb_pcmcia_intr_string,
204: pccbb_pcmcia_socket_enable,
205: pccbb_pcmcia_socket_disable,
206: pccbb_pcmcia_card_detect
207: };
208:
209: static struct cardbus_functions pccbb_funcs = {
210: pccbb_rbus_cb_space_alloc,
211: pccbb_rbus_cb_space_free,
212: pccbb_cb_intr_establish,
213: pccbb_cb_intr_disestablish,
214: pccbb_ctrl,
215: pccbb_power,
216: pccbb_make_tag,
217: pccbb_free_tag,
218: pccbb_conf_read,
219: pccbb_conf_write,
220: };
221:
222: int
223: pcicbbmatch(parent, match, aux)
224: struct device *parent;
225: void *match;
226: void *aux;
227: {
228: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
229:
230: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
231: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_CARDBUS &&
232: PCI_INTERFACE(pa->pa_class) == 0) {
233: return 1;
234: }
235:
236: return 0;
237: }
238:
239: #define MAKEID(vendor, prod) (((vendor) << PCI_VENDOR_SHIFT) \
240: | ((prod) << PCI_PRODUCT_SHIFT))
241:
242: struct yenta_chipinfo {
243: pcireg_t yc_id; /* vendor tag | product tag */
244: int yc_chiptype;
245: int yc_flags;
246: } yc_chipsets[] = {
247: /* Texas Instruments chips */
248: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1130), CB_TI113X,
249: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
250: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1131), CB_TI113X,
251: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
252: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1250), CB_TI125X,
253: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
254: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1220), CB_TI12XX,
255: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
256: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1221), CB_TI12XX,
257: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
258: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1225), CB_TI12XX,
259: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
260: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251), CB_TI125X,
261: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
262: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251B), CB_TI125X,
263: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
264: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1211), CB_TI12XX,
265: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
266: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1410), CB_TI12XX,
267: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
268: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1420), CB_TI12XX,
269: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
270: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1450), CB_TI125X,
271: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
272: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1451), CB_TI12XX,
273: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
274: { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI7XX1), CB_TI12XX,
275: PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
276:
277: /* Ricoh chips */
278: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C475), CB_RX5C47X,
279: PCCBB_PCMCIA_MEM_32},
280: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C476), CB_RX5C47X,
281: PCCBB_PCMCIA_MEM_32},
282: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C477), CB_RX5C47X,
283: PCCBB_PCMCIA_MEM_32},
284: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C478), CB_RX5C47X,
285: PCCBB_PCMCIA_MEM_32},
286: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C465), CB_RX5C46X,
287: PCCBB_PCMCIA_MEM_32},
288: { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C466), CB_RX5C46X,
289: PCCBB_PCMCIA_MEM_32},
290:
291: /* Toshiba products */
292: { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95),
293: CB_TOPIC95, PCCBB_PCMCIA_MEM_32},
294: { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95B),
295: CB_TOPIC95B, PCCBB_PCMCIA_MEM_32},
296: { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC97),
297: CB_TOPIC97, PCCBB_PCMCIA_MEM_32},
298: { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC100),
299: CB_TOPIC97, PCCBB_PCMCIA_MEM_32},
300:
301: /* Cirrus Logic products */
302: { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6832),
303: CB_CIRRUS, PCCBB_PCMCIA_MEM_32},
304: { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6833),
305: CB_CIRRUS, PCCBB_PCMCIA_MEM_32},
306:
307: /* older O2Micro bridges */
308: { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6729),
309: CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
310: { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6730),
311: CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
312: { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6872), /* 68[71]2 */
313: CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
314: { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6832),
315: CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
316: { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6836),
317: CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
318:
319: /* sentinel, or Generic chip */
320: { 0 /* null id */ , CB_UNKNOWN, PCCBB_PCMCIA_MEM_32},
321: };
322:
323: int
324: cb_chipset(pci_id, flagp)
325: u_int32_t pci_id;
326: int *flagp;
327: {
328: struct yenta_chipinfo *yc;
329:
330: /* Loop over except the last default entry. */
331: for (yc = yc_chipsets; yc < yc_chipsets +
332: sizeof(yc_chipsets) / sizeof(yc_chipsets[0]) - 1; yc++)
333: if (pci_id == yc->yc_id)
334: break;
335:
336: if (flagp != NULL)
337: *flagp = yc->yc_flags;
338:
339: return (yc->yc_chiptype);
340: }
341:
342: void
343: pccbb_shutdown(void *arg)
344: {
345: struct pccbb_softc *sc = arg;
346: pcireg_t command;
347:
348: DPRINTF(("%s: shutdown\n", sc->sc_dev.dv_xname));
349:
350: /* turn off power */
351: pccbb_power((cardbus_chipset_tag_t)sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
352:
353: bus_space_write_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_MASK,
354: 0);
355:
356: command = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
357:
358: command &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
359: PCI_COMMAND_MASTER_ENABLE);
360: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command);
361: }
362:
363: void
364: pccbbattach(parent, self, aux)
365: struct device *parent;
366: struct device *self;
367: void *aux;
368: {
369: struct pccbb_softc *sc = (void *)self;
370: struct pci_attach_args *pa = aux;
371: pci_chipset_tag_t pc = pa->pa_pc;
372: pcireg_t busreg, reg, sock_base;
373: pci_intr_handle_t ih;
374: const char *intrstr = NULL;
375: bus_addr_t sockbase;
376: int flags;
377:
378: #ifdef __HAVE_PCCBB_ATTACH_HOOK
379: pccbb_attach_hook(parent, self, pa);
380: #endif
381:
382: sc->sc_chipset = cb_chipset(pa->pa_id, &flags);
383:
384: #ifdef CBB_DEBUG
385: printf(" (chipflags %x)", flags);
386: #endif
387:
388: TAILQ_INIT(&sc->sc_memwindow);
389: TAILQ_INIT(&sc->sc_iowindow);
390:
391: sc->sc_rbus_iot = rbus_pccbb_parent_io(self, pa);
392: sc->sc_rbus_memt = rbus_pccbb_parent_mem(self, pa);
393:
394: sc->sc_flags &= ~CBB_MEMHMAPPED;
395:
396: /*
397: * MAP socket registers and ExCA registers on memory-space
398: * When no valid address is set on socket base registers (on pci
399: * config space), get it not polite way.
400: */
401: sock_base = pci_conf_read(pc, pa->pa_tag, PCI_SOCKBASE);
402:
403: if (PCI_MAPREG_MEM_ADDR(sock_base) >= 0x100000 &&
404: PCI_MAPREG_MEM_ADDR(sock_base) != 0xfffffff0) {
405: /* The address must be valid. */
406: if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_MEM, 0,
407: &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, NULL, 0))
408: {
409: printf("%s: can't map socket base address 0x%x\n",
410: sc->sc_dev.dv_xname, sock_base);
411: /*
412: * I think it's funny: socket base registers must be
413: * mapped on memory space, but ...
414: */
415: if (pci_mapreg_map(pa, PCI_SOCKBASE,
416: PCI_MAPREG_TYPE_IO, 0, &sc->sc_base_memt,
417: &sc->sc_base_memh, &sockbase, NULL, 0)) {
418: printf("%s: can't map socket base address"
419: " 0x%lx: io mode\n", sc->sc_dev.dv_xname,
420: sockbase);
421: /* give up... allocate reg space via rbus. */
422: pci_conf_write(pc, pa->pa_tag, PCI_SOCKBASE, 0);
423: } else
424: sc->sc_flags |= CBB_MEMHMAPPED;
425: } else {
426: DPRINTF(("%s: socket base address 0x%lx\n",
427: sc->sc_dev.dv_xname, sockbase));
428: sc->sc_flags |= CBB_MEMHMAPPED;
429: }
430: }
431:
432: sc->sc_mem_start = 0; /* XXX */
433: sc->sc_mem_end = 0xffffffff; /* XXX */
434:
435: /*
436: * When bus number isn't set correctly, give up using 32-bit CardBus
437: * mode.
438: */
439: busreg = pci_conf_read(pc, pa->pa_tag, PCI_BUSNUM);
440: #if notyet
441: if (((busreg >> 8) & 0xff) == 0) {
442: printf(": CardBus support disabled because of unconfigured bus number\n");
443: flags |= PCCBB_PCMCIA_16BITONLY;
444: }
445: #endif
446:
447: /* pccbb_machdep.c end */
448:
449: #if defined CBB_DEBUG
450: {
451: static char *intrname[5] = { "NON", "A", "B", "C", "D" };
452: printf(": intrpin %s, intrtag %d\n",
453: intrname[pa->pa_intrpin], pa->pa_intrline);
454: }
455: #endif
456:
457: /* setup softc */
458: sc->sc_pc = pc;
459: sc->sc_iot = pa->pa_iot;
460: sc->sc_memt = pa->pa_memt;
461: sc->sc_dmat = pa->pa_dmat;
462: sc->sc_tag = pa->pa_tag;
463: sc->sc_function = pa->pa_function;
464: sc->sc_sockbase = sock_base;
465: sc->sc_busnum = busreg;
466: sc->sc_intrtag = pa->pa_intrtag;
467: sc->sc_intrpin = pa->pa_intrpin;
468:
469: sc->sc_pcmcia_flags = flags; /* set PCMCIA facility */
470:
471: /* Map and establish the interrupt. */
472: if (pci_intr_map(pa, &ih)) {
473: printf(": couldn't map interrupt\n");
474: return;
475: }
476: intrstr = pci_intr_string(pc, ih);
477: /* must do this after intr is mapped and established */
478: sc->sc_intrline = pci_intr_line(ih);
479:
480: /*
481: * XXX pccbbintr should be called under the priority lower
482: * than any other hard interrupts.
483: */
484: sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, pccbbintr, sc,
485: sc->sc_dev.dv_xname);
486:
487: if (sc->sc_ih == NULL) {
488: printf(": couldn't establish interrupt");
489: if (intrstr != NULL) {
490: printf(" at %s", intrstr);
491: }
492: printf("\n");
493: return;
494: }
495: printf(": %s\n", intrstr);
496:
497: shutdownhook_establish(pccbb_shutdown, sc);
498:
499: /* Disable legacy register mapping. */
500: switch (sc->sc_chipset) {
501: case CB_RX5C46X: /* fallthrough */
502: #if 0
503: /* The RX5C47X-series requires writes to the PCI_LEGACY register. */
504: case CB_RX5C47X:
505: #endif
506: /*
507: * The legacy pcic io-port on Ricoh RX5C46X CardBus bridges
508: * cannot be disabled by substituting 0 into PCI_LEGACY
509: * register. Ricoh CardBus bridges have special bits on Bridge
510: * control reg (addr 0x3e on PCI config space).
511: */
512: reg = pci_conf_read(pc, pa->pa_tag, PCI_BCR_INTR);
513: reg &= ~(CB_BCRI_RL_3E0_ENA | CB_BCRI_RL_3E2_ENA);
514: pci_conf_write(pc, pa->pa_tag, PCI_BCR_INTR, reg);
515: break;
516:
517: default:
518: /* XXX I don't know proper way to kill legacy I/O. */
519: pci_conf_write(pc, pa->pa_tag, PCI_LEGACY, 0x0);
520: break;
521: }
522:
523: timeout_set(&sc->sc_ins_tmo, pci113x_insert, sc);
524: config_defer(self, pccbb_pci_callback);
525: }
526:
527: /*
528: * void pccbb_pci_callback(struct device *self)
529: *
530: * The actual attach routine: get memory space for YENTA register
531: * space, setup YENTA register and route interrupt.
532: *
533: * This function should be deferred because this device may obtain
534: * memory space dynamically. This function must avoid obtaining
535: * memory area which has already kept for another device. Also,
536: * this function MUST be done before ISA attach process because this
537: * function kills pcic compatible port used by ISA pcic.
538: */
539: void
540: pccbb_pci_callback(self)
541: struct device *self;
542: {
543: struct pccbb_softc *sc = (void *)self;
544: pci_chipset_tag_t pc = sc->sc_pc;
545: bus_space_tag_t base_memt;
546: bus_space_handle_t base_memh;
547: u_int32_t maskreg;
548: bus_addr_t sockbase;
549: struct cbslot_attach_args cba;
550: struct pcmciabus_attach_args paa;
551: struct cardslot_attach_args caa;
552: struct cardslot_softc *csc;
553:
554: if (!(sc->sc_flags & CBB_MEMHMAPPED)) {
555: /* The socket registers aren't mapped correctly. */
556: if (rbus_space_alloc(sc->sc_rbus_memt, 0, 0x1000, 0x0fff,
557: (sc->sc_chipset == CB_RX5C47X
558: || sc->sc_chipset == CB_TI113X) ? 0x10000 : 0x1000,
559: 0, &sockbase, &sc->sc_base_memh)) {
560: return;
561: }
562: sc->sc_base_memt = sc->sc_memt;
563: pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase);
564: DPRINTF(("%s: CardBus register address 0x%lx -> 0x%x\n",
565: sc->sc_dev.dv_xname, sockbase, pci_conf_read(pc, sc->sc_tag,
566: PCI_SOCKBASE)));
567: sc->sc_flags |= CBB_MEMHMAPPED;
568: }
569:
570: /* bus bridge initialization */
571: pccbb_chipinit(sc);
572:
573: base_memt = sc->sc_base_memt; /* socket regs memory tag */
574: base_memh = sc->sc_base_memh; /* socket regs memory handle */
575:
576: /* clear data structure for child device interrupt handlers */
577: sc->sc_pil = NULL;
578: sc->sc_pil_intr_enable = 1;
579:
580: powerhook_establish(pccbb_powerhook, sc);
581:
582: {
583: u_int32_t sockstat =
584: bus_space_read_4(base_memt, base_memh, CB_SOCKET_STAT);
585: if (0 == (sockstat & CB_SOCKET_STAT_CD)) {
586: sc->sc_flags |= CBB_CARDEXIST;
587: }
588: }
589:
590: /*
591: * attach cardbus
592: */
593: if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_16BITONLY)) {
594: pcireg_t busreg = pci_conf_read(pc, sc->sc_tag, PCI_BUSNUM);
595: pcireg_t bhlc = pci_conf_read(pc, sc->sc_tag, PCI_BHLC_REG);
596:
597: /* initialize cbslot_attach */
598: cba.cba_busname = "cardbus";
599: cba.cba_iot = sc->sc_iot;
600: cba.cba_memt = sc->sc_memt;
601: cba.cba_dmat = sc->sc_dmat;
602: cba.cba_bus = (busreg >> 8) & 0x0ff;
603: cba.cba_cc = (void *)sc;
604: cba.cba_cf = &pccbb_funcs;
605: cba.cba_intrline = sc->sc_intrline;
606:
607: cba.cba_rbus_iot = sc->sc_rbus_iot;
608: cba.cba_rbus_memt = sc->sc_rbus_memt;
609:
610: cba.cba_cacheline = PCI_CACHELINE(bhlc);
611: cba.cba_lattimer = PCI_CB_LATENCY(busreg);
612:
613: #if defined CBB_DEBUG
614: printf("%s: cacheline 0x%x lattimer 0x%x\n",
615: sc->sc_dev.dv_xname, cba.cba_cacheline, cba.cba_lattimer);
616: printf("%s: bhlc 0x%x lscp 0x%x\n", sc->sc_dev.dv_xname, bhlc,
617: busreg);
618: #endif
619: #if defined SHOW_REGS
620: cb_show_regs(sc->sc_pc, sc->sc_tag, sc->sc_base_memt,
621: sc->sc_base_memh);
622: #endif
623: }
624:
625: pccbb_pcmcia_attach_setup(sc, &paa);
626: caa.caa_cb_attach = NULL;
627: if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_16BITONLY)) {
628: caa.caa_cb_attach = &cba;
629: }
630: caa.caa_16_attach = &paa;
631: caa.caa_ph = &sc->sc_pcmcia_h;
632:
633: if (NULL != (csc = (void *)config_found(self, &caa, cbbprint))) {
634: DPRINTF(("pccbbattach: found cardslot\n"));
635: sc->sc_csc = csc;
636: }
637:
638: sc->sc_ints_on = 1;
639:
640: /* CSC Interrupt: Card detect interrupt on */
641: maskreg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK);
642: maskreg |= CB_SOCKET_MASK_CD; /* Card detect intr is turned on. */
643: bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, maskreg);
644: /* reset interrupt */
645: bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT,
646: bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT));
647:
648: return;
649: }
650:
651: /*
652: * void pccbb_chipinit(struct pccbb_softc *sc)
653: *
654: * This function initialize YENTA chip registers listed below:
655: * 1) PCI command reg,
656: * 2) PCI and CardBus latency timer,
657: * 3) route PCI interrupt,
658: * 4) close all memory and io windows.
659: */
660: void
661: pccbb_chipinit(sc)
662: struct pccbb_softc *sc;
663: {
664: pci_chipset_tag_t pc = sc->sc_pc;
665: pcitag_t tag = sc->sc_tag;
666: pcireg_t reg;
667:
668: /*
669: * Set PCI command reg.
670: * Some laptop's BIOSes (i.e. TICO) do not enable CardBus chip.
671: */
672: reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
673: /* I believe it is harmless. */
674: reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
675: PCI_COMMAND_MASTER_ENABLE);
676: pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg);
677:
678: /*
679: * Set CardBus latency timer.
680: */
681: reg = pci_conf_read(pc, tag, PCI_CB_LSCP_REG);
682: if (PCI_CB_LATENCY(reg) < 0x20) {
683: reg &= ~(PCI_CB_LATENCY_MASK << PCI_CB_LATENCY_SHIFT);
684: reg |= (0x20 << PCI_CB_LATENCY_SHIFT);
685: pci_conf_write(pc, tag, PCI_CB_LSCP_REG, reg);
686: }
687: DPRINTF(("CardBus latency timer 0x%x (%x)\n",
688: PCI_CB_LATENCY(reg), pci_conf_read(pc, tag, PCI_CB_LSCP_REG)));
689:
690: /*
691: * Set PCI latency timer.
692: */
693: reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
694: if (PCI_LATTIMER(reg) < 0x10) {
695: reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
696: reg |= (0x10 << PCI_LATTIMER_SHIFT);
697: pci_conf_write(pc, tag, PCI_BHLC_REG, reg);
698: }
699: DPRINTF(("PCI latency timer 0x%x (%x)\n",
700: PCI_LATTIMER(reg), pci_conf_read(pc, tag, PCI_BHLC_REG)));
701:
702: /* Route functional interrupts to PCI. */
703: reg = pci_conf_read(pc, tag, PCI_BCR_INTR);
704: reg |= CB_BCR_INTR_IREQ_ENABLE; /* disable PCI Intr */
705: reg |= CB_BCR_WRITE_POST_ENABLE; /* enable write post */
706: reg |= CB_BCR_RESET_ENABLE; /* assert reset */
707: pci_conf_write(pc, tag, PCI_BCR_INTR, reg);
708:
709: switch (sc->sc_chipset) {
710: case CB_TI113X:
711: reg = pci_conf_read(pc, tag, PCI_CBCTRL);
712: /* This bit is shared, but may read as 0 on some chips, so set
713: it explicitly on both functions. */
714: reg |= PCI113X_CBCTRL_PCI_IRQ_ENA;
715: /* CSC intr enable */
716: reg |= PCI113X_CBCTRL_PCI_CSC;
717: /* functional intr prohibit | prohibit ISA routing */
718: reg &= ~(PCI113X_CBCTRL_PCI_INTR | PCI113X_CBCTRL_INT_MASK);
719: pci_conf_write(pc, tag, PCI_CBCTRL, reg);
720: break;
721:
722: case CB_TI12XX:
723: /*
724: * Some TI 12xx (and [14][45]xx) based pci cards
725: * sometimes have issues with the MFUNC register not
726: * being initialized due to a bad EEPROM on board.
727: * Laptops that this matters on have this register
728: * properly initialized.
729: *
730: * The TI125X parts have a different register.
731: */
732: reg = pci_conf_read(pc, tag, PCI12XX_MFUNC);
733: if (reg == 0) {
734: reg &= ~PCI12XX_MFUNC_PIN0;
735: reg |= PCI12XX_MFUNC_PIN0_INTA;
736: if ((pci_conf_read(pc, tag, PCI_SYSCTRL) &
737: PCI12XX_SYSCTRL_INTRTIE) == 0) {
738: reg &= ~PCI12XX_MFUNC_PIN1;
739: reg |= PCI12XX_MFUNC_PIN1_INTB;
740: }
741: pci_conf_write(pc, tag, PCI12XX_MFUNC, reg);
742: }
743: /* FALLTHROUGH */
744:
745: case CB_TI125X:
746: /*
747: * Disable zoom video. Some machines initialize this
748: * improperly and experience has shown that this helps
749: * prevent strange behavior.
750: */
751: pci_conf_write(pc, tag, PCI12XX_MMCTRL, 0);
752:
753: reg = pci_conf_read(pc, tag, PCI_SYSCTRL);
754: reg |= PCI12XX_SYSCTRL_VCCPROT;
755: pci_conf_write(pc, tag, PCI_SYSCTRL, reg);
756: reg = pci_conf_read(pc, tag, PCI_CBCTRL);
757: reg |= PCI12XX_CBCTRL_CSC;
758: pci_conf_write(pc, tag, PCI_CBCTRL, reg);
759: break;
760:
761: case CB_TOPIC95B:
762: reg = pci_conf_read(pc, tag, TOPIC_SOCKET_CTRL);
763: reg |= TOPIC_SOCKET_CTRL_SCR_IRQSEL;
764: pci_conf_write(pc, tag, TOPIC_SOCKET_CTRL, reg);
765:
766: reg = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL);
767: DPRINTF(("%s: topic slot ctrl reg 0x%x -> ",
768: sc->sc_dev.dv_xname, reg));
769: reg |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN |
770: TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS);
771: reg &= ~TOPIC_SLOT_CTRL_SWDETECT;
772: DPRINTF(("0x%x\n", reg));
773: pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, reg);
774: break;
775:
776: case CB_TOPIC97:
777: reg = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL);
778: DPRINTF(("%s: topic slot ctrl reg 0x%x -> ",
779: sc->sc_dev.dv_xname, reg));
780: reg |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN |
781: TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS);
782: reg &= ~TOPIC_SLOT_CTRL_SWDETECT;
783: reg |= TOPIC97_SLOT_CTRL_PCIINT;
784: reg &= ~(TOPIC97_SLOT_CTRL_STSIRQP | TOPIC97_SLOT_CTRL_IRQP);
785: DPRINTF(("0x%x\n", reg));
786: pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, reg);
787:
788: /* make sure to assert LV card support bits */
789: bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh,
790: 0x800 + 0x3e, bus_space_read_1(sc->sc_base_memt,
791: sc->sc_base_memh, 0x800 + 0x3e) | 0x03);
792:
793: /* Power on the controller if the BIOS didn't */
794: reg = pci_conf_read(pc, tag, TOPIC100_PMCSR);
795: if ((reg & TOPIC100_PMCSR_MASK) != TOPIC100_PMCSR_D0)
796: pci_conf_write(pc, tag, TOPIC100_PMCSR,
797: (reg & ~TOPIC100_PMCSR_MASK) | TOPIC100_PMCSR_D0);
798: break;
799:
800: case CB_OLDO2MICRO:
801: /*
802: * older bridges have problems with both read prefetch and
803: * write bursting depending on the combination of the chipset,
804: * bridge and the cardbus card. so disable them to be on the
805: * safe side. One example is O2Micro 6812 with Atheros AR5012
806: * chipsets
807: */
808: DPRINTF(("%s: old O2Micro bridge found\n",
809: sc->sc_dev.dv_xname, reg));
810: reg = pci_conf_read(pc, tag, O2MICRO_RESERVED1);
811: pci_conf_write(pc, tag, O2MICRO_RESERVED1, reg &
812: ~(O2MICRO_RES_READ_PREFETCH | O2MICRO_RES_WRITE_BURST));
813: reg = pci_conf_read(pc, tag, O2MICRO_RESERVED2);
814: pci_conf_write(pc, tag, O2MICRO_RESERVED2, reg &
815: ~(O2MICRO_RES_READ_PREFETCH | O2MICRO_RES_WRITE_BURST));
816: break;
817: }
818:
819: /* Close all memory and I/O windows. */
820: pci_conf_write(pc, tag, PCI_CB_MEMBASE0, 0xffffffff);
821: pci_conf_write(pc, tag, PCI_CB_MEMLIMIT0, 0);
822: pci_conf_write(pc, tag, PCI_CB_MEMBASE1, 0xffffffff);
823: pci_conf_write(pc, tag, PCI_CB_MEMLIMIT1, 0);
824: pci_conf_write(pc, tag, PCI_CB_IOBASE0, 0xffffffff);
825: pci_conf_write(pc, tag, PCI_CB_IOLIMIT0, 0);
826: pci_conf_write(pc, tag, PCI_CB_IOBASE1, 0xffffffff);
827: pci_conf_write(pc, tag, PCI_CB_IOLIMIT1, 0);
828:
829: /* reset 16-bit pcmcia bus */
830: bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh,
831: 0x800 + PCIC_INTR,
832: bus_space_read_1(sc->sc_base_memt, sc->sc_base_memh,
833: 0x800 + PCIC_INTR) & ~PCIC_INTR_RESET);
834:
835: /* turn off power */
836: pccbb_power((cardbus_chipset_tag_t)sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
837: }
838:
839:
840:
841:
842: /*
843: * void pccbb_pcmcia_attach_setup(struct pccbb_softc *sc,
844: * struct pcmciabus_attach_args *paa)
845: *
846: * This function attaches 16-bit PCcard bus.
847: */
848: void
849: pccbb_pcmcia_attach_setup(sc, paa)
850: struct pccbb_softc *sc;
851: struct pcmciabus_attach_args *paa;
852: {
853: struct pcic_handle *ph = &sc->sc_pcmcia_h;
854: rbus_tag_t rb;
855:
856: /* initialize pcmcia part in pccbb_softc */
857: ph->ph_parent = (struct device *)sc;
858: ph->sock = sc->sc_function;
859: ph->flags = 0;
860: ph->shutdown = 0;
861: ph->ih_irq = sc->sc_intrline;
862: ph->ph_bus_t = sc->sc_base_memt;
863: ph->ph_bus_h = sc->sc_base_memh;
864: ph->ph_read = pccbb_pcmcia_read;
865: ph->ph_write = pccbb_pcmcia_write;
866: sc->sc_pct = &pccbb_pcmcia_funcs;
867:
868: /*
869: * We need to do a few things here:
870: * 1) Disable routing of CSC and functional interrupts to ISA IRQs by
871: * setting the IRQ numbers to 0.
872: * 2) Set bit 4 of PCIC_INTR, which is needed on some chips to enable
873: * routing of CSC interrupts (e.g. card removal) to PCI while in
874: * PCMCIA mode. We just leave this set all the time.
875: * 3) Enable card insertion/removal interrupts in case the chip also
876: * needs that while in PCMCIA mode.
877: * 4) Clear any pending CSC interrupt.
878: */
879: Pcic_write(ph, PCIC_INTR, PCIC_INTR_ENABLE | PCIC_INTR_RESET);
880: if (sc->sc_chipset == CB_TI113X) {
881: Pcic_write(ph, PCIC_CSC_INTR, 0);
882: } else {
883: Pcic_write(ph, PCIC_CSC_INTR, PCIC_CSC_INTR_CD_ENABLE);
884: Pcic_read(ph, PCIC_CSC);
885: }
886:
887: /* initialize pcmcia bus attachment */
888: paa->paa_busname = "pcmcia";
889: paa->pct = sc->sc_pct;
890: paa->pch = ph;
891: paa->iobase = 0; /* I don't use them */
892: paa->iosize = 0;
893: rb = ((struct pccbb_softc *)(ph->ph_parent))->sc_rbus_iot;
894: paa->iobase = rb->rb_start + rb->rb_offset;
895: paa->iosize = rb->rb_end - rb->rb_start;
896:
897: return;
898: }
899:
900: #if 0
901: void
902: pccbb_pcmcia_attach_card(ph)
903: struct pcic_handle *ph;
904: {
905: if (ph->flags & PCIC_FLAG_CARDP) {
906: panic("pccbb_pcmcia_attach_card: already attached");
907: }
908:
909: /* call the MI attach function */
910: pcmcia_card_attach(ph->pcmcia);
911:
912: ph->flags |= PCIC_FLAG_CARDP;
913: }
914:
915: void
916: pccbb_pcmcia_detach_card(ph, flags)
917: struct pcic_handle *ph;
918: int flags;
919: {
920: if (!(ph->flags & PCIC_FLAG_CARDP)) {
921: panic("pccbb_pcmcia_detach_card: already detached");
922: }
923:
924: ph->flags &= ~PCIC_FLAG_CARDP;
925:
926: /* call the MI detach function */
927: pcmcia_card_detach(ph->pcmcia, flags);
928: }
929: #endif
930:
931: /*
932: * int pccbbintr(arg)
933: * void *arg;
934: * This routine handles the interrupt from Yenta PCI-CardBus bridge
935: * itself.
936: */
937: int
938: pccbbintr(arg)
939: void *arg;
940: {
941: struct pccbb_softc *sc = (struct pccbb_softc *)arg;
942: u_int32_t sockevent, sockstate;
943: bus_space_tag_t memt = sc->sc_base_memt;
944: bus_space_handle_t memh = sc->sc_base_memh;
945: struct pcic_handle *ph = &sc->sc_pcmcia_h;
946:
947: if (!sc->sc_ints_on)
948: return 0;
949:
950: sockevent = bus_space_read_4(memt, memh, CB_SOCKET_EVENT);
951: bus_space_write_4(memt, memh, CB_SOCKET_EVENT, sockevent);
952: Pcic_read(ph, PCIC_CSC);
953:
954: if (sockevent == 0) {
955: /* This intr is not for me: it may be for my child devices. */
956: if (sc->sc_pil_intr_enable) {
957: return pccbbintr_function(sc);
958: } else {
959: return 0;
960: }
961: }
962:
963: if (sockevent & CB_SOCKET_EVENT_CD) {
964: sockstate = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
965: if (CB_SOCKET_STAT_CD == (sockstate & CB_SOCKET_STAT_CD)) {
966: /* A card should be removed. */
967: if (sc->sc_flags & CBB_CARDEXIST) {
968: DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname,
969: sockevent));
970: DPRINTF((" card removed, 0x%08x\n", sockstate));
971: sc->sc_flags &= ~CBB_CARDEXIST;
972: if (sc->sc_csc->sc_status &
973: CARDSLOT_STATUS_CARD_16) {
974: #if 0
975: struct pcic_handle *ph =
976: &sc->sc_pcmcia_h;
977:
978: pcmcia_card_deactivate(ph->pcmcia);
979: pccbb_pcmcia_socket_disable(ph);
980: pccbb_pcmcia_detach_card(ph,
981: DETACH_FORCE);
982: #endif
983: cardslot_event_throw(sc->sc_csc,
984: CARDSLOT_EVENT_REMOVAL_16);
985: } else if (sc->sc_csc->sc_status &
986: CARDSLOT_STATUS_CARD_CB) {
987: /* Cardbus intr removed */
988: cardslot_event_throw(sc->sc_csc,
989: CARDSLOT_EVENT_REMOVAL_CB);
990: }
991: }
992: } else if (0x00 == (sockstate & CB_SOCKET_STAT_CD) &&
993: /*
994: * The pccbbintr may called from powerdown hook when
995: * the system resumed, to detect the card
996: * insertion/removal during suspension.
997: */
998: (sc->sc_flags & CBB_CARDEXIST) == 0) {
999: if (sc->sc_flags & CBB_INSERTING) {
1000: timeout_del(&sc->sc_ins_tmo);
1001: }
1002: timeout_add(&sc->sc_ins_tmo, hz / 10);
1003: sc->sc_flags |= CBB_INSERTING;
1004: }
1005: }
1006:
1007: return (1);
1008: }
1009:
1010: /*
1011: * int pccbbintr_function(struct pccbb_softc *sc)
1012: *
1013: * This function calls each interrupt handler registered at the
1014: * bridge. The interrupt handlers are called in registered order.
1015: */
1016: int
1017: pccbbintr_function(sc)
1018: struct pccbb_softc *sc;
1019: {
1020: int retval = 0, val;
1021: struct pccbb_intrhand_list *pil;
1022: int s, splchanged;
1023:
1024: for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
1025: /*
1026: * XXX priority change. gross. I use if-else
1027: * sentense instead of switch-case sentense because of
1028: * avoiding duplicate case value error. More than one
1029: * IPL_XXX use same value. It depends on
1030: * implementation.
1031: */
1032: splchanged = 1;
1033: #if 0
1034: if (pil->pil_level == IPL_SERIAL) {
1035: s = splserial();
1036: } else if (pil->pil_level == IPL_HIGH) {
1037: #endif
1038: if (pil->pil_level == IPL_HIGH) {
1039: s = splhigh();
1040: } else if (pil->pil_level == IPL_CLOCK) {
1041: s = splclock();
1042: } else if (pil->pil_level == IPL_AUDIO) {
1043: s = splaudio();
1044: } else if (pil->pil_level == IPL_VM) {
1045: s = splvm();
1046: } else if (pil->pil_level == IPL_TTY) {
1047: s = spltty();
1048: #if 0
1049: } else if (pil->pil_level == IPL_SOFTSERIAL) {
1050: s = splsoftserial();
1051: #endif
1052: } else if (pil->pil_level == IPL_NET) {
1053: s = splnet();
1054: } else {
1055: splchanged = 0;
1056: /* XXX: ih lower than IPL_BIO runs w/ IPL_BIO. */
1057: }
1058:
1059: val = (*pil->pil_func)(pil->pil_arg);
1060: if (val != 0)
1061: pil->pil_count.ec_count++;
1062:
1063: if (splchanged != 0) {
1064: splx(s);
1065: }
1066:
1067: retval = retval == 1 ? 1 :
1068: retval == 0 ? val : val != 0 ? val : retval;
1069: }
1070:
1071: return retval;
1072: }
1073:
1074: void
1075: pci113x_insert(arg)
1076: void *arg;
1077: {
1078: struct pccbb_softc *sc = (struct pccbb_softc *)arg;
1079: u_int32_t sockevent, sockstate;
1080:
1081: sockevent = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
1082: CB_SOCKET_EVENT);
1083: sockstate = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
1084: CB_SOCKET_STAT);
1085:
1086: if (0 == (sockstate & CB_SOCKET_STAT_CD)) { /* card exist */
1087: DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname, sockevent));
1088: DPRINTF((" card inserted, 0x%08x\n", sockstate));
1089: sc->sc_flags |= CBB_CARDEXIST;
1090: /* call pccard interrupt handler here */
1091: if (sockstate & CB_SOCKET_STAT_16BIT) {
1092: /* 16-bit card found */
1093: /* pccbb_pcmcia_attach_card(&sc->sc_pcmcia_h); */
1094: cardslot_event_throw(sc->sc_csc,
1095: CARDSLOT_EVENT_INSERTION_16);
1096: } else if (sockstate & CB_SOCKET_STAT_CB) {
1097: /* cardbus card found */
1098: /* cardbus_attach_card(sc->sc_csc); */
1099: cardslot_event_throw(sc->sc_csc,
1100: CARDSLOT_EVENT_INSERTION_CB);
1101: } else {
1102: /* who are you? */
1103: }
1104: } else {
1105: timeout_add(&sc->sc_ins_tmo, hz / 10);
1106: }
1107: }
1108:
1109: #define PCCBB_PCMCIA_OFFSET 0x800
1110: u_int8_t
1111: pccbb_pcmcia_read(ph, reg)
1112: struct pcic_handle *ph;
1113: int reg;
1114: {
1115: bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h,
1116: PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_READ);
1117:
1118: return bus_space_read_1(ph->ph_bus_t, ph->ph_bus_h,
1119: PCCBB_PCMCIA_OFFSET + reg);
1120: }
1121:
1122: void
1123: pccbb_pcmcia_write(ph, reg, val)
1124: struct pcic_handle *ph;
1125: int reg;
1126: u_int8_t val;
1127: {
1128: bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h,
1129: PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_WRITE);
1130:
1131: bus_space_write_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg,
1132: val);
1133: }
1134:
1135: /*
1136: * int pccbb_ctrl(cardbus_chipset_tag_t, int)
1137: */
1138: int
1139: pccbb_ctrl(ct, command)
1140: cardbus_chipset_tag_t ct;
1141: int command;
1142: {
1143: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
1144:
1145: switch (command) {
1146: case CARDBUS_CD:
1147: if (2 == pccbb_detect_card(sc)) {
1148: int retval = 0;
1149: int status = cb_detect_voltage(sc);
1150: if (PCCARD_VCC_5V & status) {
1151: retval |= CARDBUS_5V_CARD;
1152: }
1153: if (PCCARD_VCC_3V & status) {
1154: retval |= CARDBUS_3V_CARD;
1155: }
1156: if (PCCARD_VCC_XV & status) {
1157: retval |= CARDBUS_XV_CARD;
1158: }
1159: if (PCCARD_VCC_YV & status) {
1160: retval |= CARDBUS_YV_CARD;
1161: }
1162: return retval;
1163: } else {
1164: return 0;
1165: }
1166: break;
1167: case CARDBUS_RESET:
1168: return cb_reset(sc);
1169: break;
1170: case CARDBUS_IO_ENABLE: /* fallthrough */
1171: case CARDBUS_IO_DISABLE: /* fallthrough */
1172: case CARDBUS_MEM_ENABLE: /* fallthrough */
1173: case CARDBUS_MEM_DISABLE: /* fallthrough */
1174: case CARDBUS_BM_ENABLE: /* fallthrough */
1175: case CARDBUS_BM_DISABLE: /* fallthrough */
1176: return pccbb_cardenable(sc, command);
1177: break;
1178: }
1179:
1180: return 0;
1181: }
1182:
1183: /*
1184: * int pccbb_power(cardbus_chipset_tag_t, int)
1185: * This function returns true when it succeeds and returns false when
1186: * it fails.
1187: */
1188: int
1189: pccbb_power(ct, command)
1190: cardbus_chipset_tag_t ct;
1191: int command;
1192: {
1193: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
1194:
1195: u_int32_t status, sock_ctrl;
1196: bus_space_tag_t memt = sc->sc_base_memt;
1197: bus_space_handle_t memh = sc->sc_base_memh;
1198:
1199: DPRINTF(("pccbb_power: %s and %s [%x]\n",
1200: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" :
1201: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" :
1202: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" :
1203: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" :
1204: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" :
1205: (command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" :
1206: "UNKNOWN",
1207: (command & CARDBUS_VPPMASK) == CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" :
1208: (command & CARDBUS_VPPMASK) == CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" :
1209: (command & CARDBUS_VPPMASK) == CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" :
1210: (command & CARDBUS_VPPMASK) == CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" :
1211: "UNKNOWN", command));
1212:
1213: status = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
1214: sock_ctrl = bus_space_read_4(memt, memh, CB_SOCKET_CTRL);
1215:
1216: switch (command & CARDBUS_VCCMASK) {
1217: case CARDBUS_VCC_UC:
1218: break;
1219: case CARDBUS_VCC_5V:
1220: if (CB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */
1221: sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
1222: sock_ctrl |= CB_SOCKET_CTRL_VCC_5V;
1223: } else {
1224: printf("%s: BAD voltage request: no 5 V card\n",
1225: sc->sc_dev.dv_xname);
1226: }
1227: break;
1228: case CARDBUS_VCC_3V:
1229: if (CB_SOCKET_STAT_3VCARD & status) {
1230: sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
1231: sock_ctrl |= CB_SOCKET_CTRL_VCC_3V;
1232: } else {
1233: printf("%s: BAD voltage request: no 3.3 V card\n",
1234: sc->sc_dev.dv_xname);
1235: }
1236: break;
1237: case CARDBUS_VCC_0V:
1238: sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
1239: break;
1240: default:
1241: return 0; /* power NEVER changed */
1242: break;
1243: }
1244:
1245: switch (command & CARDBUS_VPPMASK) {
1246: case CARDBUS_VPP_UC:
1247: break;
1248: case CARDBUS_VPP_0V:
1249: sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
1250: break;
1251: case CARDBUS_VPP_VCC:
1252: sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
1253: sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
1254: break;
1255: case CARDBUS_VPP_12V:
1256: sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
1257: sock_ctrl |= CB_SOCKET_CTRL_VPP_12V;
1258: break;
1259: }
1260:
1261: #if 0
1262: DPRINTF(("sock_ctrl: %x\n", sock_ctrl));
1263: #endif
1264: bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl);
1265: status = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
1266:
1267: if (status & CB_SOCKET_STAT_BADVCC) { /* bad Vcc request */
1268: printf
1269: ("%s: bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n",
1270: sc->sc_dev.dv_xname, sock_ctrl, status);
1271: DPRINTF(("pccbb_power: %s and %s [%x]\n",
1272: (command & CARDBUS_VCCMASK) ==
1273: CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" : (command &
1274: CARDBUS_VCCMASK) ==
1275: CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" : (command &
1276: CARDBUS_VCCMASK) ==
1277: CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" : (command &
1278: CARDBUS_VCCMASK) ==
1279: CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" : (command &
1280: CARDBUS_VCCMASK) ==
1281: CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" : (command &
1282: CARDBUS_VCCMASK) ==
1283: CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" : "UNKNOWN",
1284: (command & CARDBUS_VPPMASK) ==
1285: CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" : (command &
1286: CARDBUS_VPPMASK) ==
1287: CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" : (command &
1288: CARDBUS_VPPMASK) ==
1289: CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" : (command &
1290: CARDBUS_VPPMASK) ==
1291: CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" : "UNKNOWN", command));
1292: #if 0
1293: if (command == (CARDBUS_VCC_0V | CARDBUS_VPP_0V)) {
1294: u_int32_t force =
1295: bus_space_read_4(memt, memh, CB_SOCKET_FORCE);
1296: /* Reset Bad Vcc request */
1297: force &= ~CB_SOCKET_FORCE_BADVCC;
1298: bus_space_write_4(memt, memh, CB_SOCKET_FORCE, force);
1299: printf("new status 0x%x\n", bus_space_read_4(memt, memh,
1300: CB_SOCKET_STAT));
1301: return 1;
1302: }
1303: #endif
1304: return 0;
1305: }
1306:
1307: /*
1308: * XXX delay 300 ms: though the standard defines that the Vcc set-up
1309: * time is 20 ms, some PC-Card bridge requires longer duration.
1310: */
1311: delay(300 * 1000);
1312:
1313: return 1; /* power changed correctly */
1314: }
1315:
1316: #if defined CB_PCMCIA_POLL
1317: struct cb_poll_str {
1318: void *arg;
1319: int (*func)(void *);
1320: int level;
1321: pccard_chipset_tag_t ct;
1322: int count;
1323: };
1324:
1325: static struct cb_poll_str cb_poll[10];
1326: static int cb_poll_n = 0;
1327: static struct timeout cb_poll_timeout;
1328:
1329: void cb_pcmcia_poll(void *arg);
1330:
1331: void
1332: cb_pcmcia_poll(arg)
1333: void *arg;
1334: {
1335: struct cb_poll_str *poll = arg;
1336: struct cbb_pcmcia_softc *psc = (void *)poll->ct->v;
1337: struct pccbb_softc *sc = psc->cpc_parent;
1338: int s;
1339: u_int32_t spsr; /* socket present-state reg */
1340:
1341: timeout_set(&cb_poll_timeout, cb_pcmcia_poll, arg);
1342: timeout_add(&cb_poll_timeout, hz / 10);
1343: switch (poll->level) {
1344: case IPL_NET:
1345: s = splnet();
1346: break;
1347: case IPL_BIO:
1348: s = splbio();
1349: break;
1350: case IPL_TTY: /* fallthrough */
1351: default:
1352: s = spltty();
1353: break;
1354: }
1355:
1356: spsr =
1357: bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
1358: CB_SOCKET_STAT);
1359:
1360: #if defined CB_PCMCIA_POLL_ONLY && defined LEVEL2
1361: if (!(spsr & 0x40)) { /* CINT low */
1362: #else
1363: if (1) {
1364: #endif
1365: if ((*poll->func) (poll->arg) == 1) {
1366: ++poll->count;
1367: printf("intr: reported from poller, 0x%x\n", spsr);
1368: #if defined LEVEL2
1369: } else {
1370: printf("intr: miss! 0x%x\n", spsr);
1371: #endif
1372: }
1373: }
1374: splx(s);
1375: }
1376: #endif /* defined CB_PCMCIA_POLL */
1377:
1378: /*
1379: * int pccbb_detect_card(struct pccbb_softc *sc)
1380: * return value: 0 if no card exists.
1381: * 1 if 16-bit card exists.
1382: * 2 if cardbus card exists.
1383: */
1384: int
1385: pccbb_detect_card(sc)
1386: struct pccbb_softc *sc;
1387: {
1388: bus_space_handle_t base_memh = sc->sc_base_memh;
1389: bus_space_tag_t base_memt = sc->sc_base_memt;
1390: u_int32_t sockstat =
1391: bus_space_read_4(base_memt, base_memh, CB_SOCKET_STAT);
1392: int retval = 0;
1393:
1394: /*
1395: * The SCM Microsystems TI1225-based PCI-CardBus dock card that
1396: * ships with some Lucent WaveLAN cards has only one physical slot
1397: * but OpenBSD probes two. The phantom card in the second slot can
1398: * be ignored by punting on unsupported voltages.
1399: */
1400: if (sockstat & CB_SOCKET_STAT_XVCARD)
1401: return 0;
1402:
1403: /* CD1 and CD2 asserted */
1404: if (0x00 == (sockstat & CB_SOCKET_STAT_CD)) {
1405: /* card must be present */
1406: if (!(CB_SOCKET_STAT_NOTCARD & sockstat)) {
1407: /* NOTACARD DEASSERTED */
1408: if (CB_SOCKET_STAT_CB & sockstat) {
1409: /* CardBus mode */
1410: retval = 2;
1411: } else if (CB_SOCKET_STAT_16BIT & sockstat) {
1412: /* 16-bit mode */
1413: retval = 1;
1414: }
1415: }
1416: }
1417: return retval;
1418: }
1419:
1420: /*
1421: * int cb_reset(struct pccbb_softc *sc)
1422: * This function resets CardBus card.
1423: */
1424: int
1425: cb_reset(sc)
1426: struct pccbb_softc *sc;
1427: {
1428: /*
1429: * Reset Assert at least 20 ms
1430: * Some machines request longer duration.
1431: */
1432: int reset_duration =
1433: (sc->sc_chipset == CB_RX5C47X ? 400 * 1000 : 40 * 1000);
1434: u_int32_t bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
1435:
1436: /* Reset bit Assert (bit 6 at 0x3E) */
1437: bcr |= CB_BCR_RESET_ENABLE;
1438: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr);
1439: delay(reset_duration);
1440:
1441: if (CBB_CARDEXIST & sc->sc_flags) { /* A card exists. Reset it! */
1442: /* Reset bit Deassert (bit 6 at 0x3E) */
1443: bcr &= ~CB_BCR_RESET_ENABLE;
1444: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr);
1445: delay(reset_duration);
1446: }
1447: /* No card found on the slot. Keep Reset. */
1448: return 1;
1449: }
1450:
1451: /*
1452: * int cb_detect_voltage(struct pccbb_softc *sc)
1453: * This function detect card Voltage.
1454: */
1455: int
1456: cb_detect_voltage(sc)
1457: struct pccbb_softc *sc;
1458: {
1459: u_int32_t psr; /* socket present-state reg */
1460: bus_space_tag_t iot = sc->sc_base_memt;
1461: bus_space_handle_t ioh = sc->sc_base_memh;
1462: int vol = PCCARD_VCC_UKN; /* set 0 */
1463:
1464: psr = bus_space_read_4(iot, ioh, CB_SOCKET_STAT);
1465:
1466: if (0x400u & psr) {
1467: vol |= PCCARD_VCC_5V;
1468: }
1469: if (0x800u & psr) {
1470: vol |= PCCARD_VCC_3V;
1471: }
1472:
1473: return vol;
1474: }
1475:
1476: int
1477: cbbprint(aux, pcic)
1478: void *aux;
1479: const char *pcic;
1480: {
1481: /*
1482: struct cbslot_attach_args *cba = aux;
1483:
1484: if (cba->cba_slot >= 0) {
1485: printf(" slot %d", cba->cba_slot);
1486: }
1487: */
1488: return UNCONF;
1489: }
1490:
1491: /*
1492: * int pccbb_cardenable(struct pccbb_softc *sc, int function)
1493: * This function enables and disables the card
1494: */
1495: int
1496: pccbb_cardenable(sc, function)
1497: struct pccbb_softc *sc;
1498: int function;
1499: {
1500: u_int32_t command =
1501: pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
1502:
1503: DPRINTF(("pccbb_cardenable:"));
1504: switch (function) {
1505: case CARDBUS_IO_ENABLE:
1506: command |= PCI_COMMAND_IO_ENABLE;
1507: break;
1508: case CARDBUS_IO_DISABLE:
1509: command &= ~PCI_COMMAND_IO_ENABLE;
1510: break;
1511: case CARDBUS_MEM_ENABLE:
1512: command |= PCI_COMMAND_MEM_ENABLE;
1513: break;
1514: case CARDBUS_MEM_DISABLE:
1515: command &= ~PCI_COMMAND_MEM_ENABLE;
1516: break;
1517: case CARDBUS_BM_ENABLE:
1518: command |= PCI_COMMAND_MASTER_ENABLE;
1519: break;
1520: case CARDBUS_BM_DISABLE:
1521: command &= ~PCI_COMMAND_MASTER_ENABLE;
1522: break;
1523: default:
1524: return 0;
1525: }
1526:
1527: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command);
1528: DPRINTF((" command reg 0x%x\n", command));
1529: return 1;
1530: }
1531:
1532: /*
1533: * void *pccbb_cb_intr_establish(cardbus_chipset_tag_t ct,
1534: * int irq,
1535: * int level,
1536: * int (* func)(void *),
1537: * void *arg,
1538: * const char *name)
1539: *
1540: * This function registers an interrupt handler at the bridge, in
1541: * order not to call the interrupt handlers of child devices when
1542: * a card-deletion interrupt occurs.
1543: *
1544: * The arguments irq is not used because pccbb selects intr vector.
1545: */
1546: void *
1547: pccbb_cb_intr_establish(ct, irq, level, func, arg, name)
1548: cardbus_chipset_tag_t ct;
1549: int irq, level;
1550: int (*func)(void *);
1551: void *arg;
1552: const char *name;
1553: {
1554: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
1555:
1556: return pccbb_intr_establish(sc, irq, level, func, arg, name);
1557: }
1558:
1559:
1560: /*
1561: * void *pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct,
1562: * void *ih)
1563: *
1564: * This function removes an interrupt handler pointed by ih.
1565: */
1566: void
1567: pccbb_cb_intr_disestablish(ct, ih)
1568: cardbus_chipset_tag_t ct;
1569: void *ih;
1570: {
1571: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
1572:
1573: pccbb_intr_disestablish(sc, ih);
1574: }
1575:
1576:
1577: /*
1578: * void *pccbb_intr_establish(struct pccbb_softc *sc,
1579: * int irq,
1580: * int level,
1581: * int (* func)(void *),
1582: * void *arg,
1583: * const char *name)
1584: *
1585: * This function registers an interrupt handler at the bridge, in
1586: * order not to call the interrupt handlers of child devices when
1587: * a card-deletion interrupt occurs.
1588: *
1589: * The arguments irq and level are not used.
1590: */
1591: void *
1592: pccbb_intr_establish(sc, irq, level, func, arg, name)
1593: struct pccbb_softc *sc;
1594: int irq, level;
1595: int (*func)(void *);
1596: void *arg;
1597: const char *name;
1598: {
1599: struct pccbb_intrhand_list *pil, *newpil;
1600: pcireg_t reg;
1601:
1602: DPRINTF(("pccbb_intr_establish start. %p\n", sc->sc_pil));
1603:
1604: if (sc->sc_pil == NULL) {
1605: /* initialize bridge intr routing */
1606: reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
1607: reg &= ~CB_BCR_INTR_IREQ_ENABLE;
1608: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg);
1609:
1610: switch (sc->sc_chipset) {
1611: case CB_TI113X:
1612: reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
1613: /* functional intr enabled */
1614: reg |= PCI113X_CBCTRL_PCI_INTR;
1615: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg);
1616: break;
1617: default:
1618: break;
1619: }
1620: }
1621:
1622: /*
1623: * Allocate a room for interrupt handler structure.
1624: */
1625: newpil = (struct pccbb_intrhand_list *)
1626: malloc(sizeof(struct pccbb_intrhand_list), M_DEVBUF, M_WAITOK);
1627:
1628: newpil->pil_func = func;
1629: newpil->pil_arg = arg;
1630: newpil->pil_level = level;
1631: evcount_attach(&newpil->pil_count, name, &sc->sc_intrline,
1632: &evcount_intr);
1633: newpil->pil_next = NULL;
1634:
1635: if (sc->sc_pil == NULL) {
1636: sc->sc_pil = newpil;
1637: } else {
1638: for (pil = sc->sc_pil; pil->pil_next != NULL;
1639: pil = pil->pil_next);
1640: pil->pil_next = newpil;
1641: }
1642:
1643: DPRINTF(("pccbb_intr_establish add pil. %p\n", sc->sc_pil));
1644:
1645: return newpil;
1646: }
1647:
1648: /*
1649: * void *pccbb_intr_disestablish(struct pccbb_softc *sc,
1650: * void *ih)
1651: *
1652: * This function removes an interrupt handler pointed by ih.
1653: */
1654: void
1655: pccbb_intr_disestablish(sc, ih)
1656: struct pccbb_softc *sc;
1657: void *ih;
1658: {
1659: struct pccbb_intrhand_list *pil, **pil_prev;
1660: pcireg_t reg;
1661:
1662: DPRINTF(("pccbb_intr_disestablish start. %p\n", sc->sc_pil));
1663:
1664: pil_prev = &sc->sc_pil;
1665:
1666: for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
1667: if (pil == ih) {
1668: evcount_detach(&pil->pil_count);
1669: *pil_prev = pil->pil_next;
1670: free(pil, M_DEVBUF);
1671: DPRINTF(("pccbb_intr_disestablish frees one pil\n"));
1672: break;
1673: }
1674: pil_prev = &pil->pil_next;
1675: }
1676:
1677: if (sc->sc_pil == NULL) {
1678: /* No interrupt handlers */
1679:
1680: DPRINTF(("pccbb_intr_disestablish: no interrupt handler\n"));
1681:
1682: /* stop routing PCI intr */
1683: reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
1684: reg |= CB_BCR_INTR_IREQ_ENABLE;
1685: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg);
1686:
1687: switch (sc->sc_chipset) {
1688: case CB_TI113X:
1689: reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
1690: /* functional intr disabled */
1691: reg &= ~PCI113X_CBCTRL_PCI_INTR;
1692: pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg);
1693: break;
1694: default:
1695: break;
1696: }
1697: }
1698: }
1699:
1700: #if defined SHOW_REGS
1701: void
1702: cb_show_regs(pc, tag, memt, memh)
1703: pci_chipset_tag_t pc;
1704: pcitag_t tag;
1705: bus_space_tag_t memt;
1706: bus_space_handle_t memh;
1707: {
1708: int i;
1709: printf("PCI config regs:");
1710: for (i = 0; i < 0x50; i += 4) {
1711: if (i % 16 == 0) {
1712: printf("\n 0x%02x:", i);
1713: }
1714: printf(" %08x", pci_conf_read(pc, tag, i));
1715: }
1716: for (i = 0x80; i < 0xb0; i += 4) {
1717: if (i % 16 == 0) {
1718: printf("\n 0x%02x:", i);
1719: }
1720: printf(" %08x", pci_conf_read(pc, tag, i));
1721: }
1722:
1723: if (memh == 0) {
1724: printf("\n");
1725: return;
1726: }
1727:
1728: printf("\nsocket regs:");
1729: for (i = 0; i <= 0x10; i += 0x04) {
1730: printf(" %08x", bus_space_read_4(memt, memh, i));
1731: }
1732: printf("\nExCA regs:");
1733: for (i = 0; i < 0x08; ++i) {
1734: printf(" %02x", bus_space_read_1(memt, memh, 0x800 + i));
1735: }
1736: printf("\n");
1737: return;
1738: }
1739: #endif
1740:
1741: /*
1742: * cardbustag_t pccbb_make_tag(cardbus_chipset_tag_t cc,
1743: * int busno, int devno, int function)
1744: * This is the function to make a tag to access config space of
1745: * a CardBus Card. It works same as pci_conf_read.
1746: */
1747: cardbustag_t
1748: pccbb_make_tag(cc, busno, devno, function)
1749: cardbus_chipset_tag_t cc;
1750: int busno, devno, function;
1751: {
1752: struct pccbb_softc *sc = (struct pccbb_softc *)cc;
1753:
1754: return pci_make_tag(sc->sc_pc, busno, devno, function);
1755: }
1756:
1757: void
1758: pccbb_free_tag(cc, tag)
1759: cardbus_chipset_tag_t cc;
1760: cardbustag_t tag;
1761: {
1762: }
1763:
1764: /*
1765: * cardbusreg_t pccbb_conf_read(cardbus_chipset_tag_t cc,
1766: * cardbustag_t tag, int offset)
1767: * This is the function to read the config space of a CardBus Card.
1768: * It works same as pci_conf_read.
1769: */
1770: cardbusreg_t
1771: pccbb_conf_read(cc, tag, offset)
1772: cardbus_chipset_tag_t cc;
1773: cardbustag_t tag;
1774: int offset; /* register offset */
1775: {
1776: struct pccbb_softc *sc = (struct pccbb_softc *)cc;
1777:
1778: return pci_conf_read(sc->sc_pc, tag, offset);
1779: }
1780:
1781: /*
1782: * void pccbb_conf_write(cardbus_chipset_tag_t cc, cardbustag_t tag,
1783: * int offs, cardbusreg_t val)
1784: * This is the function to write the config space of a CardBus Card.
1785: * It works same as pci_conf_write.
1786: */
1787: void
1788: pccbb_conf_write(cc, tag, reg, val)
1789: cardbus_chipset_tag_t cc;
1790: cardbustag_t tag;
1791: int reg; /* register offset */
1792: cardbusreg_t val;
1793: {
1794: struct pccbb_softc *sc = (struct pccbb_softc *)cc;
1795:
1796: pci_conf_write(sc->sc_pc, tag, reg, val);
1797: }
1798:
1799: #if 0
1800: int
1801: pccbb_new_pcmcia_io_alloc(pcmcia_chipset_handle_t pch,
1802: bus_addr_t start, bus_size_t size, bus_size_t align, bus_addr_t mask,
1803: int speed, int flags,
1804: bus_space_handle_t * iohp)
1805: #endif
1806: /*
1807: * int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t pch,
1808: * bus_addr_t start, bus_size_t size,
1809: * bus_size_t align,
1810: * struct pcmcia_io_handle *pcihp
1811: *
1812: * This function only allocates I/O region for pccard. This function
1813: * never maps the allocated region to pccard I/O area.
1814: *
1815: * XXX: The interface of this function is not very good, I believe.
1816: */
1817: int
1818: pccbb_pcmcia_io_alloc(pch, start, size, align, pcihp)
1819: pcmcia_chipset_handle_t pch;
1820: bus_addr_t start; /* start address */
1821: bus_size_t size;
1822: bus_size_t align;
1823: struct pcmcia_io_handle *pcihp;
1824: {
1825: struct pcic_handle *ph = (struct pcic_handle *)pch;
1826: bus_addr_t ioaddr;
1827: int flags = 0;
1828: bus_space_tag_t iot;
1829: bus_space_handle_t ioh;
1830: bus_addr_t mask;
1831: rbus_tag_t rb;
1832:
1833: if (align == 0) {
1834: align = size; /* XXX: funny??? */
1835: }
1836:
1837: if (start != 0) {
1838: /* XXX: assume all card decode lower 10 bits by its hardware */
1839: mask = 0x3ff;
1840: /* enforce to use only masked address */
1841: start &= mask;
1842: } else {
1843: /*
1844: * calculate mask:
1845: * 1. get the most significant bit of size (call it msb).
1846: * 2. compare msb with the value of size.
1847: * 3. if size is larger, shift msb left once.
1848: * 4. obtain mask value to decrement msb.
1849: */
1850: bus_size_t size_tmp = size;
1851: int shifts = 0;
1852:
1853: mask = 1;
1854: while (size_tmp) {
1855: ++shifts;
1856: size_tmp >>= 1;
1857: }
1858: mask = (1 << shifts);
1859: if (mask < size) {
1860: mask <<= 1;
1861: }
1862: mask--;
1863: }
1864:
1865: /*
1866: * Allocate some arbitrary I/O space.
1867: */
1868:
1869: iot = ((struct pccbb_softc *)(ph->ph_parent))->sc_iot;
1870:
1871: rb = ((struct pccbb_softc *)(ph->ph_parent))->sc_rbus_iot;
1872: if (rbus_space_alloc(rb, start, size, mask, align, 0, &ioaddr, &ioh)) {
1873: return 1;
1874: }
1875:
1876: pcihp->iot = iot;
1877: pcihp->ioh = ioh;
1878: pcihp->addr = ioaddr;
1879: pcihp->size = size;
1880: pcihp->flags = flags;
1881:
1882: return 0;
1883: }
1884:
1885: /*
1886: * int pccbb_pcmcia_io_free(pcmcia_chipset_handle_t pch,
1887: * struct pcmcia_io_handle *pcihp)
1888: *
1889: * This function only frees I/O region for pccard.
1890: *
1891: * XXX: The interface of this function is not very good, I believe.
1892: */
1893: void
1894: pccbb_pcmcia_io_free(pch, pcihp)
1895: pcmcia_chipset_handle_t pch;
1896: struct pcmcia_io_handle *pcihp;
1897: {
1898: bus_space_handle_t ioh = pcihp->ioh;
1899: bus_size_t size = pcihp->size;
1900:
1901: struct pccbb_softc *sc =
1902: (struct pccbb_softc *)((struct pcic_handle *)pch)->ph_parent;
1903: rbus_tag_t rb = sc->sc_rbus_iot;
1904:
1905: rbus_space_free(rb, ioh, size, NULL);
1906: }
1907:
1908: /*
1909: * int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t pch, int width,
1910: * bus_addr_t offset, bus_size_t size,
1911: * struct pcmcia_io_handle *pcihp,
1912: * int *windowp)
1913: *
1914: * This function maps the allocated I/O region to pccard. This function
1915: * never allocates any I/O region for pccard I/O area. I don't
1916: * understand why the original authors of pcmciabus separated alloc and
1917: * map. I believe the two must be unite.
1918: *
1919: * XXX: no wait timing control?
1920: */
1921: int
1922: pccbb_pcmcia_io_map(pch, width, offset, size, pcihp, windowp)
1923: pcmcia_chipset_handle_t pch;
1924: int width;
1925: bus_addr_t offset;
1926: bus_size_t size;
1927: struct pcmcia_io_handle *pcihp;
1928: int *windowp;
1929: {
1930: struct pcic_handle *ph = (struct pcic_handle *)pch;
1931: bus_addr_t ioaddr = pcihp->addr + offset;
1932: int i, win;
1933: #if defined CBB_DEBUG
1934: static char *width_names[] = { "dynamic", "io8", "io16" };
1935: #endif
1936:
1937: /* Sanity check I/O handle. */
1938:
1939: if (((struct pccbb_softc *)ph->ph_parent)->sc_iot != pcihp->iot) {
1940: panic("pccbb_pcmcia_io_map iot is bogus");
1941: }
1942:
1943: /* XXX Sanity check offset/size. */
1944:
1945: win = -1;
1946: for (i = 0; i < PCIC_IO_WINS; i++) {
1947: if ((ph->ioalloc & (1 << i)) == 0) {
1948: win = i;
1949: ph->ioalloc |= (1 << i);
1950: break;
1951: }
1952: }
1953:
1954: if (win == -1) {
1955: return 1;
1956: }
1957:
1958: *windowp = win;
1959:
1960: /* XXX this is pretty gross */
1961:
1962: DPRINTF(("pccbb_pcmcia_io_map window %d %s port %lx+%lx\n",
1963: win, width_names[width], (u_long) ioaddr, (u_long) size));
1964:
1965: /* XXX wtf is this doing here? */
1966:
1967: #if 0
1968: printf(" port 0x%lx", (u_long) ioaddr);
1969: if (size > 1) {
1970: printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
1971: }
1972: #endif
1973:
1974: ph->io[win].addr = ioaddr;
1975: ph->io[win].size = size;
1976: ph->io[win].width = width;
1977:
1978: /* actual dirty register-value changing in the function below. */
1979: pccbb_pcmcia_do_io_map(ph, win);
1980:
1981: return 0;
1982: }
1983:
1984: /*
1985: * void pccbb_pcmcia_do_io_map(struct pcic_handle *h, int win)
1986: *
1987: * This function changes register-value to map I/O region for pccard.
1988: */
1989: void
1990: pccbb_pcmcia_do_io_map(ph, win)
1991: struct pcic_handle *ph;
1992: int win;
1993: {
1994: static u_int8_t pcic_iowidth[3] = {
1995: PCIC_IOCTL_IO0_IOCS16SRC_CARD,
1996: PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
1997: PCIC_IOCTL_IO0_DATASIZE_8BIT,
1998: PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
1999: PCIC_IOCTL_IO0_DATASIZE_16BIT,
2000: };
2001:
2002: #define PCIC_SIA_START_LOW 0
2003: #define PCIC_SIA_START_HIGH 1
2004: #define PCIC_SIA_STOP_LOW 2
2005: #define PCIC_SIA_STOP_HIGH 3
2006:
2007: int regbase_win = 0x8 + win * 0x04;
2008: u_int8_t ioctl, enable;
2009:
2010: DPRINTF(
2011: ("pccbb_pcmcia_do_io_map win %d addr 0x%lx size 0x%lx width %d\n",
2012: win, (long)ph->io[win].addr, (long)ph->io[win].size,
2013: ph->io[win].width * 8));
2014:
2015: Pcic_write(ph, regbase_win + PCIC_SIA_START_LOW,
2016: ph->io[win].addr & 0xff);
2017: Pcic_write(ph, regbase_win + PCIC_SIA_START_HIGH,
2018: (ph->io[win].addr >> 8) & 0xff);
2019:
2020: Pcic_write(ph, regbase_win + PCIC_SIA_STOP_LOW,
2021: (ph->io[win].addr + ph->io[win].size - 1) & 0xff);
2022: Pcic_write(ph, regbase_win + PCIC_SIA_STOP_HIGH,
2023: ((ph->io[win].addr + ph->io[win].size - 1) >> 8) & 0xff);
2024:
2025: ioctl = Pcic_read(ph, PCIC_IOCTL);
2026: enable = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
2027: switch (win) {
2028: case 0:
2029: ioctl &= ~(PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
2030: PCIC_IOCTL_IO0_IOCS16SRC_MASK |
2031: PCIC_IOCTL_IO0_DATASIZE_MASK);
2032: ioctl |= pcic_iowidth[ph->io[win].width];
2033: enable |= PCIC_ADDRWIN_ENABLE_IO0;
2034: break;
2035: case 1:
2036: ioctl &= ~(PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
2037: PCIC_IOCTL_IO1_IOCS16SRC_MASK |
2038: PCIC_IOCTL_IO1_DATASIZE_MASK);
2039: ioctl |= (pcic_iowidth[ph->io[win].width] << 4);
2040: enable |= PCIC_ADDRWIN_ENABLE_IO1;
2041: break;
2042: }
2043: Pcic_write(ph, PCIC_IOCTL, ioctl);
2044: Pcic_write(ph, PCIC_ADDRWIN_ENABLE, enable);
2045: #if defined CBB_DEBUG
2046: {
2047: u_int8_t start_low =
2048: Pcic_read(ph, regbase_win + PCIC_SIA_START_LOW);
2049: u_int8_t start_high =
2050: Pcic_read(ph, regbase_win + PCIC_SIA_START_HIGH);
2051: u_int8_t stop_low =
2052: Pcic_read(ph, regbase_win + PCIC_SIA_STOP_LOW);
2053: u_int8_t stop_high =
2054: Pcic_read(ph, regbase_win + PCIC_SIA_STOP_HIGH);
2055: printf
2056: (" start %02x %02x, stop %02x %02x, ioctl %02x enable %02x\n",
2057: start_low, start_high, stop_low, stop_high, ioctl, enable);
2058: }
2059: #endif
2060: }
2061:
2062: /*
2063: * void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t *h, int win)
2064: *
2065: * This function unmaps I/O region. No return value.
2066: */
2067: void
2068: pccbb_pcmcia_io_unmap(pch, win)
2069: pcmcia_chipset_handle_t pch;
2070: int win;
2071: {
2072: struct pcic_handle *ph = (struct pcic_handle *)pch;
2073: int reg;
2074:
2075: if (win >= PCIC_IO_WINS || win < 0) {
2076: panic("pccbb_pcmcia_io_unmap: window out of range");
2077: }
2078:
2079: reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
2080: switch (win) {
2081: case 0:
2082: reg &= ~PCIC_ADDRWIN_ENABLE_IO0;
2083: break;
2084: case 1:
2085: reg &= ~PCIC_ADDRWIN_ENABLE_IO1;
2086: break;
2087: }
2088: Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
2089:
2090: ph->ioalloc &= ~(1 << win);
2091: }
2092:
2093: /*
2094: * void pccbb_pcmcia_wait_ready(struct pcic_handle *ph)
2095: *
2096: * This function enables the card. All information is stored in
2097: * the first argument, pcmcia_chipset_handle_t.
2098: */
2099: void
2100: pccbb_pcmcia_wait_ready(ph)
2101: struct pcic_handle *ph;
2102: {
2103: int i;
2104:
2105: DPRINTF(("pccbb_pcmcia_wait_ready: status 0x%02x\n",
2106: Pcic_read(ph, PCIC_IF_STATUS)));
2107:
2108: for (i = 0; i < 10000; i++) {
2109: if (Pcic_read(ph, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) {
2110: return;
2111: }
2112: delay(500);
2113: #ifdef CBB_DEBUG
2114: if ((i > 5000) && (i % 100 == 99))
2115: printf(".");
2116: #endif
2117: }
2118:
2119: #ifdef DIAGNOSTIC
2120: printf("pcic_wait_ready: ready never happened, status = %02x\n",
2121: Pcic_read(ph, PCIC_IF_STATUS));
2122: #endif
2123: }
2124:
2125: /*
2126: * void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t pch)
2127: *
2128: * This function enables the card. All information is stored in
2129: * the first argument, pcmcia_chipset_handle_t.
2130: */
2131: void
2132: pccbb_pcmcia_socket_enable(pch)
2133: pcmcia_chipset_handle_t pch;
2134: {
2135: struct pcic_handle *ph = (struct pcic_handle *)pch;
2136: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2137: int cardtype, win;
2138: u_int8_t power, intr;
2139: pcireg_t spsr;
2140: int voltage;
2141:
2142: /* this bit is mostly stolen from pcic_attach_card */
2143:
2144: DPRINTF(("pccbb_pcmcia_socket_enable: "));
2145:
2146: /* get card Vcc info */
2147:
2148: spsr =
2149: bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
2150: CB_SOCKET_STAT);
2151: if (spsr & CB_SOCKET_STAT_5VCARD) {
2152: DPRINTF(("5V card\n"));
2153: voltage = CARDBUS_VCC_5V | CARDBUS_VPP_VCC;
2154: } else if (spsr & CB_SOCKET_STAT_3VCARD) {
2155: DPRINTF(("3V card\n"));
2156: voltage = CARDBUS_VCC_3V | CARDBUS_VPP_VCC;
2157: } else {
2158: printf("?V card, 0x%x\n", spsr); /* XXX */
2159: return;
2160: }
2161:
2162: /* disable socket i/o: negate output enable bit */
2163:
2164: power = 0;
2165: Pcic_write(ph, PCIC_PWRCTL, power);
2166:
2167: /* power down the socket to reset it, clear the card reset pin */
2168:
2169: pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
2170:
2171: /*
2172: * wait 200ms until power fails (Tpf). Then, wait 100ms since
2173: * we are changing Vcc (Toff).
2174: */
2175: /* delay(300*1000); too much */
2176:
2177: /* assert reset bit */
2178: intr = Pcic_read(ph, PCIC_INTR);
2179: intr &= ~(PCIC_INTR_RESET | PCIC_INTR_CARDTYPE_MASK);
2180: Pcic_write(ph, PCIC_INTR, intr);
2181:
2182: /* power up the socket and output enable */
2183: power = Pcic_read(ph, PCIC_PWRCTL);
2184: power |= PCIC_PWRCTL_OE;
2185: Pcic_write(ph, PCIC_PWRCTL, power);
2186: pccbb_power(sc, voltage);
2187:
2188: /*
2189: * hold RESET at least 10us.
2190: */
2191: delay(10);
2192: delay(2 * 1000); /* XXX: TI1130 requires it. */
2193: delay(20 * 1000); /* XXX: TI1130 requires it. */
2194:
2195: /* clear the reset flag */
2196:
2197: intr |= PCIC_INTR_RESET;
2198: Pcic_write(ph, PCIC_INTR, intr);
2199:
2200: /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
2201:
2202: delay(20000);
2203:
2204: /* wait for the chip to finish initializing */
2205:
2206: pccbb_pcmcia_wait_ready(ph);
2207:
2208: /* zero out the address windows */
2209:
2210: Pcic_write(ph, PCIC_ADDRWIN_ENABLE, 0);
2211:
2212: /* set the card type */
2213:
2214: cardtype = pcmcia_card_gettype(ph->pcmcia);
2215:
2216: intr |= ((cardtype == PCMCIA_IFTYPE_IO) ?
2217: PCIC_INTR_CARDTYPE_IO : PCIC_INTR_CARDTYPE_MEM);
2218: Pcic_write(ph, PCIC_INTR, intr);
2219:
2220: DPRINTF(("%s: pccbb_pcmcia_socket_enable %02x cardtype %s %02x\n",
2221: ph->ph_parent->dv_xname, ph->sock,
2222: ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), intr));
2223:
2224: /* reinstall all the memory and io mappings */
2225:
2226: for (win = 0; win < PCIC_MEM_WINS; ++win) {
2227: if (ph->memalloc & (1 << win)) {
2228: pccbb_pcmcia_do_mem_map(ph, win);
2229: }
2230: }
2231:
2232: for (win = 0; win < PCIC_IO_WINS; ++win) {
2233: if (ph->ioalloc & (1 << win)) {
2234: pccbb_pcmcia_do_io_map(ph, win);
2235: }
2236: }
2237: }
2238:
2239: /*
2240: * void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t *ph)
2241: *
2242: * This function disables the card. All information is stored in
2243: * the first argument, pcmcia_chipset_handle_t.
2244: */
2245: void
2246: pccbb_pcmcia_socket_disable(pch)
2247: pcmcia_chipset_handle_t pch;
2248: {
2249: struct pcic_handle *ph = (struct pcic_handle *)pch;
2250: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2251: u_int8_t power, intr;
2252:
2253: DPRINTF(("pccbb_pcmcia_socket_disable\n"));
2254:
2255: /* reset signal asserting... */
2256:
2257: intr = Pcic_read(ph, PCIC_INTR);
2258: intr &= ~(PCIC_INTR_CARDTYPE_MASK);
2259: Pcic_write(ph, PCIC_INTR, intr);
2260: delay(2 * 1000);
2261:
2262: /* power down the socket */
2263: power = Pcic_read(ph, PCIC_PWRCTL);
2264: power &= ~PCIC_PWRCTL_OE;
2265: Pcic_write(ph, PCIC_PWRCTL, power);
2266: pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
2267: /*
2268: * wait 300ms until power fails (Tpf).
2269: */
2270: delay(300 * 1000);
2271: }
2272:
2273: /*
2274: * int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t *ph)
2275: *
2276: * This function detects whether a card is in the slot or not.
2277: * If a card is inserted, return 1. Otherwise, return 0.
2278: */
2279: int
2280: pccbb_pcmcia_card_detect(pch)
2281: pcmcia_chipset_handle_t pch;
2282: {
2283: struct pcic_handle *ph = (struct pcic_handle *)pch;
2284: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2285:
2286: DPRINTF(("pccbb_pcmcia_card_detect\n"));
2287: return pccbb_detect_card(sc) == 1 ? 1 : 0;
2288: }
2289:
2290: #if 0
2291: int
2292: pccbb_new_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch,
2293: bus_addr_t start, bus_size_t size, bus_size_t align, int speed, int flags,
2294: bus_space_tag_t * memtp bus_space_handle_t * memhp)
2295: #endif
2296: /*
2297: * int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch,
2298: * bus_size_t size,
2299: * struct pcmcia_mem_handle *pcmhp)
2300: *
2301: * This function only allocates memory region for pccard. This
2302: * function never maps the allocated region to pccard memory area.
2303: *
2304: * XXX: Why the argument of start address is not in?
2305: */
2306: int
2307: pccbb_pcmcia_mem_alloc(pch, size, pcmhp)
2308: pcmcia_chipset_handle_t pch;
2309: bus_size_t size;
2310: struct pcmcia_mem_handle *pcmhp;
2311: {
2312: struct pcic_handle *ph = (struct pcic_handle *)pch;
2313: bus_space_handle_t memh;
2314: bus_addr_t addr;
2315: bus_size_t sizepg;
2316: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2317: rbus_tag_t rb;
2318:
2319: /* out of sc->memh, allocate as many pages as necessary */
2320:
2321: /* convert size to PCIC pages */
2322: /*
2323: * This is not enough; when the requested region is on the page
2324: * boundaries, this may calculate wrong result.
2325: */
2326: sizepg = (size + (PCIC_MEM_PAGESIZE - 1)) / PCIC_MEM_PAGESIZE;
2327: #if 0
2328: if (sizepg > PCIC_MAX_MEM_PAGES) {
2329: return 1;
2330: }
2331: #endif
2332:
2333: if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32)) {
2334: return 1;
2335: }
2336:
2337: addr = 0; /* XXX gcc -Wuninitialized */
2338:
2339: rb = sc->sc_rbus_memt;
2340: if (rbus_space_alloc(rb, 0, sizepg * PCIC_MEM_PAGESIZE,
2341: sizepg * PCIC_MEM_PAGESIZE - 1, PCIC_MEM_PAGESIZE, 0,
2342: &addr, &memh)) {
2343: return 1;
2344: }
2345:
2346: DPRINTF(
2347: ("pccbb_pcmcia_alloc_mem: addr 0x%lx size 0x%lx, realsize 0x%lx\n",
2348: addr, size, sizepg * PCIC_MEM_PAGESIZE));
2349:
2350: pcmhp->memt = sc->sc_memt;
2351: pcmhp->memh = memh;
2352: pcmhp->addr = addr;
2353: pcmhp->size = size;
2354: pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
2355: /* What is mhandle? I feel it is very dirty and it must go trush. */
2356: pcmhp->mhandle = 0;
2357: /* No offset??? Funny. */
2358:
2359: return 0;
2360: }
2361:
2362: /*
2363: * void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t pch,
2364: * struct pcmcia_mem_handle *pcmhp)
2365: *
2366: * This function release the memory space allocated by the function
2367: * pccbb_pcmcia_mem_alloc().
2368: */
2369: void
2370: pccbb_pcmcia_mem_free(pch, pcmhp)
2371: pcmcia_chipset_handle_t pch;
2372: struct pcmcia_mem_handle *pcmhp;
2373: {
2374: struct pcic_handle *ph = (struct pcic_handle *)pch;
2375: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2376:
2377: rbus_space_free(sc->sc_rbus_memt, pcmhp->memh, pcmhp->realsize, NULL);
2378: }
2379:
2380: /*
2381: * void pccbb_pcmcia_do_mem_map(struct pcic_handle *ph, int win)
2382: *
2383: * This function release the memory space allocated by the function
2384: * pccbb_pcmcia_mem_alloc().
2385: */
2386: void
2387: pccbb_pcmcia_do_mem_map(ph, win)
2388: struct pcic_handle *ph;
2389: int win;
2390: {
2391: int regbase_win;
2392: bus_addr_t phys_addr;
2393: bus_addr_t phys_end;
2394:
2395: #define PCIC_SMM_START_LOW 0
2396: #define PCIC_SMM_START_HIGH 1
2397: #define PCIC_SMM_STOP_LOW 2
2398: #define PCIC_SMM_STOP_HIGH 3
2399: #define PCIC_CMA_LOW 4
2400: #define PCIC_CMA_HIGH 5
2401:
2402: u_int8_t start_low, start_high = 0;
2403: u_int8_t stop_low, stop_high;
2404: u_int8_t off_low, off_high;
2405: u_int8_t mem_window;
2406: int reg;
2407:
2408: regbase_win = 0x10 + win * 0x08;
2409:
2410: phys_addr = ph->mem[win].addr;
2411: phys_end = phys_addr + ph->mem[win].size;
2412:
2413: DPRINTF(("pccbb_pcmcia_do_mem_map: start 0x%lx end 0x%lx off 0x%lx\n",
2414: phys_addr, phys_end, ph->mem[win].offset));
2415:
2416: #define PCIC_MEMREG_LSB_SHIFT PCIC_SYSMEM_ADDRX_SHIFT
2417: #define PCIC_MEMREG_MSB_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 8)
2418: #define PCIC_MEMREG_WIN_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 12)
2419:
2420: /* bit 19:12 */
2421: start_low = (phys_addr >> PCIC_MEMREG_LSB_SHIFT) & 0xff;
2422: /* bit 23:20 and bit 7 on */
2423: start_high = ((phys_addr >> PCIC_MEMREG_MSB_SHIFT) & 0x0f)
2424: | PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; /* bit 7 on */
2425: /* bit 31:24, for 32-bit address */
2426: mem_window = (phys_addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff;
2427:
2428: Pcic_write(ph, regbase_win + PCIC_SMM_START_LOW, start_low);
2429: Pcic_write(ph, regbase_win + PCIC_SMM_START_HIGH, start_high);
2430:
2431: if (((struct pccbb_softc *)ph->
2432: ph_parent)->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
2433: Pcic_write(ph, 0x40 + win, mem_window);
2434: }
2435:
2436: stop_low = (phys_end >> PCIC_MEMREG_LSB_SHIFT) & 0xff;
2437: stop_high = ((phys_end >> PCIC_MEMREG_MSB_SHIFT) & 0x0f)
2438: | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2; /* wait 2 cycles */
2439: /* XXX Geee, WAIT2!! Crazy!! I must rewrite this routine. */
2440:
2441: Pcic_write(ph, regbase_win + PCIC_SMM_STOP_LOW, stop_low);
2442: Pcic_write(ph, regbase_win + PCIC_SMM_STOP_HIGH, stop_high);
2443:
2444: off_low = (ph->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff;
2445: off_high = ((ph->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8))
2446: & PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK)
2447: | ((ph->mem[win].kind == PCMCIA_MEM_ATTR) ?
2448: PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0);
2449:
2450: Pcic_write(ph, regbase_win + PCIC_CMA_LOW, off_low);
2451: Pcic_write(ph, regbase_win + PCIC_CMA_HIGH, off_high);
2452:
2453: reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
2454: reg |= ((1 << win) | PCIC_ADDRWIN_ENABLE_MEMCS16);
2455: Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
2456:
2457: #if defined CBB_DEBUG
2458: {
2459: int r1, r2, r3, r4, r5, r6, r7 = 0;
2460:
2461: r1 = Pcic_read(ph, regbase_win + PCIC_SMM_START_LOW);
2462: r2 = Pcic_read(ph, regbase_win + PCIC_SMM_START_HIGH);
2463: r3 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_LOW);
2464: r4 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_HIGH);
2465: r5 = Pcic_read(ph, regbase_win + PCIC_CMA_LOW);
2466: r6 = Pcic_read(ph, regbase_win + PCIC_CMA_HIGH);
2467: if (((struct pccbb_softc *)(ph->
2468: ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
2469: r7 = Pcic_read(ph, 0x40 + win);
2470: }
2471:
2472: DPRINTF(("pccbb_pcmcia_do_mem_map window %d: %02x%02x %02x%02x "
2473: "%02x%02x", win, r1, r2, r3, r4, r5, r6));
2474: if (((struct pccbb_softc *)(ph->
2475: ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
2476: DPRINTF((" %02x", r7));
2477: }
2478: DPRINTF(("\n"));
2479: }
2480: #endif
2481: }
2482:
2483: /*
2484: * int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t pch, int kind,
2485: * bus_addr_t card_addr, bus_size_t size,
2486: * struct pcmcia_mem_handle *pcmhp,
2487: * bus_size_t *offsetp, int *windowp)
2488: *
2489: * This function maps memory space allocated by the function
2490: * pccbb_pcmcia_mem_alloc().
2491: */
2492: int
2493: pccbb_pcmcia_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
2494: pcmcia_chipset_handle_t pch;
2495: int kind;
2496: bus_addr_t card_addr;
2497: bus_size_t size;
2498: struct pcmcia_mem_handle *pcmhp;
2499: bus_size_t *offsetp;
2500: int *windowp;
2501: {
2502: struct pcic_handle *ph = (struct pcic_handle *)pch;
2503: bus_addr_t busaddr;
2504: long card_offset;
2505: int win;
2506:
2507: for (win = 0; win < PCIC_MEM_WINS; ++win) {
2508: if ((ph->memalloc & (1 << win)) == 0) {
2509: ph->memalloc |= (1 << win);
2510: break;
2511: }
2512: }
2513:
2514: if (win == PCIC_MEM_WINS) {
2515: return 1;
2516: }
2517:
2518: *windowp = win;
2519:
2520: /* XXX this is pretty gross */
2521:
2522: if (((struct pccbb_softc *)ph->ph_parent)->sc_memt != pcmhp->memt) {
2523: panic("pccbb_pcmcia_mem_map memt is bogus");
2524: }
2525:
2526: busaddr = pcmhp->addr;
2527:
2528: /*
2529: * compute the address offset to the pcmcia address space for the
2530: * pcic. this is intentionally signed. The masks and shifts below
2531: * will cause TRT to happen in the pcic registers. Deal with making
2532: * sure the address is aligned, and return the alignment offset.
2533: */
2534:
2535: *offsetp = card_addr % PCIC_MEM_PAGESIZE;
2536: card_addr -= *offsetp;
2537:
2538: DPRINTF(("pccbb_pcmcia_mem_map window %d bus %lx+%lx+%lx at card addr "
2539: "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
2540: (u_long) card_addr));
2541:
2542: /*
2543: * include the offset in the size, and decrement size by one, since
2544: * the hw wants start/stop
2545: */
2546: size += *offsetp - 1;
2547:
2548: card_offset = (((long)card_addr) - ((long)busaddr));
2549:
2550: ph->mem[win].addr = busaddr;
2551: ph->mem[win].size = size;
2552: ph->mem[win].offset = card_offset;
2553: ph->mem[win].kind = kind;
2554:
2555: pccbb_pcmcia_do_mem_map(ph, win);
2556:
2557: return 0;
2558: }
2559:
2560: /*
2561: * int pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t pch,
2562: * int window)
2563: *
2564: * This function unmaps memory space which mapped by the function
2565: * pccbb_pcmcia_mem_map().
2566: */
2567: void
2568: pccbb_pcmcia_mem_unmap(pch, window)
2569: pcmcia_chipset_handle_t pch;
2570: int window;
2571: {
2572: struct pcic_handle *ph = (struct pcic_handle *)pch;
2573: int reg;
2574:
2575: if (window >= PCIC_MEM_WINS) {
2576: panic("pccbb_pcmcia_mem_unmap: window out of range");
2577: }
2578:
2579: reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
2580: reg &= ~(1 << window);
2581: Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
2582:
2583: ph->memalloc &= ~(1 << window);
2584: }
2585:
2586: #if defined PCCBB_PCMCIA_POLL
2587: struct pccbb_poll_str {
2588: void *arg;
2589: int (*func)(void *);
2590: int level;
2591: struct pcic_handle *ph;
2592: int count;
2593: int num;
2594: };
2595:
2596: static struct pccbb_poll_str pccbb_poll[10];
2597: static int pccbb_poll_n = 0;
2598: static struct timeout pccbb_poll_timeout;
2599:
2600: void pccbb_pcmcia_poll(void *arg);
2601:
2602: void
2603: pccbb_pcmcia_poll(arg)
2604: void *arg;
2605: {
2606: struct pccbb_poll_str *poll = arg;
2607: struct pcic_handle *ph = poll->ph;
2608: struct pccbb_softc *sc = ph->sc;
2609: int s;
2610: u_int32_t spsr; /* socket present-state reg */
2611:
2612: timeout_set(&pccbb_poll_timeout, pccbb_pcmcia_poll, arg);
2613: timeout_add(&pccbb_poll_timeout, hz * 2);
2614: switch (poll->level) {
2615: case IPL_NET:
2616: s = splnet();
2617: break;
2618: case IPL_BIO:
2619: s = splbio();
2620: break;
2621: case IPL_TTY: /* fallthrough */
2622: default:
2623: s = spltty();
2624: break;
2625: }
2626:
2627: spsr =
2628: bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
2629: CB_SOCKET_STAT);
2630:
2631: #if defined PCCBB_PCMCIA_POLL_ONLY && defined LEVEL2
2632: if (!(spsr & 0x40)) /* CINT low */
2633: #else
2634: if (1)
2635: #endif
2636: {
2637: if ((*poll->func) (poll->arg) > 0) {
2638: ++poll->count;
2639: /* printf("intr: reported from poller, 0x%x\n", spsr); */
2640: #if defined LEVEL2
2641: } else {
2642: printf("intr: miss! 0x%x\n", spsr);
2643: #endif
2644: }
2645: }
2646: splx(s);
2647: }
2648: #endif /* defined CB_PCMCIA_POLL */
2649:
2650: /*
2651: * void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t pch,
2652: * struct pcmcia_function *pf,
2653: * int ipl,
2654: * int (*func)(void *),
2655: * void *arg);
2656: *
2657: * This function enables PC-Card interrupt. PCCBB uses PCI interrupt line.
2658: */
2659: void *
2660: pccbb_pcmcia_intr_establish(pch, pf, ipl, func, arg, xname)
2661: pcmcia_chipset_handle_t pch;
2662: struct pcmcia_function *pf;
2663: int ipl;
2664: int (*func)(void *);
2665: void *arg;
2666: char *xname;
2667: {
2668: struct pcic_handle *ph = (struct pcic_handle *)pch;
2669: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2670:
2671: if (!(pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) {
2672: /* what should I do? */
2673: if ((pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) {
2674: DPRINTF(
2675: ("%s does not provide edge nor pulse interrupt\n",
2676: sc->sc_dev.dv_xname));
2677: return NULL;
2678: }
2679: /*
2680: * XXX Noooooo! The interrupt flag must set properly!!
2681: * dumb pcmcia driver!!
2682: */
2683: }
2684:
2685: return pccbb_intr_establish(sc, -1, ipl, func, arg, xname);
2686: }
2687:
2688: /*
2689: * void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t pch,
2690: * void *ih)
2691: *
2692: * This function disables PC-Card interrupt.
2693: */
2694: void
2695: pccbb_pcmcia_intr_disestablish(pch, ih)
2696: pcmcia_chipset_handle_t pch;
2697: void *ih;
2698: {
2699: struct pcic_handle *ph = (struct pcic_handle *)pch;
2700: struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
2701:
2702: pccbb_intr_disestablish(sc, ih);
2703: }
2704:
2705: const char *
2706: pccbb_pcmcia_intr_string(pch, ih)
2707: pcmcia_chipset_handle_t pch;
2708: void *ih;
2709: {
2710: if (ih == NULL)
2711: return "couldn't establish interrupt";
2712: else
2713: return ""; /* card shares interrupt of the bridge */
2714: }
2715:
2716: /*
2717: * int
2718: * pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t ct, rbus_tag_t rb,
2719: * bus_addr_t addr, bus_size_t size,
2720: * bus_addr_t mask, bus_size_t align,
2721: * int flags, bus_addr_t *addrp;
2722: * bus_space_handle_t *bshp)
2723: *
2724: * This function allocates a portion of memory or io space for
2725: * clients. This function is called from CardBus card drivers.
2726: */
2727: int
2728: pccbb_rbus_cb_space_alloc(ct, rb, addr, size, mask, align, flags, addrp, bshp)
2729: cardbus_chipset_tag_t ct;
2730: rbus_tag_t rb;
2731: bus_addr_t addr;
2732: bus_size_t size;
2733: bus_addr_t mask;
2734: bus_size_t align;
2735: int flags;
2736: bus_addr_t *addrp;
2737: bus_space_handle_t *bshp;
2738: {
2739: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
2740:
2741: DPRINTF(
2742: ("pccbb_rbus_cb_space_alloc: adr %lx, size %lx, mask %lx, align %lx\n",
2743: addr, size, mask, align));
2744:
2745: if (align == 0) {
2746: align = size;
2747: }
2748:
2749: if (rb->rb_bt == sc->sc_memt) {
2750: if (align < 16) {
2751: return 1;
2752: }
2753: } else if (rb->rb_bt == sc->sc_iot) {
2754: if (align < 4) {
2755: return 1;
2756: }
2757: /* XXX: hack for avoiding ISA image */
2758: if (mask < 0x0100) {
2759: mask = 0x3ff;
2760: addr = 0x300;
2761: }
2762:
2763: } else {
2764: DPRINTF(
2765: ("pccbb_rbus_cb_space_alloc: Bus space tag %x is NOT used.\n",
2766: rb->rb_bt));
2767: return 1;
2768: /* XXX: panic here? */
2769: }
2770:
2771: if (rbus_space_alloc(rb, addr, size, mask, align, flags, addrp, bshp)) {
2772: printf("%s: <rbus> no bus space\n", sc->sc_dev.dv_xname);
2773: return 1;
2774: }
2775:
2776: pccbb_open_win(sc, rb->rb_bt, *addrp, size, *bshp, 0);
2777:
2778: return 0;
2779: }
2780:
2781: /*
2782: * int
2783: * pccbb_rbus_cb_space_free(cardbus_chipset_tag_t *ct, rbus_tag_t rb,
2784: * bus_space_handle_t *bshp, bus_size_t size);
2785: *
2786: * This function is called from CardBus card drivers.
2787: */
2788: int
2789: pccbb_rbus_cb_space_free(ct, rb, bsh, size)
2790: cardbus_chipset_tag_t ct;
2791: rbus_tag_t rb;
2792: bus_space_handle_t bsh;
2793: bus_size_t size;
2794: {
2795: struct pccbb_softc *sc = (struct pccbb_softc *)ct;
2796: bus_space_tag_t bt = rb->rb_bt;
2797:
2798: pccbb_close_win(sc, bt, bsh, size);
2799:
2800: if (bt == sc->sc_memt) {
2801: } else if (bt == sc->sc_iot) {
2802: } else {
2803: return 1;
2804: /* XXX: panic here? */
2805: }
2806:
2807: return rbus_space_free(rb, bsh, size, NULL);
2808: }
2809:
2810: int
2811: pccbb_open_win(sc, bst, addr, size, bsh, flags)
2812: struct pccbb_softc *sc;
2813: bus_space_tag_t bst;
2814: bus_addr_t addr;
2815: bus_size_t size;
2816: bus_space_handle_t bsh;
2817: int flags;
2818: {
2819: struct pccbb_win_chain_head *head;
2820: bus_addr_t align;
2821:
2822: head = &sc->sc_iowindow;
2823: align = 0x04;
2824: if (sc->sc_memt == bst) {
2825: head = &sc->sc_memwindow;
2826: align = 0x1000;
2827: DPRINTF(("using memory window, %x %x %x\n\n",
2828: sc->sc_iot, sc->sc_memt, bst));
2829: }
2830:
2831: if (pccbb_winlist_insert(head, addr, size, bsh, flags)) {
2832: printf("%s: pccbb_open_win: %s winlist insert failed\n",
2833: sc->sc_dev.dv_xname,
2834: (head == &sc->sc_memwindow) ? "mem" : "io");
2835: }
2836: pccbb_winset(align, sc, bst);
2837:
2838: return 0;
2839: }
2840:
2841: int
2842: pccbb_close_win(sc, bst, bsh, size)
2843: struct pccbb_softc *sc;
2844: bus_space_tag_t bst;
2845: bus_space_handle_t bsh;
2846: bus_size_t size;
2847: {
2848: struct pccbb_win_chain_head *head;
2849: bus_addr_t align;
2850:
2851: head = &sc->sc_iowindow;
2852: align = 0x04;
2853: if (sc->sc_memt == bst) {
2854: head = &sc->sc_memwindow;
2855: align = 0x1000;
2856: }
2857:
2858: if (pccbb_winlist_delete(head, bsh, size)) {
2859: printf("%s: pccbb_close_win: %s winlist delete failed\n",
2860: sc->sc_dev.dv_xname,
2861: (head == &sc->sc_memwindow) ? "mem" : "io");
2862: }
2863: pccbb_winset(align, sc, bst);
2864:
2865: return 0;
2866: }
2867:
2868: int
2869: pccbb_winlist_insert(head, start, size, bsh, flags)
2870: struct pccbb_win_chain_head *head;
2871: bus_addr_t start;
2872: bus_size_t size;
2873: bus_space_handle_t bsh;
2874: int flags;
2875: {
2876: struct pccbb_win_chain *chainp, *elem;
2877:
2878: if ((elem = malloc(sizeof(struct pccbb_win_chain), M_DEVBUF,
2879: M_NOWAIT)) == NULL)
2880: return (1); /* fail */
2881:
2882: elem->wc_start = start;
2883: elem->wc_end = start + (size - 1);
2884: elem->wc_handle = bsh;
2885: elem->wc_flags = flags;
2886:
2887: for (chainp = TAILQ_FIRST(head); chainp != NULL;
2888: chainp = TAILQ_NEXT(chainp, wc_list)) {
2889: if (chainp->wc_end < start)
2890: continue;
2891: TAILQ_INSERT_AFTER(head, chainp, elem, wc_list);
2892: return (0);
2893: }
2894:
2895: TAILQ_INSERT_TAIL(head, elem, wc_list);
2896: return (0);
2897: }
2898:
2899: int
2900: pccbb_winlist_delete(head, bsh, size)
2901: struct pccbb_win_chain_head *head;
2902: bus_space_handle_t bsh;
2903: bus_size_t size;
2904: {
2905: struct pccbb_win_chain *chainp;
2906:
2907: for (chainp = TAILQ_FIRST(head); chainp != NULL;
2908: chainp = TAILQ_NEXT(chainp, wc_list)) {
2909: if (memcmp(&chainp->wc_handle, &bsh, sizeof(bsh)))
2910: continue;
2911: if ((chainp->wc_end - chainp->wc_start) != (size - 1)) {
2912: printf("pccbb_winlist_delete: window 0x%lx size "
2913: "inconsistent: 0x%lx, 0x%lx\n",
2914: chainp->wc_start,
2915: chainp->wc_end - chainp->wc_start,
2916: size - 1);
2917: return 1;
2918: }
2919:
2920: TAILQ_REMOVE(head, chainp, wc_list);
2921: free(chainp, M_DEVBUF);
2922:
2923: return 0;
2924: }
2925:
2926: return 1; /* fail: no candidate to remove */
2927: }
2928:
2929: void
2930: pccbb_winset(align, sc, bst)
2931: bus_addr_t align;
2932: struct pccbb_softc *sc;
2933: bus_space_tag_t bst;
2934: {
2935: pci_chipset_tag_t pc;
2936: pcitag_t tag;
2937: bus_addr_t mask = ~(align - 1);
2938: struct {
2939: cardbusreg_t win_start;
2940: cardbusreg_t win_limit;
2941: int win_flags;
2942: } win[2];
2943: struct pccbb_win_chain *chainp;
2944: int offs;
2945:
2946: win[0].win_start = win[1].win_start = 0xffffffff;
2947: win[0].win_limit = win[1].win_limit = 0;
2948: win[0].win_flags = win[1].win_flags = 0;
2949:
2950: chainp = TAILQ_FIRST(&sc->sc_iowindow);
2951: offs = 0x2c;
2952: if (sc->sc_memt == bst) {
2953: chainp = TAILQ_FIRST(&sc->sc_memwindow);
2954: offs = 0x1c;
2955: }
2956:
2957: if (chainp != NULL) {
2958: win[0].win_start = chainp->wc_start & mask;
2959: win[0].win_limit = chainp->wc_end & mask;
2960: win[0].win_flags = chainp->wc_flags;
2961: chainp = TAILQ_NEXT(chainp, wc_list);
2962: }
2963:
2964: for (; chainp != NULL; chainp = TAILQ_NEXT(chainp, wc_list)) {
2965: if (win[1].win_start == 0xffffffff) {
2966: /* window 1 is not used */
2967: if ((win[0].win_flags == chainp->wc_flags) &&
2968: (win[0].win_limit + align >=
2969: (chainp->wc_start & mask))) {
2970: /* concatenate */
2971: win[0].win_limit = chainp->wc_end & mask;
2972: } else {
2973: /* make new window */
2974: win[1].win_start = chainp->wc_start & mask;
2975: win[1].win_limit = chainp->wc_end & mask;
2976: win[1].win_flags = chainp->wc_flags;
2977: }
2978: continue;
2979: }
2980:
2981: /* Both windows are engaged. */
2982: if (win[0].win_flags == win[1].win_flags) {
2983: /* same flags */
2984: if (win[0].win_flags == chainp->wc_flags) {
2985: if (win[1].win_start - (win[0].win_limit +
2986: align) <
2987: (chainp->wc_start & mask) -
2988: ((chainp->wc_end & mask) + align)) {
2989: /*
2990: * merge window 0 and 1, and set win1
2991: * to chainp
2992: */
2993: win[0].win_limit = win[1].win_limit;
2994: win[1].win_start =
2995: chainp->wc_start & mask;
2996: win[1].win_limit =
2997: chainp->wc_end & mask;
2998: } else {
2999: win[1].win_limit =
3000: chainp->wc_end & mask;
3001: }
3002: } else {
3003: /* different flags */
3004:
3005: /* concatenate win0 and win1 */
3006: win[0].win_limit = win[1].win_limit;
3007: /* allocate win[1] to new space */
3008: win[1].win_start = chainp->wc_start & mask;
3009: win[1].win_limit = chainp->wc_end & mask;
3010: win[1].win_flags = chainp->wc_flags;
3011: }
3012: } else {
3013: /* the flags of win[0] and win[1] is different */
3014: if (win[0].win_flags == chainp->wc_flags) {
3015: win[0].win_limit = chainp->wc_end & mask;
3016: /*
3017: * XXX this creates overlapping windows, so
3018: * what should the poor bridge do if one is
3019: * cachable, and the other is not?
3020: */
3021: printf("%s: overlapping windows\n",
3022: sc->sc_dev.dv_xname);
3023: } else {
3024: win[1].win_limit = chainp->wc_end & mask;
3025: }
3026: }
3027: }
3028:
3029: pc = sc->sc_pc;
3030: tag = sc->sc_tag;
3031: pci_conf_write(pc, tag, offs, win[0].win_start);
3032: pci_conf_write(pc, tag, offs + 4, win[0].win_limit);
3033: pci_conf_write(pc, tag, offs + 8, win[1].win_start);
3034: pci_conf_write(pc, tag, offs + 12, win[1].win_limit);
3035: DPRINTF(("--pccbb_winset: win0 [%x, %lx), win1 [%x, %lx)\n",
3036: pci_conf_read(pc, tag, offs),
3037: pci_conf_read(pc, tag, offs + 4) + align,
3038: pci_conf_read(pc, tag, offs + 8),
3039: pci_conf_read(pc, tag, offs + 12) + align));
3040:
3041: if (bst == sc->sc_memt) {
3042: pcireg_t bcr = pci_conf_read(pc, tag, PCI_BCR_INTR);
3043:
3044: bcr &= ~(CB_BCR_PREFETCH_MEMWIN0 | CB_BCR_PREFETCH_MEMWIN1);
3045: if (win[0].win_flags & PCCBB_MEM_CACHABLE)
3046: bcr |= CB_BCR_PREFETCH_MEMWIN0;
3047: if (win[1].win_flags & PCCBB_MEM_CACHABLE)
3048: bcr |= CB_BCR_PREFETCH_MEMWIN1;
3049: pci_conf_write(pc, tag, PCI_BCR_INTR, bcr);
3050: }
3051: }
3052:
3053: void
3054: pccbb_powerhook(why, arg)
3055: int why;
3056: void *arg;
3057: {
3058: struct pccbb_softc *sc = arg;
3059: u_int32_t reg;
3060: bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */
3061: bus_space_handle_t base_memh = sc->sc_base_memh;
3062:
3063: DPRINTF(("%s: power: why %d\n", sc->sc_dev.dv_xname, why));
3064:
3065: if (why == PWR_SUSPEND || why == PWR_STANDBY) {
3066: DPRINTF(("%s: power: why %d stopping intr\n",
3067: sc->sc_dev.dv_xname, why));
3068: if (sc->sc_pil_intr_enable) {
3069: (void)pccbbintr_function(sc);
3070: }
3071: sc->sc_pil_intr_enable = 0;
3072:
3073: /* ToDo: deactivate or suspend child devices */
3074:
3075: }
3076:
3077: if (why == PWR_RESUME) {
3078: if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_SOCKBASE) == 0)
3079: /* BIOS did not recover this register */
3080: pci_conf_write (sc->sc_pc, sc->sc_tag,
3081: PCI_SOCKBASE, sc->sc_sockbase);
3082: if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_BUSNUM) == 0)
3083: /* BIOS did not recover this register */
3084: pci_conf_write (sc->sc_pc, sc->sc_tag,
3085: PCI_BUSNUM, sc->sc_busnum);
3086: /* CSC Interrupt: Card detect interrupt on */
3087: reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK);
3088: /* Card detect intr is turned on. */
3089: reg |= CB_SOCKET_MASK_CD;
3090: bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg);
3091: /* reset interrupt */
3092: reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT);
3093: bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, reg);
3094:
3095: /*
3096: * check for card insertion or removal during suspend period.
3097: * XXX: the code can't cope with card swap (remove then
3098: * insert). how can we detect such situation?
3099: */
3100: (void)pccbbintr(sc);
3101:
3102: sc->sc_pil_intr_enable = 1;
3103: DPRINTF(("%s: power: RESUME enabling intr\n",
3104: sc->sc_dev.dv_xname));
3105:
3106: /* ToDo: activate or wakeup child devices */
3107: }
3108: }
CVSweb