Skip to content

Commit f2a80c6

Browse files
committed
m68k: Instantiate the ESP SCSI controller for the NeXTcube machine
The NeXTcube uses a NCR 53C90 SCSI interface for its disks, so we should be able to use the ESP controller from QEMU here. The code here has been basically taken from Bryce Lanham's GSoC 2011 contribution, except for the next_scsi_init() function which has been rewritte as a replacement for the esp_init() function (that has been removed quite a while ago). Note that SCSI is not working yet. The ESP code likely needs some more fixes first and there still might be some bugs left in they way we wire it up for the NeXT-Cube machine. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-ID: <20230930132351.30282-4-huth@tuxfamily.org> Signed-off-by: Thomas Huth <huth@tuxfamily.org>
1 parent 87f4ba9 commit f2a80c6

File tree

1 file changed

+110
-7
lines changed

1 file changed

+110
-7
lines changed

hw/m68k/next-cube.c

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,13 @@ struct NeXTPC {
9090

9191
uint32_t scr1;
9292
uint32_t scr2;
93-
uint8_t scsi_csr_1;
94-
uint8_t scsi_csr_2;
9593
uint32_t int_mask;
9694
uint32_t int_status;
95+
uint8_t scsi_csr_1;
96+
uint8_t scsi_csr_2;
97+
98+
qemu_irq scsi_reset;
99+
qemu_irq scsi_dma;
97100

98101
NextRtc rtc;
99102
};
@@ -466,7 +469,7 @@ static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value)
466469
DPRINTF("SCSICSR FIFO Flush\n");
467470
/* will have to add another irq to the esp if this is needed */
468471
/* esp_puflush_fifo(esp_g); */
469-
/* qemu_irq_pulse(s->scsi_dma); */
472+
qemu_irq_pulse(s->scsi_dma);
470473
}
471474

472475
if (value & SCSICSR_ENABLE) {
@@ -486,20 +489,21 @@ static void scr_writeb(NeXTPC *s, hwaddr addr, uint32_t value)
486489
if (value & SCSICSR_RESET) {
487490
DPRINTF("SCSICSR Reset\n");
488491
/* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
489-
/* qemu_irq_raise(s->scsi_reset); */
490-
/* s->scsi_csr_1 &= ~(SCSICSR_INTMASK |0x80|0x1); */
491-
492+
qemu_irq_raise(s->scsi_reset);
493+
s->scsi_csr_1 &= ~(SCSICSR_INTMASK | 0x80 | 0x1);
494+
qemu_irq_lower(s->scsi_reset);
492495
}
493496
if (value & SCSICSR_DMADIR) {
494497
DPRINTF("SCSICSR DMAdir\n");
495498
}
496499
if (value & SCSICSR_CPUDMA) {
497500
DPRINTF("SCSICSR CPUDMA\n");
498501
/* qemu_irq_raise(s->scsi_dma); */
499-
500502
s->int_status |= 0x4000000;
501503
} else {
504+
/* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
502505
s->int_status &= ~(0x4000000);
506+
/* qemu_irq_lower(s->scsi_dma); */
503507
}
504508
if (value & SCSICSR_INTMASK) {
505509
DPRINTF("SCSICSR INTMASK\n");
@@ -828,6 +832,103 @@ static void next_irq(void *opaque, int number, int level)
828832
}
829833
}
830834

835+
static void nextdma_write(void *opaque, uint8_t *buf, int size, int type)
836+
{
837+
uint32_t base_addr;
838+
int irq = 0;
839+
uint8_t align = 16;
840+
NeXTState *next_state = NEXT_MACHINE(qdev_get_machine());
841+
842+
if (type == NEXTDMA_ENRX || type == NEXTDMA_ENTX) {
843+
align = 32;
844+
}
845+
/* Most DMA is supposedly 16 byte aligned */
846+
if ((size % align) != 0) {
847+
size -= size % align;
848+
size += align;
849+
}
850+
851+
/*
852+
* prom sets the dma start using initbuf while the bootloader uses next
853+
* so we check to see if initbuf is 0
854+
*/
855+
if (next_state->dma[type].next_initbuf == 0) {
856+
base_addr = next_state->dma[type].next;
857+
} else {
858+
base_addr = next_state->dma[type].next_initbuf;
859+
}
860+
861+
cpu_physical_memory_write(base_addr, buf, size);
862+
863+
next_state->dma[type].next_initbuf = 0;
864+
865+
/* saved limit is checked to calculate packet size by both, rom and netbsd */
866+
next_state->dma[type].saved_limit = (next_state->dma[type].next + size);
867+
next_state->dma[type].saved_next = (next_state->dma[type].next);
868+
869+
/*
870+
* 32 bytes under savedbase seems to be some kind of register
871+
* of which the purpose is unknown as of yet
872+
*/
873+
/* stl_phys(s->rx_dma.base-32,0xFFFFFFFF); */
874+
875+
if (!(next_state->dma[type].csr & DMA_SUPDATE)) {
876+
next_state->dma[type].next = next_state->dma[type].start;
877+
next_state->dma[type].limit = next_state->dma[type].stop;
878+
}
879+
880+
/* Set dma registers and raise an irq */
881+
next_state->dma[type].csr |= DMA_COMPLETE; /* DON'T CHANGE THIS! */
882+
883+
switch (type) {
884+
case NEXTDMA_SCSI:
885+
irq = NEXT_SCSI_DMA_I;
886+
break;
887+
}
888+
889+
next_irq(opaque, irq, 1);
890+
next_irq(opaque, irq, 0);
891+
}
892+
893+
static void nextscsi_read(void *opaque, uint8_t *buf, int len)
894+
{
895+
DPRINTF("SCSI READ: %x\n", len);
896+
abort();
897+
}
898+
899+
static void nextscsi_write(void *opaque, uint8_t *buf, int size)
900+
{
901+
DPRINTF("SCSI WRITE: %i\n", size);
902+
nextdma_write(opaque, buf, size, NEXTDMA_SCSI);
903+
}
904+
905+
static void next_scsi_init(DeviceState *pcdev, M68kCPU *cpu)
906+
{
907+
struct NeXTPC *next_pc = NEXT_PC(pcdev);
908+
DeviceState *dev;
909+
SysBusDevice *sysbusdev;
910+
SysBusESPState *sysbus_esp;
911+
ESPState *esp;
912+
913+
dev = qdev_new(TYPE_SYSBUS_ESP);
914+
sysbus_esp = SYSBUS_ESP(dev);
915+
esp = &sysbus_esp->esp;
916+
esp->dma_memory_read = nextscsi_read;
917+
esp->dma_memory_write = nextscsi_write;
918+
esp->dma_opaque = pcdev;
919+
sysbus_esp->it_shift = 0;
920+
esp->dma_enabled = 1;
921+
sysbusdev = SYS_BUS_DEVICE(dev);
922+
sysbus_realize_and_unref(sysbusdev, &error_fatal);
923+
sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(pcdev, NEXT_SCSI_I));
924+
sysbus_mmio_map(sysbusdev, 0, 0x2114000);
925+
926+
next_pc->scsi_reset = qdev_get_gpio_in(dev, 0);
927+
next_pc->scsi_dma = qdev_get_gpio_in(dev, 1);
928+
929+
scsi_bus_legacy_handle_cmdline(&esp->bus);
930+
}
931+
831932
static void next_escc_init(DeviceState *pcdev)
832933
{
833934
DeviceState *dev;
@@ -1021,6 +1122,7 @@ static void next_cube_init(MachineState *machine)
10211122
/* TODO: */
10221123
/* Network */
10231124
/* SCSI */
1125+
next_scsi_init(pcdev, cpu);
10241126

10251127
/* DMA */
10261128
memory_region_init_io(dmamem, NULL, &dma_ops, machine, "next.dma", 0x5000);
@@ -1033,6 +1135,7 @@ static void next_machine_class_init(ObjectClass *oc, void *data)
10331135

10341136
mc->desc = "NeXT Cube";
10351137
mc->init = next_cube_init;
1138+
mc->block_default_type = IF_SCSI;
10361139
mc->default_ram_size = RAM_SIZE;
10371140
mc->default_ram_id = "next.ram";
10381141
mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");

0 commit comments

Comments
 (0)