Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / ll / ll.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: ll.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
/*
* Copyright (C) 2001, Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "@(#)1.10 04/08/04 SMI ll.cc"
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <strings.h>
#include <utime.h>
#include <unistd.h>
#include "types.h"
#include "macrolib.h"
#include "dr.h"
#include "ll_impl.h"
#include "ll_mod.h"
#include "ui.h"
static bool ll_trace = false;
typedef void* TM_OPAQUE_DATA;
ll_structT *LL::allocation_obj()
{
sp = (ll_structT *) calloc(1, sizeof(ll_structT));
assert(sp);
return (sp);
}
int LL::reg_access(char *buf, LWord paddr, bool_t wr)
{
uint32_t *reg = (uint32_t *)(buf + sizeof(uint64_t)-sizeof(uint32_t));
if (!wr) {
switch (paddr & LL_REG_ADDR_MASK) {
case LL_REG_SR:
*reg = LL::rd_status();
break;
case LL_REG_CR:
/* ignored */
break;
case LL_REG_ECR:
*reg = LL::rd_errorcode();
break;
case LL_REG_ARG_ADDR:
*reg = LL::rd_arg_addr();
break;
case LL_REG_RES_ADDR:
*reg = LL::rd_res_addr();
break;
default:
ui->error(
"%s: reg_access: read: invalid paddr 0x%llx\n", getName(),
paddr);
return (1);
}
} else {
switch (paddr & LL_REG_ADDR_MASK) {
case LL_REG_SR:
/* ignored */
break;
case LL_REG_CR:
LL::wr_control(*reg);
break;
case LL_REG_ECR:
/* ignored */
break;
case LL_REG_ARG_ADDR:
LL::wr_arg_addr(*reg);
break;
case LL_REG_RES_ADDR:
LL::wr_res_addr(*reg);
break;
default:
ui->error(
"%s: reg_access: write: invalid paddr 0x%llx\n", getName(),
paddr);
return (1);
}
}
return (0);
}
uint32_t LL::rd_status()
{
return (sp->reg_sr);
}
uint32_t LL::rd_errorcode()
{
return (sp->reg_ecr);
}
uint32_t LL::rd_arg_addr()
{
return (sp->reg_arg_addr);
}
uint32_t LL::rd_res_addr()
{
return (sp->reg_res_addr);
}
void LL::wr_control(uint32_t val)
{
sp->reg_cr = val;
/* clear errorcode */
sp->reg_ecr = 0;
switch (sp->reg_cr) {
case LL_CR_READ:
LL::cmd_read();
break;
case LL_CR_WRITE:
LL::cmd_write();
break;
case LL_CR_GETATTR:
LL::cmd_getattr();
break;
case LL_CR_SETATTR:
LL::cmd_setattr();
break;
case LL_CR_ACCESS:
LL::cmd_access();
break;
case LL_CR_LOOKUP:
LL::cmd_lookup();
break;
case LL_CR_CREATE:
LL::cmd_create();
break;
case LL_CR_REMOVE:
LL::cmd_remove();
break;
case LL_CR_RENAME:
LL::cmd_rename();
break;
case LL_CR_MKDIR:
LL::cmd_mkdir();
break;
case LL_CR_RMDIR:
LL::cmd_rmdir();
break;
case LL_CR_READDIR:
LL::cmd_readdir();
break;
case LL_CR_SYMLINK:
LL::cmd_symlink();
break;
case LL_CR_READLINK:
LL::cmd_readlink();
break;
default:
ui->error(
"%s: control register: invalid command: %d\n", getName(),
sp->reg_cr);
sp->reg_ecr = ENOTSUP;
break;
}
}
void LL::wr_arg_addr(uint32_t val)
{
sp->reg_arg_addr = val;
}
void LL::wr_res_addr(uint32_t val)
{
sp->reg_res_addr = val;
}
void LL::cmd_read()
{
ll_read_arg_t arg;
ll_read_res_t res;
int fd;
#ifdef LL_CRC
uint32_t crc = 0;
#endif
if (ll_trace) ui->output(
"%s: LL::cmd_read\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_read_arg_t));
if (ll_trace) ui->output(
" path=%s offset=%lld count=%d\n", arg.fh.path, arg.offset,
arg.count);
if ((fd = open(arg.fh.path, O_RDONLY | O_LARGEFILE)) == -1) {
if (ll_trace) ui->output(
" open(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
return;
}
if ((res.count = (uint32_t)pread(fd, res.buf, arg.count,
arg.offset)) == -1) {
if (ll_trace) ui->output(
" pread(%s, %lld, %d) failed (%d)\n", arg.fh.path,
arg.offset, arg.count, errno);
sp->reg_ecr = errno;
return;
}
close(fd);
#ifdef LL_CRC
LL::crc(&crc, res.buf, res.count);
if (ll_trace) ui->output(
" returning count=%d (crc=%x)\n", res.count, crc);
#else
if (ll_trace) ui->output(
" returning count=%d\n", res.count);
#endif
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_read_res_t));
}
void LL::cmd_write()
{
ll_write_arg_t arg;
ll_write_res_t res;
mode_t omode = 0;
int fd;
#ifdef LL_CRC
uint32_t crc = 0;
#endif
if (ll_trace) ui->output(
"%s: LL::cmd_write\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_write_arg_t));
#ifdef LL_CRC
LL::crc(&crc, arg.buf, arg.count);
if (ll_trace) ui->output(
" path=%s offset=%lld count=%d (crc=%x)\n", arg.fh.path,
arg.offset, arg.count, crc);
#else
if (ll_trace) ui->output(
" path=%s offset=%lld count=%d\n", arg.fh.path,
arg.offset, arg.count);
#endif
/*
* This is a hack to allow writes to files created with read only
* permission.
*/
if (access(arg.fh.path, W_OK) == -1) {
struct stat s;
if (stat(arg.fh.path, &s) == -1) {
if (ll_trace) ui->output(
" stat(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
return;
}
if (s.st_uid == getuid()) {
/* We own this file, so go ahead an add write
* permission. */
omode = s.st_mode;
(void) chmod(arg.fh.path, 0600);
}
}
if ((fd = open(arg.fh.path, O_WRONLY | O_LARGEFILE)) == -1) {
if (ll_trace) ui->output(
" open(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
if (omode != 0)
(void) chmod(arg.fh.path, omode);
return;
}
if ((res.count = (uint32_t)pwrite(fd, arg.buf, arg.count,
arg.offset)) == -1) {
if (ll_trace) ui->output(
" write(%s, %lld, %d) failed (%d)\n", arg.fh.path,
arg.offset, arg.count, errno);
sp->reg_ecr = errno;
if (omode != 0)
(void) chmod(arg.fh.path, omode);
return;
}
close(fd);
/* Restore the previous permission if we modified it. */
if (omode != 0)
(void) chmod(arg.fh.path, omode);
if (ll_trace) ui->output(
" returning count=%d\n", res.count);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_write_res_t));
}
void LL::cmd_getattr()
{
ll_getattr_arg_t arg;
ll_getattr_res_t res;
struct stat s;
uint64_t ino_tmp;
if (ll_trace) ui->output(
"%s: LL::cmd_getattr\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_getattr_arg_t));
if (ll_trace) ui->output(
" path=%s\n", arg.fh.path);
if (lstat(arg.fh.path, &s) == -1) {
if (ll_trace) ui->output(
" lstat(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
return;
}
switch (s.st_mode & S_IFMT) {
case S_IFREG: res.attr.type = LL_TYPE_REG; break;
case S_IFDIR: res.attr.type = LL_TYPE_DIR; break;
case S_IFLNK: res.attr.type = LL_TYPE_LNK; break;
default: res.attr.type = LL_TYPE_BAD;
}
res.attr.mode = s.st_mode & S_IAMB;
res.attr.nlink = s.st_nlink;
res.attr.uid = s.st_uid;
res.attr.gid = s.st_gid;
res.attr.size = s.st_size;
res.attr.atime = (int32_t)s.st_atime; /* XXX - trunc in 64-bit mode */
res.attr.mtime = (int32_t)s.st_mtime; /* XXX - trunc in 64-bit mode */
res.attr.ctime = (int32_t)s.st_ctime; /* XXX - trunc in 64-bit mode */
ino_tmp = ((uint64_t)s.st_dev<<32)^s.st_ino;
LL::crc(&res.attr.ino, (uchar_t *)&ino_tmp, sizeof(uint64_t));
if (ll_trace) ui->output(
" returning type=%d mode=0x%x nlink=%d uid=%d gid=%d"
" size=%lld ino=%x\n",
res.attr.type, res.attr.mode, res.attr.nlink, res.attr.uid,
res.attr.gid, res.attr.size, res.attr.ino);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_getattr_res_t));
}
void LL::cmd_setattr()
{
ll_setattr_arg_t arg;
if (ll_trace) ui->output(
"%s: LL::cmd_setattr\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_setattr_arg_t));
if (ll_trace) ui->output(
" path=%s mask=0x%x\n", arg.fh.path, arg.mask);
if (arg.mask & LL_MASK_MODE) {
if (ll_trace) ui->output(
" mode=0x%x\n", arg.attr.mode);
if (chmod(arg.fh.path, arg.attr.mode) == -1) {
if (ll_trace) ui->output(
" chmod(%s, 0x%x) failed (%d)\n", arg.fh.path,
arg.attr.mode, errno);
sp->reg_ecr = errno;
return;
}
}
if (arg.mask & (LL_MASK_UID | LL_MASK_GID)) {
if (arg.mask & LL_MASK_UID) {
if (ll_trace) ui->output(
" uid=%d\n", arg.attr.uid);
if (lchown(arg.fh.path, arg.attr.uid, -1) == -1) {
if (ll_trace) ui->output(
" lchown(%s, %d, -1) failed (%d)\n",
arg.fh.path, arg.attr.uid, errno);
sp->reg_ecr = errno;
return;
}
}
if (arg.mask & LL_MASK_GID) {
if (ll_trace) ui->output(
" gid=%d\n", arg.attr.gid);
if (lchown(arg.fh.path, -1, arg.attr.gid) == -1) {
if (ll_trace) ui->output(
" lchown(%s, -1, %d) failed (%d)\n",
arg.fh.path, arg.attr.gid, errno);
sp->reg_ecr = errno;
return;
}
}
}
if (arg.mask & (LL_MASK_ATIME | LL_MASK_MTIME)) {
struct utimbuf times;
if (arg.mask & (LL_MASK_ATIME | LL_MASK_MTIME)) {
if (ll_trace) ui->output(
" atime & mtime\n");
times.actime = arg.attr.atime;
times.modtime = arg.attr.mtime;
} else {
struct stat s;
if (lstat(arg.fh.path, &s) == -1) {
if (ll_trace) ui->output(
" lstat(%s) failed (%d)\n", arg.fh.path,
errno);
sp->reg_ecr = errno;
return;
}
if (arg.mask & LL_MASK_ATIME) {
if (ll_trace) ui->output(" atime\n");
times.actime = arg.attr.atime;
times.modtime = s.st_mtime;
}
if (arg.mask & LL_MASK_MTIME) {
if (ll_trace) ui->output(" mtime\n");
times.actime = s.st_atime;
times.modtime = arg.attr.mtime;
}
}
if (utime(arg.fh.path, &times) == -1) {
if (ll_trace) ui->output(
" utime(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
return;
}
}
if (arg.mask & LL_MASK_SIZE) {
if (ll_trace) ui->output(
" size=%lld\n", arg.attr.size);
if (truncate(arg.fh.path, arg.attr.size) == -1) {
if (ll_trace) ui->output(
" truncate(%s, %lld) failed (%d)\n", arg.fh.path,
arg.attr.size, errno);
sp->reg_ecr = errno;
return;
}
}
}
void LL::cmd_access()
{
ll_access_arg_t arg;
int amode;
if (ll_trace) ui->output(
"%s: LL::cmd_access\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_access_arg_t));
if (ll_trace) ui->output(
" path=%s\n", arg.fh.path);
amode = 0;
if (arg.amode & LL_AMODE_READ) amode |= R_OK;
if (arg.amode & LL_AMODE_WRITE) amode |= W_OK;
if (arg.amode & LL_AMODE_EXEC) amode |= X_OK;
if (access(arg.fh.path, amode) == -1) {
if (ll_trace) ui->output(
" access(%s, 0x%x) failed (%d)\n", arg.fh.path, amode,
errno);
sp->reg_ecr = errno;
return;
}
}
void LL::cmd_lookup()
{
ll_lookup_arg_t arg;
ll_lookup_res_t res;
struct stat s;
if (ll_trace) ui->output(
"%s: LL::cmd_lookup\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_lookup_arg_t));
if (ll_trace) ui->output(
" dir=%s name=%s\n", arg.dir_fh.path, arg.name);
LL::path_canon(res.fh.path, arg.dir_fh.path, arg.name);
if (lstat(res.fh.path, &s) == -1) {
if (ll_trace) ui->output(
" lstat(%s) failed (%d)\n", res.fh.path, errno);
sp->reg_ecr = errno;
return;
}
switch (s.st_mode & S_IFMT) {
case S_IFREG: res.type = LL_TYPE_REG; break;
case S_IFDIR: res.type = LL_TYPE_DIR; break;
case S_IFLNK: res.type = LL_TYPE_LNK; break;
default: res.type = LL_TYPE_BAD;
}
if (ll_trace) ui->output(
" returning path=%s type=%d\n", res.fh.path, res.type);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_lookup_res_t));
}
void LL::cmd_create()
{
ll_create_arg_t arg;
ll_create_res_t res;
mode_t om;
int fd;
if (ll_trace) ui->output(
"%s: LL::cmd_create\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_create_arg_t));
if (ll_trace) ui->output(
" dir=%s name=%s mode=0x%x\n", arg.dir_fh.path, arg.name,
arg.mode);
LL::path_canon(res.fh.path, arg.dir_fh.path, arg.name);
om = umask(0);
if ((fd = creat(res.fh.path, arg.mode)) == -1) {
if (ll_trace) ui->output(
" creat(%s, 0x%x) failed (%d)\n", res.fh.path, arg.mode,
errno);
sp->reg_ecr = errno;
umask(om);
return;
}
close(fd);
umask(om);
if (ll_trace) ui->output(
" returning path=%s\n", res.fh.path);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_create_res_t));
}
void LL::cmd_remove()
{
ll_remove_arg_t arg;
char path[LL_MAXPATHLEN];
if (ll_trace) ui->output(
"%s: LL::cmd_remove\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_remove_arg_t));
if (ll_trace) ui->output(
" dir=%s name=%s\n", arg.dir_fh.path, arg.name);
LL::path_canon(path, arg.dir_fh.path, arg.name);
if (unlink(path) == -1) {
if (ll_trace) ui->output(
" unlink(%s) failed (%d)\n", path);
sp->reg_ecr = errno;
return;
}
}
void LL::cmd_rename()
{
ll_rename_arg_t arg;
char opath[LL_MAXPATHLEN];
char npath[LL_MAXPATHLEN];
if (ll_trace) ui->output(
"%s: LL::cmd_rename\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_rename_arg_t));
if (ll_trace) ui->output(
" odir=%s oname=%s ndir=%s nname=%s\n", arg.odir_fh.path,
arg.oname, arg.ndir_fh.path, arg.nname);
LL::path_canon(opath, arg.odir_fh.path, arg.oname);
LL::path_canon(npath, arg.ndir_fh.path, arg.nname);
if (rename(opath, npath) == -1) {
if (ll_trace) ui->output(
" rename(%s, %s) failed (%d)\n", opath, npath);
sp->reg_ecr = errno;
return;
}
}
void LL::cmd_mkdir()
{
ll_mkdir_arg_t arg;
ll_mkdir_res_t res;
mode_t om;
if (ll_trace) ui->output(
"%s: LL::cmd_mkdir\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_mkdir_arg_t));
if (ll_trace) ui->output(
" dir=%s name=%s mode=0x%x\n", arg.dir_fh.path, arg.name,
arg.mode);
LL::path_canon(res.fh.path, arg.dir_fh.path, arg.name);
om = umask(0);
if (mkdir(res.fh.path, arg.mode) == -1) {
if (ll_trace) ui->output(
" mkdir(%s, 0x%x) failed (%d)\n", res.fh.path, arg.mode,
errno);
sp->reg_ecr = errno;
umask(om);
return;
}
umask(om);
if (ll_trace) ui->output(
" returning path=%s\n", res.fh.path);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_mkdir_res_t));
}
void LL::cmd_rmdir()
{
ll_rmdir_arg_t arg;
char path[LL_MAXPATHLEN];
if (ll_trace) ui->output(
"%s: LL::cmd_rmdir\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_rmdir_arg_t));
if (ll_trace) ui->output(
" dir=%s name=%s\n", arg.dir_fh.path, arg.name);
LL::path_canon(path, arg.dir_fh.path, arg.name);
if (rmdir(path) == -1) {
if (ll_trace) ui->output(
" rmdir(%s) failed (%d)\n", path, errno);
sp->reg_ecr = errno;
return;
}
}
void LL::cmd_readdir()
{
ll_readdir_arg_t arg;
ll_readdir_res_t res;
struct ll_readdir_ent *rde;
struct ll_rdce *rdce;
int count, bufoff, reclen;
if (ll_trace) ui->output(
"%s: LL::cmd_readdir\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_readdir_arg_t));
if (ll_trace) ui->output(
" path=%s offset=%lld\n", arg.fh.path, arg.offset);
if (arg.offset == 0) {
/* First time - initialize readdir cache */
if (LL::rdc_init(&arg.fh)) {
sp->reg_ecr = errno;
return;
}
rdce = LL::rdce_head;
} else {
/* Skip ahead */
for (count = 0, rdce = LL::rdce_head;
count < arg.offset && rdce != NULL;
count++, rdce = rdce->next)
;
}
bufoff = 0;
res.entries = 0;
while (rdce) {
reclen = (int)strlen(rdce->name) + 1;
reclen +=(int) sizeof(struct ll_readdir_ent);
/* Force 64-bit alignment */
reclen = (reclen + 7) & ~7;
if (reclen > (LL_DB_XFER_SIZE - bufoff))
break;
rde = (struct ll_readdir_ent *)&res.buf[bufoff];
rde->reclen = reclen;
rde->ino = rdce->ino;
strcpy(rde->name, rdce->name);
bufoff += reclen;
res.entries++;
rdce = rdce->next;
if (ll_trace) ui->output(
" name=%s ino=0x%x\n", rde->name, rde->ino);
}
if (ll_trace) ui->output(
" returning entries=%d\n", res.entries);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_readdir_res_t));
}
void LL::cmd_symlink()
{
ll_symlink_arg_t arg;
char cwd[LL_MAXPATHLEN];
if (ll_trace) ui->output(
"%s: LL::cmd_symlink\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_symlink_arg_t));
if (ll_trace) ui->output(
" dir=%s lname=%s tname=%s\n", arg.dir_fh.path, arg.lname,
arg.tname);
if (getcwd(cwd, LL_MAXPATHLEN) == NULL) {
if (ll_trace) ui->output(
" getcwd() failed (%d)\n", errno);
sp->reg_ecr = errno;
return;
}
if (chdir(arg.dir_fh.path) == -1) {
if (ll_trace) ui->output(
" chdir(%s) failed (%d)\n", arg.dir_fh.path, errno);
sp->reg_ecr = errno;
(void) chdir(cwd);
return;
}
if (symlink(arg.tname, arg.lname) == -1) {
if (ll_trace) ui->output(
" symlink(%s, %s) failed (%d)\n", arg.tname, arg.lname,
errno);
sp->reg_ecr = errno;
(void) chdir(cwd);
return;
}
(void) chdir(cwd);
}
void LL::cmd_readlink()
{
ll_readlink_arg_t arg;
ll_readlink_res_t res;
int len;
if (ll_trace) ui->output(
"%s: LL::cmd_readlink\n", getName());
LL::dma_in(sp->reg_arg_addr, &arg, sizeof(ll_readlink_arg_t));
if (ll_trace) ui->output(
" link=%s\n", arg.fh.path);
if ((len = readlink(arg.fh.path, res.path, LL_MAXPATHLEN)) == -1) {
if (ll_trace) ui->output(
" readlink(%s) failed (%d)\n", arg.fh.path, errno);
sp->reg_ecr = errno;
return;
}
res.path[len] = '\0';
if (ll_trace) ui->output(
" returning path=%s\n", res.path);
LL::dma_out(sp->reg_res_addr, &res, sizeof(ll_readlink_res_t));
}
void LL::path_canon(char *canonpath, const char *path, const char *name)
{
size_t len;
strcpy(canonpath, path);
if (strncmp(name, "..", MIN(strlen(name), 2)) == 0) {
/* handle ".." case */
len = strlen(canonpath);
while (len > 1 && (canonpath[len] != '/'))
len--;
canonpath[len] = '\0';
return;
}
/* append "/" to the directory name if not at root */
if ((len = strlen(canonpath)) && canonpath[len-1] != '/') {
strcat(canonpath, "/");
}
/* tack on the name */
strcat(canonpath, name);
}
int LL::rdc_init(struct ll_fhandle *fhp)
{
struct ll_rdce *rdce, *tmp;
DIR *dirp;
char buf[PATH_MAX + 1 + sizeof(struct dirent)];
struct dirent *dp, *retdp;
for (rdce = LL::rdce_head; rdce != NULL; ) {
tmp = rdce->next;
free(rdce);
rdce = tmp;
}
LL::rdce_tail = LL::rdce_head = NULL;
if ((dirp = opendir(fhp->path)) == NULL) {
if (ll_trace) ui->output(
" opendir(%s) failed (%d)\n", fhp->path, errno);
return (errno);
}
dp = (struct dirent *)buf;
errno = 0;
while ((readdir_r(dirp, dp, &retdp) >= 0) && retdp != NULL) {
char path[LL_MAXPATHLEN];
struct stat s;
uint64_t ino_tmp;
rdce = (struct ll_rdce *)calloc(1, sizeof(struct ll_rdce));
LL::path_canon(path, fhp->path, dp->d_name);
if (lstat(path, &s) == -1) {
if (ll_trace) ui->output(
" lstat(%s) failed (%d)\n", path, errno);
return (errno);
}
ino_tmp = ((uint64_t)s.st_dev<<32)^s.st_ino;
LL::crc(&rdce->ino, (uchar_t *)&ino_tmp, sizeof(uint64_t));
strcpy(rdce->name, dp->d_name);
if (LL::rdce_head == NULL) {
LL::rdce_head = rdce;
} else {
rdce->prev = LL::rdce_tail;
LL::rdce_tail->next = rdce;
}
LL::rdce_tail = rdce;
}
if (errno) {
int e = errno;
if (ll_trace) ui->output(
" readdir_r() failed (%d)\n", e);
closedir(dirp);
return (e);
}
closedir(dirp);
return (0);
}
void LL::dma_in(uint64_t vaddr, void *data, long count)
{
//dev_dma_in(vaddr, data, count);
pciMaster_dma(false,vaddr, data, count);
}
void LL::dma_out(uint64_t vaddr, void *data, long count)
{
//dev_dma_out(vaddr, data, count);
pciMaster_dma(true,vaddr, data, count);
}
/*
* LL::crc -- compute 32 bit CRC -- ripped from ON cksum.c
*
* This is a 32 bit CRC with polynomial
* x**32 + x**26 + x**23 + x**22 + x**16 + x**12 + x**11 + x**10 +
* x**8 + x**7 + x**5 + x**4 + x**2 + x**1 + x**0
*/
static uint32_t crctab[256] = {
0x00000000,
0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
};
/*
* LL::crc -- compute 32 bit CRC
*/
void LL::crc(uint32_t *crcp, uchar_t *bp, size_t n)
{
*crcp = 0;
while (n-- > 0)
*crcp = (*crcp<<8) ^ crctab[(uchar_t)((*crcp>>24)^*bp++)];
}
/////////////////////////////////////////////////////////
bool LL::dump (FILE *fp)
{
if (fwrite(sp, sizeof(ll_structT), 1, fp) != 1) {
return FALSE;
}
return genericPciDev::dump(DR_get_dir(),getName());
}
bool LL::restore (FILE *fp)
{
if (fread(sp, sizeof(ll_structT), 1, fp) != 1) {
return FALSE;
}
if (restore_v5_dump())
return genericPciDev::restore(DR_get_dir(),getName());
else
return true;
}