This source file includes following definitions.
- sdmmc_cisptr
- sdmmc_read_cis
- sdmmc_print_cis
- sdmmc_check_cis_quirks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
42 if (sf->number != 0)
43 return SD_IO_CIS_START;
44
45
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
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
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 }