From 98d45a155c3ce437d0eddb67b9eb2b203f87ec3b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 30 Jul 2011 16:31:35 +0800 Subject: [PATCH] Kernel - Bugfixing x86_64 port - Switched to using the PIT for timekeeping - Fixed multiple IRQ errors --- Kernel/arch/x86_64/desctab.asm | 21 +++++++----- Kernel/arch/x86_64/proc.c | 13 +++++--- Kernel/arch/x86_64/time.c | 58 ++++++---------------------------- Kernel/debug.c | 2 +- Kernel/time.c | 4 +-- Modules/Storage/ATA/io.c | 3 +- Modules/Storage/FDD/fdd.c | 43 ++++++++++++++++++------- Modules/x86/VGAText/vga.c | 20 +++++++++--- 8 files changed, 84 insertions(+), 80 deletions(-) diff --git a/Kernel/arch/x86_64/desctab.asm b/Kernel/arch/x86_64/desctab.asm index 7ad93eb7..8212773b 100644 --- a/Kernel/arch/x86_64/desctab.asm +++ b/Kernel/arch/x86_64/desctab.asm @@ -154,6 +154,7 @@ IRQ_AddHandler: ; RDI - IRQ Number ; RSI - Callback + ; Check for RDI >= 16 cmp rdi, 16 jb .numOK xor rax, rax @@ -161,10 +162,10 @@ IRQ_AddHandler: jmp .ret .numOK: - mov rax, rdi - shr rax, 3+2 + ; Get handler base into RAX + lea rax, [rdi*4] mov rcx, gaIRQ_Handlers - add rax, rcx + lea rax, [rcx+rax*8] ; Find a free callback slot %rep NUM_IRQ_CALLBACKS @@ -196,6 +197,7 @@ IRQ_AddHandler: pop rsi pop rdi + ; Assign and return mov [rax], rsi xor rax, rax @@ -292,12 +294,14 @@ IrqCommon: push gs push fs - mov rbx, [rsp+(16+2)*8] ; Calculate address - shr rbx, 3+2 ; *8*4 + mov rbx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs) +; xchg bx, bx ; Bochs Magic break (NOTE: will clear the high-bits of RBX) + shl rbx, 2 ; *8*4 mov rax, gaIRQ_Handlers - add rbx, rax + lea rbx, [rax+rbx*8] ; Check all callbacks + sub rsp, 8 ; Shadow of argument %assign i 0 %rep NUM_IRQ_CALLBACKS ; Get callback address @@ -305,17 +309,18 @@ IrqCommon: test rax, rax ; Check if it exists jz .skip.%[i] ; Set RDI to IRQ number - mov rdi, [rsp+16*8] ; Get IRQ number + mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number call rax ; Call .skip.%[i]: add rbx, 8 ; Next! %assign i i+1 %endrep + add rsp, 8 ; ACK + mov al, 0x20 mov rdi, [rsp+16*8] ; Get IRQ number cmp rdi, 8 - mov al, 0x20 jb .skipAckSecondary mov dx, 0x00A0 out dx, al diff --git a/Kernel/arch/x86_64/proc.c b/Kernel/arch/x86_64/proc.c index f2abb289..8691100c 100644 --- a/Kernel/arch/x86_64/proc.c +++ b/Kernel/arch/x86_64/proc.c @@ -12,14 +12,13 @@ #if USE_MP # include #endif +#include // === FLAGS === #define DEBUG_TRACE_SWITCH 0 // === CONSTANTS === #define SWITCH_MAGIC 0x55ECAFFF##FFFACE55 // There is no code in this area -// Base is 1193182 -#define TIMER_DIVISOR 11931 //~100Hz // === TYPES === typedef struct sCPU @@ -46,6 +45,7 @@ extern tThread gThreadZero; extern void Threads_Dump(void); extern void Proc_ReturnToUser(void); extern int GetCPUNum(void); +extern void Time_UpdateTimestamp(void); // === PROTOTYPES === void ArchThreads_Init(void); @@ -304,8 +304,8 @@ void ArchThreads_Init(void) // Set timer frequency outb(0x43, 0x34); // Set Channel 0, Low/High, Rate Generator - outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor - outb(0x40, (TIMER_DIVISOR>>8)&0xFF); // High Byte + outb(0x40, PIT_TIMER_DIVISOR&0xFF); // Low Byte of Divisor + outb(0x40, (PIT_TIMER_DIVISOR>>8)&0xFF); // High Byte // Create Per-Process Data Block if( !MM_Allocate(MM_PPD_CFG) ) @@ -541,6 +541,7 @@ int Proc_Clone(Uint *Err, Uint Flags) rip = GetRIP(); if(rip == SWITCH_MAGIC) { outb(0x20, 0x20); // ACK Timer and return as child + __asm__ __volatile__ ("sti"); return 0; } @@ -589,6 +590,7 @@ int Proc_SpawnWorker(void) rip = GetRIP(); if(rip == SWITCH_MAGIC) { outb(0x20, 0x20); // ACK Timer and return as child + __asm__ __volatile__ ("sti"); return 0; } @@ -753,6 +755,9 @@ void Proc_Scheduler(int CPU) { Uint rsp, rbp, rip; tThread *thread; + + if( CPU == 0 ) + Time_UpdateTimestamp(); // If the spinlock is set, let it complete if(IS_LOCKED(&glThreadListLock)) return; diff --git a/Kernel/arch/x86_64/time.c b/Kernel/arch/x86_64/time.c index 6153db23..03c889fe 100644 --- a/Kernel/arch/x86_64/time.c +++ b/Kernel/arch/x86_64/time.c @@ -4,18 +4,13 @@ * arch/x86_64/time.c */ #include +#include // === MACROS === #define TIMER_QUANTUM 100 -// 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz -// (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2 = 8192Hz -//#define TIMER_RATE 10 // 32 Hz -//#define TIMER_RATE 12 // 8 Hz -#define TIMER_RATE 14 // 2Hz -//#define TIMER_RATE 15 // 1HZ -#define TIMER_FREQ (0x8000>>TIMER_RATE) //Hz -#define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ)) -#define MS_PER_TICK_FRACT ((0x80000000*(1000%TIMER_FREQ))/TIMER_FREQ) +#define TIMER_FREQ PIT_TIMER_BASE_N/(PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR) +#define MS_PER_TICK_WHOLE (1000*(PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR)/PIT_TIMER_BASE_N) +#define MS_PER_TICK_FRACT ((0x80000000ULL*1000ULL*PIT_TIMER_BASE_D*PIT_TIMER_DIVISOR/PIT_TIMER_BASE_N)&0x7FFFFFFF) // === IMPORTS === extern volatile Sint64 giTimestamp; @@ -30,7 +25,7 @@ volatile Uint64 giTime_TSCPerTick = 0; // === PROTOTYPES === //Sint64 now(void); int Time_Setup(void); -void Time_Interrupt(int); +void Time_UpdateTimestamp(void); Uint64 Time_ReadTSC(void); // === CODE === @@ -57,48 +52,19 @@ Sint64 now(void) */ int Time_Setup(void) { - Uint8 val; - - Log_Log("Timer", "RTC Timer firing at %iHz (%i divisor), %i.0x%08x", - TIMER_FREQ, TIMER_RATE, MS_PER_TICK_WHOLE, MS_PER_TICK_FRACT); - - outb(0x70, inb(0x70)&0x7F); // Disable NMIs - __asm__ __volatile__ ("cli"); // Disable normal interrupts - - // Set IRQ8 firing rate - outb(0x70, 0x0A); // Set the index to register A - val = inb(0x71); // Get the current value of register A - outb(0x70, 0x0A); // Reset index to A - val &= 0xF0; - val |= TIMER_RATE; - outb(0x71, val); // Update the timer rate - - // Enable IRQ8 - outb(0x70, 0x0B); // Set the index to register B - val = inb(0x71); // Read the current value of register B - outb(0x70, 0x0B); // Set the index again (a read will reset the index to register D) - outb(0x71, val | 0x40); // Write the previous value or'd with 0x40. This turns on bit 6 of register D - - __asm__ __volatile__ ("sti"); // Re-enable normal interrupts - outb(0x70, inb(0x70)|0x80); // Re-enable NMIs - - // Install IRQ Handler - IRQ_AddHandler(8, Time_Interrupt); - - // Make sure the RTC actually fires - outb(0x70, 0x0C); // Select register C - inb(0x71); // Just throw away contents. + Log_Log("Timer", "PIT Timer firing at %iHz, %i.0x%08x miliseconds per tick", + TIMER_FREQ, MS_PER_TICK_WHOLE, MS_PER_TICK_FRACT); + + // TODO: Read time from RTC return 0; } /** * \brief Called on the timekeeping IRQ - * \param irq IRQ number (unused) */ -void Time_Interrupt(int irq) +void Time_UpdateTimestamp(void) { - //Log("RTC Tick"); Uint64 curTSC = Time_ReadTSC(); if( giTime_TSCAtLastTick ) @@ -116,10 +82,6 @@ void Time_Interrupt(int irq) } Timer_CallTimers(); - - // Make sure the RTC Fires again - outb(0x70, 0x0C); // Select register C - inb(0x71); // Just throw away contents. } #if 0 diff --git a/Kernel/debug.c b/Kernel/debug.c index 3e5ac0a9..76ed7cfb 100644 --- a/Kernel/debug.c +++ b/Kernel/debug.c @@ -12,7 +12,7 @@ #define LOCK_DEBUG_OUTPUT 1 // === IMPORTS === -extern void Threads_Dump(void); +extern void Threads_Dump(void); extern void KernelPanic_SetMode(void); extern void KernelPanic_PutChar(char Ch); diff --git a/Kernel/time.c b/Kernel/time.c index 1180cad9..3d06b0e7 100644 --- a/Kernel/time.c +++ b/Kernel/time.c @@ -84,9 +84,9 @@ void Time_RemoveTimer(int ID) */ void Time_Delay(int Delay) { - Sint64 dest = giTimestamp + Delay; + Sint64 dest = now() + Delay; //Log("Time_Delay: dest = %lli", dest); - while(dest > giTimestamp) Threads_Yield(); + while(dest > now()) Threads_Yield(); //Log("Time_Delay: giTimestamp = %lli", giTimestamp); } diff --git a/Modules/Storage/ATA/io.c b/Modules/Storage/ATA/io.c index 368c310b..de6bf96b 100644 --- a/Modules/Storage/ATA/io.c +++ b/Modules/Storage/ATA/io.c @@ -353,7 +353,8 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) // HACK: Ensure the PRDT is reset ATA_int_BusMasterWriteDWord(cont*8+4, gaATA_PRDT_PAddrs[cont]); - + ATA_int_BusMasterWriteByte(cont*8, 4); // Reset IRQ + LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes); if( Address > 0x0FFFFFFF ) outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) diff --git a/Modules/Storage/FDD/fdd.c b/Modules/Storage/FDD/fdd.c index f83a0063..801f2eb7 100644 --- a/Modules/Storage/FDD/fdd.c +++ b/Modules/Storage/FDD/fdd.c @@ -114,6 +114,7 @@ void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl); int FDD_int_GetByte(int base, Uint8 *Byte); int FDD_Reset(int id); void FDD_Recalibrate(int disk); + int FDD_Reconfigure(int ID); int FDD_int_SeekTrack(int disk, int head, int track); void FDD_int_TimerCallback(void *Arg); void FDD_int_StopMotor(void *Arg); @@ -172,6 +173,21 @@ int FDD_Install(char **Arguments) // Install IRQ6 Handler IRQ_AddHandler(6, FDD_IRQHandler); + + // Ensure the FDD version is 0x90 + { + Uint8 tmp; + FDD_int_SendByte(cPORTBASE[0], CMD_VERSION); + FDD_int_GetByte(cPORTBASE[0], &tmp); + if( tmp != 0x90 ) { + Log_Error("FDD", "Version(0x%2x) != 0x90", tmp); + return MODULE_ERR_NOTNEEDED; + } + } + + // Configure + FDD_Reconfigure(0); + // Reset Primary FDD Controller if( FDD_Reset(0) != 0 ) { return MODULE_ERR_MISC; @@ -591,7 +607,8 @@ int FDD_int_SeekTrack(int disk, int head, int track) // Set Track in structure gFDD_Devices[disk].track[head] = track; - + + LOG("Time_Delay(100)"); // Wait for Head to settle Time_Delay(100); @@ -793,38 +810,42 @@ int FDD_Reset(int id) outb(base + PORT_DIGOUTPUT, 0); // Disable FDC // Wait 4 microseconds - or use 1 thread delay Threads_Yield(); - outb(base + PORT_DIGOUTPUT, 0x0C); // Re-enable FDC (DMA and Enable) + Threads_Yield(); + outb(base + PORT_DIGOUTPUT, 8|4); // Re-enable FDC (DMA and Enable) + // Set the data rate + outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s + + // Wait for IRQ LOG("Awaiting IRQ"); FDD_WaitIRQ(); + LOG("4x SenseInterrupt"); FDD_SensInt(base, NULL, NULL); FDD_SensInt(base, NULL, NULL); FDD_SensInt(base, NULL, NULL); FDD_SensInt(base, NULL, NULL); - // Set the data rate - outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s - - // Configure + // Specify FDD_int_SendByte(base, CMD_SPECIFY); // Step and Head Load Times FDD_int_SendByte(base, 0xDF); // Step Rate Time, Head Unload Time (Nibble each) FDD_int_SendByte(base, 0x02); // Head Load Time >> 1 + // Recalibrate disks + LOG("Recalibrate disks (16x seek)"); retries = 16; while(FDD_int_SeekTrack(0, 0, 1) == 0 && retries --); // set track - if(retries < 0) return -1; + if(retries < 0) LEAVE_RET('i', -1); retries = 16; - while(FDD_int_SeekTrack(0, 1, 1) == 0); // set track - if(retries < 0) return -1; + while(FDD_int_SeekTrack(0, 1, 1) == 0 && retries --); // set track + if(retries < 0) LEAVE_RET('i', -1); LOG("Recalibrating Disk"); FDD_Recalibrate((id<<1)|0); FDD_Recalibrate((id<<1)|1); - LEAVE('i',0); - return 0; + LEAVE_RET('i', 0); } /** diff --git a/Modules/x86/VGAText/vga.c b/Modules/x86/VGAText/vga.c index 9fa9fd21..e9263130 100644 --- a/Modules/x86/VGAText/vga.c +++ b/Modules/x86/VGAText/vga.c @@ -246,18 +246,20 @@ void VGA_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colou Y /= giVT_CharHeight; H /= giVT_CharHeight; - if( X > VGA_WIDTH || Y > VGA_HEIGHT ) return ; - if( X + W > VGA_WIDTH ) W = VGA_WIDTH - X; - if( Y + H > VGA_HEIGHT ) H = VGA_HEIGHT - Y; - ch.Ch = 0x20; ch.BGCol = (Colour & 0x0F0000) >> (16-8); ch.BGCol |= (Colour & 0x000F00) >> (8-4); ch.BGCol |= (Colour & 0x00000F); + word = VGA_int_GetWord(&ch); + + Log("Fill (%i,%i) %ix%i with 0x%x", X, Y, W, H, word); + + if( X > VGA_WIDTH || Y > VGA_HEIGHT ) return ; + if( X + W > VGA_WIDTH ) W = VGA_WIDTH - X; + if( Y + H > VGA_HEIGHT ) H = VGA_HEIGHT - Y; buf = gVGA_Framebuffer + Y*VGA_WIDTH + X; - word = VGA_int_GetWord(&ch); while( H -- ) { int i; @@ -281,6 +283,14 @@ void VGA_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, // Log("(%i,%i) from (%i,%i) %ix%i", DstX, DstY, SrcX, SrcY, W, H); + if( SrcX > VGA_WIDTH || SrcY > VGA_HEIGHT ) return ; + if( SrcX + W > VGA_WIDTH ) W = VGA_WIDTH - SrcX; + if( SrcY + H > VGA_HEIGHT ) H = VGA_HEIGHT - SrcY; + if( DstX > VGA_WIDTH || DstY > VGA_HEIGHT ) return ; + if( DstX + W > VGA_WIDTH ) W = VGA_WIDTH - DstX; + if( DstY + H > VGA_HEIGHT ) H = VGA_HEIGHT - DstY; + + src = gVGA_Framebuffer + SrcY*VGA_WIDTH + SrcX; dst = gVGA_Framebuffer + DstY*VGA_WIDTH + DstX; -- 2.20.1