1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_bebox.c,v 1.9 2006/02/09 20:02:59 debug Exp $ |
* $Id: dev_bebox.c,v 1.13 2007/02/16 19:57:56 debug Exp $ |
29 |
* |
* |
30 |
* Emulation of BeBox motherboard registers. See the following URL for more |
* Emulation of BeBox motherboard registers (and interrupt controller). |
31 |
* information: |
* See the following URL for more information: |
32 |
* |
* |
33 |
* http://www.bebox.nu/history.php?s=history/benews/benews27 |
* http://www.bebox.nu/history.php?s=history/benews/benews27 |
34 |
|
* |
35 |
|
* These interrupt numbers are from NetBSD's bebox/extint.c: |
36 |
|
* |
37 |
|
* serial3 6 |
38 |
|
* serial4 7 |
39 |
|
* midi1 8 |
40 |
|
* midi2 9 |
41 |
|
* scsi 10 |
42 |
|
* pci1 11 |
43 |
|
* pci2 12 |
44 |
|
* pci3 13 |
45 |
|
* sound 14 |
46 |
|
* 8259 26 |
47 |
|
* irda 27 |
48 |
|
* a2d 28 |
49 |
|
* geekport 29 |
50 |
|
* |
51 |
|
* Note that these are in IBM order, i.e. reversed. So 8259 interrupts |
52 |
|
* go to interrupt 31 - 26 = 5, when using normal numbers. |
53 |
|
* |
54 |
|
* Interrupt routing should work to both CPUs, but I've only ever seen the |
55 |
|
* first CPU being used by NetBSD/bebox, so the second CPU is untested :-) |
56 |
*/ |
*/ |
57 |
|
|
58 |
#include <stdio.h> |
#include <stdio.h> |
61 |
|
|
62 |
#include "cpu.h" |
#include "cpu.h" |
63 |
#include "device.h" |
#include "device.h" |
64 |
#include "devices.h" |
#include "interrupt.h" |
65 |
#include "machine.h" |
#include "machine.h" |
66 |
#include "memory.h" |
#include "memory.h" |
67 |
#include "misc.h" |
#include "misc.h" |
68 |
|
|
69 |
|
|
70 |
|
struct bebox_data { |
71 |
|
struct interrupt cpu_irq[2]; |
72 |
|
|
73 |
|
/* The 5 motherboard registers: */ |
74 |
|
uint32_t cpu0_int_mask; |
75 |
|
uint32_t cpu1_int_mask; |
76 |
|
uint32_t int_status; |
77 |
|
uint32_t xpi; |
78 |
|
uint32_t resets; |
79 |
|
}; |
80 |
|
|
81 |
|
|
82 |
|
static void bebox_interrupt_assert(struct interrupt *interrupt) |
83 |
|
{ |
84 |
|
struct bebox_data *d = interrupt->extra; |
85 |
|
d->int_status |= interrupt->line; |
86 |
|
|
87 |
|
/* printf("STATUS %08x CPU0 %08x CPU1 %08x\n", |
88 |
|
d->int_status, d->cpu0_int_mask, d->cpu1_int_mask); */ |
89 |
|
|
90 |
|
if (d->int_status & d->cpu0_int_mask) |
91 |
|
INTERRUPT_ASSERT(d->cpu_irq[0]); |
92 |
|
if (d->int_status & d->cpu1_int_mask) |
93 |
|
INTERRUPT_ASSERT(d->cpu_irq[1]); |
94 |
|
} |
95 |
|
static void bebox_interrupt_deassert(struct interrupt *interrupt) |
96 |
|
{ |
97 |
|
struct bebox_data *d = interrupt->extra; |
98 |
|
d->int_status &= ~interrupt->line; |
99 |
|
|
100 |
|
if (!(d->int_status & d->cpu0_int_mask)) |
101 |
|
INTERRUPT_DEASSERT(d->cpu_irq[0]); |
102 |
|
if (!(d->int_status & d->cpu1_int_mask)) |
103 |
|
INTERRUPT_DEASSERT(d->cpu_irq[1]); |
104 |
|
} |
105 |
|
|
106 |
|
|
107 |
/* |
/* |
108 |
* check_cpu_masks(): |
* check_cpu_masks(): |
109 |
* |
* |
116 |
d->cpu1_int_mask &= 0x7fffffff; |
d->cpu1_int_mask &= 0x7fffffff; |
117 |
if ((d->cpu0_int_mask | d->cpu1_int_mask) != |
if ((d->cpu0_int_mask | d->cpu1_int_mask) != |
118 |
(d->cpu0_int_mask ^ d->cpu1_int_mask)) |
(d->cpu0_int_mask ^ d->cpu1_int_mask)) |
119 |
fatal("check_cpu_masks(): BeBox cpu int masks" |
fatal("check_cpu_masks(): BeBox cpu int masks collide!\n"); |
|
" collide!\n"); |
|
120 |
} |
} |
121 |
|
|
122 |
|
|
|
/* |
|
|
* dev_bebox_access(): |
|
|
*/ |
|
123 |
DEVICE_ACCESS(bebox) |
DEVICE_ACCESS(bebox) |
124 |
{ |
{ |
125 |
struct bebox_data *d = extra; |
struct bebox_data *d = extra; |
199 |
DEVINIT(bebox) |
DEVINIT(bebox) |
200 |
{ |
{ |
201 |
struct bebox_data *d; |
struct bebox_data *d; |
202 |
|
int i; |
203 |
|
char n[300]; |
204 |
|
struct machine *machine = devinit->machine; |
205 |
|
|
206 |
d = malloc(sizeof(struct bebox_data)); |
d = malloc(sizeof(struct bebox_data)); |
207 |
if (d == NULL) { |
if (d == NULL) { |
210 |
} |
} |
211 |
memset(d, 0, sizeof(struct bebox_data)); |
memset(d, 0, sizeof(struct bebox_data)); |
212 |
|
|
213 |
memory_device_register(devinit->machine->memory, devinit->name, |
/* Connect to the two BeBox CPUs: */ |
214 |
|
for (i=0; i<2; i++) { |
215 |
|
if (i >= machine->ncpus) { |
216 |
|
fatal("FATAL ERROR: The machine seem to be " |
217 |
|
"lacking cpu nr %i (0-based)\n", i); |
218 |
|
exit(1); |
219 |
|
} |
220 |
|
|
221 |
|
snprintf(n, sizeof(n), "%s.cpu[%i]", machine->path, i); |
222 |
|
INTERRUPT_CONNECT(n, d->cpu_irq[i]); |
223 |
|
} |
224 |
|
|
225 |
|
/* |
226 |
|
* Register the 32 BeBox interrupts: |
227 |
|
* |
228 |
|
* NOTE: They are registered on cpu[0], but the interrupt assert/ |
229 |
|
* deassert routines in this file make sure that the interrupts |
230 |
|
* are routed to the correct cpu! |
231 |
|
*/ |
232 |
|
for (i=0; i<32; i++) { |
233 |
|
struct interrupt template; |
234 |
|
snprintf(n, sizeof(n), "%s.bebox.%i", |
235 |
|
devinit->interrupt_path, i); |
236 |
|
memset(&template, 0, sizeof(template)); |
237 |
|
template.line = 1 << i; |
238 |
|
template.name = n; |
239 |
|
template.extra = d; |
240 |
|
template.interrupt_assert = bebox_interrupt_assert; |
241 |
|
template.interrupt_deassert = bebox_interrupt_deassert; |
242 |
|
interrupt_handler_register(&template); |
243 |
|
} |
244 |
|
|
245 |
|
memory_device_register(machine->memory, devinit->name, |
246 |
0x7ffff000, 0x500, dev_bebox_access, d, DM_DEFAULT, NULL); |
0x7ffff000, 0x500, dev_bebox_access, d, DM_DEFAULT, NULL); |
247 |
|
|
248 |
devinit->return_ptr = d; |
devinit->return_ptr = d; |