/*
  MemoryLayout.h, Copyright  (c) by Lukas Ruf, lr@lpr.ch,
  Swiss Federal Institute of Technology,
  Computer Engineering and Networks Laboratory.
 
  TOPSY -- A Teachable Operating System.
           Implementation of a tiny and simple
           micro kernel for teaching purposes.
 
  For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
  This software is provided under the terms of the GNU General Public Licence.
 
  A full copy of the GNU GPL is provided in the file COPYING found in the 
  development root of Topsy.
*/
/*
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Memory/ia32/MemoryLayout.h,v $
 	Author(s):             Lukas Ruf, lr@lpr.ch
 	Affiliation:           ETH Zuerich, TIK
 	Version:               $Revision: 3042 $
 	Last Date of Change:   $Date: 2007-06-28 01:28:34 +0200 (Don, 28 Jun 2007) $      by: $Author: sryffel $
*/
#ifndef __MEMORYLAYOUT_H__
#define __MEMORYLAYOUT_H__

#include "cpu.h"

/* available memory */
#define PHYSMEM       (22*1024*1024)  /* define PHYSMEM to be 22MB ??? */
#define PHYSMEM_AVAIL PHYSMEM
#define PHYSMEM_BASE  (0)             /* PHYSMEM starts at 0x00000000 */
#define USERMEM       (64*1024*1024)  /* define the USERMEM to be 64MB ??? */

/* PAGESIZE is the machines real page size */
#define PAGEBITS              12
#define PAGESIZE              (1 << PAGEBITS)
#define PAGEFRAMEMASK         (0xffffffff << PAGEBITS)
#define PAGEMASK              (~PAGEFRAMEMASK)
#define PAGENUMBER(addr)      (((unsigned long)addr) >> PAGEBITS)
#define PAGEREMAINDER(addr)   (((unsigned long)addr) & PAGEMASK)
#define PAGETOADDR(pagenr) 		((void *)(((unsigned long)(pagenr)) << PAGEBITS))
#define PAGEROUNDUP(addr) 		((((unsigned long)(addr)) + PAGEMASK) & PAGEFRAMEMASK )
#define PAGEROUNDDOWN(addr)		(((unsigned long)(addr)) & PAGEFRAMEMASK )

#define KDSEG_TO_LIN(addr)        ((void *)K0SEG_TO_PHYS(addr))
#define LIN_TO_KDSEG(addr)        ((void *)PHYS_TO_K0SEG(addr))

#define PAGETODMAPPED(pagenr)	((void *)PAGETOADDR((pagenr)))
#define DMAPPEDTOPAGE(addr)		((unsigned long)PAGENUMBER(addr))
#define DMAPPEDTOPHYS(addr)		((void *)(addr))


/* logical page size is the granularity of vm regions
 * this may be smaller on a direct mapped memory system. 
 * if paging is used LOGICAL and PHYSICAL have to be the same size 
 */
#define LOGICALPAGEBITS             8
#define LOGICALPAGESIZE            (1 << LOGICALPAGEBITS)
#define LOGICALPAGEFRAMEMASK       (0xffffffff << LOGICALPAGEBITS)
#define LOGICALPAGEMASK            (~LOGICALPAGEFRAMEMASK)
#define LOGICALPAGENUMBER(addr)    (((unsigned long)addr) >> LOGICALPAGEBITS)
#define LOGICALPAGEREMAINDER(addr) (((unsigned long)addr) & LOGICALPAGEMASK)

/* used as a boot and later as an exception stack */
#define BOOTSTACKSIZE     (2*PAGESIZE)
/* BOOTSTACKBOTTOM is relativ to the KERNEL SEGMENT. */
#define BOOTSTACKBOTTOM   (0x9E000-KERNEL_VMA_BASE)
#define BOOTSTACKTOP      (BOOTSTACKBOTTOM+BOOTSTACKSIZE-4)


#define GC_DUMMY_SEL        0*8
#define GC_OS_CODE_SEL      1*8
#define GC_OS_DATA_SEL      2*8
#define GC_OS_GLOBAL_SEL    3*8
#define GC_VIDEO_SEL        4*8
#define GC_GDT_SEL          5*8

#define GC_KCSEL            GC_OS_CODE_SEL
#define GC_KDSEL            GC_OS_DATA_SEL



/*GDT-Entries Definition Flags************************************************/

/*
;//////
;//// Memory Descriptor Codes: All Available (Descriptor Byte 5)
;//////
;//////                    PDLSCEWA */
/* Type for Data Segments */
#define MM_B5_A   0x01 /*  00000001b       Accesssed            */
#define MM_B5_W   0x02 /*  00000010b       Read/Write           */
#define MM_B5_E   0x04 /*  00000100b       Expand Down (ESP is incremented {fuck Intel}) */
/* Type for Code Segments */
#define MM_B5_A   0x01 /*  00000001b       Accesssed            */
#define MM_B5_R   0x02 /*  00000010b       Read enable          */
#define MM_B5_F   0x04 /*  00000100b       Conforming           */

#define MM_B5_C   0x08 /*  00001000b       1 = Code Segment; 0 = Data, Stack Segment  */
#define MM_B5_S   0x10 /*  00010000b       No System Segment: 0 = System; 1 = Code or Data    */
#define MM_B5_0   0x00 /*  00000000b       Ring 0               */
#define MM_B5_1   0x20 /*  00100000b       Ring 1               */
#define MM_B5_2   0x40 /*  01000000b       Ring 2               */
#define MM_B5_3   0x60 /*  01100000b       Ring 3               */
#define MM_B5_P   0x80 /*  10000000b       Present              */

#define MM_RPL_0  0x00 /*  00000000b       Ring 0               */
#define MM_RPL_1  0x01 /*  00000001b       Ring 1               */
#define MM_RPL_2  0x02 /*  00000010b       Ring 2               */
#define MM_RPL_3  0x03 /*  00000011b       Ring 3               */

/*
;//////
;//// Memory Descriptor Codes: All Available (Descriptor Byte 6)
;//////
;//////                    GD0A0000 */
#define MM_B6_A   0x10 /*  00010000b      AVL                 */
#define MM_B6_D   0x40 /*  01000000b      Code Seg: Operand Size is 32b, Data Seg: ESP (Big)                */
#define MM_B6_G   0x80 /*  10000000b      Limit in Pages (=0: in Bytes)               */

#define MM_NO_    0x00 /*  00000000b      nothing               */
/*
;//////
;//// System Descriptor Codes: Only Codes for > 80386 (no compatibility to 80286)
;//////
;//////                        PDLSTYPE */
#define SS_DESC_LDT   0x02 /*  00000010b   System Descriptor LDT Segment */
#define SS_DESC_TSG   0x05 /*  00000101b   System Descriptor Task Gate*/
#define SS_DESC_TSS   0x09 /*  00001001b   System Descriptor TSS      */
#define SS_DESC_BTS   0x0B /*  00001011b   System Descriptor Busy TSS */
#define SS_DESC_CLG   0x0C /*  00001100b   System Descriptor Call Gate*/
#define SS_DESC_INT   0x0E /*  00001110b   System Descriptor Interrupt Gate */
#define SS_DESC_TRP   0x0F /*  00001111b   System Descriptor Trap      Gate */
/*
;//////
;//// Descriptor for init of GDT Entries:
;//////
*/
/*//////
;//// OS Data & Code Descriptor
;////// */
;// MM_OSD_B5    MM_B5_P or MM_B5_0 or MM_B5_S or MM_B5_W
;// MM_OSC_B5    MM_B5_P or MM_B5_0 or MM_B5_S or MM_B5_W or MM_B5_C */
#define MM_OSD_B5    0x93 /* 10010011b */
#define MM_OSC_B5    0x9B /* 10011011b */
/*
;// ALL STACK Segments are implemented so called "expand-up" stacks 
;//     STACK GRANULARITY is BYTE */
#define MM_STACK_B5       0x93 /*   10010011b        present,DPL=00,Non-System,writeable,accessed */
#define MM_STACK_B6       0x40 /*   01000000b        BIG bit */

/*
;// ALL DATA Segments are implemented in a 32b operand mode */
;//     DATA GRANULARITY is PAGE */
#define MM_DATA_B5        0x93 /*     10010011b       ;// present,DPL=00,Non-System,writeable,accessed */
#define MM_DATA_B6        0xC0 /*     11000000b       ;// PAGE granularity, BIG bit */
#define MM_DATA_B6_BYTE   0x40 /*     01000000b       ;// BYTE granularity, BIG bit */

/* ALL CODE Segments are implemented in a 32b operand mode */
/*     CODE GRANULARITY is PAGE : non conforming */
#define MM_CODE_B5        0x9B /*     10011011b       ;// present,DPL=00,Non-System,code segment,executable/readable,accessed */
#define MM_CODE_B6        0xC0 /*     11000000b       ;// PAGE granularity, BIG bit */

#define MM_LIMIT_MAX      0x100000   /* maximum segment size: 4GB for page and 1MB for byte granularity */

/* INTERRUPT GATE */        /* P DPL   Type     res.  */
#define TSSGATE   0x8500    /* 1 00  0 0101 000 00000 */
#define INTGATE   0x8E00    /* 1 00  0 1110 000 00000 */
#define TRAPGATE  0x8F00    /* 1 00  0 1111 000 00000 */

/* Defining Interrupt GateWay with DPL of 3, i.e. Protection Level 3 Procedures
   may call this Interrupt GateWay */
                            /* P DPL   Type     res.  */
#define SYSGATE   0xEE00    /* 1 11  0 1110 000 00000 */

/* the steal region is in the kernel mapable region and has a virtual size of 4MB */
#define STEAL_START STEALALLOC
#define STEAL_SIZE  (4 * 1024 * 1024)

/*//////
;//// Task State Segment Descriptors
;////// */
#define BSP_TSS_BASE  0x1E000
#define K_TSS_SIZE    104             /* Size of Selector is BYTE */
#define K_TSS_B5      0x89            /* 10001001b */
#define K_TSS_B6      0x00            /* 00000000b */

#define U_TSS_BASE  0x1D000
#define U_TSS_SIZE  104
#define U_TSS_B5    0xE9            /* 11101001b : USER DPL Ring 3*/
#define U_TSS_B6    0x00            /* 00000000b */



/*
///////
;//// APIC
;////// 
*/
#define APIC_BASE           0xFEE00000      /* Initial Base of the APIC Registers */
#define IA32_APIC_BASE_MSR  0x1B            /* MSR of the APIC_BASE               */

#define IOAPIC_BASE         0xFEC00000      /* Initial Base of the IO-APIC Registers */
/*
///////
;//// Thread Management
;////// 
*/

// Kernel Mode Stacks
#define TM_KERNEL_MODE_STACK_NEAR   0xc0000000    /* Kernel Mode Stacks above 3GB */
#define TM_KERNEL_MODE_STACK_PAGES  2             /* 8KB of Kernel Mode Stack */
#define TM_KERNEL_MODE_STACK_SIZE   (TM_KERNEL_MODE_STACK_PAGES*PAGESIZE)

// Thread Stacks
#define TM_DEFAULTTHREADSTACKPAGES        64     /* 256KB of default Stack Size */
#define TM_DEFAULTTHREADSTACKSIZE         (TM_DEFAULTTHREADSTACKPAGES*PAGESIZE)
#define TM_DEFAULTTHREADSTACKNEAR         0

// Kernel Thread Stacks
#define TM_DEFAULTKERNELTHREADSTACKPAGES  2       /* 8KB for Kernel Threads */
#define TM_DEFAULTKERNELTHREADSTACKSIZE   (TM_DEFAULTKERNELTHREADSTACKPAGES*PAGESIZE)

#if TM_KERNEL_MODE_STACK_PAGES != TM_DEFAULTKERNELTHREADSTACKPAGES
  #error "The size of the kernel mode stacks differs from the one of the kernel thread stack!"
  #error "Change the code that depends on the two to be equal and remove this error."
#endif

#endif
