xref: /openbmc/qemu/hw/m68k/q800.c (revision 988717b46b6424907618cb845ace9d69062703af)
1  /*
2   * QEMU Motorla 680x0 Macintosh hardware System Emulator
3   *
4   * Permission is hereby granted, free of charge, to any person obtaining a copy
5   * of this software and associated documentation files (the "Software"), to deal
6   * in the Software without restriction, including without limitation the rights
7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8   * copies of the Software, and to permit persons to whom the Software is
9   * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   * THE SOFTWARE.
21   */
22  
23  #include "qemu/osdep.h"
24  #include "qemu/units.h"
25  #include "qemu-common.h"
26  #include "sysemu/sysemu.h"
27  #include "cpu.h"
28  #include "hw/hw.h"
29  #include "hw/boards.h"
30  #include "hw/irq.h"
31  #include "elf.h"
32  #include "hw/loader.h"
33  #include "ui/console.h"
34  #include "exec/address-spaces.h"
35  #include "hw/char/escc.h"
36  #include "hw/sysbus.h"
37  #include "hw/scsi/esp.h"
38  #include "bootinfo.h"
39  #include "hw/misc/mac_via.h"
40  #include "hw/input/adb.h"
41  #include "hw/nubus/mac-nubus-bridge.h"
42  #include "hw/display/macfb.h"
43  #include "hw/block/swim.h"
44  #include "net/net.h"
45  #include "qapi/error.h"
46  #include "sysemu/qtest.h"
47  #include "sysemu/runstate.h"
48  #include "sysemu/reset.h"
49  
50  #define MACROM_ADDR     0x40800000
51  #define MACROM_SIZE     0x00100000
52  
53  #define MACROM_FILENAME "MacROM.bin"
54  
55  #define Q800_MACHINE_ID 35
56  #define Q800_CPU_ID (1 << 2)
57  #define Q800_FPU_ID (1 << 2)
58  #define Q800_MMU_ID (1 << 2)
59  
60  #define MACH_MAC        3
61  #define Q800_MAC_CPU_ID 2
62  
63  #define IO_BASE               0x50000000
64  #define IO_SLICE              0x00040000
65  #define IO_SIZE               0x04000000
66  
67  #define VIA_BASE              (IO_BASE + 0x00000)
68  #define SONIC_PROM_BASE       (IO_BASE + 0x08000)
69  #define SONIC_BASE            (IO_BASE + 0x0a000)
70  #define SCC_BASE              (IO_BASE + 0x0c020)
71  #define ESP_BASE              (IO_BASE + 0x10000)
72  #define ESP_PDMA              (IO_BASE + 0x10100)
73  #define ASC_BASE              (IO_BASE + 0x14000)
74  #define SWIM_BASE             (IO_BASE + 0x1E000)
75  
76  #define NUBUS_SUPER_SLOT_BASE 0x60000000
77  #define NUBUS_SLOT_BASE       0xf0000000
78  
79  /*
80   * the video base, whereas it a Nubus address,
81   * is needed by the kernel to have early display and
82   * thus provided by the bootloader
83   */
84  #define VIDEO_BASE            0xf9001000
85  
86  #define MAC_CLOCK  3686418
87  
88  /*
89   * The GLUE (General Logic Unit) is an Apple custom integrated circuit chip
90   * that performs a variety of functions (RAM management, clock generation, ...).
91   * The GLUE chip receives interrupt requests from various devices,
92   * assign priority to each, and asserts one or more interrupt line to the
93   * CPU.
94   */
95  
96  typedef struct {
97      M68kCPU *cpu;
98      uint8_t ipr;
99  } GLUEState;
100  
101  static void GLUE_set_irq(void *opaque, int irq, int level)
102  {
103      GLUEState *s = opaque;
104      int i;
105  
106      if (level) {
107          s->ipr |= 1 << irq;
108      } else {
109          s->ipr &= ~(1 << irq);
110      }
111  
112      for (i = 7; i >= 0; i--) {
113          if ((s->ipr >> i) & 1) {
114              m68k_set_irq_level(s->cpu, i + 1, i + 25);
115              return;
116          }
117      }
118      m68k_set_irq_level(s->cpu, 0, 0);
119  }
120  
121  static void main_cpu_reset(void *opaque)
122  {
123      M68kCPU *cpu = opaque;
124      CPUState *cs = CPU(cpu);
125  
126      cpu_reset(cs);
127      cpu->env.aregs[7] = ldl_phys(cs->as, 0);
128      cpu->env.pc = ldl_phys(cs->as, 4);
129  }
130  
131  static uint8_t fake_mac_rom[] = {
132      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133  
134      /* offset: 0xa - mac_reset */
135  
136      /* via2[vDirB] |= VIA2B_vPower */
137      0x20, 0x7C, 0x50, 0xF0, 0x24, 0x00, /* moveal VIA2_BASE+vDirB,%a0 */
138      0x10, 0x10,                         /* moveb %a0@,%d0 */
139      0x00, 0x00, 0x00, 0x04,             /* orib #4,%d0 */
140      0x10, 0x80,                         /* moveb %d0,%a0@ */
141  
142      /* via2[vBufB] &= ~VIA2B_vPower */
143      0x20, 0x7C, 0x50, 0xF0, 0x20, 0x00, /* moveal VIA2_BASE+vBufB,%a0 */
144      0x10, 0x10,                         /* moveb %a0@,%d0 */
145      0x02, 0x00, 0xFF, 0xFB,             /* andib #-5,%d0 */
146      0x10, 0x80,                         /* moveb %d0,%a0@ */
147  
148      /* while (true) ; */
149      0x60, 0xFE                          /* bras [self] */
150  };
151  
152  static void q800_init(MachineState *machine)
153  {
154      M68kCPU *cpu = NULL;
155      int linux_boot;
156      int32_t kernel_size;
157      uint64_t elf_entry;
158      char *filename;
159      int bios_size;
160      ram_addr_t initrd_base;
161      int32_t initrd_size;
162      MemoryRegion *rom;
163      MemoryRegion *ram;
164      MemoryRegion *io;
165      const int io_slice_nb = (IO_SIZE / IO_SLICE) - 1;
166      int i;
167      ram_addr_t ram_size = machine->ram_size;
168      const char *kernel_filename = machine->kernel_filename;
169      const char *initrd_filename = machine->initrd_filename;
170      const char *kernel_cmdline = machine->kernel_cmdline;
171      hwaddr parameters_base;
172      CPUState *cs;
173      DeviceState *dev;
174      DeviceState *via_dev;
175      SysBusESPState *sysbus_esp;
176      ESPState *esp;
177      SysBusDevice *sysbus;
178      BusState *adb_bus;
179      NubusBus *nubus;
180      GLUEState *irq;
181      qemu_irq *pic;
182      DriveInfo *dinfo;
183  
184      linux_boot = (kernel_filename != NULL);
185  
186      if (ram_size > 1 * GiB) {
187          error_report("Too much memory for this machine: %" PRId64 " MiB, "
188                       "maximum 1024 MiB", ram_size / MiB);
189          exit(1);
190      }
191  
192      /* init CPUs */
193      cpu = M68K_CPU(cpu_create(machine->cpu_type));
194      qemu_register_reset(main_cpu_reset, cpu);
195  
196      /* RAM */
197      ram = g_malloc(sizeof(*ram));
198      memory_region_init_ram(ram, NULL, "m68k_mac.ram", ram_size, &error_abort);
199      memory_region_add_subregion(get_system_memory(), 0, ram);
200  
201      /*
202       * Memory from IO_BASE to IO_BASE + IO_SLICE is repeated
203       * from IO_BASE + IO_SLICE to IO_BASE + IO_SIZE
204       */
205      io = g_new(MemoryRegion, io_slice_nb);
206      for (i = 0; i < io_slice_nb; i++) {
207          char *name = g_strdup_printf("mac_m68k.io[%d]", i + 1);
208  
209          memory_region_init_alias(&io[i], NULL, name, get_system_memory(),
210                                   IO_BASE, IO_SLICE);
211          memory_region_add_subregion(get_system_memory(),
212                                      IO_BASE + (i + 1) * IO_SLICE, &io[i]);
213          g_free(name);
214      }
215  
216      /* IRQ Glue */
217  
218      irq = g_new0(GLUEState, 1);
219      irq->cpu = cpu;
220      pic = qemu_allocate_irqs(GLUE_set_irq, irq, 8);
221  
222      /* VIA */
223  
224      via_dev = qdev_create(NULL, TYPE_MAC_VIA);
225      dinfo = drive_get(IF_MTD, 0, 0);
226      if (dinfo) {
227          qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo),
228                              &error_abort);
229      }
230      qdev_init_nofail(via_dev);
231      sysbus = SYS_BUS_DEVICE(via_dev);
232      sysbus_mmio_map(sysbus, 0, VIA_BASE);
233      qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]);
234      qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]);
235  
236  
237      adb_bus = qdev_get_child_bus(via_dev, "adb.0");
238      dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD);
239      qdev_init_nofail(dev);
240      dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);
241      qdev_init_nofail(dev);
242  
243      /* MACSONIC */
244  
245      if (nb_nics > 1) {
246          error_report("q800 can only have one ethernet interface");
247          exit(1);
248      }
249  
250      qemu_check_nic_model(&nd_table[0], "dp83932");
251  
252      /*
253       * MacSonic driver needs an Apple MAC address
254       * Valid prefix are:
255       * 00:05:02 Apple
256       * 00:80:19 Dayna Communications, Inc.
257       * 00:A0:40 Apple
258       * 08:00:07 Apple
259       * (Q800 use the last one)
260       */
261      nd_table[0].macaddr.a[0] = 0x08;
262      nd_table[0].macaddr.a[1] = 0x00;
263      nd_table[0].macaddr.a[2] = 0x07;
264  
265      dev = qdev_create(NULL, "dp8393x");
266      qdev_set_nic_properties(dev, &nd_table[0]);
267      qdev_prop_set_uint8(dev, "it_shift", 2);
268      qdev_prop_set_bit(dev, "big_endian", true);
269      object_property_set_link(OBJECT(dev), OBJECT(get_system_memory()),
270                               "dma_mr", &error_abort);
271      qdev_init_nofail(dev);
272      sysbus = SYS_BUS_DEVICE(dev);
273      sysbus_mmio_map(sysbus, 0, SONIC_BASE);
274      sysbus_mmio_map(sysbus, 1, SONIC_PROM_BASE);
275      sysbus_connect_irq(sysbus, 0, pic[2]);
276  
277      /* SCC */
278  
279      dev = qdev_create(NULL, TYPE_ESCC);
280      qdev_prop_set_uint32(dev, "disabled", 0);
281      qdev_prop_set_uint32(dev, "frequency", MAC_CLOCK);
282      qdev_prop_set_uint32(dev, "it_shift", 1);
283      qdev_prop_set_bit(dev, "bit_swap", true);
284      qdev_prop_set_chr(dev, "chrA", serial_hd(0));
285      qdev_prop_set_chr(dev, "chrB", serial_hd(1));
286      qdev_prop_set_uint32(dev, "chnBtype", 0);
287      qdev_prop_set_uint32(dev, "chnAtype", 0);
288      qdev_init_nofail(dev);
289      sysbus = SYS_BUS_DEVICE(dev);
290      sysbus_connect_irq(sysbus, 0, pic[3]);
291      sysbus_connect_irq(sysbus, 1, pic[3]);
292      sysbus_mmio_map(sysbus, 0, SCC_BASE);
293  
294      /* SCSI */
295  
296      dev = qdev_create(NULL, TYPE_ESP);
297      sysbus_esp = ESP_STATE(dev);
298      esp = &sysbus_esp->esp;
299      esp->dma_memory_read = NULL;
300      esp->dma_memory_write = NULL;
301      esp->dma_opaque = NULL;
302      sysbus_esp->it_shift = 4;
303      esp->dma_enabled = 1;
304      qdev_init_nofail(dev);
305  
306      sysbus = SYS_BUS_DEVICE(dev);
307      sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in_named(via_dev,
308                                                           "via2-irq",
309                                                           VIA2_IRQ_SCSI_BIT));
310      sysbus_connect_irq(sysbus, 1,
311                         qdev_get_gpio_in_named(via_dev, "via2-irq",
312                                                VIA2_IRQ_SCSI_DATA_BIT));
313      sysbus_mmio_map(sysbus, 0, ESP_BASE);
314      sysbus_mmio_map(sysbus, 1, ESP_PDMA);
315  
316      scsi_bus_legacy_handle_cmdline(&esp->bus);
317  
318      /* SWIM floppy controller */
319  
320      dev = qdev_create(NULL, TYPE_SWIM);
321      qdev_init_nofail(dev);
322      sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SWIM_BASE);
323  
324      /* NuBus */
325  
326      dev = qdev_create(NULL, TYPE_MAC_NUBUS_BRIDGE);
327      qdev_init_nofail(dev);
328      sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, NUBUS_SUPER_SLOT_BASE);
329      sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, NUBUS_SLOT_BASE);
330  
331      nubus = MAC_NUBUS_BRIDGE(dev)->bus;
332  
333      /* framebuffer in nubus slot #9 */
334  
335      dev = qdev_create(BUS(nubus), TYPE_NUBUS_MACFB);
336      qdev_prop_set_uint32(dev, "width", graphic_width);
337      qdev_prop_set_uint32(dev, "height", graphic_height);
338      qdev_prop_set_uint8(dev, "depth", graphic_depth);
339      qdev_init_nofail(dev);
340  
341      cs = CPU(cpu);
342      if (linux_boot) {
343          uint64_t high;
344          kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
345                                 &elf_entry, NULL, &high, NULL, 1,
346                                 EM_68K, 0, 0);
347          if (kernel_size < 0) {
348              error_report("could not load kernel '%s'", kernel_filename);
349              exit(1);
350          }
351          stl_phys(cs->as, 4, elf_entry); /* reset initial PC */
352          parameters_base = (high + 1) & ~1;
353  
354          BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_MAC);
355          BOOTINFO1(cs->as, parameters_base, BI_FPUTYPE, Q800_FPU_ID);
356          BOOTINFO1(cs->as, parameters_base, BI_MMUTYPE, Q800_MMU_ID);
357          BOOTINFO1(cs->as, parameters_base, BI_CPUTYPE, Q800_CPU_ID);
358          BOOTINFO1(cs->as, parameters_base, BI_MAC_CPUID, Q800_MAC_CPU_ID);
359          BOOTINFO1(cs->as, parameters_base, BI_MAC_MODEL, Q800_MACHINE_ID);
360          BOOTINFO1(cs->as, parameters_base,
361                    BI_MAC_MEMSIZE, ram_size >> 20); /* in MB */
362          BOOTINFO2(cs->as, parameters_base, BI_MEMCHUNK, 0, ram_size);
363          BOOTINFO1(cs->as, parameters_base, BI_MAC_VADDR, VIDEO_BASE);
364          BOOTINFO1(cs->as, parameters_base, BI_MAC_VDEPTH, graphic_depth);
365          BOOTINFO1(cs->as, parameters_base, BI_MAC_VDIM,
366                    (graphic_height << 16) | graphic_width);
367          BOOTINFO1(cs->as, parameters_base, BI_MAC_VROW,
368                    (graphic_width * graphic_depth + 7) / 8);
369          BOOTINFO1(cs->as, parameters_base, BI_MAC_SCCBASE, SCC_BASE);
370  
371          rom = g_malloc(sizeof(*rom));
372          memory_region_init_ram_ptr(rom, NULL, "m68k_fake_mac.rom",
373                                     sizeof(fake_mac_rom), fake_mac_rom);
374          memory_region_set_readonly(rom, true);
375          memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom);
376  
377          if (kernel_cmdline) {
378              BOOTINFOSTR(cs->as, parameters_base, BI_COMMAND_LINE,
379                          kernel_cmdline);
380          }
381  
382          /* load initrd */
383          if (initrd_filename) {
384              initrd_size = get_image_size(initrd_filename);
385              if (initrd_size < 0) {
386                  error_report("could not load initial ram disk '%s'",
387                               initrd_filename);
388                  exit(1);
389              }
390  
391              initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
392              load_image_targphys(initrd_filename, initrd_base,
393                                  ram_size - initrd_base);
394              BOOTINFO2(cs->as, parameters_base, BI_RAMDISK, initrd_base,
395                        initrd_size);
396          } else {
397              initrd_base = 0;
398              initrd_size = 0;
399          }
400          BOOTINFO0(cs->as, parameters_base, BI_LAST);
401      } else {
402          uint8_t *ptr;
403          /* allocate and load BIOS */
404          rom = g_malloc(sizeof(*rom));
405          memory_region_init_ram(rom, NULL, "m68k_mac.rom", MACROM_SIZE,
406                                 &error_abort);
407          if (bios_name == NULL) {
408              bios_name = MACROM_FILENAME;
409          }
410          filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
411          memory_region_set_readonly(rom, true);
412          memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom);
413  
414          /* Load MacROM binary */
415          if (filename) {
416              bios_size = load_image_targphys(filename, MACROM_ADDR, MACROM_SIZE);
417              g_free(filename);
418          } else {
419              bios_size = -1;
420          }
421  
422          /* Remove qtest_enabled() check once firmware files are in the tree */
423          if (!qtest_enabled()) {
424              if (bios_size < 0 || bios_size > MACROM_SIZE) {
425                  error_report("could not load MacROM '%s'", bios_name);
426                  exit(1);
427              }
428  
429              ptr = rom_ptr(MACROM_ADDR, MACROM_SIZE);
430              stl_phys(cs->as, 0, ldl_p(ptr));    /* reset initial SP */
431              stl_phys(cs->as, 4,
432                       MACROM_ADDR + ldl_p(ptr + 4)); /* reset initial PC */
433          }
434      }
435  }
436  
437  static void q800_machine_class_init(ObjectClass *oc, void *data)
438  {
439      MachineClass *mc = MACHINE_CLASS(oc);
440      mc->desc = "Macintosh Quadra 800";
441      mc->init = q800_init;
442      mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
443      mc->max_cpus = 1;
444      mc->is_default = 0;
445      mc->block_default_type = IF_SCSI;
446  }
447  
448  static const TypeInfo q800_machine_typeinfo = {
449      .name       = MACHINE_TYPE_NAME("q800"),
450      .parent     = TYPE_MACHINE,
451      .class_init = q800_machine_class_init,
452  };
453  
454  static void q800_machine_register_types(void)
455  {
456      type_register_static(&q800_machine_typeinfo);
457  }
458  
459  type_init(q800_machine_register_types)
460