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