root/dev/sdmmc/sdmmc_cis.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdmmc_cisptr
  2. sdmmc_read_cis
  3. sdmmc_print_cis
  4. sdmmc_check_cis_quirks

    1 /*      $OpenBSD: sdmmc_cis.c,v 1.1 2006/06/01 21:53:41 uwe Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /* Routines to decode the Card Information Structure of SD I/O cards */
   20 
   21 #include <sys/param.h>
   22 #include <sys/systm.h>
   23 
   24 #include <dev/sdmmc/sdmmc_ioreg.h>
   25 #include <dev/sdmmc/sdmmcdevs.h>
   26 #include <dev/sdmmc/sdmmcvar.h>
   27 
   28 u_int32_t sdmmc_cisptr(struct sdmmc_function *);
   29 
   30 #ifdef SDMMC_DEBUG
   31 #define DPRINTF(s)      printf s
   32 #else
   33 #define DPRINTF(s)      /**/
   34 #endif
   35 
   36 u_int32_t
   37 sdmmc_cisptr(struct sdmmc_function *sf)
   38 {
   39         u_int32_t cisptr = 0;
   40 
   41         /* XXX where is the per-function CIS pointer register? */
   42         if (sf->number != 0)
   43                 return SD_IO_CIS_START;
   44 
   45         /* XXX is the CIS pointer stored in little-endian format? */
   46         cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+0) << 0;
   47         cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+1) << 8;
   48         cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+2) << 16;
   49         return cisptr;
   50 }
   51 
   52 int
   53 sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis *cis)
   54 {
   55         int reg;
   56         u_int8_t tplcode;
   57         u_int8_t tpllen;
   58 
   59         bzero(cis, sizeof *cis);
   60 
   61         /* XXX read per-function CIS */
   62         if (sf->number != 0)
   63                 return 1;
   64 
   65         reg = (int)sdmmc_cisptr(sf);
   66         if (reg < SD_IO_CIS_START ||
   67             reg >= (SD_IO_CIS_START+SD_IO_CIS_SIZE-16)) {
   68                 printf("%s: bad CIS ptr %#x\n", SDMMCDEVNAME(sf->sc), reg);
   69                 return 1;
   70         }
   71 
   72         for (;;) {
   73                 tplcode = sdmmc_io_read_1(sf, reg++);
   74                 tpllen = sdmmc_io_read_1(sf, reg++);
   75 
   76                 if (tplcode == 0xff || tpllen == 0) {
   77                         if (tplcode != 0xff)
   78                                 printf("%s: CIS parse error at %d, "
   79                                     "tuple code %#x, length %d\n",
   80                                     SDMMCDEVNAME(sf->sc), reg, tplcode, tpllen);
   81                         break;
   82                 }
   83 
   84                 switch (tplcode) {
   85                 case SD_IO_CISTPL_FUNCID:
   86                         if (tpllen < 2) {
   87                                 printf("%s: bad CISTPL_FUNCID length\n",
   88                                     SDMMCDEVNAME(sf->sc));
   89                                 reg += tpllen;
   90                                 break;
   91                         }
   92                         cis->function = sdmmc_io_read_1(sf, reg);
   93                         reg += tpllen;
   94                         break;
   95                 case SD_IO_CISTPL_MANFID:
   96                         if (tpllen < 4) {
   97                                 printf("%s: bad CISTPL_MANFID length\n",
   98                                     SDMMCDEVNAME(sf->sc));
   99                                 reg += tpllen;
  100                                 break;
  101                         }
  102                         cis->manufacturer = sdmmc_io_read_1(sf, reg++);
  103                         cis->manufacturer |= sdmmc_io_read_1(sf, reg++) << 8;
  104                         cis->product = sdmmc_io_read_1(sf, reg++);
  105                         cis->product |= sdmmc_io_read_1(sf, reg++) << 8;
  106                         break;
  107                 case SD_IO_CISTPL_VERS_1:
  108                         if (tpllen < 2) {
  109                                 printf("%s: CISTPL_VERS_1 too short\n",
  110                                     SDMMCDEVNAME(sf->sc));
  111                                 reg += tpllen;
  112                                 break;
  113                         }
  114                         {
  115                                 int start, i, ch, count;
  116 
  117                                 cis->cis1_major = sdmmc_io_read_1(sf, reg++);
  118                                 cis->cis1_minor = sdmmc_io_read_1(sf, reg++);
  119 
  120                                 for (count = 0, start = 0, i = 0;
  121                                      (count < 4) && ((i + 4) < 256); i++) {
  122                                         ch = sdmmc_io_read_1(sf, reg + i);
  123                                         if (ch == 0xff)
  124                                                 break;
  125                                         cis->cis1_info_buf[i] = ch;
  126                                         if (ch == 0) {
  127                                                 cis->cis1_info[count] =
  128                                                     cis->cis1_info_buf + start;
  129                                                 start = i + 1;
  130                                                 count++;
  131                                         }
  132                                 }
  133 
  134                                 reg += tpllen - 2;
  135                         }
  136                         break;
  137                 default:
  138                         DPRINTF(("%s: unknown tuple code %#x, length %d\n",
  139                             SDMMCDEVNAME(sf->sc), tplcode, tpllen));
  140                         reg += tpllen;
  141                         break;
  142                 }
  143         }
  144         return 0;
  145 }
  146 
  147 void
  148 sdmmc_print_cis(struct sdmmc_function *sf)
  149 {
  150         struct sdmmc_cis *cis = &sf->cis;
  151         int i;
  152 
  153         printf("%s: CIS version %d.%d\n", SDMMCDEVNAME(sf->sc),
  154             cis->cis1_major, cis->cis1_minor);
  155 
  156         printf("%s: CIS info: ", SDMMCDEVNAME(sf->sc));
  157         for (i = 0; i < 4; i++) {
  158                 if (cis->cis1_info[i] == NULL)
  159                         break;
  160                 if (i)
  161                         printf(", ");
  162                 printf("%s", cis->cis1_info[i]);
  163         }
  164         printf("\n");
  165 
  166         printf("%s: Manufacturer code 0x%x, product 0x%x\n",
  167             SDMMCDEVNAME(sf->sc), cis->manufacturer, cis->product);
  168 
  169         printf("%s: function %d: ", SDMMCDEVNAME(sf->sc), sf->number);
  170         switch (sf->cis.function) {
  171         case SDMMC_FUNCTION_WLAN:
  172                 printf("wireless network adapter");
  173                 break;
  174         default:
  175                 printf("unknown (%d)", sf->cis.function);
  176                 break;
  177         }
  178         printf("\n");
  179 }
  180 
  181 void
  182 sdmmc_check_cis_quirks(struct sdmmc_function *sf)
  183 {
  184         if (sf->cis.manufacturer == SDMMC_VENDOR_SPECTEC &&
  185             sf->cis.product == SDMMC_PRODUCT_SPECTEC_SDW820) {
  186                 /* This card lacks the VERS_1 tuple. */
  187                 sf->cis.cis1_major = 0x01;
  188                 sf->cis.cis1_minor = 0x00;
  189                 sf->cis.cis1_info[0] = "Spectec";
  190                 sf->cis.cis1_info[1] = "SDIO WLAN Card";
  191                 sf->cis.cis1_info[2] = "SDW-820";
  192                 sf->cis.cis1_info[3] = "";
  193         }
  194 }

/* [<][>][^][v][top][bottom][index][help] */