I2C overhaul part 5: late, but there's still stuff to do
This commit is contained in:
@@ -652,10 +652,8 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p)
|
||||
static void
|
||||
acpi_i2c_set(acpi_t *dev)
|
||||
{
|
||||
if (dev->i2c) {
|
||||
/* Check direction as well to account for the I2C pull-ups. */
|
||||
if (dev->i2c)
|
||||
i2c_gpio_set(dev->i2c, !(dev->regs.gpio_dir & 0x02) || (dev->regs.gpio_val & 0x02), !(dev->regs.gpio_dir & 0x04) || (dev->regs.gpio_val & 0x04));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -152,9 +152,9 @@ lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
return 0;
|
||||
} else if (dev->i2c_state == 0) {
|
||||
dev->i2c_state = 1;
|
||||
/* Linux lm75.c driver relies on a 3-bit address register that doesn't change if bit 2 is set. */
|
||||
if ((dev->as99127f_i2c_addr >= 0x80) && !(data & 0x04))
|
||||
dev->addr_register = (data & 0x7);
|
||||
/* Linux lm75.c driver relies on the address register not changing if bit 2 is set. */
|
||||
if ((dev->as99127f_i2c_addr < 0x80) || !(data & 0x04))
|
||||
dev->addr_register = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ enum {
|
||||
I2C_TRANSMIT_START,
|
||||
I2C_TRANSMIT,
|
||||
I2C_ACKNOWLEDGE,
|
||||
I2C_NEGACKNOWLEDGE,
|
||||
I2C_NOTACKNOWLEDGE,
|
||||
I2C_TRANSACKNOWLEDGE,
|
||||
I2C_TRANSMIT_WAIT
|
||||
};
|
||||
@@ -131,15 +131,13 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
||||
|
||||
i2c_gpio_log(1, "I2C GPIO %s: Initiating %s address %02X\n", dev->bus_name, dev->slave_read ? "read from" : "write to", dev->slave_addr);
|
||||
|
||||
if (!i2c_has_device(dev->i2c, dev->slave_addr)) {
|
||||
if (!i2c_has_device(dev->i2c, dev->slave_addr) ||
|
||||
((i == 0xff) && !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read))) { /* start only once per transfer */
|
||||
dev->slave_state = SLAVE_INVALID;
|
||||
dev->slave_addr = 0xff;
|
||||
return I2C_NEGACKNOWLEDGE;
|
||||
return I2C_NOTACKNOWLEDGE;
|
||||
}
|
||||
|
||||
if (i == 0xff) /* start only once per transfer */
|
||||
i2c_start(dev->i2c, dev->slave_addr, dev->slave_read);
|
||||
|
||||
if (dev->slave_read) {
|
||||
dev->slave_state = SLAVE_SENDDATA;
|
||||
dev->transmit = TRANSMITTER_SLAVE;
|
||||
@@ -154,17 +152,17 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
||||
i2c_gpio_log(1, "I2C GPIO %s: Receiving address %02X\n", dev->bus_name, dev->byte);
|
||||
dev->slave_state = dev->slave_read ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
||||
if (!i2c_write(dev->i2c, dev->slave_addr, dev->byte))
|
||||
return I2C_NEGACKNOWLEDGE;
|
||||
return I2C_NOTACKNOWLEDGE;
|
||||
break;
|
||||
|
||||
case SLAVE_RECEIVEDATA:
|
||||
i2c_gpio_log(1, "I2C GPIO %s: Receiving data %02X\n", dev->bus_name, dev->byte);
|
||||
if (!i2c_write(dev->i2c, dev->slave_addr, dev->byte))
|
||||
return I2C_NEGACKNOWLEDGE;
|
||||
return I2C_NOTACKNOWLEDGE;
|
||||
break;
|
||||
|
||||
case SLAVE_INVALID:
|
||||
return I2C_NEGACKNOWLEDGE;
|
||||
return I2C_NOTACKNOWLEDGE;
|
||||
}
|
||||
|
||||
return I2C_ACKNOWLEDGE;
|
||||
@@ -236,9 +234,9 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_NEGACKNOWLEDGE:
|
||||
case I2C_NOTACKNOWLEDGE:
|
||||
if (!dev->scl && scl) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Nacking transfer\n", dev->bus_name);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Not acknowledging transfer\n", dev->bus_name);
|
||||
sda = 1;
|
||||
dev->pos = 0;
|
||||
dev->state = I2C_IDLE;
|
||||
|
||||
@@ -186,6 +186,47 @@ write_fifo(serial_t *dev, uint8_t dat)
|
||||
}
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <86box/pit.h>
|
||||
HANDLE serialdbg = NULL;
|
||||
OVERLAPPED serialdbgoverlapped_r;
|
||||
OVERLAPPED serialdbgoverlapped_w;
|
||||
uint8_t serialdbg_reading = 0;
|
||||
DWORD serialdbg_read;
|
||||
uint8_t serialdbg_buf[1];
|
||||
pc_timer_t serialdbgtimer;
|
||||
void
|
||||
serial_dbg_timer(void *p)
|
||||
{
|
||||
double dbps = (double) 115200;
|
||||
double temp = 0.0;
|
||||
int word_len = 32;
|
||||
temp = (double) word_len;
|
||||
temp = (1000000.0 / dbps) * temp;
|
||||
if (serialdbg_reading) {
|
||||
if (HasOverlappedIoCompleted(&serialdbgoverlapped_r)) {
|
||||
if (!GetOverlappedResult(serialdbg, &serialdbgoverlapped_r, &serialdbg_read, FALSE)) {
|
||||
return;
|
||||
}
|
||||
//pclog("overlapped %d\n", serialdbg_read);
|
||||
for (uint32_t i = 0; i < serialdbg_read; i++) {
|
||||
pclog("reading %02X\n", serialdbg_buf[i]);
|
||||
serial_write_fifo((serial_t *) p, serialdbg_buf[i]);
|
||||
}
|
||||
serialdbg_reading = 0;
|
||||
}// else pclog(" not yet\n");
|
||||
} else {
|
||||
if (!ReadFile(serialdbg, serialdbg_buf, sizeof(serialdbg_buf), &serialdbg_read, &serialdbgoverlapped_r) && GetLastError() != ERROR_IO_PENDING) {
|
||||
pclog("serial broken (read) %08X\n", GetLastError());
|
||||
CancelIo(serialdbg);
|
||||
return;
|
||||
}
|
||||
serialdbg_reading = 1;
|
||||
}
|
||||
timer_on_auto(&serialdbgtimer, temp);//((serial_t *) p)->transmit_period);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
serial_write_fifo(serial_t *dev, uint8_t dat)
|
||||
{
|
||||
@@ -193,6 +234,8 @@ serial_write_fifo(serial_t *dev, uint8_t dat)
|
||||
|
||||
if (!(dev->mctrl & 0x10))
|
||||
write_fifo(dev, dat);
|
||||
else
|
||||
pclog("fifo not in rx mode?\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -203,6 +246,14 @@ serial_transmit(serial_t *dev, uint8_t val)
|
||||
write_fifo(dev, val);
|
||||
else if (dev->sd->dev_write)
|
||||
dev->sd->dev_write(dev, dev->sd->priv, val);
|
||||
if (serialdbg && dev->base_address == SERIAL1_ADDR) {
|
||||
uint8_t buf[1];
|
||||
buf[0] = val;
|
||||
pclog("writing %02X...", buf[0]);
|
||||
WriteFile(serialdbg, buf, 1, NULL, &serialdbgoverlapped_w);
|
||||
//while (!HasOverlappedIoCompleted(&serialdbgoverlapped_w));
|
||||
pclog("written\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,6 +374,7 @@ serial_update_speed(serial_t *dev)
|
||||
|
||||
if (timer_is_enabled(&dev->timeout_timer))
|
||||
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
||||
//pclog("SPEED UPDATED!!! %f\n", dev->transmit_period);
|
||||
}
|
||||
|
||||
|
||||
@@ -704,6 +756,15 @@ serial_init(const device_t *info)
|
||||
|
||||
next_inst++;
|
||||
|
||||
if (dev->base_address == SERIAL1_ADDR) {
|
||||
serialdbg = CreateFileA(TEXT("\\\\.\\COM4"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
pclog("%02X\n", GetLastError());
|
||||
if (serialdbg)
|
||||
timer_add(&serialdbgtimer, serial_dbg_timer, dev, 1);
|
||||
else
|
||||
pclog("serial open failed??\n");
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@ static void
|
||||
smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
uint8_t smbus_addr, cmd, read, block_len, prev_stat, timer_bytes = 0;
|
||||
uint16_t i;
|
||||
uint8_t smbus_addr, cmd, read, block_len, prev_stat;
|
||||
uint16_t timer_bytes = 0, i;
|
||||
|
||||
smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val);
|
||||
|
||||
@@ -207,7 +207,7 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x5: /* block R/W */
|
||||
timer_bytes++; /* account for the SMBus length byte now */
|
||||
timer_bytes++; /* count the SMBus length byte now */
|
||||
|
||||
/* fall-through */
|
||||
|
||||
|
||||
@@ -48,12 +48,12 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
const device_t *info;
|
||||
uint8_t slot;
|
||||
uint16_t size;
|
||||
uint16_t row1;
|
||||
uint16_t row2;
|
||||
|
||||
uint8_t data[SPD_DATA_SIZE];
|
||||
void *eeprom;
|
||||
} spd_t;
|
||||
|
||||
|
||||
216
src/mem/spd.c
216
src/mem/spd.c
@@ -33,8 +33,9 @@
|
||||
|
||||
|
||||
int spd_present = 0;
|
||||
spd_t *spd_devices[SPD_MAX_SLOTS];
|
||||
uint8_t spd_data[SPD_MAX_SLOTS][SPD_DATA_SIZE];
|
||||
spd_t *spd_modules[SPD_MAX_SLOTS];
|
||||
|
||||
static const device_t spd_device;
|
||||
|
||||
|
||||
#ifdef ENABLE_SPD_LOG
|
||||
@@ -60,30 +61,30 @@ spd_log(const char *fmt, ...)
|
||||
static void
|
||||
spd_close(void *priv)
|
||||
{
|
||||
spd_t *dev = (spd_t *) priv;
|
||||
spd_log("SPD: close()\n");
|
||||
|
||||
spd_log("SPD: closing slot %d (SMBus %02X)\n", dev->slot, SPD_BASE_ADDR + dev->slot);
|
||||
|
||||
i2c_eeprom_close(dev->eeprom);
|
||||
for (uint8_t i = 0; i < SPD_MAX_SLOTS; i++) {
|
||||
if (spd_modules[i])
|
||||
i2c_eeprom_close(spd_modules[i]->eeprom);
|
||||
}
|
||||
|
||||
spd_present = 0;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
spd_init(const device_t *info)
|
||||
{
|
||||
spd_t *dev = spd_devices[info->local];
|
||||
spd_log("SPD: init()\n");
|
||||
|
||||
spd_log("SPD: initializing slot %d (SMBus %02X)\n", dev->slot, SPD_BASE_ADDR + dev->slot);
|
||||
|
||||
dev->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + dev->slot, spd_data[info->local], SPD_DATA_SIZE, 0);
|
||||
for (uint8_t i = 0; i < SPD_MAX_SLOTS; i++) {
|
||||
if (spd_modules[i])
|
||||
spd_modules[i]->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + i, spd_modules[i]->data, sizeof(spd_modules[i]->data), 0);
|
||||
}
|
||||
|
||||
spd_present = 1;
|
||||
|
||||
return dev;
|
||||
return &spd_modules;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,71 +108,71 @@ comp_ui16_rev(const void *elem1, const void *elem2)
|
||||
|
||||
|
||||
void
|
||||
spd_populate(uint16_t *vslots, uint8_t slot_count, uint16_t total_size, uint16_t min_module_size, uint16_t max_module_size, uint8_t enable_asym)
|
||||
spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t min_module_size, uint16_t max_module_size, uint8_t enable_asym)
|
||||
{
|
||||
uint8_t vslot, next_empty_vslot, split, i;
|
||||
uint8_t row, next_empty_row, split, i;
|
||||
uint16_t asym;
|
||||
|
||||
/* populate vslots with modules in power-of-2 capacities */
|
||||
memset(vslots, 0x00, SPD_MAX_SLOTS << 1);
|
||||
for (vslot = 0; vslot < slot_count && total_size; vslot++) {
|
||||
/* Populate rows with modules in power-of-2 capacities. */
|
||||
memset(rows, 0, SPD_MAX_SLOTS << 1);
|
||||
for (row = 0; row < slot_count && total_size; row++) {
|
||||
/* populate slot */
|
||||
vslots[vslot] = 1 << log2_ui16(MIN(total_size, max_module_size));
|
||||
if (total_size >= vslots[vslot]) {
|
||||
spd_log("SPD: initial vslot %d = %d MB\n", vslot, vslots[vslot]);
|
||||
total_size -= vslots[vslot];
|
||||
rows[row] = 1 << log2_ui16(MIN(total_size, max_module_size));
|
||||
if (total_size >= rows[row]) {
|
||||
spd_log("SPD: Initial row %d = %d MB\n", row, rows[row]);
|
||||
total_size -= rows[row];
|
||||
} else {
|
||||
vslots[vslot] = 0;
|
||||
rows[row] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* did we populate all the RAM? */
|
||||
/* Did we populate all the RAM? */
|
||||
if (total_size) {
|
||||
/* work backwards to add the missing RAM as asymmetric modules if possible */
|
||||
/* Work backwards to add the missing RAM as asymmetric modules if possible. */
|
||||
if (enable_asym) {
|
||||
vslot = slot_count - 1;
|
||||
row = slot_count - 1;
|
||||
do {
|
||||
asym = (1 << log2_ui16(MIN(total_size, vslots[vslot])));
|
||||
if (vslots[vslot] + asym <= max_module_size) {
|
||||
vslots[vslot] += asym;
|
||||
asym = (1 << log2_ui16(MIN(total_size, rows[row])));
|
||||
if (rows[row] + asym <= max_module_size) {
|
||||
rows[row] += asym;
|
||||
total_size -= asym;
|
||||
}
|
||||
} while ((vslot-- > 0) && total_size);
|
||||
} while ((row-- > 0) && total_size);
|
||||
}
|
||||
|
||||
if (total_size) /* still not enough */
|
||||
spd_log("SPD: not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size);
|
||||
spd_log("SPD: Not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size);
|
||||
}
|
||||
|
||||
/* populate empty vslots by splitting modules... */
|
||||
split = (total_size == 0); /* ...if possible */
|
||||
/* Populate empty rows by splitting modules... */
|
||||
split = (total_size == 0); /* ...if possible. */
|
||||
while (split) {
|
||||
/* look for a module to split */
|
||||
/* Look for a module to split. */
|
||||
split = 0;
|
||||
for (vslot = 0; vslot < slot_count; vslot++) {
|
||||
if ((vslots[vslot] < (min_module_size << 1)) || (vslots[vslot] != (1 << log2_ui16(vslots[vslot]))))
|
||||
for (row = 0; row < slot_count; row++) {
|
||||
if ((rows[row] < (min_module_size << 1)) || (rows[row] != (1 << log2_ui16(rows[row]))))
|
||||
continue; /* no module here, module is too small to be split, or asymmetric module */
|
||||
|
||||
/* find next empty vslot */
|
||||
next_empty_vslot = 0;
|
||||
for (i = vslot + 1; i < slot_count && !next_empty_vslot; i++) {
|
||||
if (!vslots[i])
|
||||
next_empty_vslot = i;
|
||||
/* Find next empty row. */
|
||||
next_empty_row = 0;
|
||||
for (i = row + 1; i < slot_count && !next_empty_row; i++) {
|
||||
if (!rows[i])
|
||||
next_empty_row = i;
|
||||
}
|
||||
if (!next_empty_vslot)
|
||||
break; /* no empty vslots left */
|
||||
if (!next_empty_row)
|
||||
break; /* no empty rows left */
|
||||
|
||||
/* split the module into its own vslot and the next empty vslot */
|
||||
spd_log("SPD: splitting vslot %d (%d MB) into %d and %d (%d MB each)\n", vslot, vslots[vslot], vslot, next_empty_vslot, vslots[vslot] >> 1);
|
||||
vslots[vslot] = vslots[next_empty_vslot] = vslots[vslot] >> 1;
|
||||
/* Split the module into its own row and the next empty row. */
|
||||
spd_log("SPD: splitting row %d (%d MB) into %d and %d (%d MB each)\n", row, rows[row], row, next_empty_row, rows[row] >> 1);
|
||||
rows[row] = rows[next_empty_row] = rows[row] >> 1;
|
||||
split = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* sort vslots by descending capacity if any were split */
|
||||
/* Sort rows by descending capacity if any were split. */
|
||||
if (split)
|
||||
qsort(vslots, slot_count, sizeof(uint16_t), comp_ui16_rev);
|
||||
qsort(rows, slot_count, sizeof(uint16_t), comp_ui16_rev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +180,12 @@ spd_populate(uint16_t *vslots, uint8_t slot_count, uint16_t total_size, uint16_t
|
||||
void
|
||||
spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
{
|
||||
uint8_t slot, slot_count, vslot, i;
|
||||
uint16_t min_module_size, vslots[SPD_MAX_SLOTS], asym;
|
||||
device_t *info;
|
||||
uint8_t slot, slot_count, row, i;
|
||||
uint16_t min_module_size, rows[SPD_MAX_SLOTS], asym;
|
||||
spd_edo_t *edo_data;
|
||||
spd_sdram_t *sdram_data;
|
||||
|
||||
/* determine the minimum module size for this RAM type */
|
||||
/* Determine the minimum module size for this RAM type. */
|
||||
switch (ram_type) {
|
||||
case SPD_TYPE_FPM:
|
||||
case SPD_TYPE_EDO:
|
||||
@@ -201,51 +201,42 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
return;
|
||||
}
|
||||
|
||||
/* count how many (real) slots are enabled */
|
||||
/* Count how many slots are enabled. */
|
||||
slot_count = 0;
|
||||
for (slot = 0; slot < SPD_MAX_SLOTS; slot++) {
|
||||
vslots[slot] = 0;
|
||||
if (slot_mask & (1 << slot)) {
|
||||
rows[slot] = 0;
|
||||
if (slot_mask & (1 << slot))
|
||||
slot_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* populate vslots */
|
||||
spd_populate(vslots, slot_count, (mem_size >> 10), min_module_size, max_module_size, 1);
|
||||
/* Populate rows. */
|
||||
spd_populate(rows, slot_count, (mem_size >> 10), min_module_size, max_module_size, 1);
|
||||
|
||||
/* register SPD devices and populate their data according to the vslots */
|
||||
vslot = 0;
|
||||
for (slot = 0; slot < SPD_MAX_SLOTS && vslots[vslot]; slot++) {
|
||||
/* Register SPD devices and populate their data according to the rows. */
|
||||
row = 0;
|
||||
for (slot = 0; slot < SPD_MAX_SLOTS && rows[row]; slot++) {
|
||||
if (!(slot_mask & (1 << slot)))
|
||||
continue; /* slot disabled */
|
||||
|
||||
info = (device_t *) malloc(sizeof(device_t));
|
||||
memset(info, 0, sizeof(device_t));
|
||||
info->name = "Serial Presence Detect ROM";
|
||||
info->local = slot;
|
||||
info->init = spd_init;
|
||||
info->close = spd_close;
|
||||
spd_modules[slot] = (spd_t *) malloc(sizeof(spd_t));
|
||||
memset(spd_modules[slot], 0, sizeof(spd_t));
|
||||
spd_modules[slot]->slot = slot;
|
||||
spd_modules[slot]->size = rows[row];
|
||||
|
||||
spd_devices[slot] = (spd_t *) malloc(sizeof(spd_t));
|
||||
memset(spd_devices[slot], 0, sizeof(spd_t));
|
||||
spd_devices[slot]->info = info;
|
||||
spd_devices[slot]->slot = slot;
|
||||
spd_devices[slot]->size = vslots[vslot];
|
||||
|
||||
/* determine the second row size, from which the first row size can be obtained */
|
||||
asym = vslots[vslot] - (1 << log2_ui16(vslots[vslot])); /* separate the powers of 2 */
|
||||
/* Determine the second row size, from which the first row size can be obtained. */
|
||||
asym = rows[row] - (1 << log2_ui16(rows[row])); /* separate the powers of 2 */
|
||||
if (!asym) /* is the module asymmetric? */
|
||||
asym = vslots[vslot] >> 1; /* symmetric, therefore divide by 2 */
|
||||
asym = rows[row] >> 1; /* symmetric, therefore divide by 2 */
|
||||
|
||||
spd_devices[slot]->row1 = vslots[vslot] - asym;
|
||||
spd_devices[slot]->row2 = asym;
|
||||
spd_modules[slot]->row1 = rows[row] - asym;
|
||||
spd_modules[slot]->row2 = asym;
|
||||
|
||||
spd_log("SPD: registering slot %d = vslot %d = %d MB (%d/%d)\n", slot, vslot, vslots[vslot], spd_devices[slot]->row1, spd_devices[slot]->row2);
|
||||
spd_log("SPD: Registering slot %d = row %d = %d MB (%d/%d)\n", slot, row, rows[row], spd_modules[slot]->row1, spd_modules[slot]->row2);
|
||||
|
||||
switch (ram_type) {
|
||||
case SPD_TYPE_FPM:
|
||||
case SPD_TYPE_EDO:
|
||||
edo_data = (spd_edo_t *) &spd_data[slot];
|
||||
edo_data = (spd_edo_t *) &spd_modules[slot]->data;
|
||||
memset(edo_data, 0, sizeof(spd_edo_t));
|
||||
|
||||
/* EDO SPD is specified by JEDEC and present in some modules, but
|
||||
@@ -254,10 +245,10 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
edo_data->bytes_used = 0x80;
|
||||
edo_data->spd_size = 0x08;
|
||||
edo_data->mem_type = ram_type;
|
||||
edo_data->row_bits = SPD_ROLLUP(7 + log2_ui16(spd_devices[slot]->row1)); /* first row */
|
||||
edo_data->row_bits = SPD_ROLLUP(7 + log2_ui16(spd_modules[slot]->row1)); /* first row */
|
||||
edo_data->col_bits = 9;
|
||||
if (spd_devices[slot]->row1 != spd_devices[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */
|
||||
edo_data->row_bits |= SPD_ROLLUP(7 + log2_ui16(spd_devices[slot]->row2)) << 4; /* second row, if different from first */
|
||||
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */
|
||||
edo_data->row_bits |= SPD_ROLLUP(7 + log2_ui16(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
|
||||
edo_data->col_bits |= 9 << 4; /* same as first row, but just in case */
|
||||
}
|
||||
edo_data->banks = 2;
|
||||
@@ -269,7 +260,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
edo_data->dram_width = 8;
|
||||
|
||||
edo_data->spd_rev = 0x12;
|
||||
sprintf(edo_data->part_no, EMU_NAME "-%s-%03dM", (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", vslots[vslot]);
|
||||
sprintf(edo_data->part_no, EMU_NAME "-%s-%03dM", (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", rows[row]);
|
||||
for (i = strlen(edo_data->part_no); i < sizeof(edo_data->part_no); i++)
|
||||
edo_data->part_no[i] = ' '; /* part number should be space-padded */
|
||||
edo_data->rev_code[0] = BCD8(EMU_VERSION_MAJ);
|
||||
@@ -278,22 +269,22 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
edo_data->mfg_week = 17;
|
||||
|
||||
for (i = 0; i < 63; i++)
|
||||
edo_data->checksum += spd_data[slot][i];
|
||||
edo_data->checksum += spd_modules[slot]->data[i];
|
||||
for (i = 0; i < 129; i++)
|
||||
edo_data->checksum2 += spd_data[slot][i];
|
||||
edo_data->checksum2 += spd_modules[slot]->data[i];
|
||||
break;
|
||||
|
||||
case SPD_TYPE_SDRAM:
|
||||
sdram_data = (spd_sdram_t *) &spd_data[slot];
|
||||
sdram_data = (spd_sdram_t *) &spd_modules[slot]->data;
|
||||
memset(sdram_data, 0, sizeof(spd_sdram_t));
|
||||
|
||||
sdram_data->bytes_used = 0x80;
|
||||
sdram_data->spd_size = 0x08;
|
||||
sdram_data->mem_type = ram_type;
|
||||
sdram_data->row_bits = SPD_ROLLUP(6 + log2_ui16(spd_devices[slot]->row1)); /* first row */
|
||||
sdram_data->row_bits = SPD_ROLLUP(6 + log2_ui16(spd_modules[slot]->row1)); /* first row */
|
||||
sdram_data->col_bits = 9;
|
||||
if (spd_devices[slot]->row1 != spd_devices[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */
|
||||
sdram_data->row_bits |= SPD_ROLLUP(6 + log2_ui16(spd_devices[slot]->row2)) << 4; /* second row, if different from first */
|
||||
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */
|
||||
sdram_data->row_bits |= SPD_ROLLUP(6 + log2_ui16(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
|
||||
sdram_data->col_bits |= 9 << 4; /* same as first row, but just in case */
|
||||
}
|
||||
sdram_data->rows = 2;
|
||||
@@ -313,18 +304,18 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
sdram_data->tclk3 = 0xF0; /* 15 ns = 66.7 MHz */
|
||||
sdram_data->tac2 = sdram_data->tac3 = 0x10;
|
||||
sdram_data->trp = sdram_data->trrd = sdram_data->trcd = sdram_data->tras = 1;
|
||||
if (spd_devices[slot]->row1 != spd_devices[slot]->row2) {
|
||||
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) {
|
||||
/* Utilities interpret bank_density a bit differently on asymmetric modules. */
|
||||
sdram_data->bank_density = 1 << (log2_ui16(spd_devices[slot]->row1 >> 1) - 2); /* first row */
|
||||
sdram_data->bank_density |= 1 << (log2_ui16(spd_devices[slot]->row2 >> 1) - 2); /* second row */
|
||||
sdram_data->bank_density = 1 << (log2_ui16(spd_modules[slot]->row1 >> 1) - 2); /* first row */
|
||||
sdram_data->bank_density |= 1 << (log2_ui16(spd_modules[slot]->row2 >> 1) - 2); /* second row */
|
||||
} else {
|
||||
sdram_data->bank_density = 1 << (log2_ui16(spd_devices[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */
|
||||
sdram_data->bank_density = 1 << (log2_ui16(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */
|
||||
}
|
||||
sdram_data->ca_setup = sdram_data->data_setup = 0x15;
|
||||
sdram_data->ca_hold = sdram_data->data_hold = 0x08;
|
||||
|
||||
sdram_data->spd_rev = 0x12;
|
||||
sprintf(sdram_data->part_no, EMU_NAME "-SDR-%03dM", vslots[vslot]);
|
||||
sprintf(sdram_data->part_no, EMU_NAME "-SDR-%03dM", rows[row]);
|
||||
for (i = strlen(sdram_data->part_no); i < sizeof(sdram_data->part_no); i++)
|
||||
sdram_data->part_no[i] = ' '; /* part number should be space-padded */
|
||||
sdram_data->rev_code[0] = BCD8(EMU_VERSION_MAJ);
|
||||
@@ -336,15 +327,16 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
sdram_data->features = 0xFF;
|
||||
|
||||
for (i = 0; i < 63; i++)
|
||||
sdram_data->checksum += spd_data[slot][i];
|
||||
sdram_data->checksum += spd_modules[slot]->data[i];
|
||||
for (i = 0; i < 129; i++)
|
||||
sdram_data->checksum2 += spd_data[slot][i];
|
||||
sdram_data->checksum2 += spd_modules[slot]->data[i];
|
||||
break;
|
||||
}
|
||||
|
||||
device_add(info);
|
||||
vslot++;
|
||||
row++;
|
||||
}
|
||||
|
||||
device_add(&spd_device);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +344,7 @@ void
|
||||
spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit)
|
||||
{
|
||||
uint8_t row, dimm, drb, apollo = 0;
|
||||
uint16_t size, vslots[SPD_MAX_SLOTS];
|
||||
uint16_t size, rows[SPD_MAX_SLOTS];
|
||||
|
||||
/* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */
|
||||
if (reg_max < reg_min) {
|
||||
@@ -363,26 +355,26 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit
|
||||
/* No SPD: split SIMMs into pairs as if they were "DIMM"s. */
|
||||
if (!spd_present) {
|
||||
dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
|
||||
spd_populate(vslots, dimm, mem_size >> 10, drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
|
||||
spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
|
||||
}
|
||||
|
||||
/* Write DRBs for each row. */
|
||||
spd_log("Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
|
||||
spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
|
||||
for (row = 0; row <= (reg_max - reg_min); row++) {
|
||||
dimm = (row >> 1);
|
||||
size = 0;
|
||||
|
||||
if (spd_present) {
|
||||
/* SPD enabled: use SPD info for this slot, if present. */
|
||||
if (spd_devices[dimm]) {
|
||||
if (spd_devices[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */
|
||||
if (spd_modules[dimm]) {
|
||||
if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */
|
||||
size = (row & 1) ? 0 : drb_unit;
|
||||
else
|
||||
size = (row & 1) ? spd_devices[dimm]->row2 : spd_devices[dimm]->row1;
|
||||
size = (row & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1;
|
||||
}
|
||||
} else {
|
||||
/* No SPD: use the values calculated above. */
|
||||
size = (vslots[dimm] >> 1);
|
||||
size = (rows[dimm] >> 1);
|
||||
}
|
||||
|
||||
/* Determine the DRB register to write. */
|
||||
@@ -399,6 +391,16 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit
|
||||
regs[drb] = regs[drb - 1];
|
||||
if (size)
|
||||
regs[drb] += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */
|
||||
spd_log("DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]);
|
||||
spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const device_t spd_device = {
|
||||
"Serial Presence Detect ROMs",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
spd_init, spd_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
/* Flag set if this is a tagged command. */
|
||||
#define NCR_TAG_VALID (1 << 16)
|
||||
|
||||
#define NCR_NVRAM_SIZE 2048
|
||||
#define NCR_BUF_SIZE 4096
|
||||
|
||||
typedef struct ncr53c8xx_request {
|
||||
@@ -226,9 +227,9 @@ typedef struct {
|
||||
int msg_action;
|
||||
int msg_len;
|
||||
uint8_t msg[NCR_MAX_MSGIN_LEN];
|
||||
uint8_t nvram[2048]; /* 24C16 EEPROM (16 kbit) */
|
||||
uint8_t nvram[NCR_NVRAM_SIZE]; /* 24C16 EEPROM (16 Kbit) */
|
||||
void *i2c, *eeprom;
|
||||
uint8_t ram[NCR_BUF_SIZE]; /* NCR 53c875 RAM (4 kB). */
|
||||
uint8_t ram[NCR_BUF_SIZE]; /* NCR 53C875 RAM (4 KB) */
|
||||
/* 0 if SCRIPTS are running or stopped.
|
||||
* 1 if a Wait Reselect instruction has been issued.
|
||||
* 2 if processing DMA from ncr53c8xx_execute_script.
|
||||
@@ -2584,15 +2585,15 @@ ncr53c8xx_close(void *priv)
|
||||
ncr53c8xx_t *dev = (ncr53c8xx_t *)priv;
|
||||
|
||||
if (dev) {
|
||||
/* Save the serial EEPROM. */
|
||||
ncr53c8xx_eeprom(dev, 1);
|
||||
|
||||
if (dev->eeprom)
|
||||
i2c_eeprom_close(dev->eeprom);
|
||||
|
||||
if (dev->i2c)
|
||||
i2c_gpio_close(dev->i2c);
|
||||
|
||||
/* Save the serial EEPROM. */
|
||||
ncr53c8xx_eeprom(dev, 1);
|
||||
|
||||
free(dev);
|
||||
dev = NULL;
|
||||
}
|
||||
@@ -2611,7 +2612,7 @@ static const device_config_t ncr53c8xx_pci_config[] = {
|
||||
|
||||
const device_t ncr53c810_pci_device =
|
||||
{
|
||||
"NCR 53c810",
|
||||
"NCR 53C810",
|
||||
DEVICE_PCI,
|
||||
0x01,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
@@ -2621,7 +2622,7 @@ const device_t ncr53c810_pci_device =
|
||||
|
||||
const device_t ncr53c810_onboard_pci_device =
|
||||
{
|
||||
"NCR 53c810 On-Board",
|
||||
"NCR 53C810 On-Board",
|
||||
DEVICE_PCI,
|
||||
0x8001,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
@@ -2631,7 +2632,7 @@ const device_t ncr53c810_onboard_pci_device =
|
||||
|
||||
const device_t ncr53c825a_pci_device =
|
||||
{
|
||||
"NCR 53c825A",
|
||||
"NCR 53C825A",
|
||||
DEVICE_PCI,
|
||||
CHIP_825,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
@@ -2641,7 +2642,7 @@ const device_t ncr53c825a_pci_device =
|
||||
|
||||
const device_t ncr53c860_pci_device =
|
||||
{
|
||||
"NCR 53c860",
|
||||
"NCR 53C860",
|
||||
DEVICE_PCI,
|
||||
CHIP_860,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
@@ -2651,7 +2652,7 @@ const device_t ncr53c860_pci_device =
|
||||
|
||||
const device_t ncr53c875_pci_device =
|
||||
{
|
||||
"NCR 53c875",
|
||||
"NCR 53C875",
|
||||
DEVICE_PCI,
|
||||
CHIP_875,
|
||||
ncr53c8xx_init, ncr53c8xx_close, NULL,
|
||||
|
||||
@@ -2383,8 +2383,8 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p)
|
||||
svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT);
|
||||
ati68860_set_ramdac_type(mach64->svga.ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT);
|
||||
data = (val & (1 << 4)) ? ((val & (1 << 1)) ? 1 : 0) : 1;
|
||||
clk = (val & (1 << 5)) ? ((val & (1 << 2)) ? 1 : 0) : 1;
|
||||
i2c_gpio_set(mach64->i2c, clk, data);
|
||||
clk = (val & (1 << 5)) ? ((val & (1 << 2)) ? 1 : 0) : 1;
|
||||
i2c_gpio_set(mach64->i2c, clk, data);
|
||||
break;
|
||||
|
||||
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
|
||||
@@ -3372,7 +3372,7 @@ static void *mach64_common_init(const device_t *info)
|
||||
mach64->fifo_thread = thread_create(fifo_thread, mach64);
|
||||
|
||||
mach64->i2c = i2c_gpio_init("ddc_ati_mach64");
|
||||
mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c));
|
||||
mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c));
|
||||
|
||||
return mach64;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <86box/dma.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/vid_ddc.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
|
||||
@@ -499,6 +501,8 @@ typedef struct mystique_t
|
||||
|
||||
mutex_t *lock;
|
||||
} dma;
|
||||
|
||||
void *i2c, *ddc;
|
||||
} mystique_t;
|
||||
|
||||
|
||||
@@ -1020,6 +1024,17 @@ mystique_read_xreg(mystique_t *mystique, int reg)
|
||||
break;
|
||||
case XREG_XGENIODATA:
|
||||
ret = mystique->xgeniodata;
|
||||
|
||||
if (!(mystique->xgenioctrl & 0x08)) {
|
||||
ret &= 0xf7;
|
||||
if (i2c_gpio_get_scl(mystique->i2c))
|
||||
ret |= 0x08;
|
||||
}
|
||||
if (!(mystique->xgenioctrl & 0x02)) {
|
||||
ret &= 0xfd;
|
||||
if (i2c_gpio_get_sda(mystique->i2c))
|
||||
ret |= 0x02;
|
||||
}
|
||||
break;
|
||||
|
||||
case XREG_XSYSPLLM:
|
||||
@@ -1154,6 +1169,7 @@ mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val)
|
||||
|
||||
case XREG_XGENIOCTRL:
|
||||
mystique->xgenioctrl = val;
|
||||
i2c_gpio_set(mystique->i2c, !(mystique->xgenioctrl & 0x08) || (mystique->xgeniodata & 0x08), !(mystique->xgenioctrl & 0x02) || (mystique->xgeniodata & 0x02));
|
||||
break;
|
||||
case XREG_XGENIODATA:
|
||||
mystique->xgeniodata = val;
|
||||
@@ -5009,6 +5025,9 @@ mystique_init(const device_t *info)
|
||||
|
||||
mystique->svga.vsync_callback = mystique_vsync_callback;
|
||||
|
||||
mystique->i2c = i2c_gpio_init("ddc_mga");
|
||||
mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c));
|
||||
|
||||
return mystique;
|
||||
}
|
||||
|
||||
@@ -5025,6 +5044,9 @@ mystique_close(void *p)
|
||||
|
||||
svga_close(&mystique->svga);
|
||||
|
||||
ddc_close(mystique->ddc);
|
||||
i2c_gpio_close(mystique->i2c);
|
||||
|
||||
free(mystique);
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ typedef struct virge_t
|
||||
int virge_busy;
|
||||
|
||||
uint8_t subsys_stat, subsys_cntl, advfunc_cntl;
|
||||
|
||||
|
||||
uint8_t serialport;
|
||||
|
||||
void *i2c, *ddc;
|
||||
@@ -901,7 +901,7 @@ s3_virge_mmio_read(uint32_t addr, void *p)
|
||||
ret |= SERIAL_PORT_SCR;
|
||||
if ((virge->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c))
|
||||
ret |= SERIAL_PORT_SDR;
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
@@ -3848,8 +3848,8 @@ static void *s3_virge_init(const device_t *info)
|
||||
virge->fifo_not_full_event = thread_create_event();
|
||||
virge->fifo_thread = thread_create(fifo_thread, virge);
|
||||
|
||||
virge->i2c = i2c_gpio_init("ddc_s3_virge");
|
||||
virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c));
|
||||
virge->i2c = i2c_gpio_init("ddc_s3_virge");
|
||||
virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c));
|
||||
|
||||
return virge;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user