1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * PCMCIA nexus
  29  */
  30 
  31 #ifndef _PCMCIA_H
  32 #define _PCMCIA_H
  33 
  34 #pragma ident   "%Z%%M% %I%     %E% SMI"
  35 
  36 #ifdef  __cplusplus
  37 extern "C" {
  38 #endif
  39 
  40 #if defined(DEBUG)
  41 #define PCMCIA_DEBUG
  42 #endif
  43 
  44 #include <sys/modctl.h>
  45 
  46 #define PCMCIA_MAX_ADAPTERS     8 /* maximum distinct adapters */
  47 #define PCMCIA_MAX_SOCKETS      64 /* maximum distinct sockets */
  48 #define PCMCIA_MAX_WIN_ADAPT    40
  49 #define PCMCIA_MAX_WINDOWS      (PCMCIA_MAX_ADAPTERS*PCMCIA_MAX_WIN_ADAPT)
  50 #define PCMCIA_MAX_POWER        16 /* maximum power table entries */
  51 
  52 #define _VERSION(major, minor)  ((major)<<16|(minor))
  53 
  54 /*
  55  * DDI/Nexus stuff
  56  */
  57 
  58 #define PCMCIA_NEXUS_NAME       "pcmcia"
  59 #define PCMCIA_ADAPTER_NODE     "ddi_pcmcia:adapter"
  60 #define PCMCIA_SOCKET_NODE      "ddi_pcmcia:socket"
  61 #define PCMCIA_PCCARD_NODE      "ddi_pcmcia:pccard"
  62 
  63 /*
  64  * private interface between nexus and adapter specific driver
  65  * This is only an "ops" type structure
  66  */
  67 
  68 typedef struct pcmcia_if {
  69         uint32_t  pcif_magic;   /* magic number to verify correct scructure */
  70         uint32_t  pcif_version;
  71         int     (*pcif_set_callback)();
  72         int     (*pcif_get_adapter)();
  73         int     (*pcif_get_page)();
  74         int     (*pcif_get_socket)();
  75         int     (*pcif_get_status)();
  76         int     (*pcif_get_window)();
  77         int     (*pcif_inquire_adapter)();
  78         int     (*pcif_inquire_socket)();
  79         int     (*pcif_inquire_window)();
  80         int     (*pcif_reset_socket)();
  81         int     (*pcif_set_page)();
  82         int     (*pcif_set_window)();
  83         int     (*pcif_set_socket)();
  84         int     (*pcif_set_interrupt)();
  85         int     (*pcif_clr_interrupt)();
  86         int     (*pcic_init_dev)();
  87         uint32_t  (*pcic_get_tstamp)();
  88 } pcmcia_if_t;
  89 
  90 /*
  91  * magic number and version information to identify
  92  * variant of the PCMCIA nexus.
  93  */
  94 #define PCIF_MAGIC 0x50434946
  95 #define PCIF_VERSION    _VERSION(0, 1)
  96 #define PCIF_MIN_VERSION _VERSION(0, 1)
  97 #define DEFAULT_CS_NAME "cs"
  98 
  99 /*
 100  * all adapter drivers use a commonly defined structure for
 101  * their private data.  This structure must be filled in
 102  * and set.  The an_private member is for the driver writer's
 103  * use and is not looked at by the nexus.
 104  */
 105 struct pcmcia_adapter_nexus_private {
 106         dev_info_t      *an_dip;
 107         pcmcia_if_t     *an_if;
 108         void            *an_private;
 109         ddi_iblock_cookie_t *an_iblock; /* high priority handler cookies */
 110         ddi_idevice_cookie_t *an_idev;
 111         uint32_t        an_ipl;
 112 };
 113 
 114 typedef struct pcmcia_adapter_nexus_private anp_t;
 115 
 116 struct pcm_regs {
 117         uint32_t phys_hi;
 118         uint32_t phys_lo;
 119         uint32_t phys_len;
 120 };
 121 
 122 /*
 123  * shared interrupts are handled by the
 124  * nexus going through the list
 125  */
 126 typedef struct inthandler {
 127         struct inthandler       *next;
 128         struct inthandler       *prev;
 129         int                     flags;
 130         uint32_t                (*intr)(caddr_t, caddr_t);
 131         unsigned                handler_id;
 132         void                    *arg1;
 133         void                    *arg2;
 134         unsigned                socket;
 135         unsigned                irq;
 136         unsigned                priority;
 137         ddi_softintr_t          softid;
 138         ddi_iblock_cookie_t     iblk_cookie;
 139         ddi_idevice_cookie_t    idev_cookie;
 140 } inthandler_t;
 141 
 142 /*
 143  * parent private data area
 144  *      not using the old style but will adapt on request
 145  *      this allows better framework handling and 1275 compliance
 146  */
 147 
 148 struct pcmcia_parent_private {
 149         int     ppd_nreg;       /* number of regs */
 150         struct  pcm_regs *ppd_reg; /* array of regs in parsed form */
 151         int     ppd_intr;       /* number intrspecs (always 0 or 1) */
 152         struct  intrspec *ppd_intrspec;
 153         void    *pcm_dummy[3];  /* fill for prtconf -v */
 154         struct  pcm_regs *ppd_assigned; /* array of regs in parsed form */
 155         short   ppd_socket;     /* socket number of this instance */
 156         short   ppd_function;   /* function number */
 157         int     ppd_active;     /* is PC Card in a socket and active */
 158         uint32_t  ppd_flags;
 159         void    *ppd_handle; /* client handle */
 160 };
 161 
 162 #define PPD_CARD_MULTI          0x0001 /* card is multifunction card */
 163 #define PPD_CARD_CARDBUS        0x0002 /* card is CardBus type */
 164 #define PPD_CB_BUSMASTER        0x0004 /* card bus card is busmaster */
 165 #define PPD_SUSPENDED           0x0008 /* this device was pm suspended */
 166 
 167 /*
 168  * macros to make indirect functions easier
 169  * and shorter (makes cstyle happier)
 170  */
 171 
 172 #define GET_SOCKET_STATUS(f, dip, sock, stat)\
 173                         (*(f)->pcif_get_socket_status)(dip, sock, stat)
 174 #define SET_CALLBACK(f, dip, callback, sock)\
 175                         (*(f)->pcif_set_callback)(dip, callback, sock)
 176 
 177 #define GET_ADAPTER(f, dip, conf) (*(f)->pcif_get_adapter) (dip, conf)
 178 #define GET_SOCKET(f, dip, sock) (*(f)->pcif_get_socket)(dip, sock)
 179 #define GET_STATUS(f, dip, status) (*(f)->pcif_get_status)(dip, status)
 180 #define GET_WINDOW(f, dip, window) (*(f)->pcif_get_window)(dip, window)
 181 #define INQUIRE_ADAPTER(f, dip, inquire) (*(f)->pcif_inquire_adapter)(dip,\
 182                                                 inquire)
 183 #define GET_CONFIG(f, dip, conf) INQUIRE_ADAPTER(f, dip, conf)
 184 #define INQUIRE_SOCKET(f, dip, sock) (*(f)->pcif_inquire_socket)(dip, \
 185                                                 sock)
 186 #define GET_PAGE(f, dip, page) (*(f)->pcif_get_page)(dip, page)
 187 #define INQUIRE_WINDOW(f, dip, window) (*(f)->pcif_inquire_window)(dip, window)
 188 #define RESET_SOCKET(f, dip, socket, mode) \
 189                         (*(f)->pcif_reset_socket)(dip, socket, mode)
 190 #define SET_PAGE(f, dip, page) (*(f)->pcif_set_page)(dip, page)
 191 #define SET_WINDOW(f, dip, window) (*(f)->pcif_set_window)(dip, window)
 192 #define SET_SOCKET(f, dip, socket) (*(f)->pcif_set_socket)(dip, socket)
 193 #define SET_IRQ(f, dip, handler) (*(f)->pcif_set_interrupt)(dip, handler)
 194 #define CLEAR_IRQ(f, dip, handler) (*(f)->pcif_clr_interrupt)(dip, handler)
 195 
 196 typedef struct pcmcia_cs {
 197         uint32_t   pccs_magic;  /* magic number of verify correct structure */
 198         uint32_t   pccs_version;
 199         int   (*pccs_callback)();
 200         int   (*pccs_getconfig)();
 201 } pcmcia_cs_t;
 202 
 203 #define PCCS_MAGIC      0x50434353
 204 #define PCCS_VERSION    _VERSION(2, 1)
 205 
 206 /* properties used by the nexus for setup */
 207 #define ADAPT_PROP      "adapters"      /* property used to find adapter list */
 208 #define CS_PROP         "card-services" /* property specifying Card Services */
 209 #define DEF_DRV_PROP    "default-driver" /* default driver to load if no CIS */
 210 
 211 /*
 212  * per adapter structure
 213  * this structure defines everything necessary for the
 214  * the nexus to interact with the adapter specific driver
 215  */
 216 
 217 struct pcmcia_adapter {
 218         int             pca_module;     /* adapter major number */
 219         int             pca_unit;       /* adapter minor number */
 220         int             pca_number;     /* canonical adapter number */
 221         struct dev_ops  *pca_ops;
 222         dev_info_t      *pca_dip;
 223         pcmcia_if_t     *pca_if;
 224         void            *pca_power;
 225         ddi_iblock_cookie_t *pca_iblock;
 226         ddi_idevice_cookie_t *pca_idev;
 227         kmutex_t        *pca_mutex;
 228         int             pca_numpower;
 229         int             pca_numsockets;
 230         int             pca_first_socket;
 231         uint32_t        pca_flags;
 232         char            pca_name[MODMAXNAMELEN];
 233         uint32_t        pca_avail_intr;
 234         inthandler_t    pca_int_handlers;
 235 };
 236 
 237 #define PCA_RES_NEED_IRQ        0x0001 /* needs IRQ allocation */
 238 #define PCA_RES_NEED_IO         0x0002 /* needs I/O allocation */
 239 #define PCA_RES_NEED_MEM        0x0004 /* needs memory allocation */
 240 #define PCA_RES_CONSTRAINT      0x0008 /* resource constraints defined */
 241 #define PCA_IRQ_SMI_SHARE       0x0010 /* SMI and child share */
 242 #define PCA_IRQ_SHAREABLE       0x0020 /* all interrupts sharable */
 243 #define PCA_IRQ_ISA             0x0040 /* ISA style (host) interrupts */
 244 
 245 /* These flags are for open/close -- hot-plug support in future */
 246 #define PCMCIA_MAX_FUNCTIONS    8
 247 #define PCS_CARD_PRESENT        0x0001 /* card in socket */
 248 #define PCS_MULTI_FUNCTION      0x0002 /* indicates dip is multifunction */
 249 #define PCS_SOCKET_ADDED        0x0004 /* CS knows about the socket */
 250 #define PCS_COOKIES_VALID       0x0008 /* iblk and idev valid */
 251 #define PCS_IRQ_ENABLED         0x0010 /* IRQ has been enabled */
 252 #define PCS_SUSPENDED           0x0020 /* PM SUSPEND was done */
 253 
 254 typedef struct pcmcia_logical_window {
 255         int                     lw_window; /* window number */
 256         int                     lw_socket; /* logical socket number assigned */
 257         struct pcmcia_adapter   *lw_adapter;
 258         pcmcia_if_t             *lw_if;
 259         uint32_t                lw_status;
 260         baseaddr_t              lw_base;
 261         int                     lw_len;
 262 } pcmcia_logical_window_t;
 263 
 264 #define PCS_ENABLED             0x0002 /* window is enabled */
 265 
 266 /*
 267  * management interface hook
 268  */
 269 #define EM_EVENTSIZE    4
 270 struct pcmcia_mif {
 271         struct pcmcia_mif *mif_next;
 272         void            (*mif_function)();
 273         uint32_t          mif_id;
 274         uchar_t           mif_events[EM_EVENTSIZE]; /* events registered for */
 275 };
 276 
 277 #define PR_WORDSIZE     8       /* bits in word */
 278 #define PR_MASK         0x7
 279 #define PR_GET(map, bit)        (((uchar_t *)(map))[(bit)/PR_WORDSIZE] &\
 280                                         (1 << ((bit) & PR_MASK)))
 281 #define PR_SET(map, bit)        (((uchar_t *)(map))[(bit)/PR_WORDSIZE] |=\
 282                                         (1 << ((bit) & PR_MASK)))
 283 #define PR_CLEAR(map, bit)      (((uchar_t *)(map))[(bit)/PR_WORDSIZE] &=\
 284                                         ~(1 << ((bit) & PR_MASK)))
 285 #define PR_ADDR(map, bit)       (((uchar_t *)(map)) + ((bit)/PR_WORDSIZE))
 286 #define PR_ZERO(map)            bzero((caddr_t)map, sizeof (map))
 287 
 288 /* socket bit map */
 289 typedef uchar_t socket_enum_t[PCMCIA_MAX_SOCKETS/PR_WORDSIZE];
 290 
 291 /*
 292  * Max resoruce limits - all of these have to be power-of-2 aligned
 293  *      and the PR_MAX_IO_LEN and PR_MAX_MEM_LEN values must be at
 294  *      least 64 or the allocators will panic.
 295  */
 296 #define PR_MAX_IO_LEN           1024    /* bytes of IO space */
 297 #define PR_MAX_IO_RANGES        4
 298 #define PR_MAX_MEM_LEN          1024 /* pages or 4M bytes */
 299 #define PR_MAX_MEM_RANGES       32
 300 
 301 #define PR_MAX_IOADDR           0xffffffff
 302 #define PR_MAX_MEMADDR          0xffffffff
 303 #define PR_MAX_INTERRUPTS       0xff
 304 
 305 
 306 /*
 307  * structures and definitions used in the private interface
 308  */
 309 
 310 /* general values */
 311 #define PC_SUCCESS      1
 312 #define PC_FAILURE      0
 313 
 314 /* set_mem() */
 315 #define PC_MEM_AM       0
 316 #define PC_MEM_CM       1
 317 
 318 /* device classes */
 319 #define PCC_MULTI       0
 320 #define PCC_MEMORY      1
 321 #define PCC_SERIAL      2
 322 #define PCC_PARALLEL    3
 323 #define PCC_FIXED_DISK  4
 324 #define PCC_VIDEO       5
 325 #define PCC_LAN         6
 326 
 327 /*
 328  * device information structure information
 329  * this is what is used for initial construction of a device node
 330  */
 331 
 332 struct pcm_device_info {
 333         int             pd_socket;
 334         int             pd_function;
 335         int             pd_type;
 336         uint32_t        pd_handle;
 337         uint32_t        pd_tuples;
 338         uint32_t        pd_flags;
 339         char            pd_bind_name[MODMAXNAMELEN];
 340         char            pd_vers1_name[MODMAXNAMELEN*4];
 341         char            pd_generic_name[MODMAXNAMELEN];
 342 };
 343 
 344 #define PCM_GET_SOCKET(socknum)         ((socknum) & 0x1F)
 345 #define PCM_GET_FUNCTION(socknum)       (((socknum) >> 5) & 0x7)
 346 
 347 #define PCM_DEFAULT_NODEID              (-1)
 348 #define PCM_DEV_MODEL   "model"
 349 #define PCM_DEV_ACTIVE  "card-active"
 350 #define PCM_DEV_SOCKET  "socket"
 351 #define PCM_DEV_R2TYPE  "16bitcard"
 352 #define PCM_DEV_CARDBUS "cardbus"
 353 
 354 typedef
 355 struct init_dev {
 356         int     socket;
 357 } init_dev_t;
 358 
 359 /*
 360  * device descriptions
 361  * used to determine what driver to associate with a PC Card
 362  * so that automatic creation of device information trees can
 363  * be supported.
 364  */
 365 
 366 typedef
 367 struct pcm_device_node {
 368         struct pcm_device_node *pd_next;
 369         dev_info_t *pd_dip;     /* proto device info */
 370         char    pd_name[16];
 371         int     pd_flags;
 372         int     pd_devtype;     /* from device tuple */
 373         int     pd_funcid;
 374         int     pd_manfid;
 375         int     pd_manmask;
 376 } pcm_dev_node_t;
 377 
 378 #define PCMD_DEVTYPE    0x0001  /* match device type */
 379 #define PCMD_FUNCID     0x0002  /* match function ID */
 380 #define PCMD_MANFID     0x0004  /* match manufacturer ID */
 381 #define PCMD_FUNCE      0x0008  /* match function extension */
 382 #define PCMD_VERS1      0x0010  /* match VERSION_1 string(s) */
 383 #define PCMD_JEDEC      0x0020  /* JEDEC ID */
 384 
 385 #define PCM_NAME_1275           0x0001
 386 #define PCM_NAME_VERS1          0x0002
 387 #define PCM_NAME_GENERIC        0x0004
 388 #define PCM_NO_CONFIG           0x0008
 389 #define PCM_OTHER_NOCIS         0x0100
 390 #define PCM_MULTI_FUNCTION      0x0200
 391 
 392 #define PCM_MAX_R2_MEM          0x3ffffff
 393 
 394 #define PCMDEV_PREFIX   "PC,"
 395 #define PCMDEV_NAMEPREF "pccard"
 396 
 397 /* property names */
 398 #define PCM_PROP_DEVICE "device"
 399 #define PCM_PROP_FUNCID "funcid"
 400 
 401 /* 1275 specific properties */
 402 #define PCM_1275_NUMWIN         "#windows"
 403 #define PCM_1275_NUMSOCK        "#sockets"
 404 #define PCM_1275_SCIC           "status-change-int_caps"
 405 
 406 /* basic device types */
 407 
 408 #define PCM_TYPE_MULTI          0
 409 #define PCM_TYPE_MEMORY         1
 410 #define PCM_TYPE_SERIAL         2
 411 #define PCM_TYPE_PARALLEL       3
 412 #define PCM_TYPE_FIXED          4
 413 #define PCM_TYPE_VIDEO          5
 414 #define PCM_TYPE_LAN            6
 415 
 416 
 417 typedef
 418 struct string_to_int {
 419         char *sti_str;
 420         uint32_t sti_int;
 421 } str_int_t;
 422 
 423 /*
 424  * PCMCIA nexus/adapter specific ioctl commands
 425  */
 426 
 427 #define PCIOC   ('P' << 8)
 428 /* SS is temporary until design done */
 429 #define PC_SS_CMD(cmd)          (PCIOC|(cmd))
 430 
 431 /* stuff that used to be in obpdefs.h but no longer */
 432 #define PCM_DEVICETYPE  "device_type"
 433 
 434 /*
 435  * new regspec and other 1275 stuff
 436  */
 437 #define PC_REG_RELOC(x)         ((((uint32_t)x) & 0x1) << 31)
 438 #define PC_REG_PREFETCH(x)      (((x) & 0x1) << 30)
 439 #define PC_REG_TYPE(x)          (((x) & 0x1) << 29)
 440 #define PC_REG_SPACE(x)         (((x) & 0x7) << 24)
 441 #define PC_REG_SOCKET(x)        (((x) & 0x1f) << 11)
 442 #define PC_REG_FUNCTION(x)      (((x) & 0x7) << 8)
 443 #define PC_REG_BASEREG(x)       ((x) & 0xff)
 444 /* solaris internal only */
 445 #define PC_REG_REFCNT(x)        (((x) & 0xFF) << 16)
 446 
 447 #define PC_GET_REG_RELOC(x)     (((x) >> 31) & 1)
 448 #define PC_GET_REG_PREFETCH(x)  (((x) >> 30) & 1)
 449 #define PC_GET_REG_TYPE(x)      (((x) >> 29) & 1)
 450 #define PC_GET_REG_SPACE(x)     (((x) >> 24) & 7)
 451 #define PC_GET_REG_SOCKET(x)    (((x) >> 11) & 0x1f)
 452 #define PC_GET_REG_FUNCTION(x)  (((x) >> 8) & 0x7)
 453 #define PC_GET_REG_BASEREG(x)   ((x) & 0xff)
 454 /* solaris internal only */
 455 #define PC_GET_REG_REFCNT(x)    (((x) >> 16) & 0xFF)
 456 #define PC_INCR_REFCNT(x)       (((x) & 0xFF00FFFF) | \
 457                                     PC_REG_REFCNT(PC_GET_REG_REFCNT(x) + 1))
 458 #define PC_DECR_REFCNT(x)       (((x) & 0xFF00FFFF) | \
 459                                     PC_REG_REFCNT(PC_GET_REG_REFCNT(x) - 1))
 460 
 461 #define PC_REG_PHYS_HI(n, p, t, c, s, f, r) (uint32_t)( \
 462                         PC_REG_RELOC(n) | \
 463                         PC_REG_PREFETCH(p) | \
 464                         PC_REG_TYPE(t) | \
 465                         PC_REG_SPACE(c) | \
 466                         PC_REG_SOCKET(s) | \
 467                         PC_REG_FUNCTION(f) | \
 468                         PC_REG_BASEREG(r))
 469 
 470 #define PC_REG_TYPE_CARDBUS     0
 471 #define PC_REG_TYPE_16BIT       1
 472 
 473 #define PC_REG_SPACE_CONFIG     0x0
 474 #define PC_REG_SPACE_IO         0x1
 475 #define PC_REG_SPACE_MEMORY     0x2
 476 #define PC_REG_SPACE_ATTRIBUTE  0x4
 477 
 478 /*
 479  * internal properties and other prop_op defines
 480  */
 481 
 482 #define PCMCIA_PROP_UNKNOWN     0x10000 /* pass to DDI decode */
 483 #define PCMCIA_PROP_CIS         0x20000 /* need to get the tuple */
 484 
 485         /* specific known properties */
 486 #define PCMCIA_PROP_SOCKET      0 /* "socket" */
 487 #define PCMCIA_PROP_COMPAT      1 /* "compatible" */
 488 #define PCMCIA_PROP_DEFAULT_PM  2 /* power managment timestamp */
 489 #define PCMCIA_PROP_ACTIVE      3 /* card-active property */
 490 #define PCMCIA_PROP_R2TYPE      4 /* 16 bit card */
 491 #define PCMCIA_PROP_CARDBUS     5 /* card is cardbus */
 492 #define PCMCIA_PROP_OLDCS       6 /* old card services property */
 493 #define PCMCIA_PROP_REG         7 /* standard reg= property */
 494 #define PCMCIA_PROP_INTR        8 /* interrupts property */
 495 
 496 #ifdef  __cplusplus
 497 }
 498 #endif
 499 
 500 #endif  /* _PCMCIA_H */