/* mode setting sequence done by cirrus drm driver --- set mode ( 1024 x 768 @ 24 bpp ) --- vga_cirrus_write_io addr 0x3d4, val 0x11 vga_cirrus_write_io addr 0x3d5, val 0x20 vga_cirrus_write_io addr 0x3d4, val 0x0 vga_cirrus_write_io addr 0x3d5, val 0xa3 vga_cirrus_write_io addr 0x3d4, val 0x1 vga_cirrus_write_io addr 0x3d5, val 0x7f vga_cirrus_write_io addr 0x3d4, val 0x4 vga_cirrus_write_io addr 0x3d5, val 0x84 vga_cirrus_write_io addr 0x3d4, val 0x5 vga_cirrus_write_io addr 0x3d5, val 0x95 vga_cirrus_write_io addr 0x3d4, val 0x6 vga_cirrus_write_io addr 0x3d5, val 0x24 vga_cirrus_write_io addr 0x3d4, val 0x12 vga_cirrus_write_io addr 0x3d5, val 0xff vga_cirrus_write_io addr 0x3d4, val 0x9 vga_cirrus_write_io addr 0x3d5, val 0x60 vga_cirrus_write_io addr 0x3d4, val 0x7 vga_cirrus_write_io addr 0x3d5, val 0x79 vga_cirrus_write_io addr 0x3d4, val 0x1a vga_cirrus_write_io addr 0x3d5, val 0xe0 vga_cirrus_write_io addr 0x3d4, val 0x17 vga_cirrus_write_io addr 0x3d5, val 0x3 vga_cirrus_write_io addr 0x3c4, val 0x7 vga_cirrus_read_io addr 0x3c5, val 0x0 vga_cirrus_write_io addr 0x3c4, val 0x7 vga_cirrus_write_io addr 0x3c5, val 0x15 vga_cirrus_write_io addr 0x3d4, val 0x13 vga_cirrus_write_io addr 0x3d5, val 0x80 vga_cirrus_write_io addr 0x3d4, val 0x1b vga_cirrus_write_io addr 0x3d5, val 0x32 vga_cirrus_write_io addr 0x3ce, val 0x5 vga_cirrus_write_io addr 0x3cf, val 0x40 vga_cirrus_write_io addr 0x3ce, val 0x6 vga_cirrus_write_io addr 0x3cf, val 0x1 vga_cirrus_read_io addr 0x3c6, val 0xff vga_cirrus_read_io addr 0x3c6, val 0xff vga_cirrus_read_io addr 0x3c6, val 0xff vga_cirrus_read_io addr 0x3c6, val 0xff vga_cirrus_write_io addr 0x3c6, val 0xc5 --- set base address ( 0 ) --- vga_cirrus_write_io addr 0x3d4, val 0xc vga_cirrus_write_io addr 0x3d5, val 0x0 vga_cirrus_write_io addr 0x3d4, val 0xd vga_cirrus_write_io addr 0x3d5, val 0x0 vga_cirrus_write_io addr 0x3d4, val 0x1b vga_cirrus_read_io addr 0x3d5, val 0x32 vga_cirrus_write_io addr 0x3d4, val 0x1b vga_cirrus_write_io addr 0x3d5, val 0x32 vga_cirrus_write_io addr 0x3d4, val 0x1d vga_cirrus_read_io addr 0x3d5, val 0x0 vga_cirrus_write_io addr 0x3d4, val 0x1d vga_cirrus_write_io addr 0x3d5, val 0x0 -- unblank -- vga_cirrus_write_io addr 0x3c0, val 0x20 */ #include #include #include #include #include #include #include #include #include #include struct pci_access *pci; struct pci_dev *dev; static void find_device(unsigned int vendor, unsigned int device) { struct pci_filter filter; struct pci_dev *d; pci_scan_bus(pci); pci_filter_init(pci, &filter); filter.vendor = vendor; filter.device = device; for (d = pci->devices; d != NULL; d = d->next) { if (!pci_filter_match(&filter, d)) continue; dev = d; return; } return; } #define VGA_OFFSET (-0x3c0) #define BLT_OFFSET (0x100) #define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword #define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword #define CIRRUS_MMIO_BLTWIDTH 0x08 // word #define CIRRUS_MMIO_BLTHEIGHT 0x0a // word #define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word #define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word #define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword #define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword #define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte #define CIRRUS_MMIO_BLTMODE 0x18 // byte #define CIRRUS_MMIO_BLTROP 0x1a // byte #define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte #define CIRRUS_MMIO_BLTSTATUS 0x40 // byte #define CIRRUS_BLT_BUSY 0x01 #define CIRRUS_BLT_START 0x02 #define CIRRUS_BLT_RESET 0x04 #define CIRRUS_BLTMODE_BACKWARDS 0x01 #define CIRRUS_BLTMODE_MEMSYSDEST 0x02 #define CIRRUS_BLTMODE_MEMSYSSRC 0x04 #define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 #define CIRRUS_BLTMODE_PATTERNCOPY 0x40 #define CIRRUS_BLTMODE_COLOREXPAND 0x80 #define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 #define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 #define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 #define CIRRUS_ROP_0 0x00 #define CIRRUS_ROP_SRC_AND_DST 0x05 #define CIRRUS_ROP_NOP 0x06 #define CIRRUS_ROP_SRC_AND_NOTDST 0x09 #define CIRRUS_ROP_NOTDST 0x0b #define CIRRUS_ROP_SRC 0x0d #define CIRRUS_ROP_1 0x0e #define CIRRUS_ROP_NOTSRC_AND_DST 0x50 #define CIRRUS_ROP_SRC_XOR_DST 0x59 #define CIRRUS_ROP_SRC_OR_DST 0x6d #define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 #define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 #define CIRRUS_ROP_SRC_OR_NOTDST 0xad #define CIRRUS_ROP_NOTSRC 0xd0 #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda int main(int argc, char *argv[]) { char mmiofile[128]; int mmiofd; volatile uint8_t *mmio; pci = pci_alloc(); if (!pci) { fprintf(stderr, "libpci alloc failed\n"); exit(1); } pci_init(pci); find_device(0x1013, 0x00b8); if (!dev) { fprintf(stderr, "cirrus not found\n"); exit(1); } fprintf(stderr, "cirrus found at %02x:%02x.%x, mmio @ 0x%08x\n", dev->bus, dev->dev, dev->func, (uint32_t) dev->base_addr[1]); snprintf(mmiofile, sizeof(mmiofile), "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource1", dev->domain, dev->bus, dev->dev, dev->func); mmiofd = open(mmiofile, O_RDWR); if (mmiofd < 0) { fprintf(stderr, "open %s: %s\n", mmiofile, strerror(errno)); exit(1); } mmio = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_SHARED, mmiofd, 0); if (mmio == MAP_FAILED) { fprintf(stderr, "mmap %s: %s\n", mmiofile, strerror(errno)); exit(1); } fprintf(stderr, "init ok\n"); sleep(1); fprintf(stderr, "setting mode (1024x768 @ 24bpp)\n"); /* mode */ mmio[0x3d4 + VGA_OFFSET] = 0x11; mmio[0x3d5 + VGA_OFFSET] = 0x20; mmio[0x3d4 + VGA_OFFSET] = 0x0; mmio[0x3d5 + VGA_OFFSET] = 0xa3; mmio[0x3d4 + VGA_OFFSET] = 0x1; mmio[0x3d5 + VGA_OFFSET] = 0x7f; mmio[0x3d4 + VGA_OFFSET] = 0x4; mmio[0x3d5 + VGA_OFFSET] = 0x84; mmio[0x3d4 + VGA_OFFSET] = 0x5; mmio[0x3d5 + VGA_OFFSET] = 0x95; mmio[0x3d4 + VGA_OFFSET] = 0x6; mmio[0x3d5 + VGA_OFFSET] = 0x24; mmio[0x3d4 + VGA_OFFSET] = 0x12; mmio[0x3d5 + VGA_OFFSET] = 0xff; mmio[0x3d4 + VGA_OFFSET] = 0x9; mmio[0x3d5 + VGA_OFFSET] = 0x60; mmio[0x3d4 + VGA_OFFSET] = 0x7; mmio[0x3d5 + VGA_OFFSET] = 0x79; mmio[0x3d4 + VGA_OFFSET] = 0x1a; mmio[0x3d5 + VGA_OFFSET] = 0xe0; mmio[0x3d4 + VGA_OFFSET] = 0x17; mmio[0x3d5 + VGA_OFFSET] = 0x3; mmio[0x3c4 + VGA_OFFSET] = 0x7; mmio[0x3c5 + VGA_OFFSET] = 0x15; mmio[0x3d4 + VGA_OFFSET] = 0x13; mmio[0x3d5 + VGA_OFFSET] = 0x80; mmio[0x3d4 + VGA_OFFSET] = 0x1b; mmio[0x3d5 + VGA_OFFSET] = 0x32; mmio[0x3ce + VGA_OFFSET] = 0x5; mmio[0x3cf + VGA_OFFSET] = 0x40; mmio[0x3ce + VGA_OFFSET] = 0x6; mmio[0x3cf + VGA_OFFSET] = 0x1; #if 0 mmio[0x3c6 + VGA_OFFSET]; mmio[0x3c6 + VGA_OFFSET]; mmio[0x3c6 + VGA_OFFSET]; mmio[0x3c6 + VGA_OFFSET]; mmio[0x3c6 + VGA_OFFSET] = 0xc5; #endif /* base */ mmio[0x3d4 + VGA_OFFSET] = 0xc; mmio[0x3d5 + VGA_OFFSET] = 0x0; mmio[0x3d4 + VGA_OFFSET] = 0xd; mmio[0x3d5 + VGA_OFFSET] = 0x0; mmio[0x3d4 + VGA_OFFSET] = 0x1b; mmio[0x3d5 + VGA_OFFSET] = 0x32; mmio[0x3d4 + VGA_OFFSET] = 0x1d; mmio[0x3d5 + VGA_OFFSET] = 0x0; /* dpms */ mmio[0x3d4 + VGA_OFFSET] = 0x1; mmio[0x3d5 + VGA_OFFSET] = 0x0; mmio[0x3ce + VGA_OFFSET] = 0xe; mmio[0x3cf + VGA_OFFSET] = 0x1; /* unblank */ mmio[0x3c0 + VGA_OFFSET] = 0x20; fprintf(stderr, "mode done\n"); sleep(1); fprintf(stderr, "trying invalid backwards blit\n"); mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = CIRRUS_BLT_RESET; mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = 0x00; *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTWIDTH) = 1024 * 3 - 1; *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTHEIGHT) = 1 - 1; *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTDESTPITCH) = 1024 * 3; *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTSRCPITCH) = 1024 * 3; *(uint32_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTDESTADDR) = 0; *(uint32_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTSRCADDR) = 1024 * 3; mmio[BLT_OFFSET + CIRRUS_MMIO_BLTMODE] = CIRRUS_BLTMODE_PIXELWIDTH24 | CIRRUS_BLTMODE_BACKWARDS; mmio[BLT_OFFSET + CIRRUS_MMIO_BLTROP] = CIRRUS_ROP_SRC; mmio[BLT_OFFSET + CIRRUS_MMIO_BLTMODEEXT] = 0; mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = CIRRUS_BLT_START; fprintf(stderr, "blit done\n"); sleep(1); exit(0); }