/* $OpenBSD: read_conf.c,v 1.2 1996/06/23 14:30:03 deraadt Exp $ */ /* * Copyright (c) 1993, 1994 Stefan Grefen. 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 dipclaimer. * 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 Stefan Grefen. * 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. */ /* With 'help' of Barry Jaspan's code */ #include #include #include #include #include #include #include #include #include read_conf(u_char *buf, int blen,int cfidx,struct pcmcia_conf *pc_cf) { u_char code, len,*tbuf,*endp=buf+blen; int done; done = 0; while (!done && buf> TPCC_RASZ_SHIFT; rmsz = (tbuf[i] & TPCC_RMSZ) >> TPCC_RMSZ_SHIFT; i+=2; pc_cf->cfg_off = 0; switch (rasz) { case 3: pc_cf->cfg_off |= (tbuf[i+3] << 24); case 2: pc_cf->cfg_off |= (tbuf[i+2] << 16); case 1: pc_cf->cfg_off |= (tbuf[i+1] << 8); case 0: pc_cf->cfg_off |= tbuf[i]; } i+=rasz; pc_cf->cfg_regmask = 0; switch (rmsz) { default: case 3: pc_cf->cfg_regmask |= (tbuf[i+3] << 24); case 2: pc_cf->cfg_regmask |= (tbuf[i+2] << 16); case 1: pc_cf->cfg_regmask |= (tbuf[i+1] << 8); case 0: pc_cf->cfg_regmask |= tbuf[i]; } } parse_cfent(u_char *tbuf, int len,int slotid, struct pcmcia_conf *pc_cf) { int i, idx,defp,iop,io_16,ios,ftrs,intface,k; int host_addr_p, addr_size, len_size; i = 0; intface = (tbuf[i] & TPCE_INDX_INT); idx = (tbuf[i] & TPCE_INDX_ENTRY); defp = (tbuf[i] & TPCE_INDX_DEF); printf("%x %x\n",idx,slotid); if((idx==slotid) ||(defp && slotid==-1)) { int j; printf("** %x %x\n",idx,slotid); if (intface) { i++; pc_cf->iocard=(tbuf[i] & TPCE_IF_TYPE)==1; } i++; ftrs = tbuf[i++]; for (j = 0; j < (ftrs & TPCE_FS_PWR); j++) { int pwr_desc = tbuf[i++]; /* for each struct, skip all parameter defns */ for (k = 0; k < 8; pwr_desc >>= 1, k++) { if (pwr_desc & 0x01) { /* skip bytes until non-ext found */ while (tbuf[i++] & 0x80) ; } } } if (ftrs & TPCE_FS_TD) { i++; } if (ftrs & TPCE_FS_IO) { int io_addrs[16],io_lens[16]; int io_16,io_block_len, io_block_size; iop = 1; io_16 = tbuf[i] & TPCE_FS_IO_BUS16; i++; ios--; /*TMPFIX*/; io_block_len = (tbuf[i] & TPCE_FS_IO_LEN) >> TPCE_FS_IO_LEN_SHIFT; io_block_size = (tbuf[i] & TPCE_FS_IO_SIZE) >> TPCE_FS_IO_SIZE_SHIFT; ios = (tbuf[i] & TPCE_FS_IO_NUM) + 1; i++; for (j = 0; j < ios; j++) { io_addrs[j] = io_lens[j] = 0; switch (io_block_size) { case 3: io_addrs[j] |= tbuf[i+3] << 24; io_addrs[j] |= tbuf[i+2] << 16; case 2: io_addrs[j] |= tbuf[i+1] << 8; case 1: io_addrs[j] |= tbuf[i]; break; } pc_cf->io[j].start=io_addrs[j]; i += io_block_size + (io_block_size == 3 ? 1 : 0); switch (io_block_len) { case 3: io_lens[j] |= tbuf[i+3] << 24; io_lens[j] |= tbuf[i+2] << 16; case 2: io_lens[j] |= tbuf[i+1] << 8; case 1: io_lens[j] |= tbuf[i]; break; } /* io_lens[j]++; /*TMPFIX*/; pc_cf->io[j].len=io_lens[j]; pc_cf->io[j].flags=io_16?PCMCIA_MAP_16:PCMCIA_MAP_8; i += io_block_len + (io_block_len == 3 ? 1 : 0); } pc_cf->iowin=ios; } if (ftrs & TPCE_FS_IRQ) { int irq_mask,irqp,irq; pc_cf->irq_level=!!(tbuf[i] & TPCE_FS_IRQ_LEVEL); pc_cf->irq_pulse=!!(tbuf[i] & TPCE_FS_IRQ_PULSE); pc_cf->irq_share=!!(tbuf[i] & TPCE_FS_IRQ_SHARE); if (tbuf[i] & TPCE_FS_IRQ_MASK) { irq_mask = (tbuf[i+2] << 8) + tbuf[i+1]; i += 2; } else { pc_cf->irq_num = tbuf[i] & TPCE_FS_IRQ_IRQN; } i++; } if (ftrs & TPCE_FS_MEM) { int memp,mems,mem_lens[16],mem_caddrs[16],mem_haddrs[16]; memp = 1; switch ((ftrs & TPCE_FS_MEM) >> TPCE_FS_MEM_SHIFT) { case 1: mems = 1; mem_lens[0] = (tbuf[i+1] << 8) + tbuf[i]; mem_lens[0] <<= 8; printf("\tmem: len %d\n", mem_lens[0]); break; case 2: mems = 1; mem_lens[0] = (tbuf[i+1] << 8) + tbuf[i]; mem_caddrs[0] = mem_haddrs[0] = (tbuf[i+3] << 8) + tbuf[i+2]; mem_lens[0] <<= 8; mem_caddrs[0] <<= 8; break; case 3: host_addr_p = tbuf[i] & TPCE_FS_MEM_HOST; addr_size = (tbuf[i] & TPCE_FS_MEM_ADDR) >> TPCE_FS_MEM_ADDR_SHIFT; len_size = (tbuf[i] & TPCE_FS_MEM_LEN) >> TPCE_FS_MEM_LEN_SHIFT; mems = (tbuf[i] & TPCE_FS_MEM_WINS) + 1; i++; for (j = 0; j < mems; j++) { mem_lens[j] = 0; mem_caddrs[j] = 0; mem_haddrs[j] = 0; switch (len_size) { case 3: mem_lens[j] |= (tbuf[i+2] << 16); case 2: mem_lens[j] |= (tbuf[i+1] << 8); case 1: mem_lens[j] |= tbuf[i]; } i += len_size; switch (addr_size) { case 3: mem_caddrs[j] |= (tbuf[i+2] << 16); case 2: mem_caddrs[j] |= (tbuf[i+1] << 8); case 1: mem_caddrs[j] |= tbuf[i]; } i += addr_size; if (host_addr_p) { switch (addr_size) { case 3: mem_haddrs[j] |= (tbuf[i+2] << 16); case 2: mem_haddrs[j] |= (tbuf[i+1] << 8); case 1: mem_haddrs[j] |= tbuf[i]; } i += addr_size; } mem_lens[j] <<= 8; mem_caddrs[j] <<= 8; mem_haddrs[j] <<= 8; } } } } }