/*
* Copyright (c) 1999 and 2000
* HAYAKAWA Koichi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] == PCMCIABUSCF_CONTROLLER_DEFAULT) {
return (config_match(parent, cf, aux));
}
return 0;
}
static int
cardslot_16_print(void *arg, const char *pnp)
{
if (pnp != NULL) {
aprint_normal("pcmciabus at %s", pnp);
}
return UNCONF;
}
/*
* void cardslot_event_throw(struct cardslot_softc *sc, int ev)
*
* This function throws an event to the event handler. If the state
* of a slot is changed, it should be noticed using this function.
*/
void
cardslot_event_throw(struct cardslot_softc *sc, int ev)
{
struct cardslot_event *ce;
DPRINTF(("cardslot_event_throw: an event %s comes\n",
ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" :
ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" :
ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" :
ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???"));
/*
* static void cardslot_event_thread(void *arg)
*
* This function is the main routine handing cardslot events such as
* insertions and removals.
*
*/
static void
cardslot_event_thread(void *arg)
{
struct cardslot_softc *sc = arg;
struct cardslot_event *ce;
int first = 1;
static int antonym_ev[4] = {
CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16,
CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB
};
mutex_enter(&sc->sc_event_lock);
while (sc->sc_th_enable) {
if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) {
if (first) {
first = 0;
mutex_exit(&sc->sc_event_lock);
config_pending_decr(sc->sc_dev);
mutex_enter(&sc->sc_event_lock);
}
cv_wait(&sc->sc_event_cv, &sc->sc_event_lock);
continue;
}
SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) {
/* Chattering suppression */
while (1) {
struct cardslot_event *ce1, *ce2;
switch (ce->ce_type) {
case CARDSLOT_EVENT_INSERTION_CB:
if ((CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB)
|| (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_16)) {
if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) {
/*
* A card has already been
* inserted and works.
*/
break;
}
}
if (sc->sc_cb_softc) {
CARDSLOT_SET_CARDTYPE(sc->sc_status,
CARDSLOT_STATUS_CARD_CB);
if (cardbus_attach_card(sc->sc_cb_softc) > 0) {
/* at least one function works */
CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_WORKING);
} else {
/*
* no functions work or this
* card is not known
*/
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
}
} else {
printf("%s: no cardbus on %s\n", __func__,
device_xname(sc->sc_dev));
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
}
break;
case CARDSLOT_EVENT_INSERTION_16:
if ((CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB)
|| (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_16)) {
if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) {
/*
* A card has already been
* inserted and work.
*/
break;
}
}
if (sc->sc_16_softc) {
CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_16);
if (pcmcia_card_attach(sc->sc_16_softc)) {
/* Do not attach */
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
} else {
/* working */
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_WORKING);
}
} else {
printf("%s: no 16-bit pcmcia on %s\n", __func__,
device_xname(sc->sc_dev));
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
}
break;
case CARDSLOT_EVENT_REMOVAL_CB:
if (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB) {
/* CardBus card has not been inserted. */
if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) {
cardbus_detach_card(sc->sc_cb_softc);
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_CARD_NONE);
}
CARDSLOT_SET_CARDTYPE(sc->sc_status,
CARDSLOT_STATUS_CARD_NONE);
} else if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_16) {
/* Unknown card... */
CARDSLOT_SET_CARDTYPE(sc->sc_status,
CARDSLOT_STATUS_CARD_NONE);
}
CARDSLOT_SET_WORK(sc->sc_status,
CARDSLOT_STATUS_NOTWORK);
break;
case CARDSLOT_EVENT_REMOVAL_16:
DPRINTF(("%s: removal event\n", device_xname(sc->sc_dev)));
if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_16) {
/* 16-bit card has not been inserted. */
break;
}
if ((sc->sc_16_softc != NULL)
&& (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING)) {
struct pcmcia_softc *psc =
device_private(sc->sc_16_softc);