Annotation of sys/dev/cardbus/cardslot.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cardslot.c,v 1.7 2005/09/19 19:05:39 fgsch 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: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by HAYAKAWA Koichi.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <sys/param.h>
37: #include <sys/systm.h>
38: #include <sys/device.h>
39: #include <sys/malloc.h>
40: #include <sys/kernel.h>
41: #include <sys/syslog.h>
42: #include <sys/kthread.h>
43:
44: #include <machine/bus.h>
45:
46: #include <dev/cardbus/cardslotvar.h>
47: #include <dev/cardbus/cardbusvar.h>
48: #include <dev/pcmcia/pcmciavar.h>
49: #include <dev/pcmcia/pcmciachip.h>
50: #include <dev/ic/i82365var.h>
51:
52: #if defined CARDSLOT_DEBUG
53: #define STATIC
54: #define DPRINTF(a) printf a
55: #else
56: #define STATIC static
57: #define DPRINTF(a)
58: #endif
59:
60: STATIC void cardslotattach(struct device *, struct device *, void *);
61:
62: STATIC int cardslotmatch(struct device *, void *, void *);
63: static void create_slot_manager(void *);
64: static void cardslot_event_thread(void *arg);
65:
66: STATIC int cardslot_cb_print(void *aux, const char *pcic);
67: static int cardslot_16_print(void *, const char *);
68: static int cardslot_16_submatch(struct device *, void *,void *);
69:
70: struct cfattach cardslot_ca = {
71: sizeof(struct cardslot_softc), cardslotmatch, cardslotattach
72: };
73:
74: struct cfdriver cardslot_cd = {
75: NULL, "cardslot", DV_DULL
76: };
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;
101: struct pcmcia_softc *psc;
102:
103: sc->sc_slot = sc->sc_dev.dv_unit;
104: sc->sc_cb_softc = NULL;
105: sc->sc_16_softc = NULL;
106: SIMPLEQ_INIT(&sc->sc_events);
107: sc->sc_th_enable = 0;
108:
109: printf(" slot %d flags %x\n", sc->sc_slot,
110: sc->sc_dev.dv_cfdata->cf_flags);
111:
112: DPRINTF(("%s attaching CardBus bus...\n", sc->sc_dev.dv_xname));
113: if (cba != NULL) {
114: if ((csc = (void *)config_found(self, cba,
115: cardslot_cb_print)) != NULL) {
116: /* cardbus found */
117: DPRINTF(("cardslotattach: found cardbus on %s\n",
118: sc->sc_dev.dv_xname));
119: sc->sc_cb_softc = csc;
120: }
121: }
122:
123: if (pa != NULL) {
124: if ((psc = (void *)config_found_sm(self, pa, cardslot_16_print,
125: cardslot_16_submatch)) != NULL) {
126: /* pcmcia 16-bit bus found */
127: DPRINTF(("cardslotattach: found 16-bit pcmcia bus\n"));
128: sc->sc_16_softc = psc;
129: /* XXX: dirty. This code should be removed
130: * to achieve MI
131: */
132: caa->caa_ph->pcmcia = (struct device *)psc;
133: }
134: }
135:
136: if (csc != NULL || psc != NULL)
137: kthread_create_deferred(create_slot_manager, (void *)sc);
138:
139: if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) {
140: DPRINTF(("cardslotattach: CardBus card found\n"));
141: /* attach deferred */
142: cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB);
143: }
144:
145: if (psc && (psc->pct->card_detect)(psc->pch)) {
146: DPRINTF(("cardbusattach: 16-bit card found\n"));
147: /* attach deferred */
148: cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16);
149: }
150: }
151:
152: STATIC int
153: cardslot_cb_print(void *aux, const char *pnp)
154: {
155: struct cbslot_attach_args *cba = aux;
156:
157: if (pnp)
158: printf("cardbus at %s subordinate bus %d", pnp, cba->cba_bus);
159:
160: return (UNCONF);
161: }
162:
163: static int
164: cardslot_16_submatch(struct device *parent, void *match, void *aux)
165: {
166: struct cfdata *cf = match;
167:
168: if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
169: return (0);
170:
171: if (cf->cf_loc[0] == -1)
172: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
173:
174: return (0);
175: }
176:
177: static int
178: cardslot_16_print(void *arg, const char *pnp)
179: {
180: if (pnp)
181: printf("pcmciabus at %s", pnp);
182:
183: return (UNCONF);
184: }
185:
186: static void
187: create_slot_manager(void *arg)
188: {
189: struct cardslot_softc *sc = (struct cardslot_softc *)arg;
190:
191: sc->sc_th_enable = 1;
192:
193: if (kthread_create(cardslot_event_thread, sc, &sc->sc_event_thread,
194: "%s", sc->sc_dev.dv_xname)) {
195: printf("%s: unable to create event thread for slot %d\n",
196: sc->sc_dev.dv_xname, sc->sc_slot);
197: panic("create_slot_manager");
198: }
199: }
200:
201: /*
202: * void cardslot_event_throw(struct cardslot_softc *sc, int ev)
203: *
204: * This function throws an event to the event handler. If the state
205: * of a slot is changed, it should be noticed using this function.
206: */
207: void
208: cardslot_event_throw(struct cardslot_softc *sc, int ev)
209: {
210: struct cardslot_event *ce;
211:
212: DPRINTF(("cardslot_event_throw: an event %s comes\n",
213: ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" :
214: ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" :
215: ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" :
216: ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???"));
217:
218: if ((ce = (struct cardslot_event *)malloc(sizeof(struct cardslot_event),
219: M_TEMP, M_NOWAIT)) == NULL) {
220: panic("cardslot_event");
221: }
222:
223: ce->ce_type = ev;
224:
225: {
226: int s = spltty();
227: SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q);
228: splx(s);
229: }
230:
231: wakeup(&sc->sc_events);
232: }
233:
234: /*
235: * static void cardslot_event_thread(void *arg)
236: *
237: * This function is the main routine handing cardslot events such as
238: * insertions and removals.
239: *
240: */
241: static void
242: cardslot_event_thread(void *arg)
243: {
244: struct cardslot_softc *sc = arg;
245: struct cardslot_event *ce;
246: int s;
247: static int antonym_ev[4] = {
248: CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16,
249: CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB
250: };
251:
252: while (sc->sc_th_enable) {
253: s = spltty();
254: if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) {
255: splx(s);
256: (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0);
257: continue;
258: }
259: SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
260: splx(s);
261:
262: if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) {
263: /* Chattering suppression */
264: s = spltty();
265: while (1) {
266: struct cardslot_event *ce1, *ce2;
267:
268: if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) ==
269: NULL)
270: break;
271: if (ce1->ce_type != antonym_ev[ce->ce_type])
272: break;
273: if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL)
274: break;
275: if (ce2->ce_type == ce->ce_type) {
276: SIMPLEQ_REMOVE_HEAD(&sc->sc_events,
277: ce_q);
278: free(ce1, M_TEMP);
279: SIMPLEQ_REMOVE_HEAD(&sc->sc_events,
280: ce_q);
281: free(ce2, M_TEMP);
282: }
283: }
284: splx(s);
285: }
286:
287: switch (ce->ce_type) {
288: case CARDSLOT_EVENT_INSERTION_CB:
289: if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
290: CARDSLOT_STATUS_CARD_CB) ||
291: (CARDSLOT_CARDTYPE(sc->sc_status) ==
292: CARDSLOT_STATUS_CARD_16)) {
293: if (CARDSLOT_WORK(sc->sc_status) ==
294: CARDSLOT_STATUS_WORKING) {
295: /* A card has already been inserted
296: * and works.
297: */
298: break;
299: }
300: }
301:
302: if (sc->sc_cb_softc) {
303: CARDSLOT_SET_CARDTYPE(sc->sc_status,
304: CARDSLOT_STATUS_CARD_CB);
305: if (cardbus_attach_card(sc->sc_cb_softc) > 0) {
306: /* At least one function works */
307: CARDSLOT_SET_WORK(sc->sc_status,
308: CARDSLOT_STATUS_WORKING);
309: } else {
310: /* No functions work or this card is
311: * not known
312: */
313: CARDSLOT_SET_WORK(sc->sc_status,
314: CARDSLOT_STATUS_NOTWORK);
315: }
316: } else {
317: panic("no cardbus on %s", sc->sc_dev.dv_xname);
318: }
319:
320: break;
321:
322: case CARDSLOT_EVENT_INSERTION_16:
323: if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
324: CARDSLOT_STATUS_CARD_CB) ||
325: (CARDSLOT_CARDTYPE(sc->sc_status) ==
326: CARDSLOT_STATUS_CARD_16)) {
327: if (CARDSLOT_WORK(sc->sc_status) ==
328: CARDSLOT_STATUS_WORKING) {
329: /* A card has already been inserted
330: * and works.
331: */
332: break;
333: }
334: }
335: if (sc->sc_16_softc) {
336: CARDSLOT_SET_CARDTYPE(sc->sc_status,
337: CARDSLOT_STATUS_CARD_16);
338: if (pcmcia_card_attach(
339: (struct device *)sc->sc_16_softc)) {
340: /* Do not attach */
341: CARDSLOT_SET_WORK(sc->sc_status,
342: CARDSLOT_STATUS_NOTWORK);
343: } else {
344: /* working */
345: CARDSLOT_SET_WORK(sc->sc_status,
346: CARDSLOT_STATUS_WORKING);
347: }
348: } else {
349: panic("no 16-bit pcmcia on %s",
350: sc->sc_dev.dv_xname);
351: }
352:
353: break;
354:
355: case CARDSLOT_EVENT_REMOVAL_CB:
356: if (CARDSLOT_CARDTYPE(sc->sc_status) ==
357: CARDSLOT_STATUS_CARD_CB) {
358: /* CardBus card has not been inserted. */
359: if (CARDSLOT_WORK(sc->sc_status) ==
360: CARDSLOT_STATUS_WORKING) {
361: cardbus_detach_card(sc->sc_cb_softc);
362: CARDSLOT_SET_WORK(sc->sc_status,
363: CARDSLOT_STATUS_NOTWORK);
364: CARDSLOT_SET_WORK(sc->sc_status,
365: CARDSLOT_STATUS_CARD_NONE);
366: }
367: CARDSLOT_SET_CARDTYPE(sc->sc_status,
368: CARDSLOT_STATUS_CARD_NONE);
369: } else if (CARDSLOT_CARDTYPE(sc->sc_status) !=
370: CARDSLOT_STATUS_CARD_16) {
371: /* Unknown card... */
372: CARDSLOT_SET_CARDTYPE(sc->sc_status,
373: CARDSLOT_STATUS_CARD_NONE);
374: }
375: CARDSLOT_SET_WORK(sc->sc_status,
376: CARDSLOT_STATUS_NOTWORK);
377: break;
378:
379: case CARDSLOT_EVENT_REMOVAL_16:
380: DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname));
381: if (CARDSLOT_CARDTYPE(sc->sc_status) !=
382: CARDSLOT_STATUS_CARD_16) {
383: /* 16-bit card has not been inserted. */
384: break;
385: }
386: if ((sc->sc_16_softc != NULL) &&
387: (CARDSLOT_WORK(sc->sc_status) ==
388: CARDSLOT_STATUS_WORKING)) {
389: struct pcmcia_softc *psc = sc->sc_16_softc;
390:
391: pcmcia_card_deactivate((struct device *)psc);
392: pcmcia_chip_socket_disable(psc->pct, psc->pch);
393: pcmcia_card_detach((struct device *)psc,
394: DETACH_FORCE);
395: }
396: CARDSLOT_SET_CARDTYPE(sc->sc_status,
397: CARDSLOT_STATUS_CARD_NONE);
398: CARDSLOT_SET_WORK(sc->sc_status,
399: CARDSLOT_STATUS_NOTWORK);
400: break;
401:
402: default:
403: panic("cardslot_event_thread: unknown event %d",
404: ce->ce_type);
405: }
406: free(ce, M_TEMP);
407: }
408:
409: sc->sc_event_thread = NULL;
410:
411: /* In case the parent device is waiting for us to exit. */
412: wakeup(sc);
413:
414: kthread_exit(0);
415: }
CVSweb