[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     ! 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