1 /* $OpenBSD: cardslot.c,v 1.23 2022/04/06 18:59:27 naddy Exp $ */
2 /* $NetBSD: cardslot.c,v 1.9 2000/03/22 09:35:06 haya Exp $ */
3
4 /*
5 * Copyright (c) 1999 and 2000
6 * HAYAKAWA Koichi. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
36 #include <sys/syslog.h>
37 #include <sys/pool.h>
38 #include <sys/task.h>
39
40 #include <dev/cardbus/cardslotvar.h>
41 #include <dev/cardbus/cardbusvar.h>
42 #include <dev/pcmcia/pcmciavar.h>
43 #include <dev/pcmcia/pcmciachip.h>
44 #include <dev/ic/i82365var.h>
45
46 #if defined CARDSLOT_DEBUG
47 #define STATIC
48 #define DPRINTF(a) printf a
49 #else
50 #ifdef DDB
51 #define STATIC
52 #else
53 #define STATIC static
54 #endif
55 #define DPRINTF(a)
56 #endif
57
58 STATIC void cardslotattach(struct device *, struct device *, void *);
59
60 STATIC int cardslotmatch(struct device *, void *, void *);
61 STATIC void cardslot_event(void *arg);
62 STATIC void cardslot_process_event(struct cardslot_softc *);
63
64 STATIC int cardslot_cb_print(void *aux, const char *pcic);
65 STATIC int cardslot_16_print(void *, const char *);
66 STATIC int cardslot_16_submatch(struct device *, void *,void *);
67
68 const struct cfattach cardslot_ca = {
69 sizeof(struct cardslot_softc), cardslotmatch, cardslotattach
70 };
71
72 struct cfdriver cardslot_cd = {
73 NULL, "cardslot", DV_DULL
74 };
75
76 struct pool cardsloteventpool;
77
78 STATIC int
79 cardslotmatch(struct device *parent, void *match, void *aux)
80 {
81 struct cardslot_attach_args *caa = aux;
82
83 if (caa->caa_cb_attach == NULL && caa->caa_16_attach == NULL) {
84 /* Neither CardBus nor 16-bit PCMCIA are defined. */
85 return (0);
86 }
87
88 return (1);
89 }
90
91 STATIC void
92 cardslotattach(struct device *parent, struct device *self, void *aux)
93 {
94 struct cardslot_softc *sc = (struct cardslot_softc *)self;
95 struct cardslot_attach_args *caa = aux;
96
97 struct cbslot_attach_args *cba = caa->caa_cb_attach;
98 struct pcmciabus_attach_args *pa = caa->caa_16_attach;
99
100 struct cardbus_softc *csc = NULL;
101 struct pcmcia_softc *psc = NULL;
102
103 if (cardsloteventpool.pr_size == 0) {
104 pool_init(&cardsloteventpool, sizeof(struct cardslot_event),
105 0, IPL_BIO, 0, "cardslot", NULL);
106 }
107
108 sc->sc_slot = sc->sc_dev.dv_unit;
109 sc->sc_cb_softc = NULL;
110 sc->sc_16_softc = NULL;
111 SIMPLEQ_INIT(&sc->sc_events);
112 task_set(&sc->sc_event_task, cardslot_event, sc);
113
114 printf(" slot %d flags %x\n", sc->sc_slot,
115 sc->sc_dev.dv_cfdata->cf_flags);
116
117 DPRINTF(("%s attaching CardBus bus...\n", sc->sc_dev.dv_xname));
118 if (cba != NULL) {
119 if ((csc = (void *)config_found(self, cba,
120 cardslot_cb_print)) != NULL) {
121 /* cardbus found */
122 DPRINTF(("cardslotattach: found cardbus on %s\n",
123 sc->sc_dev.dv_xname));
124 sc->sc_cb_softc = csc;
125 }
126 }
127
128 if (pa != NULL) {
129 if ((psc = (void *)config_found_sm(self, pa, cardslot_16_print,
130 cardslot_16_submatch)) != NULL) {
131 /* pcmcia 16-bit bus found */
132 DPRINTF(("cardslotattach: found 16-bit pcmcia bus\n"));
133 sc->sc_16_softc = psc;
134 /* XXX: dirty. This code should be removed
135 * to achieve MI
136 */
137 caa->caa_ph->pcmcia = (struct device *)psc;
138 }
139 }
140
141 if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) {
142 DPRINTF(("cardslotattach: CardBus card found\n"));
143 /* attach deferred */
144 cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB);
145 }
146
147 if (psc && (psc->pct->card_detect)(psc->pch)) {
148 DPRINTF(("cardbusattach: 16-bit card found\n"));
149 /* attach deferred */
150 cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16);
151 }
152 }
153
154 STATIC int
155 cardslot_cb_print(void *aux, const char *pnp)
156 {
157 struct cbslot_attach_args *cba = aux;
158
159 if (pnp)
160 printf("cardbus at %s subordinate bus %d", pnp, cba->cba_bus);
161
162 return (UNCONF);
163 }
164
165 STATIC int
166 cardslot_16_submatch(struct device *parent, void *match, void *aux)
167 {
168 struct cfdata *cf = match;
169
170 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
171 return (0);
172
173 if (cf->cf_loc[0] == -1)
174 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
175
176 return (0);
177 }
178
179 STATIC int
180 cardslot_16_print(void *arg, const char *pnp)
181 {
182 if (pnp)
183 printf("pcmciabus at %s", pnp);
184
185 return (UNCONF);
186 }
187
188 /*
189 * void cardslot_event_throw(struct cardslot_softc *sc, int ev)
190 *
191 * This function throws an event to the event handler. If the state
192 * of a slot is changed, it should be noticed using this function.
193 */
194 void
195 cardslot_event_throw(struct cardslot_softc *sc, int ev)
196 {
197 struct cardslot_event *ce;
198 int s;
199
200 DPRINTF(("cardslot_event_throw: an event %s comes\n",
201 ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" :
202 ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" :
203 ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" :
204 ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???"));
205
206 ce = pool_get(&cardsloteventpool, PR_NOWAIT);
207 if (ce == NULL)
208 return;
209 ce->ce_type = ev;
210
211 s = spltty();
212 SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q);
213 splx(s);
214
215 task_add(systq, &sc->sc_event_task);
216 }
217
218 /*
219 * STATIC void cardslot_event(void *arg)
220 *
221 * This function is the main routine handing cardslot events such as
222 * insertions and removals.
223 *
224 */
225 STATIC void
226 cardslot_event(void *arg1)
227 {
228 struct cardslot_softc *sc = arg1;
229
230 while (!SIMPLEQ_EMPTY(&sc->sc_events))
231 cardslot_process_event(sc);
232 }
233
234
235 STATIC void
236 cardslot_process_event(struct cardslot_softc *sc)
237 {
238 struct cardslot_event *ce;
239 int s, ev;
240
241 s = spltty();
242 if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) {
243 splx(s);
244 return;
245 }
246 SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
247
248 if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) {
249 /* Chattering suppression */
250 static int antonym_ev[4] = {
251 CARDSLOT_EVENT_REMOVAL_16,
252 CARDSLOT_EVENT_INSERTION_16,
253 CARDSLOT_EVENT_REMOVAL_CB,
254 CARDSLOT_EVENT_INSERTION_CB
255 };
256
257 while (1) {
258 struct cardslot_event *ce1, *ce2;
259
260 if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) ==
261 NULL)
262 break;
263 if (ce1->ce_type != antonym_ev[ce->ce_type])
264 break;
265 if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL)
266 break;
267 if (ce2->ce_type == ce->ce_type) {
268 SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
269 pool_put(&cardsloteventpool, ce1);
270 SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
271 pool_put(&cardsloteventpool, ce2);
272 }
273 }
274 }
275 splx(s);
276
277 ev = ce->ce_type;
278 pool_put(&cardsloteventpool, ce);
279
280 switch (ev) {
281 case CARDSLOT_EVENT_INSERTION_CB:
282 if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
283 CARDSLOT_STATUS_CARD_CB) ||
284 (CARDSLOT_CARDTYPE(sc->sc_status) ==
285 CARDSLOT_STATUS_CARD_16)) {
286 if (CARDSLOT_WORK(sc->sc_status) ==
287 CARDSLOT_STATUS_WORKING) {
288 /* A card has already been inserted
289 * and works.
290 */
291 break;
292 }
293 }
294
295 if (sc->sc_cb_softc) {
296 CARDSLOT_SET_CARDTYPE(sc->sc_status,
297 CARDSLOT_STATUS_CARD_CB);
298 if (cardbus_attach_card(sc->sc_cb_softc) > 0) {
299 /* At least one function works */
300 CARDSLOT_SET_WORK(sc->sc_status,
301 CARDSLOT_STATUS_WORKING);
302 } else {
303 /* No functions work or this card is
304 * not known
305 */
306 CARDSLOT_SET_WORK(sc->sc_status,
307 CARDSLOT_STATUS_NOTWORK);
308 }
309 } else {
310 printf("%s: CardBus support disabled\n",
311 sc->sc_dev.dv_xname);
312 }
313 break;
314
315 case CARDSLOT_EVENT_INSERTION_16:
316 if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
317 CARDSLOT_STATUS_CARD_CB) ||
318 (CARDSLOT_CARDTYPE(sc->sc_status) ==
319 CARDSLOT_STATUS_CARD_16)) {
320 if (CARDSLOT_WORK(sc->sc_status) ==
321 CARDSLOT_STATUS_WORKING) {
322 /* A card has already been inserted
323 * and works.
324 */
325 break;
326 }
327 }
328 if (sc->sc_16_softc) {
329 CARDSLOT_SET_CARDTYPE(sc->sc_status,
330 CARDSLOT_STATUS_CARD_16);
331 if (pcmcia_card_attach(
332 (struct device *)sc->sc_16_softc)) {
333 /* Do not attach */
334 CARDSLOT_SET_WORK(sc->sc_status,
335 CARDSLOT_STATUS_NOTWORK);
336 } else {
337 /* working */
338 CARDSLOT_SET_WORK(sc->sc_status,
339 CARDSLOT_STATUS_WORKING);
340 }
341 } else {
342 panic("no 16-bit pcmcia on %s",
343 sc->sc_dev.dv_xname);
344 }
345 break;
346
347 case CARDSLOT_EVENT_REMOVAL_CB:
348 if (CARDSLOT_CARDTYPE(sc->sc_status) ==
349 CARDSLOT_STATUS_CARD_CB) {
350 /* CardBus card has not been inserted. */
351 if (CARDSLOT_WORK(sc->sc_status) ==
352 CARDSLOT_STATUS_WORKING) {
353 cardbus_detach_card(sc->sc_cb_softc);
354 CARDSLOT_SET_WORK(sc->sc_status,
355 CARDSLOT_STATUS_NOTWORK);
356 CARDSLOT_SET_WORK(sc->sc_status,
357 CARDSLOT_STATUS_CARD_NONE);
358 }
359 CARDSLOT_SET_CARDTYPE(sc->sc_status,
360 CARDSLOT_STATUS_CARD_NONE);
361 } else if (CARDSLOT_CARDTYPE(sc->sc_status) !=
362 CARDSLOT_STATUS_CARD_16) {
363 /* Unknown card... */
364 CARDSLOT_SET_CARDTYPE(sc->sc_status,
365 CARDSLOT_STATUS_CARD_NONE);
366 }
367 CARDSLOT_SET_WORK(sc->sc_status,
368 CARDSLOT_STATUS_NOTWORK);
369 break;
370
371 case CARDSLOT_EVENT_REMOVAL_16:
372 DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname));
373 if (CARDSLOT_CARDTYPE(sc->sc_status) !=
374 CARDSLOT_STATUS_CARD_16) {
375 /* 16-bit card has not been inserted. */
376 break;
377 }
378 if ((sc->sc_16_softc != NULL) &&
379 (CARDSLOT_WORK(sc->sc_status) ==
380 CARDSLOT_STATUS_WORKING)) {
381 struct pcmcia_softc *psc = sc->sc_16_softc;
382
383 pcmcia_card_deactivate((struct device *)psc);
384 pcmcia_chip_socket_disable(psc->pct, psc->pch);
385 pcmcia_card_detach((struct device *)psc,
386 DETACH_FORCE);
387 }
388 CARDSLOT_SET_CARDTYPE(sc->sc_status,
389 CARDSLOT_STATUS_CARD_NONE);
390 CARDSLOT_SET_WORK(sc->sc_status,
391 CARDSLOT_STATUS_NOTWORK);
392 break;
393
394 default:
395 panic("cardslot_event_thread: unknown event %d", ev);
396 }
397 }
Cache object: b0c0a99a94b15f5c0fa72ca7d8e187c8
|