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 CursorNM CursorNM;
16
struct CursorNM {
17
	int	enable;
18
	int	x;
19
	int	y;
20
	int	colour1;
21
	int	colour2;
22
	int	addr;
23
};
24
 
25
static void
26
neomagicenable(VGAscr* scr)
27
{
28
	Pcidev *p;
29
	int curoff, vmsize;
30
	ulong ioaddr;
31
	ulong iosize;
32
 
33
	/*
34
	 * scr->mmio holds the virtual address of the cursor registers
35
	 * in the MMIO space. This may need to change for older chips
36
	 * which have the MMIO space offset in the framebuffer region.
37
	 *
38
	 * scr->io holds the offset into mmio of the CursorNM struct.
39
	 */
40
	if(scr->mmio)
41
		return;
42
	if(p = pcimatch(nil, 0x10C8, 0)){
43
		switch(p->did){
44
		case 0x0003:		/* MagicGraph 128ZV */
45
			curoff = 0x100;
46
			vmsize = 1152*1024;
47
			ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
48
			iosize = 0x200000;
49
			break;
50
		case 0x0083:		/* MagicGraph 128ZV+ */
51
			curoff = 0x100;
52
			vmsize = 1152*1024;
53
			ioaddr = p->mem[1].bar & ~0x0F;
54
			iosize = p->mem[1].size;
55
			break;
56
		case 0x0004:		/* MagicGraph 128XD */
57
			curoff = 0x100;
58
			vmsize = 2048*1024;
59
			ioaddr = p->mem[1].bar & ~0x0F;
60
			iosize = p->mem[1].size;
61
			break;
62
		case 0x0005:		/* MagicMedia 256AV */
63
			curoff = 0x1000;
64
			vmsize = 2560*1024;
65
			ioaddr = p->mem[1].bar & ~0x0F;
66
			iosize = p->mem[1].size;
67
			break;
68
		case 0x0006:		/* MagicMedia 256ZX */
69
			curoff = 0x1000;
70
			vmsize = 4096*1024;
71
			ioaddr = p->mem[1].bar & ~0x0F;
72
			iosize = p->mem[1].size;
73
			break;
74
		case 0x0016:		/* MagicMedia 256XL+ */
75
			curoff = 0x1000;
76
			/* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
77
			vmsize = 4096*1024;
78
			ioaddr = p->mem[1].bar & ~0x0F;
79
			iosize = p->mem[1].size;
80
			break;
81
		default:
82
			return;
83
		}
84
	}
85
	else
86
		return;
87
	scr->pci = p;
88
 
89
	scr->mmio = vmap(ioaddr, iosize);
90
	if(scr->mmio == nil)
91
		return;
92
	addvgaseg("neomagicmmio", ioaddr, iosize);
93
 
94
	/*
95
	 * Find a place for the cursor data in display memory.
96
	 * 2 cursor images might be needed, 1KB each so use the
97
	 * last 2KB of the framebuffer.
98
	 */
99
	scr->storage = vmsize-2*1024;
100
	scr->io = curoff;
101
	vgalinearpci(scr);
102
	if(scr->paddr)
103
		addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
104
}
105
 
106
static void
107
neomagiccurdisable(VGAscr* scr)
108
{
109
	CursorNM *cursornm;
110
 
111
	if(scr->mmio == 0)
112
		return;
113
	cursornm = (void*)((char*)scr->mmio + scr->io);
114
	cursornm->enable = 0;
115
}
116
 
117
static void
118
neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
119
{
120
	uchar *p;
121
	uint p0, p1;
122
	int x, y;
123
 
124
	p = (uchar*)scr->vaddr;
125
	p += scr->storage + index*1024;
126
 
127
	for(y = yo; y < 16; y++){
128
		p0 = scr->set[2*y];
129
		p1 = scr->set[2*y+1];
130
		if(xo){
131
			p0 = (p0<<xo)|(p1>>(8-xo));
132
			p1 <<= xo;
133
		}
134
		*p++ = p0;
135
		*p++ = p1;
136
 
137
		for(x = 16; x < 64; x += 8)
138
			*p++ = 0x00;
139
 
140
		p0 = scr->clr[2*y]|scr->set[2*y];
141
		p1 = scr->clr[2*y+1]|scr->set[2*y+1];
142
		if(xo){
143
			p0 = (p0<<xo)|(p1>>(8-xo));
144
			p1 <<= xo;
145
		}
146
		*p++ = p0;
147
		*p++ = p1;
148
 
149
		for(x = 16; x < 64; x += 8)
150
			*p++ = 0x00;
151
	}
152
	while(y < 64+yo){
153
		for(x = 0; x < 64; x += 8){
154
			*p++ = 0x00;
155
			*p++ = 0x00;
156
		}
157
		y++;
158
	}
159
}
160
 
161
static void
162
neomagiccurload(VGAscr* scr, Cursor* curs)
163
{
164
	CursorNM *cursornm;
165
 
166
	if(scr->mmio == 0)
167
		return;
168
	cursornm = (void*)((char*)scr->mmio + scr->io);
169
 
170
	cursornm->enable = 0;
171
	memmove(&scr->Cursor, curs, sizeof(Cursor));
172
	neomagicinitcursor(scr, 0, 0, 0);
173
	cursornm->enable = 1;
174
}
175
 
176
static int
177
neomagiccurmove(VGAscr* scr, Point p)
178
{
179
	CursorNM *cursornm;
180
	int addr, index, x, xo, y, yo;
181
 
182
	if(scr->mmio == 0)
183
		return 1;
184
	cursornm = (void*)((char*)scr->mmio + scr->io);
185
 
186
	index = 0;
187
	if((x = p.x+scr->offset.x) < 0){
188
		xo = -x;
189
		x = 0;
190
	}
191
	else
192
		xo = 0;
193
	if((y = p.y+scr->offset.y) < 0){
194
		yo = -y;
195
		y = 0;
196
	}
197
	else
198
		yo = 0;
199
 
200
	if(xo || yo){
201
		index = 1;
202
		neomagicinitcursor(scr, xo, yo, index);
203
	}
204
	addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
205
	addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
206
	if(cursornm->addr != addr)
207
		cursornm->addr = addr;
208
 
209
	cursornm->x = x;
210
	cursornm->y = y;
211
 
212
	return 0;
213
}
214
 
215
static void
216
neomagiccurenable(VGAscr* scr)
217
{
218
	CursorNM *cursornm;
219
 
220
	neomagicenable(scr);
221
	if(scr->mmio == 0)
222
		return;
223
	cursornm = (void*)((char*)scr->mmio + scr->io);
224
	cursornm->enable = 0;
225
 
226
	/*
227
	 * Cursor colours.
228
	 */
229
	cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
230
	cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
231
 
232
	/*
233
	 * Load, locate and enable the 64x64 cursor.
234
	 */
235
	neomagiccurload(scr, &arrow);
236
	neomagiccurmove(scr, ZP);
237
	cursornm->enable = 1;
238
}
239
 
240
static int neomagicbltflags;
241
 
242
/* registers */
243
enum {
244
	BltStat = 0,
245
	BltCntl = 1,
246
	XPColor = 2,
247
	FGColor = 3,
248
	BGColor = 4,
249
	Pitch = 5,
250
	ClipLT = 6,
251
	ClipRB = 7,
252
	SrcBitOff = 8,
253
	SrcStartOff = 9,
254
 
255
	DstStartOff = 11,
256
	XYExt = 12,
257
 
258
	PageCntl = 20,
259
	PageBase,
260
	PostBase,
261
	PostPtr,
262
	DataPtr,
263
};
264
 
265
/* flags */
266
enum {
267
	NEO_BS0_BLT_BUSY =	0x00000001,
268
	NEO_BS0_FIFO_AVAIL =	0x00000002,
269
	NEO_BS0_FIFO_PEND =	0x00000004,
270
 
271
	NEO_BC0_DST_Y_DEC =	0x00000001,
272
	NEO_BC0_X_DEC =		0x00000002,
273
	NEO_BC0_SRC_TRANS =	0x00000004,
274
	NEO_BC0_SRC_IS_FG =	0x00000008,
275
	NEO_BC0_SRC_Y_DEC =	0x00000010,
276
	NEO_BC0_FILL_PAT =	0x00000020,
277
	NEO_BC0_SRC_MONO =	0x00000040,
278
	NEO_BC0_SYS_TO_VID =	0x00000080,
279
 
280
	NEO_BC1_DEPTH8 =	0x00000100,
281
	NEO_BC1_DEPTH16 =	0x00000200,
282
	NEO_BC1_DEPTH24 =	0x00000300,
283
	NEO_BC1_X_320 =		0x00000400,
284
	NEO_BC1_X_640 =		0x00000800,
285
	NEO_BC1_X_800 =		0x00000c00,
286
	NEO_BC1_X_1024 =	0x00001000,
287
	NEO_BC1_X_1152 =	0x00001400,
288
	NEO_BC1_X_1280 =	0x00001800,
289
	NEO_BC1_X_1600 =	0x00001c00,
290
	NEO_BC1_DST_TRANS =	0x00002000,
291
	NEO_BC1_MSTR_BLT =	0x00004000,
292
	NEO_BC1_FILTER_Z =	0x00008000,
293
 
294
	NEO_BC2_WR_TR_DST =	0x00800000,
295
 
296
	NEO_BC3_SRC_XY_ADDR =	0x01000000,
297
	NEO_BC3_DST_XY_ADDR =	0x02000000,
298
	NEO_BC3_CLIP_ON =	0x04000000,
299
	NEO_BC3_FIFO_EN =	0x08000000,
300
	NEO_BC3_BLT_ON_ADDR =	0x10000000,
301
	NEO_BC3_SKIP_MAPPING =	0x80000000,
302
 
303
	NEO_MODE1_DEPTH8 =	0x0100,
304
	NEO_MODE1_DEPTH16 =	0x0200,
305
	NEO_MODE1_DEPTH24 =	0x0300,
306
	NEO_MODE1_X_320 =	0x0400,
307
	NEO_MODE1_X_640 =	0x0800,
308
	NEO_MODE1_X_800 =	0x0c00,
309
	NEO_MODE1_X_1024 =	0x1000,
310
	NEO_MODE1_X_1152 =	0x1400,
311
	NEO_MODE1_X_1280 =	0x1800,
312
	NEO_MODE1_X_1600 =	0x1c00,
313
	NEO_MODE1_BLT_ON_ADDR =	0x2000,
314
};
315
 
316
/* Raster Operations */
317
enum {
318
	GXclear =		0x000000,	/* 0x0000 */
319
	GXand =			0x080000,	/* 0x1000 */
320
	GXandReverse =		0x040000,	/* 0x0100 */
321
	GXcopy =		0x0c0000,	/* 0x1100 */
322
	GXandInvert =		0x020000,	/* 0x0010 */
323
	GXnoop =		0x0a0000,	/* 0x1010 */
324
	GXxor =			0x060000,	/* 0x0110 */
325
	GXor =			0x0e0000,	/* 0x1110 */
326
	GXnor =			0x010000,	/* 0x0001 */
327
	GXequiv =		0x090000,	/* 0x1001 */
328
	GXinvert =		0x050000,	/* 0x0101 */
329
	GXorReverse =		0x0d0000,	/* 0x1101 */
330
	GXcopyInvert =		0x030000,	/* 0x0011 */
331
	GXorInverted =		0x0b0000,	/* 0x1011 */
332
	GXnand =		0x070000,	/* 0x0111 */
333
	GXset =			0x0f0000,	/* 0x1111 */
334
};
335
 
336
static void
337
waitforidle(VGAscr *scr)
338
{
339
	ulong *mmio;
340
	long x;
341
 
342
	mmio = scr->mmio;
343
	x = 0;
344
	while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
345
		;
346
	//if(x >= 1000000)
347
	//	iprint("idle stat %lud scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
348
}
349
 
350
static void
351
waitforfifo(VGAscr *scr, int entries)
352
{
353
	ulong *mmio;
354
	long x;
355
 
356
	mmio = scr->mmio;
357
	x = 0;
358
	while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
359
		;
360
	//if(x >= 1000000)
361
	//	iprint("fifo stat %d scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
362
	/* DirectFB says the above doesn't work.  if so... */
363
	/* waitforidle(scr); */
364
}
365
 
366
static int
367
neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
368
{
369
	ulong *mmio;
370
 
371
	mmio = scr->mmio;
372
 
373
	waitforfifo(scr, 1);
374
	mmio[FGColor] = sval;
375
	waitforfifo(scr, 3);
376
	mmio[BltCntl] = neomagicbltflags
377
		| NEO_BC3_FIFO_EN
378
		| NEO_BC0_SRC_IS_FG
379
		| NEO_BC3_SKIP_MAPPING
380
		| GXcopy;
381
	mmio[DstStartOff] = scr->paddr
382
		+ r.min.y*scr->gscreen->width*BY2WD
383
		+ r.min.x*scr->gscreen->depth/BI2BY;
384
	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
385
	waitforidle(scr);
386
	return 1;
387
}
388
 
389
static int
390
neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
391
{
392
	ulong *mmio;
393
	int pitch, pixel;
394
 
395
	mmio = scr->mmio;
396
 
397
	pitch = scr->gscreen->width*BY2WD;
398
	pixel = scr->gscreen->depth/BI2BY;
399
 
400
	waitforfifo(scr, 4);
401
	if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
402
		/* start from upper-left */
403
		mmio[BltCntl] = neomagicbltflags
404
			| NEO_BC3_FIFO_EN
405
			| NEO_BC3_SKIP_MAPPING
406
			| GXcopy;
407
		mmio[SrcStartOff] = scr->paddr
408
			+ sr.min.y*pitch + sr.min.x*pixel;
409
		mmio[DstStartOff] = scr->paddr
410
			+ r.min.y*pitch + r.min.x*pixel;
411
	} else {
412
		/* start from lower-right */
413
		mmio[BltCntl] = neomagicbltflags
414
			| NEO_BC0_X_DEC
415
			| NEO_BC0_DST_Y_DEC
416
			| NEO_BC0_SRC_Y_DEC
417
			| NEO_BC3_FIFO_EN
418
			| NEO_BC3_SKIP_MAPPING
419
			| GXcopy;
420
		mmio[SrcStartOff] = scr->paddr
421
			+ (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
422
		mmio[DstStartOff] = scr->paddr
423
			+ (r.max.y-1)*pitch + (r.max.x-1)*pixel;
424
	}
425
	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
426
	waitforidle(scr);
427
	return 1;
428
}
429
 
430
static void
431
neomagicdrawinit(VGAscr *scr)
432
{
433
	ulong *mmio;
434
	uint bltmode, pitch;
435
 
436
	mmio = scr->mmio;
437
 
438
	pitch = scr->gscreen->width*BY2WD;
439
 
440
	neomagicbltflags = bltmode = 0;
441
 
442
	switch(scr->gscreen->depth) {
443
	case 8:
444
		bltmode |= NEO_MODE1_DEPTH8;
445
		neomagicbltflags |= NEO_BC1_DEPTH8;
446
		break;
447
	case 16:
448
		bltmode |= NEO_MODE1_DEPTH16;
449
		neomagicbltflags |= NEO_BC1_DEPTH16;
450
		break;
451
	case 24:	/* I can't get it to work, and XFree86 doesn't either. */
452
	default:	/* give up */
453
		return;
454
	}
455
 
456
	switch(Dx(scr->gscreen->r)) {
457
	case 320:
458
		bltmode |= NEO_MODE1_X_320;
459
		neomagicbltflags |= NEO_BC1_X_320;
460
		break;
461
	case 640:
462
		bltmode |= NEO_MODE1_X_640;
463
		neomagicbltflags |= NEO_BC1_X_640;
464
		break;
465
	case 800:
466
		bltmode |= NEO_MODE1_X_800;
467
		neomagicbltflags |= NEO_BC1_X_800;
468
		break;
469
	case 1024:
470
		bltmode |= NEO_MODE1_X_1024;
471
		neomagicbltflags |= NEO_BC1_X_1024;
472
		break;
473
	case 1152:
474
		bltmode |= NEO_MODE1_X_1152;
475
		neomagicbltflags |= NEO_BC1_X_1152;
476
		break;
477
	case 1280:
478
		bltmode |= NEO_MODE1_X_1280;
479
		neomagicbltflags |= NEO_BC1_X_1280;
480
		break;
481
	case 1600:
482
		bltmode |= NEO_MODE1_X_1600;
483
		neomagicbltflags |= NEO_BC1_X_1600;
484
		break;
485
	default:
486
		/* don't worry about it */
487
		break;
488
	}
489
 
490
	waitforidle(scr);
491
	mmio[BltStat] = bltmode << 16;
492
	mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
493
 
494
	scr->fill = neomagichwfill;
495
	scr->scroll = neomagichwscroll;
496
}
497
 
498
VGAdev vganeomagicdev = {
499
	"neomagic",
500
 
501
	neomagicenable,
502
	nil,
503
	nil,
504
	nil,
505
	neomagicdrawinit,
506
};
507
 
508
VGAcur vganeomagiccur = {
509
	"neomagichwgc",
510
 
511
	neomagiccurenable,
512
	neomagiccurdisable,
513
	neomagiccurload,
514
	neomagiccurmove,
515
};
516