Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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