/* Record register writes */ #include #include #include #include "local.h" /* before anything else */ #include "tester.h" #include "test_record.h" /* Use a sorted single linked list for simplicity. Not fast, but that shouldn't matter. */ typedef struct _RecordEntry RecordEntry, *RecordEntryPtr; struct _RecordEntry { CARD32 addr; CARD32 data; RecordEntryPtr next; int count; }; /* -------- Zones -------- */ #define MAX_ZONE 30 #define END_ADDR 0xffffffff char* test_zones[] = {"mmio", "port", "<2>", "crt", "crt2", "seq", "seq2", "gr", "gr2", "ar", "ar2", "dac", "dac2", "<13>", "<14>", "nz", "%ch1", "%ch2", "%cx1", "%cx2", "%ph1", "%ph2"}; RecordSwitch test_nv_switches [] = { {ZONE_GR, 0, {ZONE_GR, -1, -1, ZONE_GR2}}, {ZONE_SEQ, 0, {ZONE_SEQ, -1, -1, ZONE_SEQ2}}, {-1, -1} }; RecordAccess test_nv_access [] = { {ZONE_MMIO, 0x0c0000, 0x0c0fff, BIT8}, /* PRMVIO */ {ZONE_MMIO, 0x601000, 0x601fff, BIT8}, /* PRMCIO */ {ZONE_MMIO, 0x603000, 0x603fff, BIT8}, /* PRMCIO2 */ {ZONE_MMIO, 0x681000, 0x681fff, BIT8}, /* PRMDIO */ {ZONE_MMIO, 0x683000, 0x683fff, BIT8}, /* PRMDIO2 */ {ZONE_MMIO, 0x000000, 0x7fffff, BIT32}, /* rest */ {ZONE_CRT, 0x00, 0xff, BIT8}, {ZONE_CRT2, 0x00, 0xff, BIT8}, {ZONE_AR, 0x00, 0x1f, BIT8}, {ZONE_AR2, 0x00, 0x1f, BIT8}, {ZONE_GR, 0x00, 0x0f, BIT8}, {ZONE_GR2, 0x00, 0x0f, BIT8}, {ZONE_SEQ, 0x00, 0x0f, BIT8}, {ZONE_SEQ2, 0x00, 0x0f, BIT8}, {ZONE_CH1, 0x00, 0x3f, BIT8}, {ZONE_CH2, 0x00, 0x7f, BIT8}, {ZONE_CX1, 0x00, 0xff, BIT8}, {ZONE_CX2, 0x00, 0xff, BIT8}, {ZONE_PH1, 0x00, 0xff, BIT8}, {ZONE_PH2, 0x00, 0xff, BIT8}, {0, 0, 0, BIT_NONE} }; RecordAccess test_tdfx_access [] = { {ZONE_MMIO, 0x00, 0xff, BIT32}, {ZONE_PORT, 0x3b4, 0x3b5, BIT8}, {ZONE_PORT, 0x3d4, 0x3d5, BIT8}, {ZONE_PORT, 0x3c0, 0x3ca, BIT8}, {ZONE_PORT, 0x3ce, 0x3cf, BIT8}, {ZONE_PORT, 0x3ba, 0x3ba, BIT8}, {ZONE_PORT, 0x3da, 0x3da, BIT8}, {ZONE_PORT, 0x46e8, 0x46e8, BIT8}, {ZONE_CRT, 0x00, 0x24, BIT8}, {ZONE_SEQ, 0x00, 0x04, BIT8}, {ZONE_GR, 0x00, 0x08, BIT8}, {ZONE_AR, 0x00, 0x14, BIT8}, {ZONE_CH1, 0x00, 0x3f, BIT8}, {ZONE_CH2, 0x00, 0x7f, BIT8}, {ZONE_CX1, 0x00, 0xff, BIT8}, {ZONE_CX2, 0x00, 0xff, BIT8}, {ZONE_PH1, 0x00, 0xff, BIT8}, {ZONE_PH2, 0x00, 0xff, BIT8}, {0, 0, 0, BIT_NONE} }; RecordAccess test_intel_access [] = { {ZONE_MMIO, 0x00000, 0x00fff, BIT8}, {ZONE_MMIO, 0x01000, 0x7ffff, BIT32}, {ZONE_CRT, 0x00, 0xff, BIT8}, {ZONE_SEQ, 0x00, 0x07, BIT8}, {ZONE_GR, 0x00, 0x1f, BIT8}, {ZONE_AR, 0x00, 0x14, BIT8}, {ZONE_CH1, 0x00, 0x3f, BIT8}, {ZONE_CH2, 0x00, 0x7f, BIT8}, {ZONE_CX1, 0x00, 0xff, BIT8}, {ZONE_CX2, 0x00, 0xff, BIT8}, {ZONE_PH1, 0x00, 0xff, BIT8}, {ZONE_PH2, 0x00, 0xff, BIT8}, {0, 0, 0, BIT_NONE} }; /* -------- Zone: Specials -------- */ RecordSpecial test_nv_special_main [] = { {0x6013d4, 0x6013d4, SPEC_INDEX, ZONE_CRT}, /* crt */ {0x6013d5, 0x6013d5, SPEC_DATA, ZONE_CRT}, {0x6033d4, 0x6033d4, SPEC_INDEX, ZONE_CRT2}, /* crt2 */ {0x6033d5, 0x6033d5, SPEC_DATA, ZONE_CRT2}, {0x0c03c4, 0x0c03c4, SPEC_INDEX, ZONE_SEQ}, /* seq */ {0x0c03c5, 0x0c03c5, SPEC_DATA, ZONE_SEQ}, {0x0c03ce, 0x0c03ce, SPEC_INDEX, ZONE_GR}, /* gr */ {0x0c03cf, 0x0c03cf, SPEC_DATA, ZONE_GR}, {0x00d220, 0x00d220, SPEC_INDEX, ZONE_NZ}, /* nz */ {0x00d224, 0x00d224, SPEC_DATA, ZONE_NZ}, {0x600808, 0x600808, SPEC_INCR, ZONE_MMIO}, /* PCRTC_RASTER */ {0x602808, 0x602808, SPEC_INCR, ZONE_MMIO}, /* PCRTC2_RASTER */ {0x0c03c2, 0x0c03c2, SPEC_FWD_W, 0x0c03cc}, /* W: misc, R: input stat */ {0x6013da, 0x6013da, SPEC_RESET_R, ZONE_AR}, /* AR reset */ {0x6013c0, 0x6013c0, SPEC_VGA_AR, ZONE_AR}, /* AR both index/data */ {0x6033da, 0x6033da, SPEC_RESET_R, ZONE_AR2}, /* AR reset */ {0x6033c0, 0x6033c0, SPEC_VGA_AR, ZONE_AR2}, /* AR both index/data */ {0, 0, SPEC_NONE} }; RecordSpecial test_nv_special_crt [] = { {0x36, 0x37, SPEC_NOLOG}, /* Primary I2C */ {0x3E, 0x3f, SPEC_NOLOG}, /* Secondary I2C */ {0x44, 0x44, SPEC_SWITCH, 0}, /* SEQ and AR switch */ {0x50, 0x51, SPEC_NOLOG}, /* Tertiary I2C */ {0, 0, SPEC_NONE} }; RecordSpecial test_tdfx_special_port [] = { {0x3d4, 0x3d4, SPEC_INDEX, ZONE_CRT}, /* crt */ {0x3d5, 0x3d5, SPEC_DATA, ZONE_CRT}, {0x3b4, 0x3b4, SPEC_INDEX, ZONE_CRT}, /* crt */ {0x3b5, 0x3b5, SPEC_DATA, ZONE_CRT}, }; RecordSpecial test_intel_special_main [] = { {0x003d4, 0x003d4, SPEC_INDEX, ZONE_CRT}, /* crt */ {0x003d5, 0x003d5, SPEC_DATA, ZONE_CRT}, {0x003b4, 0x003b4, SPEC_INDEX, ZONE_CRT}, /* crt */ {0x003b5, 0x003b5, SPEC_DATA, ZONE_CRT}, {0x003c4, 0x003c4, SPEC_INDEX, ZONE_SEQ}, {0x003c5, 0x003c5, SPEC_DATA, ZONE_SEQ}, {0x003ce, 0x003ce, SPEC_INDEX, ZONE_GR}, {0x003cf, 0x003cf, SPEC_DATA, ZONE_GR}, {0x003ba, 0x003ba, SPEC_RESET_R, ZONE_AR}, /* AR reset */ {0x003da, 0x003da, SPEC_RESET_R, ZONE_AR}, /* AR reset */ {0x003c0, 0x003c0, SPEC_VGA_AR, ZONE_AR}, /* AR both index/data */ {0x05010, 0x05020, SPEC_NOLOG}, /* GPIO registers */ {0, 0, SPEC_NONE} }; /* -------- */ RecordSpecial test_special_ch1 [] = { {0x10, 0x10, SPEC_READONLY}, /* CDR Connection detect */ {0x25, 0x25, SPEC_READONLY}, /* VID version id */ {0, 0, SPEC_NONE} }; RecordSpecial test_special_ch2 [] = { {0x20, 0x20, SPEC_READONLY}, /* CD Connection detect */ {0x4a, 0x4b, SPEC_READONLY}, /* VID/DID version/device id */ {0, 0, SPEC_NONE} }; RecordSpecial test_special_cx1 [] = { {0x00, 0x05, SPEC_READONLY}, /* Status registers */ {0, 0, SPEC_NONE} }; RecordSpecial test_special_cx2 [] = { {0x00, 0x07, SPEC_READONLY}, /* Status registers */ {0, 0, SPEC_NONE} }; RecordSpecial test_special_ph [] = { {0x00, 0x00, SPEC_READONLY}, /* Status byte */ {0x1b, 0x1b, SPEC_READONLY}, /* Monitor Sense Mode */ {0x1c, 0x1c, SPEC_READONLY}, /* Chip ID */ {0x80, 0x80, SPEC_READONLY}, /* FIFO Status */ {0, 0, SPEC_NONE} }; RecordSpecial* test_nv_specials [MAX_ZONE] = { /* 0 mmio */ test_nv_special_main, /* 1 port */ NULL, /* 2 ---- */ NULL, /* unused zone */ /* 3 crt */ test_nv_special_crt, /* 4 crt2 */ test_nv_special_crt, /* 5 seq */ NULL, /* 6 seq2 */ NULL, /* 7 gr */ NULL, /* 8 gr2 */ NULL, /* 9 ar */ NULL, /* 10 ar2 */ NULL, /* 11 dac */ NULL, /* 12 dac2 */ NULL, /* 13 ---- */ NULL, /* 14 ---- */ NULL, /* 15 nz */ NULL, /* 16 ch1 */ test_special_ch1, /* 17 ch2 */ test_special_ch2, /* 18 cx1 */ test_special_cx1, /* 19 cx2 */ test_special_cx2, /* 20 ph1 */ test_special_ph, /* 21 ph2 */ test_special_ph, NULL, NULL, NULL }; RecordSpecial* test_tdfx_specials [MAX_ZONE] = { /* 0 mmio */ NULL, /* test_tdfx_special_main, */ /* 1 port */ test_tdfx_special_port, /* 2 ---- */ NULL, /* unused zone */ /* 3 crt */ NULL, /* 4 crt2 */ NULL, /* 5 seq */ NULL, /* 6 seq2 */ NULL, /* 7 gr */ NULL, /* 8 gr2 */ NULL, /* 9 ar */ NULL, /* 10 ar2 */ NULL, /* 11 dac */ NULL, /* 12 dac2 */ NULL, /* 13 ---- */ NULL, /* 14 ---- */ NULL, /* 15 nz */ NULL, /* 16 ch1 */ test_special_ch1, /* 17 ch2 */ test_special_ch2, /* 18 cx1 */ test_special_cx1, /* 19 cx2 */ test_special_cx2, /* 20 ph1 */ test_special_ph, /* 21 ph2 */ test_special_ph, NULL, NULL, NULL }; RecordSpecial* test_intel_specials [MAX_ZONE] = { /* 0 mmio */ test_intel_special_main, /* 1 port */ NULL, /* test_intel_special_port, */ /* 2 ---- */ NULL, /* unused zone */ /* 3 crt */ NULL, /* 4 crt2 */ NULL, /* 5 seq */ NULL, /* 6 seq2 */ NULL, /* 7 gr */ NULL, /* 8 gr2 */ NULL, /* 9 ar */ NULL, /* 10 ar2 */ NULL, /* 11 dac */ NULL, /* 12 dac2 */ NULL, /* 13 ---- */ NULL, /* 14 ---- */ NULL, /* 15 nz */ NULL, /* 16 ch1 */ test_special_ch1, /* 17 ch2 */ test_special_ch2, /* 18 cx1 */ test_special_cx1, /* 19 cx2 */ test_special_cx2, /* 20 ph1 */ test_special_ph, /* 21 ph2 */ test_special_ph, NULL, NULL, NULL }; /* -------- Zone: Defaults -------- */ /* 68050C PLL coef 680508 VPLL1 680520 VPLL2 68x600 Gen Ctrl 1/2 68x608 Test Ctrl 1/2 60x804 PCRTC_Config? */ RecordDefault test_nv_assoc_default [] = { {0x600860, 0x00001110}, {0x602860, 0x00000000}, {END_ADDR, 0}, }; RecordInit test_nv_assoc_init [] = { {ZONE_MMIO, test_nv_assoc_default}, {ZONE_NONE, NULL} }; RecordDefault test_nv_two_default_main [] = { {0x000000, 0x00000000}, {END_ADDR, 0}, }; RecordDefault test_nv3_default_main [] = { {0x000000, 0x00030100}, /* "NV3 Rev A1" */ {END_ADDR, 0}, }; RecordInit test_nv3_init_main [] = { {ZONE_MMIO, test_nv3_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv4_default_main [] = { {0x000000, 0x20004000}, /* "NV4 Rev A1-3" */ {END_ADDR, 0}, }; RecordInit test_nv4_init_main [] = { {ZONE_MMIO, test_nv4_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv5_default_main [] = { {0x000000, 0x20104000}, /* "NV5/6 Rev A1" */ {END_ADDR, 0}, }; RecordInit test_nv5_init_main [] = { {ZONE_MMIO, test_nv5_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv11_default_main [] = { {0x000000, 0x011000A1}, {0x101000, 0x803F4443}, {0x600860, 0x00001110}, {0x602860, 0x00000000}, {END_ADDR, 0}, }; RecordInit test_nv11_init_main [] = { {ZONE_MMIO, test_nv11_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv17_default_main [] = { {0x000000, 0x017100A3}, {0x101000, 0x80C0D53F}, {0x600860, 0x00001110}, {0x602860, 0x00000000}, {END_ADDR, 0}, }; RecordInit test_nv17_init_main [] = { {ZONE_MMIO, test_nv17_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv20_default_main [] = { {0x000000, 0x020100A5}, {0x101000, 0x87F85CFB}, {0x600860, 0x00000000}, {END_ADDR, 0}, }; RecordInit test_nv20_init_main [] = { {ZONE_MMIO, test_nv20_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_nv25_default_main [] = { {0x000000, 0x025300A3}, {0x101000, 0x98C471AF}, {0x600860, 0x00011310}, {0x602860, 0x00020000}, {END_ADDR, 0}, }; RecordInit test_nv25_init_main [] = { {ZONE_MMIO, test_nv25_default_main}, {ZONE_NONE, NULL} }; RecordDefault test_xbox_default_main [] = { {0x000000, 0x02A00000}, {END_ADDR, 0}, }; /* ---- */ RecordDefault test_default_ch1 [] = { {0x10, 0x00}, /* CID = both */ {0x25, 0x50}, /* VID = CH7007A */ {END_ADDR, 0}, }; RecordDefault test_default_ch2 [] = { {0x20, 0x3e}, /* CD = all (DVIT + DACT0-3) */ {0x4a, 0x83}, /* VID = 7009A */ {0x4b, 0x17}, /* DID = 7009A,7011A */ {END_ADDR, 0}, }; RecordDefault test_default_cx1 [] = { {0x00, 0x21}, /* 000=BT869, rev=00001 */ {0x02, 0xf8}, /* both, field=0 */ {0x04, 0x12}, /* pll_lock=1, pal=1 */ {END_ADDR, 0}, }; RecordDefault test_default_cx2 [] = { {0x00, 0x60}, /* 011=CX25871, rev=00000 */ {0x02, 0xf8}, /* both, field=0 */ {0x04, 0x12}, /* pll_lock=1, pal=1 */ {0x06, 0xf0}, /* MON A-D, field=0 */ {END_ADDR, 0}, }; RecordDefault test_default_ph1 [] = { {0x00, 0x40}, /* ver=010 */ {0x1b, 0x00}, /* all DACs loaded */ {0x1c, 0x02}, /* SAA 7102/7108 */ {0x80, 0x00}, /* no overflow/underflow */ {END_ADDR, 0}, }; RecordDefault test_default_ph2 [] = { {0x00, 0xa0}, /* ver=101 */ {0x1b, 0x00}, /* all DACs loaded */ {0x1c, 0x04}, /* SAA 7104/7108A */ {0x80, 0x00}, /* no overflow/underflow */ {END_ADDR, 0}, }; /* -------- -------- */ RecordDefault test_default_nv_crt_mon [] = { {0x28, 0x00, mask:~0x80}, {0x33, 0x00, mask:~0x01}, {END_ADDR, 0}, }; RecordDefault test_default_nv_crt_tv [] = { {0x28, 0x80, mask:~0x80}, {0x33, 0x00, mask:~0x01}, {END_ADDR, 0}, }; RecordDefault test_default_nv_crt_fp [] = { {0x28, 0x80, mask:~0x80}, {0x33, 0x01, mask:~0x01}, {END_ADDR, 0}, }; RecordDefault test_default_intel_gr [] = { {0x1e, 0x00}, /* gr scratch (for locking) */ {0x1f, 0x00}, /* gr scratch (for locking) */ {END_ADDR, 0}, }; RecordInit test_intel_init_main [] = { {ZONE_GR, test_default_intel_gr}, {ZONE_NONE, NULL} }; /* -------- -------- */ RecordInit test_init_nv_mon [] = { {ZONE_CRT, test_default_nv_crt_mon}, {ZONE_CRT2, test_default_nv_crt_mon}, {ZONE_NONE, NULL} }; RecordInit test_init_nv_tv [] = { {ZONE_CRT, test_default_nv_crt_tv}, {ZONE_CRT2, test_default_nv_crt_mon}, {ZONE_NONE, NULL} }; RecordInit test_init_nv_mon_tv [] = { // {ZONE_MMIO, test_default_nv_mmio_two}, {ZONE_CRT, test_default_nv_crt_mon}, {ZONE_CRT2, test_default_nv_crt_tv}, {ZONE_NONE, NULL} }; RecordInit test_init_nv_off_fp [] = { // {ZONE_MMIO, test_default_nv_mmio_fp}, // {ZONE_CRT, test_default_nv_crt_off}, {ZONE_CRT2, test_default_nv_crt_fp}, {ZONE_NONE, NULL} }; RecordInit test_init_nv_tv_fp [] = { // {ZONE_MMIO, test_default_nv_mmio_fp}, {ZONE_CRT, test_default_nv_crt_tv}, {ZONE_CRT2, test_default_nv_crt_fp}, {ZONE_NONE, NULL} }; RecordInit test_init_i2c [] = { {ZONE_CH1, test_default_ch1}, {ZONE_CH2, test_default_ch2}, {ZONE_CX1, test_default_cx1}, {ZONE_CX2, test_default_cx2}, {ZONE_PH1, test_default_ph1}, {ZONE_PH2, test_default_ph2}, {ZONE_NONE, NULL} }; /* -------- -------- */ typedef struct { char *name; RecordInit* init; } ConfigDefault; ConfigDefault config_nv_heads [] = { {"mon", test_init_nv_mon}, {"tv", test_init_nv_tv}, {"mon_tv", test_init_nv_mon_tv}, {"off_fp", test_init_nv_off_fp}, {"tv_fp", test_init_nv_tv_fp}, {NULL, NULL} }; ConfigDefault config_defaults [] = { {"nv04", test_nv4_init_main}, {"nv05", test_nv5_init_main}, {"nv0a", NULL}, {"nv10", NULL}, {"nv11", test_nv11_init_main}, {"nv15", NULL}, {"nv17", test_nv17_init_main}, {"nv18", test_nv_assoc_init}, {"nv1a", test_nv_assoc_init}, {"nv1f", test_nv_assoc_init}, {"nv20", test_nv20_init_main}, {"nv25", test_nv25_init_main}, {"nv28", test_nv_assoc_init}, {"nv2a", NULL}, {"nv30", test_nv_assoc_init}, {"nv31", test_nv_assoc_init}, {"nv32", test_nv_assoc_init}, {"nv34", test_nv_assoc_init}, {"nv35", test_nv_assoc_init}, {"nv36", test_nv_assoc_init}, {"xbox", NULL}, {"i810", test_intel_init_main}, {"i830", test_intel_init_main}, {"i845", test_intel_init_main}, {"i855", test_intel_init_main}, {"i865", test_intel_init_main}, {"tdfx", NULL}, {NULL, NULL} }; /* -------- -------- */ typedef struct { char *name; RecordDevice** devices; } ConfigDevices; RecordDevice* test_no_devices[] = {NULL}; RecordDevice* test_ch1_devices[] = {&TestDeviceCH1, NULL}; RecordDevice* test_ch2_devices[] = {&TestDeviceCH2, NULL}; RecordDevice* test_cx1_devices[] = {&TestDeviceCX1, NULL}; RecordDevice* test_cx2_devices[] = {&TestDeviceCX2, NULL}; RecordDevice* test_ph1_devices[] = {&TestDevicePH1, NULL}; RecordDevice* test_ph2_devices[] = {&TestDevicePH2, NULL}; RecordDevice* test_all_devices[] = { &TestDeviceCH1, &TestDeviceCH2, &TestDeviceCX1, &TestDeviceCX2, &TestDevicePH1, &TestDevicePH2, NULL}; ConfigDevices config_devices [] = { {"none", test_no_devices}, {"ch1", test_ch1_devices}, {"ch2", test_ch2_devices}, {"cx1", test_cx1_devices}, {"cx2", test_cx2_devices}, {"ph1", test_ph1_devices}, {"ph2", test_ph2_devices}, {"all", test_all_devices}, {NULL, NULL} }; /* -------- -------- */ RecordConfig config_nv = { zone: test_zones, access: test_nv_access, switches: test_nv_switches, specials: test_nv_specials, devices: NULL, }; RecordConfig config_tdfx = { zone: test_zones, access: test_tdfx_access, switches: NULL, specials: test_tdfx_specials, devices: NULL, }; RecordConfig config_intel = { zone: test_zones, access: test_intel_access, switches: NULL, specials: test_intel_specials, devices: NULL, }; RecordConfig* config = NULL; RecordEntryPtr recordAccess (int zone, CARD32 addr, BitSize bits); void configDefault (int zone, RecordDefault *def) { RecordEntryPtr r; if (!def) return; for (; def->addr != END_ADDR; def++) { /* FIXME must find bits for init with mask ... */ r = recordAccess (zone, def->addr, (zone == ZONE_MMIO) ? BIT32 : BIT8); r->data &= def->mask; r->data |= def->data; // r->count = 0; /* Was present "before" */ } } void configInit (RecordInit *init) { if (!init) return; for (; init->defaults; init++) configDefault (init->zone, init->defaults); } void configSetup (char *card, char *enc, char *head) { ConfigDevices *p; ConfigDefault *q; if (strncmp (card, "nv", 2) == 0) { config = &config_nv; for (q = config_nv_heads; q->name; q++) { if (strcmp (q->name, head) == 0) { configInit (q->init); break; } } } else if (strncmp (card, "xbox", 4) == 0) { config = &config_nv; configDefault (ZONE_MMIO, test_xbox_default_main); configInit (test_init_nv_tv); } else if (strncmp (card, "i8", 2) == 0) { config = &config_intel; } else if (strncmp (card, "tdfx", 4) == 0) { config = &config_tdfx; } else { fprintf (stderr, "Cannot configure for card %s\n", card); exit (1); } configInit (test_init_i2c); for (q = config_defaults; q->name; q++) { if (strcmp (q->name, card) == 0) { configInit (q->init); break; } } for (p = config_devices; p->name; p++) { if (strcmp (p->name, enc) == 0) { config->devices = p->devices; break; } } if (!p->name) { fprintf (stderr, "Cannot configure for encoder(s) %s\n", enc); exit (1); } } int record_switches[MAX_SWITCH_NUM] = {0}; int record_index[MAX_ZONE]; /* FIXME init */ RecordEntryPtr record_roots[MAX_ZONE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; /* record_entry */ /* -------- -------- */ /* Find, and if necessary, create entry */ RecordEntryPtr recordAccess (int zone, CARD32 addr, BitSize bits) { RecordEntryPtr p, q, r; RecordDefault* d; q = NULL; p = record_roots[zone]; for (; p && p->addr < addr; p = p->next) q = p; if (p && p->addr == addr) return p; r = (RecordEntryPtr) malloc (sizeof (RecordEntry)); r->addr = addr; switch (bits) { case BIT8: r->data = testopt_default & 0xff; break; case BIT16: r->data = testopt_default & 0xffff; break; case BIT32: r->data = testopt_default & 0xffffffff; break; default: break; } r->next = p; r->count = 1; /* First access */ if (q) q->next = r; else record_roots[zone] = r; #if 0 /* See if the data has a default */ d = config->defaults[zone]; if (d) { for (; d->addr != END_ADDR; d++) { if (d->addr == addr) { r->data &= d->mask; r->data |= d->data; r->count = 0; /* Was present "before" */ break; } } } #endif return r; } /* Return special (non-zero) if addr in zone is special */ void recordSpecial (int zone, CARD32 addr, int *special, int *param) { RecordSpecial *s; if (special) *special = SPEC_NONE; if (param) *param = 0; s = config->specials[zone]; if (!s) return; for (; s->special != SPEC_NONE; s++) { if (s->low <= addr && addr <= s->high) { if (special) *special = s->special; if (param) *param = s->param; return; } } } /* Return TRUE if bit size is correct (zone 0 only) */ Bool recordBits (int zone, CARD32 addr, BitSize bits) { RecordAccess* r; for (r = config->access; r->bits != BIT_NONE; r++) { if (r->zone == zone && r->low <= addr && addr <= r->high) { if (r->bits == bits) return TRUE; break; } } if (r->bits == BIT_NONE) { printf ("BITS %06X zone %i out of range\n", addr & 0xffffff, zone); } else { printf ("BITS %06X zone %i wrong access %i/%i\n", addr & 0xffffff, zone, bits, r->bits); } return FALSE; } /* Switch zone if necessary */ int recordSwitch (int zone) { RecordSwitch* r; int res; if (config->switches) { for (r = config->switches; r->switcher != -1; r++) { if (r->zone == zone) { res = r->dest[record_switches[r->switcher]]; if (res == -1) { printf ("SWCH zone %i switch %i to invalid zone\n", zone, r->switcher); return zone; } // printf ("SWCH %-4s -> %-4s\n", config->zone[zone], config->zone[res]); return res; } } } return zone; } void recordPrintData (CARD32 data, BitSize bits) { switch (bits) { case BIT8: printf ("%02X", data); break; case BIT16: printf ("%04X", data); break; case BIT32: printf ("%08X", data); break; default: break; } } CARD32 recordReadDirect (int zone, CARD32 addr, BitSize bits) { RecordEntryPtr p = recordAccess (zone, addr, bits); return p->data; } CARD32 recordRead (int zone, CARD32 addr, BitSize bits, char *dir) { int special, param; RecordEntryPtr p; zone = recordSwitch (zone); addr &= 0xffffff; if (recordBits (zone, addr, bits)) { recordSpecial (zone, addr, &special, ¶m); switch (special) { case SPEC_INDEX: return record_index[param]; case SPEC_DATA: return recordRead (param, record_index[param], bits, dir); case SPEC_VGA_AR: printf ("vga read from attribute address reg\n"); /* fallthrough */ case SPEC_FLIP: if (record_index[param] & 1) { return recordRead (param, record_index[param] >> 1, bits, dir); } else { return record_index[param] >> 1; } case SPEC_RESET: case SPEC_RESET_R: record_index[param] &= ~1; return 0; case SPEC_FWD_R: return recordRead (zone, param, bits, dir); default: p = recordAccess (zone, addr, bits); if (testopt_log && special != SPEC_NOLOG) { printf ("%-4s %06X %s ", config->zone[zone], addr, dir); recordPrintData (p->data, bits); printf ("\n"); } if (special == SPEC_INCR) p->data++; return p->data; } } return 0; /* should never reach this */ } void recordWrite (int zone, CARD32 addr, CARD32 data, BitSize bits, char *dir) { int special, param; RecordEntryPtr p; zone = recordSwitch (zone); addr &= 0xffffff; if (recordBits (zone, addr, bits)) { recordSpecial (zone, addr, &special, ¶m); if (special == SPEC_READONLY) { if (testopt_log) { printf ("%-4s %06X %s r/o\n", config->zone[zone], addr, dir); return; } } switch (special) { case SPEC_INDEX: record_index[param] = data; return; case SPEC_DATA: recordWrite (param, record_index[param], data, bits, dir); return; case SPEC_VGA_AR: if ((record_index[param] & 1) == 0) { printf ("%-4s %06X ar\n", "vga", data); data &= 0x1f; } /* fallthrough */ case SPEC_FLIP: if (record_index[param] & 1) { recordWrite (param, record_index[param] >> 1, data, bits, dir); record_index[param] &= ~1; } else { record_index[param] = data << 1 | 1; } return; case SPEC_RESET: case SPEC_RESET_W: record_index[param] &= ~1; return; case SPEC_FWD_W: recordWrite (zone, param, data, bits, dir); return; default: p = recordAccess (zone, addr, bits); p->data = data; p->count++; if (special == SPEC_SWITCH) { if (data < MAX_SWITCH_VAL) record_switches [param] = data; } if (testopt_log && special != SPEC_NOLOG) { printf ("%-4s %06X %s ", config->zone[zone], addr, dir); recordPrintData (data, bits); printf (" (%i)\n", p->count); } return; } } } void recordPrint (char *title) { int zone; RecordEntryPtr p; if (testopt_dump) printf ("%s\n", title); for (zone = 0; zone < MAX_ZONE; zone++) { for (p = record_roots[zone]; p; p = p->next) { if (p->count > 0 && testopt_dump) { printf ("%-4s %06X = %08X (%i)\n", config->zone[zone], p->addr, p->data, p->count); } p->count = 0; } } } /* ====================================================================== */ #if 0 Checkpoints: compare with patterns mention all extra values (store extra values somewhere, and only report diff next time?) Automatically create patterns: do MMIO and recording parallel store initial values in defaults store actual values in test pattern */ #endif #if 0 A) monitor only, 0x680608, 0x00010000 /* Test Ctrl */ 0x682608, 0x00000000 /* Test Ctrl */ B) TV only, C) twin, D) FP only, 0x680608, 0x00010000 /* Test Ctrl */ 0x682608, 0x00010000 /* Test Ctrl */ E) FP twin #endif #if 0 SPECIALS 0x6013c1 /* SPEC_DATA_R() read_only */ 0x6813c7 /* palette read_mode address */ 0x6813c8 /* palette write_mode address */ 0x6813c9 /* palette data, auto_inc SPEC_DATA_INC */ crt index 44 -- associate VIO to head #endif