09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * CDDL HEADER START
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen *
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * The contents of this file are subject to the terms of the
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Common Development and Distribution License (the "License").
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * You may not use this file except in compliance with the License.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen *
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * or http://www.opensolaris.org/os/licensing.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * See the License for the specific language governing permissions
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * and limitations under the License.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen *
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * When distributing Covered Code, include this CDDL HEADER in each
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * If applicable, add the following below this CDDL HEADER, with the
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * fields enclosed by brackets "[]" replaced with your own identifying
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * information: Portions Copyright [yyyy] [name of copyright owner]
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen *
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * CDDL HEADER END
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Use is subject to license terms.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#pragma ident "%Z%%M% %I% %E% SMI"
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#include <stdio.h>
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#include <strings.h>
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#include <libgen.h>
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#include <cfga_scsi.h>
7b77b0178ffc12e4b7f782b15747abb8ece8a563jimand#include <sys/scfd/opcioif.h>
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define SCF_DRV "/devices/pseudo/scfd@200:rasctl"
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define SCFRETRY 3
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define SCFIOCWAIT 3
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define OPL_LOCATOR_OPT 0
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define OPL_LED_OPT 1
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen#define OPL_MODE_OPT 2
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenchar *opl_opts[] = {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen "locator",
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen "led",
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen "mode",
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen NULL
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen};
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic scfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_get_scf_logical_disk(const apid_t *apidp, char **errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfiocgetdiskled_t *scf_disk)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int len;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *phys_path;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *strptr;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen phys_path = strdup(apidp->path);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (phys_path == NULL) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, ENOMEM, ERR_OP_FAILED, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk->path[0] = '\0';
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((strptr = strstr(phys_path, ":")) != NULL) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen strptr[0] = '\0';
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen len = snprintf((char *)scf_disk->path, sizeof (scf_disk->path),
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen "%s", (char *)(phys_path));
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (len >= sizeof (scf_disk->path)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen free(phys_path);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_OP_FAILED, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen free(phys_path);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_UNKNOWN, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen free(phys_path);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_OK);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Open the SCF driver and use the ioctl interface to set or get the status.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen *
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Returns 0 on success. Returns OP_FAILED on error.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic scfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_disk_led_control(apid_t *apidp, char **errstring, struct cfga_msg *msgp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int request, scfiocgetdiskled_t *scf_disk)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_ret_t retval;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int scf_fd = -1;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int retry = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* paranoid check */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((apidp == NULL) || (msgp == NULL) || (scf_disk == NULL)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_UNKNOWN, 0, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_get_scf_logical_disk((const apid_t *)apidp, errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (retval != SCFGA_OK) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* errstring is set in opl_get_scf_logical_disk */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (retval);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* Open a file descriptor for the scf driver. */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_fd = open(SCF_DRV, O_RDWR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (scf_fd < 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, errno, ERRARG_OPEN, SCF_DRV, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_LIB_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Use the ioctl interface with the SCF driver to get/set the
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * hdd locator indicator.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen errno = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen while (ioctl(scf_fd, request, scf_disk) < 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* Check Retry Error Number */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (errno != EBUSY && errno != EIO) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* Check Retry Times */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (++retry > SCFRETRY) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen errno = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (void) sleep(SCFIOCWAIT);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (void) close(scf_fd);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((errno != 0) || (retry > SCFRETRY)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, errno, ERR_OP_FAILED, 0, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_LIB_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_OK);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Print the value of the hard disk locator in a human friendly form.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic void
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_print_locator(apid_t *apidp, struct cfga_msg *msgp, unsigned char led)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen led_modeid_t mode = LED_MODE_UNK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((msgp == NULL) || (msgp->message_routine == NULL)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_msg(msgp, MSG_LED_HDR, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen switch ((int)led) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_ON:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_FAULTED;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_OFF:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_OFF;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_BLINK:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_ON;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen default:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_UNK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_led_msg(msgp, apidp, LED_STR_LOCATOR, mode);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * Print the value of the hard disk fault LED in a human friendly form.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic void
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_print_led(apid_t *apidp, struct cfga_msg *msgp, unsigned char led)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen led_modeid_t mode = LED_MODE_UNK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((msgp == NULL) || (msgp->message_routine == NULL)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_msg(msgp, MSG_LED_HDR, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen switch ((int)led) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_ON:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_ON;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_OFF:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_OFF;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case SCF_DISK_LED_BLINK:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_BLINK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen default:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode = LED_MODE_UNK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_led_msg(msgp, apidp, LED_STR_FAULT, mode);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic scfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_setlocator(
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen const char *mode,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen apid_t *apidp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char **errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen struct cfga_msg *msgp)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_ret_t retval;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfiocgetdiskled_t scf_disk;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (strcmp(mode, "on") == 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk.led = SCF_DISK_LED_BLINK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else if (strcmp(mode, "off") == 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk.led = SCF_DISK_LED_OFF;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERRARG_OPT_INVAL, mode, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_disk_led_control(apidp, errstring, msgp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen SCFIOCSETDISKLED, &scf_disk);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (retval);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic scfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_getled(
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int print_switch,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen apid_t *apidp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char **errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen struct cfga_msg *msgp)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_ret_t retval;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfiocgetdiskled_t scf_disk;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (void) memset((void *)&scf_disk, 0, sizeof (scf_disk));
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_disk_led_control(apidp, errstring, msgp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen SCFIOCGETDISKLED, &scf_disk);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (retval != SCFGA_OK) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (retval);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (print_switch == OPL_LED_OPT) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen opl_print_led(apidp, msgp, scf_disk.led);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen opl_print_locator(apidp, msgp, scf_disk.led);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_OK);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenstatic scfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenopl_setled(
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen const char *mode,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen apid_t *apidp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char **errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen struct cfga_msg *msgp)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_ret_t retval;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfiocgetdiskled_t scf_disk;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (void) memset((void *)&scf_disk, 0, sizeof (scf_disk));
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (strcmp(mode, "on") == 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk.led = SCF_DISK_LED_ON;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else if (strcmp(mode, "off") == 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk.led = SCF_DISK_LED_OFF;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else if (strcmp(mode, "blink") == 0) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scf_disk.led = SCF_DISK_LED_BLINK;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERRARG_OPT_INVAL, mode, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_disk_led_control(apidp, errstring, msgp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen SCFIOCSETDISKLED, &scf_disk);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (retval);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * The func argument is a string in one of the two following forms:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * led=LED[,mode=MODE]
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * locator[=on|off]
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * which can generically be thought of as:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * name=value[,name=value]
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * So first, split the function based on the comma into two name-value
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen * pairs.
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen/*ARGSUSED*/
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenscfga_ret_t
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsenplat_dev_led(
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen const char *func,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_cmd_t cmd,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen apid_t *apidp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen prompt_t *argsp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_flags_t flags,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char **errstring)
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen{
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen scfga_ret_t retval = SCFGA_ERR;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *optptr = (char *)func;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *value = NULL;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int opt_locator = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int opt_led = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen int opt_mode = 0;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *locator_value = NULL;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *led_value = NULL;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen char *mode_value = NULL;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (func == NULL) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen while (*optptr != '\0') {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen switch (getsubopt(&optptr, opl_opts, &value)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case OPL_LOCATOR_OPT:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen opt_locator++;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen locator_value = value;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case OPL_LED_OPT:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen opt_led++;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen led_value = value;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen case OPL_MODE_OPT:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen opt_mode++;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen mode_value = value;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen default:
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_OPNOTSUPP);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen break;
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (!opt_locator && !opt_led) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (opt_locator) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((opt_locator > 1) || opt_led || opt_mode ||
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (strncmp(func, "locator", strlen("locator")) != 0) ||
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (locator_value &&
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (strcmp(locator_value, "blink") == 0))) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* Options are sane so set or get the locator. */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (locator_value) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_setlocator(locator_value, apidp,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen errstring, argsp->msgp);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_getled(OPL_LOCATOR_OPT, apidp, errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen argsp->msgp);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (opt_led) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if ((opt_led > 1) || (opt_mode > 1) || (opt_locator) ||
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (strncmp(func, "led", strlen("led")) != 0) ||
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (!led_value || strcmp(led_value, "fault")) ||
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen (opt_mode && !mode_value)) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen cfga_err(errstring, 0, ERR_CMD_INVAL, 0);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (SCFGA_ERR);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen /* options are sane so go ahead and set or get the led */
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen if (mode_value != NULL) {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_setled(mode_value, apidp, errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen argsp->msgp);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen } else {
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen retval = opl_getled(OPL_LED_OPT, apidp, errstring,
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen argsp->msgp);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen }
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen return (retval);
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen
09fe1b16b0d85a4b43987628152f516df3ae9838dnielsen}