From b6c3b3cf61caafbd91bbf3acc81995e472656a5b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 15 Oct 2009 21:30:48 +0800 Subject: [PATCH] Various Changes - Double fault protection - Optomised Memory Functions (also added memcmp) - Added worker threads - Fixes to the timer code (stop the RTC firing at 1024 Hz) - Re-included the FDD driver - Moved the NE2000 driver to /Modules - Inconcequential changes to system.c - Added block allocation to fs/ext2 - Changed the makefiles to support static linking of modules --- Kernel/Makefile | 12 +- Kernel/arch/x86/desctab.asm | 3 +- Kernel/arch/x86/errors.c | 1 + Kernel/arch/x86/include/mm_virt.h | 9 +- Kernel/arch/x86/lib.c | 27 ++- Kernel/arch/x86/mm_phys.c | 6 +- Kernel/arch/x86/mm_virt.c | 126 +++++++++++- Kernel/arch/x86/proc.c | 77 +++++++- Kernel/arch/x86/time.c | 4 +- Kernel/drv/fdd.c | 2 +- Kernel/drv/ne2000.c | 313 ------------------------------ Kernel/include/common.h | 22 ++- Kernel/lib.c | 16 +- Kernel/system.c | 2 +- Kernel/threads.c | 18 +- Kernel/vfs/fs/ext2.c | 108 ++++++++++- Makefile.cfg | 5 +- 17 files changed, 378 insertions(+), 373 deletions(-) delete mode 100644 Kernel/drv/ne2000.c diff --git a/Kernel/Makefile b/Kernel/Makefile index 195d3110..5aeee685 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -19,10 +19,12 @@ OBJ = $(addprefix arch/$(ARCHDIR)/,$(A_OBJ)) OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o drvutil.o OBJ += binary.o bin/elf.o OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o vfs/memfile.o vfs/nodecache.o -OBJ += vfs/fs/root.o vfs/fs/devfs.o vfs/fs/fat.o vfs/fs/ext2.o +OBJ += vfs/fs/root.o vfs/fs/devfs.o +OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS))) OBJ += drv/fifo.o drv/dma.o drv/pci.o drv/vterm.o drv/vga.o drv/kb.o OBJ += $(addprefix drv/, $(addsuffix .o,$(DRIVERS))) OBJ := $(addsuffix .$(ARCH), $(OBJ)) +MODS += $(addprefix ../Modules/, $(addsuffix .o.$(ARCH),$(MODULES))) BIN = ../Acess2.$(ARCH).bin DEPFILES = $(filter %.o.$(ARCH),$(OBJ)) @@ -38,9 +40,9 @@ all: $(BIN) clean: @$(RM) $(BIN) $(OBJ) $(DEPFILES) -$(BIN): $(OBJ) arch/$(ARCHDIR)/link.ld Makefile +$(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile @echo --- LD -o $(BIN) - @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) -Map ../Map.$(ARCH).txt + @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) -Map ../Map.$(ARCH).txt @objdump $(BIN) -D > $(BIN).dsm cp $(BIN) $(DISTROOT) @wc -l $(SRCFILES) > LineCounts.$(ARCH).txt @@ -51,9 +53,13 @@ $(BIN): $(OBJ) arch/$(ARCHDIR)/link.ld Makefile @$(AS) $(ASFLAGS) $< -o $@ %.o.$(ARCH): %.c Makefile +# if exists %*/Makefile +# @make -C %*/ all +# else @echo --- GCC -o $@ @$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< @$(MAKEDEP) $(CPPFLAGS) -MT $@ -o $*.d.$(ARCH) $< +# endif include/syscalls.h: syscalls.lst Makefile php GenSyscalls.php diff --git a/Kernel/arch/x86/desctab.asm b/Kernel/arch/x86/desctab.asm index 2d0a2329..f4039501 100644 --- a/Kernel/arch/x86/desctab.asm +++ b/Kernel/arch/x86/desctab.asm @@ -8,7 +8,7 @@ MAX_CPUS equ 1 %else MAX_CPUS equ 8 %endif -GDT_SIZE equ (1+2*2+MAX_CPUS)*8 ; 4 Permission levels +GDT_SIZE equ (1+2*2+1+MAX_CPUS)*8 [section .data] ; GDT @@ -21,6 +21,7 @@ _gGDT: dd 0x0000FFFF, 0x00CF9200 ; 10 PL0 Data dd 0x0000FFFF, 0x00CFFA00 ; 18 PL3 Code dd 0x0000FFFF, 0x00CFF200 ; 20 PL3 Data + dd 0, 0 ; Double Fault TSS times MAX_CPUS dd 0, 0 _gGDTptr: dw GDT_SIZE-1 diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index 0c2da16e..b9ff17d2 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -4,6 +4,7 @@ * - CPU Error Handler */ #include +#include // === CONSTANTS === #define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards diff --git a/Kernel/arch/x86/include/mm_virt.h b/Kernel/arch/x86/include/mm_virt.h index 8b7508ca..d3260fe0 100644 --- a/Kernel/arch/x86/include/mm_virt.h +++ b/Kernel/arch/x86/include/mm_virt.h @@ -1,9 +1,9 @@ /* - * AcessOS Microkernel Version - * mm_phys.h + * Acess2 + * - Virtual Memory Manager (Header) */ -#ifndef _MM_PHYS_H -#define _MM_PHYS_H +#ifndef _MM_VIRT_H +#define _MM_VIRT_H // === FUNCTIONS === extern void MM_SetCR3(Uint32 CR3); @@ -12,5 +12,6 @@ extern void MM_Deallocate(Uint VAddr); extern int MM_Map(Uint VAddr, tPAddr PAddr); extern Uint MM_Clone(); extern Uint MM_NewKStack(); +extern Uint MM_NewWorkerStack(); #endif diff --git a/Kernel/arch/x86/lib.c b/Kernel/arch/x86/lib.c index 6b9ee1e6..1bbdeabb 100644 --- a/Kernel/arch/x86/lib.c +++ b/Kernel/arch/x86/lib.c @@ -70,11 +70,25 @@ void *memsetd(void *Dest, Uint Val, Uint Num) return Dest; } +/** + * \fn int memcmp(const void *m1, const void *m2, Uint Num) + * \brief Compare two pieces of memory + */ +int memcmp(const void *m1, const void *m2, Uint Num) +{ + while(Num--) + { + if(*(Uint8*)m1 != *(Uint8*)m2) break; + m1 ++; + m2 ++; + } + return *(Uint8*)m1 - *(Uint8*)m2; +} /** * \fn void *memcpy(void *Dest, void *Src, Uint Num) */ -void *memcpy(void *Dest, void *Src, Uint Num) +void *memcpy(void *Dest, const void *Src, Uint Num) { if((Uint)Dest & 3 || (Uint)Src & 3) __asm__ __volatile__ ("rep movsb" :: "D" (Dest), "S" (Src), "c" (Num)); @@ -90,7 +104,7 @@ void *memcpy(void *Dest, void *Src, Uint Num) /** * \fn void *memcpyd(void *Dest, void *Src, Uint Num) */ -void *memcpyd(void *Dest, void *Src, Uint Num) +void *memcpyd(void *Dest, const void *Src, Uint Num) { __asm__ __volatile__ ("rep movsl" :: "D" (Dest), "S" (Src), "c" (Num)); return Dest; @@ -154,6 +168,15 @@ Uint64 __umoddi3(Uint64 Num, Uint64 Den) return Num; } +Uint16 LittleEndian16(Uint16 Val) +{ + return Val; +} +Uint16 BigEndian16(Uint16 Val) +{ + return ((Val&0xFF)<<8) | ((Val>>8)&0xFF); +} + // --- EXPORTS --- EXPORT(memcpy); EXPORT(memset); //EXPORT(memcpyw); EXPORT(memsetw); diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index 4c5cf20e..82c45c37 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -1,7 +1,7 @@ /* - AcessOS Microkernel Version - mm_phys.c -*/ + * Acess2 + * - Physical memory manager + */ #define DEBUG 1 #include #include diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index c930947d..f5b89590 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -14,9 +14,13 @@ #include #include -#define KERNEL_STACKS 0xF0000000 +#define KERNEL_STACKS 0xF0000000 #define KERNEL_STACK_SIZE 0x00002000 -#define KERNEL_STACK_END 0xFD000000 +#define KERNEL_STACKS_END 0xFD000000 +#define WORKER_STACKS 0x00100000 // Thread0 Only! +#define WORKER_STACK_SIZE KERNEL_STACK_SIZE +#define WORKER_STACKS_END 0xB0000000 +#define NUM_WORKER_STACKS ((WORKER_STACKS_END-WORKER_STACKS)/WORKER_STACK_SIZE) #define PAGE_TABLE_ADDR 0xFD000000 #define PAGE_DIR_ADDR 0xFD3F4000 #define PAGE_CR3_ADDR 0xFD3F4FD0 @@ -58,6 +62,9 @@ tPAddr *gaTmpTable = (void*)TMP_TABLE_ADDR; tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR; tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR; int gilTempMappings = 0; + int gilTempFractal = 0; +Uint32 gWorkerStacks[NUM_WORKER_STACKS/32]; + int giLastUsedWorker = 0; // === CODE === /** @@ -83,7 +90,7 @@ void MM_InstallVirtual() { if( gaPageDir[ i ] ) continue; // Skip stack tables, they are process unique - if( i > KERNEL_STACKS >> 22 && i < KERNEL_STACK_END >> 22) { + if( i > KERNEL_STACKS >> 22 && i < KERNEL_STACKS_END >> 22) { gaPageDir[ i ] = 0; continue; } @@ -128,6 +135,12 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) // If it was a user, tell the thread handler if(ErrorCode & 4) { + Warning("%s %s %s memory%s", + (ErrorCode&4?"User":"Kernel"), + (ErrorCode&2?"write to":"read from"), + (ErrorCode&1?"bad/locked":"non-present"), + (ErrorCode&16?" (Instruction Fetch)":"") + ); Warning("User Pagefault: Instruction at %p accessed %p", Regs->eip, Addr); __asm__ __volatile__ ("sti"); // Restart IRQs Threads_SegFault(Addr); @@ -417,11 +430,12 @@ Uint MM_ClearUser() Uint MM_Clone() { Uint i, j; + Uint ret; Uint page = 0; Uint kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; void *tmp; - //ENTER(""); + LOCK( &gilTempFractal ); // Create Directory Table *gTmpCR3 = MM_AllocPhys() | 3; @@ -484,7 +498,7 @@ Uint MM_Clone() // Allocate kernel stack for(i = KERNEL_STACKS >> 22; - i < KERNEL_STACK_END >> 22; + i < KERNEL_STACKS_END >> 22; i ++ ) { // Check if directory is allocated @@ -528,8 +542,11 @@ Uint MM_Clone() } } - //LEAVE('x', *gTmpCR3 & ~0xFFF); - return *gTmpCR3 & ~0xFFF; + ret = *gTmpCR3 & ~0xFFF; + RELEASE( &gilTempFractal ); + + //LEAVE('x', ret); + return ret; } /** @@ -540,7 +557,7 @@ Uint MM_NewKStack() { Uint base = KERNEL_STACKS; Uint i; - for(;base>12]; + + // Get the old ESP and EBP + __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); + __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); + + // Find a free worker stack address + for(base = giLastUsedWorker; base < NUM_WORKER_STACKS; base++) + { + // Used block + if( gWorkerStacks[base/32] == -1 ) { + base += 31; base &= ~31; + base --; // Counteracted by the base++ + continue; + } + // Used stack + if( gWorkerStacks[base/32] & (1 << base) ) { + continue; + } + } + if(base >= NUM_WORKER_STACKS) { + Warning("Uh-oh! Out of worker stacks"); + return 0; + } + + // It's ours now! + gWorkerStacks[base/32] |= (1 << base); + // Make life easier for later calls + giLastUsedWorker = base; + // We have one + base = WORKER_STACKS + base * WORKER_STACK_SIZE; + + // Acquire the lock for the temp fractal mappings + LOCK(&gilTempFractal); + + // Set the temp fractals to TID0's address space + *gTmpCR3 = (Uint)gaInitPageDir | 3; + INVLPG( gaTmpDir ); + + // Check if the directory is mapped (we are assuming that the stacks + // will fit neatly in a directory + if(gaTmpDir[ base >> 22 ] == 0) { + gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3; + INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] ); + } + + // Mapping Time! + for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 ) + { + pages[ addr >> 12 ] = MM_AllocPhys(); + gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; + } + // Release the temp mapping lock + RELEASE(&gilTempFractal); + + // Copy the old stack + oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1); + esp = oldstack - esp; // ESP as an offset in the stack + + i = (WORKER_STACK_SIZE>>12) - 1; + // Copy the contents of the old stack to the new one, altering the addresses + // `addr` is refering to bytes from the stack base (mem downwards) + for(addr = 0; addr < esp; addr += 0x1000) + { + Uint *stack = (Uint*)( oldstack-(addr+0x1000) ); + tmpPage = (void*)MM_MapTemp( pages[i] ); + // Copy old stack + for(j = 0; j < 1024; j++) + { + // Possible Stack address? + if(oldstack-esp < stack[j] && stack[j] < oldstack) + tmpPage[j] = base - (oldstack - stack[j]); + else // Seems not, best leave it alone + tmpPage[j] = stack[j]; + } + MM_FreeTemp((Uint)tmpPage); + i --; + } + + return base; +} + /** * \fn void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) * \brief Sets the flags on a page diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index f7bda0fc..5132f829 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -34,6 +34,7 @@ extern tThread *gDeleteThreads; extern tThread *Threads_GetNextToRun(int CPU); extern void Threads_Dump(); extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags); +extern void Isr7(); // === PROTOTYPES === void ArchThreads_Init(); @@ -60,6 +61,13 @@ tTSS *gTSSs = NULL; #if !USE_MP tTSS gTSS0 = {0}; #endif +// --- Error Recovery --- +char gaDoubleFaultStack[1024]; +tTSS gDoubleFault_TSS = { + .ESP0 = (Uint)&gaDoubleFaultStack[1023], + .SS0 = 0x10, + .EIP = (Uint)Isr7 +}; // === CODE === /** @@ -106,6 +114,15 @@ void ArchThreads_Init() #if USE_MP } + // Initialise Double Fault TSS + gGDT[5].LimitLow = sizeof(tTSS); + gGDT[5].LimitHi = 0; + gGDT[5].Access = 0x89; // Type + gGDT[5].Flags = 0x4; + gGDT[5].BaseLow = (Uint)&gDoubleFault_TSS & 0xFFFF; + gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16; + gGDT[5].BaseHi = (Uint)&gDoubleFault_TSS >> 24; + // Initialise TSS for(pos=0;pos> 16; - gGDT[5+pos].BaseHi = (Uint)&gTSSs[pos] >> 24; + gGDT[6+pos].LimitLow = sizeof(tTSS); + gGDT[6+pos].LimitHi = 0; + gGDT[6+pos].Access = 0x89; // Type + gGDT[6+pos].Flags = 0x4; + gGDT[6+pos].BaseLow = (Uint)&gTSSs[pos] & 0xFFFF; + gGDT[6+pos].BaseMid = (Uint)&gTSSs[pos] >> 16; + gGDT[6+pos].BaseHi = (Uint)&gTSSs[pos] >> 24; #if USE_MP } for(pos=0;posTID; } +/** + * \fn int Proc_SpawnWorker() + * \brief Spawns a new worker thread + */ +int Proc_SpawnWorker() +{ + tThread *new, *cur; + Uint eip, esp, ebp; + + cur = Proc_GetCurThread(); + + // Create new thread + new = malloc( sizeof(tThread) ); + if(!new) { + Warning("Proc_SpawnWorker - Out of heap space!\n"); + return -1; + } + memcpy(new, &gThreadZero, sizeof(tThread)); + // Set Thread ID + new->TID = giNextTID++; + // Set kernel stack + new->KernelStack = MM_NewWorkerStack(); + + // Get ESP and EBP based in the new stack + __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); + __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); + esp = cur->KernelStack - (new->KernelStack - esp); + ebp = new->KernelStack - (cur->KernelStack - ebp); + + // Save core machine state + new->SavedState.ESP = esp; + new->SavedState.EBP = ebp; + eip = GetEIP(); + if(eip == SWITCH_MAGIC) { + outb(0x20, 0x20); // ACK Timer and return as child + return 0; + } + + // Set EIP as parent + new->SavedState.EIP = eip; + + return new->TID; +} + /** * \fn Uint Proc_MakeUserStack() * \brief Creates a new user stack diff --git a/Kernel/arch/x86/time.c b/Kernel/arch/x86/time.c index bbdfcfca..9cccec7c 100644 --- a/Kernel/arch/x86/time.c +++ b/Kernel/arch/x86/time.c @@ -60,7 +60,7 @@ int Time_Setup() outb(0x70, inb(0x70)|0x80); // Disable NMIs // Install IRQ Handler - //IRQ_AddHandler(8, Time_Interrupt); + IRQ_AddHandler(8, Time_Interrupt); return 0; } @@ -80,7 +80,7 @@ void Time_Interrupt() //Log("giTimestamp = %lli", giTimestamp); - Timer_CallTimers(); + //Timer_CallTimers(); // Make sure the RTC Fires again outb(0x70, 0x0C); // Select register C diff --git a/Kernel/drv/fdd.c b/Kernel/drv/fdd.c index ae79ac76..448e87d0 100644 --- a/Kernel/drv/fdd.c +++ b/Kernel/drv/fdd.c @@ -92,7 +92,7 @@ Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); int FDD_Install(char **Arguments); // === GLOBALS === -//MODULE_DEFINE(0, 0x004B, FDD, FDD_Install, NULL, NULL); +MODULE_DEFINE(0, 0x004B, FDD, FDD_Install, NULL, NULL); static t_floppyDevice fdd_devices[2]; static volatile int fdd_inUse = 0; static volatile int fdd_irq6 = 0; diff --git a/Kernel/drv/ne2000.c b/Kernel/drv/ne2000.c deleted file mode 100644 index a0321912..00000000 --- a/Kernel/drv/ne2000.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Acess2 - * NE2000 Driver - * - * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc - */ -#define DEBUG 1 -#include -#include -#include -#include - -// === CONSTANTS === -#define MEM_START 0x40 -#define MEM_END 0xC0 -#define RX_FIRST (MEM_START) -#define RX_LAST (MEM_START+RX_BUF_SIZE-1) -#define RX_BUF_SIZE 0x40 -#define TX_FIRST (MEM_START+RX_BUF_SIZE) -#define TX_LAST (MEM_END) -#define TX_BUF_SIZE 0x40 - -static const struct { - Uint16 Vendor; - Uint16 Device; -} csaCOMPAT_DEVICES[] = { - {0x10EC, 0x8029}, // Realtek 8029 - {0x10EC, 0x8129} // Realtek 8129 -}; -#define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0])) - -enum eNe2k_Page0Read { - CMD = 0, //!< the master command register - CLDA0, //!< Current Local DMA Address 0 - CLDA1, //!< Current Local DMA Address 1 - BNRY, //!< Boundary Pointer (for ringbuffer) - TSR, //!< Transmit Status Register - NCR, //!< collisions counter - FIFO, //!< (for what purpose ??) - ISR, //!< Interrupt Status Register - CRDA0, //!< Current Remote DMA Address 0 - CRDA1, //!< Current Remote DMA Address 1 - RSR = 0xC //!< Receive Status Register -}; - -enum eNe2k_Page0Write { - PSTART = 1, //!< page start (init only) - PSTOP, //!< page stop (init only) - TPSR = 4, //!< transmit page start address - TBCR0, //!< transmit byte count (low) - TBCR1, //!< transmit byte count (high) - RSAR0 = 8, //!< remote start address (lo) - RSAR1, //!< remote start address (hi) - RBCR0, //!< remote byte count (lo) - RBCR1, //!< remote byte count (hi) - RCR, //!< receive config register - TCR, //!< transmit config register - DCR, //!< data config register (init) - IMR //!< interrupt mask register (init) -}; - -// === TYPES === -typedef struct sNe2k_Card { - Uint16 IOBase; //!< IO Port Address from PCI - Uint8 IRQ; //!< IRQ Assigned from PCI - - int NextMemPage; //!< Next Card Memory page to use - - Uint8 Buffer[RX_BUF_SIZE]; - - char Name[2]; // "0" - tVFS_Node Node; - Uint8 MacAddr[6]; -} tCard; - -// === PROTOTYPES === - int Ne2k_Install(char **Arguments); -char *Ne2k_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name); -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); -void Ne2k_IRQHandler(int IntNum); - -// === GLOBALS === -MODULE_DEFINE(0, 0x0032, Ne2k, Ne2k_Install, NULL, NULL); -tDevFS_Driver gNe2k_DriverInfo = { - NULL, "ne2k", - { - .NumACLs = 1, - .ACLs = &gVFS_ACL_EveryoneRX, - .Flags = VFS_FFLAG_DIRECTORY, - .ReadDir = Ne2k_ReadDir, - .FindDir = Ne2k_FindDir - } -}; -Uint16 gNe2k_BaseAddress; - int giNe2k_CardCount = 0; -tCard *gpNe2k_Cards = NULL; - -// === CODE === -/** - * \fn int Ne2k_Install(char **Options) - * \brief Installs the NE2000 Driver - */ -int Ne2k_Install(char **Options) -{ - int i, j, k; - int count, id, base; - - // --- Scan PCI Bus --- - // Count Cards - giNe2k_CardCount = 0; - for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) - { - giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); - } - - // Enumerate Cards - k = 0; - gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) ); - memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4); - for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) - { - count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); - for( j = 0; j < count; j ++,k ++ ) - { - id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j ); - // Create Structure - base = PCI_AssignPort( id, 0, 0x20 ); - gpNe2k_Cards[ k ].IOBase = base; - gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id ); - gpNe2k_Cards[ k ].NextMemPage = 64; - - // Install IRQ Handler - IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler); - - // Reset Card - outb( base + 0x1F, inb(base + 0x1F) ); - while( (inb( base+ISR ) & 0x80) == 0 ); - outb( base + ISR, 0x80 ); - - // Initialise Card - outb( base + CMD, 0x21 ); // No DMA and Stop - outb( base + DCR, 0x49 ); // Set WORD mode - outb( base + IMR, 0x00 ); - outb( base + ISR, 0xFF ); - outb( base + RCR, 0x20 ); // Reciever to Monitor - outb( base + TCR, 0x02 ); // Transmitter OFF (TCR.LB = 1, Internal Loopback) - outb( base + RBCR0, 6*4 ); // Remote Byte Count - outb( base + RBCR1, 0 ); - outb( base + RSAR0, 0 ); // Clear Source Address - outb( base + RSAR1, 0 ); - outb( base + CMD, 0x0A ); // Remote Read, Start - - // Read MAC Address - gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10); inb(base+0x10); - - outb( base+PSTART, RX_FIRST); // Set Receive Start - outb( base+BNRY, RX_LAST-1); // Set Boundary Page - outb( base+PSTOP, RX_LAST); // Set Stop Page - outb( base+ISR, 0xFF ); // Clear all ints - outb( base+CMD, 0x22 ); // No DMA, Start - outb( base+IMR, 0x3F ); // Set Interupt Mask - outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches - outb( base+TCR, 0x00 ); // Set Normal Transmitter mode - outb( base+TPSR, 0x40); // Set Transmit Start - // Set MAC Address - /* - Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]); - Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]); - Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]); - Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]); - Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]); - Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]); - */ - - Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x", - k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase); - Log("MAC Address %x:%x:%x:%x:%x:%x", - gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1], - gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3], - gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5] - ); - - // Set VFS Node - gpNe2k_Cards[ k ].Name[0] = '0'+k; - gpNe2k_Cards[ k ].Name[1] = '\0'; - gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ]; - gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only - gpNe2k_Cards[ k ].Node.CTime = now(); - gpNe2k_Cards[ k ].Node.Write = Ne2k_Write; - } - } - - gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount; - DevFS_AddDevice( &gNe2k_DriverInfo ); - return 0; -} - -/** - * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) - */ -char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) -{ - char ret[2]; - if(Pos < 0 || Pos >= giNe2k_CardCount) return NULL; - ret[0] = '0'+Pos; - ret[1] = '\0'; - return strdup(ret); -} - -/** - * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) - */ -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) -{ - if(Name[0] == '\0' || Name[1] != '\0') return NULL; - - return &gpNe2k_Cards[ Name[0]-'0' ].Node; -} - -/** - * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - */ -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tCard *Card = (tCard*)Node->ImplPtr; - Uint16 *buf = Buffer; - int rem = Length; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - // Sanity Check Length - if(Length > TX_BUF_SIZE) { - LEAVE('i', 0); - return 0; - } - - // Make sure that the card is in page 0 - outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA - - // Clear Remote DMA Flag - outb(Card->IOBase + ISR, 0x40); // Bit 6 - - // Send Size - Remote Byte Count Register - outb(Card->IOBase + TBCR0, Length & 0xFF); - outb(Card->IOBase + TBCR1, Length >> 8); - - // Send Size - Remote Byte Count Register - outb(Card->IOBase + RBCR0, Length & 0xFF); - outb(Card->IOBase + RBCR1, Length >> 8); - - // Set up transfer - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length)); // Page Offset - // Start - //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2); // Page 0, Transmit Packet, TXP, Start - outb(Card->IOBase + CMD, 0|0x10|0x2); // Page 0, Remote Write, Start - - // Send Data - for(rem = Length; rem; rem -= 2) - outw(Card->IOBase + 0x10, *buf++); - - while( inb(Card->IOBase + ISR) == 0) // Wait for Remote DMA Complete - ; //Proc_Yield(); - - outb( Card->IOBase + ISR, 0x40 ); // ACK Interrupt - - // Send Packet - outb(Card->IOBase + CMD, 0|0x10|0x4|0x2); - - // Complete DMA - //outb(Card->IOBase + CMD, 0|0x20); - - LEAVE('i', Length); - return Length; -} - -/** - * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) - */ -Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) -{ - Uint8 ret = Card->NextMemPage; - - Card->NextMemPage += (Length + 0xFF) >> 8; - if(Card->NextMemPage >= TX_LAST) { - Card->NextMemPage -= TX_BUF_SIZE; - } - - return ret; -} - -/** - * \fn void Ne2k_IRQHandler(int IntNum) - */ -void Ne2k_IRQHandler(int IntNum) -{ - int i; - for( i = 0; i < giNe2k_CardCount; i++ ) - { - if(gpNe2k_Cards[i].IRQ == IntNum) { - LOG("Clearing interrupts on card %i (0x%x)\n", i, inb( gpNe2k_Cards[i].IOBase + ISR )); - outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All - return ; - } - } - Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum); -} diff --git a/Kernel/include/common.h b/Kernel/include/common.h index f3401346..16d089d2 100644 --- a/Kernel/include/common.h +++ b/Kernel/include/common.h @@ -85,19 +85,20 @@ extern void MM_UnmapHWPage(Uint VAddr, Uint Number); extern tPAddr MM_AllocPhys(); extern void MM_RefPhys(tPAddr Addr); extern void MM_DerefPhys(tPAddr Addr); -extern void *memcpy(void *dest, void *src, Uint count); -extern void *memcpyd(void *dest, void *src, Uint count); +extern int memcmp(const void *m1, const void *m2, Uint count); +extern void *memcpy(void *dest, const void *src, Uint count); +extern void *memcpyd(void *dest, const void *src, Uint count); extern void *memset(void *dest, int val, Uint count); extern void *memsetd(void *dest, Uint val, Uint count); // --- Strings --- -extern Uint strlen(char *Str); -extern char *strcpy(char *__dest, char *__src); -extern int strcmp(char *__dest, char *__src); -extern int strncmp(char *Str1, char *Str2, size_t num); -extern int strucmp(char *Str1, char *Str2); -extern char *strdup(char *__str); -extern int strpos(char *Str, char Ch); -extern int strpos8(char *str, Uint32 search); +extern Uint strlen(const char *Str); +extern char *strcpy(char *__dest, const char *__src); +extern int strcmp(const char *__str1, const char *__str2); +extern int strncmp(const char *Str1, const char *Str2, size_t num); +extern int strucmp(const char *Str1, const char *Str2); +extern char *strdup(const char *__str); +extern int strpos(const char *Str, char Ch); +extern int strpos8(const char *str, Uint32 search); extern void itoa(char *buf, Uint num, int base, int minLength, char pad); extern int ReadUTF8(Uint8 *str, Uint32 *Val); extern int WriteUTF8(Uint8 *str, Uint32 Val); @@ -117,6 +118,7 @@ extern int Time_CreateTimer(int Delta, void *Callback, void *Argument); extern void Time_RemoveTimer(int ID); extern void Time_Delay(int Delay); // --- Threads --- +extern int Proc_SpawnWorker(); extern int Proc_Spawn(char *Path); extern void Threads_Exit(); extern void Threads_Yield(); diff --git a/Kernel/lib.c b/Kernel/lib.c index 68d48a6a..d3fff546 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -70,7 +70,7 @@ int tolower(int c) * \fn int strucmp(char *Str1, char *Str2) * \brief Compare \a Str1 and \a Str2 case-insensitively */ -int strucmp(char *Str1, char *Str2) +int strucmp(const char *Str1, const char *Str2) { while(*Str1 && tolower(*Str1) == tolower(*Str2)) Str1++, Str2++; @@ -81,7 +81,7 @@ int strucmp(char *Str1, char *Str2) * \fn int strpos(char *Str, char Ch) * \brief Search a string for an ascii character */ -int strpos(char *Str, char Ch) +int strpos(const char *Str, char Ch) { int pos; for(pos=0;Str[pos];pos++) @@ -104,7 +104,7 @@ int ByteSum(void *Ptr, int Size) * \fn Uint strlen(char *__str) * \brief Get the length of string */ -Uint strlen(char *__str) +Uint strlen(const char *__str) { Uint ret = 0; while(*__str++) ret++; @@ -115,7 +115,7 @@ Uint strlen(char *__str) * \fn char *strcpy(char *__str1, char *__str2) * \brief Copy a string to a new location */ -char *strcpy(char *__str1, char *__str2) +char *strcpy(char *__str1, const char *__str2) { while(*__str2) *__str1++ = *__str2++; @@ -128,7 +128,7 @@ char *strcpy(char *__str1, char *__str2) * \brief Compare two strings return the difference between * the first non-matching characters. */ -int strcmp(char *str1, char *str2) +int strcmp(const char *str1, const char *str2) { while(*str1 && *str1 == *str2) str1++, str2++; @@ -139,7 +139,7 @@ int strcmp(char *str1, char *str2) * \fn int strncmp(char *Str1, char *Str2, size_t num) * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters */ -int strncmp(char *Str1, char *Str2, size_t num) +int strncmp(const char *Str1, const char *Str2, size_t num) { if(num == 0) return 0; // TODO: Check what should officially happen here while(--num && *Str1 && *Str1 == *Str2) @@ -151,7 +151,7 @@ int strncmp(char *Str1, char *Str2, size_t num) * \fn char *strdup(char *str) * \brief Duplicates a string */ -char *strdup(char *str) +char *strdup(const char *str) { char *ret; ret = malloc(strlen(str)+1); @@ -174,7 +174,7 @@ int DivUp(int num, int dem) * \fn int strpos8(char *str, Uint32 search) * \brief Search a string for a UTF-8 character */ -int strpos8(char *str, Uint32 Search) +int strpos8(const char *str, Uint32 Search) { int pos; Uint32 val = 0; diff --git a/Kernel/system.c b/Kernel/system.c index 9b160d92..4dc92c8b 100644 --- a/Kernel/system.c +++ b/Kernel/system.c @@ -232,10 +232,10 @@ void System_ExecuteScript() } // - Load Module else if(strncmp("module ", fData+i, 6) == 0) { + //char *tmp; i += 7; i += System_Int_GetString(fData+i, &sArg1); if(!sArg1) goto read2eol; - //Log("[CFG ] Load Module '%s'\n", sArg1); Module_LoadFile(sArg1, ""); //!\todo Use the rest of the line as the argument string } // - Load Module diff --git a/Kernel/threads.c b/Kernel/threads.c index dd7cfcd2..3be97892 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -464,7 +464,7 @@ void Threads_Sleep() tThread *cur = Proc_GetCurThread(); tThread *thread; - //Log("Proc_Sleep: %i going to sleep", cur->TID); + Log("Proc_Sleep: %i going to sleep", cur->TID); // Acquire Spinlock LOCK( &giThreadListLock ); @@ -472,7 +472,8 @@ void Threads_Sleep() // Get thread before current thread thread = Threads_int_GetPrev( &gActiveThreads, cur ); if(!thread) { - Warning("Proc_Sleep - Current thread is not on the active queue"); + Warning("Threads_Sleep - Current thread is not on the active queue"); + Threads_Dump(); return; } @@ -502,11 +503,11 @@ void Threads_Sleep() // Release Spinlock RELEASE( &giThreadListLock ); - HALT(); + while(cur->Status != THREAD_STAT_ACTIVE) HALT(); } -/**c0108919: +/** * \fn void Threads_Wake( tThread *Thread ) * \brief Wakes a sleeping/waiting thread up */ @@ -630,18 +631,23 @@ int Threads_GetGID() void Threads_Dump() { tThread *thread; + tThread *cur = Proc_GetCurThread(); Log("Active Threads:"); for(thread=gActiveThreads;thread;thread=thread->Next) { - Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName); + Log("%c%i (%i) - %s", + (thread==cur?'*':' '), + thread->TID, thread->TGID, thread->ThreadName); Log(" %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum); Log(" KStack 0x%x", thread->KernelStack); } Log("Sleeping Threads:"); for(thread=gSleepingThreads;thread;thread=thread->Next) { - Log(" %i (%i) - %s", thread->TID, thread->TGID, thread->ThreadName); + Log("%c%i (%i) - %s", + (thread==cur?'*':' '), + thread->TID, thread->TGID, thread->ThreadName); Log(" %i Tickets, Quantum %i", thread->NumTickets, thread->Quantum); Log(" KStack 0x%x", thread->KernelStack); } diff --git a/Kernel/vfs/fs/ext2.c b/Kernel/vfs/fs/ext2.c index fe0f25db..50be904a 100644 --- a/Kernel/vfs/fs/ext2.c +++ b/Kernel/vfs/fs/ext2.c @@ -13,6 +13,8 @@ #include #include "fs_ext2.h" +#define EXT2_UPDATE_WRITEBACK 1 + // === STRUCTURES === typedef struct { int FD; @@ -42,6 +44,9 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name); int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent); +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock); +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); // === SEMI-GLOBALS === MODULE_DEFINE(0, 0x5B /*v0.90*/, EXT2, Ext2_Install, NULL); @@ -478,7 +483,6 @@ int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) /** - \internal \fn int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode) \brief Gets the inode descriptor for a node \param node node to get the Inode of @@ -630,3 +634,105 @@ Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) free(iBlocks); return (Uint64)BlockNum * Disk->BlockSize; } + +/** + * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) + * \brief Allocate an inode (from the current group preferably) + * \param Disk EXT2 Disk Information Structure + * \param Parent Inode ID of the parent (used to locate the child nearby) + */ +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) +{ +// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group; + return 0; +} + +/** + * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) + * \brief Allocate a block from the best possible location + * \param Disk EXT2 Disk Information Structure + * \param PrevBlock Previous block ID in the file + */ +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) +{ + int bpg = Disk->SuperBlock.s_blocks_per_group; + Uint blockgroup = PrevBlock / bpg; + Uint bitmap[Disk->BlockSize/sizeof(Uint)]; + Uint bitsperblock = 8*Disk->BlockSize; + int i, j = 0; + Uint block; + + // Are there any free blocks? + if(Disk->SuperBlock.s_free_blocks_count == 0) return 0; + + if(Disk->Groups[blockgroup].bg_free_blocks_count > 0) + { + // Search block group's bitmap + for(i = 0; i < bpg; i++) + { + // Get the block in the bitmap block + j = i & (bitsperblock-1); + + // Read in if needed + if(j == 0) { + VFS_ReadAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + } + + // Fast Check + if( bitmap[j/32] == -1 ) { + j = (j + 31) & ~31; + continue; + } + + // Is the bit set? + if( bitmap[j/32] & (1 << (j%32)) ) + continue; + + // Ooh! We found one + break; + } + if( i < bpg ) { + Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist"); + goto checkAll; // Search the entire filesystem for a free block + // Goto needed for neatness + } + + // Mark as used + bitmap[j/32] |= (1 << (j%32)); + VFS_WriteAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + block = i; + Disk->Groups[blockgroup].bg_free_blocks_count --; + } + else + { + checkAll: + Warning("[EXT2 ] TODO - Implement using blocks outside the current block group"); + return 0; + } + + // Reduce global count + Disk->SuperBlock.s_free_blocks_count --; + #if EXT2_UPDATE_WRITEBACK + Ext2_int_UpdateSuperblock(Disk); + #endif + + return block; +} + +/** + * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) + */ +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) +{ + VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock); +} diff --git a/Makefile.cfg b/Makefile.cfg index 57adb851..f6f00610 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -14,8 +14,9 @@ RMDIR = rm -rf ARCH = i386 ARCHDIR = x86 -DRIVERS = ata_x86 ne2000 -# fdd +FILESYSTEMS = fat ext2 +DRIVERS = ata_x86 fdd +MODULES = ne2000 DISTROOT = /mnt/AcessHDD/Acess2 ACESSDIR = /home/hodgeja/Projects/Acess2 -- 2.20.1