253 lines
10 KiB
C
253 lines
10 KiB
C
#include "ibm.h"
|
|
|
|
#include "fdc.h"
|
|
#include "fdd.h"
|
|
#include "io.h"
|
|
#include "lpt.h"
|
|
#include "serial.h"
|
|
#include "fdc37c93x.h"
|
|
|
|
typedef struct fdc37c93x_t
|
|
{
|
|
int index;
|
|
|
|
uint8_t global_regs[0x30];
|
|
uint8_t fdc_regs[0x100];
|
|
uint8_t ide1_regs[0x100];
|
|
uint8_t ide2_regs[0x100];
|
|
uint8_t lpt_regs[0x100];
|
|
uint8_t com1_regs[0x100];
|
|
uint8_t com2_regs[0x100];
|
|
uint8_t rtc_regs[0x100];
|
|
uint8_t kbd_regs[0x100];
|
|
uint8_t auxio_regs[0x100];
|
|
uint8_t accessbus_regs[0x100];
|
|
|
|
uint8_t lock[2];
|
|
} fdc37c93x_t;
|
|
|
|
static fdc37c93x_t fdc37c93x_global;
|
|
|
|
static void write_lock(fdc37c93x_t *fdc37c93x, uint8_t val)
|
|
{
|
|
if (val == 0x55 && fdc37c93x->lock[1] == 0x55)
|
|
fdc_3f1_enable(0);
|
|
if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55 && val != 0x55)
|
|
fdc_3f1_enable(1);
|
|
|
|
fdc37c93x->lock[0] = fdc37c93x->lock[1];
|
|
fdc37c93x->lock[1] = val;
|
|
}
|
|
|
|
void fdc37c93x_write(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
fdc37c93x_t *fdc37c93x = (fdc37c93x_t *)p;
|
|
|
|
// pclog("Write SuperIO %04x %02x\n", port, val);
|
|
if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55)
|
|
{
|
|
if (port == 0x3f0)
|
|
{
|
|
if (val == 0xaa)
|
|
write_lock(fdc37c93x, val);
|
|
else
|
|
fdc37c93x->index = val;
|
|
}
|
|
else
|
|
{
|
|
uint16_t addr;
|
|
int irq;
|
|
|
|
// pclog("fdc37c93x_write: index=%02x dev=%i val=%02x\n", fdc37c93x->index, fdc37c93x->global_regs[7], val);
|
|
if (fdc37c93x->index < 0x30)
|
|
{
|
|
if (fdc37c93x->index != 0x20 && fdc37c93x->index != 0x21)
|
|
fdc37c93x->global_regs[fdc37c93x->index] = val;
|
|
}
|
|
else switch (fdc37c93x->global_regs[7])
|
|
{
|
|
case 0:
|
|
fdc37c93x->fdc_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 1:
|
|
fdc37c93x->ide1_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 2:
|
|
fdc37c93x->ide2_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 3:
|
|
fdc37c93x->lpt_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 4:
|
|
fdc37c93x->com1_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 5:
|
|
fdc37c93x->com2_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 6:
|
|
fdc37c93x->rtc_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 7:
|
|
fdc37c93x->kbd_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 8:
|
|
fdc37c93x->auxio_regs[fdc37c93x->index] = val;
|
|
break;
|
|
case 9:
|
|
fdc37c93x->accessbus_regs[fdc37c93x->index] = val;
|
|
break;
|
|
}
|
|
|
|
fdc_remove();
|
|
if ((fdc37c93x->global_regs[0x22] & 0x01) && (fdc37c93x->fdc_regs[0x30] & 0x01))
|
|
{
|
|
// pclog("FDC enabled\n");
|
|
fdc_add();
|
|
}
|
|
/* else
|
|
pclog("FDC disabled\n");*/
|
|
|
|
lpt1_remove();
|
|
lpt2_remove();
|
|
addr = (fdc37c93x->lpt_regs[0x61] & 0xfc) | ((fdc37c93x->lpt_regs[0x60] & 3) << 8);
|
|
if ((fdc37c93x->global_regs[0x22] & (1 << 3)) && (fdc37c93x->lpt_regs[0x30] & 0x01))
|
|
{
|
|
// pclog("LPT addr = %04x\n", addr);
|
|
lpt1_init(addr);
|
|
}
|
|
/* else
|
|
pclog("LPT disabled\n");*/
|
|
|
|
serial1_remove();
|
|
addr = (fdc37c93x->com1_regs[0x61] & 0xf8) | ((fdc37c93x->com1_regs[0x60] & 3) << 8);
|
|
irq = fdc37c93x->com1_regs[0x70] & 0xf;
|
|
if ((fdc37c93x->global_regs[0x22] & (1 << 4)) && (fdc37c93x->com1_regs[0x30] & 0x01))
|
|
{
|
|
// pclog("COM1 addr = %04x, IRQ = %i\n", addr, irq);
|
|
serial1_set(addr, irq);
|
|
}
|
|
/* else
|
|
pclog("COM1 disabled\n");*/
|
|
|
|
serial2_remove();
|
|
addr = (fdc37c93x->com2_regs[0x61] & 0xf8) | ((fdc37c93x->com2_regs[0x60] & 3) << 8);
|
|
irq = fdc37c93x->com2_regs[0x70] & 0xf;
|
|
if ((fdc37c93x->global_regs[0x22] & (1 << 5)) && (fdc37c93x->com2_regs[0x30] & 0x01))
|
|
{
|
|
// pclog("COM2 addr = %04x, IRQ = %i\n", addr, irq);
|
|
serial2_set(addr, irq);
|
|
}
|
|
/* else
|
|
pclog("COM2 disabled\n");*/
|
|
|
|
|
|
fdc_update_enh_mode(fdc37c93x->fdc_regs[0xf0] & 1);
|
|
|
|
fdc_update_densel_force((fdc37c93x->fdc_regs[0xf1] & 0x0c) >> 2);
|
|
fdd_swap = (fdc37c93x->fdc_regs[0xf0] & (1 << 4)) ? 1 : 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (port == 0x3f0)
|
|
write_lock(fdc37c93x, val);
|
|
}
|
|
}
|
|
|
|
uint8_t fdc37c93x_read(uint16_t port, void *p)
|
|
{
|
|
fdc37c93x_t *fdc37c93x = (fdc37c93x_t *)p;
|
|
|
|
// pclog("Read SuperIO %04x %02x\n", port, fdc37c665_curreg);
|
|
if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55)
|
|
{
|
|
if (port == 0x3f1)
|
|
{
|
|
if (fdc37c93x->index < 0x30)
|
|
return fdc37c93x->global_regs[fdc37c93x->index];
|
|
else switch (fdc37c93x->global_regs[7])
|
|
{
|
|
case 0:
|
|
return fdc37c93x->fdc_regs[fdc37c93x->index];
|
|
case 1:
|
|
return fdc37c93x->ide1_regs[fdc37c93x->index];
|
|
case 2:
|
|
return fdc37c93x->ide2_regs[fdc37c93x->index];
|
|
case 3:
|
|
return fdc37c93x->lpt_regs[fdc37c93x->index];
|
|
case 4:
|
|
return fdc37c93x->com1_regs[fdc37c93x->index];
|
|
case 5:
|
|
return fdc37c93x->com2_regs[fdc37c93x->index];
|
|
case 6:
|
|
return fdc37c93x->rtc_regs[fdc37c93x->index];
|
|
case 7:
|
|
return fdc37c93x->kbd_regs[fdc37c93x->index];
|
|
case 8:
|
|
return fdc37c93x->auxio_regs[fdc37c93x->index];
|
|
case 9:
|
|
return fdc37c93x->accessbus_regs[fdc37c93x->index];
|
|
}
|
|
}
|
|
}
|
|
return 0xff;
|
|
}
|
|
|
|
void fdc37c932fr_init()
|
|
{
|
|
fdc37c93x_t *fdc37c93x = &fdc37c93x_global;
|
|
int c;
|
|
|
|
io_sethandler(0x03f0, 0x0002, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, fdc37c93x);
|
|
|
|
fdc_update_is_nsc(0);
|
|
|
|
memset(&fdc37c93x_global, 0, sizeof(fdc37c93x_global));
|
|
|
|
fdc37c93x->global_regs[0x03] = 0x03;
|
|
fdc37c93x->global_regs[0x20] = 0x03;
|
|
fdc37c93x->global_regs[0x21] = 0x01;
|
|
fdc37c93x->global_regs[0x24] = 0x04;
|
|
fdc37c93x->global_regs[0x26] = 0xf0;
|
|
fdc37c93x->global_regs[0x27] = 0x03;
|
|
|
|
fdc37c93x->fdc_regs[0x60] = 0x03;
|
|
fdc37c93x->fdc_regs[0x61] = 0xf0;
|
|
fdc37c93x->fdc_regs[0x70] = 0x06;
|
|
fdc37c93x->fdc_regs[0x74] = 0x02;
|
|
fdc37c93x->fdc_regs[0xf0] = 0x0e;
|
|
fdc37c93x->fdc_regs[0xf2] = 0xff;
|
|
|
|
fdc37c93x->ide1_regs[0x60] = 0x01;
|
|
fdc37c93x->ide1_regs[0x61] = 0xf0;
|
|
fdc37c93x->ide1_regs[0x62] = 0x03;
|
|
fdc37c93x->ide1_regs[0x63] = 0xf6;
|
|
fdc37c93x->ide1_regs[0x70] = 0x0e;
|
|
fdc37c93x->ide1_regs[0xf0] = 0x0c;
|
|
fdc37c93x->ide1_regs[0xf1] = 0x0d;
|
|
|
|
fdc37c93x->lpt_regs[0x74] = 0x04;
|
|
fdc37c93x->lpt_regs[0xf0] = 0x3c;
|
|
|
|
fdc37c93x->com2_regs[0x74] = 0x04;
|
|
fdc37c93x->com2_regs[0xf1] = 0x02;
|
|
fdc37c93x->com2_regs[0xf2] = 0x03;
|
|
|
|
fdc37c93x->rtc_regs[0x63] = 0x70;
|
|
fdc37c93x->rtc_regs[0xf4] = 0x03;
|
|
|
|
fdc37c93x->auxio_regs[0xb1] = 0x80;
|
|
fdc37c93x->auxio_regs[0xc0] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc1] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc5] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc6] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc7] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc8] = 0x01;
|
|
fdc37c93x->auxio_regs[0xc9] = 0x80;
|
|
for (c = 0xcb; c < 0xee; c++)
|
|
fdc37c93x->auxio_regs[c] = 0x01;
|
|
|
|
fdc_update_densel_polarity(1);
|
|
fdc_update_densel_force(0);
|
|
fdd_swap = 0;
|
|
}
|