xref: /qemu/hw/m68k/next-cube.c (revision 2a031ec7)
1956a7811SThomas Huth /*
2956a7811SThomas Huth  * NeXT Cube System Driver
3956a7811SThomas Huth  *
4956a7811SThomas Huth  * Copyright (c) 2011 Bryce Lanham
5956a7811SThomas Huth  *
6956a7811SThomas Huth  * This code is free software; you can redistribute it and/or modify
7956a7811SThomas Huth  * it under the terms of the GNU General Public License as published
8956a7811SThomas Huth  * by the Free Software Foundation; either version 2 of the License,
9956a7811SThomas Huth  * or (at your option) any later version.
10956a7811SThomas Huth  */
11956a7811SThomas Huth 
12956a7811SThomas Huth #include "qemu/osdep.h"
13956a7811SThomas Huth #include "exec/hwaddr.h"
14956a7811SThomas Huth #include "sysemu/sysemu.h"
15956a7811SThomas Huth #include "sysemu/qtest.h"
16b17bed5bSThomas Huth #include "hw/irq.h"
17956a7811SThomas Huth #include "hw/m68k/next-cube.h"
18956a7811SThomas Huth #include "hw/boards.h"
19956a7811SThomas Huth #include "hw/loader.h"
20956a7811SThomas Huth #include "hw/scsi/esp.h"
21956a7811SThomas Huth #include "hw/sysbus.h"
22db1015e9SEduardo Habkost #include "qom/object.h"
23956a7811SThomas Huth #include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */
24956a7811SThomas Huth #include "hw/block/fdc.h"
25b17bed5bSThomas Huth #include "hw/qdev-properties.h"
26956a7811SThomas Huth #include "qapi/error.h"
27cc37d98bSRichard Henderson #include "qemu/error-report.h"
28956a7811SThomas Huth #include "ui/console.h"
29956a7811SThomas Huth #include "target/m68k/cpu.h"
3075ca77ecSPeter Maydell #include "migration/vmstate.h"
31956a7811SThomas Huth 
32956a7811SThomas Huth /* #define DEBUG_NEXT */
33956a7811SThomas Huth #ifdef DEBUG_NEXT
34956a7811SThomas Huth #define DPRINTF(fmt, ...) \
35956a7811SThomas Huth     do { printf("NeXT: " fmt , ## __VA_ARGS__); } while (0)
36956a7811SThomas Huth #else
37956a7811SThomas Huth #define DPRINTF(fmt, ...) do { } while (0)
38956a7811SThomas Huth #endif
39956a7811SThomas Huth 
40956a7811SThomas Huth #define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube")
418063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(NeXTState, NEXT_MACHINE)
42956a7811SThomas Huth 
43956a7811SThomas Huth #define ENTRY       0x0100001e
44956a7811SThomas Huth #define RAM_SIZE    0x4000000
45956a7811SThomas Huth #define ROM_FILE    "Rev_2.5_v66.bin"
46956a7811SThomas Huth 
47956a7811SThomas Huth typedef struct next_dma {
48956a7811SThomas Huth     uint32_t csr;
49956a7811SThomas Huth 
50956a7811SThomas Huth     uint32_t saved_next;
51956a7811SThomas Huth     uint32_t saved_limit;
52956a7811SThomas Huth     uint32_t saved_start;
53956a7811SThomas Huth     uint32_t saved_stop;
54956a7811SThomas Huth 
55956a7811SThomas Huth     uint32_t next;
56956a7811SThomas Huth     uint32_t limit;
57956a7811SThomas Huth     uint32_t start;
58956a7811SThomas Huth     uint32_t stop;
59956a7811SThomas Huth 
60956a7811SThomas Huth     uint32_t next_initbuf;
61956a7811SThomas Huth     uint32_t size;
62956a7811SThomas Huth } next_dma;
63956a7811SThomas Huth 
64cd4fc142SThomas Huth typedef struct NextRtc {
6588d0c5b0SMark Cave-Ayland     int8_t phase;
66cd4fc142SThomas Huth     uint8_t ram[32];
67cd4fc142SThomas Huth     uint8_t command;
68cd4fc142SThomas Huth     uint8_t value;
69cd4fc142SThomas Huth     uint8_t status;
70cd4fc142SThomas Huth     uint8_t control;
71cd4fc142SThomas Huth     uint8_t retval;
72cd4fc142SThomas Huth } NextRtc;
73cd4fc142SThomas Huth 
74db1015e9SEduardo Habkost struct NeXTState {
75956a7811SThomas Huth     MachineState parent;
76956a7811SThomas Huth 
770d23b1efSMark Cave-Ayland     MemoryRegion rom;
780d23b1efSMark Cave-Ayland     MemoryRegion rom2;
790d23b1efSMark Cave-Ayland     MemoryRegion dmamem;
800d23b1efSMark Cave-Ayland     MemoryRegion bmapm1;
810d23b1efSMark Cave-Ayland     MemoryRegion bmapm2;
820d23b1efSMark Cave-Ayland 
83956a7811SThomas Huth     next_dma dma[10];
84db1015e9SEduardo Habkost };
85956a7811SThomas Huth 
86660bef33SPeter Maydell #define TYPE_NEXT_PC "next-pc"
87660bef33SPeter Maydell OBJECT_DECLARE_SIMPLE_TYPE(NeXTPC, NEXT_PC)
88660bef33SPeter Maydell 
89660bef33SPeter Maydell /* NeXT Peripheral Controller */
90660bef33SPeter Maydell struct NeXTPC {
91660bef33SPeter Maydell     SysBusDevice parent_obj;
92660bef33SPeter Maydell 
93b497f4a1SPeter Maydell     M68kCPU *cpu;
94b497f4a1SPeter Maydell 
9540831636SPeter Maydell     MemoryRegion mmiomem;
961dc7aeaeSPeter Maydell     MemoryRegion scrmem;
9740831636SPeter Maydell 
9840831636SPeter Maydell     uint32_t scr1;
9940831636SPeter Maydell     uint32_t scr2;
10022cf5ee3SMark Cave-Ayland     uint32_t old_scr2;
101ac99317bSPeter Maydell     uint32_t int_mask;
102ac99317bSPeter Maydell     uint32_t int_status;
1038220baa0SMark Cave-Ayland     uint32_t led;
104f2a80c6eSThomas Huth     uint8_t scsi_csr_1;
105f2a80c6eSThomas Huth     uint8_t scsi_csr_2;
106f2a80c6eSThomas Huth 
107f2a80c6eSThomas Huth     qemu_irq scsi_reset;
108f2a80c6eSThomas Huth     qemu_irq scsi_dma;
1096f0face7SPeter Maydell 
1106f0face7SPeter Maydell     NextRtc rtc;
111660bef33SPeter Maydell };
112660bef33SPeter Maydell 
113956a7811SThomas Huth /* Thanks to NeXT forums for this */
114956a7811SThomas Huth /*
115956a7811SThomas Huth static const uint8_t rtc_ram3[32] = {
116956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
117956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x7B, 0x00,
118956a7811SThomas Huth     0x00, 0x00, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x00,
119956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x13
120956a7811SThomas Huth };
121956a7811SThomas Huth */
122956a7811SThomas Huth static const uint8_t rtc_ram2[32] = {
123956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00,
124956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x4b, 0x00,
125956a7811SThomas Huth     0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
126956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x7e,
127956a7811SThomas Huth };
128956a7811SThomas Huth 
129956a7811SThomas Huth #define SCR2_RTCLK 0x2
130956a7811SThomas Huth #define SCR2_RTDATA 0x4
131956a7811SThomas Huth #define SCR2_TOBCD(x) (((x / 10) << 4) + (x % 10))
132956a7811SThomas Huth 
next_scr2_led_update(NeXTPC * s)1333deafd18SMark Cave-Ayland static void next_scr2_led_update(NeXTPC *s)
1343deafd18SMark Cave-Ayland {
1353deafd18SMark Cave-Ayland     if (s->scr2 & 0x1) {
1363deafd18SMark Cave-Ayland         DPRINTF("fault!\n");
1373deafd18SMark Cave-Ayland         s->led++;
1383deafd18SMark Cave-Ayland         if (s->led == 10) {
1393deafd18SMark Cave-Ayland             DPRINTF("LED flashing, possible fault!\n");
1403deafd18SMark Cave-Ayland             s->led = 0;
1413deafd18SMark Cave-Ayland         }
1423deafd18SMark Cave-Ayland     }
1433deafd18SMark Cave-Ayland }
1443deafd18SMark Cave-Ayland 
next_scr2_rtc_update(NeXTPC * s)145039b10acSMark Cave-Ayland static void next_scr2_rtc_update(NeXTPC *s)
146956a7811SThomas Huth {
14722cf5ee3SMark Cave-Ayland     uint8_t old_scr2, scr2_2;
1486f0face7SPeter Maydell     NextRtc *rtc = &s->rtc;
149956a7811SThomas Huth 
150039b10acSMark Cave-Ayland     old_scr2 = extract32(s->old_scr2, 8, 8);
151039b10acSMark Cave-Ayland     scr2_2 = extract32(s->scr2, 8, 8);
15222cf5ee3SMark Cave-Ayland 
153956a7811SThomas Huth     if (scr2_2 & 0x1) {
15488d0c5b0SMark Cave-Ayland         /* DPRINTF("RTC %x phase %i\n", scr2_2, rtc->phase); */
15588d0c5b0SMark Cave-Ayland         if (rtc->phase == -1) {
15688d0c5b0SMark Cave-Ayland             rtc->phase = 0;
157956a7811SThomas Huth         }
158956a7811SThomas Huth         /* If we are in going down clock... do something */
159956a7811SThomas Huth         if (((old_scr2 & SCR2_RTCLK) != (scr2_2 & SCR2_RTCLK)) &&
160956a7811SThomas Huth                 ((scr2_2 & SCR2_RTCLK) == 0)) {
16188d0c5b0SMark Cave-Ayland             if (rtc->phase < 8) {
162cd4fc142SThomas Huth                 rtc->command = (rtc->command << 1) |
163956a7811SThomas Huth                                ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
164956a7811SThomas Huth             }
16588d0c5b0SMark Cave-Ayland             if (rtc->phase >= 8 && rtc->phase < 16) {
166cd4fc142SThomas Huth                 rtc->value = (rtc->value << 1) |
167cd4fc142SThomas Huth                              ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
168956a7811SThomas Huth 
169956a7811SThomas Huth                 /* if we read RAM register, output RT_DATA bit */
170cd4fc142SThomas Huth                 if (rtc->command <= 0x1F) {
171956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
17288d0c5b0SMark Cave-Ayland                     if (rtc->ram[rtc->command] & (0x80 >> (rtc->phase - 8))) {
173956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
174956a7811SThomas Huth                     }
175956a7811SThomas Huth 
176cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
177956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
178956a7811SThomas Huth                 }
179956a7811SThomas Huth                 /* read the status 0x30 */
180cd4fc142SThomas Huth                 if (rtc->command == 0x30) {
181956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
182956a7811SThomas Huth                     /* for now status = 0x98 (new rtc + FTU) */
18388d0c5b0SMark Cave-Ayland                     if (rtc->status & (0x80 >> (rtc->phase - 8))) {
184956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
185956a7811SThomas Huth                     }
186956a7811SThomas Huth 
187cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
188956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
189956a7811SThomas Huth                 }
190956a7811SThomas Huth                 /* read the status 0x31 */
191cd4fc142SThomas Huth                 if (rtc->command == 0x31) {
192956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
19388d0c5b0SMark Cave-Ayland                     if (rtc->control & (0x80 >> (rtc->phase - 8))) {
194956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
195956a7811SThomas Huth                     }
196cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
197956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
198956a7811SThomas Huth                 }
199956a7811SThomas Huth 
200cd4fc142SThomas Huth                 if ((rtc->command >= 0x20) && (rtc->command <= 0x2F)) {
201956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
202956a7811SThomas Huth                     /* for now 0x00 */
203956a7811SThomas Huth                     time_t time_h = time(NULL);
204956a7811SThomas Huth                     struct tm *info = localtime(&time_h);
205956a7811SThomas Huth                     int ret = 0;
206956a7811SThomas Huth 
207cd4fc142SThomas Huth                     switch (rtc->command) {
208956a7811SThomas Huth                     case 0x20:
209956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_sec);
210956a7811SThomas Huth                         break;
211956a7811SThomas Huth                     case 0x21:
212956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_min);
213956a7811SThomas Huth                         break;
214956a7811SThomas Huth                     case 0x22:
215956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_hour);
216956a7811SThomas Huth                         break;
217956a7811SThomas Huth                     case 0x24:
218956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_mday);
219956a7811SThomas Huth                         break;
220956a7811SThomas Huth                     case 0x25:
221956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_mon + 1));
222956a7811SThomas Huth                         break;
223956a7811SThomas Huth                     case 0x26:
224956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_year - 100));
225956a7811SThomas Huth                         break;
226956a7811SThomas Huth 
227956a7811SThomas Huth                     }
228956a7811SThomas Huth 
22988d0c5b0SMark Cave-Ayland                     if (ret & (0x80 >> (rtc->phase - 8))) {
230956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
231956a7811SThomas Huth                     }
232cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
233956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
234956a7811SThomas Huth                 }
235956a7811SThomas Huth 
236956a7811SThomas Huth             }
237956a7811SThomas Huth 
23888d0c5b0SMark Cave-Ayland             rtc->phase++;
23988d0c5b0SMark Cave-Ayland             if (rtc->phase == 16) {
240cd4fc142SThomas Huth                 if (rtc->command >= 0x80 && rtc->command <= 0x9F) {
241cd4fc142SThomas Huth                     rtc->ram[rtc->command - 0x80] = rtc->value;
242956a7811SThomas Huth                 }
243956a7811SThomas Huth                 /* write to x30 register */
244cd4fc142SThomas Huth                 if (rtc->command == 0xB1) {
245956a7811SThomas Huth                     /* clear FTU */
246cd4fc142SThomas Huth                     if (rtc->value & 0x04) {
247cd4fc142SThomas Huth                         rtc->status = rtc->status & (~0x18);
248ac99317bSPeter Maydell                         s->int_status = s->int_status & (~0x04);
249956a7811SThomas Huth                     }
250956a7811SThomas Huth                 }
251956a7811SThomas Huth             }
252956a7811SThomas Huth         }
253956a7811SThomas Huth     } else {
254956a7811SThomas Huth         /* else end or abort */
25588d0c5b0SMark Cave-Ayland         rtc->phase = -1;
256cd4fc142SThomas Huth         rtc->command = 0;
257cd4fc142SThomas Huth         rtc->value = 0;
258956a7811SThomas Huth     }
259039b10acSMark Cave-Ayland 
260039b10acSMark Cave-Ayland     s->scr2 = deposit32(s->scr2, 8, 8, scr2_2);
261956a7811SThomas Huth }
262956a7811SThomas Huth 
next_mmio_read(void * opaque,hwaddr addr,unsigned size)2637e993d93SMark Cave-Ayland static uint64_t next_mmio_read(void *opaque, hwaddr addr, unsigned size)
264956a7811SThomas Huth {
2657e993d93SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
2667e993d93SMark Cave-Ayland     uint64_t val;
267956a7811SThomas Huth 
268956a7811SThomas Huth     switch (addr) {
269956a7811SThomas Huth     case 0x7000:
270ac99317bSPeter Maydell         /* DPRINTF("Read INT status: %x\n", s->int_status); */
2717e993d93SMark Cave-Ayland         val = s->int_status;
2727e993d93SMark Cave-Ayland         break;
273956a7811SThomas Huth 
274956a7811SThomas Huth     case 0x7800:
275ac99317bSPeter Maydell         DPRINTF("MMIO Read INT mask: %x\n", s->int_mask);
2767e993d93SMark Cave-Ayland         val = s->int_mask;
277956a7811SThomas Huth         break;
278956a7811SThomas Huth 
2797e993d93SMark Cave-Ayland     case 0xc000 ... 0xc003:
2807e993d93SMark Cave-Ayland         val = extract32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
2817e993d93SMark Cave-Ayland                         size << 3);
2827e993d93SMark Cave-Ayland         break;
283956a7811SThomas Huth 
2847e993d93SMark Cave-Ayland     case 0xd000 ... 0xd003:
2857e993d93SMark Cave-Ayland         val = extract32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
2867e993d93SMark Cave-Ayland                         size << 3);
2877e993d93SMark Cave-Ayland         break;
288956a7811SThomas Huth 
2897e993d93SMark Cave-Ayland     case 0x14020:
2907e993d93SMark Cave-Ayland         val = 0x7f;
291956a7811SThomas Huth         break;
292956a7811SThomas Huth 
293956a7811SThomas Huth     default:
2947e993d93SMark Cave-Ayland         val = 0;
2957e993d93SMark Cave-Ayland         DPRINTF("MMIO Read @ 0x%"HWADDR_PRIx" size %d\n", addr, size);
2967e993d93SMark Cave-Ayland         break;
297956a7811SThomas Huth     }
298956a7811SThomas Huth 
2997e993d93SMark Cave-Ayland     return val;
300956a7811SThomas Huth }
301956a7811SThomas Huth 
next_mmio_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)3027e993d93SMark Cave-Ayland static void next_mmio_write(void *opaque, hwaddr addr, uint64_t val,
303956a7811SThomas Huth                             unsigned size)
304956a7811SThomas Huth {
30540831636SPeter Maydell     NeXTPC *s = NEXT_PC(opaque);
306956a7811SThomas Huth 
3077e993d93SMark Cave-Ayland     switch (addr) {
3087e993d93SMark Cave-Ayland     case 0x7000:
3097e993d93SMark Cave-Ayland         DPRINTF("INT Status old: %x new: %x\n", s->int_status,
3107e993d93SMark Cave-Ayland                 (unsigned int)val);
3117e993d93SMark Cave-Ayland         s->int_status = val;
312956a7811SThomas Huth         break;
3137e993d93SMark Cave-Ayland 
3147e993d93SMark Cave-Ayland     case 0x7800:
3157e993d93SMark Cave-Ayland         DPRINTF("INT Mask old: %x new: %x\n", s->int_mask, (unsigned int)val);
3167e993d93SMark Cave-Ayland         s->int_mask  = val;
317956a7811SThomas Huth         break;
3187e993d93SMark Cave-Ayland 
3197e993d93SMark Cave-Ayland     case 0xc000 ... 0xc003:
3207e993d93SMark Cave-Ayland         DPRINTF("SCR1 Write: %x\n", (unsigned int)val);
3217e993d93SMark Cave-Ayland         s->scr1 = deposit32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
3227e993d93SMark Cave-Ayland                             size << 3, val);
323956a7811SThomas Huth         break;
3247e993d93SMark Cave-Ayland 
3257e993d93SMark Cave-Ayland     case 0xd000 ... 0xd003:
32622cf5ee3SMark Cave-Ayland         s->scr2 = deposit32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
32722cf5ee3SMark Cave-Ayland                             size << 3, val);
3283deafd18SMark Cave-Ayland         next_scr2_led_update(s);
329039b10acSMark Cave-Ayland         next_scr2_rtc_update(s);
33022cf5ee3SMark Cave-Ayland         s->old_scr2 = s->scr2;
3317e993d93SMark Cave-Ayland         break;
3327e993d93SMark Cave-Ayland 
333956a7811SThomas Huth     default:
3347e993d93SMark Cave-Ayland         DPRINTF("MMIO Write @ 0x%"HWADDR_PRIx " with 0x%x size %u\n", addr,
3357e993d93SMark Cave-Ayland                 (unsigned int)val, size);
336956a7811SThomas Huth     }
337956a7811SThomas Huth }
338956a7811SThomas Huth 
3397e993d93SMark Cave-Ayland static const MemoryRegionOps next_mmio_ops = {
3407e993d93SMark Cave-Ayland     .read = next_mmio_read,
3417e993d93SMark Cave-Ayland     .write = next_mmio_write,
342956a7811SThomas Huth     .valid.min_access_size = 1,
343956a7811SThomas Huth     .valid.max_access_size = 4,
3447e993d93SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
345956a7811SThomas Huth };
346956a7811SThomas Huth 
347956a7811SThomas Huth #define SCSICSR_ENABLE  0x01
348956a7811SThomas Huth #define SCSICSR_RESET   0x02  /* reset scsi dma */
349956a7811SThomas Huth #define SCSICSR_FIFOFL  0x04
350956a7811SThomas Huth #define SCSICSR_DMADIR  0x08  /* if set, scsi to mem */
351956a7811SThomas Huth #define SCSICSR_CPUDMA  0x10  /* if set, dma enabled */
352956a7811SThomas Huth #define SCSICSR_INTMASK 0x20  /* if set, interrupt enabled */
353956a7811SThomas Huth 
next_scr_readfn(void * opaque,hwaddr addr,unsigned size)3540d60da39SMark Cave-Ayland static uint64_t next_scr_readfn(void *opaque, hwaddr addr, unsigned size)
355956a7811SThomas Huth {
3560d60da39SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
3570d60da39SMark Cave-Ayland     uint64_t val;
3580d60da39SMark Cave-Ayland 
3590d60da39SMark Cave-Ayland     switch (addr) {
3600d60da39SMark Cave-Ayland     case 0x14108:
3610d60da39SMark Cave-Ayland         DPRINTF("FD read @ %x\n", (unsigned int)addr);
3620d60da39SMark Cave-Ayland         val = 0x40 | 0x04 | 0x2 | 0x1;
3630d60da39SMark Cave-Ayland         break;
3640d60da39SMark Cave-Ayland 
3650d60da39SMark Cave-Ayland     case 0x14020:
3660d60da39SMark Cave-Ayland         DPRINTF("SCSI 4020  STATUS READ %X\n", s->scsi_csr_1);
3670d60da39SMark Cave-Ayland         val = s->scsi_csr_1;
3680d60da39SMark Cave-Ayland         break;
3690d60da39SMark Cave-Ayland 
3700d60da39SMark Cave-Ayland     case 0x14021:
3710d60da39SMark Cave-Ayland         DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
3720d60da39SMark Cave-Ayland         val = 0x40;
3730d60da39SMark Cave-Ayland         break;
3740d60da39SMark Cave-Ayland 
3750d60da39SMark Cave-Ayland     /*
3760d60da39SMark Cave-Ayland      * These 4 registers are the hardware timer, not sure which register
3770d60da39SMark Cave-Ayland      * is the latch instead of data, but no problems so far.
3780d60da39SMark Cave-Ayland      *
3790d60da39SMark Cave-Ayland      * Hack: We need to have the LSB change consistently to make it work
3800d60da39SMark Cave-Ayland      */
3810d60da39SMark Cave-Ayland     case 0x1a000 ... 0x1a003:
3820d60da39SMark Cave-Ayland         val = extract32(clock(), (4 - (addr - 0x1a000) - size) << 3,
3830d60da39SMark Cave-Ayland                         size << 3);
3840d60da39SMark Cave-Ayland         break;
3850d60da39SMark Cave-Ayland 
3860d60da39SMark Cave-Ayland     /* For now return dummy byte to allow the Ethernet test to timeout */
3870d60da39SMark Cave-Ayland     case 0x6000:
3880d60da39SMark Cave-Ayland         val = 0xff;
3890d60da39SMark Cave-Ayland         break;
3900d60da39SMark Cave-Ayland 
3910d60da39SMark Cave-Ayland     default:
3920d60da39SMark Cave-Ayland         DPRINTF("BMAP Read @ 0x%x size %u\n", (unsigned int)addr, size);
3930d60da39SMark Cave-Ayland         val = 0;
3940d60da39SMark Cave-Ayland         break;
3950d60da39SMark Cave-Ayland     }
3960d60da39SMark Cave-Ayland 
3970d60da39SMark Cave-Ayland     return val;
3980d60da39SMark Cave-Ayland }
3990d60da39SMark Cave-Ayland 
next_scr_writefn(void * opaque,hwaddr addr,uint64_t val,unsigned size)4000d60da39SMark Cave-Ayland static void next_scr_writefn(void *opaque, hwaddr addr, uint64_t val,
4010d60da39SMark Cave-Ayland                              unsigned size)
4020d60da39SMark Cave-Ayland {
4030d60da39SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
4040d60da39SMark Cave-Ayland 
405956a7811SThomas Huth     switch (addr) {
406956a7811SThomas Huth     case 0x14108:
407956a7811SThomas Huth         DPRINTF("FDCSR Write: %x\n", value);
4080d60da39SMark Cave-Ayland         if (val == 0x0) {
409956a7811SThomas Huth             /* qemu_irq_raise(s->fd_irq[0]); */
410956a7811SThomas Huth         }
411956a7811SThomas Huth         break;
4120d60da39SMark Cave-Ayland 
413956a7811SThomas Huth     case 0x14020: /* SCSI Control Register */
4140d60da39SMark Cave-Ayland         if (val & SCSICSR_FIFOFL) {
415956a7811SThomas Huth             DPRINTF("SCSICSR FIFO Flush\n");
416956a7811SThomas Huth             /* will have to add another irq to the esp if this is needed */
417956a7811SThomas Huth             /* esp_puflush_fifo(esp_g); */
418956a7811SThomas Huth         }
419956a7811SThomas Huth 
4200d60da39SMark Cave-Ayland         if (val & SCSICSR_ENABLE) {
421956a7811SThomas Huth             DPRINTF("SCSICSR Enable\n");
422956a7811SThomas Huth             /*
423956a7811SThomas Huth              * qemu_irq_raise(s->scsi_dma);
424956a7811SThomas Huth              * s->scsi_csr_1 = 0xc0;
425956a7811SThomas Huth              * s->scsi_csr_1 |= 0x1;
426956a7811SThomas Huth              * qemu_irq_pulse(s->scsi_dma);
427956a7811SThomas Huth              */
428956a7811SThomas Huth         }
429956a7811SThomas Huth         /*
430956a7811SThomas Huth          * else
431956a7811SThomas Huth          *     s->scsi_csr_1 &= ~SCSICSR_ENABLE;
432956a7811SThomas Huth          */
433956a7811SThomas Huth 
4340d60da39SMark Cave-Ayland         if (val & SCSICSR_RESET) {
435956a7811SThomas Huth             DPRINTF("SCSICSR Reset\n");
436956a7811SThomas Huth             /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
437f2a80c6eSThomas Huth             qemu_irq_raise(s->scsi_reset);
438f2a80c6eSThomas Huth             s->scsi_csr_1 &= ~(SCSICSR_INTMASK | 0x80 | 0x1);
439f2a80c6eSThomas Huth             qemu_irq_lower(s->scsi_reset);
440956a7811SThomas Huth         }
4410d60da39SMark Cave-Ayland         if (val & SCSICSR_DMADIR) {
442956a7811SThomas Huth             DPRINTF("SCSICSR DMAdir\n");
443956a7811SThomas Huth         }
4440d60da39SMark Cave-Ayland         if (val & SCSICSR_CPUDMA) {
445956a7811SThomas Huth             DPRINTF("SCSICSR CPUDMA\n");
446956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_dma); */
447ac99317bSPeter Maydell             s->int_status |= 0x4000000;
448956a7811SThomas Huth         } else {
449f2a80c6eSThomas Huth             /* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
450ac99317bSPeter Maydell             s->int_status &= ~(0x4000000);
451f2a80c6eSThomas Huth             /* qemu_irq_lower(s->scsi_dma); */
452956a7811SThomas Huth         }
4530d60da39SMark Cave-Ayland         if (val & SCSICSR_INTMASK) {
454956a7811SThomas Huth             DPRINTF("SCSICSR INTMASK\n");
455956a7811SThomas Huth             /*
456956a7811SThomas Huth              * int_mask &= ~0x1000;
4570d60da39SMark Cave-Ayland              * s->scsi_csr_1 |= val;
458956a7811SThomas Huth              * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
459956a7811SThomas Huth              * if (s->scsi_queued) {
460956a7811SThomas Huth              *     s->scsi_queued = 0;
461956a7811SThomas Huth              *     next_irq(s, NEXT_SCSI_I, level);
462956a7811SThomas Huth              * }
463956a7811SThomas Huth              */
464956a7811SThomas Huth         } else {
465956a7811SThomas Huth             /* int_mask |= 0x1000; */
466956a7811SThomas Huth         }
4670d60da39SMark Cave-Ayland         if (val & 0x80) {
468956a7811SThomas Huth             /* int_mask |= 0x1000; */
469956a7811SThomas Huth             /* s->scsi_csr_1 |= 0x80; */
470956a7811SThomas Huth         }
4710d60da39SMark Cave-Ayland         DPRINTF("SCSICSR Write: %x\n", val);
4720d60da39SMark Cave-Ayland         /* s->scsi_csr_1 = val; */
4730d60da39SMark Cave-Ayland         break;
4740d60da39SMark Cave-Ayland 
475956a7811SThomas Huth     /* Hardware timer latch - not implemented yet */
476956a7811SThomas Huth     case 0x1a000:
477956a7811SThomas Huth     default:
4780d60da39SMark Cave-Ayland         DPRINTF("BMAP Write @ 0x%x with 0x%x size %u\n", (unsigned int)addr,
4790d60da39SMark Cave-Ayland                 val, size);
480956a7811SThomas Huth     }
481956a7811SThomas Huth }
482956a7811SThomas Huth 
4830d60da39SMark Cave-Ayland static const MemoryRegionOps next_scr_ops = {
4840d60da39SMark Cave-Ayland     .read = next_scr_readfn,
4850d60da39SMark Cave-Ayland     .write = next_scr_writefn,
486956a7811SThomas Huth     .valid.min_access_size = 1,
487956a7811SThomas Huth     .valid.max_access_size = 4,
4880d60da39SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
489956a7811SThomas Huth };
490956a7811SThomas Huth 
491956a7811SThomas Huth #define NEXTDMA_SCSI(x)      (0x10 + x)
492956a7811SThomas Huth #define NEXTDMA_FD(x)        (0x10 + x)
493956a7811SThomas Huth #define NEXTDMA_ENTX(x)      (0x110 + x)
494956a7811SThomas Huth #define NEXTDMA_ENRX(x)      (0x150 + x)
495956a7811SThomas Huth #define NEXTDMA_CSR          0x0
496956a7811SThomas Huth #define NEXTDMA_NEXT         0x4000
497956a7811SThomas Huth #define NEXTDMA_LIMIT        0x4004
498956a7811SThomas Huth #define NEXTDMA_START        0x4008
499956a7811SThomas Huth #define NEXTDMA_STOP         0x400c
500956a7811SThomas Huth #define NEXTDMA_NEXT_INIT    0x4200
501956a7811SThomas Huth #define NEXTDMA_SIZE         0x4204
502956a7811SThomas Huth 
next_dma_write(void * opaque,hwaddr addr,uint64_t val,unsigned int size)503c0dedcf4SMark Cave-Ayland static void next_dma_write(void *opaque, hwaddr addr, uint64_t val,
504956a7811SThomas Huth                            unsigned int size)
505956a7811SThomas Huth {
506956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
507956a7811SThomas Huth 
508956a7811SThomas Huth     switch (addr) {
509956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
510c0dedcf4SMark Cave-Ayland         if (val & DMA_DEV2M) {
511956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_DEV2M;
512956a7811SThomas Huth         }
513956a7811SThomas Huth 
514c0dedcf4SMark Cave-Ayland         if (val & DMA_SETENABLE) {
515956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
516956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_ENABLE;
517956a7811SThomas Huth         }
518c0dedcf4SMark Cave-Ayland         if (val & DMA_SETSUPDATE) {
519956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_SUPDATE;
520956a7811SThomas Huth         }
521c0dedcf4SMark Cave-Ayland         if (val & DMA_CLRCOMPLETE) {
522956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~DMA_COMPLETE;
523956a7811SThomas Huth         }
524956a7811SThomas Huth 
525c0dedcf4SMark Cave-Ayland         if (val & DMA_RESET) {
526956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
527956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
528956a7811SThomas Huth         }
529956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
530956a7811SThomas Huth         break;
531c0dedcf4SMark Cave-Ayland 
532956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
533c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].next_initbuf = val;
534956a7811SThomas Huth         break;
535c0dedcf4SMark Cave-Ayland 
536956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
537c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].next = val;
538956a7811SThomas Huth         break;
539c0dedcf4SMark Cave-Ayland 
540956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
541c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].limit = val;
542956a7811SThomas Huth         break;
543c0dedcf4SMark Cave-Ayland 
544956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
545c0dedcf4SMark Cave-Ayland         if (val & DMA_DEV2M) {
546956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_DEV2M;
547956a7811SThomas Huth         }
548c0dedcf4SMark Cave-Ayland         if (val & DMA_SETENABLE) {
549956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
550956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_ENABLE;
551956a7811SThomas Huth         }
552c0dedcf4SMark Cave-Ayland         if (val & DMA_SETSUPDATE) {
553956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_SUPDATE;
554956a7811SThomas Huth         }
555c0dedcf4SMark Cave-Ayland         if (val & DMA_CLRCOMPLETE) {
556956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~DMA_COMPLETE;
557956a7811SThomas Huth         }
558956a7811SThomas Huth 
559c0dedcf4SMark Cave-Ayland         if (val & DMA_RESET) {
560956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
561956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
562956a7811SThomas Huth             /* DPRINTF("SCSI DMA RESET\n"); */
563956a7811SThomas Huth         }
564956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
565956a7811SThomas Huth         break;
566956a7811SThomas Huth 
567956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
568c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].next = val;
569956a7811SThomas Huth         break;
570956a7811SThomas Huth 
571956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
572c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].limit = val;
573956a7811SThomas Huth         break;
574956a7811SThomas Huth 
575956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
576c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].start = val;
577956a7811SThomas Huth         break;
578956a7811SThomas Huth 
579956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
580c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].stop = val;
581956a7811SThomas Huth         break;
582956a7811SThomas Huth 
583956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
584c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].next_initbuf = val;
585956a7811SThomas Huth         break;
586956a7811SThomas Huth 
587956a7811SThomas Huth     default:
588956a7811SThomas Huth         DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)value);
589956a7811SThomas Huth     }
590956a7811SThomas Huth }
591956a7811SThomas Huth 
next_dma_read(void * opaque,hwaddr addr,unsigned int size)592c0dedcf4SMark Cave-Ayland static uint64_t next_dma_read(void *opaque, hwaddr addr, unsigned int size)
593956a7811SThomas Huth {
594956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
595c0dedcf4SMark Cave-Ayland     uint64_t val;
596956a7811SThomas Huth 
597956a7811SThomas Huth     switch (addr) {
598956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
599956a7811SThomas Huth         DPRINTF("SCSI DMA CSR READ\n");
600c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].csr;
601c0dedcf4SMark Cave-Ayland         break;
602c0dedcf4SMark Cave-Ayland 
603956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
604c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].csr;
605c0dedcf4SMark Cave-Ayland         break;
606c0dedcf4SMark Cave-Ayland 
607956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
608c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].next_initbuf;
609c0dedcf4SMark Cave-Ayland         break;
610c0dedcf4SMark Cave-Ayland 
611956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
612c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].next;
613c0dedcf4SMark Cave-Ayland         break;
614c0dedcf4SMark Cave-Ayland 
615956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
616c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].limit;
617c0dedcf4SMark Cave-Ayland         break;
618956a7811SThomas Huth 
619956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
620c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].next;
621c0dedcf4SMark Cave-Ayland         break;
622c0dedcf4SMark Cave-Ayland 
623956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
624c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].next_initbuf;
625c0dedcf4SMark Cave-Ayland         break;
626c0dedcf4SMark Cave-Ayland 
627956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
628c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].limit;
629c0dedcf4SMark Cave-Ayland         break;
630c0dedcf4SMark Cave-Ayland 
631956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
632c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].start;
633c0dedcf4SMark Cave-Ayland         break;
634c0dedcf4SMark Cave-Ayland 
635956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
636c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].stop;
637c0dedcf4SMark Cave-Ayland         break;
638956a7811SThomas Huth 
639956a7811SThomas Huth     default:
640956a7811SThomas Huth         DPRINTF("DMA read @ %x\n", (unsigned int)addr);
641c0dedcf4SMark Cave-Ayland         val = 0;
642956a7811SThomas Huth     }
643956a7811SThomas Huth 
644956a7811SThomas Huth     /*
645956a7811SThomas Huth      * once the csr's are done, subtract 0x3FEC from the addr, and that will
646956a7811SThomas Huth      * normalize the upper registers
647956a7811SThomas Huth      */
648c0dedcf4SMark Cave-Ayland 
649c0dedcf4SMark Cave-Ayland     return val;
650956a7811SThomas Huth }
651956a7811SThomas Huth 
652c0dedcf4SMark Cave-Ayland static const MemoryRegionOps next_dma_ops = {
653c0dedcf4SMark Cave-Ayland     .read = next_dma_read,
654c0dedcf4SMark Cave-Ayland     .write = next_dma_write,
655956a7811SThomas Huth     .impl.min_access_size = 4,
656956a7811SThomas Huth     .valid.min_access_size = 4,
657956a7811SThomas Huth     .valid.max_access_size = 4,
658c0dedcf4SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
659956a7811SThomas Huth };
660956a7811SThomas Huth 
next_irq(void * opaque,int number,int level)661c8abcc87SPeter Maydell static void next_irq(void *opaque, int number, int level)
662956a7811SThomas Huth {
663b497f4a1SPeter Maydell     NeXTPC *s = NEXT_PC(opaque);
664b497f4a1SPeter Maydell     M68kCPU *cpu = s->cpu;
665956a7811SThomas Huth     int shift = 0;
666956a7811SThomas Huth 
6678b81968cSMichael Tokarev     /* first switch sets interrupt status */
668956a7811SThomas Huth     /* DPRINTF("IRQ %i\n",number); */
669956a7811SThomas Huth     switch (number) {
670956a7811SThomas Huth     /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
671956a7811SThomas Huth     case NEXT_FD_I:
6725012a894SPhilippe Mathieu-Daudé         shift = 7;
673956a7811SThomas Huth         break;
674956a7811SThomas Huth     case NEXT_KBD_I:
675956a7811SThomas Huth         shift = 3;
676956a7811SThomas Huth         break;
677956a7811SThomas Huth     case NEXT_PWR_I:
678956a7811SThomas Huth         shift = 2;
679956a7811SThomas Huth         break;
680956a7811SThomas Huth     case NEXT_ENRX_I:
681956a7811SThomas Huth         shift = 9;
682956a7811SThomas Huth         break;
683956a7811SThomas Huth     case NEXT_ENTX_I:
684956a7811SThomas Huth         shift = 10;
685956a7811SThomas Huth         break;
686956a7811SThomas Huth     case NEXT_SCSI_I:
687956a7811SThomas Huth         shift = 12;
688956a7811SThomas Huth         break;
689956a7811SThomas Huth     case NEXT_CLK_I:
690956a7811SThomas Huth         shift = 5;
691956a7811SThomas Huth         break;
692956a7811SThomas Huth 
693956a7811SThomas Huth     /* level 5 - scc (serial) */
694956a7811SThomas Huth     case NEXT_SCC_I:
695956a7811SThomas Huth         shift = 17;
696956a7811SThomas Huth         break;
697956a7811SThomas Huth 
698956a7811SThomas Huth     /* level 6 - audio etherrx/tx dma */
699956a7811SThomas Huth     case NEXT_ENTX_DMA_I:
700956a7811SThomas Huth         shift = 28;
701956a7811SThomas Huth         break;
702956a7811SThomas Huth     case NEXT_ENRX_DMA_I:
703956a7811SThomas Huth         shift = 27;
704956a7811SThomas Huth         break;
705956a7811SThomas Huth     case NEXT_SCSI_DMA_I:
706956a7811SThomas Huth         shift = 26;
707956a7811SThomas Huth         break;
708956a7811SThomas Huth     case NEXT_SND_I:
709956a7811SThomas Huth         shift = 23;
710956a7811SThomas Huth         break;
711956a7811SThomas Huth     case NEXT_SCC_DMA_I:
712956a7811SThomas Huth         shift = 21;
713956a7811SThomas Huth         break;
714956a7811SThomas Huth 
715956a7811SThomas Huth     }
716956a7811SThomas Huth     /*
717956a7811SThomas Huth      * this HAS to be wrong, the interrupt handlers in mach and together
718956a7811SThomas Huth      * int_status and int_mask and return if there is a hit
719956a7811SThomas Huth      */
720ac99317bSPeter Maydell     if (s->int_mask & (1 << shift)) {
721956a7811SThomas Huth         DPRINTF("%x interrupt masked @ %x\n", 1 << shift, cpu->env.pc);
722956a7811SThomas Huth         /* return; */
723956a7811SThomas Huth     }
724956a7811SThomas Huth 
725956a7811SThomas Huth     /* second switch triggers the correct interrupt */
726956a7811SThomas Huth     if (level) {
727ac99317bSPeter Maydell         s->int_status |= 1 << shift;
728956a7811SThomas Huth 
729956a7811SThomas Huth         switch (number) {
730956a7811SThomas Huth         /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
731956a7811SThomas Huth         case NEXT_FD_I:
732956a7811SThomas Huth         case NEXT_KBD_I:
733956a7811SThomas Huth         case NEXT_PWR_I:
734956a7811SThomas Huth         case NEXT_ENRX_I:
735956a7811SThomas Huth         case NEXT_ENTX_I:
736956a7811SThomas Huth         case NEXT_SCSI_I:
737956a7811SThomas Huth         case NEXT_CLK_I:
738956a7811SThomas Huth             m68k_set_irq_level(cpu, 3, 27);
739956a7811SThomas Huth             break;
740956a7811SThomas Huth 
741956a7811SThomas Huth         /* level 5 - scc (serial) */
742956a7811SThomas Huth         case NEXT_SCC_I:
743956a7811SThomas Huth             m68k_set_irq_level(cpu, 5, 29);
744956a7811SThomas Huth             break;
745956a7811SThomas Huth 
746956a7811SThomas Huth         /* level 6 - audio etherrx/tx dma */
747956a7811SThomas Huth         case NEXT_ENTX_DMA_I:
748956a7811SThomas Huth         case NEXT_ENRX_DMA_I:
749956a7811SThomas Huth         case NEXT_SCSI_DMA_I:
750956a7811SThomas Huth         case NEXT_SND_I:
751956a7811SThomas Huth         case NEXT_SCC_DMA_I:
752956a7811SThomas Huth             m68k_set_irq_level(cpu, 6, 30);
753956a7811SThomas Huth             break;
754956a7811SThomas Huth         }
755956a7811SThomas Huth     } else {
756ac99317bSPeter Maydell         s->int_status &= ~(1 << shift);
757956a7811SThomas Huth         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
758956a7811SThomas Huth     }
759956a7811SThomas Huth }
760956a7811SThomas Huth 
nextdma_write(void * opaque,uint8_t * buf,int size,int type)761f2a80c6eSThomas Huth static void nextdma_write(void *opaque, uint8_t *buf, int size, int type)
762f2a80c6eSThomas Huth {
763f2a80c6eSThomas Huth     uint32_t base_addr;
764f2a80c6eSThomas Huth     int irq = 0;
765f2a80c6eSThomas Huth     uint8_t align = 16;
766f2a80c6eSThomas Huth     NeXTState *next_state = NEXT_MACHINE(qdev_get_machine());
767f2a80c6eSThomas Huth 
768f2a80c6eSThomas Huth     if (type == NEXTDMA_ENRX || type == NEXTDMA_ENTX) {
769f2a80c6eSThomas Huth         align = 32;
770f2a80c6eSThomas Huth     }
771f2a80c6eSThomas Huth     /* Most DMA is supposedly 16 byte aligned */
772f2a80c6eSThomas Huth     if ((size % align) != 0) {
773f2a80c6eSThomas Huth         size -= size % align;
774f2a80c6eSThomas Huth         size += align;
775f2a80c6eSThomas Huth     }
776f2a80c6eSThomas Huth 
777f2a80c6eSThomas Huth     /*
778f2a80c6eSThomas Huth      * prom sets the dma start using initbuf while the bootloader uses next
779f2a80c6eSThomas Huth      * so we check to see if initbuf is 0
780f2a80c6eSThomas Huth      */
781f2a80c6eSThomas Huth     if (next_state->dma[type].next_initbuf == 0) {
782f2a80c6eSThomas Huth         base_addr = next_state->dma[type].next;
783f2a80c6eSThomas Huth     } else {
784f2a80c6eSThomas Huth         base_addr = next_state->dma[type].next_initbuf;
785f2a80c6eSThomas Huth     }
786f2a80c6eSThomas Huth 
787f2a80c6eSThomas Huth     cpu_physical_memory_write(base_addr, buf, size);
788f2a80c6eSThomas Huth 
789f2a80c6eSThomas Huth     next_state->dma[type].next_initbuf = 0;
790f2a80c6eSThomas Huth 
791f2a80c6eSThomas Huth     /* saved limit is checked to calculate packet size by both, rom and netbsd */
792f2a80c6eSThomas Huth     next_state->dma[type].saved_limit = (next_state->dma[type].next + size);
793f2a80c6eSThomas Huth     next_state->dma[type].saved_next  = (next_state->dma[type].next);
794f2a80c6eSThomas Huth 
795f2a80c6eSThomas Huth     /*
796f2a80c6eSThomas Huth      * 32 bytes under savedbase seems to be some kind of register
797f2a80c6eSThomas Huth      * of which the purpose is unknown as of yet
798f2a80c6eSThomas Huth      */
799f2a80c6eSThomas Huth     /* stl_phys(s->rx_dma.base-32,0xFFFFFFFF); */
800f2a80c6eSThomas Huth 
801f2a80c6eSThomas Huth     if (!(next_state->dma[type].csr & DMA_SUPDATE)) {
802f2a80c6eSThomas Huth         next_state->dma[type].next  = next_state->dma[type].start;
803f2a80c6eSThomas Huth         next_state->dma[type].limit = next_state->dma[type].stop;
804f2a80c6eSThomas Huth     }
805f2a80c6eSThomas Huth 
806f2a80c6eSThomas Huth     /* Set dma registers and raise an irq */
807f2a80c6eSThomas Huth     next_state->dma[type].csr |= DMA_COMPLETE; /* DON'T CHANGE THIS! */
808f2a80c6eSThomas Huth 
809f2a80c6eSThomas Huth     switch (type) {
810f2a80c6eSThomas Huth     case NEXTDMA_SCSI:
811f2a80c6eSThomas Huth         irq = NEXT_SCSI_DMA_I;
812f2a80c6eSThomas Huth         break;
813f2a80c6eSThomas Huth     }
814f2a80c6eSThomas Huth 
815f2a80c6eSThomas Huth     next_irq(opaque, irq, 1);
816f2a80c6eSThomas Huth     next_irq(opaque, irq, 0);
817f2a80c6eSThomas Huth }
818f2a80c6eSThomas Huth 
nextscsi_read(void * opaque,uint8_t * buf,int len)819f2a80c6eSThomas Huth static void nextscsi_read(void *opaque, uint8_t *buf, int len)
820f2a80c6eSThomas Huth {
821f2a80c6eSThomas Huth     DPRINTF("SCSI READ: %x\n", len);
822f2a80c6eSThomas Huth     abort();
823f2a80c6eSThomas Huth }
824f2a80c6eSThomas Huth 
nextscsi_write(void * opaque,uint8_t * buf,int size)825f2a80c6eSThomas Huth static void nextscsi_write(void *opaque, uint8_t *buf, int size)
826f2a80c6eSThomas Huth {
827f2a80c6eSThomas Huth     DPRINTF("SCSI WRITE: %i\n", size);
828f2a80c6eSThomas Huth     nextdma_write(opaque, buf, size, NEXTDMA_SCSI);
829f2a80c6eSThomas Huth }
830f2a80c6eSThomas Huth 
next_scsi_init(DeviceState * pcdev,M68kCPU * cpu)831f2a80c6eSThomas Huth static void next_scsi_init(DeviceState *pcdev, M68kCPU *cpu)
832f2a80c6eSThomas Huth {
833f2a80c6eSThomas Huth     struct NeXTPC *next_pc = NEXT_PC(pcdev);
834f2a80c6eSThomas Huth     DeviceState *dev;
835f2a80c6eSThomas Huth     SysBusDevice *sysbusdev;
836f2a80c6eSThomas Huth     SysBusESPState *sysbus_esp;
837f2a80c6eSThomas Huth     ESPState *esp;
838f2a80c6eSThomas Huth 
839f2a80c6eSThomas Huth     dev = qdev_new(TYPE_SYSBUS_ESP);
840f2a80c6eSThomas Huth     sysbus_esp = SYSBUS_ESP(dev);
841f2a80c6eSThomas Huth     esp = &sysbus_esp->esp;
842f2a80c6eSThomas Huth     esp->dma_memory_read = nextscsi_read;
843f2a80c6eSThomas Huth     esp->dma_memory_write = nextscsi_write;
844f2a80c6eSThomas Huth     esp->dma_opaque = pcdev;
845f2a80c6eSThomas Huth     sysbus_esp->it_shift = 0;
846f2a80c6eSThomas Huth     esp->dma_enabled = 1;
847f2a80c6eSThomas Huth     sysbusdev = SYS_BUS_DEVICE(dev);
848f2a80c6eSThomas Huth     sysbus_realize_and_unref(sysbusdev, &error_fatal);
849f2a80c6eSThomas Huth     sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(pcdev, NEXT_SCSI_I));
850f2a80c6eSThomas Huth     sysbus_mmio_map(sysbusdev, 0, 0x2114000);
851f2a80c6eSThomas Huth 
852f2a80c6eSThomas Huth     next_pc->scsi_reset = qdev_get_gpio_in(dev, 0);
853f2a80c6eSThomas Huth     next_pc->scsi_dma = qdev_get_gpio_in(dev, 1);
854f2a80c6eSThomas Huth 
855f2a80c6eSThomas Huth     scsi_bus_legacy_handle_cmdline(&esp->bus);
856f2a80c6eSThomas Huth }
857f2a80c6eSThomas Huth 
next_escc_init(DeviceState * pcdev)858b497f4a1SPeter Maydell static void next_escc_init(DeviceState *pcdev)
859b17bed5bSThomas Huth {
860b17bed5bSThomas Huth     DeviceState *dev;
861b17bed5bSThomas Huth     SysBusDevice *s;
862b17bed5bSThomas Huth 
8633e80f690SMarkus Armbruster     dev = qdev_new(TYPE_ESCC);
864b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "disabled", 0);
865b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "frequency", 9600 * 384);
866b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "it_shift", 0);
867b17bed5bSThomas Huth     qdev_prop_set_bit(dev, "bit_swap", true);
868b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrB", serial_hd(1));
869b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrA", serial_hd(0));
870b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
871b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
872b17bed5bSThomas Huth 
873b17bed5bSThomas Huth     s = SYS_BUS_DEVICE(dev);
8743c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
875d9cd4039SPeter Maydell     sysbus_connect_irq(s, 0, qdev_get_gpio_in(pcdev, NEXT_SCC_I));
876d9cd4039SPeter Maydell     sysbus_connect_irq(s, 1, qdev_get_gpio_in(pcdev, NEXT_SCC_DMA_I));
877b17bed5bSThomas Huth     sysbus_mmio_map(s, 0, 0x2118000);
878b17bed5bSThomas Huth }
879b17bed5bSThomas Huth 
next_pc_reset(DeviceState * dev)880660bef33SPeter Maydell static void next_pc_reset(DeviceState *dev)
881660bef33SPeter Maydell {
88240831636SPeter Maydell     NeXTPC *s = NEXT_PC(dev);
88340831636SPeter Maydell 
88440831636SPeter Maydell     /* Set internal registers to initial values */
88540831636SPeter Maydell     /*     0x0000XX00 << vital bits */
88640831636SPeter Maydell     s->scr1 = 0x00011102;
88740831636SPeter Maydell     s->scr2 = 0x00ff0c80;
88822cf5ee3SMark Cave-Ayland     s->old_scr2 = s->scr2;
8896f0face7SPeter Maydell 
8906f0face7SPeter Maydell     s->rtc.status = 0x90;
8916f0face7SPeter Maydell 
8926f0face7SPeter Maydell     /* Load RTC RAM - TODO: provide possibility to load contents from file */
8936f0face7SPeter Maydell     memcpy(s->rtc.ram, rtc_ram2, 32);
894660bef33SPeter Maydell }
895660bef33SPeter Maydell 
next_pc_realize(DeviceState * dev,Error ** errp)896660bef33SPeter Maydell static void next_pc_realize(DeviceState *dev, Error **errp)
897660bef33SPeter Maydell {
89840831636SPeter Maydell     NeXTPC *s = NEXT_PC(dev);
89940831636SPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
90040831636SPeter Maydell 
901d9cd4039SPeter Maydell     qdev_init_gpio_in(dev, next_irq, NEXT_NUM_IRQS);
902d9cd4039SPeter Maydell 
9037e993d93SMark Cave-Ayland     memory_region_init_io(&s->mmiomem, OBJECT(s), &next_mmio_ops, s,
9047e993d93SMark Cave-Ayland                           "next.mmio", 0xd0000);
9050d60da39SMark Cave-Ayland     memory_region_init_io(&s->scrmem, OBJECT(s), &next_scr_ops, s,
9061dc7aeaeSPeter Maydell                           "next.scr", 0x20000);
90740831636SPeter Maydell     sysbus_init_mmio(sbd, &s->mmiomem);
9081dc7aeaeSPeter Maydell     sysbus_init_mmio(sbd, &s->scrmem);
909660bef33SPeter Maydell }
910660bef33SPeter Maydell 
911b497f4a1SPeter Maydell /*
912b497f4a1SPeter Maydell  * If the m68k CPU implemented its inbound irq lines as GPIO lines
913b497f4a1SPeter Maydell  * rather than via the m68k_set_irq_level() function we would not need
914b497f4a1SPeter Maydell  * this cpu link property and could instead provide outbound IRQ lines
915b497f4a1SPeter Maydell  * that the board could wire up to the CPU.
916b497f4a1SPeter Maydell  */
917b497f4a1SPeter Maydell static Property next_pc_properties[] = {
918b497f4a1SPeter Maydell     DEFINE_PROP_LINK("cpu", NeXTPC, cpu, TYPE_M68K_CPU, M68kCPU *),
919b497f4a1SPeter Maydell     DEFINE_PROP_END_OF_LIST(),
920b497f4a1SPeter Maydell };
921b497f4a1SPeter Maydell 
92275ca77ecSPeter Maydell static const VMStateDescription next_rtc_vmstate = {
92375ca77ecSPeter Maydell     .name = "next-rtc",
92488d0c5b0SMark Cave-Ayland     .version_id = 2,
92588d0c5b0SMark Cave-Ayland     .minimum_version_id = 2,
926*2a031ec7SRichard Henderson     .fields = (const VMStateField[]) {
92788d0c5b0SMark Cave-Ayland         VMSTATE_INT8(phase, NextRtc),
92875ca77ecSPeter Maydell         VMSTATE_UINT8_ARRAY(ram, NextRtc, 32),
92975ca77ecSPeter Maydell         VMSTATE_UINT8(command, NextRtc),
93075ca77ecSPeter Maydell         VMSTATE_UINT8(value, NextRtc),
93175ca77ecSPeter Maydell         VMSTATE_UINT8(status, NextRtc),
93275ca77ecSPeter Maydell         VMSTATE_UINT8(control, NextRtc),
93375ca77ecSPeter Maydell         VMSTATE_UINT8(retval, NextRtc),
93475ca77ecSPeter Maydell         VMSTATE_END_OF_LIST()
93575ca77ecSPeter Maydell     },
93675ca77ecSPeter Maydell };
93775ca77ecSPeter Maydell 
93875ca77ecSPeter Maydell static const VMStateDescription next_pc_vmstate = {
93975ca77ecSPeter Maydell     .name = "next-pc",
9408220baa0SMark Cave-Ayland     .version_id = 2,
9418220baa0SMark Cave-Ayland     .minimum_version_id = 2,
942*2a031ec7SRichard Henderson     .fields = (const VMStateField[]) {
94375ca77ecSPeter Maydell         VMSTATE_UINT32(scr1, NeXTPC),
94475ca77ecSPeter Maydell         VMSTATE_UINT32(scr2, NeXTPC),
94522cf5ee3SMark Cave-Ayland         VMSTATE_UINT32(old_scr2, NeXTPC),
94675ca77ecSPeter Maydell         VMSTATE_UINT32(int_mask, NeXTPC),
94775ca77ecSPeter Maydell         VMSTATE_UINT32(int_status, NeXTPC),
9488220baa0SMark Cave-Ayland         VMSTATE_UINT32(led, NeXTPC),
94975ca77ecSPeter Maydell         VMSTATE_UINT8(scsi_csr_1, NeXTPC),
95075ca77ecSPeter Maydell         VMSTATE_UINT8(scsi_csr_2, NeXTPC),
95175ca77ecSPeter Maydell         VMSTATE_STRUCT(rtc, NeXTPC, 0, next_rtc_vmstate, NextRtc),
95275ca77ecSPeter Maydell         VMSTATE_END_OF_LIST()
95375ca77ecSPeter Maydell     },
95475ca77ecSPeter Maydell };
95575ca77ecSPeter Maydell 
next_pc_class_init(ObjectClass * klass,void * data)956660bef33SPeter Maydell static void next_pc_class_init(ObjectClass *klass, void *data)
957660bef33SPeter Maydell {
958660bef33SPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
959660bef33SPeter Maydell 
960660bef33SPeter Maydell     dc->desc = "NeXT Peripheral Controller";
961660bef33SPeter Maydell     dc->realize = next_pc_realize;
962660bef33SPeter Maydell     dc->reset = next_pc_reset;
963b497f4a1SPeter Maydell     device_class_set_props(dc, next_pc_properties);
96475ca77ecSPeter Maydell     dc->vmsd = &next_pc_vmstate;
965660bef33SPeter Maydell }
966660bef33SPeter Maydell 
967660bef33SPeter Maydell static const TypeInfo next_pc_info = {
968660bef33SPeter Maydell     .name = TYPE_NEXT_PC,
969660bef33SPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
970660bef33SPeter Maydell     .instance_size = sizeof(NeXTPC),
971660bef33SPeter Maydell     .class_init = next_pc_class_init,
972660bef33SPeter Maydell };
973660bef33SPeter Maydell 
next_cube_init(MachineState * machine)974956a7811SThomas Huth static void next_cube_init(MachineState *machine)
975956a7811SThomas Huth {
9760d23b1efSMark Cave-Ayland     NeXTState *m = NEXT_MACHINE(machine);
977956a7811SThomas Huth     M68kCPU *cpu;
978956a7811SThomas Huth     CPUM68KState *env;
979956a7811SThomas Huth     MemoryRegion *sysmem = get_system_memory();
9801684273cSPaolo Bonzini     const char *bios_name = machine->firmware ?: ROM_FILE;
981660bef33SPeter Maydell     DeviceState *pcdev;
982956a7811SThomas Huth 
983956a7811SThomas Huth     /* Initialize the cpu core */
984956a7811SThomas Huth     cpu = M68K_CPU(cpu_create(machine->cpu_type));
985956a7811SThomas Huth     if (!cpu) {
986956a7811SThomas Huth         error_report("Unable to find m68k CPU definition");
987956a7811SThomas Huth         exit(1);
988956a7811SThomas Huth     }
989956a7811SThomas Huth     env = &cpu->env;
990956a7811SThomas Huth 
991956a7811SThomas Huth     /* Initialize CPU registers.  */
992956a7811SThomas Huth     env->vbr = 0;
993956a7811SThomas Huth     env->sr  = 0x2700;
994956a7811SThomas Huth 
995660bef33SPeter Maydell     /* Peripheral Controller */
996660bef33SPeter Maydell     pcdev = qdev_new(TYPE_NEXT_PC);
997b497f4a1SPeter Maydell     object_property_set_link(OBJECT(pcdev), "cpu", OBJECT(cpu), &error_abort);
998660bef33SPeter Maydell     sysbus_realize_and_unref(SYS_BUS_DEVICE(pcdev), &error_fatal);
999956a7811SThomas Huth 
1000956a7811SThomas Huth     /* 64MB RAM starting at 0x04000000  */
100149b64ba9SIgor Mammedov     memory_region_add_subregion(sysmem, 0x04000000, machine->ram);
1002956a7811SThomas Huth 
1003956a7811SThomas Huth     /* Framebuffer */
1004b2897f7eSPhilippe Mathieu-Daudé     sysbus_create_simple(TYPE_NEXTFB, 0x0B000000, NULL);
1005956a7811SThomas Huth 
1006956a7811SThomas Huth     /* MMIO */
100740831636SPeter Maydell     sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 0, 0x02000000);
1008956a7811SThomas Huth 
10091dc7aeaeSPeter Maydell     /* BMAP IO - acts as a catch-all for now */
10101dc7aeaeSPeter Maydell     sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02100000);
10111dc7aeaeSPeter Maydell 
1012956a7811SThomas Huth     /* BMAP memory */
10130d23b1efSMark Cave-Ayland     memory_region_init_ram_flags_nomigrate(&m->bmapm1, NULL, "next.bmapmem",
10140d23b1efSMark Cave-Ayland                                            64, RAM_SHARED, &error_fatal);
10150d23b1efSMark Cave-Ayland     memory_region_add_subregion(sysmem, 0x020c0000, &m->bmapm1);
1016956a7811SThomas Huth     /* The Rev_2.5_v66.bin firmware accesses it at 0x820c0020, too */
10170d23b1efSMark Cave-Ayland     memory_region_init_alias(&m->bmapm2, NULL, "next.bmapmem2", &m->bmapm1,
10180d23b1efSMark Cave-Ayland                              0x0, 64);
10190d23b1efSMark Cave-Ayland     memory_region_add_subregion(sysmem, 0x820c0000, &m->bmapm2);
1020956a7811SThomas Huth 
1021956a7811SThomas Huth     /* KBD */
1022b2897f7eSPhilippe Mathieu-Daudé     sysbus_create_simple(TYPE_NEXTKBD, 0x0200e000, NULL);
1023956a7811SThomas Huth 
1024956a7811SThomas Huth     /* Load ROM here */
10250d23b1efSMark Cave-Ayland     memory_region_init_rom(&m->rom, NULL, "next.rom", 0x20000, &error_fatal);
10260d23b1efSMark Cave-Ayland     memory_region_add_subregion(sysmem, 0x01000000, &m->rom);
10270d23b1efSMark Cave-Ayland     memory_region_init_alias(&m->rom2, NULL, "next.rom2", &m->rom, 0x0,
10280d23b1efSMark Cave-Ayland                              0x20000);
10290d23b1efSMark Cave-Ayland     memory_region_add_subregion(sysmem, 0x0, &m->rom2);
1030956a7811SThomas Huth     if (load_image_targphys(bios_name, 0x01000000, 0x20000) < 8) {
1031956a7811SThomas Huth         if (!qtest_enabled()) {
1032956a7811SThomas Huth             error_report("Failed to load firmware '%s'.", bios_name);
1033956a7811SThomas Huth         }
1034956a7811SThomas Huth     } else {
1035956a7811SThomas Huth         uint8_t *ptr;
1036956a7811SThomas Huth         /* Initial PC is always at offset 4 in firmware binaries */
1037956a7811SThomas Huth         ptr = rom_ptr(0x01000004, 4);
1038956a7811SThomas Huth         g_assert(ptr != NULL);
1039956a7811SThomas Huth         env->pc = ldl_p(ptr);
1040956a7811SThomas Huth         if (env->pc >= 0x01020000) {
1041956a7811SThomas Huth             error_report("'%s' does not seem to be a valid firmware image.",
1042956a7811SThomas Huth                          bios_name);
1043956a7811SThomas Huth             exit(1);
1044956a7811SThomas Huth         }
1045956a7811SThomas Huth     }
1046956a7811SThomas Huth 
1047956a7811SThomas Huth     /* Serial */
1048b497f4a1SPeter Maydell     next_escc_init(pcdev);
1049b17bed5bSThomas Huth 
1050b17bed5bSThomas Huth     /* TODO: */
1051956a7811SThomas Huth     /* Network */
1052956a7811SThomas Huth     /* SCSI */
1053f2a80c6eSThomas Huth     next_scsi_init(pcdev, cpu);
1054956a7811SThomas Huth 
1055956a7811SThomas Huth     /* DMA */
10560d23b1efSMark Cave-Ayland     memory_region_init_io(&m->dmamem, NULL, &next_dma_ops, machine,
10570d23b1efSMark Cave-Ayland                           "next.dma", 0x5000);
10580d23b1efSMark Cave-Ayland     memory_region_add_subregion(sysmem, 0x02000000, &m->dmamem);
1059956a7811SThomas Huth }
1060956a7811SThomas Huth 
next_machine_class_init(ObjectClass * oc,void * data)1061956a7811SThomas Huth static void next_machine_class_init(ObjectClass *oc, void *data)
1062956a7811SThomas Huth {
1063956a7811SThomas Huth     MachineClass *mc = MACHINE_CLASS(oc);
1064956a7811SThomas Huth 
1065956a7811SThomas Huth     mc->desc = "NeXT Cube";
1066956a7811SThomas Huth     mc->init = next_cube_init;
1067f2a80c6eSThomas Huth     mc->block_default_type = IF_SCSI;
1068956a7811SThomas Huth     mc->default_ram_size = RAM_SIZE;
106949b64ba9SIgor Mammedov     mc->default_ram_id = "next.ram";
1070956a7811SThomas Huth     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
1071956a7811SThomas Huth }
1072956a7811SThomas Huth 
1073956a7811SThomas Huth static const TypeInfo next_typeinfo = {
1074956a7811SThomas Huth     .name = TYPE_NEXT_MACHINE,
1075956a7811SThomas Huth     .parent = TYPE_MACHINE,
1076956a7811SThomas Huth     .class_init = next_machine_class_init,
1077956a7811SThomas Huth     .instance_size = sizeof(NeXTState),
1078956a7811SThomas Huth };
1079956a7811SThomas Huth 
next_register_type(void)1080956a7811SThomas Huth static void next_register_type(void)
1081956a7811SThomas Huth {
1082956a7811SThomas Huth     type_register_static(&next_typeinfo);
1083660bef33SPeter Maydell     type_register_static(&next_pc_info);
1084956a7811SThomas Huth }
1085956a7811SThomas Huth 
1086956a7811SThomas Huth type_init(next_register_type)
1087