1*7302Sgdamore@opensolaris.org /* 2*7302Sgdamore@opensolaris.org * CDDL HEADER START 3*7302Sgdamore@opensolaris.org * 4*7302Sgdamore@opensolaris.org * The contents of this file are subject to the terms of the 5*7302Sgdamore@opensolaris.org * Common Development and Distribution License (the "License"). 6*7302Sgdamore@opensolaris.org * You may not use this file except in compliance with the License. 7*7302Sgdamore@opensolaris.org * 8*7302Sgdamore@opensolaris.org * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7302Sgdamore@opensolaris.org * or http://www.opensolaris.org/os/licensing. 10*7302Sgdamore@opensolaris.org * See the License for the specific language governing permissions 11*7302Sgdamore@opensolaris.org * and limitations under the License. 12*7302Sgdamore@opensolaris.org * 13*7302Sgdamore@opensolaris.org * When distributing Covered Code, include this CDDL HEADER in each 14*7302Sgdamore@opensolaris.org * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7302Sgdamore@opensolaris.org * If applicable, add the following below this CDDL HEADER, with the 16*7302Sgdamore@opensolaris.org * fields enclosed by brackets "[]" replaced with your own identifying 17*7302Sgdamore@opensolaris.org * information: Portions Copyright [yyyy] [name of copyright owner] 18*7302Sgdamore@opensolaris.org * 19*7302Sgdamore@opensolaris.org * CDDL HEADER END 20*7302Sgdamore@opensolaris.org */ 21*7302Sgdamore@opensolaris.org /* 22*7302Sgdamore@opensolaris.org * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7302Sgdamore@opensolaris.org * Use is subject to license terms. 24*7302Sgdamore@opensolaris.org */ 25*7302Sgdamore@opensolaris.org 26*7302Sgdamore@opensolaris.org #ifndef _SYS_SDCARD_SDA_IMPL_H 27*7302Sgdamore@opensolaris.org #define _SYS_SDCARD_SDA_IMPL_H 28*7302Sgdamore@opensolaris.org 29*7302Sgdamore@opensolaris.org #include <sys/list.h> 30*7302Sgdamore@opensolaris.org #include <sys/ksynch.h> 31*7302Sgdamore@opensolaris.org #include <sys/note.h> 32*7302Sgdamore@opensolaris.org #include <sys/ddi.h> 33*7302Sgdamore@opensolaris.org #include <sys/sunddi.h> 34*7302Sgdamore@opensolaris.org #include <sys/sdcard/sda.h> 35*7302Sgdamore@opensolaris.org 36*7302Sgdamore@opensolaris.org #ifdef __cplusplus 37*7302Sgdamore@opensolaris.org extern "C" { 38*7302Sgdamore@opensolaris.org #endif 39*7302Sgdamore@opensolaris.org 40*7302Sgdamore@opensolaris.org /* 41*7302Sgdamore@opensolaris.org * Type and structure definitions. 42*7302Sgdamore@opensolaris.org */ 43*7302Sgdamore@opensolaris.org typedef struct sda_slot sda_slot_t; 44*7302Sgdamore@opensolaris.org 45*7302Sgdamore@opensolaris.org /* 46*7302Sgdamore@opensolaris.org * Per slot state. 47*7302Sgdamore@opensolaris.org */ 48*7302Sgdamore@opensolaris.org struct sda_slot { 49*7302Sgdamore@opensolaris.org sda_host_t *s_host; 50*7302Sgdamore@opensolaris.org void *s_prv; /* bus private data */ 51*7302Sgdamore@opensolaris.org 52*7302Sgdamore@opensolaris.org int s_slot_num; 53*7302Sgdamore@opensolaris.org boolean_t s_inserted; 54*7302Sgdamore@opensolaris.org boolean_t s_failed; 55*7302Sgdamore@opensolaris.org uint8_t s_num_io; 56*7302Sgdamore@opensolaris.org uint32_t s_cur_ocr; /* current ocr */ 57*7302Sgdamore@opensolaris.org 58*7302Sgdamore@opensolaris.org uint16_t s_rca; 59*7302Sgdamore@opensolaris.org uint32_t s_maxclk; /* maximum freq for card */ 60*7302Sgdamore@opensolaris.org 61*7302Sgdamore@opensolaris.org sda_cmd_t *s_xfrp; /* pending transfer cmd */ 62*7302Sgdamore@opensolaris.org hrtime_t s_xfrtmo; /* transfer timeout */ 63*7302Sgdamore@opensolaris.org 64*7302Sgdamore@opensolaris.org boolean_t s_reap; 65*7302Sgdamore@opensolaris.org boolean_t s_warn; 66*7302Sgdamore@opensolaris.org boolean_t s_ready; /* target node ready */ 67*7302Sgdamore@opensolaris.org boolean_t s_init; /* slot initializing */ 68*7302Sgdamore@opensolaris.org 69*7302Sgdamore@opensolaris.org /* these are protected by the evlock */ 70*7302Sgdamore@opensolaris.org boolean_t s_wake; /* wake up thread */ 71*7302Sgdamore@opensolaris.org boolean_t s_detach; /* detach in progress */ 72*7302Sgdamore@opensolaris.org boolean_t s_detect; /* detect event occurred */ 73*7302Sgdamore@opensolaris.org sda_fault_t s_fault; 74*7302Sgdamore@opensolaris.org boolean_t s_xfrdone; /* transfer event occurred */ 75*7302Sgdamore@opensolaris.org sda_err_t s_errno; 76*7302Sgdamore@opensolaris.org 77*7302Sgdamore@opensolaris.org uint16_t s_flags; 78*7302Sgdamore@opensolaris.org #define SLOTF_WRITABLE 0x0004 79*7302Sgdamore@opensolaris.org #define SLOTF_4BITS 0x0008 80*7302Sgdamore@opensolaris.org #define SLOTF_IFCOND 0x0010 81*7302Sgdamore@opensolaris.org #define SLOTF_MMC 0x0020 82*7302Sgdamore@opensolaris.org #define SLOTF_SDMEM 0x0040 83*7302Sgdamore@opensolaris.org #define SLOTF_SDIO 0x0080 84*7302Sgdamore@opensolaris.org #define SLOTF_SDHC 0x0100 85*7302Sgdamore@opensolaris.org #define SLOTF_MEMORY (SLOTF_MMC | SLOTF_SDMEM) 86*7302Sgdamore@opensolaris.org #define SLOTF_SD (SLOTF_SDMEM | SLOTF_SDIO) 87*7302Sgdamore@opensolaris.org 88*7302Sgdamore@opensolaris.org uint16_t s_caps; 89*7302Sgdamore@opensolaris.org #define SLOT_CAP_NOPIO 0x0002 90*7302Sgdamore@opensolaris.org #define SLOT_CAP_HISPEED 0x0004 91*7302Sgdamore@opensolaris.org #define SLOT_CAP_4BITS 0x0008 92*7302Sgdamore@opensolaris.org 93*7302Sgdamore@opensolaris.org list_t s_cmdlist; 94*7302Sgdamore@opensolaris.org list_t s_abortlist; 95*7302Sgdamore@opensolaris.org 96*7302Sgdamore@opensolaris.org /* 97*7302Sgdamore@opensolaris.org * Slot operations. Slot local copy for performance. 98*7302Sgdamore@opensolaris.org */ 99*7302Sgdamore@opensolaris.org sda_ops_t s_ops; 100*7302Sgdamore@opensolaris.org 101*7302Sgdamore@opensolaris.org /* 102*7302Sgdamore@opensolaris.org * Recursive locking of slot. 103*7302Sgdamore@opensolaris.org */ 104*7302Sgdamore@opensolaris.org kmutex_t s_lock; 105*7302Sgdamore@opensolaris.org kcondvar_t s_cv; 106*7302Sgdamore@opensolaris.org kt_did_t s_owner; /* owner holding the slot */ 107*7302Sgdamore@opensolaris.org uint32_t s_circular; /* circular sda_slot_enter() calls */ 108*7302Sgdamore@opensolaris.org 109*7302Sgdamore@opensolaris.org /* 110*7302Sgdamore@opensolaris.org * Event notification/thread wakeup. 111*7302Sgdamore@opensolaris.org */ 112*7302Sgdamore@opensolaris.org kmutex_t s_evlock; 113*7302Sgdamore@opensolaris.org kcondvar_t s_evcv; 114*7302Sgdamore@opensolaris.org 115*7302Sgdamore@opensolaris.org /* 116*7302Sgdamore@opensolaris.org * Asynch. threads. 117*7302Sgdamore@opensolaris.org */ 118*7302Sgdamore@opensolaris.org kt_did_t s_thrid; /* processing thread id */ 119*7302Sgdamore@opensolaris.org ddi_taskq_t *s_tq; /* insert taskq */ 120*7302Sgdamore@opensolaris.org 121*7302Sgdamore@opensolaris.org /* 122*7302Sgdamore@opensolaris.org * Timestamping for cfgadm benefit. 123*7302Sgdamore@opensolaris.org */ 124*7302Sgdamore@opensolaris.org uint8_t s_intransit; 125*7302Sgdamore@opensolaris.org time_t s_stamp; 126*7302Sgdamore@opensolaris.org 127*7302Sgdamore@opensolaris.org /* 128*7302Sgdamore@opensolaris.org * Memory card-specific. 129*7302Sgdamore@opensolaris.org */ 130*7302Sgdamore@opensolaris.org uint32_t s_rcsd[4]; /* raw csd */ 131*7302Sgdamore@opensolaris.org uint32_t s_rcid[4]; /* raw cid */ 132*7302Sgdamore@opensolaris.org uint32_t s_nblks; /* total blocks on device */ 133*7302Sgdamore@opensolaris.org uint16_t s_blksz; /* device block size (typ. 512) */ 134*7302Sgdamore@opensolaris.org uint16_t s_bshift; /* block address shift factor */ 135*7302Sgdamore@opensolaris.org uint32_t s_speed; /* max memory clock in hz */ 136*7302Sgdamore@opensolaris.org 137*7302Sgdamore@opensolaris.org /* Other CID and CSD values */ 138*7302Sgdamore@opensolaris.org uint32_t s_mfg; /* mfg id */ 139*7302Sgdamore@opensolaris.org char s_prod[8]; /* product id */ 140*7302Sgdamore@opensolaris.org char s_oem[2]; /* oem id */ 141*7302Sgdamore@opensolaris.org uint32_t s_serial; 142*7302Sgdamore@opensolaris.org uint8_t s_majver; 143*7302Sgdamore@opensolaris.org uint8_t s_minver; 144*7302Sgdamore@opensolaris.org uint16_t s_year; 145*7302Sgdamore@opensolaris.org uint8_t s_month; 146*7302Sgdamore@opensolaris.org 147*7302Sgdamore@opensolaris.org uint16_t s_ccc; /* card command classes */ 148*7302Sgdamore@opensolaris.org uint8_t s_r2w; /* read/write factor */ 149*7302Sgdamore@opensolaris.org uint8_t s_dsr; /* DSR implemented? */ 150*7302Sgdamore@opensolaris.org uint8_t s_perm_wp; /* permanent write protect set? */ 151*7302Sgdamore@opensolaris.org uint8_t s_temp_wp; /* temporary write protect set? */ 152*7302Sgdamore@opensolaris.org 153*7302Sgdamore@opensolaris.org char s_uuid[40]; /* fabricated universal unique id */ 154*7302Sgdamore@opensolaris.org 155*7302Sgdamore@opensolaris.org struct b2s_nexus *s_nexus; 156*7302Sgdamore@opensolaris.org struct b2s_leaf *s_leaf; 157*7302Sgdamore@opensolaris.org }; 158*7302Sgdamore@opensolaris.org 159*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_lock, sda_slot::s_circular)) 160*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_wake)) 161*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detach)) 162*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detect)) 163*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_fault)) 164*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_xfrdone)) 165*7302Sgdamore@opensolaris.org _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_errno)) 166*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_warn)) 167*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrtmo)) 168*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrp)) 169*7302Sgdamore@opensolaris.org 170*7302Sgdamore@opensolaris.org /* 171*7302Sgdamore@opensolaris.org * Per host state. One per devinfo node. There could be multiple 172*7302Sgdamore@opensolaris.org * slots per devinfo node. 173*7302Sgdamore@opensolaris.org */ 174*7302Sgdamore@opensolaris.org struct sda_host { 175*7302Sgdamore@opensolaris.org dev_info_t *h_dip; 176*7302Sgdamore@opensolaris.org int h_nslot; 177*7302Sgdamore@opensolaris.org sda_slot_t *h_slots; 178*7302Sgdamore@opensolaris.org ddi_dma_attr_t *h_dma; /* dma attr, needed for mem */ 179*7302Sgdamore@opensolaris.org 180*7302Sgdamore@opensolaris.org list_node_t h_node; /* nexus node linkage */ 181*7302Sgdamore@opensolaris.org 182*7302Sgdamore@opensolaris.org uint32_t h_flags; 183*7302Sgdamore@opensolaris.org #define HOST_ATTACH (1U << 0) /* host attach completed */ 184*7302Sgdamore@opensolaris.org #define HOST_XOPEN (1U << 2) /* exclusive open */ 185*7302Sgdamore@opensolaris.org #define HOST_SOPEN (1U << 3) /* shared open */ 186*7302Sgdamore@opensolaris.org }; 187*7302Sgdamore@opensolaris.org 188*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dip)) 189*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_nslot)) 190*7302Sgdamore@opensolaris.org _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dma)) 191*7302Sgdamore@opensolaris.org 192*7302Sgdamore@opensolaris.org /* 193*7302Sgdamore@opensolaris.org * Useful function-like macros. 194*7302Sgdamore@opensolaris.org */ 195*7302Sgdamore@opensolaris.org #define sda_setprop(s, p, v) s->s_ops.so_setprop(s->s_prv, p, v) 196*7302Sgdamore@opensolaris.org #define sda_getprop(s, p, v) s->s_ops.so_getprop(s->s_prv, p, v) 197*7302Sgdamore@opensolaris.org 198*7302Sgdamore@opensolaris.org /* 199*7302Sgdamore@opensolaris.org * sda_cmd.c 200*7302Sgdamore@opensolaris.org */ 201*7302Sgdamore@opensolaris.org void sda_cmd_init(void); 202*7302Sgdamore@opensolaris.org void sda_cmd_fini(void); 203*7302Sgdamore@opensolaris.org void sda_cmd_list_init(list_t *); 204*7302Sgdamore@opensolaris.org void sda_cmd_list_fini(list_t *); 205*7302Sgdamore@opensolaris.org sda_cmd_t *sda_cmd_alloc(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t, 206*7302Sgdamore@opensolaris.org void *, int); 207*7302Sgdamore@opensolaris.org sda_cmd_t *sda_cmd_alloc_acmd(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t, 208*7302Sgdamore@opensolaris.org void *, int); 209*7302Sgdamore@opensolaris.org void sda_cmd_free(sda_cmd_t *); 210*7302Sgdamore@opensolaris.org sda_err_t sda_cmd_errno(sda_cmd_t *); 211*7302Sgdamore@opensolaris.org void *sda_cmd_data(sda_cmd_t *); 212*7302Sgdamore@opensolaris.org void sda_cmd_submit(sda_slot_t *, sda_cmd_t *, void (*)(sda_cmd_t *)); 213*7302Sgdamore@opensolaris.org void sda_cmd_resubmit_acmd(sda_slot_t *, sda_cmd_t *); 214*7302Sgdamore@opensolaris.org void sda_cmd_notify(sda_cmd_t *, uint16_t, sda_err_t); 215*7302Sgdamore@opensolaris.org sda_err_t sda_cmd_exec(sda_slot_t *, sda_cmd_t *, uint32_t *); 216*7302Sgdamore@opensolaris.org 217*7302Sgdamore@opensolaris.org /* 218*7302Sgdamore@opensolaris.org * sda_init.c 219*7302Sgdamore@opensolaris.org */ 220*7302Sgdamore@opensolaris.org sda_err_t sda_init_card(sda_slot_t *); 221*7302Sgdamore@opensolaris.org 222*7302Sgdamore@opensolaris.org /* 223*7302Sgdamore@opensolaris.org * sda_mem.c 224*7302Sgdamore@opensolaris.org */ 225*7302Sgdamore@opensolaris.org void sda_mem_init(struct modlinkage *); 226*7302Sgdamore@opensolaris.org void sda_mem_fini(struct modlinkage *); 227*7302Sgdamore@opensolaris.org uint32_t sda_mem_maxclk(sda_slot_t *); 228*7302Sgdamore@opensolaris.org uint32_t sda_mem_getbits(uint32_t *, int, int); 229*7302Sgdamore@opensolaris.org 230*7302Sgdamore@opensolaris.org 231*7302Sgdamore@opensolaris.org /* 232*7302Sgdamore@opensolaris.org * sda_nexus.c 233*7302Sgdamore@opensolaris.org */ 234*7302Sgdamore@opensolaris.org void sda_nexus_init(void); 235*7302Sgdamore@opensolaris.org void sda_nexus_fini(void); 236*7302Sgdamore@opensolaris.org void sda_nexus_register(sda_host_t *); 237*7302Sgdamore@opensolaris.org void sda_nexus_unregister(sda_host_t *); 238*7302Sgdamore@opensolaris.org int sda_nexus_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 239*7302Sgdamore@opensolaris.org int sda_nexus_open(dev_t *, int, int, cred_t *); 240*7302Sgdamore@opensolaris.org int sda_nexus_close(dev_t, int, int, cred_t *); 241*7302Sgdamore@opensolaris.org int sda_nexus_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 242*7302Sgdamore@opensolaris.org int sda_nexus_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, 243*7302Sgdamore@opensolaris.org void *); 244*7302Sgdamore@opensolaris.org void sda_nexus_remove(sda_slot_t *); 245*7302Sgdamore@opensolaris.org void sda_nexus_insert(sda_slot_t *); 246*7302Sgdamore@opensolaris.org void sda_nexus_reap(void *); 247*7302Sgdamore@opensolaris.org 248*7302Sgdamore@opensolaris.org /* 249*7302Sgdamore@opensolaris.org * sda_slot.c 250*7302Sgdamore@opensolaris.org */ 251*7302Sgdamore@opensolaris.org void sda_slot_init(sda_slot_t *); 252*7302Sgdamore@opensolaris.org void sda_slot_fini(sda_slot_t *); 253*7302Sgdamore@opensolaris.org void sda_slot_enter(sda_slot_t *); 254*7302Sgdamore@opensolaris.org void sda_slot_exit(sda_slot_t *); 255*7302Sgdamore@opensolaris.org boolean_t sda_slot_owned(sda_slot_t *); 256*7302Sgdamore@opensolaris.org void sda_slot_attach(sda_slot_t *); 257*7302Sgdamore@opensolaris.org void sda_slot_detach(sda_slot_t *); 258*7302Sgdamore@opensolaris.org void sda_slot_reset(sda_slot_t *); 259*7302Sgdamore@opensolaris.org void sda_slot_wakeup(sda_slot_t *); 260*7302Sgdamore@opensolaris.org void sda_slot_detect(sda_slot_t *); 261*7302Sgdamore@opensolaris.org int sda_slot_power_on(sda_slot_t *); 262*7302Sgdamore@opensolaris.org void sda_slot_power_off(sda_slot_t *); 263*7302Sgdamore@opensolaris.org void sda_slot_reset(sda_slot_t *); 264*7302Sgdamore@opensolaris.org void sda_slot_shutdown(sda_slot_t *); 265*7302Sgdamore@opensolaris.org void sda_slot_transfer(sda_slot_t *, sda_err_t); 266*7302Sgdamore@opensolaris.org void sda_slot_mem_reset(sda_slot_t *, sda_err_t); 267*7302Sgdamore@opensolaris.org void sda_slot_fault(sda_slot_t *, sda_fault_t); 268*7302Sgdamore@opensolaris.org /*PRINTFLIKE2*/ 269*7302Sgdamore@opensolaris.org void sda_slot_err(sda_slot_t *, const char *, ...); 270*7302Sgdamore@opensolaris.org /*PRINTFLIKE2*/ 271*7302Sgdamore@opensolaris.org void sda_slot_log(sda_slot_t *, const char *, ...); 272*7302Sgdamore@opensolaris.org 273*7302Sgdamore@opensolaris.org #ifdef DEBUG 274*7302Sgdamore@opensolaris.org #define sda_slot_debug(...) sda_slot_log(__VA_ARGS__) 275*7302Sgdamore@opensolaris.org #else 276*7302Sgdamore@opensolaris.org #define sda_slot_debug(...) 277*7302Sgdamore@opensolaris.org #endif 278*7302Sgdamore@opensolaris.org 279*7302Sgdamore@opensolaris.org #ifdef __cplusplus 280*7302Sgdamore@opensolaris.org } 281*7302Sgdamore@opensolaris.org #endif 282*7302Sgdamore@opensolaris.org 283*7302Sgdamore@opensolaris.org #endif /* _SYS_SDCARD_SDA_IMPL_H */ 284