mirror of
https://github.com/86Box/86Box.git
synced 2025-01-22 09:11:50 -05:00
Merge branch 'master' of https://github.com/86Box/86Box
This commit is contained in:
commit
4123fad19b
1 changed files with 128 additions and 41 deletions
|
@ -15,12 +15,13 @@
|
||||||
* Copyright 2021-2022 RichardG.
|
* Copyright 2021-2022 RichardG.
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/dma.h>
|
#include <86box/dma.h>
|
||||||
|
@ -51,6 +52,12 @@ enum {
|
||||||
CRYSTAL_CS4237B = 0xc8,
|
CRYSTAL_CS4237B = 0xc8,
|
||||||
CRYSTAL_CS4238B = 0xc9
|
CRYSTAL_CS4238B = 0xc9
|
||||||
};
|
};
|
||||||
|
enum {
|
||||||
|
CRYSTAL_RAM_CMD = 0,
|
||||||
|
CRYSTAL_RAM_ADDR_LO = 1,
|
||||||
|
CRYSTAL_RAM_ADDR_HI = 2,
|
||||||
|
CRYSTAL_RAM_DATA = 3
|
||||||
|
};
|
||||||
enum {
|
enum {
|
||||||
CRYSTAL_SLAM_NONE = 0,
|
CRYSTAL_SLAM_NONE = 0,
|
||||||
CRYSTAL_SLAM_INDEX = 1,
|
CRYSTAL_SLAM_INDEX = 1,
|
||||||
|
@ -58,15 +65,31 @@ enum {
|
||||||
CRYSTAL_SLAM_BYTE2 = 3
|
CRYSTAL_SLAM_BYTE2 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_CS423X_LOG
|
||||||
|
int cs423x_do_log = ENABLE_CS423X_LOG;
|
||||||
|
|
||||||
|
static void
|
||||||
|
cs423x_log(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (cs423x_do_log) {
|
||||||
|
va_start(ap, fmt);
|
||||||
|
pclog_ex(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define cs423x_log(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0x79, 0xBC,
|
static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0x79, 0xBC,
|
||||||
0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2,
|
0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2,
|
||||||
0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13,
|
0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13,
|
||||||
0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A };
|
0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A };
|
||||||
static const uint8_t cs4236b_eeprom[8224] = {
|
static const uint8_t cs4236b_default[] = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
/* Chip configuration */
|
/* Chip configuration */
|
||||||
0x55, 0xbb, /* magic */
|
|
||||||
0x00, 0x00, /* length */
|
|
||||||
0x00, 0x03, /* CD-ROM and modem decode */
|
0x00, 0x03, /* CD-ROM and modem decode */
|
||||||
0x80, /* misc. config */
|
0x80, /* misc. config */
|
||||||
0x80, /* global config */
|
0x80, /* global config */
|
||||||
|
@ -77,8 +100,9 @@ static const uint8_t cs4236b_eeprom[8224] = {
|
||||||
0x75, 0xb9, 0xfc, /* IRQ routing */
|
0x75, 0xb9, 0xfc, /* IRQ routing */
|
||||||
0x10, 0x03, /* DMA routing */
|
0x10, 0x03, /* DMA routing */
|
||||||
|
|
||||||
/* PnP resources */
|
/* Default PnP resources */
|
||||||
0x00
|
/* 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
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,6 +121,7 @@ typedef struct cs423x_t {
|
||||||
uint16_t ram_addr;
|
uint16_t ram_addr;
|
||||||
uint16_t eeprom_size : 11;
|
uint16_t eeprom_size : 11;
|
||||||
uint16_t pnp_offset;
|
uint16_t pnp_offset;
|
||||||
|
uint16_t pnp_size;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t ad1848_type;
|
uint8_t ad1848_type;
|
||||||
uint8_t regs[8];
|
uint8_t regs[8];
|
||||||
|
@ -130,6 +155,8 @@ cs423x_nvram(cs423x_t *dev, uint8_t save)
|
||||||
else
|
else
|
||||||
(void) !fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, fp);
|
(void) !fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
cs423x_log("CS423x: EEPROM data %s failed\n", save ? "save" : "load");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,14 +174,24 @@ cs423x_read(uint16_t addr, void *priv)
|
||||||
ret |= 0x04;
|
ret |= 0x04;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3: /* Control Indirect Access Register */
|
||||||
|
/* Intel VS440FX BIOS tells CS4236 from CS4232 through the upper bits. Setting them is enough. */
|
||||||
|
ret |= 0xf0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 4: /* Control Indirect Data Register */
|
case 4: /* Control Indirect Data Register */
|
||||||
ret = dev->indirect_regs[dev->regs[3]];
|
ret = dev->indirect_regs[dev->regs[3]];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* Control/RAM Access */
|
case 5: /* Control/RAM Access */
|
||||||
/* Reading RAM is undocumented; the Windows drivers do so. */
|
/* Reading RAM is undocumented, but performed by:
|
||||||
if (dev->ram_dl == 3)
|
- Windows drivers (unknown purpose)
|
||||||
ret = dev->ram_data[dev->ram_addr++];
|
- Intel VS440FX BIOS (PnP ROM checksum recalculation) */
|
||||||
|
if (dev->ram_dl == CRYSTAL_RAM_DATA) {
|
||||||
|
ret = dev->ram_data[dev->ram_addr];
|
||||||
|
cs423x_log("CS423x: RAM read(%04X) = %02X\n", dev->ram_addr, ret);
|
||||||
|
dev->ram_addr++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* Global Status */
|
case 7: /* Global Status */
|
||||||
|
@ -175,6 +212,8 @@ cs423x_read(uint16_t addr, void *priv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cs423x_log("CS423x: read(%X) = %02X\n", reg, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +221,9 @@ static void
|
||||||
cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
cs423x_t *dev = (cs423x_t *) priv;
|
cs423x_t *dev = (cs423x_t *) priv;
|
||||||
uint8_t reg = addr & 0x07;
|
uint8_t reg = addr & 7;
|
||||||
|
|
||||||
|
cs423x_log("CS423x: write(%X, %02X)\n", reg, val);
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 1: /* EEPROM Interface */
|
case 1: /* EEPROM Interface */
|
||||||
|
@ -248,7 +289,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
|
|
||||||
case 5: /* Control/RAM Access */
|
case 5: /* Control/RAM Access */
|
||||||
switch (dev->ram_dl) {
|
switch (dev->ram_dl) {
|
||||||
case 0: /* commands */
|
case CRYSTAL_RAM_CMD: /* commands */
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0x55: /* Disable PnP Key */
|
case 0x55: /* Disable PnP Key */
|
||||||
dev->pnp_enable = 0;
|
dev->pnp_enable = 0;
|
||||||
|
@ -266,7 +307,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xaa: /* Download RAM */
|
case 0xaa: /* Download RAM */
|
||||||
dev->ram_dl = 1;
|
dev->ram_dl = CRYSTAL_RAM_ADDR_LO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -274,17 +315,19 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* low address byte */
|
case CRYSTAL_RAM_ADDR_LO: /* low address byte */
|
||||||
dev->ram_addr = val;
|
dev->ram_addr = val;
|
||||||
dev->ram_dl++;
|
dev->ram_dl = CRYSTAL_RAM_ADDR_HI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* high address byte */
|
case CRYSTAL_RAM_ADDR_HI: /* high address byte */
|
||||||
dev->ram_addr |= (val << 8);
|
dev->ram_addr |= val << 8;
|
||||||
dev->ram_dl++;
|
dev->ram_dl = CRYSTAL_RAM_DATA;
|
||||||
|
cs423x_log("CS423x: RAM start(%04X)\n", dev->ram_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* data */
|
case CRYSTAL_RAM_DATA: /* data */
|
||||||
|
cs423x_log("CS423x: RAM write(%04X, %02X)\n", dev->ram_addr, val);
|
||||||
dev->ram_data[dev->ram_addr++] = val;
|
dev->ram_data[dev->ram_addr++] = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -296,7 +339,8 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
case 6: /* RAM Access End */
|
case 6: /* RAM Access End */
|
||||||
/* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */
|
/* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */
|
||||||
if ((val == 0x00) || (val == 0x40)) {
|
if ((val == 0x00) || (val == 0x40)) {
|
||||||
dev->ram_dl = 0;
|
cs423x_log("CS423x: RAM end\n");
|
||||||
|
dev->ram_dl = CRYSTAL_RAM_CMD;
|
||||||
|
|
||||||
/* Update PnP state and resource data. */
|
/* Update PnP state and resource data. */
|
||||||
cs423x_pnp_enable(dev, 1, 0);
|
cs423x_pnp_enable(dev, 1, 0);
|
||||||
|
@ -319,6 +363,9 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||||
cs423x_t *dev = (cs423x_t *) priv;
|
cs423x_t *dev = (cs423x_t *) priv;
|
||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
|
|
||||||
|
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) {
|
switch (dev->slam_state) {
|
||||||
case CRYSTAL_SLAM_NONE:
|
case CRYSTAL_SLAM_NONE:
|
||||||
/* Not in SLAM: read and compare Crystal key. */
|
/* Not in SLAM: read and compare Crystal key. */
|
||||||
|
@ -333,6 +380,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter SLAM. */
|
/* Enter SLAM. */
|
||||||
|
cs423x_log("CS423x: SLAM unlocked\n");
|
||||||
dev->slam_state = CRYSTAL_SLAM_INDEX;
|
dev->slam_state = CRYSTAL_SLAM_INDEX;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -343,6 +391,8 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||||
case CRYSTAL_SLAM_INDEX:
|
case CRYSTAL_SLAM_INDEX:
|
||||||
/* Intercept the Activate Audio Device command. */
|
/* Intercept the Activate Audio Device command. */
|
||||||
if (val == 0x79) {
|
if (val == 0x79) {
|
||||||
|
cs423x_log("CS423x: Exiting SLAM\n");
|
||||||
|
|
||||||
/* Apply the last logical device's configuration. */
|
/* Apply the last logical device's configuration. */
|
||||||
if (dev->slam_config) {
|
if (dev->slam_config) {
|
||||||
cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev);
|
cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev);
|
||||||
|
@ -363,6 +413,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||||
case CRYSTAL_SLAM_BYTE1:
|
case CRYSTAL_SLAM_BYTE1:
|
||||||
case CRYSTAL_SLAM_BYTE2:
|
case CRYSTAL_SLAM_BYTE2:
|
||||||
/* Write register value: two bytes for I/O ports, single byte otherwise. */
|
/* Write register value: two bytes for I/O ports, single byte otherwise. */
|
||||||
|
cs423x_log("CS423x: SLAM write(%02X, %02X)\n", dev->slam_reg, val);
|
||||||
switch (dev->slam_reg) {
|
switch (dev->slam_reg) {
|
||||||
case 0x06: /* Card Select Number */
|
case 0x06: /* Card Select Number */
|
||||||
isapnp_set_csn(dev->pnp_card, val);
|
isapnp_set_csn(dev->pnp_card, val);
|
||||||
|
@ -433,7 +484,7 @@ cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for the next register, unless a two-byte read returns above. */
|
/* Prepare for the next register, unless a two-byte write returns above. */
|
||||||
dev->slam_state = CRYSTAL_SLAM_INDEX;
|
dev->slam_state = CRYSTAL_SLAM_INDEX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -454,8 +505,11 @@ cs423x_slam_enable(cs423x_t *dev, uint8_t enable)
|
||||||
|
|
||||||
/* Enable SLAM if the CKD bit is not set. */
|
/* Enable SLAM if the CKD bit is not set. */
|
||||||
if (enable && !(dev->ram_data[0x4002] & 0x10)) {
|
if (enable && !(dev->ram_data[0x4002] & 0x10)) {
|
||||||
|
cs423x_log("CS423x: Enabling SLAM\n");
|
||||||
dev->slam_enable = 1;
|
dev->slam_enable = 1;
|
||||||
io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev);
|
io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev);
|
||||||
|
} else {
|
||||||
|
cs423x_log("CS423x: Disabling SLAM\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +525,7 @@ cs423x_ctxswitch_write(uint16_t addr, UNUSED(uint8_t val), void *priv)
|
||||||
/* Flip context bit. */
|
/* Flip context bit. */
|
||||||
dev->regs[7] ^= 0x80;
|
dev->regs[7] ^= 0x80;
|
||||||
ctx ^= 0x80;
|
ctx ^= 0x80;
|
||||||
|
cs423x_log("CS423x: Context switch to %s\n", ctx ? "WSS" : "SBPro");
|
||||||
|
|
||||||
/* Update CD audio filter.
|
/* Update CD audio filter.
|
||||||
FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */
|
FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */
|
||||||
|
@ -540,10 +595,12 @@ cs423x_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||||
static void
|
static void
|
||||||
cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig)
|
cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig)
|
||||||
{
|
{
|
||||||
|
cs423x_log("CS423x: Updating PnP ROM=%d hwconfig=%d\n", update_rom, update_hwconfig);
|
||||||
|
|
||||||
if (dev->pnp_card) {
|
if (dev->pnp_card) {
|
||||||
/* Update PnP resource data if requested. */
|
/* Update PnP resource data if requested. */
|
||||||
if (update_rom)
|
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. */
|
/* 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
|
/* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't
|
||||||
|
@ -697,9 +754,21 @@ cs423x_reset(void *priv)
|
||||||
/* Clear RAM. */
|
/* Clear RAM. */
|
||||||
memset(dev->ram_data, 0, sizeof(dev->ram_data));
|
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) {
|
if (dev->eeprom) {
|
||||||
/* Load EEPROM data to RAM. */
|
/* Load EEPROM data to RAM if the magic bytes are present. */
|
||||||
memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], MIN(384, ((dev->eeprom_data[2] << 8) | dev->eeprom_data[3]) - 4));
|
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. */
|
/* Save EEPROM contents to file. */
|
||||||
cs423x_nvram(dev, 1);
|
cs423x_nvram(dev, 1);
|
||||||
|
@ -734,6 +803,7 @@ cs423x_init(const device_t *info)
|
||||||
|
|
||||||
/* Initialize model-specific data. */
|
/* Initialize model-specific data. */
|
||||||
dev->type = info->local & 0xff;
|
dev->type = info->local & 0xff;
|
||||||
|
cs423x_log("CS423x: init(%02X)\n", dev->type);
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
case CRYSTAL_CS4235:
|
case CRYSTAL_CS4235:
|
||||||
case CRYSTAL_CS4236B:
|
case CRYSTAL_CS4236B:
|
||||||
|
@ -743,30 +813,41 @@ cs423x_init(const device_t *info)
|
||||||
dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236;
|
dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236;
|
||||||
dev->pnp_offset = 0x4013;
|
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;
|
dev->ad1848.xregs[25] = dev->type;
|
||||||
|
|
||||||
if (!(info->local & CRYSTAL_NOEEPROM)) {
|
if (!(info->local & CRYSTAL_NOEEPROM)) {
|
||||||
/* Load EEPROM contents from template. */
|
/* Copy default configuration data. */
|
||||||
memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom));
|
memcpy(&dev->eeprom_data[4], cs4236b_default, sizeof(cs4236b_default));
|
||||||
|
|
||||||
|
/* Load PnP resource data ROM. */
|
||||||
FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb");
|
FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb");
|
||||||
if (fp) {
|
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);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set content size. */
|
/* Populate EEPROM header if the PnP ROM was loaded. */
|
||||||
dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8;
|
if (dev->pnp_size) {
|
||||||
dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff;
|
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) {
|
switch (dev->type) {
|
||||||
case CRYSTAL_CS4235:
|
case CRYSTAL_CS4235:
|
||||||
dev->eeprom_data[8] = 0x05;
|
if (dev->pnp_size) {
|
||||||
dev->eeprom_data[16] = 0x08;
|
dev->eeprom_data[8] = 0x05;
|
||||||
dev->eeprom_data[26] = 0x25;
|
dev->eeprom_data[16] = 0x08;
|
||||||
dev->eeprom_data[44] = '5';
|
dev->eeprom_data[26] = 0x25;
|
||||||
|
dev->eeprom_data[44] = '5';
|
||||||
|
}
|
||||||
dev->nvr_path = "cs4235.nvr";
|
dev->nvr_path = "cs4235.nvr";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -775,14 +856,18 @@ cs423x_init(const device_t *info)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CRYSTAL_CS4237B:
|
case CRYSTAL_CS4237B:
|
||||||
dev->eeprom_data[26] = 0x37;
|
if (dev->pnp_size) {
|
||||||
dev->eeprom_data[44] = '7';
|
dev->eeprom_data[26] = 0x37;
|
||||||
|
dev->eeprom_data[44] = '7';
|
||||||
|
}
|
||||||
dev->nvr_path = "cs4237b.nvr";
|
dev->nvr_path = "cs4237b.nvr";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CRYSTAL_CS4238B:
|
case CRYSTAL_CS4238B:
|
||||||
dev->eeprom_data[26] = 0x38;
|
if (dev->pnp_size) {
|
||||||
dev->eeprom_data[44] = '8';
|
dev->eeprom_data[26] = 0x38;
|
||||||
|
dev->eeprom_data[44] = '8';
|
||||||
|
}
|
||||||
dev->nvr_path = "cs4238b.nvr";
|
dev->nvr_path = "cs4238b.nvr";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -807,8 +892,8 @@ cs423x_init(const device_t *info)
|
||||||
/* Initialize I2C bus for the EEPROM. */
|
/* Initialize I2C bus for the EEPROM. */
|
||||||
dev->i2c = i2c_gpio_init("nvr_cs423x");
|
dev->i2c = i2c_gpio_init("nvr_cs423x");
|
||||||
|
|
||||||
/* Initialize I2C EEPROM if the contents are valid. */
|
/* Initialize I2C EEPROM if enabled. */
|
||||||
if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb))
|
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);
|
dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1);
|
||||||
|
|
||||||
/* Initialize ISAPnP. */
|
/* Initialize ISAPnP. */
|
||||||
|
@ -836,6 +921,8 @@ cs423x_close(void *priv)
|
||||||
{
|
{
|
||||||
cs423x_t *dev = (cs423x_t *) priv;
|
cs423x_t *dev = (cs423x_t *) priv;
|
||||||
|
|
||||||
|
cs423x_log("CS423x: close()\n");
|
||||||
|
|
||||||
/* Save EEPROM contents to file. */
|
/* Save EEPROM contents to file. */
|
||||||
if (dev->eeprom) {
|
if (dev->eeprom) {
|
||||||
cs423x_nvram(dev, 1);
|
cs423x_nvram(dev, 1);
|
||||||
|
|
Loading…
Reference in a new issue