Ported the latest changes of the ESP code from QEMU to 86box (July 19th, 2025)

This commit is contained in:
TC1995
2025-07-19 13:34:51 +02:00
parent 55008566de
commit bc24fefee8

View File

@@ -54,6 +54,12 @@
#define ESP_FIFO_SZ 16
#define ESP_CMDFIFO_SZ 32
enum ESPASCMode {
ESP_ASC_MODE_DIS = 0, /* Disconnected */
ESP_ASC_MODE_INI = 1, /* Initiator */
ESP_ASC_MODE_TGT = 2 /* Target */
};
#define ESP_TCLO 0x0
#define ESP_TCMID 0x1
#define ESP_FIFO 0x2
@@ -80,6 +86,13 @@
#define CMD_DMA 0x80
#define CMD_CMD 0x7f
#define CMD_GRP_MASK 0x70
#define CMD_GRP_MISC 0x00
#define CMD_GRP_INIT 0x01
#define CMD_GRP_TRGT 0x02
#define CMD_GRP_DISC 0x04
#define CMD_NOP 0x00
#define CMD_FLUSH 0x01
#define CMD_RESET 0x02
@@ -114,7 +127,7 @@
#define INTR_FC 0x08
#define INTR_BS 0x10
#define INTR_DC 0x20
#define INTR_ILL 0x40
#define INTR_IL 0x40
#define INTR_RST 0x80
#define SEQ_0 0x0
@@ -176,6 +189,7 @@ typedef struct esp_t {
uint8_t id, lun;
Fifo8 cmdfifo;
uint8_t cmdfifo_cdb_offset;
uint8_t asc_mode;
int data_ready;
int32_t xfer_counter;
@@ -435,12 +449,14 @@ esp_select(esp_t *dev)
esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun);
/* No such drive */
dev->rregs[ESP_RSTAT] = 0;
dev->asc_mode = ESP_ASC_MODE_DIS;
dev->rregs[ESP_RINTR] = INTR_DC;
esp_raise_irq(dev);
return -1;
} else
esp_log("ESP SCSI device present on ID %d, LUN %d\n", dev->id, dev->lun);
dev->asc_mode = ESP_ASC_MODE_INI;
return 0;
}
@@ -460,9 +476,10 @@ esp_transfer_data(esp_t *dev)
* Initial incoming data xfer is complete for sequencer command
* so raise deferred bus service and function complete interrupt
*/
dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC);
dev->rregs[ESP_RSEQ] = SEQ_CD;
break;
dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC);
dev->rregs[ESP_RSEQ] = SEQ_CD;
esp_raise_irq(dev);
break;
case CMD_SELATNS:
case (CMD_SELATNS | CMD_DMA):
@@ -470,22 +487,26 @@ esp_transfer_data(esp_t *dev)
* Initial incoming data xfer is complete so raise command
* completion interrupt
*/
dev->rregs[ESP_RINTR] |= INTR_BS;
dev->rregs[ESP_RSEQ] = SEQ_MO;
break;
dev->rregs[ESP_RINTR] |= INTR_BS;
dev->rregs[ESP_RSEQ] = SEQ_MO;
esp_raise_irq(dev);
break;
case CMD_TI:
case (CMD_TI | CMD_DMA):
/*
* Bus service interrupt raised because of initial change to
* DATA phase
* If the final COMMAND phase data was transferred using a TI
* command, clear ESP_CMD to terminate the TI command and raise
* the completion interrupt
*/
dev->rregs[ESP_CMD] = 0;
dev->rregs[ESP_RINTR] |= INTR_BS;
esp_raise_irq(dev);
break;
default:
break;
}
esp_raise_irq(dev);
}
/*
@@ -574,6 +595,7 @@ esp_do_message_phase(esp_t *dev)
/* We only support LUN 0 */
esp_log("LUN = %i\n", dev->lun);
dev->rregs[ESP_RSTAT] = 0;
dev->asc_mode = ESP_ASC_MODE_DIS;
dev->rregs[ESP_RINTR] = INTR_DC;
dev->rregs[ESP_RSEQ] = SEQ_0;
esp_raise_irq(dev);
@@ -631,6 +653,7 @@ esp_hard_reset(esp_t *dev)
fifo8_reset(&dev->cmdfifo);
dev->dma = 0;
dev->tchi_written = 0;
dev->asc_mode = ESP_ASC_MODE_DIS;
dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7;
esp_log("ESP Reset\n");
@@ -686,18 +709,20 @@ esp_do_dma(esp_t *dev)
switch (esp_get_phase(dev)) {
case STAT_MO:
len = MIN(len, fifo8_num_free(&dev->cmdfifo));
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
buf[dev->dma_86c01.pos++] = val & 0xff;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE);
if (len) {
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
buf[dev->dma_86c01.pos++] = val & 0xff;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE);
esp_set_tc(dev, esp_get_tc(dev) - len);
esp_set_tc(dev, esp_get_tc(dev) - len);
}
fifo8_push_all(&dev->cmdfifo, buf, len);
dev->cmdfifo_cdb_offset += len;
@@ -745,19 +770,21 @@ esp_do_dma(esp_t *dev)
case STAT_CD:
len = MIN(len, fifo8_num_free(&dev->cmdfifo));
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
buf[dev->dma_86c01.pos++] = val & 0xff;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE);
if (len) {
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
buf[dev->dma_86c01.pos++] = val & 0xff;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE);
fifo8_push_all(&dev->cmdfifo, buf, len);
esp_set_tc(dev, esp_get_tc(dev) - len);
fifo8_push_all(&dev->cmdfifo, buf, len);
esp_set_tc(dev, esp_get_tc(dev) - len);
}
dev->ti_size = 0;
if (esp_get_tc(dev) == 0) {
/* Command has been received */
@@ -775,20 +802,22 @@ esp_do_dma(esp_t *dev)
switch (dev->rregs[ESP_CMD]) {
case (CMD_TI | CMD_DMA):
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff);
sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff;
dev->dma_86c01.pos++;
}
dma_set_drq(dev->DmaChannel, 0);
dev->dma_86c01.pos = 0;
} else
esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE);
if (len) {
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
int val = dma_channel_read(dev->DmaChannel);
esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff);
sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff;
dev->dma_86c01.pos++;
}
dma_set_drq(dev->DmaChannel, 0);
dev->dma_86c01.pos = 0;
} else
esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE);
esp_set_tc(dev, esp_get_tc(dev) - len);
esp_set_tc(dev, esp_get_tc(dev) - len);
}
dev->buffer_pos += len;
dev->xfer_counter -= len;
dev->ti_size += len;
@@ -834,18 +863,19 @@ esp_do_dma(esp_t *dev)
switch (dev->rregs[ESP_CMD]) {
case (CMD_TI | CMD_DMA):
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]);
esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]);
dev->dma_86c01.pos++;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, READ_FROM_DEVICE);
if (len) {
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]);
esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]);
dev->dma_86c01.pos++;
}
dev->dma_86c01.pos = 0;
dma_set_drq(dev->DmaChannel, 0);
} else
esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, READ_FROM_DEVICE);
}
dev->buffer_pos += len;
dev->xfer_counter -= len;
dev->ti_size -= len;
@@ -886,6 +916,7 @@ esp_do_dma(esp_t *dev)
if (len) {
buf[0] = dev->status;
/* Length already non-zero */
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
@@ -925,6 +956,7 @@ esp_do_dma(esp_t *dev)
if (len) {
buf[0] = 0;
/* Length already non-zero */
if (dev->mca) {
dma_set_drq(dev->DmaChannel, 1);
while (dev->dma_86c01.pos < len) {
@@ -1323,6 +1355,37 @@ esp_callback(void *priv)
}
}
static int
esp_cmd_is_valid(esp_t *dev, uint8_t cmd)
{
uint8_t cmd_group = (cmd & CMD_GRP_MASK) >> 4;
/* Always allow misc commands */
if (cmd_group == CMD_GRP_MISC)
return 1;
switch (dev->asc_mode) {
case ESP_ASC_MODE_DIS:
/* Disconnected mode: only allow disconnected commands */
if (cmd_group == CMD_GRP_DISC)
return 1;
break;
case ESP_ASC_MODE_INI:
/* Initiator mode: allow initiator commands */
if (cmd_group == CMD_GRP_INIT)
return 1;
break;
default:
break;
}
return 0;
}
static uint32_t
esp_reg_read(esp_t *dev, uint32_t saddr)
{
@@ -1385,6 +1448,11 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val)
break;
case ESP_CMD:
dev->rregs[ESP_CMD] = val;
if (!esp_cmd_is_valid(dev, dev->rregs[saddr])) {
dev->rregs[ESP_RSTAT] |= INTR_IL;
esp_raise_irq(dev);
break;
}
if (val & CMD_DMA) {
dev->dma = 1;
@@ -1446,6 +1514,7 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val)
handle_satn_stop(dev);
break;
case CMD_MSGACC:
dev->asc_mode = ESP_ASC_MODE_DIS;
dev->rregs[ESP_RINTR] |= INTR_DC;
dev->rregs[ESP_RSEQ] = 0;
dev->rregs[ESP_RFLAGS] = 0;