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