/* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * * This file is part of the 86Box distribution. * * AGP Graphics Address Remapping Table remapping emulation. * * * * Authors: RichardG, * * Copyright 2021 RichardG. */ #include #include #include #include #include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> typedef struct { int aperture_enable; uint32_t aperture_base, aperture_size, aperture_mask, gart_base; mem_mapping_t aperture_mapping; } agpgart_t; #define ENABLE_AGPGART_LOG 1 #ifdef ENABLE_AGPGART_LOG int agpgart_do_log = ENABLE_AGPGART_LOG; static void agpgart_log(const char *fmt, ...) { va_list ap; if (agpgart_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else #define agpgart_log(fmt, ...) #endif void agpgart_set_aperture(void *handle, uint32_t base, uint32_t size, int enable) { agpgart_t *dev = (agpgart_t *) handle; agpgart_log("AGP GART: set_aperture(%08X, %d, %d)\n", base, size, enable); /* Disable old aperture mapping. */ mem_mapping_disable(&dev->aperture_mapping); /* Set new aperture base address, size and mask. */ dev->aperture_base = base; dev->aperture_size = size; dev->aperture_mask = size - 1; /* Enable new aperture mapping if requested. */ if (dev->aperture_base && dev->aperture_size && dev->aperture_enable) { mem_mapping_set_addr(&dev->aperture_mapping, dev->aperture_base, dev->aperture_size); mem_mapping_enable(&dev->aperture_mapping); } } void agpgart_set_gart(void *handle, uint32_t base) { agpgart_t *dev = (agpgart_t *) handle; agpgart_log("AGP GART: set_gart(%08X)\n", base); /* Set GART base address. */ dev->gart_base = base; } static uint32_t agpgart_translate(uint32_t addr, agpgart_t *dev) { /* Extract the bits we care about. */ addr &= dev->aperture_mask; /* Get the GART pointer for this page. */ register uint32_t gart_ptr = mem_readl_phys(dev->gart_base + ((addr >> 10) & 0xfffffffc)) & 0xfffff000; /* Return remapped address with the page offset. */ return gart_ptr + (addr & 0x00000fff); } static uint8_t agpgart_aperture_readb(uint32_t addr, void *priv) { agpgart_t *dev = (agpgart_t *) priv; return mem_readb_phys(agpgart_translate(addr, dev)); } static uint16_t agpgart_aperture_readw(uint32_t addr, void *priv) { agpgart_t *dev = (agpgart_t *) priv; return mem_readw_phys(agpgart_translate(addr, dev)); } static uint32_t agpgart_aperture_readl(uint32_t addr, void *priv) { agpgart_t *dev = (agpgart_t *) priv; return mem_readl_phys(agpgart_translate(addr, dev)); } static void agpgart_aperture_writeb(uint32_t addr, uint8_t val, void *priv) { agpgart_t *dev = (agpgart_t *) priv; mem_writeb_phys(agpgart_translate(addr, dev), val); } static void agpgart_aperture_writew(uint32_t addr, uint16_t val, void *priv) { agpgart_t *dev = (agpgart_t *) priv; mem_writew_phys(agpgart_translate(addr, dev), val); } static void agpgart_aperture_writel(uint32_t addr, uint32_t val, void *priv) { agpgart_t *dev = (agpgart_t *) priv; mem_writel_phys(agpgart_translate(addr, dev), val); } static void * agpgart_init(const device_t *info) { agpgart_t *dev = malloc(sizeof(agpgart_t)); memset(dev, 0, sizeof(agpgart_t)); agpgart_log("AGP GART: init()\n"); /* Create aperture mapping. */ mem_mapping_add(&dev->aperture_mapping, 0, 0, agpgart_aperture_readb, agpgart_aperture_readw, agpgart_aperture_readl, agpgart_aperture_writeb, agpgart_aperture_writew, agpgart_aperture_writel, NULL, MEM_MAPPING_EXTERNAL, dev); return dev; } static void agpgart_close(void *priv) { agpgart_t *dev = (agpgart_t *) priv; agpgart_log("AGP GART: close()\n"); /* Disable aperture. */ mem_mapping_disable(&dev->aperture_mapping); free(dev); } const device_t agpgart_device = { "AGP Graphics Address Remapping Table", DEVICE_PCI, 0, agpgart_init, agpgart_close, NULL, { NULL }, NULL, NULL, NULL };