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 "../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
/*
16
 * #9 Ticket to Ride IV.
17
 */
18
enum {
19
	IndexLo		= 0x10/4,
20
	IndexHi		= 0x14/4,
21
	Data		= 0x18/4,
22
	IndexCtl	= 0x1C/4,
23
 
24
	Zoom		= 0x54/4,
25
};
26
 
27
enum {						/* index registers */
28
	CursorSyncCtl	= 0x03,
29
	  HsyncHi = 0x01,
30
	  HsyncLo = 0x02,
31
	  VsyncHi = 0x04,
32
	  VsyncLo = 0x08,
33
 
34
	CursorCtl	= 0x30,
35
	CursorXLo	= 0x31,
36
	CursorXHi	= 0x32,
37
	CursorYLo	= 0x33,
38
	CursorYHi	= 0x34,
39
	CursorHotX	= 0x35,
40
	CursorHotY	= 0x36,
41
 
42
	CursorR1	= 0x40,
43
	CursorG1	= 0x41,
44
	CursorB1	= 0x42,
45
	CursorR2	= 0x43,
46
	CursorG2	= 0x44,
47
	CursorB2	= 0x45,
48
	CursorR3	= 0x46,
49
	CursorG3	= 0x47,
50
	CursorB3	= 0x48,
51
 
52
	CursorArray	= 0x100,
53
 
54
	CursorMode32x32	= 0x23,
55
	CursorMode64x64	= 0x27,
56
	CursorMode	= CursorMode32x32,
57
};
58
 
59
static void
60
t2r4enable(VGAscr* scr)
61
{
62
	Pcidev *p;
63
	void *mmio;
64
 
65
	if(scr->mmio)
66
		return;
67
	if(p = pcimatch(nil, 0x105D, 0)){
68
		switch(p->did){
69
		case 0x5348:
70
			break;
71
		default:
72
			return;
73
		}
74
	}
75
	else
76
		return;
77
	scr->pci = p;
78
 
79
	mmio = vmap(p->mem[4].bar & ~0x0F, p->mem[4].size);
80
	if(mmio == nil)
81
		return;
82
	addvgaseg("t2r4mmio", p->mem[4].bar & ~0x0F, p->mem[4].size);
83
 
84
	scr->mmio = mmio;
85
	vgalinearpci(scr);
86
	if(scr->paddr)
87
		addvgaseg("t2r4screen", scr->paddr, scr->apsize);
88
}
89
 
90
static uchar
91
t2r4xi(VGAscr* scr, int index)
92
{
93
	ulong *mmio;
94
 
95
	mmio = scr->mmio;
96
	mmio[IndexLo] = index & 0xFF;
97
	mmio[IndexHi] = (index>>8) & 0xFF;
98
 
99
	return mmio[Data];
100
}
101
 
102
static void
103
t2r4xo(VGAscr* scr, int index, uchar data)
104
{
105
	ulong *mmio;
106
 
107
	mmio = scr->mmio;
108
	mmio[IndexLo] = index & 0xFF;
109
	mmio[IndexHi] = (index>>8) & 0xFF;
110
 
111
	mmio[Data] = data;
112
}
113
 
114
static void
115
t2r4curdisable(VGAscr* scr)
116
{
117
	if(scr->mmio == 0)
118
		return;
119
	t2r4xo(scr, CursorCtl, 0x00);
120
}
121
 
122
static void
123
t2r4curload(VGAscr* scr, Cursor* curs)
124
{
125
	uchar *data;
126
	int size, x, y, zoom;
127
	ulong clr, *mmio, pixels, set;
128
 
129
	mmio = scr->mmio;
130
	if(mmio == 0)
131
		return;
132
 
133
	/*
134
	 * Make sure cursor is off by initialising the cursor
135
	 * control to defaults.
136
	 */
137
	t2r4xo(scr, CursorCtl, 0x00);
138
 
139
	/*
140
	 * Set auto-increment mode for index-register addressing
141
	 * and initialise the cursor array index.
142
	 */
143
	mmio[IndexCtl] = 0x01;
144
	mmio[IndexLo] = CursorArray & 0xFF;
145
	mmio[IndexHi] = (CursorArray>>8) & 0xFF;
146
 
147
	/*
148
	 * Initialise the cursor RAM array. There are 2 planes,
149
	 * p0 and p1. Data is written 4 pixels per byte, with p1 the
150
	 * MS bit of each pixel.
151
	 * The cursor is set in X-Windows mode which gives the following
152
	 * truth table:
153
	 *	p1 p0	colour
154
	 *	 0  0	underlying pixel colour
155
	 *	 0  1	underlying pixel colour
156
	 *	 1  0	cursor colour 1
157
	 *	 1  1	cursor colour 2
158
	 * Put the cursor into the top-left of the array.
159
	 *
160
	 * Although this looks a lot like the IBM RGB524 cursor, the
161
	 * scanlines appear to be twice as long as they should be and
162
	 * some of the other features are missing.
163
	 */
164
	if(mmio[Zoom] & 0x0F)
165
		zoom = 32;
166
	else
167
		zoom = 16;
168
	data = (uchar*)&mmio[Data];
169
	for(y = 0; y < zoom; y++){
170
		clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
171
		set = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
172
		pixels = 0;
173
		for(x = 0; x < 16; x++){
174
			if(set & (1<<x))
175
				pixels |= 0x03<<(x*2);
176
			else if(clr & (1<<x))
177
				pixels |= 0x02<<(x*2);
178
		}
179
 
180
		*data = pixels>>24;
181
		*data = pixels>>16;
182
		*data = pixels>>8;
183
		*data = pixels;
184
 
185
		*data = 0x00;
186
		*data = 0x00;
187
		*data = 0x00;
188
		*data = 0x00;
189
 
190
		if(CursorMode == CursorMode32x32 && zoom == 16)
191
			continue;
192
		*data = pixels>>24;
193
		*data = pixels>>16;
194
		*data = pixels>>8;
195
		*data = pixels;
196
 
197
		*data = 0x00;
198
		*data = 0x00;
199
		*data = 0x00;
200
		*data = 0x00;
201
	}
202
	if(CursorMode == CursorMode32x32)
203
		size = 32;
204
	else
205
		size = 64;
206
	while(y < size){
207
		for(x = 0; x < size/8; x++){
208
			*data = 0x00;
209
			*data = 0x00;
210
		}
211
		y++;
212
	}
213
	mmio[IndexCtl] = 0x00;
214
 
215
	/*
216
	 * Initialise the hotpoint and enable the cursor.
217
	 */
218
	t2r4xo(scr, CursorHotX, -curs->offset.x);
219
	zoom = (scr->mmio[Zoom] & 0x0F)+1;
220
	t2r4xo(scr, CursorHotY, -curs->offset.y*zoom);
221
 
222
	t2r4xo(scr, CursorCtl, CursorMode);
223
}
224
 
225
static int
226
t2r4curmove(VGAscr* scr, Point p)
227
{
228
	int y, zoom;
229
 
230
	if(scr->mmio == 0)
231
		return 1;
232
 
233
	t2r4xo(scr, CursorXLo, p.x & 0xFF);
234
	t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
235
 
236
	zoom = (scr->mmio[Zoom] & 0x0F)+1;
237
	y = p.y*zoom;
238
	t2r4xo(scr, CursorYLo, y & 0xFF);
239
	t2r4xo(scr, CursorYHi, (y>>8) & 0x0F);
240
 
241
	return 0;
242
}
243
 
244
static void
245
t2r4curenable(VGAscr* scr)
246
{
247
	t2r4enable(scr);
248
	if(scr->mmio == 0)
249
		return;
250
 
251
	/*
252
	 * Make sure cursor is off by initialising the cursor
253
	 * control to defaults.
254
	 */
255
	t2r4xo(scr, CursorCtl, 0x00);
256
 
257
	/*
258
	 * Cursor colour 1 (white),
259
	 * cursor colour 2 (black).
260
	 */
261
	t2r4xo(scr, CursorR1, Pwhite);
262
	t2r4xo(scr, CursorG1, Pwhite);
263
	t2r4xo(scr, CursorB1, Pwhite);
264
 
265
	t2r4xo(scr, CursorR2, Pblack);
266
	t2r4xo(scr, CursorG2, Pblack);
267
	t2r4xo(scr, CursorB2, Pblack);
268
 
269
	/*
270
	 * Load, locate and enable the cursor, 64x64, mode 2.
271
	 */
272
	t2r4curload(scr, &arrow);
273
	t2r4curmove(scr, ZP);
274
	t2r4xo(scr, CursorCtl, CursorMode);
275
}
276
 
277
enum {
278
	Flow		= 0x08/4,
279
	Busy		= 0x0C/4,
280
	BufCtl		= 0x20/4,
281
	DeSorg		= 0x28/4,
282
	DeDorg		= 0x2C/4,
283
	DeSptch		= 0x40/4,
284
	DeDptch		= 0x44/4,
285
	CmdOpc		= 0x50/4,
286
	CmdRop		= 0x54/4,
287
	CmdStyle 	= 0x58/4,
288
	CmdPatrn 	= 0x5C/4,
289
	CmdClp		= 0x60/4,
290
	CmdPf		= 0x64/4,
291
	Fore		= 0x68/4,
292
	Back		= 0x6C/4,
293
	Mask		= 0x70/4,
294
	DeKey		= 0x74/4,
295
	Lpat		= 0x78/4,
296
	Pctrl 		= 0x7C/4,
297
	Clptl		= 0x80/4,
298
	Clpbr		= 0x84/4,
299
	XY0		= 0x88/4,
300
	XY1		= 0x8C/4,
301
	XY2		= 0x90/4,
302
	XY3		= 0x94/4,
303
	XY4		= 0x98/4,
304
	Alpha 		= 0x128/4,
305
	ACtl 		= 0x16C/4,
306
 
307
	RBaseD 		= 0x4000/4,
308
};
309
 
310
/* wait until pipeline ready for new command */
311
static void
312
waitforfifo(VGAscr *scr)
313
{
314
	int x;
315
	ulong *d;
316
	x = 0;
317
 
318
	d = scr->mmio + RBaseD;
319
	while((d[Busy]&1) && x++ < 1000000)
320
		;
321
	if(x >= 1000000)	/* shouldn't happen */
322
		iprint("busy %8lux\n", d[Busy]);
323
}
324
 
325
/* wait until command has finished executing */
326
static void
327
waitforcmd(VGAscr *scr)
328
{
329
	int x;
330
	ulong *d;
331
	x = 0;
332
 
333
	d = scr->mmio + RBaseD;
334
	while((d[Flow]&0x1B) && x++ < 1000000)
335
		;
336
	if(x >= 1000000)	/* shouldn't happen */
337
		iprint("flow %8lux\n", d[Flow]);
338
}
339
 
340
/* wait until memory controller not busy (i.e. wait for writes to flush) */
341
static void
342
waitformem(VGAscr *scr)
343
{
344
	int x;
345
	ulong *d;
346
	x = 0;
347
 
348
	d = scr->mmio + RBaseD;
349
	while((d[Flow]&2)&& x++ < 1000000)
350
		;
351
	if(x >= 1000000)	/* shouldn't happen */
352
		iprint("mem %8lux\n", d[Busy]);
353
}
354
 
355
static int
356
t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
357
{
358
	int ctl;
359
	Point dp, sp;
360
	ulong *d;
361
	int depth;
362
 
363
	if(r.min.y == sr.min.y){	/* a purely horizontal scroll */
364
		depth = scr->gscreen->depth;
365
		switch(depth){
366
		case 32:
367
			/*
368
			 * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
369
			 * 32-bit scrolls don't work perfectly on rectangles of width <= 24.
370
			 * we bail on a bigger bound for padding.
371
			 */
372
			if(Dx(r) < 32)
373
				return 0;
374
			break;
375
		case 16:
376
			/*
377
			 * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
378
			 * 16-bit scrolls don't work perfectly on rectangles of width <= 96.
379
			 * we bail on a bigger bound for padding.
380
			 */
381
			if(Dx(r) < 104)
382
				return 0;
383
			break;
384
		}
385
	}
386
	waitformem(scr);
387
	waitforfifo(scr);
388
	d = scr->mmio + RBaseD;
389
	ctl = 0;
390
	if(r.min.x <= sr.min.x){
391
		dp.x = r.min.x;
392
		sp.x = sr.min.x;
393
	}else{
394
		ctl |= 2;
395
		dp.x = r.max.x-1;
396
		sp.x = sr.max.x-1;
397
	}
398
 
399
	if(r.min.y < sr.min.y){
400
		dp.y = r.min.y;
401
		sp.y = sr.min.y;
402
	}else{
403
		ctl |= 1;
404
		dp.y = r.max.y-1;
405
		sp.y = sr.max.y-1;
406
	}
407
 
408
	d[CmdOpc] = 0x1;	/* bitblt */
409
	d[CmdRop] = 0xC;	/* copy source */
410
	d[CmdStyle] = 0;
411
	d[CmdPatrn] = 0;
412
	d[Fore] = 0;
413
	d[Back] = 0;
414
 
415
	/* writing XY1 executes cmd */
416
	d[XY3] = ctl;
417
	d[XY0] = (sp.x<<16)|sp.y;
418
	d[XY2] = (Dx(r)<<16)|Dy(r);
419
	d[XY4] = 0;
420
	d[XY1] = (dp.x<<16)|dp.y;
421
	waitforcmd(scr);
422
 
423
	return 1;
424
}
425
 
426
static int
427
t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval)
428
{
429
	ulong *d;
430
 
431
	d = scr->mmio + RBaseD;
432
 
433
	waitformem(scr);
434
	waitforfifo(scr);
435
	d[CmdOpc] = 0x1;	/* bitblt */
436
	d[CmdRop] = 0xC;	/* copy source */
437
	d[CmdStyle] = 1;	/* use source from Fore register */
438
	d[CmdPatrn] = 0;	/* no stipple */
439
	d[Fore] = sval;
440
	d[Back] = sval;
441
 
442
	/* writing XY1 executes cmd */
443
	d[XY3] = 0;
444
	d[XY0] = (r.min.x<<16)|r.min.y;
445
	d[XY2] = (Dx(r)<<16)|Dy(r);
446
	d[XY4] = 0;
447
	d[XY1] = (r.min.x<<16)|r.min.y;
448
	waitforcmd(scr);
449
 
450
	return 1;
451
}
452
 
453
static void
454
t2r4blank(VGAscr *scr, int blank)
455
{
456
	uchar x;
457
 
458
	x = t2r4xi(scr, CursorSyncCtl);
459
	x &= ~0x0F;
460
	if(blank)
461
		x |= HsyncLo | VsyncLo;
462
	t2r4xo(scr, CursorSyncCtl, x);
463
}
464
 
465
static void
466
t2r4drawinit(VGAscr *scr)
467
{
468
	ulong pitch;
469
	int depth;
470
	int fmt;
471
	ulong *d;
472
 
473
	pitch = Dx(scr->gscreen->r);
474
	depth = scr->gscreen->depth;
475
 
476
	switch(scr->gscreen->chan){
477
	case RGB16:
478
		fmt = 3;
479
		break;
480
	case XRGB32:
481
		fmt = 2;
482
		break;
483
	case RGB15:
484
		fmt = 1;
485
		break;
486
	default:
487
		scr->fill = nil;
488
		scr->scroll = nil;
489
		return;
490
	}
491
 
492
	d = scr->mmio + RBaseD;
493
 
494
	d[BufCtl] = fmt<<24;
495
	d[DeSorg] = 0;
496
	d[DeDorg] = 0;
497
	d[DeSptch] = (pitch*depth)/8;
498
	d[DeDptch] = (pitch*depth)/8;
499
	d[CmdClp] = 0;	/* 2 = inside rectangle */
500
	d[Mask] = ~0;
501
	d[DeKey] = 0;
502
	d[Clptl] = 0; 
503
	d[Clpbr] = 0xFFF0FFF0;
504
	d[Alpha] = 0;
505
	d[ACtl] = 0;
506
 
507
	scr->fill = t2r4hwfill;
508
	scr->scroll = t2r4hwscroll;
509
	scr->blank = t2r4blank;
510
	hwblank = 1;
511
}
512
 
513
VGAdev vgat2r4dev = {
514
	"t2r4",
515
 
516
	t2r4enable,
517
	nil,
518
	nil,
519
	nil,
520
	t2r4drawinit,
521
};
522
 
523
VGAcur vgat2r4cur = {
524
	"t2r4hwgc",
525
 
526
	t2r4curenable,
527
	t2r4curdisable,
528
	t2r4curload,
529
	t2r4curmove,
530
};
531