1104640Simp/* $NetBSD: pcmcia_cis.c,v 1.17 2000/02/10 09:01:52 chopps Exp $ */ 252506Simp/* $FreeBSD$ */ 352506Simp 4139749Simp/*- 552506Simp * Copyright (c) 1997 Marc Horowitz. All rights reserved. 652506Simp * 752506Simp * Redistribution and use in source and binary forms, with or without 852506Simp * modification, are permitted provided that the following conditions 952506Simp * are met: 1052506Simp * 1. Redistributions of source code must retain the above copyright 1152506Simp * notice, this list of conditions and the following disclaimer. 1252506Simp * 2. Redistributions in binary form must reproduce the above copyright 1352506Simp * notice, this list of conditions and the following disclaimer in the 1452506Simp * documentation and/or other materials provided with the distribution. 1552506Simp * 3. All advertising materials mentioning features or use of this software 1652506Simp * must display the following acknowledgement: 1752506Simp * This product includes software developed by Marc Horowitz. 1852506Simp * 4. The name of the author may not be used to endorse or promote products 1952506Simp * derived from this software without specific prior written permission. 2052506Simp * 2152506Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2252506Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2352506Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2452506Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2552506Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2652506Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2752506Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2852506Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2952506Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3052506Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3152506Simp */ 3252506Simp 3352506Simp#include <sys/param.h> 3452506Simp#include <sys/systm.h> 3552506Simp#include <sys/malloc.h> 3652506Simp#include <sys/module.h> 3752506Simp#include <sys/kernel.h> 3852506Simp#include <sys/queue.h> 3952506Simp#include <sys/types.h> 4052506Simp 4152506Simp#include <sys/bus.h> 4252506Simp#include <machine/bus.h> 4352506Simp#include <sys/rman.h> 4452506Simp#include <machine/resource.h> 4552506Simp 4652506Simp#include <dev/pccard/pccardreg.h> 4752506Simp#include <dev/pccard/pccardvar.h> 48150361Simp#include <dev/pccard/pccardvarp.h> 49120868Simp#include <dev/pccard/pccard_cis.h> 5052506Simp 5159193Simp#include "card_if.h" 5259193Simp 5391786Simpextern int pccard_cis_debug; 5491786Simp 5559193Simp#define PCCARDCISDEBUG 5652506Simp#ifdef PCCARDCISDEBUG 57119161Simp#define DPRINTF(arg) do { if (pccard_cis_debug) printf arg; } while (0) 58119161Simp#define DEVPRINTF(arg) do { if (pccard_cis_debug) device_printf arg; } while (0) 5952506Simp#else 6052506Simp#define DPRINTF(arg) 6155720Simp#define DEVPRINTF(arg) 6252506Simp#endif 6352506Simp 64128169Simp#define PCCARD_CIS_SIZE 4096 6552506Simp 6652506Simpstruct cis_state { 6752506Simp int count; 6852506Simp int gotmfc; 6952506Simp struct pccard_config_entry temp_cfe; 7052506Simp struct pccard_config_entry *default_cfe; 7152506Simp struct pccard_card *card; 7252506Simp struct pccard_function *pf; 7352506Simp}; 7452506Simp 75147729Simpstatic int pccard_parse_cis_tuple(const struct pccard_tuple *, void *); 76147729Simpstatic int decode_funce(const struct pccard_tuple *, struct pccard_function *); 7752506Simp 7852506Simpvoid 7955720Simppccard_read_cis(struct pccard_softc *sc) 8052506Simp{ 8152506Simp struct cis_state state; 8252506Simp 83104640Simp bzero(&state, sizeof state); 8452506Simp state.card = &sc->card; 8552506Simp state.card->error = 0; 8652506Simp state.card->cis1_major = -1; 8752506Simp state.card->cis1_minor = -1; 8852506Simp state.card->cis1_info[0] = NULL; 8952506Simp state.card->cis1_info[1] = NULL; 9052506Simp state.card->cis1_info[2] = NULL; 9152506Simp state.card->cis1_info[3] = NULL; 9286272Simp state.card->manufacturer = PCMCIA_VENDOR_INVALID; 9386272Simp state.card->product = PCMCIA_PRODUCT_INVALID; 9452506Simp STAILQ_INIT(&state.card->pf_head); 9552506Simp state.pf = NULL; 9652506Simp 97161108Simp /* 98161108Simp * XXX The following shouldn't be needed, but some slow cards 99161108Simp * XXX seem to need it still. Need to investigate if there's 100161108Simp * XXX a way to tell if the card is 'ready' or not rather than 101161108Simp * XXX sleeping like this. We're called just after the power 102161108Simp * XXX up of the socket. The standard timing diagrams don't 103161108Simp * XXX seem to indicate that a delay is required. The old 104161108Simp * XXX delay was 1s. This delay is .1s. 105161108Simp */ 106167086Sjhb pause("pccard", hz / 10); 107150098Simp if (pccard_scan_cis(device_get_parent(sc->dev), sc->dev, 108150098Simp pccard_parse_cis_tuple, &state) == -1) 10952506Simp state.card->error++; 11052506Simp} 11152506Simp 11252506Simpint 113150098Simppccard_scan_cis(device_t bus, device_t dev, pccard_scan_t fct, void *arg) 11452506Simp{ 11555720Simp struct resource *res; 11655720Simp int rid; 11752506Simp struct pccard_tuple tuple; 11852506Simp int longlink_present; 11952506Simp int longlink_common; 120112358Simp u_long longlink_addr; /* Type suspect */ 12152506Simp int mfc_count; 12252506Simp int mfc_index; 123119161Simp#ifdef PCCARDCISDEBUG 124119161Simp int cis_none_cnt = 10; /* Only report 10 CIS_NONEs */ 125119161Simp#endif 12652506Simp struct { 12752506Simp int common; 12852506Simp u_long addr; 12952506Simp } mfc[256 / 5]; 13052506Simp int ret; 13152506Simp 13252506Simp ret = 0; 13352506Simp 13452506Simp /* allocate some memory */ 13552506Simp 136128169Simp /* 137128169Simp * Some reports from the field suggest that a 64k memory boundary 138128169Simp * helps card CIS being able to be read. Try it here and see what 139128169Simp * the results actually are. I'm not sure I understand why this 140128169Simp * would make cards work better, but it is easy enough to test. 141128169Simp */ 14255720Simp rid = 0; 143128169Simp res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 144128169Simp PCCARD_CIS_SIZE, RF_ACTIVE | rman_make_alignment_flags(64*1024)); 14555720Simp if (res == NULL) { 14655720Simp device_printf(dev, "can't alloc memory to read attributes\n"); 14752506Simp return -1; 14852506Simp } 149150098Simp CARD_SET_RES_FLAGS(bus, dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); 15055720Simp tuple.memt = rman_get_bustag(res); 15155720Simp tuple.memh = rman_get_bushandle(res); 15259389Simp tuple.ptr = 0; 15352506Simp 154188212Swkoszek DPRINTF(("cis mem map %#x (resource: %#lx)\n", 155119060Simp (unsigned int) tuple.memh, rman_get_start(res))); 15655720Simp 15752506Simp tuple.mult = 2; 15852506Simp 15952506Simp longlink_present = 1; 16052506Simp longlink_common = 1; 16152506Simp longlink_addr = 0; 16252506Simp 16352506Simp mfc_count = 0; 16452506Simp mfc_index = 0; 16552506Simp 16655720Simp DEVPRINTF((dev, "CIS tuple chain:\n")); 16752506Simp 16852506Simp while (1) { 16952506Simp while (1) { 170119060Simp /* 171119060Simp * Perform boundary check for insane cards. 172119060Simp * If CIS is too long, simulate CIS end. 173119060Simp * (This check may not be sufficient for 174119060Simp * malicious cards.) 175119060Simp */ 176119060Simp if (tuple.mult * tuple.ptr >= PCCARD_CIS_SIZE - 1 177119060Simp - 32 /* ad hoc value */ ) { 178119060Simp printf("CIS is too long -- truncating\n"); 179120868Simp tuple.code = CISTPL_END; 180119060Simp } else { 181119060Simp /* get the tuple code */ 182119060Simp tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 183119060Simp } 18452506Simp 18552506Simp /* two special-case tuples */ 18652506Simp 187120868Simp if (tuple.code == CISTPL_NULL) { 188119161Simp#ifdef PCCARDCISDEBUG 189119161Simp if (cis_none_cnt > 0) 190119161Simp DPRINTF(("CISTPL_NONE\n 00\n")); 191119161Simp else if (cis_none_cnt == 0) 192119161Simp DPRINTF(("TOO MANY CIS_NONE\n")); 193119161Simp cis_none_cnt--; 194119161Simp#endif 195150361Simp if ((*fct)(&tuple, arg)) { 196150361Simp ret = 1; 197150361Simp goto done; 198150361Simp } 19952506Simp tuple.ptr++; 20052506Simp continue; 201120868Simp } else if (tuple.code == CISTPL_END) { 20252506Simp DPRINTF(("CISTPL_END\n ff\n")); 20352506Simp /* Call the function for the END tuple, since 20452506Simp the CIS semantics depend on it */ 205147711Simp if ((*fct)(&tuple, arg)) { 20652506Simp ret = 1; 20752506Simp goto done; 20852506Simp } 20952506Simp tuple.ptr++; 21052506Simp break; 21152506Simp } 21252506Simp /* now all the normal tuples */ 21352506Simp 21452506Simp tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 21552506Simp switch (tuple.code) { 216120868Simp case CISTPL_LONGLINK_A: 217120868Simp case CISTPL_LONGLINK_C: 218150361Simp if ((*fct)(&tuple, arg)) { 219150361Simp ret = 1; 220150361Simp goto done; 221150361Simp } 22252506Simp if (tuple.length < 4) { 22352506Simp DPRINTF(("CISTPL_LONGLINK_%s too " 22452506Simp "short %d\n", 22552506Simp longlink_common ? "C" : "A", 22652506Simp tuple.length)); 22752506Simp break; 22852506Simp } 22952506Simp longlink_present = 1; 23052506Simp longlink_common = (tuple.code == 231120868Simp CISTPL_LONGLINK_C) ? 1 : 0; 23252506Simp longlink_addr = pccard_tuple_read_4(&tuple, 0); 233188212Swkoszek DPRINTF(("CISTPL_LONGLINK_%s %#lx\n", 23452506Simp longlink_common ? "C" : "A", 23552506Simp longlink_addr)); 23652506Simp break; 237120868Simp case CISTPL_NO_LINK: 238150361Simp if ((*fct)(&tuple, arg)) { 239150361Simp ret = 1; 240150361Simp goto done; 241150361Simp } 24252506Simp longlink_present = 0; 24352506Simp DPRINTF(("CISTPL_NO_LINK\n")); 24452506Simp break; 245120868Simp case CISTPL_CHECKSUM: 246150361Simp if ((*fct)(&tuple, arg)) { 247150361Simp ret = 1; 248150361Simp goto done; 249150361Simp } 25052506Simp if (tuple.length < 5) { 25152506Simp DPRINTF(("CISTPL_CHECKSUM too " 25252506Simp "short %d\n", tuple.length)); 25352506Simp break; 25452506Simp } { 25552506Simp int16_t offset; 25652506Simp u_long addr, length; 25752506Simp u_int cksum, sum; 25852506Simp int i; 25952506Simp 26090896Simp offset = (uint16_t) 26152506Simp pccard_tuple_read_2(&tuple, 0); 26252506Simp length = pccard_tuple_read_2(&tuple, 2); 26352506Simp cksum = pccard_tuple_read_1(&tuple, 4); 26452506Simp 26552506Simp addr = tuple.ptr + offset; 26652506Simp 267188212Swkoszek DPRINTF(("CISTPL_CHECKSUM addr=%#lx " 268188212Swkoszek "len=%#lx cksum=%#x", 26952506Simp addr, length, cksum)); 27052506Simp 27152506Simp /* 27252506Simp * XXX do more work to deal with 27352506Simp * distant regions 27452506Simp */ 27552506Simp if ((addr >= PCCARD_CIS_SIZE) || 27652506Simp ((addr + length) >= 277104640Simp PCCARD_CIS_SIZE)) { 27852506Simp DPRINTF((" skipped, " 27952506Simp "too distant\n")); 28052506Simp break; 28152506Simp } 28252506Simp sum = 0; 28352506Simp for (i = 0; i < length; i++) 28452506Simp sum += 28552506Simp bus_space_read_1(tuple.memt, 28652506Simp tuple.memh, 28752506Simp addr + tuple.mult * i); 28852506Simp if (cksum != (sum & 0xff)) { 289188212Swkoszek DPRINTF((" failed sum=%#x\n", 29052506Simp sum)); 29155720Simp device_printf(dev, 29255720Simp "CIS checksum failed\n"); 29352506Simp#if 0 29452506Simp /* 29552506Simp * XXX Some working cards have 29652506Simp * XXX bad checksums!! 29752506Simp */ 29852506Simp ret = -1; 29952506Simp#endif 30052506Simp } else { 30152506Simp DPRINTF((" ok\n")); 30252506Simp } 30352506Simp } 30452506Simp break; 305120868Simp case CISTPL_LONGLINK_MFC: 30652506Simp if (tuple.length < 1) { 30752506Simp DPRINTF(("CISTPL_LONGLINK_MFC too " 30852506Simp "short %d\n", tuple.length)); 30952506Simp break; 31052506Simp } 311104640Simp if (((tuple.length - 1) % 5) != 0) { 312104640Simp DPRINTF(("CISTPL_LONGLINK_MFC bogus " 313104640Simp "length %d\n", tuple.length)); 314104640Simp break; 315104640Simp } 31652506Simp /* 31752506Simp * this is kind of ad hoc, as I don't have 31852506Simp * any real documentation 31952506Simp */ 32052506Simp { 321104640Simp int i, tmp_count; 32252506Simp 323104640Simp /* 324104640Simp * put count into tmp var so that 325104640Simp * if we have to bail (because it's 326104640Simp * a bogus count) it won't be 327104640Simp * remembered for later use. 328104640Simp */ 329104640Simp tmp_count = 33052506Simp pccard_tuple_read_1(&tuple, 0); 331104640Simp 33252506Simp DPRINTF(("CISTPL_LONGLINK_MFC %d", 333104640Simp tmp_count)); 334104640Simp 335104640Simp /* 336104640Simp * make _sure_ it's the right size; 337104640Simp * if too short, it may be a weird 338104640Simp * (unknown/undefined) format 339104640Simp */ 340104640Simp if (tuple.length != (tmp_count*5 + 1)) { 341104640Simp DPRINTF((" bogus length %d\n", 342104640Simp tuple.length)); 343104640Simp break; 344104640Simp } 345104640Simp /* 346104640Simp * sanity check for a programming 347104640Simp * error which is difficult to find 348104640Simp * when debugging. 349104640Simp */ 350104640Simp if (tmp_count > 351104640Simp howmany(sizeof mfc, sizeof mfc[0])) 352104640Simp panic("CISTPL_LONGLINK_MFC mfc " 353104640Simp "count would blow stack"); 354104640Simp mfc_count = tmp_count; 35552506Simp for (i = 0; i < mfc_count; i++) { 35652506Simp mfc[i].common = 35752506Simp (pccard_tuple_read_1(&tuple, 35852506Simp 1 + 5 * i) == 35952506Simp PCCARD_MFC_MEM_COMMON) ? 36052506Simp 1 : 0; 36152506Simp mfc[i].addr = 36252506Simp pccard_tuple_read_4(&tuple, 36352506Simp 1 + 5 * i + 1); 364188212Swkoszek DPRINTF((" %s:%#lx", 36552506Simp mfc[i].common ? "common" : 36652506Simp "attr", mfc[i].addr)); 36752506Simp } 36852506Simp DPRINTF(("\n")); 36952506Simp } 37052506Simp /* 37152506Simp * for LONGLINK_MFC, fall through to the 37252506Simp * function. This tuple has structural and 37352506Simp * semantic content. 37452506Simp */ 37552506Simp default: 37652506Simp { 377147711Simp if ((*fct)(&tuple, arg)) { 37852506Simp ret = 1; 37952506Simp goto done; 38052506Simp } 38152506Simp } 38252506Simp break; 38352506Simp } /* switch */ 38452506Simp#ifdef PCCARDCISDEBUG 38552506Simp /* print the tuple */ 38652506Simp { 38752506Simp int i; 38852506Simp 389188212Swkoszek DPRINTF((" %#02x %#02x", tuple.code, 39052506Simp tuple.length)); 39152506Simp 39252506Simp for (i = 0; i < tuple.length; i++) { 393188212Swkoszek DPRINTF((" %#02x", 39452506Simp pccard_tuple_read_1(&tuple, i))); 39552506Simp if ((i % 16) == 13) 39652506Simp DPRINTF(("\n")); 39752506Simp } 39887352Simp 39952506Simp if ((i % 16) != 14) 40052506Simp DPRINTF(("\n")); 40152506Simp } 40252506Simp#endif 40352506Simp /* skip to the next tuple */ 40452506Simp tuple.ptr += 2 + tuple.length; 40552506Simp } 40652506Simp 40752506Simp /* 40852506Simp * the chain is done. Clean up and move onto the next one, 40952506Simp * if any. The loop is here in the case that there is an MFC 41052506Simp * card with no longlink (which defaults to existing, == 0). 41152506Simp * In general, this means that if one pointer fails, it will 41252506Simp * try the next one, instead of just bailing. 41352506Simp */ 41452506Simp while (1) { 41552506Simp if (longlink_present) { 416150098Simp CARD_SET_RES_FLAGS(bus, dev, SYS_RES_MEMORY, 417150098Simp rid, longlink_common ? 41893370Simp PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR); 419188212Swkoszek DPRINTF(("cis mem map %#x\n", 42052506Simp (unsigned int) tuple.memh)); 42152506Simp tuple.mult = longlink_common ? 1 : 2; 42293370Simp tuple.ptr = longlink_addr; 42352506Simp longlink_present = 0; 42452506Simp longlink_common = 1; 42552506Simp longlink_addr = 0; 42652506Simp } else if (mfc_count && (mfc_index < mfc_count)) { 427150098Simp CARD_SET_RES_FLAGS(bus, dev, SYS_RES_MEMORY, 428150098Simp rid, mfc[mfc_index].common ? 429150098Simp PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR); 430188212Swkoszek DPRINTF(("cis mem map %#x\n", 43152506Simp (unsigned int) tuple.memh)); 43252506Simp /* set parse state, and point at the next one */ 43352506Simp tuple.mult = mfc[mfc_index].common ? 1 : 2; 43493370Simp tuple.ptr = mfc[mfc_index].addr; 43552506Simp mfc_index++; 43652506Simp } else { 43752506Simp goto done; 43852506Simp } 43952506Simp 44052506Simp /* make sure that the link is valid */ 44152506Simp tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 442120868Simp if (tuple.code != CISTPL_LINKTARGET) { 44352506Simp DPRINTF(("CISTPL_LINKTARGET expected, " 444188212Swkoszek "code %#02x observed\n", tuple.code)); 44552506Simp continue; 44652506Simp } 44752506Simp tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 44852506Simp if (tuple.length < 3) { 44952506Simp DPRINTF(("CISTPL_LINKTARGET too short %d\n", 45052506Simp tuple.length)); 45152506Simp continue; 45252506Simp } 45352506Simp if ((pccard_tuple_read_1(&tuple, 0) != 'C') || 45452506Simp (pccard_tuple_read_1(&tuple, 1) != 'I') || 45552506Simp (pccard_tuple_read_1(&tuple, 2) != 'S')) { 45652506Simp DPRINTF(("CISTPL_LINKTARGET magic " 45752506Simp "%02x%02x%02x incorrect\n", 45852506Simp pccard_tuple_read_1(&tuple, 0), 45952506Simp pccard_tuple_read_1(&tuple, 1), 46052506Simp pccard_tuple_read_1(&tuple, 2))); 46152506Simp continue; 46252506Simp } 46352506Simp tuple.ptr += 2 + tuple.length; 46452506Simp break; 46552506Simp } 46652506Simp } 46752506Simp 46852506Simpdone: 46955720Simp bus_release_resource(dev, SYS_RES_MEMORY, rid, res); 47052506Simp 47152506Simp return (ret); 47252506Simp} 47352506Simp 47452506Simp/* XXX this is incredibly verbose. Not sure what trt is */ 47552506Simp 47652506Simpvoid 47752506Simppccard_print_cis(device_t dev) 47852506Simp{ 47964850Simp struct pccard_softc *sc = PCCARD_SOFTC(dev); 48052506Simp struct pccard_card *card = &sc->card; 48152506Simp struct pccard_function *pf; 48252506Simp struct pccard_config_entry *cfe; 48352506Simp int i; 48452506Simp 48552506Simp device_printf(dev, "CIS version "); 48652506Simp if (card->cis1_major == 4) { 48752506Simp if (card->cis1_minor == 0) 48852506Simp printf("PCCARD 1.0\n"); 48952506Simp else if (card->cis1_minor == 1) 49052506Simp printf("PCCARD 2.0 or 2.1\n"); 49152506Simp } else if (card->cis1_major >= 5) 49252506Simp printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor); 49352506Simp else 49452506Simp printf("unknown (major=%d, minor=%d)\n", 49552506Simp card->cis1_major, card->cis1_minor); 49652506Simp 49752506Simp device_printf(dev, "CIS info: "); 49852506Simp for (i = 0; i < 4; i++) { 49952506Simp if (card->cis1_info[i] == NULL) 50052506Simp break; 50152506Simp if (i) 50252506Simp printf(", "); 50352506Simp printf("%s", card->cis1_info[i]); 50452506Simp } 50552506Simp printf("\n"); 50652506Simp 507188212Swkoszek device_printf(dev, "Manufacturer code %#x, product %#x\n", 50852506Simp card->manufacturer, card->product); 50952506Simp 51052506Simp STAILQ_FOREACH(pf, &card->pf_head, pf_list) { 51152506Simp device_printf(dev, "function %d: ", pf->number); 51252506Simp 51352506Simp switch (pf->function) { 51452506Simp case PCCARD_FUNCTION_UNSPEC: 51552506Simp printf("unspecified"); 51652506Simp break; 51752506Simp case PCCARD_FUNCTION_MULTIFUNCTION: 51852506Simp printf("multi-function"); 51952506Simp break; 52052506Simp case PCCARD_FUNCTION_MEMORY: 52152506Simp printf("memory"); 52252506Simp break; 52352506Simp case PCCARD_FUNCTION_SERIAL: 52452506Simp printf("serial port"); 52552506Simp break; 52652506Simp case PCCARD_FUNCTION_PARALLEL: 52752506Simp printf("parallel port"); 52852506Simp break; 52952506Simp case PCCARD_FUNCTION_DISK: 53052506Simp printf("fixed disk"); 53152506Simp break; 53252506Simp case PCCARD_FUNCTION_VIDEO: 53352506Simp printf("video adapter"); 53452506Simp break; 53552506Simp case PCCARD_FUNCTION_NETWORK: 53652506Simp printf("network adapter"); 53752506Simp break; 53852506Simp case PCCARD_FUNCTION_AIMS: 53952506Simp printf("auto incrementing mass storage"); 54052506Simp break; 54152506Simp case PCCARD_FUNCTION_SCSI: 54252506Simp printf("SCSI bridge"); 54352506Simp break; 54452506Simp case PCCARD_FUNCTION_SECURITY: 54552506Simp printf("Security services"); 54652506Simp break; 54752506Simp case PCCARD_FUNCTION_INSTRUMENT: 54852506Simp printf("Instrument"); 54952506Simp break; 55052506Simp default: 55152506Simp printf("unknown (%d)", pf->function); 55252506Simp break; 55352506Simp } 55452506Simp 555188212Swkoszek printf(", ccr addr %#x mask %#x\n", pf->ccr_base, pf->ccr_mask); 55652506Simp 55752506Simp STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) { 55852506Simp device_printf(dev, "function %d, config table entry " 55952506Simp "%d: ", pf->number, cfe->number); 56052506Simp 56152506Simp switch (cfe->iftype) { 56252506Simp case PCCARD_IFTYPE_MEMORY: 56352506Simp printf("memory card"); 56452506Simp break; 56552506Simp case PCCARD_IFTYPE_IO: 56652506Simp printf("I/O card"); 56752506Simp break; 56852506Simp default: 56952506Simp printf("card type unknown"); 57052506Simp break; 57152506Simp } 57252506Simp 573188212Swkoszek printf("; irq mask %#x", cfe->irqmask); 57452506Simp 57552506Simp if (cfe->num_iospace) { 576188212Swkoszek printf("; iomask %#lx, iospace", cfe->iomask); 57752506Simp 57853813Simp for (i = 0; i < cfe->num_iospace; i++) { 579188212Swkoszek printf(" %#lx", cfe->iospace[i].start); 58053813Simp if (cfe->iospace[i].length) 581188212Swkoszek printf("-%#lx", 58253813Simp cfe->iospace[i].start + 58353813Simp cfe->iospace[i].length - 1); 58453813Simp } 58552506Simp } 58652506Simp if (cfe->num_memspace) { 58752506Simp printf("; memspace"); 58852506Simp 58953813Simp for (i = 0; i < cfe->num_memspace; i++) { 590188212Swkoszek printf(" %#lx", 59153813Simp cfe->memspace[i].cardaddr); 59253813Simp if (cfe->memspace[i].length) 593188212Swkoszek printf("-%#lx", 59453813Simp cfe->memspace[i].cardaddr + 59553813Simp cfe->memspace[i].length - 1); 59653813Simp if (cfe->memspace[i].hostaddr) 597188212Swkoszek printf("@%#lx", 59853813Simp cfe->memspace[i].hostaddr); 59953813Simp } 60052506Simp } 60152506Simp if (cfe->maxtwins) 60252506Simp printf("; maxtwins %d", cfe->maxtwins); 60352506Simp 60452506Simp printf(";"); 60552506Simp 60652506Simp if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED) 60752506Simp printf(" mwait_required"); 60852506Simp if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE) 60952506Simp printf(" rdybsy_active"); 61052506Simp if (cfe->flags & PCCARD_CFE_WP_ACTIVE) 61152506Simp printf(" wp_active"); 61252506Simp if (cfe->flags & PCCARD_CFE_BVD_ACTIVE) 61352506Simp printf(" bvd_active"); 61452506Simp if (cfe->flags & PCCARD_CFE_IO8) 61552506Simp printf(" io8"); 61652506Simp if (cfe->flags & PCCARD_CFE_IO16) 61752506Simp printf(" io16"); 61852506Simp if (cfe->flags & PCCARD_CFE_IRQSHARE) 61952506Simp printf(" irqshare"); 62052506Simp if (cfe->flags & PCCARD_CFE_IRQPULSE) 62152506Simp printf(" irqpulse"); 62252506Simp if (cfe->flags & PCCARD_CFE_IRQLEVEL) 62352506Simp printf(" irqlevel"); 62452506Simp if (cfe->flags & PCCARD_CFE_POWERDOWN) 62552506Simp printf(" powerdown"); 62652506Simp if (cfe->flags & PCCARD_CFE_READONLY) 62752506Simp printf(" readonly"); 62852506Simp if (cfe->flags & PCCARD_CFE_AUDIO) 62952506Simp printf(" audio"); 63052506Simp 63152506Simp printf("\n"); 63252506Simp } 63352506Simp } 63452506Simp 63552506Simp if (card->error) 63652506Simp device_printf(dev, "%d errors found while parsing CIS\n", 63752506Simp card->error); 63852506Simp} 63952506Simp 640147711Simpstatic int 641147729Simppccard_parse_cis_tuple(const struct pccard_tuple *tuple, void *arg) 64252506Simp{ 64352506Simp /* most of these are educated guesses */ 64452506Simp static struct pccard_config_entry init_cfe = { 64552506Simp -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE | 64652506Simp PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY, 64752506Simp }; 64852506Simp 64952506Simp struct cis_state *state = arg; 65052506Simp 65152506Simp switch (tuple->code) { 652120868Simp case CISTPL_END: 65352506Simp /* if we've seen a LONGLINK_MFC, and this is the first 65452506Simp * END after it, reset the function list. 65552506Simp * 65652506Simp * XXX This might also be the right place to start a 65752506Simp * new function, but that assumes that a function 65852506Simp * definition never crosses any longlink, and I'm not 65952506Simp * sure about that. This is probably safe for MFC 66052506Simp * cards, but what we have now isn't broken, so I'd 66152506Simp * rather not change it. 66252506Simp */ 66352506Simp if (state->gotmfc == 1) { 66452506Simp struct pccard_function *pf, *pfnext; 66552506Simp 66652506Simp for (pf = STAILQ_FIRST(&state->card->pf_head); 66752506Simp pf != NULL; pf = pfnext) { 66852506Simp pfnext = STAILQ_NEXT(pf, pf_list); 66952506Simp free(pf, M_DEVBUF); 67052506Simp } 67152506Simp 67252506Simp STAILQ_INIT(&state->card->pf_head); 67352506Simp 67452506Simp state->count = 0; 67552506Simp state->gotmfc = 2; 67652506Simp state->pf = NULL; 67752506Simp } 67852506Simp break; 679120868Simp case CISTPL_LONGLINK_MFC: 68052506Simp /* 68152506Simp * this tuple's structure was dealt with in scan_cis. here, 68252506Simp * record the fact that the MFC tuple was seen, so that 68352506Simp * functions declared before the MFC link can be cleaned 68452506Simp * up. 68552506Simp */ 68652506Simp state->gotmfc = 1; 68752506Simp break; 68852506Simp#ifdef PCCARDCISDEBUG 689120868Simp case CISTPL_DEVICE: 690120868Simp case CISTPL_DEVICE_A: 69152506Simp { 69252506Simp u_int reg, dtype, dspeed; 69352506Simp 69452506Simp reg = pccard_tuple_read_1(tuple, 0); 69552506Simp dtype = reg & PCCARD_DTYPE_MASK; 69652506Simp dspeed = reg & PCCARD_DSPEED_MASK; 69752506Simp 69852506Simp DPRINTF(("CISTPL_DEVICE%s type=", 699120868Simp (tuple->code == CISTPL_DEVICE) ? "" : "_A")); 70052506Simp switch (dtype) { 70152506Simp case PCCARD_DTYPE_NULL: 70252506Simp DPRINTF(("null")); 70352506Simp break; 70452506Simp case PCCARD_DTYPE_ROM: 70552506Simp DPRINTF(("rom")); 70652506Simp break; 70752506Simp case PCCARD_DTYPE_OTPROM: 70852506Simp DPRINTF(("otprom")); 70952506Simp break; 71052506Simp case PCCARD_DTYPE_EPROM: 71152506Simp DPRINTF(("eprom")); 71252506Simp break; 71352506Simp case PCCARD_DTYPE_EEPROM: 71452506Simp DPRINTF(("eeprom")); 71552506Simp break; 71652506Simp case PCCARD_DTYPE_FLASH: 71752506Simp DPRINTF(("flash")); 71852506Simp break; 71952506Simp case PCCARD_DTYPE_SRAM: 72052506Simp DPRINTF(("sram")); 72152506Simp break; 72252506Simp case PCCARD_DTYPE_DRAM: 72352506Simp DPRINTF(("dram")); 72452506Simp break; 72552506Simp case PCCARD_DTYPE_FUNCSPEC: 72652506Simp DPRINTF(("funcspec")); 72752506Simp break; 72852506Simp case PCCARD_DTYPE_EXTEND: 72952506Simp DPRINTF(("extend")); 73052506Simp break; 73152506Simp default: 73252506Simp DPRINTF(("reserved")); 73352506Simp break; 73452506Simp } 73552506Simp DPRINTF((" speed=")); 73652506Simp switch (dspeed) { 73752506Simp case PCCARD_DSPEED_NULL: 73852506Simp DPRINTF(("null")); 73952506Simp break; 74052506Simp case PCCARD_DSPEED_250NS: 74152506Simp DPRINTF(("250ns")); 74252506Simp break; 74352506Simp case PCCARD_DSPEED_200NS: 74452506Simp DPRINTF(("200ns")); 74552506Simp break; 74652506Simp case PCCARD_DSPEED_150NS: 74752506Simp DPRINTF(("150ns")); 74852506Simp break; 74952506Simp case PCCARD_DSPEED_100NS: 75052506Simp DPRINTF(("100ns")); 75152506Simp break; 75252506Simp case PCCARD_DSPEED_EXT: 75352506Simp DPRINTF(("ext")); 75452506Simp break; 75552506Simp default: 75652506Simp DPRINTF(("reserved")); 75752506Simp break; 75852506Simp } 75952506Simp } 76052506Simp DPRINTF(("\n")); 76152506Simp break; 76252506Simp#endif 763120868Simp case CISTPL_VERS_1: 76452506Simp if (tuple->length < 6) { 76552506Simp DPRINTF(("CISTPL_VERS_1 too short %d\n", 76652506Simp tuple->length)); 76752506Simp break; 76852506Simp } { 76952506Simp int start, i, ch, count; 77052506Simp 77152506Simp state->card->cis1_major = pccard_tuple_read_1(tuple, 0); 77252506Simp state->card->cis1_minor = pccard_tuple_read_1(tuple, 1); 77352506Simp 77452506Simp for (count = 0, start = 0, i = 0; 77552506Simp (count < 4) && ((i + 4) < 256); i++) { 77652506Simp ch = pccard_tuple_read_1(tuple, 2 + i); 77752506Simp if (ch == 0xff) 77852506Simp break; 77952506Simp state->card->cis1_info_buf[i] = ch; 78052506Simp if (ch == 0) { 78152506Simp state->card->cis1_info[count] = 78252506Simp state->card->cis1_info_buf + start; 78352506Simp start = i + 1; 78452506Simp count++; 78552506Simp } 78652506Simp } 78752506Simp DPRINTF(("CISTPL_VERS_1\n")); 78852506Simp } 78952506Simp break; 790120868Simp case CISTPL_MANFID: 79152506Simp if (tuple->length < 4) { 79252506Simp DPRINTF(("CISTPL_MANFID too short %d\n", 79352506Simp tuple->length)); 79452506Simp break; 79552506Simp } 79652506Simp state->card->manufacturer = pccard_tuple_read_2(tuple, 0); 79752506Simp state->card->product = pccard_tuple_read_2(tuple, 2); 79890964Sshiba /* 799104604Simp * This is for xe driver. But not limited to that driver. 80090964Sshiba * In PC Card Standard, 80190964Sshiba * Manufacturer ID: 2byte. 802104604Simp * Product ID: typically 2bytes, but there's no limit on its 803104604Simp * size. prodext is a two byte field, so maybe we should 804104604Simp * also handle the '6' case. So far no cards have surfaced 805104604Simp * with a length of '6'. 80690964Sshiba */ 807147962Simp if (tuple->length == 5 ) 80890964Sshiba state->card->prodext = pccard_tuple_read_1(tuple, 4); 80952506Simp DPRINTF(("CISTPL_MANFID\n")); 81052506Simp break; 811120868Simp case CISTPL_FUNCID: 81252506Simp if (tuple->length < 1) { 81352506Simp DPRINTF(("CISTPL_FUNCID too short %d\n", 81452506Simp tuple->length)); 81552506Simp break; 81652506Simp } 81752506Simp if ((state->pf == NULL) || (state->gotmfc == 2)) { 81852506Simp state->pf = malloc(sizeof(*state->pf), M_DEVBUF, 81967897Sdwmalone M_NOWAIT | M_ZERO); 82052506Simp state->pf->number = state->count++; 82152506Simp state->pf->last_config_index = -1; 82252506Simp STAILQ_INIT(&state->pf->cfe_head); 82352506Simp 82452506Simp STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf, 82552506Simp pf_list); 82652506Simp } 82752506Simp state->pf->function = pccard_tuple_read_1(tuple, 0); 82852506Simp 82952506Simp DPRINTF(("CISTPL_FUNCID\n")); 83052506Simp break; 831120868Simp case CISTPL_FUNCE: 83282781Sshiba if (state->pf == NULL || state->pf->function <= 0) { 83382781Sshiba DPRINTF(("CISTPL_FUNCE is not followed by " 83482781Sshiba "valid CISTPL_FUNCID\n")); 83582781Sshiba break; 83682781Sshiba } 837147729Simp if (tuple->length >= 2) 83882781Sshiba decode_funce(tuple, state->pf); 83982781Sshiba DPRINTF(("CISTPL_FUNCE\n")); 84082781Sshiba break; 841120868Simp case CISTPL_CONFIG: 84252506Simp if (tuple->length < 3) { 84352506Simp DPRINTF(("CISTPL_CONFIG too short %d\n", 84452506Simp tuple->length)); 84552506Simp break; 84652506Simp } { 84752506Simp u_int reg, rasz, rmsz, rfsz; 84852506Simp int i; 84952506Simp 85052506Simp reg = pccard_tuple_read_1(tuple, 0); 85152506Simp rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >> 85252506Simp PCCARD_TPCC_RASZ_SHIFT); 85352506Simp rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >> 85452506Simp PCCARD_TPCC_RMSZ_SHIFT); 85552506Simp rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >> 85652506Simp PCCARD_TPCC_RFSZ_SHIFT); 85752506Simp 85852506Simp if (tuple->length < (rasz + rmsz + rfsz)) { 85952506Simp DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too " 86052506Simp "short %d\n", rasz, rmsz, rfsz, 86152506Simp tuple->length)); 86252506Simp break; 86352506Simp } 86452506Simp if (state->pf == NULL) { 86552506Simp state->pf = malloc(sizeof(*state->pf), 86667897Sdwmalone M_DEVBUF, M_NOWAIT | M_ZERO); 86752506Simp state->pf->number = state->count++; 86852506Simp state->pf->last_config_index = -1; 86952506Simp STAILQ_INIT(&state->pf->cfe_head); 87052506Simp 87152506Simp STAILQ_INSERT_TAIL(&state->card->pf_head, 87252506Simp state->pf, pf_list); 87352506Simp 87452506Simp state->pf->function = PCCARD_FUNCTION_UNSPEC; 87552506Simp } 87652506Simp state->pf->last_config_index = 87752506Simp pccard_tuple_read_1(tuple, 1); 87852506Simp 87952506Simp state->pf->ccr_base = 0; 88052506Simp for (i = 0; i < rasz; i++) 88152506Simp state->pf->ccr_base |= 88252506Simp ((pccard_tuple_read_1(tuple, 2 + i)) << 88352506Simp (i * 8)); 88452506Simp 88552506Simp state->pf->ccr_mask = 0; 88652506Simp for (i = 0; i < rmsz; i++) 88752506Simp state->pf->ccr_mask |= 88852506Simp ((pccard_tuple_read_1(tuple, 88952506Simp 2 + rasz + i)) << (i * 8)); 89052506Simp 89152506Simp /* skip the reserved area and subtuples */ 89252506Simp 89352506Simp /* reset the default cfe for each cfe list */ 89452506Simp state->temp_cfe = init_cfe; 89552506Simp state->default_cfe = &state->temp_cfe; 89652506Simp } 89752506Simp DPRINTF(("CISTPL_CONFIG\n")); 89852506Simp break; 899120868Simp case CISTPL_CFTABLE_ENTRY: 90052506Simp { 901179483Simp int idx, i; 90252506Simp u_int reg, reg2; 90352506Simp u_int intface, def, num; 90452506Simp u_int power, timing, iospace, irq, memspace, misc; 90552506Simp struct pccard_config_entry *cfe; 90652506Simp 90752506Simp idx = 0; 90852506Simp 909179483Simp reg = pccard_tuple_read_1(tuple, idx++); 91052506Simp intface = reg & PCCARD_TPCE_INDX_INTFACE; 91152506Simp def = reg & PCCARD_TPCE_INDX_DEFAULT; 91252506Simp num = reg & PCCARD_TPCE_INDX_NUM_MASK; 91352506Simp 91452506Simp /* 91552506Simp * this is a little messy. Some cards have only a 91652506Simp * cfentry with the default bit set. So, as we go 91752506Simp * through the list, we add new indexes to the queue, 91852506Simp * and keep a pointer to the last one with the 91952506Simp * default bit set. if we see a record with the same 92052506Simp * index, as the default, we stash the default and 92152506Simp * replace the queue entry. otherwise, we just add 92252506Simp * new entries to the queue, pointing the default ptr 92352506Simp * at them if the default bit is set. if we get to 92452506Simp * the end with the default pointer pointing at a 92552506Simp * record which hasn't had a matching index, that's 92652506Simp * ok; it just becomes a cfentry like any other. 92752506Simp */ 92852506Simp 92952506Simp /* 93052506Simp * if the index in the cis differs from the default 93152506Simp * cis, create new entry in the queue and start it 93252506Simp * with the current default 93352506Simp */ 93452506Simp if (num != state->default_cfe->number) { 93552506Simp cfe = (struct pccard_config_entry *) 93652506Simp malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT); 937144159Ssam if (cfe == NULL) { 938144159Ssam DPRINTF(("no memory for config entry\n")); 939144159Ssam goto abort_cfe; 940144159Ssam } 94152506Simp *cfe = *state->default_cfe; 94252506Simp 94352506Simp STAILQ_INSERT_TAIL(&state->pf->cfe_head, 94452506Simp cfe, cfe_list); 94552506Simp 94652506Simp cfe->number = num; 94752506Simp 94852506Simp /* 94952506Simp * if the default bit is set in the cis, then 95052506Simp * point the new default at whatever is being 95152506Simp * filled in 95252506Simp */ 95352506Simp if (def) 95452506Simp state->default_cfe = cfe; 95552506Simp } else { 95652506Simp /* 95752506Simp * the cis index matches the default index, 95852506Simp * fill in the default cfentry. It is 95952506Simp * assumed that the cfdefault index is in the 96052506Simp * queue. For it to be otherwise, the cis 96152506Simp * index would have to be -1 (initial 96252506Simp * condition) which is not possible, or there 96352506Simp * would have to be a preceding cis entry 96452506Simp * which had the same cis index and had the 96552506Simp * default bit unset. Neither condition 96652506Simp * should happen. If it does, this cfentry 96752506Simp * is lost (written into temp space), which 96852506Simp * is an acceptable failure mode. 96952506Simp */ 97052506Simp 97152506Simp cfe = state->default_cfe; 97252506Simp 97352506Simp /* 97452506Simp * if the cis entry does not have the default 97552506Simp * bit set, copy the default out of the way 97652506Simp * first. 97752506Simp */ 97852506Simp if (!def) { 97952506Simp state->temp_cfe = *state->default_cfe; 98052506Simp state->default_cfe = &state->temp_cfe; 98152506Simp } 98252506Simp } 98352506Simp 98452506Simp if (intface) { 985179483Simp reg = pccard_tuple_read_1(tuple, idx++); 986104640Simp cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED 987104640Simp | PCCARD_CFE_RDYBSY_ACTIVE 988104640Simp | PCCARD_CFE_WP_ACTIVE 989104640Simp | PCCARD_CFE_BVD_ACTIVE); 99052506Simp if (reg & PCCARD_TPCE_IF_MWAIT) 99152506Simp cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED; 99252506Simp if (reg & PCCARD_TPCE_IF_RDYBSY) 99352506Simp cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE; 99452506Simp if (reg & PCCARD_TPCE_IF_WP) 99552506Simp cfe->flags |= PCCARD_CFE_WP_ACTIVE; 99652506Simp if (reg & PCCARD_TPCE_IF_BVD) 99752506Simp cfe->flags |= PCCARD_CFE_BVD_ACTIVE; 99852506Simp cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE; 99952506Simp } 1000179483Simp reg = pccard_tuple_read_1(tuple, idx++); 100152506Simp 100252506Simp power = reg & PCCARD_TPCE_FS_POWER_MASK; 100352506Simp timing = reg & PCCARD_TPCE_FS_TIMING; 100452506Simp iospace = reg & PCCARD_TPCE_FS_IOSPACE; 100552506Simp irq = reg & PCCARD_TPCE_FS_IRQ; 100652506Simp memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK; 100752506Simp misc = reg & PCCARD_TPCE_FS_MISC; 100852506Simp 100952506Simp if (power) { 101052506Simp /* skip over power, don't save */ 101152506Simp /* for each parameter selection byte */ 101252506Simp for (i = 0; i < power; i++) { 1013179483Simp reg = pccard_tuple_read_1(tuple, idx++); 1014179483Simp for (; reg; reg >>= 1) 1015179483Simp { 1016179483Simp /* set bit -> read */ 1017179483Simp if ((reg & 1) == 0) 1018179483Simp continue; 1019179483Simp /* skip over bytes */ 1020179483Simp do { 1021179483Simp reg2 = pccard_tuple_read_1(tuple, idx++); 1022179483Simp /* 1023179483Simp * until non-extension 1024179483Simp * byte 1025179483Simp */ 1026179483Simp } while (reg2 & 0x80); 102752506Simp } 102852506Simp } 102952506Simp } 103052506Simp if (timing) { 103152506Simp /* skip over timing, don't save */ 1032179483Simp reg = pccard_tuple_read_1(tuple, idx++); 103352506Simp 103452506Simp if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) != 103552506Simp PCCARD_TPCE_TD_RESERVED_MASK) 103652506Simp idx++; 103752506Simp if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) != 103852506Simp PCCARD_TPCE_TD_RDYBSY_MASK) 103952506Simp idx++; 104052506Simp if ((reg & PCCARD_TPCE_TD_WAIT_MASK) != 104152506Simp PCCARD_TPCE_TD_WAIT_MASK) 104252506Simp idx++; 104352506Simp } 104452506Simp if (iospace) { 104552506Simp if (tuple->length <= idx) { 104652506Simp DPRINTF(("ran out of space before TCPE_IO\n")); 104752506Simp goto abort_cfe; 104852506Simp } 104952506Simp 1050179483Simp reg = pccard_tuple_read_1(tuple, idx++); 1051104640Simp cfe->flags &= 1052104640Simp ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16); 105352506Simp if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT) 105452506Simp cfe->flags |= PCCARD_CFE_IO8; 105552506Simp if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT) 105652506Simp cfe->flags |= PCCARD_CFE_IO16; 105752506Simp cfe->iomask = 105852506Simp reg & PCCARD_TPCE_IO_IOADDRLINES_MASK; 105952506Simp 106052506Simp if (reg & PCCARD_TPCE_IO_HASRANGE) { 1061179483Simp reg = pccard_tuple_read_1(tuple, idx++); 106252506Simp cfe->num_iospace = 1 + (reg & 106352506Simp PCCARD_TPCE_IO_RANGE_COUNT); 106452506Simp 106552506Simp if (cfe->num_iospace > 106652506Simp (sizeof(cfe->iospace) / 106752506Simp sizeof(cfe->iospace[0]))) { 106852506Simp DPRINTF(("too many io " 106952506Simp "spaces %d", 107052506Simp cfe->num_iospace)); 107152506Simp state->card->error++; 107252506Simp break; 107352506Simp } 107452506Simp for (i = 0; i < cfe->num_iospace; i++) { 107552506Simp switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) { 107652506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE: 107752506Simp cfe->iospace[i].start = 1078179483Simp pccard_tuple_read_1(tuple, idx++); 107952506Simp break; 108052506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO: 108152506Simp cfe->iospace[i].start = 108252506Simp pccard_tuple_read_2(tuple, idx); 108352506Simp idx += 2; 108452506Simp break; 108552506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR: 108652506Simp cfe->iospace[i].start = 108752506Simp pccard_tuple_read_4(tuple, idx); 108852506Simp idx += 4; 108952506Simp break; 109052506Simp } 109152506Simp switch (reg & 109252506Simp PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) { 109352506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE: 109452506Simp cfe->iospace[i].length = 1095179483Simp pccard_tuple_read_1(tuple, idx++); 109652506Simp break; 109752506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO: 109852506Simp cfe->iospace[i].length = 109952506Simp pccard_tuple_read_2(tuple, idx); 110052506Simp idx += 2; 110152506Simp break; 110252506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR: 110352506Simp cfe->iospace[i].length = 110452506Simp pccard_tuple_read_4(tuple, idx); 110552506Simp idx += 4; 110652506Simp break; 110752506Simp } 110852506Simp cfe->iospace[i].length++; 110952506Simp } 111052506Simp } else { 111152506Simp cfe->num_iospace = 1; 111252506Simp cfe->iospace[0].start = 0; 111352506Simp cfe->iospace[0].length = 111452506Simp (1 << cfe->iomask); 111552506Simp } 111652506Simp } 111752506Simp if (irq) { 111852506Simp if (tuple->length <= idx) { 111952506Simp DPRINTF(("ran out of space before TCPE_IR\n")); 112052506Simp goto abort_cfe; 112152506Simp } 112252506Simp 1123179483Simp reg = pccard_tuple_read_1(tuple, idx++); 1124104640Simp cfe->flags &= ~(PCCARD_CFE_IRQSHARE 1125104640Simp | PCCARD_CFE_IRQPULSE 1126104640Simp | PCCARD_CFE_IRQLEVEL); 112752506Simp if (reg & PCCARD_TPCE_IR_SHARE) 112852506Simp cfe->flags |= PCCARD_CFE_IRQSHARE; 112952506Simp if (reg & PCCARD_TPCE_IR_PULSE) 113052506Simp cfe->flags |= PCCARD_CFE_IRQPULSE; 113152506Simp if (reg & PCCARD_TPCE_IR_LEVEL) 113252506Simp cfe->flags |= PCCARD_CFE_IRQLEVEL; 113352506Simp 113452506Simp if (reg & PCCARD_TPCE_IR_HASMASK) { 113552506Simp /* 113652506Simp * it's legal to ignore the 113752506Simp * special-interrupt bits, so I will 113852506Simp */ 113952506Simp 114052506Simp cfe->irqmask = 114152506Simp pccard_tuple_read_2(tuple, idx); 114252506Simp idx += 2; 114352506Simp } else { 114452506Simp cfe->irqmask = 114552506Simp (1 << (reg & PCCARD_TPCE_IR_IRQ)); 114652506Simp } 1147182229Simp } else { 1148182229Simp cfe->irqmask = 0xffff; 114952506Simp } 115052506Simp if (memspace) { 115152506Simp if (tuple->length <= idx) { 115252506Simp DPRINTF(("ran out of space before TCPE_MS\n")); 115352506Simp goto abort_cfe; 115452506Simp } 115552506Simp 1156142027Simp if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) { 115752506Simp cfe->num_memspace = 1; 115852506Simp cfe->memspace[0].length = 256 * 115952506Simp pccard_tuple_read_2(tuple, idx); 116052506Simp idx += 2; 116152506Simp cfe->memspace[0].cardaddr = 0; 116252506Simp cfe->memspace[0].hostaddr = 0; 116352506Simp } else if (memspace == 116452506Simp PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) { 116552506Simp cfe->num_memspace = 1; 116652506Simp cfe->memspace[0].length = 256 * 116752506Simp pccard_tuple_read_2(tuple, idx); 116852506Simp idx += 2; 116952506Simp cfe->memspace[0].cardaddr = 256 * 117052506Simp pccard_tuple_read_2(tuple, idx); 117152506Simp idx += 2; 117252506Simp cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr; 117352506Simp } else { 117452506Simp int lengthsize; 117552506Simp int cardaddrsize; 117652506Simp int hostaddrsize; 117752506Simp 1178179483Simp reg = pccard_tuple_read_1(tuple, idx++); 117953873Simp cfe->num_memspace = (reg & 118053873Simp PCCARD_TPCE_MS_COUNT) + 1; 118152506Simp if (cfe->num_memspace > 118252506Simp (sizeof(cfe->memspace) / 118352506Simp sizeof(cfe->memspace[0]))) { 118452506Simp DPRINTF(("too many mem " 118552506Simp "spaces %d", 118652506Simp cfe->num_memspace)); 118752506Simp state->card->error++; 118852506Simp break; 118952506Simp } 119052506Simp lengthsize = 119152506Simp ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >> 119252506Simp PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT); 119352506Simp cardaddrsize = 119452506Simp ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >> 119552506Simp PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT); 119652506Simp hostaddrsize = 119752506Simp (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0; 119852506Simp 119952506Simp if (lengthsize == 0) { 120052506Simp DPRINTF(("cfe memspace " 1201189682Simp "lengthsize == 0\n")); 120252506Simp } 120352506Simp for (i = 0; i < cfe->num_memspace; i++) { 120452506Simp if (lengthsize) { 120552506Simp cfe->memspace[i].length = 120652506Simp 256 * pccard_tuple_read_n(tuple, lengthsize, 120752506Simp idx); 120852506Simp idx += lengthsize; 120952506Simp } else { 121052506Simp cfe->memspace[i].length = 0; 121152506Simp } 121252506Simp if (cfe->memspace[i].length == 0) { 1213189682Simp DPRINTF(("cfe->memspace[%d].length == 0\n", 121452506Simp i)); 121552506Simp } 121652506Simp if (cardaddrsize) { 121752506Simp cfe->memspace[i].cardaddr = 121852506Simp 256 * pccard_tuple_read_n(tuple, cardaddrsize, 121952506Simp idx); 122052506Simp idx += cardaddrsize; 122152506Simp } else { 122252506Simp cfe->memspace[i].cardaddr = 0; 122352506Simp } 122452506Simp if (hostaddrsize) { 122552506Simp cfe->memspace[i].hostaddr = 122652506Simp 256 * pccard_tuple_read_n(tuple, hostaddrsize, 122752506Simp idx); 122852506Simp idx += hostaddrsize; 122952506Simp } else { 123052506Simp cfe->memspace[i].hostaddr = 0; 123152506Simp } 123252506Simp } 123352506Simp } 1234142027Simp } else 1235142027Simp cfe->num_memspace = 0; 123652506Simp if (misc) { 123752506Simp if (tuple->length <= idx) { 123852506Simp DPRINTF(("ran out of space before TCPE_MI\n")); 123952506Simp goto abort_cfe; 124052506Simp } 124152506Simp 1242179483Simp reg = pccard_tuple_read_1(tuple, idx++); 1243104640Simp cfe->flags &= ~(PCCARD_CFE_POWERDOWN 1244104640Simp | PCCARD_CFE_READONLY 1245104640Simp | PCCARD_CFE_AUDIO); 124652506Simp if (reg & PCCARD_TPCE_MI_PWRDOWN) 1247104640Simp cfe->flags |= PCCARD_CFE_POWERDOWN; 124852506Simp if (reg & PCCARD_TPCE_MI_READONLY) 1249104640Simp cfe->flags |= PCCARD_CFE_READONLY; 125052506Simp if (reg & PCCARD_TPCE_MI_AUDIO) 1251104640Simp cfe->flags |= PCCARD_CFE_AUDIO; 125252506Simp cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS; 125352506Simp 125452506Simp while (reg & PCCARD_TPCE_MI_EXT) { 1255179483Simp reg = pccard_tuple_read_1(tuple, idx++); 125652506Simp } 125752506Simp } 125852506Simp /* skip all the subtuples */ 125952506Simp } 126052506Simp 126152506Simp abort_cfe: 126252506Simp DPRINTF(("CISTPL_CFTABLE_ENTRY\n")); 126352506Simp break; 126452506Simp default: 1265188212Swkoszek DPRINTF(("unhandled CISTPL %#x\n", tuple->code)); 126652506Simp break; 126752506Simp } 126852506Simp 126952506Simp return (0); 127052506Simp} 127182781Sshiba 127282781Sshibastatic int 1273147729Simpdecode_funce(const struct pccard_tuple *tuple, struct pccard_function *pf) 127482781Sshiba{ 1275140542Simp int i; 1276140542Simp int len; 127782781Sshiba int type = pccard_tuple_read_1(tuple, 0); 127882781Sshiba 127982781Sshiba switch (pf->function) { 128082781Sshiba case PCCARD_FUNCTION_DISK: 128182781Sshiba if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) { 128282781Sshiba pf->pf_funce_disk_interface 128382781Sshiba = pccard_tuple_read_1(tuple, 1); 1284188219Simp pf->pf_funce_disk_power 1285188219Simp = pccard_tuple_read_1(tuple, 2); 128682781Sshiba } 128782781Sshiba break; 128882781Sshiba case PCCARD_FUNCTION_NETWORK: 128982781Sshiba if (type == PCCARD_TPLFE_TYPE_LAN_NID) { 1290140542Simp len = pccard_tuple_read_1(tuple, 1); 129182781Sshiba if (tuple->length < 2 + len || len > 8) { 129282781Sshiba /* tuple length not enough or nid too long */ 129382781Sshiba break; 129482781Sshiba } 129582781Sshiba for (i = 0; i < len; i++) { 129682781Sshiba pf->pf_funce_lan_nid[i] 129782781Sshiba = pccard_tuple_read_1(tuple, i + 2); 129882781Sshiba } 129982781Sshiba pf->pf_funce_lan_nidlen = len; 130082781Sshiba } 130182781Sshiba break; 130282781Sshiba default: 130382781Sshiba break; 130482781Sshiba } 130582781Sshiba return 0; 130682781Sshiba} 1307