|
Packit Service |
db8df9 |
/*
|
|
Packit Service |
db8df9 |
* Intel(R) Enclosure LED Utilities
|
|
Packit Service |
db8df9 |
* Copyright (C) 2009-2019 Intel Corporation.
|
|
Packit Service |
db8df9 |
*
|
|
Packit Service |
db8df9 |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit Service |
db8df9 |
* under the terms and conditions of the GNU General Public License,
|
|
Packit Service |
db8df9 |
* version 2, as published by the Free Software Foundation.
|
|
Packit Service |
db8df9 |
*
|
|
Packit Service |
db8df9 |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit Service |
db8df9 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit Service |
db8df9 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
Packit Service |
db8df9 |
* more details.
|
|
Packit Service |
db8df9 |
*
|
|
Packit Service |
db8df9 |
* You should have received a copy of the GNU General Public License along with
|
|
Packit Service |
db8df9 |
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
db8df9 |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
db8df9 |
*
|
|
Packit Service |
db8df9 |
*/
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
#include <errno.h>
|
|
Packit Service |
db8df9 |
#include <limits.h>
|
|
Packit Service |
db8df9 |
#include <stdint.h>
|
|
Packit Service |
db8df9 |
#include <stdio.h>
|
|
Packit Service |
db8df9 |
#include <stdlib.h>
|
|
Packit Service |
db8df9 |
#include <string.h>
|
|
Packit Service |
db8df9 |
#include <unistd.h>
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
#if _HAVE_DMALLOC_H
|
|
Packit Service |
db8df9 |
#include <dmalloc.h>
|
|
Packit Service |
db8df9 |
#endif
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
#include "ahci.h"
|
|
Packit Service |
db8df9 |
#include "config.h"
|
|
Packit Service |
db8df9 |
#include "utils.h"
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
/**
|
|
Packit Service |
db8df9 |
* Time interval in nano seconds to wait before enclosure management message
|
|
Packit Service |
db8df9 |
* is being sent to AHCI controller.
|
|
Packit Service |
db8df9 |
*/
|
|
Packit Service |
db8df9 |
#define EM_MSG_WAIT 1500000 /* 0.0015 seconds */
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
/**
|
|
Packit Service |
db8df9 |
* This array maps IBPI pattern to value recognized by AHCI driver. The driver
|
|
Packit Service |
db8df9 |
* uses this control number to issue SGPIO signals appropriately.
|
|
Packit Service |
db8df9 |
*/
|
|
Packit Service |
db8df9 |
static const unsigned int ibpi2sgpio[] = {
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_REBUILD] = 0x00480000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_FAILED_DRIVE] = 0x00400000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_LOCATE] = 0x00080000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_UNKNOWN] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_ONESHOT_NORMAL] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_NORMAL] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_LOCATE_OFF] = 0x00000000,
|
|
Packit Service |
db8df9 |
#ifdef DEBUG_IBPI
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_DEGRADED] = 0x00200000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_FAILED_ARRAY] = 0x00280000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_HOTSPARE] = 0x01800000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_PFA] = 0x01400000
|
|
Packit Service |
db8df9 |
#else
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_DEGRADED] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_FAILED_ARRAY] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_HOTSPARE] = 0x00000000,
|
|
Packit Service |
db8df9 |
[IBPI_PATTERN_PFA] = 0x00000000
|
|
Packit Service |
db8df9 |
#endif
|
|
Packit Service |
db8df9 |
};
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
/*
|
|
Packit Service |
db8df9 |
* The function sends a LED control message to AHCI controller. It uses
|
|
Packit Service |
db8df9 |
* SGPIO to control the LEDs. See ahci.h for details.
|
|
Packit Service |
db8df9 |
*/
|
|
Packit Service |
db8df9 |
int ahci_sgpio_write(struct block_device *device, enum ibpi_pattern ibpi)
|
|
Packit Service |
db8df9 |
{
|
|
Packit Service |
db8df9 |
char temp[WRITE_BUFFER_SIZE];
|
|
Packit Service |
db8df9 |
char path[PATH_MAX];
|
|
Packit Service |
db8df9 |
char *sysfs_path = device->cntrl_path;
|
|
Packit Service |
db8df9 |
const struct timespec waittime = {
|
|
Packit Service |
db8df9 |
.tv_sec = 0,
|
|
Packit Service |
db8df9 |
.tv_nsec = EM_MSG_WAIT
|
|
Packit Service |
db8df9 |
};
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
/* write only if state has changed */
|
|
Packit Service |
db8df9 |
if (ibpi == device->ibpi_prev)
|
|
Packit Service |
db8df9 |
return 1;
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
if (sysfs_path == NULL)
|
|
Packit Service |
db8df9 |
__set_errno_and_return(EINVAL);
|
|
Packit Service |
db8df9 |
if ((ibpi < IBPI_PATTERN_NORMAL) || (ibpi > IBPI_PATTERN_LOCATE_OFF))
|
|
Packit Service |
db8df9 |
__set_errno_and_return(ERANGE);
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
sprintf(temp, "%u", ibpi2sgpio[ibpi]);
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
snprintf(path, sizeof(path), "%s/em_message", sysfs_path);
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
nanosleep(&waittime, NULL);
|
|
Packit Service |
db8df9 |
return buf_write(path, temp) > 0;
|
|
Packit Service |
db8df9 |
}
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
#define SCSI_HOST "/scsi_host"
|
|
Packit Service |
db8df9 |
/*
|
|
Packit Service |
db8df9 |
* The function return path to SATA port in sysfs tree. See ahci.h for details.
|
|
Packit Service |
db8df9 |
*/
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
char *ahci_get_port_path(const char *path)
|
|
Packit Service |
db8df9 |
{
|
|
Packit Service |
db8df9 |
char *p;
|
|
Packit Service |
db8df9 |
char tmp[PATH_MAX];
|
|
Packit Service |
db8df9 |
char *buf;
|
|
Packit Service |
db8df9 |
size_t buf_size;
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
p = strstr(path, "/target");
|
|
Packit Service |
db8df9 |
if (p == NULL)
|
|
Packit Service |
db8df9 |
return NULL;
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
if (sizeof(tmp) <= (p - path))
|
|
Packit Service |
db8df9 |
return NULL;
|
|
Packit Service |
db8df9 |
strncpy(tmp, path, p - path);
|
|
Packit Service |
db8df9 |
tmp[p - path] = '\0';
|
|
Packit Service |
db8df9 |
p = strrchr(tmp, PATH_DELIM);
|
|
Packit Service |
db8df9 |
if (p == NULL)
|
|
Packit Service |
db8df9 |
return NULL;
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
buf_size = strlen(tmp) + strlen(p) + strlen(SCSI_HOST) + 1;
|
|
Packit Service |
db8df9 |
buf = malloc(buf_size);
|
|
Packit Service |
db8df9 |
if (buf == NULL)
|
|
Packit Service |
db8df9 |
return NULL;
|
|
Packit Service |
db8df9 |
|
|
Packit Service |
db8df9 |
snprintf(buf, buf_size, "%s%s%s", tmp, SCSI_HOST, p);
|
|
Packit Service |
db8df9 |
return buf;
|
|
Packit Service |
db8df9 |
}
|