nucleus.c

来自「nucleus_arm.rar」· C语言 代码 · 共 314 行

C
314
字号
/*
	NUCLEUSKL - OS Kernel based on XERXYS NUCLEUS 0.01 by Christian Lins
	(C)Copyright 2003 by Christian Lins <christian@netvader.de>
	
	This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License 
	as published by the Free Software Foundation; 
	either version 2 of the License, or (at your option) any later version. 

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See the GNU General Public License for more details. 

	You should have received a copy of the GNU General Public License along with this program; 
	if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
	
	Letzte 膎derung: 25.07.2003
*/

// v0.1: ???
// v0.2: Doug Gale
//	- Added support for __attribute__((constructor/destructor))
//	- Fixed system halts, they now sleep in hlt loop, instead of busy loop
//	- Added calls to new code initialize paging, exceptions, TSS, etc.
//	- Various little test function calls

#include <datatypes.h>
#include <nucleus.h>
#include <support.h>
#include <stdio.h>	

// Roughly in order of initialization
#include <gdt.h>
#include <interrupts.h>
#include <tss.h>
#include <except.h>
#include <video/graphic.h>
#include <drivers/pic.h>	
#include <strings.h>
#include <multi.h>
#include <drivers/mem/mem.h>
#include <drivers/timer.h>
#include <drivers/input/keyboard.h>
#include <drivers/cpu/cpu.h>
#include <drivers/block.h>
#include <drivers/cmos.h>
#include <dynlink.h>

// Extras
#include <cdsl.h>
#include <drivers/fs/fat.h>

//char waste[1000000] = { 1, 2, 3 };

// interrupts_enable will panic if this is zero
int interrupts_ok;

// Constructor/Destructor function pointer
typedef void (*CtorDtor)(void);

static void call_constructors()
{
	CtorDtor *ppctor;

	// Provided by linker script
	extern char __ctors_st[];

	// Null terminated list
	ppctor = (CtorDtor*)__ctors_st;
	while (*ppctor)
		(*ppctor++)();
}

static void call_destructors()
{
	CtorDtor *ppdtor;

	// Provided by linker script
	extern char __dtors_st[];

	// Null terminated list
	ppdtor = (CtorDtor*)__dtors_st;
	while (*--ppdtor)
		(*ppdtor)();
}

// Versionskonstanten (--> nucleus.h f黵 weitere Infos)
const int nucleus_version = 0x001; // Version: 0.01
const char nucleus_revision[] = "a2"; // Revision: alpha 2

// Systemstatus (--> nulcleus.h f黵 weitere Infos)
char nucleuskl_status = NUC_STATUS_STARTING;

// Debuglevel (--> nucleus.h f黵 weitere Infos)
char nucleuskl_debug = NUC_DEBUG_FULL;

void shutdown(void) // inline entfernt, da andere L鰏ung erforderlich
{
	// Original APM Code ist nicht im PM verf黦bar
	printf(strings_get(STRINGS_SHUTDOWN));
	
	// Endlosschleife
	halt(0);
}

void terror_nuclei(const char *nachricht)
{
	// nucleus_showdebugscreen(); oder 鋒nlich
	//video_set_draw_color(CL_RED);
	printf("\n\nterror nuclei: %s\n", nachricht);
	shutdown();
}

void dopanic(char *pFile, int nLine)
{    
	printf("\n\nKernel panic! %s (%d)", pFile, nLine);
	// Raise debug exception (to show context and traceback)
//	__asm__ __volatile__ ( "int $0x03\n");
	halt(1);
}

static void test_thread(unsigned long param)
{
	// Do nothing, this tests thread self-destruct upon return
}

void trace_message(char *msg)
{
	char *in = msg;
	short *scrn = (void*)0xB8000;

	while (*in)
		*scrn++ = 0x0800 | *in++;

	delay(1000);
}

void /*__attribute__((constructor))*/ try_ide(void)
{
	unsigned sector[128];
	char buf[256];
	int n;

	// Wait for busy bit to clear
	while (inportb(0x1F7) & 0x80);

	// Setup to read C/H/S = 0/0/1 on master drive
	outportb(0x1F2, 1);			// Sector count
	outportb(0x1F3, 1);			// Sector number
	outportb(0x1F4, 0);			// Cylinder number (16-bit)
	outportb(0x1F5, 0);			// Cylinder number (16-bit)
	outportb(0x1F6, 0 | 0xA0);	// Head 0, master

	// Wait for the ready bit to set
	while (!(inportb(0x1F7) & 0x40));

	// Write command code
	outportb(0x1F7, 0x20);

	// Wait for busy bit to clear
	while (inportb(0x1F7) & 0x80);

	// Wait for command completion (DRQ)
	while (!(inportb(0x1F7) & 0x08));

	// Transfer sector
	for (n = 0; n < 128; n++)
		sector[n] = inportd(0x1F0);

	buf[0] = 0;
	for (n = 0; n < 32; n++)
		sprintf(buf + strlen(buf), " %02X", ((char*)sector)[n]);
	trace_message(buf);
	delay(15000);
}

int main(void)
{
	int fp;

	struct datetime datetime1;

//	trace_message("In main\n");

	trace_message("Trying IDE");
	try_ide();
	trace_message("Trying IDE done");

	// Call constructors (functions using __attribute__((constructor)))
	call_constructors();

	// Initialize GDT
//	trace_message("Init GDT\n");
	gdt_init();

	// Initialize IDT
//	trace_message("Init interrupts\n");
	interrupts_init();

	// Initialize TSS
//	trace_message("Init TSS\n");
	tss_init();

	// Install exception handlers as soon as possible
//	trace_message("Init exceptions\n");
	exception_init();

	// init graphics - needed by all screen output functions
	trace_message("Init graphic\n");
	graphic_init();	

	// Initialize IRQ controllers (hardware)
	trace_message("Init IRQ controllers\n");
	irq_init(); 

	// debuglevel and language are being load from nucload
	nucleuskl_debug = *(char *)NUCLOAD_DEBUGLEVEL;
	strings_setlang(*(char *)NUCLOAD_LANGUAGE);

	// adjust output if minor version is only 1 digit long
	if(NUC_MINOR_VERSION < 10)
		dprintf("%s%d.0%d%s%s\n\n", strings_get(STRINGS_NUCLOAD1), 
				NUC_MAJOR_VERSION, NUC_MINOR_VERSION, NUC_REVISION, strings_get(STRINGS_NUCLOAD2));
	else
		dprintf("%s%d.%d%s%s\n\n", strings_get(STRINGS_NUCLOAD1), 
				NUC_MAJOR_VERSION, NUC_MINOR_VERSION, NUC_REVISION, strings_get(STRINGS_NUCLOAD2));
	
	trace_message("Init threading\n");

	// Initialize multithreading before any interrupts occur
	multi_init();

	// output debuglevel (if debuging is enabled ;-)
	dprintf("%s\n", strings_get(STRINGS_DEBUG + nucleuskl_debug));

	// Initialize memory manager
	trace_message("Init memory manager\n");
	mm_init();

	// Test exception return path
	trace_message("Test breakpoint exception\n");
	__asm__ ( "int $0x03\n" );

	// Test page fault handler
//	*(char*)0xD0000000 = 0;		// Cause page fault
	
	// Initialize timer
	trace_message("Init timer\n");
	timer_init();

	// Initialize keyboard
	trace_message("Init keyboard\n");
	keyboard_init();

	// Set global enable for interrupts
	trace_message("Enabling interrupts\n");
	interrupts_ok = 1;

	// the two PICs are being initialized
	dprintf(strings_get(STRINGS_INTINIT));
	interrupts_enable();
	dprintf(strings_get(STRINGS_OK));

	// cpuid Funktion untersucht die CPU
	trace_message("Init cpu\n");
	dprintf("%s", strings_get(STRINGS_CPUSEARCH));
	cpu_init();
	dprintf("%s%s%d%s", cpu.name, strings_get(STRINGS_CPUFOUND1), cpu.clockrate, strings_get(STRINGS_CPUFOUND2));
	dprintf("Speicher: %ld KB\n", (dword)(detect_memory()/1024));

	// Initialize block device drivers
	block_init();

	// Show graphics information
	graphic_info();	
	
	// Test FAT code
	fp = _fat_fassign("NUCLEUS.BIN", 0xFF);
	if (fp > 0)
	{
//		while ((res =_fat_fread(fp, (char *)&buf, 1)) > 0)
		{
		}
		_fat_fclose(fp);
	}

	nucleuskl_status = NUC_STATUS_RUNNING;
	
	// Initialize CMOS
	datetime1 = cmos_get_time();

	// Quick test
	dyn_test();

	dprintf("Creating threads...\n");

	thread_create(128, 20, test_thread, 0);
	thread_create(128, 20, cdsl, 0);

	// This just releases its timeslice every time it is scheduled
	while (1 == 1) {
		(*(char*)(0xb8000 + 159))++;
		multi_yield();
	}

	terror_nuclei(strings_get(STRINGS_KERNELEXIT));

	call_destructors();

	// Return to where?
	halt(0);

	return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?