Subject: problem with bus_space_map
To: None <tech-kern@netbsd.org>
From: Christian Groessler <cpg@aladdin.de>
List: tech-kern
Date: 02/10/2004 22:06:37
Hi,
I'm trying to write a driver (lkm) which maps the last 8MB of the
memory address space on i386.
See below for the lkm code.
It successfully loads, but when I unload it, the bus_space_unmap call
causes the machine to reboot.
Now when I use (MEM_LEN-1) instead of MEM_LEN for bus_space_[un]map,
I get a panic when I unload the lkm (panic: extent_free: region not
found).
It also appears that in the MEM_LEN case, the mapping isn't really
done, since the mapped address when using MEM_LEN-1 appears in a 8MB
chunk in 'pmap 0' output, whereas with MEM_LEN the mapped address
doesn't appear and also looks suspicious (< 0xC0000000).
I'm new to this so probably I'm doing something wrong. Any help is
appreciated!
chris
--------------------------------------
/* $Id: i860ldr-netbsd.c,v 1.4 2004/02/10 20:23:49 chris Exp $
*
* NetBSD Hauppauge i860 program loader driver
* (c) Copyright 2004 by Christian Groessler, chris@groessler.org
*
* netbsd current feb-2004
*/
#define VERSION_HIGH 0
#define VERSION_LOW 91
#define VERSION_ASC "0.91"
#define VERSION_BETA 1 /* this version is beta */
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/lkm.h>
#include <sys/file.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <machine/bus.h>
/*#include "i860ioctl.h"*/
/*
* function prototypes
*/
static int i860ldr_open(dev_t dev, int flag, int mode, struct proc *p);
static int i860ldr_close(dev_t dev, int flag, int mode, struct proc *p);
static int i860ldr_write(dev_t dev, struct uio *uio, int flags);
/*
* global data
*/
static unsigned int i860memsize = 8192; /* in kb */
#define MEM_BASE (0x100000000LL - i860memsize * 1024)
#define MEM_LEN ((unsigned int)(0x100000000LL - MEM_BASE))
static void *mem_base;
dev_type_open(i860ldr_open);
dev_type_close(i860ldr_close);
dev_type_write(i860ldr_write);
static const struct cdevsw i860ldr_cdevsw = {
i860ldr_open, i860ldr_close, noread, i860ldr_write, noioctl,
nostop, notty, nopoll, nommap, nokqfilter,
};
MOD_DEV("i860ldr", "i860ldr", NULL, -1, &i860ldr_cdevsw, -1)
static bus_space_handle_t memh;
static int
i860ldr_init(void)
{
if (bus_space_map(X86_BUS_SPACE_MEM, MEM_BASE, MEM_LEN, BUS_SPACE_MAP_LINEAR, &memh)) {
printf("i860ldr_init: cannot map phys. memory area %08lX, len %08lX\n",
(unsigned long)MEM_BASE, (unsigned long)MEM_LEN);
return ENXIO;
}
mem_base = bus_space_vaddr(X86_BUS_SPACE_MEM, memh);
return 0;
}
static int
i860ldr_shutdown(void)
{
bus_space_unmap(X86_BUS_SPACE_MEM, memh, MEM_LEN);
return 0;
}
static int
i860ldr_lkm(struct lkm_table *lkmtp, int cmd)
{
int error = 0;
switch (cmd) {
case LKM_E_LOAD:
error = i860ldr_init();
break;
case LKM_E_UNLOAD:
error = i860ldr_shutdown();
break;
case LKM_E_STAT:
error = lkmdispatch(lkmtp, cmd);
break;
}
return (error);
}
/*
* i860ldr_lkmentry
* External entry point.
*/
int i860ldr_lkmentry (struct lkm_table *lkmtp, int cmd, int ver)
{
DISPATCH(lkmtp, cmd, ver, i860ldr_lkm, i860ldr_lkm, lkm_nofunc);
}
/*
* open function
*/
static int i860ldr_open(dev_t dev, int flag, int mode, struct proc *p)
{
if (minor(dev) != 0) return ENXIO;
return 0;
}
/*
* close function
*/
static int i860ldr_close(dev_t dev, int flag, int mode, struct proc *p)
{
return 0;
}
/*
* write function
* access the mapped memory...
*/
static int i860ldr_write(dev_t dev, struct uio *uio, int flags)
{
unsigned char c;
printf("i860ldr_write: ouch!\n");
c = *(unsigned char *)mem_base;
printf("i860ldr_write: nono, it didn't hurt! (c = %02X)\n", c);
return 0;
}
--------------------------------------