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