//Functions.c //05/07/03 Josh Holtrop //for HOS //Modified: 10/30/03 //Writes a byte out to a port inline void outportb(unsigned int port, unsigned char value) // Output a byte to a port { asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value)); }; //Writes a word out to a port inline void outportw(unsigned int port, unsigned int value) // Output a word to a port { asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value)); }; //Reads a byte from a port inline byte inportb(unsigned short port) { unsigned char ret_val; asm volatile("inb %w1,%b0" : "=a"(ret_val) : "d"(port)); return ret_val; }; //Enables (SeTs) Interrupt Flag on the processor inline void enable_ints() { asm("sti"); }; //Disables (CLears) Interrupt Flag on the processor inline void disable_ints() { asm("cli"); }; char *strcat(char *dest, char *src) { strcpy(dest+strlen(dest), src); } //converts a binary-coded-decimal byte to its decimal equivalent inline byte bcd2byte(byte bcd) { return (10* ((bcd & 0xF0) >> 4)) + (bcd & 0x0F); } //converts a binary-coded-decimal byte to its decimal equivalent inline byte byte2bcd(byte bite) { return ((bite / 10) << 4) | (bite % 10); } void rtrim(char *str) { str += strlen(str); //now points to the null character at the end of the string str--; for (;;) { if ((*str == ' ') || (*str == '\t') || (*str == '\n')) *str-- = 0; else break; } } char *ucase(char *str) { char *ret = str; for (;;) { if (*str == 0) break; if ((*str >= 'a') && (*str <= 'z')) *str = (*str) - 32; str++; } return ret; } char *lcase(char *str) { char *ret = str; for (;;) { if (*str == 0) break; if ((*str >= 'A') && (*str <= 'Z')) *str = (*str) + 32; str++; } return ret; } //Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address void remap_pics(int pic1, int pic2) { byte a1, a2; a1 = inportb(PIC1_DATA); //0x21 a2 = inportb(PIC2_DATA); //0xA1 outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); //0x20, 0x10+0x01 00010001b outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); //0xA0, 0x10+0x01 00010001b outportb(PIC1_DATA, pic1); //0x21, pic1 outportb(PIC2_DATA, pic2); //0xA1, pic2 outportb(PIC1_DATA, 4); //0x21, 0x04 00000100b outportb(PIC2_DATA, 2); //0xA1, 0x02 00000010b outportb(PIC1_DATA, ICW4_8086); //0x21, 0x01 00000001b outportb(PIC2_DATA, ICW4_8086); //0xA1, 0x01 00000001b outportb(PIC1_DATA, a1); //0x21 outportb(PIC2_DATA, a2); //0xA1 } //Masks interrupts on first Programmable Interrupt Controller inline void pic1_mask(byte mask) { outportb(PIC1_DATA, mask); //0x21, maskfield *OCW1* } //Masks interrupts on second Programmable Interrupt Controller inline void pic2_mask(byte mask) { outportb(PIC2_DATA, mask); //0xA1, maskfield *OCW1* } //Restarts the computer inline void restart() { enable_ints(); byte temp; do { temp = inportb(0x64); if (temp & 1) inportb(0x60); } while(temp & 2); outportb (0x64, 0xfe); for (;;) { } } //Halts (freezes) the computer inline void halt() { asm("cli"); asm("hlt"); while (1) ; } //Initializes 8253 Programmable Interrupt Timer inline void init_timer() { //set timer : 2e9c = 100hz outportb(0x43, 0x34); outportb(0x40, 0x9c); //lsb outportb(0x40, 0x2e); //msb } //Signals an End Of Interrupt signal to the first PIC inline void eoi() { outportb(0x20, 0x20); } //Signals an End Of Interrupt signal to both the second and first PIC unit inline void eoi2() { outportb(0xA0, 0x20); outportb(0x20, 0x20); } //Returns the size of the kernel (code & data) // - this does not include the bss section // - this should be 4kb aligned per the linker script // - this should be the size of kernel.bin inline dword kernel_size() { return (dword)(&_bss)-(dword)(&_code); } //These functions are for reading and writing various values stored on the CMOS Real Time Clock byte rtc_readDay() { outportb(0x70, 7); return bcd2byte(inportb(0x71)); } byte rtc_readMonth() { outportb(0x70, 8); return bcd2byte(inportb(0x71)); } byte rtc_readYear() { outportb(0x70, 9); return bcd2byte(inportb(0x71)); } byte rtc_readSecond() { outportb(0x70, 0); return bcd2byte(inportb(0x71)); } byte rtc_readMinute() { outportb(0x70, 2); return bcd2byte(inportb(0x71)); } byte rtc_readHour() { outportb(0x70, 4); return bcd2byte(inportb(0x71)); } void rtc_setDay(byte day) { outportb(0x70, 7); outportb(0x71, byte2bcd(day)); } void rtc_setMonth(byte month) { outportb(0x70, 8); outportb(0x71, byte2bcd(month)); } void rtc_setYear(byte year) { outportb(0x70, 9); outportb(0x71, byte2bcd(year)); } void rtc_setSecond(byte second) { outportb(0x70, 0); outportb(0x71, byte2bcd(second)); } void rtc_setMinute(byte minute) { outportb(0x70, 2); outportb(0x71, byte2bcd(minute)); } void rtc_setHour(byte hour) { outportb(0x70, 4); outportb(0x71, byte2bcd(hour)); }