/*
* 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.
*/
/*
* SATA midlayer interface for PMC drier.
*/
static void
{
/* There is only one direction currently */
}
/*
* Run a non block-io command. Some commands are interpreted
* out of extant data. Some imply actually running a SATA command.
*
* Returns zero if we were able to run.
*
* Returns -1 only if other commands are active, either another
* command here or regular I/O active.
*
* Called with PHY lock and xp statlock held.
*/
static int
{
int i;
int saq;
"%s: target %p actv count %u",
return (-1);
}
if (xp->special_running) {
"%s: target %p special running already",
return (-1);
}
xp->special_needed = 0;
/*
* We're now running special.
*/
xp->special_running = 0;
return (0);
}
"%s: target %p cmd %p cdb0 %x with actv_cnt %u",
int retval;
xp->special_running = 0;
return (-1);
}
saq = 1;
if (retval) {
xp->special_running = 0;
"%s: target %p identify failed %x",
/*
* If the failure is due to not being
* able to get resources, return such
* that we'll try later. Otherwise,
* fail current command.
*/
"%s: sata identify failed (ENOMEM) for "
return (-1);
}
} else {
}
goto out;
}
/*
* Check to see if this device is an NCQ capable device.
* Yes, we'll end up doing this check for every INQUIRY
* if indeed we *are* only a pio device, but this is so
* infrequent that it's not really worth an extra bitfield.
*
* Note that PIO mode here means that the PMCS firmware
* performs PIO- not us.
*/
/*
* Reset existing stuff.
*/
"%s: device %s supports NCQ %u deep",
} else {
/*
* Default back to PIO.
*
* Note that non-FPDMA would still be possible,
* but for this specific configuration, if it's
* not NCQ it's safest to assume PIO.
*/
"%s: device %s assumed PIO",
}
}
} else {
saq = 0;
}
case SCMD_INQUIRY:
{
uint16_t *a, *b;
/* Check for illegal bits */
break;
}
case 0x0:
amt = 7;
break;
case 0x80:
a = (void *) &rp[4];
b = id->model_number;
for (i = 0; i < 5; i++) {
*a = ddi_swap16(*b);
a++;
b++;
}
amt = 24;
break;
case 0x83:
amt = 16;
} else {
a = (void *) &rp[16];
b = id->model_number;
for (i = 0; i < 20; i++) {
*a = ddi_swap16(*b);
a++;
b++;
}
a = (void *) &rp[40];
b = id->serial_number;
for (i = 0; i < 10; i++) {
*a = ddi_swap16(*b);
a++;
b++;
}
amt = 68;
}
break;
default:
break;
}
} else {
}
b = id->model_number;
for (i = 0; i < 8; i++) {
*a = ddi_swap16(*b);
a++;
b++;
}
inqp->inq_revision[0] =
} else {
inqp->inq_revision[0] =
}
amt = 36;
}
if (amt) {
xp->special_running = 0;
if (saq) {
}
return (-1);
}
}
break;
}
case SCMD_READ_CAPACITY:
{
/* Check for illegal bits */
break;
}
for (i = 1; i < 10; i++) {
break;
}
}
if (status != STATUS_GOOD) {
break;
}
if (last_block > 0xffffffffULL) {
last_block = 0xffffffffULL;
}
amt = 8;
if (amt) {
xp->special_running = 0;
if (saq) {
}
return (-1);
}
}
break;
}
case SCMD_REPORT_LUNS: {
int rl_len;
/* Check for illegal bits */
break;
}
if (amt) {
xp->special_running = 0;
if (saq) {
}
return (-1);
}
}
break;
}
case SCMD_REQUEST_SENSE:
/* Check for illegal bits */
break;
}
rp[0] = 0xf0;
amt = 18;
if (amt) {
xp->special_running = 0;
if (saq) {
}
return (-1);
}
}
break;
case SCMD_START_STOP:
/* Check for illegal bits */
break;
}
break;
case SCMD_SYNCHRONIZE_CACHE:
/* Check for illegal bits */
break;
}
break;
case SCMD_TEST_UNIT_READY:
/* Check for illegal bits */
break;
}
key = 0x6;
asc = 0x28;
}
break;
default:
break;
}
if (status != STATUS_GOOD) {
rp[0] = 0xf0;
} else {
}
out:
"%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
if (saq) {
}
"%s: waking up drain waiters", __func__);
}
xp->special_running = 0;
return (0);
}
/*
* Run all special commands queued up for a SATA device.
* We're only called if the caller knows we have work to do.
*
* We can't run them if things are still active for the device,
* return saying we didn't run anything.
*
* When we finish, wake up anyone waiting for active commands
* to go to zero.
*
* Called with PHY lock and xp statlock held.
*/
int
{
return (-1);
}
}
return (0);
}
/*
* Search for SATA special commands to run and run them.
* If we succeed in running the special command(s), kick
* the normal commands into operation again. Call completion
* for any commands that were completed while we were here.
*
* Called unlocked.
*/
void
{
int spinagain = 0;
continue;
}
continue;
}
"%s: deferring until drained", __func__);
spinagain++;
} else {
spinagain++;
}
}
}
if (spinagain) {
} else {
}
/*
* Run completion on any commands ready for it.
*/
}
/*
* Called with PHY lock held and scratch acquired
*/
int
{
fis[1] = 0;
fis[2] = 0;
fis[3] = 0;
fis[4] = 0;
PMCIN_DATADIR_2_INI, sizeof (ata_identify_t)));
}
/*
* Called with PHY lock held and scratch held
*/
int
{
int i, result = 0;
return (ENOMEM);
}
if (dlen) {
if (ddir == PMCIN_DATADIR_2_DEV) {
DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) {
"Condition check failed at %s():%d",
}
}
msg[15] = 0;
} else {
msg[12] = 0;
msg[13] = 0;
msg[14] = 0;
msg[15] = 0;
}
for (i = 0; i < 5; i++) {
}
msg[10] = 0;
msg[11] = 0;
return (ENOMEM);
}
if (result) {
}
return (ETIMEDOUT);
}
if (status != PMCOUT_STATUS_OK) {
"%s: Potential affiliation active on 0x%" PRIx64,
} else {
"%s: SATA I/O returned with IOMB status 0x%x",
}
return (EIO);
}
}
amt >>= 2;
for (j = 0; j < amt; j++) {
}
}
"Condition check failed at %s():%d",
}
}
return (0);
}