/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_SDCARD_SDA_IMPL_H #define _SYS_SDCARD_SDA_IMPL_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Type and structure definitions. */ typedef struct sda_slot sda_slot_t; /* * Per slot state. */ struct sda_slot { sda_host_t *s_host; void *s_prv; /* bus private data */ int s_slot_num; boolean_t s_inserted; boolean_t s_failed; uint8_t s_num_io; uint32_t s_cur_ocr; /* current ocr */ uint16_t s_rca; uint32_t s_maxclk; /* maximum freq for card */ sda_cmd_t *s_xfrp; /* pending transfer cmd */ hrtime_t s_xfrtmo; /* transfer timeout */ boolean_t s_reap; boolean_t s_warn; boolean_t s_ready; /* target node ready */ boolean_t s_init; /* slot initializing */ /* these are protected by the evlock */ boolean_t s_wake; /* wake up thread */ boolean_t s_detach; /* detach in progress */ boolean_t s_detect; /* detect event occurred */ sda_fault_t s_fault; boolean_t s_xfrdone; /* transfer event occurred */ sda_err_t s_errno; uint16_t s_flags; #define SLOTF_WRITABLE 0x0004 #define SLOTF_4BITS 0x0008 #define SLOTF_IFCOND 0x0010 #define SLOTF_MMC 0x0020 #define SLOTF_SDMEM 0x0040 #define SLOTF_SDIO 0x0080 #define SLOTF_SDHC 0x0100 #define SLOTF_MEMORY (SLOTF_MMC | SLOTF_SDMEM) #define SLOTF_SD (SLOTF_SDMEM | SLOTF_SDIO) uint16_t s_caps; #define SLOT_CAP_NOPIO 0x0002 #define SLOT_CAP_HISPEED 0x0004 #define SLOT_CAP_4BITS 0x0008 list_t s_cmdlist; list_t s_abortlist; /* * Slot operations. Slot local copy for performance. */ sda_ops_t s_ops; /* * Recursive locking of slot. */ kmutex_t s_lock; kcondvar_t s_cv; kt_did_t s_owner; /* owner holding the slot */ uint32_t s_circular; /* circular sda_slot_enter() calls */ /* * Event notification/thread wakeup. */ kmutex_t s_evlock; kcondvar_t s_evcv; /* * Asynch. threads. */ kt_did_t s_thrid; /* processing thread id */ ddi_taskq_t *s_tq; /* insert taskq */ /* * Timestamping for cfgadm benefit. */ uint8_t s_intransit; time_t s_stamp; /* * Memory card-specific. */ uint32_t s_rcsd[4]; /* raw csd */ uint32_t s_rcid[4]; /* raw cid */ uint32_t s_nblks; /* total blocks on device */ uint16_t s_blksz; /* device block size (typ. 512) */ uint16_t s_bshift; /* block address shift factor */ uint32_t s_speed; /* max memory clock in hz */ /* Other CID and CSD values */ uint32_t s_mfg; /* mfg id */ char s_prod[8]; /* product id */ char s_oem[2]; /* oem id */ uint32_t s_serial; uint8_t s_majver; uint8_t s_minver; uint16_t s_year; uint8_t s_month; uint16_t s_ccc; /* card command classes */ uint8_t s_r2w; /* read/write factor */ uint8_t s_dsr; /* DSR implemented? */ uint8_t s_perm_wp; /* permanent write protect set? */ uint8_t s_temp_wp; /* temporary write protect set? */ char s_uuid[40]; /* fabricated universal unique id */ struct b2s_nexus *s_nexus; struct b2s_leaf *s_leaf; }; _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_lock, sda_slot::s_circular)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_wake)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detach)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detect)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_fault)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_xfrdone)) _NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_errno)) _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_warn)) _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrtmo)) _NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrp)) /* * Per host state. One per devinfo node. There could be multiple * slots per devinfo node. */ struct sda_host { dev_info_t *h_dip; int h_nslot; sda_slot_t *h_slots; ddi_dma_attr_t *h_dma; /* dma attr, needed for mem */ list_node_t h_node; /* nexus node linkage */ uint32_t h_flags; #define HOST_ATTACH (1U << 0) /* host attach completed */ #define HOST_XOPEN (1U << 2) /* exclusive open */ #define HOST_SOPEN (1U << 3) /* shared open */ }; _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dip)) _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_nslot)) _NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dma)) /* * Useful function-like macros. */ #define sda_setprop(s, p, v) s->s_ops.so_setprop(s->s_prv, p, v) #define sda_getprop(s, p, v) s->s_ops.so_getprop(s->s_prv, p, v) /* * sda_cmd.c */ void sda_cmd_init(void); void sda_cmd_fini(void); void sda_cmd_list_init(list_t *); void sda_cmd_list_fini(list_t *); sda_cmd_t *sda_cmd_alloc(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t, void *, int); sda_cmd_t *sda_cmd_alloc_acmd(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t, void *, int); void sda_cmd_free(sda_cmd_t *); sda_err_t sda_cmd_errno(sda_cmd_t *); void *sda_cmd_data(sda_cmd_t *); void sda_cmd_submit(sda_slot_t *, sda_cmd_t *, void (*)(sda_cmd_t *)); void sda_cmd_resubmit_acmd(sda_slot_t *, sda_cmd_t *); void sda_cmd_notify(sda_cmd_t *, uint16_t, sda_err_t); sda_err_t sda_cmd_exec(sda_slot_t *, sda_cmd_t *, uint32_t *); /* * sda_init.c */ sda_err_t sda_init_card(sda_slot_t *); /* * sda_mem.c */ void sda_mem_init(struct modlinkage *); void sda_mem_fini(struct modlinkage *); uint32_t sda_mem_maxclk(sda_slot_t *); uint32_t sda_mem_getbits(uint32_t *, int, int); /* * sda_nexus.c */ void sda_nexus_init(void); void sda_nexus_fini(void); void sda_nexus_register(sda_host_t *); void sda_nexus_unregister(sda_host_t *); int sda_nexus_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); int sda_nexus_open(dev_t *, int, int, cred_t *); int sda_nexus_close(dev_t, int, int, cred_t *); int sda_nexus_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); int sda_nexus_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *); void sda_nexus_remove(sda_slot_t *); void sda_nexus_insert(sda_slot_t *); void sda_nexus_reap(void *); /* * sda_slot.c */ void sda_slot_init(sda_slot_t *); void sda_slot_fini(sda_slot_t *); void sda_slot_enter(sda_slot_t *); void sda_slot_exit(sda_slot_t *); boolean_t sda_slot_owned(sda_slot_t *); void sda_slot_attach(sda_slot_t *); void sda_slot_detach(sda_slot_t *); void sda_slot_reset(sda_slot_t *); void sda_slot_wakeup(sda_slot_t *); void sda_slot_detect(sda_slot_t *); int sda_slot_power_on(sda_slot_t *); void sda_slot_power_off(sda_slot_t *); void sda_slot_reset(sda_slot_t *); void sda_slot_shutdown(sda_slot_t *); void sda_slot_transfer(sda_slot_t *, sda_err_t); void sda_slot_mem_reset(sda_slot_t *, sda_err_t); void sda_slot_fault(sda_slot_t *, sda_fault_t); /*PRINTFLIKE2*/ void sda_slot_err(sda_slot_t *, const char *, ...); /*PRINTFLIKE2*/ void sda_slot_log(sda_slot_t *, const char *, ...); #ifdef DEBUG #define sda_slot_debug(...) sda_slot_log(__VA_ARGS__) #else #define sda_slot_debug(...) #endif #ifdef __cplusplus } #endif #endif /* _SYS_SDCARD_SDA_IMPL_H */