your're a bright guy, really.
I was sure there is no workaround for this. But you have found one.
Setting CR66 bit 1 while reading the BIOS ROM does prevent DRAM
corruption.
I wonder what happens if you keep this bit set for too long. Possibly
DRAM will loose some of its data becase DRAM refresh is also stopped...
But still I think, this think should go into the S3 server to protect
reading the ROM on the Trio and ViRGE chips.
Thanks!
Bernhard Bender
--- Group Manager Core Technology ELSA Computer GraphicsELSA GmbH Email: br@elsa.de Sonnenweg 11 Fax : +49 (2405) 450 100 D-52 070 Aachen, Germany WWW : http://www.elsa.de
*** Original Message Follows *** > >>> > 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 ^^^^^ ^^^^^ *** End of Original Message ***