/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
*/
/*
* Enclosure Services Devices, SAF-TE Enclosure Routines
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
static void wrslot_stat(ses_softc_t *, int);
#define ALL_ENC_STAT \
struct scfg {
/*
* Cached Configuration
*/
/*
* Cached Flag Bytes for Global Status
*/
/*
* What object index ID is where various slots start.
*/
};
#if !defined(lint)
#endif
static int
{
int err;
return (ENXIO);
return (ENOMEM);
if (err) {
return (err);
}
return (EIO);
}
sdata[5]);
return (0);
}
int
{
int r, i;
if (doinit == 0) {
if (ssc->ses_nobjects) {
if (ssc->ses_objmap) {
}
ssc->ses_nobjects = 0;
}
if (ssc->ses_private) {
}
return (0);
}
return (ENOMEM);
}
}
ssc->ses_nobjects = 0;
ssc->ses_encstat = 0;
if ((r = safte_getconfig(ssc)) != 0) {
return (r);
}
/*
* The number of objects here, as well as that reported by the
* READ_BUFFER/GET_CONFIG call, are the over-temperature flags (15)
* that get reported during READ_BUFFER/READ_ENC_STATUS.
*/
return (ENOMEM);
r = 0;
/*
* Note that this is all arranged for the convenience
* in later fetches of status.
*/
for (i = 0; i < NPSEUDO_THERM; i++)
return (0);
}
int
{
int err;
lp->uscsi_buflen = 0;
if (err) {
return (err);
}
sdata[0] = SAFTE_WT_GLOBAL;
return (err);
}
#define BAIL(r, x, k, l, m, n) \
if (r >= x) { \
kmem_free(k, l); \
kmem_free(m, n); \
return (EIO); \
}
static int
{
return (ENOMEM);
}
/*
* The number of bytes of data we need to get is
* Nfans + Npwr + Nslots + Nspkrs + Ntherm + nochoice
* (nochoice = 1 doorlock + 1 spkr + 2 pseudo therms + 10 extra)
* the extra are simply for good luck.
*/
/*
* Towards the end of this function this buffer is reused.
* Thus we need to make sure that we have allocated enough
* memory retrieving buffer 1 & 4.
* buffer 1 -> element status & drive id
* buffer 4 -> drive status & drive command history.
* buffer 4 uses 4 bytes per drive bay.
*/
}
if (buflen > 0xffff) {
return (EIO);
}
return (ENOMEM);
}
cdb[0] = SCMD_READ_BUFFER;
cdb[3] = 0;
cdb[4] = 0;
cdb[5] = 0;
cdb[6] = 0;
cdb[9] = 0;
if (err) {
return (err);
}
/*
* invalidate all status bits.
*/
for (i = 0; i < ssc->ses_nobjects; i++)
ssc->ses_encstat = 0;
/*
* Now parse returned buffer.
* If we didn't get enough data back,
* that's considered a fatal error.
*/
oid = r = 0;
/*
* 0 = Fan Operational
* 1 = Fan is malfunctioning
* 2 = Fan is not present
* 0x80 = Unknown or Not Reportable Status
*/
case 0:
nitems++;
/*
* We could get fancier and cache
* fan speeds that we have set, but
* that isn't done now.
*/
break;
case 1:
/*
* FAIL and FAN STOPPED synthesized
*/
/*
* Enclosure marked with CRITICAL error
* if only one fan or no thermometers,
* else NONCRIT error set.
*/
else
break;
case 2:
else
break;
case 0x80:
break;
default:
i, sdata[r] & 0xff);
break;
}
r++;
}
/*
* No matter how you cut it, no cooling elements when there
* should be some there is critical.
*/
}
case 0x00: /* pws operational and on */
break;
case 0x01: /* pws operational and off */
break;
case 0x10: /* pws is malfunctioning and commanded on */
else
break;
case 0x11: /* pws is malfunctioning and commanded off */
else
break;
case 0x20: /* pws is not present */
else
break;
case 0x21: /* pws is present */
break;
case 0x80: /* Unknown or Not Reportable Status */
break;
default:
i, sdata[r] & 0xff);
break;
}
r++;
}
/*
* Now I am going to save the target id's for the end of
* the function. (when I build the drive objects)
* that is when I will be getting the drive status from buffer 4
*/
}
/*
* We always have doorlock status, no matter what,
* but we only save the status if we have one.
*/
/*
* 0 = Door Locked
* 1 = Door Unlocked, or no Lock Installed
* 0x80 = Unknown or Not Reportable Status
*/
case 0:
break;
case 1:
break;
case 0x80:
break;
default:
sdata[r] & 0xff);
break;
}
}
r++;
/*
* We always have speaker status, no matter what,
* but we only save the status if we have one.
*/
if (sdata[r] == 1) {
/*
* We need to cache tone urgency indicators.
* Someday.
*/
} else if (sdata[r] == 0) {
} else {
sdata[r] & 0xff);
}
}
r++;
/*
* Status is a range from -10 to 245 deg Celsius,
* which we need to normalize to -20 to -235 according
* to the latest SCSI spec.
*/
((unsigned int) sdata[r]) - 10;
if (sdata[r] < 20) {
/*
* Set 'under temperature' failure.
*/
} else if (sdata[r] > 30) {
/*
* Set 'over temperature' failure.
*/
} else {
}
r++;
}
/*
* Now, for "pseudo" thermometers, we have two bytes
* of information in enclosure status- 16 bits. Actually,
* the MSB is a single TEMP ALERT flag indicating whether
* any other bits are set, but, thanks to fuzzy thinking,
* in the SAF-TE spec, this can also be set even if no
* other bits are set, thus making this really another
* binary temperature sensor.
*/
#if NPSEUDO_THERM == 1
if (tempflags) {
/* Set 'over temperature' failure. */
} else {
/* Set 'nominal' temperature. */
}
#else /* NPSEUDO_THERM == 1 */
for (i = 0; i < NPSEUDO_THERM; i++) {
/* ssc->ses_objmap[oid].encstat[2] = 0; */
/*
* Set 'over temperature' failure.
*/
} else {
/*
* Set 'nominal' temperature.
*/
/* ssc->ses_objmap[oid].encstat[2] = 0; */
}
}
#endif /* NPSEUDO_THERM == 1 */
/*
* Get alarm status.
*/
/*
* Now get drive slot status
*/
if (err) {
return (err);
}
} else {
}
if (status & 0x2) {
}
if ((status & 0x4) == 0) {
}
}
/* see comment below about sticky enclosure status */
return (0);
}
int
{
}
int
{
return (0);
/*
* Since SAF-TE devices aren't necessarily sticky in terms
* of state, make our soft copy of enclosure status 'sticky'-
* that is, things set in enclosure status stay set (as implied
* by conditions set in reading object status) until cleared.
*/
} else if ((encstat & ENCSTAT_NONCRITICAL) != 0) {
}
}
int
{
if (r)
return (r);
}
return (0);
}
int
{
/*
* If this is clear, we don't do diddly.
*/
return (0);
}
err = 0;
/*
* Check to see if the common bits are set and do them first.
*/
if (err)
return (err);
}
return (0);
case SESTYP_DEVICE:
{
/*
* XXX: I should probably cache the previous state
* XXX: of SESCTL_DEVOFF so that when it goes from
* XXX: true to false I can then set PREPARE FOR OPERATION
* XXX: flag in PERFORM SLOT OPERATION write buffer command.
*/
slotop |= 0x2;
}
slotop |= 0x4;
}
if (err)
return (err);
} else {
}
} else {
}
break;
}
case SESTYP_POWER:
} else {
}
if (err)
return (err);
} else {
}
break;
case SESTYP_FAN:
} else {
}
if (err)
return (err);
fsp = 4;
fsp = 3;
fsp = 2;
} else {
fsp = 1;
}
} else {
}
break;
case SESTYP_DOORLOCK:
} else {
}
break;
case SESTYP_ALARM:
/*
* On all nonzero but the 'muted' bit, we turn on the alarm,
*/
} else {
}
break;
default:
break;
}
return (0);
}
static int
{
int idx;
return (0);
case SESTYP_DEVICE:
}
/* SESCTL_RSTSWAP has no correspondence in SAF-TE */
/*
* Hmm. Try to set the 'No Drive' flag.
* Maybe that will count as a 'disable'.
*/
}
} else {
}
break;
case SESTYP_POWER:
/*
* Okay- the only one that makes sense here is to
* do the 'disable' for a power supply.
*/
}
break;
case SESTYP_FAN:
/*
* Okay- the only one that makes sense here is to
* set fan speed to zero on disable.
*/
/* remember- fans are the first items, so idx works */
}
break;
case SESTYP_DOORLOCK:
/*
* Well, we can 'disable' the lock.
*/
}
break;
case SESTYP_ALARM:
/*
* Well, we can 'disable' the alarm.
*/
}
break;
default:
break;
}
return (0);
}
/*
* This function handles all of the 16 byte WRITE BUFFER commands.
*/
static int
{
int err;
return (0);
return (ENOMEM);
return (err);
}
/*
* This function updates the status byte for the device slot described.
*
* Since this is an optional SAF-TE command, there's no point in
* returning an error.
*/
static void
{
int i;
return;
cdb[0] = SCMD_WRITE_BUFFER;
cdb[2] = 0;
cdb[3] = 0;
cdb[4] = 0;
cdb[5] = 0;
cdb[6] = 0;
cdb[7] = 0;
cdb[9] = 0;
return;
sdata[0] = SAFTE_WT_DSTAT;
}
}
/*
* This function issues the "PERFORM SLOT OPERATION" command.
*/
static int
{
int err;
return (0);
return (ENOMEM);
sdata[0] = SAFTE_WT_SLTOP;
return (err);
}
/*
* mode: c
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/