If you know where to look, the actual writes are pretty straightforward as they all take a common format: Wait for the device, then pump some commands. Which is not much different from the many other video cards from that period.
As a general tour of reverse engineering basics an example of the reset code:
Code: Select all
/* s3v_accel.c:492 */
WAITFIFO(5);
OUTREG(SRC_BASE, 0);
OUTREG(DEST_BASE, 0);
OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
You could have looked up the relevant macros:
Code: Select all
/* s3v.h:91 */
#define OUTREG(addr, val) MMIO_OUT32(ps3v->MapBase, addr, val)
which tells us that the default register is 32 bits and is located at a certain offset from MapBase:
Code: Select all
/* s3v_driverc:2182 */
ps3v->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, ps3v->PciTag,
PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) + S3_NEWMMIO_REGBASE,
S3_NEWMMIO_REGSIZE);
which maps regsize bytes from BAR + regbase. In essence the MMIO comes directly after the possible video RAM but otherwise shares a base address register.
Code: Select all
/* newmmio.h:48 */
#define S3_NEWMMIO_REGBASE 0x1000000 /* 16MB */
#define S3_NEWMMIO_REGSIZE 0x10000 /* 64KB */
You know the offset:
Code: Select all
/* s3v_macros.h:73 */
#define SRC_BASE 0xA4D4
#define DEST_BASE 0xA4D8
so altogether a write goes to BAR + REGBASE + (offset). Performing the same strategy with the value part will allow you to replicate the writes an X.org driver would perform, and all I really did so far was just a multi-file search for definitions or the relevant setters.
Now you do the same for the functions in s3v_accel.h that you want to use. You probably want to start with fills or screen-to-screen blits because you can visually inspect the results.