Re: problem reading VGA text fonts

Harald Koenig (koenig@tat.physik.uni-tuebingen.de)
Wed, 20 Nov 1996 15:40:47 +0100 (MET)

> >>>
> now the interesting question is: how can we read the BIOS (esp. on AXP)
> without currupting video memory ?
> <<<
>
> Basically, you can't :-(

knowing the real reason for the font/memory corruption it's easy to
write a small test program and play with. for a Trio64V+ card
I see horrible things going on on the screen while this program
reads the BIOS.
but with S3 864 and 968 I don't see any problems with fonts here.

below is the test program. if you see any font/screen corruption
when running it (maybe several times; can be cleaned up with "setfont" again)
you should try to set RESET_S3 to 1 and see if this fixes
corruption for your card/machine...

also you can test SPARSE memory bios access if you set TEST_JENSEN_CODE to 1.
didn't make any difference for me (but with SPARSE access, copying
was >3 times faster then using DENSE access..)

now I could play with it a bit trying to find a better workaround
than saving the whole frame buffer before accessing the BIOS.

at least for the Trio64V+ card there is no problem when I reset
the S3 graphics engine using CR66 bit 1 while reading the BIOS.
haven't tested this for ViRGE yet but at least the GE can be reset
with the same bit...

> As for what S3 chips may be affected: The ViRGE for sure, maybe the
> TrioV+ also.

Trio64V+ for sure too (at least for my AXP box)

> There is no mention in S3's stepping info about this.

:-(

Harald
-------------------------------------------------------------------------------
#define TEST_JENSEN_CODE 0
#define RESET_S3 0
#define WRITE_BIOS_TO_STDOUT 0
#define SIZE (2*32*1024)

#ifdef __alpha__
#include <sys/io.h>
#else
#include <asm/io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>

#if TEST_JENSEN_CODE /* define to test the Sparse addressing on a non-Jensen */
#define SPARSE (5)
#define isJensen (1)
#else
#define isJensen (!_bus_base())
#define SPARSE (7)
#endif

extern unsigned long _bus_base(void);
extern unsigned long _bus_base_sparse(void);
#define BUS_BASE (isJensen ? _bus_base_sparse() : _bus_base())
#define JENSEN_SHIFT(x) (isJensen ? ((long)x<<SPARSE) : (long)x)

#ifdef __alpha__

/* The outb() isn't needed on my machine, but who nows ... -- ost */
void
SlowBcopy(src, dst, len)
unsigned char *dst, *src;
int len;
{
while(len--)
{
*dst++ = *src++;
outb(0x80, 0x00);
}
}

void
SlowBCopyFromBus(src, dst, count)
unsigned char *src, *dst;
int count;
{
if (isJensen) /* Jensen */
{
unsigned long addr;
long result;

addr = (unsigned long) src;
while( count ){
result = *(volatile int *) addr;
result >>= ((addr>>SPARSE) & 3) * 8;
*dst++ = (unsigned char) (0xffUL & result);
addr += 1<<SPARSE;
count--;
outb(0x80, 0x00);
}
}
else
SlowBcopy(src,dst,count);
}
#endif

int xf86ReadBIOS(Base, Offset, Buf, Len)
unsigned long Base;
unsigned long Offset;
unsigned char *Buf;
int Len;
{
#ifdef __alpha__
/*
* The Alpha version uses "mmap" instead of "lseek/read",
* because these (currently) don't work for BUS memory.
* We trick "mmap" into mapping BUS memory for us via BUS_BASE,
* which is the KSEG address of the start of the DENSE memory
* area.
*/

/*
* NOTE: there prolly ought to be more validity checks and all
* re: boundaries and sizes and such...
*/

/*
* The Jensen lacks dense memory, thus we have to address the bus via
* the sparse addressing scheme.
*
* Martin Ostermann (ost@comnets.rwth-aachen.de) - Apr.-Sep. 1996
*/

caddr_t base;
int fd;

if ((fd = open("/dev/mem", O_RDONLY)) < 0)
{
perror("xf86ReadBios: Failed to open /dev/mem");
return(-1);
}

base = mmap((caddr_t)0, JENSEN_SHIFT(SIZE), PROT_READ,
MAP_SHARED, fd, (off_t)(JENSEN_SHIFT(Base) + BUS_BASE));

if (base == (caddr_t)-1UL)
{
perror("xf86ReadBios: Failed to mmap /dev/mem");
return(-1);
}

SlowBCopyFromBus(base+JENSEN_SHIFT(Offset), Buf, Len);

munmap((caddr_t)JENSEN_SHIFT(base), JENSEN_SHIFT(SIZE));
close(fd);
return(Len);

#else /* __alpha__ */

int fd;

if ((fd = open("/dev/mem", O_RDONLY)) < 0)
{
perror("xf86ReadBios: Failed to open /dev/mem");
return(-1);
}

if (lseek(fd, (Base+Offset), SEEK_SET) < 0)
{
perror("xf86ReadBios: /dev/mem seek failed");
close(fd);
return(-1);
}
if (read(fd, Buf, Len) != Len)
{
perror("xf86ReadBios: /dev/mem read failed");
close(fd);
return(-1);
}
close(fd);
return(Len);
#endif /* __alpha__ */
}

void main()
{
char bios[SIZE];
#if RESET_S3
int tmp;
#endif

iopl(3);

#if RESET_S3
outb(0x38, 0x3d4);
outb(0x48, 0x3d5);
outb(0x39, 0x3d4);
outb(0xa5, 0x3d5);

/* reset S3 graphics engine */
outb(0x66, 0x3d4);
tmp = inb(0x3d5);
outb(tmp | 0x02, 0x3d5);
usleep(10000); /* wait a little bit... */
#endif

xf86ReadBIOS(0xc0000, 0, bios, SIZE);

#if RESET_S3
outb(0x66, 0x3d4);
outb(tmp & ~0x02, 0x3d5);
usleep(10000); /* wait a little bit... */
#endif

#if WRITE_BIOS_TO_STDOUT
write(1,bios,SIZE);
#endif
}

--
All SCSI disks will from now on                     ___       _____
be required to send an email notice                0--,|    /OOOOOOO\
24 hours prior to complete hardware failure!      <_/  /  /OOOOOOOOOOO\
                                                    \  \/OOOOOOOOOOOOOOO\
                                                      \ OOOOOOOOOOOOOOOOO|//
Harald Koenig,                                         \/\/\/\/\/\/\/\/\/
Inst.f.Theoret.Astrophysik                              //  /     \\  \
koenig@tat.physik.uni-tuebingen.de                     ^^^^^       ^^^^^

--
To unsubscribe: send e-mail to axp-list-request@redhat.com with
'unsubscribe' as the subject.  Do not send it to axp-list@redhat.com



Feedback | Store | News | Support | Product Errata | About Us | Linux Info | Search | JumpWords
No Frames | Show Frames

Copyright © 1995-1997 Red Hat Software. Legal notices