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