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 /*
26  * SD card host support.  This is the API that host drivers access.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/conf.h>
31 #include <sys/cmn_err.h>
32 #include <sys/varargs.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/sdcard/sda.h>
36 #include <sys/sdcard/sda_impl.h>
37 
38 /*
39  * Implementation.
40  */
41 
42 void
sda_host_init_ops(struct dev_ops * devops)43 sda_host_init_ops(struct dev_ops *devops)
44 {
45 	bd_mod_init(devops);
46 }
47 
48 void
sda_host_fini_ops(struct dev_ops * devops)49 sda_host_fini_ops(struct dev_ops *devops)
50 {
51 	bd_mod_fini(devops);
52 }
53 
54 sda_host_t *
sda_host_alloc(dev_info_t * dip,int nslot,sda_ops_t * ops,ddi_dma_attr_t * dma)55 sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma)
56 {
57 	sda_host_t	*h;
58 
59 	if (ops->so_version != SDA_OPS_VERSION) {
60 		return (NULL);
61 	}
62 
63 	h = kmem_zalloc(sizeof (*h), KM_SLEEP);
64 	h->h_nslot = nslot;
65 	h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP);
66 	h->h_dma = dma;
67 	h->h_dip = dip;
68 
69 	/* initialize each slot */
70 	for (int i = 0; i < nslot; i++) {
71 		sda_slot_t *slot = &h->h_slots[i];
72 
73 		slot->s_hostp = h;
74 		slot->s_slot_num = i;
75 		slot->s_ops = *ops;
76 
77 		sda_slot_init(slot);
78 	}
79 
80 	return (h);
81 }
82 
83 void
sda_host_free(sda_host_t * h)84 sda_host_free(sda_host_t *h)
85 {
86 	for (int i = 0; i < h->h_nslot; i++) {
87 		sda_slot_fini(&h->h_slots[i]);
88 	}
89 
90 	kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot);
91 	kmem_free(h, sizeof (*h));
92 }
93 
94 void
sda_host_set_private(sda_host_t * h,int num,void * private)95 sda_host_set_private(sda_host_t *h, int num, void *private)
96 {
97 	h->h_slots[num].s_prv = private;
98 }
99 
100 int
sda_host_attach(sda_host_t * h)101 sda_host_attach(sda_host_t *h)
102 {
103 	/*
104 	 * Attach slots.
105 	 */
106 	for (int i = 0; i < h->h_nslot; i++) {
107 
108 		sda_slot_attach(&h->h_slots[i]);
109 
110 		/*
111 		 * Initiate card detection.
112 		 */
113 		sda_host_detect(h, i);
114 	}
115 
116 	return (DDI_SUCCESS);
117 }
118 
119 void
sda_host_detach(sda_host_t * h)120 sda_host_detach(sda_host_t *h)
121 {
122 	/*
123 	 * Detach slots.
124 	 */
125 	for (int i = 0; i < h->h_nslot; i++) {
126 		sda_slot_detach(&h->h_slots[i]);
127 	}
128 }
129 
130 void
sda_host_suspend(sda_host_t * h)131 sda_host_suspend(sda_host_t *h)
132 {
133 	for (int i = 0; i < h->h_nslot; i++) {
134 		sda_slot_suspend(&h->h_slots[i]);
135 	}
136 }
137 
138 void
sda_host_resume(sda_host_t * h)139 sda_host_resume(sda_host_t *h)
140 {
141 	for (int i = 0; i < h->h_nslot; i++) {
142 		sda_slot_resume(&h->h_slots[i]);
143 	}
144 }
145 
146 void
sda_host_transfer(sda_host_t * h,int num,sda_err_t errno)147 sda_host_transfer(sda_host_t *h, int num, sda_err_t errno)
148 {
149 	sda_slot_transfer(&h->h_slots[num], errno);
150 }
151 
152 void
sda_host_detect(sda_host_t * h,int num)153 sda_host_detect(sda_host_t *h, int num)
154 {
155 	sda_slot_detect(&h->h_slots[num]);
156 }
157 
158 void
sda_host_fault(sda_host_t * h,int num,sda_fault_t fail)159 sda_host_fault(sda_host_t *h, int num, sda_fault_t fail)
160 {
161 	sda_slot_fault(&h->h_slots[num], fail);
162 }
163 
164 void
sda_host_log(sda_host_t * h,int snum,const char * fmt,...)165 sda_host_log(sda_host_t *h, int snum, const char *fmt, ...)
166 {
167 	va_list	ap;
168 
169 	va_start(ap, fmt);
170 	if (h != NULL) {
171 		sda_slot_log(&h->h_slots[snum], fmt, ap);
172 	} else {
173 		sda_slot_log(NULL, fmt, ap);
174 	}
175 	va_end(ap);
176 }
177