[BACK]Return to sdmmc_cis.c CVS log [TXT][DIR] Up to [local] / sys / dev / sdmmc

Annotation of sys/dev/sdmmc/sdmmc_cis.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb