pccardvar.h revision 150098
1231057Sdim/* $NetBSD: pcmciavar.h,v 1.12 2000/02/08 12:51:31 enami Exp $ */ 2231057Sdim/* $FreeBSD: head/sys/dev/pccard/pccardvar.h 150098 2005-09-13 17:56:36Z imp $ */ 3252723Sdim 4252723Sdim/*- 5231057Sdim * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6231057Sdim * 7231057Sdim * Redistribution and use in source and binary forms, with or without 8231057Sdim * modification, are permitted provided that the following conditions 9231057Sdim * are met: 10231057Sdim * 1. Redistributions of source code must retain the above copyright 11231057Sdim * notice, this list of conditions and the following disclaimer. 12231057Sdim * 2. Redistributions in binary form must reproduce the above copyright 13231057Sdim * notice, this list of conditions and the following disclaimer in the 14231057Sdim * documentation and/or other materials provided with the distribution. 15231057Sdim * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33extern int pccard_verbose; 34 35/* 36 * PCCARD_API_LEVEL. When set to 5, we provide a 5.x compatable API 37 * for driver writers that have to share their code between 5.x and 6.x. 38 * The 5.x compatibility interfaces will be unsupported in 7.0, at which 39 * point we'll only support 6 and newer, etc. 40 */ 41#ifndef PCCARD_API_LEVEL 42#define PCCARD_API_LEVEL 6 43#elif PCCARD_API_LEVEL < 5 44#error "pccard API less than 5 unsupported" 45#endif 46 47/* 48 * Contains information about mapped/allocated i/o spaces. 49 */ 50struct pccard_io_handle { 51 bus_space_tag_t iot; /* bus space tag (from chipset) */ 52 bus_space_handle_t ioh; /* mapped space handle */ 53 bus_addr_t addr; /* resulting address in bus space */ 54 bus_size_t size; /* size of i/o space */ 55 int flags; /* misc. information */ 56 int width; 57}; 58 59#define PCCARD_IO_ALLOCATED 0x01 /* i/o space was allocated */ 60 61/* 62 * Contains information about allocated memory space. 63 */ 64struct pccard_mem_handle { 65 bus_space_tag_t memt; /* bus space tag (from chipset) */ 66 bus_space_handle_t memh; /* mapped space handle */ 67 bus_addr_t addr; /* resulting address in bus space */ 68 bus_size_t size; /* size of mem space */ 69 bus_size_t realsize; /* how much we really allocated */ 70 bus_addr_t cardaddr; /* Absolute address on card */ 71 int kind; 72}; 73 74/* pccard itself */ 75 76#define PCCARD_MEM_PAGE_SIZE 4096 77 78#define PCCARD_CFE_MWAIT_REQUIRED 0x0001 79#define PCCARD_CFE_RDYBSY_ACTIVE 0x0002 80#define PCCARD_CFE_WP_ACTIVE 0x0004 81#define PCCARD_CFE_BVD_ACTIVE 0x0008 82#define PCCARD_CFE_IO8 0x0010 83#define PCCARD_CFE_IO16 0x0020 84#define PCCARD_CFE_IRQSHARE 0x0040 85#define PCCARD_CFE_IRQPULSE 0x0080 86#define PCCARD_CFE_IRQLEVEL 0x0100 87#define PCCARD_CFE_POWERDOWN 0x0200 88#define PCCARD_CFE_READONLY 0x0400 89#define PCCARD_CFE_AUDIO 0x0800 90 91struct pccard_config_entry { 92 int number; 93 uint32_t flags; 94 int iftype; 95 int num_iospace; 96 97 /* 98 * The card will only decode this mask in any case, so we can 99 * do dynamic allocation with this in mind, in case the suggestions 100 * below are no good. 101 */ 102 u_long iomask; 103 struct { 104 u_long length; 105 u_long start; 106 } iospace[4]; /* XXX this could be as high as 16 */ 107 uint16_t irqmask; 108 int num_memspace; 109 struct { 110 u_long length; 111 u_long cardaddr; 112 u_long hostaddr; 113 } memspace[2]; /* XXX this could be as high as 8 */ 114 int maxtwins; 115 STAILQ_ENTRY(pccard_config_entry) cfe_list; 116}; 117 118struct pccard_funce_disk { 119 int pfd_interface; 120}; 121 122struct pccard_funce_lan { 123 int pfl_nidlen; 124 uint8_t pfl_nid[8]; 125}; 126 127union pccard_funce { 128 struct pccard_funce_disk pfv_disk; 129 struct pccard_funce_lan pfv_lan; 130}; 131 132struct pccard_function { 133 /* read off the card */ 134 int number; 135 int function; 136 int last_config_index; 137 uint32_t ccr_base; /* Offset with card's memory */ 138 uint32_t ccr_mask; 139 struct resource *ccr_res; 140 int ccr_rid; 141 STAILQ_HEAD(, pccard_config_entry) cfe_head; 142 STAILQ_ENTRY(pccard_function) pf_list; 143 /* run-time state */ 144 struct pccard_softc *sc; 145 struct pccard_config_entry *cfe; 146 struct pccard_mem_handle pf_pcmh; 147 device_t dev; 148#define pf_ccrt pf_pcmh.memt 149#define pf_ccrh pf_pcmh.memh 150#define pf_ccr_realsize pf_pcmh.realsize 151 uint32_t pf_ccr_offset; /* Offset from ccr_base of CIS */ 152 int pf_ccr_window; 153 bus_addr_t pf_mfc_iobase; 154 bus_addr_t pf_mfc_iomax; 155 int pf_flags; 156 driver_intr_t *intr_handler; 157 void *intr_handler_arg; 158 void *intr_handler_cookie; 159 160 union pccard_funce pf_funce; /* CISTPL_FUNCE */ 161#define pf_funce_disk_interface pf_funce.pfv_disk.pfd_interface 162#define pf_funce_lan_nid pf_funce.pfv_lan.pfl_nid 163#define pf_funce_lan_nidlen pf_funce.pfv_lan.pfl_nidlen 164}; 165 166/* pf_flags */ 167#define PFF_ENABLED 0x0001 /* function is enabled */ 168 169struct pccard_card { 170 int cis1_major; 171 int cis1_minor; 172 /* XXX waste of space? */ 173 char cis1_info_buf[256]; 174 char *cis1_info[4]; 175 /* 176 * Use int32_t for manufacturer and product so that they can 177 * hold the id value found in card CIS and special value that 178 * indicates no id was found. 179 */ 180 int32_t manufacturer; 181#define PCMCIA_VENDOR_INVALID -1 182 int32_t product; 183#define PCMCIA_PRODUCT_INVALID -1 184 int16_t prodext; 185 uint16_t error; 186#define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL } 187 STAILQ_HEAD(, pccard_function) pf_head; 188}; 189 190#define PCCARD_WIDTH_AUTO 0 191#define PCCARD_WIDTH_IO8 1 192#define PCCARD_WIDTH_IO16 2 193 194/* More later? */ 195struct pccard_ivar { 196 struct resource_list resources; 197 struct pccard_function *pf; 198}; 199 200struct pccard_softc { 201 device_t dev; 202 /* this stuff is for the socket */ 203 204 /* this stuff is for the card */ 205 struct pccard_card card; 206 int sc_enabled_count; /* num functions enabled */ 207}; 208 209struct pccard_cis_quirk { 210 int32_t manufacturer; 211 int32_t product; 212 char *cis1_info[4]; 213 struct pccard_function *pf; 214 struct pccard_config_entry *cfe; 215}; 216 217struct pccard_tuple { 218 unsigned int code; 219 unsigned int length; 220 u_long mult; 221 bus_addr_t ptr; 222 bus_space_tag_t memt; 223 bus_space_handle_t memh; 224}; 225 226typedef int (*pccard_scan_t)(const struct pccard_tuple *, void *); 227 228struct pccard_product { 229 const char *pp_name; /* NULL if end of table */ 230#define PCCARD_VENDOR_ANY (0xffffffff) 231 uint32_t pp_vendor; 232#define PCCARD_PRODUCT_ANY (0xffffffff) 233 uint32_t pp_product; 234 const char *pp_cis[4]; 235}; 236 237typedef int (*pccard_product_match_fn) (device_t dev, 238 const struct pccard_product *ent, int vpfmatch); 239 240#include "card_if.h" 241 242/* 243 * make this inline so that we don't have to worry about dangling references 244 * to it in the modules or the code. 245 */ 246static __inline const struct pccard_product * 247pccard_product_lookup(device_t dev, const struct pccard_product *tab, 248 size_t ent_size, pccard_product_match_fn matchfn) 249{ 250 return CARD_DO_PRODUCT_LOOKUP(device_get_parent(dev), dev, 251 tab, ent_size, matchfn); 252} 253 254void pccard_read_cis(struct pccard_softc *); 255void pccard_check_cis_quirks(device_t); 256void pccard_print_cis(device_t); 257int pccard_scan_cis(device_t, device_t, pccard_scan_t, void *); 258 259#define pccard_cis_read_1(tuple, idx0) \ 260 (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0))) 261 262#define pccard_tuple_read_1(tuple, idx1) \ 263 (pccard_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1))))) 264 265#define pccard_tuple_read_2(tuple, idx2) \ 266 (pccard_tuple_read_1((tuple), (idx2)) | \ 267 (pccard_tuple_read_1((tuple), (idx2)+1)<<8)) 268 269#define pccard_tuple_read_3(tuple, idx3) \ 270 (pccard_tuple_read_1((tuple), (idx3)) | \ 271 (pccard_tuple_read_1((tuple), (idx3)+1)<<8) | \ 272 (pccard_tuple_read_1((tuple), (idx3)+2)<<16)) 273 274#define pccard_tuple_read_4(tuple, idx4) \ 275 (pccard_tuple_read_1((tuple), (idx4)) | \ 276 (pccard_tuple_read_1((tuple), (idx4)+1)<<8) | \ 277 (pccard_tuple_read_1((tuple), (idx4)+2)<<16) | \ 278 (pccard_tuple_read_1((tuple), (idx4)+3)<<24)) 279 280#define pccard_tuple_read_n(tuple, n, idxn) \ 281 (((n)==1)?pccard_tuple_read_1((tuple), (idxn)) : \ 282 (((n)==2)?pccard_tuple_read_2((tuple), (idxn)) : \ 283 (((n)==3)?pccard_tuple_read_3((tuple), (idxn)) : \ 284 /* n == 4 */ pccard_tuple_read_4((tuple), (idxn))))) 285 286#define PCCARD_SPACE_MEMORY 1 287#define PCCARD_SPACE_IO 2 288 289#define pccard_mfc(sc) \ 290 (STAILQ_FIRST(&(sc)->card.pf_head) && \ 291 STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list)) 292 293/* compat layer */ 294static __inline int 295pccard_compat_probe(device_t dev) 296{ 297 return (CARD_COMPAT_DO_PROBE(device_get_parent(dev), dev)); 298} 299 300static __inline int 301pccard_compat_attach(device_t dev) 302{ 303 return (CARD_COMPAT_DO_ATTACH(device_get_parent(dev), dev)); 304} 305 306/* Convenience functions */ 307 308static __inline int 309pccard_cis_scan(device_t dev, pccard_scan_t fct, void *arg) 310{ 311 return (CARD_CIS_SCAN(device_get_parent(dev), dev, fct, arg)); 312} 313 314static __inline int 315pccard_attr_read_1(device_t dev, uint32_t offset, uint8_t *val) 316{ 317 return (CARD_ATTR_READ(device_get_parent(dev), dev, offset, val)); 318} 319 320static __inline int 321pccard_attr_write_1(device_t dev, uint32_t offset, uint8_t val) 322{ 323 return (CARD_ATTR_WRITE(device_get_parent(dev), dev, offset, val)); 324} 325 326static __inline int 327pccard_ccr_read_1(device_t dev, uint32_t offset, uint8_t *val) 328{ 329 return (CARD_CCR_READ(device_get_parent(dev), dev, offset, val)); 330} 331 332static __inline int 333pccard_ccr_write_1(device_t dev, uint32_t offset, uint8_t val) 334{ 335 return (CARD_CCR_WRITE(device_get_parent(dev), dev, offset, val)); 336} 337 338/* ivar interface */ 339enum { 340 PCCARD_IVAR_ETHADDR, /* read ethernet address from CIS tupple */ 341 PCCARD_IVAR_VENDOR, 342 PCCARD_IVAR_PRODUCT, 343 PCCARD_IVAR_PRODEXT, 344 PCCARD_IVAR_FUNCTION_NUMBER, 345 PCCARD_IVAR_VENDOR_STR, /* CIS string for "Manufacturer" */ 346 PCCARD_IVAR_PRODUCT_STR,/* CIS strnig for "Product" */ 347 PCCARD_IVAR_CIS3_STR, 348 PCCARD_IVAR_CIS4_STR, 349 PCCARD_IVAR_FUNCTION 350}; 351 352#define PCCARD_ACCESSOR(A, B, T) \ 353__inline static int \ 354pccard_get_ ## A(device_t dev, T *t) \ 355{ \ 356 return BUS_READ_IVAR(device_get_parent(dev), dev, \ 357 PCCARD_IVAR_ ## B, (uintptr_t *) t); \ 358} 359 360PCCARD_ACCESSOR(ether, ETHADDR, uint8_t) 361PCCARD_ACCESSOR(vendor, VENDOR, uint32_t) 362PCCARD_ACCESSOR(product, PRODUCT, uint32_t) 363PCCARD_ACCESSOR(prodext, PRODEXT, uint16_t) 364PCCARD_ACCESSOR(function_number,FUNCTION_NUMBER, uint32_t) 365PCCARD_ACCESSOR(function, FUNCTION, uint32_t) 366PCCARD_ACCESSOR(vendor_str, VENDOR_STR, const char *) 367PCCARD_ACCESSOR(product_str, PRODUCT_STR, const char *) 368PCCARD_ACCESSOR(cis3_str, CIS3_STR, const char *) 369PCCARD_ACCESSOR(cis4_str, CIS4_STR, const char *) 370 371/* shared memory flags */ 372enum { 373 PCCARD_A_MEM_COM, /* common */ 374 PCCARD_A_MEM_ATTR, /* attribute */ 375 PCCARD_A_MEM_8BIT, /* 8 bit */ 376 PCCARD_A_MEM_16BIT /* 16 bit */ 377}; 378 379#define PCCARD_SOFTC(d) (struct pccard_softc *) device_get_softc(d) 380#define PCCARD_IVAR(d) (struct pccard_ivar *) device_get_ivars(d) 381 382#define PCCARD_S(a, b) PCMCIA_STR_ ## a ## _ ## b 383#define PCCARD_P(a, b) PCMCIA_PRODUCT_ ## a ## _ ## b 384#define PCCARD_C(a, b) PCMCIA_CIS_ ## a ## _ ## b 385#if PCCARD_API_LEVEL >= 6 386#define PCMCIA_CARD_D(v, p) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \ 387 PCCARD_P(v, p), PCCARD_C(v, p) } 388#define PCMCIA_CARD2_D(v1, p1, p2) \ 389 { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 390 PCMCIA_CIS_ ## p2} 391#define PCMCIA_CARD(v, p) { NULL, PCMCIA_VENDOR_ ## v, \ 392 PCCARD_P(v, p), PCCARD_C(v, p) } 393#define PCMCIA_CARD2(v1, p1, p2) \ 394 { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 395 PCMCIA_CIS_ ## p2} 396#else 397#define PCMCIA_CARD_D(v, p, f) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \ 398 PCCARD_P(v, p), PCCARD_C(v, p) } 399#define PCMCIA_CARD2_D(v1, p1, p2, f) \ 400 { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 401 PCMCIA_CIS_ ## p2} 402#define PCMCIA_CARD(v, p, f) { NULL, PCMCIA_VENDOR_ ## v, \ 403 PCCARD_P(v, p), PCCARD_C(v, p) } 404#define PCMCIA_CARD2(v1, p1, p2, f) \ 405 { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ 406 PCMCIA_CIS_ ## p2} 407#endif 408