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