/* mga.c - see mga.h. Claude Opus 5.5, 2026-10-13. */ #include #include #include #include #include #include #include #include #include #include "mga.h" /* eieio: keep MMIO loads and stores in program order */ void eieio(void); #pragma mc_func eieio { "7c0006ac" } #pragma reg_killed_by eieio volatile unsigned char *mga_base, *mga_fb; unsigned int mga_pdata[8]; static gsc_handle h; static int rcmfd = -1, made = 0; int mga_open(void) { make_gp mg; static gAddrRanges ar; rcmfd = open("/dev/rcm0", O_RDWR); if (rcmfd < 0) { perror("open /dev/rcm0"); return -1; } memset(&h, 0, sizeof h); strcpy(h.devname, "mga0"); if (ioctl(rcmfd, GSC_HANDLE, &h)) { perror("GSC_HANDLE (is X running?)"); return -1; } memset(&mg, 0, sizeof mg); mg.pData = (genericPtr) mga_pdata; mg.length = sizeof mga_pdata; mg.access = EXCLUSIVE_ACCESS | ADDR_ARRAY_VERSION | ALL_ADDR_RANGES; mg.NumAddrRanges = 1; mg.AddrRanges = &ar; if (aixgsc(h.handle, MAKE_GP, &mg)) { fprintf(stderr, "MAKE_GP failed: errno %d error %d\n", errno, mg.error); return -1; } made = 1; if (mga_pdata[5] != 0x2b101a05) { fprintf(stderr, "unexpected device id 0x%08x\n", mga_pdata[5]); mga_close(); return -1; } mga_base = (volatile unsigned char *) ar.BaseAddr; mga_fb = mga_base + FB_OFFSET; return 0; } void mga_close(void) { unmake_gp ug; if (made) { memset(&ug, 0, sizeof ug); aixgsc(h.handle, UNMAKE_GP, &ug); made = 0; } if (rcmfd >= 0) { close(rcmfd); rcmfd = -1; } } void mga_out(int reg, unsigned int v) { *(volatile unsigned int *)(mga_base + reg) = v; eieio(); } unsigned int mga_in(int reg) { unsigned int v = *(volatile unsigned int *)(mga_base + reg); eieio(); return v; } void mga_outb(int reg, unsigned char v) { mga_base[reg] = v; eieio(); } unsigned char mga_inb(int reg) { unsigned char v = mga_base[reg]; eieio(); return v; } int mga_fifo(int n) { long i; for (i = 0; i < 10000000L; i++) if ((int)(mga_in(FIFOSTATUS) & 0x7f) >= n) return 0; fprintf(stderr, "mga_fifo: timeout, FIFOSTATUS 0x%08x\n", mga_in(FIFOSTATUS)); return -1; } int mga_idle(void) { long i; for (i = 0; i < 20000000L; i++) if (!(mga_in(STATUS) & 0x10000)) return 0; fprintf(stderr, "mga_idle: timeout, STATUS 0x%08x\n", mga_in(STATUS)); return -1; } void mga_getpal(unsigned char *pal) { int i; mga_outb(PALRDADD, 0); for (i = 0; i < 768; i++) pal[i] = mga_inb(PALDATA); } void mga_setpal(const unsigned char *pal) { int i; mga_outb(PALWTADD, 0); for (i = 0; i < 768; i++) mga_outb(PALDATA, pal[i]); } double mga_now(void) { struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec + tv.tv_usec / 1e6; }