Built a basic framework for sending ethernet packets from userland. Switched from...
[akaros.git] / user / parlib / src / syscall.c
1 // System call stubs.
2 #ifdef __DEPUTY__
3 #pragma nodeputy
4 #endif
5
6 #include <arch/x86.h>
7 #include <parlib.h>
8
9 // TODO: modify to take only four parameters
10 static intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
11                                  intreg_t a2, intreg_t a3,
12                                  intreg_t a4, intreg_t a5)
13 {
14         intreg_t ret;
15         asm volatile(
16             "pushl %%ebp\n\t"
17             "pushl %%esi\n\t"
18             "movl %%esp, %%ebp\n\t"
19             "leal after_sysenter, %%esi\n\t"
20             "sysenter\n\t"
21             "after_sysenter:\n\t"
22             "\tpopl %%esi\n"
23             "\tpopl %%ebp\n"
24             :"=a" (ret)
25             : "a" (num),
26               "d" (a1),
27               "c" (a2),
28               "b" (a3),
29               "D" (a4)
30             : "cc", "memory", "%esp");
31         return ret;
32 }
33
34 static intreg_t syscall_trap(uint16_t num, intreg_t a1,
35                              intreg_t a2, intreg_t a3,
36                              intreg_t a4, intreg_t a5)
37 {
38         debug("duh!\n");
39         // Generic system call: pass system call number in AX,
40         // up to five parameters in DX, CX, BX, DI, SI.
41         // Interrupt kernel with T_SYSCALL.
42         //
43         // The "volatile" tells the assembler not to optimize
44         // this instruction away just because we don't use the
45         // return value.
46         //
47         // The last clause tells the assembler that this can
48         // potentially change the condition codes and arbitrary
49         // memory locations.
50
51         asm volatile("int %1\n"
52                 : "=a" (ret)
53                 : "i" (T_SYSCALL),
54                   "a" (num),
55                   "d" (a1),
56                   "c" (a2),
57                   "b" (a3),
58                   "D" (a4),
59                   "S" (a5)
60                 : "cc", "memory");
61
62         return ret;
63 }
64
65 static intreg_t syscall(uint16_t num, intreg_t a1,
66                         intreg_t a2, intreg_t a3,
67                         intreg_t a4, intreg_t a5)
68 {
69         #ifndef SYSCALL_TRAP
70                 return syscall_sysenter(num, a1, a2, a3, a4, a5);
71         #else
72                 return syscall_trap(num, a1, a2, a3, a4, a5);
73         #endif
74 }
75
76 void sys_env_destroy(envid_t envid)
77 {
78         syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
79         while(1); //Should never get here...
80 }
81
82 envid_t sys_getenvid(void)
83 {
84          return syscall(SYS_getenvid, 0, 0, 0, 0, 0);
85 }
86
87 envid_t sys_getcpuid(void)
88 {
89          return syscall(SYS_getcpuid, 0, 0, 0, 0, 0);
90 }
91
92 ssize_t sys_cputs(const uint8_t *s, size_t len)
93 {
94     return syscall(SYS_cputs, (intreg_t) s,  len, 0, 0, 0);
95 }
96
97 uint16_t sys_cgetc(void)
98 {
99     return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
100 }
101
102 //Write a buffer over the serial port
103 ssize_t sys_serial_write(void* buf, size_t len) 
104 {
105         return syscall(SYS_serial_write, (intreg_t)buf, len, 0, 0, 0);
106 }
107
108 //Read a buffer over the serial port
109 ssize_t sys_serial_read(void* buf, size_t len) 
110 {
111         return syscall(SYS_serial_read, (intreg_t)buf, len, 0, 0, 0);
112 }
113
114 //Write a buffer over ethernet
115 ssize_t sys_eth_write(void* buf, size_t len) 
116 {
117         return syscall(SYS_eth_write, (intreg_t)buf, len, 0, 0, 0);
118 }
119
120 //Read a buffer via ethernet
121 ssize_t sys_eth_read(void* buf, size_t len) 
122 {
123         return syscall(SYS_eth_read, (intreg_t)buf, len, 0, 0, 0);
124 }