/* vim: tabstop=4 shiftwidth=4 noexpandtab * * System Functions * * Part of the ToAru OS Kernel * (C) 2011 Kevin Lange * Released under the terms of the NCSA License, see the included * README file for further information. */ #include unsigned int __irq_sem = 0; void spin_lock(uint8_t volatile * lock) { while(__sync_lock_test_and_set(lock, 0x01)) { switch_task(); } } void spin_unlock(uint8_t volatile * lock) { __sync_lock_release(lock); } /* * memcpy * Copy from source to destination. Assumes that * source and destination are not overlapping. */ void * memcpy( void * restrict dest, const void * restrict src, size_t count ) { asm volatile ("cld; rep movsb" : "+c" (count), "+S" (src), "+D" (dest) :: "memory"); return dest; } int max(int a, int b) { return (a > b) ? a : b; } int min(int a, int b) { return (a > b) ? b : a; } int abs(int a) { return (a >= 0) ? a : -a; } void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } void * memmove( void * restrict dest, const void * restrict src, size_t count ) { size_t i; unsigned char *a = dest; const unsigned char *b = src; if (src < dest) { for ( i = count; i > 0; --i) { a[i-1] = b[i-1]; } } else { for ( i = 0; i < count; ++i) { a[i] = b[i]; } } return dest; } int strcmp( const char * a, const char * b ) { uint32_t i = 0; while (1) { if (a[i] < b[i]) { return -1; } else if (a[i] > b[i]) { return 1; } else { if (a[i] == '\0') { return 0; } ++i; } } } /* * memset * Set `count` bytes to `val`. */ void * memset( void *b, int val, size_t count ) { asm volatile ("cld; rep stosb" : "+c" (count), "+D" (b) : "a" (val) : "memory"); return b; } /* * memsetw * Set `count` shorts to `val`. */ unsigned short * memsetw( unsigned short *dest, unsigned short val, int count ) { int i; i = 0; for ( ; i < count; ++i ) { dest[i] = val; } return dest; } /* * strlen * Returns the length of a given `str`. */ uint32_t strlen( const char *str ) { int i = 0; while (str[i] != (char)0) { ++i; } return i; } uint32_t __attribute__ ((pure)) krand() { static uint32_t x = 123456789; static uint32_t y = 362436069; static uint32_t z = 521288629; static uint32_t w = 88675123; uint32_t t; t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ t ^ (t >> 8); } /* * atoi * Naïve implementation thereof. */ int atoi( const char *str ) { uint32_t len = strlen(str); uint32_t out = 0; uint32_t i; uint32_t pow = 1; for (i = len; i > 0; --i) { out += (str[i-1] - 48) * pow; pow *= 10; } return out; } unsigned short inports( unsigned short _port ) { unsigned short rv; asm volatile ("inw %1, %0" : "=a" (rv) : "dN" (_port)); return rv; } void outports( unsigned short _port, unsigned short _data ) { asm volatile ("outw %1, %0" : : "dN" (_port), "a" (_data)); } unsigned int inportl( unsigned short _port ) { unsigned short rv; asm volatile ("inl %%dx, %%eax" : "=a" (rv) : "dN" (_port)); return rv; } void outportl( unsigned short _port, unsigned int _data ) { asm volatile ("outl %%eax, %%dx" : : "dN" (_port), "a" (_data)); } /* * inportb * Read from an I/O port. */ unsigned char inportb( unsigned short _port ) { unsigned char rv; asm volatile ("inb %1, %0" : "=a" (rv) : "dN" (_port)); return rv; } /* * outportb * Write to an I/O port. */ void outportb( unsigned short _port, unsigned char _data ) { asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data)); } /* * Output multiple sets of shorts */ void outportsm( unsigned short port, unsigned char * data, unsigned long size ) { asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port)); } /* * Input multiple sets of shorts */ void inportsm( unsigned short port, unsigned char * data, unsigned long size ) { asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory"); } char * strtok_r( char * str, const char * delim, char ** saveptr ) { char * token; if (str == NULL) { str = *saveptr; } str += strspn(str, delim); if (*str == '\0') { *saveptr = str; return NULL; } token = str; str = strpbrk(token, delim); if (str == NULL) { *saveptr = (char *)lfind(token, '\0'); } else { *str = '\0'; *saveptr = str + 1; } return token; } size_t lfind( const char * str, const char accept ) { size_t i = 0; while ( str[i] != accept) { i++; } return (size_t)(str) + i; } size_t rfind( const char * str, const char accept ) { size_t i = strlen(str) - 1; while (str[i] != accept) { if (i == 0) return UINT32_MAX; i--; } return (size_t)(str) + i; } char * strstr(const char * haystack, const char * needle) { const char * out = NULL; const char * ptr; const char * acc; const char * p; size_t s = strlen(needle); for (ptr = haystack; *ptr != '\0'; ++ptr) { size_t accept = 0; out = ptr; p = ptr; for (acc = needle; (*acc != '\0') && (*p != '\0'); ++acc) { if (*p == *acc) { accept++; p++; } else { break; } } if (accept == s) { return (char *)out; } } return NULL; } uint8_t startswith(const char * str, const char * accept) { size_t s = strlen(accept); for (size_t i = 0; i < s; ++i) { if (*str != *accept) return 0; str++; accept++; } return 1; } size_t strspn( const char * str, const char * accept ) { const char * ptr; const char * acc; size_t size = 0; for (ptr = str; *ptr != '\0'; ++ptr) { for (acc = accept; *acc != '\0'; ++acc) { if (*ptr == *acc) { break; } } if (*acc == '\0') { return size; } else { ++size; } } return size; } char * strpbrk( const char * str, const char * accept ) { while (*str != '\0') { const char *acc = accept; while (*acc != '\0') { if (*acc++ == *str) { return (char *) str; } } ++str; } return NULL; } void real_mode_int(int num, struct regs * r) { /* Give non-kernel access to the first 1MB of RAM */ for (uintptr_t i = 0; i < 0x00100000; i += 0x1000) { alloc_frame(get_page(i, 1, kernel_directory), 0, 1); } /* Reset protection on first 1MB of RAM when we're done */ for (uintptr_t i = 0; i < 0x00100000; i += 0x1000) { alloc_frame(get_page(i, 1, kernel_directory), 1, 0); } }