pcmcia.c revision 1.1.2.4 1 1.1.2.1 marc #define PCMCIADEBUG
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
8 1.1.2.1 marc /* XXX only needed for intr debugging */
9 1.1.2.1 marc #include <vm/vm.h>
10 1.1.2.1 marc
11 1.1.2.1 marc #include <dev/pcmcia/pcmciareg.h>
12 1.1.2.1 marc #include <dev/pcmcia/pcmciachip.h>
13 1.1.2.1 marc #include <dev/pcmcia/pcmciavar.h>
14 1.1.2.1 marc
15 1.1.2.1 marc #ifdef PCMCIADEBUG
16 1.1.2.3 thorpej int pcmcia_debug = 0;
17 1.1.2.3 thorpej #define DPRINTF(arg) if (pcmcia_debug) printf arg
18 1.1.2.1 marc #else
19 1.1.2.1 marc #define DPRINTF(arg)
20 1.1.2.1 marc #endif
21 1.1.2.1 marc
22 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
23 1.1.2.1 marc int pcmcia_match __P((struct device *, void *, void *));
24 1.1.2.1 marc int pcmcia_submatch __P((struct device *, void *, void *));
25 1.1.2.1 marc #else
26 1.1.2.1 marc int pcmcia_match __P((struct device *, struct cfdata *, void *));
27 1.1.2.1 marc int pcmcia_submatch __P((struct device *, struct cfdata *, void *));
28 1.1.2.1 marc #endif
29 1.1.2.1 marc void pcmcia_attach __P((struct device *, struct device *, void *));
30 1.1.2.1 marc int pcmcia_print __P((void *, const char *));
31 1.1.2.1 marc
32 1.1.2.1 marc int pcmcia_card_intr __P((void *));
33 1.1.2.1 marc
34 1.1.2.1 marc struct cfdriver pcmcia_cd = {
35 1.1.2.1 marc NULL, "pcmcia", DV_DULL
36 1.1.2.1 marc };
37 1.1.2.1 marc
38 1.1.2.1 marc struct cfattach pcmcia_ca = {
39 1.1.2.1 marc sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
40 1.1.2.1 marc };
41 1.1.2.1 marc
42 1.1.2.1 marc int
43 1.1.2.1 marc pcmcia_ccr_read(pf, ccr)
44 1.1.2.1 marc struct pcmcia_function *pf;
45 1.1.2.1 marc int ccr;
46 1.1.2.1 marc {
47 1.1.2.1 marc return(bus_space_read_1((pf)->ccrt, (pf)->ccrh, (pf)->ccr_offset+(ccr)));
48 1.1.2.1 marc }
49 1.1.2.1 marc
50 1.1.2.1 marc void
51 1.1.2.1 marc pcmcia_ccr_write(pf, ccr, val)
52 1.1.2.1 marc struct pcmcia_function *pf;
53 1.1.2.1 marc int ccr;
54 1.1.2.1 marc int val;
55 1.1.2.1 marc {
56 1.1.2.1 marc if (((pf)->ccr_mask) & (1<<(ccr/2))) {
57 1.1.2.1 marc bus_space_write_1((pf)->ccrt, (pf)->ccrh,
58 1.1.2.1 marc (pf)->ccr_offset+(ccr), (val));
59 1.1.2.1 marc }
60 1.1.2.1 marc }
61 1.1.2.1 marc
62 1.1.2.1 marc int
63 1.1.2.1 marc pcmcia_match(parent, match, aux)
64 1.1.2.1 marc struct device *parent;
65 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
66 1.1.2.1 marc void *match;
67 1.1.2.1 marc #else
68 1.1.2.1 marc struct cfdata *match;
69 1.1.2.1 marc #endif
70 1.1.2.1 marc void *aux;
71 1.1.2.1 marc {
72 1.1.2.1 marc /* if the autoconfiguration got this far, there's a socket here */
73 1.1.2.1 marc
74 1.1.2.1 marc return(1);
75 1.1.2.1 marc }
76 1.1.2.1 marc
77 1.1.2.1 marc void
78 1.1.2.1 marc pcmcia_attach(parent, self, aux)
79 1.1.2.1 marc struct device *parent, *self;
80 1.1.2.1 marc void *aux;
81 1.1.2.1 marc {
82 1.1.2.1 marc struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) aux;
83 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
84 1.1.2.1 marc
85 1.1.2.1 marc printf("\n");
86 1.1.2.1 marc
87 1.1.2.1 marc sc->pct = paa->pct;
88 1.1.2.1 marc sc->pch = paa->pch;
89 1.1.2.1 marc
90 1.1.2.1 marc sc->ih = NULL;
91 1.1.2.1 marc }
92 1.1.2.1 marc
93 1.1.2.1 marc int
94 1.1.2.1 marc pcmcia_attach_card(dev, iftype)
95 1.1.2.1 marc struct device *dev;
96 1.1.2.1 marc int *iftype;
97 1.1.2.1 marc {
98 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
99 1.1.2.1 marc struct pcmcia_function *pf;
100 1.1.2.1 marc struct pcmcia_attach_args paa;
101 1.1.2.1 marc int attached;
102 1.1.2.1 marc
103 1.1.2.1 marc pcmcia_read_cis(sc);
104 1.1.2.1 marc
105 1.1.2.1 marc /* bail now if the card has no functions, or if there was an error
106 1.1.2.1 marc in the cis. */
107 1.1.2.1 marc
108 1.1.2.1 marc if (sc->card.error)
109 1.1.2.1 marc return(1);
110 1.1.2.1 marc if (!sc->card.pf_head.sqh_first)
111 1.1.2.1 marc return(1);
112 1.1.2.1 marc
113 1.1.2.1 marc pcmcia_print_cis(sc);
114 1.1.2.1 marc
115 1.1.2.1 marc /* set the iftype to memory if this card has only one function,
116 1.1.2.1 marc and that is memory. */
117 1.1.2.1 marc if (sc->card.pf_head.sqh_first &&
118 1.1.2.1 marc !sc->card.pf_head.sqh_first->pf_list.sqe_next &&
119 1.1.2.1 marc (sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
120 1.1.2.1 marc PCMCIA_IFTYPE_MEMORY))
121 1.1.2.1 marc *iftype = PCMCIA_IFTYPE_MEMORY;
122 1.1.2.1 marc else
123 1.1.2.1 marc *iftype = PCMCIA_IFTYPE_IO;
124 1.1.2.1 marc
125 1.1.2.1 marc attached = 0;
126 1.1.2.1 marc
127 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
128 1.1.2.1 marc if (pf->cfe_head.sqh_first == NULL)
129 1.1.2.1 marc continue;
130 1.1.2.1 marc
131 1.1.2.1 marc pf->sc = sc;
132 1.1.2.1 marc pf->cfe = NULL;
133 1.1.2.1 marc pf->ih_fct = NULL;
134 1.1.2.1 marc pf->ih_arg = NULL;
135 1.1.2.1 marc }
136 1.1.2.1 marc
137 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
138 1.1.2.1 marc if (pf->cfe_head.sqh_first == NULL)
139 1.1.2.1 marc continue;
140 1.1.2.1 marc
141 1.1.2.1 marc paa.manufacturer = sc->card.manufacturer;
142 1.1.2.1 marc paa.product = sc->card.product;
143 1.1.2.1 marc paa.card = &sc->card;
144 1.1.2.1 marc paa.pf = pf;
145 1.1.2.1 marc
146 1.1.2.1 marc if (config_found_sm(&sc->dev, &paa, pcmcia_print, pcmcia_submatch)) {
147 1.1.2.1 marc attached++;
148 1.1.2.1 marc
149 1.1.2.1 marc DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
150 1.1.2.1 marc sc->dev.dv_xname, pf->number,
151 1.1.2.1 marc pf->ccr_window, pf->ccr_offset,
152 1.1.2.1 marc pcmcia_ccr_read(pf, 0x00),
153 1.1.2.1 marc pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
154 1.1.2.1 marc pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
155 1.1.2.1 marc pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
156 1.1.2.1 marc pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
157 1.1.2.1 marc }
158 1.1.2.1 marc }
159 1.1.2.1 marc
160 1.1.2.1 marc return(attached?0:1);
161 1.1.2.1 marc }
162 1.1.2.1 marc
163 1.1.2.1 marc void
164 1.1.2.1 marc pcmcia_detach_card(dev)
165 1.1.2.1 marc struct device *dev;
166 1.1.2.1 marc {
167 1.1.2.1 marc /* struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
168 1.1.2.1 marc /* don't do anything yet */
169 1.1.2.1 marc }
170 1.1.2.1 marc
171 1.1.2.1 marc int
172 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
173 1.1.2.1 marc pcmcia_submatch(parent, match, aux)
174 1.1.2.1 marc #else
175 1.1.2.1 marc pcmcia_submatch(parent, cf, aux)
176 1.1.2.1 marc #endif
177 1.1.2.1 marc struct device *parent;
178 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
179 1.1.2.1 marc void *match;
180 1.1.2.1 marc #else
181 1.1.2.1 marc struct cfdata *cf;
182 1.1.2.1 marc #endif
183 1.1.2.1 marc void *aux;
184 1.1.2.1 marc {
185 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
186 1.1.2.1 marc struct cfdata *cf = match;
187 1.1.2.1 marc #endif
188 1.1.2.1 marc
189 1.1.2.1 marc struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) aux;
190 1.1.2.1 marc
191 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
192 1.1.2.1 marc return(0);
193 1.1.2.1 marc
194 1.1.2.1 marc return ((*cf->cf_attach->ca_match)(parent, cf, aux));
195 1.1.2.1 marc }
196 1.1.2.1 marc
197 1.1.2.1 marc int
198 1.1.2.1 marc pcmcia_print(arg, pnp)
199 1.1.2.1 marc void *arg;
200 1.1.2.1 marc const char *pnp;
201 1.1.2.1 marc {
202 1.1.2.1 marc struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) arg;
203 1.1.2.1 marc
204 1.1.2.1 marc if (pnp)
205 1.1.2.1 marc printf("manufacturer code %x, product %x at %s",
206 1.1.2.1 marc paa->manufacturer, paa->product, pnp);
207 1.1.2.1 marc
208 1.1.2.1 marc printf(" function %d", paa->pf->number);
209 1.1.2.1 marc
210 1.1.2.1 marc return(UNCONF);
211 1.1.2.1 marc }
212 1.1.2.1 marc
213 1.1.2.1 marc int
214 1.1.2.1 marc pcmcia_enable_function(pf, pcmcia, cfe)
215 1.1.2.1 marc struct pcmcia_function *pf;
216 1.1.2.1 marc struct device *pcmcia;
217 1.1.2.1 marc struct pcmcia_config_entry *cfe;
218 1.1.2.1 marc {
219 1.1.2.1 marc struct pcmcia_function *tmp;
220 1.1.2.1 marc int reg;
221 1.1.2.1 marc
222 1.1.2.1 marc pf->cfe = cfe;
223 1.1.2.1 marc
224 1.1.2.1 marc /* it's possible for different functions' CCRs to be in the same
225 1.1.2.1 marc underlying page. Check for that. */
226 1.1.2.1 marc
227 1.1.2.1 marc for (tmp = pf->sc->card.pf_head.sqh_first;
228 1.1.2.1 marc tmp;
229 1.1.2.1 marc tmp = tmp->pf_list.sqe_next) {
230 1.1.2.1 marc if (tmp->cfe &&
231 1.1.2.1 marc (pf->ccr_base >= (tmp->ccr_base - tmp->ccr_offset)) &&
232 1.1.2.1 marc ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
233 1.1.2.1 marc (tmp->ccr_base - tmp->ccr_offset + tmp->ccr_realsize))) {
234 1.1.2.1 marc pf->ccrt = tmp->ccrt;
235 1.1.2.1 marc pf->ccrh = tmp->ccrh;
236 1.1.2.1 marc pf->ccr_realsize = tmp->ccr_realsize;
237 1.1.2.1 marc
238 1.1.2.1 marc /* pf->ccr_offset =
239 1.1.2.1 marc (tmp->ccr_offset - tmp->ccr_base) + pf->ccr_base; */
240 1.1.2.1 marc pf->ccr_offset = (tmp->ccr_offset + pf->ccr_base) - tmp->ccr_base;
241 1.1.2.1 marc pf->ccr_window = tmp->ccr_window;
242 1.1.2.1 marc /* XXX when shutting down one function, it will be necessary
243 1.1.2.1 marc to make sure this window is no longer in use before
244 1.1.2.1 marc actually unmapping and freeing it */
245 1.1.2.1 marc break;
246 1.1.2.1 marc }
247 1.1.2.1 marc }
248 1.1.2.1 marc
249 1.1.2.1 marc if (tmp == NULL) {
250 1.1.2.1 marc if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->ccrt, &pf->ccrh,
251 1.1.2.1 marc &pf->ccr_mhandle, &pf->ccr_realsize))
252 1.1.2.1 marc return(1);
253 1.1.2.1 marc
254 1.1.2.1 marc if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, PCMCIA_CCR_SIZE,
255 1.1.2.1 marc pf->ccrt, pf->ccrh, pf->ccr_base,
256 1.1.2.1 marc &pf->ccr_offset, &pf->ccr_window))
257 1.1.2.1 marc return(1);
258 1.1.2.1 marc }
259 1.1.2.1 marc
260 1.1.2.1 marc DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
261 1.1.2.1 marc pf->sc->dev.dv_xname, pf->number,
262 1.1.2.1 marc pf->ccr_window, pf->ccr_offset,
263 1.1.2.1 marc pcmcia_ccr_read(pf, 0x00),
264 1.1.2.1 marc pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
265 1.1.2.1 marc pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
266 1.1.2.1 marc pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
267 1.1.2.1 marc pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
268 1.1.2.1 marc
269 1.1.2.1 marc reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
270 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_LEVIREQ;
271 1.1.2.1 marc if (pcmcia_mfc(pf->sc))
272 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
273 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
274 1.1.2.1 marc
275 1.1.2.1 marc #if 0
276 1.1.2.1 marc reg = PCMCIA_CCR_STATUS_SIGCHG;
277 1.1.2.1 marc #else
278 1.1.2.1 marc reg = 0;
279 1.1.2.1 marc #endif
280 1.1.2.1 marc if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
281 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_IOIS8;
282 1.1.2.1 marc if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
283 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_AUDIO;
284 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
285 1.1.2.1 marc
286 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
287 1.1.2.1 marc
288 1.1.2.1 marc return(0);
289 1.1.2.1 marc }
290 1.1.2.1 marc
291 1.1.2.1 marc int
292 1.1.2.1 marc pcmcia_io_map(pf, width, size, iot, ioh, windowp)
293 1.1.2.1 marc struct pcmcia_function *pf;
294 1.1.2.1 marc int width;
295 1.1.2.1 marc bus_size_t size;
296 1.1.2.1 marc bus_space_tag_t iot;
297 1.1.2.1 marc bus_space_handle_t ioh;
298 1.1.2.1 marc int *windowp;
299 1.1.2.1 marc {
300 1.1.2.1 marc int reg;
301 1.1.2.1 marc
302 1.1.2.1 marc if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
303 1.1.2.1 marc width, size, iot, ioh, windowp))
304 1.1.2.1 marc return(1);
305 1.1.2.1 marc
306 1.1.2.1 marc /* XXX in the multifunction multi-iospace-per-function case, this
307 1.1.2.1 marc needs to cooperate with io_alloc to make sure that the spaces
308 1.1.2.1 marc don't overlap, and that the ccr's are set correctly */
309 1.1.2.1 marc
310 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
311 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioh & 0xff);
312 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioh >> 8) & 0xff);
313 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
314 1.1.2.1 marc
315 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
316 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
317 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
318 1.1.2.1 marc }
319 1.1.2.1 marc
320 1.1.2.1 marc return(0);
321 1.1.2.1 marc }
322 1.1.2.1 marc
323 1.1.2.1 marc void *
324 1.1.2.1 marc pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
325 1.1.2.1 marc struct pcmcia_function *pf;
326 1.1.2.1 marc int ipl;
327 1.1.2.1 marc int (*ih_fct) __P((void *));
328 1.1.2.1 marc void *ih_arg;
329 1.1.2.1 marc {
330 1.1.2.4 thorpej u_int16_t irqmask = pf->cfe_head.sqh_first->irqmask;
331 1.1.2.1 marc void *ret;
332 1.1.2.1 marc
333 1.1.2.1 marc /* behave differently if this is a multifunction card */
334 1.1.2.1 marc
335 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
336 1.1.2.1 marc int s, ihcnt, hiipl, reg;
337 1.1.2.1 marc struct pcmcia_function *pf2;
338 1.1.2.1 marc
339 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
340 1.1.2.1 marc and find the highest ipl number (lowest priority) */
341 1.1.2.1 marc
342 1.1.2.1 marc ihcnt = 0;
343 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
344 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
345 1.1.2.1 marc
346 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
347 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
348 1.1.2.1 marc if (pf2->ih_fct) {
349 1.1.2.1 marc if (!ihcnt) {
350 1.1.2.1 marc s = splraise(pf2->ih_ipl);
351 1.1.2.1 marc hiipl = pf2->ih_ipl;
352 1.1.2.1 marc ihcnt++;
353 1.1.2.1 marc } else {
354 1.1.2.1 marc splraise(pf2->ih_ipl);
355 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
356 1.1.2.1 marc hiipl = pf2->ih_ipl;
357 1.1.2.1 marc }
358 1.1.2.1 marc }
359 1.1.2.1 marc }
360 1.1.2.1 marc
361 1.1.2.1 marc /* set up the handler for the new function */
362 1.1.2.1 marc
363 1.1.2.1 marc pf->ih_fct = ih_fct;
364 1.1.2.1 marc pf->ih_arg = ih_arg;
365 1.1.2.1 marc pf->ih_ipl = ipl;
366 1.1.2.1 marc
367 1.1.2.1 marc /* establish the real interrupt, changing the ipl if necessary */
368 1.1.2.1 marc
369 1.1.2.1 marc if (ihcnt == 0) {
370 1.1.2.1 marc #ifdef DIAGNOSTIC
371 1.1.2.1 marc if (pf->sc->ih)
372 1.1.2.1 marc panic("card has intr handler, but no function does");
373 1.1.2.1 marc #endif
374 1.1.2.1 marc
375 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
376 1.1.2.4 thorpej irqmask, ipl,
377 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
378 1.1.2.1 marc } else if (ipl > hiipl) {
379 1.1.2.1 marc #ifdef DIAGNOSTIC
380 1.1.2.1 marc if (! pf->sc->ih)
381 1.1.2.1 marc panic("functions have ih, but the card does not");
382 1.1.2.1 marc #endif
383 1.1.2.1 marc
384 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
385 1.1.2.1 marc pf->sc->ih);
386 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
387 1.1.2.4 thorpej irqmask, ipl,
388 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
389 1.1.2.1 marc }
390 1.1.2.1 marc
391 1.1.2.1 marc if (ihcnt)
392 1.1.2.1 marc splx(s);
393 1.1.2.1 marc
394 1.1.2.1 marc ret = pf->sc->ih;
395 1.1.2.1 marc
396 1.1.2.1 marc if (ret) {
397 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
398 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
399 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
400 1.1.2.1 marc
401 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
402 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_INTRACK;
403 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
404 1.1.2.1 marc }
405 1.1.2.1 marc } else {
406 1.1.2.1 marc ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
407 1.1.2.4 thorpej irqmask, ipl, ih_fct, ih_arg);
408 1.1.2.1 marc }
409 1.1.2.1 marc
410 1.1.2.1 marc return(ret);
411 1.1.2.1 marc }
412 1.1.2.1 marc
413 1.1.2.1 marc void
414 1.1.2.1 marc pcmcia_intr_disestablish(pf, ih)
415 1.1.2.1 marc struct pcmcia_function *pf;
416 1.1.2.1 marc void *ih;
417 1.1.2.1 marc {
418 1.1.2.4 thorpej u_int16_t irqmask = pf->cfe_head.sqh_first->irqmask;
419 1.1.2.4 thorpej
420 1.1.2.1 marc /* behave differently if this is a multifunction card */
421 1.1.2.1 marc
422 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
423 1.1.2.1 marc int s, ihcnt, hiipl;
424 1.1.2.1 marc struct pcmcia_function *pf2;
425 1.1.2.1 marc
426 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
427 1.1.2.1 marc and find the highest ipl number (lowest priority). Skip
428 1.1.2.1 marc the current function. */
429 1.1.2.1 marc
430 1.1.2.1 marc ihcnt = 0;
431 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
432 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
433 1.1.2.1 marc
434 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
435 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
436 1.1.2.1 marc if (pf2 == pf)
437 1.1.2.1 marc continue;
438 1.1.2.1 marc
439 1.1.2.1 marc if (pf2->ih_fct) {
440 1.1.2.1 marc if (!ihcnt) {
441 1.1.2.1 marc s = splraise(pf2->ih_ipl);
442 1.1.2.1 marc hiipl = pf2->ih_ipl;
443 1.1.2.1 marc ihcnt++;
444 1.1.2.1 marc } else {
445 1.1.2.1 marc splraise(pf2->ih_ipl);
446 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
447 1.1.2.1 marc hiipl = pf2->ih_ipl;
448 1.1.2.1 marc }
449 1.1.2.1 marc }
450 1.1.2.1 marc }
451 1.1.2.1 marc
452 1.1.2.1 marc /* null out the handler for this function */
453 1.1.2.1 marc
454 1.1.2.1 marc pf->ih_fct = NULL;
455 1.1.2.1 marc pf->ih_arg = NULL;
456 1.1.2.1 marc
457 1.1.2.1 marc /* if the ih being removed is lower priority than the lowest
458 1.1.2.1 marc priority remaining interrupt, up the priority. */
459 1.1.2.1 marc
460 1.1.2.1 marc #ifdef DIAGNOSTIC
461 1.1.2.1 marc if (ihcnt == 0) {
462 1.1.2.1 marc panic("can't remove a handler from a card which has none");
463 1.1.2.1 marc } else
464 1.1.2.1 marc #endif
465 1.1.2.1 marc if (ihcnt == 1) {
466 1.1.2.1 marc #ifdef DIAGNOSTIC
467 1.1.2.1 marc if (!pf->sc->ih)
468 1.1.2.1 marc panic("disestablishing last function, but card has no ih");
469 1.1.2.1 marc #endif
470 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
471 1.1.2.1 marc pf->sc->ih);
472 1.1.2.1 marc pf->sc->ih = NULL;
473 1.1.2.1 marc } else if (pf->ih_ipl > hiipl) {
474 1.1.2.1 marc #ifdef DIAGNOSTIC
475 1.1.2.1 marc if (!pf->sc->ih)
476 1.1.2.1 marc panic("changing ih ipl, but card has no ih");
477 1.1.2.1 marc #endif
478 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
479 1.1.2.1 marc pf->sc->ih);
480 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
481 1.1.2.4 thorpej irqmask, hiipl,
482 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
483 1.1.2.1 marc }
484 1.1.2.1 marc
485 1.1.2.1 marc if (ihcnt)
486 1.1.2.1 marc splx(s);
487 1.1.2.1 marc } else {
488 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
489 1.1.2.1 marc }
490 1.1.2.1 marc }
491 1.1.2.1 marc
492 1.1.2.1 marc int pcmcia_card_intr(arg)
493 1.1.2.1 marc void *arg;
494 1.1.2.1 marc {
495 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
496 1.1.2.1 marc struct pcmcia_function *pf;
497 1.1.2.1 marc int reg, ret, ret2;
498 1.1.2.1 marc
499 1.1.2.1 marc ret = 0;
500 1.1.2.1 marc
501 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
502 1.1.2.1 marc #if 0
503 1.1.2.1 marc printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
504 1.1.2.1 marc sc->dev.dv_xname, pf->number,
505 1.1.2.1 marc pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
506 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
507 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_OPTION),
508 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
509 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_STATUS),
510 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
511 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_PIN));
512 1.1.2.1 marc #endif
513 1.1.2.1 marc if (pf->ih_fct &&
514 1.1.2.1 marc (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
515 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
516 1.1.2.1 marc if (reg & PCMCIA_CCR_STATUS_INTR) {
517 1.1.2.1 marc ret2 = (*pf->ih_fct)(pf->ih_arg);
518 1.1.2.1 marc if (ret2 && !ret)
519 1.1.2.1 marc ret = ret2;
520 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
521 1.1.2.1 marc #if 0
522 1.1.2.1 marc printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
523 1.1.2.1 marc #endif
524 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
525 1.1.2.1 marc reg & ~PCMCIA_CCR_STATUS_INTR);
526 1.1.2.1 marc }
527 1.1.2.1 marc }
528 1.1.2.1 marc #if 0
529 1.1.2.1 marc printf("\n");
530 1.1.2.1 marc #endif
531 1.1.2.1 marc }
532 1.1.2.1 marc
533 1.1.2.1 marc return(ret);
534 1.1.2.1 marc }
535 1.1.2.1 marc
536