123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380 |
- /* $OpenBSD: pcmcia_cis.c,v 1.20 2014/07/12 18:48:52 tedu Exp $ */
- /* $NetBSD: pcmcia_cis.c,v 1.9 1998/08/22 23:41:48 msaitoh Exp $ */
- /*
- * Copyright (c) 1997 Marc Horowitz. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Marc Horowitz.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/device.h>
- #include <sys/malloc.h>
- #include <dev/pcmcia/pcmciareg.h>
- #include <dev/pcmcia/pcmciachip.h>
- #include <dev/pcmcia/pcmciavar.h>
- #ifdef PCMCIACISDEBUG
- #define DPRINTF(arg) printf arg
- #else
- #define DPRINTF(arg)
- #endif
- #define PCMCIA_CIS_SIZE 1024
- struct cis_state {
- int count;
- int gotmfc;
- struct pcmcia_config_entry temp_cfe;
- struct pcmcia_config_entry *default_cfe;
- struct pcmcia_card *card;
- struct pcmcia_function *pf;
- };
- int pcmcia_parse_cis_tuple(struct pcmcia_tuple *, void *);
- uint8_t
- pcmcia_cis_read_1(struct pcmcia_tuple *tuple, bus_size_t idx)
- {
- if (tuple->flags & PTF_INDIRECT) {
- bus_space_write_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_CONTROL, PCMCIA_ICR_ATTR);
- idx <<= tuple->addrshift;
- bus_space_write_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 0, idx >> 0);
- bus_space_write_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 1, idx >> 8);
- bus_space_write_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 2, idx >> 16);
- bus_space_write_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 3, idx >> 24);
- return bus_space_read_1(tuple->memt, tuple->memh,
- tuple->indirect_ptr + PCMCIA_INDR_DATA);
- } else
- return bus_space_read_1(tuple->memt, tuple->memh,
- idx << tuple->addrshift);
- }
- void
- pcmcia_read_cis(sc)
- struct pcmcia_softc *sc;
- {
- struct cis_state state;
- memset(&state, 0, sizeof state);
- state.card = &sc->card;
- state.card->error = 0;
- state.card->cis1_major = -1;
- state.card->cis1_minor = -1;
- state.card->cis1_info[0] = NULL;
- state.card->cis1_info[1] = NULL;
- state.card->cis1_info[2] = NULL;
- state.card->cis1_info[3] = NULL;
- state.card->manufacturer = PCMCIA_VENDOR_INVALID;
- state.card->product = PCMCIA_PRODUCT_INVALID;
- SIMPLEQ_INIT(&state.card->pf_head);
- state.pf = NULL;
- if (pcmcia_scan_cis((struct device *)sc, pcmcia_parse_cis_tuple,
- &state) == -1)
- state.card->error++;
- }
- int
- pcmcia_scan_cis(dev, fct, arg)
- struct device *dev;
- int (*fct)(struct pcmcia_tuple *, void *);
- void *arg;
- {
- struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
- pcmcia_chipset_tag_t pct;
- pcmcia_chipset_handle_t pch;
- int window;
- struct pcmcia_mem_handle pcmh;
- struct pcmcia_tuple tuple;
- int indirect_present;
- int longlink_present;
- int longlink_common;
- u_long longlink_addr;
- int mfc_count;
- int mfc_index;
- struct {
- int common;
- u_long addr;
- } mfc[256 / 5];
- int ret;
- ret = 0;
- pct = sc->pct;
- pch = sc->pch;
- /* allocate some memory */
- if (pcmcia_chip_mem_alloc(pct, pch, PCMCIA_CIS_SIZE, &pcmh)) {
- #ifdef DIAGNOSTIC
- printf("%s: can't alloc memory to read attributes\n",
- sc->dev.dv_xname);
- #endif
- return -1;
- }
- /* initialize state for the primary tuple chain */
- if (pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_ATTR, 0,
- PCMCIA_CIS_SIZE, &pcmh, &tuple.ptr, &window)) {
- pcmcia_chip_mem_free(pct, pch, &pcmh);
- #ifdef DIAGNOSTIC
- printf("%s: can't map memory to read attributes\n",
- sc->dev.dv_xname);
- #endif
- return -1;
- }
- tuple.memt = pcmh.memt;
- tuple.memh = pcmh.memh;
- DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
- tuple.addrshift = 1;
- tuple.flags = 0;
- indirect_present = 0;
- longlink_present = 1;
- longlink_common = 1;
- longlink_addr = 0;
- mfc_count = 0;
- mfc_index = 0;
- DPRINTF(("%s: CIS tuple chain:\n", sc->dev.dv_xname));
- while (1) {
- while (1) {
- /*
- * Perform boundary check for insane cards.
- * If CIS is too long, simulate CIS end.
- * (This check may not be sufficient for
- * malicious cards.)
- */
- if ((tuple.ptr << tuple.addrshift) >=
- PCMCIA_CIS_SIZE - 1 - 32 /* ad hoc value */) {
- DPRINTF(("CISTPL_END (too long CIS)\n"));
- tuple.code = PCMCIA_CISTPL_END;
- goto cis_end;
- }
- /* get the tuple code */
- tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
- /* two special-case tuples */
- if (tuple.code == PCMCIA_CISTPL_NULL) {
- DPRINTF(("CISTPL_NONE\n 00\n"));
- tuple.ptr++;
- continue;
- } else if (tuple.code == PCMCIA_CISTPL_END) {
- DPRINTF(("CISTPL_END\n ff\n"));
- cis_end:
- /* Call the function for the END tuple, since
- the CIS semantics depend on it */
- if ((*fct) (&tuple, arg)) {
- pcmcia_chip_mem_unmap(pct, pch,
- window);
- ret = 1;
- goto done;
- }
- tuple.ptr++;
- break;
- }
- /* now all the normal tuples */
- tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
- switch (tuple.code) {
- case PCMCIA_CISTPL_INDIRECT:
- indirect_present = 1;
- DPRINTF(("CISTPL_INDIRECT\n"));
- break;
- case PCMCIA_CISTPL_LONGLINK_A:
- case PCMCIA_CISTPL_LONGLINK_C:
- if (tuple.length < 4) {
- DPRINTF(("CISTPL_LONGLINK_%s too "
- "short %d\n",
- longlink_common ? "C" : "A",
- tuple.length));
- break;
- }
- longlink_present = 1;
- longlink_common = (tuple.code ==
- PCMCIA_CISTPL_LONGLINK_C) ? 1 : 0;
- longlink_addr = pcmcia_tuple_read_4(&tuple, 0);
- DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
- longlink_common ? "C" : "A",
- longlink_addr));
- break;
- case PCMCIA_CISTPL_NO_LINK:
- longlink_present = 0;
- DPRINTF(("CISTPL_NO_LINK\n"));
- break;
- case PCMCIA_CISTPL_CHECKSUM:
- if (tuple.length < 5) {
- DPRINTF(("CISTPL_CHECKSUM too "
- "short %d\n", tuple.length));
- break;
- } {
- int16_t offset;
- u_long addr, length;
- u_int cksum, sum;
- int i;
- *((u_int16_t *) & offset) =
- pcmcia_tuple_read_2(&tuple, 0);
- length = pcmcia_tuple_read_2(&tuple, 2);
- cksum = pcmcia_tuple_read_1(&tuple, 4);
- addr = tuple.ptr + offset;
- DPRINTF(("CISTPL_CHECKSUM addr=%lx "
- "len=%lx cksum=%x",
- addr, length, cksum));
- /*
- * XXX do more work to deal with
- * distant regions
- */
- if ((addr >= PCMCIA_CIS_SIZE) ||
- ((addr + length) >=
- PCMCIA_CIS_SIZE)) {
- DPRINTF((" skipped, "
- "too distant\n"));
- break;
- }
- sum = 0;
- for (i = 0; i < length; i++)
- sum += pcmcia_cis_read_1(&tuple,
- addr + i);
- if (cksum != (sum & 0xff)) {
- DPRINTF((" failed sum=%x\n",
- sum));
- printf("%s: CIS checksum "
- "failed\n",
- sc->dev.dv_xname);
- #if 0
- /*
- * XXX Some working cards have
- * XXX bad checksums!!
- */
- ret = -1;
- #endif
- } else {
- DPRINTF((" ok\n"));
- }
- }
- break;
- case PCMCIA_CISTPL_LONGLINK_MFC:
- if (tuple.length < 6) {
- DPRINTF(("CISTPL_LONGLINK_MFC too "
- "short %d\n", tuple.length));
- break;
- }
- if (((tuple.length - 1) % 5) != 0) {
- DPRINTF(("CISTPL_LONGLINK_MFC bogus "
- "length %d\n", tuple.length));
- break;
- }
- {
- int i, tmp_count;
- /*
- * put count into tmp var so that
- * if we have to bail (because it's
- * a bogus count) it won't be
- * remembered for later use.
- */
- tmp_count =
- pcmcia_tuple_read_1(&tuple, 0);
- DPRINTF(("CISTPL_LONGLINK_MFC %d",
- tmp_count));
- /*
- * make _sure_ it's the right size;
- * if too short, it may be a weird
- * (unknown/undefined) format
- */
- if (tuple.length != (tmp_count*5 + 1)) {
- DPRINTF((" bogus length %d\n",
- tuple.length));
- break;
- }
- #ifdef PCMCIACISDEBUG /* maybe enable all the time? */
- /*
- * sanity check for a programming
- * error which is difficult to find
- * when debugging.
- */
- if (tmp_count >
- howmany(sizeof mfc, sizeof mfc[0]))
- panic("CISTPL_LONGLINK_MFC mfc "
- "count would blow stack");
- #endif
- mfc_count = tmp_count;
- for (i = 0; i < mfc_count; i++) {
- mfc[i].common =
- (pcmcia_tuple_read_1(&tuple,
- 1 + 5 * i) ==
- PCMCIA_MFC_MEM_COMMON) ?
- 1 : 0;
- mfc[i].addr =
- pcmcia_tuple_read_4(&tuple,
- 1 + 5 * i + 1);
- DPRINTF((" %s:%lx",
- mfc[i].common ? "common" :
- "attr", mfc[i].addr));
- }
- DPRINTF(("\n"));
- }
- /*
- * for LONGLINK_MFC, fall through to the
- * function. This tuple has structural and
- * semantic content.
- */
- default:
- {
- if ((*fct) (&tuple, arg)) {
- pcmcia_chip_mem_unmap(pct,
- pch, window);
- ret = 1;
- goto done;
- }
- }
- break;
- } /* switch */
- #ifdef PCMCIACISDEBUG
- /* print the tuple */
- {
- int i;
- DPRINTF((" %02x %02x", tuple.code,
- tuple.length));
- for (i = 0; i < tuple.length; i++) {
- DPRINTF((" %02x",
- pcmcia_tuple_read_1(&tuple, i)));
- if ((i % 16) == 13)
- DPRINTF(("\n"));
- }
- if ((i % 16) != 14)
- DPRINTF(("\n"));
- }
- #endif
- /* skip to the next tuple */
- tuple.ptr += 2 + tuple.length;
- }
- /*
- * the chain is done. Clean up and move onto the next one,
- * if any. The loop is here in the case that there is an MFC
- * card with no longlink (which defaults to existing, == 0).
- * In general, this means that if one pointer fails, it will
- * try the next one, instead of just bailing.
- */
- while (1) {
- pcmcia_chip_mem_unmap(pct, pch, window);
- if (indirect_present) {
- /*
- * Indirect CIS data needs to be obtained
- * from specific registers accessible at
- * a fixed location in the common window,
- * but otherwise is similar to longlink
- * in attribute memory.
- */
- pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_COMMON,
- 0, PCMCIA_INDR_SIZE,
- &pcmh, &tuple.indirect_ptr, &window);
- DPRINTF(("cis mem map %x ind %x\n",
- (unsigned int) tuple.memh,
- (unsigned int) tuple.indirect_ptr));
- tuple.addrshift = 1;
- tuple.flags |= PTF_INDIRECT;
- tuple.ptr = 0;
- longlink_present = 0;
- indirect_present = 0;
- } else if (longlink_present) {
- /*
- * if the longlink is to attribute memory,
- * then it is unindexed. That is, if the
- * link value is 0x100, then the actual
- * memory address is 0x200. This means that
- * we need to multiply by 2 before calling
- * mem_map, and then divide the resulting ptr
- * by 2 after.
- */
- if (!longlink_common)
- longlink_addr *= 2;
- pcmcia_chip_mem_map(pct, pch, longlink_common ?
- PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
- longlink_addr, PCMCIA_CIS_SIZE,
- &pcmh, &tuple.ptr, &window);
- if (!longlink_common)
- tuple.ptr /= 2;
- DPRINTF(("cis mem map %x\n",
- (unsigned int) tuple.memh));
- tuple.addrshift = longlink_common ? 0 : 1;
- longlink_present = 0;
- longlink_common = 1;
- longlink_addr = 0;
- } else if (mfc_count && (mfc_index < mfc_count)) {
- if (!mfc[mfc_index].common)
- mfc[mfc_index].addr *= 2;
- pcmcia_chip_mem_map(pct, pch,
- mfc[mfc_index].common ?
- PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
- mfc[mfc_index].addr, PCMCIA_CIS_SIZE,
- &pcmh, &tuple.ptr, &window);
- if (!mfc[mfc_index].common)
- tuple.ptr /= 2;
- DPRINTF(("cis mem map %x\n",
- (unsigned int) tuple.memh));
- /* set parse state, and point at the next one */
- tuple.addrshift = mfc[mfc_index].common ? 0 : 1;
- mfc_index++;
- } else {
- goto done;
- }
- /* make sure that the link is valid */
- tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
- if (tuple.code != PCMCIA_CISTPL_LINKTARGET) {
- DPRINTF(("CISTPL_LINKTARGET expected, "
- "code %02x observed\n", tuple.code));
- continue;
- }
- tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
- if (tuple.length < 3) {
- DPRINTF(("CISTPL_LINKTARGET too short %d\n",
- tuple.length));
- continue;
- }
- if ((pcmcia_tuple_read_1(&tuple, 0) != 'C') ||
- (pcmcia_tuple_read_1(&tuple, 1) != 'I') ||
- (pcmcia_tuple_read_1(&tuple, 2) != 'S')) {
- DPRINTF(("CISTPL_LINKTARGET magic "
- "%02x%02x%02x incorrect\n",
- pcmcia_tuple_read_1(&tuple, 0),
- pcmcia_tuple_read_1(&tuple, 1),
- pcmcia_tuple_read_1(&tuple, 2)));
- continue;
- }
- tuple.ptr += 2 + tuple.length;
- break;
- }
- }
- pcmcia_chip_mem_unmap(pct, pch, window);
- done:
- /* Last, free the allocated memory block */
- pcmcia_chip_mem_free(pct, pch, &pcmh);
- return (ret);
- }
- /* XXX this is incredibly verbose. Not sure what trt is */
- void
- pcmcia_print_cis(sc)
- struct pcmcia_softc *sc;
- {
- struct pcmcia_card *card = &sc->card;
- struct pcmcia_function *pf;
- struct pcmcia_config_entry *cfe;
- int i;
- printf("%s: CIS version ", sc->dev.dv_xname);
- if (card->cis1_major == 4) {
- if (card->cis1_minor == 0)
- printf("PCMCIA 1.0\n");
- else if (card->cis1_minor == 1)
- printf("PCMCIA 2.0 or 2.1\n");
- } else if (card->cis1_major >= 5)
- printf("PC Card Standard %d.%d\n", card->cis1_major,
- card->cis1_minor);
- else
- printf("unknown (major=%d, minor=%d)\n",
- card->cis1_major, card->cis1_minor);
- printf("%s: CIS info: ", sc->dev.dv_xname);
- for (i = 0; i < 4; i++) {
- if (card->cis1_info[i] == NULL)
- break;
- if (i)
- printf(", ");
- printf("%s", card->cis1_info[i]);
- }
- printf("\n");
- printf("%s: Manufacturer code 0x%x, product 0x%x\n",
- sc->dev.dv_xname, card->manufacturer, card->product);
- SIMPLEQ_FOREACH(pf, &card->pf_head, pf_list) {
- printf("%s: function %d: ", sc->dev.dv_xname, pf->number);
- switch (pf->function) {
- case PCMCIA_FUNCTION_UNSPEC:
- printf("unspecified");
- break;
- case PCMCIA_FUNCTION_MULTIFUNCTION:
- printf("multi-function");
- break;
- case PCMCIA_FUNCTION_MEMORY:
- printf("memory");
- break;
- case PCMCIA_FUNCTION_SERIAL:
- printf("serial port");
- break;
- case PCMCIA_FUNCTION_PARALLEL:
- printf("parallel port");
- break;
- case PCMCIA_FUNCTION_DISK:
- printf("fixed disk");
- break;
- case PCMCIA_FUNCTION_VIDEO:
- printf("video adapter");
- break;
- case PCMCIA_FUNCTION_NETWORK:
- printf("network adapter");
- break;
- case PCMCIA_FUNCTION_AIMS:
- printf("auto incrementing mass storage");
- break;
- case PCMCIA_FUNCTION_SCSI:
- printf("SCSI bridge");
- break;
- case PCMCIA_FUNCTION_SECURITY:
- printf("Security services");
- break;
- case PCMCIA_FUNCTION_INSTRUMENT:
- printf("Instrument");
- break;
- case PCMCIA_FUNCTION_IOBUS:
- printf("Serial I/O Bus Adapter");
- break;
- default:
- printf("unknown (%d)", pf->function);
- break;
- }
- printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
- SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
- printf("%s: function %d, config table entry %d: ",
- sc->dev.dv_xname, pf->number, cfe->number);
- switch (cfe->iftype) {
- case PCMCIA_IFTYPE_MEMORY:
- printf("memory card");
- break;
- case PCMCIA_IFTYPE_IO:
- printf("I/O card");
- break;
- default:
- printf("card type unknown");
- break;
- }
- printf("; irq mask %x", cfe->irqmask);
- if (cfe->num_iospace) {
- printf("; iomask %lx, iospace", cfe->iomask);
- for (i = 0; i < cfe->num_iospace; i++)
- printf(" %lx%s%lx",
- cfe->iospace[i].start,
- cfe->iospace[i].length ? "-" : "",
- cfe->iospace[i].start +
- cfe->iospace[i].length - 1);
- }
- if (cfe->num_memspace) {
- printf("; memspace");
- for (i = 0; i < cfe->num_memspace; i++)
- printf(" %lx%s%lx%s%lx",
- cfe->memspace[i].cardaddr,
- cfe->memspace[i].length ? "-" : "",
- cfe->memspace[i].cardaddr +
- cfe->memspace[i].length - 1,
- cfe->memspace[i].hostaddr ?
- "@" : "",
- cfe->memspace[i].hostaddr);
- }
- if (cfe->maxtwins)
- printf("; maxtwins %d", cfe->maxtwins);
- printf(";");
- if (cfe->flags & PCMCIA_CFE_MWAIT_REQUIRED)
- printf(" mwait_required");
- if (cfe->flags & PCMCIA_CFE_RDYBSY_ACTIVE)
- printf(" rdybsy_active");
- if (cfe->flags & PCMCIA_CFE_WP_ACTIVE)
- printf(" wp_active");
- if (cfe->flags & PCMCIA_CFE_BVD_ACTIVE)
- printf(" bvd_active");
- if (cfe->flags & PCMCIA_CFE_IO8)
- printf(" io8");
- if (cfe->flags & PCMCIA_CFE_IO16)
- printf(" io16");
- if (cfe->flags & PCMCIA_CFE_IRQSHARE)
- printf(" irqshare");
- if (cfe->flags & PCMCIA_CFE_IRQPULSE)
- printf(" irqpulse");
- if (cfe->flags & PCMCIA_CFE_IRQLEVEL)
- printf(" irqlevel");
- if (cfe->flags & PCMCIA_CFE_POWERDOWN)
- printf(" powerdown");
- if (cfe->flags & PCMCIA_CFE_READONLY)
- printf(" readonly");
- if (cfe->flags & PCMCIA_CFE_AUDIO)
- printf(" audio");
- printf("\n");
- }
- }
- if (card->error)
- printf("%s: %d errors found while parsing CIS\n",
- sc->dev.dv_xname, card->error);
- }
- int
- pcmcia_parse_cis_tuple(tuple, arg)
- struct pcmcia_tuple *tuple;
- void *arg;
- {
- /* most of these are educated guesses */
- static struct pcmcia_config_entry init_cfe = {
- -1, PCMCIA_CFE_RDYBSY_ACTIVE | PCMCIA_CFE_WP_ACTIVE |
- PCMCIA_CFE_BVD_ACTIVE, PCMCIA_IFTYPE_MEMORY,
- };
- struct cis_state *state = arg;
- switch (tuple->code) {
- case PCMCIA_CISTPL_END:
- /*
- * If we've seen a LONGLINK_MFC, and this is the first
- * END after it, reset the function list.
- *
- * XXX This might also be the right place to start a
- * new function, but that assumes that a function
- * definition never crosses any longlink, and I'm not
- * sure about that. This is probably safe for MFC
- * cards, but what we have now isn't broken, so I'd
- * rather not change it.
- */
- if (state->gotmfc == 1) {
- struct pcmcia_function *pf, *pfnext;
- for (pf = SIMPLEQ_FIRST(&state->card->pf_head);
- pf != NULL; pf = pfnext) {
- pfnext = SIMPLEQ_NEXT(pf, pf_list);
- free(pf, M_DEVBUF, 0);
- }
- SIMPLEQ_INIT(&state->card->pf_head);
- state->count = 0;
- state->gotmfc = 2;
- state->pf = NULL;
- }
- break;
- case PCMCIA_CISTPL_LONGLINK_MFC:
- /*
- * This tuple's structure was dealt with in scan_cis. here,
- * record the fact that the MFC tuple was seen, so that
- * functions declared before the MFC link can be cleaned
- * up.
- */
- state->gotmfc = 1;
- break;
- #ifdef PCMCIACISDEBUG
- case PCMCIA_CISTPL_DEVICE:
- case PCMCIA_CISTPL_DEVICE_A:
- {
- u_int reg, dtype, dspeed;
- reg = pcmcia_tuple_read_1(tuple, 0);
- dtype = reg & PCMCIA_DTYPE_MASK;
- dspeed = reg & PCMCIA_DSPEED_MASK;
- DPRINTF(("CISTPL_DEVICE%s type=",
- (tuple->code == PCMCIA_CISTPL_DEVICE) ? "" : "_A"));
- switch (dtype) {
- case PCMCIA_DTYPE_NULL:
- DPRINTF(("null"));
- break;
- case PCMCIA_DTYPE_ROM:
- DPRINTF(("rom"));
- break;
- case PCMCIA_DTYPE_OTPROM:
- DPRINTF(("otprom"));
- break;
- case PCMCIA_DTYPE_EPROM:
- DPRINTF(("eprom"));
- break;
- case PCMCIA_DTYPE_EEPROM:
- DPRINTF(("eeprom"));
- break;
- case PCMCIA_DTYPE_FLASH:
- DPRINTF(("flash"));
- break;
- case PCMCIA_DTYPE_SRAM:
- DPRINTF(("sram"));
- break;
- case PCMCIA_DTYPE_DRAM:
- DPRINTF(("dram"));
- break;
- case PCMCIA_DTYPE_FUNCSPEC:
- DPRINTF(("funcspec"));
- break;
- case PCMCIA_DTYPE_EXTEND:
- DPRINTF(("extend"));
- break;
- default:
- DPRINTF(("reserved"));
- break;
- }
- DPRINTF((" speed="));
- switch (dspeed) {
- case PCMCIA_DSPEED_NULL:
- DPRINTF(("null"));
- break;
- case PCMCIA_DSPEED_250NS:
- DPRINTF(("250ns"));
- break;
- case PCMCIA_DSPEED_200NS:
- DPRINTF(("200ns"));
- break;
- case PCMCIA_DSPEED_150NS:
- DPRINTF(("150ns"));
- break;
- case PCMCIA_DSPEED_100NS:
- DPRINTF(("100ns"));
- break;
- case PCMCIA_DSPEED_EXT:
- DPRINTF(("ext"));
- break;
- default:
- DPRINTF(("reserved"));
- break;
- }
- }
- DPRINTF(("\n"));
- break;
- #endif
- case PCMCIA_CISTPL_VERS_1:
- if (tuple->length < 6) {
- DPRINTF(("CISTPL_VERS_1 too short %d\n",
- tuple->length));
- break;
- } {
- int start, i, ch, count;
- state->card->cis1_major = pcmcia_tuple_read_1(tuple, 0);
- state->card->cis1_minor = pcmcia_tuple_read_1(tuple, 1);
- for (count = 0, start = 0, i = 0;
- (count < 4) && ((i + 4) < 256); i++) {
- ch = pcmcia_tuple_read_1(tuple, 2 + i);
- if (ch == 0xff)
- break;
- state->card->cis1_info_buf[i] = ch;
- if (ch == 0) {
- state->card->cis1_info[count] =
- state->card->cis1_info_buf + start;
- start = i + 1;
- count++;
- }
- }
- DPRINTF(("CISTPL_VERS_1\n"));
- }
- break;
- case PCMCIA_CISTPL_MANFID:
- if (tuple->length < 4) {
- DPRINTF(("CISTPL_MANFID too short %d\n",
- tuple->length));
- break;
- }
- state->card->manufacturer = pcmcia_tuple_read_2(tuple, 0);
- state->card->product = pcmcia_tuple_read_2(tuple, 2);
- DPRINTF(("CISTPL_MANFID\n"));
- break;
- case PCMCIA_CISTPL_FUNCID:
- if (tuple->length < 2) {
- DPRINTF(("CISTPL_FUNCID too short %d\n",
- tuple->length));
- break;
- }
- /*
- * As far as I understand this, manufacturers do multifunction
- * cards in various ways. Sadly enough I do not have the
- * PC-Card standard (donate!) so I can only guess what can
- * be done.
- * The original code implies FUNCID nodes are above CONFIG
- * nodes in the CIS tree, however Xircom does it the other
- * way round, which of course makes things a bit hard.
- * --niklas@openbsd.org
- */
- if (state->pf) {
- if (state->pf->function == PCMCIA_FUNCTION_UNSPEC) {
- /*
- * This looks like a opportunistic function
- * created by a CONFIG tuple. Just keep it.
- */
- } else {
- /*
- * A function is being defined, end it.
- */
- state->pf = NULL;
- }
- }
- if (state->pf == NULL) {
- state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (state->pf == NULL)
- panic("pcmcia_parse_cis_tuple");
- state->pf->number = state->count++;
- state->pf->last_config_index = -1;
- SIMPLEQ_INIT(&state->pf->cfe_head);
- SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf,
- pf_list);
- }
- state->pf->function = pcmcia_tuple_read_1(tuple, 0);
- DPRINTF(("CISTPL_FUNCID\n"));
- break;
- case PCMCIA_CISTPL_CONFIG:
- if (tuple->length < 3) {
- DPRINTF(("CISTPL_CONFIG too short %d\n",
- tuple->length));
- break;
- } {
- u_int reg, rasz, rmsz, rfsz;
- int i;
- reg = pcmcia_tuple_read_1(tuple, 0);
- rasz = 1 + ((reg & PCMCIA_TPCC_RASZ_MASK) >>
- PCMCIA_TPCC_RASZ_SHIFT);
- rmsz = 1 + ((reg & PCMCIA_TPCC_RMSZ_MASK) >>
- PCMCIA_TPCC_RMSZ_SHIFT);
- rfsz = ((reg & PCMCIA_TPCC_RFSZ_MASK) >>
- PCMCIA_TPCC_RFSZ_SHIFT);
- if (tuple->length < 2 + rasz + rmsz + rfsz) {
- DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
- "short %d\n", rasz, rmsz, rfsz,
- tuple->length));
- break;
- }
- if (state->pf == NULL) {
- state->pf = malloc(sizeof(*state->pf),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (state->pf == NULL)
- panic("pcmcia_parse_cis_tuple");
- state->pf->number = state->count++;
- state->pf->last_config_index = -1;
- SIMPLEQ_INIT(&state->pf->cfe_head);
- SIMPLEQ_INSERT_TAIL(&state->card->pf_head,
- state->pf, pf_list);
- state->pf->function = PCMCIA_FUNCTION_UNSPEC;
- }
- state->pf->last_config_index =
- pcmcia_tuple_read_1(tuple, 1);
- state->pf->ccr_base = 0;
- for (i = 0; i < rasz; i++)
- state->pf->ccr_base |=
- ((pcmcia_tuple_read_1(tuple, 2 + i)) <<
- (i * 8));
- state->pf->ccr_mask = 0;
- for (i = 0; i < rmsz; i++)
- state->pf->ccr_mask |=
- ((pcmcia_tuple_read_1(tuple,
- 2 + rasz + i)) << (i * 8));
- /* skip the reserved area and subtuples */
- /* reset the default cfe for each cfe list */
- state->temp_cfe = init_cfe;
- state->default_cfe = &state->temp_cfe;
- }
- DPRINTF(("CISTPL_CONFIG\n"));
- break;
- case PCMCIA_CISTPL_CFTABLE_ENTRY:
- if (tuple->length < 2) {
- DPRINTF(("CISTPL_CFTABLE_ENTRY too short %d\n",
- tuple->length));
- break;
- } {
- int idx, i, j;
- u_int reg, reg2;
- u_int intface, def, num;
- u_int power, timing, iospace, irq, memspace, misc;
- struct pcmcia_config_entry *cfe;
- idx = 0;
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- intface = reg & PCMCIA_TPCE_INDX_INTFACE;
- def = reg & PCMCIA_TPCE_INDX_DEFAULT;
- num = reg & PCMCIA_TPCE_INDX_NUM_MASK;
- /*
- * this is a little messy. Some cards have only a
- * cfentry with the default bit set. So, as we go
- * through the list, we add new indexes to the queue,
- * and keep a pointer to the last one with the
- * default bit set. if we see a record with the same
- * index, as the default, we stash the default and
- * replace the queue entry. otherwise, we just add
- * new entries to the queue, pointing the default ptr
- * at them if the default bit is set. if we get to
- * the end with the default pointer pointing at a
- * record which hasn't had a matching index, that's
- * ok; it just becomes a cfentry like any other.
- */
- /*
- * if the index in the cis differs from the default
- * cis, create new entry in the queue and start it
- * with the current default
- */
- if (state->default_cfe == NULL) {
- DPRINTF(("CISTPL_CFTABLE_ENTRY with no "
- "default\n"));
- break;
- }
- if (num != state->default_cfe->number) {
- cfe = (struct pcmcia_config_entry *)
- malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
- if (cfe == NULL)
- panic("pcmcia_parse_cis_tuple");
- *cfe = *state->default_cfe;
- SIMPLEQ_INSERT_TAIL(&state->pf->cfe_head,
- cfe, cfe_list);
- cfe->number = num;
- /*
- * if the default bit is set in the cis, then
- * point the new default at whatever is being
- * filled in
- */
- if (def)
- state->default_cfe = cfe;
- } else {
- /*
- * the cis index matches the default index,
- * fill in the default cfentry. It is
- * assumed that the cfdefault index is in the
- * queue. For it to be otherwise, the cis
- * index would have to be -1 (initial
- * condition) which is not possible, or there
- * would have to be a preceding cis entry
- * which had the same cis index and had the
- * default bit unset. Neither condition
- * should happen. If it does, this cfentry
- * is lost (written into temp space), which
- * is an acceptable failure mode.
- */
- cfe = state->default_cfe;
- /*
- * if the cis entry does not have the default
- * bit set, copy the default out of the way
- * first.
- */
- if (!def) {
- state->temp_cfe = *state->default_cfe;
- state->default_cfe = &state->temp_cfe;
- }
- }
- if (intface) {
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->flags &= ~(PCMCIA_CFE_MWAIT_REQUIRED
- | PCMCIA_CFE_RDYBSY_ACTIVE
- | PCMCIA_CFE_WP_ACTIVE
- | PCMCIA_CFE_BVD_ACTIVE);
- if (reg & PCMCIA_TPCE_IF_MWAIT)
- cfe->flags |= PCMCIA_CFE_MWAIT_REQUIRED;
- if (reg & PCMCIA_TPCE_IF_RDYBSY)
- cfe->flags |= PCMCIA_CFE_RDYBSY_ACTIVE;
- if (reg & PCMCIA_TPCE_IF_WP)
- cfe->flags |= PCMCIA_CFE_WP_ACTIVE;
- if (reg & PCMCIA_TPCE_IF_BVD)
- cfe->flags |= PCMCIA_CFE_BVD_ACTIVE;
- cfe->iftype = reg & PCMCIA_TPCE_IF_IFTYPE;
- }
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- power = reg & PCMCIA_TPCE_FS_POWER_MASK;
- timing = reg & PCMCIA_TPCE_FS_TIMING;
- iospace = reg & PCMCIA_TPCE_FS_IOSPACE;
- irq = reg & PCMCIA_TPCE_FS_IRQ;
- memspace = reg & PCMCIA_TPCE_FS_MEMSPACE_MASK;
- misc = reg & PCMCIA_TPCE_FS_MISC;
- if (power) {
- /* skip over power, don't save */
- /* for each parameter selection byte */
- for (i = 0; i < power; i++) {
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- /* for each bit */
- for (j = 0; j < 7; j++) {
- /* if the bit is set */
- if ((reg >> j) & 0x01) {
- /* skip over bytes */
- do {
- reg2 = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- /*
- * until
- * non-
- * extension
- * byte
- */
- } while (reg2 & 0x80);
- }
- }
- }
- }
- if (timing) {
- /* skip over timing, don't save */
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- if ((reg & PCMCIA_TPCE_TD_RESERVED_MASK) !=
- PCMCIA_TPCE_TD_RESERVED_MASK)
- idx++;
- if ((reg & PCMCIA_TPCE_TD_RDYBSY_MASK) !=
- PCMCIA_TPCE_TD_RDYBSY_MASK)
- idx++;
- if ((reg & PCMCIA_TPCE_TD_WAIT_MASK) !=
- PCMCIA_TPCE_TD_WAIT_MASK)
- idx++;
- }
- if (iospace) {
- if (tuple->length <= idx) {
- DPRINTF(("ran out of space before TPCE_IO\n"));
- goto abort_cfe;
- }
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->flags &=
- ~(PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16);
- if (reg & PCMCIA_TPCE_IO_BUSWIDTH_8BIT)
- cfe->flags |= PCMCIA_CFE_IO8;
- if (reg & PCMCIA_TPCE_IO_BUSWIDTH_16BIT)
- cfe->flags |= PCMCIA_CFE_IO16;
- cfe->iomask =
- reg & PCMCIA_TPCE_IO_IOADDRLINES_MASK;
- if (reg & PCMCIA_TPCE_IO_HASRANGE) {
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->num_iospace = 1 + (reg &
- PCMCIA_TPCE_IO_RANGE_COUNT);
- if (cfe->num_iospace >
- (sizeof(cfe->iospace) /
- sizeof(cfe->iospace[0]))) {
- DPRINTF(("too many io "
- "spaces %d",
- cfe->num_iospace));
- state->card->error++;
- break;
- }
- for (i = 0; i < cfe->num_iospace; i++) {
- switch (reg & PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK) {
- case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE:
- cfe->iospace[i].start =
- pcmcia_tuple_read_1(tuple, idx);
- idx++;
- break;
- case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO:
- cfe->iospace[i].start =
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- break;
- case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR:
- cfe->iospace[i].start =
- pcmcia_tuple_read_4(tuple, idx);
- idx += 4;
- break;
- }
- switch (reg &
- PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
- case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE:
- cfe->iospace[i].length =
- pcmcia_tuple_read_1(tuple, idx);
- idx++;
- break;
- case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO:
- cfe->iospace[i].length =
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- break;
- case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
- cfe->iospace[i].length =
- pcmcia_tuple_read_4(tuple, idx);
- idx += 4;
- break;
- }
- cfe->iospace[i].length++;
- }
- } else {
- cfe->num_iospace = 1;
- cfe->iospace[0].start = 0;
- cfe->iospace[0].length =
- (1 << cfe->iomask);
- }
- }
- if (irq) {
- if (tuple->length <= idx) {
- DPRINTF(("ran out of space before TPCE_IR\n"));
- goto abort_cfe;
- }
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->flags &= ~(PCMCIA_CFE_IRQSHARE
- | PCMCIA_CFE_IRQPULSE
- | PCMCIA_CFE_IRQLEVEL);
- if (reg & PCMCIA_TPCE_IR_SHARE)
- cfe->flags |= PCMCIA_CFE_IRQSHARE;
- if (reg & PCMCIA_TPCE_IR_PULSE)
- cfe->flags |= PCMCIA_CFE_IRQPULSE;
- if (reg & PCMCIA_TPCE_IR_LEVEL)
- cfe->flags |= PCMCIA_CFE_IRQLEVEL;
- if (reg & PCMCIA_TPCE_IR_HASMASK) {
- /*
- * it's legal to ignore the
- * special-interrupt bits, so I will
- */
- cfe->irqmask =
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- } else {
- cfe->irqmask =
- (1 << (reg & PCMCIA_TPCE_IR_IRQ));
- }
- }
- if (memspace) {
- if (tuple->length <= idx) {
- DPRINTF(("ran out of space before TPCE_MS\n"));
- goto abort_cfe;
- }
- if (memspace == PCMCIA_TPCE_FS_MEMSPACE_NONE) {
- cfe->num_memspace = 0;
- } else if (memspace == PCMCIA_TPCE_FS_MEMSPACE_LENGTH) {
- cfe->num_memspace = 1;
- cfe->memspace[0].length = 256 *
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- cfe->memspace[0].cardaddr = 0;
- cfe->memspace[0].hostaddr = 0;
- } else if (memspace ==
- PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR) {
- cfe->num_memspace = 1;
- cfe->memspace[0].length = 256 *
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- cfe->memspace[0].cardaddr = 256 *
- pcmcia_tuple_read_2(tuple, idx);
- idx += 2;
- cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
- } else {
- int lengthsize;
- int cardaddrsize;
- int hostaddrsize;
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->num_memspace = (reg &
- PCMCIA_TPCE_MS_COUNT) + 1;
- if (cfe->num_memspace >
- (sizeof(cfe->memspace) /
- sizeof(cfe->memspace[0]))) {
- DPRINTF(("too many mem "
- "spaces %d",
- cfe->num_memspace));
- state->card->error++;
- break;
- }
- lengthsize =
- ((reg & PCMCIA_TPCE_MS_LENGTH_SIZE_MASK) >>
- PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT);
- cardaddrsize =
- ((reg & PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK) >>
- PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT);
- hostaddrsize =
- (reg & PCMCIA_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
- if (lengthsize == 0) {
- DPRINTF(("cfe memspace "
- "lengthsize == 0"));
- state->card->error++;
- }
- for (i = 0; i < cfe->num_memspace; i++) {
- if (lengthsize) {
- cfe->memspace[i].length =
- 256 * pcmcia_tuple_read_n(tuple, lengthsize,
- idx);
- idx += lengthsize;
- } else {
- cfe->memspace[i].length = 0;
- }
- if (cfe->memspace[i].length == 0) {
- DPRINTF(("cfe->memspace[%d].length == 0",
- i));
- state->card->error++;
- }
- if (cardaddrsize) {
- cfe->memspace[i].cardaddr =
- 256 * pcmcia_tuple_read_n(tuple, cardaddrsize,
- idx);
- idx += cardaddrsize;
- } else {
- cfe->memspace[i].cardaddr = 0;
- }
- if (hostaddrsize) {
- cfe->memspace[i].hostaddr =
- 256 * pcmcia_tuple_read_n(tuple, hostaddrsize,
- idx);
- idx += hostaddrsize;
- } else {
- cfe->memspace[i].hostaddr = 0;
- }
- }
- }
- }
- if (misc) {
- if (tuple->length <= idx) {
- DPRINTF(("ran out of space before TPCE_MI\n"));
- goto abort_cfe;
- }
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- cfe->flags &= ~(PCMCIA_CFE_POWERDOWN
- | PCMCIA_CFE_READONLY
- | PCMCIA_CFE_AUDIO);
- if (reg & PCMCIA_TPCE_MI_PWRDOWN)
- cfe->flags |= PCMCIA_CFE_POWERDOWN;
- if (reg & PCMCIA_TPCE_MI_READONLY)
- cfe->flags |= PCMCIA_CFE_READONLY;
- if (reg & PCMCIA_TPCE_MI_AUDIO)
- cfe->flags |= PCMCIA_CFE_AUDIO;
- cfe->maxtwins = reg & PCMCIA_TPCE_MI_MAXTWINS;
- while (reg & PCMCIA_TPCE_MI_EXT) {
- reg = pcmcia_tuple_read_1(tuple, idx);
- idx++;
- }
- }
- /* skip all the subtuples */
- }
- abort_cfe:
- DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
- break;
- default:
- DPRINTF(("unhandled CISTPL %x\n", tuple->code));
- break;
- }
- return (0);
- }
|