xref: /plan9/sys/src/9/pc/vgaclgd546x.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
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 Cursor546x Cursor546x;
16 struct Cursor546x {
17 	ushort	x;
18 	ushort	y;
19 	ushort	preset;
20 	ushort	enable;
21 	ushort	addr;
22 };
23 
24 enum {
25 	PaletteState	= 0xB0,
26 	CursorMMIO	= 0xE0,
27 };
28 
29 static void
clgd546xlinear(VGAscr * scr,int,int)30 clgd546xlinear(VGAscr* scr, int, int)
31 {
32 	vgalinearpci(scr);
33 }
34 
35 static void
clgd546xenable(VGAscr * scr)36 clgd546xenable(VGAscr* scr)
37 {
38 	Pcidev *p;
39 
40 	if(scr->mmio)
41 		return;
42 	if((p = pcimatch(nil, 0x1013, 0)) == nil)
43 		return;
44 	switch(p->did){
45 	case 0xD0:
46 	case 0xD4:
47 	case 0xD6:
48 		break;
49 	default:
50 		return;
51 	}
52 
53 	scr->pci = p;
54 	scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
55 	if(scr->mmio == 0)
56 		return;
57 	addvgaseg("clgd546xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
58 }
59 
60 static void
clgd546xcurdisable(VGAscr * scr)61 clgd546xcurdisable(VGAscr* scr)
62 {
63 	Cursor546x *cursor546x;
64 
65 	if(scr->mmio == 0)
66 		return;
67 	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
68 	cursor546x->enable = 0;
69 }
70 
71 static void
clgd546xcurload(VGAscr * scr,Cursor * curs)72 clgd546xcurload(VGAscr* scr, Cursor* curs)
73 {
74 	int c, i, m, y;
75 	uchar *p;
76 	Cursor546x *cursor546x;
77 
78 	if(scr->mmio == 0)
79 		return;
80 	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
81 
82 	/*
83 	 * Disable the cursor then change only the bits
84 	 * that need it.
85 	 */
86 	cursor546x->enable = 0;
87 	p = (uchar*)scr->vaddr + scr->storage;
88 	for(y = 0; y < 16; y++){
89 		c = curs->set[2*y];
90 		m = 0;
91 		for(i = 0; i < 8; i++){
92 			if(c & (1<<(7-i)))
93 				m |= 1<<i;
94 		}
95 		*p++ = m;
96 		c = curs->set[2*y + 1];
97 		m = 0;
98 		for(i = 0; i < 8; i++){
99 			if(c & (1<<(7-i)))
100 				m |= 1<<i;
101 		}
102 		*p++ = m;
103 		p += 6;
104 		c = curs->set[2*y]|curs->clr[2*y];
105 		m = 0;
106 		for(i = 0; i < 8; i++){
107 			if(c & (1<<(7-i)))
108 				m |= 1<<i;
109 		}
110 		*p++ = m;
111 		c = curs->set[2*y + 1]|curs->clr[2*y + 1];
112 		m = 0;
113 		for(i = 0; i < 8; i++){
114 			if(c & (1<<(7-i)))
115 				m |= 1<<i;
116 		}
117 		*p++ = m;
118 		p += 6;
119 	}
120 
121 	/*
122 	 * Save the cursor hotpoint and enable the cursor.
123 	 */
124 	scr->offset = curs->offset;
125 	cursor546x->enable = 1;
126 }
127 
128 static int
clgd546xcurmove(VGAscr * scr,Point p)129 clgd546xcurmove(VGAscr* scr, Point p)
130 {
131 	int x, xo, y, yo;
132 	Cursor546x *cursor546x;
133 
134 	if(scr->mmio == 0)
135 		return 1;
136 	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
137 
138 	if((x = p.x+scr->offset.x) < 0){
139 		xo = -x;
140 		x = 0;
141 	}
142 	else
143 		xo = 0;
144 	if((y = p.y+scr->offset.y) < 0){
145 		yo = -y;
146 		y = 0;
147 	}
148 	else
149 		yo = 0;
150 
151 	cursor546x->preset = (xo<<8)|yo;
152 	cursor546x->x = x;
153 	cursor546x->y = y;
154 
155 	return 0;
156 }
157 
158 static void
clgd546xcurenable(VGAscr * scr)159 clgd546xcurenable(VGAscr* scr)
160 {
161 	uchar *p;
162 	Cursor546x *cursor546x;
163 
164 	clgd546xenable(scr);
165 	if(scr->mmio == 0)
166 		return;
167 	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
168 
169 	/*
170 	 * Cursor colours.
171 	 * Can't call setcolor here as cursor is already locked.
172 	 */
173 	p = (uchar*)scr->mmio+PaletteState;
174 	*p |= 0x08;
175 	vgao(PaddrW, 0x00);
176 	vgao(Pdata, Pwhite);
177 	vgao(Pdata, Pwhite);
178 	vgao(Pdata, Pwhite);
179 	vgao(PaddrW, 0x0F);
180 	vgao(Pdata, Pblack);
181 	vgao(Pdata, Pblack);
182 	vgao(Pdata, Pblack);
183 	*p &= ~0x08;
184 
185 	/*
186 	 * Find a place for the cursor data in display memory.
187 	 * 2 cursor images might be needed, 1KB each so use the last
188 	 * 2KB of the framebuffer and initialise them to be
189 	 * transparent.
190 	 */
191 	scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022;
192 	cursor546x->addr = (scr->storage>>10)<<2;
193 	memset((uchar*)scr->vaddr + scr->storage, 0, 2*64*16);
194 
195 	/*
196 	 * Load, locate and enable the 64x64 cursor.
197 	 */
198 	clgd546xcurload(scr, &arrow);
199 	clgd546xcurmove(scr, ZP);
200 	cursor546x->enable = 1;
201 }
202 
203 VGAdev vgaclgd546xdev = {
204 	"clgd546x",
205 
206 	clgd546xenable,
207 	nil,
208 	nil,
209 	clgd546xlinear,
210 };
211 
212 VGAcur vgaclgd546xcur = {
213 	"clgd546xhwgc",
214 
215 	clgd546xcurenable,
216 	clgd546xcurdisable,
217 	clgd546xcurload,
218 	clgd546xcurmove,
219 };
220