Kernel - Bugfixing x86_64 port
authorJohn Hodge <[email protected]>
Sat, 30 Jul 2011 08:31:35 +0000 (16:31 +0800)
committerJohn Hodge <[email protected]>
Sat, 30 Jul 2011 08:31:35 +0000 (16:31 +0800)
- Switched to using the PIT for timekeeping
- Fixed multiple IRQ errors

Kernel/arch/x86_64/desctab.asm
Kernel/arch/x86_64/proc.c
Kernel/arch/x86_64/time.c
Kernel/debug.c
Kernel/time.c
Modules/Storage/ATA/io.c
Modules/Storage/FDD/fdd.c
Modules/x86/VGAText/vga.c

index 7ad93eb..8212773 100644 (file)
@@ -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
index f2abb28..8691100 100644 (file)
 #if USE_MP
 # include <mp.h>
 #endif
+#include <arch_config.h>
 
 // === 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;
index 6153db2..03c889f 100644 (file)
@@ -4,18 +4,13 @@
  * arch/x86_64/time.c
  */
 #include <acess.h>
+#include <arch_config.h>
 
 // === 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
index 3e5ac0a..76ed7cf 100644 (file)
@@ -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);
 
index 1180cad..3d06b0e 100644 (file)
@@ -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);
 }
 
index 368c310..de6bf96 100644 (file)
@@ -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)
index f83a006..801f2eb 100644 (file)
@@ -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);
 }
 
 /**
index 9fa9fd2..e926313 100644 (file)
@@ -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;
 

UCC git Repository :: git.ucc.asn.au