LCOV - code coverage report
Current view: top level - dev/sdmmc - sdmmc_cis.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 101 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: sdmmc_cis.c,v 1.7 2016/04/23 14:15:59 kettenis 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/device.h>
      23             : #include <sys/systm.h>
      24             : 
      25             : #include <dev/sdmmc/sdmmc_ioreg.h>
      26             : #include <dev/sdmmc/sdmmcdevs.h>
      27             : #include <dev/sdmmc/sdmmcvar.h>
      28             : 
      29             : u_int32_t sdmmc_cisptr(struct sdmmc_function *);
      30             : 
      31             : #ifdef SDMMC_DEBUG
      32             : #define DPRINTF(s)      printf s
      33             : #else
      34             : #define DPRINTF(s)      /**/
      35             : #endif
      36             : 
      37             : u_int32_t
      38           0 : sdmmc_cisptr(struct sdmmc_function *sf)
      39             : {
      40           0 :         struct sdmmc_function *sf0 = sf->sc->sc_fn0;
      41             :         u_int32_t cisptr = 0;
      42             :         int reg;
      43             : 
      44           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
      45             : 
      46           0 :         reg = SD_IO_CCCR_CISPTR + (sf->number * SD_IO_CCCR_SIZE);
      47           0 :         cisptr |= sdmmc_io_read_1(sf0, reg + 0) << 0;
      48           0 :         cisptr |= sdmmc_io_read_1(sf0, reg + 1) << 8;
      49           0 :         cisptr |= sdmmc_io_read_1(sf0, reg + 2) << 16;
      50             : 
      51           0 :         return cisptr;
      52             : }
      53             : 
      54             : int
      55           0 : sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis *cis)
      56             : {
      57           0 :         struct sdmmc_function *sf0 = sf->sc->sc_fn0;
      58             :         int reg;
      59             :         u_int8_t tplcode;
      60             :         u_int8_t tpllen;
      61             : 
      62           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
      63             : 
      64           0 :         reg = (int)sdmmc_cisptr(sf);
      65           0 :         if (reg < SD_IO_CIS_START ||
      66           0 :             reg >= (SD_IO_CIS_START+SD_IO_CIS_SIZE-16)) {
      67           0 :                 printf("%s: bad CIS ptr %#x\n", DEVNAME(sf->sc), reg);
      68           0 :                 return 1;
      69             :         }
      70             : 
      71           0 :         for (;;) {
      72           0 :                 tplcode = sdmmc_io_read_1(sf0, reg++);
      73           0 :                 if (tplcode == SD_IO_CISTPL_END)
      74             :                         break;
      75           0 :                 if (tplcode == SD_IO_CISTPL_NULL)
      76           0 :                         continue;
      77             : 
      78           0 :                 tpllen = sdmmc_io_read_1(sf0, reg++);
      79           0 :                 if (tpllen == 0) {
      80           0 :                         printf("%s: CIS parse error at %d, "
      81             :                             "tuple code %#x, length %d\n",
      82           0 :                             DEVNAME(sf->sc), reg, tplcode, tpllen);
      83           0 :                         break;
      84             :                 }
      85             : 
      86           0 :                 switch (tplcode) {
      87             :                 case SD_IO_CISTPL_FUNCID:
      88           0 :                         if (tpllen < 2) {
      89           0 :                                 printf("%s: bad CISTPL_FUNCID length\n",
      90           0 :                                     DEVNAME(sf->sc));
      91           0 :                                 reg += tpllen;
      92           0 :                                 break;
      93             :                         }
      94           0 :                         cis->function = sdmmc_io_read_1(sf0, reg);
      95           0 :                         reg += tpllen;
      96           0 :                         break;
      97             :                 case SD_IO_CISTPL_MANFID:
      98           0 :                         if (tpllen < 4) {
      99           0 :                                 printf("%s: bad CISTPL_MANFID length\n",
     100           0 :                                     DEVNAME(sf->sc));
     101           0 :                                 reg += tpllen;
     102           0 :                                 break;
     103             :                         }
     104           0 :                         cis->manufacturer = sdmmc_io_read_1(sf0, reg++);
     105           0 :                         cis->manufacturer |= sdmmc_io_read_1(sf0, reg++) << 8;
     106           0 :                         cis->product = sdmmc_io_read_1(sf0, reg++);
     107           0 :                         cis->product |= sdmmc_io_read_1(sf0, reg++) << 8;
     108           0 :                         break;
     109             :                 case SD_IO_CISTPL_VERS_1:
     110           0 :                         if (tpllen < 2) {
     111           0 :                                 printf("%s: CISTPL_VERS_1 too short\n",
     112           0 :                                     DEVNAME(sf->sc));
     113           0 :                                 reg += tpllen;
     114           0 :                                 break;
     115             :                         }
     116             :                         {
     117             :                                 int start, i, ch, count;
     118             : 
     119           0 :                                 cis->cis1_major = sdmmc_io_read_1(sf0, reg++);
     120           0 :                                 cis->cis1_minor = sdmmc_io_read_1(sf0, reg++);
     121             : 
     122           0 :                                 for (count = 0, start = 0, i = 0;
     123           0 :                                      (count < 4) && ((i + 4) < 256); i++) {
     124           0 :                                         ch = sdmmc_io_read_1(sf0, reg + i);
     125           0 :                                         if (ch == 0xff)
     126             :                                                 break;
     127           0 :                                         cis->cis1_info_buf[i] = ch;
     128           0 :                                         if (ch == 0) {
     129           0 :                                                 cis->cis1_info[count] =
     130           0 :                                                     cis->cis1_info_buf + start;
     131           0 :                                                 start = i + 1;
     132           0 :                                                 count++;
     133           0 :                                         }
     134             :                                 }
     135             : 
     136           0 :                                 reg += tpllen - 2;
     137             :                         }
     138           0 :                         break;
     139             :                 default:
     140             :                         DPRINTF(("%s: unknown tuple code %#x, length %d\n",
     141             :                             DEVNAME(sf->sc), tplcode, tpllen));
     142           0 :                         reg += tpllen;
     143           0 :                         break;
     144             :                 }
     145             :         }
     146             : 
     147           0 :         return 0;
     148           0 : }
     149             : 
     150             : void
     151           0 : sdmmc_print_cis(struct sdmmc_function *sf)
     152             : {
     153           0 :         struct sdmmc_cis *cis = &sf->cis;
     154             :         int i;
     155             : 
     156           0 :         printf("%s: CIS version %d.%d\n", DEVNAME(sf->sc),
     157           0 :             cis->cis1_major, cis->cis1_minor);
     158             : 
     159           0 :         printf("%s: CIS info: ", DEVNAME(sf->sc));
     160           0 :         for (i = 0; i < 4; i++) {
     161           0 :                 if (cis->cis1_info[i] == NULL)
     162             :                         break;
     163           0 :                 if (i)
     164           0 :                         printf(", ");
     165           0 :                 printf("%s", cis->cis1_info[i]);
     166             :         }
     167           0 :         printf("\n");
     168             : 
     169           0 :         printf("%s: Manufacturer code 0x%x, product 0x%x\n",
     170           0 :             DEVNAME(sf->sc), cis->manufacturer, cis->product);
     171             : 
     172           0 :         printf("%s: function %d: ", DEVNAME(sf->sc), sf->number);
     173           0 :         switch (sf->cis.function) {
     174             :         case TPLFID_FUNCTION_SDIO:
     175           0 :                 printf("SDIO");
     176           0 :                 break;
     177             :         default:
     178           0 :                 printf("unknown (%d)", sf->cis.function);
     179           0 :                 break;
     180             :         }
     181           0 :         printf("\n");
     182           0 : }
     183             : 
     184             : void
     185           0 : sdmmc_check_cis_quirks(struct sdmmc_function *sf)
     186             : {
     187           0 :         if (sf->cis.manufacturer == SDMMC_VENDOR_SPECTEC &&
     188           0 :             sf->cis.product == SDMMC_PRODUCT_SPECTEC_SDW820) {
     189             :                 /* This card lacks the VERS_1 tuple. */
     190           0 :                 sf->cis.cis1_major = 0x01;
     191           0 :                 sf->cis.cis1_minor = 0x00;
     192           0 :                 sf->cis.cis1_info[0] = "Spectec";
     193           0 :                 sf->cis.cis1_info[1] = "SDIO WLAN Card";
     194           0 :                 sf->cis.cis1_info[2] = "SDW-820";
     195           0 :                 sf->cis.cis1_info[3] = "";
     196           0 :         }
     197           0 : }

Generated by: LCOV version 1.13