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