Solved the IRQ mess of ESDI MCA.
This should also fix the timing/fatal's on ramdisk speeds using said controller on NT and OS/2 on MCA.
This commit is contained in:
@@ -92,7 +92,7 @@
|
|||||||
#define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin"
|
#define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin"
|
||||||
#define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin"
|
#define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin"
|
||||||
|
|
||||||
#define ESDI_TIME 512.0
|
#define ESDI_TIME 500.0
|
||||||
#define CMD_ADAPTER 0
|
#define CMD_ADAPTER 0
|
||||||
|
|
||||||
typedef struct esdi_drive_t {
|
typedef struct esdi_drive_t {
|
||||||
@@ -113,6 +113,7 @@ typedef struct esdi_t {
|
|||||||
uint8_t basic_ctrl;
|
uint8_t basic_ctrl;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t irq_status;
|
uint8_t irq_status;
|
||||||
|
int irq_ena_disable;
|
||||||
int irq_in_progress;
|
int irq_in_progress;
|
||||||
int cmd_req_in_progress;
|
int cmd_req_in_progress;
|
||||||
int cmd_pos;
|
int cmd_pos;
|
||||||
@@ -218,14 +219,26 @@ esdi_mca_log(const char *fmt, ...)
|
|||||||
static __inline void
|
static __inline void
|
||||||
set_irq(esdi_t *dev)
|
set_irq(esdi_t *dev)
|
||||||
{
|
{
|
||||||
|
dev->irq_ena_disable = 1;
|
||||||
|
esdi_mca_log("Set IRQ 14: bit=%x, cmd=%02x.\n", dev->basic_ctrl & CTRL_IRQ_ENA, dev->command);
|
||||||
if (dev->basic_ctrl & CTRL_IRQ_ENA)
|
if (dev->basic_ctrl & CTRL_IRQ_ENA)
|
||||||
picint(1 << 14);
|
picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void
|
static __inline void
|
||||||
clear_irq(UNUSED(esdi_t *dev))
|
clear_irq(esdi_t *dev)
|
||||||
{
|
{
|
||||||
picintc(1 << 14);
|
dev->irq_ena_disable = 0;
|
||||||
|
esdi_mca_log("Clear IRQ 14: bit=%x, cmd=%02x.\n", dev->basic_ctrl & CTRL_IRQ_ENA, dev->command);
|
||||||
|
if (dev->basic_ctrl & CTRL_IRQ_ENA)
|
||||||
|
picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
update_irq(esdi_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t set = (dev->basic_ctrl & CTRL_IRQ_ENA) && dev->irq_ena_disable;
|
||||||
|
picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, set, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -235,10 +248,11 @@ esdi_mca_set_callback(esdi_t *dev, double callback)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback == 0.0) {
|
||||||
timer_on_auto(&dev->timer, callback);
|
esdi_mca_log("Callback Stopped.\n");
|
||||||
} else {
|
|
||||||
timer_stop(&dev->timer);
|
timer_stop(&dev->timer);
|
||||||
|
} else {
|
||||||
|
timer_on_auto(&dev->timer, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,9 +331,9 @@ complete_command_status(esdi_t *dev)
|
|||||||
{
|
{
|
||||||
dev->status_len = 7;
|
dev->status_len = 7;
|
||||||
if (dev->cmd_dev == ATTN_DEVICE_0)
|
if (dev->cmd_dev == ATTN_DEVICE_0)
|
||||||
dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0);
|
dev->status_data[0] = dev->command | STATUS_LEN(7) | STATUS_DEVICE(0);
|
||||||
else
|
else
|
||||||
dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1);
|
dev->status_data[0] = dev->command | STATUS_LEN(7) | STATUS_DEVICE(1);
|
||||||
dev->status_data[1] = 0x0000; /*Error bits*/
|
dev->status_data[1] = 0x0000; /*Error bits*/
|
||||||
dev->status_data[2] = 0x1900; /*Device status*/
|
dev->status_data[2] = 0x1900; /*Device status*/
|
||||||
dev->status_data[3] = 0; /*Number of blocks left to do*/
|
dev->status_data[3] = 0; /*Number of blocks left to do*/
|
||||||
@@ -330,15 +344,12 @@ complete_command_status(esdi_t *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define ESDI_ADAPTER_ONLY() \
|
#define ESDI_ADAPTER_ONLY() \
|
||||||
do { \
|
|
||||||
if (dev->cmd_dev != ATTN_HOST_ADAPTER) { \
|
if (dev->cmd_dev != ATTN_HOST_ADAPTER) { \
|
||||||
cmd_unsupported(dev); \
|
cmd_unsupported(dev); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
}
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ESDI_DRIVE_ONLY() \
|
#define ESDI_DRIVE_ONLY() \
|
||||||
do { \
|
|
||||||
if (dev->cmd_dev != ATTN_DEVICE_0 && dev->cmd_dev != ATTN_DEVICE_1) { \
|
if (dev->cmd_dev != ATTN_DEVICE_0 && dev->cmd_dev != ATTN_DEVICE_1) { \
|
||||||
cmd_unsupported(dev); \
|
cmd_unsupported(dev); \
|
||||||
return; \
|
return; \
|
||||||
@@ -346,8 +357,7 @@ complete_command_status(esdi_t *dev)
|
|||||||
if (dev->cmd_dev == ATTN_DEVICE_0) \
|
if (dev->cmd_dev == ATTN_DEVICE_0) \
|
||||||
drive = &dev->drives[0]; \
|
drive = &dev->drives[0]; \
|
||||||
else \
|
else \
|
||||||
drive = &dev->drives[1]; \
|
drive = &dev->drives[1];
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
esdi_callback(void *priv)
|
esdi_callback(void *priv)
|
||||||
@@ -357,19 +367,19 @@ esdi_callback(void *priv)
|
|||||||
int val;
|
int val;
|
||||||
double cmd_time = 0.0;
|
double cmd_time = 0.0;
|
||||||
|
|
||||||
esdi_mca_set_callback(dev, 0);
|
|
||||||
|
|
||||||
/* If we are returning from a RESET, handle this first. */
|
/* If we are returning from a RESET, handle this first. */
|
||||||
if (dev->in_reset) {
|
if (dev->in_reset) {
|
||||||
|
esdi_mca_log("ESDI reset.\n");
|
||||||
dev->in_reset = 0;
|
dev->in_reset = 0;
|
||||||
dev->status = STATUS_IRQ;
|
dev->status = STATUS_IRQ;
|
||||||
dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE;
|
dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esdi_mca_log("Command=%02x.\n", dev->command);
|
||||||
switch (dev->command) {
|
switch (dev->command) {
|
||||||
case CMD_READ:
|
case CMD_READ:
|
||||||
|
case 0x15:
|
||||||
ESDI_DRIVE_ONLY();
|
ESDI_DRIVE_ONLY();
|
||||||
|
|
||||||
if (!drive->present) {
|
if (!drive->present) {
|
||||||
@@ -379,6 +389,7 @@ esdi_callback(void *priv)
|
|||||||
|
|
||||||
switch (dev->cmd_state) {
|
switch (dev->cmd_state) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (dev->command == CMD_READ)
|
||||||
dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff;
|
dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff;
|
||||||
|
|
||||||
dev->sector_pos = 0;
|
dev->sector_pos = 0;
|
||||||
@@ -873,7 +884,7 @@ static uint8_t
|
|||||||
esdi_read(uint16_t port, void *priv)
|
esdi_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
esdi_t *dev = (esdi_t *) priv;
|
esdi_t *dev = (esdi_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0x00;
|
||||||
|
|
||||||
switch (port & 7) {
|
switch (port & 7) {
|
||||||
case 2: /*Basic status register*/
|
case 2: /*Basic status register*/
|
||||||
@@ -890,6 +901,7 @@ esdi_read(uint16_t port, void *priv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esdi_mca_log("ESDI: rr(%04x, %02x)\n", port & 7, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,6 +909,7 @@ static void
|
|||||||
esdi_write(uint16_t port, uint8_t val, void *priv)
|
esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
esdi_t *dev = (esdi_t *) priv;
|
esdi_t *dev = (esdi_t *) priv;
|
||||||
|
uint8_t old;
|
||||||
|
|
||||||
esdi_mca_log("ESDI: wr(%04x, %02x)\n", port & 7, val);
|
esdi_mca_log("ESDI: wr(%04x, %02x)\n", port & 7, val);
|
||||||
|
|
||||||
@@ -906,11 +919,14 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
dev->in_reset = 1;
|
dev->in_reset = 1;
|
||||||
esdi_mca_set_callback(dev, ESDI_TIME * 50);
|
esdi_mca_set_callback(dev, ESDI_TIME * 50);
|
||||||
dev->status = STATUS_BUSY;
|
dev->status = STATUS_BUSY;
|
||||||
|
} else if (!(dev->basic_ctrl & CTRL_RESET) && (val & CTRL_RESET)) {
|
||||||
|
esdi_mca_set_callback(dev, 0.0);
|
||||||
|
dev->status = STATUS_BUSY;
|
||||||
}
|
}
|
||||||
|
old = dev->basic_ctrl;
|
||||||
dev->basic_ctrl = val;
|
dev->basic_ctrl = val;
|
||||||
|
if ((val & CTRL_IRQ_ENA) && !(old & CTRL_IRQ_ENA))
|
||||||
if (!(dev->basic_ctrl & CTRL_IRQ_ENA))
|
update_irq(dev);
|
||||||
picintc(1 << 14);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /*Attention register*/
|
case 3: /*Attention register*/
|
||||||
@@ -945,6 +961,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ATTN_DEVICE_0:
|
case ATTN_DEVICE_0:
|
||||||
|
esdi_mca_log("ATTN Device 0.\n");
|
||||||
switch (val & ATTN_REQ_MASK) {
|
switch (val & ATTN_REQ_MASK) {
|
||||||
case ATTN_CMD_REQ:
|
case ATTN_CMD_REQ:
|
||||||
if (dev->cmd_req_in_progress)
|
if (dev->cmd_req_in_progress)
|
||||||
@@ -957,6 +974,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ATTN_EOI:
|
case ATTN_EOI:
|
||||||
|
esdi_mca_log("EOI.\n");
|
||||||
dev->irq_in_progress = 0;
|
dev->irq_in_progress = 0;
|
||||||
dev->status &= ~STATUS_IRQ;
|
dev->status &= ~STATUS_IRQ;
|
||||||
clear_irq(dev);
|
clear_irq(dev);
|
||||||
@@ -1112,15 +1130,40 @@ esdi_mca_write(int port, uint8_t val, void *priv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(dev->pos_regs[3] & 8)) {
|
||||||
|
switch (dev->pos_regs[3] & 7) {
|
||||||
|
case 2:
|
||||||
|
dev->bios = 0xc8000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
dev->bios = 0xcc000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
dev->bios = 0xd0000;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
dev->bios = 0xd4000;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
dev->bios = 0xd8000;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
dev->bios = 0xdc000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
dev->bios = 0;
|
||||||
|
|
||||||
if (dev->pos_regs[2] & 1) {
|
if (dev->pos_regs[2] & 1) {
|
||||||
io_sethandler(ESDI_IOADDR_PRI, 8,
|
io_sethandler(ESDI_IOADDR_PRI, 8,
|
||||||
esdi_read, esdi_readw, NULL,
|
esdi_read, esdi_readw, NULL,
|
||||||
esdi_write, esdi_writew, NULL, dev);
|
esdi_write, esdi_writew, NULL, dev);
|
||||||
|
|
||||||
if (!(dev->pos_regs[3] & 8)) {
|
if (dev->bios) {
|
||||||
mem_mapping_enable(&dev->bios_rom.mapping);
|
mem_mapping_enable(&dev->bios_rom.mapping);
|
||||||
mem_mapping_set_addr(&dev->bios_rom.mapping,
|
mem_mapping_set_addr(&dev->bios_rom.mapping, dev->bios, 0x4000);
|
||||||
((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Say hello. */
|
/* Say hello. */
|
||||||
|
Reference in New Issue
Block a user