xref: /plan9-contrib/sys/src/9/loongson/screen.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
1*a81c3ea0SDavid du Colombier /*
2*a81c3ea0SDavid du Colombier  *	radeon frame buffer
3*a81c3ea0SDavid du Colombier  *	currently use all PMON defaults
4*a81c3ea0SDavid du Colombier  */
5*a81c3ea0SDavid du Colombier #include "u.h"
6*a81c3ea0SDavid du Colombier #include "../port/lib.h"
7*a81c3ea0SDavid du Colombier #include "mem.h"
8*a81c3ea0SDavid du Colombier #include "dat.h"
9*a81c3ea0SDavid du Colombier #include "fns.h"
10*a81c3ea0SDavid du Colombier #include "io.h"
11*a81c3ea0SDavid du Colombier 
12*a81c3ea0SDavid du Colombier #define	Image	IMAGE
13*a81c3ea0SDavid du Colombier #include <draw.h>
14*a81c3ea0SDavid du Colombier #include <memdraw.h>
15*a81c3ea0SDavid du Colombier #include <cursor.h>
16*a81c3ea0SDavid du Colombier #include "screen.h"
17*a81c3ea0SDavid du Colombier 
18*a81c3ea0SDavid du Colombier enum {
19*a81c3ea0SDavid du Colombier 	Tabstop		= 4,
20*a81c3ea0SDavid du Colombier 	Scroll		= 8,
21*a81c3ea0SDavid du Colombier 	Wid			= 640,
22*a81c3ea0SDavid du Colombier 	Ht			= 480,
23*a81c3ea0SDavid du Colombier 	Depth		= 16,
24*a81c3ea0SDavid du Colombier };
25*a81c3ea0SDavid du Colombier 
26*a81c3ea0SDavid du Colombier Cursor	arrow = {
27*a81c3ea0SDavid du Colombier 	{ -1, -1 },
28*a81c3ea0SDavid du Colombier 	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
29*a81c3ea0SDavid du Colombier 	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
30*a81c3ea0SDavid du Colombier 	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
31*a81c3ea0SDavid du Colombier 	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
32*a81c3ea0SDavid du Colombier 	},
33*a81c3ea0SDavid du Colombier 	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
34*a81c3ea0SDavid du Colombier 	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
35*a81c3ea0SDavid du Colombier 	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
36*a81c3ea0SDavid du Colombier 	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
37*a81c3ea0SDavid du Colombier 	},
38*a81c3ea0SDavid du Colombier };
39*a81c3ea0SDavid du Colombier 
40*a81c3ea0SDavid du Colombier Memimage *gscreen;
41*a81c3ea0SDavid du Colombier 
42*a81c3ea0SDavid du Colombier static Memdata xgdata;
43*a81c3ea0SDavid du Colombier 
44*a81c3ea0SDavid du Colombier static Memimage xgscreen =
45*a81c3ea0SDavid du Colombier {
46*a81c3ea0SDavid du Colombier 	{ 0, 0, Wid, Ht },	/* r */
47*a81c3ea0SDavid du Colombier 	{ 0, 0, Wid, Ht },	/* clipr */
48*a81c3ea0SDavid du Colombier 	Depth,			/* depth */
49*a81c3ea0SDavid du Colombier 	3,			/* nchan */
50*a81c3ea0SDavid du Colombier 	RGB16,			/* chan */
51*a81c3ea0SDavid du Colombier 	nil,			/* cmap */
52*a81c3ea0SDavid du Colombier 	&xgdata,		/* data */
53*a81c3ea0SDavid du Colombier 	0,			/* zero */
54*a81c3ea0SDavid du Colombier 	0, 			/* width in words of a single scan line */
55*a81c3ea0SDavid du Colombier 	0,			/* layer */
56*a81c3ea0SDavid du Colombier 	0,			/* flags */
57*a81c3ea0SDavid du Colombier };
58*a81c3ea0SDavid du Colombier 
59*a81c3ea0SDavid du Colombier static Memimage		*conscol;
60*a81c3ea0SDavid du Colombier static Memimage		*back;
61*a81c3ea0SDavid du Colombier static Memsubfont	*memdefont;
62*a81c3ea0SDavid du Colombier 
63*a81c3ea0SDavid du Colombier static Lock screenlock;
64*a81c3ea0SDavid du Colombier 
65*a81c3ea0SDavid du Colombier static Point		curpos;
66*a81c3ea0SDavid du Colombier static int			h, w;
67*a81c3ea0SDavid du Colombier static Rectangle	window;
68*a81c3ea0SDavid du Colombier 
69*a81c3ea0SDavid du Colombier int screenwid;
70*a81c3ea0SDavid du Colombier int screenht;
71*a81c3ea0SDavid du Colombier int screendepth;
72*a81c3ea0SDavid du Colombier 
73*a81c3ea0SDavid du Colombier /*
74*a81c3ea0SDavid du Colombier  * Software cursor.
75*a81c3ea0SDavid du Colombier  */
76*a81c3ea0SDavid du Colombier static int	swvisible;	/* is the cursor visible? */
77*a81c3ea0SDavid du Colombier static int	swenabled;	/* is the cursor supposed to be on the screen? */
78*a81c3ea0SDavid du Colombier static Memimage *swback;	/* screen under cursor */
79*a81c3ea0SDavid du Colombier static Memimage *swimg;		/* cursor image */
80*a81c3ea0SDavid du Colombier static Memimage *swmask;	/* cursor mask */
81*a81c3ea0SDavid du Colombier static Memimage *swimg1;
82*a81c3ea0SDavid du Colombier static Memimage *swmask1;
83*a81c3ea0SDavid du Colombier 
84*a81c3ea0SDavid du Colombier static Point	swoffset;
85*a81c3ea0SDavid du Colombier static Rectangle swrect;	/* screen rectangle in swback */
86*a81c3ea0SDavid du Colombier static Point	swpt;		/* desired cursor location */
87*a81c3ea0SDavid du Colombier static Point	swvispt;	/* actual cursor location */
88*a81c3ea0SDavid du Colombier static int	swvers;		/* incremented each time cursor image changes */
89*a81c3ea0SDavid du Colombier static int	swvisvers;	/* the version on the screen */
90*a81c3ea0SDavid du Colombier 
91*a81c3ea0SDavid du Colombier /*
92*a81c3ea0SDavid du Colombier  * called with drawlock locked for us, most of the time.
93*a81c3ea0SDavid du Colombier  * kernel prints at inopportune times might mean we don't
94*a81c3ea0SDavid du Colombier  * hold the lock, but memimagedraw is now reentrant so
95*a81c3ea0SDavid du Colombier  * that should be okay: worst case we get cursor droppings.
96*a81c3ea0SDavid du Colombier  */
97*a81c3ea0SDavid du Colombier static void
swcursorhide(void)98*a81c3ea0SDavid du Colombier swcursorhide(void)
99*a81c3ea0SDavid du Colombier {
100*a81c3ea0SDavid du Colombier 	if(swvisible == 0)
101*a81c3ea0SDavid du Colombier 		return;
102*a81c3ea0SDavid du Colombier 	if(swback == nil)
103*a81c3ea0SDavid du Colombier 		return;
104*a81c3ea0SDavid du Colombier 	swvisible = 0;
105*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
106*a81c3ea0SDavid du Colombier 	flushmemscreen(swrect);
107*a81c3ea0SDavid du Colombier }
108*a81c3ea0SDavid du Colombier 
109*a81c3ea0SDavid du Colombier static void
swcursoravoid(Rectangle r)110*a81c3ea0SDavid du Colombier swcursoravoid(Rectangle r)
111*a81c3ea0SDavid du Colombier {
112*a81c3ea0SDavid du Colombier 	if(swvisible && rectXrect(r, swrect))
113*a81c3ea0SDavid du Colombier 		swcursorhide();
114*a81c3ea0SDavid du Colombier }
115*a81c3ea0SDavid du Colombier 
116*a81c3ea0SDavid du Colombier static void
swcursordraw(void)117*a81c3ea0SDavid du Colombier swcursordraw(void)
118*a81c3ea0SDavid du Colombier {
119*a81c3ea0SDavid du Colombier 	int dounlock;
120*a81c3ea0SDavid du Colombier 
121*a81c3ea0SDavid du Colombier 	if(swvisible)
122*a81c3ea0SDavid du Colombier 		return;
123*a81c3ea0SDavid du Colombier 	if(swenabled == 0)
124*a81c3ea0SDavid du Colombier 		return;
125*a81c3ea0SDavid du Colombier 	if(swback == nil || swimg1 == nil || swmask1 == nil)
126*a81c3ea0SDavid du Colombier 		return;
127*a81c3ea0SDavid du Colombier 	dounlock = canqlock(&drawlock);
128*a81c3ea0SDavid du Colombier 	swvispt = swpt;
129*a81c3ea0SDavid du Colombier 	swvisvers = swvers;
130*a81c3ea0SDavid du Colombier 	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
131*a81c3ea0SDavid du Colombier 	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
132*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
133*a81c3ea0SDavid du Colombier 	flushmemscreen(swrect);
134*a81c3ea0SDavid du Colombier 	swvisible = 1;
135*a81c3ea0SDavid du Colombier 	if(dounlock)
136*a81c3ea0SDavid du Colombier 		qunlock(&drawlock);
137*a81c3ea0SDavid du Colombier }
138*a81c3ea0SDavid du Colombier 
139*a81c3ea0SDavid du Colombier int
cursoron(int dolock)140*a81c3ea0SDavid du Colombier cursoron(int dolock)
141*a81c3ea0SDavid du Colombier {
142*a81c3ea0SDavid du Colombier 	int retry;
143*a81c3ea0SDavid du Colombier 
144*a81c3ea0SDavid du Colombier 	if (dolock)
145*a81c3ea0SDavid du Colombier 		lock(&cursor);
146*a81c3ea0SDavid du Colombier 	if (canqlock(&drawlock)) {
147*a81c3ea0SDavid du Colombier 		retry = 0;
148*a81c3ea0SDavid du Colombier 		swcursorhide();
149*a81c3ea0SDavid du Colombier 		swcursordraw();
150*a81c3ea0SDavid du Colombier 		qunlock(&drawlock);
151*a81c3ea0SDavid du Colombier 	} else
152*a81c3ea0SDavid du Colombier 		retry = 1;
153*a81c3ea0SDavid du Colombier 	if (dolock)
154*a81c3ea0SDavid du Colombier 		unlock(&cursor);
155*a81c3ea0SDavid du Colombier 	return retry;
156*a81c3ea0SDavid du Colombier }
157*a81c3ea0SDavid du Colombier 
158*a81c3ea0SDavid du Colombier void
cursoroff(int dolock)159*a81c3ea0SDavid du Colombier cursoroff(int dolock)
160*a81c3ea0SDavid du Colombier {
161*a81c3ea0SDavid du Colombier 	if (dolock)
162*a81c3ea0SDavid du Colombier 		lock(&cursor);
163*a81c3ea0SDavid du Colombier 	swcursorhide();
164*a81c3ea0SDavid du Colombier 	if (dolock)
165*a81c3ea0SDavid du Colombier 		unlock(&cursor);
166*a81c3ea0SDavid du Colombier }
167*a81c3ea0SDavid du Colombier 
168*a81c3ea0SDavid du Colombier static void
swload(Cursor * curs)169*a81c3ea0SDavid du Colombier swload(Cursor *curs)
170*a81c3ea0SDavid du Colombier {
171*a81c3ea0SDavid du Colombier 	uchar *ip, *mp;
172*a81c3ea0SDavid du Colombier 	int i, j, set, clr;
173*a81c3ea0SDavid du Colombier 
174*a81c3ea0SDavid du Colombier 	if(!swimg || !swmask || !swimg1 || !swmask1)
175*a81c3ea0SDavid du Colombier 		return;
176*a81c3ea0SDavid du Colombier 	/*
177*a81c3ea0SDavid du Colombier 	 * Build cursor image and mask.
178*a81c3ea0SDavid du Colombier 	 * Image is just the usual cursor image
179*a81c3ea0SDavid du Colombier 	 * but mask is a transparent alpha mask.
180*a81c3ea0SDavid du Colombier 	 *
181*a81c3ea0SDavid du Colombier 	 * The 16x16x8 memimages do not have
182*a81c3ea0SDavid du Colombier 	 * padding at the end of their scan lines.
183*a81c3ea0SDavid du Colombier 	 */
184*a81c3ea0SDavid du Colombier 	ip = byteaddr(swimg, ZP);
185*a81c3ea0SDavid du Colombier 	mp = byteaddr(swmask, ZP);
186*a81c3ea0SDavid du Colombier 	for(i=0; i<32; i++){
187*a81c3ea0SDavid du Colombier 		set = curs->set[i];
188*a81c3ea0SDavid du Colombier 		clr = curs->clr[i];
189*a81c3ea0SDavid du Colombier 		for(j=0x80; j; j>>=1){
190*a81c3ea0SDavid du Colombier 			*ip++ = set&j ? 0x00 : 0xFF;
191*a81c3ea0SDavid du Colombier 			*mp++ = (clr|set)&j ? 0xFF : 0x00;
192*a81c3ea0SDavid du Colombier 		}
193*a81c3ea0SDavid du Colombier 	}
194*a81c3ea0SDavid du Colombier 	swoffset = curs->offset;
195*a81c3ea0SDavid du Colombier 	swvers++;
196*a81c3ea0SDavid du Colombier 	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);
197*a81c3ea0SDavid du Colombier 	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
198*a81c3ea0SDavid du Colombier }
199*a81c3ea0SDavid du Colombier 
200*a81c3ea0SDavid du Colombier /* called from devmouse */
201*a81c3ea0SDavid du Colombier void
setcursor(Cursor * curs)202*a81c3ea0SDavid du Colombier setcursor(Cursor* curs)
203*a81c3ea0SDavid du Colombier {
204*a81c3ea0SDavid du Colombier 	cursoroff(0);
205*a81c3ea0SDavid du Colombier 	swload(curs);
206*a81c3ea0SDavid du Colombier 	cursoron(0);
207*a81c3ea0SDavid du Colombier }
208*a81c3ea0SDavid du Colombier 
209*a81c3ea0SDavid du Colombier static int
swmove(Point p)210*a81c3ea0SDavid du Colombier swmove(Point p)
211*a81c3ea0SDavid du Colombier {
212*a81c3ea0SDavid du Colombier 	swpt = addpt(p, swoffset);
213*a81c3ea0SDavid du Colombier 	return 0;
214*a81c3ea0SDavid du Colombier }
215*a81c3ea0SDavid du Colombier 
216*a81c3ea0SDavid du Colombier static void
swcursorclock(void)217*a81c3ea0SDavid du Colombier swcursorclock(void)
218*a81c3ea0SDavid du Colombier {
219*a81c3ea0SDavid du Colombier 	int x;
220*a81c3ea0SDavid du Colombier 
221*a81c3ea0SDavid du Colombier 	if(!swenabled)
222*a81c3ea0SDavid du Colombier 		return;
223*a81c3ea0SDavid du Colombier 	swmove(mousexy());
224*a81c3ea0SDavid du Colombier 	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
225*a81c3ea0SDavid du Colombier 		return;
226*a81c3ea0SDavid du Colombier 
227*a81c3ea0SDavid du Colombier 	x = splhi();
228*a81c3ea0SDavid du Colombier 	if(swenabled)
229*a81c3ea0SDavid du Colombier 	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
230*a81c3ea0SDavid du Colombier 	if(canqlock(&drawlock)){
231*a81c3ea0SDavid du Colombier 		swcursorhide();
232*a81c3ea0SDavid du Colombier 		swcursordraw();
233*a81c3ea0SDavid du Colombier 		qunlock(&drawlock);
234*a81c3ea0SDavid du Colombier 	}
235*a81c3ea0SDavid du Colombier 	splx(x);
236*a81c3ea0SDavid du Colombier }
237*a81c3ea0SDavid du Colombier 
238*a81c3ea0SDavid du Colombier void
swcursorinit(void)239*a81c3ea0SDavid du Colombier swcursorinit(void)
240*a81c3ea0SDavid du Colombier {
241*a81c3ea0SDavid du Colombier 	static int init;
242*a81c3ea0SDavid du Colombier 
243*a81c3ea0SDavid du Colombier 	if(!init){
244*a81c3ea0SDavid du Colombier 		init = 1;
245*a81c3ea0SDavid du Colombier 		addclock0link(swcursorclock, 10);
246*a81c3ea0SDavid du Colombier 		swenabled = 1;
247*a81c3ea0SDavid du Colombier 	}
248*a81c3ea0SDavid du Colombier 	if(swback){
249*a81c3ea0SDavid du Colombier 		freememimage(swback);
250*a81c3ea0SDavid du Colombier 		freememimage(swmask);
251*a81c3ea0SDavid du Colombier 		freememimage(swmask1);
252*a81c3ea0SDavid du Colombier 		freememimage(swimg);
253*a81c3ea0SDavid du Colombier 		freememimage(swimg1);
254*a81c3ea0SDavid du Colombier 	}
255*a81c3ea0SDavid du Colombier 
256*a81c3ea0SDavid du Colombier 	swback  = allocmemimage(Rect(0,0,32,32), gscreen->chan);
257*a81c3ea0SDavid du Colombier 	swmask  = allocmemimage(Rect(0,0,16,16), GREY8);
258*a81c3ea0SDavid du Colombier 	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
259*a81c3ea0SDavid du Colombier 	swimg   = allocmemimage(Rect(0,0,16,16), GREY8);
260*a81c3ea0SDavid du Colombier 	swimg1  = allocmemimage(Rect(0,0,16,16), GREY1);
261*a81c3ea0SDavid du Colombier 	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
262*a81c3ea0SDavid du Colombier 		print("software cursor: allocmemimage fails\n");
263*a81c3ea0SDavid du Colombier 		return;
264*a81c3ea0SDavid du Colombier 	}
265*a81c3ea0SDavid du Colombier 
266*a81c3ea0SDavid du Colombier 	memfillcolor(swmask, DOpaque);
267*a81c3ea0SDavid du Colombier 	memfillcolor(swmask1, DOpaque);
268*a81c3ea0SDavid du Colombier 	memfillcolor(swimg, DBlack);
269*a81c3ea0SDavid du Colombier 	memfillcolor(swimg1, DBlack);
270*a81c3ea0SDavid du Colombier }
271*a81c3ea0SDavid du Colombier 
272*a81c3ea0SDavid du Colombier static int
screensize(void)273*a81c3ea0SDavid du Colombier screensize(void)
274*a81c3ea0SDavid du Colombier {
275*a81c3ea0SDavid du Colombier 	char *p;
276*a81c3ea0SDavid du Colombier 	char *f[3];
277*a81c3ea0SDavid du Colombier 	int width, height, depth;
278*a81c3ea0SDavid du Colombier 
279*a81c3ea0SDavid du Colombier 	p = getconf("vgasize");
280*a81c3ea0SDavid du Colombier 	if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) ||
281*a81c3ea0SDavid du Colombier 			(width = atoi(f[0])) < 16 || (height = atoi(f[1])) <= 0 ||
282*a81c3ea0SDavid du Colombier 		(depth = atoi(f[2])) <= 0) {
283*a81c3ea0SDavid du Colombier 		width = screenwid? screenwid: Wid;
284*a81c3ea0SDavid du Colombier 		height = screenht? screenht: Ht;
285*a81c3ea0SDavid du Colombier 		depth = screendepth? screendepth: Depth;
286*a81c3ea0SDavid du Colombier 	}
287*a81c3ea0SDavid du Colombier 
288*a81c3ea0SDavid du Colombier 	xgscreen.r.max = Pt(width, height);
289*a81c3ea0SDavid du Colombier 	xgscreen.depth = depth;
290*a81c3ea0SDavid du Colombier 	return 0;
291*a81c3ea0SDavid du Colombier }
292*a81c3ea0SDavid du Colombier 
293*a81c3ea0SDavid du Colombier void
flushmemscreen(Rectangle)294*a81c3ea0SDavid du Colombier flushmemscreen(Rectangle)
295*a81c3ea0SDavid du Colombier {
296*a81c3ea0SDavid du Colombier }
297*a81c3ea0SDavid du Colombier 
298*a81c3ea0SDavid du Colombier static void
screenwin(void)299*a81c3ea0SDavid du Colombier screenwin(void)
300*a81c3ea0SDavid du Colombier {
301*a81c3ea0SDavid du Colombier 	char *greet;
302*a81c3ea0SDavid du Colombier 	Memimage *orange;
303*a81c3ea0SDavid du Colombier 	Point p, q;
304*a81c3ea0SDavid du Colombier 	Rectangle r;
305*a81c3ea0SDavid du Colombier 
306*a81c3ea0SDavid du Colombier 	back = memwhite;
307*a81c3ea0SDavid du Colombier 	conscol = memblack;
308*a81c3ea0SDavid du Colombier 
309*a81c3ea0SDavid du Colombier 	orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
310*a81c3ea0SDavid du Colombier 	orange->flags |= Frepl;
311*a81c3ea0SDavid du Colombier 	orange->clipr = gscreen->r;
312*a81c3ea0SDavid du Colombier 	orange->data->bdata[0] = 0x40;		/* magic: colour? */
313*a81c3ea0SDavid du Colombier 	orange->data->bdata[1] = 0xfd;		/* magic: colour? */
314*a81c3ea0SDavid du Colombier 
315*a81c3ea0SDavid du Colombier 	w = memdefont->info[' '].width;
316*a81c3ea0SDavid du Colombier 	h = memdefont->height;
317*a81c3ea0SDavid du Colombier 
318*a81c3ea0SDavid du Colombier 	r = insetrect(gscreen->r, 0);
319*a81c3ea0SDavid du Colombier 
320*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
321*a81c3ea0SDavid du Colombier 	window = insetrect(r, 0);
322*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
323*a81c3ea0SDavid du Colombier 
324*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
325*a81c3ea0SDavid du Colombier 		window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
326*a81c3ea0SDavid du Colombier 	freememimage(orange);
327*a81c3ea0SDavid du Colombier 	window = insetrect(window, 5);
328*a81c3ea0SDavid du Colombier 
329*a81c3ea0SDavid du Colombier 	greet = " Plan 9 Console ";
330*a81c3ea0SDavid du Colombier 	p = addpt(window.min, Pt(10, 0));
331*a81c3ea0SDavid du Colombier 	q = memsubfontwidth(memdefont, greet);
332*a81c3ea0SDavid du Colombier 	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
333*a81c3ea0SDavid du Colombier 	flushmemscreen(r);
334*a81c3ea0SDavid du Colombier 	window.min.y += h + 6;
335*a81c3ea0SDavid du Colombier 	curpos = window.min;
336*a81c3ea0SDavid du Colombier 	window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
337*a81c3ea0SDavid du Colombier }
338*a81c3ea0SDavid du Colombier 
339*a81c3ea0SDavid du Colombier static void
scroll(void)340*a81c3ea0SDavid du Colombier scroll(void)
341*a81c3ea0SDavid du Colombier {
342*a81c3ea0SDavid du Colombier 	int o;
343*a81c3ea0SDavid du Colombier 	Point p;
344*a81c3ea0SDavid du Colombier 	Rectangle r;
345*a81c3ea0SDavid du Colombier 
346*a81c3ea0SDavid du Colombier 	o = Scroll*h;
347*a81c3ea0SDavid du Colombier 	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
348*a81c3ea0SDavid du Colombier 	p = Pt(window.min.x, window.min.y+o);
349*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
350*a81c3ea0SDavid du Colombier 	flushmemscreen(r);
351*a81c3ea0SDavid du Colombier 	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
352*a81c3ea0SDavid du Colombier 	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
353*a81c3ea0SDavid du Colombier 	flushmemscreen(r);
354*a81c3ea0SDavid du Colombier 
355*a81c3ea0SDavid du Colombier 	curpos.y -= o;
356*a81c3ea0SDavid du Colombier }
357*a81c3ea0SDavid du Colombier 
358*a81c3ea0SDavid du Colombier static void
screenputc(char * buf)359*a81c3ea0SDavid du Colombier screenputc(char *buf)
360*a81c3ea0SDavid du Colombier {
361*a81c3ea0SDavid du Colombier 	int w;
362*a81c3ea0SDavid du Colombier 	uint pos;
363*a81c3ea0SDavid du Colombier 	Point p;
364*a81c3ea0SDavid du Colombier 	Rectangle r;
365*a81c3ea0SDavid du Colombier 	static int *xp;
366*a81c3ea0SDavid du Colombier 	static int xbuf[256];
367*a81c3ea0SDavid du Colombier 
368*a81c3ea0SDavid du Colombier 	if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
369*a81c3ea0SDavid du Colombier 		xp = xbuf;
370*a81c3ea0SDavid du Colombier 
371*a81c3ea0SDavid du Colombier 	switch (buf[0]) {
372*a81c3ea0SDavid du Colombier 	case '\n':
373*a81c3ea0SDavid du Colombier 		if (curpos.y + h >= window.max.y)
374*a81c3ea0SDavid du Colombier 			scroll();
375*a81c3ea0SDavid du Colombier 		curpos.y += h;
376*a81c3ea0SDavid du Colombier 		screenputc("\r");
377*a81c3ea0SDavid du Colombier 		break;
378*a81c3ea0SDavid du Colombier 	case '\r':
379*a81c3ea0SDavid du Colombier 		xp = xbuf;
380*a81c3ea0SDavid du Colombier 		curpos.x = window.min.x;
381*a81c3ea0SDavid du Colombier 		break;
382*a81c3ea0SDavid du Colombier 	case '\t':
383*a81c3ea0SDavid du Colombier 		p = memsubfontwidth(memdefont, " ");
384*a81c3ea0SDavid du Colombier 		w = p.x;
385*a81c3ea0SDavid du Colombier 		if (curpos.x >= window.max.x - Tabstop * w)
386*a81c3ea0SDavid du Colombier 			screenputc("\n");
387*a81c3ea0SDavid du Colombier 
388*a81c3ea0SDavid du Colombier 		pos = (curpos.x - window.min.x) / w;
389*a81c3ea0SDavid du Colombier 		pos = Tabstop - pos % Tabstop;
390*a81c3ea0SDavid du Colombier 		*xp++ = curpos.x;
391*a81c3ea0SDavid du Colombier 		r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
392*a81c3ea0SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
393*a81c3ea0SDavid du Colombier 		flushmemscreen(r);
394*a81c3ea0SDavid du Colombier 		curpos.x += pos * w;
395*a81c3ea0SDavid du Colombier 		break;
396*a81c3ea0SDavid du Colombier 	case '\b':
397*a81c3ea0SDavid du Colombier 		if (xp <= xbuf)
398*a81c3ea0SDavid du Colombier 			break;
399*a81c3ea0SDavid du Colombier 		xp--;
400*a81c3ea0SDavid du Colombier 		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
401*a81c3ea0SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
402*a81c3ea0SDavid du Colombier 		flushmemscreen(r);
403*a81c3ea0SDavid du Colombier 		curpos.x = *xp;
404*a81c3ea0SDavid du Colombier 		break;
405*a81c3ea0SDavid du Colombier 	case '\0':
406*a81c3ea0SDavid du Colombier 		break;
407*a81c3ea0SDavid du Colombier 	default:
408*a81c3ea0SDavid du Colombier 		p = memsubfontwidth(memdefont, buf);
409*a81c3ea0SDavid du Colombier 		w = p.x;
410*a81c3ea0SDavid du Colombier 
411*a81c3ea0SDavid du Colombier 		if (curpos.x >= window.max.x - w)
412*a81c3ea0SDavid du Colombier 			screenputc("\n");
413*a81c3ea0SDavid du Colombier 
414*a81c3ea0SDavid du Colombier 		*xp++ = curpos.x;
415*a81c3ea0SDavid du Colombier 		r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
416*a81c3ea0SDavid du Colombier 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
417*a81c3ea0SDavid du Colombier 		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
418*a81c3ea0SDavid du Colombier 		flushmemscreen(r);
419*a81c3ea0SDavid du Colombier 		curpos.x += w;
420*a81c3ea0SDavid du Colombier 		break;
421*a81c3ea0SDavid du Colombier 	}
422*a81c3ea0SDavid du Colombier }
423*a81c3ea0SDavid du Colombier 
424*a81c3ea0SDavid du Colombier static void
myscreenputs(char * s,int n)425*a81c3ea0SDavid du Colombier myscreenputs(char *s, int n)
426*a81c3ea0SDavid du Colombier {
427*a81c3ea0SDavid du Colombier 	int i;
428*a81c3ea0SDavid du Colombier 	Rune r;
429*a81c3ea0SDavid du Colombier 	char buf[4];
430*a81c3ea0SDavid du Colombier 
431*a81c3ea0SDavid du Colombier 	if(!islo()) {
432*a81c3ea0SDavid du Colombier 		/* don't deadlock trying to print in interrupt */
433*a81c3ea0SDavid du Colombier 		if(!canlock(&screenlock))
434*a81c3ea0SDavid du Colombier 			return;
435*a81c3ea0SDavid du Colombier 	}
436*a81c3ea0SDavid du Colombier 	else
437*a81c3ea0SDavid du Colombier 		lock(&screenlock);
438*a81c3ea0SDavid du Colombier 
439*a81c3ea0SDavid du Colombier 	while(n > 0){
440*a81c3ea0SDavid du Colombier 		i = chartorune(&r, s);
441*a81c3ea0SDavid du Colombier 		if(i == 0){
442*a81c3ea0SDavid du Colombier 			s++;
443*a81c3ea0SDavid du Colombier 			--n;
444*a81c3ea0SDavid du Colombier 			continue;
445*a81c3ea0SDavid du Colombier 		}
446*a81c3ea0SDavid du Colombier 		memmove(buf, s, i);
447*a81c3ea0SDavid du Colombier 		buf[i] = 0;
448*a81c3ea0SDavid du Colombier 		n -= i;
449*a81c3ea0SDavid du Colombier 		s += i;
450*a81c3ea0SDavid du Colombier 		screenputc(buf);
451*a81c3ea0SDavid du Colombier 	}
452*a81c3ea0SDavid du Colombier 	unlock(&screenlock);
453*a81c3ea0SDavid du Colombier }
454*a81c3ea0SDavid du Colombier 
455*a81c3ea0SDavid du Colombier void
screeninit(void)456*a81c3ea0SDavid du Colombier screeninit(void)
457*a81c3ea0SDavid du Colombier {
458*a81c3ea0SDavid du Colombier 	ulong chan;
459*a81c3ea0SDavid du Colombier 	uchar *fb;
460*a81c3ea0SDavid du Colombier 
461*a81c3ea0SDavid du Colombier 	screensize();
462*a81c3ea0SDavid du Colombier 	fb = (uchar*)fbinit();
463*a81c3ea0SDavid du Colombier 	if(fb == nil){
464*a81c3ea0SDavid du Colombier 		print("can't initialise %dx%dx%d framebuffer \n",
465*a81c3ea0SDavid du Colombier 			xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
466*a81c3ea0SDavid du Colombier 		return;
467*a81c3ea0SDavid du Colombier 	}
468*a81c3ea0SDavid du Colombier 
469*a81c3ea0SDavid du Colombier 	xgscreen.clipr = xgscreen.r;
470*a81c3ea0SDavid du Colombier 	switch(xgscreen.depth){
471*a81c3ea0SDavid du Colombier 	default:
472*a81c3ea0SDavid du Colombier 		print("unsupported screen depth %d\n", xgscreen.depth);
473*a81c3ea0SDavid du Colombier 		xgscreen.depth = 16;
474*a81c3ea0SDavid du Colombier 		/* fall through */
475*a81c3ea0SDavid du Colombier 	case 16:
476*a81c3ea0SDavid du Colombier 		chan = RGB16;
477*a81c3ea0SDavid du Colombier 		break;
478*a81c3ea0SDavid du Colombier 	case 24:
479*a81c3ea0SDavid du Colombier 		chan = BGR24;
480*a81c3ea0SDavid du Colombier 		break;
481*a81c3ea0SDavid du Colombier 	case 32:
482*a81c3ea0SDavid du Colombier 		chan = ARGB32;
483*a81c3ea0SDavid du Colombier 		break;
484*a81c3ea0SDavid du Colombier 	}
485*a81c3ea0SDavid du Colombier 	memsetchan(&xgscreen, chan);
486*a81c3ea0SDavid du Colombier 	conf.monitor = 1;
487*a81c3ea0SDavid du Colombier 	xgdata.bdata = fb;
488*a81c3ea0SDavid du Colombier 	xgdata.ref = 1;
489*a81c3ea0SDavid du Colombier 	gscreen = &xgscreen;
490*a81c3ea0SDavid du Colombier 	gscreen->width = wordsperline(gscreen->r, gscreen->depth);
491*a81c3ea0SDavid du Colombier 
492*a81c3ea0SDavid du Colombier 	memimageinit();
493*a81c3ea0SDavid du Colombier 	memdefont = getmemdefont();
494*a81c3ea0SDavid du Colombier 	screenwin();
495*a81c3ea0SDavid du Colombier 	screenputs = myscreenputs;
496*a81c3ea0SDavid du Colombier }
497*a81c3ea0SDavid du Colombier 
498*a81c3ea0SDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)499*a81c3ea0SDavid du Colombier attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
500*a81c3ea0SDavid du Colombier {
501*a81c3ea0SDavid du Colombier 	*r = gscreen->r;
502*a81c3ea0SDavid du Colombier 	*d = gscreen->depth;
503*a81c3ea0SDavid du Colombier 	*chan = gscreen->chan;
504*a81c3ea0SDavid du Colombier 	*width = gscreen->width;
505*a81c3ea0SDavid du Colombier 	*softscreen = 0;
506*a81c3ea0SDavid du Colombier 
507*a81c3ea0SDavid du Colombier 	return gscreen->data->bdata;
508*a81c3ea0SDavid du Colombier }
509*a81c3ea0SDavid du Colombier 
510*a81c3ea0SDavid du Colombier void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)511*a81c3ea0SDavid du Colombier getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
512*a81c3ea0SDavid du Colombier {
513*a81c3ea0SDavid du Colombier 	USED(p, pr, pg, pb);
514*a81c3ea0SDavid du Colombier }
515*a81c3ea0SDavid du Colombier 
516*a81c3ea0SDavid du Colombier int
setcolor(ulong p,ulong r,ulong g,ulong b)517*a81c3ea0SDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b)
518*a81c3ea0SDavid du Colombier {
519*a81c3ea0SDavid du Colombier 	USED(p, r, g, b);
520*a81c3ea0SDavid du Colombier 	return 0;
521*a81c3ea0SDavid du Colombier }
522*a81c3ea0SDavid du Colombier 
523*a81c3ea0SDavid du Colombier void
blankscreen(int blank)524*a81c3ea0SDavid du Colombier blankscreen(int blank)
525*a81c3ea0SDavid du Colombier {
526*a81c3ea0SDavid du Colombier 	USED(blank);
527*a81c3ea0SDavid du Colombier }
528*a81c3ea0SDavid du Colombier 
529*a81c3ea0SDavid du Colombier int
hwdraw(Memdrawparam * par)530*a81c3ea0SDavid du Colombier hwdraw(Memdrawparam *par)
531*a81c3ea0SDavid du Colombier {
532*a81c3ea0SDavid du Colombier 	Memimage *dst, *src, *mask;
533*a81c3ea0SDavid du Colombier 
534*a81c3ea0SDavid du Colombier 	if((dst=par->dst) == nil || dst->data == nil)
535*a81c3ea0SDavid du Colombier 		return 0;
536*a81c3ea0SDavid du Colombier 	if((src=par->src) == nil || src->data == nil)
537*a81c3ea0SDavid du Colombier 		return 0;
538*a81c3ea0SDavid du Colombier 	if((mask=par->mask) == nil || mask->data == nil)
539*a81c3ea0SDavid du Colombier 		return 0;
540*a81c3ea0SDavid du Colombier 
541*a81c3ea0SDavid du Colombier 	if(dst->data->bdata == xgdata.bdata)
542*a81c3ea0SDavid du Colombier 		swcursoravoid(par->r);
543*a81c3ea0SDavid du Colombier 	if(src->data->bdata == xgdata.bdata)
544*a81c3ea0SDavid du Colombier 		swcursoravoid(par->sr);
545*a81c3ea0SDavid du Colombier 	if(mask->data->bdata == xgdata.bdata)
546*a81c3ea0SDavid du Colombier 		swcursoravoid(par->mr);
547*a81c3ea0SDavid du Colombier 
548*a81c3ea0SDavid du Colombier 	return 0;
549*a81c3ea0SDavid du Colombier }
550*a81c3ea0SDavid du Colombier 
551*a81c3ea0SDavid du Colombier /* radeon frame buffer control */
552*a81c3ea0SDavid du Colombier typedef struct Ctlr {
553*a81c3ea0SDavid du Colombier 	Pcidev*	pcidev;
554*a81c3ea0SDavid du Colombier 	int		port;
555*a81c3ea0SDavid du Colombier 	void*	mmio;
556*a81c3ea0SDavid du Colombier 	ulong	paddr;
557*a81c3ea0SDavid du Colombier 	void*	vaddr;
558*a81c3ea0SDavid du Colombier } Ctlr;
559*a81c3ea0SDavid du Colombier 
560*a81c3ea0SDavid du Colombier static Ctlr *ctlr;
561*a81c3ea0SDavid du Colombier 
562*a81c3ea0SDavid du Colombier static Pcidev*
videopci(void)563*a81c3ea0SDavid du Colombier videopci(void)
564*a81c3ea0SDavid du Colombier {
565*a81c3ea0SDavid du Colombier 	static Pcidev *p = nil;
566*a81c3ea0SDavid du Colombier 
567*a81c3ea0SDavid du Colombier 	while((p = pcimatch(p, 0, 0)) != nil){
568*a81c3ea0SDavid du Colombier 		if(p->ccrb != Pcibcdisp || p->ccru != 0)
569*a81c3ea0SDavid du Colombier 			continue;
570*a81c3ea0SDavid du Colombier 		return p;
571*a81c3ea0SDavid du Colombier 	}
572*a81c3ea0SDavid du Colombier 	return nil;
573*a81c3ea0SDavid du Colombier }
574*a81c3ea0SDavid du Colombier 
575*a81c3ea0SDavid du Colombier static void
fbenable(void)576*a81c3ea0SDavid du Colombier fbenable(void)
577*a81c3ea0SDavid du Colombier {
578*a81c3ea0SDavid du Colombier 	Pcidev *p;
579*a81c3ea0SDavid du Colombier 
580*a81c3ea0SDavid du Colombier 	if(ctlr)
581*a81c3ea0SDavid du Colombier 		return;
582*a81c3ea0SDavid du Colombier 	p = videopci();
583*a81c3ea0SDavid du Colombier 	if(p == nil)
584*a81c3ea0SDavid du Colombier 		return;
585*a81c3ea0SDavid du Colombier 	ctlr = malloc(sizeof(Ctlr));
586*a81c3ea0SDavid du Colombier 	ctlr->pcidev = p;
587*a81c3ea0SDavid du Colombier 	ctlr->paddr = PCIMEMADDR(p->mem[0].bar & ~0x0f);
588*a81c3ea0SDavid du Colombier 	ctlr->vaddr = KSEG1ADDR(ctlr->paddr);
589*a81c3ea0SDavid du Colombier 	ctlr->port = p->mem[1].bar & ~0x01;
590*a81c3ea0SDavid du Colombier 	ctlr->mmio = KSEG1ADDR(PCIMEMADDR(p->mem[2].bar & ~0x0f));
591*a81c3ea0SDavid du Colombier }
592*a81c3ea0SDavid du Colombier 
593*a81c3ea0SDavid du Colombier void*
fbinit(void)594*a81c3ea0SDavid du Colombier fbinit(void)
595*a81c3ea0SDavid du Colombier {
596*a81c3ea0SDavid du Colombier 	if(!ctlr)
597*a81c3ea0SDavid du Colombier 		fbenable();
598*a81c3ea0SDavid du Colombier 
599*a81c3ea0SDavid du Colombier 	if(!ctlr)
600*a81c3ea0SDavid du Colombier 		return nil;
601*a81c3ea0SDavid du Colombier 	else
602*a81c3ea0SDavid du Colombier 		return ctlr->vaddr;
603*a81c3ea0SDavid du Colombier }
604