remove realmode and e820 code from kernel
parent
d8c69ebafd
commit
563437cb6d
|
@ -642,13 +642,6 @@ hexadecimal 64-bit
|
||||||
and
|
and
|
||||||
.I end
|
.I end
|
||||||
addresses of the usable memory areas.
|
addresses of the usable memory areas.
|
||||||
.SS \fL*norealmode=\fP
|
|
||||||
The PC kernel switches the processor to 16-bit real mode
|
|
||||||
to run BIOS interrupts, for example to find the memory map or to enable VESA.
|
|
||||||
This variable disables such switches.
|
|
||||||
.SS \fL*noe820scan=\fP
|
|
||||||
When available, the PC kernel uses the BIOS E820 memory map
|
|
||||||
to size memory. This variable disables the scan.
|
|
||||||
.SS \fL*maxmem=\fIvalue\fP
|
.SS \fL*maxmem=\fIvalue\fP
|
||||||
This defines the maximum physical address that the system will scan when sizing memory.
|
This defines the maximum physical address that the system will scan when sizing memory.
|
||||||
By default the PC operating system will scan up to 3.75 gigabytes
|
By default the PC operating system will scan up to 3.75 gigabytes
|
||||||
|
|
|
@ -989,6 +989,39 @@ archctlwrite(Chan*, void *a, long n, vlong)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
rmemrw(int isr, void *a, long n, vlong off)
|
||||||
|
{
|
||||||
|
if(off < 0 || n < 0)
|
||||||
|
error("bad offset/count");
|
||||||
|
if(isr){
|
||||||
|
if(off >= MB)
|
||||||
|
return 0;
|
||||||
|
if(off+n >= MB)
|
||||||
|
n = MB - off;
|
||||||
|
memmove(a, KADDR((ulong)off), n);
|
||||||
|
}else{
|
||||||
|
/* allow vga framebuf's access */
|
||||||
|
if(off >= MB || off+n > MB ||
|
||||||
|
(off < 0xA0000 || off+n > 0xB0000+0x10000))
|
||||||
|
error("bad offset/count in write");
|
||||||
|
memmove(KADDR((ulong)off), a, n);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
rmemread(Chan*, void *a, long n, vlong off)
|
||||||
|
{
|
||||||
|
return rmemrw(1, a, n, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
rmemwrite(Chan*, void *a, long n, vlong off)
|
||||||
|
{
|
||||||
|
return rmemrw(0, a, n, off);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
archinit(void)
|
archinit(void)
|
||||||
{
|
{
|
||||||
|
@ -1037,6 +1070,7 @@ archinit(void)
|
||||||
|
|
||||||
addarchfile("cputype", 0444, cputyperead, nil);
|
addarchfile("cputype", 0444, cputyperead, nil);
|
||||||
addarchfile("archctl", 0664, archctlread, archctlwrite);
|
addarchfile("archctl", 0664, archctlread, archctlwrite);
|
||||||
|
addarchfile("realmodemem", 0660, rmemread, rmemwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
172
sys/src/9/pc/l.s
172
sys/src/9/pc/l.s
|
@ -309,178 +309,6 @@ TEXT restoreregs(SB), $0
|
||||||
POPL AX
|
POPL AX
|
||||||
RET
|
RET
|
||||||
|
|
||||||
/*
|
|
||||||
* Assumed to be in protected mode at time of call.
|
|
||||||
* Switch to real mode, execute an interrupt, and
|
|
||||||
* then switch back to protected mode.
|
|
||||||
*
|
|
||||||
* Assumes:
|
|
||||||
*
|
|
||||||
* - no device interrupts are going to come in
|
|
||||||
* - 0-16MB is identity mapped in page tables
|
|
||||||
* - realmode() has copied us down from 0x100000 to 0x8000
|
|
||||||
* - can use code segment 0x0800 in real mode
|
|
||||||
* to get at l.s code
|
|
||||||
* - l.s code is less than 1 page
|
|
||||||
*/
|
|
||||||
#define RELOC (RMCODE-KTZERO)
|
|
||||||
|
|
||||||
TEXT realmodeidtptr(SB), $0
|
|
||||||
WORD $(4*256-1)
|
|
||||||
LONG $0
|
|
||||||
|
|
||||||
TEXT realmode0(SB), $0
|
|
||||||
CALL saveregs(SB)
|
|
||||||
|
|
||||||
/* switch to low code address */
|
|
||||||
LEAL physcode-KZERO(SB), AX
|
|
||||||
JMP *AX
|
|
||||||
|
|
||||||
TEXT physcode(SB), $0
|
|
||||||
|
|
||||||
/* switch to low stack */
|
|
||||||
MOVL SP, AX
|
|
||||||
MOVL $0x7C00, SP
|
|
||||||
PUSHL AX
|
|
||||||
|
|
||||||
/* change gdt to physical pointer */
|
|
||||||
MOVL m0rgdtptr-KZERO(SB), GDTR
|
|
||||||
|
|
||||||
/* load IDT with real-mode version*/
|
|
||||||
MOVL realmodeidtptr-KZERO(SB), IDTR
|
|
||||||
|
|
||||||
/* edit INT $0x00 instruction below */
|
|
||||||
MOVL $(RMUADDR-KZERO+48), AX /* &rmu.trap */
|
|
||||||
MOVL (AX), AX
|
|
||||||
MOVB AX, realmodeintrinst+(-KZERO+1+RELOC)(SB)
|
|
||||||
|
|
||||||
/* disable paging */
|
|
||||||
MOVL CR0, AX
|
|
||||||
ANDL $0x7FFFFFFF, AX
|
|
||||||
MOVL AX, CR0
|
|
||||||
/* JMP .+2 to clear prefetch queue*/
|
|
||||||
BYTE $0xEB; BYTE $0x00
|
|
||||||
|
|
||||||
/* jump to 16-bit code segment */
|
|
||||||
/* JMPFAR SELECTOR(KESEG16, SELGDT, 0):$again16bit(SB) /**/
|
|
||||||
BYTE $0xEA
|
|
||||||
LONG $again16bit-KZERO(SB)
|
|
||||||
WORD $SELECTOR(KESEG16, SELGDT, 0)
|
|
||||||
|
|
||||||
TEXT again16bit(SB), $0
|
|
||||||
/*
|
|
||||||
* Now in 16-bit compatibility mode.
|
|
||||||
* These are 32-bit instructions being interpreted
|
|
||||||
* as 16-bit instructions. I'm being lazy and
|
|
||||||
* not using the macros because I know when
|
|
||||||
* the 16- and 32-bit instructions look the same
|
|
||||||
* or close enough.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* disable protected mode and jump to real mode cs */
|
|
||||||
OPSIZE; MOVL CR0, AX
|
|
||||||
OPSIZE; XORL BX, BX
|
|
||||||
OPSIZE; INCL BX
|
|
||||||
OPSIZE; XORL BX, AX
|
|
||||||
OPSIZE; MOVL AX, CR0
|
|
||||||
|
|
||||||
/* JMPFAR 0x0800:now16real */
|
|
||||||
BYTE $0xEA
|
|
||||||
WORD $now16real-KZERO(SB)
|
|
||||||
WORD $0x0800
|
|
||||||
|
|
||||||
TEXT now16real(SB), $0
|
|
||||||
/* copy the registers for the bios call */
|
|
||||||
LWI(0x0000, rAX)
|
|
||||||
MOVW AX,SS
|
|
||||||
LWI(RMUADDR, rBP)
|
|
||||||
|
|
||||||
/* offsets are in Ureg */
|
|
||||||
LXW(44, xBP, rAX)
|
|
||||||
MOVW AX, DS
|
|
||||||
LXW(40, xBP, rAX)
|
|
||||||
MOVW AX, ES
|
|
||||||
|
|
||||||
OPSIZE; LXW(0, xBP, rDI)
|
|
||||||
OPSIZE; LXW(4, xBP, rSI)
|
|
||||||
OPSIZE; LXW(16, xBP, rBX)
|
|
||||||
OPSIZE; LXW(20, xBP, rDX)
|
|
||||||
OPSIZE; LXW(24, xBP, rCX)
|
|
||||||
OPSIZE; LXW(28, xBP, rAX)
|
|
||||||
|
|
||||||
CLC
|
|
||||||
|
|
||||||
TEXT realmodeintrinst(SB), $0
|
|
||||||
INT $0x00
|
|
||||||
|
|
||||||
/* save the registers after the call */
|
|
||||||
|
|
||||||
LWI(0x7bfc, rSP)
|
|
||||||
OPSIZE; PUSHFL
|
|
||||||
OPSIZE; PUSHL AX
|
|
||||||
|
|
||||||
LWI(0, rAX)
|
|
||||||
MOVW AX,SS
|
|
||||||
LWI(RMUADDR, rBP)
|
|
||||||
|
|
||||||
OPSIZE; SXW(rDI, 0, xBP)
|
|
||||||
OPSIZE; SXW(rSI, 4, xBP)
|
|
||||||
OPSIZE; SXW(rBX, 16, xBP)
|
|
||||||
OPSIZE; SXW(rDX, 20, xBP)
|
|
||||||
OPSIZE; SXW(rCX, 24, xBP)
|
|
||||||
OPSIZE; POPL AX
|
|
||||||
OPSIZE; SXW(rAX, 28, xBP)
|
|
||||||
|
|
||||||
MOVW DS, AX
|
|
||||||
OPSIZE; SXW(rAX, 44, xBP)
|
|
||||||
MOVW ES, AX
|
|
||||||
OPSIZE; SXW(rAX, 40, xBP)
|
|
||||||
|
|
||||||
OPSIZE; POPL AX
|
|
||||||
OPSIZE; SXW(rAX, 64, xBP) /* flags */
|
|
||||||
|
|
||||||
/* re-enter protected mode and jump to 32-bit code */
|
|
||||||
OPSIZE; MOVL $1, AX
|
|
||||||
OPSIZE; MOVL AX, CR0
|
|
||||||
|
|
||||||
/* JMPFAR SELECTOR(KESEG, SELGDT, 0):$again32bit(SB) /**/
|
|
||||||
OPSIZE
|
|
||||||
BYTE $0xEA
|
|
||||||
LONG $again32bit-KZERO(SB)
|
|
||||||
WORD $SELECTOR(KESEG, SELGDT, 0)
|
|
||||||
|
|
||||||
TEXT again32bit(SB), $0
|
|
||||||
MOVW $SELECTOR(KDSEG, SELGDT, 0),AX
|
|
||||||
MOVW AX,DS
|
|
||||||
MOVW AX,SS
|
|
||||||
MOVW AX,ES
|
|
||||||
MOVW AX,FS
|
|
||||||
MOVW AX,GS
|
|
||||||
|
|
||||||
/* enable paging and jump to kzero-address code */
|
|
||||||
MOVL CR0, AX
|
|
||||||
ORL $0x80010000, AX /* PG|WP */
|
|
||||||
MOVL AX, CR0
|
|
||||||
LEAL again32kzero(SB), AX
|
|
||||||
JMP* AX
|
|
||||||
|
|
||||||
TEXT again32kzero(SB), $0
|
|
||||||
/* breathe a sigh of relief - back in 32-bit protected mode */
|
|
||||||
|
|
||||||
/* switch to old stack */
|
|
||||||
PUSHL AX /* match popl below for 8l */
|
|
||||||
MOVL $0x7BFC, SP
|
|
||||||
POPL SP
|
|
||||||
|
|
||||||
/* restore idt */
|
|
||||||
MOVL m0idtptr(SB),IDTR
|
|
||||||
|
|
||||||
/* restore gdt */
|
|
||||||
MOVL m0gdtptr(SB), GDTR
|
|
||||||
|
|
||||||
CALL restoreregs(SB)
|
|
||||||
RET
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BIOS32.
|
* BIOS32.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,8 +60,6 @@
|
||||||
#define CONFADDR (KZERO+0x1200) /* info passed from boot loader */
|
#define CONFADDR (KZERO+0x1200) /* info passed from boot loader */
|
||||||
#define TMPADDR (KZERO+0x2000) /* used for temporary mappings */
|
#define TMPADDR (KZERO+0x2000) /* used for temporary mappings */
|
||||||
#define APBOOTSTRAP (KZERO+0x3000) /* AP bootstrap code */
|
#define APBOOTSTRAP (KZERO+0x3000) /* AP bootstrap code */
|
||||||
#define RMUADDR (KZERO+0x7C00) /* real mode Ureg */
|
|
||||||
#define RMCODE (KZERO+0x8000) /* copy of first page of KTEXT */
|
|
||||||
#define RMBUF (KZERO+0x9000) /* buffer for user space - known to vga */
|
#define RMBUF (KZERO+0x9000) /* buffer for user space - known to vga */
|
||||||
#define IDTADDR (KZERO+0x10800) /* idt */
|
#define IDTADDR (KZERO+0x10800) /* idt */
|
||||||
#define REBOOTADDR (0x11000) /* reboot code - physical address */
|
#define REBOOTADDR (0x11000) /* reboot code - physical address */
|
||||||
|
|
|
@ -526,20 +526,10 @@ struct Emap
|
||||||
{
|
{
|
||||||
uvlong base;
|
uvlong base;
|
||||||
uvlong len;
|
uvlong len;
|
||||||
ulong type;
|
|
||||||
};
|
};
|
||||||
static Emap emap[16];
|
static Emap emap[16];
|
||||||
int nemap;
|
int nemap;
|
||||||
|
|
||||||
static char *etypes[] =
|
|
||||||
{
|
|
||||||
"type=0",
|
|
||||||
"memory",
|
|
||||||
"reserved",
|
|
||||||
"acpi reclaim",
|
|
||||||
"acpi nvs",
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
emapcmp(const void *va, const void *vb)
|
emapcmp(const void *va, const void *vb)
|
||||||
{
|
{
|
||||||
|
@ -551,11 +541,7 @@ emapcmp(const void *va, const void *vb)
|
||||||
return -1;
|
return -1;
|
||||||
if(a->base > b->base)
|
if(a->base > b->base)
|
||||||
return 1;
|
return 1;
|
||||||
if(a->len < b->len)
|
return a->len - b->len;
|
||||||
return -1;
|
|
||||||
if(a->len > b->len)
|
|
||||||
return 1;
|
|
||||||
return a->type - b->type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -668,66 +654,29 @@ map(ulong base, ulong len, int type)
|
||||||
static int
|
static int
|
||||||
e820scan(void)
|
e820scan(void)
|
||||||
{
|
{
|
||||||
int i;
|
ulong base, len;
|
||||||
Ureg u;
|
|
||||||
ulong cont, base, len;
|
|
||||||
uvlong last;
|
uvlong last;
|
||||||
Emap *e;
|
Emap *e;
|
||||||
char *s;
|
char *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
if((s = getconf("e820")) != nil){
|
/* passed by bootloader */
|
||||||
for(nemap = 0; nemap < nelem(emap); nemap++){
|
if((s = getconf("e820")) == nil)
|
||||||
if(*s == 0)
|
return -1;
|
||||||
break;
|
for(nemap = 0; nemap < nelem(emap); nemap++){
|
||||||
e = emap + nemap;
|
if(*s == 0)
|
||||||
e->base = strtoull(s, &s, 16);
|
break;
|
||||||
if(*s != ' ')
|
e = emap + nemap;
|
||||||
break;
|
e->base = strtoull(s, &s, 16);
|
||||||
e->len = strtoull(s, &s, 16) - e->base;
|
if(*s != ' ')
|
||||||
if(*s != ' ' && *s != 0 || e->len >= 1ull<<32 || e->len == 0)
|
break;
|
||||||
break;
|
e->len = strtoull(s, &s, 16) - e->base;
|
||||||
e->type = Ememory;
|
if(*s != ' ' && *s != 0 || e->len >= 1ull<<32 || e->len == 0)
|
||||||
}
|
break;
|
||||||
}else{
|
|
||||||
if(getconf("*norealmode") || getconf("*noe820scan"))
|
|
||||||
return -1;
|
|
||||||
cont = 0;
|
|
||||||
for(i=0; i<nelem(emap); i++){
|
|
||||||
memset(&u, 0, sizeof u);
|
|
||||||
u.ax = 0xE820;
|
|
||||||
u.bx = cont;
|
|
||||||
u.cx = 20;
|
|
||||||
u.dx = SMAP;
|
|
||||||
u.es = (PADDR(RMBUF)>>4)&0xF000;
|
|
||||||
u.di = PADDR(RMBUF)&0xFFFF;
|
|
||||||
u.trap = 0x15;
|
|
||||||
realmode(&u);
|
|
||||||
cont = u.bx;
|
|
||||||
if((u.flags&Carry) || u.ax != SMAP || u.cx != 20)
|
|
||||||
break;
|
|
||||||
e = &emap[nemap++];
|
|
||||||
*e = *(Emap*)RMBUF;
|
|
||||||
if(u.bx == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nemap == 0)
|
if(nemap == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
qsort(emap, nemap, sizeof emap[0], emapcmp);
|
qsort(emap, nemap, sizeof emap[0], emapcmp);
|
||||||
|
|
||||||
if(s == nil && getconf("*noe820print") == nil){
|
|
||||||
for(i=0; i<nemap; i++){
|
|
||||||
e = &emap[i];
|
|
||||||
print("E820: %.8llux %.8llux ", e->base, e->base+e->len);
|
|
||||||
if(e->type < nelem(etypes))
|
|
||||||
print("%s\n", etypes[e->type]);
|
|
||||||
else
|
|
||||||
print("type=%lud\n", e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last = 0;
|
last = 0;
|
||||||
for(i=0; i<nemap; i++){
|
for(i=0; i<nemap; i++){
|
||||||
e = &emap[i];
|
e = &emap[i];
|
||||||
|
@ -747,10 +696,7 @@ e820scan(void)
|
||||||
if(last < e->base)
|
if(last < e->base)
|
||||||
map(last, e->base-last, MemUPA);
|
map(last, e->base-last, MemUPA);
|
||||||
last = base+len;
|
last = base+len;
|
||||||
if(e->type == Ememory)
|
map(base, len, MemRAM);
|
||||||
map(base, len, MemRAM);
|
|
||||||
else
|
|
||||||
map(base, len, MemReserved);
|
|
||||||
}
|
}
|
||||||
if(last < (1LL<<32))
|
if(last < (1LL<<32))
|
||||||
map(last, (u32int)-last, MemUPA);
|
map(last, (u32int)-last, MemUPA);
|
||||||
|
|
|
@ -38,7 +38,6 @@ dev
|
||||||
|
|
||||||
link
|
link
|
||||||
segdesc
|
segdesc
|
||||||
realmode
|
|
||||||
devpccard
|
devpccard
|
||||||
devi82365
|
devi82365
|
||||||
apm apmjump
|
apm apmjump
|
||||||
|
|
|
@ -39,7 +39,6 @@ dev
|
||||||
|
|
||||||
link
|
link
|
||||||
segdesc
|
segdesc
|
||||||
realmode
|
|
||||||
devpccard
|
devpccard
|
||||||
devi82365
|
devi82365
|
||||||
apm apmjump
|
apm apmjump
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
#include "u.h"
|
|
||||||
#include "tos.h"
|
|
||||||
#include "../port/lib.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "dat.h"
|
|
||||||
#include "fns.h"
|
|
||||||
#include "io.h"
|
|
||||||
#include "ureg.h"
|
|
||||||
#include "../port/error.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Back the processor into real mode to run a BIOS call,
|
|
||||||
* then return. This must be used carefully, since it
|
|
||||||
* completely disables hardware interrupts (e.g., the i8259)
|
|
||||||
* while running. It is *not* using VM86 mode.
|
|
||||||
* Maybe that's really the right answer, but real mode
|
|
||||||
* is fine for now. We don't expect to use this very much --
|
|
||||||
* just for VGA and APM.
|
|
||||||
*/
|
|
||||||
#define realmoderegs (*(Ureg*)RMUADDR)
|
|
||||||
|
|
||||||
#define LORMBUF (RMBUF-KZERO)
|
|
||||||
|
|
||||||
static Ureg rmu;
|
|
||||||
static Lock rmlock;
|
|
||||||
|
|
||||||
void
|
|
||||||
realmode(Ureg *ureg)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
ulong cr3;
|
|
||||||
extern void realmode0(void); /* in l.s */
|
|
||||||
|
|
||||||
if(getconf("*norealmode"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock(&rmlock);
|
|
||||||
realmoderegs = *ureg;
|
|
||||||
|
|
||||||
/* copy l.s so that it can be run from 16-bit mode */
|
|
||||||
memmove((void*)RMCODE, (void*)KTZERO, 0x1000);
|
|
||||||
|
|
||||||
s = splhi();
|
|
||||||
m->pdb[PDX(0)] = m->pdb[PDX(KZERO)]; /* identity map low */
|
|
||||||
cr3 = getcr3();
|
|
||||||
putcr3(PADDR(m->pdb));
|
|
||||||
if (arch)
|
|
||||||
arch->introff();
|
|
||||||
else
|
|
||||||
i8259off();
|
|
||||||
realmode0();
|
|
||||||
if(m->tss){
|
|
||||||
/*
|
|
||||||
* Called from memory.c before initialization of mmu.
|
|
||||||
* Don't turn interrupts on before the kernel is ready!
|
|
||||||
*/
|
|
||||||
if (arch)
|
|
||||||
arch->intron();
|
|
||||||
else
|
|
||||||
i8259on();
|
|
||||||
}
|
|
||||||
m->pdb[PDX(0)] = 0; /* remove low mapping */
|
|
||||||
putcr3(cr3);
|
|
||||||
splx(s);
|
|
||||||
*ureg = realmoderegs;
|
|
||||||
unlock(&rmlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
rtrapread(Chan*, void *a, long n, vlong off)
|
|
||||||
{
|
|
||||||
if(off < 0)
|
|
||||||
error("badarg");
|
|
||||||
if(n+off > sizeof rmu)
|
|
||||||
n = sizeof rmu - off;
|
|
||||||
if(n <= 0)
|
|
||||||
return 0;
|
|
||||||
memmove(a, (char*)&rmu+off, n);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
rtrapwrite(Chan*, void *a, long n, vlong off)
|
|
||||||
{
|
|
||||||
if(off || n != sizeof rmu)
|
|
||||||
error("write a Ureg");
|
|
||||||
memmove(&rmu, a, sizeof rmu);
|
|
||||||
/*
|
|
||||||
* Sanity check
|
|
||||||
*/
|
|
||||||
if(rmu.trap == 0x10){ /* VBE */
|
|
||||||
rmu.es = (LORMBUF>>4)&0xF000;
|
|
||||||
rmu.di = LORMBUF&0xFFFF;
|
|
||||||
}else
|
|
||||||
error("invalid trap arguments");
|
|
||||||
realmode(&rmu);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
rmemrw(int isr, void *a, long n, vlong off)
|
|
||||||
{
|
|
||||||
if(off < 0 || n < 0)
|
|
||||||
error("bad offset/count");
|
|
||||||
if(isr){
|
|
||||||
if(off >= MB)
|
|
||||||
return 0;
|
|
||||||
if(off+n >= MB)
|
|
||||||
n = MB - off;
|
|
||||||
memmove(a, KADDR((ulong)off), n);
|
|
||||||
}else{
|
|
||||||
/* realmode buf page ok, allow vga framebuf's access */
|
|
||||||
if(off >= MB || off+n > MB ||
|
|
||||||
(off < LORMBUF || off+n > LORMBUF+BY2PG) &&
|
|
||||||
(off < 0xA0000 || off+n > 0xB0000+0x10000))
|
|
||||||
error("bad offset/count in write");
|
|
||||||
memmove(KADDR((ulong)off), a, n);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
rmemread(Chan*, void *a, long n, vlong off)
|
|
||||||
{
|
|
||||||
return rmemrw(1, a, n, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
rmemwrite(Chan*, void *a, long n, vlong off)
|
|
||||||
{
|
|
||||||
return rmemrw(0, a, n, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
realmodelink(void)
|
|
||||||
{
|
|
||||||
addarchfile("realmode", 0660, rtrapread, rtrapwrite);
|
|
||||||
addarchfile("realmodemem", 0660, rmemread, rmemwrite);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue