direct-io.hg

view xen/drivers/video/vga.c @ 11116:d853acd5ed58

Clean up vga.c and change default font slot to zero, as other
slots are not supported by ATI video cards.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 15 11:36:10 2006 +0100 (2006-08-15)
parents ae71e1d92d44
children 3e75d9b1d556
line source
1 /******************************************************************************
2 * vga.c
3 *
4 * VGA support routines.
5 */
7 #include <xen/config.h>
8 #include <xen/compile.h>
9 #include <xen/init.h>
10 #include <xen/lib.h>
11 #include <xen/errno.h>
12 #include <xen/event.h>
13 #include <xen/spinlock.h>
14 #include <xen/console.h>
15 #include <xen/font.h>
16 #include <xen/vga.h>
17 #include <asm/io.h>
19 /* Some of the code below is taken from SVGAlib. The original,
20 unmodified copyright notice for that code is below. */
21 /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
22 /* */
23 /* This library is free software; you can redistribute it and/or */
24 /* modify it without any restrictions. This library is distributed */
25 /* in the hope that it will be useful, but without any warranty. */
27 /* Multi-chipset support Copyright 1993 Harm Hanemaayer */
28 /* partially copyrighted (C) 1993 by Hartmut Schirmer */
30 /* VGA data register ports */
31 #define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
32 #define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
33 #define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */
34 #define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */
35 #define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */
36 #define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */
37 #define VGA_MIS_R 0x3CC /* Misc Output Read Register */
38 #define VGA_MIS_W 0x3C2 /* Misc Output Write Register */
39 #define VGA_FTC_R 0x3CA /* Feature Control Read Register */
40 #define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
41 #define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
42 #define VGA_PEL_D 0x3C9 /* PEL Data Register */
43 #define VGA_PEL_MSK 0x3C6 /* PEL mask register */
45 /* EGA-specific registers */
46 #define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */
47 #define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */
49 /* VGA index register ports */
50 #define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
51 #define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
52 #define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
53 #define VGA_GFX_I 0x3CE /* Graphics Controller Index */
54 #define VGA_SEQ_I 0x3C4 /* Sequencer Index */
55 #define VGA_PEL_IW 0x3C8 /* PEL Write Index */
56 #define VGA_PEL_IR 0x3C7 /* PEL Read Index */
58 /* standard VGA indexes max counts */
59 #define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */
60 #define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */
61 #define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */
62 #define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */
63 #define VGA_MIS_C 0x01 /* Number of Misc Output Register */
65 /* VGA misc register bit masks */
66 #define VGA_MIS_COLOR 0x01
67 #define VGA_MIS_ENB_MEM_ACCESS 0x02
68 #define VGA_MIS_DCLK_28322_720 0x04
69 #define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08)
70 #define VGA_MIS_SEL_HIGH_PAGE 0x20
72 /* VGA CRT controller register indices */
73 #define VGA_CRTC_H_TOTAL 0
74 #define VGA_CRTC_H_DISP 1
75 #define VGA_CRTC_H_BLANK_START 2
76 #define VGA_CRTC_H_BLANK_END 3
77 #define VGA_CRTC_H_SYNC_START 4
78 #define VGA_CRTC_H_SYNC_END 5
79 #define VGA_CRTC_V_TOTAL 6
80 #define VGA_CRTC_OVERFLOW 7
81 #define VGA_CRTC_PRESET_ROW 8
82 #define VGA_CRTC_MAX_SCAN 9
83 #define VGA_CRTC_CURSOR_START 0x0A
84 #define VGA_CRTC_CURSOR_END 0x0B
85 #define VGA_CRTC_START_HI 0x0C
86 #define VGA_CRTC_START_LO 0x0D
87 #define VGA_CRTC_CURSOR_HI 0x0E
88 #define VGA_CRTC_CURSOR_LO 0x0F
89 #define VGA_CRTC_V_SYNC_START 0x10
90 #define VGA_CRTC_V_SYNC_END 0x11
91 #define VGA_CRTC_V_DISP_END 0x12
92 #define VGA_CRTC_OFFSET 0x13
93 #define VGA_CRTC_UNDERLINE 0x14
94 #define VGA_CRTC_V_BLANK_START 0x15
95 #define VGA_CRTC_V_BLANK_END 0x16
96 #define VGA_CRTC_MODE 0x17
97 #define VGA_CRTC_LINE_COMPARE 0x18
98 #define VGA_CRTC_REGS VGA_CRT_C
100 /* VGA CRT controller bit masks */
101 #define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */
102 #define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
104 /* VGA attribute controller register indices */
105 #define VGA_ATC_PALETTE0 0x00
106 #define VGA_ATC_PALETTE1 0x01
107 #define VGA_ATC_PALETTE2 0x02
108 #define VGA_ATC_PALETTE3 0x03
109 #define VGA_ATC_PALETTE4 0x04
110 #define VGA_ATC_PALETTE5 0x05
111 #define VGA_ATC_PALETTE6 0x06
112 #define VGA_ATC_PALETTE7 0x07
113 #define VGA_ATC_PALETTE8 0x08
114 #define VGA_ATC_PALETTE9 0x09
115 #define VGA_ATC_PALETTEA 0x0A
116 #define VGA_ATC_PALETTEB 0x0B
117 #define VGA_ATC_PALETTEC 0x0C
118 #define VGA_ATC_PALETTED 0x0D
119 #define VGA_ATC_PALETTEE 0x0E
120 #define VGA_ATC_PALETTEF 0x0F
121 #define VGA_ATC_MODE 0x10
122 #define VGA_ATC_OVERSCAN 0x11
123 #define VGA_ATC_PLANE_ENABLE 0x12
124 #define VGA_ATC_PEL 0x13
125 #define VGA_ATC_COLOR_PAGE 0x14
127 #define VGA_AR_ENABLE_DISPLAY 0x20
129 /* VGA sequencer register indices */
130 #define VGA_SEQ_RESET 0x00
131 #define VGA_SEQ_CLOCK_MODE 0x01
132 #define VGA_SEQ_PLANE_WRITE 0x02
133 #define VGA_SEQ_CHARACTER_MAP 0x03
134 #define VGA_SEQ_MEMORY_MODE 0x04
136 /* VGA sequencer register bit masks */
137 #define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */
138 #define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */
139 #define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */
140 #define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */
141 #define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */
142 #define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */
144 /* VGA graphics controller register indices */
145 #define VGA_GFX_SR_VALUE 0x00
146 #define VGA_GFX_SR_ENABLE 0x01
147 #define VGA_GFX_COMPARE_VALUE 0x02
148 #define VGA_GFX_DATA_ROTATE 0x03
149 #define VGA_GFX_PLANE_READ 0x04
150 #define VGA_GFX_MODE 0x05
151 #define VGA_GFX_MISC 0x06
152 #define VGA_GFX_COMPARE_MASK 0x07
153 #define VGA_GFX_BIT_MASK 0x08
155 /* VGA graphics controller bit masks */
156 #define VGA_GR06_GRAPHICS_MODE 0x01
158 /* macro for composing an 8-bit VGA register index and value
159 * into a single 16-bit quantity */
160 #define VGA_OUT16VAL(v, r) (((v) << 8) | (r))
162 #if defined(__i386__) || defined(__x86_64__)
163 # define vgabase 0
164 # define VGA_OUTW_WRITE
165 # define vga_readb(x) (*(x))
166 # define vga_writeb(x,y) (*(y) = (x))
167 #endif
169 /*
170 * generic VGA port read/write
171 */
173 static inline uint8_t vga_io_r(uint16_t port)
174 {
175 return inb(port);
176 }
178 static inline void vga_io_w(uint16_t port, uint8_t val)
179 {
180 outb(val, port);
181 }
183 static inline void vga_io_w_fast(uint16_t port, uint8_t reg, uint8_t val)
184 {
185 outw(VGA_OUT16VAL(val, reg), port);
186 }
188 static inline uint8_t vga_mm_r(void __iomem *regbase, uint16_t port)
189 {
190 return readb(regbase + port);
191 }
193 static inline void vga_mm_w(void __iomem *regbase, uint16_t port, uint8_t val)
194 {
195 writeb(val, regbase + port);
196 }
198 static inline void vga_mm_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val)
199 {
200 writew(VGA_OUT16VAL(val, reg), regbase + port);
201 }
203 static inline uint8_t vga_r(void __iomem *regbase, uint16_t port)
204 {
205 if (regbase)
206 return vga_mm_r(regbase, port);
207 else
208 return vga_io_r(port);
209 }
211 static inline void vga_w(void __iomem *regbase, uint16_t port, uint8_t val)
212 {
213 if (regbase)
214 vga_mm_w(regbase, port, val);
215 else
216 vga_io_w(port, val);
217 }
220 static inline void vga_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val)
221 {
222 if (regbase)
223 vga_mm_w_fast(regbase, port, reg, val);
224 else
225 vga_io_w_fast(port, reg, val);
226 }
229 /*
230 * VGA CRTC register read/write
231 */
233 static inline uint8_t vga_rcrt(void __iomem *regbase, uint8_t reg)
234 {
235 vga_w(regbase, VGA_CRT_IC, reg);
236 return vga_r(regbase, VGA_CRT_DC);
237 }
239 static inline void vga_wcrt(void __iomem *regbase, uint8_t reg, uint8_t val)
240 {
241 #ifdef VGA_OUTW_WRITE
242 vga_w_fast(regbase, VGA_CRT_IC, reg, val);
243 #else
244 vga_w(regbase, VGA_CRT_IC, reg);
245 vga_w(regbase, VGA_CRT_DC, val);
246 #endif /* VGA_OUTW_WRITE */
247 }
249 /*
250 * VGA sequencer register read/write
251 */
253 static inline uint8_t vga_rseq(void __iomem *regbase, uint8_t reg)
254 {
255 vga_w(regbase, VGA_SEQ_I, reg);
256 return vga_r(regbase, VGA_SEQ_D);
257 }
259 static inline void vga_wseq(void __iomem *regbase, uint8_t reg, uint8_t val)
260 {
261 #ifdef VGA_OUTW_WRITE
262 vga_w_fast(regbase, VGA_SEQ_I, reg, val);
263 #else
264 vga_w(regbase, VGA_SEQ_I, reg);
265 vga_w(regbase, VGA_SEQ_D, val);
266 #endif /* VGA_OUTW_WRITE */
267 }
269 /*
270 * VGA graphics controller register read/write
271 */
273 static inline uint8_t vga_rgfx(void __iomem *regbase, uint8_t reg)
274 {
275 vga_w(regbase, VGA_GFX_I, reg);
276 return vga_r(regbase, VGA_GFX_D);
277 }
279 static inline void vga_wgfx(void __iomem *regbase, uint8_t reg, uint8_t val)
280 {
281 #ifdef VGA_OUTW_WRITE
282 vga_w_fast(regbase, VGA_GFX_I, reg, val);
283 #else
284 vga_w(regbase, VGA_GFX_I, reg);
285 vga_w(regbase, VGA_GFX_D, val);
286 #endif /* VGA_OUTW_WRITE */
287 }
289 /*
290 * VGA attribute controller register read/write
291 */
293 static inline uint8_t vga_rattr(void __iomem *regbase, uint8_t reg)
294 {
295 vga_w(regbase, VGA_ATT_IW, reg);
296 return vga_r(regbase, VGA_ATT_R);
297 }
299 static inline void vga_wattr(void __iomem *regbase, uint8_t reg, uint8_t val)
300 {
301 vga_w(regbase, VGA_ATT_IW, reg);
302 vga_w(regbase, VGA_ATT_W, val);
303 }
305 static int detect_video(void *video_base)
306 {
307 volatile u16 *p = (volatile u16 *)video_base;
308 u16 saved1 = p[0], saved2 = p[1];
309 int video_found = 1;
311 p[0] = 0xAA55;
312 p[1] = 0x55AA;
313 if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
314 video_found = 0;
316 p[0] = 0x55AA;
317 p[1] = 0xAA55;
318 if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
319 video_found = 0;
321 p[0] = saved1;
322 p[1] = saved2;
324 return video_found;
325 }
327 static int detect_vga(void)
328 {
329 /*
330 * Look at a number of well-known locations. Even if video is not at
331 * 0xB8000 right now, it will appear there when we set up text mode 3.
332 *
333 * We assume if there is any sign of a video adaptor then it is at least
334 * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
335 *
336 * These checks are basically to detect headless server boxes.
337 */
338 return (detect_video(ioremap(0xA0000, 0x1000)) ||
339 detect_video(ioremap(0xB0000, 0x1000)) ||
340 detect_video(ioremap(0xB8000, 0x1000)));
341 }
343 /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
344 void *setup_vga(void)
345 {
346 /* The following VGA state was saved from a chip in text mode 3. */
347 static unsigned char regs[] = {
348 /* Sequencer registers */
349 0x03, 0x00, 0x03, 0x00, 0x02,
350 /* CRTC registers */
351 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
352 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
353 0xb9, 0xa3, 0xff,
354 /* Graphic registers */
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
356 /* Attribute registers */
357 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
358 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
359 };
361 int i, j;
363 if ( !detect_vga() )
364 {
365 printk("No VGA adaptor detected!\n");
366 return NULL;
367 }
369 inb(VGA_IS1_RC);
370 outb(0x00, VGA_ATT_IW);
372 for ( i = j = 0; i < 5; i++ )
373 vga_wseq(vgabase, i, regs[j++]);
375 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
376 vga_wcrt(vgabase, 17, regs[5+17] & 0x7F);
378 for ( i = 0; i < 25; i++ )
379 vga_wcrt(vgabase, i, regs[j++]);
381 for ( i = 0; i < 9; i++ )
382 vga_wgfx(vgabase, i, regs[j++]);
384 inb(VGA_IS1_RC);
385 for ( i = 0; i < 21; i++ )
386 vga_wattr(vgabase, i, regs[j++]);
388 inb(VGA_IS1_RC);
389 outb(0x20, VGA_ATT_IW);
391 return ioremap(0xB8000, 0x8000);
392 }
394 void vga_cursor_off(void)
395 {
396 vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, 0x20);
397 }
399 static int vga_set_scanlines(unsigned scanlines)
400 {
401 unsigned vtot, ovr, vss, vbs;
402 uint8_t vse, vbe, misc = 0;
404 switch (scanlines) {
405 case 43*8:
406 vtot = 0x1bf;
407 vss = 0x183;
408 vse = 0x05;
409 vbs = 0x163;
410 vbe = 0xba;
411 break;
412 case 25*16:
413 case 28*14:
414 vtot = 0x1bf;
415 vss = 0x19c;
416 vse = 0x0e;
417 vbs = 0x196;
418 vbe = 0xb9;
419 break;
420 case 30*16:
421 case 34*14:
422 vtot = 0x20b;
423 vss = 0x1ea;
424 vse = 0x0c;
425 vbs = 0x1e7;
426 vbe = 0x04;
427 /* Preserve clock select bits and color bit, set correct sync polarity. */
428 misc = (inb(VGA_MIS_R) & 0x0d) | 0xe2;
429 break;
430 default:
431 return -ENOSYS;
432 }
434 ovr = vga_rcrt(vgabase, VGA_CRTC_OVERFLOW);
435 if(vga_rcrt(vgabase, VGA_CRTC_V_DISP_END) + ((ovr & 0x02) << 7) + ((ovr & 0x40) << 3) == scanlines - 1)
436 return 0;
438 ovr = (ovr & 0x10)
439 | ((vtot >> 8) & 0x01)
440 | ((vtot >> 4) & 0x20)
441 | (((scanlines - 1) >> 7) & 0x02)
442 | (((scanlines - 1) >> 3) & 0x40)
443 | ((vss >> 6) & 0x04)
444 | ((vss >> 2) & 0x80)
445 | ((vbs >> 5) & 0x08);
446 vse |= vga_rcrt(vgabase, VGA_CRTC_V_SYNC_END) & 0x70;
448 vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse & 0x7f); /* Vertical sync end (also unlocks CR0-7) */
449 vga_wcrt(vgabase, VGA_CRTC_V_TOTAL, (uint8_t)vtot); /* Vertical total */
450 vga_wcrt(vgabase, VGA_CRTC_OVERFLOW, (uint8_t)ovr); /* Overflow */
451 vga_wcrt(vgabase, VGA_CRTC_V_SYNC_START, (uint8_t)vss); /* Vertical sync start */
452 vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse | 0x80); /* Vertical sync end (also locks CR0-7) */
453 vga_wcrt(vgabase, VGA_CRTC_V_DISP_END, (uint8_t)(scanlines - 1)); /* Vertical display end */
454 vga_wcrt(vgabase, VGA_CRTC_V_BLANK_START, (uint8_t)vbs); /* Vertical blank start */
455 vga_wcrt(vgabase, VGA_CRTC_V_BLANK_END, vbe); /* Vertical blank end */
457 if (misc)
458 outb(misc, VGA_MIS_W); /* Misc output register */
460 return 0;
461 }
463 #define FONT_COUNT_MAX 256
464 #define FONT_HEIGHT_MAX 32
465 #define CHAR_MAP_SIZE (FONT_COUNT_MAX * FONT_HEIGHT_MAX)
467 /*
468 * We use font slot 0 because ATI cards do not honour changes to the
469 * character map select register. The fontslot parameter can be used to
470 * choose a non-default slot if the video card supports it and you wish to
471 * preserve the BIOS-initialised font data.
472 */
473 static unsigned font_slot = 0;
474 integer_param("fontslot", font_slot);
476 int vga_load_font(const struct font_desc *font, unsigned rows)
477 {
478 unsigned fontheight = font ? font->height : 16;
479 uint8_t fsr = vga_rcrt(vgabase, VGA_CRTC_MAX_SCAN); /* Font size register */
480 int ret;
482 if (font_slot > 3 || (!font_slot && !font))
483 return -ENOSYS;
485 if (font
486 && (font->count > FONT_COUNT_MAX
487 || fontheight > FONT_HEIGHT_MAX
488 || font->width != 8))
489 return -EINVAL;
491 ret = vga_set_scanlines(rows * fontheight);
492 if (ret < 0)
493 return ret;
495 if ((fsr & 0x1f) == fontheight - 1)
496 return 0;
498 /* First, the Sequencer */
499 vga_wseq(vgabase, VGA_SEQ_RESET, 0x1);
500 /* CPU writes only to map 2 */
501 vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
502 /* Sequential addressing */
503 vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
504 /* Clear synchronous reset */
505 vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
507 /* Now, the graphics controller, select map 2 */
508 vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x02);
509 /* disable odd-even addressing */
510 vga_wgfx(vgabase, VGA_GFX_MODE, 0x00);
511 /* map start at A000:0000 */
512 vga_wgfx(vgabase, VGA_GFX_MISC, 0x00);
514 if ( font )
515 {
516 unsigned i, j;
517 const uint8_t *data = font->data;
518 uint8_t *map = (uint8_t *)__va(0xA0000) + font_slot*2*CHAR_MAP_SIZE;
520 for ( i = j = 0; i < CHAR_MAP_SIZE; )
521 {
522 vga_writeb(j < font->count * fontheight ? data[j++] : 0,
523 map + i++);
524 if ( !(j % fontheight) )
525 while ( i & (FONT_HEIGHT_MAX - 1) )
526 vga_writeb(0, map + i++);
527 }
528 }
530 /* First, the sequencer, Synchronous reset */
531 vga_wseq(vgabase, VGA_SEQ_RESET, 0x01);
532 /* CPU writes to maps 0 and 1 */
533 vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
534 /* odd-even addressing */
535 vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
536 /* Character Map Select: The default font is kept in slot 0. */
537 vga_wseq(vgabase, VGA_SEQ_CHARACTER_MAP,
538 font ? font_slot | (font_slot << 2) : 0x00);
539 /* clear synchronous reset */
540 vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
542 /* Now, the graphics controller, select map 0 for CPU */
543 vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x00);
544 /* enable even-odd addressing */
545 vga_wgfx(vgabase, VGA_GFX_MODE, 0x10);
546 /* map starts at b800:0 */
547 vga_wgfx(vgabase, VGA_GFX_MISC, 0x0e);
549 /* Font size register */
550 fsr = (fsr & 0xe0) + (fontheight - 1);
551 vga_wcrt(vgabase, VGA_CRTC_MAX_SCAN, fsr);
553 /* Cursor shape registers */
554 fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_END) & 0xe0;
555 fsr |= fontheight - fontheight / 6;
556 vga_wcrt(vgabase, VGA_CRTC_CURSOR_END, fsr);
557 fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_START) & 0xe0;
558 fsr |= (fsr & 0x1f) - 1;
559 vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, fsr);
561 return 0;
562 }