]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgahiqvideo.c
vga: make kernel vga drivers more stupid
[plan9front.git] / sys / src / 9 / pc / vgahiqvideo.c
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         Xrx             = 0x3D6,        /* Configuration Extensions Index */
17 };
18
19 static uchar
20 hiqvideoxi(long port, uchar index)
21 {
22         uchar data;
23
24         outb(port, index);
25         data = inb(port+1);
26
27         return data;
28 }
29
30 static void
31 hiqvideoxo(long port, uchar index, uchar data)
32 {
33         outb(port, index);
34         outb(port+1, data);
35 }
36
37 static void
38 hiqvideolinear(VGAscr*, int, int)
39 {
40 }
41
42 static void
43 hiqvideoenable(VGAscr* scr)
44 {
45         Pcidev *p;
46         int vmsize;
47
48         /*
49          * Only once, can't be disabled for now.
50          */
51         if(scr->mmio)
52                 return;
53         p = scr->pci;
54         if(p == nil || p->vid != 0x102C)
55                 return;
56         switch(p->did){
57         case 0x00C0:            /* 69000 HiQVideo */
58                 vmsize = 2*1024*1024;
59                 break;
60         case 0x00E0:            /* 65550 HiQV32 */
61         case 0x00E4:            /* 65554 HiQV32 */
62         case 0x00E5:            /* 65555 HiQV32 */
63                 switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
64                 default:
65                 case 0:
66                         vmsize = 1*1024*1024;
67                         break;
68                 case 1:
69                         vmsize = 2*1024*1024;
70                         break;
71                 }
72                 break;
73         default:
74                 return;
75         }
76         vgalinearpci(scr);
77         
78         if(scr->paddr)
79                 addvgaseg("hiqvideoscreen", scr->paddr, scr->apsize);
80
81         /*
82          * Find a place for the cursor data in display memory.
83          * Must be on a 4096-byte boundary.
84          * scr->mmio holds the virtual address of the cursor
85          * storage area in the framebuffer region.
86          */
87         scr->storage = vmsize-4096;
88         scr->mmio = (ulong*)((uchar*)scr->vaddr+scr->storage);
89 }
90
91 static void
92 hiqvideocurdisable(VGAscr*)
93 {
94         hiqvideoxo(Xrx, 0xA0, 0x10);
95 }
96
97 static void
98 hiqvideocurload(VGAscr* scr, Cursor* curs)
99 {
100         uchar *p;
101         int x, y;
102
103         /*
104          * Disable the cursor.
105          */
106         hiqvideocurdisable(scr);
107
108         if(scr->mmio == 0)
109                 return;
110         p = (uchar*)scr->mmio;
111
112         for(y = 0; y < 16; y += 2){
113                 *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
114                 *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
115                 *p++ = 0xFF;
116                 *p++ = 0xFF;
117                 *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
118                 *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
119                 *p++ = 0xFF;
120                 *p++ = 0xFF;
121                 *p++ = curs->set[2*y];
122                 *p++ = curs->set[2*y+1];
123                 *p++ = 0x00;
124                 *p++ = 0x00;
125                 *p++ = curs->set[2*y+2];
126                 *p++ = curs->set[2*y+3];
127                 *p++ = 0x00;
128                 *p++ = 0x00;
129         }
130         while(y < 32){
131                 for(x = 0; x < 64; x += 8)
132                         *p++ = 0xFF;
133                 for(x = 0; x < 64; x += 8)
134                         *p++ = 0x00;
135                 y += 2;
136         }
137
138         /*
139          * Save the cursor hotpoint and enable the cursor.
140          */
141         scr->offset = curs->offset;
142         hiqvideoxo(Xrx, 0xA0, 0x11);
143 }
144
145 static int
146 hiqvideocurmove(VGAscr* scr, Point p)
147 {
148         int x, y;
149
150         if(scr->mmio == 0)
151                 return 1;
152
153         if((x = p.x+scr->offset.x) < 0)
154                 x = 0x8000|(-x & 0x07FF);
155         if((y = p.y+scr->offset.y) < 0)
156                 y = 0x8000|(-y & 0x07FF);
157
158         hiqvideoxo(Xrx, 0xA4, x & 0xFF);
159         hiqvideoxo(Xrx, 0xA5, (x>>8) & 0xFF);
160         hiqvideoxo(Xrx, 0xA6, y & 0xFF);
161         hiqvideoxo(Xrx, 0xA7, (y>>8) & 0xFF);
162
163         return 0;
164 }
165
166 static void
167 hiqvideocurenable(VGAscr* scr)
168 {
169         uchar xr80;
170
171         hiqvideoenable(scr);
172         if(scr->mmio == 0)
173                 return;
174
175         /*
176          * Disable the cursor.
177          */
178         hiqvideocurdisable(scr);
179
180         /*
181          * Cursor colours.
182          * Can't call setcolor here as cursor is already locked.
183          * When done make sure the cursor enable in Xr80 is set.
184          */
185         xr80 = hiqvideoxi(Xrx, 0x80);
186         hiqvideoxo(Xrx, 0x80, xr80|0x01);
187         vgao(PaddrW, 0x04);
188         vgao(Pdata, Pwhite);
189         vgao(Pdata, Pwhite);
190         vgao(Pdata, Pwhite);
191         vgao(Pdata, Pblack);
192         vgao(Pdata, Pblack);
193         vgao(Pdata, Pblack);
194         hiqvideoxo(Xrx, 0x80, xr80|0x10);
195
196         hiqvideoxo(Xrx, 0xA2, (scr->storage>>12)<<4);
197         hiqvideoxo(Xrx, 0xA3, (scr->storage>>16) & 0x3F);
198
199         /*
200          * Load, locate and enable the 32x32 cursor.
201          * Cursor enable in Xr80 better be set already.
202          */
203         hiqvideocurload(scr, &arrow);
204         hiqvideocurmove(scr, ZP);
205         hiqvideoxo(Xrx, 0xA0, 0x11);
206 }
207
208 VGAdev vgahiqvideodev = {
209         "hiqvideo",
210
211         hiqvideoenable,                 /* enable */
212         nil,                            /* disable */
213         nil,                            /* page */
214         hiqvideolinear,                 /* linear */
215 };
216
217 VGAcur vgahiqvideocur = {
218         "hiqvideohwgc",
219
220         hiqvideocurenable,              /* enable */
221         hiqvideocurdisable,             /* disable */
222         hiqvideocurload,                /* load */
223         hiqvideocurmove,                /* move */
224 };