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