Annotation of Gnu-Mach/linux/pcmcia-cs/modules/cistpl.c, revision 1.1.1.1

1.1       root        1: /*======================================================================
                      2: 
                      3:     PCMCIA Card Information Structure parser
                      4: 
                      5:     cistpl.c 1.101 2003/12/15 03:58:03
                      6: 
                      7:     The contents of this file are subject to the Mozilla Public
                      8:     License Version 1.1 (the "License"); you may not use this file
                      9:     except in compliance with the License. You may obtain a copy of
                     10:     the License at http://www.mozilla.org/MPL/
                     11: 
                     12:     Software distributed under the License is distributed on an "AS
                     13:     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
                     14:     implied. See the License for the specific language governing
                     15:     rights and limitations under the License.
                     16: 
                     17:     The initial developer of the original code is David A. Hinds
                     18:     <[email protected]>.  Portions created by David A. Hinds
                     19:     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
                     20: 
                     21:     Alternatively, the contents of this file may be used under the
                     22:     terms of the GNU General Public License version 2 (the "GPL"), in
                     23:     which case the provisions of the GPL are applicable instead of the
                     24:     above.  If you wish to allow the use of your version of this file
                     25:     only under the terms of the GPL and not to allow others to use
                     26:     your version of this file under the MPL, indicate your decision
                     27:     by deleting the provisions above and replace them with the notice
                     28:     and other provisions required by the GPL.  If you do not delete
                     29:     the provisions above, a recipient may use your version of this
                     30:     file under either the MPL or the GPL.
                     31:     
                     32: ======================================================================*/
                     33: 
                     34: #define __NO_VERSION__
                     35: 
                     36: #include <linux/config.h>
                     37: #include <linux/module.h>
                     38: #include <linux/kernel.h>
                     39: #include <linux/string.h>
                     40: #include <linux/major.h>
                     41: #include <linux/errno.h>
                     42: #include <linux/timer.h>
                     43: #include <linux/slab.h>
                     44: #include <linux/mm.h>
                     45: #include <linux/sched.h>
                     46: #include <linux/pci.h>
                     47: #include <linux/ioport.h>
                     48: #include <asm/io.h>
                     49: #include <asm/byteorder.h>
                     50: 
                     51: #include <pcmcia/cs_types.h>
                     52: #include <pcmcia/bus_ops.h>
                     53: #include <pcmcia/ss.h>
                     54: #include <pcmcia/cs.h>
                     55: #include <pcmcia/bulkmem.h>
                     56: #include <pcmcia/cisreg.h>
                     57: #include <pcmcia/cistpl.h>
                     58: #include "cs_internal.h"
                     59: 
                     60: static const u_char mantissa[] = {
                     61:     10, 12, 13, 15, 20, 25, 30, 35,
                     62:     40, 45, 50, 55, 60, 70, 80, 90
                     63: };
                     64: 
                     65: static const u_int exponent[] = {
                     66:     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
                     67: };
                     68: 
                     69: /* Convert an extended speed byte to a time in nanoseconds */
                     70: #define SPEED_CVT(v) \
                     71:     (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
                     72: /* Convert a power byte to a current in 0.1 microamps */
                     73: #define POWER_CVT(v) \
                     74:     (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
                     75: #define POWER_SCALE(v)         (exponent[(v)&7])
                     76: 
                     77: /* Upper limit on reasonable # of tuples */
                     78: #define MAX_TUPLES             200
                     79: 
                     80: /*====================================================================*/
                     81: 
                     82: /* Parameters that can be set with 'insmod' */
                     83: 
                     84: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
                     85: 
                     86: INT_MODULE_PARM(cis_width,     0);             /* 16-bit CIS? */
                     87: 
                     88: /*======================================================================
                     89: 
                     90:     Low-level functions to read and write CIS memory.  I think the
                     91:     write routine is only useful for writing one-byte registers.
                     92:     
                     93: ======================================================================*/
                     94: 
                     95: /* Bits in attr field */
                     96: #define IS_ATTR                1
                     97: #define IS_INDIRECT    8
                     98: 
                     99: static int setup_cis_mem(socket_info_t *s);
                    100: 
                    101: static void set_cis_map(socket_info_t *s, pccard_mem_map *mem)
                    102: {
                    103:     s->ss_entry(s->sock, SS_SetMemMap, mem);
                    104:     if (s->cap.features & SS_CAP_STATIC_MAP) {
                    105:        if (s->cis_virt)
                    106:            bus_iounmap(s->cap.bus, s->cis_virt);
                    107:        s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start,
                    108:                                  s->cap.map_size);
                    109:     }
                    110: }
                    111: 
                    112: int read_cis_mem(socket_info_t *s, int attr, u_int addr,
                    113:                 u_int len, void *ptr)
                    114: {
                    115:     pccard_mem_map *mem = &s->cis_mem;
                    116:     u_char *sys, *buf = ptr;
                    117:     
                    118:     DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
                    119:     if (setup_cis_mem(s) != 0) {
                    120:        memset(ptr, 0xff, len);
                    121:        return -1;
                    122:     }
                    123:     mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
                    124: 
                    125:     if (attr & IS_INDIRECT) {
                    126:        /* Indirect accesses use a bunch of special registers at fixed
                    127:           locations in common memory */
                    128:        u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
                    129:        if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
                    130:        mem->card_start = 0; mem->flags = MAP_ACTIVE;
                    131:        set_cis_map(s, mem);
                    132:        sys = s->cis_virt;
                    133:        bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
                    134:        bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
                    135:        bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
                    136:        bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
                    137:        bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
                    138:        for ( ; len > 0; len--, buf++)
                    139:            *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0);
                    140:     } else {
                    141:        u_int inc = 1;
                    142:        if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
                    143:        sys += (addr & (s->cap.map_size-1));
                    144:        mem->card_start = addr & ~(s->cap.map_size-1);
                    145:        while (len) {
                    146:            set_cis_map(s, mem);
                    147:            sys = s->cis_virt + (addr & (s->cap.map_size-1));
                    148:            for ( ; len > 0; len--, buf++, sys += inc) {
                    149:                if (sys == s->cis_virt+s->cap.map_size) break;
                    150:                *buf = bus_readb(s->cap.bus, sys);
                    151:            }
                    152:            mem->card_start += s->cap.map_size;
                    153:            addr = 0;
                    154:        }
                    155:     }
                    156:     DEBUG(3, "cs:  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
                    157:          *(u_char *)(ptr+0), *(u_char *)(ptr+1),
                    158:          *(u_char *)(ptr+2), *(u_char *)(ptr+3));
                    159:     return 0;
                    160: }
                    161: 
                    162: void write_cis_mem(socket_info_t *s, int attr, u_int addr,
                    163:                   u_int len, void *ptr)
                    164: {
                    165:     pccard_mem_map *mem = &s->cis_mem;
                    166:     u_char *sys, *buf = ptr;
                    167:     
                    168:     DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
                    169:     if (setup_cis_mem(s) != 0) return;
                    170:     mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
                    171: 
                    172:     if (attr & IS_INDIRECT) {
                    173:        /* Indirect accesses use a bunch of special registers at fixed
                    174:           locations in common memory */
                    175:        u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
                    176:        if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
                    177:        mem->card_start = 0; mem->flags = MAP_ACTIVE;
                    178:        set_cis_map(s, mem);
                    179:        sys = s->cis_virt;
                    180:        bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
                    181:        bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
                    182:        bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
                    183:        bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
                    184:        bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
                    185:        for ( ; len > 0; len--, buf++)
                    186:            bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0);
                    187:     } else {
                    188:        int inc = 1;
                    189:        if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
                    190:        mem->card_start = addr & ~(s->cap.map_size-1);
                    191:        while (len) {
                    192:            set_cis_map(s, mem);
                    193:            sys = s->cis_virt + (addr & (s->cap.map_size-1));
                    194:            for ( ; len > 0; len--, buf++, sys += inc) {
                    195:                if (sys == s->cis_virt+s->cap.map_size) break;
                    196:                bus_writeb(s->cap.bus, *buf, sys);
                    197:            }
                    198:            mem->card_start += s->cap.map_size;
                    199:            addr = 0;
                    200:        }
                    201:     }
                    202: }
                    203: 
                    204: /*======================================================================
                    205: 
                    206:     This is tricky... when we set up CIS memory, we try to validate
                    207:     the memory window space allocations.
                    208:     
                    209: ======================================================================*/
                    210: 
                    211: /* Scratch pointer to the socket we use for validation */
                    212: static socket_info_t *vs = NULL;
                    213: 
                    214: /* Validation function for cards with a valid CIS */
                    215: static int cis_readable(u_long base)
                    216: {
                    217:     cisinfo_t info1, info2;
                    218:     int ret;
                    219:     vs->cis_mem.sys_start = base;
                    220:     vs->cis_mem.sys_stop = base+vs->cap.map_size-1;
                    221:     vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
                    222:     ret = validate_cis(vs->clients, &info1);
                    223:     /* invalidate mapping and CIS cache */
                    224:     bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0;
                    225:     if ((ret != 0) || (info1.Chains == 0))
                    226:        return 0;
                    227:     vs->cis_mem.sys_start = base+vs->cap.map_size;
                    228:     vs->cis_mem.sys_stop = base+2*vs->cap.map_size-1;
                    229:     vs->cis_virt = bus_ioremap(vs->cap.bus, base+vs->cap.map_size,
                    230:                               vs->cap.map_size);
                    231:     ret = validate_cis(vs->clients, &info2);
                    232:     bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0;
                    233:     return ((ret == 0) && (info1.Chains == info2.Chains));
                    234: }
                    235: 
                    236: /* Validation function for simple memory cards */
                    237: static int checksum(u_long base)
                    238: {
                    239:     int i, a, b, d;
                    240:     vs->cis_mem.sys_start = base;
                    241:     vs->cis_mem.sys_stop = base+vs->cap.map_size-1;
                    242:     vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
                    243:     vs->cis_mem.card_start = 0;
                    244:     vs->cis_mem.flags = MAP_ACTIVE;
                    245:     vs->ss_entry(vs->sock, SS_SetMemMap, &vs->cis_mem);
                    246:     /* Don't bother checking every word... */
                    247:     a = 0; b = -1;
                    248:     for (i = 0; i < vs->cap.map_size; i += 44) {
                    249:        d = bus_readl(vs->cap.bus, vs->cis_virt+i);
                    250:        a += d; b &= d;
                    251:     }
                    252:     bus_iounmap(vs->cap.bus, vs->cis_virt);
                    253:     return (b == -1) ? -1 : (a>>1);
                    254: }
                    255: 
                    256: static int checksum_match(u_long base)
                    257: {
                    258:     int a = checksum(base), b = checksum(base+vs->cap.map_size);
                    259:     return ((a == b) && (a >= 0));
                    260: }
                    261: 
                    262: static int setup_cis_mem(socket_info_t *s)
                    263: {
                    264:     if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
                    265:        (s->cis_mem.sys_start == 0)) {
                    266:        int low = !(s->cap.features & SS_CAP_PAGE_REGS);
                    267:        vs = s;
                    268:        validate_mem(cis_readable, checksum_match, low);
                    269:        s->cis_mem.sys_start = 0;
                    270:        vs = NULL;
                    271:        if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
                    272:                            s->cap.map_size, low, "card services")) {
                    273:            printk(KERN_NOTICE "cs: unable to map card memory!\n");
                    274:            return -1;
                    275:        }
                    276:        s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1;
                    277:        s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start,
                    278:                                  s->cap.map_size);
                    279:     }
                    280:     return 0;
                    281: }
                    282: 
                    283: void release_cis_mem(socket_info_t *s)
                    284: {
                    285:     if (s->cis_mem.sys_start != 0) {
                    286:        s->cis_mem.flags &= ~MAP_ACTIVE;
                    287:        s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem);
                    288:        if (!(s->cap.features & SS_CAP_STATIC_MAP))
                    289:            release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
                    290:        bus_iounmap(s->cap.bus, s->cis_virt);
                    291:        s->cis_mem.sys_start = 0;
                    292:        s->cis_virt = NULL;
                    293:     }
                    294: }
                    295: 
                    296: /*======================================================================
                    297: 
                    298:     This is a wrapper around read_cis_mem, with the same interface,
                    299:     but which caches information, for cards whose CIS may not be
                    300:     readable all the time.
                    301:     
                    302: ======================================================================*/
                    303: 
                    304: static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
                    305:                           u_int len, void *ptr)
                    306: {
                    307:     int i, ret;
                    308:     char *caddr;
                    309: 
                    310:     if (s->fake_cis) {
                    311:        if (s->fake_cis_len > addr+len)
                    312:            memcpy(ptr, s->fake_cis+addr, len);
                    313:        else
                    314:            memset(ptr, 0xff, len);
                    315:        return;
                    316:     }
                    317:     caddr = s->cis_cache;
                    318:     for (i = 0; i < s->cis_used; i++) {
                    319:        if ((s->cis_table[i].addr == addr) &&
                    320:            (s->cis_table[i].len == len) &&
                    321:            (s->cis_table[i].attr == attr)) break;
                    322:        caddr += s->cis_table[i].len;
                    323:     }
                    324:     if (i < s->cis_used) {
                    325:        memcpy(ptr, caddr, len);
                    326:        return;
                    327:     }
                    328: #ifdef CONFIG_CARDBUS
                    329:     if (s->state & SOCKET_CARDBUS)
                    330:        ret = read_cb_mem(s, 0, attr, addr, len, ptr);
                    331:     else
                    332: #endif
                    333:        ret = read_cis_mem(s, attr, addr, len, ptr);
                    334:     /* Copy data into the cache, if there is room */
                    335:     if ((ret == 0) && (i < MAX_CIS_TABLE) &&
                    336:        (caddr+len < s->cis_cache+MAX_CIS_DATA)) {
                    337:        s->cis_table[i].addr = addr;
                    338:        s->cis_table[i].len = len;
                    339:        s->cis_table[i].attr = attr;
                    340:        s->cis_used++;
                    341:        memcpy(caddr, ptr, len);
                    342:     }      
                    343: }
                    344: 
                    345: /*======================================================================
                    346: 
                    347:     This verifies if the CIS of a card matches what is in the CIS
                    348:     cache.
                    349:     
                    350: ======================================================================*/
                    351: 
                    352: int verify_cis_cache(socket_info_t *s)
                    353: {
                    354:     char *buf, *caddr;
                    355:     int i;
                    356: 
                    357:     buf = kmalloc(256, GFP_KERNEL);
                    358:     if (buf == NULL)
                    359:        return -1;
                    360:     caddr = s->cis_cache;
                    361:     for (i = 0; i < s->cis_used; i++) {
                    362: #ifdef CONFIG_CARDBUS
                    363:        if (s->state & SOCKET_CARDBUS)
                    364:            read_cb_mem(s, 0, s->cis_table[i].attr, s->cis_table[i].addr,
                    365:                        s->cis_table[i].len, buf);
                    366:        else
                    367: #endif
                    368:            read_cis_mem(s, s->cis_table[i].attr, s->cis_table[i].addr,
                    369:                         s->cis_table[i].len, buf);
                    370:        if (memcmp(buf, caddr, s->cis_table[i].len) != 0)
                    371:            break;
                    372:        caddr += s->cis_table[i].len;
                    373:     }
                    374:     kfree(buf);
                    375:     return (i < s->cis_used);
                    376: }
                    377: 
                    378: /*======================================================================
                    379: 
                    380:     For really bad cards, we provide a facility for uploading a
                    381:     replacement CIS.
                    382:     
                    383: ======================================================================*/
                    384: 
                    385: int replace_cis(client_handle_t handle, cisdump_t *cis)
                    386: {
                    387:     socket_info_t *s;
                    388:     if (CHECK_HANDLE(handle))
                    389:        return CS_BAD_HANDLE;
                    390:     s = SOCKET(handle);
                    391:     if (s->fake_cis != NULL) {
                    392:        kfree(s->fake_cis);
                    393:        s->fake_cis = NULL;
                    394:     }
                    395:     if (cis->Length > CISTPL_MAX_CIS_SIZE)
                    396:        return CS_BAD_SIZE;
                    397:     s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
                    398:     if (s->fake_cis == NULL)
                    399:        return CS_OUT_OF_RESOURCE;
                    400:     s->fake_cis_len = cis->Length;
                    401:     memcpy(s->fake_cis, cis->Data, cis->Length);
                    402:     return CS_SUCCESS;
                    403: }
                    404: 
                    405: /*======================================================================
                    406: 
                    407:     The high-level CIS tuple services
                    408:     
                    409: ======================================================================*/
                    410: 
                    411: typedef struct tuple_flags {
                    412:     u_int              link_space:4;
                    413:     u_int              has_link:1;
                    414:     u_int              mfc_fn:3;
                    415:     u_int              space:4;
                    416: } tuple_flags;
                    417: 
                    418: #define LINK_SPACE(f)  (((tuple_flags *)(&(f)))->link_space)
                    419: #define HAS_LINK(f)    (((tuple_flags *)(&(f)))->has_link)
                    420: #define MFC_FN(f)      (((tuple_flags *)(&(f)))->mfc_fn)
                    421: #define SPACE(f)       (((tuple_flags *)(&(f)))->space)
                    422: 
                    423: int get_next_tuple(client_handle_t handle, tuple_t *tuple);
                    424: 
                    425: int get_first_tuple(client_handle_t handle, tuple_t *tuple)
                    426: {
                    427:     socket_info_t *s;
                    428:     if (CHECK_HANDLE(handle))
                    429:        return CS_BAD_HANDLE;
                    430:     s = SOCKET(handle);
                    431:     if (!(s->state & SOCKET_PRESENT))
                    432:        return CS_NO_CARD;
                    433:     tuple->TupleLink = tuple->Flags = 0;
                    434: #ifdef CONFIG_CARDBUS
                    435:     if (s->state & SOCKET_CARDBUS) {
                    436:        u_int ptr;
                    437:        pcibios_read_config_dword(s->cap.cardbus, 0, 0x28, &ptr);
                    438:        tuple->CISOffset = ptr & ~7;
                    439:        SPACE(tuple->Flags) = (ptr & 7);
                    440:     } else
                    441: #endif
                    442:     {
                    443:        /* Assume presence of a LONGLINK_C to address 0 */
                    444:        tuple->CISOffset = tuple->LinkOffset = 0;
                    445:        SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
                    446:     }
                    447:     if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
                    448:        !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
                    449:        cisdata_t req = tuple->DesiredTuple;
                    450:        tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
                    451:        if (get_next_tuple(handle, tuple) == CS_SUCCESS) {
                    452:            tuple->DesiredTuple = CISTPL_LINKTARGET;
                    453:            if (get_next_tuple(handle, tuple) != CS_SUCCESS)
                    454:                return CS_NO_MORE_ITEMS;
                    455:        } else
                    456:            tuple->CISOffset = tuple->TupleLink = 0;
                    457:        tuple->DesiredTuple = req;
                    458:     }
                    459:     return get_next_tuple(handle, tuple);
                    460: }
                    461: 
                    462: static int follow_link(socket_info_t *s, tuple_t *tuple)
                    463: {
                    464:     u_char link[5];
                    465:     u_int ofs;
                    466: 
                    467:     if (MFC_FN(tuple->Flags)) {
                    468:        /* Get indirect link from the MFC tuple */
                    469:        read_cis_cache(s, LINK_SPACE(tuple->Flags),
                    470:                       tuple->LinkOffset, 5, link);
                    471:        ofs = le32_to_cpu(*(u_int *)(link+1));
                    472:        SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
                    473:        /* Move to the next indirect link */
                    474:        tuple->LinkOffset += 5;
                    475:        MFC_FN(tuple->Flags)--;
                    476:     } else if (HAS_LINK(tuple->Flags)) {
                    477:        ofs = tuple->LinkOffset;
                    478:        SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
                    479:        HAS_LINK(tuple->Flags) = 0;
                    480:     } else {
                    481:        return -1;
                    482:     }
                    483:     if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
                    484:        /* This is ugly, but a common CIS error is to code the long
                    485:           link offset incorrectly, so we check the right spot... */
                    486:        read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
                    487:        if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
                    488:            (strncmp(link+2, "CIS", 3) == 0))
                    489:            return ofs;
                    490:        /* Then, we try the wrong spot... */
                    491:        ofs = ofs >> 1;
                    492:     }
                    493:     read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
                    494:     if ((link[0] != CISTPL_LINKTARGET) || (link[1] < 3) ||
                    495:        (strncmp(link+2, "CIS", 3) != 0))
                    496:        return -1;
                    497:     return ofs;
                    498: }
                    499: 
                    500: int get_next_tuple(client_handle_t handle, tuple_t *tuple)
                    501: {
                    502:     socket_info_t *s;
                    503:     u_char link[2], tmp;
                    504:     int ofs, i, attr;
                    505:     
                    506:     if (CHECK_HANDLE(handle))
                    507:        return CS_BAD_HANDLE;
                    508:     s = SOCKET(handle);
                    509:     if (!(s->state & SOCKET_PRESENT))
                    510:        return CS_NO_CARD;
                    511: 
                    512:     link[1] = tuple->TupleLink;
                    513:     ofs = tuple->CISOffset + tuple->TupleLink;
                    514:     attr = SPACE(tuple->Flags);
                    515: 
                    516:     for (i = 0; i < MAX_TUPLES; i++) {
                    517:        if (link[1] == 0xff) {
                    518:            link[0] = CISTPL_END;
                    519:        } else {
                    520:            read_cis_cache(s, attr, ofs, 2, link);
                    521:            if (link[0] == CISTPL_NULL) {
                    522:                ofs++; continue;
                    523:            }
                    524:        }
                    525:        
                    526:        /* End of chain?  Follow long link if possible */
                    527:        if (link[0] == CISTPL_END) {
                    528:            if ((ofs = follow_link(s, tuple)) < 0)
                    529:                return CS_NO_MORE_ITEMS;
                    530:            attr = SPACE(tuple->Flags);
                    531:            read_cis_cache(s, attr, ofs, 2, link);
                    532:        }
                    533: 
                    534:        /* Is this a link tuple?  Make a note of it */
                    535:        if ((link[0] == CISTPL_LONGLINK_A) ||
                    536:            (link[0] == CISTPL_LONGLINK_C) ||
                    537:            (link[0] == CISTPL_LONGLINK_MFC) ||
                    538:            (link[0] == CISTPL_LINKTARGET) ||
                    539:            (link[0] == CISTPL_INDIRECT) ||
                    540:            (link[0] == CISTPL_NO_LINK)) {
                    541:            switch (link[0]) {
                    542:            case CISTPL_LONGLINK_A:
                    543:                HAS_LINK(tuple->Flags) = 1;
                    544:                LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
                    545:                read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
                    546:                break;
                    547:            case CISTPL_LONGLINK_C:
                    548:                HAS_LINK(tuple->Flags) = 1;
                    549:                LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
                    550:                read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
                    551:                break;
                    552:            case CISTPL_INDIRECT:
                    553:                HAS_LINK(tuple->Flags) = 1;
                    554:                LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
                    555:                tuple->LinkOffset = 0;
                    556:                break;
                    557:            case CISTPL_LONGLINK_MFC:
                    558:                tuple->LinkOffset = ofs + 3;
                    559:                LINK_SPACE(tuple->Flags) = attr;
                    560:                if (handle->Function == BIND_FN_ALL) {
                    561:                    /* Follow all the MFC links */
                    562:                    read_cis_cache(s, attr, ofs+2, 1, &tmp);
                    563:                    MFC_FN(tuple->Flags) = tmp;
                    564:                } else {
                    565:                    /* Follow exactly one of the links */
                    566:                    MFC_FN(tuple->Flags) = 1;
                    567:                    tuple->LinkOffset += handle->Function * 5;
                    568:                }
                    569:                break;
                    570:            case CISTPL_NO_LINK:
                    571:                HAS_LINK(tuple->Flags) = 0;
                    572:                break;
                    573:            }
                    574:            if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
                    575:                (tuple->DesiredTuple == RETURN_FIRST_TUPLE))
                    576:                break;
                    577:        } else
                    578:            if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
                    579:                break;
                    580:        
                    581:        if (link[0] == tuple->DesiredTuple)
                    582:            break;
                    583:        ofs += link[1] + 2;
                    584:     }
                    585:     if (i == MAX_TUPLES) {
                    586:        DEBUG(1, "cs: overrun in get_next_tuple for socket %d\n",
                    587:              handle->Socket);
                    588:        return CS_NO_MORE_ITEMS;
                    589:     }
                    590:     
                    591:     tuple->TupleCode = link[0];
                    592:     tuple->TupleLink = link[1];
                    593:     tuple->CISOffset = ofs + 2;
                    594:     return CS_SUCCESS;
                    595: }
                    596: 
                    597: /*====================================================================*/
                    598: 
                    599: #define _MIN(a, b)             (((a) < (b)) ? (a) : (b))
                    600: 
                    601: int get_tuple_data(client_handle_t handle, tuple_t *tuple)
                    602: {
                    603:     socket_info_t *s;
                    604:     u_int len;
                    605:     
                    606:     if (CHECK_HANDLE(handle))
                    607:        return CS_BAD_HANDLE;
                    608: 
                    609:     s = SOCKET(handle);
                    610: 
                    611:     if (tuple->TupleLink < tuple->TupleOffset)
                    612:        return CS_NO_MORE_ITEMS;
                    613:     len = tuple->TupleLink - tuple->TupleOffset;
                    614:     tuple->TupleDataLen = tuple->TupleLink;
                    615:     if (len == 0)
                    616:        return CS_SUCCESS;
                    617:     read_cis_cache(s, SPACE(tuple->Flags),
                    618:                   tuple->CISOffset + tuple->TupleOffset,
                    619:                   _MIN(len, tuple->TupleDataMax), tuple->TupleData);
                    620:     return CS_SUCCESS;
                    621: }
                    622: 
                    623: /*======================================================================
                    624: 
                    625:     Parsing routines for individual tuples
                    626:     
                    627: ======================================================================*/
                    628: 
                    629: static int parse_device(tuple_t *tuple, cistpl_device_t *device)
                    630: {
                    631:     int i;
                    632:     u_char scale;
                    633:     u_char *p, *q;
                    634: 
                    635:     p = (u_char *)tuple->TupleData;
                    636:     q = p + tuple->TupleDataLen;
                    637: 
                    638:     device->ndev = 0;
                    639:     for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
                    640:        
                    641:        if (*p == 0xff) break;
                    642:        device->dev[i].type = (*p >> 4);
                    643:        device->dev[i].wp = (*p & 0x08) ? 1 : 0;
                    644:        switch (*p & 0x07) {
                    645:        case 0: device->dev[i].speed = 0;   break;
                    646:        case 1: device->dev[i].speed = 250; break;
                    647:        case 2: device->dev[i].speed = 200; break;
                    648:        case 3: device->dev[i].speed = 150; break;
                    649:        case 4: device->dev[i].speed = 100; break;
                    650:        case 7:
                    651:            if (++p == q) return CS_BAD_TUPLE;
                    652:            device->dev[i].speed = SPEED_CVT(*p);
                    653:            while (*p & 0x80)
                    654:                if (++p == q) return CS_BAD_TUPLE;
                    655:            break;
                    656:        default:
                    657:            return CS_BAD_TUPLE;
                    658:        }
                    659: 
                    660:        if (++p == q) return CS_BAD_TUPLE;
                    661:        if (*p == 0xff) break;
                    662:        scale = *p & 7;
                    663:        if (scale == 7) return CS_BAD_TUPLE;
                    664:        device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
                    665:        device->ndev++;
                    666:        if (++p == q) break;
                    667:     }
                    668:     
                    669:     return CS_SUCCESS;
                    670: }
                    671: 
                    672: /*====================================================================*/
                    673: 
                    674: static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
                    675: {
                    676:     u_char *p;
                    677:     if (tuple->TupleDataLen < 5)
                    678:        return CS_BAD_TUPLE;
                    679:     p = (u_char *)tuple->TupleData;
                    680:     csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
                    681:     csum->len = le16_to_cpu(*(u_short *)(p + 2));
                    682:     csum->sum = *(p+4);
                    683:     return CS_SUCCESS;
                    684: }
                    685: 
                    686: /*====================================================================*/
                    687: 
                    688: static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
                    689: {
                    690:     if (tuple->TupleDataLen < 4)
                    691:        return CS_BAD_TUPLE;
                    692:     link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
                    693:     return CS_SUCCESS;
                    694: }
                    695: 
                    696: /*====================================================================*/
                    697: 
                    698: static int parse_longlink_mfc(tuple_t *tuple,
                    699:                              cistpl_longlink_mfc_t *link)
                    700: {
                    701:     u_char *p;
                    702:     int i;
                    703:     
                    704:     p = (u_char *)tuple->TupleData;
                    705:     
                    706:     link->nfn = *p; p++;
                    707:     if (tuple->TupleDataLen <= link->nfn*5)
                    708:        return CS_BAD_TUPLE;
                    709:     for (i = 0; i < link->nfn; i++) {
                    710:        link->fn[i].space = *p; p++;
                    711:        link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
                    712:     }
                    713:     return CS_SUCCESS;
                    714: }
                    715: 
                    716: /*====================================================================*/
                    717: 
                    718: static int parse_strings(u_char *p, u_char *q, int max,
                    719:                         char *s, u_char *ofs, u_char *found)
                    720: {
                    721:     int i, j, ns;
                    722: 
                    723:     if (p == q) return CS_BAD_TUPLE;
                    724:     ns = 0; j = 0;
                    725:     for (i = 0; i < max; i++) {
                    726:        if (*p == 0xff) break;
                    727:        ofs[i] = j;
                    728:        ns++;
                    729:        for (;;) {
                    730:            s[j++] = (*p == 0xff) ? '\0' : *p;
                    731:            if ((*p == '\0') || (*p == 0xff)) break;
                    732:            if (++p == q) return CS_BAD_TUPLE;
                    733:        }
                    734:        if ((*p == 0xff) || (++p == q)) break;
                    735:     }
                    736:     if (found) {
                    737:        *found = ns;
                    738:        return CS_SUCCESS;
                    739:     } else {
                    740:        return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
                    741:     }
                    742: }
                    743: 
                    744: /*====================================================================*/
                    745: 
                    746: static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
                    747: {
                    748:     u_char *p, *q;
                    749:     
                    750:     p = (u_char *)tuple->TupleData;
                    751:     q = p + tuple->TupleDataLen;
                    752:     
                    753:     vers_1->major = *p; p++;
                    754:     vers_1->minor = *p; p++;
                    755:     if (p >= q) return CS_BAD_TUPLE;
                    756: 
                    757:     return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
                    758:                         vers_1->str, vers_1->ofs, &vers_1->ns);
                    759: }
                    760: 
                    761: /*====================================================================*/
                    762: 
                    763: static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
                    764: {
                    765:     u_char *p, *q;
                    766:     
                    767:     p = (u_char *)tuple->TupleData;
                    768:     q = p + tuple->TupleDataLen;
                    769:     
                    770:     return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
                    771:                         altstr->str, altstr->ofs, &altstr->ns);
                    772: }
                    773: 
                    774: /*====================================================================*/
                    775: 
                    776: static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
                    777: {
                    778:     u_char *p, *q;
                    779:     int nid;
                    780: 
                    781:     p = (u_char *)tuple->TupleData;
                    782:     q = p + tuple->TupleDataLen;
                    783: 
                    784:     for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
                    785:        if (p > q-2) break;
                    786:        jedec->id[nid].mfr = p[0];
                    787:        jedec->id[nid].info = p[1];
                    788:        p += 2;
                    789:     }
                    790:     jedec->nid = nid;
                    791:     return CS_SUCCESS;
                    792: }
                    793: 
                    794: /*====================================================================*/
                    795: 
                    796: static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
                    797: {
                    798:     u_short *p;
                    799:     if (tuple->TupleDataLen < 4)
                    800:        return CS_BAD_TUPLE;
                    801:     p = (u_short *)tuple->TupleData;
                    802:     m->manf = le16_to_cpu(p[0]);
                    803:     m->card = le16_to_cpu(p[1]);
                    804:     return CS_SUCCESS;
                    805: }
                    806: 
                    807: /*====================================================================*/
                    808: 
                    809: static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
                    810: {
                    811:     u_char *p;
                    812:     if (tuple->TupleDataLen < 2)
                    813:        return CS_BAD_TUPLE;
                    814:     p = (u_char *)tuple->TupleData;
                    815:     f->func = p[0];
                    816:     f->sysinit = p[1];
                    817:     return CS_SUCCESS;
                    818: }
                    819: 
                    820: /*====================================================================*/
                    821: 
                    822: static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
                    823: {
                    824:     u_char *p;
                    825:     int i;
                    826:     if (tuple->TupleDataLen < 1)
                    827:        return CS_BAD_TUPLE;
                    828:     p = (u_char *)tuple->TupleData;
                    829:     f->type = p[0];
                    830:     for (i = 1; i < tuple->TupleDataLen; i++)
                    831:        f->data[i-1] = p[i];
                    832:     return CS_SUCCESS;
                    833: }
                    834: 
                    835: /*====================================================================*/
                    836: 
                    837: static int parse_config(tuple_t *tuple, cistpl_config_t *config)
                    838: {
                    839:     int rasz, rmsz, i;
                    840:     u_char *p;
                    841: 
                    842:     p = (u_char *)tuple->TupleData;
                    843:     rasz = *p & 0x03;
                    844:     rmsz = (*p & 0x3c) >> 2;
                    845:     if (tuple->TupleDataLen < rasz+rmsz+4)
                    846:        return CS_BAD_TUPLE;
                    847:     config->last_idx = *(++p);
                    848:     p++;
                    849:     config->base = 0;
                    850:     for (i = 0; i <= rasz; i++)
                    851:        config->base += p[i] << (8*i);
                    852:     p += rasz+1;
                    853:     for (i = 0; i < 4; i++)
                    854:        config->rmask[i] = 0;
                    855:     for (i = 0; i <= rmsz; i++)
                    856:        config->rmask[i>>2] += p[i] << (8*(i%4));
                    857:     config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
                    858:     return CS_SUCCESS;
                    859: }
                    860: 
                    861: /*======================================================================
                    862: 
                    863:     The following routines are all used to parse the nightmarish
                    864:     config table entries.
                    865:     
                    866: ======================================================================*/
                    867: 
                    868: static u_char *parse_power(u_char *p, u_char *q,
                    869:                           cistpl_power_t *pwr)
                    870: {
                    871:     int i;
                    872:     u_int scale;
                    873: 
                    874:     if (p == q) return NULL;
                    875:     pwr->present = *p;
                    876:     pwr->flags = 0;
                    877:     p++;
                    878:     for (i = 0; i < 7; i++)
                    879:        if (pwr->present & (1<<i)) {
                    880:            if (p == q) return NULL;
                    881:            pwr->param[i] = POWER_CVT(*p);
                    882:            scale = POWER_SCALE(*p);
                    883:            while (*p & 0x80) {
                    884:                if (++p == q) return NULL;
                    885:                if ((*p & 0x7f) < 100)
                    886:                    pwr->param[i] += (*p & 0x7f) * scale / 100;
                    887:                else if (*p == 0x7d)
                    888:                    pwr->flags |= CISTPL_POWER_HIGHZ_OK;
                    889:                else if (*p == 0x7e)
                    890:                    pwr->param[i] = 0;
                    891:                else if (*p == 0x7f)
                    892:                    pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
                    893:                else
                    894:                    return NULL;
                    895:            }
                    896:            p++;
                    897:        }
                    898:     return p;
                    899: }
                    900: 
                    901: /*====================================================================*/
                    902: 
                    903: static u_char *parse_timing(u_char *p, u_char *q,
                    904:                            cistpl_timing_t *timing)
                    905: {
                    906:     u_char scale;
                    907: 
                    908:     if (p == q) return NULL;
                    909:     scale = *p;
                    910:     if ((scale & 3) != 3) {
                    911:        if (++p == q) return NULL;
                    912:        timing->wait = SPEED_CVT(*p);
                    913:        timing->waitscale = exponent[scale & 3];
                    914:     } else
                    915:        timing->wait = 0;
                    916:     scale >>= 2;
                    917:     if ((scale & 7) != 7) {
                    918:        if (++p == q) return NULL;
                    919:        timing->ready = SPEED_CVT(*p);
                    920:        timing->rdyscale = exponent[scale & 7];
                    921:     } else
                    922:        timing->ready = 0;
                    923:     scale >>= 3;
                    924:     if (scale != 7) {
                    925:        if (++p == q) return NULL;
                    926:        timing->reserved = SPEED_CVT(*p);
                    927:        timing->rsvscale = exponent[scale];
                    928:     } else
                    929:        timing->reserved = 0;
                    930:     p++;
                    931:     return p;
                    932: }
                    933: 
                    934: /*====================================================================*/
                    935: 
                    936: static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
                    937: {
                    938:     int i, j, bsz, lsz;
                    939: 
                    940:     if (p == q) return NULL;
                    941:     io->flags = *p;
                    942: 
                    943:     if (!(*p & 0x80)) {
                    944:        io->nwin = 1;
                    945:        io->win[0].base = 0;
                    946:        io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
                    947:        return p+1;
                    948:     }
                    949:     
                    950:     if (++p == q) return NULL;
                    951:     io->nwin = (*p & 0x0f) + 1;
                    952:     bsz = (*p & 0x30) >> 4;
                    953:     if (bsz == 3) bsz++;
                    954:     lsz = (*p & 0xc0) >> 6;
                    955:     if (lsz == 3) lsz++;
                    956:     p++;
                    957:     
                    958:     for (i = 0; i < io->nwin; i++) {
                    959:        io->win[i].base = 0;
                    960:        io->win[i].len = 1;
                    961:        for (j = 0; j < bsz; j++, p++) {
                    962:            if (p == q) return NULL;
                    963:            io->win[i].base += *p << (j*8);
                    964:        }
                    965:        for (j = 0; j < lsz; j++, p++) {
                    966:            if (p == q) return NULL;
                    967:            io->win[i].len += *p << (j*8);
                    968:        }
                    969:     }
                    970:     return p;
                    971: }
                    972: 
                    973: /*====================================================================*/
                    974: 
                    975: static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
                    976: {
                    977:     int i, j, asz, lsz, has_ha;
                    978:     u_int len, ca, ha;
                    979: 
                    980:     if (p == q) return NULL;
                    981: 
                    982:     mem->nwin = (*p & 0x07) + 1;
                    983:     lsz = (*p & 0x18) >> 3;
                    984:     asz = (*p & 0x60) >> 5;
                    985:     has_ha = (*p & 0x80);
                    986:     if (++p == q) return NULL;
                    987:     
                    988:     for (i = 0; i < mem->nwin; i++) {
                    989:        len = ca = ha = 0;
                    990:        for (j = 0; j < lsz; j++, p++) {
                    991:            if (p == q) return NULL;
                    992:            len += *p << (j*8);
                    993:        }
                    994:        for (j = 0; j < asz; j++, p++) {
                    995:            if (p == q) return NULL;
                    996:            ca += *p << (j*8);
                    997:        }
                    998:        if (has_ha)
                    999:            for (j = 0; j < asz; j++, p++) {
                   1000:                if (p == q) return NULL;
                   1001:                ha += *p << (j*8);
                   1002:            }
                   1003:        mem->win[i].len = len << 8;
                   1004:        mem->win[i].card_addr = ca << 8;
                   1005:        mem->win[i].host_addr = ha << 8;
                   1006:     }
                   1007:     return p;
                   1008: }
                   1009: 
                   1010: /*====================================================================*/
                   1011: 
                   1012: static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
                   1013: {
                   1014:     if (p == q) return NULL;
                   1015:     irq->IRQInfo1 = *p; p++;
                   1016:     if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
                   1017:        if (p+2 > q) return NULL;
                   1018:        irq->IRQInfo2 = (p[1]<<8) + p[0];
                   1019:        p += 2;
                   1020:     }
                   1021:     return p;
                   1022: }
                   1023: 
                   1024: /*====================================================================*/
                   1025: 
                   1026: static int parse_cftable_entry(tuple_t *tuple,
                   1027:                               cistpl_cftable_entry_t *entry)
                   1028: {
                   1029:     u_char *p, *q, features;
                   1030: 
                   1031:     p = tuple->TupleData;
                   1032:     q = p + tuple->TupleDataLen;
                   1033:     entry->index = *p & 0x3f;
                   1034:     entry->flags = 0;
                   1035:     if (*p & 0x40)
                   1036:        entry->flags |= CISTPL_CFTABLE_DEFAULT;
                   1037:     if (*p & 0x80) {
                   1038:        if (++p == q) return CS_BAD_TUPLE;
                   1039:        if (*p & 0x10)
                   1040:            entry->flags |= CISTPL_CFTABLE_BVDS;
                   1041:        if (*p & 0x20)
                   1042:            entry->flags |= CISTPL_CFTABLE_WP;
                   1043:        if (*p & 0x40)
                   1044:            entry->flags |= CISTPL_CFTABLE_RDYBSY;
                   1045:        if (*p & 0x80)
                   1046:            entry->flags |= CISTPL_CFTABLE_MWAIT;
                   1047:        entry->interface = *p & 0x0f;
                   1048:     } else
                   1049:        entry->interface = 0;
                   1050: 
                   1051:     /* Process optional features */
                   1052:     if (++p == q) return CS_BAD_TUPLE;
                   1053:     features = *p; p++;
                   1054: 
                   1055:     /* Power options */
                   1056:     if ((features & 3) > 0) {
                   1057:        p = parse_power(p, q, &entry->vcc);
                   1058:        if (p == NULL) return CS_BAD_TUPLE;
                   1059:     } else
                   1060:        entry->vcc.present = 0;
                   1061:     if ((features & 3) > 1) {
                   1062:        p = parse_power(p, q, &entry->vpp1);
                   1063:        if (p == NULL) return CS_BAD_TUPLE;
                   1064:     } else
                   1065:        entry->vpp1.present = 0;
                   1066:     if ((features & 3) > 2) {
                   1067:        p = parse_power(p, q, &entry->vpp2);
                   1068:        if (p == NULL) return CS_BAD_TUPLE;
                   1069:     } else
                   1070:        entry->vpp2.present = 0;
                   1071: 
                   1072:     /* Timing options */
                   1073:     if (features & 0x04) {
                   1074:        p = parse_timing(p, q, &entry->timing);
                   1075:        if (p == NULL) return CS_BAD_TUPLE;
                   1076:     } else {
                   1077:        entry->timing.wait = 0;
                   1078:        entry->timing.ready = 0;
                   1079:        entry->timing.reserved = 0;
                   1080:     }
                   1081:     
                   1082:     /* I/O window options */
                   1083:     if (features & 0x08) {
                   1084:        p = parse_io(p, q, &entry->io);
                   1085:        if (p == NULL) return CS_BAD_TUPLE;
                   1086:     } else
                   1087:        entry->io.nwin = 0;
                   1088:     
                   1089:     /* Interrupt options */
                   1090:     if (features & 0x10) {
                   1091:        p = parse_irq(p, q, &entry->irq);
                   1092:        if (p == NULL) return CS_BAD_TUPLE;
                   1093:     } else
                   1094:        entry->irq.IRQInfo1 = 0;
                   1095: 
                   1096:     switch (features & 0x60) {
                   1097:     case 0x00:
                   1098:        entry->mem.nwin = 0;
                   1099:        break;
                   1100:     case 0x20:
                   1101:        entry->mem.nwin = 1;
                   1102:        entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
                   1103:        entry->mem.win[0].card_addr = 0;
                   1104:        entry->mem.win[0].host_addr = 0;
                   1105:        p += 2;
                   1106:        if (p > q) return CS_BAD_TUPLE;
                   1107:        break;
                   1108:     case 0x40:
                   1109:        entry->mem.nwin = 1;
                   1110:        entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
                   1111:        entry->mem.win[0].card_addr =
                   1112:            le16_to_cpu(*(u_short *)(p+2)) << 8;
                   1113:        entry->mem.win[0].host_addr = 0;
                   1114:        p += 4;
                   1115:        if (p > q) return CS_BAD_TUPLE;
                   1116:        break;
                   1117:     case 0x60:
                   1118:        p = parse_mem(p, q, &entry->mem);
                   1119:        if (p == NULL) return CS_BAD_TUPLE;
                   1120:        break;
                   1121:     }
                   1122: 
                   1123:     /* Misc features */
                   1124:     if (features & 0x80) {
                   1125:        if (p == q) return CS_BAD_TUPLE;
                   1126:        entry->flags |= (*p << 8);
                   1127:        while (*p & 0x80)
                   1128:            if (++p == q) return CS_BAD_TUPLE;
                   1129:        p++;
                   1130:     }
                   1131: 
                   1132:     entry->subtuples = q-p;
                   1133:     
                   1134:     return CS_SUCCESS;
                   1135: }
                   1136: 
                   1137: /*====================================================================*/
                   1138: 
                   1139: #ifdef CONFIG_CARDBUS
                   1140: 
                   1141: static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
                   1142: {
                   1143:     u_char *p;
                   1144:     if (tuple->TupleDataLen < 6)
                   1145:        return CS_BAD_TUPLE;
                   1146:     p = (u_char *)tuple->TupleData;
                   1147:     bar->attr = *p;
                   1148:     p += 2;
                   1149:     bar->size = le32_to_cpu(*(u_int *)p);
                   1150:     return CS_SUCCESS;
                   1151: }
                   1152: 
                   1153: static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
                   1154: {
                   1155:     u_char *p;
                   1156:     
                   1157:     p = (u_char *)tuple->TupleData;
                   1158:     if ((*p != 3) || (tuple->TupleDataLen < 6))
                   1159:        return CS_BAD_TUPLE;
                   1160:     config->last_idx = *(++p);
                   1161:     p++;
                   1162:     config->base = le32_to_cpu(*(u_int *)p);
                   1163:     config->subtuples = tuple->TupleDataLen - 6;
                   1164:     return CS_SUCCESS;
                   1165: }
                   1166: 
                   1167: static int parse_cftable_entry_cb(tuple_t *tuple,
                   1168:                                  cistpl_cftable_entry_cb_t *entry)
                   1169: {
                   1170:     u_char *p, *q, features;
                   1171: 
                   1172:     p = tuple->TupleData;
                   1173:     q = p + tuple->TupleDataLen;
                   1174:     entry->index = *p & 0x3f;
                   1175:     entry->flags = 0;
                   1176:     if (*p & 0x40)
                   1177:        entry->flags |= CISTPL_CFTABLE_DEFAULT;
                   1178: 
                   1179:     /* Process optional features */
                   1180:     if (++p == q) return CS_BAD_TUPLE;
                   1181:     features = *p; p++;
                   1182: 
                   1183:     /* Power options */
                   1184:     if ((features & 3) > 0) {
                   1185:        p = parse_power(p, q, &entry->vcc);
                   1186:        if (p == NULL) return CS_BAD_TUPLE;
                   1187:     } else
                   1188:        entry->vcc.present = 0;
                   1189:     if ((features & 3) > 1) {
                   1190:        p = parse_power(p, q, &entry->vpp1);
                   1191:        if (p == NULL) return CS_BAD_TUPLE;
                   1192:     } else
                   1193:        entry->vpp1.present = 0;
                   1194:     if ((features & 3) > 2) {
                   1195:        p = parse_power(p, q, &entry->vpp2);
                   1196:        if (p == NULL) return CS_BAD_TUPLE;
                   1197:     } else
                   1198:        entry->vpp2.present = 0;
                   1199: 
                   1200:     /* I/O window options */
                   1201:     if (features & 0x08) {
                   1202:        if (p == q) return CS_BAD_TUPLE;
                   1203:        entry->io = *p; p++;
                   1204:     } else
                   1205:        entry->io = 0;
                   1206:     
                   1207:     /* Interrupt options */
                   1208:     if (features & 0x10) {
                   1209:        p = parse_irq(p, q, &entry->irq);
                   1210:        if (p == NULL) return CS_BAD_TUPLE;
                   1211:     } else
                   1212:        entry->irq.IRQInfo1 = 0;
                   1213: 
                   1214:     if (features & 0x20) {
                   1215:        if (p == q) return CS_BAD_TUPLE;
                   1216:        entry->mem = *p; p++;
                   1217:     } else
                   1218:        entry->mem = 0;
                   1219: 
                   1220:     /* Misc features */
                   1221:     if (features & 0x80) {
                   1222:        if (p == q) return CS_BAD_TUPLE;
                   1223:        entry->flags |= (*p << 8);
                   1224:        if (*p & 0x80) {
                   1225:            if (++p == q) return CS_BAD_TUPLE;
                   1226:            entry->flags |= (*p << 16);
                   1227:        }
                   1228:        while (*p & 0x80)
                   1229:            if (++p == q) return CS_BAD_TUPLE;
                   1230:        p++;
                   1231:     }
                   1232: 
                   1233:     entry->subtuples = q-p;
                   1234:     
                   1235:     return CS_SUCCESS;
                   1236: }
                   1237: 
                   1238: #endif
                   1239: 
                   1240: /*====================================================================*/
                   1241: 
                   1242: static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
                   1243: {
                   1244:     u_char *p, *q;
                   1245:     int n;
                   1246: 
                   1247:     p = (u_char *)tuple->TupleData;
                   1248:     q = p + tuple->TupleDataLen;
                   1249: 
                   1250:     for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
                   1251:        if (p > q-6) break;
                   1252:        geo->geo[n].buswidth = p[0];
                   1253:        geo->geo[n].erase_block = 1 << (p[1]-1);
                   1254:        geo->geo[n].read_block  = 1 << (p[2]-1);
                   1255:        geo->geo[n].write_block = 1 << (p[3]-1);
                   1256:        geo->geo[n].partition   = 1 << (p[4]-1);
                   1257:        geo->geo[n].interleave  = 1 << (p[5]-1);
                   1258:        p += 6;
                   1259:     }
                   1260:     geo->ngeo = n;
                   1261:     return CS_SUCCESS;
                   1262: }
                   1263: 
                   1264: /*====================================================================*/
                   1265: 
                   1266: static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
                   1267: {
                   1268:     u_char *p, *q;
                   1269: 
                   1270:     if (tuple->TupleDataLen < 10)
                   1271:        return CS_BAD_TUPLE;
                   1272:     
                   1273:     p = tuple->TupleData;
                   1274:     q = p + tuple->TupleDataLen;
                   1275: 
                   1276:     v2->vers = p[0];
                   1277:     v2->comply = p[1];
                   1278:     v2->dindex = le16_to_cpu(*(u_short *)(p+2));
                   1279:     v2->vspec8 = p[6];
                   1280:     v2->vspec9 = p[7];
                   1281:     v2->nhdr = p[8];
                   1282:     p += 9;
                   1283:     return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
                   1284: }
                   1285: 
                   1286: /*====================================================================*/
                   1287: 
                   1288: static int parse_org(tuple_t *tuple, cistpl_org_t *org)
                   1289: {
                   1290:     u_char *p, *q;
                   1291:     int i;
                   1292:     
                   1293:     p = tuple->TupleData;
                   1294:     q = p + tuple->TupleDataLen;
                   1295:     if (p == q) return CS_BAD_TUPLE;
                   1296:     org->data_org = *p;
                   1297:     if (++p == q) return CS_BAD_TUPLE;
                   1298:     for (i = 0; i < 30; i++) {
                   1299:        org->desc[i] = *p;
                   1300:        if (*p == '\0') break;
                   1301:        if (++p == q) return CS_BAD_TUPLE;
                   1302:     }
                   1303:     return CS_SUCCESS;
                   1304: }
                   1305: 
                   1306: /*====================================================================*/
                   1307: 
                   1308: static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
                   1309: {
                   1310:     u_char *p;
                   1311: 
                   1312:     if (tuple->TupleDataLen < 10)
                   1313:        return CS_BAD_TUPLE;
                   1314: 
                   1315:     p = tuple->TupleData;
                   1316: 
                   1317:     fmt->type = p[0];
                   1318:     fmt->edc = p[1];
                   1319:     fmt->offset = le32_to_cpu(*(u_int *)(p+2));
                   1320:     fmt->length = le32_to_cpu(*(u_int *)(p+6));
                   1321: 
                   1322:     return CS_SUCCESS;
                   1323: }
                   1324: 
                   1325: /*====================================================================*/
                   1326: 
                   1327: int parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
                   1328: {
                   1329:     int ret = CS_SUCCESS;
                   1330:     
                   1331:     if (tuple->TupleDataLen > tuple->TupleDataMax)
                   1332:        return CS_BAD_TUPLE;
                   1333:     switch (tuple->TupleCode) {
                   1334:     case CISTPL_DEVICE:
                   1335:     case CISTPL_DEVICE_A:
                   1336:        ret = parse_device(tuple, &parse->device);
                   1337:        break;
                   1338: #ifdef CONFIG_CARDBUS
                   1339:     case CISTPL_BAR:
                   1340:        ret = parse_bar(tuple, &parse->bar);
                   1341:        break;
                   1342:     case CISTPL_CONFIG_CB:
                   1343:        ret = parse_config_cb(tuple, &parse->config);
                   1344:        break;
                   1345:     case CISTPL_CFTABLE_ENTRY_CB:
                   1346:        ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
                   1347:        break;
                   1348: #endif
                   1349:     case CISTPL_CHECKSUM:
                   1350:        ret = parse_checksum(tuple, &parse->checksum);
                   1351:        break;
                   1352:     case CISTPL_LONGLINK_A:
                   1353:     case CISTPL_LONGLINK_C:
                   1354:        ret = parse_longlink(tuple, &parse->longlink);
                   1355:        break;
                   1356:     case CISTPL_LONGLINK_MFC:
                   1357:        ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
                   1358:        break;
                   1359:     case CISTPL_VERS_1:
                   1360:        ret = parse_vers_1(tuple, &parse->version_1);
                   1361:        break;
                   1362:     case CISTPL_ALTSTR:
                   1363:        ret = parse_altstr(tuple, &parse->altstr);
                   1364:        break;
                   1365:     case CISTPL_JEDEC_A:
                   1366:     case CISTPL_JEDEC_C:
                   1367:        ret = parse_jedec(tuple, &parse->jedec);
                   1368:        break;
                   1369:     case CISTPL_MANFID:
                   1370:        ret = parse_manfid(tuple, &parse->manfid);
                   1371:        break;
                   1372:     case CISTPL_FUNCID:
                   1373:        ret = parse_funcid(tuple, &parse->funcid);
                   1374:        break;
                   1375:     case CISTPL_FUNCE:
                   1376:        ret = parse_funce(tuple, &parse->funce);
                   1377:        break;
                   1378:     case CISTPL_CONFIG:
                   1379:        ret = parse_config(tuple, &parse->config);
                   1380:        break;
                   1381:     case CISTPL_CFTABLE_ENTRY:
                   1382:        ret = parse_cftable_entry(tuple, &parse->cftable_entry);
                   1383:        break;
                   1384:     case CISTPL_DEVICE_GEO:
                   1385:     case CISTPL_DEVICE_GEO_A:
                   1386:        ret = parse_device_geo(tuple, &parse->device_geo);
                   1387:        break;
                   1388:     case CISTPL_VERS_2:
                   1389:        ret = parse_vers_2(tuple, &parse->vers_2);
                   1390:        break;
                   1391:     case CISTPL_ORG:
                   1392:        ret = parse_org(tuple, &parse->org);
                   1393:        break;
                   1394:     case CISTPL_FORMAT:
                   1395:     case CISTPL_FORMAT_A:
                   1396:        ret = parse_format(tuple, &parse->format);
                   1397:        break;
                   1398:     case CISTPL_NO_LINK:
                   1399:     case CISTPL_LINKTARGET:
                   1400:        ret = CS_SUCCESS;
                   1401:        break;
                   1402:     default:
                   1403:        ret = CS_UNSUPPORTED_FUNCTION;
                   1404:        break;
                   1405:     }
                   1406:     return ret;
                   1407: }
                   1408: 
                   1409: /*======================================================================
                   1410: 
                   1411:     This is used internally by Card Services to look up CIS stuff.
                   1412:     
                   1413: ======================================================================*/
                   1414: 
                   1415: int read_tuple(client_handle_t handle, cisdata_t code, void *parse)
                   1416: {
                   1417:     tuple_t tuple;
                   1418:     cisdata_t *buf;
                   1419:     int ret;
                   1420: 
                   1421:     buf = kmalloc(255, GFP_KERNEL);
                   1422:     if (buf == NULL)
                   1423:        return CS_OUT_OF_RESOURCE;
                   1424:     tuple.DesiredTuple = code;
                   1425:     tuple.Attributes = TUPLE_RETURN_COMMON;
                   1426:     ret = CardServices(GetFirstTuple, handle, &tuple, NULL);
                   1427:     if (ret != CS_SUCCESS) goto done;
                   1428:     tuple.TupleData = buf;
                   1429:     tuple.TupleOffset = 0;
                   1430:     tuple.TupleDataMax = 255;
                   1431:     ret = CardServices(GetTupleData, handle, &tuple, NULL);
                   1432:     if (ret != CS_SUCCESS) goto done;
                   1433:     ret = CardServices(ParseTuple, handle, &tuple, parse);
                   1434: done:
                   1435:     kfree(buf);
                   1436:     return ret;
                   1437: }
                   1438: 
                   1439: /*======================================================================
                   1440: 
                   1441:     This tries to determine if a card has a sensible CIS.  It returns
                   1442:     the number of tuples in the CIS, or 0 if the CIS looks bad.  The
                   1443:     checks include making sure several critical tuples are present and
                   1444:     valid; seeing if the total number of tuples is reasonable; and
                   1445:     looking for tuples that use reserved codes.
                   1446:     
                   1447: ======================================================================*/
                   1448: 
                   1449: int validate_cis(client_handle_t handle, cisinfo_t *info)
                   1450: {
                   1451:     tuple_t tuple;
                   1452:     cisparse_t *p;
                   1453:     int ret, reserved, dev_ok = 0, ident_ok = 0;
                   1454: 
                   1455:     if (CHECK_HANDLE(handle))
                   1456:        return CS_BAD_HANDLE;
                   1457:     p = kmalloc(sizeof(*p), GFP_KERNEL);
                   1458:     if (p == NULL)
                   1459:        return CS_OUT_OF_RESOURCE;
                   1460: 
                   1461:     info->Chains = reserved = 0;
                   1462:     tuple.DesiredTuple = RETURN_FIRST_TUPLE;
                   1463:     tuple.Attributes = TUPLE_RETURN_COMMON;
                   1464:     ret = get_first_tuple(handle, &tuple);
                   1465:     if (ret != CS_SUCCESS)
                   1466:        goto done;
                   1467: 
                   1468:     /* First tuple should be DEVICE; we should really have either that
                   1469:        or a CFTABLE_ENTRY of some sort */
                   1470:     if ((tuple.TupleCode == CISTPL_DEVICE) ||
                   1471:        (read_tuple(handle, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) ||
                   1472:        (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS))
                   1473:        dev_ok++;
                   1474: 
                   1475:     /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
                   1476:        tuple, for card identification.  Certain old D-Link and Linksys
                   1477:        cards have only a broken VERS_2 tuple; hence the bogus test. */
                   1478:     if ((read_tuple(handle, CISTPL_MANFID, p) == CS_SUCCESS) ||
                   1479:        (read_tuple(handle, CISTPL_VERS_1, p) == CS_SUCCESS) ||
                   1480:        (read_tuple(handle, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS))
                   1481:        ident_ok++;
                   1482: 
                   1483:     if (!dev_ok && !ident_ok)
                   1484:        goto done;
                   1485: 
                   1486:     for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
                   1487:        ret = get_next_tuple(handle, &tuple);
                   1488:        if (ret != CS_SUCCESS) break;
                   1489:        if (((tuple.TupleCode > 0x23) && (tuple.TupleCode < 0x40)) ||
                   1490:            ((tuple.TupleCode > 0x47) && (tuple.TupleCode < 0x80)) ||
                   1491:            ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff)))
                   1492:            reserved++;
                   1493:     }
                   1494:     if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
                   1495:        ((!dev_ok || !ident_ok) && (info->Chains > 10)))
                   1496:        info->Chains = 0;
                   1497: 
                   1498: done:
                   1499:     kfree(p);
                   1500:     return CS_SUCCESS;
                   1501: }
                   1502: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.