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))
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
@$(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
%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
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
* - CPU Error Handler
*/
#include <common.h>
+#include <proc.h>
// === CONSTANTS ===
#define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards
/*
- * 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);
extern int MM_Map(Uint VAddr, tPAddr PAddr);
extern Uint MM_Clone();
extern Uint MM_NewKStack();
+extern Uint MM_NewWorkerStack();
#endif
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));
/**
* \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;
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);
/*
- AcessOS Microkernel Version
- mm_phys.c
-*/
+ * Acess2
+ * - Physical memory manager
+ */
#define DEBUG 1
#include <common.h>
#include <mboot.h>
#include <mm_phys.h>
#include <proc.h>
-#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
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 ===
/**
{
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;
}
// 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);
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;
// Allocate kernel stack
for(i = KERNEL_STACKS >> 22;
- i < KERNEL_STACK_END >> 22;
+ i < KERNEL_STACKS_END >> 22;
i ++ )
{
// Check if directory is allocated
}
}
- //LEAVE('x', *gTmpCR3 & ~0xFFF);
- return *gTmpCR3 & ~0xFFF;
+ ret = *gTmpCR3 & ~0xFFF;
+ RELEASE( &gilTempFractal );
+
+ //LEAVE('x', ret);
+ return ret;
}
/**
{
Uint base = KERNEL_STACKS;
Uint i;
- for(;base<KERNEL_STACK_END;base+=KERNEL_STACK_SIZE)
+ for(;base<KERNEL_STACKS_END;base+=KERNEL_STACK_SIZE)
{
if(MM_GetPhysAddr(base) != 0) continue;
for(i=0;i<KERNEL_STACK_SIZE;i+=0x1000) {
return 0;
}
+/**
+ * \fn Uint MM_NewWorkerStack()
+ * \brief Creates a new worker stack
+ */
+Uint MM_NewWorkerStack()
+{
+ Uint esp, ebp;
+ Uint oldstack;
+ Uint base, addr;
+ int i, j;
+ Uint *tmpPage;
+ tPAddr pages[WORKER_STACK_SIZE>>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
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();
#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 ===
/**
#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<giNumCPUs;pos++)
{
#endif
gTSSs[pos].SS0 = 0x10;
gTSSs[pos].ESP0 = 0; // Set properly by scheduler
- gGDT[5+pos].LimitLow = sizeof(tTSS);
- gGDT[5+pos].LimitHi = 0;
- gGDT[5+pos].Access = 0x89; // Type
- gGDT[5+pos].Flags = 0x4;
- gGDT[5+pos].BaseLow = (Uint)&gTSSs[pos] & 0xFFFF;
- gGDT[5+pos].BaseMid = (Uint)&gTSSs[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;pos<giNumCPUs;pos++) {
#endif
- __asm__ __volatile__ ("ltr %%ax"::"a"(0x28+pos*8));
+ __asm__ __volatile__ ("ltr %%ax"::"a"(0x30+pos*8));
#if USE_MP
}
#endif
return newThread->TID;
}
+/**
+ * \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
outb(0x70, inb(0x70)|0x80); // Disable NMIs
// Install IRQ Handler
- //IRQ_AddHandler(8, Time_Interrupt);
+ IRQ_AddHandler(8, Time_Interrupt);
return 0;
}
//Log("giTimestamp = %lli", giTimestamp);
- Timer_CallTimers();
+ //Timer_CallTimers();
// Make sure the RTC Fires again
outb(0x70, 0x0C); // Select register C
int FDD_Install(char **Arguments);\r
\r
// === GLOBALS ===\r
-//MODULE_DEFINE(0, 0x004B, FDD, FDD_Install, NULL, NULL);\r
+MODULE_DEFINE(0, 0x004B, FDD, FDD_Install, NULL, NULL);\r
static t_floppyDevice fdd_devices[2];\r
static volatile int fdd_inUse = 0;\r
static volatile int fdd_irq6 = 0;\r
+++ /dev/null
-/* Acess2
- * NE2000 Driver
- *
- * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
- */
-#define DEBUG 1
-#include <common.h>
-#include <modules.h>
-#include <fs_devfs.h>
-#include <drv_pci.h>
-
-// === 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);
-}
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);
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();
* \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++;
* \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++)
* \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++;
* \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++;
* \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++;
* \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)
* \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);
* \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;
}
// - 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
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 );
// 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;
}
// 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
*/
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);
}
#include <modules.h>\r
#include "fs_ext2.h"\r
\r
+#define EXT2_UPDATE_WRITEBACK 1\r
+\r
// === STRUCTURES ===\r
typedef struct {\r
int FD;\r
tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);\r
int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode);\r
Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
+Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
\r
// === SEMI-GLOBALS ===\r
MODULE_DEFINE(0, 0x5B /*v0.90*/, EXT2, Ext2_Install, NULL);\r
\r
\r
/**\r
- \internal\r
\fn int Ext2_int_GetInode(vfs_node *Node, tExt2_Inode *Inode)\r
\brief Gets the inode descriptor for a node\r
\param node node to get the Inode of\r
free(iBlocks);\r
return (Uint64)BlockNum * Disk->BlockSize;\r
}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+ * \brief Allocate an inode (from the current group preferably)\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param Parent Inode ID of the parent (used to locate the child nearby)\r
+ */\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+{\r
+// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
+ * \brief Allocate a block from the best possible location\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param PrevBlock Previous block ID in the file\r
+ */\r
+Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
+{\r
+ int bpg = Disk->SuperBlock.s_blocks_per_group;\r
+ Uint blockgroup = PrevBlock / bpg;\r
+ Uint bitmap[Disk->BlockSize/sizeof(Uint)];\r
+ Uint bitsperblock = 8*Disk->BlockSize;\r
+ int i, j = 0;\r
+ Uint block;\r
+ \r
+ // Are there any free blocks?\r
+ if(Disk->SuperBlock.s_free_blocks_count == 0) return 0;\r
+ \r
+ if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)\r
+ {\r
+ // Search block group's bitmap\r
+ for(i = 0; i < bpg; i++)\r
+ {\r
+ // Get the block in the bitmap block\r
+ j = i & (bitsperblock-1);\r
+ \r
+ // Read in if needed\r
+ if(j == 0) {\r
+ VFS_ReadAt(\r
+ Disk->FD,\r
+ (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
+ Disk->BlockSize,\r
+ bitmap\r
+ );\r
+ }\r
+ \r
+ // Fast Check\r
+ if( bitmap[j/32] == -1 ) {\r
+ j = (j + 31) & ~31;\r
+ continue;\r
+ }\r
+ \r
+ // Is the bit set?\r
+ if( bitmap[j/32] & (1 << (j%32)) )\r
+ continue;\r
+ \r
+ // Ooh! We found one\r
+ break;\r
+ }\r
+ if( i < bpg ) {\r
+ Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");\r
+ goto checkAll; // Search the entire filesystem for a free block\r
+ // Goto needed for neatness\r
+ }\r
+ \r
+ // Mark as used\r
+ bitmap[j/32] |= (1 << (j%32));\r
+ VFS_WriteAt(\r
+ Disk->FD,\r
+ (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
+ Disk->BlockSize,\r
+ bitmap\r
+ );\r
+ block = i;\r
+ Disk->Groups[blockgroup].bg_free_blocks_count --;\r
+ }\r
+ else\r
+ {\r
+ checkAll:\r
+ Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");\r
+ return 0;\r
+ }\r
+ \r
+ // Reduce global count\r
+ Disk->SuperBlock.s_free_blocks_count --;\r
+ #if EXT2_UPDATE_WRITEBACK\r
+ Ext2_int_UpdateSuperblock(Disk);\r
+ #endif\r
+ \r
+ return block;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+ */\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+{\r
+ VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
+}\r
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