i82365.c revision 1.1.2.10 1 1.1.2.1 marc #define PCICDEBUG
2 1.1.2.1 marc
3 1.1.2.1 marc #include <sys/types.h>
4 1.1.2.1 marc #include <sys/param.h>
5 1.1.2.1 marc #include <sys/systm.h>
6 1.1.2.1 marc #include <sys/device.h>
7 1.1.2.1 marc #include <sys/extent.h>
8 1.1.2.1 marc #include <sys/malloc.h>
9 1.1.2.1 marc
10 1.1.2.1 marc #include <vm/vm.h>
11 1.1.2.1 marc
12 1.1.2.1 marc #include <machine/bus.h>
13 1.1.2.1 marc #include <machine/intr.h>
14 1.1.2.1 marc
15 1.1.2.1 marc #include <dev/pcmcia/pcmciareg.h>
16 1.1.2.4 thorpej #include <dev/pcmcia/pcmciavar.h>
17 1.1.2.1 marc
18 1.1.2.1 marc #include <dev/ic/i82365reg.h>
19 1.1.2.8 marc #include <dev/ic/i82365var.h>
20 1.1.2.1 marc
21 1.1.2.1 marc #ifdef PCICDEBUG
22 1.1.2.2 thorpej int pcic_debug = 0;
23 1.1.2.2 thorpej #define DPRINTF(arg) if (pcic_debug) printf arg;
24 1.1.2.1 marc #else
25 1.1.2.1 marc #define DPRINTF(arg)
26 1.1.2.1 marc #endif
27 1.1.2.1 marc
28 1.1.2.1 marc #define PCIC_VENDOR_UNKNOWN 0
29 1.1.2.1 marc #define PCIC_VENDOR_I82365SLR0 1
30 1.1.2.1 marc #define PCIC_VENDOR_I82365SLR1 2
31 1.1.2.1 marc #define PCIC_VENDOR_CIRRUS_PD6710 3
32 1.1.2.1 marc #define PCIC_VENDOR_CIRRUS_PD672X 4
33 1.1.2.1 marc
34 1.1.2.1 marc /* Individual drivers will allocate their own memory and io regions.
35 1.1.2.1 marc Memory regions must be a multiple of 4k, aligned on a 4k boundary. */
36 1.1.2.1 marc
37 1.1.2.1 marc #define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE
38 1.1.2.1 marc
39 1.1.2.1 marc void pcic_attach_socket __P((struct pcic_handle *));
40 1.1.2.1 marc void pcic_init_socket __P((struct pcic_handle *));
41 1.1.2.1 marc
42 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
43 1.1.2.1 marc int pcic_submatch __P((struct device *, void *, void *));
44 1.1.2.1 marc #else
45 1.1.2.1 marc int pcic_submatch __P((struct device *, struct cfdata *, void *));
46 1.1.2.1 marc #endif
47 1.1.2.1 marc int pcic_print __P((void *arg, const char *pnp));
48 1.1.2.1 marc int pcic_intr_socket __P((struct pcic_handle *));
49 1.1.2.1 marc
50 1.1.2.10 marc void pcic_attach_card __P((struct pcic_handle *));
51 1.1.2.10 marc void pcic_detach_card __P((struct pcic_handle *));
52 1.1.2.10 marc
53 1.1.2.10 marc void pcic_chip_do_mem_map __P((struct pcic_handle *, int));
54 1.1.2.10 marc void pcic_chip_do_io_map __P((struct pcic_handle *, int));
55 1.1.2.1 marc
56 1.1.2.1 marc struct cfdriver pcic_cd = {
57 1.1.2.1 marc NULL, "pcic", DV_DULL
58 1.1.2.1 marc };
59 1.1.2.1 marc
60 1.1.2.1 marc int
61 1.1.2.1 marc pcic_ident_ok(ident)
62 1.1.2.1 marc int ident;
63 1.1.2.1 marc {
64 1.1.2.1 marc /* this is very empirical and heuristic */
65 1.1.2.1 marc
66 1.1.2.1 marc if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO))
67 1.1.2.1 marc return(0);
68 1.1.2.1 marc
69 1.1.2.1 marc if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
70 1.1.2.1 marc #ifdef DIAGNOSTIC
71 1.1.2.1 marc printf("pcic: does not support memory and I/O cards, ignored (ident=%0x)\n",
72 1.1.2.1 marc ident);
73 1.1.2.1 marc #endif
74 1.1.2.1 marc return(0);
75 1.1.2.1 marc }
76 1.1.2.1 marc
77 1.1.2.1 marc return(1);
78 1.1.2.1 marc }
79 1.1.2.1 marc
80 1.1.2.1 marc int
81 1.1.2.1 marc pcic_vendor(h)
82 1.1.2.1 marc struct pcic_handle *h;
83 1.1.2.1 marc {
84 1.1.2.1 marc int reg;
85 1.1.2.1 marc
86 1.1.2.8 marc /* the chip_id of the cirrus toggles between 11 and 00
87 1.1.2.8 marc after a write. weird. */
88 1.1.2.1 marc
89 1.1.2.1 marc pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
90 1.1.2.1 marc reg = pcic_read(h, -1);
91 1.1.2.1 marc
92 1.1.2.1 marc if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
93 1.1.2.1 marc PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
94 1.1.2.1 marc reg = pcic_read(h, -1);
95 1.1.2.1 marc if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
96 1.1.2.1 marc if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
97 1.1.2.1 marc return(PCIC_VENDOR_CIRRUS_PD672X);
98 1.1.2.1 marc else
99 1.1.2.1 marc return(PCIC_VENDOR_CIRRUS_PD6710);
100 1.1.2.1 marc }
101 1.1.2.1 marc }
102 1.1.2.1 marc
103 1.1.2.8 marc /* XXX how do I identify the GD6729? */
104 1.1.2.8 marc
105 1.1.2.1 marc reg = pcic_read(h, PCIC_IDENT);
106 1.1.2.1 marc
107 1.1.2.1 marc if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0)
108 1.1.2.1 marc return(PCIC_VENDOR_I82365SLR0);
109 1.1.2.1 marc else
110 1.1.2.1 marc return(PCIC_VENDOR_I82365SLR1);
111 1.1.2.1 marc
112 1.1.2.1 marc return(PCIC_VENDOR_UNKNOWN);
113 1.1.2.1 marc }
114 1.1.2.1 marc
115 1.1.2.1 marc char *
116 1.1.2.1 marc pcic_vendor_to_string(vendor)
117 1.1.2.1 marc int vendor;
118 1.1.2.1 marc {
119 1.1.2.1 marc switch (vendor) {
120 1.1.2.1 marc case PCIC_VENDOR_I82365SLR0:
121 1.1.2.1 marc return("Intel 82365SL Revision 0");
122 1.1.2.1 marc case PCIC_VENDOR_I82365SLR1:
123 1.1.2.1 marc return("Intel 82365SL Revision 1");
124 1.1.2.1 marc case PCIC_VENDOR_CIRRUS_PD6710:
125 1.1.2.1 marc return("Cirrus PD6710");
126 1.1.2.1 marc case PCIC_VENDOR_CIRRUS_PD672X:
127 1.1.2.1 marc return("Cirrus PD672X");
128 1.1.2.1 marc }
129 1.1.2.1 marc
130 1.1.2.1 marc return("Unknown controller");
131 1.1.2.1 marc }
132 1.1.2.1 marc
133 1.1.2.1 marc void
134 1.1.2.8 marc pcic_attach(sc)
135 1.1.2.8 marc struct pcic_softc *sc;
136 1.1.2.1 marc {
137 1.1.2.10 marc int vendor, count, i, reg;
138 1.1.2.1 marc
139 1.1.2.1 marc /* now check for each controller/socket */
140 1.1.2.1 marc
141 1.1.2.1 marc /* this could be done with a loop, but it would violate the
142 1.1.2.1 marc abstraction */
143 1.1.2.1 marc
144 1.1.2.1 marc count = 0;
145 1.1.2.1 marc
146 1.1.2.10 marc DPRINTF(("pcic ident regs:"));
147 1.1.2.10 marc
148 1.1.2.1 marc sc->handle[0].sc = sc;
149 1.1.2.1 marc sc->handle[0].sock = C0SA;
150 1.1.2.10 marc if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) {
151 1.1.2.1 marc sc->handle[0].flags = PCIC_FLAG_SOCKETP;
152 1.1.2.1 marc count++;
153 1.1.2.1 marc } else {
154 1.1.2.1 marc sc->handle[0].flags = 0;
155 1.1.2.1 marc }
156 1.1.2.1 marc
157 1.1.2.10 marc DPRINTF((" 0x%02x", reg));
158 1.1.2.10 marc
159 1.1.2.1 marc sc->handle[1].sc = sc;
160 1.1.2.1 marc sc->handle[1].sock = C0SB;
161 1.1.2.10 marc if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) {
162 1.1.2.1 marc sc->handle[1].flags = PCIC_FLAG_SOCKETP;
163 1.1.2.1 marc count++;
164 1.1.2.1 marc } else {
165 1.1.2.1 marc sc->handle[1].flags = 0;
166 1.1.2.1 marc }
167 1.1.2.1 marc
168 1.1.2.10 marc DPRINTF((" 0x%02x", reg));
169 1.1.2.10 marc
170 1.1.2.1 marc sc->handle[2].sc = sc;
171 1.1.2.1 marc sc->handle[2].sock = C1SA;
172 1.1.2.10 marc if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT))) {
173 1.1.2.1 marc sc->handle[2].flags = PCIC_FLAG_SOCKETP;
174 1.1.2.1 marc count++;
175 1.1.2.1 marc } else {
176 1.1.2.1 marc sc->handle[2].flags = 0;
177 1.1.2.1 marc }
178 1.1.2.1 marc
179 1.1.2.10 marc DPRINTF((" 0x%02x", reg));
180 1.1.2.10 marc
181 1.1.2.1 marc sc->handle[3].sc = sc;
182 1.1.2.1 marc sc->handle[3].sock = C1SB;
183 1.1.2.10 marc if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) {
184 1.1.2.1 marc sc->handle[3].flags = PCIC_FLAG_SOCKETP;
185 1.1.2.1 marc count++;
186 1.1.2.1 marc } else {
187 1.1.2.1 marc sc->handle[3].flags = 0;
188 1.1.2.1 marc }
189 1.1.2.1 marc
190 1.1.2.10 marc DPRINTF((" 0x%02x\n", reg));
191 1.1.2.10 marc
192 1.1.2.1 marc if (count == 0)
193 1.1.2.1 marc panic("pcic_attach: attach found no sockets");
194 1.1.2.1 marc
195 1.1.2.1 marc /* establish the interrupt */
196 1.1.2.1 marc
197 1.1.2.1 marc /* XXX block interrupts? */
198 1.1.2.1 marc
199 1.1.2.1 marc for (i=0; i<PCIC_NSLOTS; i++) {
200 1.1.2.10 marc #if 0
201 1.1.2.10 marc /* this should work, but w/o it, setting tty flags
202 1.1.2.10 marc hangs at boot time. */
203 1.1.2.10 marc if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
204 1.1.2.10 marc #endif
205 1.1.2.10 marc {
206 1.1.2.10 marc pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
207 1.1.2.10 marc pcic_read(&sc->handle[i], PCIC_CSC);
208 1.1.2.10 marc }
209 1.1.2.1 marc }
210 1.1.2.1 marc
211 1.1.2.1 marc if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) ||
212 1.1.2.1 marc (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) {
213 1.1.2.1 marc vendor = pcic_vendor(&sc->handle[0]);
214 1.1.2.1 marc
215 1.1.2.1 marc printf("%s: controller 0 (%s) has ", sc->dev.dv_xname,
216 1.1.2.1 marc pcic_vendor_to_string(vendor));
217 1.1.2.1 marc
218 1.1.2.1 marc if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) &&
219 1.1.2.1 marc (sc->handle[1].flags & PCIC_FLAG_SOCKETP))
220 1.1.2.1 marc printf("sockets A and B\n");
221 1.1.2.1 marc else if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
222 1.1.2.1 marc printf("socket A only\n");
223 1.1.2.1 marc else
224 1.1.2.1 marc printf("socket B only\n");
225 1.1.2.1 marc
226 1.1.2.8 marc if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
227 1.1.2.1 marc sc->handle[0].vendor = vendor;
228 1.1.2.8 marc if (sc->handle[1].flags & PCIC_FLAG_SOCKETP)
229 1.1.2.1 marc sc->handle[1].vendor = vendor;
230 1.1.2.1 marc }
231 1.1.2.1 marc
232 1.1.2.1 marc if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) ||
233 1.1.2.1 marc (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) {
234 1.1.2.1 marc vendor = pcic_vendor(&sc->handle[2]);
235 1.1.2.1 marc
236 1.1.2.1 marc printf("%s: controller 1 (%s) has ", sc->dev.dv_xname,
237 1.1.2.1 marc pcic_vendor_to_string(vendor));
238 1.1.2.1 marc
239 1.1.2.1 marc if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) &&
240 1.1.2.1 marc (sc->handle[3].flags & PCIC_FLAG_SOCKETP))
241 1.1.2.1 marc printf("sockets A and B\n");
242 1.1.2.1 marc else if (sc->handle[2].flags & PCIC_FLAG_SOCKETP)
243 1.1.2.1 marc printf("socket A only\n");
244 1.1.2.1 marc else
245 1.1.2.1 marc printf("socket B only\n");
246 1.1.2.1 marc
247 1.1.2.8 marc if (sc->handle[2].flags & PCIC_FLAG_SOCKETP)
248 1.1.2.1 marc sc->handle[2].vendor = vendor;
249 1.1.2.8 marc if (sc->handle[3].flags & PCIC_FLAG_SOCKETP)
250 1.1.2.1 marc sc->handle[3].vendor = vendor;
251 1.1.2.1 marc }
252 1.1.2.1 marc }
253 1.1.2.1 marc
254 1.1.2.1 marc void
255 1.1.2.8 marc pcic_attach_sockets(sc)
256 1.1.2.8 marc struct pcic_softc *sc;
257 1.1.2.8 marc {
258 1.1.2.8 marc int i;
259 1.1.2.8 marc
260 1.1.2.8 marc for (i=0; i<PCIC_NSLOTS; i++)
261 1.1.2.8 marc if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
262 1.1.2.8 marc pcic_attach_socket(&sc->handle[i]);
263 1.1.2.8 marc }
264 1.1.2.8 marc
265 1.1.2.8 marc void
266 1.1.2.1 marc pcic_attach_socket(h)
267 1.1.2.1 marc struct pcic_handle *h;
268 1.1.2.1 marc {
269 1.1.2.1 marc struct pcmciabus_attach_args paa;
270 1.1.2.1 marc
271 1.1.2.1 marc /* initialize the rest of the handle */
272 1.1.2.1 marc
273 1.1.2.1 marc h->memalloc = 0;
274 1.1.2.1 marc h->ioalloc = 0;
275 1.1.2.10 marc h->ih_irq = 0;
276 1.1.2.1 marc
277 1.1.2.1 marc /* now, config one pcmcia device per socket */
278 1.1.2.1 marc
279 1.1.2.8 marc paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
280 1.1.2.1 marc paa.pch = (pcmcia_chipset_handle_t) h;
281 1.1.2.1 marc
282 1.1.2.1 marc h->pcmcia = config_found_sm(&h->sc->dev, &paa, pcic_print, pcic_submatch);
283 1.1.2.1 marc
284 1.1.2.1 marc /* if there's actually a pcmcia device attached, initialize the slot */
285 1.1.2.1 marc
286 1.1.2.1 marc if (h->pcmcia)
287 1.1.2.1 marc pcic_init_socket(h);
288 1.1.2.1 marc }
289 1.1.2.1 marc
290 1.1.2.1 marc void
291 1.1.2.1 marc pcic_init_socket(h)
292 1.1.2.1 marc struct pcic_handle *h;
293 1.1.2.1 marc {
294 1.1.2.1 marc int reg;
295 1.1.2.1 marc
296 1.1.2.1 marc /* set up the card to interrupt on card detect */
297 1.1.2.1 marc
298 1.1.2.1 marc pcic_write(h, PCIC_CSC_INTR,
299 1.1.2.1 marc (h->sc->irq<<PCIC_CSC_INTR_IRQ_SHIFT)|
300 1.1.2.1 marc PCIC_CSC_INTR_CD_ENABLE);
301 1.1.2.1 marc pcic_write(h, PCIC_INTR, 0);
302 1.1.2.1 marc pcic_read(h, PCIC_CSC);
303 1.1.2.1 marc
304 1.1.2.1 marc /* unsleep the cirrus controller */
305 1.1.2.1 marc
306 1.1.2.1 marc if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
307 1.1.2.1 marc (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
308 1.1.2.1 marc reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
309 1.1.2.1 marc if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
310 1.1.2.1 marc DPRINTF(("%s: socket %02x was suspended\n", h->sc->dev.dv_xname,
311 1.1.2.1 marc h->sock));
312 1.1.2.1 marc reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
313 1.1.2.1 marc pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
314 1.1.2.1 marc }
315 1.1.2.1 marc }
316 1.1.2.1 marc
317 1.1.2.1 marc /* if there's a card there, then attach it. */
318 1.1.2.1 marc
319 1.1.2.1 marc reg = pcic_read(h, PCIC_IF_STATUS);
320 1.1.2.1 marc
321 1.1.2.1 marc if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
322 1.1.2.1 marc PCIC_IF_STATUS_CARDDETECT_PRESENT)
323 1.1.2.1 marc pcic_attach_card(h);
324 1.1.2.1 marc }
325 1.1.2.1 marc
326 1.1.2.1 marc int
327 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
328 1.1.2.1 marc pcic_submatch(parent, match, aux)
329 1.1.2.1 marc #else
330 1.1.2.1 marc pcic_submatch(parent, cf, aux)
331 1.1.2.1 marc #endif
332 1.1.2.1 marc struct device *parent;
333 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
334 1.1.2.1 marc void *match;
335 1.1.2.1 marc #else
336 1.1.2.1 marc struct cfdata *cf;
337 1.1.2.1 marc #endif
338 1.1.2.1 marc void *aux;
339 1.1.2.1 marc {
340 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
341 1.1.2.1 marc struct cfdata *cf = match;
342 1.1.2.1 marc #endif
343 1.1.2.1 marc
344 1.1.2.1 marc struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) aux;
345 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) paa->pch;
346 1.1.2.1 marc
347 1.1.2.1 marc switch (h->sock) {
348 1.1.2.1 marc case C0SA:
349 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
350 1.1.2.1 marc return 0;
351 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 0)
352 1.1.2.1 marc return 0;
353 1.1.2.1 marc
354 1.1.2.1 marc break;
355 1.1.2.1 marc case C0SB:
356 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
357 1.1.2.1 marc return 0;
358 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 1)
359 1.1.2.1 marc return 0;
360 1.1.2.1 marc
361 1.1.2.1 marc break;
362 1.1.2.1 marc case C1SA:
363 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 1)
364 1.1.2.1 marc return 0;
365 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 0)
366 1.1.2.1 marc return 0;
367 1.1.2.1 marc
368 1.1.2.1 marc break;
369 1.1.2.1 marc case C1SB:
370 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 1)
371 1.1.2.1 marc return 0;
372 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 1)
373 1.1.2.1 marc return 0;
374 1.1.2.1 marc
375 1.1.2.1 marc break;
376 1.1.2.1 marc default:
377 1.1.2.1 marc panic("unknown pcic socket");
378 1.1.2.1 marc }
379 1.1.2.1 marc
380 1.1.2.1 marc return ((*cf->cf_attach->ca_match)(parent, cf, aux));
381 1.1.2.1 marc }
382 1.1.2.1 marc
383 1.1.2.1 marc int
384 1.1.2.1 marc pcic_print(arg, pnp)
385 1.1.2.1 marc void *arg;
386 1.1.2.1 marc const char *pnp;
387 1.1.2.1 marc {
388 1.1.2.1 marc struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) arg;
389 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) paa->pch;
390 1.1.2.1 marc
391 1.1.2.1 marc if (pnp)
392 1.1.2.1 marc printf("pcmcia at %s", pnp);
393 1.1.2.1 marc
394 1.1.2.1 marc switch (h->sock) {
395 1.1.2.1 marc case C0SA:
396 1.1.2.1 marc printf(" controller 0 socket 0");
397 1.1.2.1 marc break;
398 1.1.2.1 marc case C0SB:
399 1.1.2.1 marc printf(" controller 0 socket 1");
400 1.1.2.1 marc break;
401 1.1.2.1 marc case C1SA:
402 1.1.2.1 marc printf(" controller 1 socket 0");
403 1.1.2.1 marc break;
404 1.1.2.1 marc case C1SB:
405 1.1.2.1 marc printf(" controller 1 socket 1");
406 1.1.2.1 marc break;
407 1.1.2.1 marc default:
408 1.1.2.1 marc panic("unknown pcic socket");
409 1.1.2.1 marc }
410 1.1.2.1 marc
411 1.1.2.1 marc return(UNCONF);
412 1.1.2.1 marc }
413 1.1.2.1 marc
414 1.1.2.1 marc int
415 1.1.2.1 marc pcic_intr(arg)
416 1.1.2.1 marc void *arg;
417 1.1.2.1 marc {
418 1.1.2.1 marc struct pcic_softc *sc = (struct pcic_softc *) arg;
419 1.1.2.1 marc int i, ret = 0;
420 1.1.2.1 marc
421 1.1.2.1 marc DPRINTF(("%s: intr\n", sc->dev.dv_xname));
422 1.1.2.1 marc
423 1.1.2.1 marc for (i=0; i<PCIC_NSLOTS; i++)
424 1.1.2.1 marc if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
425 1.1.2.1 marc ret += pcic_intr_socket(&sc->handle[i]);
426 1.1.2.1 marc
427 1.1.2.1 marc return(ret?1:0);
428 1.1.2.1 marc }
429 1.1.2.1 marc
430 1.1.2.1 marc int
431 1.1.2.1 marc pcic_intr_socket(h)
432 1.1.2.1 marc struct pcic_handle *h;
433 1.1.2.1 marc {
434 1.1.2.1 marc int cscreg;
435 1.1.2.1 marc
436 1.1.2.1 marc cscreg = pcic_read(h, PCIC_CSC);
437 1.1.2.1 marc
438 1.1.2.1 marc cscreg &= (PCIC_CSC_GPI |
439 1.1.2.1 marc PCIC_CSC_CD |
440 1.1.2.1 marc PCIC_CSC_READY |
441 1.1.2.1 marc PCIC_CSC_BATTWARN |
442 1.1.2.1 marc PCIC_CSC_BATTDEAD);
443 1.1.2.1 marc
444 1.1.2.1 marc if (cscreg & PCIC_CSC_GPI) {
445 1.1.2.1 marc DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
446 1.1.2.1 marc }
447 1.1.2.1 marc if (cscreg & PCIC_CSC_CD) {
448 1.1.2.1 marc int statreg;
449 1.1.2.1 marc
450 1.1.2.1 marc statreg = pcic_read(h, PCIC_IF_STATUS);
451 1.1.2.1 marc
452 1.1.2.1 marc DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
453 1.1.2.1 marc statreg));
454 1.1.2.1 marc
455 1.1.2.8 marc /* XXX This should probably schedule something to happen after
456 1.1.2.8 marc the interrupt handler completes */
457 1.1.2.8 marc
458 1.1.2.1 marc if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
459 1.1.2.1 marc PCIC_IF_STATUS_CARDDETECT_PRESENT) {
460 1.1.2.1 marc if (!(h->flags & PCIC_FLAG_CARDP))
461 1.1.2.1 marc pcic_attach_card(h);
462 1.1.2.1 marc } else {
463 1.1.2.1 marc if (h->flags & PCIC_FLAG_CARDP)
464 1.1.2.1 marc pcic_detach_card(h);
465 1.1.2.1 marc }
466 1.1.2.1 marc }
467 1.1.2.1 marc if (cscreg & PCIC_CSC_READY) {
468 1.1.2.1 marc DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
469 1.1.2.1 marc /* shouldn't happen */
470 1.1.2.1 marc }
471 1.1.2.1 marc if (cscreg & PCIC_CSC_BATTWARN) {
472 1.1.2.1 marc DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
473 1.1.2.1 marc }
474 1.1.2.1 marc if (cscreg & PCIC_CSC_BATTDEAD) {
475 1.1.2.1 marc DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
476 1.1.2.1 marc }
477 1.1.2.1 marc
478 1.1.2.1 marc return(cscreg?1:0);
479 1.1.2.1 marc }
480 1.1.2.1 marc
481 1.1.2.1 marc void
482 1.1.2.1 marc pcic_attach_card(h)
483 1.1.2.1 marc struct pcic_handle *h;
484 1.1.2.1 marc {
485 1.1.2.1 marc if (h->flags & PCIC_FLAG_CARDP)
486 1.1.2.1 marc panic("pcic_attach_card: already attached");
487 1.1.2.1 marc
488 1.1.2.1 marc /* call the MI attach function */
489 1.1.2.1 marc
490 1.1.2.10 marc pcmcia_card_attach(h->pcmcia);
491 1.1.2.1 marc
492 1.1.2.1 marc h->flags |= PCIC_FLAG_CARDP;
493 1.1.2.1 marc }
494 1.1.2.1 marc
495 1.1.2.1 marc void
496 1.1.2.1 marc pcic_detach_card(h)
497 1.1.2.1 marc struct pcic_handle *h;
498 1.1.2.1 marc {
499 1.1.2.1 marc if (!(h->flags & PCIC_FLAG_CARDP))
500 1.1.2.9 jtk panic("pcic_attach_card: already detached");
501 1.1.2.1 marc
502 1.1.2.1 marc h->flags &= ~PCIC_FLAG_CARDP;
503 1.1.2.1 marc
504 1.1.2.1 marc /* call the MI attach function */
505 1.1.2.1 marc
506 1.1.2.10 marc pcmcia_card_detach(h->pcmcia);
507 1.1.2.1 marc
508 1.1.2.1 marc /* disable card detect resume and configuration reset */
509 1.1.2.1 marc
510 1.1.2.1 marc /* power down the socket */
511 1.1.2.1 marc
512 1.1.2.1 marc pcic_write(h, PCIC_PWRCTL, 0);
513 1.1.2.1 marc
514 1.1.2.1 marc /* reset the card */
515 1.1.2.1 marc
516 1.1.2.1 marc pcic_write(h, PCIC_INTR, 0);
517 1.1.2.1 marc }
518 1.1.2.1 marc
519 1.1.2.4 thorpej int pcic_chip_mem_alloc(pch, size, pcmhp)
520 1.1.2.1 marc pcmcia_chipset_handle_t pch;
521 1.1.2.1 marc bus_size_t size;
522 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
523 1.1.2.1 marc {
524 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
525 1.1.2.4 thorpej bus_space_handle_t memh;
526 1.1.2.4 thorpej bus_addr_t addr;
527 1.1.2.4 thorpej bus_size_t sizepg;
528 1.1.2.4 thorpej int i, mask, mhandle;
529 1.1.2.1 marc
530 1.1.2.1 marc /* out of sc->memh, allocate as many pages as necessary */
531 1.1.2.1 marc
532 1.1.2.4 thorpej /* convert size to PCIC pages */
533 1.1.2.4 thorpej sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
534 1.1.2.1 marc
535 1.1.2.4 thorpej mask = (1 << sizepg) - 1;
536 1.1.2.1 marc
537 1.1.2.4 thorpej addr = 0; /* XXX gcc -Wuninitialized */
538 1.1.2.4 thorpej mhandle = 0; /* XXX gcc -Wuninitialized */
539 1.1.2.8 marc
540 1.1.2.4 thorpej for (i=0; i<(PCIC_MEM_PAGES+1-sizepg); i++) {
541 1.1.2.1 marc if ((h->sc->subregionmask & (mask<<i)) == (mask<<i)) {
542 1.1.2.1 marc if (bus_space_subregion(h->sc->memt, h->sc->memh,
543 1.1.2.1 marc i*PCIC_MEM_PAGESIZE,
544 1.1.2.4 thorpej sizepg*PCIC_MEM_PAGESIZE, &memh))
545 1.1.2.1 marc return(1);
546 1.1.2.4 thorpej mhandle = mask << i;
547 1.1.2.4 thorpej addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE);
548 1.1.2.4 thorpej h->sc->subregionmask &= ~(mhandle);
549 1.1.2.1 marc break;
550 1.1.2.1 marc }
551 1.1.2.1 marc }
552 1.1.2.1 marc
553 1.1.2.1 marc if (i == (PCIC_MEM_PAGES+1-size))
554 1.1.2.1 marc return(1);
555 1.1.2.1 marc
556 1.1.2.4 thorpej DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long)addr,
557 1.1.2.4 thorpej (u_long)size));
558 1.1.2.4 thorpej
559 1.1.2.4 thorpej pcmhp->memt = h->sc->memt;
560 1.1.2.4 thorpej pcmhp->memh = memh;
561 1.1.2.4 thorpej pcmhp->addr = addr;
562 1.1.2.4 thorpej pcmhp->size = size;
563 1.1.2.4 thorpej pcmhp->mhandle = mhandle;
564 1.1.2.4 thorpej pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
565 1.1.2.1 marc
566 1.1.2.1 marc return(0);
567 1.1.2.1 marc }
568 1.1.2.1 marc
569 1.1.2.4 thorpej void pcic_chip_mem_free(pch, pcmhp)
570 1.1.2.1 marc pcmcia_chipset_handle_t pch;
571 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
572 1.1.2.1 marc {
573 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
574 1.1.2.1 marc
575 1.1.2.4 thorpej h->sc->subregionmask |= pcmhp->mhandle;
576 1.1.2.1 marc }
577 1.1.2.1 marc
578 1.1.2.1 marc static struct mem_map_index_st {
579 1.1.2.1 marc int sysmem_start_lsb;
580 1.1.2.1 marc int sysmem_start_msb;
581 1.1.2.1 marc int sysmem_stop_lsb;
582 1.1.2.1 marc int sysmem_stop_msb;
583 1.1.2.1 marc int cardmem_lsb;
584 1.1.2.1 marc int cardmem_msb;
585 1.1.2.1 marc int memenable;
586 1.1.2.1 marc } mem_map_index[] = {
587 1.1.2.1 marc {
588 1.1.2.1 marc PCIC_SYSMEM_ADDR0_START_LSB,
589 1.1.2.1 marc PCIC_SYSMEM_ADDR0_START_MSB,
590 1.1.2.1 marc PCIC_SYSMEM_ADDR0_STOP_LSB,
591 1.1.2.1 marc PCIC_SYSMEM_ADDR0_STOP_MSB,
592 1.1.2.1 marc PCIC_CARDMEM_ADDR0_LSB,
593 1.1.2.1 marc PCIC_CARDMEM_ADDR0_MSB,
594 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM0,
595 1.1.2.1 marc },
596 1.1.2.1 marc {
597 1.1.2.1 marc PCIC_SYSMEM_ADDR1_START_LSB,
598 1.1.2.1 marc PCIC_SYSMEM_ADDR1_START_MSB,
599 1.1.2.1 marc PCIC_SYSMEM_ADDR1_STOP_LSB,
600 1.1.2.1 marc PCIC_SYSMEM_ADDR1_STOP_MSB,
601 1.1.2.1 marc PCIC_CARDMEM_ADDR1_LSB,
602 1.1.2.1 marc PCIC_CARDMEM_ADDR1_MSB,
603 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM1,
604 1.1.2.1 marc },
605 1.1.2.1 marc {
606 1.1.2.1 marc PCIC_SYSMEM_ADDR2_START_LSB,
607 1.1.2.1 marc PCIC_SYSMEM_ADDR2_START_MSB,
608 1.1.2.1 marc PCIC_SYSMEM_ADDR2_STOP_LSB,
609 1.1.2.1 marc PCIC_SYSMEM_ADDR2_STOP_MSB,
610 1.1.2.1 marc PCIC_CARDMEM_ADDR2_LSB,
611 1.1.2.1 marc PCIC_CARDMEM_ADDR2_MSB,
612 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM2,
613 1.1.2.1 marc },
614 1.1.2.1 marc {
615 1.1.2.1 marc PCIC_SYSMEM_ADDR3_START_LSB,
616 1.1.2.1 marc PCIC_SYSMEM_ADDR3_START_MSB,
617 1.1.2.1 marc PCIC_SYSMEM_ADDR3_STOP_LSB,
618 1.1.2.1 marc PCIC_SYSMEM_ADDR3_STOP_MSB,
619 1.1.2.1 marc PCIC_CARDMEM_ADDR3_LSB,
620 1.1.2.1 marc PCIC_CARDMEM_ADDR3_MSB,
621 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM3,
622 1.1.2.1 marc },
623 1.1.2.1 marc {
624 1.1.2.1 marc PCIC_SYSMEM_ADDR4_START_LSB,
625 1.1.2.1 marc PCIC_SYSMEM_ADDR4_START_MSB,
626 1.1.2.1 marc PCIC_SYSMEM_ADDR4_STOP_LSB,
627 1.1.2.1 marc PCIC_SYSMEM_ADDR4_STOP_MSB,
628 1.1.2.1 marc PCIC_CARDMEM_ADDR4_LSB,
629 1.1.2.1 marc PCIC_CARDMEM_ADDR4_MSB,
630 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM4,
631 1.1.2.1 marc },
632 1.1.2.1 marc };
633 1.1.2.1 marc
634 1.1.2.10 marc void pcic_chip_do_mem_map(h, win)
635 1.1.2.10 marc struct pcic_handle *h;
636 1.1.2.10 marc int win;
637 1.1.2.10 marc {
638 1.1.2.10 marc int reg;
639 1.1.2.10 marc
640 1.1.2.10 marc pcic_write(h, mem_map_index[win].sysmem_start_lsb,
641 1.1.2.10 marc (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
642 1.1.2.10 marc pcic_write(h, mem_map_index[win].sysmem_start_msb,
643 1.1.2.10 marc ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
644 1.1.2.10 marc PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
645 1.1.2.10 marc
646 1.1.2.10 marc #if 0
647 1.1.2.10 marc /* XXX do I want 16 bit all the time? */
648 1.1.2.10 marc PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT;
649 1.1.2.10 marc #endif
650 1.1.2.10 marc
651 1.1.2.10 marc pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
652 1.1.2.10 marc ((h->mem[win].addr + h->mem[win].size) >>
653 1.1.2.10 marc PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
654 1.1.2.10 marc pcic_write(h, mem_map_index[win].sysmem_stop_msb,
655 1.1.2.10 marc (((h->mem[win].addr + h->mem[win].size) >>
656 1.1.2.10 marc (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
657 1.1.2.10 marc PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
658 1.1.2.10 marc PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
659 1.1.2.10 marc
660 1.1.2.10 marc pcic_write(h, mem_map_index[win].cardmem_lsb,
661 1.1.2.10 marc (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
662 1.1.2.10 marc pcic_write(h, mem_map_index[win].cardmem_msb,
663 1.1.2.10 marc ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
664 1.1.2.10 marc PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
665 1.1.2.10 marc ((h->mem[win].kind == PCMCIA_MEM_ATTR)?
666 1.1.2.10 marc PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR:0));
667 1.1.2.10 marc
668 1.1.2.10 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
669 1.1.2.10 marc reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16 );
670 1.1.2.10 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
671 1.1.2.10 marc
672 1.1.2.10 marc #ifdef PCICDEBUG
673 1.1.2.10 marc {
674 1.1.2.10 marc int r1,r2,r3,r4,r5,r6;
675 1.1.2.10 marc
676 1.1.2.10 marc r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
677 1.1.2.10 marc r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
678 1.1.2.10 marc r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
679 1.1.2.10 marc r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
680 1.1.2.10 marc r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
681 1.1.2.10 marc r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
682 1.1.2.10 marc
683 1.1.2.10 marc DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x %02x%02x\n",
684 1.1.2.10 marc win, r1, r2, r3, r4, r5, r6));
685 1.1.2.10 marc }
686 1.1.2.10 marc #endif
687 1.1.2.10 marc }
688 1.1.2.10 marc
689 1.1.2.4 thorpej int pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
690 1.1.2.1 marc pcmcia_chipset_handle_t pch;
691 1.1.2.1 marc int kind;
692 1.1.2.4 thorpej bus_addr_t card_addr;
693 1.1.2.1 marc bus_size_t size;
694 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
695 1.1.2.4 thorpej bus_addr_t *offsetp;
696 1.1.2.4 thorpej int *windowp;
697 1.1.2.1 marc {
698 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
699 1.1.2.4 thorpej bus_addr_t busaddr;
700 1.1.2.1 marc long card_offset;
701 1.1.2.1 marc int i, win;
702 1.1.2.1 marc
703 1.1.2.1 marc win = -1;
704 1.1.2.1 marc for (i=0; i<(sizeof(mem_map_index)/sizeof(mem_map_index[0])); i++) {
705 1.1.2.1 marc if ((h->memalloc & (1<<i)) == 0) {
706 1.1.2.1 marc win = i;
707 1.1.2.1 marc h->memalloc |= (1<<i);
708 1.1.2.1 marc break;
709 1.1.2.1 marc }
710 1.1.2.1 marc }
711 1.1.2.1 marc
712 1.1.2.1 marc if (win == -1)
713 1.1.2.1 marc return(1);
714 1.1.2.1 marc
715 1.1.2.4 thorpej *windowp = win;
716 1.1.2.1 marc
717 1.1.2.1 marc /* XXX this is pretty gross */
718 1.1.2.1 marc
719 1.1.2.4 thorpej if (h->sc->memt != pcmhp->memt)
720 1.1.2.1 marc panic("pcic_chip_mem_map memt is bogus");
721 1.1.2.1 marc
722 1.1.2.4 thorpej busaddr = pcmhp->addr;
723 1.1.2.1 marc
724 1.1.2.1 marc /* compute the address offset to the pcmcia address space for the
725 1.1.2.1 marc pcic. this is intentionally signed. The masks and shifts
726 1.1.2.1 marc below will cause TRT to happen in the pcic registers. Deal with
727 1.1.2.1 marc making sure the address is aligned, and return the alignment
728 1.1.2.1 marc offset. */
729 1.1.2.1 marc
730 1.1.2.4 thorpej *offsetp = card_addr % PCIC_MEM_ALIGN;
731 1.1.2.4 thorpej card_addr -= *offsetp;
732 1.1.2.1 marc
733 1.1.2.4 thorpej DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr %lx\n",
734 1.1.2.4 thorpej win, (u_long)busaddr, (u_long)*offsetp, (u_long)size,
735 1.1.2.4 thorpej (u_long)card_addr));
736 1.1.2.1 marc
737 1.1.2.1 marc /* include the offset in the size, and decrement size by one,
738 1.1.2.1 marc since the hw wants start/stop */
739 1.1.2.4 thorpej size += *offsetp - 1;
740 1.1.2.1 marc
741 1.1.2.4 thorpej card_offset = (((long) card_addr) - ((long) busaddr));
742 1.1.2.1 marc
743 1.1.2.10 marc h->mem[win].addr = busaddr;
744 1.1.2.10 marc h->mem[win].size = size;
745 1.1.2.10 marc h->mem[win].offset = card_offset;
746 1.1.2.10 marc h->mem[win].kind = kind;
747 1.1.2.1 marc
748 1.1.2.10 marc pcic_chip_do_mem_map(h, win);
749 1.1.2.1 marc
750 1.1.2.1 marc return(0);
751 1.1.2.1 marc }
752 1.1.2.1 marc
753 1.1.2.1 marc void pcic_chip_mem_unmap(pch, window)
754 1.1.2.1 marc pcmcia_chipset_handle_t pch;
755 1.1.2.1 marc int window;
756 1.1.2.1 marc {
757 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
758 1.1.2.1 marc int reg;
759 1.1.2.1 marc
760 1.1.2.1 marc if (window >= (sizeof(mem_map_index)/sizeof(mem_map_index[0])))
761 1.1.2.1 marc panic("pcic_chip_mem_unmap: window out of range");
762 1.1.2.1 marc
763 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
764 1.1.2.1 marc reg &= ~mem_map_index[window].memenable;
765 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
766 1.1.2.1 marc
767 1.1.2.4 thorpej h->memalloc &= ~(1 << window);
768 1.1.2.1 marc }
769 1.1.2.1 marc
770 1.1.2.4 thorpej int pcic_chip_io_alloc(pch, start, size, pcihp)
771 1.1.2.1 marc pcmcia_chipset_handle_t pch;
772 1.1.2.1 marc bus_addr_t start;
773 1.1.2.1 marc bus_size_t size;
774 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
775 1.1.2.1 marc {
776 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
777 1.1.2.4 thorpej bus_space_tag_t iot;
778 1.1.2.4 thorpej bus_space_handle_t ioh;
779 1.1.2.1 marc bus_addr_t ioaddr;
780 1.1.2.4 thorpej int flags = 0;
781 1.1.2.1 marc
782 1.1.2.1 marc /*
783 1.1.2.8 marc * Allocate some arbitrary I/O space.
784 1.1.2.1 marc */
785 1.1.2.1 marc
786 1.1.2.4 thorpej iot = h->sc->iot;
787 1.1.2.1 marc
788 1.1.2.1 marc if (start) {
789 1.1.2.4 thorpej ioaddr = start;
790 1.1.2.4 thorpej if (bus_space_map(iot, start, size, 0, &ioh))
791 1.1.2.1 marc return(1);
792 1.1.2.1 marc DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
793 1.1.2.4 thorpej (u_long) ioaddr, (u_long) size));
794 1.1.2.1 marc } else {
795 1.1.2.4 thorpej flags |= PCMCIA_IO_ALLOCATED;
796 1.1.2.10 marc if (bus_space_alloc(iot, h->sc->iobase, h->sc->iobase+h->sc->iosize,
797 1.1.2.10 marc size, size, 0, 0, &ioaddr, &ioh))
798 1.1.2.1 marc return(1);
799 1.1.2.1 marc DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
800 1.1.2.1 marc (u_long) ioaddr, (u_long) size));
801 1.1.2.1 marc }
802 1.1.2.1 marc
803 1.1.2.4 thorpej pcihp->iot = iot;
804 1.1.2.4 thorpej pcihp->ioh = ioh;
805 1.1.2.4 thorpej pcihp->addr = ioaddr;
806 1.1.2.4 thorpej pcihp->size = size;
807 1.1.2.4 thorpej pcihp->flags = flags;
808 1.1.2.4 thorpej
809 1.1.2.1 marc return(0);
810 1.1.2.1 marc }
811 1.1.2.1 marc
812 1.1.2.4 thorpej void pcic_chip_io_free(pch, pcihp)
813 1.1.2.1 marc pcmcia_chipset_handle_t pch;
814 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
815 1.1.2.1 marc {
816 1.1.2.4 thorpej bus_space_tag_t iot = pcihp->iot;
817 1.1.2.4 thorpej bus_space_handle_t ioh = pcihp->ioh;
818 1.1.2.4 thorpej bus_size_t size = pcihp->size;
819 1.1.2.4 thorpej
820 1.1.2.4 thorpej if (pcihp->flags & PCMCIA_IO_ALLOCATED)
821 1.1.2.4 thorpej bus_space_free(iot, ioh, size);
822 1.1.2.4 thorpej else
823 1.1.2.4 thorpej bus_space_unmap(iot, ioh, size);
824 1.1.2.1 marc }
825 1.1.2.1 marc
826 1.1.2.1 marc
827 1.1.2.1 marc static struct io_map_index_st {
828 1.1.2.1 marc int start_lsb;
829 1.1.2.1 marc int start_msb;
830 1.1.2.1 marc int stop_lsb;
831 1.1.2.1 marc int stop_msb;
832 1.1.2.1 marc int ioenable;
833 1.1.2.1 marc int ioctlmask;
834 1.1.2.1 marc int ioctl8;
835 1.1.2.1 marc int ioctl16;
836 1.1.2.1 marc } io_map_index[] = {
837 1.1.2.1 marc {
838 1.1.2.1 marc PCIC_IOADDR0_START_LSB,
839 1.1.2.1 marc PCIC_IOADDR0_START_MSB,
840 1.1.2.1 marc PCIC_IOADDR0_STOP_LSB,
841 1.1.2.1 marc PCIC_IOADDR0_STOP_MSB,
842 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_IO0,
843 1.1.2.1 marc PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
844 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
845 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_8BIT,
846 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_16BIT,
847 1.1.2.1 marc },
848 1.1.2.1 marc {
849 1.1.2.1 marc PCIC_IOADDR1_START_LSB,
850 1.1.2.1 marc PCIC_IOADDR1_START_MSB,
851 1.1.2.1 marc PCIC_IOADDR1_STOP_LSB,
852 1.1.2.1 marc PCIC_IOADDR1_STOP_MSB,
853 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_IO1,
854 1.1.2.1 marc PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
855 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
856 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO1_DATASIZE_8BIT,
857 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO1_DATASIZE_16BIT,
858 1.1.2.1 marc },
859 1.1.2.1 marc };
860 1.1.2.1 marc
861 1.1.2.10 marc void pcic_chip_do_io_map(h, win)
862 1.1.2.10 marc struct pcic_handle *h;
863 1.1.2.10 marc int win;
864 1.1.2.10 marc {
865 1.1.2.10 marc int reg;
866 1.1.2.10 marc
867 1.1.2.10 marc DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
868 1.1.2.10 marc win, (long) h->io[win].addr, (long) h->io[win].size,
869 1.1.2.10 marc h->io[win].width*8));
870 1.1.2.10 marc
871 1.1.2.10 marc pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff);
872 1.1.2.10 marc pcic_write(h, io_map_index[win].start_msb, (h->io[win].addr >> 8) & 0xff);
873 1.1.2.10 marc
874 1.1.2.10 marc pcic_write(h, io_map_index[win].stop_lsb,
875 1.1.2.10 marc (h->io[win].addr + h->io[win].size - 1) & 0xff);
876 1.1.2.10 marc pcic_write(h, io_map_index[win].stop_msb,
877 1.1.2.10 marc ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff);
878 1.1.2.10 marc
879 1.1.2.10 marc reg = pcic_read(h, PCIC_IOCTL);
880 1.1.2.10 marc reg &= ~io_map_index[win].ioctlmask;
881 1.1.2.10 marc if (h->io[win].width == PCMCIA_WIDTH_IO8)
882 1.1.2.10 marc reg |= io_map_index[win].ioctl8;
883 1.1.2.10 marc else
884 1.1.2.10 marc reg |= io_map_index[win].ioctl16;
885 1.1.2.10 marc pcic_write(h, PCIC_IOCTL, reg);
886 1.1.2.10 marc
887 1.1.2.10 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
888 1.1.2.10 marc reg |= io_map_index[win].ioenable;
889 1.1.2.10 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
890 1.1.2.10 marc }
891 1.1.2.10 marc
892 1.1.2.4 thorpej int pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
893 1.1.2.1 marc pcmcia_chipset_handle_t pch;
894 1.1.2.1 marc int width;
895 1.1.2.4 thorpej bus_addr_t offset;
896 1.1.2.1 marc bus_size_t size;
897 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
898 1.1.2.4 thorpej int *windowp;
899 1.1.2.1 marc {
900 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
901 1.1.2.4 thorpej bus_addr_t ioaddr = pcihp->addr + offset;
902 1.1.2.1 marc int i, win;
903 1.1.2.1 marc
904 1.1.2.4 thorpej /* XXX Sanity check offset/size. */
905 1.1.2.4 thorpej
906 1.1.2.1 marc win = -1;
907 1.1.2.1 marc for (i=0; i<(sizeof(io_map_index)/sizeof(io_map_index[0])); i++) {
908 1.1.2.1 marc if ((h->ioalloc & (1<<i)) == 0) {
909 1.1.2.1 marc win = i;
910 1.1.2.1 marc h->ioalloc |= (1<<i);
911 1.1.2.1 marc break;
912 1.1.2.1 marc }
913 1.1.2.1 marc }
914 1.1.2.1 marc
915 1.1.2.1 marc if (win == -1)
916 1.1.2.1 marc return(1);
917 1.1.2.1 marc
918 1.1.2.4 thorpej *windowp = win;
919 1.1.2.1 marc
920 1.1.2.1 marc /* XXX this is pretty gross */
921 1.1.2.1 marc
922 1.1.2.4 thorpej if (h->sc->iot != pcihp->iot)
923 1.1.2.1 marc panic("pcic_chip_io_map iot is bogus");
924 1.1.2.1 marc
925 1.1.2.1 marc DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
926 1.1.2.1 marc win, (width == PCMCIA_WIDTH_IO8)?"io8":"io16",
927 1.1.2.4 thorpej (u_long) ioaddr, (u_long) size));
928 1.1.2.1 marc
929 1.1.2.10 marc /* XXX wtf is this doing here? */
930 1.1.2.10 marc
931 1.1.2.6 jtk printf(" port 0x%lx", (u_long)ioaddr);
932 1.1.2.6 jtk if (size > 1)
933 1.1.2.6 jtk printf("-0x%lx", (u_long)ioaddr + (u_long)size - 1);
934 1.1.2.6 jtk
935 1.1.2.10 marc h->io[win].addr = ioaddr;
936 1.1.2.10 marc h->io[win].size = size;
937 1.1.2.10 marc h->io[win].width = width;
938 1.1.2.1 marc
939 1.1.2.10 marc pcic_chip_do_io_map(h, win);
940 1.1.2.1 marc
941 1.1.2.1 marc return(0);
942 1.1.2.1 marc }
943 1.1.2.1 marc
944 1.1.2.1 marc void pcic_chip_io_unmap(pch, window)
945 1.1.2.1 marc pcmcia_chipset_handle_t pch;
946 1.1.2.1 marc int window;
947 1.1.2.1 marc {
948 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
949 1.1.2.1 marc int reg;
950 1.1.2.1 marc
951 1.1.2.1 marc if (window >= (sizeof(io_map_index)/sizeof(io_map_index[0])))
952 1.1.2.1 marc panic("pcic_chip_io_unmap: window out of range");
953 1.1.2.1 marc
954 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
955 1.1.2.1 marc reg &= ~io_map_index[window].ioenable;
956 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
957 1.1.2.1 marc
958 1.1.2.8 marc h->ioalloc &= ~(1<<window);
959 1.1.2.7 thorpej }
960 1.1.2.7 thorpej
961 1.1.2.7 thorpej void
962 1.1.2.7 thorpej pcic_chip_socket_enable(pch)
963 1.1.2.7 thorpej pcmcia_chipset_handle_t pch;
964 1.1.2.7 thorpej {
965 1.1.2.10 marc struct pcic_handle *h = (struct pcic_handle *) pch;
966 1.1.2.10 marc int cardtype, reg, win;
967 1.1.2.10 marc
968 1.1.2.10 marc /* this bit is mostly stolen from pcic_attach_card */
969 1.1.2.10 marc
970 1.1.2.10 marc /* power down the socket to reset it, clear the card reset pin */
971 1.1.2.10 marc
972 1.1.2.10 marc pcic_write(h, PCIC_PWRCTL, 0);
973 1.1.2.10 marc
974 1.1.2.10 marc /* power up the socket */
975 1.1.2.10 marc
976 1.1.2.10 marc pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE);
977 1.1.2.10 marc delay(10000);
978 1.1.2.10 marc pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_OE);
979 1.1.2.10 marc
980 1.1.2.10 marc /* clear the reset flag */
981 1.1.2.10 marc
982 1.1.2.10 marc pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
983 1.1.2.10 marc
984 1.1.2.10 marc /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
985 1.1.2.10 marc
986 1.1.2.10 marc delay(20000);
987 1.1.2.10 marc
988 1.1.2.10 marc /* wait for the chip to finish initializing */
989 1.1.2.10 marc
990 1.1.2.10 marc pcic_wait_ready(h);
991 1.1.2.10 marc
992 1.1.2.10 marc /* zero out the address windows */
993 1.1.2.10 marc
994 1.1.2.10 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
995 1.1.2.10 marc
996 1.1.2.10 marc /* set the card type */
997 1.1.2.10 marc
998 1.1.2.10 marc cardtype = pcmcia_card_gettype(h->pcmcia);
999 1.1.2.10 marc
1000 1.1.2.10 marc reg = pcic_read(h, PCIC_INTR);
1001 1.1.2.10 marc reg &= ~PCIC_INTR_CARDTYPE_MASK;
1002 1.1.2.10 marc reg |= ((cardtype == PCMCIA_IFTYPE_IO)?
1003 1.1.2.10 marc PCIC_INTR_CARDTYPE_IO:
1004 1.1.2.10 marc PCIC_INTR_CARDTYPE_MEM);
1005 1.1.2.10 marc reg |= h->ih_irq;
1006 1.1.2.10 marc pcic_write(h, PCIC_INTR, reg);
1007 1.1.2.10 marc
1008 1.1.2.10 marc DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
1009 1.1.2.10 marc h->sc->dev.dv_xname, h->sock,
1010 1.1.2.10 marc ((cardtype == PCMCIA_IFTYPE_IO)?"io":"mem"), reg));
1011 1.1.2.10 marc
1012 1.1.2.10 marc /* reinstall all the memory and io mappings */
1013 1.1.2.10 marc
1014 1.1.2.10 marc for (win=0; win<PCIC_MEM_WINS; win++)
1015 1.1.2.10 marc if (h->memalloc & (1<<win))
1016 1.1.2.10 marc pcic_chip_do_mem_map(h, win);
1017 1.1.2.10 marc
1018 1.1.2.10 marc for (win=0; win<PCIC_IO_WINS; win++)
1019 1.1.2.10 marc if (h->ioalloc & (1<<win))
1020 1.1.2.10 marc pcic_chip_do_io_map(h, win);
1021 1.1.2.7 thorpej }
1022 1.1.2.7 thorpej
1023 1.1.2.7 thorpej void
1024 1.1.2.7 thorpej pcic_chip_socket_disable(pch)
1025 1.1.2.7 thorpej pcmcia_chipset_handle_t pch;
1026 1.1.2.7 thorpej {
1027 1.1.2.10 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1028 1.1.2.10 marc
1029 1.1.2.10 marc DPRINTF(("pcic_chip_socket_disable\n"));
1030 1.1.2.10 marc
1031 1.1.2.10 marc /* power down the socket */
1032 1.1.2.10 marc
1033 1.1.2.10 marc pcic_write(h, PCIC_PWRCTL, 0);
1034 1.1.2.1 marc }
1035