2021-10-11 18:37:13 -03:00

374 lines
8.2 KiB
C

#ifndef lint
static char sccsid[] = "@(#)standalloc.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* standalloc.c
*
* ROM Monitor's routines for allocating resources needed on a temporary
* basis (eg, for initialization or for boot drivers).
*
* Note, all requests are rounded up to fill a page. This is not a
* malloc() replacement!
*/
/* This flag causes printfs */
#ifdef OPENPROMS
static int alloc_debug = 1;
#define DPRINT if (alloc_debug) printf
#else
#define DPRINT
#endif
#include <machine/param.h>
#include <machine/pte.h>
#include <stand/saio.h>
#include <machine/mmu.h>
/*
* Artifice. This should be defined in <mmu.h>.
*/
#ifndef DVMABASE
# include <machine/cpu.h>
# define DVMABASE (0-DVMASIZE)
#endif
/*
* Artifice so standalone code uses same variable names as monitor's
* for debugging. FIXME? Or leave this way?
*/
struct globram {
char *g_nextrawvirt;
char *g_nextdmaaddr;
struct pte g_nextmainmap;
} gp[1];
/*
* Valid, supervisor-only, memory page's map entry.
* (To be copied to a map entry and then modified.)
*/
struct pte mainmapinit =
#if defined(sun3x)
{0, 0, 0, 1, 0, 0, 0, RW, PTE_VALID};
#define pg_pfnum pte_pfn
#elif defined(sun4)
{1, KW, 0, OBMEM, 0, 0, 0, 0};
#elif sun4c
{1, KW, 0, OBMEM, 0, 0, 0};
#elif sun4m
{0, 0, 0, 0, MMU_STD_SRWX, MMU_ET_PTE };
#endif
extern int memory_avail;
/*
* Say Something Here FIXME
*/
char *
resalloc(type, bytes)
enum RESOURCES type;
register unsigned bytes;
{
register char * addr; /* Allocated address */
register char * raddr; /* Running addr in loop */
#ifdef OPENPROMS
if (prom_getversion() > 0) {
switch (type) {
case RES_RAWVIRT:
addr = gp->g_nextrawvirt;
gp->g_nextrawvirt += bytes;
return (addr);
case RES_DMAVIRT:
addr = gp->g_nextdmaaddr;
gp->g_nextdmaaddr += bytes;
return (addr);
case RES_MAINMEM:
addr = gp->g_nextrawvirt;
gp->g_nextrawvirt += bytes;
break;
case RES_DMAMEM:
addr = gp->g_nextdmaaddr;
gp->g_nextdmaaddr += bytes;
break;
default:
return ((char *)0);
}
}
#endif
#ifndef sun4m
/* Initialize if needed. */
if (gp->g_nextrawvirt == 0) {
#ifdef OPENPROMS
if (prom_getversion() == 0)
reset_alloc((*(romp->v_availmemory))->size);
#else OPENPROMS
reset_alloc(*romp->v_memoryavail);
#endif OPENPROMS
}
DPRINT("resalloc(%x, %x) %x %x %x\n", type, bytes,
gp->g_nextrawvirt, gp->g_nextdmaaddr, *(int*)&(gp->g_nextmainmap));
if (bytes == 0)
return ((char *)0);
bytes = (bytes + (PAGESIZE - 1)) & ~(PAGESIZE - 1);
switch (type) {
case RES_RAWVIRT:
addr = gp->g_nextrawvirt;
gp->g_nextrawvirt += bytes;
return (addr);
case RES_DMAVIRT:
addr = gp->g_nextdmaaddr;
gp->g_nextdmaaddr += bytes;
return (addr);
case RES_MAINMEM:
addr = gp->g_nextrawvirt;
gp->g_nextrawvirt += bytes;
break;
case RES_DMAMEM:
addr = gp->g_nextdmaaddr;
gp->g_nextdmaaddr += bytes;
break;
default:
return ((char *)0);
}
/*
* Now map in main memory.
* Note that this loop goes backwards!!
*/
DPRINT("mapping to %x returning %x gp %x\n",
*(int*)&gp->g_nextmainmap, addr, gp);
for (raddr = addr;
bytes > 0;
raddr += PAGESIZE, bytes -= PAGESIZE,
gp->g_nextmainmap.pg_pfnum -= 1) {
setpgmap(raddr, *(int *)&gp->g_nextmainmap);
bzero((caddr_t)raddr, PAGESIZE);
}
return (addr);
#endif !sun4m
}
#ifdef sun3
struct pte devmaps[] = {
/* MAINMEM */
{1, KW, 0, OBMEM, 0, 0, 0},
/* OBIO */
{1, KW, 0, OBIO, 0, 0, 0},
/* MBMEM */
{1, KW, 0, VME_D16, 0, 0, btop(0xFF000000) },
/* MBIO */
{1, KW, 0, VME_D16, 0, 0, btop(0xFFFF0000) },
/* VME16A16D */
{1, KW, 0, VME_D16, 0, 0, btop(0xFFFF0000) },
/* VME16A32D */
{1, KW, 0, VME_D32, 0, 0, btop(0xFFFF0000) },
/* VME24A16D */
{1, KW, 0, VME_D16, 0, 0, btop(0xFF000000) },
/* VME24A32D */
{1, KW, 0, VME_D32, 0, 0, btop(0xFF000000) },
/* VME32A16D */
{1, KW, 0, VME_D16, 0, 0, btop(0x00000000) },
/* VME32A32D */
{1, KW, 0, VME_D32, 0, 0, btop(0x00000000) },
};
#endif sun3
#ifdef sun3x
struct pte devmaps[] = {
/* MAINMEM */
{0, 0, 0, 0, 0, 0, 0, RW, PTE_VALID},
/* OBIO */
{0, 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* MBMEM */
{btop(VME24D16_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* MBIO */
{btop(VME16D16_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* VME16A16D */
{btop(VME16D16_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* VME16A32D--not supported */
{0, 0, 0, 1, 0, 0, 0, RW, 0},
/* VME24A16D */
{btop(VME24D16_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* VME24A32D */
{btop(VME24D32_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
/* VME32A16D--not supported */
{0, 0, 0, 1, 0, 0, 0, RW, 0},
/* VME32A32D */
{btop(VME32D32_BASE), 0, 0, 1, 0, 0, 0, RW, PTE_VALID},
};
#endif sun3x
#ifdef sun4
struct pte devmaps[] = {
/* MAINMEM */
{1, KW, 0, OBMEM, 0, 0, 0, 0},
/* OBIO */
{1, KW, 0, OBIO, 0, 0, 0, 0},
/* MBMEM */
{1, KW, 0, VME_D16, 0, 0, 0, btop(0xFF000000) },
/* MBIO */
{1, KW, 0, VME_D16, 0, 0, 0, btop(0xFFFF0000) },
/* VME16A16D */
{1, KW, 0, VME_D16, 0, 0, 0, btop(0xFFFF0000) },
/* VME16A32D */
{1, KW, 0, VME_D32, 0, 0, 0, btop(0xFFFF0000) },
/* VME24A16D */
{1, KW, 0, VME_D16, 0, 0, 0, btop(0xFF000000) },
/* VME24A32D */
{1, KW, 0, VME_D32, 0, 0, 0, btop(0xFF000000) },
/* VME32A16D */
{1, KW, 0, VME_D16, 0, 0, 0, btop(0x00000000) },
/* VME32A32D */
{1, KW, 0, VME_D32, 0, 0, 0, btop(0x00000000) },
};
#endif sun4
#ifdef sun4c
struct pte devmaps[] = {
/* MAINMEM */
{1, KW, 0, OBMEM, 0, 0, 0},
/* OBIO */
{1, KW, 0, OBIO, 0, 0, 0},
};
#endif sun4c
#ifdef nodef
#ifdef sun4m
struct pte devmaps[] = {
/* MAINMEM */
{0, 0, 0, 0, MMU_STD_SRWX, MMU_ET_PTE},
/* OBIO */
{0, 0, 0, 0, MMU_STD_SRWX, MMU_ET_PTE},
};
#endif sun4m
#endif nodef
/*
* devalloc() allocates virtual memory and maps it to a device
* at a specific physical address.
*
* It returns the virtual address of that physical device.
*/
char *
devalloc(devtype, physaddr, bytes)
enum MAPTYPES devtype;
register char *physaddr;
register unsigned bytes;
{
char *addr;
register char *raddr;
register int pages;
struct pte mapper;
#ifdef OPENPROMS
extern char *prom_map();
#endif OPENPROMS
DPRINT("devalloc(%x, %x, %x) ", devtype, physaddr, bytes);
if (!bytes)
return ((char *)0);
pages = bytes + ((int)(physaddr) & (PAGESIZE-1));
#ifdef OPENPROMS
if (prom_getversion() > 0)
return (prom_map(0, devtype, physaddr, pages));
#endif
#ifndef sun4m
addr = resalloc(RES_RAWVIRT, pages);
if (!addr)
return ((char *)0);
mapper = devmaps[(int)devtype]; /* Set it up first */
mapper.pg_pfnum += btop(physaddr);
for (raddr = addr;
pages > 0;
raddr += PAGESIZE, pages -= PAGESIZE,
mapper.pg_pfnum += 1) {
DPRINT("mapping to %x ", *(int *)&mapper);
setpgmap(raddr, *(int *)&mapper);
}
DPRINT("returns roughly %x\n", addr);
return (addr + ((int)(physaddr) & (PAGESIZE-1)));
#endif !sun4m
}
#ifndef sun4m
/*
* reset_alloc() does all the setup and all the releasing for the PROMs.
*/
reset_alloc(memsize)
unsigned memsize;
{
#ifdef sun3
int i, addr, pmeg;
gp->g_nextrawvirt = (char *)0x200000;
/*
* The monitor only allocates as many PMEGs as there is real
* memory so we have to set up more PMEGs for virtual memory
* on machines with only 2 megabytes.
*/
for (i=0; i < 0x100000; i += PMGRPSIZE) { /* 1 Meg */
addr = (int)gp->g_nextrawvirt + i;
pmeg = addr / PMGRPSIZE;
setsegmap(addr, pmeg);
}
#elif defined(sun4c)
/*
* The booter loads itself at 3 Meg so we add an extra half-Meg to
* get to a place to allocate virtual addresses and still have pmegs.
* This only applies to Campus proms; OBP machines use the romvec
* alloc/free routines below.
*/
gp->g_nextrawvirt = (char *)0x380000;
#else
/*
* The booter loads itself at 2 Meg so we add an extra Meg to
* get to a place to allocate virtual addresses and still have pmegs.
* This assumes that the minimum memory size for "modern" Suns is 4 Meg.
*/
gp->g_nextrawvirt = (char *)0x300000;
#endif
gp->g_nextdmaaddr = (char *)DVMABASE;
gp->g_nextmainmap = mainmapinit;
gp->g_nextmainmap.pg_pfnum = btop(memsize) - 1;
DPRINT("reset_alloc(%x) mainmap %x gp %x nextmain %x\n",
memsize, *(int *)&mainmapinit, gp, *(int*)&gp->g_nextmainmap);
}
#endif !sun4m
#ifdef OPENPROMS
our_die_routine(retaddr)
register caddr_t retaddr;
{
return;
}
#endif OPENPROMS