7 #define DEBUG_TO_SERIAL 1
8 #define SERIAL_PORT 0x3F8
9 #define GDB_SERIAL_PORT 0x2F8
13 extern int GetCPUNum(void);
14 extern void *Proc_GetCurThread(void);
17 int gbDebug_SerialSetup = 0;
18 int gbGDB_SerialSetup = 0;
21 int putDebugChar(char ch);
25 * \brief Determine if a short spinlock is locked
26 * \param Lock Lock pointer
28 int IS_LOCKED(struct sShortSpinlock *Lock)
34 * \brief Check if the current CPU has the lock
35 * \param Lock Lock pointer
37 int CPU_HAS_LOCK(struct sShortSpinlock *Lock)
39 #if STACKED_LOCKS == 1
40 return Lock->Lock == GetCPUNum() + 1;
41 #elif STACKED_LOCKS == 2
42 return Lock->Lock == Proc_GetCurThread();
49 * \brief Acquire a Short Spinlock
50 * \param Lock Lock pointer
52 * This type of mutex should only be used for very short sections of code,
53 * or in places where a Mutex_* would be overkill, such as appending
54 * an element to linked list (usually two assignement lines in C)
56 * \note This type of lock halts interrupts, so ensure that no timing
57 * functions are called while it is held. As a matter of fact, spend as
58 * little time as possible with this lock held
59 * \note If \a STACKED_LOCKS is set, this type of spinlock can be nested
61 void SHORTLOCK(struct sShortSpinlock *Lock)
67 #if STACKED_LOCKS == 1
68 int cpu = GetCPUNum() + 1;
69 #elif STACKED_LOCKS == 2
70 void *thread = Proc_GetCurThread();
74 // Save interrupt state and clear interrupts
75 __ASM__ ("pushf;\n\tpop %0" : "=r"(IF));
76 IF &= 0x200; // AND out all but the interrupt flag
79 #if STACKED_LOCKS == 1
80 if( Lock->Lock == cpu ) {
84 #elif STACKED_LOCKS == 2
85 if( Lock->Lock == thread ) {
91 // Wait for another CPU to release
94 // If r/m32 == EAX, set ZF and set r/m32 = r32
95 // Else, clear ZF and set EAX = r/m32
96 #if STACKED_LOCKS == 1
97 __ASM__("lock cmpxchgl %2, (%3)"
99 : "a"(0), "r"(cpu), "r"(&Lock->Lock)
101 #elif STACKED_LOCKS == 2
102 __ASM__("lock cmpxchgq %2, (%3)"
104 : "a"(0), "r"(thread), "r"(&Lock->Lock)
107 __ASM__("xchgl %0, (%2)":"=a"(v):"a"(1),"D"(&Lock->Lock));
110 #if LOCK_DISABLE_INTS
111 if( v ) __ASM__("sti"); // Re-enable interrupts
115 #if LOCK_DISABLE_INTS
121 * \brief Release a short lock
122 * \param Lock Lock pointer
124 void SHORTREL(struct sShortSpinlock *Lock)
133 #if LOCK_DISABLE_INTS
134 // Lock->IF can change anytime once Lock->Lock is zeroed
149 int putDebugChar(char ch)
151 if(!gbGDB_SerialSetup) {
152 outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
153 outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
154 outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
155 outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte)
156 outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1)
157 outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
158 outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
159 gbDebug_SerialSetup = 1;
161 while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
162 outb(GDB_SERIAL_PORT, ch);
165 int getDebugChar(void)
167 if(!gbGDB_SerialSetup) {
168 outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
169 outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
170 outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
171 outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
172 outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
173 outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
174 outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
175 gbDebug_SerialSetup = 1;
177 while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ;
178 return inb(GDB_SERIAL_PORT);
182 void Debug_PutCharDebug(char ch)
185 __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
189 if(!gbDebug_SerialSetup) {
190 outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
191 outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
192 outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
193 outb(SERIAL_PORT + 1, 0x00); // (hi byte)
194 outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
195 outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
196 outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
197 gbDebug_SerialSetup = 1;
199 while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
200 outb(SERIAL_PORT, ch);
204 void Debug_PutStringDebug(const char *String)
207 Debug_PutCharDebug(*String++);
211 void outb(Uint16 Port, Uint8 Data)
213 __asm__ __volatile__ ("outb %%al, %%dx"::"d"(Port),"a"(Data));
215 void outw(Uint16 Port, Uint16 Data)
217 __asm__ __volatile__ ("outw %%ax, %%dx"::"d"(Port),"a"(Data));
219 void outd(Uint16 Port, Uint32 Data)
221 __asm__ __volatile__ ("outl %%eax, %%dx"::"d"(Port),"a"(Data));
223 Uint8 inb(Uint16 Port)
226 __asm__ __volatile__ ("inb %%dx, %%al":"=a"(ret):"d"(Port));
229 Uint16 inw(Uint16 Port)
232 __asm__ __volatile__ ("inw %%dx, %%ax":"=a"(ret):"d"(Port));
235 Uint32 ind(Uint16 Port)
238 __asm__ __volatile__ ("inl %%dx, %%eax":"=a"(ret):"d"(Port));
242 // === Endianness ===
244 Uint32 BigEndian32(Uint32 Value)
248 ret |= ((Value >> 16) & 0xFF) << 8;
249 ret |= ((Value >> 8) & 0xFF) << 16;
250 ret |= ((Value >> 0) & 0xFF) << 24;
254 Uint16 BigEndian16(Uint16 Value)
256 return (Value>>8)|(Value<<8);
260 // === Memory Manipulation ===
261 int memcmp(const void *__dest, const void *__src, size_t __count)
263 if( ((tVAddr)__dest & 7) != ((tVAddr)__src & 7) ) {
264 const Uint8 *src = __src, *dst = __dest;
269 src ++; dst ++; __count --;
274 const Uint8 *src = __src;
275 const Uint8 *dst = __dest;
276 const Uint64 *src64, *dst64;
278 while( (tVAddr)src & 7 && __count ) {
281 dst ++; src ++; __count --;
287 while( __count >= 8 )
289 if( *src64 != *dst64 )
293 if(src[0] != dst[0]) return dst[0]-src[0];
294 if(src[1] != dst[1]) return dst[1]-src[1];
295 if(src[2] != dst[2]) return dst[2]-src[2];
296 if(src[3] != dst[3]) return dst[3]-src[3];
297 if(src[4] != dst[4]) return dst[4]-src[4];
298 if(src[5] != dst[5]) return dst[5]-src[5];
299 if(src[6] != dst[6]) return dst[6]-src[6];
300 if(src[7] != dst[7]) return dst[7]-src[7];
301 return -1; // This should never happen
312 if(*dst != *src) return *dst - *src;
320 void *memcpy(void *__dest, const void *__src, size_t __count)
322 tVAddr dst = (tVAddr)__dest, src = (tVAddr)__src;
323 if( (dst & 7) != (src & 7) )
325 __asm__ __volatile__ ("rep movsb" : : "D"(dst),"S"(src),"c"(__count));
329 while( (src & 7) && __count ) {
330 *(char*)dst++ = *(char*)src++;
334 __asm__ __volatile__ ("rep movsq" : "=D"(dst),"=S"(src) : "0"(dst),"1"(src),"c"(__count/8));
335 __count = __count & 7;
337 *(char*)dst++ = *(char*)src++;
342 void *memset(void *__dest, int __val, size_t __count)
344 if( __val != 0 || ((tVAddr)__dest & 7) != 0 )
345 __asm__ __volatile__ ("rep stosb" : : "D"(__dest),"a"(__val),"c"(__count));
349 __asm__ __volatile__ ("rep stosq" : : "D"(dst),"a"(0),"c"(__count/8));
351 __count = __count & 7;
358 void *memsetd(void *__dest, Uint32 __val, size_t __count)
360 __asm__ __volatile__ ("rep stosl" : : "D"(__dest),"a"(__val),"c"(__count));
364 Uint64 DivMod64U(Uint64 Num, Uint64 Den, Uint64 *Rem)
367 __asm__ __volatile__(
369 : "=a" (ret), "=d" (rem)
370 : "a" ( Num ), "d" (0), "r" (Den)