pccard_cis.c revision 104640
1104640Simp/* $NetBSD: pcmcia_cis.c,v 1.17 2000/02/10 09:01:52 chopps Exp $ */ 252506Simp/* $FreeBSD: head/sys/dev/pccard/pccard_cis.c 104640 2002-10-07 23:03:17Z imp $ */ 352506Simp 452506Simp/* 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> 4852506Simp 4959193Simp#include "card_if.h" 5059193Simp 5191786Simpextern int pccard_cis_debug; 5291786Simp 5359193Simp#define PCCARDCISDEBUG 5452506Simp#ifdef PCCARDCISDEBUG 5591786Simp#define DPRINTF(arg) if (pccard_cis_debug) printf arg 5691786Simp#define DEVPRINTF(arg) if (pccard_cis_debug) device_printf arg 5752506Simp#else 5852506Simp#define DPRINTF(arg) 5955720Simp#define DEVPRINTF(arg) 6052506Simp#endif 6152506Simp 6252506Simp#define PCCARD_CIS_SIZE 1024 6352506Simp 6452506Simpstruct cis_state { 6552506Simp int count; 6652506Simp int gotmfc; 6752506Simp struct pccard_config_entry temp_cfe; 6852506Simp struct pccard_config_entry *default_cfe; 6952506Simp struct pccard_card *card; 7052506Simp struct pccard_function *pf; 7152506Simp}; 7252506Simp 7354250Simpint pccard_parse_cis_tuple(struct pccard_tuple *, void *); 7482781Sshibastatic int decode_funce(struct pccard_tuple *, struct pccard_function *); 7552506Simp 7652506Simpvoid 7755720Simppccard_read_cis(struct pccard_softc *sc) 7852506Simp{ 7952506Simp struct cis_state state; 8052506Simp 81104640Simp bzero(&state, sizeof state); 8252506Simp 8352506Simp state.card = &sc->card; 8452506Simp 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 9652506Simp state.pf = NULL; 9752506Simp 9858997Simp if (pccard_scan_cis(sc->dev, pccard_parse_cis_tuple, 9952506Simp &state) == -1) 10052506Simp state.card->error++; 10152506Simp} 10252506Simp 10352506Simpint 10455720Simppccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *), 10555720Simp void *arg) 10652506Simp{ 10755720Simp struct resource *res; 10855720Simp int rid; 10952506Simp struct pccard_tuple tuple; 11052506Simp int longlink_present; 11152506Simp int longlink_common; 11252506Simp u_long longlink_addr; 11352506Simp int mfc_count; 11452506Simp int mfc_index; 11552506Simp struct { 11652506Simp int common; 11752506Simp u_long addr; 11852506Simp } mfc[256 / 5]; 11952506Simp int ret; 12052506Simp 12152506Simp ret = 0; 12252506Simp 12352506Simp /* allocate some memory */ 12452506Simp 12555720Simp rid = 0; 12655720Simp res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 12759193Simp PCCARD_CIS_SIZE, RF_ACTIVE); 12855720Simp if (res == NULL) { 12955720Simp device_printf(dev, "can't alloc memory to read attributes\n"); 13052506Simp return -1; 13152506Simp } 13259193Simp CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, 13359193Simp rid, PCCARD_A_MEM_ATTR); 13455720Simp tuple.memt = rman_get_bustag(res); 13555720Simp tuple.memh = rman_get_bushandle(res); 13659389Simp tuple.ptr = 0; 13752506Simp 13852506Simp DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh)); 13955720Simp 14052506Simp tuple.mult = 2; 14152506Simp 14252506Simp longlink_present = 1; 14352506Simp longlink_common = 1; 14452506Simp longlink_addr = 0; 14552506Simp 14652506Simp mfc_count = 0; 14752506Simp mfc_index = 0; 14852506Simp 14955720Simp DEVPRINTF((dev, "CIS tuple chain:\n")); 15052506Simp 15152506Simp while (1) { 15252506Simp while (1) { 15352506Simp /* get the tuple code */ 15452506Simp 15552506Simp tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 15652506Simp 15752506Simp /* two special-case tuples */ 15852506Simp 15952506Simp if (tuple.code == PCCARD_CISTPL_NULL) { 16052506Simp DPRINTF(("CISTPL_NONE\n 00\n")); 16152506Simp tuple.ptr++; 16252506Simp continue; 16352506Simp } else if (tuple.code == PCCARD_CISTPL_END) { 16452506Simp DPRINTF(("CISTPL_END\n ff\n")); 16552506Simp /* Call the function for the END tuple, since 16652506Simp the CIS semantics depend on it */ 16752506Simp if ((*fct) (&tuple, arg)) { 16852506Simp ret = 1; 16952506Simp goto done; 17052506Simp } 17152506Simp tuple.ptr++; 17252506Simp break; 17352506Simp } 17452506Simp /* now all the normal tuples */ 17552506Simp 17652506Simp tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 17752506Simp switch (tuple.code) { 17852506Simp case PCCARD_CISTPL_LONGLINK_A: 17952506Simp case PCCARD_CISTPL_LONGLINK_C: 18052506Simp if (tuple.length < 4) { 18152506Simp DPRINTF(("CISTPL_LONGLINK_%s too " 18252506Simp "short %d\n", 18352506Simp longlink_common ? "C" : "A", 18452506Simp tuple.length)); 18552506Simp break; 18652506Simp } 18752506Simp longlink_present = 1; 18852506Simp longlink_common = (tuple.code == 18952506Simp PCCARD_CISTPL_LONGLINK_C) ? 1 : 0; 19052506Simp longlink_addr = pccard_tuple_read_4(&tuple, 0); 19152506Simp DPRINTF(("CISTPL_LONGLINK_%s %lx\n", 19252506Simp longlink_common ? "C" : "A", 19352506Simp longlink_addr)); 19452506Simp break; 19552506Simp case PCCARD_CISTPL_NO_LINK: 19652506Simp longlink_present = 0; 19752506Simp DPRINTF(("CISTPL_NO_LINK\n")); 19852506Simp break; 19952506Simp case PCCARD_CISTPL_CHECKSUM: 20052506Simp if (tuple.length < 5) { 20152506Simp DPRINTF(("CISTPL_CHECKSUM too " 20252506Simp "short %d\n", tuple.length)); 20352506Simp break; 20452506Simp } { 20552506Simp int16_t offset; 20652506Simp u_long addr, length; 20752506Simp u_int cksum, sum; 20852506Simp int i; 20952506Simp 21090896Simp offset = (uint16_t) 21152506Simp pccard_tuple_read_2(&tuple, 0); 21252506Simp length = pccard_tuple_read_2(&tuple, 2); 21352506Simp cksum = pccard_tuple_read_1(&tuple, 4); 21452506Simp 21552506Simp addr = tuple.ptr + offset; 21652506Simp 21752506Simp DPRINTF(("CISTPL_CHECKSUM addr=%lx " 21852506Simp "len=%lx cksum=%x", 21952506Simp addr, length, cksum)); 22052506Simp 22152506Simp /* 22252506Simp * XXX do more work to deal with 22352506Simp * distant regions 22452506Simp */ 22552506Simp if ((addr >= PCCARD_CIS_SIZE) || 22652506Simp ((addr + length) >= 227104640Simp PCCARD_CIS_SIZE)) { 22852506Simp DPRINTF((" skipped, " 22952506Simp "too distant\n")); 23052506Simp break; 23152506Simp } 23252506Simp sum = 0; 23352506Simp for (i = 0; i < length; i++) 23452506Simp sum += 23552506Simp bus_space_read_1(tuple.memt, 23652506Simp tuple.memh, 23752506Simp addr + tuple.mult * i); 23852506Simp if (cksum != (sum & 0xff)) { 23952506Simp DPRINTF((" failed sum=%x\n", 24052506Simp sum)); 24155720Simp device_printf(dev, 24255720Simp "CIS checksum failed\n"); 24352506Simp#if 0 24452506Simp /* 24552506Simp * XXX Some working cards have 24652506Simp * XXX bad checksums!! 24752506Simp */ 24852506Simp ret = -1; 24952506Simp#endif 25052506Simp } else { 25152506Simp DPRINTF((" ok\n")); 25252506Simp } 25352506Simp } 25452506Simp break; 25552506Simp case PCCARD_CISTPL_LONGLINK_MFC: 25652506Simp if (tuple.length < 1) { 25752506Simp DPRINTF(("CISTPL_LONGLINK_MFC too " 25852506Simp "short %d\n", tuple.length)); 25952506Simp break; 26052506Simp } 261104640Simp if (((tuple.length - 1) % 5) != 0) { 262104640Simp DPRINTF(("CISTPL_LONGLINK_MFC bogus " 263104640Simp "length %d\n", tuple.length)); 264104640Simp break; 265104640Simp } 26652506Simp /* 26752506Simp * this is kind of ad hoc, as I don't have 26852506Simp * any real documentation 26952506Simp */ 27052506Simp { 271104640Simp int i, tmp_count; 27252506Simp 273104640Simp /* 274104640Simp * put count into tmp var so that 275104640Simp * if we have to bail (because it's 276104640Simp * a bogus count) it won't be 277104640Simp * remembered for later use. 278104640Simp */ 279104640Simp tmp_count = 28052506Simp pccard_tuple_read_1(&tuple, 0); 281104640Simp 28252506Simp DPRINTF(("CISTPL_LONGLINK_MFC %d", 283104640Simp tmp_count)); 284104640Simp 285104640Simp /* 286104640Simp * make _sure_ it's the right size; 287104640Simp * if too short, it may be a weird 288104640Simp * (unknown/undefined) format 289104640Simp */ 290104640Simp if (tuple.length != (tmp_count*5 + 1)) { 291104640Simp DPRINTF((" bogus length %d\n", 292104640Simp tuple.length)); 293104640Simp break; 294104640Simp } 295104640Simp /* 296104640Simp * sanity check for a programming 297104640Simp * error which is difficult to find 298104640Simp * when debugging. 299104640Simp */ 300104640Simp if (tmp_count > 301104640Simp howmany(sizeof mfc, sizeof mfc[0])) 302104640Simp panic("CISTPL_LONGLINK_MFC mfc " 303104640Simp "count would blow stack"); 304104640Simp mfc_count = tmp_count; 30552506Simp for (i = 0; i < mfc_count; i++) { 30652506Simp mfc[i].common = 30752506Simp (pccard_tuple_read_1(&tuple, 30852506Simp 1 + 5 * i) == 30952506Simp PCCARD_MFC_MEM_COMMON) ? 31052506Simp 1 : 0; 31152506Simp mfc[i].addr = 31252506Simp pccard_tuple_read_4(&tuple, 31352506Simp 1 + 5 * i + 1); 31452506Simp DPRINTF((" %s:%lx", 31552506Simp mfc[i].common ? "common" : 31652506Simp "attr", mfc[i].addr)); 31752506Simp } 31852506Simp DPRINTF(("\n")); 31952506Simp } 32052506Simp /* 32152506Simp * for LONGLINK_MFC, fall through to the 32252506Simp * function. This tuple has structural and 32352506Simp * semantic content. 32452506Simp */ 32552506Simp default: 32652506Simp { 32752506Simp if ((*fct) (&tuple, arg)) { 32852506Simp ret = 1; 32952506Simp goto done; 33052506Simp } 33152506Simp } 33252506Simp break; 33352506Simp } /* switch */ 33452506Simp#ifdef PCCARDCISDEBUG 33552506Simp /* print the tuple */ 33652506Simp { 33752506Simp int i; 33852506Simp 33952506Simp DPRINTF((" %02x %02x", tuple.code, 34052506Simp tuple.length)); 34152506Simp 34252506Simp for (i = 0; i < tuple.length; i++) { 34352506Simp DPRINTF((" %02x", 34452506Simp pccard_tuple_read_1(&tuple, i))); 34552506Simp if ((i % 16) == 13) 34652506Simp DPRINTF(("\n")); 34752506Simp } 34887352Simp 34952506Simp if ((i % 16) != 14) 35052506Simp DPRINTF(("\n")); 35152506Simp } 35252506Simp#endif 35352506Simp /* skip to the next tuple */ 35452506Simp tuple.ptr += 2 + tuple.length; 35552506Simp } 35652506Simp 35752506Simp /* 35852506Simp * the chain is done. Clean up and move onto the next one, 35952506Simp * if any. The loop is here in the case that there is an MFC 36052506Simp * card with no longlink (which defaults to existing, == 0). 36152506Simp * In general, this means that if one pointer fails, it will 36252506Simp * try the next one, instead of just bailing. 36352506Simp */ 36452506Simp 36552506Simp while (1) { 36652506Simp if (longlink_present) { 36787352Simp CARD_SET_RES_FLAGS(device_get_parent(dev), dev, 36887352Simp SYS_RES_MEMORY, rid, longlink_common ? 36993370Simp PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR); 37052506Simp DPRINTF(("cis mem map %x\n", 37152506Simp (unsigned int) tuple.memh)); 37252506Simp tuple.mult = longlink_common ? 1 : 2; 37393370Simp tuple.ptr = longlink_addr; 37452506Simp longlink_present = 0; 37552506Simp longlink_common = 1; 37652506Simp longlink_addr = 0; 37752506Simp } else if (mfc_count && (mfc_index < mfc_count)) { 37887352Simp CARD_SET_RES_FLAGS(device_get_parent(dev), dev, 37987352Simp SYS_RES_MEMORY, rid, mfc[mfc_index].common 38093370Simp ? PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR); 38152506Simp DPRINTF(("cis mem map %x\n", 38252506Simp (unsigned int) tuple.memh)); 38352506Simp /* set parse state, and point at the next one */ 38452506Simp tuple.mult = mfc[mfc_index].common ? 1 : 2; 38593370Simp tuple.ptr = mfc[mfc_index].addr; 38652506Simp mfc_index++; 38752506Simp } else { 38852506Simp goto done; 38952506Simp } 39052506Simp 39152506Simp /* make sure that the link is valid */ 39252506Simp tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 39352506Simp if (tuple.code != PCCARD_CISTPL_LINKTARGET) { 39452506Simp DPRINTF(("CISTPL_LINKTARGET expected, " 39552506Simp "code %02x observed\n", tuple.code)); 39652506Simp continue; 39752506Simp } 39852506Simp tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 39952506Simp if (tuple.length < 3) { 40052506Simp DPRINTF(("CISTPL_LINKTARGET too short %d\n", 40152506Simp tuple.length)); 40252506Simp continue; 40352506Simp } 40452506Simp if ((pccard_tuple_read_1(&tuple, 0) != 'C') || 40552506Simp (pccard_tuple_read_1(&tuple, 1) != 'I') || 40652506Simp (pccard_tuple_read_1(&tuple, 2) != 'S')) { 40752506Simp DPRINTF(("CISTPL_LINKTARGET magic " 40852506Simp "%02x%02x%02x incorrect\n", 40952506Simp pccard_tuple_read_1(&tuple, 0), 41052506Simp pccard_tuple_read_1(&tuple, 1), 41152506Simp pccard_tuple_read_1(&tuple, 2))); 41252506Simp continue; 41352506Simp } 41452506Simp tuple.ptr += 2 + tuple.length; 41552506Simp break; 41652506Simp } 41752506Simp } 41852506Simp 41952506Simpdone: 42055720Simp bus_release_resource(dev, SYS_RES_MEMORY, rid, res); 42152506Simp 42252506Simp return (ret); 42352506Simp} 42452506Simp 42552506Simp/* XXX this is incredibly verbose. Not sure what trt is */ 42652506Simp 42752506Simpvoid 42852506Simppccard_print_cis(device_t dev) 42952506Simp{ 43064850Simp struct pccard_softc *sc = PCCARD_SOFTC(dev); 43152506Simp struct pccard_card *card = &sc->card; 43252506Simp struct pccard_function *pf; 43352506Simp struct pccard_config_entry *cfe; 43452506Simp int i; 43552506Simp 43652506Simp device_printf(dev, "CIS version "); 43752506Simp if (card->cis1_major == 4) { 43852506Simp if (card->cis1_minor == 0) 43952506Simp printf("PCCARD 1.0\n"); 44052506Simp else if (card->cis1_minor == 1) 44152506Simp printf("PCCARD 2.0 or 2.1\n"); 44252506Simp } else if (card->cis1_major >= 5) 44352506Simp printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor); 44452506Simp else 44552506Simp printf("unknown (major=%d, minor=%d)\n", 44652506Simp card->cis1_major, card->cis1_minor); 44752506Simp 44852506Simp device_printf(dev, "CIS info: "); 44952506Simp for (i = 0; i < 4; i++) { 45052506Simp if (card->cis1_info[i] == NULL) 45152506Simp break; 45252506Simp if (i) 45352506Simp printf(", "); 45452506Simp printf("%s", card->cis1_info[i]); 45552506Simp } 45652506Simp printf("\n"); 45752506Simp 45852506Simp device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n", 45952506Simp card->manufacturer, card->product); 46052506Simp 46152506Simp STAILQ_FOREACH(pf, &card->pf_head, pf_list) { 46252506Simp device_printf(dev, "function %d: ", pf->number); 46352506Simp 46452506Simp switch (pf->function) { 46552506Simp case PCCARD_FUNCTION_UNSPEC: 46652506Simp printf("unspecified"); 46752506Simp break; 46852506Simp case PCCARD_FUNCTION_MULTIFUNCTION: 46952506Simp printf("multi-function"); 47052506Simp break; 47152506Simp case PCCARD_FUNCTION_MEMORY: 47252506Simp printf("memory"); 47352506Simp break; 47452506Simp case PCCARD_FUNCTION_SERIAL: 47552506Simp printf("serial port"); 47652506Simp break; 47752506Simp case PCCARD_FUNCTION_PARALLEL: 47852506Simp printf("parallel port"); 47952506Simp break; 48052506Simp case PCCARD_FUNCTION_DISK: 48152506Simp printf("fixed disk"); 48252506Simp break; 48352506Simp case PCCARD_FUNCTION_VIDEO: 48452506Simp printf("video adapter"); 48552506Simp break; 48652506Simp case PCCARD_FUNCTION_NETWORK: 48752506Simp printf("network adapter"); 48852506Simp break; 48952506Simp case PCCARD_FUNCTION_AIMS: 49052506Simp printf("auto incrementing mass storage"); 49152506Simp break; 49252506Simp case PCCARD_FUNCTION_SCSI: 49352506Simp printf("SCSI bridge"); 49452506Simp break; 49552506Simp case PCCARD_FUNCTION_SECURITY: 49652506Simp printf("Security services"); 49752506Simp break; 49852506Simp case PCCARD_FUNCTION_INSTRUMENT: 49952506Simp printf("Instrument"); 50052506Simp break; 50152506Simp default: 50252506Simp printf("unknown (%d)", pf->function); 50352506Simp break; 50452506Simp } 50552506Simp 50652506Simp printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask); 50752506Simp 50852506Simp STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) { 50952506Simp device_printf(dev, "function %d, config table entry " 51052506Simp "%d: ", pf->number, cfe->number); 51152506Simp 51252506Simp switch (cfe->iftype) { 51352506Simp case PCCARD_IFTYPE_MEMORY: 51452506Simp printf("memory card"); 51552506Simp break; 51652506Simp case PCCARD_IFTYPE_IO: 51752506Simp printf("I/O card"); 51852506Simp break; 51952506Simp default: 52052506Simp printf("card type unknown"); 52152506Simp break; 52252506Simp } 52352506Simp 52452506Simp printf("; irq mask %x", cfe->irqmask); 52552506Simp 52652506Simp if (cfe->num_iospace) { 52752506Simp printf("; iomask %lx, iospace", cfe->iomask); 52852506Simp 52953813Simp for (i = 0; i < cfe->num_iospace; i++) { 53053813Simp printf(" %lx", cfe->iospace[i].start); 53153813Simp if (cfe->iospace[i].length) 53253813Simp printf("-%lx", 53353813Simp cfe->iospace[i].start + 53453813Simp cfe->iospace[i].length - 1); 53553813Simp } 53652506Simp } 53752506Simp if (cfe->num_memspace) { 53852506Simp printf("; memspace"); 53952506Simp 54053813Simp for (i = 0; i < cfe->num_memspace; i++) { 54153813Simp printf(" %lx", 54253813Simp cfe->memspace[i].cardaddr); 54353813Simp if (cfe->memspace[i].length) 54453813Simp printf("-%lx", 54553813Simp cfe->memspace[i].cardaddr + 54653813Simp cfe->memspace[i].length - 1); 54753813Simp if (cfe->memspace[i].hostaddr) 54853813Simp printf("@%lx", 54953813Simp cfe->memspace[i].hostaddr); 55053813Simp } 55152506Simp } 55252506Simp if (cfe->maxtwins) 55352506Simp printf("; maxtwins %d", cfe->maxtwins); 55452506Simp 55552506Simp printf(";"); 55652506Simp 55752506Simp if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED) 55852506Simp printf(" mwait_required"); 55952506Simp if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE) 56052506Simp printf(" rdybsy_active"); 56152506Simp if (cfe->flags & PCCARD_CFE_WP_ACTIVE) 56252506Simp printf(" wp_active"); 56352506Simp if (cfe->flags & PCCARD_CFE_BVD_ACTIVE) 56452506Simp printf(" bvd_active"); 56552506Simp if (cfe->flags & PCCARD_CFE_IO8) 56652506Simp printf(" io8"); 56752506Simp if (cfe->flags & PCCARD_CFE_IO16) 56852506Simp printf(" io16"); 56952506Simp if (cfe->flags & PCCARD_CFE_IRQSHARE) 57052506Simp printf(" irqshare"); 57152506Simp if (cfe->flags & PCCARD_CFE_IRQPULSE) 57252506Simp printf(" irqpulse"); 57352506Simp if (cfe->flags & PCCARD_CFE_IRQLEVEL) 57452506Simp printf(" irqlevel"); 57552506Simp if (cfe->flags & PCCARD_CFE_POWERDOWN) 57652506Simp printf(" powerdown"); 57752506Simp if (cfe->flags & PCCARD_CFE_READONLY) 57852506Simp printf(" readonly"); 57952506Simp if (cfe->flags & PCCARD_CFE_AUDIO) 58052506Simp printf(" audio"); 58152506Simp 58252506Simp printf("\n"); 58352506Simp } 58452506Simp } 58552506Simp 58652506Simp if (card->error) 58752506Simp device_printf(dev, "%d errors found while parsing CIS\n", 58852506Simp card->error); 58952506Simp} 59052506Simp 59152506Simpint 59255720Simppccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg) 59352506Simp{ 59452506Simp /* most of these are educated guesses */ 59552506Simp static struct pccard_config_entry init_cfe = { 59652506Simp -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE | 59752506Simp PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY, 59852506Simp }; 59952506Simp 60052506Simp struct cis_state *state = arg; 60152506Simp 60252506Simp switch (tuple->code) { 60352506Simp case PCCARD_CISTPL_END: 60452506Simp /* if we've seen a LONGLINK_MFC, and this is the first 60552506Simp * END after it, reset the function list. 60652506Simp * 60752506Simp * XXX This might also be the right place to start a 60852506Simp * new function, but that assumes that a function 60952506Simp * definition never crosses any longlink, and I'm not 61052506Simp * sure about that. This is probably safe for MFC 61152506Simp * cards, but what we have now isn't broken, so I'd 61252506Simp * rather not change it. 61352506Simp */ 61452506Simp if (state->gotmfc == 1) { 61552506Simp struct pccard_function *pf, *pfnext; 61652506Simp 61752506Simp for (pf = STAILQ_FIRST(&state->card->pf_head); 61852506Simp pf != NULL; pf = pfnext) { 61952506Simp pfnext = STAILQ_NEXT(pf, pf_list); 62052506Simp free(pf, M_DEVBUF); 62152506Simp } 62252506Simp 62352506Simp STAILQ_INIT(&state->card->pf_head); 62452506Simp 62552506Simp state->count = 0; 62652506Simp state->gotmfc = 2; 62752506Simp state->pf = NULL; 62852506Simp } 62952506Simp break; 63052506Simp case PCCARD_CISTPL_LONGLINK_MFC: 63152506Simp /* 63252506Simp * this tuple's structure was dealt with in scan_cis. here, 63352506Simp * record the fact that the MFC tuple was seen, so that 63452506Simp * functions declared before the MFC link can be cleaned 63552506Simp * up. 63652506Simp */ 63752506Simp state->gotmfc = 1; 63852506Simp break; 63952506Simp#ifdef PCCARDCISDEBUG 64052506Simp case PCCARD_CISTPL_DEVICE: 64152506Simp case PCCARD_CISTPL_DEVICE_A: 64252506Simp { 64352506Simp u_int reg, dtype, dspeed; 64452506Simp 64552506Simp reg = pccard_tuple_read_1(tuple, 0); 64652506Simp dtype = reg & PCCARD_DTYPE_MASK; 64752506Simp dspeed = reg & PCCARD_DSPEED_MASK; 64852506Simp 64952506Simp DPRINTF(("CISTPL_DEVICE%s type=", 65052506Simp (tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A")); 65152506Simp switch (dtype) { 65252506Simp case PCCARD_DTYPE_NULL: 65352506Simp DPRINTF(("null")); 65452506Simp break; 65552506Simp case PCCARD_DTYPE_ROM: 65652506Simp DPRINTF(("rom")); 65752506Simp break; 65852506Simp case PCCARD_DTYPE_OTPROM: 65952506Simp DPRINTF(("otprom")); 66052506Simp break; 66152506Simp case PCCARD_DTYPE_EPROM: 66252506Simp DPRINTF(("eprom")); 66352506Simp break; 66452506Simp case PCCARD_DTYPE_EEPROM: 66552506Simp DPRINTF(("eeprom")); 66652506Simp break; 66752506Simp case PCCARD_DTYPE_FLASH: 66852506Simp DPRINTF(("flash")); 66952506Simp break; 67052506Simp case PCCARD_DTYPE_SRAM: 67152506Simp DPRINTF(("sram")); 67252506Simp break; 67352506Simp case PCCARD_DTYPE_DRAM: 67452506Simp DPRINTF(("dram")); 67552506Simp break; 67652506Simp case PCCARD_DTYPE_FUNCSPEC: 67752506Simp DPRINTF(("funcspec")); 67852506Simp break; 67952506Simp case PCCARD_DTYPE_EXTEND: 68052506Simp DPRINTF(("extend")); 68152506Simp break; 68252506Simp default: 68352506Simp DPRINTF(("reserved")); 68452506Simp break; 68552506Simp } 68652506Simp DPRINTF((" speed=")); 68752506Simp switch (dspeed) { 68852506Simp case PCCARD_DSPEED_NULL: 68952506Simp DPRINTF(("null")); 69052506Simp break; 69152506Simp case PCCARD_DSPEED_250NS: 69252506Simp DPRINTF(("250ns")); 69352506Simp break; 69452506Simp case PCCARD_DSPEED_200NS: 69552506Simp DPRINTF(("200ns")); 69652506Simp break; 69752506Simp case PCCARD_DSPEED_150NS: 69852506Simp DPRINTF(("150ns")); 69952506Simp break; 70052506Simp case PCCARD_DSPEED_100NS: 70152506Simp DPRINTF(("100ns")); 70252506Simp break; 70352506Simp case PCCARD_DSPEED_EXT: 70452506Simp DPRINTF(("ext")); 70552506Simp break; 70652506Simp default: 70752506Simp DPRINTF(("reserved")); 70852506Simp break; 70952506Simp } 71052506Simp } 71152506Simp DPRINTF(("\n")); 71252506Simp break; 71352506Simp#endif 71452506Simp case PCCARD_CISTPL_VERS_1: 71552506Simp if (tuple->length < 6) { 71652506Simp DPRINTF(("CISTPL_VERS_1 too short %d\n", 71752506Simp tuple->length)); 71852506Simp break; 71952506Simp } { 72052506Simp int start, i, ch, count; 72152506Simp 72252506Simp state->card->cis1_major = pccard_tuple_read_1(tuple, 0); 72352506Simp state->card->cis1_minor = pccard_tuple_read_1(tuple, 1); 72452506Simp 72552506Simp for (count = 0, start = 0, i = 0; 72652506Simp (count < 4) && ((i + 4) < 256); i++) { 72752506Simp ch = pccard_tuple_read_1(tuple, 2 + i); 72852506Simp if (ch == 0xff) 72952506Simp break; 73052506Simp state->card->cis1_info_buf[i] = ch; 73152506Simp if (ch == 0) { 73252506Simp state->card->cis1_info[count] = 73352506Simp state->card->cis1_info_buf + start; 73452506Simp start = i + 1; 73552506Simp count++; 73652506Simp } 73752506Simp } 73852506Simp DPRINTF(("CISTPL_VERS_1\n")); 73952506Simp } 74052506Simp break; 74152506Simp case PCCARD_CISTPL_MANFID: 74252506Simp if (tuple->length < 4) { 74352506Simp DPRINTF(("CISTPL_MANFID too short %d\n", 74452506Simp tuple->length)); 74552506Simp break; 74652506Simp } 74752506Simp state->card->manufacturer = pccard_tuple_read_2(tuple, 0); 74852506Simp state->card->product = pccard_tuple_read_2(tuple, 2); 74990964Sshiba /* 750104604Simp * This is for xe driver. But not limited to that driver. 75190964Sshiba * In PC Card Standard, 75290964Sshiba * Manufacturer ID: 2byte. 753104604Simp * Product ID: typically 2bytes, but there's no limit on its 754104604Simp * size. prodext is a two byte field, so maybe we should 755104604Simp * also handle the '6' case. So far no cards have surfaced 756104604Simp * with a length of '6'. 75790964Sshiba */ 75890964Sshiba if (tuple->length == 5 ) { 75990964Sshiba state->card->prodext = pccard_tuple_read_1(tuple, 4); 76090964Sshiba } 76152506Simp DPRINTF(("CISTPL_MANFID\n")); 76252506Simp break; 76352506Simp case PCCARD_CISTPL_FUNCID: 76452506Simp if (tuple->length < 1) { 76552506Simp DPRINTF(("CISTPL_FUNCID too short %d\n", 76652506Simp tuple->length)); 76752506Simp break; 76852506Simp } 76952506Simp if ((state->pf == NULL) || (state->gotmfc == 2)) { 77052506Simp state->pf = malloc(sizeof(*state->pf), M_DEVBUF, 77167897Sdwmalone M_NOWAIT | M_ZERO); 77252506Simp state->pf->number = state->count++; 77352506Simp state->pf->last_config_index = -1; 77452506Simp STAILQ_INIT(&state->pf->cfe_head); 77552506Simp 77652506Simp STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf, 77752506Simp pf_list); 77852506Simp } 77952506Simp state->pf->function = pccard_tuple_read_1(tuple, 0); 78052506Simp 78152506Simp DPRINTF(("CISTPL_FUNCID\n")); 78252506Simp break; 78382781Sshiba case PCCARD_CISTPL_FUNCE: 78482781Sshiba if (state->pf == NULL || state->pf->function <= 0) { 78582781Sshiba DPRINTF(("CISTPL_FUNCE is not followed by " 78682781Sshiba "valid CISTPL_FUNCID\n")); 78782781Sshiba break; 78882781Sshiba } 78982781Sshiba if (tuple->length >= 2) { 79082781Sshiba decode_funce(tuple, state->pf); 79182781Sshiba } 79282781Sshiba DPRINTF(("CISTPL_FUNCE\n")); 79382781Sshiba break; 79452506Simp case PCCARD_CISTPL_CONFIG: 79552506Simp if (tuple->length < 3) { 79652506Simp DPRINTF(("CISTPL_CONFIG too short %d\n", 79752506Simp tuple->length)); 79852506Simp break; 79952506Simp } { 80052506Simp u_int reg, rasz, rmsz, rfsz; 80152506Simp int i; 80252506Simp 80352506Simp reg = pccard_tuple_read_1(tuple, 0); 80452506Simp rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >> 80552506Simp PCCARD_TPCC_RASZ_SHIFT); 80652506Simp rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >> 80752506Simp PCCARD_TPCC_RMSZ_SHIFT); 80852506Simp rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >> 80952506Simp PCCARD_TPCC_RFSZ_SHIFT); 81052506Simp 81152506Simp if (tuple->length < (rasz + rmsz + rfsz)) { 81252506Simp DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too " 81352506Simp "short %d\n", rasz, rmsz, rfsz, 81452506Simp tuple->length)); 81552506Simp break; 81652506Simp } 81752506Simp if (state->pf == NULL) { 81852506Simp state->pf = malloc(sizeof(*state->pf), 81967897Sdwmalone M_DEVBUF, 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, 82552506Simp state->pf, pf_list); 82652506Simp 82752506Simp state->pf->function = PCCARD_FUNCTION_UNSPEC; 82852506Simp } 82952506Simp state->pf->last_config_index = 83052506Simp pccard_tuple_read_1(tuple, 1); 83152506Simp 83252506Simp state->pf->ccr_base = 0; 83352506Simp for (i = 0; i < rasz; i++) 83452506Simp state->pf->ccr_base |= 83552506Simp ((pccard_tuple_read_1(tuple, 2 + i)) << 83652506Simp (i * 8)); 83752506Simp 83852506Simp state->pf->ccr_mask = 0; 83952506Simp for (i = 0; i < rmsz; i++) 84052506Simp state->pf->ccr_mask |= 84152506Simp ((pccard_tuple_read_1(tuple, 84252506Simp 2 + rasz + i)) << (i * 8)); 84352506Simp 84452506Simp /* skip the reserved area and subtuples */ 84552506Simp 84652506Simp /* reset the default cfe for each cfe list */ 84752506Simp state->temp_cfe = init_cfe; 84852506Simp state->default_cfe = &state->temp_cfe; 84952506Simp } 85052506Simp DPRINTF(("CISTPL_CONFIG\n")); 85152506Simp break; 85252506Simp case PCCARD_CISTPL_CFTABLE_ENTRY: 85352506Simp { 85452506Simp int idx, i, j; 85552506Simp u_int reg, reg2; 85652506Simp u_int intface, def, num; 85752506Simp u_int power, timing, iospace, irq, memspace, misc; 85852506Simp struct pccard_config_entry *cfe; 85952506Simp 86052506Simp idx = 0; 86152506Simp 86252506Simp reg = pccard_tuple_read_1(tuple, idx); 86352506Simp idx++; 86452506Simp intface = reg & PCCARD_TPCE_INDX_INTFACE; 86552506Simp def = reg & PCCARD_TPCE_INDX_DEFAULT; 86652506Simp num = reg & PCCARD_TPCE_INDX_NUM_MASK; 86752506Simp 86852506Simp /* 86952506Simp * this is a little messy. Some cards have only a 87052506Simp * cfentry with the default bit set. So, as we go 87152506Simp * through the list, we add new indexes to the queue, 87252506Simp * and keep a pointer to the last one with the 87352506Simp * default bit set. if we see a record with the same 87452506Simp * index, as the default, we stash the default and 87552506Simp * replace the queue entry. otherwise, we just add 87652506Simp * new entries to the queue, pointing the default ptr 87752506Simp * at them if the default bit is set. if we get to 87852506Simp * the end with the default pointer pointing at a 87952506Simp * record which hasn't had a matching index, that's 88052506Simp * ok; it just becomes a cfentry like any other. 88152506Simp */ 88252506Simp 88352506Simp /* 88452506Simp * if the index in the cis differs from the default 88552506Simp * cis, create new entry in the queue and start it 88652506Simp * with the current default 88752506Simp */ 88852506Simp if (num != state->default_cfe->number) { 88952506Simp cfe = (struct pccard_config_entry *) 89052506Simp malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT); 89152506Simp 89252506Simp *cfe = *state->default_cfe; 89352506Simp 89452506Simp STAILQ_INSERT_TAIL(&state->pf->cfe_head, 89552506Simp cfe, cfe_list); 89652506Simp 89752506Simp cfe->number = num; 89852506Simp 89952506Simp /* 90052506Simp * if the default bit is set in the cis, then 90152506Simp * point the new default at whatever is being 90252506Simp * filled in 90352506Simp */ 90452506Simp if (def) 90552506Simp state->default_cfe = cfe; 90652506Simp } else { 90752506Simp /* 90852506Simp * the cis index matches the default index, 90952506Simp * fill in the default cfentry. It is 91052506Simp * assumed that the cfdefault index is in the 91152506Simp * queue. For it to be otherwise, the cis 91252506Simp * index would have to be -1 (initial 91352506Simp * condition) which is not possible, or there 91452506Simp * would have to be a preceding cis entry 91552506Simp * which had the same cis index and had the 91652506Simp * default bit unset. Neither condition 91752506Simp * should happen. If it does, this cfentry 91852506Simp * is lost (written into temp space), which 91952506Simp * is an acceptable failure mode. 92052506Simp */ 92152506Simp 92252506Simp cfe = state->default_cfe; 92352506Simp 92452506Simp /* 92552506Simp * if the cis entry does not have the default 92652506Simp * bit set, copy the default out of the way 92752506Simp * first. 92852506Simp */ 92952506Simp if (!def) { 93052506Simp state->temp_cfe = *state->default_cfe; 93152506Simp state->default_cfe = &state->temp_cfe; 93252506Simp } 93352506Simp } 93452506Simp 93552506Simp if (intface) { 93652506Simp reg = pccard_tuple_read_1(tuple, idx); 93752506Simp idx++; 938104640Simp cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED 939104640Simp | PCCARD_CFE_RDYBSY_ACTIVE 940104640Simp | PCCARD_CFE_WP_ACTIVE 941104640Simp | PCCARD_CFE_BVD_ACTIVE); 94252506Simp if (reg & PCCARD_TPCE_IF_MWAIT) 94352506Simp cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED; 94452506Simp if (reg & PCCARD_TPCE_IF_RDYBSY) 94552506Simp cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE; 94652506Simp if (reg & PCCARD_TPCE_IF_WP) 94752506Simp cfe->flags |= PCCARD_CFE_WP_ACTIVE; 94852506Simp if (reg & PCCARD_TPCE_IF_BVD) 94952506Simp cfe->flags |= PCCARD_CFE_BVD_ACTIVE; 95052506Simp cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE; 95152506Simp } 95252506Simp reg = pccard_tuple_read_1(tuple, idx); 95352506Simp idx++; 95452506Simp 95552506Simp power = reg & PCCARD_TPCE_FS_POWER_MASK; 95652506Simp timing = reg & PCCARD_TPCE_FS_TIMING; 95752506Simp iospace = reg & PCCARD_TPCE_FS_IOSPACE; 95852506Simp irq = reg & PCCARD_TPCE_FS_IRQ; 95952506Simp memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK; 96052506Simp misc = reg & PCCARD_TPCE_FS_MISC; 96152506Simp 96252506Simp if (power) { 96352506Simp /* skip over power, don't save */ 96452506Simp /* for each parameter selection byte */ 96552506Simp for (i = 0; i < power; i++) { 96652506Simp reg = pccard_tuple_read_1(tuple, idx); 96752506Simp idx++; 96852506Simp /* for each bit */ 96952506Simp for (j = 0; j < 7; j++) { 97052506Simp /* if the bit is set */ 97152506Simp if ((reg >> j) & 0x01) { 97252506Simp /* skip over bytes */ 97352506Simp do { 97452506Simp reg2 = pccard_tuple_read_1(tuple, idx); 97552506Simp idx++; 97652506Simp /* 97752506Simp * until 97852506Simp * non-extensi 97952506Simp * on byte 98052506Simp */ 98152506Simp } while (reg2 & 0x80); 98252506Simp } 98352506Simp } 98452506Simp } 98552506Simp } 98652506Simp if (timing) { 98752506Simp /* skip over timing, don't save */ 98852506Simp reg = pccard_tuple_read_1(tuple, idx); 98952506Simp idx++; 99052506Simp 99152506Simp if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) != 99252506Simp PCCARD_TPCE_TD_RESERVED_MASK) 99352506Simp idx++; 99452506Simp if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) != 99552506Simp PCCARD_TPCE_TD_RDYBSY_MASK) 99652506Simp idx++; 99752506Simp if ((reg & PCCARD_TPCE_TD_WAIT_MASK) != 99852506Simp PCCARD_TPCE_TD_WAIT_MASK) 99952506Simp idx++; 100052506Simp } 100152506Simp if (iospace) { 100252506Simp if (tuple->length <= idx) { 100352506Simp DPRINTF(("ran out of space before TCPE_IO\n")); 100452506Simp goto abort_cfe; 100552506Simp } 100652506Simp 100752506Simp reg = pccard_tuple_read_1(tuple, idx); 100852506Simp idx++; 1009104640Simp cfe->flags &= 1010104640Simp ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16); 101152506Simp if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT) 101252506Simp cfe->flags |= PCCARD_CFE_IO8; 101352506Simp if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT) 101452506Simp cfe->flags |= PCCARD_CFE_IO16; 101552506Simp cfe->iomask = 101652506Simp reg & PCCARD_TPCE_IO_IOADDRLINES_MASK; 101752506Simp 101852506Simp if (reg & PCCARD_TPCE_IO_HASRANGE) { 101952506Simp reg = pccard_tuple_read_1(tuple, idx); 102052506Simp idx++; 102152506Simp 102252506Simp cfe->num_iospace = 1 + (reg & 102352506Simp PCCARD_TPCE_IO_RANGE_COUNT); 102452506Simp 102552506Simp if (cfe->num_iospace > 102652506Simp (sizeof(cfe->iospace) / 102752506Simp sizeof(cfe->iospace[0]))) { 102852506Simp DPRINTF(("too many io " 102952506Simp "spaces %d", 103052506Simp cfe->num_iospace)); 103152506Simp state->card->error++; 103252506Simp break; 103352506Simp } 103452506Simp for (i = 0; i < cfe->num_iospace; i++) { 103552506Simp switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) { 103652506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE: 103752506Simp cfe->iospace[i].start = 103852506Simp pccard_tuple_read_1(tuple, idx); 103952506Simp idx++; 104052506Simp break; 104152506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO: 104252506Simp cfe->iospace[i].start = 104352506Simp pccard_tuple_read_2(tuple, idx); 104452506Simp idx += 2; 104552506Simp break; 104652506Simp case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR: 104752506Simp cfe->iospace[i].start = 104852506Simp pccard_tuple_read_4(tuple, idx); 104952506Simp idx += 4; 105052506Simp break; 105152506Simp } 105252506Simp switch (reg & 105352506Simp PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) { 105452506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE: 105552506Simp cfe->iospace[i].length = 105652506Simp pccard_tuple_read_1(tuple, idx); 105752506Simp idx++; 105852506Simp break; 105952506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO: 106052506Simp cfe->iospace[i].length = 106152506Simp pccard_tuple_read_2(tuple, idx); 106252506Simp idx += 2; 106352506Simp break; 106452506Simp case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR: 106552506Simp cfe->iospace[i].length = 106652506Simp pccard_tuple_read_4(tuple, idx); 106752506Simp idx += 4; 106852506Simp break; 106952506Simp } 107052506Simp cfe->iospace[i].length++; 107152506Simp } 107252506Simp } else { 107352506Simp cfe->num_iospace = 1; 107452506Simp cfe->iospace[0].start = 0; 107552506Simp cfe->iospace[0].length = 107652506Simp (1 << cfe->iomask); 107752506Simp } 107852506Simp } 107952506Simp if (irq) { 108052506Simp if (tuple->length <= idx) { 108152506Simp DPRINTF(("ran out of space before TCPE_IR\n")); 108252506Simp goto abort_cfe; 108352506Simp } 108452506Simp 108552506Simp reg = pccard_tuple_read_1(tuple, idx); 108652506Simp idx++; 1087104640Simp cfe->flags &= ~(PCCARD_CFE_IRQSHARE 1088104640Simp | PCCARD_CFE_IRQPULSE 1089104640Simp | PCCARD_CFE_IRQLEVEL); 109052506Simp if (reg & PCCARD_TPCE_IR_SHARE) 109152506Simp cfe->flags |= PCCARD_CFE_IRQSHARE; 109252506Simp if (reg & PCCARD_TPCE_IR_PULSE) 109352506Simp cfe->flags |= PCCARD_CFE_IRQPULSE; 109452506Simp if (reg & PCCARD_TPCE_IR_LEVEL) 109552506Simp cfe->flags |= PCCARD_CFE_IRQLEVEL; 109652506Simp 109752506Simp if (reg & PCCARD_TPCE_IR_HASMASK) { 109852506Simp /* 109952506Simp * it's legal to ignore the 110052506Simp * special-interrupt bits, so I will 110152506Simp */ 110252506Simp 110352506Simp cfe->irqmask = 110452506Simp pccard_tuple_read_2(tuple, idx); 110552506Simp idx += 2; 110652506Simp } else { 110752506Simp cfe->irqmask = 110852506Simp (1 << (reg & PCCARD_TPCE_IR_IRQ)); 110952506Simp } 111052506Simp } 111152506Simp if (memspace) { 111252506Simp if (tuple->length <= idx) { 111352506Simp DPRINTF(("ran out of space before TCPE_MS\n")); 111452506Simp goto abort_cfe; 111552506Simp } 111652506Simp 111752506Simp if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) { 111852506Simp cfe->num_memspace = 0; 111952506Simp } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) { 112052506Simp cfe->num_memspace = 1; 112152506Simp cfe->memspace[0].length = 256 * 112252506Simp pccard_tuple_read_2(tuple, idx); 112352506Simp idx += 2; 112452506Simp cfe->memspace[0].cardaddr = 0; 112552506Simp cfe->memspace[0].hostaddr = 0; 112652506Simp } else if (memspace == 112752506Simp PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) { 112852506Simp cfe->num_memspace = 1; 112952506Simp cfe->memspace[0].length = 256 * 113052506Simp pccard_tuple_read_2(tuple, idx); 113152506Simp idx += 2; 113252506Simp cfe->memspace[0].cardaddr = 256 * 113352506Simp pccard_tuple_read_2(tuple, idx); 113452506Simp idx += 2; 113552506Simp cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr; 113652506Simp } else { 113752506Simp int lengthsize; 113852506Simp int cardaddrsize; 113952506Simp int hostaddrsize; 114052506Simp 114152506Simp reg = pccard_tuple_read_1(tuple, idx); 114252506Simp idx++; 114352506Simp 114453873Simp cfe->num_memspace = (reg & 114553873Simp PCCARD_TPCE_MS_COUNT) + 1; 114652506Simp 114752506Simp if (cfe->num_memspace > 114852506Simp (sizeof(cfe->memspace) / 114952506Simp sizeof(cfe->memspace[0]))) { 115052506Simp DPRINTF(("too many mem " 115152506Simp "spaces %d", 115252506Simp cfe->num_memspace)); 115352506Simp state->card->error++; 115452506Simp break; 115552506Simp } 115652506Simp lengthsize = 115752506Simp ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >> 115852506Simp PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT); 115952506Simp cardaddrsize = 116052506Simp ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >> 116152506Simp PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT); 116252506Simp hostaddrsize = 116352506Simp (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0; 116452506Simp 116552506Simp if (lengthsize == 0) { 116652506Simp DPRINTF(("cfe memspace " 116752506Simp "lengthsize == 0")); 116852506Simp state->card->error++; 116952506Simp } 117052506Simp for (i = 0; i < cfe->num_memspace; i++) { 117152506Simp if (lengthsize) { 117252506Simp cfe->memspace[i].length = 117352506Simp 256 * pccard_tuple_read_n(tuple, lengthsize, 117452506Simp idx); 117552506Simp idx += lengthsize; 117652506Simp } else { 117752506Simp cfe->memspace[i].length = 0; 117852506Simp } 117952506Simp if (cfe->memspace[i].length == 0) { 118052506Simp DPRINTF(("cfe->memspace[%d].length == 0", 118152506Simp i)); 118252506Simp state->card->error++; 118352506Simp } 118452506Simp if (cardaddrsize) { 118552506Simp cfe->memspace[i].cardaddr = 118652506Simp 256 * pccard_tuple_read_n(tuple, cardaddrsize, 118752506Simp idx); 118852506Simp idx += cardaddrsize; 118952506Simp } else { 119052506Simp cfe->memspace[i].cardaddr = 0; 119152506Simp } 119252506Simp if (hostaddrsize) { 119352506Simp cfe->memspace[i].hostaddr = 119452506Simp 256 * pccard_tuple_read_n(tuple, hostaddrsize, 119552506Simp idx); 119652506Simp idx += hostaddrsize; 119752506Simp } else { 119852506Simp cfe->memspace[i].hostaddr = 0; 119952506Simp } 120052506Simp } 120152506Simp } 120252506Simp } 120352506Simp if (misc) { 120452506Simp if (tuple->length <= idx) { 120552506Simp DPRINTF(("ran out of space before TCPE_MI\n")); 120652506Simp goto abort_cfe; 120752506Simp } 120852506Simp 120952506Simp reg = pccard_tuple_read_1(tuple, idx); 121052506Simp idx++; 1211104640Simp cfe->flags &= ~(PCCARD_CFE_POWERDOWN 1212104640Simp | PCCARD_CFE_READONLY 1213104640Simp | PCCARD_CFE_AUDIO); 121452506Simp if (reg & PCCARD_TPCE_MI_PWRDOWN) 1215104640Simp cfe->flags |= PCCARD_CFE_POWERDOWN; 121652506Simp if (reg & PCCARD_TPCE_MI_READONLY) 1217104640Simp cfe->flags |= PCCARD_CFE_READONLY; 121852506Simp if (reg & PCCARD_TPCE_MI_AUDIO) 1219104640Simp cfe->flags |= PCCARD_CFE_AUDIO; 122052506Simp cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS; 122152506Simp 122252506Simp while (reg & PCCARD_TPCE_MI_EXT) { 122352506Simp reg = pccard_tuple_read_1(tuple, idx); 122452506Simp idx++; 122552506Simp } 122652506Simp } 122752506Simp /* skip all the subtuples */ 122852506Simp } 122952506Simp 123052506Simp abort_cfe: 123152506Simp DPRINTF(("CISTPL_CFTABLE_ENTRY\n")); 123252506Simp break; 123352506Simp default: 123452506Simp DPRINTF(("unhandled CISTPL %x\n", tuple->code)); 123552506Simp break; 123652506Simp } 123752506Simp 123852506Simp return (0); 123952506Simp} 124082781Sshiba 124182781Sshibastatic int 124282781Sshibadecode_funce(struct pccard_tuple *tuple, struct pccard_function *pf) 124382781Sshiba{ 124482781Sshiba int type = pccard_tuple_read_1(tuple, 0); 124582781Sshiba 124682781Sshiba switch (pf->function) { 124782781Sshiba case PCCARD_FUNCTION_DISK: 124882781Sshiba if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) { 124982781Sshiba pf->pf_funce_disk_interface 125082781Sshiba = pccard_tuple_read_1(tuple, 1); 125182781Sshiba } 125282781Sshiba break; 125382781Sshiba case PCCARD_FUNCTION_NETWORK: 125482781Sshiba if (type == PCCARD_TPLFE_TYPE_LAN_NID) { 125582781Sshiba int i; 125682781Sshiba int len = pccard_tuple_read_1(tuple, 1); 125782781Sshiba if (tuple->length < 2 + len || len > 8) { 125882781Sshiba /* tuple length not enough or nid too long */ 125982781Sshiba break; 126082781Sshiba } 126182781Sshiba for (i = 0; i < len; i++) { 126282781Sshiba pf->pf_funce_lan_nid[i] 126382781Sshiba = pccard_tuple_read_1(tuple, i + 2); 126482781Sshiba } 126582781Sshiba pf->pf_funce_lan_nidlen = len; 126682781Sshiba } 126782781Sshiba break; 126882781Sshiba default: 126982781Sshiba break; 127082781Sshiba } 127182781Sshiba return 0; 127282781Sshiba} 1273