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