allow to handle > 512MByte physical address

This commit is contained in:
uch 1999-11-20 19:44:30 +00:00
parent 041804dc8e
commit 1b4b351fab
1 changed files with 120 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: bus_space.c,v 1.2 1999/11/20 19:40:58 uch Exp $ */
/* $NetBSD: bus_space.c,v 1.3 1999/11/20 19:44:30 uch Exp $ */
/*
* Copyright (c) 1999, by UCHIYAMA Yasushi
@ -25,7 +25,7 @@
* SUCH DAMAGE.
*
*/
/* $NetBSD: bus_space.c,v 1.2 1999/11/20 19:40:58 uch Exp $ */
/* $NetBSD: bus_space.c,v 1.3 1999/11/20 19:44:30 uch Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -70,33 +70,109 @@
#include <sys/map.h>
#include <sys/extent.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <uvm/uvm_extern.h>
#include <mips/cpuregs.h>
#include <mips/pte.h>
#include <machine/bus.h>
#define MAX_BUSSPACE_TAG 3
/* vr_internal_alloc_bus_space_tag called before pmap_bootstrap. */
static struct hpcmips_bus_space sys_bus_space[MAX_BUSSPACE_TAG]; /* System internal, ISA port, ISA mem */
#ifdef BUSSPACEDEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg)
#endif
#define MAX_BUSSPACE_TAG 10
static struct hpcmips_bus_space sys_bus_space[MAX_BUSSPACE_TAG];
static int bus_space_index = 0;
bus_space_handle_t __hpcmips_cacheable __P((bus_space_tag_t, bus_addr_t, bus_size_t, int));
bus_space_tag_t
hpcmips_alloc_bus_space_tag()
{
bus_space_tag_t t;
if (bus_space_index >= MAX_BUSSPACE_TAG)
panic("vr_internal_alloc_bus_space_tag: tag full.");
if (bus_space_index >= MAX_BUSSPACE_TAG) {
panic("hpcmips_internal_alloc_bus_space_tag: tag full.");
}
t = &sys_bus_space[bus_space_index++];
return t;
}
void
hpcmips_init_bus_space_extent(bus_space_tag_t t)
hpcmips_init_bus_space_extent(t)
bus_space_tag_t t;
{
u_int32_t pa, endpa;
vaddr_t va;
/*
* If request physical address is greater than 512MByte,
* mapping it to kseg2.
*/
if (t->t_base >= 0x20000000) {
pa = mips_trunc_page(t->t_base);
endpa = mips_round_page(t->t_base + t->t_size);
if (!(va = uvm_km_valloc(kernel_map, endpa - pa))) {
panic("hpcmips_init_bus_space_extent: can't allocate kernel virtual");
}
DPRINTF(("pa:0x%08x -> kv:0x%08x+0x%08x", (unsigned int)t->t_base,
(unsigned int)va, t->t_size));
t->t_base = va; /* kseg2 addr */
for (; pa < endpa; pa += NBPG, va += NBPG) {
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
}
}
t->t_extent = (void*)extent_create(t->t_name, t->t_base,
t->t_base + t->t_size, M_DEVBUF,
0, 0, EX_NOWAIT);
if (!t->t_extent)
panic("init_resource: unable to allocate %s map", t->t_name);
if (!t->t_extent) {
panic("hpcmips_init_bus_space_extent: unable to allocate %s map", t->t_name);
}
}
bus_space_handle_t
__hpcmips_cacheable(t, bpa, size, cacheable)
bus_space_tag_t t;
bus_addr_t bpa;
bus_size_t size;
int cacheable;
{
vaddr_t va, endva;
pt_entry_t *pte;
u_int32_t opte, npte;
MachFlushCache();
if (t->t_base >= MIPS_KSEG2_START) {
va = mips_trunc_page(bpa);
endva = mips_round_page(bpa + size);
npte = CPUISMIPS3 ? MIPS3_PG_UNCACHED : MIPS1_PG_N;
for (; va < endva; va += NBPG) {
pte = kvtopte(va);
opte = pte->pt_entry;
if (cacheable) {
opte &= ~npte;
} else {
opte |= npte;
}
pte->pt_entry = opte;
/*
* Update the same virtual address entry.
*/
MachTLBUpdate(va, opte);
}
return bpa;
}
return cacheable ? MIPS_PHYS_TO_KSEG0(bpa) : MIPS_PHYS_TO_KSEG1(bpa);
}
/* ARGSUSED */
@ -112,18 +188,19 @@ bus_space_map(t, bpa, size, flags, bshp)
int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
if (!t->t_extent) { /* Before autoconfiguration, can't use extent */
printf("bus_space_map: map temprary region:0x%08x-0x%08x\n", bpa, bpa+size);
DPRINTF(("bus_space_map: map temprary region:0x%08x-0x%08x\n", bpa, bpa+size));
bpa += t->t_base;
} else {
bpa += t->t_base;
if ((err = extent_alloc_region(t->t_extent, bpa, size, EX_NOWAIT|EX_MALLOCOK)))
if ((err = extent_alloc_region(t->t_extent, bpa, size,
EX_NOWAIT|EX_MALLOCOK))) {
return err;
}
}
if (cacheable)
*bshp = MIPS_PHYS_TO_KSEG0(bpa);
else
*bshp = MIPS_PHYS_TO_KSEG1(bpa);
return (0);
*bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
DPRINTF(("\tbus_space_map:%#x(%#x)+%#x\n", bpa, bpa - t->t_base, size));
return 0;
}
/* ARGSUSED */
@ -148,13 +225,17 @@ bus_space_alloc(t, rstart, rend, size, alignment, boundary, flags,
rend += t->t_base;
if ((err = extent_alloc_subregion(t->t_extent, rstart, rend, size,
alignment, boundary,
EX_FAST|EX_NOWAIT|EX_MALLOCOK, &bpa)))
EX_FAST|EX_NOWAIT|EX_MALLOCOK, &bpa))) {
return err;
if (cacheable)
*bshp = MIPS_PHYS_TO_KSEG0(bpa);
else
*bshp = MIPS_PHYS_TO_KSEG1(bpa);
*bpap = bpa;
}
*bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
if (bpap) {
*bpap = bpa;
}
DPRINTF(("\tbus_space_alloc:%#x(%#x)+%#x\n", (unsigned)bpa, (unsigned)(bpa - t->t_base), size));
return 0;
}
@ -178,13 +259,21 @@ bus_space_unmap(t, bsh, size)
{
int err;
u_int32_t addr;
addr = MIPS_KSEG1_TO_PHYS(bsh);
if (!t->t_extent)
return; /* Before autoconfiguration, can't use extent */
if ((err = extent_free(t->t_extent, addr, size, EX_NOWAIT)))
printf("warning: %#x-%#x of %s space lost\n",
bsh, bsh+size, t->t_name);
if (!t->t_extent) {
return; /* Before autoconfiguration, can't use extent */
}
if (t->t_base < MIPS_KSEG2_START) {
addr = MIPS_KSEG1_TO_PHYS(bsh);
} else {
addr = bsh;
}
if ((err = extent_free(t->t_extent, addr, size, EX_NOWAIT))) {
DPRINTF(("warning: %#x-%#x of %s space lost\n",
bsh, bsh+size, t->t_name));
}
}
/* ARGSUSED */
@ -195,7 +284,7 @@ bus_space_subregion(t, bsh, offset, size, nbshp)
bus_size_t offset, size;
bus_space_handle_t *nbshp;
{
*nbshp = bsh + offset;
return (0);
return 0;
}