please
This commit is contained in:
commit
a1cc1aa6ac
99 changed files with 4716 additions and 261 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@ Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
|
|||
DevEnv/
|
||||
*.o
|
||||
*.bin
|
||||
bochsout.txt
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
00000000000i[ ] Bochs x86 Emulator 2.6.9
|
||||
00000000000i[ ] Built from SVN snapshot on April 9, 2017
|
||||
00000000000i[ ] Compiled on Apr 21 2017 at 23:41:40
|
||||
00000000000i[ ] System configuration
|
||||
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
|
||||
00000000000i[ ] A20 line support: yes
|
||||
00000000000i[ ] IPS is set to 4000000
|
||||
00000000000i[ ] CPU configuration
|
||||
00000000000i[ ] SMP support: yes, quantum=16
|
||||
00000000000i[ ] level: 6
|
||||
00000000000i[ ] APIC support: xapic
|
||||
00000000000i[ ] FPU support: yes
|
||||
00000000000i[ ] MMX support: yes
|
||||
00000000000i[ ] 3dnow! support: yes
|
||||
00000000000i[ ] SEP support: yes
|
||||
00000000000i[ ] SIMD support: sse2
|
||||
00000000000i[ ] XSAVE support: no
|
||||
00000000000i[ ] AES support: no
|
||||
00000000000i[ ] SHA support: no
|
||||
00000000000i[ ] MOVBE support: no
|
||||
00000000000i[ ] ADX support: no
|
||||
00000000000i[ ] x86-64 support: yes
|
||||
00000000000i[ ] 1G paging support: no
|
||||
00000000000i[ ] MWAIT support: yes
|
||||
00000000000i[ ] Optimization configuration
|
||||
00000000000i[ ] RepeatSpeedups support: no
|
||||
00000000000i[ ] Fast function calls: no
|
||||
00000000000i[ ] Handlers Chaining speedups: no
|
||||
00000000000i[ ] Devices configuration
|
||||
00000000000i[ ] PCI support: i440FX i430FX
|
||||
00000000000i[ ] Networking: no
|
||||
00000000000i[ ] Sound support: no
|
||||
00000000000i[ ] USB support: UHCI
|
||||
00000000000i[ ] VGA extension support: vbe
|
||||
00000000000i[MEM0 ] allocated memory at 0x7f51d3416010. after alignment, vector=0x7f51d3417000
|
||||
00000000000i[MEM0 ] 32.00MB
|
||||
00000000000i[MEM0 ] mem block size = 0x00020000, blocks=256
|
||||
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('BIOS-bochs-latest')
|
||||
00000000000i[CPU0 ] WARNING: 3DNow! is not implemented yet !
|
||||
00000000000i[PLUGIN] init_dev of 'pci' plugin device by virtual method
|
||||
00000000000i[DEV ] i440FX PMC present at device 0, function 0
|
||||
00000000000i[PLUGIN] init_dev of 'pci2isa' plugin device by virtual method
|
||||
00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
|
||||
00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method
|
||||
00000000000i[CMOS ] Using local time for initial clock
|
||||
00000000000i[CMOS ] Setting initial clock to: Tue May 30 20:29:08 2017 (time0=1496194148)
|
||||
00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method
|
||||
00000000000i[DMA ] channel 4 used by cascade
|
||||
00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'pit' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'vga' plugin device by virtual method
|
||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000000a0000 - 0x0000000bffff
|
||||
00000000000i[VGA ] interval=200000, mode=realtime
|
||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000e0000000 - 0x0000e0ffffff
|
||||
00000000000i[BXVGA ] VBE Bochs Display Extension Enabled
|
||||
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
|
||||
00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24
|
||||
00000000000i[MEM0 ] rom at 0xc0000/38400 ('VGABIOS-lgpl-latest')
|
||||
00000000000i[PLUGIN] init_dev of 'floppy' plugin device by virtual method
|
||||
00000000000i[DMA ] channel 2 used by Floppy Drive
|
||||
00000000000i[FLOPPY] fd0: 'dev_kernel_grub.img' ro=0, h=2,t=80,spt=18
|
||||
00000000000i[FLOPPY] Using boot sequence floppy, none, none
|
||||
00000000000i[FLOPPY] Floppy boot signature check is enabled
|
||||
00000000000i[PLUGIN] init_dev of 'acpi' plugin device by virtual method
|
||||
00000000000i[DEV ] ACPI Controller present at device 1, function 3
|
||||
00000000000i[PLUGIN] init_dev of 'ioapic' plugin device by virtual method
|
||||
00000000000i[IOAPIC] initializing I/O APIC
|
||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000fec00000 - 0x0000fec00fff
|
||||
00000000000i[IOAPIC] IOAPIC enabled (base address = 0xfec00000)
|
||||
00000000000i[PLUGIN] init_dev of 'keyboard' plugin device by virtual method
|
||||
00000000000i[KBD ] will paste characters every 400 keyboard ticks
|
||||
00000000000i[PLUGIN] init_dev of 'harddrv' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method
|
||||
00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1
|
||||
00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'biosdev' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'speaker' plugin device by virtual method
|
||||
00000000000i[PCSPK ] Using /dev/console for output
|
||||
00000000000i[PLUGIN] init_dev of 'extfpuirq' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'parallel' plugin device by virtual method
|
||||
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
|
||||
00000000000i[PLUGIN] init_dev of 'serial' plugin device by virtual method
|
||||
00000000000i[SER ] com1 at 0x03f8 irq 4 (mode: null)
|
||||
00000000000i[PLUGIN] init_dev of 'iodebug' plugin device by virtual method
|
||||
00000000000i[PLUGIN] init_dev of 'usb_uhci' plugin device by virtual method
|
||||
00000000000i[DEV ] USB UHCI present at device 1, function 2
|
||||
00000000000i[UHCI ] USB UHCI initialized
|
||||
00000000000i[PLUGIN] register state of 'pci' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'pci2isa' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'cmos' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'dma' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'pic' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'pit' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'vga' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'floppy' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'unmapped' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'biosdev' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'speaker' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'extfpuirq' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'parallel' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'serial' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'iodebug' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'usb_uhci' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'acpi' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'ioapic' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'keyboard' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'harddrv' plugin device by virtual method
|
||||
00000000000i[PLUGIN] register state of 'pci_ide' plugin device by virtual method
|
||||
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
|
||||
00000000000i[CPU0 ] cpu hardware reset
|
||||
00000000000i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
|
||||
00000000000i[CPU0 ] CPU[0] is the bootstrap processor
|
||||
00000000000i[CPU0 ] CPUID[0x00000000]: 00000005 68747541 444d4163 69746e65
|
||||
00000000000i[CPU0 ] CPUID[0x00000001]: 00000633 00010800 00002008 17cbfbff
|
||||
00000000000i[CPU0 ] CPUID[0x00000002]: 00000000 00000000 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x00000005]: 00000040 00000040 00000003 00000020
|
||||
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 68747541 444d4163 69746e65
|
||||
00000000000i[CPU0 ] CPUID[0x80000001]: 00000633 00000000 00000101 ebd3f3ff
|
||||
00000000000i[CPU0 ] CPUID[0x80000002]: 20444d41 6c687441 74286e6f 7020296d
|
||||
00000000000i[CPU0 ] CPUID[0x80000003]: 65636f72 726f7373 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x80000004]: 00000000 00000000 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x80000005]: 01ff01ff 01ff01ff 40020140 40020140
|
||||
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000
|
||||
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000
|
||||
00000000000i[PLUGIN] reset of 'pci' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'pci2isa' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'cmos' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'dma' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'pic' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'pit' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'vga' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'floppy' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'acpi' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'ioapic' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'keyboard' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'harddrv' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'pci_ide' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'unmapped' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'biosdev' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'speaker' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'extfpuirq' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'parallel' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'serial' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'iodebug' plugin device by virtual method
|
||||
00000000000i[PLUGIN] reset of 'usb_uhci' plugin device by virtual method
|
||||
00000000000i[ ] set SIGINT handler to bx_debug_ctrlc_handler
|
||||
00000003302i[BIOS ] $Revision: 1.209 $ $Date: 2008/06/02 20:08:10 $
|
||||
00000318057i[KBD ] reset-disable command received
|
||||
00000438667i[VBIOS ] VGABios $Id: vgabios.c,v 1.67 2008/01/27 09:44:12 vruppert Exp $
|
||||
00000438738i[BXVGA ] VBE known Display Interface b0c0
|
||||
00000438770i[BXVGA ] VBE known Display Interface b0c4
|
||||
00000441695i[VBIOS ] VBE Bios $Id: vbe.c,v 1.60 2008/03/02 07:47:21 vruppert Exp $
|
||||
00000603836i[XGUI ] charmap update. Font is 9 x 16
|
||||
00000764696i[BIOS ] Starting rombios32
|
||||
00000765523i[BIOS ] ram_size=0x02000000
|
||||
00000805868i[BIOS ] Found 1 cpu(s)
|
||||
00000822169i[BIOS ] bios_table_addr: 0x000fb778 end=0x000fcc00
|
||||
00001281043i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
|
||||
00001740530i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0b
|
||||
00001740577i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x09
|
||||
00001740624i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b
|
||||
00001740671i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x09
|
||||
00001740687i[P2ISA ] write: ELCR2 = 0x0a
|
||||
00001741624i[BIOS ] PIIX3 init: elcr=00 0a
|
||||
00001761969i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237
|
||||
00001765206i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000
|
||||
00001767939i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010
|
||||
00001768400i[PIDE ] new BM-DMA address: 0xc000
|
||||
00001769283i[BIOS ] region 4: 0x0000c000
|
||||
00001771787i[BIOS ] PCI: bus=0 devfn=0x0a: vendor_id=0x8086 device_id=0x7020
|
||||
00001772176i[UHCI ] new base address: 0xc020
|
||||
00001773059i[BIOS ] region 4: 0x0000c020
|
||||
00001773330i[UHCI ] new irq line = 9
|
||||
00001775602i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113
|
||||
00001776102i[ACPI ] new irq line = 11
|
||||
00001776139i[ACPI ] new PM base address: 0xb000
|
||||
00001776201i[ACPI ] new SM base address: 0xb100
|
||||
00001776669i[CPU0 ] Enter to System Management Mode
|
||||
00001776679i[CPU0 ] RSM: Resuming from System Management Mode
|
||||
00001776713i[PCI ] setting SMRAM control register to 0x4a
|
||||
00001776995i[PCI ] setting SMRAM control register to 0x0a
|
||||
00001800276i[BIOS ] MP table addr=0x000fb850 MPC table addr=0x000fb780 size=0xd0
|
||||
00001802479i[BIOS ] SMBIOS table addr=0x000fb860
|
||||
00001805523i[BIOS ] ACPI tables: RSDP addr=0x000fb970 ACPI DATA addr=0x01ff0000 size=0x9d8
|
||||
00001825056i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
|
||||
00001826068i[BIOS ] bios_table_cur_addr: 0x000fb994
|
||||
00014040993i[BIOS ] Booting from 0000:7c00
|
||||
00060731772i[XGUI ] charmap update. Font is 9 x 16
|
||||
00300805704i[XGUI ] charmap update. Font is 9 x 16
|
||||
00547344000p[XGUI ] >>PANIC<< POWER button turned off.
|
||||
00547344000i[CPU0 ] CPU is in protected mode (active)
|
||||
00547344000i[CPU0 ] CS.mode = 32 bit
|
||||
00547344000i[CPU0 ] SS.mode = 32 bit
|
||||
00547344000i[CPU0 ] EFER = 0x00000000
|
||||
00547344000i[CPU0 ] | EAX=00000000 EBX=00101000 ECX=000b8000 EDX=000003d4
|
||||
00547344000i[CPU0 ] | ESP=00102fe0 EBP=00102fe8 ESI=000263d3 EDI=000263df
|
||||
00547344000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
|
||||
00547344000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
|
||||
00547344000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
||||
00547344000i[CPU0 ] | EIP=00100116 (00100116)
|
||||
00547344000i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
|
||||
00547344000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
|
||||
00547344000i[CMOS ] Last time is 1496194284 (Tue May 30 20:31:24 2017)
|
||||
00547344000i[XGUI ] Exit
|
||||
00547344000i[SIM ] quit_sim called with exit code 1
|
|
@ -148,9 +148,6 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
|||
nFreeFrames = _n_frames;
|
||||
info_frame_no = _info_frame_no;
|
||||
n_info_frames = _n_info_frames;
|
||||
|
||||
pools[nPools] = *this;
|
||||
nPools += 1;
|
||||
|
||||
// If _info_frame_no is zero then we keep management info in the first
|
||||
// frame(s), else we use the provided frame(s) to keep management info
|
||||
|
@ -186,23 +183,27 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
|||
{
|
||||
unsigned int i = info_frame_no / 4;
|
||||
unsigned int r = info_frame_no % 4;
|
||||
unsigned char mask = 0xC0;
|
||||
unsigned char mask = 0x80;
|
||||
mask = mask >> r*2;
|
||||
|
||||
unsigned int c = 0;
|
||||
while(c < n_info_frames)
|
||||
{
|
||||
bitmap[i] = bitmap[i] ^ mask;
|
||||
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||
if(mask == 0x02)
|
||||
{
|
||||
i++;
|
||||
mask = 0xC0;
|
||||
mask = 0x80;
|
||||
}
|
||||
c++;
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
pools[nPools] = *this;
|
||||
nPools += 1;
|
||||
|
||||
Console::puts("Frame Pool initialized\n");
|
||||
}
|
||||
|
@ -211,7 +212,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
|||
{
|
||||
// Are there enough frames left to allocate?
|
||||
assert(nFreeFrames > _n_frames);
|
||||
|
||||
|
||||
// Find a frame that is not being used and return its frame index.
|
||||
// Mark that frame as being used in the bitmap.
|
||||
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||
|
@ -226,69 +227,60 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
|||
unsigned int j = 0;
|
||||
unsigned int c = 0;
|
||||
|
||||
// used as a simple way to check if we failed to find a free
|
||||
// frame for an index i in the bitmap.
|
||||
bool failed = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
unsigned char mask = 0x80;
|
||||
unsigned char mask = 0x80 >> (j*2);
|
||||
// check every 2 bits for a free frame in the bitmap
|
||||
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
j++;
|
||||
mask >> 2;
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
failed = true;
|
||||
i++;
|
||||
j = 0;
|
||||
break;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
// if frame is found, start checking for sequence
|
||||
if(!failed)
|
||||
unsigned int temp = i;
|
||||
c++;
|
||||
while(c < _n_frames)
|
||||
{
|
||||
unsigned int temp = i;
|
||||
c++;
|
||||
while(c < _n_frames)
|
||||
if(mask != 0x02)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
mask = mask >> 2;
|
||||
}
|
||||
if(c == _n_frames)
|
||||
else
|
||||
{
|
||||
nFreeFrames -= _n_frames;
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
failed = false;
|
||||
if(c == _n_frames)
|
||||
{
|
||||
nFreeFrames -= _n_frames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame_no += i*4 + j;
|
||||
|
||||
// Update bitmap
|
||||
// First: clear most significant bit to mark head of sequence.
|
||||
bitmap[i] = bitmap[i] ^ (0x80 >> j*2);
|
||||
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||
// Second: clear both bits for all remaining frames in the sequence.
|
||||
c = 1;
|
||||
unsigned char mask = 0x80 >> j*2;
|
||||
|
@ -297,7 +289,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
|||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask >> 2;
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -346,7 +338,7 @@ void ContFramePool::release_frames(unsigned long _frame_no)
|
|||
unsigned int i = 0;
|
||||
while(i < nPools)
|
||||
{
|
||||
if(_frame_no < pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
@ -364,19 +356,24 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
|||
|
||||
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||
|
||||
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||
|
||||
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||
{
|
||||
Console::puts("Error, Frame being released is not being used\n");
|
||||
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||
{
|
||||
Console::puts("Error, Frame being released is not being used\n");
|
||||
assert(false);
|
||||
}
|
||||
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
nFreeFrames++;
|
||||
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask >> 2;
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -388,6 +385,15 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
|||
{
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
bitmap[bitmap_index] ^= (mask >> 1);
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
bitmap_index++;
|
||||
}
|
||||
nFreeFrames++;
|
||||
}
|
||||
}
|
||||
|
|
136
MP2/MP2_Sources/kernel.C
Executable file
136
MP2/MP2_Sources/kernel.C
Executable file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
File: kernel.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 02/02/17
|
||||
|
||||
|
||||
This file has the main entry point to the operating system.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define MB * (0x1 << 20)
|
||||
#define KB * (0x1 << 10)
|
||||
/* Makes things easy to read */
|
||||
|
||||
#define KERNEL_POOL_START_FRAME ((2 MB) / (4 KB))
|
||||
#define KERNEL_POOL_SIZE ((2 MB) / (4 KB))
|
||||
#define PROCESS_POOL_START_FRAME ((4 MB) / (4 KB))
|
||||
#define PROCESS_POOL_SIZE ((28 MB) / (4 KB))
|
||||
/* Definition of the kernel and process memory pools */
|
||||
|
||||
#define MEM_HOLE_START_FRAME ((15 MB) / (4 KB))
|
||||
#define MEM_HOLE_SIZE ((1 MB) / (4 KB))
|
||||
/* We have a 1 MB hole in physical memory starting at address 15 MB */
|
||||
|
||||
#define TEST_START_ADDR_PROC (4 MB)
|
||||
#define TEST_START_ADDR_KERNEL (2 MB)
|
||||
/* Used in the memory test below to generate sequences of memory references. */
|
||||
/* One is for a sequence of memory references in the kernel space, and the */
|
||||
/* other for memory references in the process space. */
|
||||
|
||||
#define N_TEST_ALLOCATIONS
|
||||
/* Number of recursive allocations that we use to test. */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H" /* LOW-LEVEL STUFF */
|
||||
#include "console.H"
|
||||
|
||||
#include "assert.H"
|
||||
#include "cont_frame_pool.H" /* The physical memory manager */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void test_memory(ContFramePool * _pool, unsigned int _allocs_to_go);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MAIN ENTRY INTO THE OS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int main() {
|
||||
|
||||
Console::init();
|
||||
|
||||
/* -- INITIALIZE FRAME POOLS -- */
|
||||
|
||||
/* ---- KERNEL POOL -- */
|
||||
|
||||
ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME,
|
||||
KERNEL_POOL_SIZE,
|
||||
0,
|
||||
0);
|
||||
|
||||
|
||||
/* ---- PROCESS POOL -- */
|
||||
|
||||
//
|
||||
unsigned long n_info_frames = ContFramePool::needed_info_frames(PROCESS_POOL_SIZE);
|
||||
|
||||
unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frames(n_info_frames);
|
||||
|
||||
ContFramePool process_mem_pool(PROCESS_POOL_START_FRAME,
|
||||
PROCESS_POOL_SIZE,
|
||||
process_mem_pool_info_frame,
|
||||
n_info_frames);
|
||||
|
||||
process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE);
|
||||
//
|
||||
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
|
||||
|
||||
Console::puts("Hello World!\n");
|
||||
|
||||
/* -- TEST MEMORY ALLOCATOR */
|
||||
|
||||
test_memory(&kernel_mem_pool, 32);
|
||||
|
||||
/* ---- Add code here to test the frame pool implementation. */
|
||||
|
||||
/* -- NOW LOOP FOREVER */
|
||||
Console::puts("Testing is DONE. We will do nothing forever\n");
|
||||
Console::puts("Feel free to turn off the machine now.\n");
|
||||
|
||||
for(;;);
|
||||
|
||||
/* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void test_memory(ContFramePool * _pool, unsigned int _allocs_to_go) {
|
||||
Console::puts("alloc_to_go = "); Console::puti(_allocs_to_go); Console::puts("\n");
|
||||
if (_allocs_to_go > 0) {
|
||||
int n_frames = _allocs_to_go % 4 + 1;
|
||||
Console::puti(n_frames);
|
||||
unsigned long frame = _pool->get_frames(n_frames);
|
||||
Console::puts("testing.");
|
||||
int * value_array = (int*)(frame * (4 KB));
|
||||
Console::puts("testing.");
|
||||
for (int i = 0; i < (1 KB) * n_frames; i++) {
|
||||
value_array[i] = _allocs_to_go;
|
||||
}
|
||||
test_memory(_pool, _allocs_to_go - 1);
|
||||
for (int i = 0; i < (1 KB) * n_frames; i++) {
|
||||
if(value_array[i] != _allocs_to_go){
|
||||
Console::puts("MEMORY TEST FAILED. ERROR IN FRAME POOL\n");
|
||||
Console::puts("i ="); Console::puti(i);
|
||||
Console::puts(" v = "); Console::puti(value_array[i]);
|
||||
Console::puts(" n ="); Console::puti(_allocs_to_go);
|
||||
Console::puts("\n");
|
||||
for(;;);
|
||||
}
|
||||
}
|
||||
ContFramePool::release_frames(frame);
|
||||
}
|
||||
}
|
||||
|
BIN
MP2/design.odt
Normal file
BIN
MP2/design.odt
Normal file
Binary file not shown.
BIN
MP2/design.pdf
Normal file
BIN
MP2/design.pdf
Normal file
Binary file not shown.
BIN
MP2/mp2.zip
Normal file
BIN
MP2/mp2.zip
Normal file
Binary file not shown.
404
MP2/mp2/cont_frame_pool.C
Normal file
404
MP2/mp2/cont_frame_pool.C
Normal file
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
File: ContFramePool.C
|
||||
|
||||
Author:
|
||||
Date :
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
POSSIBLE IMPLEMENTATION
|
||||
-----------------------
|
||||
|
||||
The class SimpleFramePool in file "simple_frame_pool.H/C" describes an
|
||||
incomplete vanilla implementation of a frame pool that allocates
|
||||
*single* frames at a time. Because it does allocate one frame at a time,
|
||||
it does not guarantee that a sequence of frames is allocated contiguously.
|
||||
This can cause problems.
|
||||
|
||||
The class ContFramePool has the ability to allocate either single frames,
|
||||
or sequences of contiguous frames. This affects how we manage the
|
||||
free frames. In SimpleFramePool it is sufficient to maintain the free
|
||||
frames.
|
||||
In ContFramePool we need to maintain free *sequences* of frames.
|
||||
|
||||
This can be done in many ways, ranging from extensions to bitmaps to
|
||||
free-lists of frames etc.
|
||||
|
||||
IMPLEMENTATION:
|
||||
|
||||
One simple way to manage sequences of free frames is to add a minor
|
||||
extension to the bitmap idea of SimpleFramePool: Instead of maintaining
|
||||
whether a frame is FREE or ALLOCATED, which requires one bit per frame,
|
||||
we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE.
|
||||
The meaning of FREE is the same as in SimpleFramePool.
|
||||
If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated
|
||||
and that it is the first such frame in a sequence of frames. Allocated
|
||||
frames that are not first in a sequence are marked as ALLOCATED.
|
||||
|
||||
NOTE: If we use this scheme to allocate only single frames, then all
|
||||
frames are marked as either FREE or HEAD-OF-SEQUENCE.
|
||||
|
||||
NOTE: In SimpleFramePool we needed only one bit to store the state of
|
||||
each frame. Now we need two bits. In a first implementation you can choose
|
||||
to use one char per frame. This will allow you to check for a given status
|
||||
without having to do bit manipulations. Once you get this to work,
|
||||
revisit the implementation and change it to using two bits. You will get
|
||||
an efficiency penalty if you use one char (i.e., 8 bits) per frame when
|
||||
two bits do the trick.
|
||||
|
||||
DETAILED IMPLEMENTATION:
|
||||
|
||||
How can we use the HEAD-OF-SEQUENCE state to implement a contiguous
|
||||
allocator? Let's look a the individual functions:
|
||||
|
||||
Constructor: Initialize all frames to FREE, except for any frames that you
|
||||
need for the management of the frame pool, if any.
|
||||
|
||||
get_frames(_n_frames): Traverse the "bitmap" of states and look for a
|
||||
sequence of at least _n_frames entries that are FREE. If you find one,
|
||||
mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as
|
||||
ALLOCATED.
|
||||
|
||||
release_frames(_first_frame_no): Check whether the first frame is marked as
|
||||
HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE.
|
||||
Traverse the subsequent frames until you reach one that is FREE or
|
||||
HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE.
|
||||
|
||||
mark_inaccessible(_base_frame_no, _n_frames): This is no different than
|
||||
get_frames, without having to search for the free sequence. You tell the
|
||||
allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many
|
||||
frames after that to mark as ALLOCATED.
|
||||
|
||||
needed_info_frames(_n_frames): This depends on how many bits you need
|
||||
to store the state of each frame. If you use a char to represent the state
|
||||
of a frame, then you need one info frame for each FRAME_SIZE frames.
|
||||
|
||||
A WORD ABOUT RELEASE_FRAMES():
|
||||
|
||||
When we releae a frame, we only know its frame number. At the time
|
||||
of a frame's release, we don't know necessarily which pool it came
|
||||
from. Therefore, the function "release_frame" is static, i.e.,
|
||||
not associated with a particular frame pool.
|
||||
|
||||
This problem is related to the lack of a so-called "placement delete" in
|
||||
C++. For a discussion of this see Stroustrup's FAQ:
|
||||
http://www.stroustrup.com/bs_faq2.html#placement-delete
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "cont_frame_pool.H"
|
||||
#include "console.H"
|
||||
#include "utils.H"
|
||||
#include "assert.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTANTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* METHODS FOR CLASS C o n t F r a m e P o o l */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
ContFramePool* ContFramePool::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
|
||||
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
|
||||
|
||||
ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames,
|
||||
unsigned long _info_frame_no,
|
||||
unsigned long _n_info_frames)
|
||||
{
|
||||
// Bitmap must fit in a single frame!
|
||||
// NOTE: In theory, we don't need to make the bitmap any larger,
|
||||
// since as stated in the instructions it is already big enough to
|
||||
// hold for 128MB of memory with one bit per frame, so should still
|
||||
// be enough for 64MB of memory with 2 bits per frame.
|
||||
// Assertion changed to match max size of frames allowed.
|
||||
assert(_n_frames <= FRAME_SIZE * 4);
|
||||
|
||||
base_frame_no = _base_frame_no;
|
||||
nframes = _n_frames;
|
||||
nFreeFrames = _n_frames;
|
||||
info_frame_no = _info_frame_no;
|
||||
n_info_frames = _n_info_frames;
|
||||
|
||||
// If _info_frame_no is zero then we keep management info in the first
|
||||
// frame(s), else we use the provided frame(s) to keep management info
|
||||
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
|
||||
if(info_frame_no == 0)
|
||||
{
|
||||
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
|
||||
}
|
||||
|
||||
// Number of frames must "fill" the bitmap!
|
||||
assert ((nframes % 8 ) == 0);
|
||||
|
||||
|
||||
// Everything ok. Proceed to mark all bits in the bitmap
|
||||
// NOTE: changed to reflect that I need 2 bits per frame now
|
||||
for(int i=0; i*4 < _n_frames; i++)
|
||||
{
|
||||
bitmap[i] = 0xFF;
|
||||
}
|
||||
|
||||
// Mark the first frame as being used if it is being used
|
||||
// NOTE: need to mark multiple frames if needed.
|
||||
if(info_frame_no == 0)
|
||||
{
|
||||
bitmap[0] = 0x3F;
|
||||
nFreeFrames--;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i = info_frame_no / 4;
|
||||
unsigned int r = info_frame_no % 4;
|
||||
unsigned char mask = 0x80;
|
||||
mask = mask >> r*2;
|
||||
|
||||
unsigned int c = 0;
|
||||
while(c < n_info_frames)
|
||||
{
|
||||
bitmap[i] = bitmap[i] ^ mask;
|
||||
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||
if(mask == 0x02)
|
||||
{
|
||||
i++;
|
||||
mask = 0x80;
|
||||
}
|
||||
c++;
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pools[nPools] = *this;
|
||||
nPools += 1;
|
||||
|
||||
Console::puts("Frame Pool initialized\n");
|
||||
}
|
||||
|
||||
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||
{
|
||||
// Are there enough frames left to allocate?
|
||||
assert(nFreeFrames > _n_frames);
|
||||
|
||||
// Find a frame that is not being used and return its frame index.
|
||||
// Mark that frame as being used in the bitmap.
|
||||
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||
// that are not being used and return the index of the head.
|
||||
unsigned int frame_no = base_frame_no;
|
||||
|
||||
// i is being used as the frame_no / 4
|
||||
// j is frame_no % 4
|
||||
// together, they will give the actual frame_no.
|
||||
// c is used as a counter to count a squence of free frames.
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
unsigned int c = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
unsigned char mask = 0x80 >> (j*2);
|
||||
// check every 2 bits for a free frame in the bitmap
|
||||
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
j++;
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
j = 0;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
// if frame is found, start checking for sequence
|
||||
unsigned int temp = i;
|
||||
c++;
|
||||
while(c < _n_frames)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(c == _n_frames)
|
||||
{
|
||||
nFreeFrames -= _n_frames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame_no += i*4 + j;
|
||||
|
||||
// Update bitmap
|
||||
// First: clear most significant bit to mark head of sequence.
|
||||
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||
// Second: clear both bits for all remaining frames in the sequence.
|
||||
c = 1;
|
||||
unsigned char mask = 0x80 >> j*2;
|
||||
unsigned int temp = i;
|
||||
while(c < _n_frames)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
|
||||
bitmap[temp] = bitmap[temp] ^ mask;
|
||||
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
|
||||
c++;
|
||||
}
|
||||
|
||||
return (frame_no);
|
||||
}
|
||||
|
||||
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames)
|
||||
{
|
||||
// Mark all frames in the range as being used.
|
||||
int i ;
|
||||
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
|
||||
mark_inaccessible(i);
|
||||
}
|
||||
nFreeFrames -= _n_frames;
|
||||
}
|
||||
|
||||
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
|
||||
{
|
||||
// Let's first do a range check.
|
||||
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
|
||||
|
||||
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
|
||||
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
|
||||
|
||||
// Is the frame being used already?
|
||||
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
|
||||
|
||||
// Update bitmap
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
bitmap[bitmap_index] ^= mask >> 1;
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
void ContFramePool::release_frames(unsigned long _frame_no)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while(i < nPools)
|
||||
{
|
||||
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pools[i].release_frames_here(_frame_no);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||
{
|
||||
unsigned char * bitmap = this->bitmap;
|
||||
|
||||
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||
|
||||
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||
{
|
||||
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||
{
|
||||
Console::puts("Error, Frame being released is not being used\n");
|
||||
assert(false);
|
||||
}
|
||||
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
nFreeFrames++;
|
||||
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
bitmap_index++;
|
||||
}
|
||||
|
||||
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
|
||||
{
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
bitmap[bitmap_index] ^= (mask >> 1);
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
bitmap_index++;
|
||||
}
|
||||
nFreeFrames++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
|
||||
{
|
||||
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
|
||||
}
|
132
MP2/mp2/cont_frame_pool.H
Executable file
132
MP2/mp2/cont_frame_pool.H
Executable file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
File: cont_frame_pool.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 17/02/04
|
||||
|
||||
Description: Management of the CONTIGUOUS Free-Frame Pool.
|
||||
|
||||
As opposed to a non-contiguous free-frame pool, here we can allocate
|
||||
a sequence of CONTIGUOUS frames.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CONT_FRAME_POOL_H_ // include file only once
|
||||
#define _CONT_FRAME_POOL_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* C o n t F r a m e P o o l */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class ContFramePool {
|
||||
|
||||
private:
|
||||
/* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */
|
||||
|
||||
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
|
||||
unsigned int nFreeFrames; //
|
||||
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
|
||||
unsigned long nframes; // Size of the frame pool
|
||||
unsigned long info_frame_no; // Where do we store the management information?
|
||||
unsigned long n_info_frames; // Number of frames needed to store management info
|
||||
static ContFramePool* pools; // List of frame pools, managed by the class
|
||||
static unsigned int nPools; // Number of pools being managed
|
||||
|
||||
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
|
||||
// a head, otherwise fails
|
||||
void release_frames_here(unsigned long _frame_no); // non-static member function
|
||||
|
||||
public:
|
||||
|
||||
// The frame size is the same as the page size, duh...
|
||||
static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE;
|
||||
|
||||
ContFramePool(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames,
|
||||
unsigned long _info_frame_no,
|
||||
unsigned long _n_info_frames);
|
||||
/*
|
||||
Initializes the data structures needed for the management of this
|
||||
frame pool.
|
||||
_base_frame_no: Number of first frame managed by this frame pool.
|
||||
_n_frames: Size, in frames, of this frame pool.
|
||||
EXAMPLE: If _base_frame_no is 16 and _n_frames is 4, this frame pool manages
|
||||
physical frames numbered 16, 17, 18 and 19.
|
||||
_info_frame_no: Number of the first frame that should be used to store the
|
||||
management information for the frame pool.
|
||||
NOTE: If _info_frame_no is 0, the frame pool is free to
|
||||
choose any frames from the pool to store management information.
|
||||
_n_info_frames: If _info_frame_no is 0, this argument specifies the
|
||||
number of consecutive frames needed to store the management information
|
||||
for the frame pool.
|
||||
EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3,
|
||||
then Frames 699, 700, and 701 are used to store the management information
|
||||
for the frame pool.
|
||||
NOTE: This function must be called before the paging system
|
||||
is initialized.
|
||||
*/
|
||||
|
||||
unsigned long get_frames(unsigned int _n_frames);
|
||||
/*
|
||||
Allocates a number of contiguous frames from the frame pool.
|
||||
_n_frames: Size of contiguous physical memory to allocate,
|
||||
in number of frames.
|
||||
If successful, returns the frame number of the first frame.
|
||||
If fails, returns 0.
|
||||
*/
|
||||
|
||||
void mark_inaccessible(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames);
|
||||
/*
|
||||
Marks a contiguous area of physical memory, i.e., a contiguous
|
||||
sequence of frames, as inaccessible.
|
||||
_base_frame_no: Number of first frame to mark as inaccessible.
|
||||
_n_frames: Number of contiguous frames to mark as inaccessible.
|
||||
*/
|
||||
|
||||
static void release_frames(unsigned long _frame_no);
|
||||
/*
|
||||
Releases a previously allocated contiguous sequence of frames
|
||||
back to its frame pool.
|
||||
The frame sequence is identified by the number of the first frame.
|
||||
NOTE: This function is static because there may be more than one frame pool
|
||||
defined in the system, and it is unclear which one this frame belongs to.
|
||||
This function must first identify the correct frame pool and then call the frame
|
||||
pool's release_frame function.
|
||||
*/
|
||||
|
||||
static unsigned long needed_info_frames(unsigned long _n_frames);
|
||||
/*
|
||||
Returns the number of frames needed to manage a frame pool of size _n_frames.
|
||||
The number returned here depends on the implementation of the frame pool and
|
||||
on the frame size.
|
||||
EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame
|
||||
(not appropriate for contiguous allocation) one would need one frame to manage a
|
||||
frame pool with up to 8 * 4096 = 32k frames = 128MB of memory!
|
||||
This function would therefore return the following value:
|
||||
_n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!)
|
||||
Other implementations need a different number of info frames.
|
||||
The exact number is computed in this function..
|
||||
*/
|
||||
};
|
||||
#endif
|
BIN
MP2/mp2/design.pdf
Normal file
BIN
MP2/mp2/design.pdf
Normal file
Binary file not shown.
BIN
MP3/MP3_Sources.zip
Normal file
BIN
MP3/MP3_Sources.zip
Normal file
Binary file not shown.
BIN
MP3/MP3_Sources/BIOS-bochs-latest
Executable file
BIN
MP3/MP3_Sources/BIOS-bochs-latest
Executable file
Binary file not shown.
101
MP3/MP3_Sources/README.TXT
Executable file
101
MP3/MP3_Sources/README.TXT
Executable file
|
@ -0,0 +1,101 @@
|
|||
CSCE 410/611/613: MP2 -- README.TXT
|
||||
|
||||
This file describes the content of this directory.
|
||||
A file marked with (*) may be of some interest to the
|
||||
student, and he/she may want to have a look at it.
|
||||
A file marked with (**) is important for this MP, and the
|
||||
student is strongly encouraged to study the contents of this file.
|
||||
|
||||
BOCH Environment:
|
||||
=================
|
||||
|
||||
FILE: DESCRIPTION:
|
||||
|
||||
BIOS-bochs-latest BIOS file.
|
||||
VGABIOS-lgpl-latest BIOS file for the graphics system.
|
||||
dev_kernel_grub.img Image file of the boot floopy.
|
||||
bochsrc.bxrc Description file for the system.
|
||||
Type 'bochs -f bochsrc.bxrc' to
|
||||
start emulation.
|
||||
|
||||
COMPILATION:
|
||||
===========
|
||||
|
||||
FILE: DESCRIPTION:
|
||||
|
||||
makefile (**) Makefile for Linux 64-bit environment.
|
||||
Works with the provided linux image.
|
||||
Type "make" to create the kernel.
|
||||
linker.ld The linker script.
|
||||
|
||||
OS COMPONENTS:
|
||||
=============
|
||||
|
||||
FILE: DESCRIPTION:
|
||||
|
||||
start.asm (*) The bootloader starts code in this file, which in turn
|
||||
jumps to the main entry in File "kernel.C".
|
||||
kernel.C (**) Main file, where the OS components are set up, and the
|
||||
system gets going.
|
||||
|
||||
assert.H/C Implements the "assert()" utility.
|
||||
utils.H/C Various utilities (e.g. memcpy, strlen,
|
||||
port I/O, etc.)
|
||||
console.H/C Routines to print to the screen.
|
||||
|
||||
machine.H (*) Definitions of some system constants and low-level
|
||||
machine operations.
|
||||
(Primarily memory sizes, register set, and
|
||||
enable/disable interrupts)
|
||||
gdt.H/C Global Descriptor Table.
|
||||
gdt_low.asm Low-level GDT code, included in "start.asm".
|
||||
idt.H/C Interrupt Descriptor Table.
|
||||
idt_low.asm Low-level IDT code, included in "start.asm".
|
||||
irq.H/C mapping of IRQ's into the IDT.
|
||||
irq_low.asm Low-level IRQ stuff. (Primarily the interrupt service
|
||||
routines and the routine stub that branches out to the
|
||||
interrupt dispatcher in "interrupts.C". Included in
|
||||
"start.asm".
|
||||
|
||||
exceptions.H/C (*) The exception dispatcher.
|
||||
interrupts.H/C The interrupt dispatcher.
|
||||
|
||||
console.H/C Routines to print to the screen.
|
||||
|
||||
simple_timer.H/C (*) Routines to control the periodic interval
|
||||
timer. This is an example of an interrupt
|
||||
handler.
|
||||
|
||||
simple_keyboard.H/C(*) Routines to access the keyboard. Primarily as
|
||||
way to wait until user presses key.
|
||||
|
||||
machine_low.H/asm Various low-level x86 specific stuff.
|
||||
|
||||
paging_low.H/asm (**) Low-level code to control the registers needed for
|
||||
memory paging.
|
||||
|
||||
page_table.H/C (**) Definition and empty implementation of a
|
||||
page table manager. In addition to interface,
|
||||
the .H file defines a few private members that
|
||||
should guide the implementation.
|
||||
|
||||
cont_frame_pool.H/C(**) Definition and empty implementation of a
|
||||
physical frame memory manager that
|
||||
supports contiguous
|
||||
allocation. NOTE that the comments in
|
||||
the implementation file give a recipe
|
||||
of how to implement such a frame pool.
|
||||
|
||||
|
||||
UTILITIES:
|
||||
==========
|
||||
|
||||
FILE: DESCRIPTION:
|
||||
|
||||
copykernel.sh (**) Simple script to copy the kernel onto
|
||||
the floppy image.
|
||||
The script mounts the floppy image, copies the kernel
|
||||
image onto it, and then unmounts the floppy image again.
|
||||
In rare cases the paths in the file may need to be
|
||||
edited to make them reflect the student's environment.
|
||||
|
BIN
MP3/MP3_Sources/VGABIOS-lgpl-latest
Executable file
BIN
MP3/MP3_Sources/VGABIOS-lgpl-latest
Executable file
Binary file not shown.
45
MP3/MP3_Sources/assert.C
Executable file
45
MP3/MP3_Sources/assert.C
Executable file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
File: assert.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
|
||||
Date : 05/01/23
|
||||
|
||||
Implementation of the assert() function.
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
|
||||
#include "utils.H"
|
||||
#include "console.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* _assert() FUNCTION: gets called when assert() macro fails. */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void _assert (const char* _file, const int _line, const char* _message ) {
|
||||
/* Prints current file, line number, and failed assertion. */
|
||||
char temp[15];
|
||||
Console::puts("Assertion failed at file: ");
|
||||
Console::puts(_file);
|
||||
Console::puts(" line: ");
|
||||
int2str(_line, temp);
|
||||
Console::puts(temp);
|
||||
Console::puts(" assertion: ");
|
||||
Console::puts(_message);
|
||||
Console::puts("\n");
|
||||
abort();
|
||||
}/* end _assert */
|
56
MP3/MP3_Sources/assert.H
Executable file
56
MP3/MP3_Sources/assert.H
Executable file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
File: assert.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
|
||||
Date : 05/01/23
|
||||
|
||||
Header file for the "assert" macro.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __assert_H__
|
||||
#define __assert_H__
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "utils.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTANTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* "ASSERT" MACRO */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* NOTE: The "assert" macros can be turned off by giving the -DNDEBUG
|
||||
argument when compiling. */
|
||||
|
||||
#ifdef assert
|
||||
# undef assert
|
||||
#endif
|
||||
|
||||
void _assert ( const char* _file, const int _line, const char* _message );
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define assert( m ) ( ( void ) 0 )
|
||||
#else
|
||||
# define assert( m ) \
|
||||
if ( !(m) ) _assert( __FILE__, __LINE__, #m );
|
||||
#endif
|
||||
|
||||
#endif
|
48
MP3/MP3_Sources/bochsrc.bxrc
Executable file
48
MP3/MP3_Sources/bochsrc.bxrc
Executable file
|
@ -0,0 +1,48 @@
|
|||
###############################################################
|
||||
# bochsrc.txt file for DLX Linux disk image.
|
||||
###############################################################
|
||||
|
||||
# how much memory the emulated machine will have
|
||||
megs: 32
|
||||
|
||||
# filename of ROM images
|
||||
romimage: file=BIOS-bochs-latest
|
||||
vgaromimage: file=VGABIOS-lgpl-latest
|
||||
|
||||
# what disk images will be used
|
||||
floppya: 1_44=dev_kernel_grub.img, status=inserted
|
||||
#floppyb: 1_44=floppyb.img, status=inserted
|
||||
|
||||
# hard disk
|
||||
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
#ata0-master: type=disk, path="c.img", cylinders=306, heads=4, spt=17
|
||||
# choose the boot disk.
|
||||
boot: floppy
|
||||
|
||||
# default config interface is textconfig.
|
||||
#config_interface: textconfig
|
||||
#config_interface: wx
|
||||
|
||||
#display_library: x
|
||||
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga
|
||||
|
||||
# where do we send log messages?
|
||||
log: bochsout.txt
|
||||
|
||||
# disable the mouse
|
||||
mouse: enabled=0
|
||||
|
||||
# enable key mapping, using US layout as default.
|
||||
#
|
||||
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
|
||||
# However, the key mapping tables are used in the paste function, so
|
||||
# in the DLX Linux example I'm enabling keyboard_mapping so that paste
|
||||
# will work. Cut&Paste is currently implemented on win32 and X windows only.
|
||||
|
||||
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
|
||||
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map
|
||||
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map
|
||||
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map
|
||||
|
||||
|
||||
clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000
|
213
MP3/MP3_Sources/console.C
Executable file
213
MP3/MP3_Sources/console.C
Executable file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
File: Console.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/02/2009
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define CONSOLE_START_ADDRESS (unsigned short *)0xB8000
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "console.H"
|
||||
|
||||
#include "utils.H"
|
||||
#include "machine.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTANTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* METHODS FOR CLASS C o n s o l e */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- GLOBAL VARIABLES -- */
|
||||
|
||||
int Console::attrib; /* background and foreground color */
|
||||
int Console::csr_x; /* position of cursor */
|
||||
int Console::csr_y;
|
||||
unsigned short * Console::textmemptr; /* text pointer */
|
||||
|
||||
/* -- CONSTRUCTOR -- */
|
||||
|
||||
void Console::init(unsigned char _fore_color,
|
||||
unsigned char _back_color) {
|
||||
set_TextColor(_fore_color, _back_color);
|
||||
csr_x = 0;
|
||||
csr_y = 0;
|
||||
textmemptr = CONSOLE_START_ADDRESS;
|
||||
cls();
|
||||
}
|
||||
|
||||
|
||||
void Console::scroll() {
|
||||
|
||||
/* A blank is defined as a space... we need to give it
|
||||
* backcolor too */
|
||||
unsigned blank = 0x20 | (attrib << 8);
|
||||
|
||||
/* Row 25 is the end, this means we need to scroll up */
|
||||
if(csr_y >= 25)
|
||||
{
|
||||
/* Move the current text chunk that makes up the screen
|
||||
* back in the buffer by a line */
|
||||
unsigned temp = csr_y - 25 + 1;
|
||||
memcpy ((char*)textmemptr, (char*)(textmemptr + temp * 80), (25 - temp) * 80 * 2);
|
||||
|
||||
/* Finally, we set the chunk of memory that occupies
|
||||
* the last line of text to our 'blank' character */
|
||||
memsetw (textmemptr + (25 - temp) * 80, blank, 80);
|
||||
csr_y = 25 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Console::move_cursor() {
|
||||
|
||||
/* The equation for finding the index in a linear
|
||||
* chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x] */
|
||||
unsigned temp = csr_y * 80 + csr_x;
|
||||
|
||||
/* This sends a command to indicies 14 and 15 in the
|
||||
* Console Control Register of the VGA controller. These
|
||||
* are the high and low bytes of the index that show
|
||||
* where the hardware cursor is to be 'blinking'. To
|
||||
* learn more, you should look up some VGA specific
|
||||
* programming documents. A great start to graphics:
|
||||
* http://www.brackeen.com/home/vga */
|
||||
Machine::outportb(0x3D4, (char)14);
|
||||
//outportb(0x3D5, temp >> 8);
|
||||
Machine::outportb(0x3D4, 15);
|
||||
//outportb(0x3D5, (char)temp);
|
||||
}
|
||||
|
||||
/* Clear the screen */
|
||||
void Console::cls() {
|
||||
|
||||
/* Again, we need the 'short' that will be used to
|
||||
* represent a space with color */
|
||||
unsigned blank = 0x20 | (attrib << 8);
|
||||
|
||||
/* Sets the entire screen to spaces in our current
|
||||
* color */
|
||||
for(int i = 0; i < 25; i++)
|
||||
memsetw (textmemptr + i * 80, blank, 80);
|
||||
|
||||
/* Update out virtual cursor, and then move the
|
||||
* hardware cursor */
|
||||
csr_x = 0;
|
||||
csr_y = 0;
|
||||
move_cursor();
|
||||
}
|
||||
|
||||
/* Puts a single character on the screen */
|
||||
void Console::putch(const char _c){
|
||||
|
||||
|
||||
/* Handle a backspace, by moving the cursor back one space */
|
||||
if(_c == 0x08)
|
||||
{
|
||||
if(csr_x != 0) csr_x--;
|
||||
}
|
||||
/* Handles a tab by incrementing the cursor's x, but only
|
||||
* to a point that will make it divisible by 8 */
|
||||
else if(_c == 0x09)
|
||||
{
|
||||
csr_x = (csr_x + 8) & ~(8 - 1);
|
||||
}
|
||||
/* Handles a 'Carriage Return', which simply brings the
|
||||
* cursor back to the margin */
|
||||
else if(_c == '\r')
|
||||
{
|
||||
csr_x = 0;
|
||||
}
|
||||
/* We handle our newlines the way DOS and the BIOS do: we
|
||||
* treat it as if a 'CR' was also there, so we bring the
|
||||
* cursor to the margin and we increment the 'y' value */
|
||||
else if(_c == '\n')
|
||||
{
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
/* Any character greater than and including a space, is a
|
||||
* printable character. The equation for finding the index
|
||||
* in a linear chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x] */
|
||||
else if(_c >= ' ')
|
||||
{
|
||||
unsigned short * where = textmemptr + (csr_y * 80 + csr_x);
|
||||
*where = _c | (attrib << 8); /* Character AND attributes: color */
|
||||
csr_x++;
|
||||
}
|
||||
|
||||
/* If the cursor has reached the edge of the screen's width, we
|
||||
* insert a new line in there */
|
||||
if(csr_x >= 80)
|
||||
{
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/* Scroll the screen if needed, and finally move the cursor */
|
||||
scroll();
|
||||
move_cursor();
|
||||
}
|
||||
|
||||
/* Uses the above routine to output a string... */
|
||||
void Console::puts(const char * _s) {
|
||||
|
||||
for (int i = 0; i < strlen(_s); i++) {
|
||||
putch(_s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Console::puti(const int _n) {
|
||||
char foostr[15];
|
||||
|
||||
int2str(_n, foostr);
|
||||
puts(foostr);
|
||||
}
|
||||
|
||||
void Console::putui(const unsigned int _n) {
|
||||
char foostr[15];
|
||||
|
||||
uint2str(_n, foostr);
|
||||
putch('<');
|
||||
puts(foostr);
|
||||
putch('>');
|
||||
}
|
||||
|
||||
|
||||
/* -- COLOR CONTROL -- */
|
||||
void Console::set_TextColor(const unsigned char _forecolor,
|
||||
const unsigned char _backcolor) {
|
||||
/* Top 4 bytes are the background, bottom 4 bytes
|
||||
* are the foreground color */
|
||||
attrib = (_backcolor << 4) | (_forecolor & 0x0F);
|
||||
}
|
||||
|
113
MP3/MP3_Sources/console.H
Executable file
113
MP3/MP3_Sources/console.H
Executable file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
File: Console.H
|
||||
|
||||
Author : R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/02/12
|
||||
|
||||
The class Console encapsulates the output operations ot the console
|
||||
screen. Since the console is initialized at the very beginning of the
|
||||
boot-up of the operating system, when no memory management is available
|
||||
yet, all functions and storage for the console are static.
|
||||
|
||||
The console is initialized with an "init" function instead of a
|
||||
constructor. (We don't want to deal with constructors that are called
|
||||
before the "main()" function.)
|
||||
|
||||
By making all functions static, we can access them across all object
|
||||
files without having to declare a global Console object or pass pointers
|
||||
to a locally declared object.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _Console_H_ // include file only once
|
||||
#define _Console_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
typedef enum {
|
||||
BLACK = 0,
|
||||
BLUE = 1,
|
||||
GREEN = 2,
|
||||
CYAN = 3,
|
||||
RED = 4,
|
||||
MAGENTA = 5,
|
||||
BROWN = 6,
|
||||
LIGHT_GREY = 7,
|
||||
DARK_GREY = 8,
|
||||
LIGHT_BLUE = 9,
|
||||
LIGHT_GREEN = 10,
|
||||
LIGHT_CYAN = 11,
|
||||
LIGHT_RED = 12,
|
||||
LIGHT_MAGENTA = 13,
|
||||
LIGHT_BROWN = 14,
|
||||
WHITE = 15
|
||||
} COLOR_CODE;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CLASS C o n s o l e */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class Console {
|
||||
private:
|
||||
static int attrib; /* background and foreground color */
|
||||
static int csr_x; /* position of cursor */
|
||||
static int csr_y;
|
||||
static unsigned short * textmemptr; /* text pointer */
|
||||
public:
|
||||
|
||||
/* -- INITIALIZER (we have no constructor, there is no memory mgmt yet.) */
|
||||
static void init(unsigned char _fore_color = WHITE,
|
||||
unsigned char _back_color = BLACK);
|
||||
|
||||
static void scroll();
|
||||
|
||||
static void move_cursor();
|
||||
/* Update the hardware cursor. */
|
||||
|
||||
static void cls();
|
||||
/* Clear the screen. */
|
||||
|
||||
static void putch(const char _c);
|
||||
/* Put a single character on the screen. */
|
||||
|
||||
static void puts(const char * _s);
|
||||
/* Display a NULL-terminated string on the screen.*/
|
||||
|
||||
static void puti(const int _i);
|
||||
/* Display a integer on the screen.*/
|
||||
|
||||
static void putui(const unsigned int _u);
|
||||
/* Display a unsigned integer on the screen.*/
|
||||
|
||||
static void set_TextColor(unsigned char _fore_color, unsigned char _back_color);
|
||||
/* Set the color of the foreground and background. */
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
404
MP3/MP3_Sources/cont_frame_pool.C
Normal file
404
MP3/MP3_Sources/cont_frame_pool.C
Normal file
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
File: ContFramePool.C
|
||||
|
||||
Author:
|
||||
Date :
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
POSSIBLE IMPLEMENTATION
|
||||
-----------------------
|
||||
|
||||
The class SimpleFramePool in file "simple_frame_pool.H/C" describes an
|
||||
incomplete vanilla implementation of a frame pool that allocates
|
||||
*single* frames at a time. Because it does allocate one frame at a time,
|
||||
it does not guarantee that a sequence of frames is allocated contiguously.
|
||||
This can cause problems.
|
||||
|
||||
The class ContFramePool has the ability to allocate either single frames,
|
||||
or sequences of contiguous frames. This affects how we manage the
|
||||
free frames. In SimpleFramePool it is sufficient to maintain the free
|
||||
frames.
|
||||
In ContFramePool we need to maintain free *sequences* of frames.
|
||||
|
||||
This can be done in many ways, ranging from extensions to bitmaps to
|
||||
free-lists of frames etc.
|
||||
|
||||
IMPLEMENTATION:
|
||||
|
||||
One simple way to manage sequences of free frames is to add a minor
|
||||
extension to the bitmap idea of SimpleFramePool: Instead of maintaining
|
||||
whether a frame is FREE or ALLOCATED, which requires one bit per frame,
|
||||
we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE.
|
||||
The meaning of FREE is the same as in SimpleFramePool.
|
||||
If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated
|
||||
and that it is the first such frame in a sequence of frames. Allocated
|
||||
frames that are not first in a sequence are marked as ALLOCATED.
|
||||
|
||||
NOTE: If we use this scheme to allocate only single frames, then all
|
||||
frames are marked as either FREE or HEAD-OF-SEQUENCE.
|
||||
|
||||
NOTE: In SimpleFramePool we needed only one bit to store the state of
|
||||
each frame. Now we need two bits. In a first implementation you can choose
|
||||
to use one char per frame. This will allow you to check for a given status
|
||||
without having to do bit manipulations. Once you get this to work,
|
||||
revisit the implementation and change it to using two bits. You will get
|
||||
an efficiency penalty if you use one char (i.e., 8 bits) per frame when
|
||||
two bits do the trick.
|
||||
|
||||
DETAILED IMPLEMENTATION:
|
||||
|
||||
How can we use the HEAD-OF-SEQUENCE state to implement a contiguous
|
||||
allocator? Let's look a the individual functions:
|
||||
|
||||
Constructor: Initialize all frames to FREE, except for any frames that you
|
||||
need for the management of the frame pool, if any.
|
||||
|
||||
get_frames(_n_frames): Traverse the "bitmap" of states and look for a
|
||||
sequence of at least _n_frames entries that are FREE. If you find one,
|
||||
mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as
|
||||
ALLOCATED.
|
||||
|
||||
release_frames(_first_frame_no): Check whether the first frame is marked as
|
||||
HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE.
|
||||
Traverse the subsequent frames until you reach one that is FREE or
|
||||
HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE.
|
||||
|
||||
mark_inaccessible(_base_frame_no, _n_frames): This is no different than
|
||||
get_frames, without having to search for the free sequence. You tell the
|
||||
allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many
|
||||
frames after that to mark as ALLOCATED.
|
||||
|
||||
needed_info_frames(_n_frames): This depends on how many bits you need
|
||||
to store the state of each frame. If you use a char to represent the state
|
||||
of a frame, then you need one info frame for each FRAME_SIZE frames.
|
||||
|
||||
A WORD ABOUT RELEASE_FRAMES():
|
||||
|
||||
When we releae a frame, we only know its frame number. At the time
|
||||
of a frame's release, we don't know necessarily which pool it came
|
||||
from. Therefore, the function "release_frame" is static, i.e.,
|
||||
not associated with a particular frame pool.
|
||||
|
||||
This problem is related to the lack of a so-called "placement delete" in
|
||||
C++. For a discussion of this see Stroustrup's FAQ:
|
||||
http://www.stroustrup.com/bs_faq2.html#placement-delete
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "cont_frame_pool.H"
|
||||
#include "console.H"
|
||||
#include "utils.H"
|
||||
#include "assert.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTANTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* METHODS FOR CLASS C o n t F r a m e P o o l */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
ContFramePool* ContFramePool::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
|
||||
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
|
||||
|
||||
ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames,
|
||||
unsigned long _info_frame_no,
|
||||
unsigned long _n_info_frames)
|
||||
{
|
||||
// Bitmap must fit in a single frame!
|
||||
// NOTE: In theory, we don't need to make the bitmap any larger,
|
||||
// since as stated in the instructions it is already big enough to
|
||||
// hold for 128MB of memory with one bit per frame, so should still
|
||||
// be enough for 64MB of memory with 2 bits per frame.
|
||||
// Assertion changed to match max size of frames allowed.
|
||||
assert(_n_frames <= FRAME_SIZE * 4);
|
||||
|
||||
base_frame_no = _base_frame_no;
|
||||
nframes = _n_frames;
|
||||
nFreeFrames = _n_frames;
|
||||
info_frame_no = _info_frame_no;
|
||||
n_info_frames = _n_info_frames;
|
||||
|
||||
// If _info_frame_no is zero then we keep management info in the first
|
||||
// frame(s), else we use the provided frame(s) to keep management info
|
||||
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
|
||||
if(info_frame_no == 0)
|
||||
{
|
||||
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
|
||||
}
|
||||
|
||||
// Number of frames must "fill" the bitmap!
|
||||
assert ((nframes % 8 ) == 0);
|
||||
|
||||
|
||||
// Everything ok. Proceed to mark all bits in the bitmap
|
||||
// NOTE: changed to reflect that I need 2 bits per frame now
|
||||
for(int i=0; i*4 < _n_frames; i++)
|
||||
{
|
||||
bitmap[i] = 0xFF;
|
||||
}
|
||||
|
||||
// Mark the first frame as being used if it is being used
|
||||
// NOTE: need to mark multiple frames if needed.
|
||||
if(info_frame_no == 0)
|
||||
{
|
||||
bitmap[0] = 0x3F;
|
||||
nFreeFrames--;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i = info_frame_no / 4;
|
||||
unsigned int r = info_frame_no % 4;
|
||||
unsigned char mask = 0x80;
|
||||
mask = mask >> r*2;
|
||||
|
||||
unsigned int c = 0;
|
||||
while(c < n_info_frames)
|
||||
{
|
||||
bitmap[i] = bitmap[i] ^ mask;
|
||||
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||
if(mask == 0x02)
|
||||
{
|
||||
i++;
|
||||
mask = 0x80;
|
||||
}
|
||||
c++;
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pools[nPools] = *this;
|
||||
nPools += 1;
|
||||
|
||||
Console::puts("Frame Pool initialized\n");
|
||||
}
|
||||
|
||||
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||
{
|
||||
// Are there enough frames left to allocate?
|
||||
assert(nFreeFrames > _n_frames);
|
||||
|
||||
// Find a frame that is not being used and return its frame index.
|
||||
// Mark that frame as being used in the bitmap.
|
||||
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||
// that are not being used and return the index of the head.
|
||||
unsigned int frame_no = base_frame_no;
|
||||
|
||||
// i is being used as the frame_no / 4
|
||||
// j is frame_no % 4
|
||||
// together, they will give the actual frame_no.
|
||||
// c is used as a counter to count a squence of free frames.
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
unsigned int c = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
unsigned char mask = 0x80 >> (j*2);
|
||||
// check every 2 bits for a free frame in the bitmap
|
||||
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
j++;
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
j = 0;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
// if frame is found, start checking for sequence
|
||||
unsigned int temp = i;
|
||||
c++;
|
||||
while(c < _n_frames)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(c == _n_frames)
|
||||
{
|
||||
nFreeFrames -= _n_frames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame_no += i*4 + j;
|
||||
|
||||
// Update bitmap
|
||||
// First: clear most significant bit to mark head of sequence.
|
||||
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||
// Second: clear both bits for all remaining frames in the sequence.
|
||||
c = 1;
|
||||
unsigned char mask = 0x80 >> j*2;
|
||||
unsigned int temp = i;
|
||||
while(c < _n_frames)
|
||||
{
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp++;
|
||||
mask = 0x80;
|
||||
}
|
||||
|
||||
bitmap[temp] = bitmap[temp] ^ mask;
|
||||
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
|
||||
c++;
|
||||
}
|
||||
|
||||
return (frame_no);
|
||||
}
|
||||
|
||||
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames)
|
||||
{
|
||||
// Mark all frames in the range as being used.
|
||||
int i ;
|
||||
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
|
||||
mark_inaccessible(i);
|
||||
}
|
||||
nFreeFrames -= _n_frames;
|
||||
}
|
||||
|
||||
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
|
||||
{
|
||||
// Let's first do a range check.
|
||||
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
|
||||
|
||||
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
|
||||
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
|
||||
|
||||
// Is the frame being used already?
|
||||
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
|
||||
|
||||
// Update bitmap
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
bitmap[bitmap_index] ^= mask >> 1;
|
||||
nFreeFrames--;
|
||||
}
|
||||
|
||||
void ContFramePool::release_frames(unsigned long _frame_no)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while(i < nPools)
|
||||
{
|
||||
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pools[i].release_frames_here(_frame_no);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||
{
|
||||
unsigned char * bitmap = this->bitmap;
|
||||
|
||||
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||
|
||||
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||
{
|
||||
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||
{
|
||||
Console::puts("Error, Frame being released is not being used\n");
|
||||
assert(false);
|
||||
}
|
||||
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
nFreeFrames++;
|
||||
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
bitmap_index++;
|
||||
}
|
||||
|
||||
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
|
||||
{
|
||||
bitmap[bitmap_index] ^= mask;
|
||||
bitmap[bitmap_index] ^= (mask >> 1);
|
||||
if(mask != 0x02)
|
||||
{
|
||||
mask = mask >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
bitmap_index++;
|
||||
}
|
||||
nFreeFrames++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
|
||||
{
|
||||
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
|
||||
}
|
132
MP3/MP3_Sources/cont_frame_pool.H
Executable file
132
MP3/MP3_Sources/cont_frame_pool.H
Executable file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
File: cont_frame_pool.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 17/02/04
|
||||
|
||||
Description: Management of the CONTIGUOUS Free-Frame Pool.
|
||||
|
||||
As opposed to a non-contiguous free-frame pool, here we can allocate
|
||||
a sequence of CONTIGUOUS frames.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CONT_FRAME_POOL_H_ // include file only once
|
||||
#define _CONT_FRAME_POOL_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* C o n t F r a m e P o o l */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class ContFramePool {
|
||||
|
||||
private:
|
||||
/* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */
|
||||
|
||||
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
|
||||
unsigned int nFreeFrames; //
|
||||
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
|
||||
unsigned long nframes; // Size of the frame pool
|
||||
unsigned long info_frame_no; // Where do we store the management information?
|
||||
unsigned long n_info_frames; // Number of frames needed to store management info
|
||||
static ContFramePool* pools; // List of frame pools, managed by the class
|
||||
static unsigned int nPools; // Number of pools being managed
|
||||
|
||||
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
|
||||
// a head, otherwise fails
|
||||
void release_frames_here(unsigned long _frame_no); // non-static member function
|
||||
|
||||
public:
|
||||
|
||||
// The frame size is the same as the page size, duh...
|
||||
static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE;
|
||||
|
||||
ContFramePool(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames,
|
||||
unsigned long _info_frame_no,
|
||||
unsigned long _n_info_frames);
|
||||
/*
|
||||
Initializes the data structures needed for the management of this
|
||||
frame pool.
|
||||
_base_frame_no: Number of first frame managed by this frame pool.
|
||||
_n_frames: Size, in frames, of this frame pool.
|
||||
EXAMPLE: If _base_frame_no is 16 and _n_frames is 4, this frame pool manages
|
||||
physical frames numbered 16, 17, 18 and 19.
|
||||
_info_frame_no: Number of the first frame that should be used to store the
|
||||
management information for the frame pool.
|
||||
NOTE: If _info_frame_no is 0, the frame pool is free to
|
||||
choose any frames from the pool to store management information.
|
||||
_n_info_frames: If _info_frame_no is 0, this argument specifies the
|
||||
number of consecutive frames needed to store the management information
|
||||
for the frame pool.
|
||||
EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3,
|
||||
then Frames 699, 700, and 701 are used to store the management information
|
||||
for the frame pool.
|
||||
NOTE: This function must be called before the paging system
|
||||
is initialized.
|
||||
*/
|
||||
|
||||
unsigned long get_frames(unsigned int _n_frames);
|
||||
/*
|
||||
Allocates a number of contiguous frames from the frame pool.
|
||||
_n_frames: Size of contiguous physical memory to allocate,
|
||||
in number of frames.
|
||||
If successful, returns the frame number of the first frame.
|
||||
If fails, returns 0.
|
||||
*/
|
||||
|
||||
void mark_inaccessible(unsigned long _base_frame_no,
|
||||
unsigned long _n_frames);
|
||||
/*
|
||||
Marks a contiguous area of physical memory, i.e., a contiguous
|
||||
sequence of frames, as inaccessible.
|
||||
_base_frame_no: Number of first frame to mark as inaccessible.
|
||||
_n_frames: Number of contiguous frames to mark as inaccessible.
|
||||
*/
|
||||
|
||||
static void release_frames(unsigned long _frame_no);
|
||||
/*
|
||||
Releases a previously allocated contiguous sequence of frames
|
||||
back to its frame pool.
|
||||
The frame sequence is identified by the number of the first frame.
|
||||
NOTE: This function is static because there may be more than one frame pool
|
||||
defined in the system, and it is unclear which one this frame belongs to.
|
||||
This function must first identify the correct frame pool and then call the frame
|
||||
pool's release_frame function.
|
||||
*/
|
||||
|
||||
static unsigned long needed_info_frames(unsigned long _n_frames);
|
||||
/*
|
||||
Returns the number of frames needed to manage a frame pool of size _n_frames.
|
||||
The number returned here depends on the implementation of the frame pool and
|
||||
on the frame size.
|
||||
EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame
|
||||
(not appropriate for contiguous allocation) one would need one frame to manage a
|
||||
frame pool with up to 8 * 4096 = 32k frames = 128MB of memory!
|
||||
This function would therefore return the following value:
|
||||
_n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!)
|
||||
Other implementations need a different number of info frames.
|
||||
The exact number is computed in this function..
|
||||
*/
|
||||
};
|
||||
#endif
|
5
MP3/MP3_Sources/copykernel.sh
Executable file
5
MP3/MP3_Sources/copykernel.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
# Replace "/mnt/floppy" with the whatever directory is appropriate.
|
||||
sudo mount -o loop dev_kernel_grub.img /mnt/floppy
|
||||
sudo cp kernel.bin /mnt/floppy
|
||||
sleep 1s
|
||||
sudo umount /mnt/floppy
|
BIN
MP1/MP1_Sources/dev_kernel_grub.img → MP3/MP3_Sources/dev_kernel_grub.img
Normal file → Executable file
BIN
MP1/MP1_Sources/dev_kernel_grub.img → MP3/MP3_Sources/dev_kernel_grub.img
Normal file → Executable file
Binary file not shown.
183
MP3/MP3_Sources/exceptions.C
Executable file
183
MP3/MP3_Sources/exceptions.C
Executable file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
File: exceptions.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/05
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "utils.H"
|
||||
#include "console.H"
|
||||
#include "idt.H"
|
||||
#include "exceptions.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXTERNS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* The low-level functions (defined in file 'IDT::low.s') that handle the
|
||||
32 Intel-defined CPU exceptions.
|
||||
These functions are actually merely stubs that put the error code and
|
||||
the exception code on the stack and then call a low-level function, which
|
||||
in turn calls the exception dispatcher (defined in 'exceptions.H').
|
||||
Yes, there are more efficient ways to handle exceptions, but they require more
|
||||
code replication.
|
||||
*/
|
||||
extern "C" void isr0();
|
||||
extern "C" void isr1();
|
||||
extern "C" void isr2();
|
||||
extern "C" void isr3();
|
||||
extern "C" void isr4();
|
||||
extern "C" void isr5();
|
||||
extern "C" void isr6();
|
||||
extern "C" void isr7();
|
||||
extern "C" void isr8();
|
||||
extern "C" void isr9();
|
||||
extern "C" void isr10();
|
||||
extern "C" void isr11();
|
||||
extern "C" void isr12();
|
||||
extern "C" void isr13();
|
||||
extern "C" void isr14();
|
||||
extern "C" void isr15();
|
||||
extern "C" void isr16();
|
||||
extern "C" void isr17();
|
||||
extern "C" void isr18();
|
||||
extern "C" void isr19();
|
||||
extern "C" void isr20();
|
||||
extern "C" void isr21();
|
||||
extern "C" void isr22();
|
||||
extern "C" void isr23();
|
||||
extern "C" void isr24();
|
||||
extern "C" void isr25();
|
||||
extern "C" void isr26();
|
||||
extern "C" void isr27();
|
||||
extern "C" void isr28();
|
||||
extern "C" void isr29();
|
||||
extern "C" void isr30();
|
||||
extern "C" void isr31();
|
||||
|
||||
extern "C" void lowlevel_dispatch_exception(REGS * _r) {
|
||||
ExceptionHandler::dispatch_exception(_r);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* STATIC VARIABLES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
ExceptionHandler * ExceptionHandler::handler_table[ExceptionHandler::EXCEPTION_TABLE_SIZE];
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXPORTED EXCEPTION DISPATCHER FUNCTIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void ExceptionHandler::init_dispatcher() {
|
||||
|
||||
/* -- INITIALIZE LOW-LEVEL EXCEPTION HANDLERS */
|
||||
/* Add any new ISRs to the IDT here using IDT::set_gate */
|
||||
IDT::set_gate( 0, (unsigned) isr0, 0x08, 0x8E);
|
||||
IDT::set_gate( 1, (unsigned) isr1, 0x08, 0x8E);
|
||||
IDT::set_gate( 2, (unsigned) isr2, 0x08, 0x8E);
|
||||
IDT::set_gate( 3, (unsigned) isr3, 0x08, 0x8E);
|
||||
IDT::set_gate( 4, (unsigned) isr4, 0x08, 0x8E);
|
||||
IDT::set_gate( 5, (unsigned) isr5, 0x08, 0x8E);
|
||||
IDT::set_gate( 6, (unsigned) isr6, 0x08, 0x8E);
|
||||
IDT::set_gate( 7, (unsigned) isr7, 0x08, 0x8E);
|
||||
|
||||
IDT::set_gate( 8, (unsigned) isr8, 0x08, 0x8E);
|
||||
IDT::set_gate( 9, (unsigned) isr9, 0x08, 0x8E);
|
||||
IDT::set_gate(10, (unsigned)isr10, 0x08, 0x8E);
|
||||
IDT::set_gate(11, (unsigned)isr11, 0x08, 0x8E);
|
||||
IDT::set_gate(12, (unsigned)isr12, 0x08, 0x8E);
|
||||
IDT::set_gate(13, (unsigned)isr13, 0x08, 0x8E);
|
||||
IDT::set_gate(14, (unsigned)isr14, 0x08, 0x8E);
|
||||
IDT::set_gate(15, (unsigned)isr15, 0x08, 0x8E);
|
||||
|
||||
IDT::set_gate(16, (unsigned)isr16, 0x08, 0x8E);
|
||||
IDT::set_gate(17, (unsigned)isr17, 0x08, 0x8E);
|
||||
IDT::set_gate(18, (unsigned)isr18, 0x08, 0x8E);
|
||||
IDT::set_gate(19, (unsigned)isr19, 0x08, 0x8E);
|
||||
IDT::set_gate(20, (unsigned)isr20, 0x08, 0x8E);
|
||||
IDT::set_gate(21, (unsigned)isr21, 0x08, 0x8E);
|
||||
IDT::set_gate(22, (unsigned)isr22, 0x08, 0x8E);
|
||||
IDT::set_gate(23, (unsigned)isr23, 0x08, 0x8E);
|
||||
|
||||
IDT::set_gate(24, (unsigned)isr24, 0x08, 0x8E);
|
||||
IDT::set_gate(25, (unsigned)isr25, 0x08, 0x8E);
|
||||
IDT::set_gate(26, (unsigned)isr26, 0x08, 0x8E);
|
||||
IDT::set_gate(27, (unsigned)isr27, 0x08, 0x8E);
|
||||
IDT::set_gate(28, (unsigned)isr28, 0x08, 0x8E);
|
||||
IDT::set_gate(29, (unsigned)isr29, 0x08, 0x8E);
|
||||
IDT::set_gate(30, (unsigned)isr30, 0x08, 0x8E);
|
||||
IDT::set_gate(31, (unsigned)isr31, 0x08, 0x8E);
|
||||
|
||||
/* -- INITIALIZE THE HIGH-LEVEL EXCEPTION HANDLER */
|
||||
int i;
|
||||
for(i = 0; i < EXCEPTION_TABLE_SIZE; i++) {
|
||||
handler_table[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ExceptionHandler::dispatch_exception(REGS * _r) {
|
||||
|
||||
/* -- EXCEPTION NUMBER */
|
||||
unsigned int exc_no = _r->int_no;
|
||||
|
||||
Console::puts("EXCEPTION DISPATCHER: exc_no = ");
|
||||
Console::putui(exc_no);
|
||||
Console::puts("\n");
|
||||
|
||||
assert((exc_no >= 0) && (exc_no < EXCEPTION_TABLE_SIZE));
|
||||
|
||||
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS EXCEPTION NO? */
|
||||
ExceptionHandler * handler = handler_table[exc_no];
|
||||
|
||||
if (!handler) {
|
||||
/* --- NO HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
|
||||
Console::puts("NO DEFAULT EXCEPTION HANDLER REGISTERED\n");
|
||||
abort();
|
||||
}
|
||||
else {
|
||||
/* -- HANDLE THE EXCEPTION OR INTERRUPT */
|
||||
handler->handle_exception(_r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ExceptionHandler::register_handler(unsigned int _isr_code,
|
||||
ExceptionHandler * _handler) {
|
||||
|
||||
assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE);
|
||||
|
||||
handler_table[_isr_code] = _handler;
|
||||
|
||||
Console::puts("Installed exception handler at ISR ");
|
||||
Console::putui(_isr_code);
|
||||
Console::puts("\n");
|
||||
|
||||
}
|
||||
|
||||
void ExceptionHandler::deregister_handler(unsigned int _isr_code) {
|
||||
assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE);
|
||||
|
||||
handler_table[_isr_code] = NULL;
|
||||
|
||||
Console::puts("UNINSTALLED exception handler at ISR ");
|
||||
Console::putui(_isr_code);
|
||||
Console::puts("\n");
|
||||
|
||||
}
|
||||
|
||||
|
86
MP3/MP3_Sources/exceptions.H
Executable file
86
MP3/MP3_Sources/exceptions.H
Executable file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
File: exceptions.h
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/05
|
||||
|
||||
Description: High-level exception handling.
|
||||
|
||||
CPU exceptions are caught by low-level exception and interrupt
|
||||
handler stubs, which all eventually cause the high-level
|
||||
exception dispatcher to be called (see 'dispatch_exception() below).
|
||||
|
||||
The dispatcher then looks up the appropriate exception handler
|
||||
for the given exception, and calls it.
|
||||
Specific exception handlers are installed by registering an exception handler
|
||||
object of a class appropriately derived from class 'ExceptionHandler'. The
|
||||
functionality of the exception handler is then implemented in function
|
||||
'handle_exception(REGS * _regs)'.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _exceptions_H_ // include file only once
|
||||
#define _exceptions_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "machine.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* E x c e p t i o n H a n d l e r */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class ExceptionHandler {
|
||||
|
||||
private:
|
||||
|
||||
/* The Exception Handler Table */
|
||||
const static int EXCEPTION_TABLE_SIZE = 32;
|
||||
static ExceptionHandler * handler_table[EXCEPTION_TABLE_SIZE];
|
||||
|
||||
public:
|
||||
|
||||
/* -- POPULATE DISPATCHER TABLE */
|
||||
|
||||
static void register_handler(unsigned int _isr_code,
|
||||
ExceptionHandler * _handler);
|
||||
/* This function allows to install an exception handler for the given
|
||||
exception code. The handler is a function pointer defined above.
|
||||
Interrupt handlers are installed as exception handlers as well.
|
||||
The 'register_interrupt' function uses irq2isr to map the IRQ
|
||||
number to the code. */
|
||||
|
||||
static void deregister_handler(unsigned int _isr_code);
|
||||
|
||||
/* -- DISPATCHER */
|
||||
static void init_dispatcher();
|
||||
/* This function is called to initialize the high-level exception handling.
|
||||
No high level exception handlers are installed yet. If an exception
|
||||
occurs at this point, the system displays an error message and
|
||||
terminates. */
|
||||
|
||||
static void dispatch_exception(REGS * _r);
|
||||
/* This is the high-level exception dispatcher. It dispatches the exception
|
||||
to the previously registered exception handler.
|
||||
This function is called by the low-level function
|
||||
"lowlevel_dispatch_exception(REGS * _r)".*/
|
||||
|
||||
/* -- MANAGE INSTANCES OF EXCEPTION HANDLERS */
|
||||
|
||||
virtual void handle_exception(REGS * _regs) {
|
||||
assert(false); // sometimes pure virtual functions dont link correctly.
|
||||
}
|
||||
/* Different exception handlers are derived from the base class ExceptionHandler
|
||||
and their functionality is implemented in this function.*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
124
MP3/MP3_Sources/gdt.C
Executable file
124
MP3/MP3_Sources/gdt.C
Executable file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
File: gdt.C
|
||||
|
||||
Date : 09/03/02
|
||||
|
||||
Description: Management of the Global Descriptor Table (GDT)
|
||||
|
||||
The GDT describes memory access priviledges for memory segments.
|
||||
|
||||
While the table is initialized by GRUB already, it may be a good idea to
|
||||
do this again in the kernel code.
|
||||
|
||||
For details see Section 5 of Brandon Friesen's Tutorial
|
||||
on OS Kernel Development.
|
||||
URL: http://www.osdever.net/bkerndev/Docs/title.htm
|
||||
|
||||
* bkerndev - Bran's Kernel Development Tutorial
|
||||
* By: Brandon F. (friesenb@gmail.com)
|
||||
* Desc: Interrupt Descriptor Table management
|
||||
*
|
||||
* Notes: No warranty expressed or implied. Use at own risk.
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
//#include "assert.H"
|
||||
#include "utils.H"
|
||||
#include "gdt.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Defines a GDT entry. We use the 'packed' directive to prevent the
|
||||
compiler from optimizing by aligning structure elements at word
|
||||
boundaries. */
|
||||
struct gdt_entry {
|
||||
unsigned short limit_low;
|
||||
unsigned short base_low;
|
||||
unsigned char base_middle;
|
||||
unsigned char access;
|
||||
unsigned char granularity;
|
||||
unsigned char base_high;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Special pointer that includes the limit: The max bytes
|
||||
taken up by the GDT, minus 1. Again, this NEEDS to be packed. */
|
||||
struct gdt_ptr {
|
||||
unsigned short limit;
|
||||
unsigned int base;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* VARIABLES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static struct gdt_entry gdt[GDT::SIZE];
|
||||
struct gdt_ptr gp;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXTERNS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* This function is defined in 'gdt_low.asm', which in turn is included in
|
||||
'start.asm'. */
|
||||
extern "C" void gdt_flush();
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXPORTED FUNCTIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Use this function to set up an entry in the GDT. */
|
||||
void GDT::set_gate(int num,
|
||||
unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran) {
|
||||
|
||||
/* Setup the descriptor base address */
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
|
||||
/* Setup the descriptor limits */
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = ((limit >> 16) & 0x0F);
|
||||
|
||||
/* Finally, set up the granularity and access flags */
|
||||
gdt[num].granularity |= (gran & 0xF0);
|
||||
gdt[num].access = access;
|
||||
}
|
||||
|
||||
|
||||
/* Installs the GDT */
|
||||
void GDT::init() {
|
||||
|
||||
/* Sets up the special GDT pointer. */
|
||||
gp.limit = (sizeof (struct gdt_entry) * SIZE) - 1;
|
||||
gp.base = (unsigned int)&gdt;
|
||||
|
||||
/* Our NULL descriptor */
|
||||
set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
/* The second entry is our Code Segment. The base address
|
||||
is 0, the limit is 4GByte, it uses 4kB granularity,
|
||||
uses 32-bit opcodes, and is a Code Segment descriptor.
|
||||
Please check the GDT section in Bran's Kernel Development
|
||||
tutorial to see exactly what each value means. */
|
||||
set_gate(1, 0, 0xFFFFFFFF, 0x9a, 0xCF);
|
||||
|
||||
/* The third entry is our Data Segment. It's EXACTLY the
|
||||
same as the code segment, but the descriptor type in
|
||||
this entry's access byte says it's a Data Segment. */
|
||||
set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
||||
|
||||
/* Flush out the old GDT, and install the new changes. */
|
||||
gdt_flush();
|
||||
}
|
48
MP3/MP3_Sources/gdt.H
Executable file
48
MP3/MP3_Sources/gdt.H
Executable file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
File: gdt.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/02
|
||||
|
||||
Description: Management of the Global Descriptor Table (GDT)
|
||||
|
||||
The GDT describes memory access priviledges for memory segments.
|
||||
|
||||
While the table is initialized by GRUB already, it may be a good idea to
|
||||
do this again in the kernel code.
|
||||
|
||||
For details see Section 5 of Brandon Friesen's Tutotial
|
||||
on OS Kernel Development.
|
||||
URL: http://www.osdever.net/bkerndev/Docs/title.htm
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _GDT_H_ // include file only once
|
||||
#define _GDT_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* GDT */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class GDT {
|
||||
|
||||
private:
|
||||
|
||||
/* Use this function to set up an entry in the GDT. */
|
||||
static void set_gate(int num,
|
||||
unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran);
|
||||
|
||||
public:
|
||||
|
||||
static const unsigned int SIZE = 3;
|
||||
|
||||
static void init();
|
||||
/* Initialize the GDT to have a null segment, a code segment,
|
||||
and one data segment. */
|
||||
|
||||
};
|
||||
|
||||
#endif
|
18
MP3/MP3_Sources/gdt_low.asm
Executable file
18
MP3/MP3_Sources/gdt_low.asm
Executable file
|
@ -0,0 +1,18 @@
|
|||
; This will set up our new segment registers. We need to do
|
||||
; something special in order to set CS. We do what is called a
|
||||
; far jump. A jump that includes a segment as well as an offset.
|
||||
; This is declared in C as 'extern void gdt_flush();'
|
||||
global _gdt_flush ; Allows the C code to link to this.
|
||||
extern _gp ; Says that '_gp' is in another file
|
||||
|
||||
_gdt_flush:
|
||||
lgdt[_gp] ; Load the GDT with our '_gp', a special pointer
|
||||
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
; mov ss, ax
|
||||
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: FAR JUMP!
|
||||
flush2:
|
||||
ret ; Returns back to the C code!
|
108
MP3/MP3_Sources/idt.C
Executable file
108
MP3/MP3_Sources/idt.C
Executable file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
File: idt.C
|
||||
|
||||
Date : 09/03/02
|
||||
|
||||
*/
|
||||
|
||||
/* Based largely on
|
||||
* bkerndev - Bran's Kernel Development Tutorial
|
||||
* By: Brandon F. (friesenb@gmail.com)
|
||||
* Desc: Interrupt Descriptor Table management
|
||||
*
|
||||
* Notes: No warranty expressed or implied. Use at own risk. */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
//#include "assert.H"
|
||||
#include "utils.H"
|
||||
#include "idt.H"
|
||||
#include "console.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXTERNS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Used to load our IDT, defined in 'idt_low.s' */
|
||||
extern "C" void idt_load();
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
struct idt_entry
|
||||
{
|
||||
unsigned short base_lo;
|
||||
unsigned short sel;
|
||||
unsigned char always0;
|
||||
unsigned char flags;
|
||||
unsigned short base_hi;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_ptr
|
||||
{
|
||||
unsigned short limit;
|
||||
unsigned int base;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* VARIABLES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Declare an IDT of IDT_SIZE entries. We use only the first 32
|
||||
entries. If any undefined IDT entry is hit, it normally
|
||||
cause an "Unhandled Interrupt" exception. Any descriptor
|
||||
for which the 'presence' bit is cleared will generate an
|
||||
"Unhandled Interrupt" exception. */
|
||||
struct idt_entry idt[IDT::SIZE];
|
||||
struct idt_ptr idtp;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* HOOKING UP THE LOW-LEVEL EXCEPTION HANDLER TO EXCEPTIONDISPATCHER. */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Use this function to set an entry in the IDT. */
|
||||
void IDT::set_gate(unsigned char num, unsigned long base,
|
||||
unsigned short sel, unsigned char flags) {
|
||||
|
||||
Console::puts("Installing handler in IDT position ");
|
||||
Console::puti((int)num);
|
||||
Console::puts("\n");
|
||||
|
||||
/* The interrupt routine's base address */
|
||||
idt[num].base_lo = (base & 0xFFFF);
|
||||
idt[num].base_hi = (base >> 16) & 0xFFFF;
|
||||
|
||||
/* The segment or 'selector' that this IDT entry will use
|
||||
* is set here, along with any access flags */
|
||||
idt[num].sel = sel;
|
||||
idt[num].always0 = 0;
|
||||
idt[num].flags = flags;
|
||||
|
||||
}
|
||||
|
||||
/* Installs the IDT */
|
||||
void IDT::init() {
|
||||
|
||||
/* Sets the special IDT pointer up. */
|
||||
idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
|
||||
idtp.base = (unsigned int)&idt;
|
||||
|
||||
/* Clear out the entire IDT, initializing it to zeros. */
|
||||
memset(&idt, 0, sizeof(struct idt_entry) * 256);
|
||||
|
||||
|
||||
/* Points the processor's internal register to the new IDT */
|
||||
idt_load();
|
||||
}
|
57
MP3/MP3_Sources/idt.H
Executable file
57
MP3/MP3_Sources/idt.H
Executable file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
File: idt.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/02
|
||||
|
||||
Description: the Interrupt Description Table (IDT)
|
||||
|
||||
The IDT contains pointer to low-level exception and interrupt handlers.
|
||||
The way the exception handling is set up, all low-level handlers route
|
||||
the exception to a single exception dispatcher, which in turn
|
||||
calls a high-level exception dispatcher (see file 'exceptions.H').
|
||||
|
||||
For details see Section 6 of Brandon Friesen's Tutorial
|
||||
on OS Kernel Development.
|
||||
URL: http://www.osdever.net/bkerndev/Docs/title.htm
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _IDT_H_ // include file only once
|
||||
#define _IDT_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
//#define IDT_SIZE 256
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Class IDT */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class IDT {
|
||||
|
||||
public:
|
||||
|
||||
static const int SIZE = 256;
|
||||
|
||||
static void init();
|
||||
/* Initialize the IDT, and fill the 32 first entries with pointers to handle
|
||||
the 32 Intel-defined exceptions. After initializing the IDT, these exceptions
|
||||
are routed to the exception dispatcher (see 'exceptions.H'). At this point,
|
||||
no exception handlers are installed yet.
|
||||
*/
|
||||
|
||||
static void set_gate(unsigned char num, unsigned long base,
|
||||
unsigned short sel, unsigned char flags);
|
||||
/* Used to install a low-level exception handler in the IDT. For high-level
|
||||
exception handlers, use the exception management framework defined in
|
||||
file 'exceptions.H'.
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
279
MP3/MP3_Sources/idt_low.asm
Executable file
279
MP3/MP3_Sources/idt_low.asm
Executable file
|
@ -0,0 +1,279 @@
|
|||
; This is the exception de-multiplexer code.
|
||||
; All low-level exception handling routines do the following:
|
||||
; 1. disable interrupts
|
||||
; 2. push error code on the stack (if the exception did not already
|
||||
; do so! (Some exceptions automatically push the error code onto the
|
||||
; stack.)
|
||||
; 3. push the number of the exception onto the stack.
|
||||
; 4. call the common interrupt service routine function, which then
|
||||
; branches back out based on the exception number on the stack.
|
||||
; (We do this because we don't want to replicate again and again the code
|
||||
; to save the processor state.)
|
||||
;
|
||||
|
||||
; Here come the interrupt service routines for the 32 exceptions.
|
||||
global _isr0
|
||||
global _isr1
|
||||
global _isr2
|
||||
global _isr3
|
||||
global _isr4
|
||||
global _isr5
|
||||
global _isr6
|
||||
global _isr7
|
||||
global _isr8
|
||||
global _isr9
|
||||
global _isr10
|
||||
global _isr11
|
||||
global _isr12
|
||||
global _isr13
|
||||
global _isr14
|
||||
global _isr15
|
||||
global _isr16
|
||||
global _isr17
|
||||
global _isr18
|
||||
global _isr19
|
||||
global _isr20
|
||||
global _isr21
|
||||
global _isr22
|
||||
global _isr23
|
||||
global _isr24
|
||||
global _isr25
|
||||
global _isr26
|
||||
global _isr27
|
||||
global _isr28
|
||||
global _isr29
|
||||
global _isr30
|
||||
global _isr31
|
||||
|
||||
|
||||
extern _promptA
|
||||
extern _promptB
|
||||
extern _promptC
|
||||
|
||||
|
||||
; 0: Divide By Zero Exception
|
||||
_isr0:
|
||||
push byte 0
|
||||
push byte 0
|
||||
jmp isr_common_stub
|
||||
|
||||
; 1: Debug Exception
|
||||
_isr1:
|
||||
push byte 0
|
||||
push byte 1
|
||||
jmp isr_common_stub
|
||||
|
||||
; 2: Non Maskable Interrupt Exception
|
||||
_isr2:
|
||||
push byte 0
|
||||
push byte 2
|
||||
jmp isr_common_stub
|
||||
|
||||
; 3: Int 3 Exception
|
||||
_isr3:
|
||||
push byte 0
|
||||
push byte 3
|
||||
jmp isr_common_stub
|
||||
|
||||
; 4: INTO Exception
|
||||
_isr4:
|
||||
push byte 0
|
||||
push byte 4
|
||||
jmp isr_common_stub
|
||||
|
||||
; 5: Out of Bounds Exception
|
||||
_isr5:
|
||||
push byte 0
|
||||
push byte 5
|
||||
jmp isr_common_stub
|
||||
|
||||
; 6: Invalid Opcode Exception
|
||||
_isr6:
|
||||
push byte 0
|
||||
push byte 6
|
||||
jmp isr_common_stub
|
||||
|
||||
; 7: Coprocessor Not Available Exception
|
||||
_isr7:
|
||||
push byte 0
|
||||
push byte 7
|
||||
jmp isr_common_stub
|
||||
|
||||
; 8: Double Fault Exception (With Error Code!)
|
||||
_isr8:
|
||||
push byte 8
|
||||
jmp isr_common_stub
|
||||
|
||||
; 9: Coprocessor Segment Overrun Exception
|
||||
_isr9:
|
||||
push byte 0
|
||||
push byte 9
|
||||
jmp isr_common_stub
|
||||
|
||||
; 10: Bad TSS Exception (With Error Code!)
|
||||
_isr10:
|
||||
push byte 10
|
||||
jmp isr_common_stub
|
||||
|
||||
; 11: Segment Not Present Exception (With Error Code!)
|
||||
_isr11:
|
||||
push byte 11
|
||||
jmp isr_common_stub
|
||||
|
||||
; 12: Stack Fault Exception (With Error Code!)
|
||||
_isr12:
|
||||
push byte 12
|
||||
jmp isr_common_stub
|
||||
|
||||
; 13: General Protection Fault Exception (With Error Code!)
|
||||
_isr13:
|
||||
push byte 13
|
||||
jmp isr_common_stub
|
||||
|
||||
; 14: Page Fault Exception (With Error Code!)
|
||||
_isr14:
|
||||
push byte 14
|
||||
jmp isr_common_stub
|
||||
|
||||
; 15: Reserved Exception
|
||||
_isr15:
|
||||
push byte 0
|
||||
push byte 15
|
||||
jmp isr_common_stub
|
||||
|
||||
; 16: Floating Point Exception
|
||||
_isr16:
|
||||
push byte 0
|
||||
push byte 16
|
||||
jmp isr_common_stub
|
||||
|
||||
; 17: Alignment Check Exception
|
||||
_isr17:
|
||||
push byte 0
|
||||
push byte 17
|
||||
jmp isr_common_stub
|
||||
|
||||
; 18: Machine Check Exception
|
||||
_isr18:
|
||||
push byte 0
|
||||
push byte 18
|
||||
jmp isr_common_stub
|
||||
|
||||
; 19: Reserved
|
||||
_isr19:
|
||||
push byte 0
|
||||
push byte 19
|
||||
jmp isr_common_stub
|
||||
|
||||
; 20: Reserved
|
||||
_isr20:
|
||||
push byte 0
|
||||
push byte 20
|
||||
jmp isr_common_stub
|
||||
|
||||
; 21: Reserved
|
||||
_isr21:
|
||||
push byte 0
|
||||
push byte 21
|
||||
jmp isr_common_stub
|
||||
|
||||
; 22: Reserved
|
||||
_isr22:
|
||||
push byte 0
|
||||
push byte 22
|
||||
jmp isr_common_stub
|
||||
|
||||
; 23: Reserved
|
||||
_isr23:
|
||||
push byte 0
|
||||
push byte 23
|
||||
jmp isr_common_stub
|
||||
|
||||
; 24: Reserved
|
||||
_isr24:
|
||||
push byte 0
|
||||
push byte 24
|
||||
jmp isr_common_stub
|
||||
|
||||
; 25: Reserved
|
||||
_isr25:
|
||||
push byte 0
|
||||
push byte 25
|
||||
jmp isr_common_stub
|
||||
|
||||
; 26: Reserved
|
||||
_isr26:
|
||||
push byte 0
|
||||
push byte 26
|
||||
jmp isr_common_stub
|
||||
|
||||
; 27: Reserved
|
||||
_isr27:
|
||||
push byte 0
|
||||
push byte 27
|
||||
jmp isr_common_stub
|
||||
|
||||
; 28: Reserved
|
||||
_isr28:
|
||||
push byte 0
|
||||
push byte 28
|
||||
jmp isr_common_stub
|
||||
|
||||
; 29: Reserved
|
||||
_isr29:
|
||||
push byte 0
|
||||
push byte 29
|
||||
jmp isr_common_stub
|
||||
|
||||
; 30: Reserved
|
||||
_isr30:
|
||||
push byte 0
|
||||
push byte 30
|
||||
jmp isr_common_stub
|
||||
|
||||
; 31: Reserved
|
||||
_isr31:
|
||||
push byte 0
|
||||
push byte 31
|
||||
jmp isr_common_stub
|
||||
|
||||
|
||||
|
||||
; The common stub below will pun out into C. Let the
|
||||
; assembler know that the function is defined in 'exceptions.C'.
|
||||
extern _lowlevel_dispatch_exception
|
||||
|
||||
; This is the common low-level stub for the exception handler.
|
||||
; It saves the processor state, sets up for kernel mode
|
||||
; segments, calls the C-level exception handler,
|
||||
; and finally restores the stack frame.
|
||||
isr_common_stub:
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
mov eax, esp ; Push us the stack
|
||||
push eax
|
||||
mov eax, _lowlevel_dispatch_exception
|
||||
call eax ; A special call, preserves the 'eip' register
|
||||
pop eax
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
add esp, 8 ; Ceans up the pushed error code and pushed ISR number
|
||||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP1
|
||||
|
||||
|
||||
|
||||
; load the IDT defined in '_idtp' into the processor.
|
||||
; This is declared in C as 'extern void _idt_load();'
|
||||
; In turn, the variable '_idtp' is defined in file 'idt.C'.
|
||||
global _idt_load
|
||||
extern _idtp
|
||||
_idt_load:
|
||||
lidt [_idtp]
|
||||
ret
|
172
MP3/MP3_Sources/interrupts.C
Executable file
172
MP3/MP3_Sources/interrupts.C
Executable file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
File: interrupts.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/05
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* (none) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "utils.H"
|
||||
#include "console.H"
|
||||
#include "idt.H"
|
||||
#include "irq.H"
|
||||
#include "exceptions.H"
|
||||
#include "interrupts.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXTERNS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* The low-level functions (defined in file 'irq_low.s') that handle the
|
||||
16 PIC-generated interrupts.
|
||||
These functions are actually merely stubs that put the error code and
|
||||
the exception code on the stack and then call a low-level function, which
|
||||
in turn calls the interrupt dispatcher.
|
||||
Yes, there are more efficient ways to handle exceptions, but they require more
|
||||
code replication.
|
||||
*/
|
||||
|
||||
extern "C" void irq0();
|
||||
extern "C" void irq1();
|
||||
extern "C" void irq2();
|
||||
extern "C" void irq3();
|
||||
extern "C" void irq4();
|
||||
extern "C" void irq5();
|
||||
extern "C" void irq6();
|
||||
extern "C" void irq7();
|
||||
extern "C" void irq8();
|
||||
extern "C" void irq9();
|
||||
extern "C" void irq10();
|
||||
extern "C" void irq11();
|
||||
extern "C" void irq12();
|
||||
extern "C" void irq13();
|
||||
extern "C" void irq14();
|
||||
extern "C" void irq15();
|
||||
|
||||
extern "C" void lowlevel_dispatch_interrupt(REGS * _r) {
|
||||
InterruptHandler::dispatch_interrupt(_r);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* LOCAL VARIABLES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
InterruptHandler * InterruptHandler::handler_table[InterruptHandler::IRQ_TABLE_SIZE];
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void InterruptHandler::init_dispatcher() {
|
||||
|
||||
/* -- INITIALIZE LOW-LEVEL INTERRUPT HANDLERS */
|
||||
/* Add any new ISRs to the IDT here using IDT::set_gate */
|
||||
IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E);
|
||||
IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E);
|
||||
IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E);
|
||||
IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E);
|
||||
IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E);
|
||||
IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E);
|
||||
IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E);
|
||||
IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E);
|
||||
|
||||
IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E);
|
||||
IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E);
|
||||
IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E);
|
||||
IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E);
|
||||
IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E);
|
||||
IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E);
|
||||
IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E);
|
||||
IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E);
|
||||
|
||||
/* -- INITIALIZE THE HIGH-LEVEL INTERRUPT HANDLER */
|
||||
int i;
|
||||
for(i = 0; i < IRQ_TABLE_SIZE; i++) {
|
||||
handler_table[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool InterruptHandler::generated_by_slave_PIC(unsigned int int_no) {
|
||||
return int_no > 7;
|
||||
}
|
||||
|
||||
void InterruptHandler::dispatch_interrupt(REGS * _r) {
|
||||
|
||||
/* -- INTERRUPT NUMBER */
|
||||
unsigned int int_no = _r->int_no - IRQ_BASE;
|
||||
|
||||
//Console::puts("INTERRUPT DISPATCHER: int_no = ");
|
||||
//Console::putui(int_no);
|
||||
//Console::puts("\n");
|
||||
|
||||
assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));
|
||||
|
||||
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */
|
||||
|
||||
InterruptHandler * handler = handler_table[int_no];
|
||||
|
||||
if (!handler) {
|
||||
/* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
|
||||
Console::puts("INTERRUPT NO: ");
|
||||
Console::puti(int_no);
|
||||
Console::puts("\n");
|
||||
Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
|
||||
// abort();
|
||||
}
|
||||
else {
|
||||
/* -- HANDLE THE INTERRUPT */
|
||||
handler->handle_interrupt(_r);
|
||||
}
|
||||
|
||||
/* This is an interrupt that was raised by the interrupt controller. We need
|
||||
to send and end-of-interrupt (EOI) signal to the controller after the
|
||||
interrupt has been handled. */
|
||||
|
||||
/* Check if the interrupt was generated by the slave interrupt controller.
|
||||
If so, send an End-of-Interrupt (EOI) message to the slave controller. */
|
||||
|
||||
if (generated_by_slave_PIC(int_no)) {
|
||||
Machine::outportb(0xA0, 0x20);
|
||||
}
|
||||
|
||||
/* Send an EOI message to the master interrupt controller. */
|
||||
Machine::outportb(0x20, 0x20);
|
||||
|
||||
}
|
||||
|
||||
void InterruptHandler::register_handler(unsigned int _irq_code,
|
||||
InterruptHandler * _handler) {
|
||||
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
|
||||
|
||||
handler_table[_irq_code] = _handler;
|
||||
|
||||
Console::puts("Installed interrupt handler at IRQ ");
|
||||
Console::putui(_irq_code);
|
||||
Console::puts("\n");
|
||||
|
||||
}
|
||||
|
||||
void InterruptHandler::deregister_handler(unsigned int _irq_code) {
|
||||
|
||||
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
|
||||
|
||||
handler_table[_irq_code] = NULL;
|
||||
|
||||
Console::puts("UNINSTALLED interrupt handler at IRQ ");
|
||||
Console::putui(_irq_code);
|
||||
Console::puts("\n");
|
||||
|
||||
}
|
90
MP3/MP3_Sources/interrupts.H
Executable file
90
MP3/MP3_Sources/interrupts.H
Executable file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
File: interrupts.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 11/11/10
|
||||
|
||||
Description: High-level interrupt handling.
|
||||
|
||||
CPU exceptions are caught by low-level exception and interrupt
|
||||
handler stubs, which all eventually cause the high-level
|
||||
exception dispatcher to be called (see 'dispatch_exception() below).
|
||||
|
||||
The dispatcher then looks up the appropriate exception handler
|
||||
for the given exception, and calls it.
|
||||
Specific exception handlers are installed by registering an exception handler
|
||||
object of a class appropriately derived from class 'ExceptionHandler'. The
|
||||
functionality of the exception handler is then implemented in function
|
||||
'handle_exception(REGS * _regs)'.
|
||||
*/
|
||||
|
||||
#ifndef _interrupts_H_ // include file only once
|
||||
#define _interrupts_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "machine.H"
|
||||
#include "exceptions.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* I n t e r r u p t H a n d l e r */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class InterruptHandler {
|
||||
|
||||
private:
|
||||
|
||||
/* The Interrupt Handler Table */
|
||||
const static int IRQ_TABLE_SIZE = 16;
|
||||
const static int IRQ_BASE = 32;
|
||||
|
||||
static InterruptHandler * handler_table[IRQ_TABLE_SIZE];
|
||||
|
||||
static bool generated_by_slave_PIC(unsigned int int_no);
|
||||
/* Has the particular interupt been generated by the Slave PIC? */
|
||||
|
||||
public:
|
||||
|
||||
/* -- POPULATE INTERRUPT-DISPATCHER TABLE */
|
||||
static void register_handler(unsigned int _irq_code,
|
||||
InterruptHandler * _handler);
|
||||
/* This function allows to install an interrupt handler for the given
|
||||
Interrupt code. The handler is a function pointer defined above.
|
||||
Interrupt handlers are installed as Interrupt handlers as well.
|
||||
The 'register_interrupt' function uses irq2isr to map the IRQ
|
||||
number to the code. */
|
||||
|
||||
static void deregister_handler(unsigned int _irq_code);
|
||||
|
||||
/* -- INITIALIZER */
|
||||
static void init_dispatcher();
|
||||
/* This function is called to initialize the high-level interrupt
|
||||
handling. No high level interrupt handlers are installed yet.
|
||||
If an interrupt occurs at this point, the system displays an error
|
||||
message and terminates. */
|
||||
|
||||
static void dispatch_interrupt(REGS * _r);
|
||||
/* This is the high-level interrupt dispatcher. It dispatches the interrupt
|
||||
to the previously registered interrupt handler.
|
||||
This function is called by the low-level function
|
||||
"lowlevel_dispatch_interrupt(REGS * _r)".*/
|
||||
|
||||
/* -- MANAGE INSTANCES OF INTERRUPT HANDLERS */
|
||||
|
||||
virtual void handle_interrupt(REGS * _regs) {
|
||||
assert(false); // sometimes pure virtual functions don't link correctly.
|
||||
}
|
||||
/* Different interrupt handlers are derived from the base class
|
||||
InterruptHandler, and their functionality is implemented in
|
||||
this function.*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
60
MP3/MP3_Sources/irq.C
Executable file
60
MP3/MP3_Sources/irq.C
Executable file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
File: irq.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/05
|
||||
|
||||
This code borrows heavily from Brandon Friesen's the code in Brandon
|
||||
Friesen's OS Development Tutorial.
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define IRQ_BASE 32
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H"
|
||||
#include "irq.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* LOCAL FUNCTIONS . */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Normally, IRQs 0 to 7 are mapped to IDT entries 8 to 15.
|
||||
For a variety of reasons it is a good idea to re-map these
|
||||
IRQs to different locations
|
||||
We send a sequence of commands to the PICs - 8259's - in order
|
||||
to have IRQ0 to IRQ15 be remapped to IDT entries 32 to 47.
|
||||
*/
|
||||
static void irq_remap()
|
||||
{
|
||||
Machine::outportb(0x20, 0x11);
|
||||
Machine::outportb(0xA0, 0x11);
|
||||
Machine::outportb(0x21, 0x20);
|
||||
Machine::outportb(0xA1, 0x28);
|
||||
Machine::outportb(0x21, 0x04);
|
||||
Machine::outportb(0xA1, 0x02);
|
||||
Machine::outportb(0x21, 0x01);
|
||||
Machine::outportb(0xA1, 0x01);
|
||||
Machine::outportb(0x21, 0x0);
|
||||
Machine::outportb(0xA1, 0x0);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* EXPORTED FUNCTIONS . */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void IRQ::init() {
|
||||
|
||||
irq_remap();
|
||||
|
||||
|
||||
}
|
38
MP3/MP3_Sources/irq.H
Executable file
38
MP3/MP3_Sources/irq.H
Executable file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
File: irq.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/02
|
||||
|
||||
Description: Interrupt Table (IRQ)
|
||||
|
||||
For details see Section 7 of Brandon Friesen's Tutorial
|
||||
on OS Kernel Development.
|
||||
URL: http://www.osdever.net/bkerndev/Docs/title.htm
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _IRQ_H_ // include file only once
|
||||
#define _IRQ_H_
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class IRQ {
|
||||
|
||||
public:
|
||||
|
||||
static void init();
|
||||
/* Initialize the IRQ handlers, i.e. fill 16 entries with pointers to handle
|
||||
the PIC generated interrupts. These interrupts are routed to the exception
|
||||
dispatcher (see 'exceptions.H'). At this point, no exception handlers are
|
||||
installed yet.
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
136
MP3/MP3_Sources/irq_low.asm
Executable file
136
MP3/MP3_Sources/irq_low.asm
Executable file
|
@ -0,0 +1,136 @@
|
|||
global _irq0
|
||||
global _irq1
|
||||
global _irq2
|
||||
global _irq3
|
||||
global _irq4
|
||||
global _irq5
|
||||
global _irq6
|
||||
global _irq7
|
||||
global _irq8
|
||||
global _irq9
|
||||
global _irq10
|
||||
global _irq11
|
||||
global _irq12
|
||||
global _irq13
|
||||
global _irq14
|
||||
global _irq15
|
||||
|
||||
; 32: IRQ0
|
||||
_irq0:
|
||||
push byte 0
|
||||
push byte 32
|
||||
jmp irq_common_stub
|
||||
|
||||
; 33: IRQ1
|
||||
_irq1:
|
||||
push byte 0
|
||||
push byte 33
|
||||
jmp irq_common_stub
|
||||
|
||||
; 34: IRQ2
|
||||
_irq2:
|
||||
push byte 0
|
||||
push byte 34
|
||||
jmp irq_common_stub
|
||||
|
||||
; 35: IRQ3
|
||||
_irq3:
|
||||
push byte 0
|
||||
push byte 35
|
||||
jmp irq_common_stub
|
||||
|
||||
; 36: IRQ4
|
||||
_irq4:
|
||||
push byte 0
|
||||
push byte 36
|
||||
jmp irq_common_stub
|
||||
|
||||
; 37: IRQ5
|
||||
_irq5:
|
||||
push byte 0
|
||||
push byte 37
|
||||
jmp irq_common_stub
|
||||
|
||||
; 38: IRQ6
|
||||
_irq6:
|
||||
push byte 0
|
||||
push byte 38
|
||||
jmp irq_common_stub
|
||||
|
||||
; 39: IRQ7
|
||||
_irq7:
|
||||
push byte 0
|
||||
push byte 39
|
||||
jmp irq_common_stub
|
||||
|
||||
; 40: IRQ8
|
||||
_irq8:
|
||||
push byte 0
|
||||
push byte 40
|
||||
jmp irq_common_stub
|
||||
|
||||
; 41: IRQ9
|
||||
_irq9:
|
||||
push byte 0
|
||||
push byte 41
|
||||
jmp irq_common_stub
|
||||
|
||||
; 42: IRQ10
|
||||
_irq10:
|
||||
push byte 0
|
||||
push byte 42
|
||||
jmp irq_common_stub
|
||||
|
||||
; 43: IRQ11
|
||||
_irq11:
|
||||
push byte 0
|
||||
push byte 43
|
||||
jmp irq_common_stub
|
||||
|
||||
; 44: IRQ12
|
||||
_irq12:
|
||||
push byte 0
|
||||
push byte 44
|
||||
jmp irq_common_stub
|
||||
|
||||
; 45: IRQ13
|
||||
_irq13:
|
||||
push byte 0
|
||||
push byte 45
|
||||
jmp irq_common_stub
|
||||
|
||||
; 46: IRQ14
|
||||
_irq14:
|
||||
push byte 0
|
||||
push byte 46
|
||||
jmp irq_common_stub
|
||||
|
||||
; 47: IRQ15
|
||||
_irq15:
|
||||
push byte 0
|
||||
push byte 47
|
||||
jmp irq_common_stub
|
||||
|
||||
extern _lowlevel_dispatch_interrupt
|
||||
|
||||
irq_common_stub:
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
mov eax, esp
|
||||
|
||||
push eax
|
||||
mov eax, _lowlevel_dispatch_interrupt
|
||||
call eax
|
||||
pop eax
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
add esp, 8
|
||||
iret
|
196
MP3/MP3_Sources/kernel.C
Executable file
196
MP3/MP3_Sources/kernel.C
Executable file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
File: kernel.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/03
|
||||
|
||||
|
||||
This file has the main entry point to the operating system.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H" /* LOW-LEVEL STUFF */
|
||||
#include "console.H"
|
||||
#include "gdt.H"
|
||||
#include "idt.H" /* LOW-LEVEL EXCEPTION MGMT. */
|
||||
#include "irq.H"
|
||||
#include "exceptions.H"
|
||||
#include "interrupts.H"
|
||||
|
||||
#include "simple_keyboard.H" /* SIMPLE KB DRIVER */
|
||||
#include "simple_timer.H" /* TIMER MANAGEMENT */
|
||||
|
||||
#include "page_table.H"
|
||||
#include "paging_low.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define MB * (0x1 << 20)
|
||||
#define KB * (0x1 << 10)
|
||||
#define KERNEL_POOL_START_FRAME ((2 MB) / Machine::PAGE_SIZE)
|
||||
#define KERNEL_POOL_SIZE ((2 MB) / Machine::PAGE_SIZE)
|
||||
#define PROCESS_POOL_START_FRAME ((4 MB) / Machine::PAGE_SIZE)
|
||||
#define PROCESS_POOL_SIZE ((28 MB) / Machine::PAGE_SIZE)
|
||||
/* definition of the kernel and process memory pools */
|
||||
|
||||
#define MEM_HOLE_START_FRAME ((15 MB) / Machine::PAGE_SIZE)
|
||||
#define MEM_HOLE_SIZE ((1 MB) / Machine::PAGE_SIZE)
|
||||
/* we have a 1 MB hole in physical memory starting at address 15 MB */
|
||||
|
||||
#define FAULT_ADDR (4 MB)
|
||||
/* used in the code later as address referenced to cause page faults. */
|
||||
#define NACCESS ((1 MB) / 4)
|
||||
/* NACCESS integer access (i.e. 4 bytes in each access) are made starting at address FAULT_ADDR */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MAIN ENTRY INTO THE OS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int main() {
|
||||
|
||||
GDT::init();
|
||||
Console::init();
|
||||
IDT::init();
|
||||
ExceptionHandler::init_dispatcher();
|
||||
IRQ::init();
|
||||
InterruptHandler::init_dispatcher();
|
||||
|
||||
|
||||
/* -- EXAMPLE OF AN EXCEPTION HANDLER: Division-by-Zero -- */
|
||||
|
||||
class DBZ_Handler : public ExceptionHandler {
|
||||
/* We derive Division-by-Zero handler from ExceptionHandler
|
||||
and overload the method handle_exception. */
|
||||
public:
|
||||
virtual void handle_exception(REGS * _regs) {
|
||||
Console::puts("DIVISION BY ZERO!\n");
|
||||
for(;;);
|
||||
}
|
||||
} dbz_handler;
|
||||
|
||||
/* Register the DBZ handler for exception no.0
|
||||
with the exception dispatcher. */
|
||||
ExceptionHandler::register_handler(0, &dbz_handler);
|
||||
|
||||
|
||||
/* -- EXAMPLE OF AN INTERRUPT HANDLER: Very simple timer -- */
|
||||
|
||||
SimpleTimer timer(100); /* timer ticks every 10ms. */
|
||||
|
||||
/* ---- Register timer handler for interrupt no.0
|
||||
with the interrupt dispatcher. */
|
||||
InterruptHandler::register_handler(0, &timer);
|
||||
|
||||
/* NOTE: The timer chip starts periodically firing as
|
||||
soon as we enable interrupts.
|
||||
It is important to install a timer handler, as we
|
||||
would get a lot of uncaptured interrupts otherwise. */
|
||||
|
||||
/* -- INSTALL INTERRUPT HANDLER FOR SIMPLE KEYBOARD -- */
|
||||
|
||||
SimpleKeyboard::init();
|
||||
|
||||
/* NOTE: In the SimpleKeyboard::init() a private static object of
|
||||
type SimpleKeyboard is created and its interrupt handler is
|
||||
registered with the interrupt dispatcher. Subsequent calls to the
|
||||
static function SimpleKeyboard::wait() look until a key is pressed.*/
|
||||
|
||||
/* -- ENABLE INTERRUPTS -- */
|
||||
|
||||
Machine::enable_interrupts();
|
||||
|
||||
/* -- INITIALIZE FRAME POOLS -- */
|
||||
|
||||
ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME,
|
||||
KERNEL_POOL_SIZE,
|
||||
0,
|
||||
0);
|
||||
|
||||
unsigned long n_info_frames = ContFramePool::needed_info_frames(PROCESS_POOL_SIZE);
|
||||
|
||||
unsigned long process_mem_pool_info_frame = kernel_mem_pool.get_frames(n_info_frames);
|
||||
|
||||
ContFramePool process_mem_pool(PROCESS_POOL_START_FRAME,
|
||||
PROCESS_POOL_SIZE,
|
||||
process_mem_pool_info_frame,
|
||||
n_info_frames);
|
||||
|
||||
/* Take care of the hole in the memory. */
|
||||
process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE);
|
||||
|
||||
/* -- INITIALIZE MEMORY (PAGING) -- */
|
||||
|
||||
/* ---- INSTALL PAGE FAULT HANDLER -- */
|
||||
|
||||
class PageFault_Handler : public ExceptionHandler {
|
||||
/* We derive the page fault handler from ExceptionHandler
|
||||
and overload the method handle_exception. */
|
||||
public:
|
||||
virtual void handle_exception(REGS * _regs) {
|
||||
PageTable::handle_fault(_regs);
|
||||
}
|
||||
} pagefault_handler;
|
||||
|
||||
/* ---- Register the page fault handler for exception no.14
|
||||
with the exception dispatcher. */
|
||||
ExceptionHandler::register_handler(14, &pagefault_handler);
|
||||
|
||||
/* ---- INITIALIZE THE PAGE TABLE -- */
|
||||
|
||||
PageTable::init_paging(&kernel_mem_pool,
|
||||
&process_mem_pool,
|
||||
4 MB); /* We share the first 4MB */
|
||||
|
||||
PageTable pt;
|
||||
|
||||
pt.load();
|
||||
|
||||
PageTable::enable_paging();
|
||||
|
||||
Console::puts("WE TURNED ON PAGING!\n");
|
||||
Console::puts("If we see this message, the page tables have been\n");
|
||||
Console::puts("set up mostly correctly.\n");
|
||||
|
||||
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
|
||||
|
||||
Console::puts("Hello World!\n");
|
||||
|
||||
/* -- GENERATE MEMORY REFERENCES */
|
||||
|
||||
int *foo = (int *) FAULT_ADDR;
|
||||
int i;
|
||||
|
||||
for (i=0; i<NACCESS; i++) {
|
||||
foo[i] = i;
|
||||
}
|
||||
|
||||
Console::puts("DONE WRITING TO MEMORY. Now testing...\n");
|
||||
|
||||
for (i=0; i<NACCESS; i++) {
|
||||
if(foo[i] != i) {
|
||||
Console::puts("TEST FAILED for access number:");
|
||||
Console::putui(i);
|
||||
Console::puts("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NACCESS) {
|
||||
Console::puts("TEST PASSED\n");
|
||||
}
|
||||
|
||||
/* -- STOP HERE */
|
||||
Console::puts("YOU CAN SAFELY TURN OFF THE MACHINE NOW.\n");
|
||||
for(;;);
|
||||
|
||||
/* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */
|
||||
return 1;
|
||||
}
|
36
MP3/MP3_Sources/linker.ld
Executable file
36
MP3/MP3_Sources/linker.ld
Executable file
|
@ -0,0 +1,36 @@
|
|||
OUTPUT_FORMAT("binary")
|
||||
ENTRY(start)
|
||||
phys = 0x00100000;
|
||||
SECTIONS
|
||||
{
|
||||
.text phys : AT(phys) {
|
||||
code = .;
|
||||
*(.text)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : AT(phys + (data - code))
|
||||
{
|
||||
data = .;
|
||||
*(.data)
|
||||
start_ctors = .;
|
||||
*(.ctor*)
|
||||
end_ctors = .;
|
||||
start_dtors = .;
|
||||
*(.dtor*)
|
||||
end_dtors = .;
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.bss : AT(phys + (bss - code))
|
||||
{
|
||||
bss = .;
|
||||
*(.bss)
|
||||
*(.gnu.linkonce.b.*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .;
|
||||
}
|
||||
|
70
MP3/MP3_Sources/machine.C
Executable file
70
MP3/MP3_Sources/machine.C
Executable file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
File: machine.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/04
|
||||
|
||||
LOW-LEVEL MACHINE FUNCTIONS.
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H"
|
||||
#include "machine_low.H"
|
||||
|
||||
#include "assert.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INTERRUPTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
bool Machine::interrupts_enabled() {
|
||||
/* We check the IF flag (INTERRUPT ENABLE) in the EFLAGS status register. */
|
||||
return get_EFLAGS() & (1 << 9);
|
||||
}
|
||||
|
||||
void Machine::enable_interrupts() {
|
||||
assert(!interrupts_enabled());
|
||||
__asm__ __volatile__ ("sti");
|
||||
}
|
||||
|
||||
void Machine::disable_interrupts() {
|
||||
assert(interrupts_enabled());
|
||||
__asm__ __volatile__ ("cli");
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* PORT I/O OPERATIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* We will use this later on for reading from the I/O ports to get data
|
||||
* from devices such as the keyboard. We are using what is called
|
||||
* 'inline assembly' in these routines to actually do the work */
|
||||
char Machine::inportb (unsigned short _port) {
|
||||
unsigned char rv;
|
||||
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
unsigned short Machine::inportw (unsigned short _port) {
|
||||
unsigned short rv;
|
||||
__asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* We will use this to write to I/O ports to send bytes to devices. This
|
||||
* will be used in the next tutorial for changing the textmode cursor
|
||||
* position. Again, we use some inline assembly for the stuff that simply
|
||||
* cannot be done in C */
|
||||
void Machine::outportb (unsigned short _port, char _data) {
|
||||
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
|
||||
}
|
||||
|
||||
void Machine::outportw (unsigned short _port, unsigned short _data) {
|
||||
__asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data));
|
||||
}
|
123
MP3/MP3_Sources/machine.H
Executable file
123
MP3/MP3_Sources/machine.H
Executable file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
File: machine.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/05
|
||||
|
||||
Description: Low-level definitions for x86 architecture.
|
||||
|
||||
- Register context
|
||||
- Data and code segment for kernel.
|
||||
- Interrupt enable/disable.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _machine_H_ // include file only once
|
||||
#define _machine_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* REGISTER CONTEXT ON THE STACK WHEN EXCEPTION/INTERRUPT REACHES EXCEPTION
|
||||
DISPATCHER OR INTERRUPT DISPATCHER.
|
||||
THIS IS ALSO USED IN THREAD SCHEDULING (for context switching) */
|
||||
typedef struct regs {
|
||||
|
||||
/* segment descriptors */
|
||||
unsigned int gs;
|
||||
unsigned int fs;
|
||||
unsigned int es;
|
||||
unsigned int ds;
|
||||
|
||||
/* General purpose registers, managed by pusha/popa in x86. */
|
||||
unsigned int edi;
|
||||
unsigned int esi;
|
||||
unsigned int ebp;
|
||||
unsigned int esp;
|
||||
unsigned int ebx;
|
||||
unsigned int edx;
|
||||
unsigned int ecx;
|
||||
unsigned int eax;
|
||||
|
||||
/* In the low-level handlers (i.e. before we call the
|
||||
exception or interrupt dispatcher) we push number
|
||||
of the interrupt and error code onto the stack. */
|
||||
unsigned int int_no;
|
||||
unsigned int err_code;
|
||||
|
||||
/* These registers are pushed on the stack when
|
||||
the exception occurs. */
|
||||
unsigned int eip;
|
||||
unsigned int cs;
|
||||
unsigned int eflags;
|
||||
|
||||
/* These registers are pushed on the stack only when
|
||||
the exception occured in user mode.
|
||||
As long as you are in kernel mode, the register context
|
||||
is 68 bytes long, and not 76! */
|
||||
unsigned int useresp;
|
||||
unsigned int ss;
|
||||
} REGS;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CLASS M a c h i n e */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class Machine {
|
||||
|
||||
public:
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* MEMORY MANAGEMENT */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
static const unsigned int PAGE_SIZE = 4096;
|
||||
static const unsigned int PT_ENTRIES_PER_PAGE = 1024;
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* INTERRUPTS */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
This is done by checking the Interrupt Enabled flag in the
|
||||
EFLAG status register and by issuing STI/CLI instructions.
|
||||
(NOTE: If we have multiple threads, each has its own status register.)
|
||||
*/
|
||||
|
||||
static bool interrupts_enabled();
|
||||
/* Returns whether interrupts are enabled. */
|
||||
|
||||
static void enable_interrupts();
|
||||
static void disable_interrupts();
|
||||
/* Issue CLI/STI instructions. */
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* PORT I/O OPERATIONS */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
static char inportb (unsigned short _port);
|
||||
static unsigned short inportw (unsigned short _port);
|
||||
/* Read data from input port _port.*/
|
||||
|
||||
static void outportb (unsigned short _port, char _data);
|
||||
static void outportw (unsigned short _port, unsigned short _data);
|
||||
/* Write _data to output port _port.*/
|
||||
|
||||
};
|
||||
#endif
|
31
MP3/MP3_Sources/machine_low.H
Executable file
31
MP3/MP3_Sources/machine_low.H
Executable file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
File: machine_low.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 12/09/03
|
||||
|
||||
|
||||
Low-level CPU operations.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _machine_low_H_ // include file only once
|
||||
#define _machine_low_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* (none) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* LOW-LEVER CPU OPERATIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
extern "C" unsigned long get_EFLAGS();
|
||||
/* Return value of the EFLAGS status register. */
|
||||
|
||||
#endif
|
||||
|
18
MP3/MP3_Sources/machine_low.asm
Executable file
18
MP3/MP3_Sources/machine_low.asm
Executable file
|
@ -0,0 +1,18 @@
|
|||
; File: machine_low.asm
|
||||
;
|
||||
; Low level CPU handling functions.
|
||||
;
|
||||
; September 3, 2012
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; get_EFLAGS()
|
||||
;
|
||||
; Returns value of the EFLAGS status register.
|
||||
;
|
||||
; ----------------------------------------------------------------------
|
||||
global _get_EFLAGS
|
||||
; this function is exported.
|
||||
_get_EFLAGS:
|
||||
pushfd ; push eflags
|
||||
pop eax ; pop contents into eax
|
||||
ret
|
78
MP3/MP3_Sources/makefile
Executable file
78
MP3/MP3_Sources/makefile
Executable file
|
@ -0,0 +1,78 @@
|
|||
CPP = gcc
|
||||
CPP_OPTIONS = -m32 -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables
|
||||
|
||||
all: kernel.bin
|
||||
|
||||
clean:
|
||||
rm -f *.o *.bin
|
||||
|
||||
start.o: start.asm gdt_low.asm idt_low.asm irq_low.asm
|
||||
nasm -f aout -o start.o start.asm
|
||||
|
||||
utils.o: utils.C utils.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o utils.o utils.C
|
||||
|
||||
assert.o: assert.C assert.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o assert.o assert.C
|
||||
|
||||
|
||||
# ==== VARIOUS LOW-LEVEL STUFF =====
|
||||
|
||||
gdt.o: gdt.C gdt.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o gdt.o gdt.C
|
||||
|
||||
machine.o: machine.C machine.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o machine.o machine.C
|
||||
|
||||
machine_low.o: machine_low.asm machine_low.H
|
||||
nasm -f aout -o machine_low.o machine_low.asm
|
||||
|
||||
# ==== EXCEPTIONS AND INTERRUPTS =====
|
||||
|
||||
idt.o: idt.C idt.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o idt.o idt.C
|
||||
|
||||
irq.o: irq.C irq.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o irq.o irq.C
|
||||
|
||||
exceptions.o: exceptions.C exceptions.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o exceptions.o exceptions.C
|
||||
|
||||
interrupts.o: interrupts.C interrupts.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o interrupts.o interrupts.C
|
||||
|
||||
# ==== DEVICES =====
|
||||
|
||||
console.o: console.C console.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o console.o console.C
|
||||
|
||||
simple_timer.o: simple_timer.C simple_timer.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o simple_timer.o simple_timer.C
|
||||
|
||||
simple_keyboard.o: simple_keyboard.C simple_keyboard.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o simple_keyboard.o simple_keyboard.C
|
||||
|
||||
# ==== MEMORY =====
|
||||
|
||||
paging_low.o: paging_low.asm paging_low.H
|
||||
nasm -f aout -o paging_low.o paging_low.asm
|
||||
|
||||
page_table.o: page_table.C page_table.H paging_low.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o page_table.o page_table.C
|
||||
|
||||
cont_frame_pool.o: cont_frame_pool.C cont_frame_pool.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o cont_frame_pool.o cont_frame_pool.C
|
||||
|
||||
# ==== KERNEL MAIN FILE =====
|
||||
|
||||
kernel.o: kernel.C console.H simple_timer.H page_table.H
|
||||
$(CPP) $(CPP_OPTIONS) -c -o kernel.o kernel.C
|
||||
|
||||
|
||||
kernel.bin: start.o utils.o kernel.o assert.o console.o gdt.o idt.o irq.o exceptions.o \
|
||||
interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o machine.o \
|
||||
machine_low.o
|
||||
ld -melf_i386 -T linker.ld -o kernel.bin start.o utils.o kernel.o assert.o console.o \
|
||||
gdt.o idt.o irq.o exceptions.o \
|
||||
interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o machine.o \
|
||||
machine_low.o
|
91
MP3/MP3_Sources/page_table.C
Normal file
91
MP3/MP3_Sources/page_table.C
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "assert.H"
|
||||
#include "exceptions.H"
|
||||
#include "console.H"
|
||||
#include "paging_low.H"
|
||||
#include "page_table.H"
|
||||
|
||||
PageTable * PageTable::current_page_table = NULL;
|
||||
unsigned int PageTable::paging_enabled = 0;
|
||||
ContFramePool * PageTable::kernel_mem_pool = NULL;
|
||||
ContFramePool * PageTable::process_mem_pool = NULL;
|
||||
unsigned long PageTable::shared_size = 0;
|
||||
|
||||
|
||||
|
||||
void PageTable::init_paging(ContFramePool * _kernel_mem_pool,
|
||||
ContFramePool * _process_mem_pool,
|
||||
const unsigned long _shared_size)
|
||||
{
|
||||
kernel_mem_pool = _kernel_mem_pool;
|
||||
process_mem_pool = process_mem_pool;
|
||||
shared_size = _shared_size;
|
||||
|
||||
Console::puts("\nInitialized Paging System\n");
|
||||
}
|
||||
|
||||
PageTable::PageTable()
|
||||
{
|
||||
//kernel_mem_pool->get_frames(1); // Need to take one frame for page directory.
|
||||
|
||||
//page_directory = (unsigned long *) 0x32000; // Should be the starting address after 1st 2MB
|
||||
page_directory = (unsigned long *) kernel_mem_pool->get_frames(1); // Should I get the address like this???
|
||||
|
||||
//unsigned long * page_table = (unsigned long *) 0x33000; // Should be 4kb after the page directory.
|
||||
unsigned long * page_table = page_directory + 0x1000; // Might be able to just do this.
|
||||
|
||||
unsigned long tempaddr; // Temporary address iterator.
|
||||
|
||||
// We need to map the first 4MB.
|
||||
for(unsigned int i = 0; i < 1024; i++)
|
||||
{
|
||||
page_table[i] = tempaddr | 3; // set bits 0 and 1 to present and read/write respectively
|
||||
tempaddr += 4096; // 4096 = 4kb
|
||||
}
|
||||
|
||||
|
||||
// Fill first entry of page directory.
|
||||
page_directory[0] = *page_table;
|
||||
page_directory[0] = page_directory[0] | 3;
|
||||
|
||||
for(unsigned int j = 1; j < 1024; j++)
|
||||
{
|
||||
page_directory[j] = 0 | 2;
|
||||
}
|
||||
|
||||
current_page_table = this;
|
||||
|
||||
Console::puts("\nConstructed Page Table object\n");
|
||||
}
|
||||
|
||||
|
||||
void PageTable::load()
|
||||
{
|
||||
write_cr3(*page_directory);
|
||||
current_page_table = this;
|
||||
Console::puts("\nLoaded page table\n");
|
||||
}
|
||||
|
||||
void PageTable::enable_paging()
|
||||
{
|
||||
write_cr3(*current_page_table->page_directory);
|
||||
write_cr0(read_cr0() | 0x80000000);
|
||||
paging_enabled = read_cr0();
|
||||
Console::puts("\nEnabled paging\n");
|
||||
}
|
||||
|
||||
void PageTable::handle_fault(REGS * _r)
|
||||
{
|
||||
/*
|
||||
unsigned long tempframe = process_mem_pool->get_frames(1);
|
||||
Console::puts("\nerror code: ");
|
||||
Console::puti(_r->err_code);
|
||||
|
||||
unsigned char mask = 0x00;
|
||||
|
||||
|
||||
read_cr2();
|
||||
*/
|
||||
assert(false);
|
||||
Console::puts("\nhandled page fault\n");
|
||||
}
|
||||
|
91
MP3/MP3_Sources/page_table.H
Executable file
91
MP3/MP3_Sources/page_table.H
Executable file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
File: page_table.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 16/12/07
|
||||
|
||||
Description: Basic Paging.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _page_table_H_ // include file only once
|
||||
#define _page_table_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "machine.H"
|
||||
#include "exceptions.H"
|
||||
#include "cont_frame_pool.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* P A G E - T A B L E */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class PageTable {
|
||||
|
||||
private:
|
||||
|
||||
/* THESE MEMBERS ARE COMMON TO ENTIRE PAGING SUBSYSTEM */
|
||||
static PageTable * current_page_table; /* pointer to currently loaded page table object */
|
||||
static unsigned int paging_enabled; /* is paging turned on (i.e. are addresses logical)? */
|
||||
static ContFramePool * kernel_mem_pool; /* Frame pool for the kernel memory */
|
||||
static ContFramePool * process_mem_pool; /* Frame pool for the process memory */
|
||||
static unsigned long shared_size; /* size of shared address space */
|
||||
|
||||
/* DATA FOR CURRENT PAGE TABLE */
|
||||
unsigned long * page_directory; /* where is page directory located? */
|
||||
|
||||
public:
|
||||
static const unsigned int PAGE_SIZE = Machine::PAGE_SIZE;
|
||||
/* in bytes */
|
||||
static const unsigned int ENTRIES_PER_PAGE = Machine::PT_ENTRIES_PER_PAGE;
|
||||
/* in entries, duh! */
|
||||
|
||||
static void init_paging(ContFramePool * _kernel_mem_pool,
|
||||
ContFramePool * _process_mem_pool,
|
||||
const unsigned long _shared_size);
|
||||
/* Set the global parameters for the paging subsystem. */
|
||||
|
||||
PageTable();
|
||||
/* Initializes a page table with a given location for the directory and the
|
||||
page table proper.
|
||||
NOTE: The PageTable object still needs to be stored somewhere!
|
||||
Probably it is best to have it on the stack, as there is no
|
||||
memory manager yet...
|
||||
NOTE2: It may also be simpler to create the first page table *before*
|
||||
paging has been enabled.
|
||||
*/
|
||||
|
||||
void load();
|
||||
/* Makes the given page table the current table. This must be done once during
|
||||
system startup and whenever the address space is switched (e.g. during
|
||||
process switching). */
|
||||
|
||||
static void enable_paging();
|
||||
/* Enable paging on the CPU. Typically, a CPU start with paging disabled, and
|
||||
memory is accessed by addressing physical memory directly. After paging is
|
||||
enabled, memory is addressed logically. */
|
||||
|
||||
static void handle_fault(REGS * _r);
|
||||
/* The page fault handler. */
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
51
MP3/MP3_Sources/paging_low.H
Executable file
51
MP3/MP3_Sources/paging_low.H
Executable file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
File: paging_low.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/28
|
||||
|
||||
|
||||
Low-level register operations for x86 paging subsystem.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _paging_low_H_ // include file only once
|
||||
#define _paging_low_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- none -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FORWARDS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* LOW-LEVEL PAGING ROUTINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* The low-level functions (defined in file 'paging_low.asm') that handle the
|
||||
low-level function to manage the page tables. */
|
||||
|
||||
|
||||
/* -- CR0 -- */
|
||||
extern "C" unsigned long read_cr0();
|
||||
extern "C" void write_cr0(unsigned long _val);
|
||||
|
||||
/* -- CR2 -- */
|
||||
extern "C" unsigned long read_cr2();
|
||||
|
||||
/* -- CR3 -- */
|
||||
extern "C" unsigned long read_cr3();
|
||||
extern "C" void write_cr3(unsigned long _val);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
32
MP3/MP3_Sources/paging_low.asm
Executable file
32
MP3/MP3_Sources/paging_low.asm
Executable file
|
@ -0,0 +1,32 @@
|
|||
global _read_cr0
|
||||
_read_cr0:
|
||||
mov eax, cr0
|
||||
retn
|
||||
|
||||
global _write_cr0
|
||||
_write_cr0:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8]
|
||||
mov cr0, eax
|
||||
pop ebp
|
||||
retn
|
||||
|
||||
global _read_cr2
|
||||
_read_cr2:
|
||||
mov eax, cr2
|
||||
retn
|
||||
|
||||
global _read_cr3
|
||||
_read_cr3:
|
||||
mov eax, cr3
|
||||
retn
|
||||
|
||||
global _write_cr3
|
||||
_write_cr3:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8]
|
||||
mov cr3, eax
|
||||
pop ebp
|
||||
retn
|
79
MP3/MP3_Sources/simple_keyboard.C
Executable file
79
MP3/MP3_Sources/simple_keyboard.C
Executable file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
File: simple_keyboard.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 2017/06/30
|
||||
|
||||
Simple control of the keyboard.
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* (none) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "machine.H"
|
||||
#include "console.H"
|
||||
#include "interrupts.H"
|
||||
#include "simple_keyboard.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTRUCTOR */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
SimpleKeyboard::SimpleKeyboard() {
|
||||
key_pressed = false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* METHODS FOR CLASS S i m p l e K e y b o a r d */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void SimpleKeyboard::handle_interrupt(REGS *_r) {
|
||||
/* What to do when keyboard interrupt occurs? In this case, we update
|
||||
"key_pressed". */
|
||||
|
||||
unsigned char status = Machine::inportb(STATUS_PORT);
|
||||
/* lowest bit of status will be set if buffer is not empty. */
|
||||
if (status & 0x01) {
|
||||
char kc = Machine::inportb(DATA_PORT);
|
||||
if (kc >= 0) {
|
||||
key_pressed = true;
|
||||
key_code = kc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleKeyboard::wait() {
|
||||
/* Loop until the user presses a key. */
|
||||
|
||||
kb.key_pressed = false;
|
||||
|
||||
while(kb.key_pressed == false);
|
||||
|
||||
}
|
||||
|
||||
char SimpleKeyboard::read() {
|
||||
/* Loop until the user presses a key, and then return the keycode. */
|
||||
kb.key_pressed = false;
|
||||
|
||||
while (kb.key_pressed == false);
|
||||
|
||||
return kb.key_code;
|
||||
}
|
||||
|
||||
SimpleKeyboard SimpleKeyboard::kb;
|
||||
|
||||
void SimpleKeyboard::init() {
|
||||
InterruptHandler::register_handler(1, &kb);
|
||||
}
|
||||
|
||||
|
68
MP3/MP3_Sources/simple_keyboard.H
Executable file
68
MP3/MP3_Sources/simple_keyboard.H
Executable file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
File: simple_keyboard.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 2017/02/17
|
||||
|
||||
Implements an interrupt handler for the keyboard.
|
||||
The function is implemented in 'handle_interrupt'.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLE_KEYBOARD_H_
|
||||
#define _SIMPLE_KEYBOARD_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "interrupts.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* S I M P L E K E Y B O A R D */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class SimpleKeyboard : public InterruptHandler {
|
||||
|
||||
public :
|
||||
|
||||
SimpleKeyboard();
|
||||
/* Initialize the simple keyboard. */
|
||||
|
||||
virtual void handle_interrupt(REGS *_r);
|
||||
/* This must be installed as the interrupt handler for the keyboard
|
||||
when the system gets initialized. (e.g. in "kernel.C")
|
||||
*/
|
||||
|
||||
static void init();
|
||||
|
||||
static void wait();
|
||||
/* Wait until keyboard is pressed. The implementation is based
|
||||
on busy looping! */
|
||||
|
||||
static char read();
|
||||
/* Wait until keyboard is pressed and return the keycode.
|
||||
Note: The keycode is not the same as the character!
|
||||
Note2: This is a very "approximate" implementation. Not complete,
|
||||
and likely not correct. Use only under duress!
|
||||
The implementation is based on busy looping! */
|
||||
|
||||
private:
|
||||
bool key_pressed;
|
||||
char key_code;
|
||||
static SimpleKeyboard kb;
|
||||
|
||||
static const unsigned short STATUS_PORT = 0x64;
|
||||
static const unsigned short DATA_PORT = 0x60;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
100
MP3/MP3_Sources/simple_timer.C
Executable file
100
MP3/MP3_Sources/simple_timer.C
Executable file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
File: simple_timer.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/19
|
||||
|
||||
Simple control of the
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "assert.H"
|
||||
#include "utils.H"
|
||||
#include "console.H"
|
||||
#include "interrupts.H"
|
||||
#include "simple_timer.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTRUCTOR */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
SimpleTimer::SimpleTimer(int _hz) {
|
||||
/* How long has the system been running? */
|
||||
seconds = 0;
|
||||
ticks = 0; /* ticks since last "seconds" update. */
|
||||
|
||||
/* At what frequency do we update the ticks counter? */
|
||||
/* hz = 18; */
|
||||
/* Actually, by defaults it is 18.22Hz.
|
||||
In this way, a 16-bit counter wraps
|
||||
around every hour. */
|
||||
set_frequency(_hz);
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* METHODS FOR CLASS S i m p l e T i m e r */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
void SimpleTimer::handle_interrupt(REGS *_r) {
|
||||
/* What to do when timer interrupt occurs? In this case, we update "ticks",
|
||||
and maybe update "seconds".
|
||||
This must be installed as the interrupt handler for the timer in the
|
||||
when the system gets initialized. (e.g. in "kernel.C") */
|
||||
|
||||
/* Increment our "ticks" count */
|
||||
ticks++;
|
||||
|
||||
/* Whenever a second is over, we update counter accordingly. */
|
||||
if (ticks >= hz )
|
||||
{
|
||||
seconds++;
|
||||
ticks = 0;
|
||||
Console::puts("One second has passed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SimpleTimer::set_frequency(int _hz) {
|
||||
/* Set the interrupt frequency for the simple timer.
|
||||
Preferably set this before installing the timer handler! */
|
||||
|
||||
hz = _hz; /* Remember the frequency. */
|
||||
int divisor = 1193180 / _hz; /* The input clock runs at 1.19MHz */
|
||||
Machine::outportb(0x43, 0x34); /* Set command byte to be 0x36. */
|
||||
Machine::outportb(0x40, divisor & 0xFF); /* Set low byte of divisor. */
|
||||
Machine::outportb(0x40, divisor >> 8); /* Set high byte of divisor. */
|
||||
}
|
||||
|
||||
void SimpleTimer::current(unsigned long * _seconds, int * _ticks) {
|
||||
/* Return the current "time" since the system started. */
|
||||
|
||||
*_seconds = seconds;
|
||||
*_ticks = ticks;
|
||||
}
|
||||
|
||||
void SimpleTimer::wait(unsigned long _seconds) {
|
||||
/* Wait for a particular time to be passed. This is based on busy looping! */
|
||||
|
||||
unsigned long now_seconds;
|
||||
int now_ticks;
|
||||
current(&now_seconds, &now_ticks);
|
||||
|
||||
unsigned long then_seconds = now_seconds + _seconds;
|
||||
|
||||
while((seconds <= then_seconds) && (ticks < now_ticks));
|
||||
}
|
||||
|
||||
|
70
MP3/MP3_Sources/simple_timer.H
Executable file
70
MP3/MP3_Sources/simple_timer.H
Executable file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
File: simple_timer.H
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
Date : 09/03/19
|
||||
|
||||
This is a simple example of a hardware interrupt handler.
|
||||
As an example, this implements a timer, which in turn
|
||||
triggers a function to be called at the given frequency.
|
||||
The function is implemented in 'handle_interrupt'.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLE_TIMER_H_
|
||||
#define _SIMPLE_TIMER_H_
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "interrupts.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* S I M P L E T I M E R */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
class SimpleTimer : public InterruptHandler {
|
||||
|
||||
private:
|
||||
|
||||
/* How long has the system been running? */
|
||||
unsigned long seconds;
|
||||
int ticks; /* ticks since last "seconds" update. */
|
||||
|
||||
/* At what frequency do we update the ticks counter? */
|
||||
int hz; /* Actually, by defaults it is 18.22Hz.
|
||||
In this way, a 16-bit counter wraps
|
||||
around every hour. */
|
||||
|
||||
void set_frequency(int _hz);
|
||||
/* Set the interrupt frequency for the simple timer. */
|
||||
|
||||
public :
|
||||
|
||||
SimpleTimer(int _hz);
|
||||
/* Initialize the simple timer, and set its frequency. */
|
||||
|
||||
virtual void handle_interrupt(REGS *_r);
|
||||
/* This must be installed as the interrupt handler for the timer
|
||||
when the system gets initialized. (e.g. in "kernel.C")
|
||||
*/
|
||||
|
||||
void current(unsigned long * _seconds, int * _ticks);
|
||||
/* Return the current "time" since the system started. */
|
||||
|
||||
void wait(unsigned long _seconds);
|
||||
/* Wait for a particular time to be passed. The implementation is based
|
||||
on busy looping! */
|
||||
|
||||
};
|
||||
|
||||
#endif
|
110
MP3/MP3_Sources/start.asm
Executable file
110
MP3/MP3_Sources/start.asm
Executable file
|
@ -0,0 +1,110 @@
|
|||
; bkerndev - Bran's Kernel Development Tutorial
|
||||
; By: Brandon F. (friesenb@gmail.com)
|
||||
; Desc: Kernel entry point, stack, and Interrupt Service Routines.
|
||||
;
|
||||
; Notes: No warranty expressed or implied. Use at own risk.
|
||||
;
|
||||
; This is the kernel's entry point. We could either call main here,
|
||||
; or we can use this to setup the stack or other nice stuff, like
|
||||
; perhaps setting up the GDT and segments. Please note that interrupts
|
||||
; are disabled at this point: More on interrupts later!
|
||||
[BITS 32]
|
||||
global start
|
||||
start:
|
||||
mov esp, _sys_stack ; This points the stack to our new stack area
|
||||
jmp stublet
|
||||
|
||||
; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
|
||||
ALIGN 4
|
||||
mboot:
|
||||
; Multiboot macros to make a few lines later more readable
|
||||
MULTIBOOT_PAGE_ALIGN equ 1<<0
|
||||
MULTIBOOT_MEMORY_INFO equ 1<<1
|
||||
MULTIBOOT_AOUT_KLUDGE equ 1<<16
|
||||
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
|
||||
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
|
||||
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
EXTERN code, bss, end
|
||||
|
||||
; This is the GRUB Multiboot header. A boot signature
|
||||
dd MULTIBOOT_HEADER_MAGIC
|
||||
dd MULTIBOOT_HEADER_FLAGS
|
||||
dd MULTIBOOT_CHECKSUM
|
||||
|
||||
; AOUT kludge - must be physical addresses. Make a note of these:
|
||||
; The linker script fills in the data for these ones!
|
||||
dd mboot ; header_addr:
|
||||
; address corresponding to the multiboot header
|
||||
dd code ; load_addr:
|
||||
; physical address of the beginning of the text segment
|
||||
dd bss ; load_end_addr:
|
||||
; physical address of the end of the data segment
|
||||
; (load_end_addr - load_addr) specifies how much data to load.
|
||||
dd end ; bss_end_addr:
|
||||
; pysical address of end of bss segment.
|
||||
; boot loader initializes this area to zero,
|
||||
; and reserves the memory
|
||||
dd start ; entry_addr:
|
||||
; physical address to which the boot loader should jump
|
||||
; to start running the OS
|
||||
|
||||
stublet:
|
||||
|
||||
; Initilization of static global objects. This goes through each object
|
||||
; in the ctors section of the object file, where the global constructors
|
||||
; created by C++ are put, and calls it. Normally C++ compilers add some code
|
||||
; to do this, but that code is in the standard library - which we do not
|
||||
; include
|
||||
; See linker.ld to see where we tell the linker to put them.
|
||||
extern start_ctors, end_ctors, start_dtors, end_dtors
|
||||
|
||||
static_ctors_loop:
|
||||
mov ebx, start_ctors
|
||||
jmp .test
|
||||
.body:
|
||||
call [ebx]
|
||||
add ebx,4
|
||||
.test:
|
||||
cmp ebx, end_ctors
|
||||
jb .body
|
||||
|
||||
; Entering the kernel proper.
|
||||
extern _main
|
||||
call _main
|
||||
|
||||
; Deinitialization of static global objects. This goes through each object
|
||||
; in the dtors section of the object file, where the global destructors
|
||||
; created by C++ are put, and calls it. Normally C++ compilers add some code
|
||||
; to do this, but that code is in the standard library - which we do not include.
|
||||
; See linker.ld to see where we tell the linker to put them.
|
||||
|
||||
static_dtors_loop:
|
||||
mov ebx, start_dtors
|
||||
jmp .test
|
||||
.body:
|
||||
call [ebx]
|
||||
add ebx,4
|
||||
.test:
|
||||
cmp ebx, end_dtors
|
||||
jb .body
|
||||
|
||||
; Enter an endless loop here in order to stop.
|
||||
jmp $
|
||||
|
||||
; Set up Global Descriptor Table
|
||||
%include "gdt_low.asm"
|
||||
|
||||
; Set up Low-level Exception Handling
|
||||
%include "idt_low.asm"
|
||||
|
||||
; Set up Low-level Interrupt Handling
|
||||
%include "irq_low.asm"
|
||||
|
||||
; Here is the definition of our BSS section. Right now, we'll use
|
||||
; it just to store the stack. Remember that a stack actually grows
|
||||
; downwards, so we declare the size of the data before declaring
|
||||
; the identifier '_sys_stack'
|
||||
SECTION .bss
|
||||
resb 8192 ; This reserves 8KBytes of memory here
|
||||
_sys_stack:
|
||||
|
167
MP3/MP3_Sources/utils.C
Executable file
167
MP3/MP3_Sources/utils.C
Executable file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
File: utils.C
|
||||
|
||||
Author: R. Bettati
|
||||
Department of Computer Science
|
||||
Texas A&M University
|
||||
|
||||
Date : 09/02/12
|
||||
|
||||
*/
|
||||
|
||||
/* Some of the code comes from Brandon Friesens OS Tutorial:
|
||||
* bkerndev - Bran's Kernel Development Tutorial
|
||||
* By: Brandon F. (friesenb@gmail.com)
|
||||
* Desc: Interrupt Descriptor Table management
|
||||
*
|
||||
* Notes: No warranty expressed or implied. Use at own risk. */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none ) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INCLUDES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#include "utils.H"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DATA STRUCTURES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CONSTANTS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* -- (none) -- */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* ABORT (USED e.g. IN _ASSERT() */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void abort() {
|
||||
for(;;);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MEMORY OPERATIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void *memcpy(void *dest, const void *src, int count)
|
||||
{
|
||||
const char *sp = (const char *)src;
|
||||
char *dp = (char *)dest;
|
||||
for(; count != 0; count--) *dp++ = *sp++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, char val, int count)
|
||||
{
|
||||
char *temp = (char *)dest;
|
||||
for( ; count != 0; count--) *temp++ = val;
|
||||
return dest;
|
||||
}
|
||||
|
||||
unsigned short *memsetw(unsigned short *dest, unsigned short val, int count)
|
||||
{
|
||||
unsigned short *temp = (unsigned short *)dest;
|
||||
for( ; count != 0; count--) *temp++ = val;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* STRING OPERATIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int strlen(const char *_str) {
|
||||
/* This loops through character array 'str', returning how
|
||||
* many characters it needs to check before it finds a 0.
|
||||
* In simple words, it returns the length in bytes of a string */
|
||||
int len = 0;
|
||||
while (*_str != 0) {
|
||||
_str++;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
void strcpy(char* _dst, char* _src) {
|
||||
while (*_src != 0) {
|
||||
*_dst = *_src;
|
||||
_dst++;
|
||||
_src++;
|
||||
}
|
||||
*_dst = 0; // put terminating 0 at end.
|
||||
}
|
||||
|
||||
void int2str(int _num, char * _str) {
|
||||
/* -- THIS IMPLEMENTATION IS ONE PRETTY BAD HACK. */
|
||||
int i;
|
||||
char temp[11];
|
||||
|
||||
temp[0] = '\0';
|
||||
for(i = 1; i <= 10; i++) {
|
||||
temp[i] = _num % 10 + '0';
|
||||
_num /= 10;
|
||||
}
|
||||
for(i = 10; temp[i] == '0'; i--);
|
||||
if( i == 0 )
|
||||
i++;
|
||||
while( i >= 0 )
|
||||
*_str++ = temp[i--];
|
||||
}
|
||||
|
||||
|
||||
void uint2str(unsigned int _num, char * _str) {
|
||||
/* -- THIS IS A BAD HACK AS WELL. */
|
||||
int i;
|
||||
char temp[11];
|
||||
|
||||
temp[0] = '\0';
|
||||
for(i = 1; i <= 10; i++) {
|
||||
temp[i] = _num % 10 + '0';
|
||||
_num /= 10;
|
||||
}
|
||||
for(i = 10; temp[i] == '0'; i--);
|
||||
if( i == 0 )
|
||||
i++;
|
||||
while( i >= 0 )
|
||||
*_str++ = temp[i--];
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* POERT I/O OPERATIONS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* We will use this later on for reading from the I/O ports to get data
|
||||
* from devices such as the keyboard. We are using what is called
|
||||
* 'inline assembly' in these routines to actually do the work */
|
||||
char inportb (unsigned short _port) {
|
||||
unsigned char rv;
|
||||
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
unsigned short inportw (unsigned short _port) {
|
||||
unsigned short rv;
|
||||
__asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* We will use this to write to I/O ports to send bytes to devices. This
|
||||
* will be used in the next tutorial for changing the textmode cursor
|
||||
* position. Again, we use some inline assembly for the stuff that simply
|
||||
* cannot be done in C */
|
||||
void outportb (unsigned short _port, char _data) {
|
||||
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
|
||||
}
|
||||
|
||||
void outportw (unsigned short _port, unsigned short _data) {
|
||||
__asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data));
|
||||
}
|
62
MP3/MP3_Sources/utils.H
Executable file
62
MP3/MP3_Sources/utils.H
Executable file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
File : utils.H
|
||||
|
||||
Author : Riccardo Bettati
|
||||
Modified : 2017/05/02
|
||||
|
||||
Description : Various definitions (NULL) and
|
||||
utility functions (e.g. abort, memory and
|
||||
string functions).
|
||||
*/
|
||||
|
||||
#ifndef _utils_h_
|
||||
#define _utils_h_
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* GENERAL CONSTANTS */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* ABORT */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
void abort();
|
||||
/* Stop execution. */
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* SIMPLE MEMORY OPERATIONS */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
void *memcpy(void *dest, const void *src, int count);
|
||||
/* Copy _count bytes from _src to _dest. (No check for uverlapping) */
|
||||
|
||||
void *memset(void *dest, char val, int count);
|
||||
/* Set _count bytes to value _val, starting from location _dest. */
|
||||
|
||||
unsigned short *memsetw(unsigned short *dest, unsigned short val, int count);
|
||||
/* Same as above, but operations are 16-bit wide. */
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/* SIMPLE STRING OPERATIONS (STRINGS ARE NULL-TERMINATED) */
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
int strlen(const char * _str);
|
||||
/* Determine the length of null-terminated string. */
|
||||
|
||||
void strcpy(char * _dst, char * _src);
|
||||
/* Copy null-terminated string from _src to _dst. */
|
||||
|
||||
void int2str(int _num, char * _str);
|
||||
/* Convert int to null-terminated string. */
|
||||
|
||||
void uint2str(unsigned int _num, char * _str);
|
||||
/* Convert unsigned int to null-terminated string. */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
BIN
MP3/__MACOSX/._MP3_Sources
Normal file
BIN
MP3/__MACOSX/._MP3_Sources
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._README.TXT
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._README.TXT
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._assert.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._assert.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._assert.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._assert.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._console.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._console.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._console.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._console.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._copykernel.sh
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._copykernel.sh
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._kernel.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._kernel.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._linker.ld
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._linker.ld
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._makefile
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._makefile
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._page_table.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._page_table.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._page_table.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._page_table.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._start.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._start.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._utils.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._utils.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._utils.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._utils.H
Normal file
Binary file not shown.
BIN
MP3/handout_mp3.pdf
Normal file
BIN
MP3/handout_mp3.pdf
Normal file
Binary file not shown.
Reference in a new issue