Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / arch / ppc-sam440 / kernel / syscall.c
blob901771000bacd8b3340a1980524bf18871804f9c
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
7 #include <asm/amcc440.h>
8 #include <asm/io.h>
10 #include LC_LIBDEFS_FILE
11 #include "kernel_intern.h"
12 #include "kernel_syscall.h"
13 #include "kernel_globals.h"
14 #include "kernel_scheduler.h"
15 #include "kernel_intr.h"
17 extern char * __text_start;
18 extern char * __text_end;
20 #define CFGADD(bus,dev,func,reg) \
21 ( 0x80000000 | ((bus)<<16) | \
22 ((dev)<<11) | ((func)<<8) | ((reg)&~3))
24 typedef union _pcicfg
26 uint32_t ul;
27 uint16_t uw[2];
28 uint8_t ub[4];
29 } pcicfg;
31 static uint32_t _read_config_long(int reg)
33 uint32_t temp;
34 outl_le(CFGADD(0, 0, 0, reg),PCI0_CFGADDR);
35 temp=inl_le(PCI0_CFGDATA);
36 return temp;
39 static uint16_t _read_config_word(int reg)
41 pcicfg temp;
43 temp.ul = _read_config_long(reg);
44 return temp.uw[1 - ((reg&2)>>1)];
47 static void _write_config_long(int reg, uint32_t val)
49 outl_le(CFGADD(0, 0, 0, reg),PCI0_CFGADDR);
50 outl_le(val,PCI0_CFGDATA);
53 static void _write_config_word(int reg, uint16_t val)
55 pcicfg temp;
57 temp.ul = _read_config_long(reg);
58 temp.uw[1 - ((reg&2)>>1)] = val;
59 _write_config_long(reg, temp.ul);
62 void syscall_handler(context_t *ctx, uint8_t exception)
64 struct KernelBase *KernelBase = getKernelBase();
66 D(bug("[KRN] SysCall: SRR0=%p, SRR1=%p, SC=%d\n", ctx->cpu.srr0, ctx->cpu.srr1, ctx->cpu.gpr[3]));
68 switch (ctx->cpu.gpr[3])
70 case SC_CLI:
71 /* Disable all external interrupts */
72 wrdcr(UIC0_ER, 0);
73 break;
75 case SC_STI:
76 /* Enable selected external interrupts */
77 wrdcr(UIC0_ER, uic_er[0]);
78 break;
80 case SC_IRQ_ENABLE:
81 uic_enable(ctx->cpu.gpr[4]);
82 break;
84 case SC_IRQ_DISABLE:
85 uic_disable(ctx->cpu.gpr[4]);
86 break;
88 case SC_SUPERSTATE:
89 ctx->cpu.gpr[3] = ctx->cpu.srr1;
90 ctx->cpu.srr1 &= ~MSR_PR;
91 break;
93 case SC_ISSUPERSTATE:
94 if (ctx->cpu.srr1 & MSR_PR)
95 ctx->cpu.gpr[3] = 0;
96 else
97 ctx->cpu.gpr[3] = 1;
98 break;
100 case SC_INVALIDATED:
102 char *start = (char*)((IPTR)ctx->cpu.gpr[4] & 0xffffffe0);
103 char *end = (char*)(((IPTR)ctx->cpu.gpr[4] + ctx->cpu.gpr[5] + 31) & 0xffffffe0);
104 char *ptr;
106 for (ptr = start; ptr < end; ptr +=32)
108 asm volatile("dcbi 0,%0"::"r"(ptr));
110 asm volatile("sync");
111 break;
114 case SC_REBOOT:
117 * Hard case on Sam440. First of all, the CPU has to be found on PCI bus.
118 * The PCI Bus reset signal will be issued there. Further, CPU returns from
119 * exception to address 0xfffffffc.
122 D(bug("[KRN] REBOOT..."));
124 D(bug("[KRN] LR=%08x", ctx->cpu.lr));
125 D(bug("[KRN] Backtrace:\n"));
126 uint32_t *sp = (uint32_t *)ctx->cpu.gpr[1];
127 while(*sp) {
128 sp = (uint32_t *)sp[0];
129 D(bug("[KRN] %08x\n", sp[1]));
132 uint64_t newtbu = mftbu() + KernelBase->kb_PlatformData->pd_OPBFreq;
133 while(newtbu > mftbu());
134 D(bug("3..."));
135 newtbu = mftbu() + KernelBase->kb_PlatformData->pd_OPBFreq;
136 while(newtbu > mftbu());
137 D(bug("2..."));
138 newtbu = mftbu() + KernelBase->kb_PlatformData->pd_OPBFreq;
139 while(newtbu > mftbu());
140 D(bug("1..."));
141 newtbu = mftbu() + KernelBase->kb_PlatformData->pd_OPBFreq;
142 while(newtbu > mftbu());
143 D(bug("\n\n\n"));
145 /* PCI Bridge options 2 register */
146 uint16_t val = _read_config_word(0x60);
147 /* Set the PCI reset signal */
148 _write_config_word(0x60, val | (1 << 12));
149 int i;
150 /* Let the PCI reset last as long as needed */
151 for (i=0; i < 100; i++)
152 asm volatile("sync");
153 /* De-assert the PCI reset */
154 _write_config_word(0x60, val & ~(1 << 12));
156 /* Restart CPU */
157 asm volatile("mtsrr0 %0; mtsrr1 %1; rfi"::"r"(0xfffffffc), "r"(1 << 6));
158 while(1);
160 default:
161 core_SysCall(ctx->cpu.gpr[3], ctx);
162 break;