diff options
author | yokota <yokota@FreeBSD.org> | 1997-04-27 09:03:10 +0000 |
---|---|---|
committer | yokota <yokota@FreeBSD.org> | 1997-04-27 09:03:10 +0000 |
commit | a04669c796650a51df44d84793f6e8aa684b4388 (patch) | |
tree | 31cb002be239290e5a53f91e5ab73a772c30b29d /sys/dev | |
parent | 4deb06a037f7e9be2228918e7ece7bba6efef34c (diff) | |
download | FreeBSD-src-a04669c796650a51df44d84793f6e8aa684b4388.zip FreeBSD-src-a04669c796650a51df44d84793f6e8aa684b4388.tar.gz |
Addresses the following two problems.
1) i586_bcopy() problem
There have been a number of reports that the syscons doesn't work
properly if i586_bcopy() is enabled.
The problem prevented users from installing 2.2(.1)-RELEASE. The
symptom is that the system looks frozen during device probe or just
before the main installation menu. The workaround was to specify the
flag 0x01 to the npx device so that i586_bcopy() is disabled.
The patch forces the syscons to call generic_bcopy() when copying
to/from the video memory, even if CPU is Pentium and i586_bcopy() is
enabled. i586_bcopy() is still called for copy operations between
non-video memory regions.
PR: kern/2277, kern/3066, kern/3107, kern/3134
2) video mode parameter table problem
The syscons reads and uses the video mode parameter table provided by
the VGA BIOS to set VGA registers when changing video mode and
modifying font data. It appears that in some VGA BIOSes the table is
not ordered as the syscons expects, and this leads to screen
corruption.
The problem prevented users from installing 2.2(.1)-RELEASE. The
symptom is the corrupt screen or strange vertical lines soon after the
kernel is loaded into memory (just after the kernel decompression).
The patch performs simplistic test and if it fails, set video_mode_ptr
to NULL so that the video mode switching won't happen.
This is an interim kludge. There should be a better way to deal with
the problem.
PR: kern/2498, conf/2775, conf/3354
Reviewed by: sos
Tested by: PR originators (not all of them, though)
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/syscons/syscons.c | 124 |
1 files changed, 116 insertions, 8 deletions
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 35110c6..e80e6df 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.209 1997/04/10 12:26:50 yokota Exp $ + * $Id: syscons.c,v 1.210 1997/04/20 16:05:33 bde Exp $ */ #include "sc.h" @@ -79,7 +79,10 @@ #define WARM 1 /* this may break on older VGA's but is useful on real 32 bit systems */ -#define bcopyw bcopy +/* XXX use sc_bcopy where video memory is concerned */ +#define bcopyw bcopy +#define sc_bcopy generic_bcopy +extern void generic_bcopy(const void *, void *, size_t); static default_attr user_default = { (FG_LIGHTGREY | BG_BLACK) << 8, @@ -126,6 +129,7 @@ static long scrn_time_stamp; char font_14[256*14]; char font_16[256*16]; char palette[256*3]; +static char vgaregs[64]; static char *cut_buffer; static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, @@ -200,6 +204,9 @@ static int mask2attr(struct term_stat *term); static void set_keyboard(int command, int data); static void update_leds(int which); static void set_vgaregs(char *modetable); +static void read_vgaregs(char *buf); +static int comp_vgaregs(u_char *buf1, u_char *buf2); +static void dump_vgaregs(u_char *buf); static void set_font_mode(void); static void set_normal_mode(void); static void set_destructive_cursor(scr_stat *scp); @@ -489,6 +496,19 @@ scattach(struct isa_device *dev) update_leds(scp->status); + if (bootverbose) { + printf("sc%d: BIOS video mode:%d\n", + dev->id_unit, *(u_char *)pa_to_va(0x449)); + printf("sc%d: VGA registers upon power-up\n", dev->id_unit); + dump_vgaregs(vgaregs); + printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode); + if (video_mode_ptr != NULL) { + printf("sc%d: VGA registers for mode:%d\n", + dev->id_unit, scp->mode); + dump_vgaregs(video_mode_ptr + (64*scp->mode)); + } + } + printf("sc%d: ", dev->id_unit); if (crtc_vga) if (crtc_addr == MONO_BASE) @@ -1470,7 +1490,7 @@ sccnputc(dev_t dev, int c) s = splclock(); if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) { if (/* timer not running && */ (scp->start <= scp->end)) { - bcopyw(scp->scr_buf + scp->start, Crtat + scp->start, + sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, (1 + scp->end - scp->start) * sizeof(u_short)); scp->start = scp->xsize * scp->ysize; scp->end = 0; @@ -1562,7 +1582,7 @@ scrn_timer(void *arg) if (!scrn_blanked) { /* update screen image */ if (scp->start <= scp->end) { - bcopyw(scp->scr_buf + scp->start, Crtat + scp->start, + sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, (1 + scp->end - scp->start) * sizeof(u_short)); } @@ -2429,6 +2449,7 @@ scinit(void) u_long segoff; crtc_vga = TRUE; + read_vgaregs(vgaregs); /* Get the BIOS video mode pointer */ segoff = *(u_long *)pa_to_va(0x4a8); @@ -2445,8 +2466,14 @@ scinit(void) init_scp(console[0]); cur_console = console[0]; + /* discard the video mode table if we are not familiar with it... */ + if (video_mode_ptr) { + if (comp_vgaregs(vgaregs, video_mode_ptr + 64*console[0]->mode)) + video_mode_ptr = NULL; + } + /* copy screen to temporary buffer */ - bcopyw(Crtat, sc_buffer, + sc_bcopy(Crtat, sc_buffer, console[0]->xsize * console[0]->ysize * sizeof(u_short)); console[0]->scr_buf = console[0]->mouse_pos = sc_buffer; @@ -3321,6 +3348,80 @@ set_vgaregs(char *modetable) } static void +read_vgaregs(char *buf) +{ + int i, j; + int s; + + bzero(buf, 64); + + s = splhigh(); + + outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ + outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ + for (i=0, j=5; i<4; i++) { + outb(TSIDX, i+1); + buf[j++] = inb(TSREG); + } + buf[9] = inb(MISC + 10); /* dot-clock */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ + + for (i=0, j=10; i<25; i++) { /* crtc */ + outb(crtc_addr, i); + buf[j++] = inb(crtc_addr+1); + } + for (i=0, j=35; i<20; i++) { /* attribute ctrl */ + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, i); + buf[j++] = inb(ATC + 1); + } + for (i=0, j=55; i<9; i++) { /* graph data ctrl */ + outb(GDCIDX, i); + buf[j++] = inb(GDCREG); + } + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + + buf[0] = *(char *)pa_to_va(0x44a); /* COLS */ + buf[1] = *(char *)pa_to_va(0x484); /* ROWS */ + buf[2] = *(char *)pa_to_va(0x485); /* POINTS */ + buf[3] = *(char *)pa_to_va(0x44c); + buf[4] = *(char *)pa_to_va(0x44d); + + splx(s); +} + +static int +comp_vgaregs(u_char *buf1, u_char *buf2) +{ + int i; + + for(i = 0; i < 24; ++i) { + if (*buf1++ != *buf2++) + return 1; + } + buf1 += 2; /* skip the cursor position register value */ + buf2 += 2; + for(i = 26; i < 64; ++i) { + if (*buf1++ != *buf2++) + return 1; + } + return 0; +} + +static void +dump_vgaregs(u_char *buf) +{ + int i; + + for(i = 0; i < 64;) { + printf("%02x ", buf[i]); + if ((++i % 16) == 0) + printf("\n"); + } +} + +static void set_font_mode() { int s = splhigh(); @@ -3392,6 +3493,9 @@ set_normal_mode() modetable = video_mode_ptr + (64*M_VGA_C80x25); } + if (video_mode_ptr == NULL) + modetable = vgaregs; + /* setup vga for normal operation mode again */ inb(crtc_addr+6); /* reset flip-flop */ outb(ATC, 0x10); outb(ATC, modetable[0x10+35]); @@ -3508,7 +3612,7 @@ set_destructive_cursor(scr_stat *scp) while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; #endif set_font_mode(); - bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); + sc_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); set_normal_mode(); } @@ -3668,7 +3772,7 @@ draw_mouse_image(scr_stat *scp) while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; #endif set_font_mode(); - bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); + sc_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); set_normal_mode(); *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; @@ -3805,8 +3909,12 @@ toggle_splash_screen(scr_stat *scp) { static int toggle = 0; static u_char save_mode; - int s = splhigh(); + int s; + + if (video_mode_ptr == NULL) + return; + s = splhigh(); if (toggle) { scp->mode = save_mode; scp->status &= ~UNKNOWN_MODE; |