diff --git a/src/device/clock_ics9xxx.c b/src/device/clock_ics9xxx.c index 70b5b4eec..2a8cfef25 100644 --- a/src/device/clock_ics9xxx.c +++ b/src/device/clock_ics9xxx.c @@ -27,10 +27,16 @@ #include "cpu.h" +#define ICS9xxx_DEVICE(model_enum) }, [model_enum] = {.model = model_enum, .name = #model_enum, + + enum { - ICS9150_08 = 1, + ICS9xxx_xx, + ICS9150_08, ICS9248_39, + ICS9248_81, ICS9248_98, + ICS9248_101, ICS9250_08, ICS9250_10, ICS9250_13, @@ -47,7 +53,8 @@ enum { ICS9250_30, ICS9250_32, ICS9250_38, - ICS9250_50 + ICS9250_50, + ICS9xxx_MAX }; typedef struct { @@ -57,31 +64,40 @@ typedef struct { } ics9xxx_frequency_t; typedef struct { - uint8_t model; - uint8_t max_reg: 3; - uint8_t regs[8]; - struct { - uint8_t normal_reg: 3; - uint8_t normal_bit: 3; - uint8_t inv_reg: 3; - uint8_t inv_bit: 3; + uint8_t max_reg: 3; /* largest register index */ + uint8_t regs[8]; /* default registers */ + struct { /* for each hardware frequency select bit [FS0:FS4]: */ + uint8_t normal_reg: 3; /* which register (or -1) for non-inverted input (FSn) */ + uint8_t normal_bit: 3; /* which bit (0-7) for non-inverted input (FSn) */ + uint8_t inv_reg: 3; /* which register (or -1) for inverted input (FSn#) */ + uint8_t inv_bit: 3; /* which bit (0-7) for inverted input (FSn#) */ } fs_regs[5]; - uint8_t normal_bits_fixed: 1; + uint8_t normal_bits_fixed: 1; /* set to 1 if the non-inverted bits are straps (hardware select only) */ + struct { /* hardware select bit, which should be cleared for hardware select (latched inputs), or set for programming */ + uint8_t normal_reg: 3; /* which register (or -1) */ + uint8_t normal_bit: 3; /* which bit (0-7) */ + } hw_select; - uint8_t frequencies_ref; - ics9xxx_frequency_t frequencies[32]; - ics9xxx_frequency_t *frequencies_ptr; + uint8_t frequencies_ref; /* which other model to use the frequency table from (or 0) */ + ics9xxx_frequency_t frequencies[32]; /* frequency table, if not using another model's table */ + /* remaining fields are "don't care" for the table */ + uint8_t model; /* populated by macro */ + const char *name; /* populated by macro */ + ics9xxx_frequency_t *frequencies_ptr; /* populated at runtime */ int8_t addr_register; + uint8_t relevant_regs; uint8_t bus_match: 5; } ics9xxx_t; static const ics9xxx_t ics9xxx_devices[] = { - [ICS9150_08] = { + [ICS9xxx_xx] = {0 + ICS9xxx_DEVICE(ICS9150_08) .max_reg = 5, .regs = {0x00, 0xff, 0xff, 0xff, 0x6f, 0xbf}, .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 5000, .pci_div = 2}, {.bus = 7500, .pci_div = 2}, @@ -92,11 +108,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 13333, .pci_div = 4}, {.bus = 10020, .pci_div = 3}, } - }, - [ICS9248_39] = { + ICS9xxx_DEVICE(ICS9248_39) .max_reg = 5, .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff}, .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 12400, .pci_div = 3}, {.bus = 7500, .pci_div = 2}, @@ -115,11 +131,34 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 12400, .pci_div = 4}, {.bus = 13300, .pci_div = 4} } - }, - [ICS9248_98] = { + ICS9xxx_DEVICE(ICS9248_81) + .max_reg = 5, + .regs = {0x82, 0xfe, 0x7f, 0xff, 0xff, 0xb7}, + .fs_regs = {{0, 4, 1, 0}, {0, 5, 2, 7}, {0, 6, 5, 6}, {0, 2, 5, 3}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = { + {.bus = 9000, .ram_mult = 1, .pci_div = 3}, + {.bus = 6670, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 9500, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 10000, .ram_mult = 0.75, .pci_div = 3}, + {.bus = 11200, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 12400, .ram_mult = 2.0/3.0, .pci_div = 4}, + {.bus = 13330, .ram_mult = 2.0/3.0, .pci_div = 4}, + {.bus = 6670, .ram_mult = 1, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1, .pci_div = 3}, + {.bus = 8330, .ram_mult = 1, .pci_div = 3}, + {.bus = 9500, .ram_mult = 1, .pci_div = 3}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 11200, .ram_mult = 1, .pci_div = 3}, + {.bus = 12400, .ram_mult = 1, .pci_div = 4}, + {.bus = 13330, .ram_mult = 1, .pci_div = 4}, + } + ICS9xxx_DEVICE(ICS9248_98) .max_reg = 6, .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff, 0x06}, - .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {0, 2, -1, -1}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 8000, .pci_div = 2}, {.bus = 7500, .pci_div = 2}, @@ -154,17 +193,39 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 14199, .pci_div = 4}, {.bus = 13801, .pci_div = 4} } - }, - [ICS9250_08] = { + ICS9xxx_DEVICE(ICS9248_101) + .max_reg = 5, + .regs = {0x82, 0xff, 0xff, 0xff, 0xf5, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .frequencies = { + {.bus = 12400, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 11499, .pci_div = 3}, + {.bus = 10999, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 8331, .pci_div = 2}, + {.bus = 13700, .pci_div = 4}, + {.bus = 7500, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 9500, .pci_div = 3}, + {.bus = 8331, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 9000, .pci_div = 3}, + {.bus = 9622, .pci_div = 3}, + {.bus = 6682, .pci_div = 2}, + {.bus = 9150, .pci_div = 3} + } + ICS9xxx_DEVICE(ICS9250_08) .max_reg = 5, .regs = {0x00, 0xff, 0xff, 0xff, 0x6d, 0xbf}, .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies_ref = ICS9248_39 - }, - [ICS9250_10] = { + ICS9xxx_DEVICE(ICS9250_10) .max_reg = 5, .regs = {0x1f, 0xff, 0xfe, 0x00, 0x00, 0x06}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {5, 4, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies = { {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, {.bus = 7067, .ram_mult = 1.5, .pci_div = 2}, @@ -183,11 +244,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 10900, .ram_mult = 1, .pci_div = 3}, {.bus = 13300, .ram_mult = 1, .pci_div = 3} } - }, - [ICS9250_13] = { + ICS9xxx_DEVICE(ICS9250_13) .max_reg = 5, .regs = {0x82, 0xcf, 0x7f, 0xff, 0xff, 0xf7}, .fs_regs = {{0, 4, 1, 4}, {0, 5, 5, 7}, {0, 6, 1, 5}, {0, 2, 2, 7}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 9000, .ram_mult = 1, .pci_div = 2}, {.bus = 8901, .ram_mult = 1, .pci_div = 2}, @@ -206,11 +267,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 7199, .ram_mult = 1, .pci_div = 2}, {.bus = 6682, .ram_mult = 1, .pci_div = 2} } - }, - [ICS9250_14] = { + ICS9xxx_DEVICE(ICS9250_14) .max_reg = 5, .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 6781, .ram_mult = 1.5, .pci_div = 2}, {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, @@ -245,11 +306,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 13975, .ram_mult = 1, .pci_div = 3}, {.bus = 14969, .ram_mult = 1, .pci_div = 3} } - }, - [ICS9250_16] = { + ICS9xxx_DEVICE(ICS9250_16) .max_reg = 5, .regs = {0x1f, 0xff, 0xff, 0x00, 0x00, 0x06}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies = { {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, @@ -268,11 +329,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 14000, .ram_mult = 1, .pci_div = 4}, {.bus = 13299, .ram_mult = 1, .pci_div = 4} } - }, - [ICS9250_18] = { + ICS9xxx_DEVICE(ICS9250_18) .max_reg = 5, .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 8000, .pci_div = 2}, {.bus = 7500, .pci_div = 2}, @@ -307,17 +368,17 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 14199, .pci_div = 4}, {.bus = 13801, .pci_div = 4} } - }, - [ICS9250_19] = { + ICS9xxx_DEVICE(ICS9250_19) .max_reg = 5, .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, .frequencies_ref = ICS9250_08 - }, - [ICS9250_23] = { + ICS9xxx_DEVICE(ICS9250_23) .max_reg = 5, .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 6900, .ram_mult = 1.5, .pci_div = 2}, {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, @@ -352,11 +413,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 15330, .ram_mult = 0.75, .pci_div = 4}, {.bus = 16667, .ram_mult = 0.75, .pci_div = 4} } - }, - [ICS9250_25] = { + ICS9xxx_DEVICE(ICS9250_25) .max_reg = 6, .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff, 0x06}, .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 5500, .ram_mult = 1.5, .pci_div = 2}, {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, @@ -391,17 +452,17 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, {.bus = 15333, .ram_mult = 0.75, .pci_div = 4} } - }, - [ICS9250_26] = { + ICS9xxx_DEVICE(ICS9250_26) .max_reg = 5, .regs = {0x1e, 0xff, 0xff, 0x00, 0x00, 0x06}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies_ref = ICS9250_16 - }, - [ICS9250_27] = { + ICS9xxx_DEVICE(ICS9250_27) .max_reg = 5, .regs = {0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies = { {.bus = 6666, .ram_mult = 1.5, .pci_div = 2}, {.bus = 13332, .ram_mult = 1, .pci_div = 4}, @@ -412,23 +473,23 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 10000, .ram_mult = 1, .pci_div = 3}, {.bus = 13332, .ram_mult = 1, .pci_div = 4} } - }, - [ICS9250_28] = { + ICS9xxx_DEVICE(ICS9250_28) .max_reg = 4, .regs = {0x1e, 0xff, 0xfe, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies_ref = ICS9250_27 - }, - [ICS9250_29] = { + ICS9xxx_DEVICE(ICS9250_29) .max_reg = 5, .regs = {0x16, 0xff, 0xfe, 0x00, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, .frequencies_ref = ICS9250_27 - }, - [ICS9250_30] = { + ICS9xxx_DEVICE(ICS9250_30) .max_reg = 6, .regs = {0x02, 0x0f, 0xff, 0xff, 0xeb, 0xff, 0x06}, .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, .frequencies = { {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, @@ -463,13 +524,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, {.bus = 16000, .ram_mult = 0.75, .pci_div = 4} } - }, - [ICS9250_32] = { + ICS9xxx_DEVICE(ICS9250_32) .max_reg = 4, .regs = {0x07, 0xff, 0xff, 0x00, 0x00}, .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}} - }, - [ICS9250_38] = { + ICS9xxx_DEVICE(ICS9250_38) .max_reg = 6, .regs = {0x18, 0x07, 0xfe, 0xc7, 0xfc, 0x00, 0x80}, .fs_regs = {{0, 0, -1, -1}, {0, 1, -1, -1}, {0, 2, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, @@ -484,11 +543,11 @@ static const ics9xxx_t ics9xxx_devices[] = { {.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6}, {.bus = 13333, .ram_mult = 0.5, .pci_div = 2} } - }, - [ICS9250_50] = { + ICS9xxx_DEVICE(ICS9250_50) .max_reg = 6, .regs = {0x02, 0x6f, 0xff, 0xff, 0xef, 0xff, 0x06}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .fs_regs = {{-1, -1, 1, 6}, {-1, -1, 4, 2}, {-1, -1, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, .frequencies = { [0] = {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, [8] = {.bus = 10000, .ram_mult = 1, .pci_div = 3}, @@ -498,7 +557,7 @@ static const ics9xxx_t ics9xxx_devices[] = { } }; -#define ENABLE_ICS9xxx_LOG 1 + #ifdef ENABLE_ICS9xxx_LOG int ics9xxx_do_log = ENABLE_ICS9xxx_LOG; @@ -519,6 +578,84 @@ ics9xxx_log(const char *fmt, ...) #endif +#ifdef ENABLE_ICS9xxx_DETECT +static uint16_t detect_bus = 0; +static uint8_t detect_reg = 0; +static uint8_t discarded[sizeof(ics9xxx_devices) / sizeof(ics9xxx_devices[0])] = {0}; + + +static void +ics9xxx_detect_reset(void *priv) +{ + pclog("Please enter the frequency set in the BIOS (7500 for 75.00 MHz)\nAnswer 0 if unsure or set to auto, I'll ask again next reset.\n"); + scanf("%hu", &detect_bus); + if ((detect_bus > 0) && (detect_bus < 1000)) + detect_bus *= 100; + pclog("Frequency interpreted as %d\n", detect_bus); +} + + +static void +ics9xxx_detect(ics9xxx_t *dev) +{ + if (!detect_bus) { + pclog("Frequency not entered on this reset, ignoring change.\n"); + return; + } + + if ((detect_reg == 0) && (dev->regs[detect_reg] >= 0xfe)) { + pclog("Register %d set to %02X, probably not it, trying %d instead\n", detect_reg, dev->regs[detect_reg], 3); + detect_reg = 3; + dev->relevant_regs = 1 << detect_reg; + return; + } + + if (!(dev->regs[detect_reg] & 0x40)) + pclog("Bit 3 of register %d is clear, probably in hardware select mode!\n", detect_reg); + + uint8_t matches = 0, val, bitmask; + ics9xxx_frequency_t *frequencies_ptr; + uint32_t delta; + for (uint8_t j = 0; j < ICS9xxx_MAX; j++) { + if (discarded[j]) + continue; + discarded[j] = 1; + + frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_devices[ics9xxx_devices[j].frequencies_ref ? ics9xxx_devices[j].frequencies_ref : j].frequencies; + if (!frequencies_ptr) + continue; + + for (uint8_t i = 0; i < (sizeof(ics9xxx_devices[j].frequencies) / sizeof(ics9xxx_devices[j].frequencies[0])); i++) { + if (!frequencies_ptr[i].bus) + continue; + + delta = ABS((int32_t) (detect_bus - frequencies_ptr[i].bus)); + if (delta <= 100) { + val = bitmask = 0; + for (uint8_t k = 0; k < sizeof(ics9xxx_devices[j].fs_regs) / sizeof(ics9xxx_devices[j].fs_regs[0]); k++) { + if (ics9xxx_devices[j].fs_regs[k].normal_reg == detect_reg) { + bitmask |= 1 << k; + val |= (1 << k) * !!(dev->regs[detect_reg] & (1 << ics9xxx_devices[j].fs_regs[k].normal_bit)); + } + } + if (bitmask && (val == (i & bitmask))) { + matches++; + discarded[j] = 0; + pclog("> Potential match for %s (frequency %d index %d)\n", ics9xxx_devices[j].name, frequencies_ptr[i].bus, val); + } + } + } + } + + pclog("Found a total of %d matches for register %d value %02X and bus frequency %d\n", matches, detect_reg, dev->regs[detect_reg], detect_bus); + if (matches == 0) { + pclog("Resetting list of discarded models since there were no matches.\n"); + memset(discarded, 0, sizeof(discarded)); + } +} +#endif + + static uint8_t ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv) { @@ -557,13 +694,23 @@ ics9xxx_read(void *bus, uint8_t addr, void *priv) static void ics9xxx_set(ics9xxx_t *dev, uint8_t val) { - /* Add register-defined frequency bits to the static frequency bits we were passed. */ - for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { - if ((dev->fs_regs[i].normal_reg < 7) && (dev->regs[dev->fs_regs[i].normal_reg] & (1 << dev->fs_regs[i].normal_bit))) - val |= 1 << i; + /* Get the active mode, which determines what to add to the static frequency bits we were passed. */ + uint8_t hw_select = (dev->hw_select.normal_reg < 7) && !(dev->regs[dev->hw_select.normal_reg] & (1 << dev->hw_select.normal_bit)); + if (hw_select) { + /* Hardware select mode: add strapped frequency bits. */ + val |= dev->bus_match; + } else { + /* Programmable mode: add register-defined frequency bits. */ + for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { + if ((dev->fs_regs[i].normal_reg < 7) && (dev->regs[dev->fs_regs[i].normal_reg] & (1 << dev->fs_regs[i].normal_bit))) + val |= 1 << i; + } } - ics9xxx_log("ICS9xxx: set(%02X) = %d\n", val, ics9xxx_devices[dev->model].frequencies[val].bus); +#ifdef ENABLE_ICS9xxx_LOG + uint16_t bus = ics9xxx_devices[dev->model].frequencies[val].bus; + ics9xxx_log("ICS9xxx: set(%d) = hw=%d bus=%d ram=%d pci=%d\n", val, hw_select, bus, bus * ics9xxx_devices[dev->model].frequencies[val].ram_mult, bus / ics9xxx_devices[dev->model].frequencies[val].pci_div); +#endif } @@ -576,28 +723,22 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv) if (dev->addr_register >= 0) { /* Preserve fixed bits. */ - for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { - if (dev->normal_bits_fixed && (dev->fs_regs[i].normal_reg == dev->addr_register)) - data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].normal_bit)) | (data & ~(1 << dev->fs_regs[i].normal_bit)); - if (dev->fs_regs[i].inv_reg == dev->addr_register) - data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].inv_bit)) | (data & ~(1 << dev->fs_regs[i].inv_bit)); +#ifdef ENABLE_ICS9xxx_DETECT + if (dev->model != ICS9xxx_xx) +#endif + { + for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { + if (dev->normal_bits_fixed && (dev->fs_regs[i].normal_reg == dev->addr_register)) + data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].normal_bit)) | (data & ~(1 << dev->fs_regs[i].normal_bit)); + if (dev->fs_regs[i].inv_reg == dev->addr_register) + data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].inv_bit)) | (data & ~(1 << dev->fs_regs[i].inv_bit)); + } } switch (dev->addr_register) { case 0: if (dev->model == ICS9250_38) data = (dev->regs[dev->addr_register] & ~0xe8) | (data & 0xe8); - else { - dev->regs[dev->addr_register] = data; - if (dev->model == ICS9250_10) - ics9xxx_set(dev, (cpu_busspeed >= 100000000) * 0x08); - else if ((dev->model == ICS9250_16) || (dev->model == ICS9250_26)) - ics9xxx_set(dev, ((cpu_busspeed >= 120000000) * 0x08) | ((((cpu_busspeed >= 100000000) && (cpu_busspeed < 120000000)) || (cpu_busspeed == 150000000) || (cpu_busspeed == 132999999)) * 0x04)); - else if ((dev->model == ICS9250_27) || (dev->model == ICS9250_28) || (dev->model == ICS9250_29)) - ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01)); - else - ics9xxx_set(dev, 0x00); - } break; case 1: @@ -621,8 +762,38 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv) break; } dev->regs[dev->addr_register] = data; + + /* Update frequency if a relevant register was written to. */ + if (dev->relevant_regs & (1 << dev->addr_register)) { + switch (dev->model) { +#ifdef ENABLE_ICS9xxx_DETECT + case ICS9xxx_xx: + ics9xxx_detect(dev); + break; +#endif + + case ICS9250_10: + ics9xxx_set(dev, (cpu_busspeed >= 100000000) * 0x08); + break; + + case ICS9250_16: + case ICS9250_26: + ics9xxx_set(dev, ((cpu_busspeed >= 120000000) * 0x08) | ((((cpu_busspeed >= 100000000) && (cpu_busspeed < 120000000)) || (cpu_busspeed == 150000000) || (cpu_busspeed == 132999999)) * 0x04)); + break; + + case ICS9250_27: + case ICS9250_28: + case ICS9250_29: + ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01)); + break; + + default: + ics9xxx_set(dev, 0x00); + break; + } + } } - + if (++dev->addr_register > dev->max_reg) dev->addr_register = 0; /* roll-over */ @@ -631,10 +802,13 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv) static uint8_t -find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) { +ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) { uint8_t best_match = 0; uint32_t delta, best_delta = -1; + if (dev->model == ICS9xxx_xx) + return 0; + for (uint8_t i = 0; i < (sizeof(dev->frequencies) / sizeof(dev->frequencies[0])); i++) { if (((i & preset_mask) != preset) || !dev->frequencies_ptr[i].bus) continue; @@ -646,7 +820,7 @@ find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset } } - ics9xxx_log("ICS9xxx: find_match(%02X, %d) = %d (%02X)\n", dev->model, bus, dev->frequencies_ptr[best_match].bus, best_match); + ics9xxx_log("ICS9xxx: find_match(%02X, %d) = match=%d bus=%d\n", dev->model, bus, best_match, dev->frequencies_ptr[best_match].bus); return best_match; } @@ -658,35 +832,59 @@ ics9xxx_init(const device_t *info) ics9xxx_t *dev = (ics9xxx_t *) malloc(sizeof(ics9xxx_t)); memcpy(dev, &ics9xxx_devices[info->local], sizeof(ics9xxx_t)); - ics9xxx_log("ICS9xxx: init(%02X)\n", info->local); + ics9xxx_log("ICS9xxx: init(%s)\n", dev->name); - dev->model = info->local; - dev->frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_devices[dev->frequencies_ref ? dev->frequencies_ref : dev->model].frequencies; - if (!dev->frequencies_ptr) - fatal("ICS9xxx: NULL frequency table\n"); - - /* Determine which frequency bits cannot be strapped (register only). */ - uint8_t register_only_bits = 0x00; uint8_t i; - for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { - if ((dev->fs_regs[i].normal_reg == 7) && (dev->fs_regs[i].inv_reg == 7)) - register_only_bits |= 1 << i; - } +#ifdef ENABLE_ICS9xxx_DETECT + if (dev->model == ICS9xxx_xx) { /* detection device */ + dev->max_reg = 6; + dev->relevant_regs = 1 << 0; /* register 0 matters the most on the detection device */ - /* Find bus speed match and set default register bits accordingly. */ - dev->bus_match = find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00); - for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { - if (dev->fs_regs[i].normal_reg < 7) { - if (dev->bus_match & (1 << i)) - dev->regs[dev->fs_regs[i].normal_reg] |= 1 << dev->fs_regs[i].normal_bit; - else - dev->regs[dev->fs_regs[i].normal_reg] &= ~(1 << dev->fs_regs[i].normal_bit); + for (i = 0; i < ICS9xxx_MAX; i++) { + for (uint8_t j = 0; j < ICS9xxx_MAX; j++) { + if (i == j) + continue; + if (!memcmp(&ics9xxx_devices[i], &ics9xxx_devices[j], sizeof(ics9xxx_devices[i]))) + pclog("Optimization warning: %d and %d have duplicate tables\n", i, j); + } } - if (dev->fs_regs[i].inv_reg < 7) { - if (dev->bus_match & (1 << i)) - dev->regs[dev->fs_regs[i].inv_reg] &= ~(1 << dev->fs_regs[i].inv_bit); - else - dev->regs[dev->fs_regs[i].inv_reg] |= 1 << dev->fs_regs[i].inv_bit; + + ics9xxx_detect_reset(dev); + } else +#endif + { /* regular device */ + dev->frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_devices[dev->frequencies_ref ? dev->frequencies_ref : dev->model].frequencies; + if (!dev->frequencies_ptr) + fatal("ICS9xxx: NULL frequency table\n"); + + /* Determine which frequency bits cannot be strapped (register only). */ + uint8_t register_only_bits = 0x00; + for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { + if (!dev->normal_bits_fixed && (dev->fs_regs[i].normal_reg < 7)) /* mark a normal, programmable bit as relevant */ + dev->relevant_regs |= 1 << dev->fs_regs[i].normal_reg; + if ((dev->fs_regs[i].normal_reg == 7) && (dev->fs_regs[i].inv_reg == 7)) /* mark as register only */ + register_only_bits |= 1 << i; + } + + /* Mark the hardware select bit's register as relevant, if there's one. */ + if (dev->hw_select.normal_reg < 7) + dev->relevant_regs |= 1 << dev->hw_select.normal_reg; + + /* Find bus speed match and set default register bits accordingly. */ + dev->bus_match = ics9xxx_find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00); + for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) { + if (dev->fs_regs[i].normal_reg < 7) { + if (dev->bus_match & (1 << i)) + dev->regs[dev->fs_regs[i].normal_reg] |= 1 << dev->fs_regs[i].normal_bit; + else + dev->regs[dev->fs_regs[i].normal_reg] &= ~(1 << dev->fs_regs[i].normal_bit); + } + if (dev->fs_regs[i].inv_reg < 7) { + if (dev->bus_match & (1 << i)) + dev->regs[dev->fs_regs[i].inv_reg] &= ~(1 << dev->fs_regs[i].inv_bit); + else + dev->regs[dev->fs_regs[i].inv_reg] |= 1 << dev->fs_regs[i].inv_bit; + } } } @@ -709,6 +907,18 @@ ics9xxx_close(void *priv) } +#ifdef ENABLE_ICS9xxx_DETECT +const device_t ics9xxx_detect_device = { + "ICS9xxx-xx Clock Generator", + DEVICE_PCI, + ICS9xxx_xx, + ics9xxx_init, ics9xxx_close, ics9xxx_detect_reset, + { NULL }, NULL, NULL, + NULL +}; +#endif + + const device_t ics9150_08_device = { "ICS9150-08 Clock Generator", DEVICE_ISA, @@ -729,6 +939,16 @@ const device_t ics9248_39_device = { }; +const device_t ics9248_81_device = { + "ICS9248-81 Clock Generator", + DEVICE_ISA, + ICS9248_81, + ics9xxx_init, ics9xxx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + const device_t ics9248_98_device = { "ICS9248-98 Clock Generator", DEVICE_ISA, @@ -739,6 +959,16 @@ const device_t ics9248_98_device = { }; +const device_t ics9248_101_device = { + "ICS9248-101 Clock Generator", + DEVICE_ISA, + ICS9248_101, + ics9xxx_init, ics9xxx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + const device_t ics9250_08_device = { "ICS9250-08 Clock Generator", DEVICE_ISA, diff --git a/src/include/86box/clock.h b/src/include/86box/clock.h index da8ff9e2e..5ba7d508b 100644 --- a/src/include/86box/clock.h +++ b/src/include/86box/clock.h @@ -18,9 +18,12 @@ # define EMU_CLOCK_H /* clock_ics9xxx.c */ +extern const device_t ics9xxx_detect_device; extern const device_t ics9150_08_device; extern const device_t ics9248_39_device; +extern const device_t ics9248_81_device; extern const device_t ics9248_98_device; +extern const device_t ics9248_101_device; extern const device_t ics9250_08_device; extern const device_t ics9250_10_device; extern const device_t ics9250_13_device; diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index a04b4e392..45809515f 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -431,6 +431,7 @@ machine_at_6via90ap_init(const machine_t *model) device_add(&via_vt82c686b_device); device_add(&via_vt82c686_sio_device); device_add(&keyboard_ps2_ami_pci_device); + device_add(&ics9250_18_device); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); device_add(&via_vt82c686_hwm_device); /* fans: CPU1, CPU2; temperatures: CPU, System, unused */