pcmcia.c revision 1.1.2.3 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.1 marc void *ret;
331 1.1.2.1 marc
332 1.1.2.1 marc /* behave differently if this is a multifunction card */
333 1.1.2.1 marc
334 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
335 1.1.2.1 marc int s, ihcnt, hiipl, reg;
336 1.1.2.1 marc struct pcmcia_function *pf2;
337 1.1.2.1 marc
338 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
339 1.1.2.1 marc and find the highest ipl number (lowest priority) */
340 1.1.2.1 marc
341 1.1.2.1 marc ihcnt = 0;
342 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
343 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
344 1.1.2.1 marc
345 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
346 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
347 1.1.2.1 marc if (pf2->ih_fct) {
348 1.1.2.1 marc if (!ihcnt) {
349 1.1.2.1 marc s = splraise(pf2->ih_ipl);
350 1.1.2.1 marc hiipl = pf2->ih_ipl;
351 1.1.2.1 marc ihcnt++;
352 1.1.2.1 marc } else {
353 1.1.2.1 marc splraise(pf2->ih_ipl);
354 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
355 1.1.2.1 marc hiipl = pf2->ih_ipl;
356 1.1.2.1 marc }
357 1.1.2.1 marc }
358 1.1.2.1 marc }
359 1.1.2.1 marc
360 1.1.2.1 marc /* set up the handler for the new function */
361 1.1.2.1 marc
362 1.1.2.1 marc pf->ih_fct = ih_fct;
363 1.1.2.1 marc pf->ih_arg = ih_arg;
364 1.1.2.1 marc pf->ih_ipl = ipl;
365 1.1.2.1 marc
366 1.1.2.1 marc /* establish the real interrupt, changing the ipl if necessary */
367 1.1.2.1 marc
368 1.1.2.1 marc if (ihcnt == 0) {
369 1.1.2.1 marc #ifdef DIAGNOSTIC
370 1.1.2.1 marc if (pf->sc->ih)
371 1.1.2.1 marc panic("card has intr handler, but no function does");
372 1.1.2.1 marc #endif
373 1.1.2.1 marc
374 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
375 1.1.2.1 marc ipl, pcmcia_card_intr,
376 1.1.2.1 marc pf->sc);
377 1.1.2.1 marc } else if (ipl > hiipl) {
378 1.1.2.1 marc #ifdef DIAGNOSTIC
379 1.1.2.1 marc if (! pf->sc->ih)
380 1.1.2.1 marc panic("functions have ih, but the card does not");
381 1.1.2.1 marc #endif
382 1.1.2.1 marc
383 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
384 1.1.2.1 marc pf->sc->ih);
385 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
386 1.1.2.1 marc ipl, pcmcia_card_intr,
387 1.1.2.1 marc pf->sc);
388 1.1.2.1 marc }
389 1.1.2.1 marc
390 1.1.2.1 marc if (ihcnt)
391 1.1.2.1 marc splx(s);
392 1.1.2.1 marc
393 1.1.2.1 marc ret = pf->sc->ih;
394 1.1.2.1 marc
395 1.1.2.1 marc if (ret) {
396 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
397 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
398 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
399 1.1.2.1 marc
400 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
401 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_INTRACK;
402 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
403 1.1.2.1 marc }
404 1.1.2.1 marc } else {
405 1.1.2.1 marc ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
406 1.1.2.1 marc ipl, ih_fct, ih_arg);
407 1.1.2.1 marc }
408 1.1.2.1 marc
409 1.1.2.1 marc return(ret);
410 1.1.2.1 marc }
411 1.1.2.1 marc
412 1.1.2.1 marc void
413 1.1.2.1 marc pcmcia_intr_disestablish(pf, ih)
414 1.1.2.1 marc struct pcmcia_function *pf;
415 1.1.2.1 marc void *ih;
416 1.1.2.1 marc {
417 1.1.2.1 marc /* behave differently if this is a multifunction card */
418 1.1.2.1 marc
419 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
420 1.1.2.1 marc int s, ihcnt, hiipl;
421 1.1.2.1 marc struct pcmcia_function *pf2;
422 1.1.2.1 marc
423 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
424 1.1.2.1 marc and find the highest ipl number (lowest priority). Skip
425 1.1.2.1 marc the current function. */
426 1.1.2.1 marc
427 1.1.2.1 marc ihcnt = 0;
428 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
429 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
430 1.1.2.1 marc
431 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
432 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
433 1.1.2.1 marc if (pf2 == pf)
434 1.1.2.1 marc continue;
435 1.1.2.1 marc
436 1.1.2.1 marc if (pf2->ih_fct) {
437 1.1.2.1 marc if (!ihcnt) {
438 1.1.2.1 marc s = splraise(pf2->ih_ipl);
439 1.1.2.1 marc hiipl = pf2->ih_ipl;
440 1.1.2.1 marc ihcnt++;
441 1.1.2.1 marc } else {
442 1.1.2.1 marc splraise(pf2->ih_ipl);
443 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
444 1.1.2.1 marc hiipl = pf2->ih_ipl;
445 1.1.2.1 marc }
446 1.1.2.1 marc }
447 1.1.2.1 marc }
448 1.1.2.1 marc
449 1.1.2.1 marc /* null out the handler for this function */
450 1.1.2.1 marc
451 1.1.2.1 marc pf->ih_fct = NULL;
452 1.1.2.1 marc pf->ih_arg = NULL;
453 1.1.2.1 marc
454 1.1.2.1 marc /* if the ih being removed is lower priority than the lowest
455 1.1.2.1 marc priority remaining interrupt, up the priority. */
456 1.1.2.1 marc
457 1.1.2.1 marc #ifdef DIAGNOSTIC
458 1.1.2.1 marc if (ihcnt == 0) {
459 1.1.2.1 marc panic("can't remove a handler from a card which has none");
460 1.1.2.1 marc } else
461 1.1.2.1 marc #endif
462 1.1.2.1 marc if (ihcnt == 1) {
463 1.1.2.1 marc #ifdef DIAGNOSTIC
464 1.1.2.1 marc if (!pf->sc->ih)
465 1.1.2.1 marc panic("disestablishing last function, but card has no ih");
466 1.1.2.1 marc #endif
467 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
468 1.1.2.1 marc pf->sc->ih);
469 1.1.2.1 marc pf->sc->ih = NULL;
470 1.1.2.1 marc } else if (pf->ih_ipl > hiipl) {
471 1.1.2.1 marc #ifdef DIAGNOSTIC
472 1.1.2.1 marc if (!pf->sc->ih)
473 1.1.2.1 marc panic("changing ih ipl, but card has no ih");
474 1.1.2.1 marc #endif
475 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
476 1.1.2.1 marc pf->sc->ih);
477 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
478 1.1.2.1 marc hiipl, pcmcia_card_intr,
479 1.1.2.1 marc pf->sc);
480 1.1.2.1 marc }
481 1.1.2.1 marc
482 1.1.2.1 marc if (ihcnt)
483 1.1.2.1 marc splx(s);
484 1.1.2.1 marc } else {
485 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
486 1.1.2.1 marc }
487 1.1.2.1 marc }
488 1.1.2.1 marc
489 1.1.2.1 marc int pcmcia_card_intr(arg)
490 1.1.2.1 marc void *arg;
491 1.1.2.1 marc {
492 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
493 1.1.2.1 marc struct pcmcia_function *pf;
494 1.1.2.1 marc int reg, ret, ret2;
495 1.1.2.1 marc
496 1.1.2.1 marc ret = 0;
497 1.1.2.1 marc
498 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
499 1.1.2.1 marc #if 0
500 1.1.2.1 marc printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
501 1.1.2.1 marc sc->dev.dv_xname, pf->number,
502 1.1.2.1 marc pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
503 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
504 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_OPTION),
505 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
506 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_STATUS),
507 1.1.2.1 marc bus_space_read_1(pf->ccrt, pf->ccrh,
508 1.1.2.1 marc pf->ccr_offset+PCMCIA_CCR_PIN));
509 1.1.2.1 marc #endif
510 1.1.2.1 marc if (pf->ih_fct &&
511 1.1.2.1 marc (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
512 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
513 1.1.2.1 marc if (reg & PCMCIA_CCR_STATUS_INTR) {
514 1.1.2.1 marc ret2 = (*pf->ih_fct)(pf->ih_arg);
515 1.1.2.1 marc if (ret2 && !ret)
516 1.1.2.1 marc ret = ret2;
517 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
518 1.1.2.1 marc #if 0
519 1.1.2.1 marc printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
520 1.1.2.1 marc #endif
521 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
522 1.1.2.1 marc reg & ~PCMCIA_CCR_STATUS_INTR);
523 1.1.2.1 marc }
524 1.1.2.1 marc }
525 1.1.2.1 marc #if 0
526 1.1.2.1 marc printf("\n");
527 1.1.2.1 marc #endif
528 1.1.2.1 marc }
529 1.1.2.1 marc
530 1.1.2.1 marc return(ret);
531 1.1.2.1 marc }
532 1.1.2.1 marc
533