Commit e80cfcfc8884400e826328b772971913a14d0f44

Authored by bellard
1 parent 9772c73b

SPARC merge


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1179 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -50,7 +50,7 @@ install: all
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,7 +107,7 @@ tarbin:
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 \
... ...
Makefile.target
... ... @@ -175,6 +175,7 @@ endif
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,7 +301,7 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
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
... ...
cpu-exec.c
... ... @@ -261,7 +261,7 @@ int cpu_exec(CPUState *env1)
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);
... ...
... ... @@ -9,9 +9,7 @@
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,19 +201,23 @@ const char *lookup_symbol(void *orig_addr)
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 }
... ...
... ... @@ -9,7 +9,11 @@ void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
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 */
... ...
gdbstub.c
... ... @@ -298,11 +298,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
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,7 +313,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
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,12 +330,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
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,8 +486,10 @@ static void gdb_vm_stopped(void *opaque, int reason)
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);
... ...
hw/fdc.c
... ... @@ -21,6 +21,10 @@
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,6 +94,16 @@ typedef struct fdrive_t {
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,6 +469,18 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
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,7 +499,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
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,11 +530,8 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
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);
... ...
hw/iommu.c
... ... @@ -117,8 +117,6 @@ typedef struct IOMMUState {
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,25 +185,61 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
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,6 +247,8 @@ void iommu_init(uint32_t addr)
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  
... ...
hw/lance.c
... ... @@ -147,6 +147,7 @@ struct lance_init_block {
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,32 +158,28 @@ 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,7 +187,7 @@ 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,7 +205,7 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
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,7 +289,7 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
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,7 +300,7 @@ static int lance_can_receive(void *opaque)
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,7 +320,7 @@ static int lance_can_receive(void *opaque)
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,23 +330,23 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
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,7 +361,7 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
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,18 +372,18 @@ static void lance_send(void *opaque)
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,8 +392,8 @@ static void lance_send(void *opaque)
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,24 +401,20 @@ static void lance_send(void *opaque)
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,33 +429,61 @@ static CPUWriteMemoryFunc *ledma_mem_write[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  
... ...
hw/m48t08.c
... ... @@ -32,19 +32,14 @@
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,14 +78,13 @@ static void set_time (m48t08_t *NVRAM, struct tm *tm)
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,25 +161,18 @@ void m48t08_write (m48t08_t *NVRAM, uint32_t val)
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,65 +212,36 @@ uint32_t m48t08_read (m48t08_t *NVRAM)
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,10 +249,7 @@ 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,12 +258,8 @@ static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
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,14 +268,10 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
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,12 +287,42 @@ static CPUReadMemoryFunc *nvram_read[] = {
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,25 +332,13 @@ m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
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  
... ...
hw/m48t08.h
... ... @@ -3,10 +3,8 @@
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__) */
... ...
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,27 +152,27 @@ static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint3
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,6 +227,7 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
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,20 +246,19 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
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,12 +276,13 @@ int load_elf(const char * filename, uint8_t *addr)
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,17 +295,45 @@ int load_elf(const char * filename, uint8_t *addr)
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,64 +341,3 @@ int load_kernel(const char *filename, uint8_t *addr)
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   -
... ...
hw/sched.c deleted 100644 โ†’ 0
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   -
hw/slavio_intctl.c 0 โ†’ 100644
  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];
  42 + uint32_t intregm_pending;
  43 + uint32_t intregm_disabled;
  44 + uint32_t target_cpu;
  45 +#ifdef DEBUG_IRQ_COUNT
  46 + uint64_t irq_count[32];
  47 +#endif
  48 +} SLAVIO_INTCTLState;
  49 +
  50 +#define INTCTL_MAXADDR 0xf
  51 +#define INTCTLM_MAXADDR 0xf
  52 +
  53 +// per-cpu interrupt controller
  54 +static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
  55 +{
  56 + SLAVIO_INTCTLState *s = opaque;
  57 + uint32_t saddr;
  58 + int cpu;
  59 +
  60 + cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
  61 + saddr = (addr & INTCTL_MAXADDR) >> 2;
  62 + switch (saddr) {
  63 + case 0:
  64 + return s->intreg_pending[cpu];
  65 + default:
  66 + break;
  67 + }
  68 + return 0;
  69 +}
  70 +
  71 +static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  72 +{
  73 + SLAVIO_INTCTLState *s = opaque;
  74 + uint32_t saddr;
  75 + int cpu;
  76 +
  77 + cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
  78 + saddr = (addr & INTCTL_MAXADDR) >> 2;
  79 + switch (saddr) {
  80 + case 1: // clear pending softints
  81 + if (val & 0x4000)
  82 + val |= 80000000;
  83 + val &= 0xfffe0000;
  84 + s->intreg_pending[cpu] &= ~val;
  85 + break;
  86 + case 2: // set softint
  87 + val &= 0xfffe0000;
  88 + s->intreg_pending[cpu] |= val;
  89 + break;
  90 + default:
  91 + break;
  92 + }
  93 +}
  94 +
  95 +static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
  96 + slavio_intctl_mem_readl,
  97 + slavio_intctl_mem_readl,
  98 + slavio_intctl_mem_readl,
  99 +};
  100 +
  101 +static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
  102 + slavio_intctl_mem_writel,
  103 + slavio_intctl_mem_writel,
  104 + slavio_intctl_mem_writel,
  105 +};
  106 +
  107 +// master system interrupt controller
  108 +static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
  109 +{
  110 + SLAVIO_INTCTLState *s = opaque;
  111 + uint32_t saddr;
  112 +
  113 + saddr = (addr & INTCTLM_MAXADDR) >> 2;
  114 + switch (saddr) {
  115 + case 0:
  116 + return s->intregm_pending;
  117 + case 1:
  118 + return s->intregm_disabled;
  119 + case 4:
  120 + return s->target_cpu;
  121 + default:
  122 + break;
  123 + }
  124 + return 0;
  125 +}
  126 +
  127 +static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  128 +{
  129 + SLAVIO_INTCTLState *s = opaque;
  130 + uint32_t saddr;
  131 +
  132 + saddr = (addr & INTCTLM_MAXADDR) >> 2;
  133 + switch (saddr) {
  134 + case 2: // clear (enable)
  135 + // Force unused bits
  136 + val |= 0x7fb2007f;
  137 + s->intregm_disabled &= ~val;
  138 + break;
  139 + case 3: // set (disable, clear pending)
  140 + // Force unused bits
  141 + val &= ~0x7fb2007f;
  142 + s->intregm_disabled |= val;
  143 + s->intregm_pending &= ~val;
  144 + break;
  145 + case 4:
  146 + s->target_cpu = val & (MAX_CPUS - 1);
  147 + break;
  148 + default:
  149 + break;
  150 + }
  151 +}
  152 +
  153 +static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
  154 + slavio_intctlm_mem_readl,
  155 + slavio_intctlm_mem_readl,
  156 + slavio_intctlm_mem_readl,
  157 +};
  158 +
  159 +static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
  160 + slavio_intctlm_mem_writel,
  161 + slavio_intctlm_mem_writel,
  162 + slavio_intctlm_mem_writel,
  163 +};
  164 +
  165 +void slavio_pic_info(void *opaque)
  166 +{
  167 + SLAVIO_INTCTLState *s = opaque;
  168 + int i;
  169 +
  170 + for (i = 0; i < MAX_CPUS; i++) {
  171 + term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
  172 + }
  173 + term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
  174 +}
  175 +
  176 +void slavio_irq_info(void *opaque)
  177 +{
  178 +#ifndef DEBUG_IRQ_COUNT
  179 + term_printf("irq statistic code not compiled.\n");
  180 +#else
  181 + SLAVIO_INTCTLState *s = opaque;
  182 + int i;
  183 + int64_t count;
  184 +
  185 + term_printf("IRQ statistics:\n");
  186 + for (i = 0; i < 32; i++) {
  187 + count = s->irq_count[i];
  188 + if (count > 0)
  189 + term_printf("%2d: %lld\n", i, count);
  190 + }
  191 +#endif
  192 +}
  193 +
  194 +static const uint32_t intbit_to_level[32] = {
  195 + 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
  196 + 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0,
  197 +};
  198 +
  199 +/*
  200 + * "irq" here is the bit number in the system interrupt register to
  201 + * separate serial and keyboard interrupts sharing a level.
  202 + */
  203 +void slavio_pic_set_irq(void *opaque, int irq, int level)
  204 +{
  205 + SLAVIO_INTCTLState *s = opaque;
  206 +
  207 + if (irq < 32) {
  208 + uint32_t mask = 1 << irq;
  209 + uint32_t pil = intbit_to_level[irq];
  210 + if (pil > 0) {
  211 + if (level) {
  212 + s->intregm_pending |= mask;
  213 + s->intreg_pending[s->target_cpu] |= 1 << pil;
  214 + }
  215 + else {
  216 + s->intregm_pending &= ~mask;
  217 + s->intreg_pending[s->target_cpu] &= ~(1 << pil);
  218 + }
  219 + if (level &&
  220 + !(s->intregm_disabled & mask) &&
  221 + !(s->intregm_disabled & 0x80000000) &&
  222 + (pil == 15 || (pil > cpu_single_env->psrpil && cpu_single_env->psret == 1))) {
  223 +#ifdef DEBUG_IRQ_COUNT
  224 + if (level == 1)
  225 + s->irq_count[pil]++;
  226 +#endif
  227 + cpu_single_env->interrupt_index = TT_EXTINT | pil;
  228 + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
  229 + }
  230 + }
  231 + }
  232 +}
  233 +
  234 +static void slavio_intctl_save(QEMUFile *f, void *opaque)
  235 +{
  236 + SLAVIO_INTCTLState *s = opaque;
  237 + int i;
  238 +
  239 + for (i = 0; i < MAX_CPUS; i++) {
  240 + qemu_put_be32s(f, &s->intreg_pending[i]);
  241 + }
  242 + qemu_put_be32s(f, &s->intregm_pending);
  243 + qemu_put_be32s(f, &s->intregm_disabled);
  244 + qemu_put_be32s(f, &s->target_cpu);
  245 +}
  246 +
  247 +static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
  248 +{
  249 + SLAVIO_INTCTLState *s = opaque;
  250 + int i;
  251 +
  252 + if (version_id != 1)
  253 + return -EINVAL;
  254 +
  255 + for (i = 0; i < MAX_CPUS; i++) {
  256 + qemu_get_be32s(f, &s->intreg_pending[i]);
  257 + }
  258 + qemu_get_be32s(f, &s->intregm_pending);
  259 + qemu_get_be32s(f, &s->intregm_disabled);
  260 + qemu_get_be32s(f, &s->target_cpu);
  261 + return 0;
  262 +}
  263 +
  264 +static void slavio_intctl_reset(void *opaque)
  265 +{
  266 + SLAVIO_INTCTLState *s = opaque;
  267 + int i;
  268 +
  269 + for (i = 0; i < MAX_CPUS; i++) {
  270 + s->intreg_pending[i] = 0;
  271 + }
  272 + s->intregm_disabled = 0xffffffff;
  273 + s->intregm_pending = 0;
  274 + s->target_cpu = 0;
  275 +}
  276 +
  277 +void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
  278 +{
  279 + int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
  280 + SLAVIO_INTCTLState *s;
  281 +
  282 + s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
  283 + if (!s)
  284 + return NULL;
  285 +
  286 + for (i = 0; i < MAX_CPUS; i++) {
  287 + slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
  288 + cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
  289 + }
  290 +
  291 + slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
  292 + cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
  293 +
  294 + register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
  295 + qemu_register_reset(slavio_intctl_reset, s);
  296 + slavio_intctl_reset(s);
  297 + return s;
  298 +}
  299 +
... ...
hw/slavio_serial.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU Sparc SLAVIO serial port 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 +
  26 +//#define DEBUG_SERIAL
  27 +
  28 +/* debug keyboard */
  29 +//#define DEBUG_KBD
  30 +
  31 +/* debug keyboard : only mouse */
  32 +//#define DEBUG_MOUSE
  33 +
  34 +/*
  35 + * This is the serial port, mouse and keyboard part of chip STP2001
  36 + * (Slave I/O), also produced as NCR89C105. See
  37 + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  38 + *
  39 + * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
  40 + * mouse and keyboard ports don't implement all functions and they are
  41 + * only asynchronous. There is no DMA.
  42 + *
  43 + */
  44 +
  45 +typedef struct ChannelState {
  46 + int irq;
  47 + int reg;
  48 + int rxint, txint;
  49 + uint8_t rx, tx, wregs[16], rregs[16];
  50 + CharDriverState *chr;
  51 +} ChannelState;
  52 +
  53 +struct SerialState {
  54 + struct ChannelState chn[2];
  55 +};
  56 +
  57 +#define SERIAL_MAXADDR 7
  58 +
  59 +static void slavio_serial_update_irq(ChannelState *s)
  60 +{
  61 + if ((s->wregs[1] & 1) && // interrupts enabled
  62 + (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
  63 + ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
  64 + s->rxint == 1) || // rx ints enabled, pending
  65 + ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
  66 + pic_set_irq(s->irq, 1);
  67 + } else {
  68 + pic_set_irq(s->irq, 0);
  69 + }
  70 +}
  71 +
  72 +static void slavio_serial_reset_chn(ChannelState *s)
  73 +{
  74 + int i;
  75 +
  76 + s->reg = 0;
  77 + for (i = 0; i < SERIAL_MAXADDR; i++) {
  78 + s->rregs[i] = 0;
  79 + s->wregs[i] = 0;
  80 + }
  81 + s->wregs[4] = 4;
  82 + s->wregs[9] = 0xc0;
  83 + s->wregs[11] = 8;
  84 + s->wregs[14] = 0x30;
  85 + s->wregs[15] = 0xf8;
  86 + s->rregs[0] = 0x44;
  87 + s->rregs[1] = 6;
  88 +
  89 + s->rx = s->tx = 0;
  90 + s->rxint = s->txint = 0;
  91 +}
  92 +
  93 +static void slavio_serial_reset(void *opaque)
  94 +{
  95 + SerialState *s = opaque;
  96 + slavio_serial_reset_chn(&s->chn[0]);
  97 + slavio_serial_reset_chn(&s->chn[1]);
  98 +}
  99 +
  100 +static void slavio_serial_mem_writeb(void *opaque, uint32_t addr, uint32_t val)
  101 +{
  102 + SerialState *ser = opaque;
  103 + ChannelState *s;
  104 + uint32_t saddr;
  105 + int newreg, channel;
  106 +
  107 + val &= 0xff;
  108 + saddr = (addr & 3) >> 1;
  109 + channel = (addr & SERIAL_MAXADDR) >> 2;
  110 + s = &ser->chn[channel];
  111 + switch (saddr) {
  112 + case 0:
  113 + newreg = 0;
  114 + switch (s->reg) {
  115 + case 0:
  116 + newreg = val & 7;
  117 + val &= 0x38;
  118 + switch (val) {
  119 + case 8:
  120 + s->reg |= 0x8;
  121 + break;
  122 + case 0x20:
  123 + s->rxint = 0;
  124 + break;
  125 + case 0x28:
  126 + s->txint = 0;
  127 + break;
  128 + default:
  129 + break;
  130 + }
  131 + break;
  132 + case 1 ... 8:
  133 + case 10 ... 15:
  134 + s->wregs[s->reg] = val;
  135 + break;
  136 + case 9:
  137 + switch (val & 0xc0) {
  138 + case 0:
  139 + default:
  140 + break;
  141 + case 0x40:
  142 + slavio_serial_reset_chn(&ser->chn[1]);
  143 + return;
  144 + case 0x80:
  145 + slavio_serial_reset_chn(&ser->chn[0]);
  146 + return;
  147 + case 0xc0:
  148 + slavio_serial_reset(ser);
  149 + return;
  150 + }
  151 + break;
  152 + default:
  153 + break;
  154 + }
  155 + if (s->reg == 0)
  156 + s->reg = newreg;
  157 + else
  158 + s->reg = 0;
  159 + break;
  160 + case 1:
  161 + if (s->wregs[5] & 8) { // tx enabled
  162 + s->tx = val;
  163 + if (s->chr)
  164 + qemu_chr_write(s->chr, &s->tx, 1);
  165 + s->txint = 1;
  166 + }
  167 + break;
  168 + default:
  169 + break;
  170 + }
  171 +}
  172 +
  173 +static uint32_t slavio_serial_mem_readb(void *opaque, uint32_t addr)
  174 +{
  175 + SerialState *ser = opaque;
  176 + ChannelState *s;
  177 + uint32_t saddr;
  178 + uint32_t ret;
  179 + int channel;
  180 +
  181 + saddr = (addr & 3) >> 1;
  182 + channel = (addr & SERIAL_MAXADDR) >> 2;
  183 + s = &ser->chn[channel];
  184 + switch (saddr) {
  185 + case 0:
  186 + ret = s->rregs[s->reg];
  187 + s->reg = 0;
  188 + return ret;
  189 + case 1:
  190 + s->rregs[0] &= ~1;
  191 + return s->rx;
  192 + default:
  193 + break;
  194 + }
  195 + return 0;
  196 +}
  197 +
  198 +static int serial_can_receive(void *opaque)
  199 +{
  200 + ChannelState *s = opaque;
  201 + if (((s->wregs[3] & 1) == 0) // Rx not enabled
  202 + || ((s->rregs[0] & 1) == 1)) // char already available
  203 + return 0;
  204 + else
  205 + return 1;
  206 +}
  207 +
  208 +static void serial_receive_byte(ChannelState *s, int ch)
  209 +{
  210 + s->rregs[0] |= 1;
  211 + s->rx = ch;
  212 + s->rxint = 1;
  213 + slavio_serial_update_irq(s);
  214 +}
  215 +
  216 +static void serial_receive_break(ChannelState *s)
  217 +{
  218 + s->rregs[0] |= 0x80;
  219 + slavio_serial_update_irq(s);
  220 +}
  221 +
  222 +static void serial_receive1(void *opaque, const uint8_t *buf, int size)
  223 +{
  224 + ChannelState *s = opaque;
  225 + serial_receive_byte(s, buf[0]);
  226 +}
  227 +
  228 +static void serial_event(void *opaque, int event)
  229 +{
  230 + ChannelState *s = opaque;
  231 + if (event == CHR_EVENT_BREAK)
  232 + serial_receive_break(s);
  233 +}
  234 +
  235 +static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
  236 + slavio_serial_mem_readb,
  237 + slavio_serial_mem_readb,
  238 + slavio_serial_mem_readb,
  239 +};
  240 +
  241 +static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
  242 + slavio_serial_mem_writeb,
  243 + slavio_serial_mem_writeb,
  244 + slavio_serial_mem_writeb,
  245 +};
  246 +
  247 +static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
  248 +{
  249 + qemu_put_be32s(f, &s->irq);
  250 + qemu_put_be32s(f, &s->reg);
  251 + qemu_put_be32s(f, &s->rxint);
  252 + qemu_put_be32s(f, &s->txint);
  253 + qemu_put_8s(f, &s->rx);
  254 + qemu_put_8s(f, &s->tx);
  255 + qemu_put_buffer(f, s->wregs, 16);
  256 + qemu_put_buffer(f, s->rregs, 16);
  257 +}
  258 +
  259 +static void slavio_serial_save(QEMUFile *f, void *opaque)
  260 +{
  261 + SerialState *s = opaque;
  262 +
  263 + slavio_serial_save_chn(f, &s->chn[0]);
  264 + slavio_serial_save_chn(f, &s->chn[1]);
  265 +}
  266 +
  267 +static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
  268 +{
  269 + if (version_id != 1)
  270 + return -EINVAL;
  271 +
  272 + qemu_get_be32s(f, &s->irq);
  273 + qemu_get_be32s(f, &s->reg);
  274 + qemu_get_be32s(f, &s->rxint);
  275 + qemu_get_be32s(f, &s->txint);
  276 + qemu_get_8s(f, &s->rx);
  277 + qemu_get_8s(f, &s->tx);
  278 + qemu_get_buffer(f, s->wregs, 16);
  279 + qemu_get_buffer(f, s->rregs, 16);
  280 + return 0;
  281 +}
  282 +
  283 +static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
  284 +{
  285 + SerialState *s = opaque;
  286 + int ret;
  287 +
  288 + ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
  289 + if (ret != 0)
  290 + return ret;
  291 + ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
  292 + return ret;
  293 +
  294 +}
  295 +
  296 +SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
  297 +{
  298 + int slavio_serial_io_memory;
  299 + SerialState *s;
  300 +
  301 + s = qemu_mallocz(sizeof(SerialState));
  302 + if (!s)
  303 + return NULL;
  304 + s->chn[0].irq = irq;
  305 + s->chn[1].irq = irq;
  306 + s->chn[0].chr = chr1;
  307 + s->chn[1].chr = chr2;
  308 +
  309 + slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
  310 + cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
  311 +
  312 + if (chr1) {
  313 + qemu_chr_add_read_handler(chr1, serial_can_receive, serial_receive1, &s->chn[0]);
  314 + qemu_chr_add_event_handler(chr1, serial_event);
  315 + }
  316 + if (chr2) {
  317 + qemu_chr_add_read_handler(chr2, serial_can_receive, serial_receive1, &s->chn[1]);
  318 + qemu_chr_add_event_handler(chr2, serial_event);
  319 + }
  320 + register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
  321 + qemu_register_reset(slavio_serial_reset, s);
  322 + slavio_serial_reset(s);
  323 + return s;
  324 +}
  325 +
  326 +static void sunkbd_event(void *opaque, int ch)
  327 +{
  328 + ChannelState *s = opaque;
  329 + // XXX: PC -> Sun Type 5 translation?
  330 + serial_receive_byte(s, ch);
  331 +}
  332 +
  333 +static void sunmouse_event(void *opaque,
  334 + int dx, int dy, int dz, int buttons_state)
  335 +{
  336 + ChannelState *s = opaque;
  337 + int ch;
  338 +
  339 + // XXX
  340 + ch = 0x42;
  341 + serial_receive_byte(s, ch);
  342 +}
  343 +
  344 +void slavio_serial_ms_kbd_init(int base, int irq)
  345 +{
  346 + int slavio_serial_io_memory;
  347 + SerialState *s;
  348 +
  349 + s = qemu_mallocz(sizeof(SerialState));
  350 + if (!s)
  351 + return;
  352 + s->chn[0].irq = irq;
  353 + s->chn[1].irq = irq;
  354 + s->chn[0].chr = NULL;
  355 + s->chn[1].chr = NULL;
  356 +
  357 + slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
  358 + cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
  359 +
  360 + qemu_add_kbd_event_handler(sunkbd_event, &s->chn[0]);
  361 + qemu_add_mouse_event_handler(sunmouse_event, &s->chn[1]);
  362 + qemu_register_reset(slavio_serial_reset, s);
  363 + slavio_serial_reset(s);
  364 +}
... ...
hw/slavio_timer.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU Sparc SLAVIO timer 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 +
  26 +//#define DEBUG_TIMER
  27 +
  28 +/*
  29 + * Registers of hardware timer in sun4m.
  30 + *
  31 + * This is the timer/counter part of chip STP2001 (Slave I/O), also
  32 + * produced as NCR89C105. See
  33 + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  34 + *
  35 + * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
  36 + * are zero. Bit 31 is 1 when count has been reached.
  37 + *
  38 + */
  39 +
  40 +typedef struct SLAVIO_TIMERState {
  41 + uint32_t limit, count, counthigh;
  42 + int64_t count_load_time;
  43 + int64_t expire_time;
  44 + int64_t stop_time, tick_offset;
  45 + QEMUTimer *irq_timer;
  46 + int irq;
  47 + int reached, stopped;
  48 + int mode; // 0 = processor, 1 = user, 2 = system
  49 +} SLAVIO_TIMERState;
  50 +
  51 +#define TIMER_MAXADDR 0x1f
  52 +#define CNT_FREQ 2000000
  53 +#define MAX_CPUS 16
  54 +
  55 +// Update count, set irq, update expire_time
  56 +static void slavio_timer_get_out(SLAVIO_TIMERState *s)
  57 +{
  58 + int out;
  59 + int64_t diff, ticks, count;
  60 + uint32_t limit;
  61 +
  62 + // There are three clock tick units: CPU ticks, register units
  63 + // (nanoseconds), and counter ticks (500 ns).
  64 + if (s->mode == 1 && s->stopped)
  65 + ticks = s->stop_time;
  66 + else
  67 + ticks = qemu_get_clock(vm_clock) - s->tick_offset;
  68 +
  69 + out = (ticks >= s->expire_time);
  70 + if (out)
  71 + s->reached = 0x80000000;
  72 + if (!s->limit)
  73 + limit = 0x7fffffff;
  74 + else
  75 + limit = s->limit;
  76 +
  77 + // Convert register units to counter ticks
  78 + limit = limit >> 9;
  79 +
  80 + // Convert cpu ticks to counter ticks
  81 + diff = muldiv64(ticks - s->count_load_time, CNT_FREQ, ticks_per_sec);
  82 +
  83 + // Calculate what the counter should be, convert to register
  84 + // units
  85 + count = diff % limit;
  86 + s->count = count << 9;
  87 + s->counthigh = count >> 22;
  88 +
  89 + // Expire time: CPU ticks left to next interrupt
  90 + // Convert remaining counter ticks to CPU ticks
  91 + s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
  92 +
  93 +#ifdef DEBUG_TIMER
  94 + term_printf("timer: irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
  95 +#endif
  96 + if (s->mode != 1)
  97 + pic_set_irq(s->irq, out);
  98 +}
  99 +
  100 +// timer callback
  101 +static void slavio_timer_irq(void *opaque)
  102 +{
  103 + SLAVIO_TIMERState *s = opaque;
  104 +
  105 + if (!s->irq_timer)
  106 + return;
  107 + slavio_timer_get_out(s);
  108 + if (s->mode != 1)
  109 + qemu_mod_timer(s->irq_timer, s->expire_time);
  110 +}
  111 +
  112 +static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
  113 +{
  114 + SLAVIO_TIMERState *s = opaque;
  115 + uint32_t saddr;
  116 +
  117 + saddr = (addr & TIMER_MAXADDR) >> 2;
  118 + switch (saddr) {
  119 + case 0:
  120 + // read limit (system counter mode) or read most signifying
  121 + // part of counter (user mode)
  122 + if (s->mode != 1) {
  123 + // clear irq
  124 + pic_set_irq(s->irq, 0);
  125 + s->count_load_time = qemu_get_clock(vm_clock);
  126 + s->reached = 0;
  127 + return s->limit;
  128 + }
  129 + else {
  130 + slavio_timer_get_out(s);
  131 + return s->counthigh & 0x7fffffff;
  132 + }
  133 + case 1:
  134 + // read counter and reached bit (system mode) or read lsbits
  135 + // of counter (user mode)
  136 + slavio_timer_get_out(s);
  137 + if (s->mode != 1)
  138 + return (s->count & 0x7fffffff) | s->reached;
  139 + else
  140 + return s->count;
  141 + case 3:
  142 + // read start/stop status
  143 + return s->stopped;
  144 + case 4:
  145 + // read user/system mode
  146 + return s->mode & 1;
  147 + default:
  148 + return 0;
  149 + }
  150 +}
  151 +
  152 +static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  153 +{
  154 + SLAVIO_TIMERState *s = opaque;
  155 + uint32_t saddr;
  156 +
  157 + saddr = (addr & TIMER_MAXADDR) >> 2;
  158 + switch (saddr) {
  159 + case 0:
  160 + // set limit, reset counter
  161 + s->count_load_time = qemu_get_clock(vm_clock);
  162 + // fall through
  163 + case 2:
  164 + // set limit without resetting counter
  165 + if (!val)
  166 + s->limit = 0x7fffffff;
  167 + else
  168 + s->limit = val & 0x7fffffff;
  169 + slavio_timer_irq(s);
  170 + break;
  171 + case 3:
  172 + // start/stop user counter
  173 + if (s->mode == 1) {
  174 + if (val & 1) {
  175 + s->stop_time = qemu_get_clock(vm_clock);
  176 + s->stopped = 1;
  177 + }
  178 + else {
  179 + if (s->stopped)
  180 + s->tick_offset += qemu_get_clock(vm_clock) - s->stop_time;
  181 + s->stopped = 0;
  182 + }
  183 + }
  184 + break;
  185 + case 4:
  186 + // bit 0: user (1) or system (0) counter mode
  187 + if (s->mode == 0 || s->mode == 1)
  188 + s->mode = val & 1;
  189 + break;
  190 + default:
  191 + break;
  192 + }
  193 +}
  194 +
  195 +static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
  196 + slavio_timer_mem_readl,
  197 + slavio_timer_mem_readl,
  198 + slavio_timer_mem_readl,
  199 +};
  200 +
  201 +static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
  202 + slavio_timer_mem_writel,
  203 + slavio_timer_mem_writel,
  204 + slavio_timer_mem_writel,
  205 +};
  206 +
  207 +static void slavio_timer_save(QEMUFile *f, void *opaque)
  208 +{
  209 + SLAVIO_TIMERState *s = opaque;
  210 +
  211 + qemu_put_be32s(f, &s->limit);
  212 + qemu_put_be32s(f, &s->count);
  213 + qemu_put_be32s(f, &s->counthigh);
  214 + qemu_put_be64s(f, &s->count_load_time);
  215 + qemu_put_be64s(f, &s->expire_time);
  216 + qemu_put_be64s(f, &s->stop_time);
  217 + qemu_put_be64s(f, &s->tick_offset);
  218 + qemu_put_be32s(f, &s->irq);
  219 + qemu_put_be32s(f, &s->reached);
  220 + qemu_put_be32s(f, &s->stopped);
  221 + qemu_put_be32s(f, &s->mode);
  222 +}
  223 +
  224 +static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
  225 +{
  226 + SLAVIO_TIMERState *s = opaque;
  227 +
  228 + if (version_id != 1)
  229 + return -EINVAL;
  230 +
  231 + qemu_get_be32s(f, &s->limit);
  232 + qemu_get_be32s(f, &s->count);
  233 + qemu_get_be32s(f, &s->counthigh);
  234 + qemu_get_be64s(f, &s->count_load_time);
  235 + qemu_get_be64s(f, &s->expire_time);
  236 + qemu_get_be64s(f, &s->stop_time);
  237 + qemu_get_be64s(f, &s->tick_offset);
  238 + qemu_get_be32s(f, &s->irq);
  239 + qemu_get_be32s(f, &s->reached);
  240 + qemu_get_be32s(f, &s->stopped);
  241 + qemu_get_be32s(f, &s->mode);
  242 + return 0;
  243 +}
  244 +
  245 +static void slavio_timer_reset(void *opaque)
  246 +{
  247 + SLAVIO_TIMERState *s = opaque;
  248 +
  249 + s->limit = 0;
  250 + s->count = 0;
  251 + s->count_load_time = qemu_get_clock(vm_clock);;
  252 + s->stop_time = s->count_load_time;
  253 + s->tick_offset = 0;
  254 + s->reached = 0;
  255 + s->mode &= 2;
  256 + s->stopped = 1;
  257 + slavio_timer_get_out(s);
  258 +}
  259 +
  260 +static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
  261 +{
  262 + int slavio_timer_io_memory;
  263 + SLAVIO_TIMERState *s;
  264 +
  265 + s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
  266 + if (!s)
  267 + return;
  268 + s->irq = irq;
  269 + s->mode = mode;
  270 + s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
  271 +
  272 + slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
  273 + slavio_timer_mem_write, s);
  274 + cpu_register_physical_memory(addr, TIMER_MAXADDR, slavio_timer_io_memory);
  275 + register_savevm("slavio_timer", addr, 1, slavio_timer_save, slavio_timer_load, s);
  276 + qemu_register_reset(slavio_timer_reset, s);
  277 + slavio_timer_reset(s);
  278 +}
  279 +
  280 +void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2)
  281 +{
  282 + int i;
  283 +
  284 + for (i = 0; i < MAX_CPUS; i++) {
  285 + slavio_timer_init_internal(addr1 + i * TARGET_PAGE_SIZE, irq1, 0);
  286 + }
  287 +
  288 + slavio_timer_init_internal(addr2, irq2, 2);
  289 +}
... ...
hw/sun4m.c
... ... @@ -25,29 +25,32 @@
25 25 #include "m48t08.h"
26 26  
27 27 #define KERNEL_LOAD_ADDR 0x00004000
28   -#define MMU_CONTEXT_TBL 0x00003000
29   -#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
30   -#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
31   -#define PROM_ADDR 0xffd04000
  28 +#define PROM_ADDR 0xffd00000
32 29 #define PROM_FILENAMEB "proll.bin"
33 30 #define PROM_FILENAMEE "proll.elf"
34   -#define PROLL_MAGIC_ADDR 0x20000000
35   -#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
  31 +#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
36 32 #define PHYS_JJ_IDPROM_OFF 0x1FD8
37 33 #define PHYS_JJ_EEPROM_SIZE 0x2000
38   -#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
  34 +// IRQs are not PIL ones, but master interrupt controller register
  35 +// bits
  36 +#define PHYS_JJ_IOMMU 0x10000000 /* I/O MMU */
39 37 #define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
40   -#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
41   -#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
42   -#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
43   -#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
44   -#define PHYS_JJ_LE_IRQ 6
45   -#define PHYS_JJ_CLOCK 0x71D00000
46   -#define PHYS_JJ_CLOCK_IRQ 10
47   -#define PHYS_JJ_CLOCK1 0x71D10000
48   -#define PHYS_JJ_CLOCK1_IRQ 14
49   -#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
  38 +#define PHYS_JJ_LEDMA 0x78400010 /* Lance DMA controller */
  39 +#define PHYS_JJ_LE 0x78C00000 /* Lance ethernet */
  40 +#define PHYS_JJ_LE_IRQ 16
  41 +#define PHYS_JJ_CLOCK 0x71D00000 /* Per-CPU timer/counter, L14 */
  42 +#define PHYS_JJ_CLOCK_IRQ 7
  43 +#define PHYS_JJ_CLOCK1 0x71D10000 /* System timer/counter, L10 */
  44 +#define PHYS_JJ_CLOCK1_IRQ 19
  45 +#define PHYS_JJ_INTR0 0x71E00000 /* Per-CPU interrupt control registers */
50 46 #define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
  47 +#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
  48 +#define PHYS_JJ_MS_KBD_IRQ 14
  49 +#define PHYS_JJ_SER 0x71100000 /* Serial */
  50 +#define PHYS_JJ_SER_IRQ 15
  51 +#define PHYS_JJ_SCSI_IRQ 18
  52 +#define PHYS_JJ_FDC 0x71400000 /* Floppy */
  53 +#define PHYS_JJ_FLOPPY_IRQ 22
51 54  
52 55 /* TSC handling */
53 56  
... ... @@ -57,13 +60,73 @@ uint64_t cpu_get_tsc()
57 60 }
58 61  
59 62 void DMA_run() {}
60   -void SB16_run() {}
61   -int serial_can_receive(SerialState *s) { return 0; }
62   -void serial_receive_byte(SerialState *s, int ch) {}
63   -void serial_receive_break(SerialState *s) {}
64 63  
65 64 static m48t08_t *nvram;
66 65  
  66 +static void nvram_init(m48t08_t *nvram, uint8_t *macaddr)
  67 +{
  68 + unsigned char tmp = 0;
  69 + int i, j;
  70 +
  71 + i = 0x1fd8;
  72 + m48t08_write(nvram, i++, 0x01);
  73 + m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
  74 + j = 0;
  75 + m48t08_write(nvram, i++, macaddr[j++]);
  76 + m48t08_write(nvram, i++, macaddr[j++]);
  77 + m48t08_write(nvram, i++, macaddr[j++]);
  78 + m48t08_write(nvram, i++, macaddr[j++]);
  79 + m48t08_write(nvram, i++, macaddr[j++]);
  80 + m48t08_write(nvram, i, macaddr[j]);
  81 +
  82 + /* Calculate checksum */
  83 + for (i = 0x1fd8; i < 0x1fe7; i++) {
  84 + tmp ^= m48t08_read(nvram, i);
  85 + }
  86 + m48t08_write(nvram, 0x1fe7, tmp);
  87 +}
  88 +
  89 +static void *slavio_intctl;
  90 +
  91 +void pic_info()
  92 +{
  93 + slavio_pic_info(slavio_intctl);
  94 +}
  95 +
  96 +void irq_info()
  97 +{
  98 + slavio_irq_info(slavio_intctl);
  99 +}
  100 +
  101 +void pic_set_irq(int irq, int level)
  102 +{
  103 + slavio_pic_set_irq(slavio_intctl, irq, level);
  104 +}
  105 +
  106 +static void *tcx;
  107 +
  108 +void vga_update_display()
  109 +{
  110 + tcx_update_display(tcx);
  111 +}
  112 +
  113 +void vga_invalidate_display()
  114 +{
  115 + tcx_invalidate_display(tcx);
  116 +}
  117 +
  118 +void vga_screen_dump(const char *filename)
  119 +{
  120 + tcx_screen_dump(tcx, filename);
  121 +}
  122 +
  123 +static void *iommu;
  124 +
  125 +uint32_t iommu_translate(uint32_t addr)
  126 +{
  127 + return iommu_translate_local(iommu, addr);
  128 +}
  129 +
67 130 /* Sun4m hardware initialisation */
68 131 void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
69 132 DisplayState *ds, const char **fd_filename, int snapshot,
... ... @@ -72,42 +135,50 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
72 135 {
73 136 char buf[1024];
74 137 int ret, linux_boot;
75   - unsigned long bios_offset;
  138 + unsigned long vram_size = 0x100000, prom_offset;
76 139  
77 140 linux_boot = (kernel_filename != NULL);
78 141  
79 142 /* allocate RAM */
80 143 cpu_register_physical_memory(0, ram_size, 0);
81   - bios_offset = ram_size;
82 144  
83   - iommu_init(PHYS_JJ_IOMMU);
84   - sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
85   - tcx_init(ds, PHYS_JJ_TCX_FB);
  145 + iommu = iommu_init(PHYS_JJ_IOMMU);
  146 + slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
  147 + tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size);
86 148 lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
87   - nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr);
88   - timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
89   - timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
90   - magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
  149 + nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
  150 + nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr);
  151 + slavio_timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ, PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
  152 + slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
  153 + slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[0], serial_hds[1]);
  154 + fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
91 155  
92   - /* We load Proll as the kernel and start it. It will issue a magic
93   - IO to load the real kernel */
94   - if (linux_boot) {
  156 + prom_offset = ram_size + vram_size;
  157 +
  158 + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
  159 + ret = load_elf(buf, phys_ram_base + prom_offset);
  160 + if (ret < 0) {
95 161 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
96   - ret = load_kernel(buf,
97   - phys_ram_base + KERNEL_LOAD_ADDR);
  162 + ret = load_image(buf, phys_ram_base + prom_offset);
  163 + }
  164 + if (ret < 0) {
  165 + fprintf(stderr, "qemu: could not load prom '%s'\n",
  166 + buf);
  167 + exit(1);
  168 + }
  169 + cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
  170 + prom_offset | IO_MEM_ROM);
  171 +
  172 + if (linux_boot) {
  173 + ret = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  174 + if (ret < 0)
  175 + ret = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  176 + if (ret < 0)
  177 + ret = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
98 178 if (ret < 0) {
99 179 fprintf(stderr, "qemu: could not load kernel '%s'\n",
100   - buf);
101   - exit(1);
  180 + kernel_filename);
  181 + exit(1);
102 182 }
103 183 }
104   - /* Setup a MMU entry for entire address space */
105   - stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
106   - stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
107   - stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00..
108   - stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
109   - stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00..
110   - /* 3 = U:RWX S:RWX */
111   - stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
112   - stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
113 184 }
... ...
hw/tcx.c
... ... @@ -25,179 +25,254 @@
25 25  
26 26 #define MAXX 1024
27 27 #define MAXY 768
  28 +/*
  29 + * Proll uses only small part of display, we need to switch to full
  30 + * display when we get linux framebuffer console or X11 running. For
  31 + * now it's just slower and awkward.
  32 +*/
  33 +#if 1
28 34 #define XSZ (8*80)
29 35 #define YSZ (24*11)
30 36 #define XOFF (MAXX-XSZ)
31 37 #define YOFF (MAXY-YSZ)
  38 +#else
  39 +#define XSZ MAXX
  40 +#define YSZ MAXY
  41 +#define XOFF 0
  42 +#define YOFF 0
  43 +#endif
32 44  
33 45 typedef struct TCXState {
34 46 uint32_t addr;
35 47 DisplayState *ds;
36 48 uint8_t *vram;
  49 + unsigned long vram_offset;
  50 + uint8_t r[256], g[256], b[256];
37 51 } TCXState;
38 52  
39   -static TCXState *ts;
40   -
41   -void vga_update_display()
  53 +static void tcx_draw_line32(TCXState *s1, uint8_t *d,
  54 + const uint8_t *s, int width)
42 55 {
43   - dpy_update(ts->ds, 0, 0, XSZ, YSZ);
  56 + int x;
  57 + uint8_t val;
  58 +
  59 + for(x = 0; x < width; x++) {
  60 + val = *s++;
  61 + *d++ = s1->r[val];
  62 + *d++ = s1->g[val];
  63 + *d++ = s1->b[val];
  64 + d++;
  65 + }
44 66 }
45 67  
46   -void vga_invalidate_display() {}
  68 +static void tcx_draw_line24(TCXState *s1, uint8_t *d,
  69 + const uint8_t *s, int width)
  70 +{
  71 + int x;
  72 + uint8_t val;
47 73  
48   -static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
  74 + for(x = 0; x < width; x++) {
  75 + val = *s++;
  76 + *d++ = s1->r[val];
  77 + *d++ = s1->g[val];
  78 + *d++ = s1->b[val];
  79 + }
  80 +}
  81 +
  82 +static void tcx_draw_line8(TCXState *s1, uint8_t *d,
  83 + const uint8_t *s, int width)
49 84 {
50   - TCXState *s = opaque;
51   - uint32_t saddr;
52   - unsigned int x, y;
53   -
54   - saddr = addr - s->addr - YOFF*MAXX - XOFF;
55   - y = saddr / MAXX;
56   - x = saddr - y * MAXX;
57   - if (x < XSZ && y < YSZ) {
58   - return s->vram[y * XSZ + x];
  85 + int x;
  86 + uint8_t val;
  87 +
  88 + for(x = 0; x < width; x++) {
  89 + val = *s++;
  90 + /* XXX translate between palettes? */
  91 + *d++ = val;
59 92 }
60   - return 0;
61 93 }
62 94  
63   -static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
  95 +/* Fixed line length 1024 allows us to do nice tricks not possible on
  96 + VGA... */
  97 +void tcx_update_display(void *opaque)
64 98 {
65   - uint32_t v;
66   -#ifdef TARGET_WORDS_BIGENDIAN
67   - v = tcx_mem_readb(opaque, addr) << 8;
68   - v |= tcx_mem_readb(opaque, addr + 1);
  99 + TCXState *ts = opaque;
  100 + uint32_t page;
  101 + int y, page_min, page_max, y_start, dd, ds;
  102 + uint8_t *d, *s;
  103 + void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
  104 +
  105 + if (ts->ds->depth == 0)
  106 + return;
  107 +#ifdef LD_BYPASS_OK
  108 + page = ts->vram_offset + YOFF*MAXX;
69 109 #else
70   - v = tcx_mem_readb(opaque, addr);
71   - v |= tcx_mem_readb(opaque, addr + 1) << 8;
  110 + page = ts->addr + YOFF*MAXX;
72 111 #endif
73   - return v;
  112 + y_start = -1;
  113 + page_min = 0x7fffffff;
  114 + page_max = -1;
  115 + d = ts->ds->data;
  116 + s = ts->vram + YOFF*MAXX + XOFF;
  117 + dd = ts->ds->linesize;
  118 + ds = 1024;
  119 +
  120 + switch (ts->ds->depth) {
  121 + case 32:
  122 + f = tcx_draw_line32;
  123 + break;
  124 + case 24:
  125 + f = tcx_draw_line24;
  126 + break;
  127 + default:
  128 + case 8:
  129 + f = tcx_draw_line8;
  130 + break;
  131 + case 0:
  132 + return;
  133 + }
  134 +
  135 + for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
  136 + if (cpu_physical_memory_is_dirty(page)) {
  137 + if (y_start < 0)
  138 + y_start = y;
  139 + if (page < page_min)
  140 + page_min = page;
  141 + if (page > page_max)
  142 + page_max = page;
  143 + f(ts, d, s, XSZ);
  144 + d += dd;
  145 + s += ds;
  146 + f(ts, d, s, XSZ);
  147 + d += dd;
  148 + s += ds;
  149 + f(ts, d, s, XSZ);
  150 + d += dd;
  151 + s += ds;
  152 + f(ts, d, s, XSZ);
  153 + d += dd;
  154 + s += ds;
  155 + } else {
  156 + if (y_start >= 0) {
  157 + /* flush to display */
  158 + dpy_update(ts->ds, 0, y_start,
  159 + XSZ, y - y_start);
  160 + y_start = -1;
  161 + }
  162 + d += dd * 4;
  163 + s += ds * 4;
  164 + }
  165 + }
  166 + if (y_start >= 0) {
  167 + /* flush to display */
  168 + dpy_update(ts->ds, 0, y_start,
  169 + XSZ, y - y_start);
  170 + }
  171 + /* reset modified pages */
  172 + if (page_max != -1) {
  173 + cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
  174 + }
74 175 }
75 176  
76   -static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
  177 +void tcx_invalidate_display(void *opaque)
77 178 {
78   - uint32_t v;
79   -#ifdef TARGET_WORDS_BIGENDIAN
80   - v = tcx_mem_readb(opaque, addr) << 24;
81   - v |= tcx_mem_readb(opaque, addr + 1) << 16;
82   - v |= tcx_mem_readb(opaque, addr + 2) << 8;
83   - v |= tcx_mem_readb(opaque, addr + 3);
  179 + TCXState *s = opaque;
  180 + int i;
  181 +
  182 + for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
  183 +#ifdef LD_BYPASS_OK
  184 + cpu_physical_memory_set_dirty(s->vram_offset + i);
84 185 #else
85   - v = tcx_mem_readb(opaque, addr);
86   - v |= tcx_mem_readb(opaque, addr + 1) << 8;
87   - v |= tcx_mem_readb(opaque, addr + 2) << 16;
88   - v |= tcx_mem_readb(opaque, addr + 3) << 24;
  186 + cpu_physical_memory_set_dirty(s->addr + i);
89 187 #endif
90   - return v;
  188 + }
91 189 }
92 190  
93   -static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  191 +static void tcx_save(QEMUFile *f, void *opaque)
94 192 {
95 193 TCXState *s = opaque;
96   - uint32_t saddr;
97   - unsigned int x, y;
98   - char *sptr;
99   -
100   - saddr = addr - s->addr - YOFF*MAXX - XOFF;
101   - y = saddr / MAXX;
102   - x = saddr - y * MAXX;
103   - if (x < XSZ && y < YSZ) {
104   - sptr = s->ds->data;
105   - if (sptr) {
106   - if (s->ds->depth == 24 || s->ds->depth == 32) {
107   - /* XXX need to do CLUT translation */
108   - sptr[y * s->ds->linesize + x*4] = val & 0xff;
109   - sptr[y * s->ds->linesize + x*4+1] = val & 0xff;
110   - sptr[y * s->ds->linesize + x*4+2] = val & 0xff;
111   - }
112   - else if (s->ds->depth == 8) {
113   - sptr[y * s->ds->linesize + x] = val & 0xff;
114   - }
115   - }
116   - cpu_physical_memory_set_dirty(addr);
117   - s->vram[y * XSZ + x] = val & 0xff;
118   - }
  194 +
  195 + qemu_put_be32s(f, (uint32_t *)&s->addr);
  196 + qemu_put_be32s(f, (uint32_t *)&s->vram);
  197 + qemu_put_buffer(f, s->r, 256);
  198 + qemu_put_buffer(f, s->g, 256);
  199 + qemu_put_buffer(f, s->b, 256);
119 200 }
120 201  
121   -static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  202 +static int tcx_load(QEMUFile *f, void *opaque, int version_id)
122 203 {
123   -#ifdef TARGET_WORDS_BIGENDIAN
124   - tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
125   - tcx_mem_writeb(opaque, addr + 1, val & 0xff);
126   -#else
127   - tcx_mem_writeb(opaque, addr, val & 0xff);
128   - tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
129   -#endif
  204 + TCXState *s = opaque;
  205 +
  206 + if (version_id != 1)
  207 + return -EINVAL;
  208 +
  209 + qemu_get_be32s(f, (uint32_t *)&s->addr);
  210 + qemu_get_be32s(f, (uint32_t *)&s->vram);
  211 + qemu_get_buffer(f, s->r, 256);
  212 + qemu_get_buffer(f, s->g, 256);
  213 + qemu_get_buffer(f, s->b, 256);
  214 + return 0;
130 215 }
131 216  
132   -static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  217 +static void tcx_reset(void *opaque)
133 218 {
134   -#ifdef TARGET_WORDS_BIGENDIAN
135   - tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
136   - tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
137   - tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
138   - tcx_mem_writeb(opaque, addr + 3, val & 0xff);
139   -#else
140   - tcx_mem_writeb(opaque, addr, val & 0xff);
141   - tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
142   - tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
143   - tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  219 + TCXState *s = opaque;
  220 +
  221 + /* Initialize palette */
  222 + memset(s->r, 0, 256);
  223 + memset(s->g, 0, 256);
  224 + memset(s->b, 0, 256);
  225 + s->r[255] = s->g[255] = s->b[255] = 255;
  226 + memset(s->vram, 0, MAXX*MAXY);
  227 +#ifdef LD_BYPASS_OK
  228 + cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY - 1);
144 229 #endif
145 230 }
146 231  
147   -static CPUReadMemoryFunc *tcx_mem_read[3] = {
148   - tcx_mem_readb,
149   - tcx_mem_readw,
150   - tcx_mem_readl,
151   -};
152   -
153   -static CPUWriteMemoryFunc *tcx_mem_write[3] = {
154   - tcx_mem_writeb,
155   - tcx_mem_writew,
156   - tcx_mem_writel,
157   -};
158   -
159   -void tcx_init(DisplayState *ds, uint32_t addr)
  232 +void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
  233 + unsigned long vram_offset, int vram_size)
160 234 {
161 235 TCXState *s;
162   - int tcx_io_memory;
163 236  
164 237 s = qemu_mallocz(sizeof(TCXState));
165 238 if (!s)
166   - return;
  239 + return NULL;
167 240 s->ds = ds;
168 241 s->addr = addr;
169   - ts = s;
170   - tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
171   - cpu_register_physical_memory(addr, 0x100000,
172   - tcx_io_memory);
173   - s->vram = qemu_mallocz(XSZ*YSZ);
  242 + s->vram = vram_base;
  243 + s->vram_offset = vram_offset;
  244 +
  245 + cpu_register_physical_memory(addr, vram_size, vram_offset);
  246 +
  247 + register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
  248 + qemu_register_reset(tcx_reset, s);
  249 + tcx_reset(s);
174 250 dpy_resize(s->ds, XSZ, YSZ);
  251 + return s;
175 252 }
176 253  
177   -void vga_screen_dump(const char *filename)
  254 +void tcx_screen_dump(void *opaque, const char *filename)
178 255 {
179   - TCXState *s = ts;
  256 + TCXState *s = opaque;
180 257 FILE *f;
181   - uint8_t *d, *d1;
182   - unsigned int v;
  258 + uint8_t *d, *d1, v;
183 259 int y, x;
184 260  
185 261 f = fopen(filename, "wb");
186 262 if (!f)
187   - return -1;
188   - fprintf(f, "P6\n%d %d\n%d\n",
189   - XSZ, YSZ, 255);
190   - d1 = s->vram;
  263 + return;
  264 + fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255);
  265 + d1 = s->vram + YOFF*MAXX + XOFF;
191 266 for(y = 0; y < YSZ; y++) {
192 267 d = d1;
193 268 for(x = 0; x < XSZ; x++) {
194 269 v = *d;
195   - fputc((v) & 0xff, f);
196   - fputc((v) & 0xff, f);
197   - fputc((v) & 0xff, f);
  270 + fputc(s->r[v], f);
  271 + fputc(s->g[v], f);
  272 + fputc(s->b[v], f);
198 273 d++;
199 274 }
200   - d1 += XSZ;
  275 + d1 += MAXX;
201 276 }
202 277 fclose(f);
203 278 return;
... ...
hw/timer.c deleted 100644 โ†’ 0
1   -/*
2   - * QEMU Sparc timer 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   -
26   -/*
27   - * Registers of hardware timer in sun4m.
28   - */
29   -struct sun4m_timer_percpu {
30   - volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
31   - volatile unsigned int l14_cur_count;
32   -};
33   -
34   -struct sun4m_timer_global {
35   - volatile unsigned int l10_timer_limit;
36   - volatile unsigned int l10_cur_count;
37   -};
38   -
39   -typedef struct TIMERState {
40   - uint32_t addr;
41   - uint32_t timer_regs[2];
42   - int irq;
43   -} TIMERState;
44   -
45   -static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
46   -{
47   - TIMERState *s = opaque;
48   - uint32_t saddr;
49   -
50   - saddr = (addr - s->addr) >> 2;
51   - switch (saddr) {
52   - default:
53   - return s->timer_regs[saddr];
54   - break;
55   - }
56   - return 0;
57   -}
58   -
59   -static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
60   -{
61   - TIMERState *s = opaque;
62   - uint32_t saddr;
63   -
64   - saddr = (addr - s->addr) >> 2;
65   - switch (saddr) {
66   - default:
67   - s->timer_regs[saddr] = val;
68   - break;
69   - }
70   -}
71   -
72   -static CPUReadMemoryFunc *timer_mem_read[3] = {
73   - timer_mem_readl,
74   - timer_mem_readl,
75   - timer_mem_readl,
76   -};
77   -
78   -static CPUWriteMemoryFunc *timer_mem_write[3] = {
79   - timer_mem_writel,
80   - timer_mem_writel,
81   - timer_mem_writel,
82   -};
83   -
84   -void timer_init(uint32_t addr, int irq)
85   -{
86   - int timer_io_memory;
87   - TIMERState *s;
88   -
89   - s = qemu_mallocz(sizeof(TIMERState));
90   - if (!s)
91   - return;
92   - s->addr = addr;
93   - s->irq = irq;
94   -
95   - timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
96   - cpu_register_physical_memory(addr, 2, timer_io_memory);
97   -}
linux-user/elfload.c
... ... @@ -841,6 +841,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
841 841 unsigned int i;
842 842 struct elf_shdr sechdr, symtab, strtab;
843 843 char *strings;
  844 + struct syminfo *s;
844 845  
845 846 lseek(fd, hdr->e_shoff, SEEK_SET);
846 847 for (i = 0; i < hdr->e_shnum; i++) {
... ... @@ -866,24 +867,27 @@ static void load_symbols(struct elfhdr *hdr, int fd)
866 867  
867 868 found:
868 869 /* Now know where the strtab and symtab are. Snarf them. */
869   - disas_symtab = malloc(symtab.sh_size);
870   - disas_strtab = strings = malloc(strtab.sh_size);
871   - if (!disas_symtab || !disas_strtab)
  870 + s = malloc(sizeof(*s));
  871 + s->disas_symtab = malloc(symtab.sh_size);
  872 + s->disas_strtab = strings = malloc(strtab.sh_size);
  873 + if (!s->disas_symtab || !s->disas_strtab)
872 874 return;
873 875  
874 876 lseek(fd, symtab.sh_offset, SEEK_SET);
875   - if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
  877 + if (read(fd, s->disas_symtab, symtab.sh_size) != symtab.sh_size)
876 878 return;
877 879  
878 880 #ifdef BSWAP_NEEDED
879 881 for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
880   - bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
  882 + bswap_sym(s->disas_symtab + sizeof(struct elf_sym)*i);
881 883 #endif
882 884  
883 885 lseek(fd, strtab.sh_offset, SEEK_SET);
884 886 if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
885 887 return;
886   - disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
  888 + s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
  889 + s->next = syminfos;
  890 + syminfos = s;
887 891 }
888 892  
889 893 static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
... ...
linux-user/main.c
... ... @@ -497,6 +497,8 @@ void cpu_loop (CPUSPARCState *env)
497 497 case TT_WIN_UNF: /* window underflow */
498 498 restore_window(env);
499 499 break;
  500 + case 0x100: // XXX, why do we get these?
  501 + break;
500 502 default:
501 503 printf ("Unhandled trap: 0x%x\n", trapnr);
502 504 cpu_dump_state(env, stderr, fprintf, 0);
... ...
linux-user/signal.c
... ... @@ -1354,13 +1354,14 @@ struct target_rt_signal_frame {
1354 1354 __siginfo_fpu_t fpu_state;
1355 1355 };
1356 1356  
1357   -#define UREG_O0 0
1358   -#define UREG_O6 6
1359   -#define UREG_I0 16
1360   -#define UREG_I1 17
1361   -#define UREG_I2 18
1362   -#define UREG_I6 22
1363   -#define UREG_I7 23
  1357 +#define UREG_O0 16
  1358 +#define UREG_O6 22
  1359 +#define UREG_I0 0
  1360 +#define UREG_I1 1
  1361 +#define UREG_I2 2
  1362 +#define UREG_I6 6
  1363 +#define UREG_I7 7
  1364 +#define UREG_L0 8
1364 1365 #define UREG_FP UREG_I6
1365 1366 #define UREG_SP UREG_O6
1366 1367  
... ... @@ -1385,23 +1386,20 @@ setup___siginfo(__siginfo_t *si, CPUState *env, target_ulong mask)
1385 1386 {
1386 1387 int err = 0, i;
1387 1388  
1388   - fprintf(stderr, "2.a %lx psr: %lx regs: %lx\n", si, env->psr, si->si_regs.psr);
1389 1389 err |= __put_user(env->psr, &si->si_regs.psr);
1390   - fprintf(stderr, "2.a1 pc:%lx\n", si->si_regs.pc);
1391 1390 err |= __put_user(env->pc, &si->si_regs.pc);
1392 1391 err |= __put_user(env->npc, &si->si_regs.npc);
1393 1392 err |= __put_user(env->y, &si->si_regs.y);
1394   - fprintf(stderr, "2.b\n");
1395 1393 for (i=0; i < 7; i++) {
1396 1394 err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
1397 1395 }
1398 1396 for (i=0; i < 7; i++) {
1399   - err |= __put_user(env->regwptr[i+16], &si->si_regs.u_regs[i+8]);
  1397 + err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
1400 1398 }
1401   - fprintf(stderr, "2.c\n");
1402 1399 err |= __put_user(mask, &si->si_mask);
1403 1400 return err;
1404 1401 }
  1402 +
1405 1403 static int
1406 1404 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1407 1405 CPUState *env, unsigned long mask)
... ... @@ -1434,6 +1432,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
1434 1432 sf = (struct target_signal_frame *)
1435 1433 get_sigframe(ka, env, sigframe_size);
1436 1434  
  1435 + //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
1437 1436 #if 0
1438 1437 if (invalid_frame_pointer(sf, sigframe_size))
1439 1438 goto sigill_and_return;
... ... @@ -1451,13 +1450,11 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
1451 1450 }
1452 1451  
1453 1452 for (i = 0; i < 7; i++) {
1454   - err |= __put_user(env->regwptr[i + 8], &sf->ss.locals[i]);
  1453 + err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
1455 1454 }
1456 1455 for (i = 0; i < 7; i++) {
1457   - err |= __put_user(env->regwptr[i + 16], &sf->ss.ins[i]);
  1456 + err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
1458 1457 }
1459   - //err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
1460   - // sizeof(struct reg_window));
1461 1458 if (err)
1462 1459 goto sigsegv;
1463 1460  
... ... @@ -1486,13 +1483,15 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
1486 1483  
1487 1484 /* Flush instruction space. */
1488 1485 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
1489   - //tb_flush(env);
  1486 + tb_flush(env);
1490 1487 }
  1488 + //cpu_dump_state(env, stderr, fprintf, 0);
1491 1489 return;
1492 1490  
1493 1491 sigill_and_return:
1494 1492 force_sig(TARGET_SIGILL);
1495 1493 sigsegv:
  1494 + //fprintf(stderr, "force_sig\n");
1496 1495 force_sig(TARGET_SIGSEGV);
1497 1496 }
1498 1497 static inline int
... ... @@ -1542,13 +1541,16 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
1542 1541 long do_sigreturn(CPUState *env)
1543 1542 {
1544 1543 struct target_signal_frame *sf;
1545   - unsigned long up_psr, pc, npc;
  1544 + uint32_t up_psr, pc, npc;
1546 1545 target_sigset_t set;
  1546 + sigset_t host_set;
1547 1547 __siginfo_fpu_t *fpu_save;
1548   - int err;
  1548 + int err, i;
1549 1549  
1550   - sf = (struct new_signal_frame *) env->regwptr[UREG_FP];
1551   - fprintf(stderr, "sigreturn sf: %lx\n", &sf);
  1550 + sf = (struct target_signal_frame *) env->regwptr[UREG_FP];
  1551 + fprintf(stderr, "sigreturn\n");
  1552 + fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
  1553 + //cpu_dump_state(env, stderr, fprintf, 0);
1552 1554  
1553 1555 /* 1. Make sure we are not getting garbage from the user */
1554 1556 #if 0
... ... @@ -1567,36 +1569,41 @@ long do_sigreturn(CPUState *env)
1567 1569 goto segv_and_exit;
1568 1570  
1569 1571 /* 2. Restore the state */
1570   - up_psr = env->psr;
1571   - //err |= __copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs)
1572   - //);
  1572 + err |= __get_user(up_psr, &sf->info.si_regs.psr);
  1573 +
1573 1574 /* User can only change condition codes and FPU enabling in %psr. */
1574 1575 env->psr = (up_psr & ~(PSR_ICC /* | PSR_EF */))
1575 1576 | (env->psr & (PSR_ICC /* | PSR_EF */));
1576   - fprintf(stderr, "psr: %lx\n", env->psr);
  1577 + fprintf(stderr, "psr: %x\n", env->psr);
  1578 + env->pc = pc-4;
  1579 + env->npc = pc;
  1580 + err |= __get_user(env->y, &sf->info.si_regs.y);
  1581 + for (i=0; i < 7; i++) {
  1582 + err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
  1583 + }
  1584 + for (i=0; i < 7; i++) {
  1585 + err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
  1586 + }
1577 1587  
1578 1588 err |= __get_user(fpu_save, &sf->fpu_save);
1579 1589  
1580   - if (fpu_save)
1581   - err |= restore_fpu_state(env, fpu_save);
  1590 + //if (fpu_save)
  1591 + // err |= restore_fpu_state(env, fpu_save);
1582 1592  
1583 1593 /* This is pretty much atomic, no amount locking would prevent
1584 1594 * the races which exist anyways.
1585 1595 */
1586 1596 err |= __get_user(set.sig[0], &sf->info.si_mask);
1587   - //err |= __copy_from_user(&set.sig[1], &sf->extramask,
1588   - // (_NSIG_WORDS-1) * sizeof(unsigned int));
  1597 + for(i = 1; i < TARGET_NSIG_WORDS; i++) {
  1598 + err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
  1599 + }
  1600 +
  1601 + target_to_host_sigset_internal(&host_set, &set);
  1602 + sigprocmask(SIG_SETMASK, &host_set, NULL);
1589 1603  
1590 1604 if (err)
1591 1605 goto segv_and_exit;
1592 1606  
1593   -#if 0
1594   - sigdelsetmask(&set, ~_BLOCKABLE);
1595   - spin_lock_irq(&current->sigmask_lock);
1596   - current->blocked = set;
1597   - recalc_sigpending(current);
1598   - spin_unlock_irq(&current->sigmask_lock);
1599   -#endif
1600 1607 fprintf(stderr, "returning %lx\n", env->regwptr[0]);
1601 1608 return env->regwptr[0];
1602 1609  
... ...
pc-bios/proll.bin deleted 100644 โ†’ 0
No preview for this file type
pc-bios/proll.elf 0 โ†’ 100644
No preview for this file type
pc-bios/proll.patch
1   -diff -ru proll_18.orig/mrcoffee/main.c proll_18/mrcoffee/main.c
2   ---- proll_18.orig/mrcoffee/main.c 2002-09-13 16:16:59.000000000 +0200
3   -+++ proll_18/mrcoffee/main.c 2004-09-26 11:52:23.000000000 +0200
4   -@@ -101,6 +101,7 @@
5   - le_probe();
6   - init_net();
  1 +diff -ruN proll_18.orig/Makefile proll-patch4/Makefile
  2 +--- proll_18.orig/Makefile 2002-09-13 14:16:59.000000000 +0000
  3 ++++ proll-patch4/Makefile 2004-11-13 15:50:49.000000000 +0000
  4 +@@ -4,6 +4,7 @@
  5 + make -C krups-ser all
  6 + make -C espresso all
  7 + make -C espresso-ser all
  8 ++ make -C qemu all
7 9  
  10 + clean:
  11 + make -C mrcoffee clean
  12 +@@ -11,3 +12,4 @@
  13 + make -C krups-ser clean
  14 + make -C espresso clean
  15 + make -C espresso-ser clean
  16 ++ make -C qemu clean
  17 +diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
  18 +--- proll_18.orig/qemu/head.S 1970-01-01 00:00:00.000000000 +0000
  19 ++++ proll-patch4/qemu/head.S 2004-11-13 15:50:49.000000000 +0000
  20 +@@ -0,0 +1,515 @@
  21 ++/**
  22 ++ ** Standalone startup code for Linux PROM emulator.
  23 ++ ** Copyright 1999 Pete A. Zaitcev
  24 ++ ** This code is licensed under GNU General Public License.
  25 ++ **/
  26 ++/*
  27 ++ * $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
  28 ++ */
  29 ++
  30 ++#include <psr.h>
  31 ++#include <asi.h>
  32 ++#include <crs.h>
  33 ++/* #include <asm/head.h> */ /* Trap entries. Do not use. */
  34 ++#include "phys_jj.h"
  35 ++
  36 ++#define C_LABEL(name) name
  37 ++#define REGWIN_SZ 0x40
  38 ++
  39 ++#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
  40 ++
  41 ++ /* 22 is 24-2, (va)>>(SRMMU_PGDIR_SHIFT-PTESIZESHFT) */
  42 ++#define VATOPGDOFF(va) (((va)>>22)&0x3FC)
  43 ++#define VATOPMDOFF(va) (((va)>>16)&0xFC)
  44 ++
  45 ++#define NOP_INSN 0x01000000 /* Used to patch sparc_save_state */
  46 ++
  47 ++/* Here are some trap goodies */
  48 ++
  49 ++#if 0
  50 ++/* Generic trap entry. */
  51 ++#define TRAP_ENTRY(type, label) \
  52 ++ rd %psr, %l0; b label; rd %wim, %l3; nop;
  53 ++#endif
  54 ++
  55 ++/* Data/text faults. */
  56 ++#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 1, %l7;
  57 ++#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 0, %l7;
  58 ++
  59 ++#if 0
  60 ++/* This is for traps we should NEVER get. */
  61 ++#define BAD_TRAP(num) \
  62 ++ rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
  63 ++
  64 ++/* This is for traps when we want just skip the instruction which caused it */
  65 ++#define SKIP_TRAP(type, name) \
  66 ++ jmpl %l2, %g0; rett %l2 + 4; nop; nop;
  67 ++
  68 ++/* Notice that for the system calls we pull a trick. We load up a
  69 ++ * different pointer to the system call vector table in %l7, but call
  70 ++ * the same generic system call low-level entry point. The trap table
  71 ++ * entry sequences are also HyperSparc pipeline friendly ;-)
  72 ++ */
  73 ++
  74 ++/* Software trap for Linux system calls. */
  75 ++#define LINUX_SYSCALL_TRAP \
  76 ++ sethi %hi(C_LABEL(sys_call_table)), %l7; \
  77 ++ or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
  78 ++ b linux_sparc_syscall; \
  79 ++ rd %psr, %l0;
  80 ++
  81 ++/* Software trap for SunOS4.1.x system calls. */
  82 ++#define SUNOS_SYSCALL_TRAP \
  83 ++ rd %psr, %l0; \
  84 ++ sethi %hi(C_LABEL(sunos_sys_table)), %l7; \
  85 ++ b linux_sparc_syscall; \
  86 ++ or %l7, %lo(C_LABEL(sunos_sys_table)), %l7;
  87 ++
  88 ++/* Software trap for Slowaris system calls. */
  89 ++#define SOLARIS_SYSCALL_TRAP \
  90 ++ b solaris_syscall; \
  91 ++ rd %psr, %l0; \
  92 ++ nop; \
  93 ++ nop;
  94 ++
  95 ++#define INDIRECT_SOLARIS_SYSCALL(x) \
  96 ++ mov x, %g1; \
  97 ++ b solaris_syscall; \
  98 ++ rd %psr, %l0; \
  99 ++ nop;
  100 ++
  101 ++#define BREAKPOINT_TRAP \
  102 ++ b breakpoint_trap; \
  103 ++ rd %psr,%l0; \
  104 ++ nop; \
  105 ++ nop;
  106 ++
  107 ++/* Software trap for Sparc-netbsd system calls. */
  108 ++#define NETBSD_SYSCALL_TRAP \
  109 ++ sethi %hi(C_LABEL(sys_call_table)), %l7; \
  110 ++ or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
  111 ++ b bsd_syscall; \
  112 ++ rd %psr, %l0;
  113 ++
  114 ++/* The Get Condition Codes software trap for userland. */
  115 ++#define GETCC_TRAP \
  116 ++ b getcc_trap_handler; mov %psr, %l0; nop; nop;
  117 ++
  118 ++/* The Set Condition Codes software trap for userland. */
  119 ++#define SETCC_TRAP \
  120 ++ b setcc_trap_handler; mov %psr, %l0; nop; nop;
  121 ++
  122 ++/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
  123 ++ * gets handled with another macro.
  124 ++ */
  125 ++#define TRAP_ENTRY_INTERRUPT(int_level) \
  126 ++ mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
  127 ++
  128 ++/* NMI's (Non Maskable Interrupts) are special, you can't keep them
  129 ++ * from coming in, and basically if you get one, the shows over. ;(
  130 ++ * On the sun4c they are usually asynchronous memory errors, on the
  131 ++ * the sun4m they could be either due to mem errors or a software
  132 ++ * initiated interrupt from the prom/kern on an SMP box saying "I
  133 ++ * command you to do CPU tricks, read your mailbox for more info."
  134 ++ */
  135 ++#define NMI_TRAP \
  136 ++ rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
  137 ++
  138 ++#endif
  139 ++
  140 ++/* Window overflows/underflows are special and we need to try to be as
  141 ++ * efficient as possible here....
  142 ++ */
  143 ++#define WINDOW_SPILL \
  144 ++ rd %psr, %l0; rd %wim, %l3; b spill_window_entry; nop;
  145 ++
  146 ++#define WINDOW_FILL \
  147 ++ rd %psr, %l0; rd %wim, %l3; b fill_window_entry; nop;
  148 ++
  149 ++#define STUB_TRAP ba stub_trap; nop; nop; nop;
  150 ++
  151 ++#define TRAP_ENTRY(a,b) STUB_TRAP
  152 ++#define SKIP_TRAP(a,b) STUB_TRAP
  153 ++#define SUNOS_SYSCALL_TRAP STUB_TRAP
  154 ++#define SOLARIS_SYSCALL_TRAP STUB_TRAP
  155 ++#define NETBSD_SYSCALL_TRAP STUB_TRAP
  156 ++#define LINUX_SYSCALL_TRAP STUB_TRAP
  157 ++#define BREAKPOINT_TRAP STUB_TRAP
  158 ++#define NMI_TRAP STUB_TRAP
  159 ++#define GETCC_TRAP STUB_TRAP
  160 ++#define SETCC_TRAP STUB_TRAP
  161 ++#define BAD_TRAP(n) STUB_TRAP
  162 ++#define TRAP_ENTRY_INTERRUPT(i) STUB_TRAP
  163 ++#define INDIRECT_SOLARIS_SYSCALL(i) STUB_TRAP
  164 ++
  165 ++ .section ".text"
  166 ++ .globl start, _start
  167 ++_start:
  168 ++start:
  169 ++ .globl spill_window_entry, fill_window_entry
  170 ++C_LABEL(trapbase):
  171 ++t_zero: b goprol; nop; nop; nop;
  172 ++t_tflt: SRMMU_TFAULT /* Inst. Access Exception */
  173 ++t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
  174 ++t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
  175 ++t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
  176 ++t_wovf: WINDOW_SPILL /* Window Overflow */
  177 ++t_wunf: WINDOW_FILL /* Window Underflow */
  178 ++t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
  179 ++t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
  180 ++t_dflt: SRMMU_DFAULT /* Data Miss Exception */
  181 ++t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
  182 ++t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
  183 ++t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
  184 ++t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
  185 ++t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
  186 ++t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
  187 ++t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
  188 ++t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
  189 ++t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
  190 ++t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
  191 ++t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
  192 ++t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
  193 ++t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
  194 ++t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
  195 ++t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
  196 ++t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
  197 ++t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
  198 ++t_nmi: NMI_TRAP /* Level 15 (NMI) */
  199 ++t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
  200 ++t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
  201 ++t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
  202 ++t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
  203 ++t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
  204 ++t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
  205 ++t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
  206 ++t_dacce:SRMMU_DFAULT /* Data Access Error */
  207 ++t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
  208 ++t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
  209 ++t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
  210 ++t_bad2d: BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f)
  211 ++ BAD_TRAP(0x30) BAD_TRAP(0x31) BAD_TRAP(0x32) BAD_TRAP(0x33)
  212 ++ BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36) BAD_TRAP(0x37)
  213 ++ BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
  214 ++t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
  215 ++ BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f)
  216 ++ BAD_TRAP(0x40) BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43)
  217 ++ BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46) BAD_TRAP(0x47)
  218 ++ BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
  219 ++ BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
  220 ++ BAD_TRAP(0x50) BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53)
  221 ++ BAD_TRAP(0x54) BAD_TRAP(0x55) BAD_TRAP(0x56) BAD_TRAP(0x57)
  222 ++ BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a) BAD_TRAP(0x5b)
  223 ++ BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
  224 ++ BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63)
  225 ++ BAD_TRAP(0x64) BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67)
  226 ++ BAD_TRAP(0x68) BAD_TRAP(0x69) BAD_TRAP(0x6a) BAD_TRAP(0x6b)
  227 ++ BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e) BAD_TRAP(0x6f)
  228 ++ BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
  229 ++ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77)
  230 ++ BAD_TRAP(0x78) BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b)
  231 ++ BAD_TRAP(0x7c) BAD_TRAP(0x7d) BAD_TRAP(0x7e) BAD_TRAP(0x7f)
  232 ++t_sunos:SUNOS_SYSCALL_TRAP /* SunOS System Call */
  233 ++t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
  234 ++t_divz: BAD_TRAP(0x82) /* Divide by zero trap */
  235 ++t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
  236 ++t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
  237 ++t_rchk: BAD_TRAP(0x85) /* Range Check */
  238 ++t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
  239 ++t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
  240 ++t_slowl:SOLARIS_SYSCALL_TRAP /* Slowaris System Call */
  241 ++t_netbs:NETBSD_SYSCALL_TRAP /* Net-B.S. System Call */
  242 ++t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d)
  243 ++ BAD_TRAP(0x8e) BAD_TRAP(0x8f)
  244 ++t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
  245 ++t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93)
  246 ++ BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97)
  247 ++ BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
  248 ++t_getcc:GETCC_TRAP /* Get Condition Codes */
  249 ++t_setcc:SETCC_TRAP /* Set Condition Codes */
  250 ++t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3)
  251 ++ BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
  252 ++t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
  253 ++ BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
  254 ++ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf)
  255 ++ BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3)
  256 ++ BAD_TRAP(0xb4) BAD_TRAP(0xb5) BAD_TRAP(0xb6) BAD_TRAP(0xb7)
  257 ++ BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) BAD_TRAP(0xbb)
  258 ++ BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
  259 ++t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3)
  260 ++ BAD_TRAP(0xc4) BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7)
  261 ++ BAD_TRAP(0xc8) BAD_TRAP(0xc9) BAD_TRAP(0xca) BAD_TRAP(0xcb)
  262 ++ BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce) BAD_TRAP(0xcf)
  263 ++ BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
  264 ++t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7)
  265 ++ BAD_TRAP(0xd8) BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb)
  266 ++ BAD_TRAP(0xdc) BAD_TRAP(0xdd) BAD_TRAP(0xde) BAD_TRAP(0xdf)
  267 ++ BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2) BAD_TRAP(0xe3)
  268 ++ BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
  269 ++t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb)
  270 ++ BAD_TRAP(0xec) BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef)
  271 ++ BAD_TRAP(0xf0) BAD_TRAP(0xf1) BAD_TRAP(0xf2) BAD_TRAP(0xf3)
  272 ++ BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) BAD_TRAP(0xf7)
  273 ++ BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
  274 ++t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
  275 ++dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
  276 ++dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
  277 ++
  278 ++stub_trap:
  279 ++ set (PHYS_JJ_TCX_FB + 0xbf0), %g5 /* 2 cells from side */
  280 ++ set 0x00ffffff, %g4
  281 ++ sta %g4, [%g5] ASI_M_BYPASS
  282 ++1: ba 1b; nop
  283 ++
  284 ++ .section ".bss"
  285 ++ .align 8
  286 ++bss_start:
  287 ++ .align 0x1000 ! PAGE_SIZE
  288 ++ .globl C_LABEL(bootup_user_stack)
  289 ++ .type bootup_user_stack,#object
  290 ++ .size bootup_user_stack,0x2000
  291 ++C_LABEL(bootup_user_stack): .skip 0x2000
  292 ++
  293 ++ .section ".text"
  294 ++
  295 ++goprol:
  296 ++ ! %g1 contains end of memory
  297 ++ ! map PROLDATA to PROLBASE+PROLSIZE to end of ram
  298 ++ set PROLSIZE+0x1000-PROLDATA+PROLBASE, %g2 ! add 0x1000 for temp tables
  299 ++ sub %g1, %g2, %g2 ! start of private memory
  300 ++ srl %g2, 0x4, %g7 ! ctx table at s+0x0
  301 ++ add %g2, 0x400, %g3 ! l1 table at s+0x400
  302 ++ srl %g3, 0x4, %g3
  303 ++ or %g3, 0x1, %g3
  304 ++ sta %g3, [%g2] ASI_M_BYPASS
  305 ++ add %g2, 0x400, %g2 ! s+0x400
  306 ++ add %g2, 0x800, %g3 ! l2 table for ram (00xxxxxx) at s+0x800
  307 ++ srl %g3, 0x4, %g3
  308 ++ or %g3, 0x1, %g3
  309 ++ sta %g3, [%g2] ASI_M_BYPASS
  310 ++ add %g2, 0x500, %g3 ! l2 table for rom (ffxxxxxx) at s+0x900
  311 ++ add %g2, 0x3fc, %g2 ! s+0x7fc
  312 ++ srl %g3, 0x4, %g3
  313 ++ or %g3, 0x1, %g3
  314 ++ sta %g3, [%g2] ASI_M_BYPASS
  315 ++ add %g2, 0x4, %g2 ! s+0x800
  316 ++ set ((7 << 2) | 2), %g3 ! 7 = U: --- S: RWX (main memory)
  317 ++ sta %g3, [%g2] ASI_M_BYPASS
  318 ++ add %g2, 0x200, %g3 ! l3 table for rom at s+0xa00
  319 ++ add %g2, 0x1d0, %g2 ! s+0x9d0
  320 ++ srl %g3, 0x4, %g3
  321 ++ or %g3, 0x1, %g3
  322 ++ sta %g3, [%g2] ASI_M_BYPASS
  323 ++ add %g2, 0x30, %g2 ! s+0xa00
  324 ++
  325 ++ set PROLBASE, %g3
  326 ++ set 0x1000, %g5
  327 ++ set (PROLDATA-PROLBASE)/0x1000, %g6 ! # of .text pages
  328 ++1: srl %g3, 0x4, %g4
  329 ++ or %g4, ((7 << 2) | 2), %g4 ! 4 = U: --X S: --X (rom, execute only)
  330 ++ sta %g4, [%g2] ASI_M_BYPASS
  331 ++ add %g2, 4, %g2
  332 ++ add %g3, %g5, %g3
  333 ++ deccc %g6
  334 ++ bne 1b
  335 ++ nop
  336 ++#if 0
  337 ++ set (PROLDATA-PROLRODATA)/0x1000, %g6 ! # of .rodata pages
  338 ++1: srl %g3, 0x4, %g4
  339 ++ or %g4, ((0 << 2) | 2), %g4 ! 0 = U: R-- S: R-- (rom, read only)
  340 ++ sta %g4, [%g2] ASI_M_BYPASS
  341 ++ add %g2, 4, %g2
  342 ++ add %g3, %g5, %g3
  343 ++ deccc %g6
  344 ++ bne 1b
  345 ++ nop
  346 ++#endif
  347 ++ set (PROLBASE+PROLSIZE-PROLDATA)/0x1000, %g6 ! # of .bss pages
  348 ++ set 0x1000, %g4
  349 ++ sll %g7, 0x4, %g3
  350 ++ add %g4, %g3, %g3
  351 ++1: srl %g3, 0x4, %g4
  352 ++ or %g4, ((7 << 2) | 2), %g4 ! 5 = U: R-- S: RW- (data area, read/write)
  353 ++ sta %g4, [%g2] ASI_M_BYPASS
  354 ++ add %g2, 4, %g2
  355 ++ add %g3, %g5, %g3
  356 ++ deccc %g6
  357 ++ bne 1b
  358 ++ nop
  359 ++
  360 ++ mov %g1, %g3
  361 ++
  362 ++ set AC_M_CTPR, %g2
  363 ++ sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr
  364 ++ set 1, %g1
  365 ++ sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
  366 ++
  367 ++ /*
  368 ++ * The code which enables traps is a simplified version of
  369 ++ * kernel head.S.
  370 ++ *
  371 ++ * We know number of windows as 8 so we do not calculate them.
  372 ++ * The deadwood is here for any case.
  373 ++ */
  374 ++
  375 ++ /* Turn on Supervisor, EnableFloating, and all the PIL bits.
  376 ++ * Also puts us in register window zero with traps off.
  377 ++ */
  378 ++ set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
  379 ++ wr %g2, 0x0, %psr
  380 ++ WRITE_PAUSE
  381 ++
  382 ++ /* I want a kernel stack NOW! */
  383 ++ set C_LABEL(bootup_user_stack), %g1
  384 ++ set (0x2000 - REGWIN_SZ), %g2
  385 ++ add %g1, %g2, %sp
  386 ++ mov 0, %fp /* And for good luck */
  387 ++
  388 ++ /* Zero out our BSS section. */
  389 ++ set C_LABEL(bss_start) , %o0 ! First address of BSS
  390 ++ set C_LABEL(end) , %o1 ! Last address of BSS
  391 ++ ba 2f
  392 ++ nop
  393 ++1:
  394 ++ st %g0, [%o0]
  395 ++2:
  396 ++ subcc %o0, %o1, %g0
  397 ++ bl 1b
  398 ++ add %o0, 0x4, %o0
  399 ++
  400 ++ sethi %hi( C_LABEL(ram_size) ), %o0
  401 ++ st %g3, [%o0 + %lo( C_LABEL(ram_size) )]
  402 ++
  403 ++ mov 2, %g1
  404 ++ wr %g1, 0x0, %wim ! make window 1 invalid
  405 ++ WRITE_PAUSE
  406 ++
  407 ++#if 0
  408 ++ wr %g0, 0x0, %wim
  409 ++ WRITE_PAUSE
  410 ++ save
  411 ++ rd %psr, %g3
  412 ++ restore
  413 ++ and %g3, PSR_CWP, %g3
  414 ++ add %g3, 0x1, %g3
  415 ++#else
  416 ++ or %g0, 8, %g3
  417 ++#endif
  418 ++
  419 ++#if 0
  420 ++ sethi %hi( C_LABEL(cputyp) ), %o0
  421 ++ st %g7, [%o0 + %lo( C_LABEL(cputyp) )]
  422 ++
  423 ++ sethi %hi( C_LABEL(nwindows) ), %g4
  424 ++ st %g3, [%g4 + %lo( C_LABEL(nwindows) )]
  425 ++
  426 ++ sub %g3, 0x1, %g3
  427 ++ sethi %hi( C_LABEL(nwindowsm1) ), %g4
  428 ++ st %g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
  429 ++#endif
  430 ++
  431 ++ /* Here we go, start using Linux's trap table... */
  432 ++ set C_LABEL(trapbase), %g3
  433 ++ wr %g3, 0x0, %tbr
  434 ++ WRITE_PAUSE
  435 ++
  436 ++ /* Finally, turn on traps so that we can call c-code. */
  437 ++ rd %psr, %g3
  438 ++ wr %g3, 0x0, %psr
  439 ++ WRITE_PAUSE
  440 ++
  441 ++ wr %g3, PSR_ET, %psr
  442 ++ WRITE_PAUSE
  443 ++
  444 ++ .globl prolmain
  445 ++ call C_LABEL(prolmain)
  446 ++ nop
  447 ++
  448 ++3:
  449 ++ b 3b
  450 ++ nop
  451 ++
  452 ++/*
  453 ++ * Memory access trap handler
  454 ++ * %l0 program %psr from trap table entry
  455 ++ * %l1 program %pc from hardware
  456 ++ * %l2 program %npc from hardware
  457 ++ * %l3 program %wim from trap table entry
  458 ++ * %l4
  459 ++ * %l5
  460 ++ * %l6
  461 ++ * %l7 text flag from trap table entry
  462 ++ */
  463 ++
  464 ++ .section ".text"
  465 ++ .globl srmmu_fault
  466 ++C_LABEL(srmmu_fault):
  467 ++
  468 ++ set AC_M_SFAR, %l6
  469 ++ set AC_M_SFSR, %l5
  470 ++ lda [%l6] ASI_M_MMUREGS, %l6
  471 ++ lda [%l5] ASI_M_MMUREGS, %l5
  472 ++
  473 ++ set ignore_fault, %l5
  474 ++ ld [%l5], %l5
  475 ++ subcc %l5, %g0, %g0 /* NULL pointer trap faults always */
  476 ++ be 3f
  477 ++ nop
  478 ++ subcc %l5, %l6, %g0
  479 ++ be 2f
  480 ++ nop
  481 ++3:
  482 ++
  483 ++ set (PHYS_JJ_TCX_FB + 0xbf0), %g5 /* 2 cells from side */
  484 ++ set 0x00ffffff, %g4
  485 ++ sta %g4, [%g5] ASI_M_BYPASS
  486 ++ add %g5, 8, %g5 /* On right side */
  487 ++ sta %g4, [%g5] ASI_M_BYPASS
  488 ++1: ba 1b; nop
  489 ++
  490 ++2:
  491 ++ set C_LABEL(fault_ignored), %l5
  492 ++ mov 1, %l6
  493 ++ st %l6, [%l5]
  494 ++
  495 ++ /*
  496 ++ * Skip the faulting instruction.
  497 ++ * I think it works when next instruction is a branch even.
  498 ++ */
  499 ++ or %l2, 0, %l1
  500 ++ add %l2, 4, %l2
  501 ++
  502 ++ wr %l0, 0, %psr
  503 ++ WRITE_PAUSE
  504 ++ jmp %l1
  505 ++ rett %l2
  506 ++
  507 ++/*
  508 ++ * Slow external versions of st_bypass and ld_bypass.
  509 ++ * rconsole.c uses inlines. We call these in places which are not speed
  510 ++ * critical, to avoid compiler bugs.
  511 ++ */
  512 ++ .globl C_LABEL(st_bypass)
  513 ++C_LABEL(st_bypass):
  514 ++ retl
  515 ++ sta %o1, [%o0] ASI_M_BYPASS
  516 ++ .globl C_LABEL(ld_bypass)
  517 ++C_LABEL(ld_bypass):
  518 ++ retl
  519 ++ lda [%o0] ASI_M_BYPASS, %o0
  520 ++ .globl C_LABEL(sth_bypass)
  521 ++C_LABEL(sth_bypass):
  522 ++ retl
  523 ++ stha %o1, [%o0] ASI_M_BYPASS
  524 ++ .globl C_LABEL(ldh_bypass)
  525 ++C_LABEL(ldh_bypass):
  526 ++ retl
  527 ++ lduha [%o0] ASI_M_BYPASS, %o0
  528 ++ .globl C_LABEL(stb_bypass)
  529 ++C_LABEL(stb_bypass):
  530 ++ retl
  531 ++ stba %o1, [%o0] ASI_M_BYPASS
  532 ++ .globl C_LABEL(ldb_bypass)
  533 ++C_LABEL(ldb_bypass):
  534 ++ retl
  535 ++ lduba [%o0] ASI_M_BYPASS, %o0
  536 +diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
  537 +--- proll_18.orig/qemu/main.c 1970-01-01 00:00:00.000000000 +0000
  538 ++++ proll-patch4/qemu/main.c 2004-11-23 19:05:34.000000000 +0000
  539 +@@ -0,0 +1,178 @@
  540 ++/**
  541 ++ ** Proll (PROM replacement)
  542 ++ ** Copyright 1999 Pete Zaitcev
  543 ++ ** This code is licensed under GNU General Public License.
  544 ++ **/
  545 ++#include <stdarg.h>
  546 ++
  547 ++// #include <asm/contregs.h>
  548 ++#include <asi.h>
  549 ++#include "pgtsrmmu.h"
  550 ++#include "iommu.h" /* Typical SBus IOMMU for sun4m */
  551 ++#include "phys_jj.h"
  552 ++#include "vconsole.h"
  553 ++#include "version.h"
  554 ++#include <general.h> /* __P() */
  555 ++#include <net.h> /* init_net() */
  556 ++#include <romlib.h> /* we are a provider for part of this. */
  557 ++#include <netpriv.h> /* myipaddr */
  558 ++#include <arpa.h>
  559 ++#include <system.h> /* our own prototypes */
  560 ++
  561 ++static void init_idprom(void);
  562 ++static void makepages_q(struct phym *t, unsigned int highbase);
  563 ++
  564 ++struct vconterm dp0;
  565 ++struct mem cmem; /* Current memory, virtual */
  566 ++struct mem cio; /* Current I/O space */
  567 ++struct phym pmem; /* Current phys. mem. */
  568 ++struct iommu ciommu; /* Our IOMMU on sun4m */
  569 ++
  570 ++static char *hw_idprom;
  571 ++int ignore_fault, fault_ignored, ram_size;
  572 ++
  573 ++/*
  574 ++ */
  575 ++void prolmain()
  576 ++{
  577 ++ //static const char fname[14] = "00000000.PROL";
  578 ++ static struct banks bb;
  579 ++ unsigned int hiphybas;
  580 ++ const void *romvec;
  581 ++
  582 ++ vcon_init(&dp0, PHYS_JJ_TCX_FB);
  583 ++ printk("PROLL %s QEMU\n", PROLL_VERSION_STRING);
  584 ++ printk("%d MB total\n", ram_size/(1024*1024));
  585 ++
  586 ++ bb.nbanks = 1;
  587 ++ bb.bankv[0].start = 0;
  588 ++ bb.bankv[0].length = ram_size;
  589 ++
  590 ++ hiphybas = ram_size - PROLSIZE;
  591 ++
  592 ++ mem_init(&cmem, (char *) &_end, (char *)(PROLBASE+PROLSIZE));
  593 ++ makepages_q(&pmem, hiphybas);
  594 ++ init_mmu_swift((unsigned int)pmem.pctp - PROLBASE + hiphybas);
  595 ++
  596 ++ mem_init(&cio, (char *)(PROLBASE+PROLSIZE),
  597 ++ (char *)(PROLBASE+PROLSIZE+IOMAPSIZE));
  598 ++
  599 ++ iommu_init(&ciommu, hiphybas);
  600 ++
  601 ++ /*
  602 ++ */
  603 ++ init_idprom();
  604 ++ sched_init();
  605 ++ le_probe();
  606 ++ init_net();
  607 ++
  608 ++#if 0
  609 ++#if 0 /* RARP */
  610 ++ if (rarp() != 0) fatal();
  611 ++ /* printrarp(); */
  612 ++ xtoa(myipaddr, fname, 8);
  613 ++ if (load(servaddr, fname) != 0) fatal();
  614 ++#else
  615 ++ if (bootp() != 0) fatal();
  616 ++ /*
  617 ++ * boot_rec.bp_file cannot be used because system PROM
  618 ++ * uses it to locate ourselves. If we load from boot_rec.bp_file,
  619 ++ * we will loop reloading PROLL over and over again.
  620 ++ * Thus we use traditional PROLL scheme HEXIPADDR.PROL (single L).
  621 ++ */
  622 ++ xtoa(myipaddr, fname, 8);
  623 ++ if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
  624 ++#endif
  625 ++#endif
  626 ++
  627 ++ romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
  628 ++
  629 ++ printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
  630 ++ PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
  631 ++ (int)cio.start, (int)cio.curp);
  632 ++ //set_timeout(5); while (!chk_timeout()) { } /* P3: let me read */
  633 ++
  634 ++ {
  635 ++ void (*entry)(const void *, int, int, int, int) = (void (*)(const void*, int, int, int, int)) LOADBASE;
  636 ++ entry(romvec, 0, 0, 0, 0);
  637 ++ }
  638 ++
  639 ++ mem_fini(&cmem);
  640 ++ vcon_fini(&dp0);
  641 ++}
  642 ++
  643 ++/*
  644 ++ * dvma_alloc over iommu_alloc.
  645 ++ */
  646 ++void *dvma_alloc(int size, unsigned int *pphys)
  647 ++{
  648 ++ return iommu_alloc(&ciommu, size, pphys);
  649 ++}
  650 ++
  651 ++/*
  652 ++ */
  653 ++void udelay(unsigned long usecs)
  654 ++{
  655 ++ int i, n;
  656 ++ n = usecs*50;
  657 ++ for (i = 0; i < n; i++) { }
  658 ++}
  659 ++
  660 ++static void init_idprom()
  661 ++{
  662 ++ char *va_prom;
  663 ++
  664 ++ if ((va_prom = map_io(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE)) == NULL) {
  665 ++ printk("init_idprom: cannot map eeprom\n");
  666 ++ fatal();
  667 ++ }
  668 ++ bcopy(va_prom + PHYS_JJ_IDPROM_OFF, idprom, IDPROM_SIZE);
  669 ++ /*
  670 ++ * hw_idprom is not used anywhere.
  671 ++ * It's just as we hate to leave hanging pointers (I/O page here).
  672 ++ */
  673 ++ hw_idprom = va_prom;
  674 ++}
  675 ++
  676 ++/*
  677 ++ * Make CPU page tables.
  678 ++ * Returns pointer to context table.
  679 ++ * Here we ignore memory allocation errors which "should not happen"
  680 ++ * because we cannot print anything anyways if memory initialization fails.
  681 ++ */
  682 ++void makepages_q(struct phym *t, unsigned int highbase)
  683 ++{
  684 ++ unsigned int *ctp, *l1, pte;
  685 ++ int i;
  686 ++ unsigned int pa, va;
  687 ++
  688 ++ ctp = mem_zalloc(&cmem, NCTX_SWIFT*sizeof(int), NCTX_SWIFT*sizeof(int));
  689 ++ l1 = mem_zalloc(&cmem, 256*sizeof(int), 256*sizeof(int));
  690 ++
  691 ++ pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4);
  692 ++ for (i = 0; i < NCTX_SWIFT; i++) {
  693 ++ ctp[i] = pte;
  694 ++ }
  695 ++
  696 ++ pa = PROLBASE;
  697 ++ for (va = PROLBASE; va < PROLDATA; va += PAGE_SIZE) {
  698 ++ map_page(l1, va, pa, 0, highbase);
  699 ++ pa += PAGE_SIZE;
  700 ++ }
  701 ++ pa = highbase + PROLDATA - PROLBASE;
  702 ++ for (va = PROLDATA; va < PROLBASE + PROLSIZE; va += PAGE_SIZE) {
  703 ++ map_page(l1, va, pa, 0, highbase);
  704 ++ pa += PAGE_SIZE;
  705 ++ }
  706 ++
  707 ++ /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
  708 ++ pa = 0;
  709 ++ for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
  710 ++ map_page(l1, va, pa, 0, highbase);
  711 ++ pa += PAGE_SIZE;
  712 ++ }
  713 ++
  714 ++ t->pctp = ctp;
  715 ++ t->pl1 = l1;
  716 ++ t->pbas = highbase;
  717 ++}
  718 +diff -ruN proll_18.orig/qemu/Makefile proll-patch4/qemu/Makefile
  719 +--- proll_18.orig/qemu/Makefile 1970-01-01 00:00:00.000000000 +0000
  720 ++++ proll-patch4/qemu/Makefile 2004-11-13 15:50:49.000000000 +0000
  721 +@@ -0,0 +1,119 @@
  722 ++#
  723 ++# proll:
  724 ++# qemu/Makefile - make PROLL for QEMU
  725 ++# $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
  726 ++#
  727 ++# Copyright 1999 Pete Zaitcev
  728 ++# This is Free Software is licensed under terms of GNU General Public License.
  729 ++#
  730 ++
  731 ++CC = gcc
  732 ++
  733 ++#CROSS = /usr/local/sparc/bin/sparc-sun-linux-
  734 ++CROSS = sparc-unknown-linux-gnu-
  735 ++
  736 ++CROSSCC = $(CROSS)gcc
  737 ++CROSSLD = $(CROSS)ld
  738 ++CROSSNM = $(CROSS)nm
  739 ++
  740 ++RM = /bin/rm -f
  741 ++ELFTOAOUT = elftoaout
  742 ++
  743 ++#
  744 ++SRC = ../src
  745 ++
  746 ++# Due to remapping algorithm PROLBASE should be algned on PMD.
  747 ++# We make PROLBASE a define instead of using _start because we
  748 ++# want to shift it to form a PGD entry. A relocatable label will not work.
  749 ++# Linux kernel expects us to be at LINUX_OPPROM_BEGVM <asm-sparc/openprom.h>.
  750 ++PROLBASE = 0xffd00000
  751 ++PROLRODATA = 0xffd07000
  752 ++PROLDATA = 0xffd09000
  753 ++PROLSIZE = (240*1024)
  754 ++
  755 ++# Linux
  756 ++# Fixed %g6 is for arch/sparc/kernel/head.S, it seems ok w/o -ffixed-g6.
  757 ++# Kernel uses -fcall-used-g5 -fcall-used-g7, we probably do not need them.
  758 ++# __ANSI__ is supposed to be on by default but it is not.
  759 ++CFLAGS = -O2 -Wall -DPROLBASE=$(PROLBASE) -DPROLDATA=$(PROLDATA) -DPROLRODATA=$(PROLRODATA) -D__ANSI__=1 -I$(SRC) -mcpu=hypersparc -g
  760 ++ASFLAGS = -D__ASSEMBLY__ -I$(SRC) -DPROLRODATA=$(PROLRODATA) -DPROLDATA=$(PROLDATA) -DPROLSIZE=$(PROLSIZE) -g
  761 ++# Solaris or Linux/i386 cross compilation
  762 ++#CFLAGS = -Iinclude -O
  763 ++
  764 ++LDFLAGS = -N -Ttext $(PROLBASE) --section-start .rodata=$(PROLRODATA) -Tdata $(PROLDATA) -Tbss $(PROLDATA)
  765 ++
  766 ++ALL = proll.aout
  767 ++PROLLEXE = proll.elf
  768 ++
  769 ++OBJS = head.o wuf.o wof.o main.o vconsole.o hconsole.o rconsole.o \
  770 ++ printf.o le.o system.o iommu.o \
  771 ++ arp.o netinit.o bootp.o packet.o tftp.o udp.o sched_4m.o openprom.o
  772 ++
  773 ++all: $(ALL)
  774 ++
  775 ++$(PROLLEXE): $(OBJS)
  776 ++ $(CROSSLD) $(LDFLAGS) -o $(PROLLEXE) $(OBJS)
  777 ++
  778 ++head.o: head.S $(SRC)/phys_jj.h \
  779 ++ $(SRC)/asi.h $(SRC)/psr.h $(SRC)/crs.h
  780 ++ $(CROSSCC) $(ASFLAGS) -DPROLBASE=$(PROLBASE) -o $*.o -c $*.S
  781 ++
  782 ++main.o: main.c $(SRC)/asi.h $(SRC)/pgtsrmmu.h $(SRC)/iommu.h \
  783 ++ $(SRC)/phys_jj.h $(SRC)/vconsole.h $(SRC)/version.h $(SRC)/general.h \
  784 ++ $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h
  785 ++ $(CROSSCC) $(CFLAGS) -c $*.c
  786 ++openprom.o: openprom.c $(SRC)/openprom.h $(SRC)/general.h $(SRC)/romlib.h \
  787 ++ $(SRC)/vconsole.h $(SRC)/system.h $(SRC)/phys_jj.h
  788 ++ $(CROSSCC) $(CFLAGS) -c $*.c
  789 ++
  790 ++system.o: $(SRC)/system.c $(SRC)/vconsole.h $(SRC)/pgtsrmmu.h \
  791 ++ $(SRC)/timer.h $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/asi.h \
  792 ++ $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h $(SRC)/crs.h
  793 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  794 ++iommu.o: $(SRC)/iommu.c $(SRC)/pgtsrmmu.h $(SRC)/phys_jj.h $(SRC)/iommu.h \
  795 ++ $(SRC)/vconsole.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/asi.h
  796 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  797 ++vconsole.o: $(SRC)/vconsole.c $(SRC)/vconsole.h $(SRC)/hconsole.h
  798 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  799 ++hconsole.o: $(SRC)/hconsole.c $(SRC)/hconsole.h $(SRC)/rconsole.h $(SRC)/phys_jj.h
  800 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  801 ++rconsole.o: $(SRC)/rconsole.c $(SRC)/rconsole.h
  802 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  803 ++printf.o: $(SRC)/printf.c
  804 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  805 ++le.o: $(SRC)/le.c $(SRC)/dma.h $(SRC)/system.h $(SRC)/netpriv.h $(SRC)/romlib.h $(SRC)/general.h $(SRC)/net.h $(SRC)/phys_jj.h
  806 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  807 ++
  808 ++arp.o: $(SRC)/arp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h
  809 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  810 ++netinit.o: $(SRC)/netinit.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
  811 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  812 ++tftp.o: $(SRC)/tftp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/tftp.h
  813 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  814 ++udp.o: $(SRC)/udp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
  815 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  816 ++packet.o: $(SRC)/packet.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h
  817 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  818 ++sched_4m.o: $(SRC)/sched_4m.c $(SRC)/system.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/phys_jj.h
  819 ++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
  820 ++bootp.o: $(SRC)/bootp.c $(SRC)/general.h $(SRC)/net.h \
  821 ++ $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/bootp.h
  822 ++ $(CROSSCC) $(CFLAGS) -DNOBPEXT=1 -c $(SRC)/$*.c
  823 ++
  824 ++wuf.o: $(SRC)/wuf.S
  825 ++ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
  826 ++wof.o: $(SRC)/wof.S
  827 ++ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
  828 ++
  829 ++#genlab.o: genlab.c
  830 ++# $(CC) -c $*.c
  831 ++#
  832 ++#genlab: genlab.o
  833 ++# $(CC) -o genlab genlab.o
  834 ++
  835 ++clean:
  836 ++ $(RM) $(OBJS)
  837 ++ $(RM) $(PROLLEXE) proll.aout
  838 ++
  839 ++proll.aout: $(PROLLEXE)
  840 ++ $(ELFTOAOUT) -o proll.aout $(PROLLEXE)
  841 +diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
  842 +--- proll_18.orig/qemu/openprom.c 1970-01-01 00:00:00.000000000 +0000
  843 ++++ proll-patch4/qemu/openprom.c 2004-11-23 19:14:05.000000000 +0000
  844 +@@ -0,0 +1,596 @@
  845 ++/*
  846 ++ * PROM interface support
  847 ++ * Copyright 1996 The Australian National University.
  848 ++ * Copyright 1996 Fujitsu Laboratories Limited
  849 ++ * Copyright 1999 Pete A. Zaitcev
  850 ++ * This software may be distributed under the terms of the Gnu
  851 ++ * Public License version 2 or later
  852 ++ */
  853 ++
  854 ++#include <openprom.h>
  855 ++#include <general.h>
  856 ++#include <romlib.h>
  857 ++#include <system.h>
  858 ++#include <vconsole.h>
  859 ++#include "phys_jj.h"
  860 ++
  861 ++struct property {
  862 ++ const char *name;
  863 ++ const char *value;
  864 ++ const int length;
  865 ++};
  866 ++
  867 ++struct node {
  868 ++ const struct property *properties;
  869 ++ /* short */ const int sibling;
  870 ++ /* short */ const int child;
  871 ++};
  872 ++
  873 ++static int obp_nextnode(int node);
  874 ++static int obp_child(int node);
  875 ++static int obp_proplen(int node, char *name);
  876 ++static int obp_getprop(int node, char *name, char *val);
  877 ++static int obp_setprop(int node, char *name, char *val, int len);
  878 ++static const char *obp_nextprop(int node, char *name);
  879 ++
  880 ++static char obp_idprom[IDPROM_SIZE];
  881 ++static const struct property null_properties = { NULL, NULL, -1 };
  882 ++static const int prop_true = -1;
  883 ++
  884 ++static const struct property propv_root[] = {
  885 ++ {"name", "SUNW,JavaStation-1", sizeof("SUNW,JavaStation-1") },
  886 ++ {"idprom", obp_idprom, IDPROM_SIZE},
  887 ++ {"banner-name", "JavaStation", sizeof("JavaStation")},
  888 ++ {"compatible", "sun4m", 6},
  889 ++ {NULL, NULL, -1}
  890 ++};
  891 ++
  892 ++static const int prop_iommu_reg[] = {
  893 ++ 0x0, 0x10000000, 0x00000300,
  894 ++};
  895 ++static const struct property propv_iommu[] = {
  896 ++ {"name", "iommu", sizeof("iommu")},
  897 ++ {"reg", (char*)&prop_iommu_reg[0], sizeof(prop_iommu_reg) },
  898 ++ {NULL, NULL, -1}
  899 ++};
  900 ++
  901 ++static const int prop_sbus_ranges[] = {
  902 ++ 0x0, 0x0, 0x0, 0x30000000, 0x10000000,
  903 ++ 0x1, 0x0, 0x0, 0x40000000, 0x10000000,
  904 ++ 0x2, 0x0, 0x0, 0x50000000, 0x10000000,
  905 ++ 0x3, 0x0, 0x0, 0x60000000, 0x10000000,
  906 ++ 0x4, 0x0, 0x0, 0x70000000, 0x10000000,
  907 ++};
  908 ++static const struct property propv_sbus[] = {
  909 ++ {"name", "sbus", 5},
  910 ++ {"ranges", (char*)&prop_sbus_ranges[0], sizeof(prop_sbus_ranges)},
  911 ++ {NULL, NULL, -1}
  912 ++};
  913 ++
  914 ++static const int prop_tcx_regs[] = {
  915 ++ 0x2, 0x00800000, 0x00100000,
  916 ++ 0x2, 0x02000000, 0x00000001,
  917 ++ 0x2, 0x04000000, 0x00800000,
  918 ++ 0x2, 0x06000000, 0x00800000,
  919 ++ 0x2, 0x0a000000, 0x00000001,
  920 ++ 0x2, 0x0c000000, 0x00000001,
  921 ++ 0x2, 0x0e000000, 0x00000001,
  922 ++ 0x2, 0x00700000, 0x00001000,
  923 ++ 0x2, 0x00200000, 0x00000004,
  924 ++ 0x2, 0x00300000, 0x0000081c,
  925 ++ 0x2, 0x00000000, 0x00010000,
  926 ++ 0x2, 0x00240000, 0x00000004,
  927 ++ 0x2, 0x00280000, 0x00000001,
  928 ++};
  929 ++
  930 ++#if 1 /* Zaitcev */
  931 ++static const int pixfreq = 0x03dfd240;
  932 ++static const int hbporch = 0xa0;
  933 ++static const int vfreq = 0x3c;
  934 ++#endif
  935 ++#if 0 /* Kevin Boone - 70Hz refresh */
  936 ++static const int pixfreq = 0x047868C0;
  937 ++static const int hbporch = 0x90;
  938 ++static const int vfreq = 0x46;
  939 ++#endif
  940 ++
  941 ++static const int vbporch = 0x1d;
  942 ++static const int vsync = 0x6;
  943 ++static const int hsync = 0x88;
  944 ++static const int vfporch = 0x3;
  945 ++static const int hfporch = 0x18;
  946 ++static const int height = 0x300;
  947 ++static const int width = 0x400;
  948 ++static const int linebytes = 0x400;
  949 ++static const int depth = 8;
  950 ++static const int tcx_intr[] = { 5, 0 };
  951 ++static const int tcx_interrupts = 5;
  952 ++static const struct property propv_sbus_tcx[] = {
  953 ++ {"name", "SUNW,tcx", sizeof("SUNW,tcx")},
  954 ++ {"vbporch", (char*)&vbporch, sizeof(int)},
  955 ++ {"hbporch", (char*)&hbporch, sizeof(int)},
  956 ++ {"vsync", (char*)&vsync, sizeof(int)},
  957 ++ {"hsync", (char*)&hsync, sizeof(int)},
  958 ++ {"vfporch", (char*)&vfporch, sizeof(int)},
  959 ++ {"hfporch", (char*)&hfporch, sizeof(int)},
  960 ++ {"pixfreq", (char*)&pixfreq, sizeof(int)},
  961 ++ {"vfreq", (char*)&vfreq, sizeof(int)},
  962 ++ {"height", (char*)&height, sizeof(int)},
  963 ++ {"width", (char*)&width, sizeof(int)},
  964 ++ {"linebytes", (char*)&linebytes, sizeof(int)},
  965 ++ {"depth", (char*)&depth, sizeof(int)},
  966 ++ {"reg", (char*)&prop_tcx_regs[0], sizeof(prop_tcx_regs)},
  967 ++ {"tcx-8-bit", (char*)&prop_true, 0},
  968 ++ {"intr", (char*)&tcx_intr[0], sizeof(tcx_intr)},
  969 ++ {"interrupts", (char*)&tcx_interrupts, sizeof(tcx_interrupts)},
  970 ++ {"device_type", "display", sizeof("display")},
  971 ++ {NULL, NULL, -1}
  972 ++};
  973 ++
  974 ++static const int prop_cs4231_reg[] = {
  975 ++ 0x3, 0x0C000000, 0x00000040
  976 ++};
  977 ++static const int cs4231_interrupts = 5;
  978 ++static const int cs4231_intr[] = { 5, 0 };
  979 ++
  980 ++static const struct property propv_sbus_cs4231[] = {
  981 ++ {"name", "SUNW,CS4231", sizeof("SUNW,CS4231") },
  982 ++ {"intr", (char*)&cs4231_intr[0], sizeof(cs4231_intr) },
  983 ++ {"interrupts", (char*)&cs4231_interrupts, sizeof(cs4231_interrupts) },
  984 ++ {"reg", (char*)&prop_cs4231_reg[0], sizeof(prop_cs4231_reg) },
  985 ++ {"device_type", "serial", sizeof("serial") },
  986 ++ {"alias", "audio", sizeof("audio") },
  987 ++ {NULL, NULL, -1}
  988 ++};
  989 ++
  990 ++static const int cpu_nctx = NCTX_SWIFT;
  991 ++static const int cpu_cache_line_size = 0x20;
  992 ++static const int cpu_cache_nlines = 0x200;
  993 ++static const struct property propv_cpu[] = {
  994 ++ {"name", "STP1012PGA", sizeof("STP1012PGA") },
  995 ++ {"device_type", "cpu", 4 },
  996 ++ {"mmu-nctx", (char*)&cpu_nctx, sizeof(int)},
  997 ++ {"cache-line-size", (char*)&cpu_cache_line_size, sizeof(int)},
  998 ++ {"cache-nlines", (char*)&cpu_cache_nlines, sizeof(int)},
  999 ++ {NULL, NULL, -1}
  1000 ++};
  1001 ++
  1002 ++static const int prop_obio_ranges[] = {
  1003 ++ 0x0, 0x0, 0x0, 0x71000000, 0x01000000,
  1004 ++};
  1005 ++static const struct property propv_obio[] = {
  1006 ++ {"name", "obio", 5 },
  1007 ++ {"ranges", (char*)&prop_obio_ranges[0], sizeof(prop_obio_ranges) },
  1008 ++ {NULL, NULL, -1}
  1009 ++};
  1010 ++
  1011 ++static const int prop_auxio_reg[] = {
  1012 ++ 0x0, 0x00900000, 0x00000001,
  1013 ++};
  1014 ++static const struct property propv_obio_auxio[] = {
  1015 ++ {"name", "auxio", sizeof("auxio") },
  1016 ++ {"reg", (char*)&prop_auxio_reg[0], sizeof(prop_auxio_reg) },
  1017 ++ {NULL, NULL, -1}
  1018 ++};
  1019 ++
  1020 ++static const int prop_int_reg[] = {
  1021 ++ 0x0, 0x00e00000, 0x00000010,
  1022 ++ 0x0, 0x00e10000, 0x00000010,
  1023 ++};
  1024 ++static const struct property propv_obio_int[] = {
  1025 ++ {"name", "interrupt", sizeof("interrupt")},
  1026 ++ {"reg", (char*)&prop_int_reg[0], sizeof(prop_int_reg) },
  1027 ++ {NULL, NULL, -1}
  1028 ++};
  1029 ++
  1030 ++static const int prop_cnt_reg[] = {
  1031 ++ 0x0, 0x00d00000, 0x00000010,
  1032 ++ 0x0, 0x00d10000, 0x00000010,
  1033 ++};
  1034 ++static const struct property propv_obio_cnt[] = {
  1035 ++ {"name", "counter", sizeof("counter")},
  1036 ++ {"reg", (char*)&prop_cnt_reg[0], sizeof(prop_cnt_reg) },
  1037 ++ {NULL, NULL, -1}
  1038 ++};
  1039 ++
  1040 ++static const int prop_eeprom_reg[] = {
  1041 ++ 0x0, 0x00200000, 0x00002000,
  1042 ++};
  1043 ++static const struct property propv_obio_eep[] = {
  1044 ++ {"name", "eeprom", sizeof("eeprom")},
  1045 ++ {"reg", (char*)&prop_eeprom_reg[0], sizeof(prop_eeprom_reg) },
  1046 ++ {"model", "mk48t08", sizeof("mk48t08")},
  1047 ++ {NULL, NULL, -1}
  1048 ++};
  1049 ++
  1050 ++static const int prop_su_reg[] = {
  1051 ++ 0x0, 0x003002f8, 0x00000008,
  1052 ++};
  1053 ++static const struct property propv_obio_su[] = {
  1054 ++ {"name", "su", sizeof("su")},
  1055 ++ {"reg", (char*)&prop_su_reg[0], sizeof(prop_su_reg) },
  1056 ++ {NULL, NULL, -1}
  1057 ++};
  1058 ++
  1059 ++static const int prop_zs_intr[] = { 0x26, 0x0 };
  1060 ++static const int prop_zs_reg[] = {
  1061 ++ 0x4, 0x00000000, 0x0000000f,
  1062 ++};
  1063 ++static const int prop_zs_slave[] = { 0x1 };
  1064 ++static const struct property propv_obio_zs[] = {
  1065 ++ {"name", "zs", sizeof("zs")},
  1066 ++ {"reg", (char*)&prop_zs_reg[0], sizeof(prop_zs_reg) },
  1067 ++ {"reg", (char*)&prop_zs_slave[0], sizeof(prop_zs_slave) },
  1068 ++ {"device_type", "serial", sizeof("serial") },
  1069 ++ {NULL, NULL, -1}
  1070 ++};
  1071 ++
  1072 ++static const int prop_zs1_intr[] = { 0x26, 0x0 };
  1073 ++static const int prop_zs1_reg[] = {
  1074 ++ 0x4, 0x00100000, 0x0000000f,
  1075 ++};
  1076 ++static const int prop_zs1_slave[] = { 0x0 };
  1077 ++static const struct property propv_obio_zs1[] = {
  1078 ++ {"name", "zs", sizeof("zs")},
  1079 ++ {"reg", (char*)&prop_zs1_reg[0], sizeof(prop_zs1_reg) },
  1080 ++ {"reg", (char*)&prop_zs1_slave[0], sizeof(prop_zs1_slave) },
  1081 ++ {"device_type", "serial", sizeof("serial") },
  1082 ++ {NULL, NULL, -1}
  1083 ++};
  1084 ++
  1085 ++static const int prop_ledma_reg[] = {
  1086 ++ 0x4, 0x08400010, 0x00000020,
  1087 ++};
  1088 ++static const int prop_ledma_burst = 0x3f;
  1089 ++static const struct property propv_sbus_ledma[] = {
  1090 ++ {"name", "ledma", sizeof("ledma")},
  1091 ++ {"reg", (char*)&prop_ledma_reg[0], sizeof(prop_ledma_reg) },
  1092 ++ {"burst-sizes", (char*)&prop_ledma_burst, sizeof(int) },
  1093 ++ {NULL, NULL, -1}
  1094 ++};
  1095 ++
  1096 ++static const int prop_le_reg[] = {
  1097 ++ 0x4, 0x08c00000, 0x00000004,
  1098 ++};
  1099 ++static const int prop_le_busmaster_regval = 0x7;
  1100 ++static const int prop_le_intr[] = { 0x26, 0x0 };
  1101 ++static const struct property propv_sbus_ledma_le[] = {
  1102 ++ {"name", "le", sizeof("le")},
  1103 ++ {"reg", (char*)&prop_le_reg[0], sizeof(prop_le_reg) },
  1104 ++ {"busmaster-regval", (char*)&prop_le_busmaster_regval, sizeof(int)},
  1105 ++ {"intr", (char*)&prop_le_intr[0], sizeof(prop_le_intr) },
  1106 ++ {NULL, NULL, -1}
  1107 ++};
  1108 ++
  1109 ++static const struct node nodes[] = {
  1110 ++ { &null_properties, 1, 0 }, /* 0 = big brother of root */
  1111 ++ { propv_root, 0, 2 }, /* 1 "/" */
  1112 ++ { propv_iommu, 8, 3 }, /* 2 "/iommu" */
  1113 ++ { propv_sbus, 0, 4 }, /* 3 "/iommu/sbus" */
  1114 ++ { propv_sbus_tcx, 5, 0 }, /* 4 "/iommu/sbus/SUNW,tcx" */
  1115 ++ { propv_sbus_ledma, 7, 6 }, /* 5 "/iommu/sbus/ledma" */
  1116 ++ { propv_sbus_ledma_le, 0, 0 }, /* 6 "/iommu/sbus/ledma/le" */
  1117 ++ { propv_sbus_cs4231, 0, 0 }, /* 7 "/iommu/sbus/SUNW,CS4231 */
  1118 ++ { propv_cpu, 9, 0 }, /* 8 "/STP1012PGA" */
  1119 ++ { propv_obio, 0, 10 }, /* 9 "/obio" */
  1120 ++ { propv_obio_int, 11, 0 }, /* 10 "/obio/interrupt" */
  1121 ++ { propv_obio_cnt, 12, 0 }, /* 11 "/obio/counter" */
  1122 ++ { propv_obio_eep, 13, 0 }, /* 12 "/obio/eeprom" */
  1123 ++ { propv_obio_su, 14, 0 }, /* 13 "/obio/su" */
  1124 ++ { propv_obio_auxio, 0, 0 }, /* 14 "/obio/auxio" */
  1125 ++ { propv_obio_zs, 0, 0 }, /* 14 "/obio/zs@0,0" */
  1126 ++ { propv_obio_zs1, 0, 0 }, /* 14 "/obio/zs@0,100000" */
  1127 ++};
  1128 ++
  1129 ++static struct linux_mlist_v0 totphys[MAX_BANKS];
  1130 ++static struct linux_mlist_v0 totmap[1];
  1131 ++static struct linux_mlist_v0 totavail[MAX_BANKS];
  1132 ++
  1133 ++static struct linux_mlist_v0 *ptphys;
  1134 ++static struct linux_mlist_v0 *ptmap;
  1135 ++static struct linux_mlist_v0 *ptavail;
  1136 ++
  1137 ++static const struct linux_nodeops nodeops0 = {
  1138 ++ obp_nextnode, /* int (*no_nextnode)(int node); */
  1139 ++ obp_child, /* int (*no_child)(int node); */
  1140 ++ obp_proplen, /* int (*no_proplen)(int node, char *name); */
  1141 ++ obp_getprop, /* int (*no_getprop)(int node,char *name,char *val); */
  1142 ++ obp_setprop, /* int (*no_setprop)(int node, char *name,
  1143 ++ char *val, int len); */
  1144 ++ obp_nextprop /* char * (*no_nextprop)(int node, char *name); */
  1145 ++};
  1146 ++
  1147 ++static const char arg_nfsroot[] = "console=ttyS0 ip=bootp root=nfs";
  1148 ++
  1149 ++static const struct linux_arguments_v0 obp_arg = {
  1150 ++ { "le()", arg_nfsroot, NULL, NULL, NULL, NULL, NULL, NULL },
  1151 ++ { "" },
  1152 ++ { 'l', 'e' }, 0, 0, 0, NULL,
  1153 ++ NULL
  1154 ++};
  1155 ++static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
  1156 ++
  1157 ++static const void * const synch_hook = NULL;
  1158 ++#if 0
  1159 ++static const char obp_stdin = PROMDEV_KBD;
  1160 ++static const char obp_stdout = PROMDEV_SCREEN;
  1161 ++#else
  1162 ++static const char obp_stdin = PROMDEV_TTYA;
  1163 ++static const char obp_stdout = PROMDEV_TTYA;
  1164 ++#endif
  1165 ++
  1166 ++static int obp_nbgetchar(void);
  1167 ++static int obp_nbputchar(int ch);
  1168 ++static void obp_reboot(char *);
  1169 ++static void obp_abort(void);
  1170 ++static void obp_halt(void);
  1171 ++static int obp_devopen(char *str);
  1172 ++static int obp_devclose(int dev_desc);
  1173 ++static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf);
  1174 ++
  1175 ++static void doublewalk(unsigned ptab1, unsigned va)
  1176 ++{
  1177 ++unsigned int proc_tablewalk(int ctx, unsigned int va);
  1178 ++unsigned int mem_tablewalk(unsigned int pa, unsigned int va);
  1179 ++
  1180 ++ proc_tablewalk(0, va);
  1181 ++ if (ptab1 != 0) mem_tablewalk(ptab1, va);
  1182 ++}
  1183 ++
8 1184 +#ifdef ORIG
9   - #if 0 /* RARP */
10   - if (rarp() != 0) fatal();
11   - /* printrarp(); */
12   -@@ -117,13 +118,20 @@
13   - xtoa(myipaddr, fname, 8);
14   - if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
  1185 ++static const struct linux_romvec romvec0 = {
  1186 ++ LINUX_OPPROM_MAGIC, /* pv_magic_cookie */
  1187 ++ 0, /* pv_romvers - Format selector! */
  1188 ++ 77, /* pv_plugin_revision */
  1189 ++ 0x10203, /* pv_printrev */
  1190 ++ { /* pv_v0mem */
  1191 ++ &ptphys, /* v0_totphys */
  1192 ++ &ptmap, /* v0_prommap */
  1193 ++ &ptavail /* v0_available */
  1194 ++ },
  1195 ++ &nodeops0, /* struct linux_nodeops *pv_nodeops; */
  1196 ++ (void*)doublewalk, /* P3 */ /* char **pv_bootstr; */
  1197 ++ { /* struct linux_dev_v0_funcs pv_v0devops; */
  1198 ++ &obp_devopen, /* v0_devopen */
  1199 ++ &obp_devclose, /* v0_devclose */
  1200 ++ &obp_rdblkdev, /* v0_rdblkdev */
  1201 ++ NULL, /* v0_wrblkdev */
  1202 ++ NULL, /* v0_wrnetdev */
  1203 ++ NULL, /* v0_rdnetdev */
  1204 ++ NULL, /* v0_rdchardev */
  1205 ++ NULL, /* v0_wrchardev */
  1206 ++ NULL /* v0_seekdev */
  1207 ++ },
  1208 ++ &obp_stdin, /* char *pv_stdin */
  1209 ++ &obp_stdout, /* char *pv_stdout; */
  1210 ++ obp_nbgetchar, /* int (*pv_getchar)(void); */
  1211 ++ obp_nbputchar, /* void (*pv_putchar)(int ch); */
  1212 ++ obp_nbgetchar, /* int (*pv_nbgetchar)(void); */
  1213 ++ obp_nbputchar, /* int (*pv_nbputchar)(int ch); */
  1214 ++ NULL, /* void (*pv_putstr)(char *str, int len); */
  1215 ++ obp_reboot, /* void (*pv_reboot)(char *bootstr); */
  1216 ++ NULL, /* void (*pv_printf)(__const__ char *fmt, ...); */
  1217 ++ obp_abort, /* void (*pv_abort)(void); */
  1218 ++ NULL, /* __volatile__ int *pv_ticks; */
  1219 ++ obp_halt, /* void (*pv_halt)(void); */
  1220 ++ (void *)&synch_hook, /* void (**pv_synchook)(void); */
  1221 ++
  1222 ++#if 0
  1223 ++ /* Evaluate a forth string, not different proto for V0 and V2->up. */
  1224 ++ union {
  1225 ++ void (*v0_eval)(int len, char *str);
  1226 ++ void (*v2_eval)(char *str);
  1227 ++ } pv_fortheval;
  1228 ++#endif
  1229 ++ { 0 }, /* pv_fortheval */
  1230 ++
  1231 ++ &obp_argp, /* struct linux_arguments_v0 **pv_v0bootargs; */
  1232 ++ NULL, /* pv_enaddr */
  1233 ++ { /* pv_v2bootargs */
  1234 ++ NULL, /* char **bootpath; */
  1235 ++ NULL, /* char **bootargs; */
  1236 ++ NULL, /* fd_stdin; */
  1237 ++ NULL, /* fd_stdout */
  1238 ++ },
  1239 ++ { /* pv_v2devops */
  1240 ++ NULL, /* v2_inst2pkg */
  1241 ++ NULL, /* v2_dumb_mem_alloc */
  1242 ++ NULL, /* v2_dumb_mem_free */
  1243 ++ NULL, /* v2_dumb_mmap */
  1244 ++ NULL, /* v2_dumb_munmap */
  1245 ++ NULL, /* v2_dev_open */
  1246 ++ NULL, /* v2_dev_close */
  1247 ++ NULL, /* v2_dev_read */
  1248 ++ NULL, /* v2_dev_write */
  1249 ++ NULL, /* v2_dev_seek */
  1250 ++ NULL, /* v2_wheee2 */
  1251 ++ NULL, /* v2_wheee3 */
  1252 ++ },
  1253 ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* filler[15] */
  1254 ++ NULL, /* pv_setctxt */
  1255 ++ NULL, /* v3_cpustart */
  1256 ++ NULL, /* v3_cpustop */
  1257 ++ NULL, /* v3_cpuidle */
  1258 ++ NULL /* v3_cpuresume */
  1259 ++};
  1260 ++#endif
  1261 ++
  1262 ++static struct linux_romvec romvec0;
  1263 ++
  1264 ++void *
  1265 ++init_openprom(int bankc, struct bank *bankv, unsigned hiphybas)
  1266 ++{
  1267 ++ int i;
  1268 ++
  1269 ++ /*
  1270 ++ * Avoid data segment allocations
  1271 ++ */
  1272 ++ ptphys = totphys;
  1273 ++ ptmap = totmap;
  1274 ++ ptavail = totavail;
  1275 ++ /*
  1276 ++ * Form memory descriptors.
  1277 ++ */
  1278 ++ for (i = 0; i < bankc; i++) {
  1279 ++ totphys[i].theres_more = &totphys[i+1];
  1280 ++ totphys[i].start_adr = (char*) bankv[i].start;
  1281 ++ totphys[i].num_bytes = bankv[i].length;
  1282 ++ }
  1283 ++ totphys[i-1].theres_more = 0;
  1284 ++
  1285 ++ /*
  1286 ++ * XXX Merged in normal PROM when full banks touch.
  1287 ++ */
  1288 ++ for (i = 0; i < bankc; i++) {
  1289 ++ unsigned bankbase = bankv[i].start;
  1290 ++ unsigned banksize = bankv[i].length;
  1291 ++ if (hiphybas > bankbase &&
  1292 ++ hiphybas < bankbase + banksize) {
  1293 ++ banksize = hiphybas - bankbase;
  1294 ++ }
  1295 ++ totavail[i].theres_more = &totavail[i+1];
  1296 ++ totavail[i].start_adr = (char*) bankbase;
  1297 ++ totavail[i].num_bytes = banksize;
  1298 ++ }
  1299 ++ totavail[i-1].theres_more = 0;
  1300 ++
  1301 ++ totmap[0].theres_more = 0;
  1302 ++ totmap[0].start_adr = (char*) PROLBASE;
  1303 ++ totmap[0].num_bytes = PROLSIZE;
  1304 ++
  1305 ++ /*
  1306 ++ * idprom
  1307 ++ */
  1308 ++ bcopy(idprom, obp_idprom, IDPROM_SIZE);
  1309 ++
  1310 ++ // Linux wants a R/W romvec table
  1311 ++ romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
  1312 ++ romvec0.pv_plugin_revision = 77;
  1313 ++ romvec0.pv_printrev = 0x10203;
  1314 ++ romvec0.pv_v0mem.v0_totphys = &ptphys;
  1315 ++ romvec0.pv_v0mem.v0_prommap = &ptmap;
  1316 ++ romvec0.pv_v0mem.v0_available = &ptavail;
  1317 ++ romvec0.pv_nodeops = &nodeops0;
  1318 ++ romvec0.pv_bootstr = (void *)doublewalk;
  1319 ++ romvec0.pv_stdin = &obp_stdin;
  1320 ++ romvec0.pv_stdout = &obp_stdout;
  1321 ++ romvec0.pv_getchar = obp_nbgetchar;
  1322 ++ romvec0.pv_putchar = obp_nbputchar;
  1323 ++ romvec0.pv_nbgetchar = obp_nbgetchar;
  1324 ++ romvec0.pv_nbputchar = obp_nbputchar;
  1325 ++ romvec0.pv_reboot = obp_reboot;
  1326 ++ romvec0.pv_abort = obp_abort;
  1327 ++ romvec0.pv_halt = obp_halt;
  1328 ++ romvec0.pv_synchook = &synch_hook;
  1329 ++ romvec0.pv_v0bootargs = &obp_argp;
  1330 ++ return &romvec0;
  1331 ++}
  1332 ++
  1333 ++static const struct property *find_property(int node,char *name)
  1334 ++{
  1335 ++ const struct property *prop = &nodes[node].properties[0];
  1336 ++ while (prop && prop->name) {
  1337 ++ if (bcmp(prop->name, name, 128) == 0) return prop;
  1338 ++ prop++;
  1339 ++ }
  1340 ++ return NULL;
  1341 ++}
  1342 ++
  1343 ++static int obp_nextnode(int node)
  1344 ++{
  1345 ++ return nodes[node].sibling;
  1346 ++}
  1347 ++
  1348 ++static int obp_child(int node)
  1349 ++{
  1350 ++ return nodes[node].child;
  1351 ++}
  1352 ++
  1353 ++static int obp_proplen(int node, char *name)
  1354 ++{
  1355 ++ const struct property *prop = find_property(node,name);
  1356 ++ if (prop) return prop->length;
  1357 ++ return -1;
  1358 ++}
  1359 ++
  1360 ++static int obp_getprop(int node, char *name, char *value)
  1361 ++{
  1362 ++ const struct property *prop;
  1363 ++
  1364 ++ prop = find_property(node,name);
  1365 ++ if (prop) {
  1366 ++ memcpy(value,prop->value,prop->length);
  1367 ++ //printk("obp_getprop '%s'= %s\n", name, value);
  1368 ++ return prop->length;
  1369 ++ }
  1370 ++ //printk("obp_getprop: not found\n");
  1371 ++ return -1;
  1372 ++}
  1373 ++
  1374 ++static int obp_setprop(int node, char *name, char *value, int len)
  1375 ++{
  1376 ++ return -1;
  1377 ++}
  1378 ++
  1379 ++static const char *obp_nextprop(int node,char *name)
  1380 ++{
  1381 ++ const struct property *prop = find_property(node,name);
  1382 ++ if (prop) return prop[1].name;
  1383 ++ return NULL;
  1384 ++}
  1385 ++
  1386 ++#if 0
  1387 ++static unsigned char calc_idprom_cksum(struct idprom *idprom)
  1388 ++{
  1389 ++ unsigned char cksum, i, *ptr = (unsigned char *)idprom;
  1390 ++
  1391 ++ for (i = cksum = 0; i <= 0x0E; i++)
  1392 ++ cksum ^= *ptr++;
  1393 ++
  1394 ++ return cksum;
  1395 ++}
  1396 ++#endif
  1397 ++
  1398 ++static int obp_nbgetchar(void) {
  1399 ++ return -1;
  1400 ++}
  1401 ++
  1402 ++static int obp_nbputchar(int ch) {
  1403 ++ extern struct vconterm dp0;
  1404 ++ char buf = ch;
  1405 ++
  1406 ++ /* We do not use printk() in order to reduce stack depth. */
  1407 ++ vcon_write(&dp0, &buf, 1);
  1408 ++ return 0;
  1409 ++}
  1410 ++
  1411 ++static void obp_reboot(char *str) {
  1412 ++ printk("rebooting (%s): not implemented, freezing\n", str);
  1413 ++ for (;;) {}
  1414 ++}
  1415 ++
  1416 ++static void obp_abort() {
  1417 ++ printk("abort, freezing\n");
  1418 ++ for (;;) {}
  1419 ++}
  1420 ++
  1421 ++static void obp_halt() {
  1422 ++ printk("halt, freezing\n");
  1423 ++ for (;;) {}
  1424 ++}
  1425 ++
  1426 ++static int obp_devopen(char *str) {
  1427 ++ //printk("open %s\n", str);
  1428 ++ return 0;
  1429 ++}
  1430 ++
  1431 ++static int obp_devclose(int dev_desc) {
  1432 ++ //printk("close %d\n", dev_desc);
  1433 ++ return 0;
  1434 ++}
  1435 ++
  1436 ++static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf) {
  1437 ++ //printk("rdblkdev: fd %d, num_blks %d, blk_st %d, buf 0x%x\n", dev_desc, num_blks, blk_st, buf);
  1438 ++ //buf[8] = 'L';
  1439 ++ return num_blks;
  1440 ++}
  1441 +diff -ruN proll_18.orig/src/arp.c proll-patch4/src/arp.c
  1442 +--- proll_18.orig/src/arp.c 2001-12-24 05:12:31.000000000 +0000
  1443 ++++ proll-patch4/src/arp.c 2004-11-13 15:50:49.000000000 +0000
  1444 +@@ -45,7 +45,7 @@
  1445 + #endif
  1446 + static struct arp_cache arp_list[ARPNUM]; /* ARP address cache */
  1447 + static int next_arp; /* next table entry */
  1448 +-static t_ipaddr def_gw = IP_ANY; /* default routing */
  1449 ++static t_ipaddr def_gw; /* default routing */
  1450 +
  1451 +
  1452 +
  1453 +@@ -144,7 +144,7 @@
  1454 + *
  1455 + * Resolve IP address and return pointer to hardware address.
  1456 + */
  1457 +-unsigned char *ip_resolve(ip)
  1458 ++const unsigned char *ip_resolve(ip)
  1459 + t_ipaddr ip;
  1460 + {
  1461 + int i;
  1462 +@@ -230,14 +230,11 @@
  1463 + */
  1464 + int init_arp()
  1465 + {
  1466 +- /* Set name of module for error messages */
  1467 +- net_module_name = "arp";
  1468 +-
  1469 + #ifndef NOARP
  1470 + /* Register ARP packet type and set send buffer pointer */
  1471 + if ((arpbuf = (struct arphdr *)reg_type(htons(ETH_P_ARP), arp_recv)) == NULL)
  1472 + return(FALSE);
15 1473 #endif
  1474 +-
  1475 ++ def_gw = IP_ANY;
  1476 + return(TRUE);
  1477 + }
  1478 +diff -ruN proll_18.orig/src/arp.h proll-patch4/src/arp.h
  1479 +--- proll_18.orig/src/arp.h 1999-03-18 03:39:43.000000000 +0000
  1480 ++++ proll-patch4/src/arp.h 2004-11-13 15:50:49.000000000 +0000
  1481 +@@ -104,7 +104,7 @@
  1482 + extern int init_arp __P((void));
  1483 +
  1484 + /* Resolve IP address and return pointer to hardware address */
  1485 +-extern unsigned char *ip_resolve __P((t_ipaddr ip));
  1486 ++extern const unsigned char *ip_resolve __P((t_ipaddr ip));
  1487 +
  1488 + /* Add a new antry to the ARP cache */
  1489 + extern void addcache __P((unsigned char *ha, t_ipaddr ip));
  1490 +diff -ruN proll_18.orig/src/hconsole.c proll-patch4/src/hconsole.c
  1491 +--- proll_18.orig/src/hconsole.c 2002-07-23 05:52:48.000000000 +0000
  1492 ++++ proll-patch4/src/hconsole.c 2004-11-13 15:50:49.000000000 +0000
  1493 +@@ -42,7 +42,11 @@
  1494 + * No probing sequence or argument passing, hardcode everything. XXX
  1495 + */
  1496 + raster8_cons_a(q, 768, 1024, (char *)a0);
  1497 ++#if 1
  1498 + raster_cons_2(r, q, 768-(24*11)-1, 1024-(8*80)-1, (24*11), (8*80));
  1499 ++#else
  1500 ++ raster_cons_2(r, q, 0, 0, 768, 1024);
16 1501 +#endif
  1502 + t->r_ = r;
  1503 + t->r0_ = q;
  1504 + t->f_ = &f_master;
  1505 +diff -ruN proll_18.orig/src/lat7_2.bm proll-patch4/src/lat7_2.bm
  1506 +--- proll_18.orig/src/lat7_2.bm 1999-02-27 05:48:54.000000000 +0000
  1507 ++++ proll-patch4/src/lat7_2.bm 2004-11-13 15:50:49.000000000 +0000
  1508 +@@ -1,6 +1,6 @@
  1509 + #define lat7_2_width 128
  1510 + #define lat7_2_height 88
  1511 +-static unsigned char lat7_2_bits[] = {
  1512 ++static unsigned const char lat7_2_bits[] = {
  1513 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1514 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x12, 0x1e, 0x0c, 0x02, 0x70, 0x18,
  1515 + 0x22, 0x22, 0x18, 0x00, 0x00, 0x18, 0x18, 0xff, 0x18, 0x00, 0x12, 0x02,
  1516 +diff -ruN proll_18.orig/src/lat7_2_swapped.bm proll-patch4/src/lat7_2_swapped.bm
  1517 +--- proll_18.orig/src/lat7_2_swapped.bm 1970-01-01 00:00:00.000000000 +0000
  1518 ++++ proll-patch4/src/lat7_2_swapped.bm 2004-11-13 15:50:49.000000000 +0000
  1519 +@@ -0,0 +1,121 @@
  1520 ++#define lat7_2_width 128
  1521 ++#define lat7_2_height 88
  1522 ++static unsigned const char lat7_2_bits[] = {
  1523 ++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
  1524 ++ 0x55, 0x00, 0x2a, 0x00, 0x55, 0x00, 0x2a, 0x00, 0x55, 0x00, 0x00, 0x48,
  1525 ++ 0x48, 0x78, 0x48, 0x5f, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x78, 0x40,
  1526 ++ 0x70, 0x40, 0x4f, 0x08, 0x0e, 0x08, 0x08, 0x00, 0x00, 0x30, 0x40, 0x40,
  1527 ++ 0x40, 0x3e, 0x09, 0x0e, 0x0a, 0x09, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40,
  1528 ++ 0x7f, 0x08, 0x0e, 0x08, 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x0e, 0x00, 0x00,
  1529 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
  1530 ++ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x44, 0x64, 0x54, 0x4c, 0x54, 0x10, 0x10,
  1531 ++ 0x10, 0x1f, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x1f, 0x04, 0x04, 0x04,
  1532 ++ 0x04, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00,
  1533 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x00,
  1534 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
  1535 ++ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
  1536 ++ 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00,
  1537 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1538 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1539 ++ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1540 ++ 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1541 ++ 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18,
  1542 ++ 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
  1543 ++ 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00,
  1544 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x00,
  1545 ++ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
  1546 ++ 0x06, 0x0c, 0x18, 0x30, 0x18, 0x6c, 0x36, 0x18, 0x0c, 0x00, 0x00, 0x60,
  1547 ++ 0x30, 0x18, 0x0c, 0x18, 0x36, 0x6c, 0x18, 0x30, 0x00, 0x00, 0x7f, 0x36,
  1548 ++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x7e,
  1549 ++ 0x18, 0x7e, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x30, 0x78,
  1550 ++ 0x30, 0x72, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
  1551 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
  1552 ++ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1553 ++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00,
  1554 ++ 0x00, 0x00, 0x00, 0x66, 0x66, 0x22, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
  1555 ++ 0x00, 0x00, 0x36, 0x7f, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x00, 0x00, 0x00,
  1556 ++ 0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00,
  1557 ++ 0x72, 0x56, 0x6c, 0x18, 0x36, 0x6a, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x18,
  1558 ++ 0x24, 0x28, 0x30, 0x4a, 0x44, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
  1559 ++ 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18,
  1560 ++ 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x18, 0x18,
  1561 ++ 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x7e, 0x3c,
  1562 ++ 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18,
  1563 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
  1564 ++ 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
  1565 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
  1566 ++ 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x00,
  1567 ++ 0x00, 0x3c, 0x46, 0x4e, 0x5a, 0x72, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00,
  1568 ++ 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c,
  1569 ++ 0x66, 0x06, 0x0c, 0x18, 0x32, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
  1570 ++ 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
  1571 ++ 0x66, 0x7e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x60, 0x7c, 0x66,
  1572 ++ 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66,
  1573 ++ 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x46, 0x06, 0x0c, 0x18, 0x30,
  1574 ++ 0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c,
  1575 ++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00,
  1576 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
  1577 ++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00,
  1578 ++ 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
  1579 ++ 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
  1580 ++ 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
  1581 ++ 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x5e,
  1582 ++ 0x56, 0x5e, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66,
  1583 ++ 0x7e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66,
  1584 ++ 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66,
  1585 ++ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c,
  1586 ++ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x60, 0x62, 0x7e, 0x00,
  1587 ++ 0x00, 0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x00,
  1588 ++ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00,
  1589 ++ 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
  1590 ++ 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7e,
  1591 ++ 0x46, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6c,
  1592 ++ 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60,
  1593 ++ 0x60, 0x60, 0x62, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x41, 0x63, 0x77, 0x7f,
  1594 ++ 0x6b, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x6e,
  1595 ++ 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66,
  1596 ++ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60,
  1597 ++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x6e, 0x3c, 0x02,
  1598 ++ 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x00, 0x00,
  1599 ++ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00,
  1600 ++ 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
  1601 ++ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x66,
  1602 ++ 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63,
  1603 ++ 0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c,
  1604 ++ 0x18, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c,
  1605 ++ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x46, 0x0c, 0x18, 0x30,
  1606 ++ 0x62, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
  1607 ++ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02,
  1608 ++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00,
  1609 ++ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1610 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  1611 ++ 0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1612 ++ 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60,
  1613 ++ 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1614 ++ 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
  1615 ++ 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
  1616 ++ 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x78,
  1617 ++ 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66,
  1618 ++ 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66,
  1619 ++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x1c, 0x00,
  1620 ++ 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38,
  1621 ++ 0x00, 0x00, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x7c, 0x66, 0x00, 0x00, 0x00,
  1622 ++ 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
  1623 ++ 0x00, 0x00, 0x76, 0x7f, 0x6b, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
  1624 ++ 0x00, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1625 ++ 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
  1626 ++ 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66,
  1627 ++ 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x72, 0x60,
  1628 ++ 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x3c, 0x06,
  1629 ++ 0x3c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x78, 0x30, 0x30, 0x36, 0x1c,
  1630 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3a, 0x00,
  1631 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00,
  1632 ++ 0x00, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x6b, 0x36, 0x00, 0x00, 0x00,
  1633 ++ 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00,
  1634 ++ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x00,
  1635 ++ 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18,
  1636 ++ 0x18, 0x30, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18,
  1637 ++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x30, 0x18, 0x18, 0x0c,
  1638 ++ 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0x00, 0x00, 0x00,
  1639 ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x00, 0x00, 0x00, 0x00,
  1640 ++ 0x00, 0x00, 0x00, 0x00};
  1641 +diff -ruN proll_18.orig/src/le.c proll-patch4/src/le.c
  1642 +--- proll_18.orig/src/le.c 2002-07-23 05:52:49.000000000 +0000
  1643 ++++ proll-patch4/src/le.c 2004-11-13 15:50:49.000000000 +0000
  1644 +@@ -185,8 +185,6 @@
  1645 + unsigned short rap; /* register address port */
  1646 + };
  1647 +
  1648 +-int sparc_lance_debug = 2;
  1649 +-
  1650 + /* The Lance uses 24 bit addresses */
  1651 + /* On the Sun4c the DVMA will provide the remaining bytes for us */
  1652 + /* On the Sun4m we have to instruct the ledma to provide them */
  1653 +diff -ruN proll_18.orig/src/netinit.c proll-patch4/src/netinit.c
  1654 +--- proll_18.orig/src/netinit.c 2002-09-13 21:53:33.000000000 +0000
  1655 ++++ proll-patch4/src/netinit.c 2004-11-13 15:50:49.000000000 +0000
  1656 +@@ -49,13 +49,20 @@
  1657 + unsigned char myhwaddr[ETH_ALEN]; /* my own hardware addr */
  1658 + t_ipaddr myipaddr; /* my own IP address */
  1659 + t_ipaddr mynetmask; /* my own netmask */
  1660 +- char *net_module_name; /* name of init module */
  1661 + t_ipaddr servaddr; /* IP of RARP&TFTP server */
  1662 +
  1663 + /* Broadcast hardware address */
  1664 +-unsigned char bcasthw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  1665 ++const unsigned char bcasthw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  1666 +
  1667 +
  1668 ++unsigned int seed;
  1669 ++
  1670 ++/* This is taken from x86 to be used in network kernel. Returns 15 bits. */
  1671 ++short int random()
  1672 ++{
  1673 ++ seed = (seed + 23968)*0x015A4E35 >> 1;
  1674 ++ return seed & 0x7FFF;
  1675 ++}
  1676 +
  1677 + /*
  1678 + **************************************************************************
  1679 +@@ -104,10 +111,17 @@
  1680 + */
  1681 + void init_net()
  1682 + {
  1683 ++ /* Avoid data segment allocations */
  1684 ++ seed = 151;
  1685 ++
  1686 + /* Initialize the different network layer modules */
  1687 + init_packet();
  1688 +- if (!init_arp() || !init_udp()) {
  1689 +- printf("\nERROR: init_%s\n", net_module_name);
  1690 ++ if (!init_arp()) {
  1691 ++ printf("\nERROR: init_arp\n");
  1692 ++ fatal();
  1693 ++ }
  1694 ++ if (!init_udp()) {
  1695 ++ printf("\nERROR: init_udp\n");
  1696 + fatal();
  1697 + }
  1698 + }
  1699 +diff -ruN proll_18.orig/src/netpriv.h proll-patch4/src/netpriv.h
  1700 +--- proll_18.orig/src/netpriv.h 1999-04-27 05:39:37.000000000 +0000
  1701 ++++ proll-patch4/src/netpriv.h 2004-11-13 15:50:49.000000000 +0000
  1702 +@@ -130,10 +130,9 @@
  1703 + *
  1704 + */
  1705 + extern unsigned char myhwaddr[ETH_ALEN]; /* my own hardware address */
  1706 +-extern unsigned char bcasthw[ETH_ALEN]; /* broadcast hardware addr */
  1707 ++extern const unsigned char bcasthw[ETH_ALEN]; /* broadcast hardware addr */
  1708 + extern t_ipaddr myipaddr; /* my own IP address */
  1709 + extern t_ipaddr mynetmask; /* netmask for my network */
  1710 +-extern char *net_module_name; /* initialized module's name */
  1711 + extern t_ipaddr servaddr; /* server IP address */
  1712 +
  1713 +
  1714 +@@ -150,7 +149,7 @@
  1715 + extern unsigned char *reg_type __P((int typeval, int (* receive)()));
  1716 +
  1717 + /* Write a packet to the network */
  1718 +-extern int write_packet __P((int bufsize, int typeval, unsigned char *addr));
  1719 ++extern int write_packet __P((int bufsize, int typeval, const unsigned char *addr));
  1720 +
  1721 + /* Empty read buffer */
  1722 + extern void empty_buf __P((void));
  1723 +diff -ruN proll_18.orig/src/openprom.h proll-patch4/src/openprom.h
  1724 +--- proll_18.orig/src/openprom.h 2002-07-14 02:26:30.000000000 +0000
  1725 ++++ proll-patch4/src/openprom.h 2004-11-13 15:50:49.000000000 +0000
  1726 +@@ -54,20 +54,20 @@
  1727 + };
  1728 +
  1729 + struct linux_mem_v0 {
  1730 +- struct linux_mlist_v0 **v0_totphys;
  1731 +- struct linux_mlist_v0 **v0_prommap;
  1732 +- struct linux_mlist_v0 **v0_available; /* What we can use */
  1733 ++ struct linux_mlist_v0 * const *v0_totphys;
  1734 ++ struct linux_mlist_v0 * const *v0_prommap;
  1735 ++ struct linux_mlist_v0 * const *v0_available; /* What we can use */
  1736 + };
  1737 +
  1738 + /* Arguments sent to the kernel from the boot prompt. */
  1739 + struct linux_arguments_v0 {
  1740 +- char *argv[8];
  1741 ++ const char *argv[8];
  1742 + char args[100];
  1743 + char boot_dev[2];
  1744 + int boot_dev_ctrl;
  1745 + int boot_dev_unit;
  1746 + int dev_partition;
  1747 +- char *kernel_file_name;
  1748 ++ const char *kernel_file_name;
  1749 + void *aieee1; /* XXX */
  1750 + };
17 1751  
18   - romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
  1752 +@@ -91,13 +91,13 @@
  1753 + struct linux_mem_v0 pv_v0mem;
19 1754  
20   - printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
21   - PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
22   - (int)cio.start, (int)cio.curp);
  1755 + /* Node operations. */
  1756 +- struct linux_nodeops *pv_nodeops;
  1757 ++ const struct linux_nodeops *pv_nodeops;
  1758 +
  1759 + char **pv_bootstr;
  1760 + struct linux_dev_v0_funcs pv_v0devops;
  1761 +
  1762 +- char *pv_stdin;
  1763 +- char *pv_stdout;
  1764 ++ const char *pv_stdin;
  1765 ++ const char *pv_stdout;
  1766 + #define PROMDEV_KBD 0 /* input from keyboard */
  1767 + #define PROMDEV_SCREEN 0 /* output to screen */
  1768 + #define PROMDEV_TTYA 1 /* in/out to ttya */
  1769 +@@ -127,7 +127,7 @@
  1770 + void (*v2_eval)(char *str);
  1771 + } pv_fortheval;
  1772 +
  1773 +- struct linux_arguments_v0 **pv_v0bootargs;
  1774 ++ const struct linux_arguments_v0 * const *pv_v0bootargs;
  1775 +
  1776 + /* Get ether address. */
  1777 + unsigned int (*pv_enaddr)(int d, char *enaddr);
  1778 +@@ -175,7 +175,7 @@
  1779 + int (*no_proplen)(int node, char *name);
  1780 + int (*no_getprop)(int node, char *name, char *val);
  1781 + int (*no_setprop)(int node, char *name, char *val, int len);
  1782 +- char * (*no_nextprop)(int node, char *name);
  1783 ++ const char * (*no_nextprop)(int node, char *name);
  1784 + };
  1785 +
  1786 + /* More fun PROM structures for device probing. */
  1787 +diff -ruN proll_18.orig/src/packet.c proll-patch4/src/packet.c
  1788 +--- proll_18.orig/src/packet.c 2000-02-11 04:56:45.000000000 +0000
  1789 ++++ proll-patch4/src/packet.c 2004-11-13 15:50:49.000000000 +0000
  1790 +@@ -41,7 +41,7 @@
  1791 + int aligner;
  1792 + } wbuf;
  1793 + static struct sk_buff *rskb;
  1794 +-static int nqskb = 0;
  1795 ++static int nqskb;
  1796 +
  1797 +
  1798 + void init_packet()
  1799 +@@ -62,6 +62,8 @@
  1800 + for (i = 0; i < MAXSKBS; i++) {
  1801 + skev[i].skb.allocn = i;
  1802 + }
  1803 ++
  1804 ++ nqskb = 0;
  1805 + }
  1806 +
  1807 + unsigned char *reg_type(int ptype, int (*func)())
  1808 +@@ -81,7 +83,7 @@
  1809 + return wbuf.s;
  1810 + }
  1811 +
  1812 +-int write_packet(int leng, int type, unsigned char *dst)
  1813 ++int write_packet(int leng, int type, const unsigned char *dst)
  1814 + {
  1815 + struct sk_buff *skb;
  1816 + unsigned char *s;
  1817 +diff -ruN proll_18.orig/src/printf.c proll-patch4/src/printf.c
  1818 +--- proll_18.orig/src/printf.c 1999-03-19 07:03:59.000000000 +0000
  1819 ++++ proll-patch4/src/printf.c 2004-11-13 15:50:49.000000000 +0000
  1820 +@@ -19,7 +19,7 @@
  1821 + static void printn(struct prf_fp *, unsigned long, unsigned int);
  1822 + static void putchar(char, struct prf_fp *);
  1823 +
  1824 +-static char hextab[] = "0123456789ABCDEF";
  1825 ++static const char hextab[] = "0123456789ABCDEF";
  1826 +
  1827 + /*
  1828 + * Scaled down version of C Library printf.
  1829 +@@ -41,7 +41,7 @@
  1830 + void
  1831 + prf(struct prf_fp *filog, char *fmt, va_list adx)
  1832 + {
  1833 +- register c;
  1834 ++ register int c;
  1835 + char *s;
  1836 +
  1837 + for(;;) {
  1838 +@@ -60,7 +60,7 @@
  1839 + putchar(va_arg(adx,unsigned), filog);
  1840 + } else if(c == 's') {
  1841 + s = va_arg(adx,char*);
  1842 +- while(c = *s++)
  1843 ++ while((c = *s++))
  1844 + putchar(c,filog);
  1845 + } else if (c == 'l' || c == 'O') {
  1846 + printn(filog, (long)va_arg(adx,long), c=='l'?10:8);
  1847 +diff -ruN proll_18.orig/src/rconsole.c proll-patch4/src/rconsole.c
  1848 +--- proll_18.orig/src/rconsole.c 1999-01-16 07:16:55.000000000 +0000
  1849 ++++ proll-patch4/src/rconsole.c 2004-11-13 15:50:49.000000000 +0000
  1850 +@@ -28,12 +28,18 @@
  1851 + * move to California. Only plain lat7 survived.
  1852 + * I recreated lat7-1 changes in lat7-2. --zaitcev
  1853 + */
23 1854 +#ifdef ORIG
24   - set_timeout(5); while (!chk_timeout()) { } /* P3: let me read */
  1855 + #include "lat7_2.bm" /* lat7_1.bm */
25 1856 +#else
26   -+ printk("loading kernel:");
27   -+ i = ld_bypass(0x20000000);
28   -+ printk(" done, size %d\n", i);
  1857 ++#include "lat7_2_swapped.bm" /* lat7_1.bm */
29 1858 +#endif
  1859 + #define LAT7_NCHARS 128
  1860 + #define LAT7_HEIGHT 11
  1861 + #define LAT7_WIDTH 8
30 1862  
31   - {
32   - void (*entry)(void *, int) = (void (*)(void*, int)) LOADBASE;
33   -diff -ru proll_18.orig/mrcoffee/openprom.c proll_18/mrcoffee/openprom.c
34   ---- proll_18.orig/mrcoffee/openprom.c 2002-09-13 16:17:03.000000000 +0200
35   -+++ proll_18/mrcoffee/openprom.c 2004-09-21 21:27:16.000000000 +0200
36   -@@ -144,10 +144,14 @@
37   - };
  1863 ++#ifdef ORIG
  1864 + static Rf_scan lat7_body[ LAT7_NCHARS*LAT7_HEIGHT ];
  1865 ++#endif
38 1866  
39   - static int cpu_nctx = NCTX_SWIFT;
40   -+static int cpu_cache_line_size = 0x20;
41   -+static int cpu_cache_nlines = 0x200;
42   - static struct property propv_cpu[] = {
43   - {"name", "STP1012PGA", sizeof("STP1012PGA") },
44   - {"device_type", "cpu", 4 },
45   - {"mmu-nctx", (char*)&cpu_nctx, sizeof(int)},
46   -+ {"cache-line-size", (char*)&cpu_cache_line_size, sizeof(int)},
47   -+ {"cache-nlines", (char*)&cpu_cache_nlines, sizeof(int)},
48   - {NULL, NULL, -1}
  1867 + #if 1
  1868 + /*
  1869 +@@ -94,6 +100,7 @@
  1870 +
  1871 + #endif
  1872 +
  1873 ++#ifdef ORIG
  1874 + static inline int swapbits(int w0)
  1875 + {
  1876 + int w1 = 0;
  1877 +@@ -105,13 +112,16 @@
  1878 + }
  1879 + return w1;
  1880 + }
  1881 ++#endif
  1882 +
  1883 + void font_cons_7(struct rfont *p)
  1884 + {
  1885 ++#ifdef ORIG
  1886 + int x;
  1887 + int col = 0;
  1888 + int row = 0;
  1889 + int erow = 0;
  1890 ++
  1891 + for (x = 0; x < LAT7_NCHARS*LAT7_HEIGHT; x++ ) {
  1892 + lat7_body[ (erow * lat7_2_width/8 + col) * LAT7_HEIGHT + row ] =
  1893 + swapbits(lat7_2_bits[x]) & 0xFF;
  1894 +@@ -124,6 +134,9 @@
  1895 + }
  1896 + }
  1897 + p->body_ = lat7_body;
  1898 ++#else
  1899 ++ p->body_ = lat7_2_bits;
  1900 ++#endif
  1901 + p->nchars_ = LAT7_NCHARS;
  1902 + p->width_ = LAT7_WIDTH;
  1903 + p->height_ = LAT7_HEIGHT;
  1904 +diff -ruN proll_18.orig/src/rconsole.h proll-patch4/src/rconsole.h
  1905 +--- proll_18.orig/src/rconsole.h 1999-01-16 05:00:59.000000000 +0000
  1906 ++++ proll-patch4/src/rconsole.h 2004-11-13 15:50:49.000000000 +0000
  1907 +@@ -13,10 +13,10 @@
  1908 + */
  1909 +
  1910 + #define RF_MAXWIDTH 16
  1911 +-typedef unsigned short Rf_scan; /* __w16 to be used */
  1912 ++typedef unsigned char Rf_scan; /* __w16 to be used */
  1913 +
  1914 + struct rfont {
  1915 +- Rf_scan *body_;
  1916 ++ const Rf_scan *body_;
  1917 + int nchars_; /* 128 for ASCII ... 65536 for Unicode */
  1918 + int width_; /* [Pixels]. Maximum size is 16. */
  1919 + int height_; /* [Pixels == scan lines]. */
  1920 +diff -ruN proll_18.orig/src/romlib.h proll-patch4/src/romlib.h
  1921 +--- proll_18.orig/src/romlib.h 1999-04-20 04:26:45.000000000 +0000
  1922 ++++ proll-patch4/src/romlib.h 2004-11-13 15:50:49.000000000 +0000
  1923 +@@ -73,12 +73,12 @@
  1924 + #define memcpy(dst, src, len) bcopy(src, dst, len)
  1925 + #define memcmp(x1, x2, len) bcmp(x1, x2, len)
  1926 + #define memset(p, len, zero) bzero(p, len)
  1927 +-extern void bcopy(void *b1, void *b2, int length);
  1928 +-extern int bcmp(void *b1, void *b2, int length);
  1929 ++extern void bcopy(const void *b1, void *b2, int length);
  1930 ++extern int bcmp(const void *b1, const void *b2, int length);
  1931 + extern void bzero(void *b, int c);
  1932 + /* gcc complains about "conflicting types for builtin function strlen". */
  1933 + #define strlen(s) ssize(s)
  1934 +-extern int ssize(char *s);
  1935 ++extern int ssize(const char *s);
  1936 +
  1937 +
  1938 + /*
  1939 +diff -ruN proll_18.orig/src/sched_4m.c proll-patch4/src/sched_4m.c
  1940 +--- proll_18.orig/src/sched_4m.c 1999-04-27 05:48:51.000000000 +0000
  1941 ++++ proll-patch4/src/sched_4m.c 2004-11-13 15:50:49.000000000 +0000
  1942 +@@ -108,7 +108,7 @@
  1943 + static int set_bolt; /* Tick counter limit */
  1944 + static struct handsc hndv[16];
  1945 +
  1946 +-static unsigned int intr_to_mask[16] = {
  1947 ++static unsigned const int intr_to_mask[16] = {
  1948 + 0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
  1949 + 0, 0, 0, 0, 0, 0, 0, 0,
49 1950 };
  1951 +diff -ruN proll_18.orig/src/swap.c proll-patch4/src/swap.c
  1952 +--- proll_18.orig/src/swap.c 1970-01-01 00:00:00.000000000 +0000
  1953 ++++ proll-patch4/src/swap.c 2004-11-13 15:50:49.000000000 +0000
  1954 +@@ -0,0 +1,21 @@
  1955 ++// Convert the lat7 font so that no conversion is needed at runtime.
  1956 ++#define ORIG
  1957 ++#include "rconsole.c"
  1958 ++
  1959 ++#include <stdio.h>
  1960 ++
  1961 ++int main()
  1962 ++{
  1963 ++ struct rfont p;
  1964 ++ int i;
  1965 ++
  1966 ++ font_cons_7(&p);
  1967 ++
  1968 ++ printf(" ");
  1969 ++ for (i = 0; i < LAT7_NCHARS*LAT7_HEIGHT; i++) {
  1970 ++ printf("0x%02x, ", p.body_[i]);
  1971 ++ if ((i % 12) == 11)
  1972 ++ printf("\n ");
  1973 ++ }
  1974 ++ printf("\n");
  1975 ++}
  1976 +diff -ruN proll_18.orig/src/system.c proll-patch4/src/system.c
  1977 +--- proll_18.orig/src/system.c 2002-07-23 05:52:49.000000000 +0000
  1978 ++++ proll-patch4/src/system.c 2004-11-13 15:50:49.000000000 +0000
  1979 +@@ -298,8 +298,8 @@
  1980 + }
  1981 +
  1982 + /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
  1983 +- pa = PAGE_SIZE;
  1984 +- for (va = PAGE_SIZE; va < LOWMEMSZ; va += PAGE_SIZE) {
  1985 ++ pa = 0;
  1986 ++ for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
  1987 + map_page(l1, va, pa, 0, highbase);
  1988 + pa += PAGE_SIZE;
  1989 + }
  1990 +@@ -518,12 +518,12 @@
  1991 + while (len--) *((char *)s)++ = 0;
  1992 + }
  1993 +
  1994 +-void bcopy(void *f, void *t, int len) {
  1995 ++void bcopy(const void *f, void *t, int len) {
  1996 + while (len--) *((char *)t)++ = *((char *)f)++;
  1997 + }
  1998 +
  1999 + /* Comparison is 7-bit */
  2000 +-int bcmp(void *s1, void *s2, int len)
  2001 ++int bcmp(const void *s1, const void *s2, int len)
  2002 + {
  2003 + int i;
  2004 + char ch;
  2005 +@@ -538,8 +538,8 @@
  2006 + return 0;
  2007 + }
  2008 +
  2009 +-int strlen(char *s) {
  2010 +- char *p;
  2011 ++int strlen(const char *s) {
  2012 ++ const char *p;
  2013 + for (p = s; *p != 0; p++) { }
  2014 + return p - s;
  2015 + }
  2016 +@@ -560,14 +560,6 @@
  2017 + va_end(x1);
  2018 + }
  2019 +
  2020 +-/* This is taken from x86 to be used in network kernel. Returns 15 bits. */
  2021 +-short int random()
  2022 +-{
  2023 +- static unsigned int seed = 151;
  2024 +- seed = (seed + 23968)*0x015A4E35 >> 1;
  2025 +- return seed & 0x7FFF;
  2026 +-}
  2027 +-
  2028 + void fatal()
  2029 + {
  2030 + printk("fatal.");
  2031 +diff -ruN proll_18.orig/src/system.h proll-patch4/src/system.h
  2032 +--- proll_18.orig/src/system.h 2002-09-13 21:53:32.000000000 +0000
  2033 ++++ proll-patch4/src/system.h 2004-11-13 15:50:49.000000000 +0000
  2034 +@@ -16,7 +16,7 @@
  2035 + #define IOMAPSIZE (1*1024*1024) /* 1 Meg maximum: we do not map framebuffer. */
  2036 + #define NCTX_SWIFT 0x100
  2037 +
  2038 +-#define MAX_BANKS 3 /* Allocation for all machines */
  2039 ++#define MAX_BANKS 8 /* Allocation for all machines */
  2040 +
  2041 + #ifndef __ASSEMBLY__
  2042 + struct bank {
  2043 +diff -ruN proll_18.orig/src/udp.c proll-patch4/src/udp.c
  2044 +--- proll_18.orig/src/udp.c 2001-12-24 05:12:53.000000000 +0000
  2045 ++++ proll-patch4/src/udp.c 2004-11-13 15:50:49.000000000 +0000
  2046 +@@ -81,7 +81,7 @@
  2047 + int source;
  2048 + int dest;
  2049 + {
  2050 +- register unsigned char *addr;
  2051 ++ const register unsigned char *addr;
50 2052  
  2053 + /* Set global variables */
  2054 + usource = source;
  2055 +@@ -299,9 +299,6 @@
  2056 + */
  2057 + int init_udp()
  2058 + {
  2059 +- /* Set module name for error handling */
  2060 +- net_module_name = "udp";
  2061 +-
  2062 + /* Register IP packet type and set write buffer pointer */
  2063 + if ((writebuf = reg_type(htons(ETH_P_IP), ip_recv)) == NULL)
  2064 + return(FALSE);
... ...
qemu-doc.texi
... ... @@ -1099,6 +1099,29 @@ Set the initial VGA graphic mode. The default is 800x600x15.
1099 1099 More information is available at
1100 1100 @url{http://jocelyn.mayer.free.fr/qemu-ppc/}.
1101 1101  
  1102 +@chapter Sparc System emulator invocation
  1103 +
  1104 +Use the executable @file{qemu-system-sparc} to simulate a JavaStation
  1105 +(sun4m architecture). The emulation is far from complete.
  1106 +
  1107 +QEMU emulates the following sun4m peripherials:
  1108 +
  1109 +@itemize @minus
  1110 +@item
  1111 +IOMMU
  1112 +@item
  1113 +TCX Frame buffer
  1114 +@item
  1115 +Lance (Am7990) Ethernet
  1116 +@item
  1117 +Non Volatile RAM M48T08
  1118 +@item
  1119 +Slave I/O: timers, interrupt controllers, Zilog serial ports
  1120 +@end itemize
  1121 +
  1122 +QEMU uses the Proll, a PROM replacement available at
  1123 +@url{http://people.redhat.com/zaitcev/linux/}.
  1124 +
1102 1125 @chapter QEMU User space emulator invocation
1103 1126  
1104 1127 @section Quick Start
... ...
qemu-tech.texi
... ... @@ -126,7 +126,7 @@ maximum performances.
126 126  
127 127 @itemize
128 128  
129   -@item Full PowerPC 32 bit emulation, including priviledged instructions,
  129 +@item Full PowerPC 32 bit emulation, including privileged instructions,
130 130 FPU and MMU.
131 131  
132 132 @item Can run most PowerPC Linux binaries.
... ... @@ -137,7 +137,8 @@ FPU and MMU.
137 137  
138 138 @itemize
139 139  
140   -@item SPARC V8 user support, except FPU instructions.
  140 +@item Somewhat complete SPARC V8 emulation, including privileged
  141 +instructions, FPU and MMU.
141 142  
142 143 @item Can run some SPARC Linux binaries.
143 144  
... ...
target-sparc/cpu.h
... ... @@ -10,23 +10,42 @@
10 10 /* trap definitions */
11 11 #define TT_ILL_INSN 0x02
12 12 #define TT_PRIV_INSN 0x03
  13 +#define TT_NFPU_INSN 0x04
13 14 #define TT_WIN_OVF 0x05
14 15 #define TT_WIN_UNF 0x06
15 16 #define TT_FP_EXCP 0x08
16 17 #define TT_DIV_ZERO 0x2a
17 18 #define TT_TRAP 0x80
  19 +#define TT_EXTINT 0x10
18 20  
19 21 #define PSR_NEG (1<<23)
20 22 #define PSR_ZERO (1<<22)
21 23 #define PSR_OVF (1<<21)
22 24 #define PSR_CARRY (1<<20)
23 25 #define PSR_ICC (PSR_NEG|PSR_ZERO|PSR_OVF|PSR_CARRY)
  26 +#define PSR_EF (1<<12)
  27 +#define PSR_PIL 0xf00
24 28 #define PSR_S (1<<7)
25 29 #define PSR_PS (1<<6)
26 30 #define PSR_ET (1<<5)
27 31 #define PSR_CWP 0x1f
28 32 /* Fake impl 0, version 4 */
29   -#define GET_PSR(env) ((0<<28) | (4<<24) | env->psr | (env->psrs? PSR_S : 0) | (env->psrs? PSR_PS : 0) |(env->psret? PSR_ET : 0) | env->cwp)
  33 +#define GET_PSR(env) ((0 << 28) | (4 << 24) | env->psr | \
  34 + (env->psref? PSR_EF : 0) | \
  35 + (env->psrpil << 8) | \
  36 + (env->psrs? PSR_S : 0) | \
  37 + (env->psrs? PSR_PS : 0) | \
  38 + (env->psret? PSR_ET : 0) | env->cwp)
  39 +
  40 +#define PUT_PSR(env, val) do { int _tmp = val; \
  41 + env->psr = _tmp & ~PSR_ICC; \
  42 + env->psref = (_tmp & PSR_EF)? 1 : 0; \
  43 + env->psrpil = (_tmp & PSR_PIL) >> 8; \
  44 + env->psrs = (_tmp & PSR_S)? 1 : 0; \
  45 + env->psrps = (_tmp & PSR_PS)? 1 : 0; \
  46 + env->psret = (_tmp & PSR_ET)? 1 : 0; \
  47 + set_cwp(_tmp & PSR_CWP & (NWINDOWS - 1)); \
  48 + } while (0)
30 49  
31 50 /* Trap base register */
32 51 #define TBR_BASE_MASK 0xfffff000
... ... @@ -65,6 +84,9 @@
65 84 #define FSR_FTT1 (1<<15)
66 85 #define FSR_FTT0 (1<<14)
67 86 #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
  87 +#define FSR_FTT_IEEE_EXCP (1 << 14)
  88 +#define FSR_FTT_UNIMPFPOP (3 << 14)
  89 +#define FSR_FTT_INVAL_FPR (6 << 14)
68 90  
69 91 #define FSR_FCC1 (1<<11)
70 92 #define FSR_FCC0 (1<<10)
... ... @@ -106,6 +128,8 @@ typedef struct CPUSPARCState {
106 128 int psrs; /* supervisor mode (extracted from PSR) */
107 129 int psrps; /* previous supervisor mode */
108 130 int psret; /* enable traps */
  131 + int psrpil; /* interrupt level */
  132 + int psref; /* enable fpu */
109 133 jmp_buf jmp_env;
110 134 int user_mode_only;
111 135 int exception_index;
... ... @@ -144,6 +168,8 @@ typedef struct CPUSPARCState {
144 168 CPUSPARCState *cpu_sparc_init(void);
145 169 int cpu_sparc_exec(CPUSPARCState *s);
146 170 int cpu_sparc_close(CPUSPARCState *s);
  171 +void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f);
  172 +double cpu_put_fp64(uint64_t mant, uint16_t exp);
147 173  
148 174 struct siginfo;
149 175 int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
... ...
target-sparc/exec.h
... ... @@ -40,6 +40,9 @@ void do_interrupt(int intno, int is_int, int error_code,
40 40 void raise_exception_err(int exception_index, int error_code);
41 41 void raise_exception(int tt);
42 42 void memcpy32(uint32_t *dst, const uint32_t *src);
  43 +uint32_t mmu_probe(uint32_t address, int mmulev);
  44 +void dump_mmu(void);
  45 +void helper_debug();
43 46  
44 47 /* XXX: move that to a generic header */
45 48 #if !defined(CONFIG_USER_ONLY)
... ...
target-sparc/fop_template.h
... ... @@ -51,18 +51,6 @@ void OPPROTO glue(op_store_FT2_fpr_fpr, REGNAME)(void)
51 51 }
52 52  
53 53 /* double floating point registers moves */
54   -#if 0
55   -#define CPU_DOUBLE_U_DEF
56   -typedef union {
57   - double d;
58   - struct {
59   - uint32_t lower;
60   - uint32_t upper;
61   - } l;
62   - uint64_t ll;
63   -} CPU_DoubleU;
64   -#endif /* CPU_DOUBLE_U_DEF */
65   -
66 54 void OPPROTO glue(op_load_fpr_DT0_fpr, REGNAME)(void)
67 55 {
68 56 CPU_DoubleU u;
... ...
target-sparc/helper.c
... ... @@ -19,7 +19,8 @@
19 19 */
20 20 #include "exec.h"
21 21  
22   -#define DEBUG_PCALL
  22 +//#define DEBUG_PCALL
  23 +//#define DEBUG_MMU
23 24  
24 25 /* Sparc MMU emulation */
25 26 int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
... ... @@ -108,80 +109,71 @@ static const int rw_table[2][8] = {
108 109 { 0, 1, 0, 1, 0, 0, 0, 0 }
109 110 };
110 111  
111   -
112   -/* Perform address translation */
113   -int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
114   - int is_user, int is_softmmu)
  112 +int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
  113 + int *access_index, uint32_t address, int rw,
  114 + int is_user)
115 115 {
116   - int exception = 0;
117   - int access_perms = 0, access_index = 0;
118   - uint8_t *pde_ptr;
  116 + int access_perms = 0;
  117 + target_phys_addr_t pde_ptr;
119 118 uint32_t pde, virt_addr;
120   - int error_code = 0, is_dirty, prot, ret = 0;
121   - unsigned long paddr, vaddr, page_offset;
122   -
123   - if (env->user_mode_only) {
124   - /* user mode only emulation */
125   - ret = -2;
126   - goto do_fault;
127   - }
  119 + int error_code = 0, is_dirty;
  120 + unsigned long page_offset;
128 121  
129 122 virt_addr = address & TARGET_PAGE_MASK;
130 123 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
131   - paddr = address;
132   - page_offset = address & (TARGET_PAGE_SIZE - 1);
133   - prot = PAGE_READ | PAGE_WRITE;
134   - goto do_mapping;
  124 + *physical = address;
  125 + *prot = PAGE_READ | PAGE_WRITE;
  126 + return 0;
135 127 }
136 128  
137 129 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
138 130 /* Context base + context number */
139   - pde_ptr = phys_ram_base + (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
140   - pde = ldl_raw(pde_ptr);
  131 + pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
  132 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  133 + bswap32s(&pde);
141 134  
142 135 /* Ctx pde */
143 136 switch (pde & PTE_ENTRYTYPE_MASK) {
  137 + default:
144 138 case 0: /* Invalid */
145   - error_code = 1;
146   - goto do_fault;
147   - case 2: /* PTE, maybe should not happen? */
  139 + return 1;
  140 + case 2: /* L0 PTE, maybe should not happen? */
148 141 case 3: /* Reserved */
149   - error_code = 4;
150   - goto do_fault;
151   - case 1: /* L1 PDE */
152   - pde_ptr = phys_ram_base + ((address >> 22) & ~3) + ((pde & ~3) << 4);
153   - pde = ldl_raw(pde_ptr);
  142 + return 4;
  143 + case 1: /* L0 PDE */
  144 + pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
  145 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  146 + bswap32s(&pde);
154 147  
155 148 switch (pde & PTE_ENTRYTYPE_MASK) {
  149 + default:
156 150 case 0: /* Invalid */
157   - error_code = 1;
158   - goto do_fault;
  151 + return 1;
159 152 case 3: /* Reserved */
160   - error_code = 4;
161   - goto do_fault;
162   - case 1: /* L2 PDE */
163   - pde_ptr = phys_ram_base + ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
164   - pde = ldl_raw(pde_ptr);
  153 + return 4;
  154 + case 1: /* L1 PDE */
  155 + pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
  156 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  157 + bswap32s(&pde);
165 158  
166 159 switch (pde & PTE_ENTRYTYPE_MASK) {
  160 + default:
167 161 case 0: /* Invalid */
168   - error_code = 1;
169   - goto do_fault;
  162 + return 1;
170 163 case 3: /* Reserved */
171   - error_code = 4;
172   - goto do_fault;
173   - case 1: /* L3 PDE */
174   - pde_ptr = phys_ram_base + ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
175   - pde = ldl_raw(pde_ptr);
  164 + return 4;
  165 + case 1: /* L2 PDE */
  166 + pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
  167 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  168 + bswap32s(&pde);
176 169  
177 170 switch (pde & PTE_ENTRYTYPE_MASK) {
  171 + default:
178 172 case 0: /* Invalid */
179   - error_code = 1;
180   - goto do_fault;
  173 + return 1;
181 174 case 1: /* PDE, should not happen */
182 175 case 3: /* Reserved */
183   - error_code = 4;
184   - goto do_fault;
  176 + return 4;
185 177 case 2: /* L3 PTE */
186 178 virt_addr = address & TARGET_PAGE_MASK;
187 179 page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
... ... @@ -201,40 +193,58 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
201 193 /* update page modified and dirty bits */
202 194 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
203 195 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
  196 + uint32_t tmppde;
204 197 pde |= PG_ACCESSED_MASK;
205 198 if (is_dirty)
206 199 pde |= PG_MODIFIED_MASK;
207   - stl_raw(pde_ptr, pde);
  200 + tmppde = bswap32(pde);
  201 + cpu_physical_memory_write(pde_ptr, (uint8_t *)&tmppde, 4);
208 202 }
209   -
210 203 /* check access */
211   - access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
  204 + *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
212 205 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
213   - error_code = access_table[access_index][access_perms];
  206 + error_code = access_table[*access_index][access_perms];
214 207 if (error_code)
215   - goto do_fault;
  208 + return error_code;
216 209  
217 210 /* the page can be put in the TLB */
218   - prot = PAGE_READ;
  211 + *prot = PAGE_READ;
219 212 if (pde & PG_MODIFIED_MASK) {
220 213 /* only set write access if already dirty... otherwise wait
221 214 for dirty access */
222 215 if (rw_table[is_user][access_perms])
223   - prot |= PAGE_WRITE;
  216 + *prot |= PAGE_WRITE;
224 217 }
225 218  
226 219 /* Even if large ptes, we map only one 4KB page in the cache to
227 220 avoid filling it too fast */
228   - virt_addr = address & TARGET_PAGE_MASK;
229   - paddr = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
  221 + *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
  222 + return 0;
  223 +}
  224 +
  225 +/* Perform address translation */
  226 +int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
  227 + int is_user, int is_softmmu)
  228 +{
  229 + int exception = 0;
  230 + uint32_t virt_addr, paddr;
  231 + unsigned long vaddr;
  232 + int error_code = 0, prot, ret = 0, access_index;
230 233  
231   - do_mapping:
232   - vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
  234 + if (env->user_mode_only) {
  235 + /* user mode only emulation */
  236 + error_code = -2;
  237 + goto do_fault_user;
  238 + }
233 239  
234   - ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
235   - return ret;
  240 + error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
  241 + if (error_code == 0) {
  242 + virt_addr = address & TARGET_PAGE_MASK;
  243 + vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
  244 + ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
  245 + return ret;
  246 + }
236 247  
237   - do_fault:
238 248 if (env->mmuregs[3]) /* Fault status register */
239 249 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
240 250 env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
... ... @@ -242,7 +252,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
242 252  
243 253 if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault
244 254 return 0;
245   -
  255 + do_fault_user:
246 256 env->exception_index = exception;
247 257 env->error_code = error_code;
248 258 return error_code;
... ... @@ -289,13 +299,14 @@ void do_interrupt(int intno, int is_int, int error_code,
289 299 count, intno, error_code, is_int,
290 300 env->pc,
291 301 env->npc, env->regwptr[6]);
292   -#if 0
  302 +#if 1
293 303 cpu_dump_state(env, logfile, fprintf, 0);
294 304 {
295 305 int i;
296 306 uint8_t *ptr;
  307 +
297 308 fprintf(logfile, " code=");
298   - ptr = env->pc;
  309 + ptr = (uint8_t *)env->pc;
299 310 for(i = 0; i < 16; i++) {
300 311 fprintf(logfile, " %02x", ldub(ptr + i));
301 312 }
... ... @@ -305,11 +316,18 @@ void do_interrupt(int intno, int is_int, int error_code,
305 316 count++;
306 317 }
307 318 #endif
  319 +#if !defined(CONFIG_USER_ONLY)
  320 + if (env->psret == 0) {
  321 + fprintf(logfile, "Trap while interrupts disabled, Error state!\n");
  322 + qemu_system_shutdown_request();
  323 + return;
  324 + }
  325 +#endif
308 326 env->psret = 0;
309 327 cwp = (env->cwp - 1) & (NWINDOWS - 1);
310 328 set_cwp(cwp);
311   - env->regwptr[9] = env->pc;
312   - env->regwptr[10] = env->npc;
  329 + env->regwptr[9] = env->pc - 4; // XXX?
  330 + env->regwptr[10] = env->pc;
313 331 env->psrps = env->psrs;
314 332 env->psrs = 1;
315 333 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
... ... @@ -322,3 +340,106 @@ void raise_exception_err(int exception_index, int error_code)
322 340 {
323 341 raise_exception(exception_index);
324 342 }
  343 +
  344 +uint32_t mmu_probe(uint32_t address, int mmulev)
  345 +{
  346 + target_phys_addr_t pde_ptr;
  347 + uint32_t pde;
  348 +
  349 + /* Context base + context number */
  350 + pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
  351 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  352 + bswap32s(&pde);
  353 + switch (pde & PTE_ENTRYTYPE_MASK) {
  354 + default:
  355 + case 0: /* Invalid */
  356 + case 2: /* PTE, maybe should not happen? */
  357 + case 3: /* Reserved */
  358 + return 0;
  359 + case 1: /* L1 PDE */
  360 + if (mmulev == 3)
  361 + return pde;
  362 + pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
  363 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  364 + bswap32s(&pde);
  365 +
  366 + switch (pde & PTE_ENTRYTYPE_MASK) {
  367 + default:
  368 + case 0: /* Invalid */
  369 + case 3: /* Reserved */
  370 + return 0;
  371 + case 2: /* L1 PTE */
  372 + return pde;
  373 + case 1: /* L2 PDE */
  374 + if (mmulev == 2)
  375 + return pde;
  376 + pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
  377 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  378 + bswap32s(&pde);
  379 +
  380 + switch (pde & PTE_ENTRYTYPE_MASK) {
  381 + default:
  382 + case 0: /* Invalid */
  383 + case 3: /* Reserved */
  384 + return 0;
  385 + case 2: /* L2 PTE */
  386 + return pde;
  387 + case 1: /* L3 PDE */
  388 + if (mmulev == 1)
  389 + return pde;
  390 + pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
  391 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  392 + bswap32s(&pde);
  393 +
  394 + switch (pde & PTE_ENTRYTYPE_MASK) {
  395 + default:
  396 + case 0: /* Invalid */
  397 + case 1: /* PDE, should not happen */
  398 + case 3: /* Reserved */
  399 + return 0;
  400 + case 2: /* L3 PTE */
  401 + return pde;
  402 + }
  403 + }
  404 + }
  405 + }
  406 + return 0;
  407 +}
  408 +
  409 +void dump_mmu(void)
  410 +{
  411 +#ifdef DEBUG_MMU
  412 + uint32_t pa, va, va1, va2;
  413 + int n, m, o;
  414 + target_phys_addr_t pde_ptr;
  415 + uint32_t pde;
  416 +
  417 + printf("MMU dump:\n");
  418 + pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
  419 + cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
  420 + bswap32s(&pde);
  421 + printf("Root ptr: 0x%08x, ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
  422 + for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
  423 + pde_ptr = mmu_probe(va, 2);
  424 + if (pde_ptr) {
  425 + pa = cpu_get_phys_page_debug(env, va);
  426 + printf("VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va, pa, pde_ptr);
  427 + for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
  428 + pde_ptr = mmu_probe(va1, 1);
  429 + if (pde_ptr) {
  430 + pa = cpu_get_phys_page_debug(env, va1);
  431 + printf(" VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va1, pa, pde_ptr);
  432 + for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
  433 + pde_ptr = mmu_probe(va2, 0);
  434 + if (pde_ptr) {
  435 + pa = cpu_get_phys_page_debug(env, va2);
  436 + printf(" VA: 0x%08x, PA: 0x%08x PTE: 0x%08x\n", va2, pa, pde_ptr);
  437 + }
  438 + }
  439 + }
  440 + }
  441 + }
  442 + }
  443 + printf("MMU dump ends\n");
  444 +#endif
  445 +}
... ...
target-sparc/op.c
... ... @@ -524,13 +524,7 @@ void OPPROTO op_rdpsr(void)
524 524  
525 525 void OPPROTO op_wrpsr(void)
526 526 {
527   - int cwp;
528   - env->psr = T0 & ~PSR_ICC;
529   - env->psrs = (T0 & PSR_S)? 1 : 0;
530   - env->psrps = (T0 & PSR_PS)? 1 : 0;
531   - env->psret = (T0 & PSR_ET)? 1 : 0;
532   - cwp = (T0 & PSR_CWP) & (NWINDOWS - 1);
533   - set_cwp(cwp);
  527 + PUT_PSR(env,T0);
534 528 FORCE_RET();
535 529 }
536 530  
... ... @@ -602,10 +596,27 @@ void OPPROTO op_trapcc_T0(void)
602 596 FORCE_RET();
603 597 }
604 598  
605   -void OPPROTO op_debug(void)
  599 +void OPPROTO op_trap_ifnofpu(void)
  600 +{
  601 + if (!env->psref) {
  602 + env->exception_index = TT_NFPU_INSN;
  603 + cpu_loop_exit();
  604 + }
  605 + FORCE_RET();
  606 +}
  607 +
  608 +void OPPROTO op_fpexception_im(void)
606 609 {
607   - env->exception_index = EXCP_DEBUG;
  610 + env->exception_index = TT_FP_EXCP;
  611 + env->fsr &= ~FSR_FTT_MASK;
  612 + env->fsr |= PARAM1;
608 613 cpu_loop_exit();
  614 + FORCE_RET();
  615 +}
  616 +
  617 +void OPPROTO op_debug(void)
  618 +{
  619 + helper_debug();
609 620 }
610 621  
611 622 void OPPROTO op_exit_tb(void)
... ...
target-sparc/op_helper.c
... ... @@ -2,6 +2,8 @@
2 2 #include <fenv.h>
3 3 #include "exec.h"
4 4  
  5 +//#define DEBUG_MMU
  6 +
5 7 #ifdef USE_INT_TO_FLOAT_HELPERS
6 8 void do_fitos(void)
7 9 {
... ... @@ -33,6 +35,13 @@ void do_fcmps (void)
33 35 {
34 36 if (isnan(FT0) || isnan(FT1)) {
35 37 T0 = FSR_FCC1 | FSR_FCC0;
  38 + env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
  39 + env->fsr |= T0;
  40 + if (env->fsr & FSR_NVM) {
  41 + raise_exception(TT_FP_EXCP);
  42 + } else {
  43 + env->fsr |= FSR_NVA;
  44 + }
36 45 } else if (FT0 < FT1) {
37 46 T0 = FSR_FCC0;
38 47 } else if (FT0 > FT1) {
... ... @@ -47,6 +56,13 @@ void do_fcmpd (void)
47 56 {
48 57 if (isnan(DT0) || isnan(DT1)) {
49 58 T0 = FSR_FCC1 | FSR_FCC0;
  59 + env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
  60 + env->fsr |= T0;
  61 + if (env->fsr & FSR_NVM) {
  62 + raise_exception(TT_FP_EXCP);
  63 + } else {
  64 + env->fsr |= FSR_NVA;
  65 + }
50 66 } else if (DT0 < DT1) {
51 67 T0 = FSR_FCC0;
52 68 } else if (DT0 > DT1) {
... ... @@ -59,55 +75,131 @@ void do_fcmpd (void)
59 75  
60 76 void helper_ld_asi(int asi, int size, int sign)
61 77 {
62   - switch(asi) {
  78 + uint32_t ret;
  79 +
  80 + switch (asi) {
63 81 case 3: /* MMU probe */
64   - T1 = 0;
65   - return;
  82 + {
  83 + int mmulev;
  84 +
  85 + mmulev = (T0 >> 8) & 15;
  86 + if (mmulev > 4)
  87 + ret = 0;
  88 + else {
  89 + ret = mmu_probe(T0, mmulev);
  90 + //bswap32s(&ret);
  91 + }
  92 +#ifdef DEBUG_MMU
  93 + printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
  94 +#endif
  95 + }
  96 + break;
66 97 case 4: /* read MMU regs */
67 98 {
68   - int temp, reg = (T0 >> 8) & 0xf;
  99 + int reg = (T0 >> 8) & 0xf;
69 100  
70   - temp = env->mmuregs[reg];
  101 + ret = env->mmuregs[reg];
71 102 if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/
72   - env->mmuregs[reg] = 0;
73   - T1 = temp;
  103 + env->mmuregs[4] = 0;
74 104 }
75   - return;
  105 + break;
76 106 case 0x20 ... 0x2f: /* MMU passthrough */
77   - {
78   - int temp;
79   -
80   - cpu_physical_memory_read(T0, (void *) &temp, size);
81   - bswap32s(&temp);
82   - T1 = temp;
83   - }
84   - return;
  107 + cpu_physical_memory_read(T0, (void *) &ret, size);
  108 + if (size == 4)
  109 + bswap32s(&ret);
  110 + else if (size == 2)
  111 + bswap16s(&ret);
  112 + break;
85 113 default:
86   - T1 = 0;
87   - return;
  114 + ret = 0;
  115 + break;
88 116 }
  117 + T1 = ret;
89 118 }
90 119  
91 120 void helper_st_asi(int asi, int size, int sign)
92 121 {
93 122 switch(asi) {
94 123 case 3: /* MMU flush */
95   - return;
  124 + {
  125 + int mmulev;
  126 +
  127 + mmulev = (T0 >> 8) & 15;
  128 + switch (mmulev) {
  129 + case 0: // flush page
  130 + tlb_flush_page(cpu_single_env, T0 & 0xfffff000);
  131 + break;
  132 + case 1: // flush segment (256k)
  133 + case 2: // flush region (16M)
  134 + case 3: // flush context (4G)
  135 + case 4: // flush entire
  136 + tlb_flush(cpu_single_env, 1);
  137 + break;
  138 + default:
  139 + break;
  140 + }
  141 + dump_mmu();
  142 + return;
  143 + }
96 144 case 4: /* write MMU regs */
97 145 {
98   - int reg = (T0 >> 8) & 0xf;
  146 + int reg = (T0 >> 8) & 0xf, oldreg;
  147 +
  148 + oldreg = env->mmuregs[reg];
99 149 if (reg == 0) {
100 150 env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
101 151 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
102 152 } else
103 153 env->mmuregs[reg] = T1;
  154 + if (oldreg != env->mmuregs[reg]) {
  155 +#if 0
  156 + // XXX: Only if MMU mapping change, we may need to flush?
  157 + tlb_flush(cpu_single_env, 1);
  158 + cpu_loop_exit();
  159 + FORCE_RET();
  160 +#endif
  161 + }
  162 + dump_mmu();
104 163 return;
105 164 }
  165 + case 0x17: /* Block copy, sta access */
  166 + {
  167 + // value (T1) = src
  168 + // address (T0) = dst
  169 + // copy 32 bytes
  170 + int src = T1, dst = T0;
  171 + uint8_t temp[32];
  172 +
  173 + bswap32s(&src);
  174 +
  175 + cpu_physical_memory_read(src, (void *) &temp, 32);
  176 + cpu_physical_memory_write(dst, (void *) &temp, 32);
  177 + }
  178 + return;
  179 + case 0x1f: /* Block fill, stda access */
  180 + {
  181 + // value (T1, T2)
  182 + // address (T0) = dst
  183 + // fill 32 bytes
  184 + int i, dst = T0;
  185 + uint64_t val;
  186 +
  187 + val = (((uint64_t)T1) << 32) | T2;
  188 + bswap64s(&val);
  189 +
  190 + for (i = 0; i < 32; i += 8, dst += 8) {
  191 + cpu_physical_memory_write(dst, (void *) &val, 8);
  192 + }
  193 + }
  194 + return;
106 195 case 0x20 ... 0x2f: /* MMU passthrough */
107 196 {
108 197 int temp = T1;
109   -
110   - bswap32s(&temp);
  198 + if (size == 4)
  199 + bswap32s(&temp);
  200 + else if (size == 2)
  201 + bswap16s(&temp);
  202 +
111 203 cpu_physical_memory_write(T0, (void *) &temp, size);
112 204 }
113 205 return;
... ... @@ -116,27 +208,6 @@ void helper_st_asi(int asi, int size, int sign)
116 208 }
117 209 }
118 210  
119   -#if 0
120   -void do_ldd_raw(uint32_t addr)
121   -{
122   - T1 = ldl_raw((void *) addr);
123   - T0 = ldl_raw((void *) (addr + 4));
124   -}
125   -
126   -#if !defined(CONFIG_USER_ONLY)
127   -void do_ldd_user(uint32_t addr)
128   -{
129   - T1 = ldl_user((void *) addr);
130   - T0 = ldl_user((void *) (addr + 4));
131   -}
132   -void do_ldd_kernel(uint32_t addr)
133   -{
134   - T1 = ldl_kernel((void *) addr);
135   - T0 = ldl_kernel((void *) (addr + 4));
136   -}
137   -#endif
138   -#endif
139   -
140 211 void helper_rett()
141 212 {
142 213 int cwp;
... ... @@ -166,3 +237,22 @@ void helper_ldfsr(void)
166 237 break;
167 238 }
168 239 }
  240 +
  241 +void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
  242 +{
  243 + int exptemp;
  244 +
  245 + *pmant = ldexp(frexp(f, &exptemp), 53);
  246 + *pexp = exptemp;
  247 +}
  248 +
  249 +double cpu_put_fp64(uint64_t mant, uint16_t exp)
  250 +{
  251 + return ldexp((double) mant, exp - 53);
  252 +}
  253 +
  254 +void helper_debug()
  255 +{
  256 + env->exception_index = EXCP_DEBUG;
  257 + cpu_loop_exit();
  258 +}
... ...
target-sparc/op_mem.h
... ... @@ -43,12 +43,8 @@ void OPPROTO glue(op_swap, MEMSUFFIX)(void)
43 43  
44 44 void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
45 45 {
46   -#if 1
47 46 T1 = glue(ldl, MEMSUFFIX)((void *) T0);
48 47 T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
49   -#else
50   - glue(do_ldd, MEMSUFFIX)(T0);
51   -#endif
52 48 }
53 49  
54 50 /*** Floating-point store ***/
... ...
target-sparc/translate.c
... ... @@ -646,6 +646,7 @@ static void disas_sparc_insn(DisasContext * dc)
646 646 switch (xop) {
647 647 case 0x0:
648 648 case 0x1: /* UNIMPL */
  649 + case 0x5: /*CBN+x */
649 650 default:
650 651 goto illegal_insn;
651 652 case 0x2: /* BN+x */
... ... @@ -657,16 +658,24 @@ static void disas_sparc_insn(DisasContext * dc)
657 658 }
658 659 case 0x6: /* FBN+x */
659 660 {
  661 +#if !defined(CONFIG_USER_ONLY)
  662 + gen_op_trap_ifnofpu();
  663 +#endif
660 664 target <<= 2;
661 665 target = sign_extend(target, 22);
662 666 do_fbranch(dc, target, insn);
663 667 goto jmp_insn;
664 668 }
665 669 case 0x4: /* SETHI */
666   - gen_movl_imm_T0(target << 10);
667   - gen_movl_T0_reg(rd);
668   - break;
669   - case 0x5: /*CBN+x */
  670 +#define OPTIM
  671 +#if defined(OPTIM)
  672 + if (rd) { // nop
  673 +#endif
  674 + gen_movl_imm_T0(target << 10);
  675 + gen_movl_T0_reg(rd);
  676 +#if defined(OPTIM)
  677 + }
  678 +#endif
670 679 break;
671 680 }
672 681 break;
... ... @@ -691,14 +700,24 @@ static void disas_sparc_insn(DisasContext * dc)
691 700 gen_movl_reg_T0(rs1);
692 701 if (IS_IMM) {
693 702 rs2 = GET_FIELD(insn, 25, 31);
  703 +#if defined(OPTIM)
694 704 if (rs2 != 0) {
695   - gen_movl_imm_T1(rs2);
696   - gen_op_add_T1_T0();
  705 +#endif
  706 + gen_movl_imm_T1(rs2);
  707 + gen_op_add_T1_T0();
  708 +#if defined(OPTIM)
697 709 }
  710 +#endif
698 711 } else {
699 712 rs2 = GET_FIELD(insn, 27, 31);
700   - gen_movl_reg_T1(rs2);
701   - gen_op_add_T1_T0();
  713 +#if defined(OPTIM)
  714 + if (rs2 != 0) {
  715 +#endif
  716 + gen_movl_reg_T1(rs2);
  717 + gen_op_add_T1_T0();
  718 +#if defined(OPTIM)
  719 + }
  720 +#endif
702 721 }
703 722 save_state(dc);
704 723 cond = GET_FIELD(insn, 3, 6);
... ... @@ -707,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc)
707 726 dc->is_br = 1;
708 727 goto jmp_insn;
709 728 } else {
  729 + gen_cond(cond);
710 730 gen_op_trapcc_T0();
711 731 }
712 732 } else if (xop == 0x28) {
... ... @@ -741,7 +761,10 @@ static void disas_sparc_insn(DisasContext * dc)
741 761 gen_movl_T0_reg(rd);
742 762 break;
743 763 #endif
744   - } else if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
  764 + } else if (xop == 0x34) { /* FPU Operations */
  765 +#if !defined(CONFIG_USER_ONLY)
  766 + gen_op_trap_ifnofpu();
  767 +#endif
745 768 rs1 = GET_FIELD(insn, 13, 17);
746 769 rs2 = GET_FIELD(insn, 27, 31);
747 770 xop = GET_FIELD(insn, 18, 26);
... ... @@ -770,6 +793,8 @@ static void disas_sparc_insn(DisasContext * dc)
770 793 gen_op_fsqrtd();
771 794 gen_op_store_DT0_fpr(rd);
772 795 break;
  796 + case 0x2b: /* fsqrtq */
  797 + goto nfpu_insn;
773 798 case 0x41:
774 799 gen_op_load_fpr_FT0(rs1);
775 800 gen_op_load_fpr_FT1(rs2);
... ... @@ -782,6 +807,8 @@ static void disas_sparc_insn(DisasContext * dc)
782 807 gen_op_faddd();
783 808 gen_op_store_DT0_fpr(rd);
784 809 break;
  810 + case 0x43: /* faddq */
  811 + goto nfpu_insn;
785 812 case 0x45:
786 813 gen_op_load_fpr_FT0(rs1);
787 814 gen_op_load_fpr_FT1(rs2);
... ... @@ -794,6 +821,8 @@ static void disas_sparc_insn(DisasContext * dc)
794 821 gen_op_fsubd();
795 822 gen_op_store_DT0_fpr(rd);
796 823 break;
  824 + case 0x47: /* fsubq */
  825 + goto nfpu_insn;
797 826 case 0x49:
798 827 gen_op_load_fpr_FT0(rs1);
799 828 gen_op_load_fpr_FT1(rs2);
... ... @@ -806,6 +835,8 @@ static void disas_sparc_insn(DisasContext * dc)
806 835 gen_op_fmuld();
807 836 gen_op_store_DT0_fpr(rd);
808 837 break;
  838 + case 0x4b: /* fmulq */
  839 + goto nfpu_insn;
809 840 case 0x4d:
810 841 gen_op_load_fpr_FT0(rs1);
811 842 gen_op_load_fpr_FT1(rs2);
... ... @@ -818,32 +849,16 @@ static void disas_sparc_insn(DisasContext * dc)
818 849 gen_op_fdivd();
819 850 gen_op_store_DT0_fpr(rd);
820 851 break;
821   - case 0x51:
822   - gen_op_load_fpr_FT0(rs1);
823   - gen_op_load_fpr_FT1(rs2);
824   - gen_op_fcmps();
825   - break;
826   - case 0x52:
827   - gen_op_load_fpr_DT0(rs1);
828   - gen_op_load_fpr_DT1(rs2);
829   - gen_op_fcmpd();
830   - break;
831   - case 0x55: /* fcmpes */
832   - gen_op_load_fpr_FT0(rs1);
833   - gen_op_load_fpr_FT1(rs2);
834   - gen_op_fcmps(); /* XXX */
835   - break;
836   - case 0x56: /* fcmped */
837   - gen_op_load_fpr_DT0(rs1);
838   - gen_op_load_fpr_DT1(rs2);
839   - gen_op_fcmpd(); /* XXX */
840   - break;
  852 + case 0x4f: /* fdivq */
  853 + goto nfpu_insn;
841 854 case 0x69:
842 855 gen_op_load_fpr_FT0(rs1);
843 856 gen_op_load_fpr_FT1(rs2);
844 857 gen_op_fsmuld();
845 858 gen_op_store_DT0_fpr(rd);
846 859 break;
  860 + case 0x6e: /* fdmulq */
  861 + goto nfpu_insn;
847 862 case 0xc4:
848 863 gen_op_load_fpr_FT1(rs2);
849 864 gen_op_fitos();
... ... @@ -854,6 +869,8 @@ static void disas_sparc_insn(DisasContext * dc)
854 869 gen_op_fdtos();
855 870 gen_op_store_FT0_fpr(rd);
856 871 break;
  872 + case 0xc7: /* fqtos */
  873 + goto nfpu_insn;
857 874 case 0xc8:
858 875 gen_op_load_fpr_FT1(rs2);
859 876 gen_op_fitod();
... ... @@ -864,6 +881,14 @@ static void disas_sparc_insn(DisasContext * dc)
864 881 gen_op_fstod();
865 882 gen_op_store_DT0_fpr(rd);
866 883 break;
  884 + case 0xcb: /* fqtod */
  885 + goto nfpu_insn;
  886 + case 0xcc: /* fitoq */
  887 + goto nfpu_insn;
  888 + case 0xcd: /* fstoq */
  889 + goto nfpu_insn;
  890 + case 0xce: /* fdtoq */
  891 + goto nfpu_insn;
867 892 case 0xd1:
868 893 gen_op_load_fpr_FT1(rs2);
869 894 gen_op_fstoi();
... ... @@ -874,13 +899,85 @@ static void disas_sparc_insn(DisasContext * dc)
874 899 gen_op_fdtoi();
875 900 gen_op_store_FT0_fpr(rd);
876 901 break;
  902 + case 0xd3: /* fqtoi */
  903 + goto nfpu_insn;
877 904 default:
878 905 goto illegal_insn;
879 906 }
880   - } else {
  907 + } else if (xop == 0x35) { /* FPU Operations */
  908 +#if !defined(CONFIG_USER_ONLY)
  909 + gen_op_trap_ifnofpu();
  910 +#endif
881 911 rs1 = GET_FIELD(insn, 13, 17);
882   - gen_movl_reg_T0(rs1);
883   - if (IS_IMM) { /* immediate */
  912 + rs2 = GET_FIELD(insn, 27, 31);
  913 + xop = GET_FIELD(insn, 18, 26);
  914 + switch (xop) {
  915 + case 0x51:
  916 + gen_op_load_fpr_FT0(rs1);
  917 + gen_op_load_fpr_FT1(rs2);
  918 + gen_op_fcmps();
  919 + break;
  920 + case 0x52:
  921 + gen_op_load_fpr_DT0(rs1);
  922 + gen_op_load_fpr_DT1(rs2);
  923 + gen_op_fcmpd();
  924 + break;
  925 + case 0x53: /* fcmpq */
  926 + goto nfpu_insn;
  927 + case 0x55: /* fcmpes */
  928 + gen_op_load_fpr_FT0(rs1);
  929 + gen_op_load_fpr_FT1(rs2);
  930 + gen_op_fcmps(); /* XXX should trap if qNaN or sNaN */
  931 + break;
  932 + case 0x56: /* fcmped */
  933 + gen_op_load_fpr_DT0(rs1);
  934 + gen_op_load_fpr_DT1(rs2);
  935 + gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN */
  936 + break;
  937 + case 0x57: /* fcmpeq */
  938 + goto nfpu_insn;
  939 + default:
  940 + goto illegal_insn;
  941 + }
  942 +#if defined(OPTIM)
  943 + } else if (xop == 0x2) {
  944 + // clr/mov shortcut
  945 +
  946 + rs1 = GET_FIELD(insn, 13, 17);
  947 + if (rs1 == 0) {
  948 + // or %g0, x, y -> mov T1, x; mov y, T1
  949 + if (IS_IMM) { /* immediate */
  950 + rs2 = GET_FIELDs(insn, 19, 31);
  951 + gen_movl_imm_T1(rs2);
  952 + } else { /* register */
  953 + rs2 = GET_FIELD(insn, 27, 31);
  954 + gen_movl_reg_T1(rs2);
  955 + }
  956 + gen_movl_T1_reg(rd);
  957 + } else {
  958 + gen_movl_reg_T0(rs1);
  959 + if (IS_IMM) { /* immediate */
  960 + // or x, #0, y -> mov T1, x; mov y, T1
  961 + rs2 = GET_FIELDs(insn, 19, 31);
  962 + if (rs2 != 0) {
  963 + gen_movl_imm_T1(rs2);
  964 + gen_op_or_T1_T0();
  965 + }
  966 + } else { /* register */
  967 + // or x, %g0, y -> mov T1, x; mov y, T1
  968 + rs2 = GET_FIELD(insn, 27, 31);
  969 + if (rs2 != 0) {
  970 + gen_movl_reg_T1(rs2);
  971 + gen_op_or_T1_T0();
  972 + }
  973 + }
  974 + gen_movl_T0_reg(rd);
  975 + }
  976 +#endif
  977 + } else if (xop < 0x38) {
  978 + rs1 = GET_FIELD(insn, 13, 17);
  979 + gen_movl_reg_T0(rs1);
  980 + if (IS_IMM) { /* immediate */
884 981 rs2 = GET_FIELDs(insn, 19, 31);
885 982 gen_movl_imm_T1(rs2);
886 983 } else { /* register */
... ... @@ -901,10 +998,10 @@ static void disas_sparc_insn(DisasContext * dc)
901 998 gen_op_logic_T0_cc();
902 999 break;
903 1000 case 0x2:
904   - gen_op_or_T1_T0();
905   - if (xop & 0x10)
906   - gen_op_logic_T0_cc();
907   - break;
  1001 + gen_op_or_T1_T0();
  1002 + if (xop & 0x10)
  1003 + gen_op_logic_T0_cc();
  1004 + break;
908 1005 case 0x3:
909 1006 gen_op_xor_T1_T0();
910 1007 if (xop & 0x10)
... ... @@ -964,9 +1061,14 @@ static void disas_sparc_insn(DisasContext * dc)
964 1061 default:
965 1062 goto illegal_insn;
966 1063 }
967   - gen_movl_T0_reg(rd);
  1064 + gen_movl_T0_reg(rd);
968 1065 } else {
969 1066 switch (xop) {
  1067 + case 0x20: /* taddcc */
  1068 + case 0x21: /* tsubcc */
  1069 + case 0x22: /* taddcctv */
  1070 + case 0x23: /* tsubcctv */
  1071 + goto illegal_insn;
970 1072 case 0x24: /* mulscc */
971 1073 gen_op_mulscc_T1_T0();
972 1074 gen_movl_T0_reg(rd);
... ... @@ -1021,56 +1123,72 @@ static void disas_sparc_insn(DisasContext * dc)
1021 1123 }
1022 1124 break;
1023 1125 #endif
1024   - case 0x38: /* jmpl */
1025   - {
1026   - gen_op_add_T1_T0();
1027   - gen_op_movl_npc_T0();
1028   - if (rd != 0) {
1029   - gen_op_movl_T0_im((long) (dc->pc));
1030   - gen_movl_T0_reg(rd);
1031   - }
1032   - dc->pc = dc->npc;
1033   - dc->npc = DYNAMIC_PC;
1034   - }
1035   - goto jmp_insn;
1036   -#if !defined(CONFIG_USER_ONLY)
1037   - case 0x39: /* rett */
1038   - {
1039   - if (!supervisor(dc))
1040   - goto priv_insn;
1041   - gen_op_add_T1_T0();
1042   - gen_op_movl_npc_T0();
1043   - gen_op_rett();
1044   -#if 0
1045   - dc->pc = dc->npc;
1046   - dc->npc = DYNAMIC_PC;
  1126 + default:
  1127 + goto illegal_insn;
  1128 + }
  1129 + }
  1130 + } else {
  1131 + rs1 = GET_FIELD(insn, 13, 17);
  1132 + gen_movl_reg_T0(rs1);
  1133 + if (IS_IMM) { /* immediate */
  1134 + rs2 = GET_FIELDs(insn, 19, 31);
  1135 +#if defined(OPTIM)
  1136 + if (rs2) {
1047 1137 #endif
1048   - }
1049   -#if 0
1050   - goto jmp_insn;
  1138 + gen_movl_imm_T1(rs2);
  1139 + gen_op_add_T1_T0();
  1140 +#if defined(OPTIM)
  1141 + }
1051 1142 #endif
1052   - break;
  1143 + } else { /* register */
  1144 + rs2 = GET_FIELD(insn, 27, 31);
  1145 +#if defined(OPTIM)
  1146 + if (rs2) {
  1147 +#endif
  1148 + gen_movl_reg_T1(rs2);
  1149 + gen_op_add_T1_T0();
  1150 +#if defined(OPTIM)
  1151 + }
1053 1152 #endif
1054   - case 0x3b: /* flush */
1055   - gen_op_add_T1_T0();
1056   - gen_op_flush_T0();
1057   - break;
1058   - case 0x3c: /* save */
1059   - save_state(dc);
1060   - gen_op_add_T1_T0();
1061   - gen_op_save();
1062   - gen_movl_T0_reg(rd);
1063   - break;
1064   - case 0x3d: /* restore */
1065   - save_state(dc);
1066   - gen_op_add_T1_T0();
1067   - gen_op_restore();
1068   - gen_movl_T0_reg(rd);
1069   - break;
1070   - default:
1071   - goto illegal_insn;
1072   - }
1073 1153 }
  1154 + switch (xop) {
  1155 + case 0x38: /* jmpl */
  1156 + {
  1157 + gen_op_movl_npc_T0();
  1158 + if (rd != 0) {
  1159 + gen_op_movl_T0_im((long) (dc->pc));
  1160 + gen_movl_T0_reg(rd);
  1161 + }
  1162 + dc->pc = dc->npc;
  1163 + dc->npc = DYNAMIC_PC;
  1164 + }
  1165 + goto jmp_insn;
  1166 +#if !defined(CONFIG_USER_ONLY)
  1167 + case 0x39: /* rett */
  1168 + {
  1169 + if (!supervisor(dc))
  1170 + goto priv_insn;
  1171 + gen_op_movl_npc_T0();
  1172 + gen_op_rett();
  1173 + }
  1174 + break;
  1175 +#endif
  1176 + case 0x3b: /* flush */
  1177 + gen_op_flush_T0();
  1178 + break;
  1179 + case 0x3c: /* save */
  1180 + save_state(dc);
  1181 + gen_op_save();
  1182 + gen_movl_T0_reg(rd);
  1183 + break;
  1184 + case 0x3d: /* restore */
  1185 + save_state(dc);
  1186 + gen_op_restore();
  1187 + gen_movl_T0_reg(rd);
  1188 + break;
  1189 + default:
  1190 + goto illegal_insn;
  1191 + }
1074 1192 }
1075 1193 break;
1076 1194 }
... ... @@ -1081,14 +1199,24 @@ static void disas_sparc_insn(DisasContext * dc)
1081 1199 gen_movl_reg_T0(rs1);
1082 1200 if (IS_IMM) { /* immediate */
1083 1201 rs2 = GET_FIELDs(insn, 19, 31);
  1202 +#if defined(OPTIM)
1084 1203 if (rs2 != 0) {
  1204 +#endif
1085 1205 gen_movl_imm_T1(rs2);
1086 1206 gen_op_add_T1_T0();
  1207 +#if defined(OPTIM)
1087 1208 }
  1209 +#endif
1088 1210 } else { /* register */
1089 1211 rs2 = GET_FIELD(insn, 27, 31);
1090   - gen_movl_reg_T1(rs2);
1091   - gen_op_add_T1_T0();
  1212 +#if defined(OPTIM)
  1213 + if (rs2 != 0) {
  1214 +#endif
  1215 + gen_movl_reg_T1(rs2);
  1216 + gen_op_add_T1_T0();
  1217 +#if defined(OPTIM)
  1218 + }
  1219 +#endif
1092 1220 }
1093 1221 if (xop < 4 || (xop > 7 && xop < 0x14) || \
1094 1222 (xop > 0x17 && xop < 0x20)) {
... ... @@ -1116,8 +1244,10 @@ static void disas_sparc_insn(DisasContext * dc)
1116 1244 gen_op_ldst(ldstub);
1117 1245 break;
1118 1246 case 0x0f: /* swap register with memory. Also atomically */
  1247 + gen_movl_reg_T1(rd);
1119 1248 gen_op_ldst(swap);
1120 1249 break;
  1250 +#if !defined(CONFIG_USER_ONLY)
1121 1251 case 0x10: /* load word alternate */
1122 1252 if (!supervisor(dc))
1123 1253 goto priv_insn;
... ... @@ -1157,11 +1287,18 @@ static void disas_sparc_insn(DisasContext * dc)
1157 1287 case 0x1f: /* swap reg with alt. memory. Also atomically */
1158 1288 if (!supervisor(dc))
1159 1289 goto priv_insn;
  1290 + gen_movl_reg_T1(rd);
1160 1291 gen_op_swapa(insn, 1, 4, 0);
1161 1292 break;
  1293 +#endif
  1294 + default:
  1295 + goto illegal_insn;
1162 1296 }
1163 1297 gen_movl_T1_reg(rd);
1164 1298 } else if (xop >= 0x20 && xop < 0x24) {
  1299 +#if !defined(CONFIG_USER_ONLY)
  1300 + gen_op_trap_ifnofpu();
  1301 +#endif
1165 1302 switch (xop) {
1166 1303 case 0x20: /* load fpreg */
1167 1304 gen_op_ldst(ldf);
... ... @@ -1169,11 +1306,14 @@ static void disas_sparc_insn(DisasContext * dc)
1169 1306 break;
1170 1307 case 0x21: /* load fsr */
1171 1308 gen_op_ldfsr();
  1309 + gen_op_store_FT0_fpr(rd);
1172 1310 break;
1173 1311 case 0x23: /* load double fpreg */
1174 1312 gen_op_ldst(lddf);
1175 1313 gen_op_store_DT0_fpr(rd);
1176 1314 break;
  1315 + default:
  1316 + goto illegal_insn;
1177 1317 }
1178 1318 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18)) {
1179 1319 gen_movl_reg_T1(rd);
... ... @@ -1192,6 +1332,7 @@ static void disas_sparc_insn(DisasContext * dc)
1192 1332 gen_movl_reg_T2(rd + 1);
1193 1333 gen_op_ldst(std);
1194 1334 break;
  1335 +#if !defined(CONFIG_USER_ONLY)
1195 1336 case 0x14:
1196 1337 if (!supervisor(dc))
1197 1338 goto priv_insn;
... ... @@ -1214,24 +1355,37 @@ static void disas_sparc_insn(DisasContext * dc)
1214 1355 gen_movl_reg_T2(rd + 1);
1215 1356 gen_op_stda(insn, 0, 8, 0);
1216 1357 break;
  1358 +#endif
  1359 + default:
  1360 + goto illegal_insn;
1217 1361 }
1218 1362 } else if (xop > 0x23 && xop < 0x28) {
  1363 +#if !defined(CONFIG_USER_ONLY)
  1364 + gen_op_trap_ifnofpu();
  1365 +#endif
1219 1366 switch (xop) {
1220 1367 case 0x24:
1221 1368 gen_op_load_fpr_FT0(rd);
1222 1369 gen_op_ldst(stf);
1223 1370 break;
1224 1371 case 0x25:
  1372 + gen_op_load_fpr_FT0(rd);
1225 1373 gen_op_stfsr();
1226 1374 break;
1227 1375 case 0x27:
1228 1376 gen_op_load_fpr_DT0(rd);
1229 1377 gen_op_ldst(stdf);
1230 1378 break;
  1379 + case 0x26: /* stdfq */
  1380 + default:
  1381 + goto illegal_insn;
1231 1382 }
1232 1383 } else if (xop > 0x33 && xop < 0x38) {
1233 1384 /* Co-processor */
  1385 + goto illegal_insn;
1234 1386 }
  1387 + else
  1388 + goto illegal_insn;
1235 1389 }
1236 1390 }
1237 1391 /* default case for non jump instructions */
... ... @@ -1246,17 +1400,24 @@ static void disas_sparc_insn(DisasContext * dc)
1246 1400 dc->pc = dc->npc;
1247 1401 dc->npc = dc->npc + 4;
1248 1402 }
1249   - jmp_insn:;
  1403 + jmp_insn:
1250 1404 return;
1251 1405 illegal_insn:
1252 1406 save_state(dc);
1253 1407 gen_op_exception(TT_ILL_INSN);
1254 1408 dc->is_br = 1;
1255 1409 return;
  1410 +#if !defined(CONFIG_USER_ONLY)
1256 1411 priv_insn:
1257 1412 save_state(dc);
1258 1413 gen_op_exception(TT_PRIV_INSN);
1259 1414 dc->is_br = 1;
  1415 + return;
  1416 +#endif
  1417 + nfpu_insn:
  1418 + save_state(dc);
  1419 + gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
  1420 + dc->is_br = 1;
1260 1421 }
1261 1422  
1262 1423 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
... ... @@ -1271,6 +1432,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1271 1432 dc->tb = tb;
1272 1433 pc_start = tb->pc;
1273 1434 dc->pc = pc_start;
  1435 + last_pc = dc->pc;
1274 1436 dc->npc = (target_ulong) tb->cs_base;
1275 1437 #if defined(CONFIG_USER_ONLY)
1276 1438 dc->mem_idx = 0;
... ... @@ -1285,8 +1447,13 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1285 1447 if (env->nb_breakpoints > 0) {
1286 1448 for(j = 0; j < env->nb_breakpoints; j++) {
1287 1449 if (env->breakpoints[j] == dc->pc) {
1288   - gen_debug(dc, dc->pc);
1289   - break;
  1450 + if (dc->pc != pc_start)
  1451 + save_state(dc);
  1452 + gen_op_debug();
  1453 + gen_op_movl_T0_0();
  1454 + gen_op_exit_tb();
  1455 + dc->is_br = 1;
  1456 + goto exit_gen_loop;
1290 1457 }
1291 1458 }
1292 1459 }
... ... @@ -1310,8 +1477,18 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1310 1477 /* if the next PC is different, we abort now */
1311 1478 if (dc->pc != (last_pc + 4))
1312 1479 break;
  1480 + /* if single step mode, we generate only one instruction and
  1481 + generate an exception */
  1482 + if (env->singlestep_enabled) {
  1483 + gen_op_jmp_im(dc->pc);
  1484 + gen_op_movl_T0_0();
  1485 + gen_op_exit_tb();
  1486 + break;
  1487 + }
1313 1488 } while ((gen_opc_ptr < gen_opc_end) &&
1314 1489 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
  1490 +
  1491 + exit_gen_loop:
1315 1492 if (!dc->is_br) {
1316 1493 if (dc->pc != DYNAMIC_PC &&
1317 1494 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
... ... @@ -1338,7 +1515,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1338 1515 }
1339 1516 #endif
1340 1517 } else {
1341   - tb->size = dc->npc - pc_start;
  1518 + tb->size = last_pc + 4 - pc_start;
1342 1519 }
1343 1520 #ifdef DEBUG_DISAS
1344 1521 if (loglevel & CPU_LOG_TB_IN_ASM) {
... ... @@ -1366,14 +1543,10 @@ int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
1366 1543 return gen_intermediate_code_internal(tb, 1, env);
1367 1544 }
1368 1545  
1369   -CPUSPARCState *cpu_sparc_init(void)
1370   -{
1371   - CPUSPARCState *env;
1372   -
1373   - cpu_exec_init();
  1546 +extern int ram_size;
1374 1547  
1375   - if (!(env = malloc(sizeof(CPUSPARCState))))
1376   - return (NULL);
  1548 +void cpu_reset(CPUSPARCState *env)
  1549 +{
1377 1550 memset(env, 0, sizeof(*env));
1378 1551 env->cwp = 0;
1379 1552 env->wim = 1;
... ... @@ -1381,14 +1554,24 @@ CPUSPARCState *cpu_sparc_init(void)
1381 1554 #if defined(CONFIG_USER_ONLY)
1382 1555 env->user_mode_only = 1;
1383 1556 #else
1384   - /* Emulate Prom */
1385 1557 env->psrs = 1;
1386   - env->pc = 0x4000;
  1558 + env->pc = 0xffd00000;
  1559 + env->gregs[1] = ram_size;
  1560 + env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
1387 1561 env->npc = env->pc + 4;
1388   - env->mmuregs[0] = (0x10<<24) | MMU_E; /* Impl 1, ver 0, MMU Enabled */
1389   - env->mmuregs[1] = 0x3000 >> 4; /* MMU Context table */
1390 1562 #endif
  1563 +}
  1564 +
  1565 +CPUSPARCState *cpu_sparc_init(void)
  1566 +{
  1567 + CPUSPARCState *env;
  1568 +
  1569 + cpu_exec_init();
  1570 +
  1571 + if (!(env = malloc(sizeof(CPUSPARCState))))
  1572 + return (NULL);
1391 1573 cpu_single_env = env;
  1574 + cpu_reset(env);
1392 1575 return (env);
1393 1576 }
1394 1577  
... ... @@ -1436,11 +1619,24 @@ void cpu_dump_state(CPUState *env, FILE *f,
1436 1619 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
1437 1620 }
1438 1621  
  1622 +#if defined(CONFIG_USER_ONLY)
1439 1623 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1440 1624 {
1441 1625 return addr;
1442 1626 }
1443 1627  
  1628 +#else
  1629 +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  1630 +{
  1631 + uint32_t phys_addr;
  1632 + int prot, access_index;
  1633 +
  1634 + if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
  1635 + return -1;
  1636 + return phys_addr;
  1637 +}
  1638 +#endif
  1639 +
1444 1640 void helper_flush(target_ulong addr)
1445 1641 {
1446 1642 addr &= ~7;
... ...
... ... @@ -2214,10 +2214,74 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
2214 2214 #elif defined(TARGET_SPARC)
2215 2215 void cpu_save(QEMUFile *f, void *opaque)
2216 2216 {
  2217 + CPUState *env = opaque;
  2218 + int i;
  2219 + uint32_t tmp;
  2220 +
  2221 + for(i = 1; i < 8; i++)
  2222 + qemu_put_be32s(f, &env->gregs[i]);
  2223 + tmp = env->regwptr - env->regbase;
  2224 + qemu_put_be32s(f, &tmp);
  2225 + for(i = 1; i < NWINDOWS * 16 + 8; i++)
  2226 + qemu_put_be32s(f, &env->regbase[i]);
  2227 +
  2228 + /* FPU */
  2229 + for(i = 0; i < 32; i++) {
  2230 + uint64_t mant;
  2231 + uint16_t exp;
  2232 + cpu_get_fp64(&mant, &exp, env->fpr[i]);
  2233 + qemu_put_be64(f, mant);
  2234 + qemu_put_be16(f, exp);
  2235 + }
  2236 + qemu_put_be32s(f, &env->pc);
  2237 + qemu_put_be32s(f, &env->npc);
  2238 + qemu_put_be32s(f, &env->y);
  2239 + tmp = GET_PSR(env);
  2240 + qemu_put_be32s(f, &tmp);
  2241 + qemu_put_be32s(f, &env->fsr);
  2242 + qemu_put_be32s(f, &env->cwp);
  2243 + qemu_put_be32s(f, &env->wim);
  2244 + qemu_put_be32s(f, &env->tbr);
  2245 + /* MMU */
  2246 + for(i = 0; i < 16; i++)
  2247 + qemu_put_be32s(f, &env->mmuregs[i]);
2217 2248 }
2218 2249  
2219 2250 int cpu_load(QEMUFile *f, void *opaque, int version_id)
2220 2251 {
  2252 + CPUState *env = opaque;
  2253 + int i;
  2254 + uint32_t tmp;
  2255 +
  2256 + for(i = 1; i < 8; i++)
  2257 + qemu_get_be32s(f, &env->gregs[i]);
  2258 + qemu_get_be32s(f, &tmp);
  2259 + env->regwptr = env->regbase + tmp;
  2260 + for(i = 1; i < NWINDOWS * 16 + 8; i++)
  2261 + qemu_get_be32s(f, &env->regbase[i]);
  2262 +
  2263 + /* FPU */
  2264 + for(i = 0; i < 32; i++) {
  2265 + uint64_t mant;
  2266 + uint16_t exp;
  2267 +
  2268 + qemu_get_be64s(f, &mant);
  2269 + qemu_get_be16s(f, &exp);
  2270 + env->fpr[i] = cpu_put_fp64(mant, exp);
  2271 + }
  2272 + qemu_get_be32s(f, &env->pc);
  2273 + qemu_get_be32s(f, &env->npc);
  2274 + qemu_get_be32s(f, &env->y);
  2275 + qemu_get_be32s(f, &tmp);
  2276 + PUT_PSR(env, tmp);
  2277 + qemu_get_be32s(f, &env->fsr);
  2278 + qemu_get_be32s(f, &env->cwp);
  2279 + qemu_get_be32s(f, &env->wim);
  2280 + qemu_get_be32s(f, &env->tbr);
  2281 + /* MMU */
  2282 + for(i = 0; i < 16; i++)
  2283 + qemu_get_be32s(f, &env->mmuregs[i]);
  2284 + tlb_flush(env, 1);
2221 2285 return 0;
2222 2286 }
2223 2287 #else
... ... @@ -2388,7 +2452,7 @@ void qemu_system_shutdown_request(void)
2388 2452  
2389 2453 static void main_cpu_reset(void *opaque)
2390 2454 {
2391   -#ifdef TARGET_I386
  2455 +#if defined(TARGET_I386) || defined(TARGET_SPARC)
2392 2456 CPUState *env = opaque;
2393 2457 cpu_reset(env);
2394 2458 #endif
... ...
... ... @@ -261,7 +261,7 @@ typedef void QEMUTimerCB(void *opaque);
261 261 Hz. */
262 262 extern QEMUClock *rt_clock;
263 263  
264   -/* Rge virtual clock is only run during the emulation. It is stopped
  264 +/* The virtual clock is only run during the emulation. It is stopped
265 265 when the virtual machine is stopped. Virtual timers use a high
266 266 precision clock, usually cpu cycles (use ticks_per_sec). */
267 267 extern QEMUClock *vm_clock;
... ... @@ -672,25 +672,38 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
672 672 DisplayState *ds, const char **fd_filename, int snapshot,
673 673 const char *kernel_filename, const char *kernel_cmdline,
674 674 const char *initrd_filename);
  675 +uint32_t iommu_translate(uint32_t addr);
675 676  
676 677 /* iommu.c */
677   -void iommu_init(uint32_t addr);
678   -uint32_t iommu_translate(uint32_t addr);
  678 +void *iommu_init(uint32_t addr);
  679 +uint32_t iommu_translate_local(void *opaque, uint32_t addr);
679 680  
680 681 /* lance.c */
681 682 void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
682 683  
683 684 /* tcx.c */
684   -void tcx_init(DisplayState *ds, uint32_t addr);
685   -
686   -/* sched.c */
687   -void sched_init();
  685 +void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
  686 + unsigned long vram_offset, int vram_size);
  687 +void tcx_update_display(void *opaque);
  688 +void tcx_invalidate_display(void *opaque);
  689 +void tcx_screen_dump(void *opaque, const char *filename);
  690 +
  691 +/* slavio_intctl.c */
  692 +void *slavio_intctl_init();
  693 +void slavio_pic_info(void *opaque);
  694 +void slavio_irq_info(void *opaque);
  695 +void slavio_pic_set_irq(void *opaque, int irq, int level);
688 696  
689 697 /* magic-load.c */
690   -void magic_init(const char *kfn, int kloadaddr, uint32_t addr);
  698 +int load_elf(const char *filename, uint8_t *addr);
  699 +int load_aout(const char *filename, uint8_t *addr);
  700 +
  701 +/* slavio_timer.c */
  702 +void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2);
691 703  
692   -/* timer.c */
693   -void timer_init(uint32_t addr, int irq);
  704 +/* slavio_serial.c */
  705 +SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
  706 +void slavio_serial_ms_kbd_init(int base, int irq);
694 707  
695 708 /* NVRAM helpers */
696 709 #include "hw/m48t59.h"
... ...