xref: /qemu/hw/m68k/next-cube.c (revision 8063396b)
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"
13b17bed5bSThomas Huth #include "cpu.h"
14956a7811SThomas Huth #include "exec/hwaddr.h"
15956a7811SThomas Huth #include "exec/address-spaces.h"
16956a7811SThomas Huth #include "sysemu/sysemu.h"
17956a7811SThomas Huth #include "sysemu/qtest.h"
18b17bed5bSThomas Huth #include "hw/irq.h"
19956a7811SThomas Huth #include "hw/m68k/next-cube.h"
20956a7811SThomas Huth #include "hw/boards.h"
21956a7811SThomas Huth #include "hw/loader.h"
22956a7811SThomas Huth #include "hw/scsi/esp.h"
23956a7811SThomas Huth #include "hw/sysbus.h"
24db1015e9SEduardo Habkost #include "qom/object.h"
25956a7811SThomas Huth #include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */
26956a7811SThomas Huth #include "hw/block/fdc.h"
27b17bed5bSThomas Huth #include "hw/qdev-properties.h"
28956a7811SThomas Huth #include "qapi/error.h"
29956a7811SThomas Huth #include "ui/console.h"
30956a7811SThomas Huth #include "target/m68k/cpu.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")
41*8063396bSEduardo 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 {
65cd4fc142SThomas Huth     uint8_t ram[32];
66cd4fc142SThomas Huth     uint8_t command;
67cd4fc142SThomas Huth     uint8_t value;
68cd4fc142SThomas Huth     uint8_t status;
69cd4fc142SThomas Huth     uint8_t control;
70cd4fc142SThomas Huth     uint8_t retval;
71cd4fc142SThomas Huth } NextRtc;
72cd4fc142SThomas Huth 
73db1015e9SEduardo Habkost struct NeXTState {
74956a7811SThomas Huth     MachineState parent;
75956a7811SThomas Huth 
76956a7811SThomas Huth     uint32_t int_mask;
77956a7811SThomas Huth     uint32_t int_status;
78956a7811SThomas Huth 
79956a7811SThomas Huth     uint8_t scsi_csr_1;
80956a7811SThomas Huth     uint8_t scsi_csr_2;
81956a7811SThomas Huth     next_dma dma[10];
82956a7811SThomas Huth     qemu_irq *scsi_irq;
83956a7811SThomas Huth     qemu_irq scsi_dma;
84956a7811SThomas Huth     qemu_irq scsi_reset;
85956a7811SThomas Huth     qemu_irq *fd_irq;
86956a7811SThomas Huth 
87956a7811SThomas Huth     uint32_t scr1;
88956a7811SThomas Huth     uint32_t scr2;
89956a7811SThomas Huth 
90cd4fc142SThomas Huth     NextRtc rtc;
91db1015e9SEduardo Habkost };
92956a7811SThomas Huth 
93956a7811SThomas Huth /* Thanks to NeXT forums for this */
94956a7811SThomas Huth /*
95956a7811SThomas Huth static const uint8_t rtc_ram3[32] = {
96956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
97956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x7B, 0x00,
98956a7811SThomas Huth     0x00, 0x00, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x00,
99956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x13
100956a7811SThomas Huth };
101956a7811SThomas Huth */
102956a7811SThomas Huth static const uint8_t rtc_ram2[32] = {
103956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00,
104956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x4b, 0x00,
105956a7811SThomas Huth     0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
106956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x7e,
107956a7811SThomas Huth };
108956a7811SThomas Huth 
109956a7811SThomas Huth #define SCR2_RTCLK 0x2
110956a7811SThomas Huth #define SCR2_RTDATA 0x4
111956a7811SThomas Huth #define SCR2_TOBCD(x) (((x / 10) << 4) + (x % 10))
112956a7811SThomas Huth 
113956a7811SThomas Huth static void nextscr2_write(NeXTState *s, uint32_t val, int size)
114956a7811SThomas Huth {
115956a7811SThomas Huth     static int led;
116956a7811SThomas Huth     static int phase;
117956a7811SThomas Huth     static uint8_t old_scr2;
118956a7811SThomas Huth     uint8_t scr2_2;
119cd4fc142SThomas Huth     NextRtc *rtc = &s->rtc;
120956a7811SThomas Huth 
121956a7811SThomas Huth     if (size == 4) {
122956a7811SThomas Huth         scr2_2 = (val >> 8) & 0xFF;
123956a7811SThomas Huth     } else {
124956a7811SThomas Huth         scr2_2 = val & 0xFF;
125956a7811SThomas Huth     }
126956a7811SThomas Huth 
127956a7811SThomas Huth     if (val & 0x1) {
128956a7811SThomas Huth         DPRINTF("fault!\n");
129956a7811SThomas Huth         led++;
130956a7811SThomas Huth         if (led == 10) {
131956a7811SThomas Huth             DPRINTF("LED flashing, possible fault!\n");
132956a7811SThomas Huth             led = 0;
133956a7811SThomas Huth         }
134956a7811SThomas Huth     }
135956a7811SThomas Huth 
136956a7811SThomas Huth     if (scr2_2 & 0x1) {
137956a7811SThomas Huth         /* DPRINTF("RTC %x phase %i\n", scr2_2, phase); */
138956a7811SThomas Huth         if (phase == -1) {
139956a7811SThomas Huth             phase = 0;
140956a7811SThomas Huth         }
141956a7811SThomas Huth         /* If we are in going down clock... do something */
142956a7811SThomas Huth         if (((old_scr2 & SCR2_RTCLK) != (scr2_2 & SCR2_RTCLK)) &&
143956a7811SThomas Huth                 ((scr2_2 & SCR2_RTCLK) == 0)) {
144956a7811SThomas Huth             if (phase < 8) {
145cd4fc142SThomas Huth                 rtc->command = (rtc->command << 1) |
146956a7811SThomas Huth                                ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
147956a7811SThomas Huth             }
148956a7811SThomas Huth             if (phase >= 8 && phase < 16) {
149cd4fc142SThomas Huth                 rtc->value = (rtc->value << 1) |
150cd4fc142SThomas Huth                              ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
151956a7811SThomas Huth 
152956a7811SThomas Huth                 /* if we read RAM register, output RT_DATA bit */
153cd4fc142SThomas Huth                 if (rtc->command <= 0x1F) {
154956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
155cd4fc142SThomas Huth                     if (rtc->ram[rtc->command] & (0x80 >> (phase - 8))) {
156956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
157956a7811SThomas Huth                     }
158956a7811SThomas Huth 
159cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
160956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
161956a7811SThomas Huth                 }
162956a7811SThomas Huth                 /* read the status 0x30 */
163cd4fc142SThomas Huth                 if (rtc->command == 0x30) {
164956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
165956a7811SThomas Huth                     /* for now status = 0x98 (new rtc + FTU) */
166cd4fc142SThomas Huth                     if (rtc->status & (0x80 >> (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 0x31 */
174cd4fc142SThomas Huth                 if (rtc->command == 0x31) {
175956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
176cd4fc142SThomas Huth                     if (rtc->control & (0x80 >> (phase - 8))) {
177956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
178956a7811SThomas Huth                     }
179cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
180956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
181956a7811SThomas Huth                 }
182956a7811SThomas Huth 
183cd4fc142SThomas Huth                 if ((rtc->command >= 0x20) && (rtc->command <= 0x2F)) {
184956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
185956a7811SThomas Huth                     /* for now 0x00 */
186956a7811SThomas Huth                     time_t time_h = time(NULL);
187956a7811SThomas Huth                     struct tm *info = localtime(&time_h);
188956a7811SThomas Huth                     int ret = 0;
189956a7811SThomas Huth 
190cd4fc142SThomas Huth                     switch (rtc->command) {
191956a7811SThomas Huth                     case 0x20:
192956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_sec);
193956a7811SThomas Huth                         break;
194956a7811SThomas Huth                     case 0x21:
195956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_min);
196956a7811SThomas Huth                         break;
197956a7811SThomas Huth                     case 0x22:
198956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_hour);
199956a7811SThomas Huth                         break;
200956a7811SThomas Huth                     case 0x24:
201956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_mday);
202956a7811SThomas Huth                         break;
203956a7811SThomas Huth                     case 0x25:
204956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_mon + 1));
205956a7811SThomas Huth                         break;
206956a7811SThomas Huth                     case 0x26:
207956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_year - 100));
208956a7811SThomas Huth                         break;
209956a7811SThomas Huth 
210956a7811SThomas Huth                     }
211956a7811SThomas Huth 
212956a7811SThomas Huth                     if (ret & (0x80 >> (phase - 8))) {
213956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
214956a7811SThomas Huth                     }
215cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
216956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
217956a7811SThomas Huth                 }
218956a7811SThomas Huth 
219956a7811SThomas Huth             }
220956a7811SThomas Huth 
221956a7811SThomas Huth             phase++;
222956a7811SThomas Huth             if (phase == 16) {
223cd4fc142SThomas Huth                 if (rtc->command >= 0x80 && rtc->command <= 0x9F) {
224cd4fc142SThomas Huth                     rtc->ram[rtc->command - 0x80] = rtc->value;
225956a7811SThomas Huth                 }
226956a7811SThomas Huth                 /* write to x30 register */
227cd4fc142SThomas Huth                 if (rtc->command == 0xB1) {
228956a7811SThomas Huth                     /* clear FTU */
229cd4fc142SThomas Huth                     if (rtc->value & 0x04) {
230cd4fc142SThomas Huth                         rtc->status = rtc->status & (~0x18);
231956a7811SThomas Huth                         s->int_status = s->int_status & (~0x04);
232956a7811SThomas Huth                     }
233956a7811SThomas Huth                 }
234956a7811SThomas Huth             }
235956a7811SThomas Huth         }
236956a7811SThomas Huth     } else {
237956a7811SThomas Huth         /* else end or abort */
238956a7811SThomas Huth         phase = -1;
239cd4fc142SThomas Huth         rtc->command = 0;
240cd4fc142SThomas Huth         rtc->value = 0;
241956a7811SThomas Huth     }
242956a7811SThomas Huth     s->scr2 = val & 0xFFFF00FF;
243956a7811SThomas Huth     s->scr2 |= scr2_2 << 8;
244956a7811SThomas Huth     old_scr2 = scr2_2;
245956a7811SThomas Huth }
246956a7811SThomas Huth 
247956a7811SThomas Huth static uint32_t mmio_readb(NeXTState *s, hwaddr addr)
248956a7811SThomas Huth {
249956a7811SThomas Huth     switch (addr) {
250956a7811SThomas Huth     case 0xc000:
251956a7811SThomas Huth         return (s->scr1 >> 24) & 0xFF;
252956a7811SThomas Huth     case 0xc001:
253956a7811SThomas Huth         return (s->scr1 >> 16) & 0xFF;
254956a7811SThomas Huth     case 0xc002:
255956a7811SThomas Huth         return (s->scr1 >> 8)  & 0xFF;
256956a7811SThomas Huth     case 0xc003:
257956a7811SThomas Huth         return (s->scr1 >> 0)  & 0xFF;
258956a7811SThomas Huth 
259956a7811SThomas Huth     case 0xd000:
260956a7811SThomas Huth         return (s->scr2 >> 24) & 0xFF;
261956a7811SThomas Huth     case 0xd001:
262956a7811SThomas Huth         return (s->scr2 >> 16) & 0xFF;
263956a7811SThomas Huth     case 0xd002:
264956a7811SThomas Huth         return (s->scr2 >> 8)  & 0xFF;
265956a7811SThomas Huth     case 0xd003:
266956a7811SThomas Huth         return (s->scr2 >> 0)  & 0xFF;
267956a7811SThomas Huth     case 0x14020:
268956a7811SThomas Huth         DPRINTF("MMIO Read 0x4020\n");
269956a7811SThomas Huth         return 0x7f;
270956a7811SThomas Huth 
271956a7811SThomas Huth     default:
272956a7811SThomas Huth         DPRINTF("MMIO Read B @ %"HWADDR_PRIx"\n", addr);
273956a7811SThomas Huth         return 0x0;
274956a7811SThomas Huth     }
275956a7811SThomas Huth }
276956a7811SThomas Huth 
277956a7811SThomas Huth static uint32_t mmio_readw(NeXTState *s, hwaddr addr)
278956a7811SThomas Huth {
279956a7811SThomas Huth     switch (addr) {
280956a7811SThomas Huth     default:
281956a7811SThomas Huth         DPRINTF("MMIO Read W @ %"HWADDR_PRIx"\n", addr);
282956a7811SThomas Huth         return 0x0;
283956a7811SThomas Huth     }
284956a7811SThomas Huth }
285956a7811SThomas Huth 
286956a7811SThomas Huth static uint32_t mmio_readl(NeXTState *s, hwaddr addr)
287956a7811SThomas Huth {
288956a7811SThomas Huth     switch (addr) {
289956a7811SThomas Huth     case 0x7000:
290956a7811SThomas Huth         /* DPRINTF("Read INT status: %x\n", s->int_status); */
291956a7811SThomas Huth         return s->int_status;
292956a7811SThomas Huth 
293956a7811SThomas Huth     case 0x7800:
294956a7811SThomas Huth         DPRINTF("MMIO Read INT mask: %x\n", s->int_mask);
295956a7811SThomas Huth         return s->int_mask;
296956a7811SThomas Huth 
297956a7811SThomas Huth     case 0xc000:
298956a7811SThomas Huth         return s->scr1;
299956a7811SThomas Huth 
300956a7811SThomas Huth     case 0xd000:
301956a7811SThomas Huth         return s->scr2;
302956a7811SThomas Huth 
303956a7811SThomas Huth     default:
304956a7811SThomas Huth         DPRINTF("MMIO Read L @ %"HWADDR_PRIx"\n", addr);
305956a7811SThomas Huth         return 0x0;
306956a7811SThomas Huth     }
307956a7811SThomas Huth }
308956a7811SThomas Huth 
309956a7811SThomas Huth static void mmio_writeb(NeXTState *s, hwaddr addr, uint32_t val)
310956a7811SThomas Huth {
311956a7811SThomas Huth     switch (addr) {
312956a7811SThomas Huth     case 0xd003:
313956a7811SThomas Huth         nextscr2_write(s, val, 1);
314956a7811SThomas Huth         break;
315956a7811SThomas Huth     default:
316956a7811SThomas Huth         DPRINTF("MMIO Write B @ %x with %x\n", (unsigned int)addr, val);
317956a7811SThomas Huth     }
318956a7811SThomas Huth 
319956a7811SThomas Huth }
320956a7811SThomas Huth 
321956a7811SThomas Huth static void mmio_writew(NeXTState *s, hwaddr addr, uint32_t val)
322956a7811SThomas Huth {
323956a7811SThomas Huth     DPRINTF("MMIO Write W\n");
324956a7811SThomas Huth }
325956a7811SThomas Huth 
326956a7811SThomas Huth static void mmio_writel(NeXTState *s, hwaddr addr, uint32_t val)
327956a7811SThomas Huth {
328956a7811SThomas Huth     switch (addr) {
329956a7811SThomas Huth     case 0x7000:
330956a7811SThomas Huth         DPRINTF("INT Status old: %x new: %x\n", s->int_status, val);
331956a7811SThomas Huth         s->int_status = val;
332956a7811SThomas Huth         break;
333956a7811SThomas Huth     case 0x7800:
334956a7811SThomas Huth         DPRINTF("INT Mask old: %x new: %x\n", s->int_mask, val);
335956a7811SThomas Huth         s->int_mask  = val;
336956a7811SThomas Huth         break;
337956a7811SThomas Huth     case 0xc000:
338956a7811SThomas Huth         DPRINTF("SCR1 Write: %x\n", val);
339956a7811SThomas Huth         break;
340956a7811SThomas Huth     case 0xd000:
341956a7811SThomas Huth         nextscr2_write(s, val, 4);
342956a7811SThomas Huth         break;
343956a7811SThomas Huth 
344956a7811SThomas Huth     default:
345956a7811SThomas Huth         DPRINTF("MMIO Write l @ %x with %x\n", (unsigned int)addr, val);
346956a7811SThomas Huth     }
347956a7811SThomas Huth }
348956a7811SThomas Huth 
349956a7811SThomas Huth static uint64_t mmio_readfn(void *opaque, hwaddr addr, unsigned size)
350956a7811SThomas Huth {
351956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
352956a7811SThomas Huth 
353956a7811SThomas Huth     switch (size) {
354956a7811SThomas Huth     case 1:
355956a7811SThomas Huth         return mmio_readb(ns, addr);
356956a7811SThomas Huth     case 2:
357956a7811SThomas Huth         return mmio_readw(ns, addr);
358956a7811SThomas Huth     case 4:
359956a7811SThomas Huth         return mmio_readl(ns, addr);
360956a7811SThomas Huth     default:
361956a7811SThomas Huth         g_assert_not_reached();
362956a7811SThomas Huth     }
363956a7811SThomas Huth }
364956a7811SThomas Huth 
365956a7811SThomas Huth static void mmio_writefn(void *opaque, hwaddr addr, uint64_t value,
366956a7811SThomas Huth                          unsigned size)
367956a7811SThomas Huth {
368956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
369956a7811SThomas Huth 
370956a7811SThomas Huth     switch (size) {
371956a7811SThomas Huth     case 1:
372956a7811SThomas Huth         mmio_writeb(ns, addr, value);
373956a7811SThomas Huth         break;
374956a7811SThomas Huth     case 2:
375956a7811SThomas Huth         mmio_writew(ns, addr, value);
376956a7811SThomas Huth         break;
377956a7811SThomas Huth     case 4:
378956a7811SThomas Huth         mmio_writel(ns, addr, value);
379956a7811SThomas Huth         break;
380956a7811SThomas Huth     default:
381956a7811SThomas Huth         g_assert_not_reached();
382956a7811SThomas Huth     }
383956a7811SThomas Huth }
384956a7811SThomas Huth 
385956a7811SThomas Huth static const MemoryRegionOps mmio_ops = {
386956a7811SThomas Huth     .read = mmio_readfn,
387956a7811SThomas Huth     .write = mmio_writefn,
388956a7811SThomas Huth     .valid.min_access_size = 1,
389956a7811SThomas Huth     .valid.max_access_size = 4,
390956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
391956a7811SThomas Huth };
392956a7811SThomas Huth 
393956a7811SThomas Huth static uint32_t scr_readb(NeXTState *s, hwaddr addr)
394956a7811SThomas Huth {
395956a7811SThomas Huth     switch (addr) {
396956a7811SThomas Huth     case 0x14108:
397956a7811SThomas Huth         DPRINTF("FD read @ %x\n", (unsigned int)addr);
398956a7811SThomas Huth         return 0x40 | 0x04 | 0x2 | 0x1;
399956a7811SThomas Huth     case 0x14020:
400956a7811SThomas Huth         DPRINTF("SCSI 4020  STATUS READ %X\n", s->scsi_csr_1);
401956a7811SThomas Huth         return s->scsi_csr_1;
402956a7811SThomas Huth 
403956a7811SThomas Huth     case 0x14021:
404956a7811SThomas Huth         DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
405956a7811SThomas Huth         return 0x40;
406956a7811SThomas Huth 
407956a7811SThomas Huth     /*
408956a7811SThomas Huth      * These 4 registers are the hardware timer, not sure which register
409956a7811SThomas Huth      * is the latch instead of data, but no problems so far
410956a7811SThomas Huth      */
411956a7811SThomas Huth     case 0x1a000:
412956a7811SThomas Huth         return 0xff & (clock() >> 24);
413956a7811SThomas Huth     case 0x1a001:
414956a7811SThomas Huth         return 0xff & (clock() >> 16);
415956a7811SThomas Huth     case 0x1a002:
416956a7811SThomas Huth         return 0xff & (clock() >> 8);
417956a7811SThomas Huth     case 0x1a003:
418956a7811SThomas Huth         /* Hack: We need to have this change consistently to make it work */
419956a7811SThomas Huth         return 0xFF & clock();
420956a7811SThomas Huth 
421956a7811SThomas Huth     default:
422956a7811SThomas Huth         DPRINTF("BMAP Read B @ %x\n", (unsigned int)addr);
423956a7811SThomas Huth         return 0;
424956a7811SThomas Huth     }
425956a7811SThomas Huth }
426956a7811SThomas Huth 
427956a7811SThomas Huth static uint32_t scr_readw(NeXTState *s, hwaddr addr)
428956a7811SThomas Huth {
429956a7811SThomas Huth     DPRINTF("BMAP Read W @ %x\n", (unsigned int)addr);
430956a7811SThomas Huth     return 0;
431956a7811SThomas Huth }
432956a7811SThomas Huth 
433956a7811SThomas Huth static uint32_t scr_readl(NeXTState *s, hwaddr addr)
434956a7811SThomas Huth {
435956a7811SThomas Huth     DPRINTF("BMAP Read L @ %x\n", (unsigned int)addr);
436956a7811SThomas Huth     return 0;
437956a7811SThomas Huth }
438956a7811SThomas Huth 
439956a7811SThomas Huth #define SCSICSR_ENABLE  0x01
440956a7811SThomas Huth #define SCSICSR_RESET   0x02  /* reset scsi dma */
441956a7811SThomas Huth #define SCSICSR_FIFOFL  0x04
442956a7811SThomas Huth #define SCSICSR_DMADIR  0x08  /* if set, scsi to mem */
443956a7811SThomas Huth #define SCSICSR_CPUDMA  0x10  /* if set, dma enabled */
444956a7811SThomas Huth #define SCSICSR_INTMASK 0x20  /* if set, interrupt enabled */
445956a7811SThomas Huth 
446956a7811SThomas Huth static void scr_writeb(NeXTState *s, hwaddr addr, uint32_t value)
447956a7811SThomas Huth {
448956a7811SThomas Huth     switch (addr) {
449956a7811SThomas Huth     case 0x14108:
450956a7811SThomas Huth         DPRINTF("FDCSR Write: %x\n", value);
451956a7811SThomas Huth 
452956a7811SThomas Huth         if (value == 0x0) {
453956a7811SThomas Huth             /* qemu_irq_raise(s->fd_irq[0]); */
454956a7811SThomas Huth         }
455956a7811SThomas Huth         break;
456956a7811SThomas Huth     case 0x14020: /* SCSI Control Register */
457956a7811SThomas Huth         if (value & SCSICSR_FIFOFL) {
458956a7811SThomas Huth             DPRINTF("SCSICSR FIFO Flush\n");
459956a7811SThomas Huth             /* will have to add another irq to the esp if this is needed */
460956a7811SThomas Huth             /* esp_puflush_fifo(esp_g); */
461956a7811SThomas Huth             /* qemu_irq_pulse(s->scsi_dma); */
462956a7811SThomas Huth         }
463956a7811SThomas Huth 
464956a7811SThomas Huth         if (value & SCSICSR_ENABLE) {
465956a7811SThomas Huth             DPRINTF("SCSICSR Enable\n");
466956a7811SThomas Huth             /*
467956a7811SThomas Huth              * qemu_irq_raise(s->scsi_dma);
468956a7811SThomas Huth              * s->scsi_csr_1 = 0xc0;
469956a7811SThomas Huth              * s->scsi_csr_1 |= 0x1;
470956a7811SThomas Huth              * qemu_irq_pulse(s->scsi_dma);
471956a7811SThomas Huth              */
472956a7811SThomas Huth         }
473956a7811SThomas Huth         /*
474956a7811SThomas Huth          * else
475956a7811SThomas Huth          *     s->scsi_csr_1 &= ~SCSICSR_ENABLE;
476956a7811SThomas Huth          */
477956a7811SThomas Huth 
478956a7811SThomas Huth         if (value & SCSICSR_RESET) {
479956a7811SThomas Huth             DPRINTF("SCSICSR Reset\n");
480956a7811SThomas Huth             /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
481956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_reset); */
482956a7811SThomas Huth             /* s->scsi_csr_1 &= ~(SCSICSR_INTMASK |0x80|0x1); */
483956a7811SThomas Huth 
484956a7811SThomas Huth         }
485956a7811SThomas Huth         if (value & SCSICSR_DMADIR) {
486956a7811SThomas Huth             DPRINTF("SCSICSR DMAdir\n");
487956a7811SThomas Huth         }
488956a7811SThomas Huth         if (value & SCSICSR_CPUDMA) {
489956a7811SThomas Huth             DPRINTF("SCSICSR CPUDMA\n");
490956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_dma); */
491956a7811SThomas Huth 
492956a7811SThomas Huth             s->int_status |= 0x4000000;
493956a7811SThomas Huth         } else {
494956a7811SThomas Huth             s->int_status &= ~(0x4000000);
495956a7811SThomas Huth         }
496956a7811SThomas Huth         if (value & SCSICSR_INTMASK) {
497956a7811SThomas Huth             DPRINTF("SCSICSR INTMASK\n");
498956a7811SThomas Huth             /*
499956a7811SThomas Huth              * int_mask &= ~0x1000;
500956a7811SThomas Huth              * s->scsi_csr_1 |= value;
501956a7811SThomas Huth              * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
502956a7811SThomas Huth              * if (s->scsi_queued) {
503956a7811SThomas Huth              *     s->scsi_queued = 0;
504956a7811SThomas Huth              *     next_irq(s, NEXT_SCSI_I, level);
505956a7811SThomas Huth              * }
506956a7811SThomas Huth              */
507956a7811SThomas Huth         } else {
508956a7811SThomas Huth             /* int_mask |= 0x1000; */
509956a7811SThomas Huth         }
510956a7811SThomas Huth         if (value & 0x80) {
511956a7811SThomas Huth             /* int_mask |= 0x1000; */
512956a7811SThomas Huth             /* s->scsi_csr_1 |= 0x80; */
513956a7811SThomas Huth         }
514956a7811SThomas Huth         DPRINTF("SCSICSR Write: %x\n", value);
515956a7811SThomas Huth         /* s->scsi_csr_1 = value; */
516956a7811SThomas Huth         return;
517956a7811SThomas Huth     /* Hardware timer latch - not implemented yet */
518956a7811SThomas Huth     case 0x1a000:
519956a7811SThomas Huth     default:
520956a7811SThomas Huth         DPRINTF("BMAP Write B @ %x with %x\n", (unsigned int)addr, value);
521956a7811SThomas Huth     }
522956a7811SThomas Huth }
523956a7811SThomas Huth 
524956a7811SThomas Huth static void scr_writew(NeXTState *s, hwaddr addr, uint32_t value)
525956a7811SThomas Huth {
526956a7811SThomas Huth     DPRINTF("BMAP Write W @ %x with %x\n", (unsigned int)addr, value);
527956a7811SThomas Huth }
528956a7811SThomas Huth 
529956a7811SThomas Huth static void scr_writel(NeXTState *s, hwaddr addr, uint32_t value)
530956a7811SThomas Huth {
531956a7811SThomas Huth     DPRINTF("BMAP Write L @ %x with %x\n", (unsigned int)addr, value);
532956a7811SThomas Huth }
533956a7811SThomas Huth 
534956a7811SThomas Huth static uint64_t scr_readfn(void *opaque, hwaddr addr, unsigned size)
535956a7811SThomas Huth {
536956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
537956a7811SThomas Huth 
538956a7811SThomas Huth     switch (size) {
539956a7811SThomas Huth     case 1:
540956a7811SThomas Huth         return scr_readb(ns, addr);
541956a7811SThomas Huth     case 2:
542956a7811SThomas Huth         return scr_readw(ns, addr);
543956a7811SThomas Huth     case 4:
544956a7811SThomas Huth         return scr_readl(ns, addr);
545956a7811SThomas Huth     default:
546956a7811SThomas Huth         g_assert_not_reached();
547956a7811SThomas Huth     }
548956a7811SThomas Huth }
549956a7811SThomas Huth 
550956a7811SThomas Huth static void scr_writefn(void *opaque, hwaddr addr, uint64_t value,
551956a7811SThomas Huth                         unsigned size)
552956a7811SThomas Huth {
553956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
554956a7811SThomas Huth 
555956a7811SThomas Huth     switch (size) {
556956a7811SThomas Huth     case 1:
557956a7811SThomas Huth         scr_writeb(ns, addr, value);
558956a7811SThomas Huth         break;
559956a7811SThomas Huth     case 2:
560956a7811SThomas Huth         scr_writew(ns, addr, value);
561956a7811SThomas Huth         break;
562956a7811SThomas Huth     case 4:
563956a7811SThomas Huth         scr_writel(ns, addr, value);
564956a7811SThomas Huth         break;
565956a7811SThomas Huth     default:
566956a7811SThomas Huth         g_assert_not_reached();
567956a7811SThomas Huth     }
568956a7811SThomas Huth }
569956a7811SThomas Huth 
570956a7811SThomas Huth static const MemoryRegionOps scr_ops = {
571956a7811SThomas Huth     .read = scr_readfn,
572956a7811SThomas Huth     .write = scr_writefn,
573956a7811SThomas Huth     .valid.min_access_size = 1,
574956a7811SThomas Huth     .valid.max_access_size = 4,
575956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
576956a7811SThomas Huth };
577956a7811SThomas Huth 
578956a7811SThomas Huth #define NEXTDMA_SCSI(x)      (0x10 + x)
579956a7811SThomas Huth #define NEXTDMA_FD(x)        (0x10 + x)
580956a7811SThomas Huth #define NEXTDMA_ENTX(x)      (0x110 + x)
581956a7811SThomas Huth #define NEXTDMA_ENRX(x)      (0x150 + x)
582956a7811SThomas Huth #define NEXTDMA_CSR          0x0
583956a7811SThomas Huth #define NEXTDMA_NEXT         0x4000
584956a7811SThomas Huth #define NEXTDMA_LIMIT        0x4004
585956a7811SThomas Huth #define NEXTDMA_START        0x4008
586956a7811SThomas Huth #define NEXTDMA_STOP         0x400c
587956a7811SThomas Huth #define NEXTDMA_NEXT_INIT    0x4200
588956a7811SThomas Huth #define NEXTDMA_SIZE         0x4204
589956a7811SThomas Huth 
590956a7811SThomas Huth static void dma_writel(void *opaque, hwaddr addr, uint64_t value,
591956a7811SThomas Huth                        unsigned int size)
592956a7811SThomas Huth {
593956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
594956a7811SThomas Huth 
595956a7811SThomas Huth     switch (addr) {
596956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
597956a7811SThomas Huth         if (value & DMA_DEV2M) {
598956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_DEV2M;
599956a7811SThomas Huth         }
600956a7811SThomas Huth 
601956a7811SThomas Huth         if (value & DMA_SETENABLE) {
602956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
603956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_ENABLE;
604956a7811SThomas Huth         }
605956a7811SThomas Huth         if (value & DMA_SETSUPDATE) {
606956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_SUPDATE;
607956a7811SThomas Huth         }
608956a7811SThomas Huth         if (value & DMA_CLRCOMPLETE) {
609956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~DMA_COMPLETE;
610956a7811SThomas Huth         }
611956a7811SThomas Huth 
612956a7811SThomas Huth         if (value & DMA_RESET) {
613956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
614956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
615956a7811SThomas Huth         }
616956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
617956a7811SThomas Huth         break;
618956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
619956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].next_initbuf = value;
620956a7811SThomas Huth         break;
621956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
622956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].next = value;
623956a7811SThomas Huth         break;
624956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
625956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].limit = value;
626956a7811SThomas Huth         break;
627956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
628956a7811SThomas Huth         if (value & DMA_DEV2M) {
629956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_DEV2M;
630956a7811SThomas Huth         }
631956a7811SThomas Huth         if (value & DMA_SETENABLE) {
632956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
633956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_ENABLE;
634956a7811SThomas Huth         }
635956a7811SThomas Huth         if (value & DMA_SETSUPDATE) {
636956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_SUPDATE;
637956a7811SThomas Huth         }
638956a7811SThomas Huth         if (value & DMA_CLRCOMPLETE) {
639956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~DMA_COMPLETE;
640956a7811SThomas Huth         }
641956a7811SThomas Huth 
642956a7811SThomas Huth         if (value & DMA_RESET) {
643956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
644956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
645956a7811SThomas Huth             /* DPRINTF("SCSI DMA RESET\n"); */
646956a7811SThomas Huth         }
647956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
648956a7811SThomas Huth         break;
649956a7811SThomas Huth 
650956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
651956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].next = value;
652956a7811SThomas Huth         break;
653956a7811SThomas Huth 
654956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
655956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].limit = value;
656956a7811SThomas Huth         break;
657956a7811SThomas Huth 
658956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
659956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].start = value;
660956a7811SThomas Huth         break;
661956a7811SThomas Huth 
662956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
663956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].stop = value;
664956a7811SThomas Huth         break;
665956a7811SThomas Huth 
666956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
667956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].next_initbuf = value;
668956a7811SThomas Huth         break;
669956a7811SThomas Huth 
670956a7811SThomas Huth     default:
671956a7811SThomas Huth         DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)value);
672956a7811SThomas Huth     }
673956a7811SThomas Huth }
674956a7811SThomas Huth 
675956a7811SThomas Huth static uint64_t dma_readl(void *opaque, hwaddr addr, unsigned int size)
676956a7811SThomas Huth {
677956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
678956a7811SThomas Huth 
679956a7811SThomas Huth     switch (addr) {
680956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
681956a7811SThomas Huth         DPRINTF("SCSI DMA CSR READ\n");
682956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].csr;
683956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
684956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].csr;
685956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
686956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].next_initbuf;
687956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
688956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].next;
689956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
690956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].limit;
691956a7811SThomas Huth 
692956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
693956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].next;
694956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
695956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].next_initbuf;
696956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
697956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].limit;
698956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
699956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].start;
700956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
701956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].stop;
702956a7811SThomas Huth 
703956a7811SThomas Huth     default:
704956a7811SThomas Huth         DPRINTF("DMA read @ %x\n", (unsigned int)addr);
705956a7811SThomas Huth         return 0;
706956a7811SThomas Huth     }
707956a7811SThomas Huth 
708956a7811SThomas Huth     /*
709956a7811SThomas Huth      * once the csr's are done, subtract 0x3FEC from the addr, and that will
710956a7811SThomas Huth      * normalize the upper registers
711956a7811SThomas Huth      */
712956a7811SThomas Huth }
713956a7811SThomas Huth 
714956a7811SThomas Huth static const MemoryRegionOps dma_ops = {
715956a7811SThomas Huth     .read = dma_readl,
716956a7811SThomas Huth     .write = dma_writel,
717956a7811SThomas Huth     .impl.min_access_size = 4,
718956a7811SThomas Huth     .valid.min_access_size = 4,
719956a7811SThomas Huth     .valid.max_access_size = 4,
720956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
721956a7811SThomas Huth };
722956a7811SThomas Huth 
723956a7811SThomas Huth /*
724956a7811SThomas Huth  * TODO: set the shift numbers as values in the enum, so the first switch
725956a7811SThomas Huth  * will not be needed
726956a7811SThomas Huth  */
727956a7811SThomas Huth void next_irq(void *opaque, int number, int level)
728956a7811SThomas Huth {
729956a7811SThomas Huth     M68kCPU *cpu = opaque;
730956a7811SThomas Huth     int shift = 0;
731956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(qdev_get_machine());
732956a7811SThomas Huth 
733956a7811SThomas Huth     /* first switch sets interupt status */
734956a7811SThomas Huth     /* DPRINTF("IRQ %i\n",number); */
735956a7811SThomas Huth     switch (number) {
736956a7811SThomas Huth     /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
737956a7811SThomas Huth     case NEXT_FD_I:
7385012a894SPhilippe Mathieu-Daudé         shift = 7;
739956a7811SThomas Huth         break;
740956a7811SThomas Huth     case NEXT_KBD_I:
741956a7811SThomas Huth         shift = 3;
742956a7811SThomas Huth         break;
743956a7811SThomas Huth     case NEXT_PWR_I:
744956a7811SThomas Huth         shift = 2;
745956a7811SThomas Huth         break;
746956a7811SThomas Huth     case NEXT_ENRX_I:
747956a7811SThomas Huth         shift = 9;
748956a7811SThomas Huth         break;
749956a7811SThomas Huth     case NEXT_ENTX_I:
750956a7811SThomas Huth         shift = 10;
751956a7811SThomas Huth         break;
752956a7811SThomas Huth     case NEXT_SCSI_I:
753956a7811SThomas Huth         shift = 12;
754956a7811SThomas Huth         break;
755956a7811SThomas Huth     case NEXT_CLK_I:
756956a7811SThomas Huth         shift = 5;
757956a7811SThomas Huth         break;
758956a7811SThomas Huth 
759956a7811SThomas Huth     /* level 5 - scc (serial) */
760956a7811SThomas Huth     case NEXT_SCC_I:
761956a7811SThomas Huth         shift = 17;
762956a7811SThomas Huth         break;
763956a7811SThomas Huth 
764956a7811SThomas Huth     /* level 6 - audio etherrx/tx dma */
765956a7811SThomas Huth     case NEXT_ENTX_DMA_I:
766956a7811SThomas Huth         shift = 28;
767956a7811SThomas Huth         break;
768956a7811SThomas Huth     case NEXT_ENRX_DMA_I:
769956a7811SThomas Huth         shift = 27;
770956a7811SThomas Huth         break;
771956a7811SThomas Huth     case NEXT_SCSI_DMA_I:
772956a7811SThomas Huth         shift = 26;
773956a7811SThomas Huth         break;
774956a7811SThomas Huth     case NEXT_SND_I:
775956a7811SThomas Huth         shift = 23;
776956a7811SThomas Huth         break;
777956a7811SThomas Huth     case NEXT_SCC_DMA_I:
778956a7811SThomas Huth         shift = 21;
779956a7811SThomas Huth         break;
780956a7811SThomas Huth 
781956a7811SThomas Huth     }
782956a7811SThomas Huth     /*
783956a7811SThomas Huth      * this HAS to be wrong, the interrupt handlers in mach and together
784956a7811SThomas Huth      * int_status and int_mask and return if there is a hit
785956a7811SThomas Huth      */
786956a7811SThomas Huth     if (ns->int_mask & (1 << shift)) {
787956a7811SThomas Huth         DPRINTF("%x interrupt masked @ %x\n", 1 << shift, cpu->env.pc);
788956a7811SThomas Huth         /* return; */
789956a7811SThomas Huth     }
790956a7811SThomas Huth 
791956a7811SThomas Huth     /* second switch triggers the correct interrupt */
792956a7811SThomas Huth     if (level) {
793956a7811SThomas Huth         ns->int_status |= 1 << shift;
794956a7811SThomas Huth 
795956a7811SThomas Huth         switch (number) {
796956a7811SThomas Huth         /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
797956a7811SThomas Huth         case NEXT_FD_I:
798956a7811SThomas Huth         case NEXT_KBD_I:
799956a7811SThomas Huth         case NEXT_PWR_I:
800956a7811SThomas Huth         case NEXT_ENRX_I:
801956a7811SThomas Huth         case NEXT_ENTX_I:
802956a7811SThomas Huth         case NEXT_SCSI_I:
803956a7811SThomas Huth         case NEXT_CLK_I:
804956a7811SThomas Huth             m68k_set_irq_level(cpu, 3, 27);
805956a7811SThomas Huth             break;
806956a7811SThomas Huth 
807956a7811SThomas Huth         /* level 5 - scc (serial) */
808956a7811SThomas Huth         case NEXT_SCC_I:
809956a7811SThomas Huth             m68k_set_irq_level(cpu, 5, 29);
810956a7811SThomas Huth             break;
811956a7811SThomas Huth 
812956a7811SThomas Huth         /* level 6 - audio etherrx/tx dma */
813956a7811SThomas Huth         case NEXT_ENTX_DMA_I:
814956a7811SThomas Huth         case NEXT_ENRX_DMA_I:
815956a7811SThomas Huth         case NEXT_SCSI_DMA_I:
816956a7811SThomas Huth         case NEXT_SND_I:
817956a7811SThomas Huth         case NEXT_SCC_DMA_I:
818956a7811SThomas Huth             m68k_set_irq_level(cpu, 6, 30);
819956a7811SThomas Huth             break;
820956a7811SThomas Huth         }
821956a7811SThomas Huth     } else {
822956a7811SThomas Huth         ns->int_status &= ~(1 << shift);
823956a7811SThomas Huth         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
824956a7811SThomas Huth     }
825956a7811SThomas Huth }
826956a7811SThomas Huth 
827b17bed5bSThomas Huth static void next_serial_irq(void *opaque, int n, int level)
828b17bed5bSThomas Huth {
829b17bed5bSThomas Huth     /* DPRINTF("SCC IRQ NUM %i\n",n); */
830b17bed5bSThomas Huth     if (n) {
831b17bed5bSThomas Huth         next_irq(opaque, NEXT_SCC_DMA_I, level);
832b17bed5bSThomas Huth     } else {
833b17bed5bSThomas Huth         next_irq(opaque, NEXT_SCC_I, level);
834b17bed5bSThomas Huth     }
835b17bed5bSThomas Huth }
836b17bed5bSThomas Huth 
837b17bed5bSThomas Huth static void next_escc_init(M68kCPU *cpu)
838b17bed5bSThomas Huth {
839b17bed5bSThomas Huth     qemu_irq *ser_irq = qemu_allocate_irqs(next_serial_irq, cpu, 2);
840b17bed5bSThomas Huth     DeviceState *dev;
841b17bed5bSThomas Huth     SysBusDevice *s;
842b17bed5bSThomas Huth 
8433e80f690SMarkus Armbruster     dev = qdev_new(TYPE_ESCC);
844b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "disabled", 0);
845b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "frequency", 9600 * 384);
846b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "it_shift", 0);
847b17bed5bSThomas Huth     qdev_prop_set_bit(dev, "bit_swap", true);
848b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrB", serial_hd(1));
849b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrA", serial_hd(0));
850b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
851b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
852b17bed5bSThomas Huth 
853b17bed5bSThomas Huth     s = SYS_BUS_DEVICE(dev);
8543c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
855b17bed5bSThomas Huth     sysbus_connect_irq(s, 0, ser_irq[0]);
856b17bed5bSThomas Huth     sysbus_connect_irq(s, 1,  ser_irq[1]);
857b17bed5bSThomas Huth     sysbus_mmio_map(s, 0, 0x2118000);
858b17bed5bSThomas Huth }
859b17bed5bSThomas Huth 
860956a7811SThomas Huth static void next_cube_init(MachineState *machine)
861956a7811SThomas Huth {
862956a7811SThomas Huth     M68kCPU *cpu;
863956a7811SThomas Huth     CPUM68KState *env;
864956a7811SThomas Huth     MemoryRegion *rom = g_new(MemoryRegion, 1);
865956a7811SThomas Huth     MemoryRegion *mmiomem = g_new(MemoryRegion, 1);
866956a7811SThomas Huth     MemoryRegion *scrmem = g_new(MemoryRegion, 1);
867956a7811SThomas Huth     MemoryRegion *dmamem = g_new(MemoryRegion, 1);
868956a7811SThomas Huth     MemoryRegion *bmapm1 = g_new(MemoryRegion, 1);
869956a7811SThomas Huth     MemoryRegion *bmapm2 = g_new(MemoryRegion, 1);
870956a7811SThomas Huth     MemoryRegion *sysmem = get_system_memory();
871956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(machine);
872956a7811SThomas Huth     DeviceState *dev;
873956a7811SThomas Huth 
874956a7811SThomas Huth     /* Initialize the cpu core */
875956a7811SThomas Huth     cpu = M68K_CPU(cpu_create(machine->cpu_type));
876956a7811SThomas Huth     if (!cpu) {
877956a7811SThomas Huth         error_report("Unable to find m68k CPU definition");
878956a7811SThomas Huth         exit(1);
879956a7811SThomas Huth     }
880956a7811SThomas Huth     env = &cpu->env;
881956a7811SThomas Huth 
882956a7811SThomas Huth     /* Initialize CPU registers.  */
883956a7811SThomas Huth     env->vbr = 0;
884956a7811SThomas Huth     env->sr  = 0x2700;
885956a7811SThomas Huth 
886956a7811SThomas Huth     /* Set internal registers to initial values */
887956a7811SThomas Huth     /*     0x0000XX00 << vital bits */
888956a7811SThomas Huth     ns->scr1 = 0x00011102;
889956a7811SThomas Huth     ns->scr2 = 0x00ff0c80;
890cd4fc142SThomas Huth     ns->rtc.status = 0x90;
891956a7811SThomas Huth 
892956a7811SThomas Huth     /* Load RTC RAM - TODO: provide possibility to load contents from file */
893cd4fc142SThomas Huth     memcpy(ns->rtc.ram, rtc_ram2, 32);
894956a7811SThomas Huth 
895956a7811SThomas Huth     /* 64MB RAM starting at 0x04000000  */
89649b64ba9SIgor Mammedov     memory_region_add_subregion(sysmem, 0x04000000, machine->ram);
897956a7811SThomas Huth 
898956a7811SThomas Huth     /* Framebuffer */
8993e80f690SMarkus Armbruster     dev = qdev_new(TYPE_NEXTFB);
9003c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
901956a7811SThomas Huth     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0B000000);
902956a7811SThomas Huth 
903956a7811SThomas Huth     /* MMIO */
904956a7811SThomas Huth     memory_region_init_io(mmiomem, NULL, &mmio_ops, machine, "next.mmio",
905956a7811SThomas Huth                           0xD0000);
906956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02000000, mmiomem);
907956a7811SThomas Huth 
908956a7811SThomas Huth     /* BMAP memory */
909956a7811SThomas Huth     memory_region_init_ram_shared_nomigrate(bmapm1, NULL, "next.bmapmem", 64,
910956a7811SThomas Huth                                             true, &error_fatal);
911956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x020c0000, bmapm1);
912956a7811SThomas Huth     /* The Rev_2.5_v66.bin firmware accesses it at 0x820c0020, too */
913956a7811SThomas Huth     memory_region_init_alias(bmapm2, NULL, "next.bmapmem2", bmapm1, 0x0, 64);
914956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x820c0000, bmapm2);
915956a7811SThomas Huth 
916956a7811SThomas Huth     /* BMAP IO - acts as a catch-all for now */
917956a7811SThomas Huth     memory_region_init_io(scrmem, NULL, &scr_ops, machine, "next.scr",
918956a7811SThomas Huth                           0x20000);
919956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02100000, scrmem);
920956a7811SThomas Huth 
921956a7811SThomas Huth     /* KBD */
9223e80f690SMarkus Armbruster     dev = qdev_new(TYPE_NEXTKBD);
9233c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
924956a7811SThomas Huth     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000);
925956a7811SThomas Huth 
926956a7811SThomas Huth     /* Load ROM here */
927956a7811SThomas Huth     if (bios_name == NULL) {
928956a7811SThomas Huth         bios_name = ROM_FILE;
929956a7811SThomas Huth     }
930956a7811SThomas Huth     /* still not sure if the rom should also be mapped at 0x0*/
931956a7811SThomas Huth     memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal);
932956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x01000000, rom);
933956a7811SThomas Huth     if (load_image_targphys(bios_name, 0x01000000, 0x20000) < 8) {
934956a7811SThomas Huth         if (!qtest_enabled()) {
935956a7811SThomas Huth             error_report("Failed to load firmware '%s'.", bios_name);
936956a7811SThomas Huth         }
937956a7811SThomas Huth     } else {
938956a7811SThomas Huth         uint8_t *ptr;
939956a7811SThomas Huth         /* Initial PC is always at offset 4 in firmware binaries */
940956a7811SThomas Huth         ptr = rom_ptr(0x01000004, 4);
941956a7811SThomas Huth         g_assert(ptr != NULL);
942956a7811SThomas Huth         env->pc = ldl_p(ptr);
943956a7811SThomas Huth         if (env->pc >= 0x01020000) {
944956a7811SThomas Huth             error_report("'%s' does not seem to be a valid firmware image.",
945956a7811SThomas Huth                          bios_name);
946956a7811SThomas Huth             exit(1);
947956a7811SThomas Huth         }
948956a7811SThomas Huth     }
949956a7811SThomas Huth 
950956a7811SThomas Huth     /* Serial */
951b17bed5bSThomas Huth     next_escc_init(cpu);
952b17bed5bSThomas Huth 
953b17bed5bSThomas Huth     /* TODO: */
954956a7811SThomas Huth     /* Network */
955956a7811SThomas Huth     /* SCSI */
956956a7811SThomas Huth 
957956a7811SThomas Huth     /* DMA */
958956a7811SThomas Huth     memory_region_init_io(dmamem, NULL, &dma_ops, machine, "next.dma", 0x5000);
959956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02000000, dmamem);
960956a7811SThomas Huth }
961956a7811SThomas Huth 
962956a7811SThomas Huth static void next_machine_class_init(ObjectClass *oc, void *data)
963956a7811SThomas Huth {
964956a7811SThomas Huth     MachineClass *mc = MACHINE_CLASS(oc);
965956a7811SThomas Huth 
966956a7811SThomas Huth     mc->desc = "NeXT Cube";
967956a7811SThomas Huth     mc->init = next_cube_init;
968956a7811SThomas Huth     mc->default_ram_size = RAM_SIZE;
96949b64ba9SIgor Mammedov     mc->default_ram_id = "next.ram";
970956a7811SThomas Huth     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
971956a7811SThomas Huth }
972956a7811SThomas Huth 
973956a7811SThomas Huth static const TypeInfo next_typeinfo = {
974956a7811SThomas Huth     .name = TYPE_NEXT_MACHINE,
975956a7811SThomas Huth     .parent = TYPE_MACHINE,
976956a7811SThomas Huth     .class_init = next_machine_class_init,
977956a7811SThomas Huth     .instance_size = sizeof(NeXTState),
978956a7811SThomas Huth };
979956a7811SThomas Huth 
980956a7811SThomas Huth static void next_register_type(void)
981956a7811SThomas Huth {
982956a7811SThomas Huth     type_register_static(&next_typeinfo);
983956a7811SThomas Huth }
984956a7811SThomas Huth 
985956a7811SThomas Huth type_init(next_register_type)
986