main: write to pci config registers
This commit is contained in:
parent
b903bc3967
commit
60ccbef127
@ -1,5 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
from generate import renderer
|
from generate import renderer
|
||||||
|
import string
|
||||||
|
|
||||||
with open(sys.argv[1], 'r') as f:
|
with open(sys.argv[1], 'r') as f:
|
||||||
buf = f.read()
|
buf = f.read()
|
||||||
@ -54,6 +55,18 @@ def reg_type(length):
|
|||||||
return "reg32"
|
return "reg32"
|
||||||
assert False, length
|
assert False, length
|
||||||
|
|
||||||
|
|
||||||
|
def format_name(s):
|
||||||
|
def do():
|
||||||
|
prev_lower = False
|
||||||
|
for i, c in enumerate(s):
|
||||||
|
if prev_lower and i > 0 and c in string.ascii_uppercase:
|
||||||
|
yield "_"
|
||||||
|
prev_lower = c in string.ascii_lowercase
|
||||||
|
yield c.upper()
|
||||||
|
|
||||||
|
return "".join(do())
|
||||||
|
|
||||||
def render_struct(buf):
|
def render_struct(buf):
|
||||||
next_address = 0
|
next_address = 0
|
||||||
reserved_ix = 0
|
reserved_ix = 0
|
||||||
@ -65,14 +78,19 @@ def render_struct(buf):
|
|||||||
reserved_ix += 1
|
reserved_ix += 1
|
||||||
length = bits_length(bits)
|
length = bits_length(bits)
|
||||||
arr = "" if length != 3 else "[3]"
|
arr = "" if length != 3 else "[3]"
|
||||||
yield f"{reg_type(length)} {register_name}{arr};"
|
yield f"{reg_type(length)} {format_name(register_name)}{arr};"
|
||||||
next_address = addr + length
|
next_address = addr + length
|
||||||
yield "};"
|
yield "};"
|
||||||
yield ""
|
yield ""
|
||||||
for register_name, addr, bits, description in lines:
|
for register_name, addr, bits, description in lines:
|
||||||
length = bits_length(bits)
|
length = bits_length(bits)
|
||||||
arr = "" if length != 3 else "[0]"
|
arr = "" if length != 3 else "[0]"
|
||||||
yield f"static_assert((offsetof (struct voodoo2_config, {register_name}{arr})) == 0x{addr:02x});"
|
yield f"static_assert((offsetof (struct voodoo2_config, {format_name(register_name)}{arr})) == 0x{addr:02x});"
|
||||||
|
|
||||||
|
def render_macros(buf):
|
||||||
|
lines = list(parse_lines(buf))
|
||||||
|
for register_name, addr, bits, description in lines:
|
||||||
|
yield f"#define PCI__CONFIG__{format_name(register_name)} (0x{addr:02x})"
|
||||||
|
|
||||||
def render_all(buf):
|
def render_all(buf):
|
||||||
yield "#pragma once"
|
yield "#pragma once"
|
||||||
@ -82,7 +100,7 @@ def render_all(buf):
|
|||||||
yield ""
|
yield ""
|
||||||
yield '#include "reg.h"'
|
yield '#include "reg.h"'
|
||||||
yield ""
|
yield ""
|
||||||
yield from render_struct(buf)
|
yield from render_macros(buf)
|
||||||
yield ""
|
yield ""
|
||||||
yield "typedef struct voodoo2_config voodoo2_config;"
|
yield "typedef struct voodoo2_config voodoo2_config;"
|
||||||
|
|
||||||
|
@ -18,3 +18,13 @@
|
|||||||
#define DAC__PLL_PARAMETER__CLK1_fA_PLL 0x0a
|
#define DAC__PLL_PARAMETER__CLK1_fA_PLL 0x0a
|
||||||
#define DAC__PLL_PARAMETER__CLK1_fB_PLL 0x0b
|
#define DAC__PLL_PARAMETER__CLK1_fB_PLL 0x0b
|
||||||
#define DAC__PLL_PARAMETER__PLL_CONTROL 0x0e
|
#define DAC__PLL_PARAMETER__PLL_CONTROL 0x0e
|
||||||
|
|
||||||
|
#define DAC__COMMAND__COLOR_MODE__MULTIPLEXED_16BIT_PSUEDO_COLOR_WITH_PALETTE (0b0001 << 4) // mode 4
|
||||||
|
#define DAC__COMMAND__COLOR_MODE__15BIT_DIRECT_COLOR_WITH_BYPASS (0b0011 << 4) // mode 5
|
||||||
|
#define DAC__COMMAND__COLOR_MODE__16BIT_DIRECT_COLOR_WITH_BYPASS (0b0101 << 4) // mode 6
|
||||||
|
#define DAC__COMMAND__COLOR_MODE__24BIT_TRUE_COLOR_WITH_BYPASS (0b0111 << 4) // mode 7
|
||||||
|
#define DAC__COMMAND__COLOR_MODE__24BIT_PACKED_TRUE_COLOR_WITH_BYPASS (0b1011 << 4) // mode 8
|
||||||
|
|
||||||
|
#define DAC__PLL_CONTROL__CLK0_SELECT(n) (((n) & 0b111) << 0)
|
||||||
|
#define DAC__PLL_CONTROL__CLK1_SELECT(n) (((n) & 0b1) << 4)
|
||||||
|
#define DAC__PLL_CONTROL__ENABLE_INTERNAL_CLOCK_SELECT (1 << 5)
|
191
main.c
191
main.c
@ -10,52 +10,25 @@
|
|||||||
#include "voodoo2.h"
|
#include "voodoo2.h"
|
||||||
#include "voodoo2_bits.h"
|
#include "voodoo2_bits.h"
|
||||||
#include "voodoo2_config.h"
|
#include "voodoo2_config.h"
|
||||||
#include "dac.h"
|
#include "voodoo2_config_bits.h"
|
||||||
|
#include "ics5342.h"
|
||||||
|
|
||||||
struct name_int {
|
static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2)
|
||||||
const char * name;
|
|
||||||
uint32_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
void print_registers(struct voodoo2_reg * reg)
|
|
||||||
{
|
|
||||||
const struct name_int registers[] = {
|
|
||||||
{"status", reg->status},
|
|
||||||
{"fbiInit0", reg->fbiInit0},
|
|
||||||
{"fbiInit1", reg->fbiInit1},
|
|
||||||
{"fbiInit2", reg->fbiInit2},
|
|
||||||
{"fbiInit3", reg->fbiInit3},
|
|
||||||
{"fbiInit4", reg->fbiInit4},
|
|
||||||
{"fbiInit5", reg->fbiInit5},
|
|
||||||
{"fbiInit6", reg->fbiInit6},
|
|
||||||
{"fbiInit7", reg->fbiInit7},
|
|
||||||
//
|
|
||||||
{"backPorch", reg->backPorch},
|
|
||||||
{"videoDimensions", reg->videoDimensions},
|
|
||||||
{"hSync", reg->hSync},
|
|
||||||
{"vSync", reg->vSync},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < (sizeof (registers)) / (sizeof (registers[0])); i++) {
|
|
||||||
printf("%s %08x\n", registers[i].name, registers[i].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void wait_graphics_busy(voodoo2_reg * voodoo2)
|
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int i = 0; i < 4096; i++) {
|
for (int i = 0; i < 4096; i++) {
|
||||||
if (voodoo2->status & STATUS__GRAPHICS_BUSY) {
|
if (voodoo2->status & STATUS__GRAPHICS_BUSY) {
|
||||||
cnt += 1;
|
|
||||||
} else {
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
} else {
|
||||||
|
cnt += 1;
|
||||||
}
|
}
|
||||||
if (cnt >= 3)
|
if (cnt >= 3)
|
||||||
return;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!"busy wait timeout");
|
#define wait_graphics_busy(voodoo2) assert(_wait_graphics_busy(voodoo2));
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dac_data_read(voodoo2_reg * voodoo2,
|
static inline void dac_data_read(voodoo2_reg * voodoo2,
|
||||||
int data,
|
int data,
|
||||||
@ -128,40 +101,132 @@ static inline mn_t dac_read_pll_16(voodoo2_reg * voodoo2,
|
|||||||
return (mn_t){ m, n };
|
return (mn_t){ m, n };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t read_fd_u8(int fd, uint32_t offset)
|
||||||
|
{
|
||||||
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
||||||
|
assert(ret == offset);
|
||||||
|
uint8_t value;
|
||||||
|
ssize_t len = read(fd, &value, 1);
|
||||||
|
assert(len == 1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t read_fd_u16(int fd, uint32_t offset)
|
||||||
|
{
|
||||||
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
||||||
|
assert(ret == offset);
|
||||||
|
uint16_t value;
|
||||||
|
ssize_t len = read(fd, &value, 2);
|
||||||
|
assert(len == 2);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_fd_u8(int fd, uint32_t offset, uint8_t value)
|
||||||
|
{
|
||||||
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
||||||
|
assert(ret == offset);
|
||||||
|
ssize_t len = write(fd, &value, 1);
|
||||||
|
assert(len == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_fd_u32(int fd, uint32_t offset, uint32_t value)
|
||||||
|
{
|
||||||
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
||||||
|
assert(ret == offset);
|
||||||
|
ssize_t len = write(fd, &value, 4);
|
||||||
|
assert(len == 4);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const char * config_path = "/sys/bus/pci/devices/0000:02:0a.0/config";
|
const char * config_path = "/sys/bus/pci/devices/0000:02:0a.0/config";
|
||||||
int fd = open(config_path, O_RDWR | O_SYNC);
|
int config_fd = open(config_path, O_RDWR | O_SYNC);
|
||||||
assert(fd >= 0);
|
assert(config_fd >= 0);
|
||||||
|
|
||||||
uint32_t config_size = (sizeof (struct voodoo2_config));
|
uint16_t vendor_id = read_fd_u16(config_fd, PCI__CONFIG__VENDOR_ID);
|
||||||
|
uint16_t device_id = read_fd_u16(config_fd, PCI__CONFIG__DEVICE_ID);
|
||||||
|
printf("Vendor ID: %04x\n", vendor_id);
|
||||||
|
printf("Device ID: %04x\n", device_id);
|
||||||
|
assert(vendor_id == 0x121a);
|
||||||
|
assert(device_id == 0x0002);
|
||||||
|
|
||||||
void * config_base = mmap(0, config_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
////////////////////////////////////////////////////////////////////////
|
||||||
assert(config_base != MAP_FAILED);
|
// PCI enable
|
||||||
voodoo2_config * config = (voodoo2_config *)config_base;
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
{
|
||||||
|
const char * enable_path = "/sys/bus/pci/devices/0000:02:0a.0/enable";
|
||||||
|
int enable_fd = open(enable_path, O_RDWR | O_SYNC);
|
||||||
|
assert(enable_fd >= 0);
|
||||||
|
|
||||||
printf("Vendor ID: %04x\n", config->Vendor_ID);
|
if (read_fd_u8(enable_fd, 0) == '0') {
|
||||||
printf("Device ID: %04x\n", config->Device_ID);
|
write_fd_u8(enable_fd, 0, '1'); // enable
|
||||||
|
assert(read_fd_u8(enable_fd, 0) != '0');
|
||||||
|
}
|
||||||
|
close(enable_fd);
|
||||||
|
}
|
||||||
|
|
||||||
munmap(config_base, config_size);
|
////////////////////////////////////////////////////////////////////////
|
||||||
close(fd);
|
// PCI resource0
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
const char * resource0_path = "/sys/bus/pci/devices/0000:02:0a.0/resource0";
|
||||||
|
int resource0_fd = open(resource0_path, O_RDWR | O_SYNC);
|
||||||
|
assert(resource0_fd >= 0);
|
||||||
|
|
||||||
|
uint32_t resource0_size = 16 * 1024 * 1024;
|
||||||
|
void * resource0_base = mmap(0, resource0_size, PROT_READ | PROT_WRITE, MAP_SHARED, resource0_fd, 0);
|
||||||
|
assert(resource0_base != MAP_FAILED);
|
||||||
|
|
||||||
|
voodoo2_reg * voodoo2 = (voodoo2_reg *)resource0_base;
|
||||||
|
|
||||||
|
int init_enable;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// reset
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
init_enable
|
||||||
|
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS;
|
||||||
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
||||||
|
//wait_graphics_busy(voodoo2);
|
||||||
|
|
||||||
|
voodoo2->fbiInit0
|
||||||
|
= FBIINIT0__CHUCK_GRAPHICS_RESET
|
||||||
|
| FBIINIT0__CHUCK_FIFO_RESET
|
||||||
|
;
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
|
||||||
|
voodoo2->fbiInit1
|
||||||
|
= FBIINIT1__VIDEO_TIMING_RESET
|
||||||
|
;
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
|
||||||
|
voodoo2->fbiInit2
|
||||||
|
= 0; // disable DRAM refresh
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// DAC initialization
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
init_enable
|
||||||
|
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS
|
||||||
|
| INIT_ENABLE__REMAP_FBIINIT2_FBIINIT3_TO_DACREAD_VIDEOCHECKSUM;
|
||||||
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
|
||||||
|
int command = DAC__COMMAND__COLOR_MODE__16BIT_DIRECT_COLOR_WITH_BYPASS;
|
||||||
|
dac_data_write(voodoo2, command, DAC__RS__COMMAND);
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
dac_data_read(voodoo2, command, DAC__RS__COMMAND);
|
||||||
|
wait_graphics_busy(voodoo2);
|
||||||
|
int command_read = voodoo2->fbiInit2 & 0xff;
|
||||||
|
printf("dac read: DAC__RS__COMMAND: m: %02x\n", command_read);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// cleanup
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
close(config_fd);
|
||||||
|
close(resource0_fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
const char * filename = "/sys/bus/pci/devices/0000:02:0a.0/resource0";
|
|
||||||
|
|
||||||
int fd = open(filename, O_RDWR | O_SYNC);
|
|
||||||
assert(fd >= 0);
|
|
||||||
|
|
||||||
uint32_t map_size = 0x4000;
|
|
||||||
|
|
||||||
void * map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
assert(map_base != MAP_FAILED);
|
|
||||||
|
|
||||||
struct voodoo2_reg * reg = (struct voodoo2_reg *)map_base;
|
|
||||||
print_registers(reg);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
@ -5,53 +5,27 @@
|
|||||||
|
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
|
|
||||||
struct voodoo2_config {
|
#define PCI__CONFIG__VENDOR_ID (0x00)
|
||||||
reg16 Vendor_ID;
|
#define PCI__CONFIG__DEVICE_ID (0x02)
|
||||||
reg16 Device_ID;
|
#define PCI__CONFIG__COMMAND (0x04)
|
||||||
reg16 Command;
|
#define PCI__CONFIG__STATUS (0x06)
|
||||||
reg16 Status;
|
#define PCI__CONFIG__REVISION_ID (0x08)
|
||||||
reg8 Revision_ID;
|
#define PCI__CONFIG__CLASS_CODE (0x09)
|
||||||
reg8 Class_code[3];
|
#define PCI__CONFIG__CACHE_LINE_SIZE (0x0c)
|
||||||
reg8 Cache_line_size;
|
#define PCI__CONFIG__LATENCY_TIMER (0x0d)
|
||||||
reg8 Latency_timer;
|
#define PCI__CONFIG__HEADER_TYPE (0x0e)
|
||||||
reg8 Header_type;
|
#define PCI__CONFIG__BIST (0x0f)
|
||||||
reg8 BIST;
|
#define PCI__CONFIG__MEM_BASE_ADDR (0x10)
|
||||||
reg32 memBaseAddr;
|
#define PCI__CONFIG__INTERRUPT_LINE (0x3c)
|
||||||
reg8 _reserved0[40];
|
#define PCI__CONFIG__INTERRUPT_PIN (0x3d)
|
||||||
reg8 Interrupt_line;
|
#define PCI__CONFIG__MIN_GNT (0x3e)
|
||||||
reg8 Interrupt_pin;
|
#define PCI__CONFIG__MAX_LAT (0x3f)
|
||||||
reg8 Min_gnt;
|
#define PCI__CONFIG__INIT_ENABLE (0x40)
|
||||||
reg8 Max_lat;
|
#define PCI__CONFIG__BUS_SNOOP0 (0x44)
|
||||||
reg32 initEnable;
|
#define PCI__CONFIG__BUS_SNOOP1 (0x48)
|
||||||
reg32 busSnoop0;
|
#define PCI__CONFIG__CFG_STATUS (0x4c)
|
||||||
reg32 busSnoop1;
|
#define PCI__CONFIG__CFG_SCRATCH (0x50)
|
||||||
reg32 cfgStatus;
|
#define PCI__CONFIG__SI_PROCESS (0x54)
|
||||||
reg32 cfgScratch;
|
|
||||||
reg32 siProcess;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Vendor_ID)) == 0x00);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Device_ID)) == 0x02);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Command)) == 0x04);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Status)) == 0x06);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Revision_ID)) == 0x08);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Class_code[0])) == 0x09);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Cache_line_size)) == 0x0c);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Latency_timer)) == 0x0d);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Header_type)) == 0x0e);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, BIST)) == 0x0f);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, memBaseAddr)) == 0x10);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Interrupt_line)) == 0x3c);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Interrupt_pin)) == 0x3d);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Min_gnt)) == 0x3e);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, Max_lat)) == 0x3f);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, initEnable)) == 0x40);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, busSnoop0)) == 0x44);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, busSnoop1)) == 0x48);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, cfgStatus)) == 0x4c);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, cfgScratch)) == 0x50);
|
|
||||||
static_assert((offsetof (struct voodoo2_config, siProcess)) == 0x54);
|
|
||||||
|
|
||||||
typedef struct voodoo2_config voodoo2_config;
|
typedef struct voodoo2_config voodoo2_config;
|
||||||
|
|
||||||
|
5
voodoo2_config_bits.h
Normal file
5
voodoo2_config_bits.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS (1 << 0)
|
||||||
|
#define INIT_ENABLE__ENABLE_WRITES_TO_PCI_FIFO (1 << 1)
|
||||||
|
#define INIT_ENABLE__REMAP_FBIINIT2_FBIINIT3_TO_DACREAD_VIDEOCHECKSUM (1 << 2)
|
Loading…
x
Reference in New Issue
Block a user