pccardvar.h revision 150098
139213Sgibbs/* $NetBSD: pcmciavar.h,v 1.12 2000/02/08 12:51:31 enami Exp $ */ 239213Sgibbs/* $FreeBSD: head/sys/dev/pccard/pccardvar.h 150098 2005-09-13 17:56:36Z imp $ */ 339213Sgibbs 439213Sgibbs/*- 539213Sgibbs * Copyright (c) 1997 Marc Horowitz. All rights reserved. 639213Sgibbs * 739213Sgibbs * Redistribution and use in source and binary forms, with or without 839213Sgibbs * modification, are permitted provided that the following conditions 939213Sgibbs * are met: 1039213Sgibbs * 1. Redistributions of source code must retain the above copyright 1139213Sgibbs * notice, this list of conditions and the following disclaimer. 1239213Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1339213Sgibbs * notice, this list of conditions and the following disclaimer in the 1439213Sgibbs * documentation and/or other materials provided with the distribution. 1539213Sgibbs * 3. All advertising materials mentioning features or use of this software 1639213Sgibbs * must display the following acknowledgement: 1739213Sgibbs * This product includes software developed by Marc Horowitz. 1839213Sgibbs * 4. The name of the author may not be used to endorse or promote products 1939213Sgibbs * derived from this software without specific prior written permission. 2039213Sgibbs * 2139213Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2239213Sgibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2339213Sgibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2439213Sgibbs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2539213Sgibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2639213Sgibbs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2739213Sgibbs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2850477Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2939213Sgibbs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3039213Sgibbs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3139213Sgibbs */ 3239213Sgibbs 3339213Sgibbsextern int pccard_verbose; 3439213Sgibbs 3539213Sgibbs/* 3660041Sphk * PCCARD_API_LEVEL. When set to 5, we provide a 5.x compatable API 3739213Sgibbs * for driver writers that have to share their code between 5.x and 6.x. 3839213Sgibbs * The 5.x compatibility interfaces will be unsupported in 7.0, at which 3939213Sgibbs * point we'll only support 6 and newer, etc. 4050073Sken */ 4139213Sgibbs#ifndef PCCARD_API_LEVEL 4239213Sgibbs#define PCCARD_API_LEVEL 6 4339213Sgibbs#elif PCCARD_API_LEVEL < 5 4439213Sgibbs#error "pccard API less than 5 unsupported" 4539213Sgibbs#endif 4639213Sgibbs 4739213Sgibbs/* 4839213Sgibbs * Contains information about mapped/allocated i/o spaces. 4939213Sgibbs */ 5039213Sgibbsstruct pccard_io_handle { 5139213Sgibbs bus_space_tag_t iot; /* bus space tag (from chipset) */ 5250073Sken bus_space_handle_t ioh; /* mapped space handle */ 5350073Sken bus_addr_t addr; /* resulting address in bus space */ 5439213Sgibbs bus_size_t size; /* size of i/o space */ 5539213Sgibbs int flags; /* misc. information */ 5639213Sgibbs int width; 5739213Sgibbs}; 5839213Sgibbs 5939213Sgibbs#define PCCARD_IO_ALLOCATED 0x01 /* i/o space was allocated */ 6039213Sgibbs 6139213Sgibbs/* 6239213Sgibbs * Contains information about allocated memory space. 6339213Sgibbs */ 6439213Sgibbsstruct pccard_mem_handle { 6539213Sgibbs bus_space_tag_t memt; /* bus space tag (from chipset) */ 6639213Sgibbs bus_space_handle_t memh; /* mapped space handle */ 6739213Sgibbs bus_addr_t addr; /* resulting address in bus space */ 6839213Sgibbs bus_size_t size; /* size of mem space */ 6939213Sgibbs bus_size_t realsize; /* how much we really allocated */ 7039213Sgibbs bus_addr_t cardaddr; /* Absolute address on card */ 7139213Sgibbs int kind; 7239213Sgibbs}; 7339213Sgibbs 7439213Sgibbs/* pccard itself */ 7539213Sgibbs 7639213Sgibbs#define PCCARD_MEM_PAGE_SIZE 4096 7739213Sgibbs 7859249Sphk#define PCCARD_CFE_MWAIT_REQUIRED 0x0001 79112006Sphk#define PCCARD_CFE_RDYBSY_ACTIVE 0x0002 8060938Sjake#define PCCARD_CFE_WP_ACTIVE 0x0004 8139213Sgibbs#define PCCARD_CFE_BVD_ACTIVE 0x0008 8239213Sgibbs#define PCCARD_CFE_IO8 0x0010 8339213Sgibbs#define PCCARD_CFE_IO16 0x0020 8450073Sken#define PCCARD_CFE_IRQSHARE 0x0040 8553257Sken#define PCCARD_CFE_IRQPULSE 0x0080 8639213Sgibbs#define PCCARD_CFE_IRQLEVEL 0x0100 8739213Sgibbs#define PCCARD_CFE_POWERDOWN 0x0200 8839213Sgibbs#define PCCARD_CFE_READONLY 0x0400 8939213Sgibbs#define PCCARD_CFE_AUDIO 0x0800 9039213Sgibbs 9139213Sgibbsstruct pccard_config_entry { 9239213Sgibbs int number; 9339213Sgibbs uint32_t flags; 9439213Sgibbs int iftype; 9540603Sken int num_iospace; 9639213Sgibbs 9739213Sgibbs /* 9839213Sgibbs * The card will only decode this mask in any case, so we can 9939213Sgibbs * do dynamic allocation with this in mind, in case the suggestions 10050073Sken * below are no good. 10139213Sgibbs */ 10239213Sgibbs u_long iomask; 10339213Sgibbs struct { 10439213Sgibbs u_long length; 10539213Sgibbs u_long start; 10639213Sgibbs } iospace[4]; /* XXX this could be as high as 16 */ 10739213Sgibbs uint16_t irqmask; 10839213Sgibbs int num_memspace; 10939213Sgibbs struct { 11039213Sgibbs u_long length; 11139213Sgibbs u_long cardaddr; 11239213Sgibbs u_long hostaddr; 11339213Sgibbs } memspace[2]; /* XXX this could be as high as 8 */ 11439213Sgibbs int maxtwins; 11539213Sgibbs STAILQ_ENTRY(pccard_config_entry) cfe_list; 11672119Speter}; 11739213Sgibbs 11839213Sgibbsstruct pccard_funce_disk { 11939213Sgibbs int pfd_interface; 12047625Sphk}; 121111815Sphk 122111815Sphkstruct pccard_funce_lan { 123111815Sphk int pfl_nidlen; 124111815Sphk uint8_t pfl_nid[8]; 125111815Sphk}; 126111815Sphk 127111815Sphkunion pccard_funce { 128111815Sphk struct pccard_funce_disk pfv_disk; 12939213Sgibbs struct pccard_funce_lan pfv_lan; 13039213Sgibbs}; 13150073Sken 13250073Skenstruct pccard_function { 13350073Sken /* read off the card */ 13450073Sken int number; 13539213Sgibbs int function; 13683366Sjulian int last_config_index; 13739213Sgibbs uint32_t ccr_base; /* Offset with card's memory */ 13839213Sgibbs uint32_t ccr_mask; 13939213Sgibbs struct resource *ccr_res; 14039213Sgibbs int ccr_rid; 14139213Sgibbs STAILQ_HEAD(, pccard_config_entry) cfe_head; 14240603Sken STAILQ_ENTRY(pccard_function) pf_list; 14339213Sgibbs /* run-time state */ 14439213Sgibbs struct pccard_softc *sc; 145101940Snjl struct pccard_config_entry *cfe; 14639213Sgibbs struct pccard_mem_handle pf_pcmh; 14739213Sgibbs device_t dev; 14839213Sgibbs#define pf_ccrt pf_pcmh.memt 14939213Sgibbs#define pf_ccrh pf_pcmh.memh 15039213Sgibbs#define pf_ccr_realsize pf_pcmh.realsize 15140603Sken uint32_t pf_ccr_offset; /* Offset from ccr_base of CIS */ 15240603Sken int pf_ccr_window; 15340603Sken bus_addr_t pf_mfc_iobase; 15440603Sken bus_addr_t pf_mfc_iomax; 15540603Sken int pf_flags; 15640603Sken driver_intr_t *intr_handler; 15739213Sgibbs void *intr_handler_arg; 15849982Sbillf void *intr_handler_cookie; 15939213Sgibbs 16041297Sken union pccard_funce pf_funce; /* CISTPL_FUNCE */ 16141297Sken#define pf_funce_disk_interface pf_funce.pfv_disk.pfd_interface 16239213Sgibbs#define pf_funce_lan_nid pf_funce.pfv_lan.pfl_nid 16341297Sken#define pf_funce_lan_nidlen pf_funce.pfv_lan.pfl_nidlen 16439213Sgibbs}; 16541297Sken 16641297Sken/* pf_flags */ 16739213Sgibbs#define PFF_ENABLED 0x0001 /* function is enabled */ 16839213Sgibbs 16939213Sgibbsstruct pccard_card { 17039213Sgibbs int cis1_major; 17139213Sgibbs int cis1_minor; 17239213Sgibbs /* XXX waste of space? */ 17339213Sgibbs char cis1_info_buf[256]; 17439213Sgibbs char *cis1_info[4]; 17539213Sgibbs /* 17639213Sgibbs * Use int32_t for manufacturer and product so that they can 17739213Sgibbs * hold the id value found in card CIS and special value that 17839213Sgibbs * indicates no id was found. 17939213Sgibbs */ 18083366Sjulian int32_t manufacturer; 18139213Sgibbs#define PCMCIA_VENDOR_INVALID -1 18239213Sgibbs int32_t product; 18339213Sgibbs#define PCMCIA_PRODUCT_INVALID -1 18439213Sgibbs int16_t prodext; 18539213Sgibbs uint16_t error; 186101940Snjl#define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL } 18739213Sgibbs STAILQ_HEAD(, pccard_function) pf_head; 18839213Sgibbs}; 18939213Sgibbs 19039213Sgibbs#define PCCARD_WIDTH_AUTO 0 19139213Sgibbs#define PCCARD_WIDTH_IO8 1 19239213Sgibbs#define PCCARD_WIDTH_IO16 2 19339213Sgibbs 19439213Sgibbs/* More later? */ 19539213Sgibbsstruct pccard_ivar { 19639213Sgibbs struct resource_list resources; 19739213Sgibbs struct pccard_function *pf; 19839213Sgibbs}; 19939213Sgibbs 20039213Sgibbsstruct pccard_softc { 20139213Sgibbs device_t dev; 20239213Sgibbs /* this stuff is for the socket */ 20339213Sgibbs 20439213Sgibbs /* this stuff is for the card */ 20539213Sgibbs struct pccard_card card; 20639213Sgibbs int sc_enabled_count; /* num functions enabled */ 20759249Sphk}; 20839213Sgibbs 20939213Sgibbsstruct pccard_cis_quirk { 21039213Sgibbs int32_t manufacturer; 21139213Sgibbs int32_t product; 21239213Sgibbs char *cis1_info[4]; 213101940Snjl struct pccard_function *pf; 21476362Sphk struct pccard_config_entry *cfe; 21539213Sgibbs}; 21676362Sphk 21776362Sphkstruct pccard_tuple { 21839213Sgibbs unsigned int code; 21939213Sgibbs unsigned int length; 22039213Sgibbs u_long mult; 22139213Sgibbs bus_addr_t ptr; 22239213Sgibbs bus_space_tag_t memt; 22339213Sgibbs bus_space_handle_t memh; 22439213Sgibbs}; 22539213Sgibbs 22639213Sgibbstypedef int (*pccard_scan_t)(const struct pccard_tuple *, void *); 22739213Sgibbs 22839213Sgibbsstruct pccard_product { 22939213Sgibbs const char *pp_name; /* NULL if end of table */ 23039213Sgibbs#define PCCARD_VENDOR_ANY (0xffffffff) 23139213Sgibbs uint32_t pp_vendor; 23239213Sgibbs#define PCCARD_PRODUCT_ANY (0xffffffff) 23376362Sphk uint32_t pp_product; 23476362Sphk const char *pp_cis[4]; 23539213Sgibbs}; 23639213Sgibbs 23739213Sgibbstypedef int (*pccard_product_match_fn) (device_t dev, 23839213Sgibbs const struct pccard_product *ent, int vpfmatch); 23939213Sgibbs 24059249Sphk#include "card_if.h" 24139213Sgibbs 24239213Sgibbs/* 24339213Sgibbs * make this inline so that we don't have to worry about dangling references 24439213Sgibbs * to it in the modules or the code. 24539213Sgibbs */ 24639213Sgibbsstatic __inline const struct pccard_product * 24739213Sgibbspccard_product_lookup(device_t dev, const struct pccard_product *tab, 24839213Sgibbs size_t ent_size, pccard_product_match_fn matchfn) 24939213Sgibbs{ 25039213Sgibbs return CARD_DO_PRODUCT_LOOKUP(device_get_parent(dev), dev, 25139213Sgibbs tab, ent_size, matchfn); 25239213Sgibbs} 25339213Sgibbs 25439213Sgibbsvoid pccard_read_cis(struct pccard_softc *); 25539213Sgibbsvoid pccard_check_cis_quirks(device_t); 25639213Sgibbsvoid pccard_print_cis(device_t); 25739213Sgibbsint pccard_scan_cis(device_t, device_t, pccard_scan_t, void *); 25839213Sgibbs 25939213Sgibbs#define pccard_cis_read_1(tuple, idx0) \ 26039213Sgibbs (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0))) 26139213Sgibbs 26239213Sgibbs#define pccard_tuple_read_1(tuple, idx1) \ 26339213Sgibbs (pccard_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1))))) 26439213Sgibbs 26539213Sgibbs#define pccard_tuple_read_2(tuple, idx2) \ 26639213Sgibbs (pccard_tuple_read_1((tuple), (idx2)) | \ 26739213Sgibbs (pccard_tuple_read_1((tuple), (idx2)+1)<<8)) 26839213Sgibbs 26939213Sgibbs#define pccard_tuple_read_3(tuple, idx3) \ 27039213Sgibbs (pccard_tuple_read_1((tuple), (idx3)) | \ 27139213Sgibbs (pccard_tuple_read_1((tuple), (idx3)+1)<<8) | \ 27239213Sgibbs (pccard_tuple_read_1((tuple), (idx3)+2)<<16)) 27339213Sgibbs 27439213Sgibbs#define pccard_tuple_read_4(tuple, idx4) \ 27539213Sgibbs (pccard_tuple_read_1((tuple), (idx4)) | \ 27639213Sgibbs (pccard_tuple_read_1((tuple), (idx4)+1)<<8) | \ 27739213Sgibbs (pccard_tuple_read_1((tuple), (idx4)+2)<<16) | \ 27839213Sgibbs (pccard_tuple_read_1((tuple), (idx4)+3)<<24)) 27939213Sgibbs 28039213Sgibbs#define pccard_tuple_read_n(tuple, n, idxn) \ 28139213Sgibbs (((n)==1)?pccard_tuple_read_1((tuple), (idxn)) : \ 28239213Sgibbs (((n)==2)?pccard_tuple_read_2((tuple), (idxn)) : \ 28339213Sgibbs (((n)==3)?pccard_tuple_read_3((tuple), (idxn)) : \ 28439213Sgibbs /* n == 4 */ pccard_tuple_read_4((tuple), (idxn))))) 28539213Sgibbs 28639213Sgibbs#define PCCARD_SPACE_MEMORY 1 28739213Sgibbs#define PCCARD_SPACE_IO 2 28839213Sgibbs 28939213Sgibbs#define pccard_mfc(sc) \ 29039213Sgibbs (STAILQ_FIRST(&(sc)->card.pf_head) && \ 29139213Sgibbs STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list)) 29239213Sgibbs 29339213Sgibbs/* compat layer */ 29439213Sgibbsstatic __inline int 29539213Sgibbspccard_compat_probe(device_t dev) 29639213Sgibbs{ 29739213Sgibbs return (CARD_COMPAT_DO_PROBE(device_get_parent(dev), dev)); 29839213Sgibbs} 29939213Sgibbs 30039213Sgibbsstatic __inline int 30139213Sgibbspccard_compat_attach(device_t dev) 30239213Sgibbs{ 30339213Sgibbs return (CARD_COMPAT_DO_ATTACH(device_get_parent(dev), dev)); 30439213Sgibbs} 30539213Sgibbs 30639213Sgibbs/* Convenience functions */ 30739213Sgibbs 30839213Sgibbsstatic __inline int 30939213Sgibbspccard_cis_scan(device_t dev, pccard_scan_t fct, void *arg) 31039213Sgibbs{ 31139213Sgibbs return (CARD_CIS_SCAN(device_get_parent(dev), dev, fct, arg)); 31239213Sgibbs} 31359249Sphk 31439213Sgibbsstatic __inline int 31550073Skenpccard_attr_read_1(device_t dev, uint32_t offset, uint8_t *val) 31650073Sken{ 31739213Sgibbs return (CARD_ATTR_READ(device_get_parent(dev), dev, offset, val)); 31839213Sgibbs} 319112006Sphk 32039213Sgibbsstatic __inline int 32139213Sgibbspccard_attr_write_1(device_t dev, uint32_t offset, uint8_t val) 32256148Smjacob{ 32343819Sken return (CARD_ATTR_WRITE(device_get_parent(dev), dev, offset, val)); 32439213Sgibbs} 32553257Sken 32653257Skenstatic __inline int 32753257Skenpccard_ccr_read_1(device_t dev, uint32_t offset, uint8_t *val) 328101940Snjl{ 329101940Snjl return (CARD_CCR_READ(device_get_parent(dev), dev, offset, val)); 33039213Sgibbs} 33139213Sgibbs 33239213Sgibbsstatic __inline int 33339213Sgibbspccard_ccr_write_1(device_t dev, uint32_t offset, uint8_t val) 33439213Sgibbs{ 33539213Sgibbs return (CARD_CCR_WRITE(device_get_parent(dev), dev, offset, val)); 33639213Sgibbs} 33739213Sgibbs 33839213Sgibbs/* ivar interface */ 33939213Sgibbsenum { 34039213Sgibbs PCCARD_IVAR_ETHADDR, /* read ethernet address from CIS tupple */ 34139213Sgibbs PCCARD_IVAR_VENDOR, 34239213Sgibbs PCCARD_IVAR_PRODUCT, 34339213Sgibbs PCCARD_IVAR_PRODEXT, 34439213Sgibbs PCCARD_IVAR_FUNCTION_NUMBER, 34539213Sgibbs PCCARD_IVAR_VENDOR_STR, /* CIS string for "Manufacturer" */ 34639213Sgibbs PCCARD_IVAR_PRODUCT_STR,/* CIS strnig for "Product" */ 34739213Sgibbs PCCARD_IVAR_CIS3_STR, 34839213Sgibbs PCCARD_IVAR_CIS4_STR, 34939213Sgibbs PCCARD_IVAR_FUNCTION 35039213Sgibbs}; 35139213Sgibbs 35240603Sken#define PCCARD_ACCESSOR(A, B, T) \ 35340603Sken__inline static int \ 35440603Skenpccard_get_ ## A(device_t dev, T *t) \ 35540603Sken{ \ 35640603Sken return BUS_READ_IVAR(device_get_parent(dev), dev, \ 35740603Sken PCCARD_IVAR_ ## B, (uintptr_t *) t); \ 35840603Sken} 35940603Sken 36040603SkenPCCARD_ACCESSOR(ether, ETHADDR, uint8_t) 36140603SkenPCCARD_ACCESSOR(vendor, VENDOR, uint32_t) 36240603SkenPCCARD_ACCESSOR(product, PRODUCT, uint32_t) 36340603SkenPCCARD_ACCESSOR(prodext, PRODEXT, uint16_t) 36440603SkenPCCARD_ACCESSOR(function_number,FUNCTION_NUMBER, uint32_t) 36540603SkenPCCARD_ACCESSOR(function, FUNCTION, uint32_t) 36640603SkenPCCARD_ACCESSOR(vendor_str, VENDOR_STR, const char *) 36740603SkenPCCARD_ACCESSOR(product_str, PRODUCT_STR, const char *) 36840603SkenPCCARD_ACCESSOR(cis3_str, CIS3_STR, const char *) 36940603SkenPCCARD_ACCESSOR(cis4_str, CIS4_STR, const char *) 37040603Sken 37140603Sken/* shared memory flags */ 37240603Skenenum { 37340603Sken PCCARD_A_MEM_COM, /* common */ 37440603Sken PCCARD_A_MEM_ATTR, /* attribute */ 37540603Sken PCCARD_A_MEM_8BIT, /* 8 bit */ 37640603Sken PCCARD_A_MEM_16BIT /* 16 bit */ 37740603Sken}; 37840603Sken 37940603Sken#define PCCARD_SOFTC(d) (struct pccard_softc *) device_get_softc(d) 38040603Sken#define PCCARD_IVAR(d) (struct pccard_ivar *) device_get_ivars(d) 38140603Sken 38240603Sken#define PCCARD_S(a, b) PCMCIA_STR_ ## a ## _ ## b 38340603Sken#define PCCARD_P(a, b) PCMCIA_PRODUCT_ ## a ## _ ## b 38440603Sken#define PCCARD_C(a, b) PCMCIA_CIS_ ## a ## _ ## b 385112946Sphk#if PCCARD_API_LEVEL >= 6 38640603Sken#define PCMCIA_CARD_D(v, p) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \ 38740603Sken PCCARD_P(v, p), PCCARD_C(v, p) } 38840603Sken#define PCMCIA_CARD2_D(v1, p1, p2) \ 38940603Sken { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 39040603Sken PCMCIA_CIS_ ## p2} 39140603Sken#define PCMCIA_CARD(v, p) { NULL, PCMCIA_VENDOR_ ## v, \ 39240603Sken PCCARD_P(v, p), PCCARD_C(v, p) } 39340603Sken#define PCMCIA_CARD2(v1, p1, p2) \ 39439213Sgibbs { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 39539213Sgibbs PCMCIA_CIS_ ## p2} 39640603Sken#else 39740603Sken#define PCMCIA_CARD_D(v, p, f) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \ 39840603Sken PCCARD_P(v, p), PCCARD_C(v, p) } 39940603Sken#define PCMCIA_CARD2_D(v1, p1, p2, f) \ 400112006Sphk { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 40140603Sken PCMCIA_CIS_ ## p2} 40253257Sken#define PCMCIA_CARD(v, p, f) { NULL, PCMCIA_VENDOR_ ## v, \ 40353257Sken PCCARD_P(v, p), PCCARD_C(v, p) } 40439213Sgibbs#define PCMCIA_CARD2(v1, p1, p2, f) \ 40539213Sgibbs { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 40640603Sken PCMCIA_CIS_ ## p2} 40739213Sgibbs#endif 40839213Sgibbs