|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* Copyright (c) 2015 American Megatrends, Inc.
|
|
Packit Service |
ed0f68 |
* All rights reserved.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
ed0f68 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
ed0f68 |
* are met:
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* 1. Redistributions of source code must retain the above copyright notice,
|
|
Packit Service |
ed0f68 |
* this list of conditions and the following disclaimer.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit Service |
ed0f68 |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit Service |
ed0f68 |
* and/or other materials provided with the distribution.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* 3. Neither the name of the copyright holder nor the names of its
|
|
Packit Service |
ed0f68 |
* contributors may be used to endorse or promote products derived from this
|
|
Packit Service |
ed0f68 |
* software without specific prior written permission.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit Service |
ed0f68 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit Service |
ed0f68 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
ed0f68 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
Packit Service |
ed0f68 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit Service |
ed0f68 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit Service |
ed0f68 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit Service |
ed0f68 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit Service |
ed0f68 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit Service |
ed0f68 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit Service |
ed0f68 |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#define _BSD_SOURCE
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#include <ipmitool/helper.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/log.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/bswap.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_intf.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_oem.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_strings.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_constants.h>
|
|
Packit Service |
ed0f68 |
#include <scsi/sg.h>
|
|
Packit Service |
ed0f68 |
#include <sys/ioctl.h>
|
|
Packit Service |
ed0f68 |
#include <scsi/scsi_ioctl.h>
|
|
Packit Service |
ed0f68 |
#include <scsi/scsi.h>
|
|
Packit Service |
ed0f68 |
#include <sys/file.h>
|
|
Packit Service |
ed0f68 |
#include <sys/stat.h>
|
|
Packit Service |
ed0f68 |
#include <sys/types.h>
|
|
Packit Service |
ed0f68 |
#include <fcntl.h>
|
|
Packit Service |
ed0f68 |
#include <errno.h>
|
|
Packit Service |
ed0f68 |
#include <unistd.h>
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#define PACKED __attribute__ ((packed))
|
|
Packit Service |
ed0f68 |
#define BEGIN_SIG "$G2-CONFIG-HOST$"
|
|
Packit Service |
ed0f68 |
#define BEGIN_SIG_LEN 16
|
|
Packit Service |
ed0f68 |
#define MAX_REQUEST_SIZE 64 * 1024
|
|
Packit Service |
ed0f68 |
#define CMD_RESERVED 0x0000
|
|
Packit Service |
ed0f68 |
#define SCSI_AMICMD_CURI_WRITE 0xE2
|
|
Packit Service |
ed0f68 |
#define SCSI_AMICMD_CURI_READ 0xE3
|
|
Packit Service |
ed0f68 |
#define SCSI_AMIDEF_CMD_SECTOR 0x01
|
|
Packit Service |
ed0f68 |
#define SCSI_AMIDEF_DATA_SECTOR 0x02
|
|
Packit Service |
ed0f68 |
#define ERR_SUCCESS 0 /* Success */
|
|
Packit Service |
ed0f68 |
#define ERR_BIG_DATA 1 /* Too Much Data */
|
|
Packit Service |
ed0f68 |
#define ERR_NO_DATA 2 /* No/Less Data Available */
|
|
Packit Service |
ed0f68 |
#define ERR_UNSUPPORTED 3 /* Unsupported Command */
|
|
Packit Service |
ed0f68 |
#define IN_PROCESS 0x8000 /* Bit 15 of Status */
|
|
Packit Service |
ed0f68 |
#define SCSI_AMICMD_ID 0xEE
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* SCSI Command Packets */
|
|
Packit Service |
ed0f68 |
typedef struct {
|
|
Packit Service |
ed0f68 |
unsigned char OpCode;
|
|
Packit Service |
ed0f68 |
unsigned char Lun;
|
|
Packit Service |
ed0f68 |
unsigned int Lba;
|
|
Packit Service |
ed0f68 |
union {
|
|
Packit Service |
ed0f68 |
struct {
|
|
Packit Service |
ed0f68 |
unsigned char Reserved6;
|
|
Packit Service |
ed0f68 |
unsigned short Length;
|
|
Packit Service |
ed0f68 |
unsigned char Reserved9[3];
|
|
Packit Service |
ed0f68 |
} PACKED Cmd10;
|
|
Packit Service |
ed0f68 |
struct Len32 {
|
|
Packit Service |
ed0f68 |
unsigned int Length32;
|
|
Packit Service |
ed0f68 |
unsigned char Reserved10[2];
|
|
Packit Service |
ed0f68 |
} PACKED Cmd12;
|
|
Packit Service |
ed0f68 |
} PACKED CmdLen;
|
|
Packit Service |
ed0f68 |
} PACKED SCSI_COMMAND_PACKET;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
typedef struct {
|
|
Packit Service |
ed0f68 |
uint8_t byNetFnLUN;
|
|
Packit Service |
ed0f68 |
uint8_t byCmd;
|
|
Packit Service |
ed0f68 |
uint8_t byData[MAX_REQUEST_SIZE];
|
|
Packit Service |
ed0f68 |
} PACKED IPMIUSBRequest_T;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
typedef struct {
|
|
Packit Service |
ed0f68 |
uint8_t BeginSig[BEGIN_SIG_LEN];
|
|
Packit Service |
ed0f68 |
uint16_t Command;
|
|
Packit Service |
ed0f68 |
uint16_t Status;
|
|
Packit Service |
ed0f68 |
uint32_t DataInLen;
|
|
Packit Service |
ed0f68 |
uint32_t DataOutLen;
|
|
Packit Service |
ed0f68 |
uint32_t InternalUseDataIn;
|
|
Packit Service |
ed0f68 |
uint32_t InternalUseDataOut;
|
|
Packit Service |
ed0f68 |
} CONFIG_CMD;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int ipmi_usb_setup(struct ipmi_intf *intf);
|
|
Packit Service |
ed0f68 |
static struct ipmi_rs *ipmi_usb_send_cmd(struct ipmi_intf *intf,
|
|
Packit Service |
ed0f68 |
struct ipmi_rq *req);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
struct ipmi_intf ipmi_usb_intf = {
|
|
Packit Service |
ed0f68 |
.name = "usb",
|
|
Packit Service |
ed0f68 |
.desc = "IPMI USB Interface(OEM Interface for AMI Devices)",
|
|
Packit Service |
ed0f68 |
.setup = ipmi_usb_setup,
|
|
Packit Service |
ed0f68 |
.sendrecv = ipmi_usb_send_cmd,
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
scsiProbeNew(int *num_ami_devices, int *sg_nos)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int inplen = *num_ami_devices;
|
|
Packit Service |
ed0f68 |
int numdevfound = 0;
|
|
Packit Service |
ed0f68 |
char linebuf[81];
|
|
Packit Service |
ed0f68 |
char vendor[81];
|
|
Packit Service |
ed0f68 |
int lineno = 0;
|
|
Packit Service |
ed0f68 |
FILE *fp;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
fp = fopen("/proc/scsi/sg/device_strs", "r");
|
|
Packit Service |
ed0f68 |
if (fp == NULL) {
|
|
Packit Service |
ed0f68 |
/* Return 1 on error */
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
while (1) {
|
|
Packit Service |
ed0f68 |
/* Read line by line and search for "AMI" */
|
|
Packit Service |
ed0f68 |
if (fgets(linebuf, 80, fp) == NULL) {
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (sscanf(linebuf, "%s", vendor) == 1) {
|
|
Packit Service |
ed0f68 |
if (strncmp(vendor, "AMI", strlen("AMI")) == 0) {
|
|
Packit Service |
ed0f68 |
numdevfound++;
|
|
Packit Service |
ed0f68 |
sg_nos[numdevfound - 1] = lineno;
|
|
Packit Service |
ed0f68 |
if (numdevfound == inplen) {
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
lineno++;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
*num_ami_devices = numdevfound;
|
|
Packit Service |
ed0f68 |
if (fp != NULL) {
|
|
Packit Service |
ed0f68 |
fclose(fp);
|
|
Packit Service |
ed0f68 |
fp = NULL;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
OpenCD(struct ipmi_intf *intf, char *CDName)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
intf->fd = open(CDName, O_RDWR);
|
|
Packit Service |
ed0f68 |
if (intf->fd == (-1)) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "OpenCD:Unable to open device, %s",
|
|
Packit Service |
ed0f68 |
strerror(errno));
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
sendscsicmd_SGIO(int cd_desc, unsigned char *cdb_buf, unsigned char cdb_len,
|
|
Packit Service |
ed0f68 |
void *data_buf, unsigned int *data_len, int direction,
|
|
Packit Service |
ed0f68 |
void *sense_buf, unsigned char slen, unsigned int timeout)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
sg_io_hdr_t io_hdr;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Prepare command */
|
|
Packit Service |
ed0f68 |
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
|
|
Packit Service |
ed0f68 |
io_hdr.interface_id = 'S';
|
|
Packit Service |
ed0f68 |
io_hdr.cmd_len = cdb_len;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Transfer direction and length */
|
|
Packit Service |
ed0f68 |
io_hdr.dxfer_direction = direction;
|
|
Packit Service |
ed0f68 |
io_hdr.dxfer_len = *data_len;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
io_hdr.dxferp = data_buf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
io_hdr.cmdp = cdb_buf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
io_hdr.sbp = (unsigned char *)sense_buf;
|
|
Packit Service |
ed0f68 |
io_hdr.mx_sb_len = slen;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
io_hdr.timeout = timeout;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!timeout) {
|
|
Packit Service |
ed0f68 |
io_hdr.timeout = 20000;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (ioctl(cd_desc, SG_IO, &io_hdr) < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "sendscsicmd_SGIO: SG_IO ioctl error");
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
if (io_hdr.status != 0) {
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!timeout) {
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - Not OK");
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - OK");
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
AMI_SPT_CMD_Identify(int cd_desc, char *szSignature)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
SCSI_COMMAND_PACKET IdPkt = {0};
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
unsigned int siglen = 10;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
IdPkt.OpCode = SCSI_AMICMD_ID;
|
|
Packit Service |
ed0f68 |
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&IdPkt,
|
|
Packit Service |
ed0f68 |
10, szSignature, &siglen, SG_DXFER_FROM_DEV,
|
|
Packit Service |
ed0f68 |
NULL, 0, 5000);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return ret;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
IsG2Drive(int cd_desc)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
char szSignature[15];
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
memset(szSignature, 0, 15);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
flock(cd_desc, LOCK_EX);
|
|
Packit Service |
ed0f68 |
ret = AMI_SPT_CMD_Identify(cd_desc, szSignature);
|
|
Packit Service |
ed0f68 |
flock(cd_desc, LOCK_UN);
|
|
Packit Service |
ed0f68 |
if (ret != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG,
|
|
Packit Service |
ed0f68 |
"IsG2Drive:Unable to send ID command to the device");
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (strncmp(szSignature, "$$$AMI$$$", strlen("$$$AMI$$$")) != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"IsG2Drive:Signature mismatch when ID command sent");
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
FindG2CDROM(struct ipmi_intf *intf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int err = 0;
|
|
Packit Service |
ed0f68 |
char device[256];
|
|
Packit Service |
ed0f68 |
int devarray[16];
|
|
Packit Service |
ed0f68 |
int numdev = 16;
|
|
Packit Service |
ed0f68 |
int iter;
|
|
Packit Service |
ed0f68 |
err = scsiProbeNew(&numdev, devarray);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (err == 0 && numdev > 0) {
|
|
Packit Service |
ed0f68 |
for (iter = 0; iter < numdev; iter++) {
|
|
Packit Service |
ed0f68 |
sprintf(device, "/dev/sg%d", devarray[iter]);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!OpenCD(intf, device)) {
|
|
Packit Service |
ed0f68 |
if (!IsG2Drive(intf->fd)) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "USB Device found");
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
close(intf->fd);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Unable to find Virtual CDROM Device");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
ipmi_usb_setup(struct ipmi_intf *intf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
if (FindG2CDROM(intf) == 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Error in USB session setup \n");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
intf->opened = 1;
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
void
|
|
Packit Service |
ed0f68 |
InitCmdHeader(CONFIG_CMD *pG2CDCmdHeader)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
memset(pG2CDCmdHeader, 0, sizeof(CONFIG_CMD));
|
|
Packit Service |
ed0f68 |
memcpy((char *)pG2CDCmdHeader->BeginSig, BEGIN_SIG, BEGIN_SIG_LEN);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
AMI_SPT_CMD_SendCmd(int cd_desc, char *Buffer, char type, uint16_t buflen,
|
|
Packit Service |
ed0f68 |
unsigned int timeout)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
SCSI_COMMAND_PACKET Cmdpkt;
|
|
Packit Service |
ed0f68 |
char sensebuff[32];
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
unsigned int pktLen;
|
|
Packit Service |
ed0f68 |
int count = 3;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
Cmdpkt.OpCode = SCSI_AMICMD_CURI_WRITE;
|
|
Packit Service |
ed0f68 |
Cmdpkt.Lba = htonl(type);
|
|
Packit Service |
ed0f68 |
Cmdpkt.CmdLen.Cmd10.Length = htons(1);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
pktLen = buflen;
|
|
Packit Service |
ed0f68 |
while (count > 0) {
|
|
Packit Service |
ed0f68 |
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
|
|
Packit Service |
ed0f68 |
10, Buffer, &pktLen, SG_DXFER_TO_DEV,
|
|
Packit Service |
ed0f68 |
sensebuff, 32, timeout);
|
|
Packit Service |
ed0f68 |
count--;
|
|
Packit Service |
ed0f68 |
if (ret == 0) {
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
ret = (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return ret;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
AMI_SPT_CMD_RecvCmd(int cd_desc, char *Buffer, char type, uint16_t buflen)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
SCSI_COMMAND_PACKET Cmdpkt;
|
|
Packit Service |
ed0f68 |
char sensebuff[32];
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
unsigned int pktLen;
|
|
Packit Service |
ed0f68 |
int count = 3;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
Cmdpkt.OpCode = SCSI_AMICMD_CURI_READ;
|
|
Packit Service |
ed0f68 |
Cmdpkt.Lba = htonl(type);
|
|
Packit Service |
ed0f68 |
Cmdpkt.CmdLen.Cmd10.Length = htons(1);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
pktLen = buflen;
|
|
Packit Service |
ed0f68 |
while (count > 0) {
|
|
Packit Service |
ed0f68 |
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
|
|
Packit Service |
ed0f68 |
10, Buffer, &pktLen, SG_DXFER_FROM_DEV,
|
|
Packit Service |
ed0f68 |
sensebuff, 32, 5000);
|
|
Packit Service |
ed0f68 |
count--;
|
|
Packit Service |
ed0f68 |
if (0 == ret) {
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
ret = (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return ret;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
ReadCD(int cd_desc, char CmdData, char *Buffer, uint32_t DataLen)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
ret = AMI_SPT_CMD_RecvCmd(cd_desc, Buffer, CmdData, DataLen);
|
|
Packit Service |
ed0f68 |
if (ret != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Error while reading CD-Drive");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
WriteCD(int cd_desc, char CmdData, char *Buffer, unsigned int timeout,
|
|
Packit Service |
ed0f68 |
uint32_t DataLen)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int ret;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
ret = AMI_SPT_CMD_SendCmd(cd_desc, Buffer, CmdData, DataLen, timeout);
|
|
Packit Service |
ed0f68 |
if (ret != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Error while writing to CD-Drive");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
WriteSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
|
|
Packit Service |
ed0f68 |
uint32_t NumBytes, uint32_t timeout)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
uint32_t BytesWritten = 0;
|
|
Packit Service |
ed0f68 |
int retVal;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (NumBytes == 0) {
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
while (BytesWritten < NumBytes) {
|
|
Packit Service |
ed0f68 |
if ((retVal = WriteCD(intf->fd, Sector,
|
|
Packit Service |
ed0f68 |
(Buffer + BytesWritten),
|
|
Packit Service |
ed0f68 |
timeout, NumBytes)) != 0) {
|
|
Packit Service |
ed0f68 |
return retVal;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
BytesWritten += NumBytes;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
ReadSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
|
|
Packit Service |
ed0f68 |
uint32_t NumBytes)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
uint32_t BytesRead = 0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (NumBytes == 0) {
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
while (BytesRead < NumBytes) {
|
|
Packit Service |
ed0f68 |
if (ReadCD(intf->fd, Sector, (Buffer + BytesRead),
|
|
Packit Service |
ed0f68 |
NumBytes) == (-1)) {
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
BytesRead += NumBytes;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
WaitForCommandCompletion(struct ipmi_intf *intf, CONFIG_CMD *pG2CDCmdHeader,
|
|
Packit Service |
ed0f68 |
uint32_t timeout, uint32_t DataLen)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
uint32_t TimeCounter = 0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
do {
|
|
Packit Service |
ed0f68 |
if (ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
Packit Service |
ed0f68 |
(char *)(pG2CDCmdHeader), DataLen) == (-1)) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "ReadCD returned ERROR");
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (pG2CDCmdHeader->Status & IN_PROCESS) {
|
|
Packit Service |
ed0f68 |
usleep(1000);
|
|
Packit Service |
ed0f68 |
if (timeout > 0) {
|
|
Packit Service |
ed0f68 |
TimeCounter++;
|
|
Packit Service |
ed0f68 |
if (TimeCounter == (timeout + 1)) {
|
|
Packit Service |
ed0f68 |
return 2;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Command completed");
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
} while (1);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
SendDataToUSBDriver(struct ipmi_intf *intf, char *ReqBuffer,
|
|
Packit Service |
ed0f68 |
unsigned int ReqBuffLen, unsigned char *ResBuffer,
|
|
Packit Service |
ed0f68 |
int *ResBuffLen, unsigned int timeout)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
char CmdHeaderBuffer[sizeof(CONFIG_CMD)];
|
|
Packit Service |
ed0f68 |
int retVal;
|
|
Packit Service |
ed0f68 |
int waitretval = 0;
|
|
Packit Service |
ed0f68 |
unsigned int to = 0;
|
|
Packit Service |
ed0f68 |
uint32_t DataLen = 0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
CONFIG_CMD *pG2CDCmdHeader = (CONFIG_CMD *)CmdHeaderBuffer;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* FillHeader */
|
|
Packit Service |
ed0f68 |
InitCmdHeader(pG2CDCmdHeader);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Set command number */
|
|
Packit Service |
ed0f68 |
pG2CDCmdHeader->Command = CMD_RESERVED;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Fill Lengths */
|
|
Packit Service |
ed0f68 |
pG2CDCmdHeader->DataOutLen = *ResBuffLen;
|
|
Packit Service |
ed0f68 |
pG2CDCmdHeader->DataInLen = ReqBuffLen;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!timeout) {
|
|
Packit Service |
ed0f68 |
to = 3000;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
DataLen = sizeof(CONFIG_CMD);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (WriteCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
Packit Service |
ed0f68 |
(char *)(pG2CDCmdHeader), to, DataLen) == (-1)) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"Error in Write CD of SCSI_AMIDEF_CMD_SECTOR");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Write the data to hard disk */
|
|
Packit Service |
ed0f68 |
if ((retVal = WriteSplitData(intf, ReqBuffer,
|
|
Packit Service |
ed0f68 |
SCSI_AMIDEF_DATA_SECTOR,
|
|
Packit Service |
ed0f68 |
ReqBuffLen, timeout)) != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"Error in WriteSplitData of SCSI_AMIDEF_DATA_SECTOR");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!timeout) {
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Read Status now */
|
|
Packit Service |
ed0f68 |
waitretval = WaitForCommandCompletion(intf, pG2CDCmdHeader, timeout,
|
|
Packit Service |
ed0f68 |
DataLen);
|
|
Packit Service |
ed0f68 |
if (waitretval != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "WaitForCommandComplete failed");
|
|
Packit Service |
ed0f68 |
return (0 - waitretval);
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "WaitForCommandCompletion SUCCESS");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
switch (pG2CDCmdHeader->Status) {
|
|
Packit Service |
ed0f68 |
case ERR_SUCCESS:
|
|
Packit Service |
ed0f68 |
*ResBuffLen = pG2CDCmdHeader->DataOutLen;
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Before ReadSplitData %x", *ResBuffLen);
|
|
Packit Service |
ed0f68 |
if (ReadSplitData(intf, (char *)ResBuffer,
|
|
Packit Service |
ed0f68 |
SCSI_AMIDEF_DATA_SECTOR,
|
|
Packit Service |
ed0f68 |
pG2CDCmdHeader->DataOutLen) != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"Err ReadSplitData SCSI_AMIDEF_DATA_SCTR");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
/* Additional read to see verify there was not problem
|
|
Packit Service |
ed0f68 |
* with the previous read
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
DataLen = sizeof(CONFIG_CMD);
|
|
Packit Service |
ed0f68 |
ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
Packit Service |
ed0f68 |
(char *)(pG2CDCmdHeader), DataLen);
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
case ERR_BIG_DATA:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Too much data");
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
case ERR_NO_DATA:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Too little data");
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
case ERR_UNSUPPORTED:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unsupported command");
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
default:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unknown status");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return pG2CDCmdHeader->Status;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static struct ipmi_rs *
|
|
Packit Service |
ed0f68 |
ipmi_usb_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
static struct ipmi_rs rsp;
|
|
Packit Service |
ed0f68 |
long timeout = 20000;
|
|
Packit Service |
ed0f68 |
uint8_t byRet = 0;
|
|
Packit Service |
ed0f68 |
char ReqBuff[MAX_REQUEST_SIZE] = {0};
|
|
Packit Service |
ed0f68 |
IPMIUSBRequest_T *pReqPkt = (IPMIUSBRequest_T *)ReqBuff;
|
|
Packit Service |
ed0f68 |
int retries = 0;
|
|
Packit Service |
ed0f68 |
/********** FORM IPMI PACKET *****************/
|
|
Packit Service |
ed0f68 |
pReqPkt->byNetFnLUN = req->msg.netfn << 2;
|
|
Packit Service |
ed0f68 |
pReqPkt->byNetFnLUN += req->msg.lun;
|
|
Packit Service |
ed0f68 |
pReqPkt->byCmd = req->msg.cmd;
|
|
Packit Service |
ed0f68 |
if (req->msg.data_len) {
|
|
Packit Service |
ed0f68 |
memcpy(pReqPkt->byData, req->msg.data, req->msg.data_len);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/********** SEND DATA TO USB ******************/
|
|
Packit Service |
ed0f68 |
while (retries < 3) {
|
|
Packit Service |
ed0f68 |
retries++;
|
|
Packit Service |
ed0f68 |
byRet = SendDataToUSBDriver(intf, ReqBuff,
|
|
Packit Service |
ed0f68 |
2 + req->msg.data_len, rsp.data,
|
|
Packit Service |
ed0f68 |
&rsp.data_len,timeout);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (byRet == 0) {
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (retries == 3) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"Error while sending command using",
|
|
Packit Service |
ed0f68 |
"SendDataToUSBDriver");
|
|
Packit Service |
ed0f68 |
rsp.ccode = byRet;
|
|
Packit Service |
ed0f68 |
return &rsp;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rsp.ccode = rsp.data[0];
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Save response data for caller */
|
|
Packit Service |
ed0f68 |
if ((rsp.ccode == 0) && (rsp.data_len > 0)) {
|
|
Packit Service |
ed0f68 |
memmove(rsp.data, rsp.data + 1, rsp.data_len - 1);
|
|
Packit Service |
ed0f68 |
rsp.data[rsp.data_len] = 0;
|
|
Packit Service |
ed0f68 |
rsp.data_len -= 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return &rsp;
|
|
Packit Service |
ed0f68 |
}
|