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 ^^^^^ ^^^^^