Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
#include "io.h"
7
#include "../port/error.h"
8
 
9
#define	Image	IMAGE
10
#include <draw.h>
11
#include <memdraw.h>
12
#include <cursor.h>
13
#include "screen.h"
14
 
15
typedef struct
16
{
17
	ushort	ctl;
18
	ushort	pad;
19
	ulong	base;
20
	ulong	pos;
21
} CursorI81x;
22
 
23
enum {
24
	Fbsize		= 8*MB,
25
 
26
	hwCur		= 0x70080,
27
	SRX		= 0x3c4,
28
	DPMSsync	= 0x5002,
29
};
30
 
31
static void
32
i81xblank(VGAscr *scr, int blank)
33
{
34
	char *srx, *srxd, *dpms;
35
	char sr01, mode;
36
 
37
	srx = (char *)scr->mmio+SRX;
38
	srxd = srx+1;
39
	dpms = (char *)scr->mmio+DPMSsync;
40
 
41
	*srx = 0x01;
42
	sr01 = *srxd & ~0x20;
43
	mode = *dpms & 0xf0;
44
 
45
	if(blank) {
46
		sr01 |= 0x20;
47
		mode |= 0x0a;
48
	}
49
	*srxd = sr01;
50
	*dpms = mode;
51
}
52
 
53
static Pcidev *
54
i81xpcimatch(void)
55
{
56
	Pcidev *p;
57
 
58
	p = nil;
59
	while((p = pcimatch(p, 0x8086, 0)) != nil){
60
		switch(p->did){
61
		default:
62
			continue;
63
		case 0x7121:
64
		case 0x7123:
65
		case 0x7125:
66
		case 0x1102:
67
		case 0x1112:
68
		case 0x1132:
69
		case 0x3577:	/* IBM R31 uses intel 830M chipset */
70
			return p;
71
		}
72
	}
73
	return nil;
74
}
75
 
76
static void
77
i81xenable(VGAscr* scr)
78
{
79
	Pcidev *p;
80
	int size;
81
	Mach *mach0;
82
	ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
83
 
84
	if(scr->mmio)
85
		return;
86
	p = i81xpcimatch();
87
	if(p == nil)
88
		return;
89
	scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
90
	if(scr->mmio == 0)
91
		return;
92
	addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
93
 
94
	/* allocate page table */
95
	pgtbl = xspanalloc(64*1024, BY2PG, 0);
96
	scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
97
 
98
	size = p->mem[0].size;
99
	if(size > 0)
100
		size = Fbsize;
101
	vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
102
	addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
103
 
104
	/*
105
	 * allocate backing store for frame buffer
106
	 * and populate device page tables.
107
	 */
108
	fbuf = PADDR(xspanalloc(size, BY2PG, 0));
109
	fbend = PGROUND(fbuf+size);
110
	rp = scr->mmio+0x10000/4;
111
	while(fbuf < fbend) {
112
		*rp++ = fbuf | 1;
113
		fbuf += BY2PG;
114
	}
115
 
116
	/*
117
	 * allocate space for the cursor data in system memory.
118
	 * must be uncached.
119
	 */
120
	cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
121
	mach0 = MACHP(0);
122
	pte = mmuwalk(mach0->pdb, cursor, 2, 0);
123
	if(pte == nil)
124
		panic("i81x cursor mmuwalk");
125
	*pte |= PTEUNCACHED;
126
	scr->storage = cursor;
127
 
128
	scr->blank = i81xblank;
129
	hwblank = 1;
130
}
131
 
132
static void
133
i81xcurdisable(VGAscr* scr)
134
{
135
	CursorI81x *hwcurs;
136
 
137
	if(scr->mmio == 0)
138
		return;
139
	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
140
	hwcurs->ctl = (1<<4);
141
}
142
 
143
static void
144
i81xcurload(VGAscr* scr, Cursor* curs)
145
{
146
	int y;
147
	uchar *p;
148
	CursorI81x *hwcurs;
149
 
150
	if(scr->mmio == 0)
151
		return;
152
	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
153
 
154
	/*
155
	 * Disable the cursor then load the new image in
156
	 * the top-left of the 32x32 array.
157
	 * Unused portions of the image have been initialised to be
158
	 * transparent.
159
	 */
160
	hwcurs->ctl = (1<<4);
161
	p = (uchar*)scr->storage;
162
	for(y = 0; y < 16; y += 2) {
163
		*p++ = ~(curs->clr[2*y]|curs->set[2*y]);
164
		*p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
165
		p += 2;
166
		*p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
167
		*p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
168
		p += 2;
169
		*p++ = curs->set[2*y];
170
		*p++ = curs->set[2*y+1];
171
		p += 2;
172
		*p++ = curs->set[2*y+2];
173
		*p++ = curs->set[2*y+3];
174
		p += 2;
175
	}
176
 
177
	/*
178
	 * Save the cursor hotpoint and enable the cursor.
179
	 * The 0,0 cursor point is top-left.
180
	 */
181
	scr->offset.x = curs->offset.x;
182
	scr->offset.y = curs->offset.y;
183
	hwcurs->ctl = (1<<4)|1;
184
}
185
 
186
static int
187
i81xcurmove(VGAscr* scr, Point p)
188
{
189
	int x, y;
190
	ulong pos;
191
	CursorI81x *hwcurs;
192
 
193
	if(scr->mmio == 0)
194
		return 1;
195
	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
196
 
197
	x = p.x+scr->offset.x;
198
	y = p.y+scr->offset.y;
199
	pos = 0;
200
	if(x < 0) {
201
		pos |= (1<<15);
202
		x = -x;
203
	}
204
	if(y < 0) {
205
		pos |= (1<<31);
206
		y = -y;
207
	}
208
	pos |= ((y&0x7ff)<<16)|(x&0x7ff);
209
	hwcurs->pos = pos;
210
 
211
	return 0;
212
}
213
 
214
static void
215
i81xcurenable(VGAscr* scr)
216
{
217
	int i;
218
	uchar *p;
219
	CursorI81x *hwcurs;
220
 
221
	i81xenable(scr);
222
	if(scr->mmio == 0)
223
		return;
224
	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
225
 
226
	/*
227
	 * Initialise the 32x32 cursor to be transparent in 2bpp mode.
228
	 */
229
	hwcurs->base = PADDR(scr->storage);
230
	p = (uchar*)scr->storage;
231
	for(i = 0; i < 32/2; i++) {
232
		memset(p, 0xff, 8);
233
		memset(p+8, 0, 8);
234
		p += 16;
235
	}
236
	/*
237
	 * Load, locate and enable the 32x32 cursor in 2bpp mode.
238
	 */
239
	i81xcurload(scr, &arrow);
240
	i81xcurmove(scr, ZP);
241
}
242
 
243
VGAdev vgai81xdev = {
244
	"i81x",
245
 
246
	i81xenable,
247
	nil,
248
	nil,
249
	nil,
250
};
251
 
252
VGAcur vgai81xcur = {
253
	"i81xhwgc",
254
 
255
	i81xcurenable,
256
	i81xcurdisable,
257
	i81xcurload,
258
	i81xcurmove,
259
};