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.
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.
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]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
28 * Memory target support for SDcard.
31 #include <sys/types.h>
34 #include <sys/blkdev.h>
36 #include <sys/sunddi.h>
37 #include <sys/sdcard/sda.h>
38 #include <sys/sdcard/sda_impl.h>
40 static int sda_mem_errno(sda_err_t
);
41 static int sda_mem_rw(sda_slot_t
*, bd_xfer_t
*, uint8_t, uint16_t);
42 static void sda_mem_done(sda_cmd_t
*);
43 static void sda_mem_getstring(uint32_t *, char *, int, int);
46 * To minimize complexity and reduce layering, we implement almost the
47 * entire memory card driver (sdcard) here. The memory card still
48 * needs to be a separate driver though, due to the requirement to
49 * have both SCSI HBA bus ops and SD bus ops.
53 * Everything beyond this is private.
57 sda_mem_errno(sda_err_t errno
)
60 if (errno
== SDA_EOK
) {
86 sda_mem_done(sda_cmd_t
*cmdp
)
88 bd_xfer_t
*xfer
= sda_cmd_data(cmdp
);
89 int errno
= sda_cmd_errno(cmdp
);
91 bd_xfer_done(xfer
, sda_mem_errno(errno
));
96 sda_mem_rw(sda_slot_t
*slot
, bd_xfer_t
*xfer
, uint8_t cmd
, uint16_t flags
)
103 blkno
= xfer
->x_blkno
;
104 nblks
= xfer
->x_nblks
;
108 if ((blkno
+ nblks
) > slot
->s_nblks
) {
112 cmdp
= sda_cmd_alloc(slot
, cmd
, blkno
<< slot
->s_bshift
,
113 R1
, xfer
, KM_NOSLEEP
);
118 if (slot
->s_hostp
->h_dma
!= NULL
) {
119 cmdp
->sc_dmah
= xfer
->x_dmah
;
120 cmdp
->sc_ndmac
= xfer
->x_ndmac
;
121 cmdp
->sc_dmac
= xfer
->x_dmac
;
125 cmdp
->sc_kvaddr
= xfer
->x_kaddr
;
128 rblen
= slot
->s_blksz
;
130 /* other fields are set by sda_cmd_alloc */
131 cmdp
->sc_blksz
= rblen
;
132 cmdp
->sc_nblks
= (uint16_t)nblks
;
133 cmdp
->sc_flags
= flags
;
135 sda_cmd_submit(slot
, cmdp
, sda_mem_done
);
140 sda_mem_bd_read(void *arg
, bd_xfer_t
*xfer
)
142 sda_slot_t
*slot
= arg
;
146 if (xfer
->x_flags
& BD_XFER_POLL
) {
149 if (xfer
->x_nblks
> 1) {
150 cmd
= CMD_READ_MULTI
;
151 flags
= SDA_CMDF_DAT
| SDA_CMDF_MEM
| SDA_CMDF_READ
|
154 cmd
= CMD_READ_SINGLE
;
155 flags
= SDA_CMDF_DAT
| SDA_CMDF_MEM
| SDA_CMDF_READ
;
158 return (sda_mem_rw(slot
, xfer
, cmd
, flags
));
162 sda_mem_bd_write(void *arg
, bd_xfer_t
*xfer
)
164 sda_slot_t
*slot
= arg
;
168 if (xfer
->x_flags
& BD_XFER_POLL
) {
171 if ((slot
->s_flags
& SLOTF_WRITABLE
) == 0) {
174 if (xfer
->x_nblks
> 1) {
175 cmd
= CMD_WRITE_MULTI
;
176 flags
= SDA_CMDF_DAT
| SDA_CMDF_MEM
| SDA_CMDF_WRITE
|
179 cmd
= CMD_WRITE_SINGLE
;
180 flags
= SDA_CMDF_DAT
| SDA_CMDF_MEM
| SDA_CMDF_WRITE
;
183 return (sda_mem_rw(slot
, xfer
, cmd
, flags
));
187 sda_mem_bd_driveinfo(void *arg
, bd_drive_t
*drive
)
189 sda_slot_t
*slot
= arg
;
191 drive
->d_qsize
= 4; /* we queue up internally, 4 is enough */
192 drive
->d_maxxfer
= 65536;
193 drive
->d_removable
= B_TRUE
;
194 drive
->d_hotpluggable
= B_FALSE
;
195 drive
->d_target
= slot
->s_slot_num
;
199 sda_mem_bd_mediainfo(void *arg
, bd_media_t
*media
)
201 sda_slot_t
*slot
= arg
;
203 sda_slot_enter(slot
);
204 if (!slot
->s_ready
) {
208 media
->m_nblks
= slot
->s_nblks
;
209 media
->m_blksize
= slot
->s_blksz
;
210 media
->m_readonly
= slot
->s_flags
& SLOTF_WRITABLE
? B_FALSE
: B_TRUE
;
211 media
->m_solidstate
= B_TRUE
;
217 sda_mem_getbits(uint32_t *resp
, int hibit
, int len
)
222 for (bit
= hibit
; len
--; bit
--) {
224 val
|= ((resp
[bit
/ 32]) >> (bit
% 32)) & 1;
230 sda_mem_getstring(uint32_t *resp
, char *s
, int hibit
, int len
)
233 *s
++ = sda_mem_getbits(resp
, hibit
, 8);
240 sda_mem_maxclk(sda_slot_t
*slot
)
242 static const uint32_t mult
[16] = {
243 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
246 static const uint32_t units
[8] = {
247 10000, 100000, 1000000, 10000000, 0, 0, 0, 0,
251 ts
= sda_mem_getbits(slot
->s_rcsd
, 103, 8);
253 return ((units
[ts
& 0x7]) * (mult
[(ts
>> 3) & 0xf]));
257 sda_mem_parse_cid_csd(sda_slot_t
*slot
)
270 csdver
= sda_mem_getbits(rcsd
, 127, 2);
272 if (slot
->s_flags
& SLOTF_SDMEM
) {
275 csize
= sda_mem_getbits(rcsd
, 73, 12);
276 rblen
= (1 << sda_mem_getbits(rcsd
, 83, 4));
277 cmult
= (4 << sda_mem_getbits(rcsd
, 49, 3));
282 csize
= sda_mem_getbits(rcsd
, 69, 22);
287 sda_slot_err(slot
, "Unknown SD CSD version (%d)",
289 return (DDI_FAILURE
);
292 slot
->s_mfg
= sda_mem_getbits(rcid
, 127, 8);
293 sda_mem_getstring(rcid
, slot
->s_oem
, 119, 2);
294 sda_mem_getstring(rcid
, slot
->s_prod
, 103, 5);
295 slot
->s_majver
= sda_mem_getbits(rcid
, 63, 4);
296 slot
->s_minver
= sda_mem_getbits(rcid
, 59, 4);
297 slot
->s_serial
= sda_mem_getbits(rcid
, 55, 32);
298 slot
->s_year
= sda_mem_getbits(rcid
, 19, 8) + 2000;
299 slot
->s_month
= sda_mem_getbits(rcid
, 11, 4);
301 } else if (slot
->s_flags
& SLOTF_MMC
) {
302 if ((csdver
< 1) || (csdver
> 2)) {
303 sda_slot_err(slot
, "Unknown MMC CSD version (%d)",
305 return (DDI_FAILURE
);
308 switch (sda_mem_getbits(rcsd
, 125, 4)) {
309 case 0: /* MMC 1.0 - 1.2 */
310 case 1: /* MMC 1.4 */
311 slot
->s_mfg
= sda_mem_getbits(rcid
, 127, 24);
313 sda_mem_getstring(rcid
, slot
->s_prod
, 103, 7);
314 slot
->s_majver
= sda_mem_getbits(rcid
, 47, 4);
315 slot
->s_minver
= sda_mem_getbits(rcid
, 43, 4);
316 slot
->s_serial
= sda_mem_getbits(rcid
, 39, 24);
319 case 2: /* MMC 2.0 - 2.2 */
320 case 3: /* MMC 3.1 - 3.3 */
321 case 4: /* MMC 4.x */
322 slot
->s_mfg
= sda_mem_getbits(rcid
, 127, 8);
323 sda_mem_getstring(rcid
, slot
->s_oem
, 119, 2);
324 sda_mem_getstring(rcid
, slot
->s_prod
, 103, 6);
325 slot
->s_majver
= sda_mem_getbits(rcid
, 55, 4);
326 slot
->s_minver
= sda_mem_getbits(rcid
, 51, 4);
327 slot
->s_serial
= sda_mem_getbits(rcid
, 47, 32);
331 /* this error isn't fatal to us */
332 sda_slot_err(slot
, "Unknown MMCA version (%d)",
333 sda_mem_getbits(rcsd
, 125, 4));
337 slot
->s_year
= sda_mem_getbits(rcid
, 11, 4) + 1997;
338 slot
->s_month
= sda_mem_getbits(rcid
, 15, 4);
340 csize
= sda_mem_getbits(rcsd
, 73, 12);
341 rblen
= (1 << sda_mem_getbits(rcsd
, 83, 4));
342 cmult
= (4 << sda_mem_getbits(rcsd
, 49, 3));
347 sda_slot_err(slot
, "Card type unknown");
348 return (DDI_FAILURE
);
352 * These fields are common to all known MMC/SDcard memory cards.
354 * The spec requires that block size 512 be supported.
355 * The media may have a different native size, but 512
356 * byte blocks will always work. This is true for SDcard,
357 * and apparently for MMC as well.
359 rblen
= max(rblen
, 512); /* paranoia */
360 slot
->s_nblks
= (csize
+ 1) * cmult
* (rblen
/ 512);
361 slot
->s_bshift
= bshift
;
364 slot
->s_r2w
= (1 << sda_mem_getbits(rcsd
, 28, 3));
365 slot
->s_ccc
= sda_mem_getbits(rcsd
, 95, 12);
366 slot
->s_perm_wp
= sda_mem_getbits(rcsd
, 13, 1);
367 slot
->s_temp_wp
= sda_mem_getbits(rcsd
, 12, 1);
368 slot
->s_dsr
= sda_mem_getbits(rcsd
, 76, 1);
370 if (((slot
->s_ccc
& (1 << 4)) == 0) ||
371 (slot
->s_perm_wp
!= 0) || (slot
->s_temp_wp
!= 0)) {
372 slot
->s_flags
&= ~SLOTF_WRITABLE
;
375 return (DDI_SUCCESS
);