/*
 * kl_mem.c
 *
 * This file handles the architecture-independent parts KLIB.
 *
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH,
 *                    IBM Corporation
 */
#include <klib.h>

int cmpreadmem(int fd, paddr_t in_addr, char *buffer,
        unsigned int nbytes, unsigned int flags);

/*
 * Name: seekmem()
 * Func: Seek through physical system memory or vmcore image to the offset
 *       of a particular physical address.
 */
static k_error_t
seekmem(meminfo_t *mip, paddr_t paddr)
{
	off_t off;

	kl_reset_error();
	if ((off = lseek(mip->core_fd, paddr, SEEK_SET)) == -1) {
		KL_ERROR = KLE_INVALID_LSEEK;
	}
	return(KL_ERROR);
}

/*
 * Name: kl_readmem()
 * Func: Read a 'size' block from physical address 'addr' in the system 
 *       memory image.
 */
k_error_t
kl_readmem(paddr_t addr, unsigned size, void *buffer)
{
	meminfo_t *mip;

	kl_reset_error();

	if ((mip = KLP->k_meminfo)) {
		if (mip->core_type == dev_kmem) {
			seekmem(mip, addr);
			if (!KL_ERROR) {
				if (read(mip->core_fd, buffer, size) != size) {
					KL_ERROR = KLE_INVALID_READ;	
				}
			} 
		} else if(mip->core_type == s390_core) {
                        seekmem(mip, addr + S390_DUMP_HEADER_SIZE);
                        if (!KL_ERROR) {
                                if (read(mip->core_fd, buffer, size) != size) {
                                        KL_ERROR = KLE_INVALID_READ;
                                }
                        }
                } else {
			if (cmpreadmem(mip->core_fd, addr, buffer,
				size, 0) <= 0) {
					KL_ERROR = KLE_INVALID_READ;
			}
		}
	} else {
		KL_ERROR = KLE_BAD_MEMINFO;
	}
	return(KL_ERROR);
}

/*
 * Name: kl_readmem()
 * Func: Read a 'size' block from virtual address 'addr' in the system 
 *       memory image.
 */
k_error_t
kl_readkmem(kaddr_t addr, unsigned size, void *buffer)
{
	meminfo_t *mip;
	int fd;
	ssize_t readcnt;

	kl_reset_error();

	mip = KLP->k_meminfo;
	if ((mip && mip->core_type == dev_kmem)) {

		if ((fd = open("/dev/kmem", O_RDONLY)) < 0)
			return KLE_INVALID_READ; 

		if (lseek(fd, addr, SEEK_SET) == -1) {
			close(fd);
			return KLE_INVALID_READ;
		}

		readcnt = read(fd, buffer, size);
		if (readcnt != size)
			KL_ERROR = KLE_INVALID_READ;

		close(fd);
	} else {
		KL_ERROR = KLE_INVALID_READ;
	}
	return(KL_ERROR);
}
