FreeBSD/Linux Kernel Cross Reference
sys/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 }
Cache object: fdbcb8b25357746ff709fa3aa66904e3
|