Files
OpenCellular/util/comm-dev.c
Bill Richardson 85a1941f9d Use EC_CMD_READ_MEMMAP on platforms without mapped memory.
LPC-based ECs provide a region of memory that is mapped into the AP's
address space, making it easy to read.

This CL uses an alternate EC host command to read that region, for those
systems that don't have mapped memory.

BUG=none
BRANCH=none
TEST=none

I tested this by building a special command into ectool.

Change-Id: If5cc52356f61522ae96e20d4c5d365accc299987
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/59662
2013-07-03 14:22:04 -07:00

117 lines
2.5 KiB
C

/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "cros_ec_dev.h"
#include "comm-host.h"
#include "ec_commands.h"
static int fd = -1;
static int ec_command_dev(int command, int version,
const void *outdata, int outsize,
void *indata, int insize)
{
struct cros_ec_command s_cmd;
int r;
s_cmd.command = command;
s_cmd.version = version;
s_cmd.result = 0xff;
s_cmd.outsize = outsize;
s_cmd.outdata = (uint8_t *)outdata;
s_cmd.insize = insize;
s_cmd.indata = indata;
r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd);
if (r < 0) {
fprintf(stderr, "ioctl %d, errno %d (%s), EC result %d\n",
r, errno, strerror(errno), s_cmd.result);
if (errno == EAGAIN && s_cmd.result == EC_RES_IN_PROGRESS) {
s_cmd.command = EC_CMD_RESEND_RESPONSE;
r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd);
fprintf(stderr,
"ioctl %d, errno %d (%s), EC result %d\n",
r, errno, strerror(errno), s_cmd.result);
}
} else if (s_cmd.result != EC_RES_SUCCESS) {
fprintf(stderr, "EC result %d\n", s_cmd.result);
}
return r ? r : s_cmd.insize;
}
static int ec_readmem_dev(int offset, int bytes, void *dest)
{
struct cros_ec_readmem s_mem;
struct ec_params_read_memmap r_mem;
int r;
static int fake_it;
if (!fake_it) {
s_mem.offset = offset;
s_mem.bytes = bytes;
s_mem.buffer = dest;
r = ioctl(fd, CROS_EC_DEV_IOCRDMEM, &s_mem);
if (r < 0 && errno == ENOTTY)
fake_it = 1;
else
return r;
}
r_mem.offset = offset;
r_mem.size = bytes;
return ec_command_dev(EC_CMD_READ_MEMMAP, 0,
&r_mem, sizeof(r_mem),
dest, bytes);
}
int comm_init_dev(void)
{
char version[80];
int r;
char *s;
fd = open("/dev/" CROS_EC_DEV_NAME, O_RDWR);
if (fd < 0)
return 1;
r = read(fd, version, sizeof(version)-1);
if (r <= 0) {
close(fd);
return 2;
}
version[r] = '\0';
s = strchr(version, '\n');
if (s)
*s = '\0';
if (strcmp(version, CROS_EC_DEV_VERSION)) {
close(fd);
return 3;
}
ec_command = ec_command_dev;
if (ec_readmem_dev(EC_MEMMAP_ID, 2, version) == 2 &&
version[0] == 'E' && version[1] == 'C')
ec_readmem = ec_readmem_dev;
/*
* TODO: need a way to get this from the driver and EC. For now,
* pick a magic lowest common denominator value.
*/
ec_max_outsize = EC_HOST_PARAM_SIZE - 8;
return 0;
}