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