sda_impl.h revision 12426:cdff5d2ea989
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#ifndef	_SYS_SDCARD_SDA_IMPL_H
26#define	_SYS_SDCARD_SDA_IMPL_H
27
28#include <sys/list.h>
29#include <sys/ksynch.h>
30#include <sys/note.h>
31#include <sys/blkdev.h>
32#include <sys/ddi.h>
33#include <sys/sunddi.h>
34#include <sys/sdcard/sda.h>
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40/*
41 * Type and structure definitions.
42 */
43typedef struct sda_slot sda_slot_t;
44
45/*
46 * Per slot state.
47 */
48struct 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
57	uint8_t		s_num_io;
58	uint32_t	s_cur_ocr;		/* current ocr */
59
60	uint16_t	s_rca;
61	uint32_t	s_maxclk;		/* maximum freq for card */
62
63	sda_cmd_t	*s_xfrp;		/* pending transfer cmd */
64	hrtime_t	s_xfrtmo;		/* transfer timeout */
65
66	boolean_t	s_reap;
67	boolean_t	s_warn;
68	boolean_t	s_ready;		/* target node ready */
69	boolean_t	s_init;			/* slot initializing */
70
71	/* these are protected by the evlock */
72	boolean_t	s_wake;			/* wake up thread */
73	boolean_t	s_detach;		/* detach in progress */
74	boolean_t	s_suspend;		/* host has DDI_SUSPENDed */
75	boolean_t	s_detect;		/* detect event occurred */
76	sda_fault_t	s_fault;
77	boolean_t	s_xfrdone;		/* transfer event occurred */
78	sda_err_t	s_errno;
79
80	uint16_t	s_flags;
81#define	SLOTF_WRITABLE		0x0004
82#define	SLOTF_4BITS		0x0008
83#define	SLOTF_IFCOND		0x0010
84#define	SLOTF_MMC		0x0020
85#define	SLOTF_SDMEM		0x0040
86#define	SLOTF_SDIO		0x0080
87#define	SLOTF_SDHC		0x0100
88#define	SLOTF_MEMORY		(SLOTF_MMC | SLOTF_SDMEM)
89#define	SLOTF_SD		(SLOTF_SDMEM | SLOTF_SDIO)
90
91	uint16_t	s_caps;
92#define	SLOT_CAP_NOPIO		0x0002
93#define	SLOT_CAP_HISPEED	0x0004
94#define	SLOT_CAP_4BITS		0x0008
95
96	list_t		s_cmdlist;
97	list_t		s_abortlist;
98
99	/*
100	 * Slot operations.  Slot local copy for performance.
101	 */
102	sda_ops_t	s_ops;
103
104	/*
105	 * Recursive locking of slot.
106	 */
107	kmutex_t	s_lock;
108	kcondvar_t	s_cv;
109	kt_did_t	s_owner;	/* owner holding the slot */
110	uint32_t	s_circular;	/* circular sda_slot_enter() calls */
111
112	/*
113	 * Event notification/thread wakeup.
114	 */
115	kmutex_t	s_evlock;
116	kcondvar_t	s_evcv;
117
118	/*
119	 * Asynch. threads.
120	 */
121	ddi_taskq_t	*s_hp_tq;	/* insert taskq */
122	ddi_taskq_t	*s_main_tq;	/* main processing taskq */
123
124	/*
125	 * Timestamping for cfgadm benefit.
126	 */
127	uint8_t		s_intransit;
128	time_t		s_stamp;
129
130	/*
131	 * Memory card-specific.
132	 */
133	uint32_t	s_rcsd[4];	/* raw csd */
134	uint32_t	s_rcid[4];	/* raw cid */
135	uint32_t	s_nblks;	/* total blocks on device */
136	uint16_t	s_blksz;	/* device block size (typ. 512) */
137	uint16_t	s_bshift;	/* block address shift factor */
138	uint32_t	s_speed;	/* max memory clock in hz */
139
140	/* Other CID and CSD values */
141	uint32_t	s_mfg;		/* mfg id */
142	char		s_prod[8];	/* product id */
143	char		s_oem[2];	/* oem id */
144	uint32_t	s_serial;
145	uint8_t		s_majver;
146	uint8_t		s_minver;
147	uint16_t	s_year;
148	uint8_t		s_month;
149
150	uint16_t	s_ccc;		/* card command classes */
151	uint8_t		s_r2w;		/* read/write factor */
152	uint8_t		s_dsr;		/* DSR implemented? */
153	uint8_t		s_perm_wp;	/* permanent write protect set? */
154	uint8_t		s_temp_wp;	/* temporary write protect set? */
155
156	bd_handle_t	s_bdh;		/* block dev handle */
157};
158
159/*
160 * Per host state.  One per devinfo node.  There could be multiple
161 * slots per devinfo node.
162 */
163struct sda_host {
164	dev_info_t	*h_dip;
165	int		h_nslot;
166	sda_slot_t	*h_slots;
167	ddi_dma_attr_t	*h_dma;		/* dma attr, needed for mem */
168
169	list_node_t	h_node;		/* nexus node linkage */
170
171	uint32_t	h_flags;
172#define	HOST_ATTACH	(1U << 0)	/* host attach completed */
173#define	HOST_XOPEN	(1U << 2)	/* exclusive open */
174#define	HOST_SOPEN	(1U << 3)	/* shared open */
175};
176
177/*
178 * Useful function-like macros.
179 */
180#define	sda_setprop(s, p, v)	s->s_ops.so_setprop(s->s_prv, p, v)
181#define	sda_getprop(s, p, v)	s->s_ops.so_getprop(s->s_prv, p, v)
182
183/*
184 * sda_cmd.c
185 */
186void sda_cmd_init(void);
187void sda_cmd_fini(void);
188void sda_cmd_list_init(list_t *);
189void sda_cmd_list_fini(list_t *);
190sda_cmd_t *sda_cmd_alloc(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t,
191    void *, int);
192sda_cmd_t *sda_cmd_alloc_acmd(sda_slot_t *, sda_index_t, uint32_t, sda_rtype_t,
193    void *, int);
194void sda_cmd_free(sda_cmd_t *);
195sda_err_t sda_cmd_errno(sda_cmd_t *);
196void *sda_cmd_data(sda_cmd_t *);
197void sda_cmd_submit(sda_slot_t *, sda_cmd_t *, void (*)(sda_cmd_t *));
198void sda_cmd_resubmit_acmd(sda_slot_t *, sda_cmd_t *);
199void sda_cmd_notify(sda_cmd_t *, uint16_t, sda_err_t);
200sda_err_t sda_cmd_exec(sda_slot_t *, sda_cmd_t *, uint32_t *);
201
202/*
203 * sda_init.c
204 */
205sda_err_t sda_init_card(sda_slot_t *);
206
207/*
208 * sda_mem.c
209 */
210void sda_mem_init(struct modlinkage *);
211void sda_mem_fini(struct modlinkage *);
212uint32_t sda_mem_maxclk(sda_slot_t *);
213uint32_t sda_mem_getbits(uint32_t *, int, int);
214int sda_mem_parse_cid_csd(sda_slot_t *);
215int sda_mem_bd_read(void *, bd_xfer_t *);
216int sda_mem_bd_write(void *, bd_xfer_t *);
217void sda_mem_bd_driveinfo(void *, bd_drive_t *);
218int sda_mem_bd_mediainfo(void *, bd_media_t *);
219
220
221/*
222 * sda_nexus.c
223 */
224void sda_nexus_init(void);
225void sda_nexus_fini(void);
226void sda_nexus_register(sda_host_t *);
227void sda_nexus_unregister(sda_host_t *);
228int sda_nexus_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
229int sda_nexus_open(dev_t *, int, int, cred_t *);
230int sda_nexus_close(dev_t, int, int, cred_t *);
231int sda_nexus_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
232int sda_nexus_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
233    void *);
234void sda_nexus_remove(sda_slot_t *);
235void sda_nexus_insert(sda_slot_t *);
236void sda_nexus_reap(void *);
237
238/*
239 * sda_slot.c
240 */
241void sda_slot_init(sda_slot_t *);
242void sda_slot_fini(sda_slot_t *);
243void sda_slot_enter(sda_slot_t *);
244void sda_slot_exit(sda_slot_t *);
245boolean_t sda_slot_owned(sda_slot_t *);
246void sda_slot_attach(sda_slot_t *);
247void sda_slot_detach(sda_slot_t *);
248void sda_slot_suspend(sda_slot_t *);
249void sda_slot_resume(sda_slot_t *);
250void sda_slot_reset(sda_slot_t *);
251void sda_slot_wakeup(sda_slot_t *);
252void sda_slot_detect(sda_slot_t *);
253int sda_slot_power_on(sda_slot_t *);
254void sda_slot_power_off(sda_slot_t *);
255void sda_slot_reset(sda_slot_t *);
256void sda_slot_shutdown(sda_slot_t *);
257void sda_slot_transfer(sda_slot_t *, sda_err_t);
258void sda_slot_fault(sda_slot_t *, sda_fault_t);
259/*PRINTFLIKE2*/
260void sda_slot_err(sda_slot_t *, const char *, ...);
261/*PRINTFLIKE2*/
262void sda_slot_log(sda_slot_t *, const char *, ...);
263
264#ifdef	DEBUG
265#define	sda_slot_debug(...)	sda_slot_log(__VA_ARGS__)
266#else
267#define	sda_slot_debug(...)
268#endif
269
270#ifdef __cplusplus
271}
272#endif
273
274#endif	/* _SYS_SDCARD_SDA_IMPL_H */
275