Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"tos.h"
3
#include	"../port/lib.h"
4
#include	"mem.h"
5
#include	"dat.h"
6
#include	"fns.h"
7
#include	"io.h"
8
#include	"ureg.h"
9
#include	"../port/error.h"
10
 
11
/*
12
 * Back the processor into real mode to run a BIOS call,
13
 * then return.  This must be used carefully, since it 
14
 * completely disables hardware interrupts (e.g., the i8259)
15
 * while running.  It is *not* using VM86 mode. 
16
 * Maybe that's really the right answer, but real mode
17
 * is fine for now.  We don't expect to use this very much --
18
 * just for VGA and APM.
19
 */
20
#define realmoderegs (*(Ureg*)RMUADDR)
21
 
22
#define LORMBUF (RMBUF-KZERO)
23
 
24
static Ureg rmu;
25
static Lock rmlock;
26
 
27
void
28
realmode(Ureg *ureg)
29
{
30
	int s;
31
	ulong cr3;
32
	extern void realmode0(void);	/* in l.s */
33
 
34
	if(getconf("*norealmode"))
35
		return;
36
 
37
	lock(&rmlock);
38
	realmoderegs = *ureg;
39
 
40
	/* copy l.s so that it can be run from 16-bit mode */
41
	memmove((void*)RMCODE, (void*)KTZERO, 0x1000);
42
 
43
	s = splhi();
44
	m->pdb[PDX(0)] = m->pdb[PDX(KZERO)];	/* identity map low */
45
	cr3 = getcr3();
46
	putcr3(PADDR(m->pdb));
47
	if (arch)
48
		arch->introff();
49
	else
50
		i8259off();
51
	realmode0();
52
	if(m->tss){
53
		/*
54
		 * Called from memory.c before initialization of mmu.
55
		 * Don't turn interrupts on before the kernel is ready!
56
		 */
57
		if (arch)
58
			arch->intron();
59
		else
60
			i8259on();
61
	}
62
	m->pdb[PDX(0)] = 0;	/* remove low mapping */
63
	putcr3(cr3);
64
	splx(s);
65
	*ureg = realmoderegs;
66
	unlock(&rmlock);
67
}
68
 
69
static long
70
rtrapread(Chan*, void *a, long n, vlong off)
71
{
72
	if(off < 0)
73
		error("badarg");
74
	if(n+off > sizeof rmu)
75
		n = sizeof rmu - off;
76
	if(n <= 0)
77
		return 0;
78
	memmove(a, (char*)&rmu+off, n);
79
	return n;
80
}
81
 
82
static long
83
rtrapwrite(Chan*, void *a, long n, vlong off)
84
{
85
	if(off || n != sizeof rmu)
86
		error("write a Ureg");
87
	memmove(&rmu, a, sizeof rmu);
88
	/*
89
	 * Sanity check
90
	 */
91
	if(rmu.trap == 0x10){	/* VBE */
92
		rmu.es = (LORMBUF>>4)&0xF000;
93
		rmu.di = LORMBUF&0xFFFF;
94
	}else
95
		error("invalid trap arguments");
96
	realmode(&rmu);
97
	return n;
98
}
99
 
100
static long
101
rmemrw(int isr, void *a, long n, vlong off)
102
{
103
	if(off < 0 || n < 0)
104
		error("bad offset/count");
105
	if(isr){
106
		if(off >= MB)
107
			return 0;
108
		if(off+n >= MB)
109
			n = MB - off;
110
		memmove(a, KADDR((ulong)off), n);
111
	}else{
112
		/* realmode buf page ok, allow vga framebuf's access */
113
		if(off >= MB || off+n > MB ||
114
		    (off < LORMBUF || off+n > LORMBUF+BY2PG) &&
115
		    (off < 0xA0000 || off+n > 0xB0000+0x10000))
116
			error("bad offset/count in write");
117
		memmove(KADDR((ulong)off), a, n);
118
	}
119
	return n;
120
}
121
 
122
static long
123
rmemread(Chan*, void *a, long n, vlong off)
124
{
125
	return rmemrw(1, a, n, off);
126
}
127
 
128
static long
129
rmemwrite(Chan*, void *a, long n, vlong off)
130
{
131
	return rmemrw(0, a, n, off);
132
}
133
 
134
void
135
realmodelink(void)
136
{
137
	addarchfile("realmode", 0660, rtrapread, rtrapwrite);
138
	addarchfile("realmodemem", 0660, rmemread, rmemwrite);
139
}
140