summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-07-10 21:04:18 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-07-10 21:04:18 +0200
commit573b82fd2d46ebca7f98e5323e9f18e593a7996f (patch)
tree643d480130d1a6ac2639d63b384f43ca9cd82d83
parentea3afaaf2e1926328ca94fa1227c49631adaf5e7 (diff)
downloadabaos-573b82fd2d46ebca7f98e5323e9f18e593a7996f.tar.gz
abaos-573b82fd2d46ebca7f98e5323e9f18e593a7996f.tar.bz2
VGA Z-buffer is now dynamically allocated and freed
memory management can reuse the last pointer malloced if freed again
-rw-r--r--src/.gdbinit1
-rw-r--r--src/drivers/video/vga.c55
-rw-r--r--src/drivers/video/vga.h6
-rw-r--r--src/kernel/kernel.c13
-rw-r--r--src/kernel/memorymanagement.c15
-rw-r--r--src/kernel/memorymanagement.h1
6 files changed, 71 insertions, 20 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index e5b0f07..da2e75c 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1,4 +1,3 @@
-set disassemble-next-line on
target remote localhost:1234
symbol-file kernel.sym
break kernel_main
diff --git a/src/drivers/video/vga.c b/src/drivers/video/vga.c
index 0cd623d..751cbc5 100644
--- a/src/drivers/video/vga.c
+++ b/src/drivers/video/vga.c
@@ -1,6 +1,7 @@
#include "vga.h"
#include "stdio.h"
+#include "stdlib.h"
#include "kernel.h"
@@ -48,7 +49,12 @@ void vga_deactivate( void *obj )
void vga_deinit( void *obj )
{
- // nothing to do
+ vga_t *vga = (vga_t *)obj;
+
+ if( vga->zbuffer != NULL ) {
+ free( vga->zbuffer );
+ vga->zbuffer = NULL;
+ }
}
void vga_print_info( void *obj )
@@ -213,19 +219,19 @@ static uint8_t *get_frame_buffer_segment( vga_t *vga )
uint8_t *segment = 0x0;
switch( segment_no ) {
- case 0: // A0000h - BFFFFh, 128k
+ case 0: // A0000h - BFFFFh
segment = (uint8_t *)0xA0000;
break;
- case 1: // A0000h - AFFFFh, 64k
+ case 1: // A0000h - AFFFFh
segment = (uint8_t *)0xA0000;
break;
- case 2: // B0000h - B7FFFh, 32k
+ case 2: // B0000h - B7FFFh
segment = (uint8_t *)0xB0000;
break;
- case 3: // B8000h - BFFFFh, 32k
+ case 3: // B8000h - BFFFFh
segment = (uint8_t *)0xB8000;
break;
}
@@ -237,6 +243,34 @@ static uint8_t *get_frame_buffer_segment( vga_t *vga )
return segment;
}
+static size_t get_frame_buffer_segment_size( vga_t *vga )
+{
+ port8_write( &vga->graphics_controller_index_port, 0x06 );
+ uint8_t segment_no = ( port8_read( &vga->graphics_controller_data_port ) >> 2 ) & 0x03;
+ size_t segment_size = 0;
+
+ switch( segment_no ) {
+ case 0: // 128k
+ segment_size = 128 * 1024;
+ break;
+
+ case 1: // 64k
+ segment_size = 64 * 1024;
+ break;
+
+ case 2: // 32k
+ case 3:
+ segment_size = 32 * 1024;
+ break;
+ }
+
+#ifdef DEBUG
+ printf( "segment size: %d 0x%X\n", segment_no, segment_size );
+#endif
+
+ return segment_size;
+}
+
bool vga_set_mode( vga_t *vga, const vga_mode_t mode )
{
// do not allow unknown timings!
@@ -252,7 +286,6 @@ bool vga_set_mode( vga_t *vga, const vga_mode_t mode )
vga->mode.segment = get_frame_buffer_segment( vga );
vga_use_z_buffer( vga, false );
- memset( vga->zbuffer, 0, sizeof( vga->zbuffer ) );
return true;
}
@@ -389,11 +422,21 @@ void vga_wait_for_retrace( vga_t *vga )
void vga_use_z_buffer( vga_t *vga, bool use )
{
+ if( vga->use_z_buffer == use ) {
+ return;
+ }
+
vga->use_z_buffer = use;
if( vga->use_z_buffer ) {
+ size_t size = get_frame_buffer_segment_size( vga );
+ vga->zbuffer = (uint8_t *)malloc( size );
vga->base_addr = &vga->zbuffer[0];
} else {
+ if( vga->zbuffer != NULL ) {
+ free( vga->zbuffer );
+ vga->zbuffer = NULL;
+ }
vga->base_addr = vga->mode.segment;
}
}
diff --git a/src/drivers/video/vga.h b/src/drivers/video/vga.h
index bdc15cf..aa842dc 100644
--- a/src/drivers/video/vga.h
+++ b/src/drivers/video/vga.h
@@ -42,11 +42,7 @@ typedef struct {
port8_t attribute_controller_reset_port;
vga_mode_t mode;
bool use_z_buffer;
- // TODO: the Z-buffer should actually be allocated dynamically
- // depending on the current mode, for now it's a static buffer
- // able to store the biggest resolution, being planar
- // 320x200x8 aka 64k
- uint8_t zbuffer[65535];
+ uint8_t *zbuffer;
// stores either the address to the beginning of the segment
// (real mapped I/O memory or the beginning of the Z buffer
uint8_t *base_addr;
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index f2210d6..c0bc285 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -91,13 +91,14 @@ void kernel_main( void )
// TODO: get memupper from multiboot header (but this needs
// a multiboot compliant entry function first) or use BIOS
// functions to determine size of memory, for now assume we
- // have at least, for now use the memory above 1 MB, 64 MB
- // heap is enough for what we are doing in the kernel
- memory_manager_init( &global_context.memory_manager, 0x100000, 0xFFFF );
+ // have at least, for now use the memory above 1 MB, 128 KB
+ // heap is enough for what we are doing in the kernel plus
+ // eventual z buffering the VGA graphic mode
+ uint32_t heap_offset = 0x01000000;
+ size_t heap_size = 128 * 1024;
+ memory_manager_init( &global_context.memory_manager, heap_offset, heap_size );
__stdlib_set_memory_manager( &global_context.memory_manager );
- printf( "Kernel heap at 0x%X, size 0x%X\n", 0x100000, 0xFFFF );
- void *test = malloc( 2048 );
- free( test );
+ printf( "Kernel heap at 0x%X, size 0x%X\n", heap_offset, heap_size );
// exit point in case of kernel panic, do this as soon as
// possible, as soon we have an early console we can croak on
diff --git a/src/kernel/memorymanagement.c b/src/kernel/memorymanagement.c
index dc2d160..b8a84b2 100644
--- a/src/kernel/memorymanagement.c
+++ b/src/kernel/memorymanagement.c
@@ -11,6 +11,7 @@ void memory_manager_init( memory_manager_t *memory_manager, size_t offset, size_
memory_manager->offset = offset;
memory_manager->size = size;
memory_manager->free_ptr = offset;
+ memory_manager->prev_ptr = 0xFFFFFFFF;
}
void *memory_manager_allocate( memory_manager_t *memory_manager, size_t size )
@@ -19,10 +20,11 @@ void *memory_manager_allocate( memory_manager_t *memory_manager, size_t size )
if( memory_manager->free_ptr - memory_manager->offset + size > memory_manager->size ) {
kernel_panic( "Heap allocation out of memory (requested %d bytes, available %d)",
- size, size - ( memory_manager->free_ptr - memory_manager->offset ) - 1 );
+ size, size - ( memory_manager->free_ptr - memory_manager->offset ) );
}
p = (void *)memory_manager->free_ptr;
+ memory_manager->prev_ptr = memory_manager->free_ptr;
memory_manager->free_ptr += size;
return p;
@@ -34,7 +36,16 @@ void memory_manager_deallocate( memory_manager_t *memory_manager, void **p )
kernel_panic( "Double free of pointer 0x%X in heap", *p );
}
- *p = NULL;
+ // This actually doesn't work and we do it outside after free, when
+ // a buffer has an optional semantic
+ //*p = NULL;
+
+ // are we freeing the previously allocated block, if yes, we can
+ // adjust the free pointer
+ if( (uint32_t)*p == memory_manager->prev_ptr ) {
+ memory_manager->free_ptr = memory_manager->prev_ptr;
+ memory_manager->prev_ptr = 0xFFFFFFFF;
+ }
}
diff --git a/src/kernel/memorymanagement.h b/src/kernel/memorymanagement.h
index 16f0b29..647c05d 100644
--- a/src/kernel/memorymanagement.h
+++ b/src/kernel/memorymanagement.h
@@ -6,6 +6,7 @@
typedef struct {
size_t offset;
size_t size;
+ uint32_t prev_ptr;
uint32_t free_ptr;
} memory_manager_t;