Hi,

I'm playing around with my G400 using mmio access.  Can someone tell me
what I'm doing wrong?  Writing to the registers doesn't produce a seg
fault (so it seems that it would be mapped correctly), but reading back
from them afterwards gives me either strange values or zero.

(Ignore the WARPREG* reading, that was only a test to see if they really
were W/O.)

Poking a value into any of the other registers has no effect on what is
read back later.  Some of them are explicitly marked as R/W, but I can't
tell from the databook whether or not the value I write in that register
should be "latched" and available for subsequent reads, or if some
altogether different value is typically made available for reading from
that reg.

Any PCI posting should be flushed out by the read, and I made sure that
access to MMIO space is enabled by hitting a register in the pci config
space.  Curiously, making changes to PCI config space seems to be fine,
even while I am banging my head on the mmio.  (If I disable MMIO access
there, then any reads from MMIO space obviously return 0xffffffff.)

I tried using msync, munmap, etc, and none of that seems to have an
effect.  I'm slowly beginning to suspect that R/W doesn't mean what I
think it means with respect to MMIO registers.

-- 
Ryan Underwood, <[EMAIL PROTECTED]>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <sys/mman.h>
#include <pci/pci.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define MGA_VENDOR 0x102b
#define G400_DEVICE 0x0525

#include "warp_hw.h"

#define MGAREG(x) *(volatile u32 *)(MGABASE1+x)
#define MGA_LEN 0x4000

void init_warp_regs(volatile void *MGABASE1) {
	int i;

	/* memset(MGABASE1+WARPREG(0), 0, 64*4); */
	fprintf(stderr, "Seeding WARP regs...\n");
	for (i = 0; i < 64; i++) {
		MGAREG(WARPREG(i)) = i+1;
		fprintf(stderr, "[%d]:\t%8lx ", i, i+1);
		if (!((i+1)%4)) fprintf(stderr, "\n");
	}

//	fprintf(stderr, "Setting WMISC (0x%08p) to 3...\n", MGABASE1+WMISC);
//	MGAREG(WMISC) &= 3;
//	fprintf(stderr, "WMISC (0x%08p) is %d\n", MGABASE1+WMISC, MGAREG(WMISC));

	fprintf(stderr, "Setting WIADDRNB (%08p) to 0x30000...\n", MGABASE1+WIADDRNB);
	MGAREG(WIADDRNB) = 0x30000;
	fprintf(stderr, "WIADDRNB (%08p) is %d\n", MGABASE1+WIADDRNB, MGAREG(WIADDRNB));

	fprintf(stderr, "Setting C2CTL (%08p:%08lx) \n", MGABASE1+C2CTL, MGAREG(C2CTL));
	MGAREG(C2CTL) &= C2CTL_C2EN;
	fprintf(stderr, "C2CTL (%08p) is %d\n", MGABASE1+C2CTL, MGAREG(C2CTL));

}

void dump_warp(volatile void *MGABASE1) {

	int i;

	fprintf(stderr, "Display WARP0 regs:\n");
	for (i = 0; i < 64; i++) {
		fprintf(stderr, "[%d]:\t%8lx ", i, MGAREG(WARPREG(i)));
		if (!((i+1)%4)) fprintf(stderr, "\n");
	}

	fprintf(stderr, "WARP0 Interrupt %s\n", (MGAREG(IEN) & WIEN)? "enabled":"disabled");
	fprintf(stderr, "WARP0 Cache-miss Interrupt %s\n", (MGAREG(IEN) & WCIEN)? "enabled":"disabled");
	fprintf(stderr, "WARP1 Interrupt %s\n", (MGAREG(IEN) & WIEN1)? "enabled":"disabled");
	fprintf(stderr, "WARP1 Cache-miss Interrupt %s\n", (MGAREG(IEN) & WCIEN1)? "enabled":"disabled");

	fprintf(stderr, "Drawing engine status: %s\n", (MGAREG(STATUS) & DWGENGSTS)? "busy": "idle");
	fprintf(stderr, "WARP0 status: %s\n", (MGAREG(STATUS) & WBUSY)? "not idle": "idle");
	fprintf(stderr, "WARP1 status: %s\n", (MGAREG(STATUS) & WBUSY1)? "not idle": "idle");
	fprintf(stderr, "WARP BFIFO Path: %s\n", (MGAREG(STATUS) & WARPBFPATH)? "WARP1": "WARP0");
	fprintf(stderr, "WARPFIFO Input Path: %s\n", (MGAREG(STATUS) & WFIPATH)?
				"WARPFIFO1": "WARPFIFO0");
	fprintf(stderr, "WARPFIFO Output Path: %s\n", (MGAREG(STATUS) & WFOPATH)?
				"WARPFIFO1": "WARPFIFO0");

	fprintf(stderr, "WARP microcode address: 0x%lx\n", MGAREG(WCODEADDR) & 0xffffff00);

	fprintf(stderr, "WARP microcode caching %s\n", (MGAREG(WMISC) & (1 << 0))? "enabled":"disabled");
	fprintf(stderr, "WARP microcode load strategy: ");
	
	if (MGAREG(WMISC) & (1 << 0)) {
		if (MGAREG(WMISC) & (1 << 1)) {
			fprintf(stderr, "bus mastering\n");
		}
		else {
			fprintf(stderr, "interrupt\n");
		}
	}
	else {
		fprintf(stderr, "direct load\n");
	}

}

int main(int argc, char**argv) {

	volatile void *MGABASE1;
	struct pci_access *all_devices;
	struct pci_dev cfg;
	struct pci_dev *cur;
	int fd, i;
	u32 mgabase_addr = 0;
	u32 ret;

	assert(!getuid());
	iopl(3);
	/* Scan PCI buses for G400 */

	all_devices = pci_alloc();
	all_devices->numeric_ids = 1;
	pci_init(all_devices);
	pci_scan_bus(all_devices);

	cur = all_devices->devices;

	for (i = 0; ; i++) {
		if (cur[i].vendor_id == MGA_VENDOR && cur[i].device_id == G400_DEVICE) {
			printf("found MGA: irq %d\n", cur[i].irq);
			memcpy(&cfg, &cur[i], sizeof(struct pci_dev));
			mgabase_addr = pci_read_long(&cur[i], 0x14) & PCI_ADDR_MEM_MASK;
			break;
		}
		if (cur[i].next == NULL) break;
	}

	if (mgabase_addr == 0) {
		fprintf(stderr, "MGABASE1 not found\n");
		exit(EXIT_FAILURE);
	}

	fprintf(stderr,"MGABASE1: 0x%lx\n", mgabase_addr);
	fprintf(stderr,"MGABASE2: 0x%lx\n", pci_read_long(&cfg, 0x10));

	fprintf(stderr,"DEVID: 0x%lx\n", (ret = pci_read_long(&cfg, 0x00)));
	fprintf(stderr,"DEVCTRL: 0x%lx\n", (ret = pci_read_long(&cfg, 0x04)));
	if (!(ret & DEVCTRL_MEMSPACE)) {
		fprintf(stderr,"Enabling MMIO access\n");
		pci_write_long(&cfg, 0x04, ret|DEVCTRL_MEMSPACE);
		fprintf(stderr,"DEVCTRL: 0x%lx\n", (ret = pci_read_long(&cfg, 0x04)));
	}
	fprintf(stderr,"OPTION: 0x%lx\n", (ret = pci_read_long(&cfg, 0x40)));
	fprintf(stderr,"OPTION2: 0x%lx\n", (ret = pci_read_long(&cfg, 0x50)));
	fprintf(stderr,"OPTION3: 0x%lx\n", (ret = pci_read_long(&cfg, 0x54)));
	fprintf(stderr,"PM_CSR: 0x%lx\n", (ret = pci_read_long(&cfg, 0xe0)));
	fprintf(stderr,"PM_IDENT: 0x%lx\n", (ret = pci_read_long(&cfg, 0xdc)));
	fprintf(stderr,"ROMBASE: 0x%lx\n", (ret = pci_read_long(&cfg, 0x30)));
	fprintf(stderr,"SUBSYSID: 0x%lx\n", (ret = pci_read_long(&cfg, 0x2c)));
	pci_cleanup(all_devices);

	fd = open("/dev/mem", O_RDWR);
	if (fd == -1) {
		perror("open");
		exit(EXIT_FAILURE);
	}

	MGABASE1 = mmap(NULL, MGA_LEN, PROT_READ|PROT_WRITE,
			MAP_SHARED, fd, (off_t)mgabase_addr);

	if (MGABASE1 == MAP_FAILED) {
		perror("mmap");
		exit(EXIT_FAILURE);
	}

	fprintf(stderr, "mmap successful: 0x%lx\n", MGABASE1);

	{
		char *buf;
		asprintf(&buf, "cat /proc/%d/maps", getpid());
		system(buf);
		free(buf);
	}

	init_warp_regs(MGABASE1);
	dump_warp(MGABASE1);

	if (munmap((void*)MGABASE1, MGA_LEN) == -1) {
		perror("munmap");
	}

	close(fd);
}

Attachment: signature.asc
Description: Digital signature

Reply via email to