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