xref: /qemu/hw/m68k/next-cube.c (revision 039b10ac)
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 
77956a7811SThomas Huth     next_dma dma[10];
78db1015e9SEduardo Habkost };
79956a7811SThomas Huth 
80660bef33SPeter Maydell #define TYPE_NEXT_PC "next-pc"
81660bef33SPeter Maydell OBJECT_DECLARE_SIMPLE_TYPE(NeXTPC, NEXT_PC)
82660bef33SPeter Maydell 
83660bef33SPeter Maydell /* NeXT Peripheral Controller */
84660bef33SPeter Maydell struct NeXTPC {
85660bef33SPeter Maydell     SysBusDevice parent_obj;
86660bef33SPeter Maydell 
87b497f4a1SPeter Maydell     M68kCPU *cpu;
88b497f4a1SPeter Maydell 
8940831636SPeter Maydell     MemoryRegion mmiomem;
901dc7aeaeSPeter Maydell     MemoryRegion scrmem;
9140831636SPeter Maydell 
9240831636SPeter Maydell     uint32_t scr1;
9340831636SPeter Maydell     uint32_t scr2;
9422cf5ee3SMark Cave-Ayland     uint32_t old_scr2;
95ac99317bSPeter Maydell     uint32_t int_mask;
96ac99317bSPeter Maydell     uint32_t int_status;
978220baa0SMark Cave-Ayland     uint32_t led;
98f2a80c6eSThomas Huth     uint8_t scsi_csr_1;
99f2a80c6eSThomas Huth     uint8_t scsi_csr_2;
100f2a80c6eSThomas Huth 
101f2a80c6eSThomas Huth     qemu_irq scsi_reset;
102f2a80c6eSThomas Huth     qemu_irq scsi_dma;
1036f0face7SPeter Maydell 
1046f0face7SPeter Maydell     NextRtc rtc;
105660bef33SPeter Maydell };
106660bef33SPeter Maydell 
107956a7811SThomas Huth /* Thanks to NeXT forums for this */
108956a7811SThomas Huth /*
109956a7811SThomas Huth static const uint8_t rtc_ram3[32] = {
110956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
111956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x7B, 0x00,
112956a7811SThomas Huth     0x00, 0x00, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x00,
113956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x13
114956a7811SThomas Huth };
115956a7811SThomas Huth */
116956a7811SThomas Huth static const uint8_t rtc_ram2[32] = {
117956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00,
118956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x4b, 0x00,
119956a7811SThomas Huth     0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
120956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x7e,
121956a7811SThomas Huth };
122956a7811SThomas Huth 
123956a7811SThomas Huth #define SCR2_RTCLK 0x2
124956a7811SThomas Huth #define SCR2_RTDATA 0x4
125956a7811SThomas Huth #define SCR2_TOBCD(x) (((x / 10) << 4) + (x % 10))
126956a7811SThomas Huth 
1273deafd18SMark Cave-Ayland static void next_scr2_led_update(NeXTPC *s)
1283deafd18SMark Cave-Ayland {
1293deafd18SMark Cave-Ayland     if (s->scr2 & 0x1) {
1303deafd18SMark Cave-Ayland         DPRINTF("fault!\n");
1313deafd18SMark Cave-Ayland         s->led++;
1323deafd18SMark Cave-Ayland         if (s->led == 10) {
1333deafd18SMark Cave-Ayland             DPRINTF("LED flashing, possible fault!\n");
1343deafd18SMark Cave-Ayland             s->led = 0;
1353deafd18SMark Cave-Ayland         }
1363deafd18SMark Cave-Ayland     }
1373deafd18SMark Cave-Ayland }
1383deafd18SMark Cave-Ayland 
139*039b10acSMark Cave-Ayland static void next_scr2_rtc_update(NeXTPC *s)
140956a7811SThomas Huth {
14122cf5ee3SMark Cave-Ayland     uint8_t old_scr2, scr2_2;
1426f0face7SPeter Maydell     NextRtc *rtc = &s->rtc;
143956a7811SThomas Huth 
144*039b10acSMark Cave-Ayland     old_scr2 = extract32(s->old_scr2, 8, 8);
145*039b10acSMark Cave-Ayland     scr2_2 = extract32(s->scr2, 8, 8);
14622cf5ee3SMark Cave-Ayland 
147956a7811SThomas Huth     if (scr2_2 & 0x1) {
14888d0c5b0SMark Cave-Ayland         /* DPRINTF("RTC %x phase %i\n", scr2_2, rtc->phase); */
14988d0c5b0SMark Cave-Ayland         if (rtc->phase == -1) {
15088d0c5b0SMark Cave-Ayland             rtc->phase = 0;
151956a7811SThomas Huth         }
152956a7811SThomas Huth         /* If we are in going down clock... do something */
153956a7811SThomas Huth         if (((old_scr2 & SCR2_RTCLK) != (scr2_2 & SCR2_RTCLK)) &&
154956a7811SThomas Huth                 ((scr2_2 & SCR2_RTCLK) == 0)) {
15588d0c5b0SMark Cave-Ayland             if (rtc->phase < 8) {
156cd4fc142SThomas Huth                 rtc->command = (rtc->command << 1) |
157956a7811SThomas Huth                                ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
158956a7811SThomas Huth             }
15988d0c5b0SMark Cave-Ayland             if (rtc->phase >= 8 && rtc->phase < 16) {
160cd4fc142SThomas Huth                 rtc->value = (rtc->value << 1) |
161cd4fc142SThomas Huth                              ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
162956a7811SThomas Huth 
163956a7811SThomas Huth                 /* if we read RAM register, output RT_DATA bit */
164cd4fc142SThomas Huth                 if (rtc->command <= 0x1F) {
165956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
16688d0c5b0SMark Cave-Ayland                     if (rtc->ram[rtc->command] & (0x80 >> (rtc->phase - 8))) {
167956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
168956a7811SThomas Huth                     }
169956a7811SThomas Huth 
170cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
171956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
172956a7811SThomas Huth                 }
173956a7811SThomas Huth                 /* read the status 0x30 */
174cd4fc142SThomas Huth                 if (rtc->command == 0x30) {
175956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
176956a7811SThomas Huth                     /* for now status = 0x98 (new rtc + FTU) */
17788d0c5b0SMark Cave-Ayland                     if (rtc->status & (0x80 >> (rtc->phase - 8))) {
178956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
179956a7811SThomas Huth                     }
180956a7811SThomas Huth 
181cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
182956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
183956a7811SThomas Huth                 }
184956a7811SThomas Huth                 /* read the status 0x31 */
185cd4fc142SThomas Huth                 if (rtc->command == 0x31) {
186956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
18788d0c5b0SMark Cave-Ayland                     if (rtc->control & (0x80 >> (rtc->phase - 8))) {
188956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
189956a7811SThomas Huth                     }
190cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
191956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
192956a7811SThomas Huth                 }
193956a7811SThomas Huth 
194cd4fc142SThomas Huth                 if ((rtc->command >= 0x20) && (rtc->command <= 0x2F)) {
195956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
196956a7811SThomas Huth                     /* for now 0x00 */
197956a7811SThomas Huth                     time_t time_h = time(NULL);
198956a7811SThomas Huth                     struct tm *info = localtime(&time_h);
199956a7811SThomas Huth                     int ret = 0;
200956a7811SThomas Huth 
201cd4fc142SThomas Huth                     switch (rtc->command) {
202956a7811SThomas Huth                     case 0x20:
203956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_sec);
204956a7811SThomas Huth                         break;
205956a7811SThomas Huth                     case 0x21:
206956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_min);
207956a7811SThomas Huth                         break;
208956a7811SThomas Huth                     case 0x22:
209956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_hour);
210956a7811SThomas Huth                         break;
211956a7811SThomas Huth                     case 0x24:
212956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_mday);
213956a7811SThomas Huth                         break;
214956a7811SThomas Huth                     case 0x25:
215956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_mon + 1));
216956a7811SThomas Huth                         break;
217956a7811SThomas Huth                     case 0x26:
218956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_year - 100));
219956a7811SThomas Huth                         break;
220956a7811SThomas Huth 
221956a7811SThomas Huth                     }
222956a7811SThomas Huth 
22388d0c5b0SMark Cave-Ayland                     if (ret & (0x80 >> (rtc->phase - 8))) {
224956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
225956a7811SThomas Huth                     }
226cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
227956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
228956a7811SThomas Huth                 }
229956a7811SThomas Huth 
230956a7811SThomas Huth             }
231956a7811SThomas Huth 
23288d0c5b0SMark Cave-Ayland             rtc->phase++;
23388d0c5b0SMark Cave-Ayland             if (rtc->phase == 16) {
234cd4fc142SThomas Huth                 if (rtc->command >= 0x80 && rtc->command <= 0x9F) {
235cd4fc142SThomas Huth                     rtc->ram[rtc->command - 0x80] = rtc->value;
236956a7811SThomas Huth                 }
237956a7811SThomas Huth                 /* write to x30 register */
238cd4fc142SThomas Huth                 if (rtc->command == 0xB1) {
239956a7811SThomas Huth                     /* clear FTU */
240cd4fc142SThomas Huth                     if (rtc->value & 0x04) {
241cd4fc142SThomas Huth                         rtc->status = rtc->status & (~0x18);
242ac99317bSPeter Maydell                         s->int_status = s->int_status & (~0x04);
243956a7811SThomas Huth                     }
244956a7811SThomas Huth                 }
245956a7811SThomas Huth             }
246956a7811SThomas Huth         }
247956a7811SThomas Huth     } else {
248956a7811SThomas Huth         /* else end or abort */
24988d0c5b0SMark Cave-Ayland         rtc->phase = -1;
250cd4fc142SThomas Huth         rtc->command = 0;
251cd4fc142SThomas Huth         rtc->value = 0;
252956a7811SThomas Huth     }
253*039b10acSMark Cave-Ayland 
254*039b10acSMark Cave-Ayland     s->scr2 = deposit32(s->scr2, 8, 8, scr2_2);
255956a7811SThomas Huth }
256956a7811SThomas Huth 
2577e993d93SMark Cave-Ayland static uint64_t next_mmio_read(void *opaque, hwaddr addr, unsigned size)
258956a7811SThomas Huth {
2597e993d93SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
2607e993d93SMark Cave-Ayland     uint64_t val;
261956a7811SThomas Huth 
262956a7811SThomas Huth     switch (addr) {
263956a7811SThomas Huth     case 0x7000:
264ac99317bSPeter Maydell         /* DPRINTF("Read INT status: %x\n", s->int_status); */
2657e993d93SMark Cave-Ayland         val = s->int_status;
2667e993d93SMark Cave-Ayland         break;
267956a7811SThomas Huth 
268956a7811SThomas Huth     case 0x7800:
269ac99317bSPeter Maydell         DPRINTF("MMIO Read INT mask: %x\n", s->int_mask);
2707e993d93SMark Cave-Ayland         val = s->int_mask;
271956a7811SThomas Huth         break;
272956a7811SThomas Huth 
2737e993d93SMark Cave-Ayland     case 0xc000 ... 0xc003:
2747e993d93SMark Cave-Ayland         val = extract32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
2757e993d93SMark Cave-Ayland                         size << 3);
2767e993d93SMark Cave-Ayland         break;
277956a7811SThomas Huth 
2787e993d93SMark Cave-Ayland     case 0xd000 ... 0xd003:
2797e993d93SMark Cave-Ayland         val = extract32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
2807e993d93SMark Cave-Ayland                         size << 3);
2817e993d93SMark Cave-Ayland         break;
282956a7811SThomas Huth 
2837e993d93SMark Cave-Ayland     case 0x14020:
2847e993d93SMark Cave-Ayland         val = 0x7f;
285956a7811SThomas Huth         break;
286956a7811SThomas Huth 
287956a7811SThomas Huth     default:
2887e993d93SMark Cave-Ayland         val = 0;
2897e993d93SMark Cave-Ayland         DPRINTF("MMIO Read @ 0x%"HWADDR_PRIx" size %d\n", addr, size);
2907e993d93SMark Cave-Ayland         break;
291956a7811SThomas Huth     }
292956a7811SThomas Huth 
2937e993d93SMark Cave-Ayland     return val;
294956a7811SThomas Huth }
295956a7811SThomas Huth 
2967e993d93SMark Cave-Ayland static void next_mmio_write(void *opaque, hwaddr addr, uint64_t val,
297956a7811SThomas Huth                             unsigned size)
298956a7811SThomas Huth {
29940831636SPeter Maydell     NeXTPC *s = NEXT_PC(opaque);
300956a7811SThomas Huth 
3017e993d93SMark Cave-Ayland     switch (addr) {
3027e993d93SMark Cave-Ayland     case 0x7000:
3037e993d93SMark Cave-Ayland         DPRINTF("INT Status old: %x new: %x\n", s->int_status,
3047e993d93SMark Cave-Ayland                 (unsigned int)val);
3057e993d93SMark Cave-Ayland         s->int_status = val;
306956a7811SThomas Huth         break;
3077e993d93SMark Cave-Ayland 
3087e993d93SMark Cave-Ayland     case 0x7800:
3097e993d93SMark Cave-Ayland         DPRINTF("INT Mask old: %x new: %x\n", s->int_mask, (unsigned int)val);
3107e993d93SMark Cave-Ayland         s->int_mask  = val;
311956a7811SThomas Huth         break;
3127e993d93SMark Cave-Ayland 
3137e993d93SMark Cave-Ayland     case 0xc000 ... 0xc003:
3147e993d93SMark Cave-Ayland         DPRINTF("SCR1 Write: %x\n", (unsigned int)val);
3157e993d93SMark Cave-Ayland         s->scr1 = deposit32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
3167e993d93SMark Cave-Ayland                             size << 3, val);
317956a7811SThomas Huth         break;
3187e993d93SMark Cave-Ayland 
3197e993d93SMark Cave-Ayland     case 0xd000 ... 0xd003:
32022cf5ee3SMark Cave-Ayland         s->scr2 = deposit32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
32122cf5ee3SMark Cave-Ayland                             size << 3, val);
3223deafd18SMark Cave-Ayland         next_scr2_led_update(s);
323*039b10acSMark Cave-Ayland         next_scr2_rtc_update(s);
32422cf5ee3SMark Cave-Ayland         s->old_scr2 = s->scr2;
3257e993d93SMark Cave-Ayland         break;
3267e993d93SMark Cave-Ayland 
327956a7811SThomas Huth     default:
3287e993d93SMark Cave-Ayland         DPRINTF("MMIO Write @ 0x%"HWADDR_PRIx " with 0x%x size %u\n", addr,
3297e993d93SMark Cave-Ayland                 (unsigned int)val, size);
330956a7811SThomas Huth     }
331956a7811SThomas Huth }
332956a7811SThomas Huth 
3337e993d93SMark Cave-Ayland static const MemoryRegionOps next_mmio_ops = {
3347e993d93SMark Cave-Ayland     .read = next_mmio_read,
3357e993d93SMark Cave-Ayland     .write = next_mmio_write,
336956a7811SThomas Huth     .valid.min_access_size = 1,
337956a7811SThomas Huth     .valid.max_access_size = 4,
3387e993d93SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
339956a7811SThomas Huth };
340956a7811SThomas Huth 
341956a7811SThomas Huth #define SCSICSR_ENABLE  0x01
342956a7811SThomas Huth #define SCSICSR_RESET   0x02  /* reset scsi dma */
343956a7811SThomas Huth #define SCSICSR_FIFOFL  0x04
344956a7811SThomas Huth #define SCSICSR_DMADIR  0x08  /* if set, scsi to mem */
345956a7811SThomas Huth #define SCSICSR_CPUDMA  0x10  /* if set, dma enabled */
346956a7811SThomas Huth #define SCSICSR_INTMASK 0x20  /* if set, interrupt enabled */
347956a7811SThomas Huth 
3480d60da39SMark Cave-Ayland static uint64_t next_scr_readfn(void *opaque, hwaddr addr, unsigned size)
349956a7811SThomas Huth {
3500d60da39SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
3510d60da39SMark Cave-Ayland     uint64_t val;
3520d60da39SMark Cave-Ayland 
3530d60da39SMark Cave-Ayland     switch (addr) {
3540d60da39SMark Cave-Ayland     case 0x14108:
3550d60da39SMark Cave-Ayland         DPRINTF("FD read @ %x\n", (unsigned int)addr);
3560d60da39SMark Cave-Ayland         val = 0x40 | 0x04 | 0x2 | 0x1;
3570d60da39SMark Cave-Ayland         break;
3580d60da39SMark Cave-Ayland 
3590d60da39SMark Cave-Ayland     case 0x14020:
3600d60da39SMark Cave-Ayland         DPRINTF("SCSI 4020  STATUS READ %X\n", s->scsi_csr_1);
3610d60da39SMark Cave-Ayland         val = s->scsi_csr_1;
3620d60da39SMark Cave-Ayland         break;
3630d60da39SMark Cave-Ayland 
3640d60da39SMark Cave-Ayland     case 0x14021:
3650d60da39SMark Cave-Ayland         DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
3660d60da39SMark Cave-Ayland         val = 0x40;
3670d60da39SMark Cave-Ayland         break;
3680d60da39SMark Cave-Ayland 
3690d60da39SMark Cave-Ayland     /*
3700d60da39SMark Cave-Ayland      * These 4 registers are the hardware timer, not sure which register
3710d60da39SMark Cave-Ayland      * is the latch instead of data, but no problems so far.
3720d60da39SMark Cave-Ayland      *
3730d60da39SMark Cave-Ayland      * Hack: We need to have the LSB change consistently to make it work
3740d60da39SMark Cave-Ayland      */
3750d60da39SMark Cave-Ayland     case 0x1a000 ... 0x1a003:
3760d60da39SMark Cave-Ayland         val = extract32(clock(), (4 - (addr - 0x1a000) - size) << 3,
3770d60da39SMark Cave-Ayland                         size << 3);
3780d60da39SMark Cave-Ayland         break;
3790d60da39SMark Cave-Ayland 
3800d60da39SMark Cave-Ayland     /* For now return dummy byte to allow the Ethernet test to timeout */
3810d60da39SMark Cave-Ayland     case 0x6000:
3820d60da39SMark Cave-Ayland         val = 0xff;
3830d60da39SMark Cave-Ayland         break;
3840d60da39SMark Cave-Ayland 
3850d60da39SMark Cave-Ayland     default:
3860d60da39SMark Cave-Ayland         DPRINTF("BMAP Read @ 0x%x size %u\n", (unsigned int)addr, size);
3870d60da39SMark Cave-Ayland         val = 0;
3880d60da39SMark Cave-Ayland         break;
3890d60da39SMark Cave-Ayland     }
3900d60da39SMark Cave-Ayland 
3910d60da39SMark Cave-Ayland     return val;
3920d60da39SMark Cave-Ayland }
3930d60da39SMark Cave-Ayland 
3940d60da39SMark Cave-Ayland static void next_scr_writefn(void *opaque, hwaddr addr, uint64_t val,
3950d60da39SMark Cave-Ayland                              unsigned size)
3960d60da39SMark Cave-Ayland {
3970d60da39SMark Cave-Ayland     NeXTPC *s = NEXT_PC(opaque);
3980d60da39SMark Cave-Ayland 
399956a7811SThomas Huth     switch (addr) {
400956a7811SThomas Huth     case 0x14108:
401956a7811SThomas Huth         DPRINTF("FDCSR Write: %x\n", value);
4020d60da39SMark Cave-Ayland         if (val == 0x0) {
403956a7811SThomas Huth             /* qemu_irq_raise(s->fd_irq[0]); */
404956a7811SThomas Huth         }
405956a7811SThomas Huth         break;
4060d60da39SMark Cave-Ayland 
407956a7811SThomas Huth     case 0x14020: /* SCSI Control Register */
4080d60da39SMark Cave-Ayland         if (val & SCSICSR_FIFOFL) {
409956a7811SThomas Huth             DPRINTF("SCSICSR FIFO Flush\n");
410956a7811SThomas Huth             /* will have to add another irq to the esp if this is needed */
411956a7811SThomas Huth             /* esp_puflush_fifo(esp_g); */
412956a7811SThomas Huth         }
413956a7811SThomas Huth 
4140d60da39SMark Cave-Ayland         if (val & SCSICSR_ENABLE) {
415956a7811SThomas Huth             DPRINTF("SCSICSR Enable\n");
416956a7811SThomas Huth             /*
417956a7811SThomas Huth              * qemu_irq_raise(s->scsi_dma);
418956a7811SThomas Huth              * s->scsi_csr_1 = 0xc0;
419956a7811SThomas Huth              * s->scsi_csr_1 |= 0x1;
420956a7811SThomas Huth              * qemu_irq_pulse(s->scsi_dma);
421956a7811SThomas Huth              */
422956a7811SThomas Huth         }
423956a7811SThomas Huth         /*
424956a7811SThomas Huth          * else
425956a7811SThomas Huth          *     s->scsi_csr_1 &= ~SCSICSR_ENABLE;
426956a7811SThomas Huth          */
427956a7811SThomas Huth 
4280d60da39SMark Cave-Ayland         if (val & SCSICSR_RESET) {
429956a7811SThomas Huth             DPRINTF("SCSICSR Reset\n");
430956a7811SThomas Huth             /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
431f2a80c6eSThomas Huth             qemu_irq_raise(s->scsi_reset);
432f2a80c6eSThomas Huth             s->scsi_csr_1 &= ~(SCSICSR_INTMASK | 0x80 | 0x1);
433f2a80c6eSThomas Huth             qemu_irq_lower(s->scsi_reset);
434956a7811SThomas Huth         }
4350d60da39SMark Cave-Ayland         if (val & SCSICSR_DMADIR) {
436956a7811SThomas Huth             DPRINTF("SCSICSR DMAdir\n");
437956a7811SThomas Huth         }
4380d60da39SMark Cave-Ayland         if (val & SCSICSR_CPUDMA) {
439956a7811SThomas Huth             DPRINTF("SCSICSR CPUDMA\n");
440956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_dma); */
441ac99317bSPeter Maydell             s->int_status |= 0x4000000;
442956a7811SThomas Huth         } else {
443f2a80c6eSThomas Huth             /* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
444ac99317bSPeter Maydell             s->int_status &= ~(0x4000000);
445f2a80c6eSThomas Huth             /* qemu_irq_lower(s->scsi_dma); */
446956a7811SThomas Huth         }
4470d60da39SMark Cave-Ayland         if (val & SCSICSR_INTMASK) {
448956a7811SThomas Huth             DPRINTF("SCSICSR INTMASK\n");
449956a7811SThomas Huth             /*
450956a7811SThomas Huth              * int_mask &= ~0x1000;
4510d60da39SMark Cave-Ayland              * s->scsi_csr_1 |= val;
452956a7811SThomas Huth              * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
453956a7811SThomas Huth              * if (s->scsi_queued) {
454956a7811SThomas Huth              *     s->scsi_queued = 0;
455956a7811SThomas Huth              *     next_irq(s, NEXT_SCSI_I, level);
456956a7811SThomas Huth              * }
457956a7811SThomas Huth              */
458956a7811SThomas Huth         } else {
459956a7811SThomas Huth             /* int_mask |= 0x1000; */
460956a7811SThomas Huth         }
4610d60da39SMark Cave-Ayland         if (val & 0x80) {
462956a7811SThomas Huth             /* int_mask |= 0x1000; */
463956a7811SThomas Huth             /* s->scsi_csr_1 |= 0x80; */
464956a7811SThomas Huth         }
4650d60da39SMark Cave-Ayland         DPRINTF("SCSICSR Write: %x\n", val);
4660d60da39SMark Cave-Ayland         /* s->scsi_csr_1 = val; */
4670d60da39SMark Cave-Ayland         break;
4680d60da39SMark Cave-Ayland 
469956a7811SThomas Huth     /* Hardware timer latch - not implemented yet */
470956a7811SThomas Huth     case 0x1a000:
471956a7811SThomas Huth     default:
4720d60da39SMark Cave-Ayland         DPRINTF("BMAP Write @ 0x%x with 0x%x size %u\n", (unsigned int)addr,
4730d60da39SMark Cave-Ayland                 val, size);
474956a7811SThomas Huth     }
475956a7811SThomas Huth }
476956a7811SThomas Huth 
4770d60da39SMark Cave-Ayland static const MemoryRegionOps next_scr_ops = {
4780d60da39SMark Cave-Ayland     .read = next_scr_readfn,
4790d60da39SMark Cave-Ayland     .write = next_scr_writefn,
480956a7811SThomas Huth     .valid.min_access_size = 1,
481956a7811SThomas Huth     .valid.max_access_size = 4,
4820d60da39SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
483956a7811SThomas Huth };
484956a7811SThomas Huth 
485956a7811SThomas Huth #define NEXTDMA_SCSI(x)      (0x10 + x)
486956a7811SThomas Huth #define NEXTDMA_FD(x)        (0x10 + x)
487956a7811SThomas Huth #define NEXTDMA_ENTX(x)      (0x110 + x)
488956a7811SThomas Huth #define NEXTDMA_ENRX(x)      (0x150 + x)
489956a7811SThomas Huth #define NEXTDMA_CSR          0x0
490956a7811SThomas Huth #define NEXTDMA_NEXT         0x4000
491956a7811SThomas Huth #define NEXTDMA_LIMIT        0x4004
492956a7811SThomas Huth #define NEXTDMA_START        0x4008
493956a7811SThomas Huth #define NEXTDMA_STOP         0x400c
494956a7811SThomas Huth #define NEXTDMA_NEXT_INIT    0x4200
495956a7811SThomas Huth #define NEXTDMA_SIZE         0x4204
496956a7811SThomas Huth 
497c0dedcf4SMark Cave-Ayland static void next_dma_write(void *opaque, hwaddr addr, uint64_t val,
498956a7811SThomas Huth                            unsigned int size)
499956a7811SThomas Huth {
500956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
501956a7811SThomas Huth 
502956a7811SThomas Huth     switch (addr) {
503956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
504c0dedcf4SMark Cave-Ayland         if (val & DMA_DEV2M) {
505956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_DEV2M;
506956a7811SThomas Huth         }
507956a7811SThomas Huth 
508c0dedcf4SMark Cave-Ayland         if (val & DMA_SETENABLE) {
509956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
510956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_ENABLE;
511956a7811SThomas Huth         }
512c0dedcf4SMark Cave-Ayland         if (val & DMA_SETSUPDATE) {
513956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_SUPDATE;
514956a7811SThomas Huth         }
515c0dedcf4SMark Cave-Ayland         if (val & DMA_CLRCOMPLETE) {
516956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~DMA_COMPLETE;
517956a7811SThomas Huth         }
518956a7811SThomas Huth 
519c0dedcf4SMark Cave-Ayland         if (val & DMA_RESET) {
520956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
521956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
522956a7811SThomas Huth         }
523956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
524956a7811SThomas Huth         break;
525c0dedcf4SMark Cave-Ayland 
526956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
527c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].next_initbuf = val;
528956a7811SThomas Huth         break;
529c0dedcf4SMark Cave-Ayland 
530956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
531c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].next = val;
532956a7811SThomas Huth         break;
533c0dedcf4SMark Cave-Ayland 
534956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
535c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_ENRX].limit = val;
536956a7811SThomas Huth         break;
537c0dedcf4SMark Cave-Ayland 
538956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
539c0dedcf4SMark Cave-Ayland         if (val & DMA_DEV2M) {
540956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_DEV2M;
541956a7811SThomas Huth         }
542c0dedcf4SMark Cave-Ayland         if (val & DMA_SETENABLE) {
543956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
544956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_ENABLE;
545956a7811SThomas Huth         }
546c0dedcf4SMark Cave-Ayland         if (val & DMA_SETSUPDATE) {
547956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_SUPDATE;
548956a7811SThomas Huth         }
549c0dedcf4SMark Cave-Ayland         if (val & DMA_CLRCOMPLETE) {
550956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~DMA_COMPLETE;
551956a7811SThomas Huth         }
552956a7811SThomas Huth 
553c0dedcf4SMark Cave-Ayland         if (val & DMA_RESET) {
554956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
555956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
556956a7811SThomas Huth             /* DPRINTF("SCSI DMA RESET\n"); */
557956a7811SThomas Huth         }
558956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
559956a7811SThomas Huth         break;
560956a7811SThomas Huth 
561956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
562c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].next = val;
563956a7811SThomas Huth         break;
564956a7811SThomas Huth 
565956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
566c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].limit = val;
567956a7811SThomas Huth         break;
568956a7811SThomas Huth 
569956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
570c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].start = val;
571956a7811SThomas Huth         break;
572956a7811SThomas Huth 
573956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
574c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].stop = val;
575956a7811SThomas Huth         break;
576956a7811SThomas Huth 
577956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
578c0dedcf4SMark Cave-Ayland         next_state->dma[NEXTDMA_SCSI].next_initbuf = val;
579956a7811SThomas Huth         break;
580956a7811SThomas Huth 
581956a7811SThomas Huth     default:
582956a7811SThomas Huth         DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)value);
583956a7811SThomas Huth     }
584956a7811SThomas Huth }
585956a7811SThomas Huth 
586c0dedcf4SMark Cave-Ayland static uint64_t next_dma_read(void *opaque, hwaddr addr, unsigned int size)
587956a7811SThomas Huth {
588956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
589c0dedcf4SMark Cave-Ayland     uint64_t val;
590956a7811SThomas Huth 
591956a7811SThomas Huth     switch (addr) {
592956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
593956a7811SThomas Huth         DPRINTF("SCSI DMA CSR READ\n");
594c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].csr;
595c0dedcf4SMark Cave-Ayland         break;
596c0dedcf4SMark Cave-Ayland 
597956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
598c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].csr;
599c0dedcf4SMark Cave-Ayland         break;
600c0dedcf4SMark Cave-Ayland 
601956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
602c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].next_initbuf;
603c0dedcf4SMark Cave-Ayland         break;
604c0dedcf4SMark Cave-Ayland 
605956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
606c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].next;
607c0dedcf4SMark Cave-Ayland         break;
608c0dedcf4SMark Cave-Ayland 
609956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
610c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_ENRX].limit;
611c0dedcf4SMark Cave-Ayland         break;
612956a7811SThomas Huth 
613956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
614c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].next;
615c0dedcf4SMark Cave-Ayland         break;
616c0dedcf4SMark Cave-Ayland 
617956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
618c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].next_initbuf;
619c0dedcf4SMark Cave-Ayland         break;
620c0dedcf4SMark Cave-Ayland 
621956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
622c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].limit;
623c0dedcf4SMark Cave-Ayland         break;
624c0dedcf4SMark Cave-Ayland 
625956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
626c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].start;
627c0dedcf4SMark Cave-Ayland         break;
628c0dedcf4SMark Cave-Ayland 
629956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
630c0dedcf4SMark Cave-Ayland         val = next_state->dma[NEXTDMA_SCSI].stop;
631c0dedcf4SMark Cave-Ayland         break;
632956a7811SThomas Huth 
633956a7811SThomas Huth     default:
634956a7811SThomas Huth         DPRINTF("DMA read @ %x\n", (unsigned int)addr);
635c0dedcf4SMark Cave-Ayland         val = 0;
636956a7811SThomas Huth     }
637956a7811SThomas Huth 
638956a7811SThomas Huth     /*
639956a7811SThomas Huth      * once the csr's are done, subtract 0x3FEC from the addr, and that will
640956a7811SThomas Huth      * normalize the upper registers
641956a7811SThomas Huth      */
642c0dedcf4SMark Cave-Ayland 
643c0dedcf4SMark Cave-Ayland     return val;
644956a7811SThomas Huth }
645956a7811SThomas Huth 
646c0dedcf4SMark Cave-Ayland static const MemoryRegionOps next_dma_ops = {
647c0dedcf4SMark Cave-Ayland     .read = next_dma_read,
648c0dedcf4SMark Cave-Ayland     .write = next_dma_write,
649956a7811SThomas Huth     .impl.min_access_size = 4,
650956a7811SThomas Huth     .valid.min_access_size = 4,
651956a7811SThomas Huth     .valid.max_access_size = 4,
652c0dedcf4SMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
653956a7811SThomas Huth };
654956a7811SThomas Huth 
655c8abcc87SPeter Maydell static void next_irq(void *opaque, int number, int level)
656956a7811SThomas Huth {
657b497f4a1SPeter Maydell     NeXTPC *s = NEXT_PC(opaque);
658b497f4a1SPeter Maydell     M68kCPU *cpu = s->cpu;
659956a7811SThomas Huth     int shift = 0;
660956a7811SThomas Huth 
6618b81968cSMichael Tokarev     /* first switch sets interrupt status */
662956a7811SThomas Huth     /* DPRINTF("IRQ %i\n",number); */
663956a7811SThomas Huth     switch (number) {
664956a7811SThomas Huth     /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
665956a7811SThomas Huth     case NEXT_FD_I:
6665012a894SPhilippe Mathieu-Daudé         shift = 7;
667956a7811SThomas Huth         break;
668956a7811SThomas Huth     case NEXT_KBD_I:
669956a7811SThomas Huth         shift = 3;
670956a7811SThomas Huth         break;
671956a7811SThomas Huth     case NEXT_PWR_I:
672956a7811SThomas Huth         shift = 2;
673956a7811SThomas Huth         break;
674956a7811SThomas Huth     case NEXT_ENRX_I:
675956a7811SThomas Huth         shift = 9;
676956a7811SThomas Huth         break;
677956a7811SThomas Huth     case NEXT_ENTX_I:
678956a7811SThomas Huth         shift = 10;
679956a7811SThomas Huth         break;
680956a7811SThomas Huth     case NEXT_SCSI_I:
681956a7811SThomas Huth         shift = 12;
682956a7811SThomas Huth         break;
683956a7811SThomas Huth     case NEXT_CLK_I:
684956a7811SThomas Huth         shift = 5;
685956a7811SThomas Huth         break;
686956a7811SThomas Huth 
687956a7811SThomas Huth     /* level 5 - scc (serial) */
688956a7811SThomas Huth     case NEXT_SCC_I:
689956a7811SThomas Huth         shift = 17;
690956a7811SThomas Huth         break;
691956a7811SThomas Huth 
692956a7811SThomas Huth     /* level 6 - audio etherrx/tx dma */
693956a7811SThomas Huth     case NEXT_ENTX_DMA_I:
694956a7811SThomas Huth         shift = 28;
695956a7811SThomas Huth         break;
696956a7811SThomas Huth     case NEXT_ENRX_DMA_I:
697956a7811SThomas Huth         shift = 27;
698956a7811SThomas Huth         break;
699956a7811SThomas Huth     case NEXT_SCSI_DMA_I:
700956a7811SThomas Huth         shift = 26;
701956a7811SThomas Huth         break;
702956a7811SThomas Huth     case NEXT_SND_I:
703956a7811SThomas Huth         shift = 23;
704956a7811SThomas Huth         break;
705956a7811SThomas Huth     case NEXT_SCC_DMA_I:
706956a7811SThomas Huth         shift = 21;
707956a7811SThomas Huth         break;
708956a7811SThomas Huth 
709956a7811SThomas Huth     }
710956a7811SThomas Huth     /*
711956a7811SThomas Huth      * this HAS to be wrong, the interrupt handlers in mach and together
712956a7811SThomas Huth      * int_status and int_mask and return if there is a hit
713956a7811SThomas Huth      */
714ac99317bSPeter Maydell     if (s->int_mask & (1 << shift)) {
715956a7811SThomas Huth         DPRINTF("%x interrupt masked @ %x\n", 1 << shift, cpu->env.pc);
716956a7811SThomas Huth         /* return; */
717956a7811SThomas Huth     }
718956a7811SThomas Huth 
719956a7811SThomas Huth     /* second switch triggers the correct interrupt */
720956a7811SThomas Huth     if (level) {
721ac99317bSPeter Maydell         s->int_status |= 1 << shift;
722956a7811SThomas Huth 
723956a7811SThomas Huth         switch (number) {
724956a7811SThomas Huth         /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
725956a7811SThomas Huth         case NEXT_FD_I:
726956a7811SThomas Huth         case NEXT_KBD_I:
727956a7811SThomas Huth         case NEXT_PWR_I:
728956a7811SThomas Huth         case NEXT_ENRX_I:
729956a7811SThomas Huth         case NEXT_ENTX_I:
730956a7811SThomas Huth         case NEXT_SCSI_I:
731956a7811SThomas Huth         case NEXT_CLK_I:
732956a7811SThomas Huth             m68k_set_irq_level(cpu, 3, 27);
733956a7811SThomas Huth             break;
734956a7811SThomas Huth 
735956a7811SThomas Huth         /* level 5 - scc (serial) */
736956a7811SThomas Huth         case NEXT_SCC_I:
737956a7811SThomas Huth             m68k_set_irq_level(cpu, 5, 29);
738956a7811SThomas Huth             break;
739956a7811SThomas Huth 
740956a7811SThomas Huth         /* level 6 - audio etherrx/tx dma */
741956a7811SThomas Huth         case NEXT_ENTX_DMA_I:
742956a7811SThomas Huth         case NEXT_ENRX_DMA_I:
743956a7811SThomas Huth         case NEXT_SCSI_DMA_I:
744956a7811SThomas Huth         case NEXT_SND_I:
745956a7811SThomas Huth         case NEXT_SCC_DMA_I:
746956a7811SThomas Huth             m68k_set_irq_level(cpu, 6, 30);
747956a7811SThomas Huth             break;
748956a7811SThomas Huth         }
749956a7811SThomas Huth     } else {
750ac99317bSPeter Maydell         s->int_status &= ~(1 << shift);
751956a7811SThomas Huth         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
752956a7811SThomas Huth     }
753956a7811SThomas Huth }
754956a7811SThomas Huth 
755f2a80c6eSThomas Huth static void nextdma_write(void *opaque, uint8_t *buf, int size, int type)
756f2a80c6eSThomas Huth {
757f2a80c6eSThomas Huth     uint32_t base_addr;
758f2a80c6eSThomas Huth     int irq = 0;
759f2a80c6eSThomas Huth     uint8_t align = 16;
760f2a80c6eSThomas Huth     NeXTState *next_state = NEXT_MACHINE(qdev_get_machine());
761f2a80c6eSThomas Huth 
762f2a80c6eSThomas Huth     if (type == NEXTDMA_ENRX || type == NEXTDMA_ENTX) {
763f2a80c6eSThomas Huth         align = 32;
764f2a80c6eSThomas Huth     }
765f2a80c6eSThomas Huth     /* Most DMA is supposedly 16 byte aligned */
766f2a80c6eSThomas Huth     if ((size % align) != 0) {
767f2a80c6eSThomas Huth         size -= size % align;
768f2a80c6eSThomas Huth         size += align;
769f2a80c6eSThomas Huth     }
770f2a80c6eSThomas Huth 
771f2a80c6eSThomas Huth     /*
772f2a80c6eSThomas Huth      * prom sets the dma start using initbuf while the bootloader uses next
773f2a80c6eSThomas Huth      * so we check to see if initbuf is 0
774f2a80c6eSThomas Huth      */
775f2a80c6eSThomas Huth     if (next_state->dma[type].next_initbuf == 0) {
776f2a80c6eSThomas Huth         base_addr = next_state->dma[type].next;
777f2a80c6eSThomas Huth     } else {
778f2a80c6eSThomas Huth         base_addr = next_state->dma[type].next_initbuf;
779f2a80c6eSThomas Huth     }
780f2a80c6eSThomas Huth 
781f2a80c6eSThomas Huth     cpu_physical_memory_write(base_addr, buf, size);
782f2a80c6eSThomas Huth 
783f2a80c6eSThomas Huth     next_state->dma[type].next_initbuf = 0;
784f2a80c6eSThomas Huth 
785f2a80c6eSThomas Huth     /* saved limit is checked to calculate packet size by both, rom and netbsd */
786f2a80c6eSThomas Huth     next_state->dma[type].saved_limit = (next_state->dma[type].next + size);
787f2a80c6eSThomas Huth     next_state->dma[type].saved_next  = (next_state->dma[type].next);
788f2a80c6eSThomas Huth 
789f2a80c6eSThomas Huth     /*
790f2a80c6eSThomas Huth      * 32 bytes under savedbase seems to be some kind of register
791f2a80c6eSThomas Huth      * of which the purpose is unknown as of yet
792f2a80c6eSThomas Huth      */
793f2a80c6eSThomas Huth     /* stl_phys(s->rx_dma.base-32,0xFFFFFFFF); */
794f2a80c6eSThomas Huth 
795f2a80c6eSThomas Huth     if (!(next_state->dma[type].csr & DMA_SUPDATE)) {
796f2a80c6eSThomas Huth         next_state->dma[type].next  = next_state->dma[type].start;
797f2a80c6eSThomas Huth         next_state->dma[type].limit = next_state->dma[type].stop;
798f2a80c6eSThomas Huth     }
799f2a80c6eSThomas Huth 
800f2a80c6eSThomas Huth     /* Set dma registers and raise an irq */
801f2a80c6eSThomas Huth     next_state->dma[type].csr |= DMA_COMPLETE; /* DON'T CHANGE THIS! */
802f2a80c6eSThomas Huth 
803f2a80c6eSThomas Huth     switch (type) {
804f2a80c6eSThomas Huth     case NEXTDMA_SCSI:
805f2a80c6eSThomas Huth         irq = NEXT_SCSI_DMA_I;
806f2a80c6eSThomas Huth         break;
807f2a80c6eSThomas Huth     }
808f2a80c6eSThomas Huth 
809f2a80c6eSThomas Huth     next_irq(opaque, irq, 1);
810f2a80c6eSThomas Huth     next_irq(opaque, irq, 0);
811f2a80c6eSThomas Huth }
812f2a80c6eSThomas Huth 
813f2a80c6eSThomas Huth static void nextscsi_read(void *opaque, uint8_t *buf, int len)
814f2a80c6eSThomas Huth {
815f2a80c6eSThomas Huth     DPRINTF("SCSI READ: %x\n", len);
816f2a80c6eSThomas Huth     abort();
817f2a80c6eSThomas Huth }
818f2a80c6eSThomas Huth 
819f2a80c6eSThomas Huth static void nextscsi_write(void *opaque, uint8_t *buf, int size)
820f2a80c6eSThomas Huth {
821f2a80c6eSThomas Huth     DPRINTF("SCSI WRITE: %i\n", size);
822f2a80c6eSThomas Huth     nextdma_write(opaque, buf, size, NEXTDMA_SCSI);
823f2a80c6eSThomas Huth }
824f2a80c6eSThomas Huth 
825f2a80c6eSThomas Huth static void next_scsi_init(DeviceState *pcdev, M68kCPU *cpu)
826f2a80c6eSThomas Huth {
827f2a80c6eSThomas Huth     struct NeXTPC *next_pc = NEXT_PC(pcdev);
828f2a80c6eSThomas Huth     DeviceState *dev;
829f2a80c6eSThomas Huth     SysBusDevice *sysbusdev;
830f2a80c6eSThomas Huth     SysBusESPState *sysbus_esp;
831f2a80c6eSThomas Huth     ESPState *esp;
832f2a80c6eSThomas Huth 
833f2a80c6eSThomas Huth     dev = qdev_new(TYPE_SYSBUS_ESP);
834f2a80c6eSThomas Huth     sysbus_esp = SYSBUS_ESP(dev);
835f2a80c6eSThomas Huth     esp = &sysbus_esp->esp;
836f2a80c6eSThomas Huth     esp->dma_memory_read = nextscsi_read;
837f2a80c6eSThomas Huth     esp->dma_memory_write = nextscsi_write;
838f2a80c6eSThomas Huth     esp->dma_opaque = pcdev;
839f2a80c6eSThomas Huth     sysbus_esp->it_shift = 0;
840f2a80c6eSThomas Huth     esp->dma_enabled = 1;
841f2a80c6eSThomas Huth     sysbusdev = SYS_BUS_DEVICE(dev);
842f2a80c6eSThomas Huth     sysbus_realize_and_unref(sysbusdev, &error_fatal);
843f2a80c6eSThomas Huth     sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(pcdev, NEXT_SCSI_I));
844f2a80c6eSThomas Huth     sysbus_mmio_map(sysbusdev, 0, 0x2114000);
845f2a80c6eSThomas Huth 
846f2a80c6eSThomas Huth     next_pc->scsi_reset = qdev_get_gpio_in(dev, 0);
847f2a80c6eSThomas Huth     next_pc->scsi_dma = qdev_get_gpio_in(dev, 1);
848f2a80c6eSThomas Huth 
849f2a80c6eSThomas Huth     scsi_bus_legacy_handle_cmdline(&esp->bus);
850f2a80c6eSThomas Huth }
851f2a80c6eSThomas Huth 
852b497f4a1SPeter Maydell static void next_escc_init(DeviceState *pcdev)
853b17bed5bSThomas Huth {
854b17bed5bSThomas Huth     DeviceState *dev;
855b17bed5bSThomas Huth     SysBusDevice *s;
856b17bed5bSThomas Huth 
8573e80f690SMarkus Armbruster     dev = qdev_new(TYPE_ESCC);
858b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "disabled", 0);
859b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "frequency", 9600 * 384);
860b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "it_shift", 0);
861b17bed5bSThomas Huth     qdev_prop_set_bit(dev, "bit_swap", true);
862b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrB", serial_hd(1));
863b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrA", serial_hd(0));
864b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
865b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
866b17bed5bSThomas Huth 
867b17bed5bSThomas Huth     s = SYS_BUS_DEVICE(dev);
8683c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
869d9cd4039SPeter Maydell     sysbus_connect_irq(s, 0, qdev_get_gpio_in(pcdev, NEXT_SCC_I));
870d9cd4039SPeter Maydell     sysbus_connect_irq(s, 1, qdev_get_gpio_in(pcdev, NEXT_SCC_DMA_I));
871b17bed5bSThomas Huth     sysbus_mmio_map(s, 0, 0x2118000);
872b17bed5bSThomas Huth }
873b17bed5bSThomas Huth 
874660bef33SPeter Maydell static void next_pc_reset(DeviceState *dev)
875660bef33SPeter Maydell {
87640831636SPeter Maydell     NeXTPC *s = NEXT_PC(dev);
87740831636SPeter Maydell 
87840831636SPeter Maydell     /* Set internal registers to initial values */
87940831636SPeter Maydell     /*     0x0000XX00 << vital bits */
88040831636SPeter Maydell     s->scr1 = 0x00011102;
88140831636SPeter Maydell     s->scr2 = 0x00ff0c80;
88222cf5ee3SMark Cave-Ayland     s->old_scr2 = s->scr2;
8836f0face7SPeter Maydell 
8846f0face7SPeter Maydell     s->rtc.status = 0x90;
8856f0face7SPeter Maydell 
8866f0face7SPeter Maydell     /* Load RTC RAM - TODO: provide possibility to load contents from file */
8876f0face7SPeter Maydell     memcpy(s->rtc.ram, rtc_ram2, 32);
888660bef33SPeter Maydell }
889660bef33SPeter Maydell 
890660bef33SPeter Maydell static void next_pc_realize(DeviceState *dev, Error **errp)
891660bef33SPeter Maydell {
89240831636SPeter Maydell     NeXTPC *s = NEXT_PC(dev);
89340831636SPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
89440831636SPeter Maydell 
895d9cd4039SPeter Maydell     qdev_init_gpio_in(dev, next_irq, NEXT_NUM_IRQS);
896d9cd4039SPeter Maydell 
8977e993d93SMark Cave-Ayland     memory_region_init_io(&s->mmiomem, OBJECT(s), &next_mmio_ops, s,
8987e993d93SMark Cave-Ayland                           "next.mmio", 0xd0000);
8990d60da39SMark Cave-Ayland     memory_region_init_io(&s->scrmem, OBJECT(s), &next_scr_ops, s,
9001dc7aeaeSPeter Maydell                           "next.scr", 0x20000);
90140831636SPeter Maydell     sysbus_init_mmio(sbd, &s->mmiomem);
9021dc7aeaeSPeter Maydell     sysbus_init_mmio(sbd, &s->scrmem);
903660bef33SPeter Maydell }
904660bef33SPeter Maydell 
905b497f4a1SPeter Maydell /*
906b497f4a1SPeter Maydell  * If the m68k CPU implemented its inbound irq lines as GPIO lines
907b497f4a1SPeter Maydell  * rather than via the m68k_set_irq_level() function we would not need
908b497f4a1SPeter Maydell  * this cpu link property and could instead provide outbound IRQ lines
909b497f4a1SPeter Maydell  * that the board could wire up to the CPU.
910b497f4a1SPeter Maydell  */
911b497f4a1SPeter Maydell static Property next_pc_properties[] = {
912b497f4a1SPeter Maydell     DEFINE_PROP_LINK("cpu", NeXTPC, cpu, TYPE_M68K_CPU, M68kCPU *),
913b497f4a1SPeter Maydell     DEFINE_PROP_END_OF_LIST(),
914b497f4a1SPeter Maydell };
915b497f4a1SPeter Maydell 
91675ca77ecSPeter Maydell static const VMStateDescription next_rtc_vmstate = {
91775ca77ecSPeter Maydell     .name = "next-rtc",
91888d0c5b0SMark Cave-Ayland     .version_id = 2,
91988d0c5b0SMark Cave-Ayland     .minimum_version_id = 2,
92075ca77ecSPeter Maydell     .fields = (VMStateField[]) {
92188d0c5b0SMark Cave-Ayland         VMSTATE_INT8(phase, NextRtc),
92275ca77ecSPeter Maydell         VMSTATE_UINT8_ARRAY(ram, NextRtc, 32),
92375ca77ecSPeter Maydell         VMSTATE_UINT8(command, NextRtc),
92475ca77ecSPeter Maydell         VMSTATE_UINT8(value, NextRtc),
92575ca77ecSPeter Maydell         VMSTATE_UINT8(status, NextRtc),
92675ca77ecSPeter Maydell         VMSTATE_UINT8(control, NextRtc),
92775ca77ecSPeter Maydell         VMSTATE_UINT8(retval, NextRtc),
92875ca77ecSPeter Maydell         VMSTATE_END_OF_LIST()
92975ca77ecSPeter Maydell     },
93075ca77ecSPeter Maydell };
93175ca77ecSPeter Maydell 
93275ca77ecSPeter Maydell static const VMStateDescription next_pc_vmstate = {
93375ca77ecSPeter Maydell     .name = "next-pc",
9348220baa0SMark Cave-Ayland     .version_id = 2,
9358220baa0SMark Cave-Ayland     .minimum_version_id = 2,
93675ca77ecSPeter Maydell     .fields = (VMStateField[]) {
93775ca77ecSPeter Maydell         VMSTATE_UINT32(scr1, NeXTPC),
93875ca77ecSPeter Maydell         VMSTATE_UINT32(scr2, NeXTPC),
93922cf5ee3SMark Cave-Ayland         VMSTATE_UINT32(old_scr2, NeXTPC),
94075ca77ecSPeter Maydell         VMSTATE_UINT32(int_mask, NeXTPC),
94175ca77ecSPeter Maydell         VMSTATE_UINT32(int_status, NeXTPC),
9428220baa0SMark Cave-Ayland         VMSTATE_UINT32(led, NeXTPC),
94375ca77ecSPeter Maydell         VMSTATE_UINT8(scsi_csr_1, NeXTPC),
94475ca77ecSPeter Maydell         VMSTATE_UINT8(scsi_csr_2, NeXTPC),
94575ca77ecSPeter Maydell         VMSTATE_STRUCT(rtc, NeXTPC, 0, next_rtc_vmstate, NextRtc),
94675ca77ecSPeter Maydell         VMSTATE_END_OF_LIST()
94775ca77ecSPeter Maydell     },
94875ca77ecSPeter Maydell };
94975ca77ecSPeter Maydell 
950660bef33SPeter Maydell static void next_pc_class_init(ObjectClass *klass, void *data)
951660bef33SPeter Maydell {
952660bef33SPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
953660bef33SPeter Maydell 
954660bef33SPeter Maydell     dc->desc = "NeXT Peripheral Controller";
955660bef33SPeter Maydell     dc->realize = next_pc_realize;
956660bef33SPeter Maydell     dc->reset = next_pc_reset;
957b497f4a1SPeter Maydell     device_class_set_props(dc, next_pc_properties);
95875ca77ecSPeter Maydell     dc->vmsd = &next_pc_vmstate;
959660bef33SPeter Maydell }
960660bef33SPeter Maydell 
961660bef33SPeter Maydell static const TypeInfo next_pc_info = {
962660bef33SPeter Maydell     .name = TYPE_NEXT_PC,
963660bef33SPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
964660bef33SPeter Maydell     .instance_size = sizeof(NeXTPC),
965660bef33SPeter Maydell     .class_init = next_pc_class_init,
966660bef33SPeter Maydell };
967660bef33SPeter Maydell 
968956a7811SThomas Huth static void next_cube_init(MachineState *machine)
969956a7811SThomas Huth {
970956a7811SThomas Huth     M68kCPU *cpu;
971956a7811SThomas Huth     CPUM68KState *env;
972956a7811SThomas Huth     MemoryRegion *rom = g_new(MemoryRegion, 1);
97387f4ba9eSThomas Huth     MemoryRegion *rom2 = g_new(MemoryRegion, 1);
974956a7811SThomas Huth     MemoryRegion *dmamem = g_new(MemoryRegion, 1);
975956a7811SThomas Huth     MemoryRegion *bmapm1 = g_new(MemoryRegion, 1);
976956a7811SThomas Huth     MemoryRegion *bmapm2 = g_new(MemoryRegion, 1);
977956a7811SThomas Huth     MemoryRegion *sysmem = get_system_memory();
9781684273cSPaolo Bonzini     const char *bios_name = machine->firmware ?: ROM_FILE;
979660bef33SPeter Maydell     DeviceState *pcdev;
980956a7811SThomas Huth 
981956a7811SThomas Huth     /* Initialize the cpu core */
982956a7811SThomas Huth     cpu = M68K_CPU(cpu_create(machine->cpu_type));
983956a7811SThomas Huth     if (!cpu) {
984956a7811SThomas Huth         error_report("Unable to find m68k CPU definition");
985956a7811SThomas Huth         exit(1);
986956a7811SThomas Huth     }
987956a7811SThomas Huth     env = &cpu->env;
988956a7811SThomas Huth 
989956a7811SThomas Huth     /* Initialize CPU registers.  */
990956a7811SThomas Huth     env->vbr = 0;
991956a7811SThomas Huth     env->sr  = 0x2700;
992956a7811SThomas Huth 
993660bef33SPeter Maydell     /* Peripheral Controller */
994660bef33SPeter Maydell     pcdev = qdev_new(TYPE_NEXT_PC);
995b497f4a1SPeter Maydell     object_property_set_link(OBJECT(pcdev), "cpu", OBJECT(cpu), &error_abort);
996660bef33SPeter Maydell     sysbus_realize_and_unref(SYS_BUS_DEVICE(pcdev), &error_fatal);
997956a7811SThomas Huth 
998956a7811SThomas Huth     /* 64MB RAM starting at 0x04000000  */
99949b64ba9SIgor Mammedov     memory_region_add_subregion(sysmem, 0x04000000, machine->ram);
1000956a7811SThomas Huth 
1001956a7811SThomas Huth     /* Framebuffer */
1002b2897f7eSPhilippe Mathieu-Daudé     sysbus_create_simple(TYPE_NEXTFB, 0x0B000000, NULL);
1003956a7811SThomas Huth 
1004956a7811SThomas Huth     /* MMIO */
100540831636SPeter Maydell     sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 0, 0x02000000);
1006956a7811SThomas Huth 
10071dc7aeaeSPeter Maydell     /* BMAP IO - acts as a catch-all for now */
10081dc7aeaeSPeter Maydell     sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02100000);
10091dc7aeaeSPeter Maydell 
1010956a7811SThomas Huth     /* BMAP memory */
10117f863cbaSDavid Hildenbrand     memory_region_init_ram_flags_nomigrate(bmapm1, NULL, "next.bmapmem", 64,
10127f863cbaSDavid Hildenbrand                                            RAM_SHARED, &error_fatal);
1013956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x020c0000, bmapm1);
1014956a7811SThomas Huth     /* The Rev_2.5_v66.bin firmware accesses it at 0x820c0020, too */
1015956a7811SThomas Huth     memory_region_init_alias(bmapm2, NULL, "next.bmapmem2", bmapm1, 0x0, 64);
1016956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x820c0000, bmapm2);
1017956a7811SThomas Huth 
1018956a7811SThomas Huth     /* KBD */
1019b2897f7eSPhilippe Mathieu-Daudé     sysbus_create_simple(TYPE_NEXTKBD, 0x0200e000, NULL);
1020956a7811SThomas Huth 
1021956a7811SThomas Huth     /* Load ROM here */
1022956a7811SThomas Huth     memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal);
1023956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x01000000, rom);
102487f4ba9eSThomas Huth     memory_region_init_alias(rom2, NULL, "next.rom2", rom, 0x0, 0x20000);
102587f4ba9eSThomas Huth     memory_region_add_subregion(sysmem, 0x0, rom2);
1026956a7811SThomas Huth     if (load_image_targphys(bios_name, 0x01000000, 0x20000) < 8) {
1027956a7811SThomas Huth         if (!qtest_enabled()) {
1028956a7811SThomas Huth             error_report("Failed to load firmware '%s'.", bios_name);
1029956a7811SThomas Huth         }
1030956a7811SThomas Huth     } else {
1031956a7811SThomas Huth         uint8_t *ptr;
1032956a7811SThomas Huth         /* Initial PC is always at offset 4 in firmware binaries */
1033956a7811SThomas Huth         ptr = rom_ptr(0x01000004, 4);
1034956a7811SThomas Huth         g_assert(ptr != NULL);
1035956a7811SThomas Huth         env->pc = ldl_p(ptr);
1036956a7811SThomas Huth         if (env->pc >= 0x01020000) {
1037956a7811SThomas Huth             error_report("'%s' does not seem to be a valid firmware image.",
1038956a7811SThomas Huth                          bios_name);
1039956a7811SThomas Huth             exit(1);
1040956a7811SThomas Huth         }
1041956a7811SThomas Huth     }
1042956a7811SThomas Huth 
1043956a7811SThomas Huth     /* Serial */
1044b497f4a1SPeter Maydell     next_escc_init(pcdev);
1045b17bed5bSThomas Huth 
1046b17bed5bSThomas Huth     /* TODO: */
1047956a7811SThomas Huth     /* Network */
1048956a7811SThomas Huth     /* SCSI */
1049f2a80c6eSThomas Huth     next_scsi_init(pcdev, cpu);
1050956a7811SThomas Huth 
1051956a7811SThomas Huth     /* DMA */
1052c0dedcf4SMark Cave-Ayland     memory_region_init_io(dmamem, NULL, &next_dma_ops, machine, "next.dma",
1053c0dedcf4SMark Cave-Ayland                           0x5000);
1054956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02000000, dmamem);
1055956a7811SThomas Huth }
1056956a7811SThomas Huth 
1057956a7811SThomas Huth static void next_machine_class_init(ObjectClass *oc, void *data)
1058956a7811SThomas Huth {
1059956a7811SThomas Huth     MachineClass *mc = MACHINE_CLASS(oc);
1060956a7811SThomas Huth 
1061956a7811SThomas Huth     mc->desc = "NeXT Cube";
1062956a7811SThomas Huth     mc->init = next_cube_init;
1063f2a80c6eSThomas Huth     mc->block_default_type = IF_SCSI;
1064956a7811SThomas Huth     mc->default_ram_size = RAM_SIZE;
106549b64ba9SIgor Mammedov     mc->default_ram_id = "next.ram";
1066956a7811SThomas Huth     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
1067956a7811SThomas Huth }
1068956a7811SThomas Huth 
1069956a7811SThomas Huth static const TypeInfo next_typeinfo = {
1070956a7811SThomas Huth     .name = TYPE_NEXT_MACHINE,
1071956a7811SThomas Huth     .parent = TYPE_MACHINE,
1072956a7811SThomas Huth     .class_init = next_machine_class_init,
1073956a7811SThomas Huth     .instance_size = sizeof(NeXTState),
1074956a7811SThomas Huth };
1075956a7811SThomas Huth 
1076956a7811SThomas Huth static void next_register_type(void)
1077956a7811SThomas Huth {
1078956a7811SThomas Huth     type_register_static(&next_typeinfo);
1079660bef33SPeter Maydell     type_register_static(&next_pc_info);
1080956a7811SThomas Huth }
1081956a7811SThomas Huth 
1082956a7811SThomas Huth type_init(next_register_type)
1083