xref: /qemu/hw/m68k/next-cube.c (revision 660bef33)
1956a7811SThomas Huth /*
2956a7811SThomas Huth  * NeXT Cube System Driver
3956a7811SThomas Huth  *
4956a7811SThomas Huth  * Copyright (c) 2011 Bryce Lanham
5956a7811SThomas Huth  *
6956a7811SThomas Huth  * This code is free software; you can redistribute it and/or modify
7956a7811SThomas Huth  * it under the terms of the GNU General Public License as published
8956a7811SThomas Huth  * by the Free Software Foundation; either version 2 of the License,
9956a7811SThomas Huth  * or (at your option) any later version.
10956a7811SThomas Huth  */
11956a7811SThomas Huth 
12956a7811SThomas Huth #include "qemu/osdep.h"
13b17bed5bSThomas Huth #include "cpu.h"
14956a7811SThomas Huth #include "exec/hwaddr.h"
15956a7811SThomas Huth #include "exec/address-spaces.h"
16956a7811SThomas Huth #include "sysemu/sysemu.h"
17956a7811SThomas Huth #include "sysemu/qtest.h"
18b17bed5bSThomas Huth #include "hw/irq.h"
19956a7811SThomas Huth #include "hw/m68k/next-cube.h"
20956a7811SThomas Huth #include "hw/boards.h"
21956a7811SThomas Huth #include "hw/loader.h"
22956a7811SThomas Huth #include "hw/scsi/esp.h"
23956a7811SThomas Huth #include "hw/sysbus.h"
24db1015e9SEduardo Habkost #include "qom/object.h"
25956a7811SThomas Huth #include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */
26956a7811SThomas Huth #include "hw/block/fdc.h"
27b17bed5bSThomas Huth #include "hw/qdev-properties.h"
28956a7811SThomas Huth #include "qapi/error.h"
29956a7811SThomas Huth #include "ui/console.h"
30956a7811SThomas Huth #include "target/m68k/cpu.h"
31956a7811SThomas Huth 
32956a7811SThomas Huth /* #define DEBUG_NEXT */
33956a7811SThomas Huth #ifdef DEBUG_NEXT
34956a7811SThomas Huth #define DPRINTF(fmt, ...) \
35956a7811SThomas Huth     do { printf("NeXT: " fmt , ## __VA_ARGS__); } while (0)
36956a7811SThomas Huth #else
37956a7811SThomas Huth #define DPRINTF(fmt, ...) do { } while (0)
38956a7811SThomas Huth #endif
39956a7811SThomas Huth 
40956a7811SThomas Huth #define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube")
418063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(NeXTState, NEXT_MACHINE)
42956a7811SThomas Huth 
43956a7811SThomas Huth #define ENTRY       0x0100001e
44956a7811SThomas Huth #define RAM_SIZE    0x4000000
45956a7811SThomas Huth #define ROM_FILE    "Rev_2.5_v66.bin"
46956a7811SThomas Huth 
47956a7811SThomas Huth typedef struct next_dma {
48956a7811SThomas Huth     uint32_t csr;
49956a7811SThomas Huth 
50956a7811SThomas Huth     uint32_t saved_next;
51956a7811SThomas Huth     uint32_t saved_limit;
52956a7811SThomas Huth     uint32_t saved_start;
53956a7811SThomas Huth     uint32_t saved_stop;
54956a7811SThomas Huth 
55956a7811SThomas Huth     uint32_t next;
56956a7811SThomas Huth     uint32_t limit;
57956a7811SThomas Huth     uint32_t start;
58956a7811SThomas Huth     uint32_t stop;
59956a7811SThomas Huth 
60956a7811SThomas Huth     uint32_t next_initbuf;
61956a7811SThomas Huth     uint32_t size;
62956a7811SThomas Huth } next_dma;
63956a7811SThomas Huth 
64cd4fc142SThomas Huth typedef struct NextRtc {
65cd4fc142SThomas Huth     uint8_t ram[32];
66cd4fc142SThomas Huth     uint8_t command;
67cd4fc142SThomas Huth     uint8_t value;
68cd4fc142SThomas Huth     uint8_t status;
69cd4fc142SThomas Huth     uint8_t control;
70cd4fc142SThomas Huth     uint8_t retval;
71cd4fc142SThomas Huth } NextRtc;
72cd4fc142SThomas Huth 
73db1015e9SEduardo Habkost struct NeXTState {
74956a7811SThomas Huth     MachineState parent;
75956a7811SThomas Huth 
76956a7811SThomas Huth     uint32_t int_mask;
77956a7811SThomas Huth     uint32_t int_status;
78956a7811SThomas Huth 
79956a7811SThomas Huth     uint8_t scsi_csr_1;
80956a7811SThomas Huth     uint8_t scsi_csr_2;
81956a7811SThomas Huth     next_dma dma[10];
82956a7811SThomas Huth     qemu_irq *scsi_irq;
83956a7811SThomas Huth     qemu_irq scsi_dma;
84956a7811SThomas Huth     qemu_irq scsi_reset;
85956a7811SThomas Huth     qemu_irq *fd_irq;
86956a7811SThomas Huth 
87956a7811SThomas Huth     uint32_t scr1;
88956a7811SThomas Huth     uint32_t scr2;
89956a7811SThomas Huth 
90cd4fc142SThomas Huth     NextRtc rtc;
91db1015e9SEduardo Habkost };
92956a7811SThomas Huth 
93*660bef33SPeter Maydell #define TYPE_NEXT_PC "next-pc"
94*660bef33SPeter Maydell OBJECT_DECLARE_SIMPLE_TYPE(NeXTPC, NEXT_PC)
95*660bef33SPeter Maydell 
96*660bef33SPeter Maydell /* NeXT Peripheral Controller */
97*660bef33SPeter Maydell struct NeXTPC {
98*660bef33SPeter Maydell     SysBusDevice parent_obj;
99*660bef33SPeter Maydell 
100*660bef33SPeter Maydell     /* Temporary until all functionality has been moved into this device */
101*660bef33SPeter Maydell     NeXTState *ns;
102*660bef33SPeter Maydell };
103*660bef33SPeter Maydell 
104956a7811SThomas Huth /* Thanks to NeXT forums for this */
105956a7811SThomas Huth /*
106956a7811SThomas Huth static const uint8_t rtc_ram3[32] = {
107956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
108956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x7B, 0x00,
109956a7811SThomas Huth     0x00, 0x00, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x00,
110956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x13
111956a7811SThomas Huth };
112956a7811SThomas Huth */
113956a7811SThomas Huth static const uint8_t rtc_ram2[32] = {
114956a7811SThomas Huth     0x94, 0x0f, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00,
115956a7811SThomas Huth     0x00, 0x00, 0xfb, 0x6d, 0x00, 0x00, 0x4b, 0x00,
116956a7811SThomas Huth     0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
117956a7811SThomas Huth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x7e,
118956a7811SThomas Huth };
119956a7811SThomas Huth 
120956a7811SThomas Huth #define SCR2_RTCLK 0x2
121956a7811SThomas Huth #define SCR2_RTDATA 0x4
122956a7811SThomas Huth #define SCR2_TOBCD(x) (((x / 10) << 4) + (x % 10))
123956a7811SThomas Huth 
124956a7811SThomas Huth static void nextscr2_write(NeXTState *s, uint32_t val, int size)
125956a7811SThomas Huth {
126956a7811SThomas Huth     static int led;
127956a7811SThomas Huth     static int phase;
128956a7811SThomas Huth     static uint8_t old_scr2;
129956a7811SThomas Huth     uint8_t scr2_2;
130cd4fc142SThomas Huth     NextRtc *rtc = &s->rtc;
131956a7811SThomas Huth 
132956a7811SThomas Huth     if (size == 4) {
133956a7811SThomas Huth         scr2_2 = (val >> 8) & 0xFF;
134956a7811SThomas Huth     } else {
135956a7811SThomas Huth         scr2_2 = val & 0xFF;
136956a7811SThomas Huth     }
137956a7811SThomas Huth 
138956a7811SThomas Huth     if (val & 0x1) {
139956a7811SThomas Huth         DPRINTF("fault!\n");
140956a7811SThomas Huth         led++;
141956a7811SThomas Huth         if (led == 10) {
142956a7811SThomas Huth             DPRINTF("LED flashing, possible fault!\n");
143956a7811SThomas Huth             led = 0;
144956a7811SThomas Huth         }
145956a7811SThomas Huth     }
146956a7811SThomas Huth 
147956a7811SThomas Huth     if (scr2_2 & 0x1) {
148956a7811SThomas Huth         /* DPRINTF("RTC %x phase %i\n", scr2_2, phase); */
149956a7811SThomas Huth         if (phase == -1) {
150956a7811SThomas Huth             phase = 0;
151956a7811SThomas Huth         }
152956a7811SThomas Huth         /* If we are in going down clock... do something */
153956a7811SThomas Huth         if (((old_scr2 & SCR2_RTCLK) != (scr2_2 & SCR2_RTCLK)) &&
154956a7811SThomas Huth                 ((scr2_2 & SCR2_RTCLK) == 0)) {
155956a7811SThomas Huth             if (phase < 8) {
156cd4fc142SThomas Huth                 rtc->command = (rtc->command << 1) |
157956a7811SThomas Huth                                ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
158956a7811SThomas Huth             }
159956a7811SThomas Huth             if (phase >= 8 && phase < 16) {
160cd4fc142SThomas Huth                 rtc->value = (rtc->value << 1) |
161cd4fc142SThomas Huth                              ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
162956a7811SThomas Huth 
163956a7811SThomas Huth                 /* if we read RAM register, output RT_DATA bit */
164cd4fc142SThomas Huth                 if (rtc->command <= 0x1F) {
165956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
166cd4fc142SThomas Huth                     if (rtc->ram[rtc->command] & (0x80 >> (phase - 8))) {
167956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
168956a7811SThomas Huth                     }
169956a7811SThomas Huth 
170cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
171956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
172956a7811SThomas Huth                 }
173956a7811SThomas Huth                 /* read the status 0x30 */
174cd4fc142SThomas Huth                 if (rtc->command == 0x30) {
175956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
176956a7811SThomas Huth                     /* for now status = 0x98 (new rtc + FTU) */
177cd4fc142SThomas Huth                     if (rtc->status & (0x80 >> (phase - 8))) {
178956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
179956a7811SThomas Huth                     }
180956a7811SThomas Huth 
181cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
182956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
183956a7811SThomas Huth                 }
184956a7811SThomas Huth                 /* read the status 0x31 */
185cd4fc142SThomas Huth                 if (rtc->command == 0x31) {
186956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
187cd4fc142SThomas Huth                     if (rtc->control & (0x80 >> (phase - 8))) {
188956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
189956a7811SThomas Huth                     }
190cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
191956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
192956a7811SThomas Huth                 }
193956a7811SThomas Huth 
194cd4fc142SThomas Huth                 if ((rtc->command >= 0x20) && (rtc->command <= 0x2F)) {
195956a7811SThomas Huth                     scr2_2 = scr2_2 & (~SCR2_RTDATA);
196956a7811SThomas Huth                     /* for now 0x00 */
197956a7811SThomas Huth                     time_t time_h = time(NULL);
198956a7811SThomas Huth                     struct tm *info = localtime(&time_h);
199956a7811SThomas Huth                     int ret = 0;
200956a7811SThomas Huth 
201cd4fc142SThomas Huth                     switch (rtc->command) {
202956a7811SThomas Huth                     case 0x20:
203956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_sec);
204956a7811SThomas Huth                         break;
205956a7811SThomas Huth                     case 0x21:
206956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_min);
207956a7811SThomas Huth                         break;
208956a7811SThomas Huth                     case 0x22:
209956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_hour);
210956a7811SThomas Huth                         break;
211956a7811SThomas Huth                     case 0x24:
212956a7811SThomas Huth                         ret = SCR2_TOBCD(info->tm_mday);
213956a7811SThomas Huth                         break;
214956a7811SThomas Huth                     case 0x25:
215956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_mon + 1));
216956a7811SThomas Huth                         break;
217956a7811SThomas Huth                     case 0x26:
218956a7811SThomas Huth                         ret = SCR2_TOBCD((info->tm_year - 100));
219956a7811SThomas Huth                         break;
220956a7811SThomas Huth 
221956a7811SThomas Huth                     }
222956a7811SThomas Huth 
223956a7811SThomas Huth                     if (ret & (0x80 >> (phase - 8))) {
224956a7811SThomas Huth                         scr2_2 |= SCR2_RTDATA;
225956a7811SThomas Huth                     }
226cd4fc142SThomas Huth                     rtc->retval = (rtc->retval << 1) |
227956a7811SThomas Huth                                   ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
228956a7811SThomas Huth                 }
229956a7811SThomas Huth 
230956a7811SThomas Huth             }
231956a7811SThomas Huth 
232956a7811SThomas Huth             phase++;
233956a7811SThomas Huth             if (phase == 16) {
234cd4fc142SThomas Huth                 if (rtc->command >= 0x80 && rtc->command <= 0x9F) {
235cd4fc142SThomas Huth                     rtc->ram[rtc->command - 0x80] = rtc->value;
236956a7811SThomas Huth                 }
237956a7811SThomas Huth                 /* write to x30 register */
238cd4fc142SThomas Huth                 if (rtc->command == 0xB1) {
239956a7811SThomas Huth                     /* clear FTU */
240cd4fc142SThomas Huth                     if (rtc->value & 0x04) {
241cd4fc142SThomas Huth                         rtc->status = rtc->status & (~0x18);
242956a7811SThomas Huth                         s->int_status = s->int_status & (~0x04);
243956a7811SThomas Huth                     }
244956a7811SThomas Huth                 }
245956a7811SThomas Huth             }
246956a7811SThomas Huth         }
247956a7811SThomas Huth     } else {
248956a7811SThomas Huth         /* else end or abort */
249956a7811SThomas Huth         phase = -1;
250cd4fc142SThomas Huth         rtc->command = 0;
251cd4fc142SThomas Huth         rtc->value = 0;
252956a7811SThomas Huth     }
253956a7811SThomas Huth     s->scr2 = val & 0xFFFF00FF;
254956a7811SThomas Huth     s->scr2 |= scr2_2 << 8;
255956a7811SThomas Huth     old_scr2 = scr2_2;
256956a7811SThomas Huth }
257956a7811SThomas Huth 
258956a7811SThomas Huth static uint32_t mmio_readb(NeXTState *s, hwaddr addr)
259956a7811SThomas Huth {
260956a7811SThomas Huth     switch (addr) {
261956a7811SThomas Huth     case 0xc000:
262956a7811SThomas Huth         return (s->scr1 >> 24) & 0xFF;
263956a7811SThomas Huth     case 0xc001:
264956a7811SThomas Huth         return (s->scr1 >> 16) & 0xFF;
265956a7811SThomas Huth     case 0xc002:
266956a7811SThomas Huth         return (s->scr1 >> 8)  & 0xFF;
267956a7811SThomas Huth     case 0xc003:
268956a7811SThomas Huth         return (s->scr1 >> 0)  & 0xFF;
269956a7811SThomas Huth 
270956a7811SThomas Huth     case 0xd000:
271956a7811SThomas Huth         return (s->scr2 >> 24) & 0xFF;
272956a7811SThomas Huth     case 0xd001:
273956a7811SThomas Huth         return (s->scr2 >> 16) & 0xFF;
274956a7811SThomas Huth     case 0xd002:
275956a7811SThomas Huth         return (s->scr2 >> 8)  & 0xFF;
276956a7811SThomas Huth     case 0xd003:
277956a7811SThomas Huth         return (s->scr2 >> 0)  & 0xFF;
278956a7811SThomas Huth     case 0x14020:
279956a7811SThomas Huth         DPRINTF("MMIO Read 0x4020\n");
280956a7811SThomas Huth         return 0x7f;
281956a7811SThomas Huth 
282956a7811SThomas Huth     default:
283956a7811SThomas Huth         DPRINTF("MMIO Read B @ %"HWADDR_PRIx"\n", addr);
284956a7811SThomas Huth         return 0x0;
285956a7811SThomas Huth     }
286956a7811SThomas Huth }
287956a7811SThomas Huth 
288956a7811SThomas Huth static uint32_t mmio_readw(NeXTState *s, hwaddr addr)
289956a7811SThomas Huth {
290956a7811SThomas Huth     switch (addr) {
291956a7811SThomas Huth     default:
292956a7811SThomas Huth         DPRINTF("MMIO Read W @ %"HWADDR_PRIx"\n", addr);
293956a7811SThomas Huth         return 0x0;
294956a7811SThomas Huth     }
295956a7811SThomas Huth }
296956a7811SThomas Huth 
297956a7811SThomas Huth static uint32_t mmio_readl(NeXTState *s, hwaddr addr)
298956a7811SThomas Huth {
299956a7811SThomas Huth     switch (addr) {
300956a7811SThomas Huth     case 0x7000:
301956a7811SThomas Huth         /* DPRINTF("Read INT status: %x\n", s->int_status); */
302956a7811SThomas Huth         return s->int_status;
303956a7811SThomas Huth 
304956a7811SThomas Huth     case 0x7800:
305956a7811SThomas Huth         DPRINTF("MMIO Read INT mask: %x\n", s->int_mask);
306956a7811SThomas Huth         return s->int_mask;
307956a7811SThomas Huth 
308956a7811SThomas Huth     case 0xc000:
309956a7811SThomas Huth         return s->scr1;
310956a7811SThomas Huth 
311956a7811SThomas Huth     case 0xd000:
312956a7811SThomas Huth         return s->scr2;
313956a7811SThomas Huth 
314956a7811SThomas Huth     default:
315956a7811SThomas Huth         DPRINTF("MMIO Read L @ %"HWADDR_PRIx"\n", addr);
316956a7811SThomas Huth         return 0x0;
317956a7811SThomas Huth     }
318956a7811SThomas Huth }
319956a7811SThomas Huth 
320956a7811SThomas Huth static void mmio_writeb(NeXTState *s, hwaddr addr, uint32_t val)
321956a7811SThomas Huth {
322956a7811SThomas Huth     switch (addr) {
323956a7811SThomas Huth     case 0xd003:
324956a7811SThomas Huth         nextscr2_write(s, val, 1);
325956a7811SThomas Huth         break;
326956a7811SThomas Huth     default:
327956a7811SThomas Huth         DPRINTF("MMIO Write B @ %x with %x\n", (unsigned int)addr, val);
328956a7811SThomas Huth     }
329956a7811SThomas Huth 
330956a7811SThomas Huth }
331956a7811SThomas Huth 
332956a7811SThomas Huth static void mmio_writew(NeXTState *s, hwaddr addr, uint32_t val)
333956a7811SThomas Huth {
334956a7811SThomas Huth     DPRINTF("MMIO Write W\n");
335956a7811SThomas Huth }
336956a7811SThomas Huth 
337956a7811SThomas Huth static void mmio_writel(NeXTState *s, hwaddr addr, uint32_t val)
338956a7811SThomas Huth {
339956a7811SThomas Huth     switch (addr) {
340956a7811SThomas Huth     case 0x7000:
341956a7811SThomas Huth         DPRINTF("INT Status old: %x new: %x\n", s->int_status, val);
342956a7811SThomas Huth         s->int_status = val;
343956a7811SThomas Huth         break;
344956a7811SThomas Huth     case 0x7800:
345956a7811SThomas Huth         DPRINTF("INT Mask old: %x new: %x\n", s->int_mask, val);
346956a7811SThomas Huth         s->int_mask  = val;
347956a7811SThomas Huth         break;
348956a7811SThomas Huth     case 0xc000:
349956a7811SThomas Huth         DPRINTF("SCR1 Write: %x\n", val);
350956a7811SThomas Huth         break;
351956a7811SThomas Huth     case 0xd000:
352956a7811SThomas Huth         nextscr2_write(s, val, 4);
353956a7811SThomas Huth         break;
354956a7811SThomas Huth 
355956a7811SThomas Huth     default:
356956a7811SThomas Huth         DPRINTF("MMIO Write l @ %x with %x\n", (unsigned int)addr, val);
357956a7811SThomas Huth     }
358956a7811SThomas Huth }
359956a7811SThomas Huth 
360956a7811SThomas Huth static uint64_t mmio_readfn(void *opaque, hwaddr addr, unsigned size)
361956a7811SThomas Huth {
362956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
363956a7811SThomas Huth 
364956a7811SThomas Huth     switch (size) {
365956a7811SThomas Huth     case 1:
366956a7811SThomas Huth         return mmio_readb(ns, addr);
367956a7811SThomas Huth     case 2:
368956a7811SThomas Huth         return mmio_readw(ns, addr);
369956a7811SThomas Huth     case 4:
370956a7811SThomas Huth         return mmio_readl(ns, addr);
371956a7811SThomas Huth     default:
372956a7811SThomas Huth         g_assert_not_reached();
373956a7811SThomas Huth     }
374956a7811SThomas Huth }
375956a7811SThomas Huth 
376956a7811SThomas Huth static void mmio_writefn(void *opaque, hwaddr addr, uint64_t value,
377956a7811SThomas Huth                          unsigned size)
378956a7811SThomas Huth {
379956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
380956a7811SThomas Huth 
381956a7811SThomas Huth     switch (size) {
382956a7811SThomas Huth     case 1:
383956a7811SThomas Huth         mmio_writeb(ns, addr, value);
384956a7811SThomas Huth         break;
385956a7811SThomas Huth     case 2:
386956a7811SThomas Huth         mmio_writew(ns, addr, value);
387956a7811SThomas Huth         break;
388956a7811SThomas Huth     case 4:
389956a7811SThomas Huth         mmio_writel(ns, addr, value);
390956a7811SThomas Huth         break;
391956a7811SThomas Huth     default:
392956a7811SThomas Huth         g_assert_not_reached();
393956a7811SThomas Huth     }
394956a7811SThomas Huth }
395956a7811SThomas Huth 
396956a7811SThomas Huth static const MemoryRegionOps mmio_ops = {
397956a7811SThomas Huth     .read = mmio_readfn,
398956a7811SThomas Huth     .write = mmio_writefn,
399956a7811SThomas Huth     .valid.min_access_size = 1,
400956a7811SThomas Huth     .valid.max_access_size = 4,
401956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
402956a7811SThomas Huth };
403956a7811SThomas Huth 
404956a7811SThomas Huth static uint32_t scr_readb(NeXTState *s, hwaddr addr)
405956a7811SThomas Huth {
406956a7811SThomas Huth     switch (addr) {
407956a7811SThomas Huth     case 0x14108:
408956a7811SThomas Huth         DPRINTF("FD read @ %x\n", (unsigned int)addr);
409956a7811SThomas Huth         return 0x40 | 0x04 | 0x2 | 0x1;
410956a7811SThomas Huth     case 0x14020:
411956a7811SThomas Huth         DPRINTF("SCSI 4020  STATUS READ %X\n", s->scsi_csr_1);
412956a7811SThomas Huth         return s->scsi_csr_1;
413956a7811SThomas Huth 
414956a7811SThomas Huth     case 0x14021:
415956a7811SThomas Huth         DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
416956a7811SThomas Huth         return 0x40;
417956a7811SThomas Huth 
418956a7811SThomas Huth     /*
419956a7811SThomas Huth      * These 4 registers are the hardware timer, not sure which register
420956a7811SThomas Huth      * is the latch instead of data, but no problems so far
421956a7811SThomas Huth      */
422956a7811SThomas Huth     case 0x1a000:
423956a7811SThomas Huth         return 0xff & (clock() >> 24);
424956a7811SThomas Huth     case 0x1a001:
425956a7811SThomas Huth         return 0xff & (clock() >> 16);
426956a7811SThomas Huth     case 0x1a002:
427956a7811SThomas Huth         return 0xff & (clock() >> 8);
428956a7811SThomas Huth     case 0x1a003:
429956a7811SThomas Huth         /* Hack: We need to have this change consistently to make it work */
430956a7811SThomas Huth         return 0xFF & clock();
431956a7811SThomas Huth 
432956a7811SThomas Huth     default:
433956a7811SThomas Huth         DPRINTF("BMAP Read B @ %x\n", (unsigned int)addr);
434956a7811SThomas Huth         return 0;
435956a7811SThomas Huth     }
436956a7811SThomas Huth }
437956a7811SThomas Huth 
438956a7811SThomas Huth static uint32_t scr_readw(NeXTState *s, hwaddr addr)
439956a7811SThomas Huth {
440956a7811SThomas Huth     DPRINTF("BMAP Read W @ %x\n", (unsigned int)addr);
441956a7811SThomas Huth     return 0;
442956a7811SThomas Huth }
443956a7811SThomas Huth 
444956a7811SThomas Huth static uint32_t scr_readl(NeXTState *s, hwaddr addr)
445956a7811SThomas Huth {
446956a7811SThomas Huth     DPRINTF("BMAP Read L @ %x\n", (unsigned int)addr);
447956a7811SThomas Huth     return 0;
448956a7811SThomas Huth }
449956a7811SThomas Huth 
450956a7811SThomas Huth #define SCSICSR_ENABLE  0x01
451956a7811SThomas Huth #define SCSICSR_RESET   0x02  /* reset scsi dma */
452956a7811SThomas Huth #define SCSICSR_FIFOFL  0x04
453956a7811SThomas Huth #define SCSICSR_DMADIR  0x08  /* if set, scsi to mem */
454956a7811SThomas Huth #define SCSICSR_CPUDMA  0x10  /* if set, dma enabled */
455956a7811SThomas Huth #define SCSICSR_INTMASK 0x20  /* if set, interrupt enabled */
456956a7811SThomas Huth 
457956a7811SThomas Huth static void scr_writeb(NeXTState *s, hwaddr addr, uint32_t value)
458956a7811SThomas Huth {
459956a7811SThomas Huth     switch (addr) {
460956a7811SThomas Huth     case 0x14108:
461956a7811SThomas Huth         DPRINTF("FDCSR Write: %x\n", value);
462956a7811SThomas Huth 
463956a7811SThomas Huth         if (value == 0x0) {
464956a7811SThomas Huth             /* qemu_irq_raise(s->fd_irq[0]); */
465956a7811SThomas Huth         }
466956a7811SThomas Huth         break;
467956a7811SThomas Huth     case 0x14020: /* SCSI Control Register */
468956a7811SThomas Huth         if (value & SCSICSR_FIFOFL) {
469956a7811SThomas Huth             DPRINTF("SCSICSR FIFO Flush\n");
470956a7811SThomas Huth             /* will have to add another irq to the esp if this is needed */
471956a7811SThomas Huth             /* esp_puflush_fifo(esp_g); */
472956a7811SThomas Huth             /* qemu_irq_pulse(s->scsi_dma); */
473956a7811SThomas Huth         }
474956a7811SThomas Huth 
475956a7811SThomas Huth         if (value & SCSICSR_ENABLE) {
476956a7811SThomas Huth             DPRINTF("SCSICSR Enable\n");
477956a7811SThomas Huth             /*
478956a7811SThomas Huth              * qemu_irq_raise(s->scsi_dma);
479956a7811SThomas Huth              * s->scsi_csr_1 = 0xc0;
480956a7811SThomas Huth              * s->scsi_csr_1 |= 0x1;
481956a7811SThomas Huth              * qemu_irq_pulse(s->scsi_dma);
482956a7811SThomas Huth              */
483956a7811SThomas Huth         }
484956a7811SThomas Huth         /*
485956a7811SThomas Huth          * else
486956a7811SThomas Huth          *     s->scsi_csr_1 &= ~SCSICSR_ENABLE;
487956a7811SThomas Huth          */
488956a7811SThomas Huth 
489956a7811SThomas Huth         if (value & SCSICSR_RESET) {
490956a7811SThomas Huth             DPRINTF("SCSICSR Reset\n");
491956a7811SThomas Huth             /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
492956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_reset); */
493956a7811SThomas Huth             /* s->scsi_csr_1 &= ~(SCSICSR_INTMASK |0x80|0x1); */
494956a7811SThomas Huth 
495956a7811SThomas Huth         }
496956a7811SThomas Huth         if (value & SCSICSR_DMADIR) {
497956a7811SThomas Huth             DPRINTF("SCSICSR DMAdir\n");
498956a7811SThomas Huth         }
499956a7811SThomas Huth         if (value & SCSICSR_CPUDMA) {
500956a7811SThomas Huth             DPRINTF("SCSICSR CPUDMA\n");
501956a7811SThomas Huth             /* qemu_irq_raise(s->scsi_dma); */
502956a7811SThomas Huth 
503956a7811SThomas Huth             s->int_status |= 0x4000000;
504956a7811SThomas Huth         } else {
505956a7811SThomas Huth             s->int_status &= ~(0x4000000);
506956a7811SThomas Huth         }
507956a7811SThomas Huth         if (value & SCSICSR_INTMASK) {
508956a7811SThomas Huth             DPRINTF("SCSICSR INTMASK\n");
509956a7811SThomas Huth             /*
510956a7811SThomas Huth              * int_mask &= ~0x1000;
511956a7811SThomas Huth              * s->scsi_csr_1 |= value;
512956a7811SThomas Huth              * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
513956a7811SThomas Huth              * if (s->scsi_queued) {
514956a7811SThomas Huth              *     s->scsi_queued = 0;
515956a7811SThomas Huth              *     next_irq(s, NEXT_SCSI_I, level);
516956a7811SThomas Huth              * }
517956a7811SThomas Huth              */
518956a7811SThomas Huth         } else {
519956a7811SThomas Huth             /* int_mask |= 0x1000; */
520956a7811SThomas Huth         }
521956a7811SThomas Huth         if (value & 0x80) {
522956a7811SThomas Huth             /* int_mask |= 0x1000; */
523956a7811SThomas Huth             /* s->scsi_csr_1 |= 0x80; */
524956a7811SThomas Huth         }
525956a7811SThomas Huth         DPRINTF("SCSICSR Write: %x\n", value);
526956a7811SThomas Huth         /* s->scsi_csr_1 = value; */
527956a7811SThomas Huth         return;
528956a7811SThomas Huth     /* Hardware timer latch - not implemented yet */
529956a7811SThomas Huth     case 0x1a000:
530956a7811SThomas Huth     default:
531956a7811SThomas Huth         DPRINTF("BMAP Write B @ %x with %x\n", (unsigned int)addr, value);
532956a7811SThomas Huth     }
533956a7811SThomas Huth }
534956a7811SThomas Huth 
535956a7811SThomas Huth static void scr_writew(NeXTState *s, hwaddr addr, uint32_t value)
536956a7811SThomas Huth {
537956a7811SThomas Huth     DPRINTF("BMAP Write W @ %x with %x\n", (unsigned int)addr, value);
538956a7811SThomas Huth }
539956a7811SThomas Huth 
540956a7811SThomas Huth static void scr_writel(NeXTState *s, hwaddr addr, uint32_t value)
541956a7811SThomas Huth {
542956a7811SThomas Huth     DPRINTF("BMAP Write L @ %x with %x\n", (unsigned int)addr, value);
543956a7811SThomas Huth }
544956a7811SThomas Huth 
545956a7811SThomas Huth static uint64_t scr_readfn(void *opaque, hwaddr addr, unsigned size)
546956a7811SThomas Huth {
547956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
548956a7811SThomas Huth 
549956a7811SThomas Huth     switch (size) {
550956a7811SThomas Huth     case 1:
551956a7811SThomas Huth         return scr_readb(ns, addr);
552956a7811SThomas Huth     case 2:
553956a7811SThomas Huth         return scr_readw(ns, addr);
554956a7811SThomas Huth     case 4:
555956a7811SThomas Huth         return scr_readl(ns, addr);
556956a7811SThomas Huth     default:
557956a7811SThomas Huth         g_assert_not_reached();
558956a7811SThomas Huth     }
559956a7811SThomas Huth }
560956a7811SThomas Huth 
561956a7811SThomas Huth static void scr_writefn(void *opaque, hwaddr addr, uint64_t value,
562956a7811SThomas Huth                         unsigned size)
563956a7811SThomas Huth {
564956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(opaque);
565956a7811SThomas Huth 
566956a7811SThomas Huth     switch (size) {
567956a7811SThomas Huth     case 1:
568956a7811SThomas Huth         scr_writeb(ns, addr, value);
569956a7811SThomas Huth         break;
570956a7811SThomas Huth     case 2:
571956a7811SThomas Huth         scr_writew(ns, addr, value);
572956a7811SThomas Huth         break;
573956a7811SThomas Huth     case 4:
574956a7811SThomas Huth         scr_writel(ns, addr, value);
575956a7811SThomas Huth         break;
576956a7811SThomas Huth     default:
577956a7811SThomas Huth         g_assert_not_reached();
578956a7811SThomas Huth     }
579956a7811SThomas Huth }
580956a7811SThomas Huth 
581956a7811SThomas Huth static const MemoryRegionOps scr_ops = {
582956a7811SThomas Huth     .read = scr_readfn,
583956a7811SThomas Huth     .write = scr_writefn,
584956a7811SThomas Huth     .valid.min_access_size = 1,
585956a7811SThomas Huth     .valid.max_access_size = 4,
586956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
587956a7811SThomas Huth };
588956a7811SThomas Huth 
589956a7811SThomas Huth #define NEXTDMA_SCSI(x)      (0x10 + x)
590956a7811SThomas Huth #define NEXTDMA_FD(x)        (0x10 + x)
591956a7811SThomas Huth #define NEXTDMA_ENTX(x)      (0x110 + x)
592956a7811SThomas Huth #define NEXTDMA_ENRX(x)      (0x150 + x)
593956a7811SThomas Huth #define NEXTDMA_CSR          0x0
594956a7811SThomas Huth #define NEXTDMA_NEXT         0x4000
595956a7811SThomas Huth #define NEXTDMA_LIMIT        0x4004
596956a7811SThomas Huth #define NEXTDMA_START        0x4008
597956a7811SThomas Huth #define NEXTDMA_STOP         0x400c
598956a7811SThomas Huth #define NEXTDMA_NEXT_INIT    0x4200
599956a7811SThomas Huth #define NEXTDMA_SIZE         0x4204
600956a7811SThomas Huth 
601956a7811SThomas Huth static void dma_writel(void *opaque, hwaddr addr, uint64_t value,
602956a7811SThomas Huth                        unsigned int size)
603956a7811SThomas Huth {
604956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
605956a7811SThomas Huth 
606956a7811SThomas Huth     switch (addr) {
607956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
608956a7811SThomas Huth         if (value & DMA_DEV2M) {
609956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_DEV2M;
610956a7811SThomas Huth         }
611956a7811SThomas Huth 
612956a7811SThomas Huth         if (value & DMA_SETENABLE) {
613956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
614956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_ENABLE;
615956a7811SThomas Huth         }
616956a7811SThomas Huth         if (value & DMA_SETSUPDATE) {
617956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr |= DMA_SUPDATE;
618956a7811SThomas Huth         }
619956a7811SThomas Huth         if (value & DMA_CLRCOMPLETE) {
620956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~DMA_COMPLETE;
621956a7811SThomas Huth         }
622956a7811SThomas Huth 
623956a7811SThomas Huth         if (value & DMA_RESET) {
624956a7811SThomas Huth             next_state->dma[NEXTDMA_ENRX].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
625956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
626956a7811SThomas Huth         }
627956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
628956a7811SThomas Huth         break;
629956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
630956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].next_initbuf = value;
631956a7811SThomas Huth         break;
632956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
633956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].next = value;
634956a7811SThomas Huth         break;
635956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
636956a7811SThomas Huth         next_state->dma[NEXTDMA_ENRX].limit = value;
637956a7811SThomas Huth         break;
638956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
639956a7811SThomas Huth         if (value & DMA_DEV2M) {
640956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_DEV2M;
641956a7811SThomas Huth         }
642956a7811SThomas Huth         if (value & DMA_SETENABLE) {
643956a7811SThomas Huth             /* DPRINTF("SCSI DMA ENABLE\n"); */
644956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_ENABLE;
645956a7811SThomas Huth         }
646956a7811SThomas Huth         if (value & DMA_SETSUPDATE) {
647956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr |= DMA_SUPDATE;
648956a7811SThomas Huth         }
649956a7811SThomas Huth         if (value & DMA_CLRCOMPLETE) {
650956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~DMA_COMPLETE;
651956a7811SThomas Huth         }
652956a7811SThomas Huth 
653956a7811SThomas Huth         if (value & DMA_RESET) {
654956a7811SThomas Huth             next_state->dma[NEXTDMA_SCSI].csr &= ~(DMA_COMPLETE | DMA_SUPDATE |
655956a7811SThomas Huth                                                   DMA_ENABLE | DMA_DEV2M);
656956a7811SThomas Huth             /* DPRINTF("SCSI DMA RESET\n"); */
657956a7811SThomas Huth         }
658956a7811SThomas Huth         /* DPRINTF("RXCSR \tWrite: %x\n",value); */
659956a7811SThomas Huth         break;
660956a7811SThomas Huth 
661956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
662956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].next = value;
663956a7811SThomas Huth         break;
664956a7811SThomas Huth 
665956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
666956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].limit = value;
667956a7811SThomas Huth         break;
668956a7811SThomas Huth 
669956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
670956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].start = value;
671956a7811SThomas Huth         break;
672956a7811SThomas Huth 
673956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
674956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].stop = value;
675956a7811SThomas Huth         break;
676956a7811SThomas Huth 
677956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
678956a7811SThomas Huth         next_state->dma[NEXTDMA_SCSI].next_initbuf = value;
679956a7811SThomas Huth         break;
680956a7811SThomas Huth 
681956a7811SThomas Huth     default:
682956a7811SThomas Huth         DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)value);
683956a7811SThomas Huth     }
684956a7811SThomas Huth }
685956a7811SThomas Huth 
686956a7811SThomas Huth static uint64_t dma_readl(void *opaque, hwaddr addr, unsigned int size)
687956a7811SThomas Huth {
688956a7811SThomas Huth     NeXTState *next_state = NEXT_MACHINE(opaque);
689956a7811SThomas Huth 
690956a7811SThomas Huth     switch (addr) {
691956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_CSR):
692956a7811SThomas Huth         DPRINTF("SCSI DMA CSR READ\n");
693956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].csr;
694956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_CSR):
695956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].csr;
696956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT_INIT):
697956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].next_initbuf;
698956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_NEXT):
699956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].next;
700956a7811SThomas Huth     case NEXTDMA_ENRX(NEXTDMA_LIMIT):
701956a7811SThomas Huth         return next_state->dma[NEXTDMA_ENRX].limit;
702956a7811SThomas Huth 
703956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT):
704956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].next;
705956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_NEXT_INIT):
706956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].next_initbuf;
707956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_LIMIT):
708956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].limit;
709956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_START):
710956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].start;
711956a7811SThomas Huth     case NEXTDMA_SCSI(NEXTDMA_STOP):
712956a7811SThomas Huth         return next_state->dma[NEXTDMA_SCSI].stop;
713956a7811SThomas Huth 
714956a7811SThomas Huth     default:
715956a7811SThomas Huth         DPRINTF("DMA read @ %x\n", (unsigned int)addr);
716956a7811SThomas Huth         return 0;
717956a7811SThomas Huth     }
718956a7811SThomas Huth 
719956a7811SThomas Huth     /*
720956a7811SThomas Huth      * once the csr's are done, subtract 0x3FEC from the addr, and that will
721956a7811SThomas Huth      * normalize the upper registers
722956a7811SThomas Huth      */
723956a7811SThomas Huth }
724956a7811SThomas Huth 
725956a7811SThomas Huth static const MemoryRegionOps dma_ops = {
726956a7811SThomas Huth     .read = dma_readl,
727956a7811SThomas Huth     .write = dma_writel,
728956a7811SThomas Huth     .impl.min_access_size = 4,
729956a7811SThomas Huth     .valid.min_access_size = 4,
730956a7811SThomas Huth     .valid.max_access_size = 4,
731956a7811SThomas Huth     .endianness = DEVICE_NATIVE_ENDIAN,
732956a7811SThomas Huth };
733956a7811SThomas Huth 
734956a7811SThomas Huth /*
735956a7811SThomas Huth  * TODO: set the shift numbers as values in the enum, so the first switch
736956a7811SThomas Huth  * will not be needed
737956a7811SThomas Huth  */
738c8abcc87SPeter Maydell static void next_irq(void *opaque, int number, int level)
739956a7811SThomas Huth {
740956a7811SThomas Huth     M68kCPU *cpu = opaque;
741956a7811SThomas Huth     int shift = 0;
742956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(qdev_get_machine());
743956a7811SThomas Huth 
744956a7811SThomas Huth     /* first switch sets interupt status */
745956a7811SThomas Huth     /* DPRINTF("IRQ %i\n",number); */
746956a7811SThomas Huth     switch (number) {
747956a7811SThomas Huth     /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
748956a7811SThomas Huth     case NEXT_FD_I:
7495012a894SPhilippe Mathieu-Daudé         shift = 7;
750956a7811SThomas Huth         break;
751956a7811SThomas Huth     case NEXT_KBD_I:
752956a7811SThomas Huth         shift = 3;
753956a7811SThomas Huth         break;
754956a7811SThomas Huth     case NEXT_PWR_I:
755956a7811SThomas Huth         shift = 2;
756956a7811SThomas Huth         break;
757956a7811SThomas Huth     case NEXT_ENRX_I:
758956a7811SThomas Huth         shift = 9;
759956a7811SThomas Huth         break;
760956a7811SThomas Huth     case NEXT_ENTX_I:
761956a7811SThomas Huth         shift = 10;
762956a7811SThomas Huth         break;
763956a7811SThomas Huth     case NEXT_SCSI_I:
764956a7811SThomas Huth         shift = 12;
765956a7811SThomas Huth         break;
766956a7811SThomas Huth     case NEXT_CLK_I:
767956a7811SThomas Huth         shift = 5;
768956a7811SThomas Huth         break;
769956a7811SThomas Huth 
770956a7811SThomas Huth     /* level 5 - scc (serial) */
771956a7811SThomas Huth     case NEXT_SCC_I:
772956a7811SThomas Huth         shift = 17;
773956a7811SThomas Huth         break;
774956a7811SThomas Huth 
775956a7811SThomas Huth     /* level 6 - audio etherrx/tx dma */
776956a7811SThomas Huth     case NEXT_ENTX_DMA_I:
777956a7811SThomas Huth         shift = 28;
778956a7811SThomas Huth         break;
779956a7811SThomas Huth     case NEXT_ENRX_DMA_I:
780956a7811SThomas Huth         shift = 27;
781956a7811SThomas Huth         break;
782956a7811SThomas Huth     case NEXT_SCSI_DMA_I:
783956a7811SThomas Huth         shift = 26;
784956a7811SThomas Huth         break;
785956a7811SThomas Huth     case NEXT_SND_I:
786956a7811SThomas Huth         shift = 23;
787956a7811SThomas Huth         break;
788956a7811SThomas Huth     case NEXT_SCC_DMA_I:
789956a7811SThomas Huth         shift = 21;
790956a7811SThomas Huth         break;
791956a7811SThomas Huth 
792956a7811SThomas Huth     }
793956a7811SThomas Huth     /*
794956a7811SThomas Huth      * this HAS to be wrong, the interrupt handlers in mach and together
795956a7811SThomas Huth      * int_status and int_mask and return if there is a hit
796956a7811SThomas Huth      */
797956a7811SThomas Huth     if (ns->int_mask & (1 << shift)) {
798956a7811SThomas Huth         DPRINTF("%x interrupt masked @ %x\n", 1 << shift, cpu->env.pc);
799956a7811SThomas Huth         /* return; */
800956a7811SThomas Huth     }
801956a7811SThomas Huth 
802956a7811SThomas Huth     /* second switch triggers the correct interrupt */
803956a7811SThomas Huth     if (level) {
804956a7811SThomas Huth         ns->int_status |= 1 << shift;
805956a7811SThomas Huth 
806956a7811SThomas Huth         switch (number) {
807956a7811SThomas Huth         /* level 3 - floppy, kbd/mouse, power, ether rx/tx, scsi, clock */
808956a7811SThomas Huth         case NEXT_FD_I:
809956a7811SThomas Huth         case NEXT_KBD_I:
810956a7811SThomas Huth         case NEXT_PWR_I:
811956a7811SThomas Huth         case NEXT_ENRX_I:
812956a7811SThomas Huth         case NEXT_ENTX_I:
813956a7811SThomas Huth         case NEXT_SCSI_I:
814956a7811SThomas Huth         case NEXT_CLK_I:
815956a7811SThomas Huth             m68k_set_irq_level(cpu, 3, 27);
816956a7811SThomas Huth             break;
817956a7811SThomas Huth 
818956a7811SThomas Huth         /* level 5 - scc (serial) */
819956a7811SThomas Huth         case NEXT_SCC_I:
820956a7811SThomas Huth             m68k_set_irq_level(cpu, 5, 29);
821956a7811SThomas Huth             break;
822956a7811SThomas Huth 
823956a7811SThomas Huth         /* level 6 - audio etherrx/tx dma */
824956a7811SThomas Huth         case NEXT_ENTX_DMA_I:
825956a7811SThomas Huth         case NEXT_ENRX_DMA_I:
826956a7811SThomas Huth         case NEXT_SCSI_DMA_I:
827956a7811SThomas Huth         case NEXT_SND_I:
828956a7811SThomas Huth         case NEXT_SCC_DMA_I:
829956a7811SThomas Huth             m68k_set_irq_level(cpu, 6, 30);
830956a7811SThomas Huth             break;
831956a7811SThomas Huth         }
832956a7811SThomas Huth     } else {
833956a7811SThomas Huth         ns->int_status &= ~(1 << shift);
834956a7811SThomas Huth         cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
835956a7811SThomas Huth     }
836956a7811SThomas Huth }
837956a7811SThomas Huth 
838b17bed5bSThomas Huth static void next_serial_irq(void *opaque, int n, int level)
839b17bed5bSThomas Huth {
840b17bed5bSThomas Huth     /* DPRINTF("SCC IRQ NUM %i\n",n); */
841b17bed5bSThomas Huth     if (n) {
842b17bed5bSThomas Huth         next_irq(opaque, NEXT_SCC_DMA_I, level);
843b17bed5bSThomas Huth     } else {
844b17bed5bSThomas Huth         next_irq(opaque, NEXT_SCC_I, level);
845b17bed5bSThomas Huth     }
846b17bed5bSThomas Huth }
847b17bed5bSThomas Huth 
848b17bed5bSThomas Huth static void next_escc_init(M68kCPU *cpu)
849b17bed5bSThomas Huth {
850b17bed5bSThomas Huth     qemu_irq *ser_irq = qemu_allocate_irqs(next_serial_irq, cpu, 2);
851b17bed5bSThomas Huth     DeviceState *dev;
852b17bed5bSThomas Huth     SysBusDevice *s;
853b17bed5bSThomas Huth 
8543e80f690SMarkus Armbruster     dev = qdev_new(TYPE_ESCC);
855b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "disabled", 0);
856b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "frequency", 9600 * 384);
857b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "it_shift", 0);
858b17bed5bSThomas Huth     qdev_prop_set_bit(dev, "bit_swap", true);
859b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrB", serial_hd(1));
860b17bed5bSThomas Huth     qdev_prop_set_chr(dev, "chrA", serial_hd(0));
861b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
862b17bed5bSThomas Huth     qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
863b17bed5bSThomas Huth 
864b17bed5bSThomas Huth     s = SYS_BUS_DEVICE(dev);
8653c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
866b17bed5bSThomas Huth     sysbus_connect_irq(s, 0, ser_irq[0]);
867b17bed5bSThomas Huth     sysbus_connect_irq(s, 1,  ser_irq[1]);
868b17bed5bSThomas Huth     sysbus_mmio_map(s, 0, 0x2118000);
869b17bed5bSThomas Huth }
870b17bed5bSThomas Huth 
871*660bef33SPeter Maydell static void next_pc_reset(DeviceState *dev)
872*660bef33SPeter Maydell {
873*660bef33SPeter Maydell }
874*660bef33SPeter Maydell 
875*660bef33SPeter Maydell static void next_pc_realize(DeviceState *dev, Error **errp)
876*660bef33SPeter Maydell {
877*660bef33SPeter Maydell }
878*660bef33SPeter Maydell 
879*660bef33SPeter Maydell static void next_pc_class_init(ObjectClass *klass, void *data)
880*660bef33SPeter Maydell {
881*660bef33SPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
882*660bef33SPeter Maydell 
883*660bef33SPeter Maydell     dc->desc = "NeXT Peripheral Controller";
884*660bef33SPeter Maydell     dc->realize = next_pc_realize;
885*660bef33SPeter Maydell     dc->reset = next_pc_reset;
886*660bef33SPeter Maydell     /* We will add the VMState in a later commit */
887*660bef33SPeter Maydell }
888*660bef33SPeter Maydell 
889*660bef33SPeter Maydell static const TypeInfo next_pc_info = {
890*660bef33SPeter Maydell     .name = TYPE_NEXT_PC,
891*660bef33SPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
892*660bef33SPeter Maydell     .instance_size = sizeof(NeXTPC),
893*660bef33SPeter Maydell     .class_init = next_pc_class_init,
894*660bef33SPeter Maydell };
895*660bef33SPeter Maydell 
896956a7811SThomas Huth static void next_cube_init(MachineState *machine)
897956a7811SThomas Huth {
898956a7811SThomas Huth     M68kCPU *cpu;
899956a7811SThomas Huth     CPUM68KState *env;
900956a7811SThomas Huth     MemoryRegion *rom = g_new(MemoryRegion, 1);
901956a7811SThomas Huth     MemoryRegion *mmiomem = g_new(MemoryRegion, 1);
902956a7811SThomas Huth     MemoryRegion *scrmem = g_new(MemoryRegion, 1);
903956a7811SThomas Huth     MemoryRegion *dmamem = g_new(MemoryRegion, 1);
904956a7811SThomas Huth     MemoryRegion *bmapm1 = g_new(MemoryRegion, 1);
905956a7811SThomas Huth     MemoryRegion *bmapm2 = g_new(MemoryRegion, 1);
906956a7811SThomas Huth     MemoryRegion *sysmem = get_system_memory();
9071684273cSPaolo Bonzini     const char *bios_name = machine->firmware ?: ROM_FILE;
908956a7811SThomas Huth     NeXTState *ns = NEXT_MACHINE(machine);
909956a7811SThomas Huth     DeviceState *dev;
910*660bef33SPeter Maydell     DeviceState *pcdev;
911956a7811SThomas Huth 
912956a7811SThomas Huth     /* Initialize the cpu core */
913956a7811SThomas Huth     cpu = M68K_CPU(cpu_create(machine->cpu_type));
914956a7811SThomas Huth     if (!cpu) {
915956a7811SThomas Huth         error_report("Unable to find m68k CPU definition");
916956a7811SThomas Huth         exit(1);
917956a7811SThomas Huth     }
918956a7811SThomas Huth     env = &cpu->env;
919956a7811SThomas Huth 
920956a7811SThomas Huth     /* Initialize CPU registers.  */
921956a7811SThomas Huth     env->vbr = 0;
922956a7811SThomas Huth     env->sr  = 0x2700;
923956a7811SThomas Huth 
924*660bef33SPeter Maydell     /* Peripheral Controller */
925*660bef33SPeter Maydell     pcdev = qdev_new(TYPE_NEXT_PC);
926*660bef33SPeter Maydell     sysbus_realize_and_unref(SYS_BUS_DEVICE(pcdev), &error_fatal);
927*660bef33SPeter Maydell     /* Temporary while we refactor this code */
928*660bef33SPeter Maydell     NEXT_PC(pcdev)->ns = ns;
929*660bef33SPeter Maydell 
930956a7811SThomas Huth     /* Set internal registers to initial values */
931956a7811SThomas Huth     /*     0x0000XX00 << vital bits */
932956a7811SThomas Huth     ns->scr1 = 0x00011102;
933956a7811SThomas Huth     ns->scr2 = 0x00ff0c80;
934cd4fc142SThomas Huth     ns->rtc.status = 0x90;
935956a7811SThomas Huth 
936956a7811SThomas Huth     /* Load RTC RAM - TODO: provide possibility to load contents from file */
937cd4fc142SThomas Huth     memcpy(ns->rtc.ram, rtc_ram2, 32);
938956a7811SThomas Huth 
939956a7811SThomas Huth     /* 64MB RAM starting at 0x04000000  */
94049b64ba9SIgor Mammedov     memory_region_add_subregion(sysmem, 0x04000000, machine->ram);
941956a7811SThomas Huth 
942956a7811SThomas Huth     /* Framebuffer */
9433e80f690SMarkus Armbruster     dev = qdev_new(TYPE_NEXTFB);
9443c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
945956a7811SThomas Huth     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0B000000);
946956a7811SThomas Huth 
947956a7811SThomas Huth     /* MMIO */
948956a7811SThomas Huth     memory_region_init_io(mmiomem, NULL, &mmio_ops, machine, "next.mmio",
949956a7811SThomas Huth                           0xD0000);
950956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02000000, mmiomem);
951956a7811SThomas Huth 
952956a7811SThomas Huth     /* BMAP memory */
953956a7811SThomas Huth     memory_region_init_ram_shared_nomigrate(bmapm1, NULL, "next.bmapmem", 64,
954956a7811SThomas Huth                                             true, &error_fatal);
955956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x020c0000, bmapm1);
956956a7811SThomas Huth     /* The Rev_2.5_v66.bin firmware accesses it at 0x820c0020, too */
957956a7811SThomas Huth     memory_region_init_alias(bmapm2, NULL, "next.bmapmem2", bmapm1, 0x0, 64);
958956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x820c0000, bmapm2);
959956a7811SThomas Huth 
960956a7811SThomas Huth     /* BMAP IO - acts as a catch-all for now */
961956a7811SThomas Huth     memory_region_init_io(scrmem, NULL, &scr_ops, machine, "next.scr",
962956a7811SThomas Huth                           0x20000);
963956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02100000, scrmem);
964956a7811SThomas Huth 
965956a7811SThomas Huth     /* KBD */
9663e80f690SMarkus Armbruster     dev = qdev_new(TYPE_NEXTKBD);
9673c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
968956a7811SThomas Huth     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000);
969956a7811SThomas Huth 
970956a7811SThomas Huth     /* Load ROM here */
971956a7811SThomas Huth     /* still not sure if the rom should also be mapped at 0x0*/
972956a7811SThomas Huth     memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal);
973956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x01000000, rom);
974956a7811SThomas Huth     if (load_image_targphys(bios_name, 0x01000000, 0x20000) < 8) {
975956a7811SThomas Huth         if (!qtest_enabled()) {
976956a7811SThomas Huth             error_report("Failed to load firmware '%s'.", bios_name);
977956a7811SThomas Huth         }
978956a7811SThomas Huth     } else {
979956a7811SThomas Huth         uint8_t *ptr;
980956a7811SThomas Huth         /* Initial PC is always at offset 4 in firmware binaries */
981956a7811SThomas Huth         ptr = rom_ptr(0x01000004, 4);
982956a7811SThomas Huth         g_assert(ptr != NULL);
983956a7811SThomas Huth         env->pc = ldl_p(ptr);
984956a7811SThomas Huth         if (env->pc >= 0x01020000) {
985956a7811SThomas Huth             error_report("'%s' does not seem to be a valid firmware image.",
986956a7811SThomas Huth                          bios_name);
987956a7811SThomas Huth             exit(1);
988956a7811SThomas Huth         }
989956a7811SThomas Huth     }
990956a7811SThomas Huth 
991956a7811SThomas Huth     /* Serial */
992b17bed5bSThomas Huth     next_escc_init(cpu);
993b17bed5bSThomas Huth 
994b17bed5bSThomas Huth     /* TODO: */
995956a7811SThomas Huth     /* Network */
996956a7811SThomas Huth     /* SCSI */
997956a7811SThomas Huth 
998956a7811SThomas Huth     /* DMA */
999956a7811SThomas Huth     memory_region_init_io(dmamem, NULL, &dma_ops, machine, "next.dma", 0x5000);
1000956a7811SThomas Huth     memory_region_add_subregion(sysmem, 0x02000000, dmamem);
1001956a7811SThomas Huth }
1002956a7811SThomas Huth 
1003956a7811SThomas Huth static void next_machine_class_init(ObjectClass *oc, void *data)
1004956a7811SThomas Huth {
1005956a7811SThomas Huth     MachineClass *mc = MACHINE_CLASS(oc);
1006956a7811SThomas Huth 
1007956a7811SThomas Huth     mc->desc = "NeXT Cube";
1008956a7811SThomas Huth     mc->init = next_cube_init;
1009956a7811SThomas Huth     mc->default_ram_size = RAM_SIZE;
101049b64ba9SIgor Mammedov     mc->default_ram_id = "next.ram";
1011956a7811SThomas Huth     mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
1012956a7811SThomas Huth }
1013956a7811SThomas Huth 
1014956a7811SThomas Huth static const TypeInfo next_typeinfo = {
1015956a7811SThomas Huth     .name = TYPE_NEXT_MACHINE,
1016956a7811SThomas Huth     .parent = TYPE_MACHINE,
1017956a7811SThomas Huth     .class_init = next_machine_class_init,
1018956a7811SThomas Huth     .instance_size = sizeof(NeXTState),
1019956a7811SThomas Huth };
1020956a7811SThomas Huth 
1021956a7811SThomas Huth static void next_register_type(void)
1022956a7811SThomas Huth {
1023956a7811SThomas Huth     type_register_static(&next_typeinfo);
1024*660bef33SPeter Maydell     type_register_static(&next_pc_info);
1025956a7811SThomas Huth }
1026956a7811SThomas Huth 
1027956a7811SThomas Huth type_init(next_register_type)
1028