pcmcia.c revision 1.1.2.9 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.8 marc pcmcia_card_attach(dev)
102 1.1.2.1 marc struct device *dev;
103 1.1.2.1 marc {
104 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
105 1.1.2.1 marc struct pcmcia_function *pf;
106 1.1.2.1 marc struct pcmcia_attach_args paa;
107 1.1.2.1 marc int attached;
108 1.1.2.1 marc
109 1.1.2.8 marc /* this is here so that when socket_enable calls gettype, trt happens */
110 1.1.2.8 marc sc->card.pf_head.sqh_first = NULL;
111 1.1.2.8 marc
112 1.1.2.8 marc pcmcia_chip_socket_enable(sc->pct, sc->pch);
113 1.1.2.8 marc
114 1.1.2.1 marc pcmcia_read_cis(sc);
115 1.1.2.1 marc
116 1.1.2.8 marc pcmcia_chip_socket_disable(sc->pct, sc->pch);
117 1.1.2.8 marc
118 1.1.2.1 marc /* bail now if the card has no functions, or if there was an error
119 1.1.2.1 marc in the cis. */
120 1.1.2.1 marc
121 1.1.2.1 marc if (sc->card.error)
122 1.1.2.1 marc return(1);
123 1.1.2.1 marc if (!sc->card.pf_head.sqh_first)
124 1.1.2.1 marc return(1);
125 1.1.2.1 marc
126 1.1.2.5 thorpej if (pcmcia_verbose)
127 1.1.2.5 thorpej pcmcia_print_cis(sc);
128 1.1.2.1 marc
129 1.1.2.1 marc attached = 0;
130 1.1.2.1 marc
131 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
132 1.1.2.1 marc if (pf->cfe_head.sqh_first == NULL)
133 1.1.2.1 marc continue;
134 1.1.2.1 marc
135 1.1.2.1 marc pf->sc = sc;
136 1.1.2.1 marc pf->cfe = NULL;
137 1.1.2.1 marc pf->ih_fct = NULL;
138 1.1.2.1 marc pf->ih_arg = NULL;
139 1.1.2.1 marc }
140 1.1.2.1 marc
141 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
142 1.1.2.1 marc if (pf->cfe_head.sqh_first == NULL)
143 1.1.2.1 marc continue;
144 1.1.2.1 marc
145 1.1.2.1 marc paa.manufacturer = sc->card.manufacturer;
146 1.1.2.1 marc paa.product = sc->card.product;
147 1.1.2.1 marc paa.card = &sc->card;
148 1.1.2.1 marc paa.pf = pf;
149 1.1.2.1 marc
150 1.1.2.1 marc if (config_found_sm(&sc->dev, &paa, pcmcia_print, pcmcia_submatch)) {
151 1.1.2.1 marc attached++;
152 1.1.2.1 marc
153 1.1.2.1 marc DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
154 1.1.2.1 marc sc->dev.dv_xname, pf->number,
155 1.1.2.5 thorpej pf->pf_ccr_window, pf->pf_ccr_offset,
156 1.1.2.1 marc pcmcia_ccr_read(pf, 0x00),
157 1.1.2.1 marc pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
158 1.1.2.1 marc pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
159 1.1.2.1 marc pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
160 1.1.2.1 marc pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
161 1.1.2.1 marc }
162 1.1.2.1 marc }
163 1.1.2.1 marc
164 1.1.2.1 marc return(attached?0:1);
165 1.1.2.1 marc }
166 1.1.2.1 marc
167 1.1.2.1 marc void
168 1.1.2.8 marc pcmcia_card_detach(dev)
169 1.1.2.1 marc struct device *dev;
170 1.1.2.1 marc {
171 1.1.2.1 marc /* struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
172 1.1.2.1 marc /* don't do anything yet */
173 1.1.2.1 marc }
174 1.1.2.1 marc
175 1.1.2.1 marc int
176 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
177 1.1.2.1 marc pcmcia_submatch(parent, match, aux)
178 1.1.2.1 marc #else
179 1.1.2.1 marc pcmcia_submatch(parent, cf, aux)
180 1.1.2.1 marc #endif
181 1.1.2.1 marc struct device *parent;
182 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
183 1.1.2.1 marc void *match;
184 1.1.2.1 marc #else
185 1.1.2.1 marc struct cfdata *cf;
186 1.1.2.1 marc #endif
187 1.1.2.1 marc void *aux;
188 1.1.2.1 marc {
189 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
190 1.1.2.1 marc struct cfdata *cf = match;
191 1.1.2.1 marc #endif
192 1.1.2.1 marc
193 1.1.2.1 marc struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) aux;
194 1.1.2.1 marc
195 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
196 1.1.2.1 marc return(0);
197 1.1.2.1 marc
198 1.1.2.1 marc return ((*cf->cf_attach->ca_match)(parent, cf, aux));
199 1.1.2.1 marc }
200 1.1.2.1 marc
201 1.1.2.1 marc int
202 1.1.2.1 marc pcmcia_print(arg, pnp)
203 1.1.2.1 marc void *arg;
204 1.1.2.1 marc const char *pnp;
205 1.1.2.1 marc {
206 1.1.2.5 thorpej struct pcmcia_attach_args *pa = (struct pcmcia_attach_args *) arg;
207 1.1.2.5 thorpej struct pcmcia_softc *sc = pa->pf->sc;
208 1.1.2.5 thorpej struct pcmcia_card *card = &sc->card;
209 1.1.2.5 thorpej int i;
210 1.1.2.5 thorpej
211 1.1.2.5 thorpej if (pnp) {
212 1.1.2.5 thorpej for (i = 0; i < 4; i++) {
213 1.1.2.5 thorpej if (!card->cis1_info[i])
214 1.1.2.5 thorpej break;
215 1.1.2.5 thorpej if (i)
216 1.1.2.5 thorpej printf(", ");
217 1.1.2.5 thorpej printf("%s", card->cis1_info[i]);
218 1.1.2.5 thorpej }
219 1.1.2.5 thorpej if (i)
220 1.1.2.5 thorpej printf(" ");
221 1.1.2.5 thorpej printf("(manufacturer 0x%x, product 0x%x)", card->manufacturer,
222 1.1.2.5 thorpej card->product);
223 1.1.2.5 thorpej }
224 1.1.2.1 marc
225 1.1.2.5 thorpej printf(" function %d", pa->pf->number);
226 1.1.2.1 marc
227 1.1.2.1 marc return(UNCONF);
228 1.1.2.1 marc }
229 1.1.2.1 marc
230 1.1.2.8 marc int pcmcia_card_gettype(dev)
231 1.1.2.8 marc struct device *dev;
232 1.1.2.8 marc {
233 1.1.2.8 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
234 1.1.2.8 marc
235 1.1.2.8 marc /* set the iftype to memory if this card has no functions (not yet
236 1.1.2.8 marc probed), or only one function, and that is memory. */
237 1.1.2.8 marc if (!sc->card.pf_head.sqh_first ||
238 1.1.2.8 marc (sc->card.pf_head.sqh_first &&
239 1.1.2.8 marc !sc->card.pf_head.sqh_first->pf_list.sqe_next &&
240 1.1.2.8 marc (sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
241 1.1.2.8 marc PCMCIA_IFTYPE_MEMORY)))
242 1.1.2.8 marc return(PCMCIA_IFTYPE_MEMORY);
243 1.1.2.8 marc else
244 1.1.2.8 marc return(PCMCIA_IFTYPE_IO);
245 1.1.2.8 marc }
246 1.1.2.8 marc
247 1.1.2.7 thorpej /* Initialize a PCMCIA function. May be called as long as the function
248 1.1.2.7 thorpej is disabled. */
249 1.1.2.7 thorpej void
250 1.1.2.7 thorpej pcmcia_function_init(pf, cfe)
251 1.1.2.1 marc struct pcmcia_function *pf;
252 1.1.2.1 marc struct pcmcia_config_entry *cfe;
253 1.1.2.1 marc {
254 1.1.2.7 thorpej
255 1.1.2.7 thorpej if (pf->pf_flags & PFF_ENABLED)
256 1.1.2.7 thorpej panic("pcmcia_function_init: function is enabled");
257 1.1.2.7 thorpej
258 1.1.2.7 thorpej /* Remember which configuration entry we are using. */
259 1.1.2.7 thorpej pf->cfe = cfe;
260 1.1.2.7 thorpej }
261 1.1.2.7 thorpej
262 1.1.2.7 thorpej /* Enable a PCMCIA function */
263 1.1.2.7 thorpej int
264 1.1.2.7 thorpej pcmcia_function_enable(pf)
265 1.1.2.7 thorpej struct pcmcia_function *pf;
266 1.1.2.7 thorpej {
267 1.1.2.1 marc struct pcmcia_function *tmp;
268 1.1.2.1 marc int reg;
269 1.1.2.1 marc
270 1.1.2.7 thorpej if (pf->cfe == NULL)
271 1.1.2.7 thorpej panic("pcmcia_function_enable: function not initialized");
272 1.1.2.9 thorpej if (pf->pf_flags & PFF_ENABLED) {
273 1.1.2.9 thorpej /*
274 1.1.2.9 thorpej * Don't do anything if we're already enabled.
275 1.1.2.9 thorpej */
276 1.1.2.9 thorpej return (0);
277 1.1.2.9 thorpej }
278 1.1.2.7 thorpej
279 1.1.2.7 thorpej /* Increase the reference count on the socket, enabling power,
280 1.1.2.7 thorpej if necessary. */
281 1.1.2.7 thorpej if (pf->sc->sc_enabled_count++ == 0)
282 1.1.2.7 thorpej pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
283 1.1.2.1 marc
284 1.1.2.1 marc /* it's possible for different functions' CCRs to be in the same
285 1.1.2.1 marc underlying page. Check for that. */
286 1.1.2.1 marc
287 1.1.2.1 marc for (tmp = pf->sc->card.pf_head.sqh_first;
288 1.1.2.1 marc tmp;
289 1.1.2.1 marc tmp = tmp->pf_list.sqe_next) {
290 1.1.2.7 thorpej if ((tmp->pf_flags & PFF_ENABLED) &&
291 1.1.2.5 thorpej (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
292 1.1.2.1 marc ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
293 1.1.2.5 thorpej (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize))) {
294 1.1.2.5 thorpej pf->pf_ccrt = tmp->pf_ccrt;
295 1.1.2.5 thorpej pf->pf_ccrh = tmp->pf_ccrh;
296 1.1.2.5 thorpej pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
297 1.1.2.5 thorpej
298 1.1.2.5 thorpej /* pf->pf_ccr_offset =
299 1.1.2.5 thorpej (tmp->pf_ccr_offset - tmp->ccr_base) + pf->ccr_base; */
300 1.1.2.5 thorpej pf->pf_ccr_offset =
301 1.1.2.5 thorpej (tmp->pf_ccr_offset + pf->ccr_base) - tmp->ccr_base;
302 1.1.2.5 thorpej pf->pf_ccr_window = tmp->pf_ccr_window;
303 1.1.2.1 marc break;
304 1.1.2.1 marc }
305 1.1.2.1 marc }
306 1.1.2.1 marc
307 1.1.2.1 marc if (tmp == NULL) {
308 1.1.2.5 thorpej if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
309 1.1.2.7 thorpej goto bad;
310 1.1.2.1 marc
311 1.1.2.5 thorpej if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
312 1.1.2.5 thorpej PCMCIA_CCR_SIZE, &pf->pf_pcmh,
313 1.1.2.7 thorpej &pf->pf_ccr_offset, &pf->pf_ccr_window)) {
314 1.1.2.7 thorpej pcmcia_mem_free(pf, &pf->pf_pcmh);
315 1.1.2.7 thorpej goto bad;
316 1.1.2.7 thorpej }
317 1.1.2.1 marc }
318 1.1.2.1 marc
319 1.1.2.1 marc DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
320 1.1.2.1 marc pf->sc->dev.dv_xname, pf->number,
321 1.1.2.5 thorpej pf->pf_ccr_window, pf->pf_ccr_offset,
322 1.1.2.1 marc pcmcia_ccr_read(pf, 0x00),
323 1.1.2.1 marc pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
324 1.1.2.1 marc pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
325 1.1.2.1 marc pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
326 1.1.2.1 marc pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
327 1.1.2.1 marc
328 1.1.2.1 marc reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
329 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_LEVIREQ;
330 1.1.2.1 marc if (pcmcia_mfc(pf->sc))
331 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
332 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
333 1.1.2.1 marc
334 1.1.2.1 marc reg = 0;
335 1.1.2.8 marc
336 1.1.2.1 marc if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
337 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_IOIS8;
338 1.1.2.1 marc if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
339 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_AUDIO;
340 1.1.2.7 thorpej /* Not really needed, since we start with 0. */
341 1.1.2.7 thorpej if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN)
342 1.1.2.7 thorpej reg &= ~PCMCIA_CCR_STATUS_PWRDWN;
343 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
344 1.1.2.1 marc
345 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
346 1.1.2.1 marc
347 1.1.2.7 thorpej pf->pf_flags |= PFF_ENABLED;
348 1.1.2.1 marc return(0);
349 1.1.2.7 thorpej
350 1.1.2.7 thorpej bad:
351 1.1.2.8 marc /* Decrement the reference count, and power down the socket,
352 1.1.2.7 thorpej if necessary. */
353 1.1.2.7 thorpej if (pf->sc->sc_enabled_count-- == 1)
354 1.1.2.7 thorpej pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
355 1.1.2.7 thorpej return (1);
356 1.1.2.7 thorpej }
357 1.1.2.7 thorpej
358 1.1.2.7 thorpej /* Disable PCMCIA function. */
359 1.1.2.7 thorpej void
360 1.1.2.7 thorpej pcmcia_function_disable(pf)
361 1.1.2.7 thorpej struct pcmcia_function *pf;
362 1.1.2.7 thorpej {
363 1.1.2.7 thorpej struct pcmcia_function *tmp;
364 1.1.2.7 thorpej int reg;
365 1.1.2.7 thorpej
366 1.1.2.7 thorpej if (pf->cfe == NULL)
367 1.1.2.7 thorpej panic("pcmcia_function_enable: function not initialized");
368 1.1.2.9 thorpej if ((pf->pf_flags & PFF_ENABLED) == 0) {
369 1.1.2.9 thorpej /*
370 1.1.2.9 thorpej * Don't do anything if we're already disabled.
371 1.1.2.9 thorpej */
372 1.1.2.9 thorpej return;
373 1.1.2.9 thorpej }
374 1.1.2.7 thorpej
375 1.1.2.7 thorpej /* Power down the function if the card supports it. */
376 1.1.2.7 thorpej if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN) {
377 1.1.2.7 thorpej reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
378 1.1.2.7 thorpej reg |= PCMCIA_CCR_STATUS_PWRDWN;
379 1.1.2.7 thorpej pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
380 1.1.2.7 thorpej }
381 1.1.2.7 thorpej
382 1.1.2.7 thorpej /* it's possible for different functions' CCRs to be in the same
383 1.1.2.7 thorpej underlying page. Check for that. Note we mark us as disabled
384 1.1.2.7 thorpej first to avoid matching ourself. */
385 1.1.2.7 thorpej
386 1.1.2.7 thorpej pf->pf_flags &= ~PFF_ENABLED;
387 1.1.2.7 thorpej for (tmp = pf->sc->card.pf_head.sqh_first;
388 1.1.2.7 thorpej tmp;
389 1.1.2.7 thorpej tmp = tmp->pf_list.sqe_next) {
390 1.1.2.7 thorpej if ((tmp->pf_flags & PFF_ENABLED) &&
391 1.1.2.7 thorpej (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
392 1.1.2.7 thorpej ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
393 1.1.2.7 thorpej (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
394 1.1.2.7 thorpej break;
395 1.1.2.7 thorpej }
396 1.1.2.7 thorpej
397 1.1.2.7 thorpej /* Not used by anyone else; unmap the CCR. */
398 1.1.2.7 thorpej if (tmp == NULL) {
399 1.1.2.7 thorpej pcmcia_mem_unmap(pf, pf->pf_ccr_window);
400 1.1.2.7 thorpej pcmcia_mem_free(pf, &pf->pf_pcmh);
401 1.1.2.7 thorpej }
402 1.1.2.7 thorpej
403 1.1.2.8 marc /* Decrement the reference count, and power down the socket,
404 1.1.2.7 thorpej if necessary. */
405 1.1.2.8 marc if (--pf->sc->sc_enabled_count == 0)
406 1.1.2.7 thorpej pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
407 1.1.2.1 marc }
408 1.1.2.1 marc
409 1.1.2.1 marc int
410 1.1.2.5 thorpej pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
411 1.1.2.1 marc struct pcmcia_function *pf;
412 1.1.2.1 marc int width;
413 1.1.2.5 thorpej bus_addr_t offset;
414 1.1.2.1 marc bus_size_t size;
415 1.1.2.5 thorpej struct pcmcia_io_handle *pcihp;
416 1.1.2.1 marc int *windowp;
417 1.1.2.1 marc {
418 1.1.2.5 thorpej bus_addr_t ioaddr;
419 1.1.2.1 marc int reg;
420 1.1.2.1 marc
421 1.1.2.1 marc if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
422 1.1.2.5 thorpej width, offset, size, pcihp, windowp))
423 1.1.2.1 marc return(1);
424 1.1.2.1 marc
425 1.1.2.5 thorpej ioaddr = pcihp->addr + offset;
426 1.1.2.5 thorpej
427 1.1.2.1 marc /* XXX in the multifunction multi-iospace-per-function case, this
428 1.1.2.1 marc needs to cooperate with io_alloc to make sure that the spaces
429 1.1.2.1 marc don't overlap, and that the ccr's are set correctly */
430 1.1.2.1 marc
431 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
432 1.1.2.5 thorpej pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioaddr & 0xff);
433 1.1.2.5 thorpej pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioaddr >> 8) & 0xff);
434 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
435 1.1.2.1 marc
436 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
437 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
438 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
439 1.1.2.1 marc }
440 1.1.2.1 marc
441 1.1.2.1 marc return(0);
442 1.1.2.1 marc }
443 1.1.2.1 marc
444 1.1.2.1 marc void *
445 1.1.2.1 marc pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
446 1.1.2.1 marc struct pcmcia_function *pf;
447 1.1.2.1 marc int ipl;
448 1.1.2.1 marc int (*ih_fct) __P((void *));
449 1.1.2.1 marc void *ih_arg;
450 1.1.2.1 marc {
451 1.1.2.1 marc void *ret;
452 1.1.2.1 marc
453 1.1.2.1 marc /* behave differently if this is a multifunction card */
454 1.1.2.1 marc
455 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
456 1.1.2.1 marc int s, ihcnt, hiipl, reg;
457 1.1.2.1 marc struct pcmcia_function *pf2;
458 1.1.2.1 marc
459 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
460 1.1.2.1 marc and find the highest ipl number (lowest priority) */
461 1.1.2.1 marc
462 1.1.2.1 marc ihcnt = 0;
463 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
464 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
465 1.1.2.1 marc
466 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
467 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
468 1.1.2.1 marc if (pf2->ih_fct) {
469 1.1.2.1 marc if (!ihcnt) {
470 1.1.2.1 marc s = splraise(pf2->ih_ipl);
471 1.1.2.1 marc hiipl = pf2->ih_ipl;
472 1.1.2.1 marc ihcnt++;
473 1.1.2.1 marc } else {
474 1.1.2.1 marc splraise(pf2->ih_ipl);
475 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
476 1.1.2.1 marc hiipl = pf2->ih_ipl;
477 1.1.2.1 marc }
478 1.1.2.1 marc }
479 1.1.2.1 marc }
480 1.1.2.1 marc
481 1.1.2.1 marc /* set up the handler for the new function */
482 1.1.2.1 marc
483 1.1.2.1 marc pf->ih_fct = ih_fct;
484 1.1.2.1 marc pf->ih_arg = ih_arg;
485 1.1.2.1 marc pf->ih_ipl = ipl;
486 1.1.2.1 marc
487 1.1.2.1 marc /* establish the real interrupt, changing the ipl if necessary */
488 1.1.2.1 marc
489 1.1.2.1 marc if (ihcnt == 0) {
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("card has intr handler, but no function does");
493 1.1.2.1 marc #endif
494 1.1.2.1 marc
495 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
496 1.1.2.6 thorpej pf, ipl,
497 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
498 1.1.2.1 marc } else if (ipl > hiipl) {
499 1.1.2.1 marc #ifdef DIAGNOSTIC
500 1.1.2.1 marc if (! pf->sc->ih)
501 1.1.2.1 marc panic("functions have ih, but the card does not");
502 1.1.2.1 marc #endif
503 1.1.2.1 marc
504 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
505 1.1.2.1 marc pf->sc->ih);
506 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
507 1.1.2.6 thorpej pf, ipl,
508 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
509 1.1.2.1 marc }
510 1.1.2.1 marc
511 1.1.2.1 marc if (ihcnt)
512 1.1.2.1 marc splx(s);
513 1.1.2.1 marc
514 1.1.2.1 marc ret = pf->sc->ih;
515 1.1.2.1 marc
516 1.1.2.1 marc if (ret) {
517 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
518 1.1.2.1 marc reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
519 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
520 1.1.2.1 marc
521 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
522 1.1.2.1 marc reg |= PCMCIA_CCR_STATUS_INTRACK;
523 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
524 1.1.2.1 marc }
525 1.1.2.1 marc } else {
526 1.1.2.1 marc ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
527 1.1.2.6 thorpej pf, ipl, ih_fct, ih_arg);
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 1.1.2.1 marc void
534 1.1.2.1 marc pcmcia_intr_disestablish(pf, ih)
535 1.1.2.1 marc struct pcmcia_function *pf;
536 1.1.2.1 marc void *ih;
537 1.1.2.1 marc {
538 1.1.2.4 thorpej
539 1.1.2.1 marc /* behave differently if this is a multifunction card */
540 1.1.2.1 marc
541 1.1.2.1 marc if (pcmcia_mfc(pf->sc)) {
542 1.1.2.1 marc int s, ihcnt, hiipl;
543 1.1.2.1 marc struct pcmcia_function *pf2;
544 1.1.2.1 marc
545 1.1.2.1 marc /* mask all the ipl's which are already used by this card,
546 1.1.2.1 marc and find the highest ipl number (lowest priority). Skip
547 1.1.2.1 marc the current function. */
548 1.1.2.1 marc
549 1.1.2.1 marc ihcnt = 0;
550 1.1.2.1 marc s = 0; /* this is only here to keep the compipler happy */
551 1.1.2.1 marc hiipl = 0; /* this is only here to keep the compipler happy */
552 1.1.2.1 marc
553 1.1.2.1 marc for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
554 1.1.2.1 marc pf2 = pf2->pf_list.sqe_next) {
555 1.1.2.1 marc if (pf2 == pf)
556 1.1.2.1 marc continue;
557 1.1.2.1 marc
558 1.1.2.1 marc if (pf2->ih_fct) {
559 1.1.2.1 marc if (!ihcnt) {
560 1.1.2.1 marc s = splraise(pf2->ih_ipl);
561 1.1.2.1 marc hiipl = pf2->ih_ipl;
562 1.1.2.1 marc ihcnt++;
563 1.1.2.1 marc } else {
564 1.1.2.1 marc splraise(pf2->ih_ipl);
565 1.1.2.1 marc if (pf2->ih_ipl > hiipl)
566 1.1.2.1 marc hiipl = pf2->ih_ipl;
567 1.1.2.1 marc }
568 1.1.2.1 marc }
569 1.1.2.1 marc }
570 1.1.2.1 marc
571 1.1.2.1 marc /* null out the handler for this function */
572 1.1.2.1 marc
573 1.1.2.1 marc pf->ih_fct = NULL;
574 1.1.2.1 marc pf->ih_arg = NULL;
575 1.1.2.1 marc
576 1.1.2.1 marc /* if the ih being removed is lower priority than the lowest
577 1.1.2.1 marc priority remaining interrupt, up the priority. */
578 1.1.2.1 marc
579 1.1.2.1 marc #ifdef DIAGNOSTIC
580 1.1.2.1 marc if (ihcnt == 0) {
581 1.1.2.1 marc panic("can't remove a handler from a card which has none");
582 1.1.2.1 marc } else
583 1.1.2.1 marc #endif
584 1.1.2.1 marc if (ihcnt == 1) {
585 1.1.2.1 marc #ifdef DIAGNOSTIC
586 1.1.2.1 marc if (!pf->sc->ih)
587 1.1.2.1 marc panic("disestablishing last function, but card has no ih");
588 1.1.2.1 marc #endif
589 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
590 1.1.2.1 marc pf->sc->ih);
591 1.1.2.1 marc pf->sc->ih = NULL;
592 1.1.2.1 marc } else if (pf->ih_ipl > hiipl) {
593 1.1.2.1 marc #ifdef DIAGNOSTIC
594 1.1.2.1 marc if (!pf->sc->ih)
595 1.1.2.1 marc panic("changing ih ipl, but card has no ih");
596 1.1.2.1 marc #endif
597 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
598 1.1.2.1 marc pf->sc->ih);
599 1.1.2.1 marc pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
600 1.1.2.6 thorpej pf, hiipl,
601 1.1.2.4 thorpej pcmcia_card_intr, pf->sc);
602 1.1.2.1 marc }
603 1.1.2.1 marc
604 1.1.2.1 marc if (ihcnt)
605 1.1.2.1 marc splx(s);
606 1.1.2.1 marc } else {
607 1.1.2.1 marc pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
608 1.1.2.1 marc }
609 1.1.2.1 marc }
610 1.1.2.1 marc
611 1.1.2.1 marc int pcmcia_card_intr(arg)
612 1.1.2.1 marc void *arg;
613 1.1.2.1 marc {
614 1.1.2.1 marc struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
615 1.1.2.1 marc struct pcmcia_function *pf;
616 1.1.2.1 marc int reg, ret, ret2;
617 1.1.2.1 marc
618 1.1.2.1 marc ret = 0;
619 1.1.2.1 marc
620 1.1.2.1 marc for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
621 1.1.2.1 marc #if 0
622 1.1.2.1 marc printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
623 1.1.2.1 marc sc->dev.dv_xname, pf->number,
624 1.1.2.1 marc pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
625 1.1.2.5 thorpej bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
626 1.1.2.5 thorpej pf->pf_ccr_offset+PCMCIA_CCR_OPTION),
627 1.1.2.5 thorpej bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
628 1.1.2.5 thorpej pf->pf_ccr_offset+PCMCIA_CCR_STATUS),
629 1.1.2.5 thorpej bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
630 1.1.2.5 thorpej pf->pf_ccr_offset+PCMCIA_CCR_PIN));
631 1.1.2.1 marc #endif
632 1.1.2.1 marc if (pf->ih_fct &&
633 1.1.2.1 marc (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
634 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
635 1.1.2.1 marc if (reg & PCMCIA_CCR_STATUS_INTR) {
636 1.1.2.1 marc ret2 = (*pf->ih_fct)(pf->ih_arg);
637 1.1.2.1 marc if (ret2 && !ret)
638 1.1.2.1 marc ret = ret2;
639 1.1.2.1 marc reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
640 1.1.2.1 marc #if 0
641 1.1.2.1 marc printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
642 1.1.2.1 marc #endif
643 1.1.2.1 marc pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
644 1.1.2.1 marc reg & ~PCMCIA_CCR_STATUS_INTR);
645 1.1.2.1 marc }
646 1.1.2.1 marc }
647 1.1.2.1 marc #if 0
648 1.1.2.1 marc printf("\n");
649 1.1.2.1 marc #endif
650 1.1.2.1 marc }
651 1.1.2.1 marc
652 1.1.2.1 marc return(ret);
653 1.1.2.1 marc }
654