xref: /plan9/sys/src/9/pc/vgacyber938x.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 enum {
16 	CursorON	= 0xC8,
17 	CursorOFF	= 0x00,
18 };
19 
20 static int
cyber938xpageset(VGAscr *,int page)21 cyber938xpageset(VGAscr*, int page)
22 {
23 	int opage;
24 
25 	opage = inb(0x3D8);
26 
27 	outb(0x3D8, page);
28 	outb(0x3D9, page);
29 
30 	return opage;
31 }
32 
33 static void
cyber938xpage(VGAscr * scr,int page)34 cyber938xpage(VGAscr* scr, int page)
35 {
36 	lock(&scr->devlock);
37 	cyber938xpageset(scr, page);
38 	unlock(&scr->devlock);
39 }
40 
41 static void
cyber938xlinear(VGAscr * scr,int,int)42 cyber938xlinear(VGAscr* scr, int, int)
43 {
44 	Pcidev *p;
45 
46 	if(scr->vaddr)
47 		return;
48 
49 	vgalinearpciid(scr, 0x1023, 0);
50 	p = scr->pci;
51 
52 	/*
53 	 * Heuristic to detect the MMIO space.  We're flying blind
54 	 * here, with only the XFree86 source to guide us.
55 	 */
56 	if(p->mem[1].size == 0x20000)
57 		scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
58 
59 	if(scr->apsize)
60 		addvgaseg("cyber938xscreen", scr->paddr, scr->apsize);
61 	if(scr->mmio)
62 		addvgaseg("cyber938xmmio", p->mem[1].bar&~0x0F, 0x20000);
63 }
64 
65 static void
cyber938xcurdisable(VGAscr *)66 cyber938xcurdisable(VGAscr*)
67 {
68 	vgaxo(Crtx, 0x50, CursorOFF);
69 }
70 
71 static void
cyber938xcurload(VGAscr * scr,Cursor * curs)72 cyber938xcurload(VGAscr* scr, Cursor* curs)
73 {
74 	uchar *p;
75 	int islinear, opage, y;
76 
77 	cyber938xcurdisable(scr);
78 
79 	opage = 0;
80 	p = scr->vaddr;
81 	islinear = vgaxi(Crtx, 0x21) & 0x20;
82 	if(!islinear){
83 		lock(&scr->devlock);
84 		opage = cyber938xpageset(scr, scr->storage>>16);
85 		p += (scr->storage & 0xFFFF);
86 	}
87 	else
88 		p += scr->storage;
89 
90 	for(y = 0; y < 16; y++){
91 		*p++ = curs->set[2*y]|curs->clr[2*y];
92 		*p++ = curs->set[2*y + 1]|curs->clr[2*y + 1];
93 		*p++ = 0x00;
94 		*p++ = 0x00;
95 		*p++ = curs->set[2*y];
96 		*p++ = curs->set[2*y + 1];
97 		*p++ = 0x00;
98 		*p++ = 0x00;
99 	}
100 	memset(p, 0, (32-y)*8);
101 
102 	if(!islinear){
103 		cyber938xpageset(scr, opage);
104 		unlock(&scr->devlock);
105 	}
106 
107 	/*
108 	 * Save the cursor hotpoint and enable the cursor.
109 	 */
110 	scr->offset = curs->offset;
111 	vgaxo(Crtx, 0x50, CursorON);
112 }
113 
114 static int
cyber938xcurmove(VGAscr * scr,Point p)115 cyber938xcurmove(VGAscr* scr, Point p)
116 {
117 	int x, xo, y, yo;
118 
119 	/*
120 	 * Mustn't position the cursor offscreen even partially,
121 	 * or it might disappear. Therefore, if x or y is -ve, adjust the
122 	 * cursor origins instead.
123 	 */
124 	if((x = p.x+scr->offset.x) < 0){
125 		xo = -x;
126 		x = 0;
127 	}
128 	else
129 		xo = 0;
130 	if((y = p.y+scr->offset.y) < 0){
131 		yo = -y;
132 		y = 0;
133 	}
134 	else
135 		yo = 0;
136 
137 	/*
138 	 * Load the new values.
139 	 */
140 	vgaxo(Crtx, 0x46, xo);
141 	vgaxo(Crtx, 0x47, yo);
142 	vgaxo(Crtx, 0x40, x & 0xFF);
143 	vgaxo(Crtx, 0x41, (x>>8) & 0xFF);
144 	vgaxo(Crtx, 0x42, y & 0xFF);
145 	vgaxo(Crtx, 0x43, (y>>8) & 0xFF);
146 
147 	return 0;
148 }
149 
150 static void
cyber938xcurenable(VGAscr * scr)151 cyber938xcurenable(VGAscr* scr)
152 {
153 	int i;
154 	ulong storage;
155 
156 	cyber938xcurdisable(scr);
157 
158 	/*
159 	 * Cursor colours.
160 	 */
161 	for(i = 0x48; i < 0x4C; i++)
162 		vgaxo(Crtx, i, 0x00);
163 	for(i = 0x4C; i < 0x50; i++)
164 		vgaxo(Crtx, i, 0xFF);
165 
166 	/*
167 	 * Find a place for the cursor data in display memory.
168 	 */
169 	storage = ((scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024);
170 	vgaxo(Crtx, 0x44, storage & 0xFF);
171 	vgaxo(Crtx, 0x45, (storage>>8) & 0xFF);
172 	storage *= 1024;
173 	scr->storage = storage;
174 
175 	/*
176 	 * Load, locate and enable the 32x32 cursor.
177 	 * (64x64 is bit 0, X11 format is bit 6 and cursor
178 	 * enable is bit 7). Bit 3 needs to be set on 9382
179 	 * chips otherwise even the white bits are black.
180 	 */
181 	cyber938xcurload(scr, &arrow);
182 	cyber938xcurmove(scr, ZP);
183 	vgaxo(Crtx, 0x50, CursorON);
184 }
185 
186 VGAdev vgacyber938xdev = {
187 	"cyber938x",
188 
189 	nil,				/* enable */
190 	nil,				/* disable */
191 	cyber938xpage,			/* page */
192 	cyber938xlinear,		/* linear */
193 	nil,				/* drawinit */
194 };
195 
196 VGAcur vgacyber938xcur = {
197 	"cyber938xhwgc",
198 
199 	cyber938xcurenable,		/* enable */
200 	cyber938xcurdisable,		/* disable */
201 	cyber938xcurload,		/* load */
202 	cyber938xcurmove,		/* move */
203 };
204