summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1997-04-27 09:03:10 +0000
committeryokota <yokota@FreeBSD.org>1997-04-27 09:03:10 +0000
commita04669c796650a51df44d84793f6e8aa684b4388 (patch)
tree31cb002be239290e5a53f91e5ab73a772c30b29d /sys/dev
parent4deb06a037f7e9be2228918e7ece7bba6efef34c (diff)
downloadFreeBSD-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.c124
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;
OpenPOWER on IntegriCloud