dev_bebox.cc Source File

Back to the index.

dev_bebox.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: BeBox motherboard registers and interrupt controller
29  *
30  * See the following URL for more information:
31  *
32  * http://www.bebox.nu/history.php?s=history/benews/benews27
33  *
34  * These interrupt numbers are from NetBSD's bebox/extint.c:
35  *
36  * serial3 6
37  * serial4 7
38  * midi1 8
39  * midi2 9
40  * scsi 10
41  * pci1 11
42  * pci2 12
43  * pci3 13
44  * sound 14
45  * 8259 26
46  * irda 27
47  * a2d 28
48  * geekport 29
49  *
50  * Note that these are in IBM order, i.e. reversed. So 8259 interrupts
51  * go to interrupt 31 - 26 = 5, when using normal numbers.
52  *
53  * Interrupt routing should work to both CPUs, but I've only ever seen the
54  * first CPU being used by NetBSD/bebox, so the second CPU is untested :-)
55  */
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #include "cpu.h"
62 #include "device.h"
63 #include "interrupt.h"
64 #include "machine.h"
65 #include "memory.h"
66 #include "misc.h"
67 
68 
69 struct bebox_data {
70  struct interrupt cpu_irq[2];
71 
72  /* The 5 motherboard registers: */
73  uint32_t cpu0_int_mask;
74  uint32_t cpu1_int_mask;
75  uint32_t int_status;
76  uint32_t xpi;
77  uint32_t resets;
78 };
79 
80 
81 static void bebox_interrupt_assert(struct interrupt *interrupt)
82 {
83  struct bebox_data *d = (struct bebox_data *) interrupt->extra;
84  d->int_status |= interrupt->line;
85 
86  /* printf("STATUS %08x CPU0 %08x CPU1 %08x\n",
87  d->int_status, d->cpu0_int_mask, d->cpu1_int_mask); */
88 
89  if (d->int_status & d->cpu0_int_mask)
91  if (d->int_status & d->cpu1_int_mask)
93 }
94 static void bebox_interrupt_deassert(struct interrupt *interrupt)
95 {
96  struct bebox_data *d = (struct bebox_data *) interrupt->extra;
97  d->int_status &= ~interrupt->line;
98 
99  if (!(d->int_status & d->cpu0_int_mask))
101  if (!(d->int_status & d->cpu1_int_mask))
103 }
104 
105 
106 /*
107  * check_cpu_masks():
108  *
109  * BeBox interrupt enable bits are not allowed to be present in
110  * both CPUs at the same time.
111  */
112 static void check_cpu_masks(struct cpu *cpu, struct bebox_data *d)
113 {
114  d->cpu0_int_mask &= 0x7fffffff;
115  d->cpu1_int_mask &= 0x7fffffff;
116  if ((d->cpu0_int_mask | d->cpu1_int_mask) !=
117  (d->cpu0_int_mask ^ d->cpu1_int_mask))
118  fatal("check_cpu_masks(): BeBox cpu int masks collide!\n");
119 }
120 
121 
123 {
124  struct bebox_data *d = (struct bebox_data *) extra;
125  uint64_t idata = 0, odata = 0;
126 
127  if (writeflag == MEM_WRITE)
128  idata = memory_readmax64(cpu, data, len);
129 
130  switch (relative_addr) {
131 
132  case 0x0f0:
133  if (writeflag == MEM_READ)
134  odata = d->cpu0_int_mask;
135  else {
136  if (idata & 0x80000000)
137  d->cpu0_int_mask |= idata;
138  else
139  d->cpu0_int_mask &= ~idata;
140  check_cpu_masks(cpu, d);
141  }
142  break;
143 
144  case 0x1f0:
145  if (writeflag == MEM_READ)
146  odata = d->cpu1_int_mask;
147  else {
148  if (idata & 0x80000000)
149  d->cpu1_int_mask |= idata;
150  else
151  d->cpu1_int_mask &= ~idata;
152  check_cpu_masks(cpu, d);
153  }
154  break;
155 
156  case 0x2f0:
157  if (writeflag == MEM_READ)
158  odata = d->int_status;
159  else {
160  if (idata & 0x80000000)
161  d->int_status |= idata;
162  else
163  d->int_status &= ~idata;
164  d->int_status &= 0x7fffffff;
165  }
166  break;
167 
168  case 0x3f0:
169  if (writeflag == MEM_READ) {
170  odata = d->xpi;
171 
172  /* Bit 6 (counted from the left) is cpuid: */
173  odata &= ~0x02000000;
174  if (cpu->cpu_id == 1)
175  odata |= 0x02000000;
176  } else {
177  fatal("[ bebox: unimplemented write to 0x3f0:"
178  " 0x%08x ]\n", (int)idata);
179  }
180  break;
181  default:
182  if (writeflag==MEM_READ) {
183  fatal("[ bebox: unimplemented read from 0x%08lx ]\n",
184  (long)relative_addr);
185  } else {
186  fatal("[ bebox: unimplemented write to 0x%08lx: 0x"
187  "%08x ]\n", (long)relative_addr, (int)idata);
188  }
189  }
190 
191  if (writeflag == MEM_READ)
192  memory_writemax64(cpu, data, len, odata);
193 
194  return 1;
195 }
196 
197 
198 DEVINIT(bebox)
199 {
200  struct bebox_data *d;
201  int i;
202  char n[300];
203  struct machine *machine = devinit->machine;
204 
205  CHECK_ALLOCATION(d = (struct bebox_data *) malloc(sizeof(struct bebox_data)));
206  memset(d, 0, sizeof(struct bebox_data));
207 
208  /* Connect to the two BeBox CPUs: */
209  for (i=0; i<2; i++) {
210  if (i >= machine->ncpus) {
211  fatal("FATAL ERROR: The machine seem to be "
212  "lacking cpu nr %i (0-based)\n", i);
213  exit(1);
214  }
215 
216  snprintf(n, sizeof(n), "%s.cpu[%i]", machine->path, i);
217  INTERRUPT_CONNECT(n, d->cpu_irq[i]);
218  }
219 
220  /*
221  * Register the 32 BeBox interrupts:
222  *
223  * NOTE: They are registered on cpu[0], but the interrupt assert/
224  * deassert routines in this file make sure that the interrupts
225  * are routed to the correct cpu!
226  */
227  for (i=0; i<32; i++) {
228  struct interrupt templ;
229  snprintf(n, sizeof(n), "%s.bebox.%i",
230  devinit->interrupt_path, i);
231  memset(&templ, 0, sizeof(templ));
232  templ.line = 1 << i;
233  templ.name = n;
234  templ.extra = d;
235  templ.interrupt_assert = bebox_interrupt_assert;
236  templ.interrupt_deassert = bebox_interrupt_deassert;
238  }
239 
241  0x7ffff000, 0x500, dev_bebox_access, d, DM_DEFAULT, NULL);
242 
243  devinit->return_ptr = d;
244 
245  return 1;
246 }
247 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
void fatal(const char *fmt,...)
Definition: main.cc:152
uint32_t resets
Definition: dev_bebox.cc:77
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define DM_DEFAULT
Definition: memory.h:130
char * name
Definition: device.h:43
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
#define MEM_READ
Definition: memory.h:116
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
struct memory * memory
Definition: machine.h:126
DEVICE_ACCESS(bebox)
Definition: dev_bebox.cc:122
uint32_t cpu0_int_mask
Definition: dev_bebox.cc:73
void * return_ptr
Definition: device.h:56
uint32_t int_status
Definition: dev_bebox.cc:75
int ncpus
Definition: machine.h:139
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
char * path
Definition: machine.h:108
u_short data
Definition: siireg.h:79
uint32_t cpu1_int_mask
Definition: dev_bebox.cc:74
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
#define MEM_WRITE
Definition: memory.h:117
Definition: device.h:40
int cpu_id
Definition: cpu.h:359
uint32_t line
Definition: interrupt.h:51
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
struct machine * machine
Definition: device.h:41
char * name
Definition: interrupt.h:66
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
struct interrupt cpu_irq[2]
Definition: dev_bebox.cc:70
DEVINIT(bebox)
Definition: dev_bebox.cc:198
addr & if(addr >=0x24 &&page !=NULL)
void * extra
Definition: interrupt.h:59
uint32_t xpi
Definition: dev_bebox.cc:76
char * interrupt_path
Definition: device.h:50
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13