2 #include <aros/debug.h>
3 #include <asm/amcc440.h>
6 #include LC_LIBDEFS_FILE
7 #include "kernel_intern.h"
8 #include "kernel_syscall.h"
9 #include "kernel_globals.h"
10 #include "kernel_scheduler.h"
11 #include "kernel_intr.h"
13 extern char * __text_start
;
14 extern char * __text_end
;
16 #define CFGADD(bus,dev,func,reg) \
17 ( 0x80000000 | ((bus)<<16) | \
18 ((dev)<<11) | ((func)<<8) | ((reg)&~3))
27 static uint32_t _read_config_long(int reg
)
30 outl_le(CFGADD(0, 0, 0, reg
),PCI0_CFGADDR
);
31 temp
=inl_le(PCI0_CFGDATA
);
35 static uint16_t _read_config_word(int reg
)
39 temp
.ul
= _read_config_long(reg
);
40 return temp
.uw
[1 - ((reg
&2)>>1)];
43 static void _write_config_long(int reg
, uint32_t val
)
45 outl_le(CFGADD(0, 0, 0, reg
),PCI0_CFGADDR
);
46 outl_le(val
,PCI0_CFGDATA
);
49 static void _write_config_word(int reg
, uint16_t val
)
53 temp
.ul
= _read_config_long(reg
);
54 temp
.uw
[1 - ((reg
&2)>>1)] = val
;
55 _write_config_long(reg
, temp
.ul
);
58 void syscall_handler(context_t
*ctx
, uint8_t exception
)
60 struct KernelBase
*KernelBase
= getKernelBase();
62 D(bug("[KRN] SysCall: SRR0=%p, SRR1=%p, SC=%d\n", ctx
->cpu
.srr0
, ctx
->cpu
.srr1
, ctx
->cpu
.gpr
[3]));
64 switch (ctx
->cpu
.gpr
[3])
67 /* Disable all external interrupts */
72 /* Enable selected external interrupts */
73 wrdcr(UIC0_ER
, uic_er
[0]);
77 uic_enable(ctx
->cpu
.gpr
[4]);
81 uic_disable(ctx
->cpu
.gpr
[4]);
85 ctx
->cpu
.gpr
[3] = ctx
->cpu
.srr1
;
86 ctx
->cpu
.srr1
&= ~MSR_PR
;
90 if (ctx
->cpu
.srr1
& MSR_PR
)
98 char *start
= (char*)((IPTR
)ctx
->cpu
.gpr
[4] & 0xffffffe0);
99 char *end
= (char*)(((IPTR
)ctx
->cpu
.gpr
[4] + ctx
->cpu
.gpr
[5] + 31) & 0xffffffe0);
102 for (ptr
= start
; ptr
< end
; ptr
+=32)
104 asm volatile("dcbi 0,%0"::"r"(ptr
));
106 asm volatile("sync");
113 * Hard case on Sam440. First of all, the CPU has to be found on PCI bus.
114 * The PCI Bus reset signal will be issued there. Further, CPU returns from
115 * exception to address 0xfffffffc.
118 D(bug("[KRN] REBOOT..."));
120 D(bug("[KRN] LR=%08x", ctx
->cpu
.lr
));
121 D(bug("[KRN] Backtrace:\n"));
122 uint32_t *sp
= (uint32_t *)ctx
->cpu
.gpr
[1];
124 sp
= (uint32_t *)sp
[0];
125 D(bug("[KRN] %08x\n", sp
[1]));
128 uint64_t newtbu
= mftbu() + KernelBase
->kb_PlatformData
->pd_OPBFreq
;
129 while(newtbu
> mftbu());
131 newtbu
= mftbu() + KernelBase
->kb_PlatformData
->pd_OPBFreq
;
132 while(newtbu
> mftbu());
134 newtbu
= mftbu() + KernelBase
->kb_PlatformData
->pd_OPBFreq
;
135 while(newtbu
> mftbu());
137 newtbu
= mftbu() + KernelBase
->kb_PlatformData
->pd_OPBFreq
;
138 while(newtbu
> mftbu());
141 /* PCI Bridge options 2 register */
142 uint16_t val
= _read_config_word(0x60);
143 /* Set the PCI reset signal */
144 _write_config_word(0x60, val
| (1 << 12));
146 /* Let the PCI reset last as long as needed */
147 for (i
=0; i
< 100; i
++)
148 asm volatile("sync");
149 /* De-assert the PCI reset */
150 _write_config_word(0x60, val
& ~(1 << 12));
153 asm volatile("mtsrr0 %0; mtsrr1 %1; rfi"::"r"(0xfffffffc), "r"(1 << 6));
157 core_SysCall(ctx
->cpu
.gpr
[3], ctx
);