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