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