Home | History | Annotate | Line # | Download | only in cardbus
cardbus.c revision 1.7
      1 /*	$NetBSD: cardbus.c,v 1.7 1999/10/29 11:30:27 joda Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997, 1998 and 1999
      5  *     HAYAKAWA Koichi.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by HAYAKAWA Koichi.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission.
     20  *
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     25  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32  * POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #include "opt_cardbus.h"
     36 
     37 #include <sys/types.h>
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/device.h>
     41 #include <sys/malloc.h>
     42 #include <sys/kernel.h>
     43 #include <sys/syslog.h>
     44 
     45 #include <machine/bus.h>
     46 
     47 #include <dev/cardbus/cardbusvar.h>
     48 #include <dev/cardbus/pccardcis.h>
     49 
     50 #include <dev/cardbus/cardbus_exrom.h>
     51 
     52 #include <dev/pci/pcivar.h>	/* XXX */
     53 #include <dev/pci/pcireg.h>	/* XXX */
     54 
     55 #if defined CARDBUS_DEBUG
     56 #define STATIC
     57 #define DPRINTF(a) printf a
     58 #define DDELAY(x) delay((x)*1000*1000)
     59 #else
     60 #define STATIC static
     61 #define DPRINTF(a)
     62 #endif
     63 
     64 
     65 
     66 STATIC void cardbusattach __P((struct device *, struct device *, void *));
     67 /* STATIC int cardbusprint __P((void *, const char *)); */
     68 int cardbus_attach_card __P((struct cardbus_softc *));
     69 
     70 #if !defined __BROKEN_INDIRECT_CONFIG
     71 STATIC int cardbusmatch __P((struct device *, struct cfdata *, void *));
     72 static int cardbussubmatch __P((struct device *, struct cfdata *, void *));
     73 #else
     74 STATIC int cardbusmatch __P((struct device *, void *, void *));
     75 static int cardbussubmatch __P((struct device *, void *, void *));
     76 #endif
     77 static int cardbusprint __P((void *, const char *));
     78 
     79 static int decode_tuples __P((u_int8_t *, int));
     80 
     81 static int cardbus_read_tuples __P((struct cardbus_attach_args *,
     82 				    cardbusreg_t, u_int8_t *, size_t));
     83 
     84 
     85 struct cfattach cardbus_ca = {
     86 	sizeof(struct cardbus_softc), cardbusmatch, cardbusattach
     87 };
     88 
     89 #ifndef __NetBSD_Version__
     90 struct cfdriver cardbus_cd = {
     91 	NULL, "cardbus", DV_DULL
     92 };
     93 #endif
     94 
     95 
     96 STATIC int
     97 #if defined __BROKEN_INDIRECT_CONFIG
     98 cardbusmatch(parent, match, aux)
     99      struct device *parent;
    100      void *match;
    101      void *aux;
    102 #else
    103 cardbusmatch(parent, cf, aux)
    104      struct device *parent;
    105      struct cfdata *cf;
    106      void *aux;
    107 #endif
    108 {
    109 #if defined __BROKEN_INDIRECT_CONFIG
    110   struct cfdata *cf = match;
    111 #endif
    112   struct cbslot_attach_args *cba = aux;
    113 
    114   if (strcmp(cba->cba_busname, cf->cf_driver->cd_name)) {
    115     DPRINTF(("cardbusmatch: busname differs %s <=> %s\n",
    116 	     cba->cba_busname, cf->cf_driver->cd_name));
    117     return 0;
    118   }
    119 
    120 #if 0
    121   /* which function? */
    122   if (cf->cbslotcf_func != CBSLOT_UNK_FUNC &&
    123       cf->cbslotcf_func != cba->cba_function) {
    124     DPRINTF(("cardbusmatch: function differs %d <=> %d\n",
    125 	     cf->cbslotcf_func, cba->cba_function));
    126     return 0;
    127   }
    128 #endif
    129 
    130   if (cba->cba_function < 0 || cba->cba_function > 255) {
    131     return 0;
    132   }
    133 
    134   return 1;
    135 }
    136 
    137 
    138 
    139 STATIC void
    140 cardbusattach(parent, self, aux)
    141      struct device *parent;
    142      struct device *self;
    143      void *aux;
    144 {
    145   struct cardbus_softc *sc = (void *)self;
    146   struct cbslot_attach_args *cba = aux;
    147   int cdstatus;
    148 
    149   sc->sc_bus = cba->cba_bus;
    150   sc->sc_device = cba->cba_function;
    151   sc->sc_intrline = cba->cba_intrline;
    152   sc->sc_cacheline = cba->cba_cacheline;
    153   sc->sc_lattimer = cba->cba_lattimer;
    154 
    155   printf(": bus %d device %d", sc->sc_bus, sc->sc_device);
    156   printf(" cacheline 0x%x, lattimer 0x%x\n", sc->sc_cacheline,sc->sc_lattimer);
    157 
    158   sc->sc_iot = cba->cba_iot;	/* CardBus I/O space tag */
    159   sc->sc_memt = cba->cba_memt;	/* CardBus MEM space tag */
    160   sc->sc_dmat = cba->cba_dmat;	/* DMA tag */
    161   sc->sc_cc = cba->cba_cc;
    162   sc->sc_cf = cba->cba_cf;
    163 
    164 #if rbus
    165   sc->sc_rbus_iot = cba->cba_rbus_iot;
    166   sc->sc_rbus_memt = cba->cba_rbus_memt;
    167 #endif
    168 
    169   sc->sc_funcs = NULL;
    170 
    171   cdstatus = 0;
    172 }
    173 
    174 static int
    175 cardbus_read_tuples(ca, cis_ptr, tuples, len)
    176      struct cardbus_attach_args *ca;
    177      cardbusreg_t cis_ptr;
    178      u_int8_t *tuples;
    179      size_t len;
    180 {
    181 #ifdef CARDBUS_DEBUG
    182     static const char __func__[] = "cardbus_read_tuples";
    183 #endif
    184     cardbus_chipset_tag_t cc = ca->ca_ct->ct_cc;
    185     cardbus_function_tag_t cf = ca->ca_ct->ct_cf;
    186     cardbustag_t tag = ca->ca_tag;
    187     cardbusreg_t command;
    188     int found = 0;
    189 
    190     int i, j;
    191     int cardbus_space = cis_ptr & CARDBUS_CIS_ASIMASK;
    192     bus_space_handle_t bar_memh;
    193     bus_size_t bar_size;
    194     bus_addr_t bar_addr;
    195 
    196     int reg;
    197 
    198     memset(tuples, 0, len);
    199 
    200     cis_ptr = cis_ptr & CARDBUS_CIS_ADDRMASK;
    201 
    202     switch(cardbus_space) {
    203     case CARDBUS_CIS_ASI_TUPLE:
    204 	DPRINTF(("%s: reading CIS data from configuration space\n", __func__));
    205 	for (i = cis_ptr, j = 0; i < 0xff; i += 4) {
    206 	    u_int32_t e = (cf->cardbus_conf_read)(cc, tag, i);
    207 	    tuples[j] = 0xff & e;
    208 	    e >>= 8;
    209 	    tuples[j + 1] = 0xff & e;
    210 	    e >>= 8;
    211 	    tuples[j + 2] = 0xff & e;
    212 	    e >>= 8;
    213 	    tuples[j + 3] = 0xff & e;
    214 	    j += 4;
    215 	}
    216 	found++;
    217 	break;
    218 
    219     case CARDBUS_CIS_ASI_BAR0:
    220     case CARDBUS_CIS_ASI_BAR1:
    221     case CARDBUS_CIS_ASI_BAR2:
    222     case CARDBUS_CIS_ASI_BAR3:
    223     case CARDBUS_CIS_ASI_BAR4:
    224     case CARDBUS_CIS_ASI_BAR5:
    225     case CARDBUS_CIS_ASI_ROM:
    226 	if(cardbus_space == CARDBUS_CIS_ASI_ROM) {
    227 	    reg = CARDBUS_ROM_REG;
    228 	    DPRINTF(("%s: reading CIS data from ROM\n", __func__));
    229 	} else {
    230 	    reg = CARDBUS_BASE0_REG + (cardbus_space - 1) * 4;
    231 	    DPRINTF(("%s: reading CIS data from BAR%d\n",
    232 		     __func__, cardbus_space - 1));
    233 	}
    234 
    235 	/* XXX zero register so mapreg_map doesn't get confused by old
    236            contents */
    237 	cardbus_conf_write(cc, cf, tag, reg, 0);
    238 	if(Cardbus_mapreg_map(ca->ca_ct, reg,
    239 			      CARDBUS_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    240 			      0,
    241 			      NULL, &bar_memh, &bar_addr, &bar_size)) {
    242 	    printf("%s: failed to map memory\n", __func__);
    243 	    return 1;
    244 	}
    245 
    246 
    247 	if(cardbus_space == CARDBUS_CIS_ASI_ROM) {
    248 	    cardbusreg_t exrom;
    249 	    int save;
    250 	    struct cardbus_rom_image_head rom_image;
    251 	    struct cardbus_rom_image *p;
    252 
    253 	    save = splhigh();
    254 	    /* enable rom address decoder */
    255 	    exrom = cardbus_conf_read(cc, cf, tag, reg);
    256 	    cardbus_conf_write(cc, cf, tag, reg, exrom | 1);
    257 
    258 	    command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG);
    259 	    cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG,
    260 			       command | CARDBUS_COMMAND_MEM_ENABLE);
    261 
    262 	    printf("reg = %x\n", reg);
    263 	    printf("bar_addr = %lx, exrom = %x\n", bar_addr, exrom);
    264 	    printf("exrom = %x\n", cardbus_conf_read(cc, cf, tag, reg));
    265 
    266 	    if(cardbus_read_exrom(ca->ca_memt, bar_memh, &rom_image))
    267 		goto out;
    268 
    269 	    for(p = SIMPLEQ_FIRST(&rom_image);
    270 		p;
    271 		p = SIMPLEQ_NEXT(p, next)) {
    272 		if(p->rom_image == CARDBUS_CIS_ASI_ROM_IMAGE(cis_ptr)) {
    273 		    bus_space_read_region_1(p->romt, p->romh,
    274 					    CARDBUS_CIS_ADDR(cis_ptr),
    275 					    tuples, 256);
    276 		    found++;
    277 		}
    278 		break;
    279 	    }
    280 	    while((p = SIMPLEQ_FIRST(&rom_image)) != NULL) {
    281 		SIMPLEQ_REMOVE_HEAD(&rom_image, p, next);
    282 		free(p, M_DEVBUF);
    283 	    }
    284 	out:
    285 	    exrom = cardbus_conf_read(cc, cf, tag, reg);
    286 	    cardbus_conf_write(cc, cf, tag, reg, exrom & ~1);
    287 	    splx(save);
    288 	} else {
    289 	    command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG);
    290 	    cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG,
    291 			       command | CARDBUS_COMMAND_MEM_ENABLE);
    292 	    /* XXX byte order? */
    293 	    bus_space_read_region_1(ca->ca_memt, bar_memh,
    294 				    cis_ptr, tuples, 256);
    295 	    found++;
    296 	}
    297 	command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG);
    298 	cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG,
    299 			   command & ~CARDBUS_COMMAND_MEM_ENABLE);
    300 	cardbus_conf_write(cc, cf, tag, reg, 0);
    301 #if 0
    302 	/* XXX unmap memory */
    303 	(*ca->ca_ct->ct_cf->cardbus_space_free)(ca->ca_ct,
    304 						ca->ca_ct->ct_sc->sc_rbus_memt,
    305 						bar_memh, bar_size);
    306 #endif
    307 	break;
    308 
    309 #ifdef DIAGNOSTIC
    310     default:
    311 	panic("%s: bad CIS space (%d)", __func__, cardbus_space);
    312 #endif
    313     }
    314     return !found;
    315 }
    316 
    317 /*
    318  * int cardbus_attach_card(struct cardbus_softc *sc)
    319  *
    320  *    This function attaches the card on the slot: turns on power,
    321  *    reads and analyses tuple, sets consifuration index.
    322  *
    323  *    This function returns the number of recognised device functions.
    324  *    If no functions are recognised, return 0.
    325  */
    326 int
    327 cardbus_attach_card(sc)
    328      struct cardbus_softc *sc;
    329 {
    330   cardbus_chipset_tag_t cc;
    331   cardbus_function_tag_t cf;
    332   int cdstatus;
    333   cardbustag_t tag;
    334   cardbusreg_t id, class, cis_ptr;
    335   cardbusreg_t bhlc;
    336   u_int8_t tuple[2048];
    337   int function, nfunction;
    338   struct cardbus_devfunc **previous_next = &(sc->sc_funcs);
    339   struct device *csc;
    340   int no_work_funcs = 0;
    341   cardbus_devfunc_t ct;
    342 
    343   cc = sc->sc_cc;
    344   cf = sc->sc_cf;
    345 
    346   DPRINTF(("cardbus_attach_card: cb%d start\n", sc->sc_dev.dv_unit));
    347 
    348   /* inspect initial voltage */
    349   if (0 == (cdstatus = (cf->cardbus_ctrl)(cc, CARDBUS_CD))) {
    350     DPRINTF(("cardbusattach: no CardBus card on cb%d\n", sc->sc_dev.dv_unit));
    351     return 0;
    352   }
    353 
    354   if (cdstatus & CARDBUS_3V_CARD) {
    355     cf->cardbus_power(cc, CARDBUS_VCC_3V);
    356     sc->sc_poweron_func = 1;	/* function 0 on */
    357   }
    358 
    359   (cf->cardbus_ctrl)(cc, CARDBUS_RESET);
    360 
    361   function = 0;
    362 
    363   tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, function);
    364 
    365   /*
    366    * Wait until power comes up.  Maxmum 500 ms.
    367    */
    368   {
    369     int i;
    370     for (i = 0; i < 5; ++i) {
    371       id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG);
    372       if (id != 0xffffffff && id != 0) {
    373 	break;
    374       }
    375       delay(100*1000);		/* or tsleep */
    376     }
    377     if (i == 5) {
    378       return 0;
    379     }
    380   }
    381 
    382   bhlc = cardbus_conf_read(cc, cf, tag, CARDBUS_BHLC_REG);
    383   if (CARDBUS_LATTIMER(bhlc) < 0x10) {
    384     bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
    385     bhlc |= (0x10 << CARDBUS_LATTIMER_SHIFT);
    386     cardbus_conf_write(cc, cf, tag, CARDBUS_BHLC_REG, bhlc);
    387   }
    388 
    389   nfunction = CARDBUS_HDRTYPE_MULTIFN(bhlc) ? 8 : 1;
    390 
    391   /*
    392    *           XXX multi-function card
    393    *
    394    * I don't know how to process CIS information for
    395    * multi-function cards.
    396    */
    397 
    398   id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG);
    399   class = cardbus_conf_read(cc, cf, tag, CARDBUS_CLASS_REG);
    400   cis_ptr = cardbus_conf_read(cc, cf, tag, CARDBUS_CIS_REG);
    401 
    402   DPRINTF(("cardbus_attach_card: Vendor 0x%x, Product 0x%x, CIS 0x%x\n",
    403 	   CARDBUS_VENDOR(id), CARDBUS_PRODUCT(id), cis_ptr));
    404 
    405   {
    406     struct cardbus_attach_args ca;
    407 
    408     /* we need to allocate the ct here, since we might
    409        need it when reading the CIS */
    410     if (NULL == (ct = (cardbus_devfunc_t)malloc(sizeof(struct cardbus_devfunc),
    411 						M_DEVBUF, M_NOWAIT))) {
    412       panic("no room for cardbus_tag");
    413     }
    414 
    415     ct->ct_cc = sc->sc_cc;
    416     ct->ct_cf = sc->sc_cf;
    417     ct->ct_bus = sc->sc_bus;
    418     ct->ct_dev = sc->sc_device;
    419     ct->ct_func = function;
    420     ct->ct_sc = sc;
    421     ct->ct_next = NULL;
    422     *previous_next = ct;
    423 
    424     ca.ca_unit = sc->sc_dev.dv_unit;
    425     ca.ca_ct = ct;
    426 
    427     ca.ca_iot = sc->sc_iot;
    428     ca.ca_memt = sc->sc_memt;
    429     ca.ca_dmat = sc->sc_dmat;
    430 
    431     ca.ca_tag = tag;
    432     ca.ca_device = sc->sc_device;
    433     ca.ca_function = function;
    434     ca.ca_id = id;
    435     ca.ca_class = class;
    436 
    437     ca.ca_intrline = sc->sc_intrline;
    438 
    439     bzero(tuple, 2048);
    440 
    441     if(cardbus_read_tuples(&ca, cis_ptr, tuple, sizeof(tuple))) {
    442       printf("cardbus_attach_card: failed to read CIS\n");
    443       free(ct, M_DEVBUF);
    444       return 0;
    445     }
    446 
    447     decode_tuples(tuple, 2048);
    448 
    449 
    450     if (NULL == (csc = config_found_sm((void *)sc, &ca, cardbusprint, cardbussubmatch))) {
    451       /* do not match */
    452       cf->cardbus_power(cc, CARDBUS_VCC_0V);
    453       sc->sc_poweron_func = 0;	/* no functions on */
    454       free(cc, M_DEVBUF);
    455       free(ct, M_DEVBUF);
    456       *previous_next = NULL;
    457     } else {
    458       /* found */
    459       previous_next = &(ct->ct_next);
    460       ct->ct_device = csc;
    461       ++no_work_funcs;
    462     }
    463   }
    464 
    465   return no_work_funcs;
    466 }
    467 
    468 
    469 static int
    470 #ifdef __BROKEN_INDIRECT_CONFIG
    471 cardbussubmatch(parent, match, aux)
    472 #else
    473 cardbussubmatch(parent, cf, aux)
    474 #endif
    475      struct device *parent;
    476 #ifdef __BROKEN_INDIRECT_CONFIG
    477      void *match;
    478 #else
    479      struct cfdata *cf;
    480 #endif
    481      void *aux;
    482 {
    483 #ifdef __BROKEN_INDIRECT_CONFIG
    484   struct cfdata *cf = match;
    485 #endif
    486   struct cardbus_attach_args *ca = aux;
    487 
    488   if (cf->cardbuscf_dev != CARDBUS_UNK_DEV &&
    489       cf->cardbuscf_dev != ca->ca_unit) {
    490     return 0;
    491   }
    492   if (cf->cardbuscf_function != CARDBUS_UNK_FUNCTION &&
    493       cf->cardbuscf_function != ca->ca_function) {
    494     return 0;
    495   }
    496 
    497   return ((*cf->cf_attach->ca_match)(parent, cf, aux));
    498 }
    499 
    500 
    501 
    502 static int
    503 cardbusprint(aux, pnp)
    504      void *aux;
    505      const char *pnp;
    506 {
    507   register struct cardbus_attach_args *ca = aux;
    508   char devinfo[256];
    509 
    510   if (pnp) {
    511     pci_devinfo(ca->ca_id, ca->ca_class, 1, devinfo);
    512     printf("%s at %s", devinfo, pnp);
    513   }
    514   printf(" dev %d function %d", ca->ca_device, ca->ca_function);
    515 
    516   return UNCONF;
    517 }
    518 
    519 
    520 
    521 
    522 
    523 
    524 /*
    525  * void *cardbus_intr_establish(cc, cf, irq, level, func, arg)
    526  *   Interrupt handler of pccard.
    527  *  args:
    528  *   cardbus_chipset_tag_t *cc
    529  *   int irq:
    530  */
    531 void *
    532 cardbus_intr_establish(cc, cf, irq, level, func, arg)
    533      cardbus_chipset_tag_t cc;
    534      cardbus_function_tag_t cf;
    535      cardbus_intr_handle_t irq;
    536      int level;
    537      int (*func) __P((void *));
    538      void *arg;
    539 {
    540   DPRINTF(("- cardbus_intr_establish: irq %d\n", irq));
    541 
    542   return (*cf->cardbus_intr_establish)(cc, irq, level, func, arg);
    543 }
    544 
    545 
    546 
    547 /*
    548  * void cardbus_intr_disestablish(cc, cf, handler)
    549  *   Interrupt handler of pccard.
    550  *  args:
    551  *   cardbus_chipset_tag_t *cc
    552  */
    553 void
    554 cardbus_intr_disestablish(cc, cf, handler)
    555      cardbus_chipset_tag_t cc;
    556      cardbus_function_tag_t cf;
    557      void *handler;
    558 {
    559   DPRINTF(("- pccard_intr_disestablish\n"));
    560 
    561  (*cf->cardbus_intr_disestablish)(cc, handler);
    562   return;
    563 }
    564 
    565 
    566 
    567 /*
    568  * int cardbus_function_enable(cardbus_devfunc_t ct)
    569  *
    570  *   This function enables a function on a card.  When no power is
    571  *  applied on the card, power will be applied on it.
    572  */
    573 int
    574 cardbus_function_enable(ct)
    575      cardbus_devfunc_t ct;
    576 {
    577   struct cardbus_softc *sc = ct->ct_sc;
    578   int func = ct->ct_func;
    579   cardbus_chipset_tag_t cc = sc->sc_cc;
    580   cardbus_function_tag_t cf = sc->sc_cf;
    581   cardbusreg_t command;
    582   cardbustag_t tag;
    583 
    584   DPRINTF(("entering cardbus_function_enable...  "));
    585 
    586   /* entering critical area */
    587 
    588   if (sc->sc_poweron_func == 0) {
    589     /* no functions are enabled */
    590     (*cf->cardbus_power)(cc, CARDBUS_VCC_3V); /* XXX: sc_vold should be used */
    591     (*cf->cardbus_ctrl)(cc, CARDBUS_RESET);
    592   }
    593 
    594   sc->sc_poweron_func |= (1 << func);
    595 
    596   /* exiting critical area */
    597 
    598   tag = Cardbus_make_tag(ct);
    599   command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG);
    600   command |= (CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE); /* XXX: good guess needed */
    601   cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG, command);
    602   Cardbus_free_tag(ct, tag);
    603 
    604 
    605   DPRINTF(("%x\n", sc->sc_poweron_func));
    606 
    607   return 0;
    608 }
    609 
    610 
    611 /*
    612  * int cardbus_function_disable(cardbus_devfunc_t ct)
    613  *
    614  *   This function disable a function on a card.  When no functions are
    615  *  enabled, it turns off the power.
    616  */
    617 int
    618 cardbus_function_disable(ct)
    619      cardbus_devfunc_t ct;
    620 {
    621   struct cardbus_softc *sc = ct->ct_sc;
    622   int func = ct->ct_func;
    623   cardbus_chipset_tag_t cc = sc->sc_cc;
    624   cardbus_function_tag_t cf = sc->sc_cf;
    625 
    626   DPRINTF(("entering cardbus_enable_disable...  "));
    627 
    628   sc->sc_poweron_func &= ~(1 << func);
    629 
    630   DPRINTF(("%x\n", sc->sc_poweron_func));
    631 
    632   if (sc->sc_poweron_func == 0) {
    633     /* power-off because no functions are enabled */
    634     (*cf->cardbus_power)(cc, CARDBUS_VCC_0V);
    635   }
    636 
    637   return 0;
    638 }
    639 
    640 
    641 
    642 
    643 
    644 
    645 
    646 /*
    647  * below this line, there are some functions for decoding tuples.
    648  * They should go out from this file.
    649  */
    650 
    651 static u_int8_t *decode_tuple __P((u_int8_t *));
    652 #ifdef CARDBUS_DEBUG
    653 static char *tuple_name __P((int));
    654 #endif
    655 
    656 static int
    657 decode_tuples(tuple, buflen)
    658      u_int8_t *tuple;
    659      int buflen;
    660 {
    661   u_int8_t *tp = tuple;
    662 
    663   if (CISTPL_LINKTARGET != *tuple) {
    664     DPRINTF(("WRONG TUPLE: 0x%x\n", *tuple));
    665     return 0;
    666   }
    667 
    668   while (NULL != (tp = decode_tuple(tp))) {
    669     if (tuple + buflen < tp) {
    670       break;
    671     }
    672   }
    673 
    674   return 1;
    675 }
    676 
    677 
    678 static u_int8_t *
    679 decode_tuple(tuple)
    680      u_int8_t *tuple;
    681 {
    682   u_int8_t type;
    683   u_int8_t len;
    684 #ifdef CARDBUS_DEBUG
    685   int i;
    686 #endif
    687 
    688   type = tuple[0];
    689   len = tuple[1] + 2;
    690 
    691 #ifdef CARDBUS_DEBUG
    692   printf("tuple: %s len %d\n", tuple_name(type), len);
    693 #endif
    694   if (CISTPL_END == type) {
    695     return NULL;
    696   }
    697 
    698 #ifdef CARDBUS_DEBUG
    699   for (i = 0; i < len; ++i) {
    700     if (i % 16 == 0) {
    701       printf("  0x%2x:", i);
    702     }
    703     printf(" %x",tuple[i]);
    704     if (i % 16 == 15) {
    705       printf("\n");
    706     }
    707   }
    708   if (i % 16 != 0) {
    709     printf("\n");
    710   }
    711 #endif
    712 
    713   return tuple + len;
    714 }
    715 
    716 
    717 #ifdef CARDBUS_DEBUG
    718 static char *
    719 tuple_name(type)
    720      int type;
    721 {
    722   static char *tuple_name_s [] = {
    723     "TPL_NULL", "TPL_DEVICE", "Reserved", "Reserved", /* 0-3 */
    724     "CONFIG_CB", "CFTABLE_ENTRY_CB", "Reserved", "BAR", /* 4-7 */
    725     "Reserved", "Reserved", "Reserved", "Reserved", /* 8-B */
    726     "Reserved", "Reserved", "Reserved", "Reserved", /* C-F */
    727     "CHECKSUM", "LONGLINK_A", "LONGLINK_C", "LINKTARGET",	/* 10-13 */
    728     "NO_LINK", "VERS_1", "ALTSTR", "DEVICE_A",
    729     "JEDEC_C", "JEDEC_A", "CONFIG", "CFTABLE_ENTRY",
    730     "DEVICE_OC", "DEVICE_OA", "DEVICE_GEO", "DEVICE_GEO_A",
    731     "MANFID", "FUNCID", "FUNCE", "SWIL", /* 20-23 */
    732     "Reserved", "Reserved", "Reserved", "Reserved", /* 24-27 */
    733     "Reserved", "Reserved", "Reserved", "Reserved", /* 28-2B */
    734     "Reserved", "Reserved", "Reserved", "Reserved", /* 2C-2F */
    735     "Reserved", "Reserved", "Reserved", "Reserved", /* 30-33 */
    736     "Reserved", "Reserved", "Reserved", "Reserved", /* 34-37 */
    737     "Reserved", "Reserved", "Reserved", "Reserved", /* 38-3B */
    738     "Reserved", "Reserved", "Reserved", "Reserved", /* 3C-3F */
    739     "VERS_2", "FORMAT", "GEOMETRY", "BYTEORDER",
    740     "DATE", "BATTERY", "ORG"
    741   };
    742 #define NAME_LEN(x) (sizeof x / sizeof(x[0]))
    743 
    744   if (type > 0 && type < NAME_LEN(tuple_name_s)) {
    745     return tuple_name_s[type];
    746   } else if (0xff == type) {
    747     return "END";
    748   } else {
    749     return "Reserved";
    750   }
    751 }
    752 #endif
    753