Revision e80cfcfc
b/Makefile | ||
---|---|---|
50 | 50 |
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \ |
51 | 51 |
pc-bios/vgabios-cirrus.bin \ |
52 | 52 |
pc-bios/ppc_rom.bin \ |
53 |
pc-bios/proll.bin \
|
|
53 |
pc-bios/proll.elf \
|
|
54 | 54 |
pc-bios/linux_boot.bin "$(datadir)" |
55 | 55 |
mkdir -p "$(docdir)" |
56 | 56 |
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)" |
... | ... | |
107 | 107 |
$(datadir)/vgabios.bin \ |
108 | 108 |
$(datadir)/vgabios-cirrus.bin \ |
109 | 109 |
$(datadir)/ppc_rom.bin \ |
110 |
$(datadir)/proll.bin \
|
|
110 |
$(datadir)/proll.elf \
|
|
111 | 111 |
$(datadir)/linux_boot.bin \ |
112 | 112 |
$(docdir)/qemu-doc.html \ |
113 | 113 |
$(docdir)/qemu-tech.html \ |
b/Makefile.target | ||
---|---|---|
175 | 175 |
|
176 | 176 |
ifeq ($(CONFIG_DARWIN),yes) |
177 | 177 |
OP_CFLAGS+= -mdynamic-no-pic |
178 |
LIBS+=-lmx |
|
178 | 179 |
endif |
179 | 180 |
|
180 | 181 |
######################################################### |
... | ... | |
300 | 301 |
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o |
301 | 302 |
endif |
302 | 303 |
ifeq ($(TARGET_ARCH), sparc) |
303 |
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
|
|
304 |
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o
|
|
304 | 305 |
endif |
305 | 306 |
ifdef CONFIG_GDBSTUB |
306 | 307 |
VL_OBJS+=gdbstub.o |
b/cpu-exec.c | ||
---|---|---|
261 | 261 |
} |
262 | 262 |
#elif defined(TARGET_SPARC) |
263 | 263 |
if (interrupt_request & CPU_INTERRUPT_HARD) { |
264 |
do_interrupt(0, 0, 0, 0, 0);
|
|
264 |
do_interrupt(env->interrupt_index, 0, 0, 0, 0);
|
|
265 | 265 |
env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
266 | 266 |
} else if (interrupt_request & CPU_INTERRUPT_TIMER) { |
267 | 267 |
//do_interrupt(0, 0, 0, 0, 0); |
b/disas.c | ||
---|---|---|
9 | 9 |
#include "disas.h" |
10 | 10 |
|
11 | 11 |
/* Filled in by elfload.c. Simplistic, but will do for now. */ |
12 |
unsigned int disas_num_syms; |
|
13 |
void *disas_symtab; |
|
14 |
const char *disas_strtab; |
|
12 |
struct syminfo *syminfos = NULL; |
|
15 | 13 |
|
16 | 14 |
/* Get LENGTH bytes from info's buffer, at target address memaddr. |
17 | 15 |
Transfer them to myaddr. */ |
... | ... | |
203 | 201 |
{ |
204 | 202 |
unsigned int i; |
205 | 203 |
/* Hack, because we know this is x86. */ |
206 |
Elf32_Sym *sym = disas_symtab; |
|
207 |
|
|
208 |
for (i = 0; i < disas_num_syms; i++) { |
|
209 |
if (sym[i].st_shndx == SHN_UNDEF |
|
210 |
|| sym[i].st_shndx >= SHN_LORESERVE) |
|
211 |
continue; |
|
212 |
|
|
213 |
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC) |
|
214 |
continue; |
|
215 |
|
|
216 |
if ((long)orig_addr >= sym[i].st_value |
|
217 |
&& (long)orig_addr < sym[i].st_value + sym[i].st_size) |
|
218 |
return disas_strtab + sym[i].st_name; |
|
204 |
Elf32_Sym *sym; |
|
205 |
struct syminfo *s; |
|
206 |
|
|
207 |
for (s = syminfos; s; s = s->next) { |
|
208 |
sym = s->disas_symtab; |
|
209 |
for (i = 0; i < s->disas_num_syms; i++) { |
|
210 |
if (sym[i].st_shndx == SHN_UNDEF |
|
211 |
|| sym[i].st_shndx >= SHN_LORESERVE) |
|
212 |
continue; |
|
213 |
|
|
214 |
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC) |
|
215 |
continue; |
|
216 |
|
|
217 |
if ((long)orig_addr >= sym[i].st_value |
|
218 |
&& (long)orig_addr < sym[i].st_value + sym[i].st_size) |
|
219 |
return s->disas_strtab + sym[i].st_name; |
|
220 |
} |
|
219 | 221 |
} |
220 | 222 |
return ""; |
221 | 223 |
} |
b/disas.h | ||
---|---|---|
9 | 9 |
const char *lookup_symbol(void *orig_addr); |
10 | 10 |
|
11 | 11 |
/* Filled in by elfload.c. Simplistic, but will do for now. */ |
12 |
extern unsigned int disas_num_syms; |
|
13 |
extern void *disas_symtab; /* FIXME: includes are a mess --RR */ |
|
14 |
extern const char *disas_strtab; |
|
12 |
extern struct syminfo { |
|
13 |
unsigned int disas_num_syms; |
|
14 |
void *disas_symtab; |
|
15 |
const char *disas_strtab; |
|
16 |
struct syminfo *next; |
|
17 |
} *syminfos; |
|
18 |
|
|
15 | 19 |
#endif /* _QEMU_DISAS_H */ |
b/gdbstub.c | ||
---|---|---|
298 | 298 |
} |
299 | 299 |
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ |
300 | 300 |
registers[64] = tswapl(env->y); |
301 |
tmp = (0<<28) | (4<<24) | env->psr \ |
|
302 |
| (env->psrs? PSR_S : 0) \ |
|
303 |
| (env->psrs? PSR_PS : 0) \ |
|
304 |
| (env->psret? PSR_ET : 0) \ |
|
305 |
| env->cwp; |
|
301 |
tmp = GET_PSR(env); |
|
306 | 302 |
registers[65] = tswapl(tmp); |
307 | 303 |
registers[66] = tswapl(env->wim); |
308 | 304 |
registers[67] = tswapl(env->tbr); |
... | ... | |
317 | 313 |
|
318 | 314 |
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
319 | 315 |
{ |
320 |
uint32_t *registers = (uint32_t *)mem_buf, tmp;
|
|
316 |
uint32_t *registers = (uint32_t *)mem_buf; |
|
321 | 317 |
int i; |
322 | 318 |
|
323 | 319 |
/* fill in g0..g7 */ |
... | ... | |
334 | 330 |
} |
335 | 331 |
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ |
336 | 332 |
env->y = tswapl(registers[64]); |
337 |
tmp = tswapl(registers[65]); |
|
338 |
env->psr = tmp & ~PSR_ICC; |
|
339 |
env->psrs = (tmp & PSR_S)? 1 : 0; |
|
340 |
env->psrps = (tmp & PSR_PS)? 1 : 0; |
|
341 |
env->psret = (tmp & PSR_ET)? 1 : 0; |
|
342 |
env->cwp = (tmp & PSR_CWP); |
|
333 |
PUT_PSR(env, tswapl(registers[65])); |
|
343 | 334 |
env->wim = tswapl(registers[66]); |
344 | 335 |
env->tbr = tswapl(registers[67]); |
345 | 336 |
env->pc = tswapl(registers[68]); |
... | ... | |
495 | 486 |
/* disable single step if it was enable */ |
496 | 487 |
cpu_single_step(cpu_single_env, 0); |
497 | 488 |
|
498 |
if (reason == EXCP_DEBUG) |
|
489 |
if (reason == EXCP_DEBUG) { |
|
490 |
tb_flush(cpu_single_env); |
|
499 | 491 |
ret = SIGTRAP; |
492 |
} |
|
500 | 493 |
else |
501 | 494 |
ret = 0; |
502 | 495 |
snprintf(buf, sizeof(buf), "S%02x", ret); |
b/hw/fdc.c | ||
---|---|---|
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 |
/* |
|
25 |
* The controller is used in Sun4m systems in a slightly different |
|
26 |
* way. There are changes in DOR register and DMA is not available. |
|
27 |
*/ |
|
24 | 28 |
#include "vl.h" |
25 | 29 |
|
26 | 30 |
/********************************************************/ |
... | ... | |
90 | 94 |
uint8_t ro; /* Is read-only */ |
91 | 95 |
} fdrive_t; |
92 | 96 |
|
97 |
#ifdef TARGET_SPARC |
|
98 |
#define DMA_read_memory(a,b,c,d) |
|
99 |
#define DMA_write_memory(a,b,c,d) |
|
100 |
#define DMA_register_channel(a,b,c) |
|
101 |
#define DMA_hold_DREQ(a) |
|
102 |
#define DMA_release_DREQ(a) |
|
103 |
#define DMA_get_channel_mode(a) (0) |
|
104 |
#define DMA_schedule(a) |
|
105 |
#endif |
|
106 |
|
|
93 | 107 |
static void fd_init (fdrive_t *drv, BlockDriverState *bs) |
94 | 108 |
{ |
95 | 109 |
/* Drive */ |
... | ... | |
455 | 469 |
} |
456 | 470 |
} |
457 | 471 |
|
472 |
static CPUReadMemoryFunc *fdctrl_mem_read[3] = { |
|
473 |
fdctrl_read, |
|
474 |
fdctrl_read, |
|
475 |
fdctrl_read, |
|
476 |
}; |
|
477 |
|
|
478 |
static CPUWriteMemoryFunc *fdctrl_mem_write[3] = { |
|
479 |
fdctrl_write, |
|
480 |
fdctrl_write, |
|
481 |
fdctrl_write, |
|
482 |
}; |
|
483 |
|
|
458 | 484 |
static void fd_change_cb (void *opaque) |
459 | 485 |
{ |
460 | 486 |
fdrive_t *drv = opaque; |
... | ... | |
473 | 499 |
BlockDriverState **fds) |
474 | 500 |
{ |
475 | 501 |
fdctrl_t *fdctrl; |
476 |
// int io_mem;
|
|
502 |
int io_mem; |
|
477 | 503 |
int i; |
478 | 504 |
|
479 | 505 |
FLOPPY_DPRINTF("init controller\n"); |
... | ... | |
504 | 530 |
fdctrl_reset(fdctrl, 0); |
505 | 531 |
fdctrl->state = FD_CTRL_ACTIVE; |
506 | 532 |
if (mem_mapped) { |
507 |
FLOPPY_ERROR("memory mapped floppy not supported by now !\n"); |
|
508 |
#if 0 |
|
509 |
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write); |
|
510 |
cpu_register_physical_memory(base, 0x08, io_mem); |
|
511 |
#endif |
|
533 |
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl); |
|
534 |
cpu_register_physical_memory(io_base, 0x08, io_mem); |
|
512 | 535 |
} else { |
513 | 536 |
register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl); |
514 | 537 |
register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl); |
b/hw/iommu.c | ||
---|---|---|
117 | 117 |
uint32_t iostart; |
118 | 118 |
} IOMMUState; |
119 | 119 |
|
120 |
static IOMMUState *ps; |
|
121 |
|
|
122 | 120 |
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr) |
123 | 121 |
{ |
124 | 122 |
IOMMUState *s = opaque; |
... | ... | |
187 | 185 |
iommu_mem_writew, |
188 | 186 |
}; |
189 | 187 |
|
190 |
uint32_t iommu_translate(uint32_t addr)
|
|
188 |
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
|
|
191 | 189 |
{ |
192 |
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa; |
|
190 |
IOMMUState *s = opaque; |
|
191 |
uint32_t *iopte = (void *)(s->regs[1] << 4), pa; |
|
193 | 192 |
|
194 |
iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
|
|
195 |
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
|
|
193 |
iopte += ((addr - s->iostart) >> PAGE_SHIFT); |
|
194 |
cpu_physical_memory_read((uint32_t)iopte, (void *) &pa, 4);
|
|
196 | 195 |
bswap32s(&pa); |
197 | 196 |
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */ |
198 | 197 |
return pa + (addr & PAGE_MASK); |
199 | 198 |
} |
200 | 199 |
|
201 |
void iommu_init(uint32_t addr) |
|
200 |
static void iommu_save(QEMUFile *f, void *opaque) |
|
201 |
{ |
|
202 |
IOMMUState *s = opaque; |
|
203 |
int i; |
|
204 |
|
|
205 |
qemu_put_be32s(f, &s->addr); |
|
206 |
for (i = 0; i < sizeof(struct iommu_regs); i += 4) |
|
207 |
qemu_put_be32s(f, &s->regs[i]); |
|
208 |
qemu_put_be32s(f, &s->iostart); |
|
209 |
} |
|
210 |
|
|
211 |
static int iommu_load(QEMUFile *f, void *opaque, int version_id) |
|
212 |
{ |
|
213 |
IOMMUState *s = opaque; |
|
214 |
int i; |
|
215 |
|
|
216 |
if (version_id != 1) |
|
217 |
return -EINVAL; |
|
218 |
|
|
219 |
qemu_get_be32s(f, &s->addr); |
|
220 |
for (i = 0; i < sizeof(struct iommu_regs); i += 4) |
|
221 |
qemu_put_be32s(f, &s->regs[i]); |
|
222 |
qemu_get_be32s(f, &s->iostart); |
|
223 |
|
|
224 |
return 0; |
|
225 |
} |
|
226 |
|
|
227 |
static void iommu_reset(void *opaque) |
|
228 |
{ |
|
229 |
IOMMUState *s = opaque; |
|
230 |
|
|
231 |
memset(s->regs, 0, sizeof(struct iommu_regs)); |
|
232 |
s->iostart = 0; |
|
233 |
} |
|
234 |
|
|
235 |
void *iommu_init(uint32_t addr) |
|
202 | 236 |
{ |
203 | 237 |
IOMMUState *s; |
204 | 238 |
int iommu_io_memory; |
205 | 239 |
|
206 | 240 |
s = qemu_mallocz(sizeof(IOMMUState)); |
207 | 241 |
if (!s) |
208 |
return; |
|
242 |
return NULL;
|
|
209 | 243 |
|
210 | 244 |
s->addr = addr; |
211 | 245 |
|
... | ... | |
213 | 247 |
cpu_register_physical_memory(addr, sizeof(struct iommu_regs), |
214 | 248 |
iommu_io_memory); |
215 | 249 |
|
216 |
ps = s; |
|
250 |
register_savevm("iommu", addr, 1, iommu_save, iommu_load, s); |
|
251 |
qemu_register_reset(iommu_reset, s); |
|
252 |
return s; |
|
217 | 253 |
} |
218 | 254 |
|
b/hw/lance.c | ||
---|---|---|
147 | 147 |
}; |
148 | 148 |
|
149 | 149 |
#define LEDMA_REGS 4 |
150 |
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) |
|
150 | 151 |
#if 0 |
151 | 152 |
/* Structure to describe the current status of DMA registers on the Sparc */ |
152 | 153 |
struct sparc_dma_registers { |
... | ... | |
157 | 158 |
}; |
158 | 159 |
#endif |
159 | 160 |
|
160 |
typedef struct LEDMAState { |
|
161 |
uint32_t addr; |
|
162 |
uint32_t regs[LEDMA_REGS]; |
|
163 |
} LEDMAState; |
|
164 |
|
|
165 | 161 |
typedef struct LANCEState { |
166 |
uint32_t paddr; |
|
167 | 162 |
NetDriverState *nd; |
168 | 163 |
uint32_t leptr; |
169 | 164 |
uint16_t addr; |
170 | 165 |
uint16_t regs[LE_MAXREG]; |
171 | 166 |
uint8_t phys[6]; /* mac address */ |
172 | 167 |
int irq; |
173 |
LEDMAState *ledma; |
|
168 |
unsigned int rxptr, txptr; |
|
169 |
uint32_t ledmaregs[LEDMA_REGS]; |
|
174 | 170 |
} LANCEState; |
175 | 171 |
|
176 |
static unsigned int rxptr, txptr; |
|
177 |
|
|
178 | 172 |
static void lance_send(void *opaque); |
179 | 173 |
|
180 |
static void lance_reset(LANCEState *s)
|
|
174 |
static void lance_reset(void *opaque)
|
|
181 | 175 |
{ |
176 |
LANCEState *s = opaque; |
|
182 | 177 |
memcpy(s->phys, s->nd->macaddr, 6); |
183 |
rxptr = 0; |
|
184 |
txptr = 0; |
|
178 |
s->rxptr = 0; |
|
179 |
s->txptr = 0; |
|
180 |
memset(s->regs, 0, LE_MAXREG * 2); |
|
185 | 181 |
s->regs[LE_CSR0] = LE_C0_STOP; |
182 |
memset(s->ledmaregs, 0, LEDMA_REGS * 4); |
|
186 | 183 |
} |
187 | 184 |
|
188 | 185 |
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) |
... | ... | |
190 | 187 |
LANCEState *s = opaque; |
191 | 188 |
uint32_t saddr; |
192 | 189 |
|
193 |
saddr = addr - s->paddr;
|
|
190 |
saddr = addr & LE_MAXREG;
|
|
194 | 191 |
switch (saddr >> 1) { |
195 | 192 |
case LE_RDP: |
196 | 193 |
return s->regs[s->addr]; |
... | ... | |
208 | 205 |
uint32_t saddr; |
209 | 206 |
uint16_t reg; |
210 | 207 |
|
211 |
saddr = addr - s->paddr;
|
|
208 |
saddr = addr & LE_MAXREG;
|
|
212 | 209 |
switch (saddr >> 1) { |
213 | 210 |
case LE_RDP: |
214 | 211 |
switch(s->addr) { |
... | ... | |
292 | 289 |
static int lance_can_receive(void *opaque) |
293 | 290 |
{ |
294 | 291 |
LANCEState *s = opaque; |
295 |
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
|
|
292 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
|
|
296 | 293 |
struct lance_init_block *ib; |
297 | 294 |
int i; |
298 | 295 |
uint16_t temp; |
... | ... | |
303 | 300 |
ib = (void *) iommu_translate(dmaptr); |
304 | 301 |
|
305 | 302 |
for (i = 0; i < RX_RING_SIZE; i++) { |
306 |
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
303 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
|
|
307 | 304 |
temp &= 0xff; |
308 | 305 |
if (temp == (LE_R1_OWN)) { |
309 | 306 |
#ifdef DEBUG_LANCE |
... | ... | |
323 | 320 |
static void lance_receive(void *opaque, const uint8_t *buf, int size) |
324 | 321 |
{ |
325 | 322 |
LANCEState *s = opaque; |
326 |
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
|
|
323 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
|
|
327 | 324 |
struct lance_init_block *ib; |
328 | 325 |
unsigned int i, old_rxptr, j; |
329 | 326 |
uint16_t temp; |
... | ... | |
333 | 330 |
|
334 | 331 |
ib = (void *) iommu_translate(dmaptr); |
335 | 332 |
|
336 |
old_rxptr = rxptr; |
|
337 |
for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) { |
|
338 |
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
333 |
old_rxptr = s->rxptr;
|
|
334 |
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
|
|
335 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
|
|
339 | 336 |
if (temp == (LE_R1_OWN)) { |
340 |
rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
|
|
337 |
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
|
|
341 | 338 |
temp = size; |
342 | 339 |
bswap16s(&temp); |
343 |
cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2); |
|
340 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2);
|
|
344 | 341 |
#if 0 |
345 |
cpu_physical_memory_write(&ib->rx_buf[i], buf, size); |
|
342 |
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
|
|
346 | 343 |
#else |
347 | 344 |
for (j = 0; j < size; j++) { |
348 |
cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
|
|
345 |
cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1);
|
|
349 | 346 |
} |
350 | 347 |
#endif |
351 | 348 |
temp = LE_R1_POK; |
352 |
cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
349 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
|
|
353 | 350 |
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; |
354 | 351 |
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) |
355 | 352 |
pic_set_irq(s->irq, 1); |
... | ... | |
364 | 361 |
static void lance_send(void *opaque) |
365 | 362 |
{ |
366 | 363 |
LANCEState *s = opaque; |
367 |
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
|
|
364 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
|
|
368 | 365 |
struct lance_init_block *ib; |
369 | 366 |
unsigned int i, old_txptr, j; |
370 | 367 |
uint16_t temp; |
... | ... | |
375 | 372 |
|
376 | 373 |
ib = (void *) iommu_translate(dmaptr); |
377 | 374 |
|
378 |
old_txptr = txptr; |
|
379 |
for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) { |
|
380 |
cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); |
|
375 |
old_txptr = s->txptr;
|
|
376 |
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
|
|
377 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
|
|
381 | 378 |
if (temp == (LE_T1_POK|LE_T1_OWN)) { |
382 |
cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2); |
|
379 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2);
|
|
383 | 380 |
bswap16s(&temp); |
384 | 381 |
temp = (~temp) + 1; |
385 | 382 |
#if 0 |
386 |
cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp); |
|
383 |
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp);
|
|
387 | 384 |
#else |
388 | 385 |
for (j = 0; j < temp; j++) { |
389 |
cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
|
|
386 |
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1);
|
|
390 | 387 |
} |
391 | 388 |
#endif |
392 | 389 |
|
... | ... | |
395 | 392 |
#endif |
396 | 393 |
qemu_send_packet(s->nd, pkt_buf, temp); |
397 | 394 |
temp = LE_T1_POK; |
398 |
cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); |
|
399 |
txptr = (txptr + 1) & TX_RING_MOD_MASK;
|
|
395 |
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
|
|
396 |
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
|
|
400 | 397 |
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; |
401 | 398 |
} |
402 | 399 |
} |
... | ... | |
404 | 401 |
|
405 | 402 |
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) |
406 | 403 |
{ |
407 |
LEDMAState *s = opaque;
|
|
404 |
LANCEState *s = opaque;
|
|
408 | 405 |
uint32_t saddr; |
409 | 406 |
|
410 |
saddr = (addr - s->addr) >> 2; |
|
411 |
if (saddr < LEDMA_REGS) |
|
412 |
return s->regs[saddr]; |
|
413 |
else |
|
414 |
return 0; |
|
407 |
saddr = (addr & LEDMA_MAXADDR) >> 2; |
|
408 |
return s->ledmaregs[saddr]; |
|
415 | 409 |
} |
416 | 410 |
|
417 | 411 |
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
418 | 412 |
{ |
419 |
LEDMAState *s = opaque;
|
|
413 |
LANCEState *s = opaque;
|
|
420 | 414 |
uint32_t saddr; |
421 | 415 |
|
422 |
saddr = (addr - s->addr) >> 2; |
|
423 |
if (saddr < LEDMA_REGS) |
|
424 |
s->regs[saddr] = val; |
|
416 |
saddr = (addr & LEDMA_MAXADDR) >> 2; |
|
417 |
s->ledmaregs[saddr] = val; |
|
425 | 418 |
} |
426 | 419 |
|
427 | 420 |
static CPUReadMemoryFunc *ledma_mem_read[3] = { |
... | ... | |
436 | 429 |
ledma_mem_writel, |
437 | 430 |
}; |
438 | 431 |
|
432 |
static void lance_save(QEMUFile *f, void *opaque) |
|
433 |
{ |
|
434 |
LANCEState *s = opaque; |
|
435 |
int i; |
|
436 |
|
|
437 |
qemu_put_be32s(f, &s->leptr); |
|
438 |
qemu_put_be16s(f, &s->addr); |
|
439 |
for (i = 0; i < LE_MAXREG; i ++) |
|
440 |
qemu_put_be16s(f, &s->regs[i]); |
|
441 |
qemu_put_buffer(f, s->phys, 6); |
|
442 |
qemu_put_be32s(f, &s->irq); |
|
443 |
for (i = 0; i < LEDMA_REGS; i ++) |
|
444 |
qemu_put_be32s(f, &s->ledmaregs[i]); |
|
445 |
} |
|
446 |
|
|
447 |
static int lance_load(QEMUFile *f, void *opaque, int version_id) |
|
448 |
{ |
|
449 |
LANCEState *s = opaque; |
|
450 |
int i; |
|
451 |
|
|
452 |
if (version_id != 1) |
|
453 |
return -EINVAL; |
|
454 |
|
|
455 |
qemu_get_be32s(f, &s->leptr); |
|
456 |
qemu_get_be16s(f, &s->addr); |
|
457 |
for (i = 0; i < LE_MAXREG; i ++) |
|
458 |
qemu_get_be16s(f, &s->regs[i]); |
|
459 |
qemu_get_buffer(f, s->phys, 6); |
|
460 |
qemu_get_be32s(f, &s->irq); |
|
461 |
for (i = 0; i < LEDMA_REGS; i ++) |
|
462 |
qemu_get_be32s(f, &s->ledmaregs[i]); |
|
463 |
return 0; |
|
464 |
} |
|
465 |
|
|
439 | 466 |
void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) |
440 | 467 |
{ |
441 | 468 |
LANCEState *s; |
442 |
LEDMAState *led; |
|
443 | 469 |
int lance_io_memory, ledma_io_memory; |
444 | 470 |
|
445 | 471 |
s = qemu_mallocz(sizeof(LANCEState)); |
446 | 472 |
if (!s) |
447 | 473 |
return; |
448 | 474 |
|
449 |
s->paddr = leaddr; |
|
450 | 475 |
s->nd = nd; |
451 | 476 |
s->irq = irq; |
452 | 477 |
|
453 | 478 |
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); |
454 | 479 |
cpu_register_physical_memory(leaddr, 8, lance_io_memory); |
455 | 480 |
|
456 |
led = qemu_mallocz(sizeof(LEDMAState)); |
|
457 |
if (!led) |
|
458 |
return; |
|
459 |
|
|
460 |
s->ledma = led; |
|
461 |
led->addr = ledaddr; |
|
462 |
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led); |
|
481 |
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); |
|
463 | 482 |
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); |
464 | 483 |
|
465 | 484 |
lance_reset(s); |
466 | 485 |
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s); |
486 |
register_savevm("lance", leaddr, 1, lance_save, lance_load, s); |
|
487 |
qemu_register_reset(lance_reset, s); |
|
467 | 488 |
} |
468 | 489 |
|
b/hw/m48t08.c | ||
---|---|---|
32 | 32 |
#define NVRAM_PRINTF(fmt, args...) do { } while (0) |
33 | 33 |
#endif |
34 | 34 |
|
35 |
#define NVRAM_MAX_MEM 0xfff0 |
|
35 |
#define NVRAM_MAX_MEM 0x1ff0 |
|
36 |
#define NVRAM_MAXADDR 0x1fff |
|
36 | 37 |
|
37 | 38 |
struct m48t08_t { |
38 |
/* Hardware parameters */ |
|
39 |
int mem_index; |
|
40 |
uint32_t mem_base; |
|
41 |
uint16_t size; |
|
42 | 39 |
/* RTC management */ |
43 | 40 |
time_t time_offset; |
44 | 41 |
time_t stop_time; |
45 | 42 |
/* NVRAM storage */ |
46 |
uint8_t lock; |
|
47 |
uint16_t addr; |
|
48 | 43 |
uint8_t *buffer; |
49 | 44 |
}; |
50 | 45 |
|
... | ... | |
83 | 78 |
} |
84 | 79 |
|
85 | 80 |
/* Direct access to NVRAM */ |
86 |
void m48t08_write (m48t08_t *NVRAM, uint32_t val) |
|
81 |
void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val)
|
|
87 | 82 |
{ |
88 | 83 |
struct tm tm; |
89 | 84 |
int tmp; |
90 | 85 |
|
91 |
if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000) |
|
92 |
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val); |
|
93 |
switch (NVRAM->addr) { |
|
86 |
addr &= NVRAM_MAXADDR; |
|
87 |
switch (addr) { |
|
94 | 88 |
case 0x1FF8: |
95 | 89 |
/* control */ |
96 | 90 |
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90; |
... | ... | |
167 | 161 |
} |
168 | 162 |
break; |
169 | 163 |
default: |
170 |
/* Check lock registers state */ |
|
171 |
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) |
|
172 |
break; |
|
173 |
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) |
|
174 |
break; |
|
175 |
if (NVRAM->addr < NVRAM_MAX_MEM || |
|
176 |
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { |
|
177 |
NVRAM->buffer[NVRAM->addr] = val & 0xFF; |
|
178 |
} |
|
164 |
NVRAM->buffer[addr] = val & 0xFF; |
|
179 | 165 |
break; |
180 | 166 |
} |
181 | 167 |
} |
182 | 168 |
|
183 |
uint32_t m48t08_read (m48t08_t *NVRAM)
|
|
169 |
uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr)
|
|
184 | 170 |
{ |
185 | 171 |
struct tm tm; |
186 |
uint32_t retval = 0xFF;
|
|
172 |
uint8_t retval = 0xFF;
|
|
187 | 173 |
|
188 |
switch (NVRAM->addr) { |
|
174 |
addr &= NVRAM_MAXADDR; |
|
175 |
switch (addr) { |
|
189 | 176 |
case 0x1FF8: |
190 | 177 |
/* control */ |
191 | 178 |
goto do_read; |
... | ... | |
225 | 212 |
retval = toBCD(tm.tm_year); |
226 | 213 |
break; |
227 | 214 |
default: |
228 |
/* Check lock registers state */ |
|
229 |
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) |
|
230 |
break; |
|
231 |
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) |
|
232 |
break; |
|
233 |
if (NVRAM->addr < NVRAM_MAX_MEM || |
|
234 |
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { |
|
235 |
do_read: |
|
236 |
retval = NVRAM->buffer[NVRAM->addr]; |
|
237 |
} |
|
215 |
do_read: |
|
216 |
retval = NVRAM->buffer[addr]; |
|
238 | 217 |
break; |
239 | 218 |
} |
240 |
if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000) |
|
241 |
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval); |
|
242 |
|
|
243 | 219 |
return retval; |
244 | 220 |
} |
245 | 221 |
|
246 |
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr) |
|
247 |
{ |
|
248 |
NVRAM->addr = addr; |
|
249 |
} |
|
250 |
|
|
251 |
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock) |
|
252 |
{ |
|
253 |
NVRAM->lock ^= 1 << lock; |
|
254 |
} |
|
255 |
|
|
256 | 222 |
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
257 | 223 |
{ |
258 | 224 |
m48t08_t *NVRAM = opaque; |
259 | 225 |
|
260 |
addr -= NVRAM->mem_base; |
|
261 |
if (addr < NVRAM_MAX_MEM) |
|
262 |
NVRAM->buffer[addr] = value; |
|
226 |
m48t08_write(NVRAM, addr, value); |
|
263 | 227 |
} |
264 | 228 |
|
265 | 229 |
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
266 | 230 |
{ |
267 | 231 |
m48t08_t *NVRAM = opaque; |
268 | 232 |
|
269 |
addr -= NVRAM->mem_base; |
|
270 |
if (addr < NVRAM_MAX_MEM) { |
|
271 |
NVRAM->buffer[addr] = value >> 8; |
|
272 |
NVRAM->buffer[addr + 1] = value; |
|
273 |
} |
|
233 |
m48t08_write(NVRAM, addr, value); |
|
234 |
m48t08_write(NVRAM, addr + 1, value >> 8); |
|
274 | 235 |
} |
275 | 236 |
|
276 | 237 |
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
277 | 238 |
{ |
278 | 239 |
m48t08_t *NVRAM = opaque; |
279 | 240 |
|
280 |
addr -= NVRAM->mem_base; |
|
281 |
if (addr < NVRAM_MAX_MEM) { |
|
282 |
NVRAM->buffer[addr] = value >> 24; |
|
283 |
NVRAM->buffer[addr + 1] = value >> 16; |
|
284 |
NVRAM->buffer[addr + 2] = value >> 8; |
|
285 |
NVRAM->buffer[addr + 3] = value; |
|
286 |
} |
|
241 |
m48t08_write(NVRAM, addr, value); |
|
242 |
m48t08_write(NVRAM, addr + 1, value >> 8); |
|
243 |
m48t08_write(NVRAM, addr + 2, value >> 16); |
|
244 |
m48t08_write(NVRAM, addr + 3, value >> 24); |
|
287 | 245 |
} |
288 | 246 |
|
289 | 247 |
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) |
... | ... | |
291 | 249 |
m48t08_t *NVRAM = opaque; |
292 | 250 |
uint32_t retval = 0; |
293 | 251 |
|
294 |
addr -= NVRAM->mem_base; |
|
295 |
if (addr < NVRAM_MAX_MEM) |
|
296 |
retval = NVRAM->buffer[addr]; |
|
297 |
|
|
252 |
retval = m48t08_read(NVRAM, addr); |
|
298 | 253 |
return retval; |
299 | 254 |
} |
300 | 255 |
|
... | ... | |
303 | 258 |
m48t08_t *NVRAM = opaque; |
304 | 259 |
uint32_t retval = 0; |
305 | 260 |
|
306 |
addr -= NVRAM->mem_base; |
|
307 |
if (addr < NVRAM_MAX_MEM) { |
|
308 |
retval = NVRAM->buffer[addr] << 8; |
|
309 |
retval |= NVRAM->buffer[addr + 1]; |
|
310 |
} |
|
311 |
|
|
261 |
retval = m48t08_read(NVRAM, addr) << 8; |
|
262 |
retval |= m48t08_read(NVRAM, addr + 1); |
|
312 | 263 |
return retval; |
313 | 264 |
} |
314 | 265 |
|
... | ... | |
317 | 268 |
m48t08_t *NVRAM = opaque; |
318 | 269 |
uint32_t retval = 0; |
319 | 270 |
|
320 |
addr -= NVRAM->mem_base; |
|
321 |
if (addr < NVRAM_MAX_MEM) { |
|
322 |
retval = NVRAM->buffer[addr] << 24; |
|
323 |
retval |= NVRAM->buffer[addr + 1] << 16; |
|
324 |
retval |= NVRAM->buffer[addr + 2] << 8; |
|
325 |
retval |= NVRAM->buffer[addr + 3]; |
|
326 |
} |
|
327 |
|
|
271 |
retval = m48t08_read(NVRAM, addr) << 24; |
|
272 |
retval |= m48t08_read(NVRAM, addr + 1) << 16; |
|
273 |
retval |= m48t08_read(NVRAM, addr + 2) << 8; |
|
274 |
retval |= m48t08_read(NVRAM, addr + 3); |
|
328 | 275 |
return retval; |
329 | 276 |
} |
330 | 277 |
|
... | ... | |
340 | 287 |
&nvram_readl, |
341 | 288 |
}; |
342 | 289 |
|
290 |
static void nvram_save(QEMUFile *f, void *opaque) |
|
291 |
{ |
|
292 |
m48t08_t *s = opaque; |
|
293 |
|
|
294 |
qemu_put_be32s(f, (uint32_t *)&s->time_offset); |
|
295 |
qemu_put_be32s(f, (uint32_t *)&s->stop_time); |
|
296 |
qemu_put_buffer(f, s->buffer, 0x2000); |
|
297 |
} |
|
298 |
|
|
299 |
static int nvram_load(QEMUFile *f, void *opaque, int version_id) |
|
300 |
{ |
|
301 |
m48t08_t *s = opaque; |
|
302 |
|
|
303 |
if (version_id != 1) |
|
304 |
return -EINVAL; |
|
305 |
|
|
306 |
qemu_get_be32s(f, (uint32_t *)&s->time_offset); |
|
307 |
qemu_get_be32s(f, (uint32_t *)&s->stop_time); |
|
308 |
qemu_get_buffer(f, s->buffer, 0x2000); |
|
309 |
return 0; |
|
310 |
} |
|
311 |
|
|
312 |
static void m48t08_reset(void *opaque) |
|
313 |
{ |
|
314 |
m48t08_t *s = opaque; |
|
315 |
|
|
316 |
s->time_offset = 0; |
|
317 |
s->stop_time = 0; |
|
318 |
} |
|
319 |
|
|
320 |
|
|
343 | 321 |
/* Initialisation routine */ |
344 |
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
|
|
322 |
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size) |
|
345 | 323 |
{ |
346 | 324 |
m48t08_t *s; |
347 |
int i; |
|
348 |
unsigned char tmp = 0; |
|
325 |
int mem_index; |
|
349 | 326 |
|
350 | 327 |
s = qemu_mallocz(sizeof(m48t08_t)); |
351 | 328 |
if (!s) |
... | ... | |
355 | 332 |
qemu_free(s); |
356 | 333 |
return NULL; |
357 | 334 |
} |
358 |
s->size = size; |
|
359 |
s->mem_base = mem_base; |
|
360 |
s->addr = 0; |
|
361 | 335 |
if (mem_base != 0) { |
362 |
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
|
|
363 |
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
|
|
336 |
mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s); |
|
337 |
cpu_register_physical_memory(mem_base, 0x2000, mem_index);
|
|
364 | 338 |
} |
365 |
s->lock = 0; |
|
366 | 339 |
|
367 |
i = 0x1fd8; |
|
368 |
s->buffer[i++] = 0x01; |
|
369 |
s->buffer[i++] = 0x80; /* Sun4m OBP */ |
|
370 |
memcpy(&s->buffer[i], macaddr, 6); |
|
371 |
|
|
372 |
/* Calculate checksum */ |
|
373 |
for (i = 0x1fd8; i < 0x1fe7; i++) { |
|
374 |
tmp ^= s->buffer[i]; |
|
375 |
} |
|
376 |
s->buffer[0x1fe7] = tmp; |
|
340 |
register_savevm("nvram", mem_base, 1, nvram_save, nvram_load, s); |
|
341 |
qemu_register_reset(m48t08_reset, s); |
|
377 | 342 |
return s; |
378 | 343 |
} |
379 | 344 |
|
b/hw/m48t08.h | ||
---|---|---|
3 | 3 |
|
4 | 4 |
typedef struct m48t08_t m48t08_t; |
5 | 5 |
|
6 |
void m48t08_write (m48t08_t *NVRAM, uint32_t val); |
|
7 |
uint32_t m48t08_read (m48t08_t *NVRAM); |
|
8 |
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr); |
|
9 |
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock); |
|
10 |
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr); |
|
6 |
void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val); |
|
7 |
uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr); |
|
8 |
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size); |
|
11 | 9 |
|
12 | 10 |
#endif /* !defined (__M48T08_H__) */ |
b/hw/magic-load.c | ||
---|---|---|
1 | 1 |
#include "vl.h" |
2 | 2 |
#include "disas.h" |
3 |
#include "exec-all.h" |
|
4 |
|
|
5 |
struct exec |
|
6 |
{ |
|
7 |
uint32_t a_info; /* Use macros N_MAGIC, etc for access */ |
|
8 |
uint32_t a_text; /* length of text, in bytes */ |
|
9 |
uint32_t a_data; /* length of data, in bytes */ |
|
10 |
uint32_t a_bss; /* length of uninitialized data area, in bytes */ |
|
11 |
uint32_t a_syms; /* length of symbol table data in file, in bytes */ |
|
12 |
uint32_t a_entry; /* start address */ |
|
13 |
uint32_t a_trsize; /* length of relocation info for text, in bytes */ |
|
14 |
uint32_t a_drsize; /* length of relocation info for data, in bytes */ |
|
15 |
}; |
|
16 |
|
|
17 |
#ifdef BSWAP_NEEDED |
|
18 |
static void bswap_ahdr(struct exec *e) |
|
19 |
{ |
|
20 |
bswap32s(&e->a_info); |
|
21 |
bswap32s(&e->a_text); |
|
22 |
bswap32s(&e->a_data); |
|
23 |
bswap32s(&e->a_bss); |
|
24 |
bswap32s(&e->a_syms); |
|
25 |
bswap32s(&e->a_entry); |
|
26 |
bswap32s(&e->a_trsize); |
|
27 |
bswap32s(&e->a_drsize); |
|
28 |
} |
|
29 |
#else |
|
30 |
#define bswap_ahdr(x) do { } while (0) |
|
31 |
#endif |
|
32 |
|
|
33 |
#define N_MAGIC(exec) ((exec).a_info & 0xffff) |
|
34 |
#define OMAGIC 0407 |
|
35 |
#define NMAGIC 0410 |
|
36 |
#define ZMAGIC 0413 |
|
37 |
#define QMAGIC 0314 |
|
38 |
#define _N_HDROFF(x) (1024 - sizeof (struct exec)) |
|
39 |
#define N_TXTOFF(x) \ |
|
40 |
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ |
|
41 |
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) |
|
42 |
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0) |
|
43 |
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) |
|
44 |
#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1)) |
|
45 |
|
|
46 |
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) |
|
47 |
|
|
48 |
#define N_DATADDR(x) \ |
|
49 |
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ |
|
50 |
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) |
|
51 |
|
|
3 | 52 |
|
4 | 53 |
#define ELF_CLASS ELFCLASS32 |
5 | 54 |
#define ELF_DATA ELFDATA2MSB |
... | ... | |
103 | 152 |
return NULL; |
104 | 153 |
} |
105 | 154 |
|
106 |
static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
|
|
155 |
static void *find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
|
|
107 | 156 |
{ |
108 | 157 |
int retval; |
109 | 158 |
|
110 | 159 |
retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET); |
111 | 160 |
if (retval < 0) |
112 |
return -1;
|
|
161 |
return NULL;
|
|
113 | 162 |
|
114 | 163 |
retval = read(fd, shdr, sizeof(*shdr)); |
115 | 164 |
if (retval < 0) |
116 |
return -1;
|
|
165 |
return NULL;
|
|
117 | 166 |
bswap_shdr(shdr); |
118 | 167 |
if (shdr->sh_type == SHT_STRTAB) |
119 | 168 |
return qemu_malloc(shdr->sh_size);; |
120 |
return 0;
|
|
169 |
return NULL;
|
|
121 | 170 |
} |
122 | 171 |
|
123 |
static int read_program(int fd, struct elf_phdr *phdr, void *dst) |
|
172 |
static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
|
|
124 | 173 |
{ |
125 | 174 |
int retval; |
126 |
retval = lseek(fd, 0x4000, SEEK_SET);
|
|
175 |
retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
|
|
127 | 176 |
if (retval < 0) |
128 | 177 |
return -1; |
129 | 178 |
return read(fd, dst, phdr->p_filesz); |
... | ... | |
178 | 227 |
{ |
179 | 228 |
struct elf_shdr symtab, strtab; |
180 | 229 |
struct elf_sym *syms; |
230 |
struct syminfo *s; |
|
181 | 231 |
int nsyms, i; |
182 | 232 |
char *str; |
183 | 233 |
|
... | ... | |
196 | 246 |
goto error_freesyms; |
197 | 247 |
|
198 | 248 |
/* Commit */ |
199 |
if (disas_symtab) |
|
200 |
qemu_free(disas_symtab); /* XXX Merge with old symbols? */ |
|
201 |
if (disas_strtab) |
|
202 |
qemu_free(disas_strtab); |
|
203 |
disas_symtab = syms; |
|
204 |
disas_num_syms = nsyms; |
|
205 |
disas_strtab = str; |
|
249 |
s = qemu_mallocz(sizeof(*s)); |
|
250 |
s->disas_symtab = syms; |
|
251 |
s->disas_num_syms = nsyms; |
|
252 |
s->disas_strtab = str; |
|
253 |
s->next = syminfos; |
|
254 |
syminfos = s; |
|
206 | 255 |
return; |
207 | 256 |
error_freesyms: |
208 | 257 |
qemu_free(syms); |
209 | 258 |
return; |
210 | 259 |
} |
211 | 260 |
|
212 |
int load_elf(const char * filename, uint8_t *addr)
|
|
261 |
int load_elf(const char *filename, uint8_t *addr) |
|
213 | 262 |
{ |
214 | 263 |
struct elfhdr ehdr; |
215 | 264 |
struct elf_phdr phdr; |
... | ... | |
227 | 276 |
|
228 | 277 |
if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E' |
229 | 278 |
|| ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F' |
230 |
|| ehdr.e_machine != EM_SPARC) |
|
279 |
|| (ehdr.e_machine != EM_SPARC |
|
280 |
&& ehdr.e_machine != EM_SPARC32PLUS)) |
|
231 | 281 |
goto error; |
232 | 282 |
|
233 | 283 |
if (find_phdr(&ehdr, fd, &phdr, PT_LOAD)) |
234 | 284 |
goto error; |
235 |
retval = read_program(fd, &phdr, addr); |
|
285 |
retval = read_program(fd, &phdr, addr, ehdr.e_entry);
|
|
236 | 286 |
if (retval < 0) |
237 | 287 |
goto error; |
238 | 288 |
|
... | ... | |
245 | 295 |
return -1; |
246 | 296 |
} |
247 | 297 |
|
248 |
int load_kernel(const char *filename, uint8_t *addr)
|
|
298 |
int load_aout(const char *filename, uint8_t *addr)
|
|
249 | 299 |
{ |
250 |
int fd, size; |
|
300 |
int fd, size, ret; |
|
301 |
struct exec e; |
|
302 |
uint32_t magic; |
|
251 | 303 |
|
252 | 304 |
fd = open(filename, O_RDONLY | O_BINARY); |
253 | 305 |
if (fd < 0) |
254 | 306 |
return -1; |
255 |
/* load 32 bit code */ |
|
256 |
size = read(fd, addr, 16 * 1024 * 1024);
|
|
307 |
|
|
308 |
size = read(fd, &e, sizeof(e));
|
|
257 | 309 |
if (size < 0) |
258 | 310 |
goto fail; |
311 |
|
|
312 |
bswap_ahdr(&e); |
|
313 |
|
|
314 |
magic = N_MAGIC(e); |
|
315 |
switch (magic) { |
|
316 |
case ZMAGIC: |
|
317 |
case QMAGIC: |
|
318 |
case OMAGIC: |
|
319 |
lseek(fd, N_TXTOFF(e), SEEK_SET); |
|
320 |
size = read(fd, addr, e.a_text + e.a_data); |
|
321 |
if (size < 0) |
|
322 |
goto fail; |
|
323 |
break; |
|
324 |
case NMAGIC: |
|
325 |
lseek(fd, N_TXTOFF(e), SEEK_SET); |
|
326 |
size = read(fd, addr, e.a_text); |
|
327 |
if (size < 0) |
|
328 |
goto fail; |
|
329 |
ret = read(fd, addr + N_DATADDR(e), e.a_data); |
|
330 |
if (ret < 0) |
|
331 |
goto fail; |
|
332 |
size += ret; |
|
333 |
break; |
|
334 |
default: |
|
335 |
goto fail; |
|
336 |
} |
|
259 | 337 |
close(fd); |
260 | 338 |
return size; |
261 | 339 |
fail: |
... | ... | |
263 | 341 |
return -1; |
264 | 342 |
} |
265 | 343 |
|
266 |
typedef struct MAGICState { |
|
267 |
uint32_t addr; |
|
268 |
uint32_t saved_addr; |
|
269 |
int magic_state; |
|
270 |
char saved_kfn[1024]; |
|
271 |
} MAGICState; |
|
272 |
|
|
273 |
static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr) |
|
274 |
{ |
|
275 |
int ret; |
|
276 |
MAGICState *s = opaque; |
|
277 |
|
|
278 |
if (s->magic_state == 0) { |
|
279 |
ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr); |
|
280 |
if (ret < 0) |
|
281 |
ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr); |
|
282 |
if (ret < 0) { |
|
283 |
fprintf(stderr, "qemu: could not load kernel '%s'\n", |
|
284 |
s->saved_kfn); |
|
285 |
} |
|
286 |
s->magic_state = 1; /* No more magic */ |
|
287 |
tb_flush(); |
|
288 |
return bswap32(ret); |
|
289 |
} |
|
290 |
return 0; |
|
291 |
} |
|
292 |
|
|
293 |
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
294 |
{ |
|
295 |
} |
|
296 |
|
|
297 |
|
|
298 |
static CPUReadMemoryFunc *magic_mem_read[3] = { |
|
299 |
magic_mem_readl, |
|
300 |
magic_mem_readl, |
|
301 |
magic_mem_readl, |
|
302 |
}; |
|
303 |
|
|
304 |
static CPUWriteMemoryFunc *magic_mem_write[3] = { |
|
305 |
magic_mem_writel, |
|
306 |
magic_mem_writel, |
|
307 |
magic_mem_writel, |
|
308 |
}; |
|
309 |
|
|
310 |
void magic_init(const char *kfn, int kloadaddr, uint32_t addr) |
|
311 |
{ |
|
312 |
int magic_io_memory; |
|
313 |
MAGICState *s; |
|
314 |
|
|
315 |
s = qemu_mallocz(sizeof(MAGICState)); |
|
316 |
if (!s) |
|
317 |
return; |
|
318 |
|
|
319 |
strcpy(s->saved_kfn, kfn); |
|
320 |
s->saved_addr = kloadaddr; |
|
321 |
s->magic_state = 0; |
|
322 |
s->addr = addr; |
|
323 |
magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s); |
|
324 |
cpu_register_physical_memory(addr, 4, magic_io_memory); |
|
325 |
} |
|
326 |
|
/dev/null | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU interrupt controller emulation |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2004 Fabrice Bellard |
|
5 |
* |
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
* of this software and associated documentation files (the "Software"), to deal |
|
8 |
* in the Software without restriction, including without limitation the rights |
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
* copies of the Software, and to permit persons to whom the Software is |
|
11 |
* furnished to do so, subject to the following conditions: |
|
12 |
* |
|
13 |
* The above copyright notice and this permission notice shall be included in |
|
14 |
* all copies or substantial portions of the Software. |
|
15 |
* |
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 |
* THE SOFTWARE. |
|
23 |
*/ |
|
24 |
#include "vl.h" |
|
25 |
//#define DEBUG_IRQ_COUNT |
|
26 |
|
|
27 |
/* These registers are used for sending/receiving irqs from/to |
|
28 |
* different cpu's. |
|
29 |
*/ |
|
30 |
struct sun4m_intreg_percpu { |
|
31 |
unsigned int tbt; /* Intrs pending for this cpu, by PIL. */ |
|
32 |
/* These next two registers are WRITE-ONLY and are only |
|
33 |
* "on bit" sensitive, "off bits" written have NO affect. |
|
34 |
*/ |
|
35 |
unsigned int clear; /* Clear this cpus irqs here. */ |
|
36 |
unsigned int set; /* Set this cpus irqs here. */ |
|
37 |
}; |
|
38 |
/* |
|
39 |
* djhr |
|
40 |
* Actually the clear and set fields in this struct are misleading.. |
|
41 |
* according to the SLAVIO manual (and the same applies for the SEC) |
|
42 |
* the clear field clears bits in the mask which will ENABLE that IRQ |
|
43 |
* the set field sets bits in the mask to DISABLE the IRQ. |
|
44 |
* |
|
45 |
* Also the undirected_xx address in the SLAVIO is defined as |
|
46 |
* RESERVED and write only.. |
|
47 |
* |
|
48 |
* DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor |
|
49 |
* sun4m machines, for MP the layout makes more sense. |
|
50 |
*/ |
|
51 |
struct sun4m_intreg_master { |
|
52 |
unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */ |
|
53 |
unsigned int irqs; /* Master IRQ bits. */ |
|
54 |
|
|
55 |
/* Again, like the above, two these registers are WRITE-ONLY. */ |
|
56 |
unsigned int clear; /* Clear master IRQ's by setting bits here. */ |
|
57 |
unsigned int set; /* Set master IRQ's by setting bits here. */ |
|
58 |
|
|
59 |
/* This register is both READ and WRITE. */ |
|
60 |
unsigned int undirected_target; /* Which cpu gets undirected irqs. */ |
|
61 |
}; |
|
62 |
|
|
63 |
#define SUN4M_INT_ENABLE 0x80000000 |
|
64 |
#define SUN4M_INT_E14 0x00000080 |
|
65 |
#define SUN4M_INT_E10 0x00080000 |
|
66 |
|
|
67 |
#define SUN4M_HARD_INT(x) (0x000000001 << (x)) |
|
68 |
#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) |
|
69 |
|
|
70 |
#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ |
|
71 |
#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ |
|
72 |
#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ |
|
73 |
#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ |
|
74 |
#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ |
|
75 |
#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ |
|
76 |
#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ |
|
77 |
#define SUN4M_INT_REALTIME 0x00080000 /* system timer */ |
|
78 |
#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ |
|
79 |
#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ |
|
80 |
#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ |
|
81 |
#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ |
|
82 |
#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ |
|
83 |
|
|
84 |
#define SUN4M_INT_SBUS(x) (1 << (x+7)) |
|
85 |
#define SUN4M_INT_VME(x) (1 << (x)) |
|
86 |
|
|
87 |
typedef struct SCHEDState { |
|
88 |
uint32_t addr, addrg; |
|
89 |
uint32_t intreg_pending; |
|
90 |
uint32_t intreg_enabled; |
|
91 |
uint32_t intregm_pending; |
|
92 |
uint32_t intregm_enabled; |
|
93 |
} SCHEDState; |
|
94 |
|
|
95 |
static SCHEDState *ps; |
|
96 |
|
|
97 |
#ifdef DEBUG_IRQ_COUNT |
|
98 |
static uint64_t irq_count[32]; |
|
99 |
#endif |
|
100 |
|
|
101 |
static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr) |
|
102 |
{ |
|
103 |
SCHEDState *s = opaque; |
|
104 |
uint32_t saddr; |
|
105 |
|
|
106 |
saddr = (addr - s->addr) >> 2; |
|
107 |
switch (saddr) { |
|
108 |
case 0: |
|
109 |
return s->intreg_pending; |
|
110 |
break; |
|
111 |
default: |
|
112 |
break; |
|
113 |
} |
|
114 |
return 0; |
|
115 |
} |
|
116 |
|
|
117 |
static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
118 |
{ |
|
119 |
SCHEDState *s = opaque; |
|
120 |
uint32_t saddr; |
|
121 |
|
|
122 |
saddr = (addr - s->addr) >> 2; |
|
123 |
switch (saddr) { |
|
124 |
case 0: |
|
125 |
s->intreg_pending = val; |
|
126 |
break; |
|
127 |
case 1: // clear |
|
128 |
s->intreg_enabled &= ~val; |
|
129 |
break; |
|
130 |
case 2: // set |
|
131 |
s->intreg_enabled |= val; |
|
132 |
break; |
|
133 |
default: |
|
134 |
break; |
|
135 |
} |
|
136 |
} |
|
137 |
|
|
138 |
static CPUReadMemoryFunc *intreg_mem_read[3] = { |
|
139 |
intreg_mem_readl, |
|
140 |
intreg_mem_readl, |
|
141 |
intreg_mem_readl, |
|
142 |
}; |
|
143 |
|
|
144 |
static CPUWriteMemoryFunc *intreg_mem_write[3] = { |
|
145 |
intreg_mem_writel, |
|
146 |
intreg_mem_writel, |
|
147 |
intreg_mem_writel, |
|
148 |
}; |
|
149 |
|
|
150 |
static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr) |
|
151 |
{ |
|
152 |
SCHEDState *s = opaque; |
|
153 |
uint32_t saddr; |
|
154 |
|
|
155 |
saddr = (addr - s->addrg) >> 2; |
|
156 |
switch (saddr) { |
|
157 |
case 0: |
|
158 |
return s->intregm_pending; |
|
159 |
break; |
|
160 |
case 1: |
|
161 |
return s->intregm_enabled; |
|
162 |
break; |
|
163 |
default: |
|
164 |
break; |
|
165 |
} |
|
166 |
return 0; |
|
167 |
} |
|
168 |
|
|
169 |
static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
170 |
{ |
|
171 |
SCHEDState *s = opaque; |
|
172 |
uint32_t saddr; |
|
173 |
|
|
174 |
saddr = (addr - s->addrg) >> 2; |
|
175 |
switch (saddr) { |
|
176 |
case 0: |
|
177 |
s->intregm_pending = val; |
|
178 |
break; |
|
179 |
case 1: |
|
180 |
s->intregm_enabled = val; |
|
181 |
break; |
|
182 |
case 2: // clear |
|
183 |
s->intregm_enabled &= ~val; |
|
184 |
break; |
|
185 |
case 3: // set |
|
186 |
s->intregm_enabled |= val; |
|
187 |
break; |
|
188 |
default: |
|
189 |
break; |
|
190 |
} |
|
191 |
} |
|
192 |
|
|
193 |
static CPUReadMemoryFunc *intregm_mem_read[3] = { |
|
194 |
intregm_mem_readl, |
|
195 |
intregm_mem_readl, |
|
196 |
intregm_mem_readl, |
|
197 |
}; |
|
198 |
|
|
199 |
static CPUWriteMemoryFunc *intregm_mem_write[3] = { |
|
200 |
intregm_mem_writel, |
|
201 |
intregm_mem_writel, |
|
202 |
intregm_mem_writel, |
|
203 |
}; |
|
204 |
|
|
205 |
void pic_info(void) |
|
206 |
{ |
|
207 |
term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled); |
|
208 |
term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled); |
|
209 |
} |
|
210 |
|
|
211 |
void irq_info(void) |
|
212 |
{ |
|
213 |
#ifndef DEBUG_IRQ_COUNT |
|
214 |
term_printf("irq statistic code not compiled.\n"); |
|
215 |
#else |
|
216 |
int i; |
|
217 |
int64_t count; |
|
218 |
|
|
219 |
term_printf("IRQ statistics:\n"); |
|
220 |
for (i = 0; i < 32; i++) { |
|
221 |
count = irq_count[i]; |
|
222 |
if (count > 0) |
|
223 |
term_printf("%2d: %lld\n", i, count); |
|
224 |
} |
|
225 |
#endif |
|
226 |
} |
|
227 |
|
|
228 |
static const unsigned int intr_to_mask[16] = { |
|
229 |
0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0, |
|
230 |
0, 0, 0, 0, 0, 0, 0, 0, |
|
231 |
}; |
|
232 |
|
|
233 |
void pic_set_irq(int irq, int level) |
|
234 |
{ |
|
235 |
if (irq < 16) { |
|
236 |
unsigned int mask = intr_to_mask[irq]; |
|
237 |
ps->intreg_pending |= 1 << irq; |
|
238 |
if (ps->intregm_enabled & mask) { |
|
239 |
cpu_single_env->interrupt_index = irq; |
|
240 |
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); |
|
241 |
} |
|
242 |
} |
|
243 |
#ifdef DEBUG_IRQ_COUNT |
|
244 |
if (level == 1) |
|
245 |
irq_count[irq]++; |
|
246 |
#endif |
|
247 |
} |
|
248 |
|
|
249 |
void sched_init(uint32_t addr, uint32_t addrg) |
|
250 |
{ |
|
251 |
int intreg_io_memory, intregm_io_memory; |
|
252 |
SCHEDState *s; |
|
253 |
|
|
254 |
s = qemu_mallocz(sizeof(SCHEDState)); |
|
255 |
if (!s) |
|
256 |
return; |
|
257 |
s->addr = addr; |
|
258 |
s->addrg = addrg; |
|
259 |
|
|
260 |
intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s); |
|
261 |
cpu_register_physical_memory(addr, 3, intreg_io_memory); |
|
262 |
|
|
263 |
intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s); |
|
264 |
cpu_register_physical_memory(addrg, 5, intregm_io_memory); |
|
265 |
|
|
266 |
ps = s; |
|
267 |
} |
|
268 |
|
b/hw/slavio_intctl.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU Sparc SLAVIO interrupt controller emulation |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2004 Fabrice Bellard |
|
5 |
* |
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
* of this software and associated documentation files (the "Software"), to deal |
|
8 |
* in the Software without restriction, including without limitation the rights |
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
* copies of the Software, and to permit persons to whom the Software is |
|
11 |
* furnished to do so, subject to the following conditions: |
|
12 |
* |
|
13 |
* The above copyright notice and this permission notice shall be included in |
|
14 |
* all copies or substantial portions of the Software. |
|
15 |
* |
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 |
* THE SOFTWARE. |
|
23 |
*/ |
|
24 |
#include "vl.h" |
|
25 |
//#define DEBUG_IRQ_COUNT |
|
26 |
|
|
27 |
/* |
|
28 |
* Registers of interrupt controller in sun4m. |
|
29 |
* |
|
30 |
* This is the interrupt controller part of chip STP2001 (Slave I/O), also |
|
31 |
* produced as NCR89C105. See |
|
32 |
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt |
|
33 |
* |
|
34 |
* There is a system master controller and one for each cpu. |
|
35 |
* |
|
36 |
*/ |
|
37 |
|
|
38 |
#define MAX_CPUS 16 |
|
39 |
|
|
40 |
typedef struct SLAVIO_INTCTLState { |
|
41 |
uint32_t intreg_pending[MAX_CPUS]; |
Also available in: Unified diff