Added the CMD640 (but the associated PB520R is not yet properly done, needs the 82091AA, so it's disabled until I implement it), fixed initialization of the IDE registers on the SMSC southbridge, bumped up the number of emulated serial ports to 4 (was 2), and added the ability to properly have multiple W83977's on a single machine.
This commit is contained in:
@@ -39,7 +39,8 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t tries, regs[48],
|
||||
uint8_t id, tries,
|
||||
regs[48],
|
||||
dev_regs[256][208];
|
||||
int locked, rw_locked,
|
||||
cur_reg, base_address,
|
||||
@@ -49,6 +50,9 @@ typedef struct {
|
||||
} w83977f_t;
|
||||
|
||||
|
||||
static int next_id = 0;
|
||||
|
||||
|
||||
static void w83977f_write(uint16_t port, uint8_t val, void *priv);
|
||||
static uint8_t w83977f_read(uint16_t port, void *priv);
|
||||
|
||||
@@ -86,6 +90,9 @@ w83977f_fdc_handler(w83977f_t *dev)
|
||||
{
|
||||
uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31];
|
||||
|
||||
if (dev->id == 1)
|
||||
return;
|
||||
|
||||
fdc_remove(dev->fdc);
|
||||
|
||||
if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8))
|
||||
@@ -105,12 +112,21 @@ w83977f_lpt_handler(w83977f_t *dev)
|
||||
if (io_len == 8)
|
||||
io_mask = 0xff8;
|
||||
|
||||
lpt1_remove();
|
||||
if (dev->id == 1) {
|
||||
lpt2_remove();
|
||||
|
||||
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||
lpt1_init(io_base);
|
||||
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||
lpt2_init(io_base);
|
||||
|
||||
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
|
||||
lpt2_irq(dev->dev_regs[1][0x40] & 0x0f);
|
||||
} else {
|
||||
lpt1_remove();
|
||||
|
||||
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||
lpt1_init(io_base);
|
||||
|
||||
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +265,9 @@ w83977f_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xf0:
|
||||
switch (ld) {
|
||||
case 0x00:
|
||||
if (dev->id == 1)
|
||||
break;
|
||||
|
||||
if (valxor & 0x20)
|
||||
fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1);
|
||||
if (valxor & 0x10)
|
||||
@@ -269,6 +288,9 @@ w83977f_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xf1:
|
||||
switch (ld) {
|
||||
case 0x00:
|
||||
if (dev->id == 1)
|
||||
break;
|
||||
|
||||
if (valxor & 0xc0)
|
||||
fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6);
|
||||
if (valxor & 0x0c)
|
||||
@@ -283,6 +305,9 @@ w83977f_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xf2:
|
||||
switch (ld) {
|
||||
case 0x00:
|
||||
if (dev->id == 1)
|
||||
break;
|
||||
|
||||
if (valxor & 0xc0)
|
||||
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
|
||||
if (valxor & 0x30)
|
||||
@@ -297,6 +322,9 @@ w83977f_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
||||
switch (ld) {
|
||||
case 0x00:
|
||||
if (dev->id == 1)
|
||||
break;
|
||||
|
||||
if (valxor & 0x18)
|
||||
fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3);
|
||||
break;
|
||||
@@ -358,7 +386,11 @@ w83977f_reset(w83977f_t *dev)
|
||||
dev->dev_regs[0][0x00] = 0x01;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[0][0x01] = 0x02;
|
||||
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0;
|
||||
if (next_id == 1) {
|
||||
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0x70;
|
||||
} else {
|
||||
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0;
|
||||
}
|
||||
dev->dev_regs[0][0x40] = 0x06;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[0][0x41] = 0x02; /* Read-only */
|
||||
@@ -369,8 +401,13 @@ w83977f_reset(w83977f_t *dev)
|
||||
dev->dev_regs[1][0x00] = 0x01;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[1][0x01] = 0x02;
|
||||
dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78;
|
||||
dev->dev_regs[1][0x40] = 0x07;
|
||||
if (next_id == 1) {
|
||||
dev->dev_regs[1][0x30] = 0x02; dev->dev_regs[1][0x31] = 0x78;
|
||||
dev->dev_regs[1][0x40] = 0x05;
|
||||
} else {
|
||||
dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78;
|
||||
dev->dev_regs[1][0x40] = 0x07;
|
||||
}
|
||||
if (!dev->type)
|
||||
dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */
|
||||
dev->dev_regs[1][0x44] = 0x04;
|
||||
@@ -380,7 +417,11 @@ w83977f_reset(w83977f_t *dev)
|
||||
dev->dev_regs[2][0x00] = 0x01;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[2][0x01] = 0x02;
|
||||
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8;
|
||||
if (next_id == 1) {
|
||||
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xe8;
|
||||
} else {
|
||||
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8;
|
||||
}
|
||||
dev->dev_regs[2][0x40] = 0x04;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[2][0x41] = 0x02; /* Read-only */
|
||||
@@ -389,7 +430,11 @@ w83977f_reset(w83977f_t *dev)
|
||||
dev->dev_regs[3][0x00] = 0x01;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[3][0x01] = 0x02;
|
||||
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8;
|
||||
if (next_id == 1) {
|
||||
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xe8;
|
||||
} else {
|
||||
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8;
|
||||
}
|
||||
dev->dev_regs[3][0x40] = 0x03;
|
||||
if (!dev->type)
|
||||
dev->dev_regs[3][0x41] = 0x02; /* Read-only */
|
||||
@@ -461,12 +506,18 @@ w83977f_reset(w83977f_t *dev)
|
||||
dev->dev_regs[10][0xc0] = 0x8f;
|
||||
}
|
||||
|
||||
fdc_reset(dev->fdc);
|
||||
if (next_id == 1) {
|
||||
serial_setup(dev->uart[0], SERIAL3_ADDR, SERIAL3_IRQ);
|
||||
serial_setup(dev->uart[1], SERIAL4_ADDR, SERIAL4_IRQ);
|
||||
} else {
|
||||
fdc_reset(dev->fdc);
|
||||
|
||||
serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
|
||||
serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
|
||||
serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
|
||||
serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
|
||||
|
||||
w83977f_fdc_handler(dev);
|
||||
}
|
||||
|
||||
w83977f_fdc_handler(dev);
|
||||
w83977f_lpt_handler(dev);
|
||||
w83977f_serial_handler(dev, 0);
|
||||
w83977f_serial_handler(dev, 1);
|
||||
@@ -483,6 +534,8 @@ w83977f_close(void *priv)
|
||||
{
|
||||
w83977f_t *dev = (w83977f_t *) priv;
|
||||
|
||||
next_id = 0;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -496,13 +549,20 @@ w83977f_init(const device_t *info)
|
||||
dev->type = info->local & 0x0f;
|
||||
dev->hefras = info->local & 0x40;
|
||||
|
||||
dev->fdc = device_add(&fdc_at_smc_device);
|
||||
dev->id = next_id;
|
||||
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
if (next_id == 1)
|
||||
dev->hefras ^= 0x40;
|
||||
else
|
||||
dev->fdc = device_add(&fdc_at_smc_device);
|
||||
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
||||
|
||||
w83977f_reset(dev);
|
||||
|
||||
next_id++;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user