]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vga.c
pc, pc64: more conservative pcirouting
[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         static char rb[UTFmax+1];
123         static int nrb;
124         char *e;
125         int gotdraw;
126         VGAscr *scr;
127         Rectangle flushr;
128
129         scr = &vgascreen[0];
130
131         if(!islo()){
132                 /*
133                  * Don't deadlock trying to
134                  * print in an interrupt.
135                  */
136                 if(!canlock(&vgascreenlock))
137                         return;
138         }
139         else
140                 lock(&vgascreenlock);
141
142         /*
143          * Be nice to hold this, but not going to deadlock
144          * waiting for it.  Just try and see.
145          */
146         gotdraw = canqlock(&drawlock);
147
148         flushr = Rect(10000, 10000, -10000, -10000);
149
150         e = s + n;
151         while(s < e){
152                 rb[nrb++] = *s++;
153                 if(nrb >= UTFmax || fullrune(rb, nrb)){
154                         rb[nrb] = 0;
155                         vgascreenputc(scr, rb, &flushr);
156                         nrb = 0;
157                 }
158         }
159         flushmemscreen(flushr);
160
161         if(gotdraw)
162                 qunlock(&drawlock);
163         unlock(&vgascreenlock);
164 }
165
166 static Memimage*
167 mkcolor(Memimage *screen, ulong color)
168 {
169         Memimage *i;
170
171         if(i = allocmemimage(Rect(0,0,1,1), screen->chan)){
172                 i->flags |= Frepl;
173                 i->clipr = screen->r;
174                 memfillcolor(i, color);
175         }
176         return i;
177 }
178
179 void
180 vgascreenwin(VGAscr* scr)
181 {
182         Memimage *i;
183         Rectangle r;
184         Point p;
185         int h;
186
187         qlock(&drawlock);
188         
189         h = scr->memdefont->height;
190         r = scr->gscreen->r;
191
192         if(i = mkcolor(scr->gscreen, 0x444488FF)){
193                 memimagedraw(scr->gscreen, r, i, ZP, nil, ZP, S);
194                 freememimage(i);
195         }
196
197         window = insetrect(r, 20);
198         memimagedraw(scr->gscreen, window, conscol, ZP, memopaque, ZP, S);
199         window = insetrect(window, 4);
200         memimagedraw(scr->gscreen, window, back, ZP, memopaque, ZP, S);
201
202         if(i = mkcolor(scr->gscreen, 0xAAAAAAFF)){
203                 memimagedraw(scr->gscreen, Rect(window.min.x, window.min.y,
204                         window.max.x, window.min.y+h+5+6), i, ZP, nil, ZP, S);
205                 freememimage(i);
206
207                 window = insetrect(window, 5);
208                 p = addpt(window.min, Pt(10, 0));
209                 memimagestring(scr->gscreen, p, memblack, ZP, scr->memdefont, " Plan 9 Console ");
210                 window.min.y += h+6;
211         } else
212                 window = insetrect(window, 5);
213
214         window.max.y = window.min.y+(Dy(window)/h)*h;
215         curpos = window.min;
216
217         flushmemscreen(r);
218
219         qunlock(&drawlock);
220
221         screenputs = vgascreenputs;
222 }
223
224 /*
225  * Supposedly this is the way to turn DPMS
226  * monitors off using just the VGA registers.
227  * Unfortunately, it seems to mess up the video mode
228  * on the cards I've tried.
229  */
230 void
231 vgablank(VGAscr*, int blank)
232 {
233         uchar seq1, crtc17;
234
235         if(blank) {
236                 seq1 = 0x00;
237                 crtc17 = 0x80;
238         } else {
239                 seq1 = 0x20;
240                 crtc17 = 0x00;
241         }
242
243         outs(Seqx, 0x0100);                     /* synchronous reset */
244         seq1 |= vgaxi(Seqx, 1) & ~0x20;
245         vgaxo(Seqx, 1, seq1);
246         crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
247         delay(10);
248         vgaxo(Crtx, 0x17, crtc17);
249         outs(Crtx, 0x0300);                             /* end synchronous reset */
250 }
251
252 void
253 addvgaseg(char *name, ulong pa, ulong size)
254 {
255         Physseg seg;
256
257         memset(&seg, 0, sizeof seg);
258         seg.attr = SG_PHYSICAL;
259         seg.name = name;
260         seg.pa = pa;
261         seg.size = size;
262         addphysseg(&seg);
263 }