sda_mem.c revision 484a3518b37b5c1d1ae17965b07c1c7ab8dcfea5
/*
* 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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Memory target support for SDcard.
*/
static int sda_mem_quiesce(dev_info_t *);
static void sda_mem_b2s_done(sda_cmd_t *);
static void sda_mem_getstring(uint32_t *, char *, int, int);
/*
* To minimize complexity and reduce layering, we implement almost the
* entire memory card driver (sdcard) here. The memory card still
* needs to be a separate driver though, due to the requirement to
* have both SCSI HBA bus ops and SD bus ops.
*/
/*
* SCSA layer supplies a cb_ops, but we don't want it, because we
* don't want to expose a SCSI attachment point. (Our parent handles
* the attachment point, the SCSI one would be confusing.) We have to
* supply a stubbed out one, to prevent SCSA from trying to create minor
* nodes on our behalf.
*
* Perhaps at some future point we might want to expose a separate set
* of ioctls for these nodes, but for now we rely on our parent to do
* all that work.
*/
static struct cb_ops sda_mem_ops = {
nodev, /* cb_open */
nodev, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
nodev, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_stream */
D_MP /* cb_flag */
};
/*
* Here are the public functions.
*/
void
{
/* it turns out that this can't ever really fail */
(void) b2s_mod_init(modlp);
}
void
{
}
/*
* Everything beyond this is private.
*/
int
{
int errno;
return (ENOMEM);
}
return (errno);
}
{
int rv;
case B2S_CMD_READ:
if (nblks > 1) {
} else {
}
break;
case B2S_CMD_WRITE:
if (nblks > 1) {
} else {
}
break;
default:
ASSERT(0);
break;
}
return (B_TRUE);
}
} else {
}
}
if (nblks == 0) {
/*
* This is not strictly a failure, but no work to do.
* We have to do it late here because we don't want to
* by pass the above media readiness checks.
*/
goto failed;
}
if (nblks > 0xffff) {
rv = B2S_EINVAL;
goto failed;
}
rv = B2S_EBLKADDR;
goto failed;
}
return (B_TRUE);
return (B_TRUE);
}
{
int rv;
if (rv != 0) {
return (B_TRUE);
}
if (rv != 0) {
return (B_TRUE);
}
return (B_TRUE);
}
return (B_TRUE);
}
{
/* the hot path */
return (B2S_EOK);
}
switch (errno) {
case SDA_ENOMEM:
return (B2S_ENOMEM);
case SDA_ETIME:
return (B2S_ETIMEDOUT);
case SDA_EWPROTECT:
return (B2S_EWPROTECT);
case SDA_ESUSPENDED:
case SDA_ENODEV:
return (B2S_ENOMEDIA);
case SDA_EFAULT:
case SDA_ECRC7:
case SDA_EPROTO:
return (B2S_EHARDWARE);
case SDA_ERESET:
return (B2S_ERESET);
case SDA_EIO:
case SDA_ERESID:
default:
return (B2S_EIO);
}
}
void
{
}
{
int rv;
case B2S_CMD_WRITE:
rv = B2S_EWPROTECT;
} else {
}
break;
case B2S_CMD_READ:
case B2S_CMD_INQUIRY:
"SD Memory Card";
break;
case B2S_CMD_GETMEDIA:
rv = B2S_ENODEV;
} else {
/* detect read-only cards */
} else {
}
}
break;
case B2S_CMD_FORMAT:
case B2S_CMD_ABORT:
break;
case B2S_CMD_RESET:
break;
case B2S_CMD_START:
case B2S_CMD_STOP:
case B2S_CMD_SYNC:
break;
case B2S_CMD_LOCK:
case B2S_CMD_UNLOCK:
default:
rv = B2S_ENOTSUP;
break;
}
return (B_TRUE);
}
int
{
switch (cmd) {
case DDI_ATTACH:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
leafinfo.leaf_target = 0;
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
int
{
switch (cmd) {
case DDI_DETACH:
return (DDI_FAILURE);
}
/* nothing to do */
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
int
{
/* no work to do */
return (DDI_SUCCESS);
}
{
val <<= 1;
}
return (val);
}
void
{
while (len--) {
hibit -= 8;
}
*s = 0;
}
{
0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
};
10000, 100000, 1000000, 10000000, 0, 0, 0, 0,
};
}
int
{
int csdver;
char date[16];
char *dtype;
switch (csdver) {
case 0:
/* see comment above */
bshift = 9;
break;
case 1:
rblen = 512;
cmult = 1024;
bshift = 0;
break;
default:
csdver);
return (DDI_FAILURE);
}
csdver);
return (DDI_FAILURE);
}
dtype = "mmc";
case 0: /* MMC 1.0 - 1.2 */
case 1: /* MMC 1.4 */
break;
case 2: /* MMC 2.0 - 2.2 */
case 3: /* MMC 3.1 - 3.3 */
case 4: /* MMC 4.x */
break;
default:
/* this error isn't fatal to us */
break;
}
bshift = 9;
} else {
return (DDI_FAILURE);
}
/*
*
* The spec requires that block size 512 be supported.
* The media may have a different native size, but 512
* byte blocks will always work. This is true for SDcard,
* and apparently for MMC as well.
*/
}
return (DDI_SUCCESS);
}