CS423x: Refactor EEPROM-less mode

This commit is contained in:
RichardG867
2025-01-18 14:57:05 -03:00
parent 9dd6a1b29f
commit f6175add8f

View File

@@ -87,11 +87,9 @@ static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0
0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2,
0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13,
0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A };
static const uint8_t cs4236b_eeprom[8224] = {
static const uint8_t cs4236b_default[] = {
// clang-format off
/* Chip configuration */
0x55, 0xbb, /* magic */
0x00, 0x00, /* length */
0x00, 0x03, /* CD-ROM and modem decode */
0x80, /* misc. config */
0x80, /* global config */
@@ -102,8 +100,9 @@ static const uint8_t cs4236b_eeprom[8224] = {
0x75, 0xb9, 0xfc, /* IRQ routing */
0x10, 0x03, /* DMA routing */
/* PnP resources */
0x00
/* Default PnP resources */
/* TODO: broken, not picked up by VS440FX BIOS, pending hardware research of the actual defaults */
0x0e, 0x63, 0x42, 0x36, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x10, 0x00, 0x14, 0x41, 0xd0, 0xff, 0xff, 0x79, 0x00
// clang-format on
};
@@ -122,6 +121,7 @@ typedef struct cs423x_t {
uint16_t ram_addr;
uint16_t eeprom_size : 11;
uint16_t pnp_offset;
uint16_t pnp_size;
uint8_t type;
uint8_t ad1848_type;
uint8_t regs[8];
@@ -363,7 +363,8 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
cs423x_t *dev = (cs423x_t *) priv;
uint8_t idx;
cs423x_log("CS423x: slam_write(%02X)\n", val);
if ((dev->slam_state != CRYSTAL_SLAM_NONE) || (val == slam_init_key[dev->key_pos])) /* cut down on ISAPnP-related noise */
cs423x_log("CS423x: slam_write(%02X)\n", val);
switch (dev->slam_state) {
case CRYSTAL_SLAM_NONE:
@@ -599,7 +600,7 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig)
if (dev->pnp_card) {
/* Update PnP resource data if requested. */
if (update_rom)
isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], 384);
isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], dev->pnp_size);
/* Disable PnP key if the PKD bit is set, or if it was disabled by command 0x55. */
/* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't
@@ -753,9 +754,21 @@ cs423x_reset(void *priv)
/* Clear RAM. */
memset(dev->ram_data, 0, sizeof(dev->ram_data));
/* Load default configuration data to RAM. */
memcpy(&dev->ram_data[0x4000], cs4236b_default, sizeof(cs4236b_default));
dev->pnp_size = 19;
if (dev->eeprom) {
/* Load EEPROM data to RAM. */
memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], MIN(384, ((dev->eeprom_data[2] << 8) | dev->eeprom_data[3]) - 4));
/* Load EEPROM data to RAM if the magic bytes are present. */
if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb)) {
cs423x_log("CS423x: EEPROM data valid, loading to RAM\n");
dev->pnp_size = (dev->eeprom_data[2] << 8) | dev->eeprom_data[3];
if (dev->pnp_size > 384)
dev->pnp_size = 384;
memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], sizeof(dev->eeprom_data) - 4);
} else {
cs423x_log("CS423x: EEPROM data invalid, ignoring\n");
}
/* Save EEPROM contents to file. */
cs423x_nvram(dev, 1);
@@ -800,30 +813,41 @@ cs423x_init(const device_t *info)
dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236;
dev->pnp_offset = 0x4013;
/* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init */
/* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init. */
dev->ad1848.xregs[25] = dev->type;
if (!(info->local & CRYSTAL_NOEEPROM)) {
/* Load EEPROM contents from template. */
memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom));
/* Copy default configuration data. */
memcpy(&dev->eeprom_data[4], cs4236b_default, sizeof(cs4236b_default));
/* Load PnP resource data ROM. */
FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb");
if (fp) {
(void) !fread(&(dev->eeprom_data[23]), 1, 8201, fp);
uint16_t eeprom_pnp_offset = (dev->pnp_offset & 0x1ff) + 4;
/* This is wrong. The header field only indicates PnP resource data length, and real chips use
it to locate the firmware patch area, but we don't need any of that, so we can get away
with pretending the whole ROM is PnP data, at least until we can get full EEPROM dumps. */
dev->pnp_size = fread(&dev->eeprom_data[eeprom_pnp_offset], 1, sizeof(dev->eeprom_data) - eeprom_pnp_offset, fp);
fclose(fp);
}
/* Set content size. */
dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8;
dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff;
/* Populate EEPROM header if the PnP ROM was loaded. */
if (dev->pnp_size) {
dev->eeprom_data[0] = 0x55;
dev->eeprom_data[1] = 0xbb;
dev->eeprom_data[2] = dev->pnp_size >> 8;
dev->eeprom_data[3] = dev->pnp_size;
}
/* Set PnP card ID and EEPROM file name. */
/* Patch PnP ROM and set EEPROM file name. */
switch (dev->type) {
case CRYSTAL_CS4235:
dev->eeprom_data[8] = 0x05;
dev->eeprom_data[16] = 0x08;
dev->eeprom_data[26] = 0x25;
dev->eeprom_data[44] = '5';
if (dev->pnp_size) {
dev->eeprom_data[8] = 0x05;
dev->eeprom_data[16] = 0x08;
dev->eeprom_data[26] = 0x25;
dev->eeprom_data[44] = '5';
}
dev->nvr_path = "cs4235.nvr";
break;
@@ -832,14 +856,18 @@ cs423x_init(const device_t *info)
break;
case CRYSTAL_CS4237B:
dev->eeprom_data[26] = 0x37;
dev->eeprom_data[44] = '7';
if (dev->pnp_size) {
dev->eeprom_data[26] = 0x37;
dev->eeprom_data[44] = '7';
}
dev->nvr_path = "cs4237b.nvr";
break;
case CRYSTAL_CS4238B:
dev->eeprom_data[26] = 0x38;
dev->eeprom_data[44] = '8';
if (dev->pnp_size) {
dev->eeprom_data[26] = 0x38;
dev->eeprom_data[44] = '8';
}
dev->nvr_path = "cs4238b.nvr";
break;
@@ -864,8 +892,8 @@ cs423x_init(const device_t *info)
/* Initialize I2C bus for the EEPROM. */
dev->i2c = i2c_gpio_init("nvr_cs423x");
/* Initialize I2C EEPROM if the contents are valid. */
if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb))
/* Initialize I2C EEPROM if enabled. */
if (!(info->local & CRYSTAL_NOEEPROM))
dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1);
/* Initialize ISAPnP. */