]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vga.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / 9 / pc / vga.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 static Memimage* back;
16 static Memimage *conscol;
17
18 static Point curpos;
19 static Rectangle window;
20 static int *xp;
21 static int xbuf[256];
22 Lock vgascreenlock;
23 int drawdebug;
24
25 void
26 vgaimageinit(ulong chan)
27 {
28         if(back == nil){
29                 back = allocmemimage(Rect(0,0,1,1), chan);      /* RSC BUG */
30                 if(back == nil)
31                         panic("back alloc");            /* RSC BUG */
32                 back->flags |= Frepl;
33                 back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
34                 memfillcolor(back, DBlack);
35         }
36
37         if(conscol == nil){
38                 conscol = allocmemimage(Rect(0,0,1,1), chan);   /* RSC BUG */
39                 if(conscol == nil)
40                         panic("conscol alloc"); /* RSC BUG */
41                 conscol->flags |= Frepl;
42                 conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
43                 memfillcolor(conscol, DWhite);
44         }
45 }
46
47 static void
48 vgascroll(VGAscr* scr)
49 {
50         int h, o;
51         Point p;
52         Rectangle r;
53
54         h = scr->memdefont->height;
55         o = 8*h;
56         r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
57         p = Pt(window.min.x, window.min.y+o);
58         memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
59         r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
60         memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
61
62         curpos.y -= o;
63 }
64
65 static void
66 vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
67 {
68         Point p;
69         int h, w, pos;
70         Rectangle r;
71
72 //      drawdebug = 1;
73         if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
74                 xp = xbuf;
75
76         h = scr->memdefont->height;
77         switch(buf[0]){
78
79         case '\n':
80                 if(curpos.y+h >= window.max.y){
81                         vgascroll(scr);
82                         *flushr = window;
83                 }
84                 curpos.y += h;
85                 vgascreenputc(scr, "\r", flushr);
86                 break;
87
88         case '\r':
89                 xp = xbuf;
90                 curpos.x = window.min.x;
91                 break;
92
93         case '\t':
94                 p = memsubfontwidth(scr->memdefont, " ");
95                 w = p.x;
96                 if(curpos.x >= window.max.x-4*w)
97                         vgascreenputc(scr, "\n", flushr);
98
99                 pos = (curpos.x-window.min.x)/w;
100                 pos = 4-(pos%4);
101                 *xp++ = curpos.x;
102                 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
103                 memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
104                 curpos.x += pos*w;
105                 break;
106
107         case '\b':
108                 if(xp <= xbuf)
109                         break;
110                 xp--;
111                 r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
112                 memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
113                 combinerect(flushr, r);
114                 curpos.x = *xp;
115                 break;
116
117         case '\0':
118                 break;
119
120         default:
121                 p = memsubfontwidth(scr->memdefont, buf);
122                 w = p.x;
123
124                 if(curpos.x >= window.max.x-w)
125                         vgascreenputc(scr, "\n", flushr);
126
127                 *xp++ = curpos.x;
128                 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
129                 memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
130                 memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
131                 combinerect(flushr, r);
132                 curpos.x += w;
133         }
134 //      drawdebug = 0;
135 }
136
137 static void
138 vgascreenputs(char* s, int n)
139 {
140         int i, gotdraw;
141         Rune r;
142         char buf[4];
143         VGAscr *scr;
144         Rectangle flushr;
145
146         scr = &vgascreen[0];
147
148         if(!islo()){
149                 /*
150                  * Don't deadlock trying to
151                  * print in an interrupt.
152                  */
153                 if(!canlock(&vgascreenlock))
154                         return;
155         }
156         else
157                 lock(&vgascreenlock);
158
159         /*
160          * Be nice to hold this, but not going to deadlock
161          * waiting for it.  Just try and see.
162          */
163         gotdraw = canqlock(&drawlock);
164
165         flushr = Rect(10000, 10000, -10000, -10000);
166
167         while(n > 0){
168                 i = chartorune(&r, s);
169                 if(i == 0){
170                         s++;
171                         --n;
172                         continue;
173                 }
174                 memmove(buf, s, i);
175                 buf[i] = 0;
176                 n -= i;
177                 s += i;
178                 vgascreenputc(scr, buf, &flushr);
179         }
180         flushmemscreen(flushr);
181
182         if(gotdraw)
183                 qunlock(&drawlock);
184         unlock(&vgascreenlock);
185 }
186
187 void
188 vgascreenwin(VGAscr* scr)
189 {
190         int h, w;
191
192         h = scr->memdefont->height;
193         w = scr->memdefont->info[' '].width;
194
195         window = insetrect(scr->gscreen->r, 48);
196         window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
197         window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
198         curpos = window.min;
199
200         screenputs = vgascreenputs;
201 }
202
203 /*
204  * Supposedly this is the way to turn DPMS
205  * monitors off using just the VGA registers.
206  * Unfortunately, it seems to mess up the video mode
207  * on the cards I've tried.
208  */
209 void
210 vgablank(VGAscr*, int blank)
211 {
212         uchar seq1, crtc17;
213
214         if(blank) {
215                 seq1 = 0x00;
216                 crtc17 = 0x80;
217         } else {
218                 seq1 = 0x20;
219                 crtc17 = 0x00;
220         }
221
222         outs(Seqx, 0x0100);                     /* synchronous reset */
223         seq1 |= vgaxi(Seqx, 1) & ~0x20;
224         vgaxo(Seqx, 1, seq1);
225         crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
226         delay(10);
227         vgaxo(Crtx, 0x17, crtc17);
228         outs(Crtx, 0x0300);                             /* end synchronous reset */
229 }
230
231 void
232 addvgaseg(char *name, ulong pa, ulong size)
233 {
234         Physseg seg;
235
236         memset(&seg, 0, sizeof seg);
237         seg.attr = SG_PHYSICAL;
238         seg.name = name;
239         seg.pa = pa;
240         seg.size = size;
241         addphysseg(&seg);
242 }
243
244 void
245 cornerstring(char *s)
246 {
247         int h, w;
248         VGAscr *scr;
249         Rectangle r;
250         Point p;
251
252         scr = &vgascreen[0];
253         if(scr->vaddr == nil || screenputs != vgascreenputs)
254                 return;
255         p = memsubfontwidth(scr->memdefont, s);
256         w = p.x;
257         h = scr->memdefont->height;
258
259         r = Rect(0, 0, w, h);
260         memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
261         memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
262 //      flushmemscreen(r);
263 }