1*d47bcd29Schs /* $NetBSD: pcmcia_cis.c,v 1.57 2019/11/10 21:16:36 chs Exp $ */
2c66b8643Sthorpej
3c66b8643Sthorpej /*
4c66b8643Sthorpej * Copyright (c) 1997 Marc Horowitz. All rights reserved.
5c66b8643Sthorpej *
6c66b8643Sthorpej * Redistribution and use in source and binary forms, with or without
7c66b8643Sthorpej * modification, are permitted provided that the following conditions
8c66b8643Sthorpej * are met:
9c66b8643Sthorpej * 1. Redistributions of source code must retain the above copyright
10c66b8643Sthorpej * notice, this list of conditions and the following disclaimer.
11c66b8643Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
12c66b8643Sthorpej * notice, this list of conditions and the following disclaimer in the
13c66b8643Sthorpej * documentation and/or other materials provided with the distribution.
14c66b8643Sthorpej * 3. All advertising materials mentioning features or use of this software
15c66b8643Sthorpej * must display the following acknowledgement:
16c66b8643Sthorpej * This product includes software developed by Marc Horowitz.
17c66b8643Sthorpej * 4. The name of the author may not be used to endorse or promote products
18c66b8643Sthorpej * derived from this software without specific prior written permission.
19c66b8643Sthorpej *
20c66b8643Sthorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21c66b8643Sthorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22c66b8643Sthorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23c66b8643Sthorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24c66b8643Sthorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25c66b8643Sthorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26c66b8643Sthorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27c66b8643Sthorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28c66b8643Sthorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29c66b8643Sthorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30c66b8643Sthorpej */
31c66b8643Sthorpej
32ab5d9d2bSlukem #include <sys/cdefs.h>
33*d47bcd29Schs __KERNEL_RCSID(0, "$NetBSD: pcmcia_cis.c,v 1.57 2019/11/10 21:16:36 chs Exp $");
34ab5d9d2bSlukem
35c66b8643Sthorpej #include <sys/param.h>
36c66b8643Sthorpej #include <sys/systm.h>
37c66b8643Sthorpej #include <sys/device.h>
38c66b8643Sthorpej #include <sys/malloc.h>
39c66b8643Sthorpej
40c66b8643Sthorpej #include <dev/pcmcia/pcmciareg.h>
41c66b8643Sthorpej #include <dev/pcmcia/pcmciachip.h>
42c66b8643Sthorpej #include <dev/pcmcia/pcmciavar.h>
43c66b8643Sthorpej
44c66b8643Sthorpej #ifdef PCMCIACISDEBUG
45c66b8643Sthorpej int pcmciacis_debug = 0;
46c66b8643Sthorpej #define DPRINTF(arg) if (pcmciacis_debug) printf arg
47c66b8643Sthorpej #else
48c66b8643Sthorpej #define DPRINTF(arg)
49c66b8643Sthorpej #endif
50c66b8643Sthorpej
51c66b8643Sthorpej #define PCMCIA_CIS_SIZE 1024
52c66b8643Sthorpej
53c66b8643Sthorpej struct cis_state {
54c66b8643Sthorpej int count;
55c66b8643Sthorpej int gotmfc;
56c66b8643Sthorpej struct pcmcia_config_entry temp_cfe;
57c66b8643Sthorpej struct pcmcia_config_entry *default_cfe;
58c66b8643Sthorpej struct pcmcia_card *card;
59c66b8643Sthorpej struct pcmcia_function *pf;
60c66b8643Sthorpej };
61c66b8643Sthorpej
6218db93c7Sperry int pcmcia_parse_cis_tuple(struct pcmcia_tuple *, void *);
6318db93c7Sperry static void create_pf(struct cis_state *);
648130f0ecShaya
65c2909c51Schristos static void decode_end(struct pcmcia_tuple *, struct cis_state *);
66c2909c51Schristos static void decode_longlink_mfc(struct pcmcia_tuple *, struct cis_state *);
67c2909c51Schristos static void decode_device(struct pcmcia_tuple *, struct cis_state *);
68c2909c51Schristos static void decode_vers_1(struct pcmcia_tuple *, struct cis_state *);
69c2909c51Schristos static void decode_manfid(struct pcmcia_tuple *, struct cis_state *);
70c2909c51Schristos static void decode_funcid(struct pcmcia_tuple *, struct cis_state *);
71c2909c51Schristos static void decode_funce(struct pcmcia_tuple *, struct cis_state *);
72c2909c51Schristos static void decode_config(struct pcmcia_tuple *, struct cis_state *);
73c2909c51Schristos static void decode_cftable_entry(struct pcmcia_tuple *, struct cis_state *);
74c2909c51Schristos
75c66b8643Sthorpej
764251568aSchristos static void
create_pf(struct cis_state * state)774251568aSchristos create_pf(struct cis_state *state)
784251568aSchristos {
79*d47bcd29Schs state->pf = malloc(sizeof(*state->pf), M_DEVBUF, M_WAITOK|M_ZERO);
804251568aSchristos state->pf->number = state->count++;
814251568aSchristos state->pf->last_config_index = -1;
824251568aSchristos SIMPLEQ_INIT(&state->pf->cfe_head);
834251568aSchristos SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf, pf_list);
844251568aSchristos }
854251568aSchristos
864251568aSchristos void
pcmcia_free_pf(struct pcmcia_function_head * pfhead)874251568aSchristos pcmcia_free_pf(struct pcmcia_function_head *pfhead)
884251568aSchristos {
89740cc023Senami struct pcmcia_function *pf, *npf;
90740cc023Senami struct pcmcia_config_entry *cfe, *ncfe;
914251568aSchristos
92740cc023Senami for (pf = SIMPLEQ_FIRST(pfhead); pf != NULL; pf = npf) {
93740cc023Senami npf = SIMPLEQ_NEXT(pf, pf_list);
94740cc023Senami for (cfe = SIMPLEQ_FIRST(&pf->cfe_head); cfe != NULL;
95740cc023Senami cfe = ncfe) {
96740cc023Senami ncfe = SIMPLEQ_NEXT(cfe, cfe_list);
97740cc023Senami free(cfe, M_DEVBUF);
984251568aSchristos }
99740cc023Senami free(pf, M_DEVBUF);
1004251568aSchristos }
1014251568aSchristos
1024251568aSchristos SIMPLEQ_INIT(pfhead);
1034251568aSchristos }
1044251568aSchristos
105c66b8643Sthorpej void
pcmcia_read_cis(struct pcmcia_softc * sc)106454af1c0Sdsl pcmcia_read_cis(struct pcmcia_softc *sc)
107c66b8643Sthorpej {
108c66b8643Sthorpej struct cis_state state;
109c66b8643Sthorpej
110d4471177Scgd memset(&state, 0, sizeof state);
111c66b8643Sthorpej
112c66b8643Sthorpej state.card = &sc->card;
113c66b8643Sthorpej
114c66b8643Sthorpej state.card->error = 0;
115c66b8643Sthorpej state.card->cis1_major = -1;
116c66b8643Sthorpej state.card->cis1_minor = -1;
117c66b8643Sthorpej state.card->cis1_info[0] = NULL;
118c66b8643Sthorpej state.card->cis1_info[1] = NULL;
119c66b8643Sthorpej state.card->cis1_info[2] = NULL;
120c66b8643Sthorpej state.card->cis1_info[3] = NULL;
121e3bc2915Schristos state.card->manufacturer = PCMCIA_VENDOR_INVALID;
1224e304b8dSenami state.card->product = PCMCIA_PRODUCT_INVALID;
123c66b8643Sthorpej SIMPLEQ_INIT(&state.card->pf_head);
124c66b8643Sthorpej
125c66b8643Sthorpej state.pf = NULL;
126c66b8643Sthorpej
12702b7e019Sdrochner if (pcmcia_scan_cis(sc->dev, pcmcia_parse_cis_tuple,
12883449d89Schristos &state) == -1)
129c66b8643Sthorpej state.card->error++;
130c66b8643Sthorpej }
131c66b8643Sthorpej
132c66b8643Sthorpej int
pcmcia_scan_cis(device_t dev,int (* fct)(struct pcmcia_tuple *,void *),void * arg)1337cf29912Scegger pcmcia_scan_cis(device_t dev,
134d3189d35Scegger int (*fct)(struct pcmcia_tuple *, void *),
135d3189d35Scegger void *arg)
136c66b8643Sthorpej {
13702b7e019Sdrochner struct pcmcia_softc *sc = device_private(dev);
138c66b8643Sthorpej pcmcia_chipset_tag_t pct;
139c66b8643Sthorpej pcmcia_chipset_handle_t pch;
140c66b8643Sthorpej int window;
141c66b8643Sthorpej struct pcmcia_mem_handle pcmh;
142c66b8643Sthorpej struct pcmcia_tuple tuple;
143c66b8643Sthorpej int longlink_present;
144c66b8643Sthorpej int longlink_common;
145c66b8643Sthorpej u_long longlink_addr;
146c66b8643Sthorpej int mfc_count;
147c66b8643Sthorpej int mfc_index;
148c66b8643Sthorpej struct {
149c66b8643Sthorpej int common;
150c66b8643Sthorpej u_long addr;
151c66b8643Sthorpej } mfc[256 / 5];
152c66b8643Sthorpej int ret;
153c66b8643Sthorpej
154c66b8643Sthorpej ret = 0;
155c66b8643Sthorpej
156c66b8643Sthorpej pct = sc->pct;
157c66b8643Sthorpej pch = sc->pch;
158c66b8643Sthorpej
159c66b8643Sthorpej /* allocate some memory */
160c66b8643Sthorpej
161c66b8643Sthorpej if (pcmcia_chip_mem_alloc(pct, pch, PCMCIA_CIS_SIZE, &pcmh)) {
162c66b8643Sthorpej #ifdef DIAGNOSTIC
16302b7e019Sdrochner aprint_error_dev(sc->dev,
16402b7e019Sdrochner "can't alloc memory to read attributes\n");
165c66b8643Sthorpej #endif
16683449d89Schristos return -1;
167c66b8643Sthorpej }
168c66b8643Sthorpej /* initialize state for the primary tuple chain */
169c66b8643Sthorpej if (pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_ATTR, 0,
170c66b8643Sthorpej PCMCIA_CIS_SIZE, &pcmh, &tuple.ptr, &window)) {
171c66b8643Sthorpej pcmcia_chip_mem_free(pct, pch, &pcmh);
172c66b8643Sthorpej #ifdef DIAGNOSTIC
17302b7e019Sdrochner aprint_error_dev(sc->dev,
17402b7e019Sdrochner "can't map memory to read attributes\n");
175c66b8643Sthorpej #endif
17683449d89Schristos return -1;
177c66b8643Sthorpej }
178d85c2b7eStoshii tuple.memt = pcmh.memt;
179d85c2b7eStoshii tuple.memh = pcmh.memh;
180d85c2b7eStoshii
181c66b8643Sthorpej DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
182c66b8643Sthorpej
183c66b8643Sthorpej tuple.mult = 2;
184c66b8643Sthorpej
185c66b8643Sthorpej longlink_present = 1;
186c66b8643Sthorpej longlink_common = 1;
187c66b8643Sthorpej longlink_addr = 0;
188c66b8643Sthorpej
189c66b8643Sthorpej mfc_count = 0;
190c66b8643Sthorpej mfc_index = 0;
191c66b8643Sthorpej
19202b7e019Sdrochner DPRINTF(("%s: CIS tuple chain:\n", device_xname(sc->dev)));
193c66b8643Sthorpej
194c66b8643Sthorpej while (1) {
1954343cdf0Smycroft DELAY(1000);
1964343cdf0Smycroft
197c66b8643Sthorpej while (1) {
1980f210a88Sitohy /*
1990f210a88Sitohy * Perform boundary check for insane cards.
2000f210a88Sitohy * If CIS is too long, simulate CIS end.
2010f210a88Sitohy * (This check may not be sufficient for
2020f210a88Sitohy * malicious cards.)
2030f210a88Sitohy */
2040f210a88Sitohy if (tuple.mult * tuple.ptr >= PCMCIA_CIS_SIZE - 1
2050f210a88Sitohy - 32 /* ad hoc value */ ) {
2060f210a88Sitohy DPRINTF(("CISTPL_END (too long CIS)\n"));
2070f210a88Sitohy tuple.code = PCMCIA_CISTPL_END;
2080f210a88Sitohy goto cis_end;
2090f210a88Sitohy }
2100f210a88Sitohy
211c66b8643Sthorpej /* get the tuple code */
212c66b8643Sthorpej
213c66b8643Sthorpej tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
214c66b8643Sthorpej
215c66b8643Sthorpej /* two special-case tuples */
216c66b8643Sthorpej
217d663cd12Smarc if (tuple.code == PCMCIA_CISTPL_NULL) {
218ea0d4e37Smycroft DPRINTF((" 00\nCISTPL_NONE\n"));
219c66b8643Sthorpej tuple.ptr++;
220c66b8643Sthorpej continue;
221d663cd12Smarc } else if (tuple.code == PCMCIA_CISTPL_END) {
222ea0d4e37Smycroft DPRINTF((" ff\nCISTPL_END\n"));
2230f210a88Sitohy cis_end:
224d663cd12Smarc /* Call the function for the END tuple, since
225d663cd12Smarc the CIS semantics depend on it */
226d663cd12Smarc if ((*fct) (&tuple, arg)) {
227d663cd12Smarc pcmcia_chip_mem_unmap(pct, pch,
228d663cd12Smarc window);
229d663cd12Smarc ret = 1;
230d663cd12Smarc goto done;
231d663cd12Smarc }
232c66b8643Sthorpej tuple.ptr++;
233c66b8643Sthorpej break;
234c66b8643Sthorpej }
235ea0d4e37Smycroft
236c66b8643Sthorpej /* now all the normal tuples */
237c66b8643Sthorpej
238c66b8643Sthorpej tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
2394343cdf0Smycroft #ifdef PCMCIACISDEBUG
2404343cdf0Smycroft /* print the tuple */
2414343cdf0Smycroft {
2424343cdf0Smycroft int i;
2434343cdf0Smycroft
2444343cdf0Smycroft DPRINTF((" %02x %02x", tuple.code,
2454343cdf0Smycroft tuple.length));
2464343cdf0Smycroft
2474343cdf0Smycroft for (i = 0; i < tuple.length; i++) {
2484343cdf0Smycroft DPRINTF((" %02x",
2494343cdf0Smycroft pcmcia_tuple_read_1(&tuple, i)));
2504343cdf0Smycroft if ((i % 16) == 13)
2514343cdf0Smycroft DPRINTF(("\n"));
2524343cdf0Smycroft }
2534343cdf0Smycroft if ((i % 16) != 14)
2544343cdf0Smycroft DPRINTF(("\n"));
2554343cdf0Smycroft }
2564343cdf0Smycroft #endif
257c66b8643Sthorpej switch (tuple.code) {
258c66b8643Sthorpej case PCMCIA_CISTPL_LONGLINK_A:
259c66b8643Sthorpej case PCMCIA_CISTPL_LONGLINK_C:
260c66b8643Sthorpej if (tuple.length < 4) {
261c66b8643Sthorpej DPRINTF(("CISTPL_LONGLINK_%s too "
262c66b8643Sthorpej "short %d\n",
263c66b8643Sthorpej longlink_common ? "C" : "A",
264c66b8643Sthorpej tuple.length));
265c66b8643Sthorpej break;
266c66b8643Sthorpej }
267c66b8643Sthorpej longlink_present = 1;
268c66b8643Sthorpej longlink_common = (tuple.code ==
269c66b8643Sthorpej PCMCIA_CISTPL_LONGLINK_C) ? 1 : 0;
270c66b8643Sthorpej longlink_addr = pcmcia_tuple_read_4(&tuple, 0);
271c66b8643Sthorpej DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
272c66b8643Sthorpej longlink_common ? "C" : "A",
273c66b8643Sthorpej longlink_addr));
274c66b8643Sthorpej break;
275c66b8643Sthorpej case PCMCIA_CISTPL_NO_LINK:
276c66b8643Sthorpej longlink_present = 0;
277c66b8643Sthorpej DPRINTF(("CISTPL_NO_LINK\n"));
278c66b8643Sthorpej break;
279c66b8643Sthorpej case PCMCIA_CISTPL_CHECKSUM:
280c66b8643Sthorpej if (tuple.length < 5) {
281c66b8643Sthorpej DPRINTF(("CISTPL_CHECKSUM too "
282c66b8643Sthorpej "short %d\n", tuple.length));
283c66b8643Sthorpej break;
284c66b8643Sthorpej } {
285c66b8643Sthorpej int16_t offset;
286c66b8643Sthorpej u_long addr, length;
287c66b8643Sthorpej u_int cksum, sum;
288c66b8643Sthorpej int i;
289c66b8643Sthorpej
290c66b8643Sthorpej *((u_int16_t *) & offset) =
291c66b8643Sthorpej pcmcia_tuple_read_2(&tuple, 0);
292c66b8643Sthorpej length = pcmcia_tuple_read_2(&tuple, 2);
293c66b8643Sthorpej cksum = pcmcia_tuple_read_1(&tuple, 4);
294c66b8643Sthorpej
295c66b8643Sthorpej addr = tuple.ptr + offset;
296c66b8643Sthorpej
297c66b8643Sthorpej DPRINTF(("CISTPL_CHECKSUM addr=%lx "
298c66b8643Sthorpej "len=%lx cksum=%x",
299c66b8643Sthorpej addr, length, cksum));
300c66b8643Sthorpej
301c66b8643Sthorpej /*
302c66b8643Sthorpej * XXX do more work to deal with
303c66b8643Sthorpej * distant regions
304c66b8643Sthorpej */
305c66b8643Sthorpej if ((addr >= PCMCIA_CIS_SIZE) ||
306bd4bd1bfSchristos #if 0
307c66b8643Sthorpej ((addr + length) < 0) ||
308bd4bd1bfSchristos #endif
309c66b8643Sthorpej ((addr + length) >=
310c66b8643Sthorpej PCMCIA_CIS_SIZE)) {
311c66b8643Sthorpej DPRINTF((" skipped, "
312c66b8643Sthorpej "too distant\n"));
313c66b8643Sthorpej break;
314c66b8643Sthorpej }
315c66b8643Sthorpej sum = 0;
316c66b8643Sthorpej for (i = 0; i < length; i++)
317c66b8643Sthorpej sum +=
318c66b8643Sthorpej bus_space_read_1(tuple.memt,
319c66b8643Sthorpej tuple.memh,
320c66b8643Sthorpej addr + tuple.mult * i);
321c66b8643Sthorpej if (cksum != (sum & 0xff)) {
322c66b8643Sthorpej DPRINTF((" failed sum=%x\n",
323c66b8643Sthorpej sum));
32402b7e019Sdrochner aprint_error_dev(sc->dev,
32502b7e019Sdrochner "CIS checksum failed\n");
326c66b8643Sthorpej #if 0
327c66b8643Sthorpej /*
328c66b8643Sthorpej * XXX Some working cards have
329c66b8643Sthorpej * XXX bad checksums!!
330c66b8643Sthorpej */
33183449d89Schristos ret = -1;
332c66b8643Sthorpej #endif
333c66b8643Sthorpej } else {
334c66b8643Sthorpej DPRINTF((" ok\n"));
335c66b8643Sthorpej }
336c66b8643Sthorpej }
337c66b8643Sthorpej break;
338c66b8643Sthorpej case PCMCIA_CISTPL_LONGLINK_MFC:
339c66b8643Sthorpej if (tuple.length < 1) {
340c66b8643Sthorpej DPRINTF(("CISTPL_LONGLINK_MFC too "
341c66b8643Sthorpej "short %d\n", tuple.length));
342c66b8643Sthorpej break;
343c66b8643Sthorpej }
344d4471177Scgd if (((tuple.length - 1) % 5) != 0) {
345d4471177Scgd DPRINTF(("CISTPL_LONGLINK_MFC bogus "
346d4471177Scgd "length %d\n", tuple.length));
347d4471177Scgd break;
348d4471177Scgd }
349c66b8643Sthorpej /*
350c66b8643Sthorpej * this is kind of ad hoc, as I don't have
351c66b8643Sthorpej * any real documentation
352c66b8643Sthorpej */
353c66b8643Sthorpej {
354d4471177Scgd int i, tmp_count;
355c66b8643Sthorpej
356d4471177Scgd /*
357d4471177Scgd * put count into tmp var so that
358d4471177Scgd * if we have to bail (because it's
359d4471177Scgd * a bogus count) it won't be
360d4471177Scgd * remembered for later use.
361d4471177Scgd */
362d4471177Scgd tmp_count =
363c66b8643Sthorpej pcmcia_tuple_read_1(&tuple, 0);
364c66b8643Sthorpej DPRINTF(("CISTPL_LONGLINK_MFC %d",
365d4471177Scgd tmp_count));
366d4471177Scgd
367d4471177Scgd /*
368d4471177Scgd * make _sure_ it's the right size;
369d4471177Scgd * if too short, it may be a weird
370d4471177Scgd * (unknown/undefined) format
371d4471177Scgd */
372d4471177Scgd if (tuple.length != (tmp_count*5 + 1)) {
373d4471177Scgd DPRINTF((" bogus length %d\n",
374d4471177Scgd tuple.length));
375d4471177Scgd break;
376d4471177Scgd }
377d4471177Scgd
378d4471177Scgd #ifdef PCMCIACISDEBUG /* maybe enable all the time? */
379d4471177Scgd /*
380d4471177Scgd * sanity check for a programming
381d4471177Scgd * error which is difficult to find
382d4471177Scgd * when debugging.
383d4471177Scgd */
384d4471177Scgd if (tmp_count >
385d4471177Scgd howmany(sizeof mfc, sizeof mfc[0]))
386d4471177Scgd panic("CISTPL_LONGLINK_MFC mfc "
387d4471177Scgd "count would blow stack");
388d4471177Scgd #endif
389d4471177Scgd
390d4471177Scgd mfc_count = tmp_count;
391c66b8643Sthorpej for (i = 0; i < mfc_count; i++) {
392c66b8643Sthorpej mfc[i].common =
393c66b8643Sthorpej (pcmcia_tuple_read_1(&tuple,
394c66b8643Sthorpej 1 + 5 * i) ==
395c66b8643Sthorpej PCMCIA_MFC_MEM_COMMON) ?
396c66b8643Sthorpej 1 : 0;
397c66b8643Sthorpej mfc[i].addr =
398c66b8643Sthorpej pcmcia_tuple_read_4(&tuple,
399c66b8643Sthorpej 1 + 5 * i + 1);
400c66b8643Sthorpej DPRINTF((" %s:%lx",
401c66b8643Sthorpej mfc[i].common ? "common" :
402c66b8643Sthorpej "attr", mfc[i].addr));
403c66b8643Sthorpej }
404c66b8643Sthorpej DPRINTF(("\n"));
405c66b8643Sthorpej }
406c66b8643Sthorpej /*
407c66b8643Sthorpej * for LONGLINK_MFC, fall through to the
408c66b8643Sthorpej * function. This tuple has structural and
409c66b8643Sthorpej * semantic content.
410c66b8643Sthorpej */
411fbffadb9Smrg /* FALLTHROUGH */
412c66b8643Sthorpej default:
413c66b8643Sthorpej {
414c66b8643Sthorpej if ((*fct) (&tuple, arg)) {
415c66b8643Sthorpej pcmcia_chip_mem_unmap(pct,
416c66b8643Sthorpej pch, window);
41783449d89Schristos ret = 1;
418c66b8643Sthorpej goto done;
419c66b8643Sthorpej }
420c66b8643Sthorpej }
421c66b8643Sthorpej break;
422c66b8643Sthorpej } /* switch */
423c66b8643Sthorpej /* skip to the next tuple */
424c66b8643Sthorpej tuple.ptr += 2 + tuple.length;
425c66b8643Sthorpej }
4269ada0bf4Smarc
427c66b8643Sthorpej /*
428c66b8643Sthorpej * the chain is done. Clean up and move onto the next one,
429c66b8643Sthorpej * if any. The loop is here in the case that there is an MFC
430c66b8643Sthorpej * card with no longlink (which defaults to existing, == 0).
431c66b8643Sthorpej * In general, this means that if one pointer fails, it will
432c66b8643Sthorpej * try the next one, instead of just bailing.
433c66b8643Sthorpej */
434c66b8643Sthorpej
435c66b8643Sthorpej while (1) {
436c66b8643Sthorpej pcmcia_chip_mem_unmap(pct, pch, window);
437c66b8643Sthorpej
438c66b8643Sthorpej if (longlink_present) {
439c66b8643Sthorpej /*
440c66b8643Sthorpej * if the longlink is to attribute memory,
441c66b8643Sthorpej * then it is unindexed. That is, if the
442c66b8643Sthorpej * link value is 0x100, then the actual
443c66b8643Sthorpej * memory address is 0x200. This means that
444c66b8643Sthorpej * we need to multiply by 2 before calling
445c66b8643Sthorpej * mem_map, and then divide the resulting ptr
446c66b8643Sthorpej * by 2 after.
447c66b8643Sthorpej */
448c66b8643Sthorpej
449c66b8643Sthorpej if (!longlink_common)
450c66b8643Sthorpej longlink_addr *= 2;
451c66b8643Sthorpej
452c66b8643Sthorpej pcmcia_chip_mem_map(pct, pch, longlink_common ?
453d8595b9aSchopps (PCMCIA_WIDTH_MEM8 | PCMCIA_MEM_COMMON) :
454d8595b9aSchopps PCMCIA_MEM_ATTR,
455c66b8643Sthorpej longlink_addr, PCMCIA_CIS_SIZE,
456c66b8643Sthorpej &pcmh, &tuple.ptr, &window);
457c66b8643Sthorpej
45839b794a4Sgdamore tuple.memt = pcmh.memt;
45939b794a4Sgdamore tuple.memh = pcmh.memh;
46039b794a4Sgdamore
461c66b8643Sthorpej if (!longlink_common)
462c66b8643Sthorpej tuple.ptr /= 2;
463c66b8643Sthorpej
464c66b8643Sthorpej DPRINTF(("cis mem map %x\n",
465c66b8643Sthorpej (unsigned int) tuple.memh));
466c66b8643Sthorpej
467c66b8643Sthorpej tuple.mult = longlink_common ? 1 : 2;
468c66b8643Sthorpej longlink_present = 0;
469c66b8643Sthorpej longlink_common = 1;
470c66b8643Sthorpej longlink_addr = 0;
471c66b8643Sthorpej } else if (mfc_count && (mfc_index < mfc_count)) {
472c66b8643Sthorpej if (!mfc[mfc_index].common)
473c66b8643Sthorpej mfc[mfc_index].addr *= 2;
474c66b8643Sthorpej
475c66b8643Sthorpej pcmcia_chip_mem_map(pct, pch,
476c66b8643Sthorpej mfc[mfc_index].common ?
47791026fe7Senami (PCMCIA_WIDTH_MEM8 | PCMCIA_MEM_COMMON) :
47891026fe7Senami PCMCIA_MEM_ATTR,
479c66b8643Sthorpej mfc[mfc_index].addr, PCMCIA_CIS_SIZE,
480c66b8643Sthorpej &pcmh, &tuple.ptr, &window);
481c66b8643Sthorpej
482c66b8643Sthorpej if (!mfc[mfc_index].common)
483c66b8643Sthorpej tuple.ptr /= 2;
484c66b8643Sthorpej
485c66b8643Sthorpej DPRINTF(("cis mem map %x\n",
486c66b8643Sthorpej (unsigned int) tuple.memh));
487c66b8643Sthorpej
488c66b8643Sthorpej /* set parse state, and point at the next one */
489c66b8643Sthorpej
490c66b8643Sthorpej tuple.mult = mfc[mfc_index].common ? 1 : 2;
491c66b8643Sthorpej
492c66b8643Sthorpej mfc_index++;
493c66b8643Sthorpej } else {
494c66b8643Sthorpej goto done;
495c66b8643Sthorpej }
496c66b8643Sthorpej
497c66b8643Sthorpej /* make sure that the link is valid */
498c66b8643Sthorpej tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
499c66b8643Sthorpej if (tuple.code != PCMCIA_CISTPL_LINKTARGET) {
500c66b8643Sthorpej DPRINTF(("CISTPL_LINKTARGET expected, "
501c66b8643Sthorpej "code %02x observed\n", tuple.code));
502c66b8643Sthorpej continue;
503c66b8643Sthorpej }
504c66b8643Sthorpej tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
505c66b8643Sthorpej if (tuple.length < 3) {
506c66b8643Sthorpej DPRINTF(("CISTPL_LINKTARGET too short %d\n",
507c66b8643Sthorpej tuple.length));
508c66b8643Sthorpej continue;
509c66b8643Sthorpej }
510c66b8643Sthorpej if ((pcmcia_tuple_read_1(&tuple, 0) != 'C') ||
511c66b8643Sthorpej (pcmcia_tuple_read_1(&tuple, 1) != 'I') ||
512c66b8643Sthorpej (pcmcia_tuple_read_1(&tuple, 2) != 'S')) {
513c66b8643Sthorpej DPRINTF(("CISTPL_LINKTARGET magic "
514c66b8643Sthorpej "%02x%02x%02x incorrect\n",
515c66b8643Sthorpej pcmcia_tuple_read_1(&tuple, 0),
516c66b8643Sthorpej pcmcia_tuple_read_1(&tuple, 1),
517c66b8643Sthorpej pcmcia_tuple_read_1(&tuple, 2)));
518c66b8643Sthorpej continue;
519c66b8643Sthorpej }
520c66b8643Sthorpej tuple.ptr += 2 + tuple.length;
521c66b8643Sthorpej
522c66b8643Sthorpej break;
523c66b8643Sthorpej }
524c66b8643Sthorpej }
525c66b8643Sthorpej
526c66b8643Sthorpej pcmcia_chip_mem_unmap(pct, pch, window);
527c66b8643Sthorpej
528c66b8643Sthorpej done:
529c66b8643Sthorpej /* Last, free the allocated memory block */
530c66b8643Sthorpej pcmcia_chip_mem_free(pct, pch, &pcmh);
531c66b8643Sthorpej
532c66b8643Sthorpej return (ret);
533c66b8643Sthorpej }
534c66b8643Sthorpej
535c66b8643Sthorpej /* XXX this is incredibly verbose. Not sure what trt is */
536c66b8643Sthorpej
537c66b8643Sthorpej void
pcmcia_print_cis(struct pcmcia_softc * sc)538454af1c0Sdsl pcmcia_print_cis(struct pcmcia_softc *sc)
539c66b8643Sthorpej {
540c66b8643Sthorpej struct pcmcia_card *card = &sc->card;
541c66b8643Sthorpej struct pcmcia_function *pf;
542c66b8643Sthorpej struct pcmcia_config_entry *cfe;
543c66b8643Sthorpej int i;
544c66b8643Sthorpej
54502b7e019Sdrochner printf("%s: CIS version ", device_xname(sc->dev));
5467734e0efSmsaitoh if (card->cis1_major == 4) {
5477734e0efSmsaitoh if (card->cis1_minor == 0)
5487734e0efSmsaitoh printf("PCMCIA 1.0\n");
5497734e0efSmsaitoh else if (card->cis1_minor == 1)
5507734e0efSmsaitoh printf("PCMCIA 2.0 or 2.1\n");
5517734e0efSmsaitoh } else if (card->cis1_major >= 5)
5527734e0efSmsaitoh printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
553c66b8643Sthorpej else
554c66b8643Sthorpej printf("unknown (major=%d, minor=%d)\n",
555c66b8643Sthorpej card->cis1_major, card->cis1_minor);
556c66b8643Sthorpej
55702b7e019Sdrochner printf("%s: CIS info: ", device_xname(sc->dev));
558c66b8643Sthorpej for (i = 0; i < 4; i++) {
559c66b8643Sthorpej if (card->cis1_info[i] == NULL)
560c66b8643Sthorpej break;
561c66b8643Sthorpej if (i)
562c66b8643Sthorpej printf(", ");
563c66b8643Sthorpej printf("%s", card->cis1_info[i]);
564c66b8643Sthorpej }
565c66b8643Sthorpej printf("\n");
566c66b8643Sthorpej
567c66b8643Sthorpej printf("%s: Manufacturer code 0x%x, product 0x%x\n",
56802b7e019Sdrochner device_xname(sc->dev), card->manufacturer, card->product);
569c66b8643Sthorpej
57006de4264Slukem SIMPLEQ_FOREACH(pf, &card->pf_head, pf_list) {
57102b7e019Sdrochner printf("%s: function %d: ", device_xname(sc->dev), pf->number);
572c66b8643Sthorpej
573c66b8643Sthorpej switch (pf->function) {
574a461703dSnathanw case PCMCIA_FUNCTION_UNSPEC:
575a461703dSnathanw printf("unspecified");
576a461703dSnathanw break;
577a461703dSnathanw case PCMCIA_FUNCTION_MULTIFUNCTION:
578c66b8643Sthorpej printf("multi-function");
579c66b8643Sthorpej break;
580a461703dSnathanw case PCMCIA_FUNCTION_MEMORY:
581c66b8643Sthorpej printf("memory");
582c66b8643Sthorpej break;
583a461703dSnathanw case PCMCIA_FUNCTION_SERIAL:
584c66b8643Sthorpej printf("serial port");
585c66b8643Sthorpej break;
586a461703dSnathanw case PCMCIA_FUNCTION_PARALLEL:
587c66b8643Sthorpej printf("parallel port");
588c66b8643Sthorpej break;
589a461703dSnathanw case PCMCIA_FUNCTION_DISK:
590c66b8643Sthorpej printf("fixed disk");
5918130f0ecShaya switch (pf->pf_funce_disk_interface) {
5928130f0ecShaya case PCMCIA_TPLFE_DDI_PCCARD_ATA:
5938130f0ecShaya printf("(ata)");
5948130f0ecShaya break;
5958130f0ecShaya default:
5968130f0ecShaya break;
5978130f0ecShaya }
598c66b8643Sthorpej break;
599a461703dSnathanw case PCMCIA_FUNCTION_VIDEO:
600c66b8643Sthorpej printf("video adapter");
601c66b8643Sthorpej break;
602a461703dSnathanw case PCMCIA_FUNCTION_NETWORK:
603c66b8643Sthorpej printf("network adapter");
604c66b8643Sthorpej break;
605a461703dSnathanw case PCMCIA_FUNCTION_AIMS:
606c66b8643Sthorpej printf("auto incrementing mass storage");
607c66b8643Sthorpej break;
608a461703dSnathanw case PCMCIA_FUNCTION_SCSI:
60934b0df80Smsaitoh printf("SCSI bridge");
61034b0df80Smsaitoh break;
611a461703dSnathanw case PCMCIA_FUNCTION_SECURITY:
61234b0df80Smsaitoh printf("Security services");
61334b0df80Smsaitoh break;
614a461703dSnathanw case PCMCIA_FUNCTION_INSTRUMENT:
61534b0df80Smsaitoh printf("Instrument");
61634b0df80Smsaitoh break;
617c66b8643Sthorpej default:
618c66b8643Sthorpej printf("unknown (%d)", pf->function);
619c66b8643Sthorpej break;
620c66b8643Sthorpej }
621c66b8643Sthorpej
622c66b8643Sthorpej printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
623c66b8643Sthorpej
62406de4264Slukem SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
625c66b8643Sthorpej printf("%s: function %d, config table entry %d: ",
62602b7e019Sdrochner device_xname(sc->dev), pf->number, cfe->number);
627c66b8643Sthorpej
628c66b8643Sthorpej switch (cfe->iftype) {
629c66b8643Sthorpej case PCMCIA_IFTYPE_MEMORY:
630c66b8643Sthorpej printf("memory card");
631c66b8643Sthorpej break;
632c66b8643Sthorpej case PCMCIA_IFTYPE_IO:
633c66b8643Sthorpej printf("I/O card");
634c66b8643Sthorpej break;
635c66b8643Sthorpej default:
636c66b8643Sthorpej printf("card type unknown");
637c66b8643Sthorpej break;
638c66b8643Sthorpej }
639c66b8643Sthorpej
640c66b8643Sthorpej printf("; irq mask %x", cfe->irqmask);
641c66b8643Sthorpej
642c66b8643Sthorpej if (cfe->num_iospace) {
643c66b8643Sthorpej printf("; iomask %lx, iospace", cfe->iomask);
644c66b8643Sthorpej
6458567277aSenami for (i = 0; i < cfe->num_iospace; i++) {
6468567277aSenami printf(" %lx", cfe->iospace[i].start);
647c95ed3d2Sbad if (cfe->iospace[i].length)
648c95ed3d2Sbad printf("-%lx",
649c66b8643Sthorpej cfe->iospace[i].start +
650c66b8643Sthorpej cfe->iospace[i].length - 1);
651c66b8643Sthorpej }
6528567277aSenami }
653c66b8643Sthorpej if (cfe->num_memspace) {
654c66b8643Sthorpej printf("; memspace");
655c66b8643Sthorpej
6568567277aSenami for (i = 0; i < cfe->num_memspace; i++) {
657c95ed3d2Sbad printf(" %lx",
658c95ed3d2Sbad cfe->memspace[i].cardaddr);
659c95ed3d2Sbad if (cfe->memspace[i].length)
660c95ed3d2Sbad printf("-%lx",
661c66b8643Sthorpej cfe->memspace[i].cardaddr +
662c95ed3d2Sbad cfe->memspace[i].length - 1);
663c95ed3d2Sbad if (cfe->memspace[i].hostaddr)
664c95ed3d2Sbad printf("@%lx",
665c66b8643Sthorpej cfe->memspace[i].hostaddr);
666c66b8643Sthorpej }
6678567277aSenami }
668c66b8643Sthorpej if (cfe->maxtwins)
669c66b8643Sthorpej printf("; maxtwins %d", cfe->maxtwins);
670c66b8643Sthorpej
671c66b8643Sthorpej printf(";");
672c66b8643Sthorpej
673c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_MWAIT_REQUIRED)
674c66b8643Sthorpej printf(" mwait_required");
675c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_RDYBSY_ACTIVE)
676c66b8643Sthorpej printf(" rdybsy_active");
677c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_WP_ACTIVE)
678c66b8643Sthorpej printf(" wp_active");
679c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_BVD_ACTIVE)
680c66b8643Sthorpej printf(" bvd_active");
681c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_IO8)
682c66b8643Sthorpej printf(" io8");
683c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_IO16)
684c66b8643Sthorpej printf(" io16");
685c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_IRQSHARE)
686c66b8643Sthorpej printf(" irqshare");
687c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_IRQPULSE)
688c66b8643Sthorpej printf(" irqpulse");
689c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_IRQLEVEL)
690c66b8643Sthorpej printf(" irqlevel");
691c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_POWERDOWN)
692c66b8643Sthorpej printf(" powerdown");
693c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_READONLY)
694c66b8643Sthorpej printf(" readonly");
695c66b8643Sthorpej if (cfe->flags & PCMCIA_CFE_AUDIO)
696c66b8643Sthorpej printf(" audio");
697c66b8643Sthorpej
698c66b8643Sthorpej printf("\n");
699c66b8643Sthorpej }
700c66b8643Sthorpej }
701c66b8643Sthorpej
702c66b8643Sthorpej if (card->error)
703c66b8643Sthorpej printf("%s: %d errors found while parsing CIS\n",
70402b7e019Sdrochner device_xname(sc->dev), card->error);
705c66b8643Sthorpej }
706c66b8643Sthorpej
707c66b8643Sthorpej int
pcmcia_parse_cis_tuple(struct pcmcia_tuple * tuple,void * arg)708454af1c0Sdsl pcmcia_parse_cis_tuple(struct pcmcia_tuple *tuple, void *arg)
709c66b8643Sthorpej {
710c66b8643Sthorpej struct cis_state *state = arg;
711c66b8643Sthorpej
712c66b8643Sthorpej switch (tuple->code) {
713d663cd12Smarc case PCMCIA_CISTPL_END:
714c2909c51Schristos decode_end(tuple, state);
715c2909c51Schristos break;
716c2909c51Schristos
717c2909c51Schristos case PCMCIA_CISTPL_LONGLINK_MFC:
718c2909c51Schristos decode_longlink_mfc(tuple, state);
719c2909c51Schristos break;
720c2909c51Schristos
721c2909c51Schristos case PCMCIA_CISTPL_DEVICE:
722c2909c51Schristos case PCMCIA_CISTPL_DEVICE_A:
723c2909c51Schristos decode_device(tuple, state);
724c2909c51Schristos break;
725c2909c51Schristos
726c2909c51Schristos case PCMCIA_CISTPL_VERS_1:
727c2909c51Schristos decode_vers_1(tuple, state);
728c2909c51Schristos break;
729c2909c51Schristos
730c2909c51Schristos case PCMCIA_CISTPL_MANFID:
731c2909c51Schristos decode_manfid(tuple, state);
732c2909c51Schristos break;
733c2909c51Schristos
734c2909c51Schristos case PCMCIA_CISTPL_FUNCID:
735c2909c51Schristos decode_funcid(tuple, state);
736c2909c51Schristos break;
737c2909c51Schristos
738c2909c51Schristos case PCMCIA_CISTPL_FUNCE:
739c2909c51Schristos decode_funce(tuple, state);
740c2909c51Schristos break;
741c2909c51Schristos
742c2909c51Schristos case PCMCIA_CISTPL_CONFIG:
743c2909c51Schristos decode_config(tuple, state);
744c2909c51Schristos break;
745c2909c51Schristos
746c2909c51Schristos case PCMCIA_CISTPL_CFTABLE_ENTRY:
747c2909c51Schristos decode_cftable_entry(tuple, state);
748c2909c51Schristos break;
749c2909c51Schristos default:
750c2909c51Schristos DPRINTF(("unhandled CISTPL %x\n", tuple->code));
751c2909c51Schristos break;
752c2909c51Schristos }
753c2909c51Schristos
754c2909c51Schristos return (0);
755c2909c51Schristos }
756c2909c51Schristos
757c2909c51Schristos static void
decode_end(struct pcmcia_tuple * tuple,struct cis_state * state)758168cd830Schristos decode_end(struct pcmcia_tuple *tuple, struct cis_state *state)
759c2909c51Schristos {
760d663cd12Smarc /* if we've seen a LONGLINK_MFC, and this is the first
761d663cd12Smarc * END after it, reset the function list.
762d663cd12Smarc *
763d663cd12Smarc * XXX This might also be the right place to start a
764d663cd12Smarc * new function, but that assumes that a function
765d663cd12Smarc * definition never crosses any longlink, and I'm not
766d663cd12Smarc * sure about that. This is probably safe for MFC
767d663cd12Smarc * cards, but what we have now isn't broken, so I'd
768d663cd12Smarc * rather not change it.
769c66b8643Sthorpej */
770d663cd12Smarc if (state->gotmfc == 1) {
771d663cd12Smarc state->gotmfc = 2;
7724251568aSchristos state->count = 0;
773c66b8643Sthorpej state->pf = NULL;
7744251568aSchristos
7754251568aSchristos pcmcia_free_pf(&state->card->pf_head);
776c66b8643Sthorpej }
777c2909c51Schristos }
778c2909c51Schristos
779c2909c51Schristos static void
decode_longlink_mfc(struct pcmcia_tuple * tuple,struct cis_state * state)780168cd830Schristos decode_longlink_mfc(struct pcmcia_tuple *tuple,
7814d595fd7Schristos struct cis_state *state)
782c2909c51Schristos {
783d663cd12Smarc /*
784d663cd12Smarc * this tuple's structure was dealt with in scan_cis. here,
785d663cd12Smarc * record the fact that the MFC tuple was seen, so that
786d663cd12Smarc * functions declared before the MFC link can be cleaned
787d663cd12Smarc * up.
788d663cd12Smarc */
7894251568aSchristos if (state->gotmfc == 0) {
790d663cd12Smarc state->gotmfc = 1;
7914251568aSchristos } else {
7924251568aSchristos DPRINTF(("got LONGLINK_MFC again!"));
7934251568aSchristos }
794c2909c51Schristos }
795c2909c51Schristos
796c2909c51Schristos static void
decode_device(struct pcmcia_tuple * tuple,struct cis_state * state)797168cd830Schristos decode_device(struct pcmcia_tuple *tuple,
798168cd830Schristos struct cis_state *state)
799c66b8643Sthorpej {
800c2909c51Schristos #ifdef PCMCIACISDEBUG
801c66b8643Sthorpej u_int reg, dtype, dspeed;
802c66b8643Sthorpej
803c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, 0);
804c66b8643Sthorpej dtype = reg & PCMCIA_DTYPE_MASK;
805c66b8643Sthorpej dspeed = reg & PCMCIA_DSPEED_MASK;
806c66b8643Sthorpej
807c66b8643Sthorpej DPRINTF(("CISTPL_DEVICE%s type=",
808c66b8643Sthorpej (tuple->code == PCMCIA_CISTPL_DEVICE) ? "" : "_A"));
809c66b8643Sthorpej switch (dtype) {
810c66b8643Sthorpej case PCMCIA_DTYPE_NULL:
811c66b8643Sthorpej DPRINTF(("null"));
812c66b8643Sthorpej break;
813c66b8643Sthorpej case PCMCIA_DTYPE_ROM:
814c66b8643Sthorpej DPRINTF(("rom"));
815c66b8643Sthorpej break;
816c66b8643Sthorpej case PCMCIA_DTYPE_OTPROM:
817c66b8643Sthorpej DPRINTF(("otprom"));
818c66b8643Sthorpej break;
819c66b8643Sthorpej case PCMCIA_DTYPE_EPROM:
820c66b8643Sthorpej DPRINTF(("eprom"));
821c66b8643Sthorpej break;
822c66b8643Sthorpej case PCMCIA_DTYPE_EEPROM:
823c66b8643Sthorpej DPRINTF(("eeprom"));
824c66b8643Sthorpej break;
825c66b8643Sthorpej case PCMCIA_DTYPE_FLASH:
826c66b8643Sthorpej DPRINTF(("flash"));
827c66b8643Sthorpej break;
828c66b8643Sthorpej case PCMCIA_DTYPE_SRAM:
829c66b8643Sthorpej DPRINTF(("sram"));
830c66b8643Sthorpej break;
831c66b8643Sthorpej case PCMCIA_DTYPE_DRAM:
832c66b8643Sthorpej DPRINTF(("dram"));
833c66b8643Sthorpej break;
834c66b8643Sthorpej case PCMCIA_DTYPE_FUNCSPEC:
835c66b8643Sthorpej DPRINTF(("funcspec"));
836c66b8643Sthorpej break;
837c66b8643Sthorpej case PCMCIA_DTYPE_EXTEND:
838c66b8643Sthorpej DPRINTF(("extend"));
839c66b8643Sthorpej break;
840c66b8643Sthorpej default:
841c66b8643Sthorpej DPRINTF(("reserved"));
842c66b8643Sthorpej break;
843c66b8643Sthorpej }
844c66b8643Sthorpej DPRINTF((" speed="));
845c66b8643Sthorpej switch (dspeed) {
846c66b8643Sthorpej case PCMCIA_DSPEED_NULL:
847c66b8643Sthorpej DPRINTF(("null"));
848c66b8643Sthorpej break;
849c66b8643Sthorpej case PCMCIA_DSPEED_250NS:
850c66b8643Sthorpej DPRINTF(("250ns"));
851c66b8643Sthorpej break;
852c66b8643Sthorpej case PCMCIA_DSPEED_200NS:
853c66b8643Sthorpej DPRINTF(("200ns"));
854c66b8643Sthorpej break;
855c66b8643Sthorpej case PCMCIA_DSPEED_150NS:
856c66b8643Sthorpej DPRINTF(("150ns"));
857c66b8643Sthorpej break;
858c66b8643Sthorpej case PCMCIA_DSPEED_100NS:
859c66b8643Sthorpej DPRINTF(("100ns"));
860c66b8643Sthorpej break;
861c66b8643Sthorpej case PCMCIA_DSPEED_EXT:
862c66b8643Sthorpej DPRINTF(("ext"));
863c66b8643Sthorpej break;
864c66b8643Sthorpej default:
865c66b8643Sthorpej DPRINTF(("reserved"));
866c66b8643Sthorpej break;
867c66b8643Sthorpej }
868c66b8643Sthorpej DPRINTF(("\n"));
869c66b8643Sthorpej #endif
870c2909c51Schristos }
871c2909c51Schristos
872c2909c51Schristos static void
decode_vers_1(struct pcmcia_tuple * tuple,struct cis_state * state)873c2909c51Schristos decode_vers_1(struct pcmcia_tuple *tuple, struct cis_state *state)
874c2909c51Schristos {
875c2909c51Schristos int start, i, ch, count;
876c2909c51Schristos
877c66b8643Sthorpej if (tuple->length < 6) {
878c66b8643Sthorpej DPRINTF(("CISTPL_VERS_1 too short %d\n",
879c66b8643Sthorpej tuple->length));
880c2909c51Schristos return;
881c2909c51Schristos }
882c66b8643Sthorpej state->card->cis1_major = pcmcia_tuple_read_1(tuple, 0);
883c66b8643Sthorpej state->card->cis1_minor = pcmcia_tuple_read_1(tuple, 1);
884c66b8643Sthorpej
885c66b8643Sthorpej for (count = 0, start = 0, i = 0;
886c66b8643Sthorpej (count < 4) && ((i + 4) < 256); i++) {
887c66b8643Sthorpej ch = pcmcia_tuple_read_1(tuple, 2 + i);
888ceafcbd8Sjun if (ch == 0xff) {
889ceafcbd8Sjun if (i > start) {
890ceafcbd8Sjun state->card->cis1_info_buf[i] = 0;
891ceafcbd8Sjun state->card->cis1_info[count] =
892ceafcbd8Sjun state->card->cis1_info_buf + start;
893ceafcbd8Sjun }
894c66b8643Sthorpej break;
895ceafcbd8Sjun }
896c66b8643Sthorpej state->card->cis1_info_buf[i] = ch;
897c66b8643Sthorpej if (ch == 0) {
898c66b8643Sthorpej state->card->cis1_info[count] =
899c66b8643Sthorpej state->card->cis1_info_buf + start;
900c66b8643Sthorpej start = i + 1;
901c66b8643Sthorpej count++;
902c66b8643Sthorpej }
903c66b8643Sthorpej }
904c66b8643Sthorpej DPRINTF(("CISTPL_VERS_1\n"));
905c66b8643Sthorpej }
906c2909c51Schristos
907c2909c51Schristos static void
decode_manfid(struct pcmcia_tuple * tuple,struct cis_state * state)908c2909c51Schristos decode_manfid(struct pcmcia_tuple *tuple, struct cis_state *state)
909c2909c51Schristos {
910c66b8643Sthorpej if (tuple->length < 4) {
911c66b8643Sthorpej DPRINTF(("CISTPL_MANFID too short %d\n",
912c66b8643Sthorpej tuple->length));
913c2909c51Schristos return;
914c66b8643Sthorpej }
915c66b8643Sthorpej state->card->manufacturer = pcmcia_tuple_read_2(tuple, 0);
916c66b8643Sthorpej state->card->product = pcmcia_tuple_read_2(tuple, 2);
917c66b8643Sthorpej DPRINTF(("CISTPL_MANFID\n"));
918c2909c51Schristos }
919c2909c51Schristos
920c2909c51Schristos static void
decode_funcid(struct pcmcia_tuple * tuple,struct cis_state * state)921c2909c51Schristos decode_funcid(struct pcmcia_tuple *tuple, struct cis_state *state)
922c2909c51Schristos {
923c66b8643Sthorpej if (tuple->length < 1) {
924c66b8643Sthorpej DPRINTF(("CISTPL_FUNCID too short %d\n",
925c66b8643Sthorpej tuple->length));
926c2909c51Schristos return;
927c66b8643Sthorpej }
928b495351fSbouyer if (state->pf) {
929b495351fSbouyer if (state->pf->function == PCMCIA_FUNCTION_UNSPEC) {
930b495351fSbouyer /*
931b495351fSbouyer * This looks like a opportunistic function
932b495351fSbouyer * created by a CONFIG tuple. Just keep it.
933b495351fSbouyer */
934b495351fSbouyer } else {
935b495351fSbouyer /*
936b495351fSbouyer * A function is being defined, end it.
937b495351fSbouyer */
938b495351fSbouyer state->pf = NULL;
939b495351fSbouyer }
940b495351fSbouyer }
9414251568aSchristos if (state->pf == NULL)
9424251568aSchristos create_pf(state);
943c66b8643Sthorpej state->pf->function = pcmcia_tuple_read_1(tuple, 0);
944c66b8643Sthorpej
945c66b8643Sthorpej DPRINTF(("CISTPL_FUNCID\n"));
946c2909c51Schristos }
947c2909c51Schristos
948c2909c51Schristos static void
decode_funce(struct pcmcia_tuple * tuple,struct cis_state * state)949c2909c51Schristos decode_funce(struct pcmcia_tuple *tuple, struct cis_state *state)
950c2909c51Schristos {
951c2909c51Schristos struct pcmcia_function *pf = state->pf;
952c2909c51Schristos int type = pcmcia_tuple_read_1(tuple, 0);
953c2909c51Schristos
9548130f0ecShaya if (state->pf == NULL || state->pf->function <= 0) {
9558130f0ecShaya DPRINTF(("CISTPL_FUNCE is not followed by "
9568130f0ecShaya "valid CISTPL_FUNCID\n"));
957c2909c51Schristos return;
9588130f0ecShaya }
959c2909c51Schristos if (tuple->length < 2)
960c2909c51Schristos return;
961c2909c51Schristos switch (pf->function) {
962c2909c51Schristos case PCMCIA_FUNCTION_DISK:
963c2909c51Schristos if (type == PCMCIA_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
964c2909c51Schristos pf->pf_funce_disk_interface
965c2909c51Schristos = pcmcia_tuple_read_1(tuple, 1);
9668130f0ecShaya }
9678130f0ecShaya break;
968c2909c51Schristos case PCMCIA_FUNCTION_NETWORK:
969c2909c51Schristos if (type == PCMCIA_TPLFE_TYPE_LAN_NID) {
970c2909c51Schristos int i;
971c2909c51Schristos int len = pcmcia_tuple_read_1(tuple, 1);
972c2909c51Schristos if (tuple->length < 2 + len || len > 8) {
973c2909c51Schristos /* tuple length not enough or nid too long */
974c66b8643Sthorpej break;
975c2909c51Schristos }
976c2909c51Schristos for (i = 0; i < len; ++i) {
977c2909c51Schristos pf->pf_funce_lan_nid[i]
978c2909c51Schristos = pcmcia_tuple_read_1(tuple, 2 + i);
979c2909c51Schristos }
980c2909c51Schristos pf->pf_funce_lan_nidlen = len;
981c2909c51Schristos }
982c2909c51Schristos break;
983c2909c51Schristos default:
984c2909c51Schristos break;
985c2909c51Schristos }
986c2909c51Schristos
987c2909c51Schristos return;
988c2909c51Schristos }
989c2909c51Schristos
990c2909c51Schristos static void
decode_config(struct pcmcia_tuple * tuple,struct cis_state * state)991c2909c51Schristos decode_config(struct pcmcia_tuple *tuple, struct cis_state *state)
992c2909c51Schristos {
993c66b8643Sthorpej u_int reg, rasz, rmsz, rfsz;
994c66b8643Sthorpej int i;
995c2909c51Schristos /* most of these are educated guesses */
996c2909c51Schristos static const struct pcmcia_config_entry init_cfe = {
9973cd45450Schristos .number = -1,
9983cd45450Schristos .flags = PCMCIA_CFE_RDYBSY_ACTIVE | PCMCIA_CFE_WP_ACTIVE |
9993cd45450Schristos PCMCIA_CFE_BVD_ACTIVE,
10003cd45450Schristos .iftype = PCMCIA_IFTYPE_MEMORY,
1001c2909c51Schristos };
1002c66b8643Sthorpej
1003c2909c51Schristos if (tuple->length < 3) {
1004c2909c51Schristos DPRINTF(("CISTPL_CONFIG too short %d\n", tuple->length));
1005c2909c51Schristos return;
1006c2909c51Schristos }
1007c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, 0);
1008c66b8643Sthorpej rasz = 1 + ((reg & PCMCIA_TPCC_RASZ_MASK) >>
1009c66b8643Sthorpej PCMCIA_TPCC_RASZ_SHIFT);
1010c66b8643Sthorpej rmsz = 1 + ((reg & PCMCIA_TPCC_RMSZ_MASK) >>
1011c66b8643Sthorpej PCMCIA_TPCC_RMSZ_SHIFT);
1012c66b8643Sthorpej rfsz = ((reg & PCMCIA_TPCC_RFSZ_MASK) >>
1013c66b8643Sthorpej PCMCIA_TPCC_RFSZ_SHIFT);
1014c66b8643Sthorpej
1015c66b8643Sthorpej if (tuple->length < (rasz + rmsz + rfsz)) {
1016c2909c51Schristos DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too short %d\n",
1017c2909c51Schristos rasz, rmsz, rfsz, tuple->length));
1018c2909c51Schristos return;
1019c66b8643Sthorpej }
1020c66b8643Sthorpej if (state->pf == NULL) {
10214251568aSchristos create_pf(state);
1022a461703dSnathanw state->pf->function = PCMCIA_FUNCTION_UNSPEC;
1023c66b8643Sthorpej }
1024c66b8643Sthorpej state->pf->last_config_index =
1025c66b8643Sthorpej pcmcia_tuple_read_1(tuple, 1);
1026c66b8643Sthorpej
1027c66b8643Sthorpej state->pf->ccr_base = 0;
1028c66b8643Sthorpej for (i = 0; i < rasz; i++)
1029c2909c51Schristos state->pf->ccr_base |= ((pcmcia_tuple_read_1(tuple, 2 + i)) <<
1030c66b8643Sthorpej (i * 8));
1031c66b8643Sthorpej
1032c66b8643Sthorpej state->pf->ccr_mask = 0;
1033c66b8643Sthorpej for (i = 0; i < rmsz; i++)
1034c2909c51Schristos state->pf->ccr_mask |= ((pcmcia_tuple_read_1(tuple,
1035c66b8643Sthorpej 2 + rasz + i)) << (i * 8));
1036c66b8643Sthorpej
1037c66b8643Sthorpej /* skip the reserved area and subtuples */
1038c66b8643Sthorpej
1039c66b8643Sthorpej /* reset the default cfe for each cfe list */
1040c66b8643Sthorpej state->temp_cfe = init_cfe;
1041c66b8643Sthorpej state->default_cfe = &state->temp_cfe;
1042c66b8643Sthorpej DPRINTF(("CISTPL_CONFIG\n"));
1043c2909c51Schristos }
1044c2909c51Schristos
1045c2909c51Schristos static void
decode_cftable_entry(struct pcmcia_tuple * tuple,struct cis_state * state)1046c2909c51Schristos decode_cftable_entry(struct pcmcia_tuple *tuple, struct cis_state *state)
1047c66b8643Sthorpej {
1048c66b8643Sthorpej int idx, i, j;
1049c66b8643Sthorpej u_int reg, reg2;
1050c66b8643Sthorpej u_int intface, def, num;
1051c66b8643Sthorpej u_int power, timing, iospace, irq, memspace, misc;
1052c66b8643Sthorpej struct pcmcia_config_entry *cfe;
1053c66b8643Sthorpej
1054c66b8643Sthorpej idx = 0;
1055c66b8643Sthorpej
1056c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1057c66b8643Sthorpej idx++;
1058c66b8643Sthorpej intface = reg & PCMCIA_TPCE_INDX_INTFACE;
1059c66b8643Sthorpej def = reg & PCMCIA_TPCE_INDX_DEFAULT;
1060c66b8643Sthorpej num = reg & PCMCIA_TPCE_INDX_NUM_MASK;
1061c66b8643Sthorpej
1062c66b8643Sthorpej /*
1063c66b8643Sthorpej * this is a little messy. Some cards have only a
1064c66b8643Sthorpej * cfentry with the default bit set. So, as we go
1065c66b8643Sthorpej * through the list, we add new indexes to the queue,
1066c66b8643Sthorpej * and keep a pointer to the last one with the
1067c66b8643Sthorpej * default bit set. if we see a record with the same
1068c66b8643Sthorpej * index, as the default, we stash the default and
1069c66b8643Sthorpej * replace the queue entry. otherwise, we just add
1070c66b8643Sthorpej * new entries to the queue, pointing the default ptr
1071c66b8643Sthorpej * at them if the default bit is set. if we get to
1072c66b8643Sthorpej * the end with the default pointer pointing at a
1073c66b8643Sthorpej * record which hasn't had a matching index, that's
1074c66b8643Sthorpej * ok; it just becomes a cfentry like any other.
1075c66b8643Sthorpej */
1076c66b8643Sthorpej
1077c66b8643Sthorpej /*
1078c66b8643Sthorpej * if the index in the cis differs from the default
1079c66b8643Sthorpej * cis, create new entry in the queue and start it
1080c66b8643Sthorpej * with the current default
1081c66b8643Sthorpej */
1082d4471177Scgd if (state->default_cfe == NULL) {
1083d4471177Scgd DPRINTF(("CISTPL_CFTABLE_ENTRY with no "
1084d4471177Scgd "default\n"));
1085c2909c51Schristos return;
1086d4471177Scgd }
1087c66b8643Sthorpej if (num != state->default_cfe->number) {
1088*d47bcd29Schs cfe = malloc(sizeof(*cfe), M_DEVBUF, M_WAITOK);
1089c66b8643Sthorpej *cfe = *state->default_cfe;
1090c66b8643Sthorpej
1091c2909c51Schristos SIMPLEQ_INSERT_TAIL(&state->pf->cfe_head, cfe, cfe_list);
1092c66b8643Sthorpej
1093c66b8643Sthorpej cfe->number = num;
1094c66b8643Sthorpej
1095c66b8643Sthorpej /*
1096c66b8643Sthorpej * if the default bit is set in the cis, then
1097c66b8643Sthorpej * point the new default at whatever is being
1098c66b8643Sthorpej * filled in
1099c66b8643Sthorpej */
1100c66b8643Sthorpej if (def)
1101c66b8643Sthorpej state->default_cfe = cfe;
1102c66b8643Sthorpej } else {
1103c66b8643Sthorpej /*
1104c66b8643Sthorpej * the cis index matches the default index,
1105c66b8643Sthorpej * fill in the default cfentry. It is
1106c66b8643Sthorpej * assumed that the cfdefault index is in the
1107c66b8643Sthorpej * queue. For it to be otherwise, the cis
1108c66b8643Sthorpej * index would have to be -1 (initial
1109c66b8643Sthorpej * condition) which is not possible, or there
1110c66b8643Sthorpej * would have to be a preceding cis entry
1111c66b8643Sthorpej * which had the same cis index and had the
1112c66b8643Sthorpej * default bit unset. Neither condition
1113c66b8643Sthorpej * should happen. If it does, this cfentry
1114c66b8643Sthorpej * is lost (written into temp space), which
1115c66b8643Sthorpej * is an acceptable failure mode.
1116c66b8643Sthorpej */
1117c66b8643Sthorpej
1118c66b8643Sthorpej cfe = state->default_cfe;
1119c66b8643Sthorpej
1120c66b8643Sthorpej /*
1121c66b8643Sthorpej * if the cis entry does not have the default
1122c66b8643Sthorpej * bit set, copy the default out of the way
1123c66b8643Sthorpej * first.
1124c66b8643Sthorpej */
1125c66b8643Sthorpej if (!def) {
1126c66b8643Sthorpej state->temp_cfe = *state->default_cfe;
1127c66b8643Sthorpej state->default_cfe = &state->temp_cfe;
1128c66b8643Sthorpej }
1129c66b8643Sthorpej }
1130c66b8643Sthorpej
1131c66b8643Sthorpej if (intface) {
1132c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1133c66b8643Sthorpej idx++;
1134b5064330Schopps cfe->flags &= ~(PCMCIA_CFE_MWAIT_REQUIRED
1135b5064330Schopps | PCMCIA_CFE_RDYBSY_ACTIVE
1136b5064330Schopps | PCMCIA_CFE_WP_ACTIVE
1137b5064330Schopps | PCMCIA_CFE_BVD_ACTIVE);
1138c66b8643Sthorpej if (reg & PCMCIA_TPCE_IF_MWAIT)
1139c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_MWAIT_REQUIRED;
1140c66b8643Sthorpej if (reg & PCMCIA_TPCE_IF_RDYBSY)
1141c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_RDYBSY_ACTIVE;
1142c66b8643Sthorpej if (reg & PCMCIA_TPCE_IF_WP)
1143c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_WP_ACTIVE;
1144c66b8643Sthorpej if (reg & PCMCIA_TPCE_IF_BVD)
1145c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_BVD_ACTIVE;
1146c66b8643Sthorpej cfe->iftype = reg & PCMCIA_TPCE_IF_IFTYPE;
1147c66b8643Sthorpej }
1148c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1149c66b8643Sthorpej idx++;
1150c66b8643Sthorpej
1151c66b8643Sthorpej power = reg & PCMCIA_TPCE_FS_POWER_MASK;
1152c66b8643Sthorpej timing = reg & PCMCIA_TPCE_FS_TIMING;
1153c66b8643Sthorpej iospace = reg & PCMCIA_TPCE_FS_IOSPACE;
1154c66b8643Sthorpej irq = reg & PCMCIA_TPCE_FS_IRQ;
1155c66b8643Sthorpej memspace = reg & PCMCIA_TPCE_FS_MEMSPACE_MASK;
1156c66b8643Sthorpej misc = reg & PCMCIA_TPCE_FS_MISC;
1157c66b8643Sthorpej
1158c66b8643Sthorpej if (power) {
1159c66b8643Sthorpej /* skip over power, don't save */
1160c66b8643Sthorpej /* for each parameter selection byte */
1161c66b8643Sthorpej for (i = 0; i < power; i++) {
1162c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1163c66b8643Sthorpej idx++;
1164c66b8643Sthorpej /* for each bit */
1165c66b8643Sthorpej for (j = 0; j < 7; j++) {
1166c66b8643Sthorpej /* if the bit is set */
1167c66b8643Sthorpej if ((reg >> j) & 0x01) {
1168c66b8643Sthorpej /* skip over bytes */
1169c66b8643Sthorpej do {
1170c66b8643Sthorpej reg2 = pcmcia_tuple_read_1(tuple, idx);
1171c66b8643Sthorpej idx++;
1172c66b8643Sthorpej /*
1173c66b8643Sthorpej * until
1174e959b27dSmjl * non-
1175e959b27dSmjl * extension
1176e959b27dSmjl * byte
1177c66b8643Sthorpej */
1178c66b8643Sthorpej } while (reg2 & 0x80);
1179c66b8643Sthorpej }
1180c66b8643Sthorpej }
1181c66b8643Sthorpej }
1182c66b8643Sthorpej }
1183c66b8643Sthorpej if (timing) {
1184c66b8643Sthorpej /* skip over timing, don't save */
1185c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1186c66b8643Sthorpej idx++;
1187c66b8643Sthorpej
1188c66b8643Sthorpej if ((reg & PCMCIA_TPCE_TD_RESERVED_MASK) !=
1189c66b8643Sthorpej PCMCIA_TPCE_TD_RESERVED_MASK)
1190c66b8643Sthorpej idx++;
1191c66b8643Sthorpej if ((reg & PCMCIA_TPCE_TD_RDYBSY_MASK) !=
1192c66b8643Sthorpej PCMCIA_TPCE_TD_RDYBSY_MASK)
1193c66b8643Sthorpej idx++;
1194c66b8643Sthorpej if ((reg & PCMCIA_TPCE_TD_WAIT_MASK) !=
1195c66b8643Sthorpej PCMCIA_TPCE_TD_WAIT_MASK)
1196c66b8643Sthorpej idx++;
1197c66b8643Sthorpej }
1198c66b8643Sthorpej if (iospace) {
11999ada0bf4Smarc if (tuple->length <= idx) {
12009ada0bf4Smarc DPRINTF(("ran out of space before TCPE_IO\n"));
12019ada0bf4Smarc goto abort_cfe;
12029ada0bf4Smarc }
12039ada0bf4Smarc
1204c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1205c66b8643Sthorpej idx++;
1206c66b8643Sthorpej
1207b5064330Schopps cfe->flags &=
1208b5064330Schopps ~(PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16);
1209c66b8643Sthorpej if (reg & PCMCIA_TPCE_IO_BUSWIDTH_8BIT)
1210c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_IO8;
1211c66b8643Sthorpej if (reg & PCMCIA_TPCE_IO_BUSWIDTH_16BIT)
1212c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_IO16;
1213c66b8643Sthorpej cfe->iomask =
1214c66b8643Sthorpej reg & PCMCIA_TPCE_IO_IOADDRLINES_MASK;
1215c66b8643Sthorpej
1216c66b8643Sthorpej if (reg & PCMCIA_TPCE_IO_HASRANGE) {
1217c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1218c66b8643Sthorpej idx++;
1219c66b8643Sthorpej
1220c66b8643Sthorpej cfe->num_iospace = 1 + (reg &
1221c66b8643Sthorpej PCMCIA_TPCE_IO_RANGE_COUNT);
1222c66b8643Sthorpej
1223c66b8643Sthorpej if (cfe->num_iospace >
1224c66b8643Sthorpej (sizeof(cfe->iospace) /
1225c66b8643Sthorpej sizeof(cfe->iospace[0]))) {
1226c66b8643Sthorpej DPRINTF(("too many io "
1227c66b8643Sthorpej "spaces %d",
1228c66b8643Sthorpej cfe->num_iospace));
1229c66b8643Sthorpej state->card->error++;
1230c2909c51Schristos return;
1231c66b8643Sthorpej }
1232c66b8643Sthorpej for (i = 0; i < cfe->num_iospace; i++) {
1233c66b8643Sthorpej switch (reg & PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK) {
12340f8f9a1fSitojun case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_NONE:
12350f8f9a1fSitojun cfe->iospace[i].start =
12360f8f9a1fSitojun 0;
12370f8f9a1fSitojun break;
1238c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE:
1239c66b8643Sthorpej cfe->iospace[i].start =
1240c66b8643Sthorpej pcmcia_tuple_read_1(tuple, idx);
1241c66b8643Sthorpej idx++;
1242c66b8643Sthorpej break;
1243c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO:
1244c66b8643Sthorpej cfe->iospace[i].start =
1245c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1246c66b8643Sthorpej idx += 2;
1247c66b8643Sthorpej break;
1248c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1249c66b8643Sthorpej cfe->iospace[i].start =
1250c66b8643Sthorpej pcmcia_tuple_read_4(tuple, idx);
1251c66b8643Sthorpej idx += 4;
1252c66b8643Sthorpej break;
1253c66b8643Sthorpej }
1254c66b8643Sthorpej switch (reg &
1255c66b8643Sthorpej PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
12560f8f9a1fSitojun case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_NONE:
12570f8f9a1fSitojun cfe->iospace[i].length =
12580f8f9a1fSitojun 0;
12590f8f9a1fSitojun break;
1260c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1261c66b8643Sthorpej cfe->iospace[i].length =
1262c66b8643Sthorpej pcmcia_tuple_read_1(tuple, idx);
1263c66b8643Sthorpej idx++;
1264c66b8643Sthorpej break;
1265c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1266c66b8643Sthorpej cfe->iospace[i].length =
1267c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1268c66b8643Sthorpej idx += 2;
1269c66b8643Sthorpej break;
1270c66b8643Sthorpej case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1271c66b8643Sthorpej cfe->iospace[i].length =
1272c66b8643Sthorpej pcmcia_tuple_read_4(tuple, idx);
1273c66b8643Sthorpej idx += 4;
1274c66b8643Sthorpej break;
1275c66b8643Sthorpej }
1276c66b8643Sthorpej cfe->iospace[i].length++;
1277c66b8643Sthorpej }
1278c66b8643Sthorpej } else {
1279c66b8643Sthorpej cfe->num_iospace = 1;
1280c66b8643Sthorpej cfe->iospace[0].start = 0;
1281c66b8643Sthorpej cfe->iospace[0].length =
1282c66b8643Sthorpej (1 << cfe->iomask);
1283c66b8643Sthorpej }
1284c66b8643Sthorpej }
1285c66b8643Sthorpej if (irq) {
12869ada0bf4Smarc if (tuple->length <= idx) {
12879ada0bf4Smarc DPRINTF(("ran out of space before TCPE_IR\n"));
12889ada0bf4Smarc goto abort_cfe;
12899ada0bf4Smarc }
12909ada0bf4Smarc
1291c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1292c66b8643Sthorpej idx++;
1293c66b8643Sthorpej
1294b5064330Schopps cfe->flags &= ~(PCMCIA_CFE_IRQSHARE
1295b5064330Schopps | PCMCIA_CFE_IRQPULSE
1296b5064330Schopps | PCMCIA_CFE_IRQLEVEL);
1297c66b8643Sthorpej if (reg & PCMCIA_TPCE_IR_SHARE)
1298c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_IRQSHARE;
1299c66b8643Sthorpej if (reg & PCMCIA_TPCE_IR_PULSE)
1300c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_IRQPULSE;
1301c66b8643Sthorpej if (reg & PCMCIA_TPCE_IR_LEVEL)
1302c66b8643Sthorpej cfe->flags |= PCMCIA_CFE_IRQLEVEL;
1303c66b8643Sthorpej
1304c66b8643Sthorpej if (reg & PCMCIA_TPCE_IR_HASMASK) {
1305c66b8643Sthorpej /*
1306c66b8643Sthorpej * it's legal to ignore the
1307c66b8643Sthorpej * special-interrupt bits, so I will
1308c66b8643Sthorpej */
1309c66b8643Sthorpej
1310c66b8643Sthorpej cfe->irqmask =
1311c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1312c66b8643Sthorpej idx += 2;
1313c66b8643Sthorpej } else {
1314c66b8643Sthorpej cfe->irqmask =
1315c66b8643Sthorpej (1 << (reg & PCMCIA_TPCE_IR_IRQ));
1316c66b8643Sthorpej }
1317c66b8643Sthorpej }
13184b5dc3b5Schristos if (memspace) {
13194b5dc3b5Schristos int lengthsize;
13204b5dc3b5Schristos int cardaddrsize;
13214b5dc3b5Schristos int hostaddrsize;
13224b5dc3b5Schristos
1323abddbf01Srpaulo if (tuple->length <= idx) {
13249ada0bf4Smarc DPRINTF(("ran out of space before TCPE_MS\n"));
13259ada0bf4Smarc goto abort_cfe;
13269ada0bf4Smarc }
13279ada0bf4Smarc
1328c2909c51Schristos switch (memspace) {
13294b5dc3b5Schristos #ifdef notdef /* This is 0 */
1330c2909c51Schristos case PCMCIA_TPCE_FS_MEMSPACE_NONE:
13319ada0bf4Smarc cfe->num_memspace = 0;
1332c2909c51Schristos break;
13334b5dc3b5Schristos #endif
1334c2909c51Schristos
1335c2909c51Schristos case PCMCIA_TPCE_FS_MEMSPACE_LENGTH:
1336c66b8643Sthorpej cfe->num_memspace = 1;
1337c66b8643Sthorpej cfe->memspace[0].length = 256 *
1338c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1339c66b8643Sthorpej idx += 2;
1340c66b8643Sthorpej cfe->memspace[0].cardaddr = 0;
1341c66b8643Sthorpej cfe->memspace[0].hostaddr = 0;
1342c2909c51Schristos break;
1343c2909c51Schristos
1344c2909c51Schristos case PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR:
1345c66b8643Sthorpej cfe->num_memspace = 1;
1346c66b8643Sthorpej cfe->memspace[0].length = 256 *
1347c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1348c66b8643Sthorpej idx += 2;
1349c66b8643Sthorpej cfe->memspace[0].cardaddr = 256 *
1350c66b8643Sthorpej pcmcia_tuple_read_2(tuple, idx);
1351c66b8643Sthorpej idx += 2;
1352c2909c51Schristos cfe->memspace[0].hostaddr =
1353c2909c51Schristos cfe->memspace[0].cardaddr;
1354c2909c51Schristos break;
1355c2909c51Schristos
1356c2909c51Schristos default:
1357c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1358c66b8643Sthorpej idx++;
1359c66b8643Sthorpej
1360c2909c51Schristos cfe->num_memspace = (reg & PCMCIA_TPCE_MS_COUNT)
1361c2909c51Schristos + 1;
1362c66b8643Sthorpej
1363c66b8643Sthorpej if (cfe->num_memspace >
1364c66b8643Sthorpej (sizeof(cfe->memspace) /
1365c66b8643Sthorpej sizeof(cfe->memspace[0]))) {
1366c2909c51Schristos DPRINTF(("too many mem spaces %d",
1367c66b8643Sthorpej cfe->num_memspace));
1368c66b8643Sthorpej state->card->error++;
1369c2909c51Schristos return;
1370c66b8643Sthorpej }
1371c66b8643Sthorpej lengthsize =
1372c66b8643Sthorpej ((reg & PCMCIA_TPCE_MS_LENGTH_SIZE_MASK) >>
1373c66b8643Sthorpej PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT);
1374c66b8643Sthorpej cardaddrsize =
1375c2909c51Schristos ((reg &
1376c2909c51Schristos PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK) >>
1377c66b8643Sthorpej PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT);
1378c66b8643Sthorpej hostaddrsize =
1379c2909c51Schristos (reg & PCMCIA_TPCE_MS_HOSTADDR) ?
1380c2909c51Schristos cardaddrsize : 0;
1381c66b8643Sthorpej
1382c66b8643Sthorpej if (lengthsize == 0) {
1383c66b8643Sthorpej DPRINTF(("cfe memspace "
1384c66b8643Sthorpej "lengthsize == 0"));
1385c66b8643Sthorpej state->card->error++;
1386c66b8643Sthorpej }
1387c66b8643Sthorpej for (i = 0; i < cfe->num_memspace; i++) {
1388c66b8643Sthorpej if (lengthsize) {
1389c2909c51Schristos cfe->memspace[i].length = 256 *
1390c2909c51Schristos pcmcia_tuple_read_n(tuple,
1391c2909c51Schristos lengthsize, idx);
1392c66b8643Sthorpej idx += lengthsize;
1393c66b8643Sthorpej } else {
1394c66b8643Sthorpej cfe->memspace[i].length = 0;
1395c66b8643Sthorpej }
1396c66b8643Sthorpej if (cfe->memspace[i].length == 0) {
1397c2909c51Schristos DPRINTF(("cfe->memspace"
1398c2909c51Schristos "[%d].length == 0", i));
1399c66b8643Sthorpej state->card->error++;
1400c66b8643Sthorpej }
1401c66b8643Sthorpej if (cardaddrsize) {
1402c66b8643Sthorpej cfe->memspace[i].cardaddr =
1403c2909c51Schristos 256 *
1404c2909c51Schristos pcmcia_tuple_read_n(tuple,
1405c2909c51Schristos cardaddrsize, idx);
1406c66b8643Sthorpej idx += cardaddrsize;
1407c66b8643Sthorpej } else {
1408c66b8643Sthorpej cfe->memspace[i].cardaddr = 0;
1409c66b8643Sthorpej }
1410c66b8643Sthorpej if (hostaddrsize) {
1411c66b8643Sthorpej cfe->memspace[i].hostaddr =
1412c2909c51Schristos 256 *
1413c2909c51Schristos pcmcia_tuple_read_n(tuple,
1414c2909c51Schristos hostaddrsize, idx);
1415c66b8643Sthorpej idx += hostaddrsize;
1416c66b8643Sthorpej } else {
1417c66b8643Sthorpej cfe->memspace[i].hostaddr = 0;
1418c66b8643Sthorpej }
1419c66b8643Sthorpej }
1420c66b8643Sthorpej }
14212fdcddedSrpaulo }
1422c2909c51Schristos
1423c66b8643Sthorpej if (misc) {
14249ada0bf4Smarc if (tuple->length <= idx) {
14259ada0bf4Smarc DPRINTF(("ran out of space before TCPE_MI\n"));
14269ada0bf4Smarc goto abort_cfe;
14279ada0bf4Smarc }
14289ada0bf4Smarc
1429c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1430c66b8643Sthorpej idx++;
1431c66b8643Sthorpej
1432b5064330Schopps cfe->flags &= ~(PCMCIA_CFE_POWERDOWN
1433b5064330Schopps | PCMCIA_CFE_READONLY
1434b5064330Schopps | PCMCIA_CFE_AUDIO);
1435c66b8643Sthorpej if (reg & PCMCIA_TPCE_MI_PWRDOWN)
1436b7868a43Senami cfe->flags |= PCMCIA_CFE_POWERDOWN;
1437c66b8643Sthorpej if (reg & PCMCIA_TPCE_MI_READONLY)
1438b7868a43Senami cfe->flags |= PCMCIA_CFE_READONLY;
1439c66b8643Sthorpej if (reg & PCMCIA_TPCE_MI_AUDIO)
1440b7868a43Senami cfe->flags |= PCMCIA_CFE_AUDIO;
1441c66b8643Sthorpej cfe->maxtwins = reg & PCMCIA_TPCE_MI_MAXTWINS;
1442c66b8643Sthorpej
1443c66b8643Sthorpej while (reg & PCMCIA_TPCE_MI_EXT) {
1444c66b8643Sthorpej reg = pcmcia_tuple_read_1(tuple, idx);
1445c66b8643Sthorpej idx++;
1446c66b8643Sthorpej }
1447c66b8643Sthorpej }
14489ada0bf4Smarc
1449c2909c51Schristos /* skip all the subtuples */
14509ada0bf4Smarc abort_cfe:
1451c66b8643Sthorpej DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
14528130f0ecShaya }
1453