Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 1 | // Basic x86 asm functions and function defs. |
| 2 | // |
Kevin O'Connor | 244caf8 | 2010-09-15 21:48:16 -0400 | [diff] [blame] | 3 | // Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net> |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 4 | // |
Kevin O'Connor | b1b7c2a | 2009-01-15 20:52:58 -0500 | [diff] [blame] | 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. |
Kevin O'Connor | 786502d | 2008-02-27 10:41:41 -0500 | [diff] [blame] | 6 | #ifndef __UTIL_H |
| 7 | #define __UTIL_H |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 8 | |
Kevin O'Connor | 9521e26 | 2008-07-04 13:04:29 -0400 | [diff] [blame] | 9 | #include "types.h" // u32 |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 10 | |
Kevin O'Connor | 786502d | 2008-02-27 10:41:41 -0500 | [diff] [blame] | 11 | static inline void irq_disable(void) |
| 12 | { |
| 13 | asm volatile("cli": : :"memory"); |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 14 | } |
| 15 | |
Kevin O'Connor | 786502d | 2008-02-27 10:41:41 -0500 | [diff] [blame] | 16 | static inline void irq_enable(void) |
| 17 | { |
| 18 | asm volatile("sti": : :"memory"); |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 19 | } |
| 20 | |
Kevin O'Connor | 9eb2100 | 2012-01-29 13:30:56 -0500 | [diff] [blame] | 21 | static inline u32 save_flags(void) |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 22 | { |
Kevin O'Connor | 9eb2100 | 2012-01-29 13:30:56 -0500 | [diff] [blame] | 23 | u32 flags; |
| 24 | asm volatile("pushfl ; popl %0" : "=rm" (flags)); |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 25 | return flags; |
| 26 | } |
| 27 | |
Kevin O'Connor | 9eb2100 | 2012-01-29 13:30:56 -0500 | [diff] [blame] | 28 | static inline void restore_flags(u32 flags) |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 29 | { |
| 30 | asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc"); |
| 31 | } |
| 32 | |
Kevin O'Connor | 06ad44e | 2008-04-05 19:30:02 -0400 | [diff] [blame] | 33 | static inline void cpu_relax(void) |
| 34 | { |
| 35 | asm volatile("rep ; nop": : :"memory"); |
| 36 | } |
| 37 | |
Kevin O'Connor | 38fcbfe | 2008-02-25 22:30:47 -0500 | [diff] [blame] | 38 | static inline void nop(void) |
| 39 | { |
| 40 | asm volatile("nop"); |
| 41 | } |
| 42 | |
Kevin O'Connor | 95b2f78 | 2008-03-05 19:52:06 -0500 | [diff] [blame] | 43 | static inline void hlt(void) |
| 44 | { |
Kevin O'Connor | 9c447c3 | 2010-05-23 10:24:22 -0400 | [diff] [blame] | 45 | asm volatile("hlt": : :"memory"); |
Kevin O'Connor | 95b2f78 | 2008-03-05 19:52:06 -0500 | [diff] [blame] | 46 | } |
| 47 | |
Kevin O'Connor | da4a648 | 2008-06-08 13:48:06 -0400 | [diff] [blame] | 48 | static inline void wbinvd(void) |
| 49 | { |
Kevin O'Connor | 9c447c3 | 2010-05-23 10:24:22 -0400 | [diff] [blame] | 50 | asm volatile("wbinvd": : :"memory"); |
Kevin O'Connor | da4a648 | 2008-06-08 13:48:06 -0400 | [diff] [blame] | 51 | } |
| 52 | |
Kevin O'Connor | 745de85 | 2012-01-29 14:15:14 -0500 | [diff] [blame^] | 53 | #define CPUID_TSC (1 << 4) |
Kevin O'Connor | e97ca7b | 2009-06-21 09:10:28 -0400 | [diff] [blame] | 54 | #define CPUID_MSR (1 << 5) |
| 55 | #define CPUID_APIC (1 << 9) |
| 56 | #define CPUID_MTRR (1 << 12) |
Kevin O'Connor | 9eb2100 | 2012-01-29 13:30:56 -0500 | [diff] [blame] | 57 | static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) |
Kevin O'Connor | 84ad59a | 2008-07-04 05:47:26 -0400 | [diff] [blame] | 58 | { |
| 59 | asm("cpuid" |
| 60 | : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) |
| 61 | : "0" (index)); |
| 62 | } |
| 63 | |
Kevin O'Connor | 87b533b | 2011-07-10 22:35:07 -0400 | [diff] [blame] | 64 | static inline u32 getcr0(void) { |
| 65 | u32 cr0; |
| 66 | asm("movl %%cr0, %0" : "=r"(cr0)); |
| 67 | return cr0; |
| 68 | } |
| 69 | static inline void setcr0(u32 cr0) { |
| 70 | asm("movl %0, %%cr0" : : "r"(cr0)); |
| 71 | } |
| 72 | |
Kevin O'Connor | e97ca7b | 2009-06-21 09:10:28 -0400 | [diff] [blame] | 73 | static inline u64 rdmsr(u32 index) |
| 74 | { |
| 75 | u64 ret; |
| 76 | asm ("rdmsr" : "=A"(ret) : "c"(index)); |
| 77 | return ret; |
| 78 | } |
| 79 | |
| 80 | static inline void wrmsr(u32 index, u64 val) |
| 81 | { |
| 82 | asm volatile ("wrmsr" : : "c"(index), "A"(val)); |
| 83 | } |
| 84 | |
Kevin O'Connor | bc2aecd | 2008-11-28 16:40:06 -0500 | [diff] [blame] | 85 | static inline u64 rdtscll(void) |
| 86 | { |
| 87 | u64 val; |
| 88 | asm volatile("rdtsc" : "=A" (val)); |
| 89 | return val; |
| 90 | } |
| 91 | |
Kevin O'Connor | 0bf9270 | 2009-08-01 11:45:37 -0400 | [diff] [blame] | 92 | static inline u32 __ffs(u32 word) |
| 93 | { |
| 94 | asm("bsf %1,%0" |
| 95 | : "=r" (word) |
| 96 | : "rm" (word)); |
| 97 | return word; |
| 98 | } |
Kevin O'Connor | 86916ce | 2009-11-14 13:34:27 -0500 | [diff] [blame] | 99 | static inline u32 __fls(u32 word) |
| 100 | { |
| 101 | asm("bsr %1,%0" |
| 102 | : "=r" (word) |
| 103 | : "rm" (word)); |
| 104 | return word; |
| 105 | } |
Kevin O'Connor | 0bf9270 | 2009-08-01 11:45:37 -0400 | [diff] [blame] | 106 | |
Kevin O'Connor | 68caaa7 | 2010-02-15 10:46:37 -0500 | [diff] [blame] | 107 | static inline u16 __htons_constant(u16 val) { |
| 108 | return (val<<8) | (val>>8); |
| 109 | } |
| 110 | static inline u32 __htonl_constant(u32 val) { |
| 111 | return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24); |
| 112 | } |
| 113 | static inline u32 __htonl(u32 val) { |
| 114 | asm("bswapl %0" : "+r"(val)); |
| 115 | return val; |
| 116 | } |
| 117 | #define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x)) |
| 118 | #define ntohl(x) htonl(x) |
| 119 | #define htons(x) __htons_constant(x) |
| 120 | #define ntohs(x) htons(x) |
| 121 | |
Isaku Yamahata | 2f54bb4 | 2010-07-20 16:37:16 +0900 | [diff] [blame] | 122 | static inline u16 cpu_to_le16(u16 x) |
| 123 | { |
| 124 | return x; |
| 125 | } |
| 126 | |
| 127 | static inline u32 cpu_to_le32(u32 x) |
| 128 | { |
| 129 | return x; |
| 130 | } |
| 131 | |
Isaku Yamahata | baae940 | 2011-10-24 17:11:07 +0900 | [diff] [blame] | 132 | static inline u32 le32_to_cpu(u32 x) |
| 133 | { |
| 134 | return x; |
| 135 | } |
| 136 | |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 137 | static inline u32 getesp(void) { |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 138 | u32 esp; |
| 139 | asm("movl %%esp, %0" : "=rm"(esp)); |
| 140 | return esp; |
| 141 | } |
| 142 | |
Kevin O'Connor | 91031ed | 2009-10-12 09:49:27 -0400 | [diff] [blame] | 143 | static inline void writel(void *addr, u32 val) { |
| 144 | *(volatile u32 *)addr = val; |
| 145 | } |
| 146 | static inline void writew(void *addr, u16 val) { |
| 147 | *(volatile u16 *)addr = val; |
| 148 | } |
| 149 | static inline void writeb(void *addr, u8 val) { |
| 150 | *(volatile u8 *)addr = val; |
| 151 | } |
| 152 | static inline u32 readl(const void *addr) { |
| 153 | return *(volatile const u32 *)addr; |
| 154 | } |
| 155 | static inline u16 readw(const void *addr) { |
| 156 | return *(volatile const u16 *)addr; |
| 157 | } |
| 158 | static inline u8 readb(const void *addr) { |
| 159 | return *(volatile const u8 *)addr; |
| 160 | } |
| 161 | |
Kevin O'Connor | 942d495 | 2009-06-10 22:44:06 -0400 | [diff] [blame] | 162 | #define call16_simpint(nr, peax, pflags) do { \ |
Kevin O'Connor | 0b60a06 | 2009-06-15 23:03:05 -0400 | [diff] [blame] | 163 | ASSERT16(); \ |
Kevin O'Connor | 942d495 | 2009-06-10 22:44:06 -0400 | [diff] [blame] | 164 | asm volatile( \ |
Kevin O'Connor | 4ed378a | 2010-03-13 22:29:55 -0500 | [diff] [blame] | 165 | "pushl %%ebp\n" \ |
| 166 | "sti\n" \ |
Kevin O'Connor | 942d495 | 2009-06-10 22:44:06 -0400 | [diff] [blame] | 167 | "stc\n" \ |
| 168 | "int %2\n" \ |
| 169 | "pushfl\n" \ |
| 170 | "popl %1\n" \ |
| 171 | "cli\n" \ |
Kevin O'Connor | 4ed378a | 2010-03-13 22:29:55 -0500 | [diff] [blame] | 172 | "cld\n" \ |
| 173 | "popl %%ebp" \ |
| 174 | : "+a"(*peax), "=c"(*pflags) \ |
Kevin O'Connor | 942d495 | 2009-06-10 22:44:06 -0400 | [diff] [blame] | 175 | : "i"(nr) \ |
Kevin O'Connor | 4ed378a | 2010-03-13 22:29:55 -0500 | [diff] [blame] | 176 | : "ebx", "edx", "esi", "edi", "cc", "memory"); \ |
Kevin O'Connor | 942d495 | 2009-06-10 22:44:06 -0400 | [diff] [blame] | 177 | } while (0) |
| 178 | |
Kevin O'Connor | ae6924d | 2010-07-25 14:46:21 -0400 | [diff] [blame] | 179 | // GDT bits |
Kevin O'Connor | ad90159 | 2009-12-13 11:25:25 -0500 | [diff] [blame] | 180 | #define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set |
| 181 | #define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set |
| 182 | #define GDT_B (0x1ULL << 54) // Big flag |
| 183 | #define GDT_G (0x1ULL << 55) // Granularity flag |
Kevin O'Connor | ae6924d | 2010-07-25 14:46:21 -0400 | [diff] [blame] | 184 | // GDT bits for segment base |
| 185 | #define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ |
| 186 | | (((u64)(v) & 0x00ffffff) << 16)) |
| 187 | // GDT bits for segment limit (0-1Meg) |
| 188 | #define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ |
| 189 | | (((u64)(v) & 0x0000ffff) << 0)) |
| 190 | // GDT bits for segment limit (0-4Gig in 4K chunks) |
| 191 | #define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12)) |
Kevin O'Connor | ad90159 | 2009-12-13 11:25:25 -0500 | [diff] [blame] | 192 | |
| 193 | struct descloc_s { |
| 194 | u16 length; |
| 195 | u32 addr; |
| 196 | } PACKED; |
| 197 | |
Kevin O'Connor | a83ff55 | 2009-01-01 21:00:59 -0500 | [diff] [blame] | 198 | // util.c |
Kevin O'Connor | 9eb2100 | 2012-01-29 13:30:56 -0500 | [diff] [blame] | 199 | void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); |
Kevin O'Connor | 9521e26 | 2008-07-04 13:04:29 -0400 | [diff] [blame] | 200 | struct bregs; |
| 201 | inline void call16(struct bregs *callregs); |
Kevin O'Connor | 6e5b4a4 | 2008-12-06 13:03:52 -0500 | [diff] [blame] | 202 | inline void call16big(struct bregs *callregs); |
Kevin O'Connor | 9521e26 | 2008-07-04 13:04:29 -0400 | [diff] [blame] | 203 | inline void __call16_int(struct bregs *callregs, u16 offset); |
Kevin O'Connor | 3a47a31 | 2008-03-01 14:46:37 -0500 | [diff] [blame] | 204 | #define call16_int(nr, callregs) do { \ |
| 205 | extern void irq_trampoline_ ##nr (); \ |
Kevin O'Connor | 117fc21 | 2008-04-13 18:17:02 -0400 | [diff] [blame] | 206 | __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \ |
Kevin O'Connor | 38fcbfe | 2008-02-25 22:30:47 -0500 | [diff] [blame] | 207 | } while (0) |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 208 | u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); |
| 209 | u8 checksum(void *buf, u32 len); |
| 210 | size_t strlen(const char *s); |
| 211 | int memcmp(const void *s1, const void *s2, size_t n); |
| 212 | int strcmp(const char *s1, const char *s2); |
| 213 | inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len); |
| 214 | inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len); |
| 215 | void *memset(void *s, int c, size_t n); |
Gerd Hoffmann | 0a80608 | 2010-11-29 09:42:11 +0100 | [diff] [blame] | 216 | void memset_fl(void *ptr, u8 val, size_t size); |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 217 | inline void memcpy_far(u16 d_seg, void *d_far |
| 218 | , u16 s_seg, const void *s_far, size_t len); |
Kevin O'Connor | 8f59aa3 | 2010-06-06 16:11:45 -0400 | [diff] [blame] | 219 | void memcpy_fl(void *d_fl, const void *s_fl, size_t len); |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 220 | void *memcpy(void *d1, const void *s1, size_t len); |
Kevin O'Connor | 52a300f | 2009-12-26 23:32:57 -0500 | [diff] [blame] | 221 | #if MODESEGMENT == 0 |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 222 | #define memcpy __builtin_memcpy |
| 223 | #endif |
| 224 | void iomemcpy(void *d, const void *s, u32 len); |
| 225 | void *memmove(void *d, const void *s, size_t len); |
| 226 | char *strtcpy(char *dest, const char *src, size_t len); |
Kevin O'Connor | 2e109a6 | 2010-12-24 10:39:32 -0500 | [diff] [blame] | 227 | char *strchr(const char *s, int c); |
Kevin O'Connor | 9e881a3 | 2011-01-08 12:06:54 -0500 | [diff] [blame] | 228 | void nullTrailingSpace(char *buf); |
Kevin O'Connor | 9f4e1d9 | 2009-02-08 15:44:08 -0500 | [diff] [blame] | 229 | int get_keystroke(int msec); |
Kevin O'Connor | 38fcbfe | 2008-02-25 22:30:47 -0500 | [diff] [blame] | 230 | |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 231 | // stacks.c |
Kevin O'Connor | af9629b | 2010-11-25 09:17:31 -0500 | [diff] [blame] | 232 | u32 call32(void *func, u32 eax, u32 errret); |
Kevin O'Connor | bca0736 | 2010-03-20 20:41:38 -0400 | [diff] [blame] | 233 | inline u32 stack_hop(u32 eax, u32 edx, void *func); |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 234 | extern struct thread_info MainThread; |
Kevin O'Connor | 533b628 | 2011-07-16 13:13:12 -0400 | [diff] [blame] | 235 | extern int CanPreempt; |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 236 | struct thread_info *getCurThread(void); |
| 237 | void yield(void); |
Kevin O'Connor | 9c447c3 | 2010-05-23 10:24:22 -0400 | [diff] [blame] | 238 | void wait_irq(void); |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 239 | void run_thread(void (*func)(void*), void *data); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 240 | void wait_threads(void); |
Kevin O'Connor | e908665 | 2010-02-27 13:49:47 -0500 | [diff] [blame] | 241 | struct mutex_s { u32 isLocked; }; |
| 242 | void mutex_lock(struct mutex_s *mutex); |
| 243 | void mutex_unlock(struct mutex_s *mutex); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 244 | void start_preempt(void); |
| 245 | void finish_preempt(void); |
Kevin O'Connor | d7eb27e | 2010-03-20 18:17:19 -0400 | [diff] [blame] | 246 | int wait_preempt(void); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 247 | void check_preempt(void); |
Kevin O'Connor | 7cefbfa | 2009-12-10 21:35:49 -0500 | [diff] [blame] | 248 | |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 249 | // output.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 250 | void debug_serial_setup(void); |
Kevin O'Connor | e07e18e | 2009-02-08 17:07:29 -0500 | [diff] [blame] | 251 | void panic(const char *fmt, ...) |
Kevin O'Connor | dad41d9 | 2010-01-01 03:04:19 -0500 | [diff] [blame] | 252 | __attribute__ ((format (printf, 1, 2))) __noreturn; |
Kevin O'Connor | 567e4e3 | 2008-04-05 11:37:51 -0400 | [diff] [blame] | 253 | void printf(const char *fmt, ...) |
| 254 | __attribute__ ((format (printf, 1, 2))); |
Kevin O'Connor | 2be312c | 2009-11-24 09:37:53 -0500 | [diff] [blame] | 255 | int snprintf(char *str, size_t size, const char *fmt, ...) |
Kevin O'Connor | 9ed6b62 | 2009-10-07 21:41:08 -0400 | [diff] [blame] | 256 | __attribute__ ((format (printf, 3, 4))); |
Kevin O'Connor | ca2bc1c | 2010-12-29 21:41:19 -0500 | [diff] [blame] | 257 | char * znprintf(size_t size, const char *fmt, ...) |
| 258 | __attribute__ ((format (printf, 2, 3))); |
Kevin O'Connor | cfdc13f | 2010-02-14 13:07:54 -0500 | [diff] [blame] | 259 | void __dprintf(const char *fmt, ...) |
| 260 | __attribute__ ((format (printf, 1, 2))); |
| 261 | void __debug_enter(struct bregs *regs, const char *fname); |
| 262 | void __debug_isr(const char *fname); |
| 263 | void __debug_stub(struct bregs *regs, int lineno, const char *fname); |
| 264 | void __warn_invalid(struct bregs *regs, int lineno, const char *fname); |
| 265 | void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname); |
Kevin O'Connor | 7fb8ba8 | 2010-02-26 08:45:00 -0500 | [diff] [blame] | 266 | void __warn_internalerror(int lineno, const char *fname); |
Kevin O'Connor | cfdc13f | 2010-02-14 13:07:54 -0500 | [diff] [blame] | 267 | void __warn_noalloc(int lineno, const char *fname); |
| 268 | void __warn_timeout(int lineno, const char *fname); |
| 269 | void __set_invalid(struct bregs *regs, int lineno, const char *fname); |
| 270 | void __set_unimplemented(struct bregs *regs, int lineno, const char *fname); |
| 271 | void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname); |
| 272 | void __set_code_unimplemented(struct bregs *regs, u32 linecode |
| 273 | , const char *fname); |
| 274 | void hexdump(const void *d, int len); |
| 275 | |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 276 | #define dprintf(lvl, fmt, args...) do { \ |
| 277 | if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \ |
| 278 | __dprintf((fmt) , ##args ); \ |
| 279 | } while (0) |
Kevin O'Connor | 15c1f22 | 2008-06-12 22:59:43 -0400 | [diff] [blame] | 280 | #define debug_enter(regs, lvl) do { \ |
| 281 | if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ |
Kevin O'Connor | 0560034 | 2009-01-02 13:10:58 -0500 | [diff] [blame] | 282 | __debug_enter((regs), __func__); \ |
Kevin O'Connor | 15c1f22 | 2008-06-12 22:59:43 -0400 | [diff] [blame] | 283 | } while (0) |
| 284 | #define debug_isr(lvl) do { \ |
| 285 | if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \ |
| 286 | __debug_isr(__func__); \ |
| 287 | } while (0) |
Kevin O'Connor | 0560034 | 2009-01-02 13:10:58 -0500 | [diff] [blame] | 288 | #define debug_stub(regs) \ |
| 289 | __debug_stub((regs), __LINE__, __func__) |
Kevin O'Connor | cfdc13f | 2010-02-14 13:07:54 -0500 | [diff] [blame] | 290 | #define warn_invalid(regs) \ |
| 291 | __warn_invalid((regs), __LINE__, __func__) |
| 292 | #define warn_unimplemented(regs) \ |
| 293 | __warn_unimplemented((regs), __LINE__, __func__) |
Kevin O'Connor | 7fb8ba8 | 2010-02-26 08:45:00 -0500 | [diff] [blame] | 294 | #define warn_internalerror() \ |
| 295 | __warn_internalerror(__LINE__, __func__) |
Kevin O'Connor | cfdc13f | 2010-02-14 13:07:54 -0500 | [diff] [blame] | 296 | #define warn_noalloc() \ |
| 297 | __warn_noalloc(__LINE__, __func__) |
| 298 | #define warn_timeout() \ |
| 299 | __warn_timeout(__LINE__, __func__) |
| 300 | #define set_invalid(regs) \ |
| 301 | __set_invalid((regs), __LINE__, __func__) |
| 302 | #define set_code_invalid(regs, code) \ |
| 303 | __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__) |
| 304 | #define set_unimplemented(regs) \ |
| 305 | __set_unimplemented((regs), __LINE__, __func__) |
| 306 | #define set_code_unimplemented(regs, code) \ |
| 307 | __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__) |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 308 | |
| 309 | // kbd.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 310 | void kbd_setup(void); |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 311 | void handle_15c2(struct bregs *regs); |
Kevin O'Connor | 114592f | 2009-09-28 21:32:08 -0400 | [diff] [blame] | 312 | void process_key(u8 key); |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 313 | |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 314 | // mouse.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 315 | void mouse_setup(void); |
Kevin O'Connor | 5787748 | 2009-12-09 21:00:41 -0500 | [diff] [blame] | 316 | void process_mouse(u8 data); |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 317 | |
| 318 | // system.c |
Kevin O'Connor | e791636 | 2008-12-28 22:03:17 -0500 | [diff] [blame] | 319 | extern u32 RamSize; |
| 320 | extern u64 RamSizeOver4G; |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 321 | void mathcp_setup(void); |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 322 | |
Kevin O'Connor | 913cc2e | 2008-04-13 17:31:45 -0400 | [diff] [blame] | 323 | // serial.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 324 | void serial_setup(void); |
| 325 | void lpt_setup(void); |
Kevin O'Connor | 913cc2e | 2008-04-13 17:31:45 -0400 | [diff] [blame] | 326 | |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 327 | // clock.c |
Kevin O'Connor | 991eaff | 2010-02-13 21:51:47 -0500 | [diff] [blame] | 328 | #define PIT_TICK_RATE 1193180 // Underlying HZ of PIT |
| 329 | #define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer |
Kevin O'Connor | 745de85 | 2012-01-29 14:15:14 -0500 | [diff] [blame^] | 330 | int check_tsc(u64 end); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 331 | void timer_setup(void); |
Kevin O'Connor | bc2aecd | 2008-11-28 16:40:06 -0500 | [diff] [blame] | 332 | void ndelay(u32 count); |
| 333 | void udelay(u32 count); |
| 334 | void mdelay(u32 count); |
Kevin O'Connor | 10ad799 | 2009-10-24 11:06:08 -0400 | [diff] [blame] | 335 | void nsleep(u32 count); |
| 336 | void usleep(u32 count); |
| 337 | void msleep(u32 count); |
Kevin O'Connor | 4e6c970 | 2008-12-13 10:45:50 -0500 | [diff] [blame] | 338 | u64 calc_future_tsc(u32 msecs); |
Kevin O'Connor | 1c46a54 | 2009-10-17 23:53:32 -0400 | [diff] [blame] | 339 | u64 calc_future_tsc_usec(u32 usecs); |
Kevin O'Connor | b5cc2ca | 2010-05-23 11:38:53 -0400 | [diff] [blame] | 340 | u32 calc_future_timer_ticks(u32 count); |
| 341 | u32 calc_future_timer(u32 msecs); |
| 342 | int check_timer(u32 end); |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 343 | void handle_1583(struct bregs *regs); |
Kevin O'Connor | 5be0490 | 2008-05-18 17:12:06 -0400 | [diff] [blame] | 344 | void handle_1586(struct bregs *regs); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 345 | void useRTC(void); |
| 346 | void releaseRTC(void); |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 347 | |
Kevin O'Connor | 95b2f78 | 2008-03-05 19:52:06 -0500 | [diff] [blame] | 348 | // apm.c |
Kevin O'Connor | 244caf8 | 2010-09-15 21:48:16 -0400 | [diff] [blame] | 349 | void apm_shutdown(void); |
Kevin O'Connor | c003148 | 2010-01-01 13:03:17 -0500 | [diff] [blame] | 350 | void handle_1553(struct bregs *regs); |
Kevin O'Connor | 95b2f78 | 2008-03-05 19:52:06 -0500 | [diff] [blame] | 351 | |
Kevin O'Connor | a0dc296 | 2008-03-16 14:29:32 -0400 | [diff] [blame] | 352 | // pcibios.c |
| 353 | void handle_1ab1(struct bregs *regs); |
Kevin O'Connor | 871e0a0 | 2009-12-30 12:14:53 -0500 | [diff] [blame] | 354 | void bios32_setup(void); |
Kevin O'Connor | a0dc296 | 2008-03-16 14:29:32 -0400 | [diff] [blame] | 355 | |
Kevin O'Connor | da4a648 | 2008-06-08 13:48:06 -0400 | [diff] [blame] | 356 | // shadow.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 357 | void make_bios_writable(void); |
| 358 | void make_bios_readonly(void); |
Kevin O'Connor | 244caf8 | 2010-09-15 21:48:16 -0400 | [diff] [blame] | 359 | void qemu_prep_reset(void); |
Kevin O'Connor | da4a648 | 2008-06-08 13:48:06 -0400 | [diff] [blame] | 360 | |
Kevin O'Connor | 0525d29 | 2008-07-04 06:18:30 -0400 | [diff] [blame] | 361 | // pciinit.c |
Kevin O'Connor | 0d6b8d5 | 2010-07-10 13:12:37 -0400 | [diff] [blame] | 362 | extern const u8 pci_irqs[4]; |
Kevin O'Connor | 40f5b5a | 2009-09-13 10:46:57 -0400 | [diff] [blame] | 363 | void pci_setup(void); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 364 | |
Kevin O'Connor | f7ba6d7 | 2008-07-04 05:05:54 -0400 | [diff] [blame] | 365 | // smm.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 366 | void smm_init(void); |
Kevin O'Connor | f7ba6d7 | 2008-07-04 05:05:54 -0400 | [diff] [blame] | 367 | |
Kevin O'Connor | e97ca7b | 2009-06-21 09:10:28 -0400 | [diff] [blame] | 368 | // smp.c |
Kevin O'Connor | 603bfc3 | 2009-06-22 20:04:56 -0400 | [diff] [blame] | 369 | extern u32 CountCPUs; |
Kevin O'Connor | 8470585 | 2009-10-08 22:13:15 -0400 | [diff] [blame] | 370 | extern u32 MaxCountCPUs; |
Kevin O'Connor | e97ca7b | 2009-06-21 09:10:28 -0400 | [diff] [blame] | 371 | void wrmsr_smp(u32 index, u64 val); |
| 372 | void smp_probe(void); |
Kevin O'Connor | 84ad59a | 2008-07-04 05:47:26 -0400 | [diff] [blame] | 373 | |
Kevin O'Connor | c781293 | 2008-06-08 23:08:12 -0400 | [diff] [blame] | 374 | // coreboot.c |
Kevin O'Connor | c1de91b | 2011-07-02 13:50:21 -0400 | [diff] [blame] | 375 | extern const char *CBvendor, *CBpart; |
Kevin O'Connor | 1edc89d | 2009-04-30 21:50:35 -0400 | [diff] [blame] | 376 | struct cbfs_file; |
Kevin O'Connor | e230426 | 2010-06-13 16:05:17 -0400 | [diff] [blame] | 377 | struct cbfs_file *cbfs_finddatafile(const char *fname); |
Kevin O'Connor | 1f83625 | 2009-08-16 20:17:35 -0400 | [diff] [blame] | 378 | struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last); |
Kevin O'Connor | 0088259 | 2009-08-18 22:21:10 -0400 | [diff] [blame] | 379 | u32 cbfs_datasize(struct cbfs_file *file); |
Kevin O'Connor | 1f83625 | 2009-08-16 20:17:35 -0400 | [diff] [blame] | 380 | const char *cbfs_filename(struct cbfs_file *file); |
Kevin O'Connor | 0088259 | 2009-08-18 22:21:10 -0400 | [diff] [blame] | 381 | int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen); |
Kevin O'Connor | 1f83625 | 2009-08-16 20:17:35 -0400 | [diff] [blame] | 382 | void cbfs_run_payload(struct cbfs_file *file); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 383 | void coreboot_copy_biostable(void); |
Kevin O'Connor | 89a1efd | 2011-01-08 12:24:39 -0500 | [diff] [blame] | 384 | void cbfs_payload_setup(void); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 385 | void coreboot_setup(void); |
Kevin O'Connor | c781293 | 2008-06-08 23:08:12 -0400 | [diff] [blame] | 386 | |
Ian Campbell | 1442c31 | 2011-06-01 11:00:28 +0100 | [diff] [blame] | 387 | // biostable.c |
| 388 | void copy_pir(void *pos); |
| 389 | void copy_mptable(void *pos); |
| 390 | void copy_acpi_rsdp(void *pos); |
Ian Campbell | 74c7878 | 2011-06-01 11:00:29 +0100 | [diff] [blame] | 391 | void copy_smbios(void *pos); |
Ian Campbell | 1442c31 | 2011-06-01 11:00:28 +0100 | [diff] [blame] | 392 | |
Kevin O'Connor | cbffa8e | 2008-08-17 11:11:07 -0400 | [diff] [blame] | 393 | // vgahooks.c |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 394 | void handle_155f(struct bregs *regs); |
Kevin O'Connor | c1de91b | 2011-07-02 13:50:21 -0400 | [diff] [blame] | 395 | struct pci_device; |
| 396 | void vgahook_setup(struct pci_device *pci); |
Kevin O'Connor | cbffa8e | 2008-08-17 11:11:07 -0400 | [diff] [blame] | 397 | |
Kevin O'Connor | 714325c | 2008-11-01 20:32:27 -0400 | [diff] [blame] | 398 | // optionroms.c |
Kevin O'Connor | 0a92412 | 2009-02-08 19:43:47 -0500 | [diff] [blame] | 399 | void call_bcv(u16 seg, u16 ip); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 400 | void optionrom_setup(void); |
| 401 | void vga_setup(void); |
| 402 | void s3_resume_vga_init(void); |
Kevin O'Connor | e773930 | 2009-07-26 19:16:09 -0400 | [diff] [blame] | 403 | extern u32 RomEnd; |
Kevin O'Connor | 422263d | 2011-07-05 20:56:07 -0400 | [diff] [blame] | 404 | extern int ScreenAndDebug; |
Kevin O'Connor | 714325c | 2008-11-01 20:32:27 -0400 | [diff] [blame] | 405 | |
Kevin O'Connor | afbed1b | 2010-06-28 07:34:53 -0400 | [diff] [blame] | 406 | // bootsplash.c |
| 407 | void enable_vga_console(void); |
Kevin O'Connor | 9a01a9c | 2010-08-25 21:07:48 -0400 | [diff] [blame] | 408 | void enable_bootsplash(void); |
Kevin O'Connor | afbed1b | 2010-06-28 07:34:53 -0400 | [diff] [blame] | 409 | void disable_bootsplash(void); |
| 410 | |
Kevin O'Connor | 18e38b2 | 2008-12-10 20:40:13 -0500 | [diff] [blame] | 411 | // resume.c |
Kevin O'Connor | 87b533b | 2011-07-10 22:35:07 -0400 | [diff] [blame] | 412 | extern int HaveRunPost; |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 413 | void init_dma(void); |
Kevin O'Connor | 18e38b2 | 2008-12-10 20:40:13 -0500 | [diff] [blame] | 414 | |
Kevin O'Connor | 0c3068d | 2008-12-21 17:51:36 -0500 | [diff] [blame] | 415 | // pnpbios.c |
| 416 | #define PNP_SIGNATURE 0x506e5024 // $PnP |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 417 | u16 get_pnp_offset(void); |
| 418 | void pnp_setup(void); |
Kevin O'Connor | 0c3068d | 2008-12-21 17:51:36 -0500 | [diff] [blame] | 419 | |
Kevin O'Connor | e54ee38 | 2009-07-26 19:33:13 -0400 | [diff] [blame] | 420 | // pmm.c |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 421 | extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 422 | void malloc_setup(void); |
Kevin O'Connor | 533b628 | 2011-07-16 13:13:12 -0400 | [diff] [blame] | 423 | void malloc_fixupreloc(void); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 424 | void malloc_finalize(void); |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 425 | void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align); |
| 426 | int pmm_free(void *data); |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 427 | void pmm_setup(void); |
| 428 | void pmm_finalize(void); |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 429 | #define PMM_DEFAULT_HANDLE 0xFFFFFFFF |
Kevin O'Connor | 0bf9270 | 2009-08-01 11:45:37 -0400 | [diff] [blame] | 430 | // Minimum alignment of malloc'd memory |
| 431 | #define MALLOC_MIN_ALIGN 16 |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 432 | // Helper functions for memory allocation. |
Kevin O'Connor | f416fe9 | 2009-09-24 20:51:55 -0400 | [diff] [blame] | 433 | static inline void *malloc_low(u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 434 | return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); |
Kevin O'Connor | f416fe9 | 2009-09-24 20:51:55 -0400 | [diff] [blame] | 435 | } |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 436 | static inline void *malloc_high(u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 437 | return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 438 | } |
| 439 | static inline void *malloc_fseg(u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 440 | return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 441 | } |
Kevin O'Connor | a576c9c | 2010-07-26 22:43:18 -0400 | [diff] [blame] | 442 | static inline void *malloc_tmplow(u32 size) { |
| 443 | return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); |
| 444 | } |
Kevin O'Connor | 114592f | 2009-09-28 21:32:08 -0400 | [diff] [blame] | 445 | static inline void *malloc_tmphigh(u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 446 | return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); |
Kevin O'Connor | 114592f | 2009-09-28 21:32:08 -0400 | [diff] [blame] | 447 | } |
Kevin O'Connor | 575ffc8 | 2010-02-21 23:20:10 -0500 | [diff] [blame] | 448 | static inline void *malloc_tmp(u32 size) { |
| 449 | void *ret = malloc_tmphigh(size); |
| 450 | if (ret) |
| 451 | return ret; |
Kevin O'Connor | a576c9c | 2010-07-26 22:43:18 -0400 | [diff] [blame] | 452 | return malloc_tmplow(size); |
Kevin O'Connor | 575ffc8 | 2010-02-21 23:20:10 -0500 | [diff] [blame] | 453 | } |
Kevin O'Connor | 9ed6b62 | 2009-10-07 21:41:08 -0400 | [diff] [blame] | 454 | static inline void *memalign_low(u32 align, u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 455 | return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align); |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 456 | } |
| 457 | static inline void *memalign_high(u32 align, u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 458 | return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align); |
Kevin O'Connor | 415d429 | 2009-08-30 19:19:31 -0400 | [diff] [blame] | 459 | } |
Kevin O'Connor | 12fa24a | 2010-09-15 00:25:32 -0400 | [diff] [blame] | 460 | static inline void *memalign_tmplow(u32 align, u32 size) { |
| 461 | return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, align); |
| 462 | } |
Kevin O'Connor | 9ed6b62 | 2009-10-07 21:41:08 -0400 | [diff] [blame] | 463 | static inline void *memalign_tmphigh(u32 align, u32 size) { |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 464 | return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align); |
| 465 | } |
Kevin O'Connor | 12fa24a | 2010-09-15 00:25:32 -0400 | [diff] [blame] | 466 | static inline void *memalign_tmp(u32 align, u32 size) { |
| 467 | void *ret = memalign_tmphigh(align, size); |
| 468 | if (ret) |
| 469 | return ret; |
| 470 | return memalign_tmplow(align, size); |
| 471 | } |
Kevin O'Connor | d948e2b | 2009-10-12 12:54:56 -0400 | [diff] [blame] | 472 | static inline void free(void *data) { |
| 473 | pmm_free(data); |
Kevin O'Connor | 9ed6b62 | 2009-10-07 21:41:08 -0400 | [diff] [blame] | 474 | } |
Kevin O'Connor | e54ee38 | 2009-07-26 19:33:13 -0400 | [diff] [blame] | 475 | |
Kevin O'Connor | 7061eb6 | 2009-01-04 21:48:22 -0500 | [diff] [blame] | 476 | // mtrr.c |
| 477 | void mtrr_setup(void); |
| 478 | |
Kevin O'Connor | 18e38b2 | 2008-12-10 20:40:13 -0500 | [diff] [blame] | 479 | // romlayout.S |
Kevin O'Connor | 1ca05b0 | 2010-01-03 17:43:37 -0500 | [diff] [blame] | 480 | void reset_vector(void) __noreturn; |
Kevin O'Connor | 18e38b2 | 2008-12-10 20:40:13 -0500 | [diff] [blame] | 481 | |
Kevin O'Connor | 3085376 | 2009-01-17 18:49:20 -0500 | [diff] [blame] | 482 | // misc.c |
| 483 | extern u8 BiosChecksum; |
| 484 | |
Kevin O'Connor | c95d2ce | 2009-07-29 20:41:39 -0400 | [diff] [blame] | 485 | // version (auto generated file out/version.c) |
| 486 | extern const char VERSION[]; |
| 487 | |
Kevin O'Connor | 786502d | 2008-02-27 10:41:41 -0500 | [diff] [blame] | 488 | #endif // util.h |