mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-21 12:47:25 +00:00
refactor include
This commit is contained in:
parent
9945ad6119
commit
33b9d60691
40 changed files with 5342 additions and 5424 deletions
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
** SCCS ID: @(#)bootstrap.h 2.4 1/22/25
|
||||
**
|
||||
** @file bootstrap.h
|
||||
**
|
||||
** @author K. Reek
|
||||
** @author Warren R. Carithers, Garrett C. Smith
|
||||
**
|
||||
** Addresses where various stuff goes in memory.
|
||||
*/
|
||||
|
||||
#ifndef BOOTSTRAP_H_
|
||||
#define BOOTSTRAP_H_
|
||||
|
||||
/*
|
||||
** The boot device
|
||||
*/
|
||||
#define BDEV_FLOPPY 0x00
|
||||
#define BDEV_USB 0x80 /* hard drive */
|
||||
|
||||
#define BDEV BDEV_USB /* default */
|
||||
|
||||
/*
|
||||
** Bootstrap definitions
|
||||
*/
|
||||
#define BOOT_SEG 0x07c0 /* 07c0:0000 */
|
||||
#define BOOT_DISP 0x0000
|
||||
#define BOOT_ADDR ((BOOT_SEG << 4) + BOOT_DISP)
|
||||
|
||||
#define PART2_DISP 0x0200 /* 07c0:0200 */
|
||||
#define PART2_ADDR ((BOOT_SEG << 4) + PART2_DISP)
|
||||
|
||||
#define SECTOR_SIZE 0x200 /* 512 bytes */
|
||||
|
||||
/* Note: this assumes the bootstrap is two sectors long! */
|
||||
#define BOOT_SIZE (SECTOR_SIZE + SECTOR_SIZE)
|
||||
|
||||
#define OFFSET_LIMIT (0x10000 - SECTOR_SIZE)
|
||||
|
||||
#define BOOT_SP_DISP 0x4000 /* stack pointer 07c0:4000, or 0xbc00 */
|
||||
#define BOOT_SP_ADDR ((BOOT_SEG << 4) + BOOT_SP_DISP)
|
||||
|
||||
#define SECTOR1_END (BOOT_ADDR + SECTOR_SIZE)
|
||||
#define SECTOR2_END (BOOT_ADDR + BOOT_SIZE)
|
||||
|
||||
// location of the user blob data
|
||||
// (three halfwords of data)
|
||||
#define USER_BLOB_DATA (SECTOR2_END - 12)
|
||||
|
||||
/*
|
||||
** The target program itself
|
||||
*/
|
||||
#define TARGET_SEG 0x00001000 /* 1000:0000 */
|
||||
#define TARGET_ADDR 0x00010000 /* and upward */
|
||||
#define TARGET_STACK 0x00010000 /* and downward */
|
||||
|
||||
/*
|
||||
** The Global Descriptor Table (0000:0500 - 0000:2500)
|
||||
*/
|
||||
#define GDT_SEG 0x00000050
|
||||
#define GDT_ADDR 0x00000500
|
||||
|
||||
/* segment register values */
|
||||
#define GDT_LINEAR 0x0008 /* All of memory, R/W */
|
||||
#define GDT_CODE 0x0010 /* All of memory, R/E */
|
||||
#define GDT_DATA 0x0018 /* All of memory, R/W */
|
||||
#define GDT_STACK 0x0020 /* All of memory, R/W */
|
||||
|
||||
/*
|
||||
** The Interrupt Descriptor Table (0000:2500 - 0000:2D00)
|
||||
*/
|
||||
#define IDT_SEG 0x00000250
|
||||
#define IDT_ADDR 0x00002500
|
||||
|
||||
/*
|
||||
** Additional I/O ports used by the bootstrap code
|
||||
*/
|
||||
|
||||
// keyboard controller
|
||||
#define KBD_DATA 0x60
|
||||
#define KBD_CMD 0x64
|
||||
#define KBD_STAT 0x64
|
||||
|
||||
// status register bits
|
||||
#define KBD_OBSTAT 0x01
|
||||
#define KBD_IBSTAT 0x02
|
||||
#define KBD_SYSFLAG 0x04
|
||||
#define KBD_CMDDAT 0x08
|
||||
|
||||
// commands
|
||||
#define KBD_P1_DISABLE 0xad
|
||||
#define KBD_P1_ENABLE 0xae
|
||||
#define KBD_RD_OPORT 0xd0
|
||||
#define KBD_WT_OPORT 0xd1
|
||||
|
||||
#ifdef ASM_SRC
|
||||
|
||||
// segment descriptor macros for use in assembly source files
|
||||
// layout:
|
||||
// .word lower 16 bits of limit
|
||||
// .word lower 16 bits of base
|
||||
// .byte middle 8 bits of base
|
||||
// .byte type byte
|
||||
// .byte granularity byte
|
||||
// .byte upper 8 bits of base
|
||||
// we use 4K units, so we ignore the lower 12 bits of the limit
|
||||
#define SEGNULL .word 0, 0, 0, 0
|
||||
|
||||
#define SEGMENT(base, limit, dpl, type) \
|
||||
.word(((limit) >> 12) & 0xffff); \
|
||||
.word((base) & 0xffff); \
|
||||
.byte(((base) >> 16) & 0xff); \
|
||||
.byte(SEG_PRESENT | (dpl) | SEG_NON_SYSTEM | (type)); \
|
||||
.byte(SEG_GRAN_4KBYTE | SEG_DB_32BIT | (((limit) >> 28) & 0xf)); \
|
||||
.byte(((base) >> 24) & 0xff)
|
||||
|
||||
#endif /* ASM_SRC */
|
||||
|
||||
#endif
|
287
include/cio.h
287
include/cio.h
|
@ -1,287 +0,0 @@
|
|||
/**
|
||||
** SCCS ID: @(#)cio.h 2.7 1/22/25
|
||||
**
|
||||
** @file cio.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @authors K. Reek, Jon Coles
|
||||
**
|
||||
** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers)
|
||||
**
|
||||
** Declarations and descriptions of console I/O routines
|
||||
**
|
||||
** These routines provide a rudimentary capability for printing to
|
||||
** the screen and reading from the keyboard.
|
||||
**
|
||||
** Screen output:
|
||||
** There are two families of functions. The first provides a window
|
||||
** that behaves in the usual manner: writes extending beyond the right
|
||||
** edge of the window wrap around to the next line, the top line
|
||||
** scrolls off the window to make room for new lines at the bottom.
|
||||
** However, you may choose what part of the screen contains this
|
||||
** scrolling window. This allows you to print some text at fixed
|
||||
** locations on the screen while the rest of the screen scrolls.
|
||||
**
|
||||
** The second family allows for printing at fixed locations on the
|
||||
** screen. No scrolling or line wrapping are done for these functions.
|
||||
** It is not intended that these functions be used to write in the
|
||||
** scrolling area of the screen.
|
||||
**
|
||||
** In both sets of functions, the (x,y) coordinates are interpreted
|
||||
** as (column,row), with the upper left corner of the screen being
|
||||
** (0,0) and the lower right corner being (79,24).
|
||||
**
|
||||
** The printf provided in both sets of functions has the same
|
||||
** conversion capabilities. Format codes are of the form:
|
||||
**
|
||||
** %-0WC
|
||||
**
|
||||
** where "-", "0", and "W" are all optional:
|
||||
** "-" is the left-adjust flag (default is right-adjust)
|
||||
** "0" is the zero-fill flag (default is space-fill)
|
||||
** "W" is a number specifying the minimum field width (default: 1 )
|
||||
** and "C" is the conversion type, which must be one of these:
|
||||
** "c" print a single character
|
||||
** "s" print a null-terminated string
|
||||
** "d" print an integer as a decimal value
|
||||
** "x" print an integer as a hexadecimal value
|
||||
** "o" print an integer as a octal value
|
||||
**
|
||||
** Keyboard input:
|
||||
** Two functions are provided: getting a single character and getting
|
||||
** a newline-terminated line. A third function returns a count of
|
||||
** the number of characters available for immediate reading.
|
||||
** No conversions are provided (yet).
|
||||
*/
|
||||
|
||||
#ifndef CIO_H_
|
||||
#define CIO_H_
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
// EOT indicator (control-D)
|
||||
#define EOT '\04'
|
||||
|
||||
/*****************************************************************************
|
||||
**
|
||||
** INITIALIZATION ROUTINES
|
||||
**
|
||||
** Initializes the I/O system.
|
||||
*/
|
||||
|
||||
/**
|
||||
** cio_init
|
||||
**
|
||||
** Initializes the I/O routines. Must be called before
|
||||
** any CIO functions can be used.
|
||||
**
|
||||
** @param notify pointer to an input notification function, or NULL
|
||||
*/
|
||||
void cio_init(void (*notify)(int));
|
||||
|
||||
/*****************************************************************************
|
||||
**
|
||||
** SCROLLING OUTPUT ROUTINES
|
||||
**
|
||||
** Each operation begins at the current cursor position and advances
|
||||
** it. If a newline is output, the reminder of that line is cleared.
|
||||
** Output extending past the end of the line is wrapped. If the
|
||||
** cursor is moved below the scrolling region's bottom edge, scrolling
|
||||
** is delayed until the next output is produced.
|
||||
*/
|
||||
|
||||
/**
|
||||
** cio_setscroll
|
||||
**
|
||||
** This sets the scrolling region to be the area defined by the arguments.
|
||||
** The remainder of the screen does not scroll and may be used to display
|
||||
** data you do not want to move. By default, the scrolling region is the
|
||||
** entire screen. X and Y coordinates begin at 0 in the upper left corner
|
||||
** of the screen.
|
||||
**
|
||||
** @param min_x,min_y upper-left corner of the region
|
||||
** @param max_x,max_y lower-right corner of the region
|
||||
*/
|
||||
void cio_setscroll(unsigned int min_x, unsigned int min_y, unsigned int max_x,
|
||||
unsigned int max_y);
|
||||
|
||||
/**
|
||||
** cio_moveto
|
||||
**
|
||||
** Moves the cursor to the specified position. (0,0) indicates
|
||||
** the upper left corner of the scrolling region. Subsequent
|
||||
** output will begin at the cursor position.
|
||||
**
|
||||
** @param x,y desired coordinate position
|
||||
*/
|
||||
void cio_moveto(unsigned int x, unsigned int y);
|
||||
|
||||
/**
|
||||
** cio_putchar
|
||||
**
|
||||
** Prints a single character.
|
||||
**
|
||||
** @param c the character to be printed
|
||||
*/
|
||||
void cio_putchar(unsigned int c);
|
||||
|
||||
/**
|
||||
** cio_puts
|
||||
**
|
||||
** Prints the characters in the string up to but not including
|
||||
** the terminating null byte.
|
||||
**
|
||||
** @param str pointer to a NUL-terminated string to be printed
|
||||
*/
|
||||
void cio_puts(const char *str);
|
||||
|
||||
/**
|
||||
** cio_write
|
||||
**
|
||||
** Prints "length" characters from the buffer.
|
||||
**
|
||||
** @param buf the buffer of characters
|
||||
** @param length the number of characters to print
|
||||
*/
|
||||
void cio_write(const char *buf, int length);
|
||||
|
||||
/**
|
||||
** cio_printf
|
||||
**
|
||||
** Limited form of printf (see the beginning of this file for
|
||||
** a list of what is implemented).
|
||||
**
|
||||
** @param fmt a printf-style format control string
|
||||
** @param ... optional additional values to be printed
|
||||
*/
|
||||
void cio_printf(char *fmt, ...);
|
||||
|
||||
/**
|
||||
** cio_scroll
|
||||
**
|
||||
** Scroll the scrolling region up by the given number of lines.
|
||||
** The output routines scroll automatically so normally you
|
||||
** do not need to call this routine yourself.
|
||||
**
|
||||
** @param lines the number of lines to scroll
|
||||
*/
|
||||
void cio_scroll(unsigned int lines);
|
||||
|
||||
/**
|
||||
** cio_clearscroll
|
||||
**
|
||||
** Clears the entire scrolling region to blank spaces, and
|
||||
** moves the cursor to (0,0).
|
||||
*/
|
||||
void cio_clearscroll(void);
|
||||
|
||||
/*****************************************************************************
|
||||
**
|
||||
** NON-SCROLLING OUTPUT ROUTINES
|
||||
**
|
||||
** Coordinates are relative to the entire screen: (0,0) is the upper
|
||||
** left corner. There is no line wrap or scrolling.
|
||||
*/
|
||||
|
||||
/**
|
||||
** cio_putchar_at
|
||||
**
|
||||
** Prints the given character. If a newline is printed,
|
||||
** the rest of the line is cleared. If this happens to the
|
||||
** left of the scrolling region, the clearing stops when the
|
||||
** region is reached. If this happens inside the scrolling
|
||||
** region, the clearing stops when the edge of the region
|
||||
** is reached.
|
||||
**
|
||||
** @param x,y desired coordinate position
|
||||
** @param c the character to be printed
|
||||
*/
|
||||
void cio_putchar_at(unsigned int x, unsigned int y, unsigned int c);
|
||||
|
||||
/**
|
||||
** cio_puts_at
|
||||
**
|
||||
** Prints the given string. cio_putchar_at is used to print
|
||||
** the individual characters; see that description for details.
|
||||
**
|
||||
** @param x,y desired coordinate position
|
||||
** @param str pointer to a NUL-terminated string to be printed
|
||||
*/
|
||||
void cio_puts_at(unsigned int x, unsigned int y, const char *str);
|
||||
|
||||
/**
|
||||
** cio_printf_at
|
||||
**
|
||||
** Limited form of printf (see the beginning of this file for
|
||||
** a list of what is implemented).
|
||||
**
|
||||
** @param x,y desired coordinate position
|
||||
** @param fmt a printf-style format control string
|
||||
** @param ... optional additional values to be printed
|
||||
*/
|
||||
void cio_printf_at(unsigned int x, unsigned int y, char *fmt, ...);
|
||||
|
||||
/**
|
||||
** cio_clearscreen
|
||||
**
|
||||
** This function clears the entire screen, including the scrolling region.
|
||||
*/
|
||||
void cio_clearscreen(void);
|
||||
|
||||
/*****************************************************************************
|
||||
**
|
||||
** INPUT ROUTINES
|
||||
**
|
||||
** When interrupts are enabled, a keyboard ISR collects keystrokes
|
||||
** and saves them until the program calls for them. If the input
|
||||
** queue fills, additional characters are silently discarded.
|
||||
** When interrupts are not enabled, keystrokes made when no input
|
||||
** routines have been ** called are lost. This can cause errors in
|
||||
** the input translation because the states of the Shift and Ctrl keys
|
||||
** may not be tracked accurately. If interrupts are disabled, the user
|
||||
** is advised to refrain from typing anything except when the program is
|
||||
** waiting for input.
|
||||
*/
|
||||
|
||||
/**
|
||||
** cio_getchar
|
||||
**
|
||||
** If the character is not immediately available, the function
|
||||
** waits until the character arrives.
|
||||
**
|
||||
** @return the next character from the keyboard input buffer
|
||||
*/
|
||||
int cio_getchar(void);
|
||||
|
||||
/**
|
||||
** cio_gets
|
||||
**
|
||||
** This function reads a newline-terminated line from the
|
||||
** keyboard. cio_getchar is used to obtain the characters;
|
||||
** see that description for more details. The function
|
||||
** returns when:
|
||||
** a newline is entered (this is stored in the buffer)
|
||||
** ctrl-D is entered (not stored in the buffer)
|
||||
** the buffer becomes full.
|
||||
** The buffer is null-terminated in all cases.
|
||||
**
|
||||
** @param buffer destination buffer for the input character sequence
|
||||
** @param size the buffer length
|
||||
**
|
||||
** @return count of the number of characters read into the buffer
|
||||
*/
|
||||
int cio_gets(char *buffer, unsigned int size);
|
||||
|
||||
/**
|
||||
** cio_input_queue
|
||||
**
|
||||
** This function lets the program determine whether there is input
|
||||
** available. This indicates whether or not a call to cio_getchar()
|
||||
** would block.
|
||||
**
|
||||
** @return number of characters in the input queue
|
||||
*/
|
||||
int cio_input_queue(void);
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/**
|
||||
** @file clock.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Clock module declarations
|
||||
*/
|
||||
|
||||
#ifndef CLOCK_H_
|
||||
#define CLOCK_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// conversion functions for seconds, ms, and ticks
|
||||
// (SEC_TO_MS is defined in defs.h)
|
||||
#define MS_TO_TICKS(n) ((n))
|
||||
#define SEC_TO_TICKS(n) (MS_TO_TICKS(SEC_TO_MS(n)))
|
||||
#define TICKS_TO_SEC(n) ((n) / CLOCK_FREQ)
|
||||
#define TICKS_TO_SEC_ROUNDED(n) (((n) + (CLOCK_FREQ - 1)) / CLOCK_FREQ)
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
// current system time
|
||||
extern uint32_t system_time;
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: clk_init
|
||||
**
|
||||
** Clock module initialization
|
||||
*/
|
||||
void clk_init(void);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
** @file common.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Common definitions for the baseline system.
|
||||
**
|
||||
** This header file pulls in the standard header information needed
|
||||
** by all parts of the system. It is purely for our convenience.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
|
||||
// everything needs these; they also pull in
|
||||
// the kernel- or user-level defs and lib headers
|
||||
#include <types.h>
|
||||
#include <params.h>
|
||||
#include <defs.h>
|
||||
#include <lib.h>
|
||||
|
||||
#ifdef KERNEL_SRC
|
||||
|
||||
// only kernel code needs these headers
|
||||
#include <common.h>
|
||||
#include <cio.h>
|
||||
#include <debug.h>
|
||||
|
||||
#endif /* KERNEL_SRC */
|
||||
|
||||
#endif
|
132
include/compat.h
132
include/compat.h
|
@ -1,132 +0,0 @@
|
|||
/**
|
||||
** @file compat.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Compatibility definitions for standard modules.
|
||||
**
|
||||
** These definitions are here to simplify the integration
|
||||
** of some pre-written modules into the 452 baseline system.
|
||||
** This is used primarily for the 'kmem' and 'sio' modules.
|
||||
**
|
||||
** We use CPP symbols and not actual data types for things here,
|
||||
** as this means we don't need to include any other header files
|
||||
** into this file. This helps get around "include loops" (e.g.,
|
||||
** a.h includes b.h, which includes c.h, which includes a.h) when
|
||||
** there are many interdependencies between source files.
|
||||
*/
|
||||
|
||||
#ifndef COMPAT_H_
|
||||
#define COMPAT_H_
|
||||
|
||||
#include <common.h>
|
||||
#include <procs.h>
|
||||
|
||||
/*
|
||||
** Section 1: sized integer types
|
||||
**
|
||||
** Internally, we use standard names for "sized" integer types for
|
||||
** simplicity. If those disagree with the names used in the rest of
|
||||
** the system, we take the opportunity to define our names here.
|
||||
**
|
||||
** To enable these, uncomment them, and place the apropriate
|
||||
** existing type names in place of the '?' characters.
|
||||
*/
|
||||
|
||||
// standard "sized integer" types
|
||||
// #define int8_t ?
|
||||
// #define uint8_t ?
|
||||
// #define int16_t ?
|
||||
// #define uint16_t ?
|
||||
// #define int32_t ?
|
||||
// #define uint32_t ?
|
||||
// #define int64_t ?
|
||||
// #define uint64_t ?
|
||||
// #define bool_t ?
|
||||
|
||||
/*
|
||||
** Section 2: other types
|
||||
**
|
||||
** Add type definitions here as needed.
|
||||
**
|
||||
** Note: we do not include the PCB and Queue declarations
|
||||
** here because we don't actually need them in this header
|
||||
** file - we're only defining CPP macros. Whatever file
|
||||
** uses these macros, however, must include the appropriate
|
||||
** headers if it uses these macros.
|
||||
**
|
||||
** To enable these, uncomment them, and place the apropriate
|
||||
** existing type names in place of the '?' characters.
|
||||
*/
|
||||
|
||||
// type name for the PCB
|
||||
#define PCBTYPE pcb_t
|
||||
|
||||
// type name for our queue
|
||||
#define QTYPE pcb_queue_t
|
||||
|
||||
/*
|
||||
** Section 3: interface and behavior
|
||||
**
|
||||
** Include #define statements here as needed to define
|
||||
** the names of functions and globals used in these modules
|
||||
** in terms of the names used in the rest of the baseline.
|
||||
**
|
||||
** To enable these, uncomment them, and place the apropriate
|
||||
** existing variable or function names in place of the '?' characters.
|
||||
*/
|
||||
|
||||
// string functions
|
||||
#define SLENGTH strlen
|
||||
|
||||
// scheduler
|
||||
#define SCHED schedule
|
||||
|
||||
// dispatcher
|
||||
#define DISPATCH dispatch
|
||||
|
||||
/*
|
||||
** blocked queue for reading processes
|
||||
**
|
||||
** Define this if we are blocking processes which try to
|
||||
** read from the SIO when no characters are available.
|
||||
** Its value should be the name of the globally-visible
|
||||
** queue to be used.
|
||||
*/
|
||||
#define QNAME sioread
|
||||
|
||||
#ifdef QNAME
|
||||
|
||||
// Only define these macros if we need to be able to create and
|
||||
// manage a queue of things. It is expected that these will need
|
||||
// to be customized based on the names and calling sequences of
|
||||
// the appropriate functions.
|
||||
|
||||
// invoke the queue creation function
|
||||
// examples:
|
||||
//
|
||||
// #define QCREATE(q) do {
|
||||
// _que_create( &(q), NULL );
|
||||
// } while(0)
|
||||
//
|
||||
// #define QCREATE(q) // do nothing
|
||||
|
||||
#define QCREATE(q) // handled elsewhere for us
|
||||
|
||||
// check to see if the queue is empty
|
||||
// examples:
|
||||
//
|
||||
// #define QEMPTY(q) queue_is_empty(q)
|
||||
// #define QEMPTY(q) (quene_length(q) > 0)
|
||||
#define QEMPTY(q) pcb_queue_empty(q)
|
||||
|
||||
// this macro expands into code that removes a value from
|
||||
// 'q' and places it into 'd'
|
||||
#define QDEQUE(q, d) \
|
||||
do { \
|
||||
assert(pcb_queue_remove((q), (pcb_t **)&(d)) == SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
#endif /* QNAME */
|
||||
|
||||
#endif
|
22
include/ctype.h
Normal file
22
include/ctype.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @file ctype.h
|
||||
*
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* C type libaray functions
|
||||
*/
|
||||
|
||||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H
|
||||
|
||||
/**
|
||||
* @returns 1 if c is a space
|
||||
*/
|
||||
extern int isspace(int c);
|
||||
|
||||
/**
|
||||
* @returns 1 if c is a digit (0 - 9)
|
||||
*/
|
||||
extern int isdigit(int c);
|
||||
|
||||
#endif /* ctype.h */
|
356
include/debug.h
356
include/debug.h
|
@ -1,356 +0,0 @@
|
|||
/**
|
||||
** @file debug.h
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** Debugging macros and constants.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_H_
|
||||
#define DEBUG_H_
|
||||
|
||||
// Standard system headers
|
||||
|
||||
#include <cio.h>
|
||||
#include <support.h>
|
||||
|
||||
// Kernel library
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** General function entry/exit announcements
|
||||
*/
|
||||
|
||||
#ifdef ANNOUNCE_ENTRY
|
||||
// Announce that we have entered a kernel function
|
||||
// usage: ENTERING( "name" ), EXITING( "name" )
|
||||
// currently, these do not use the macro parameter, but could be
|
||||
// modified to do so; instead, we use the __func__ CPP pseudo-macro
|
||||
// to get the function name
|
||||
#define ENTERING(n) \
|
||||
do { \
|
||||
cio_puts(" enter " __func__); \
|
||||
} while (0)
|
||||
#define EXITING(n) \
|
||||
do { \
|
||||
cio_puts(" exit " __func__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ENTERING(m) // do nothing
|
||||
#define EXITING(m) // do nothing
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Console messages when error conditions are noted.
|
||||
*/
|
||||
|
||||
// Warning messages to the console
|
||||
// m: message (condition, etc.)
|
||||
#define WARNING(m) \
|
||||
do { \
|
||||
cio_printf("\n** %s (%s @ %d): ", __func__, __FILE__, __LINE__); \
|
||||
cio_puts(m); \
|
||||
cio_putchar('\n'); \
|
||||
} while (0)
|
||||
|
||||
// Panic messages to the console
|
||||
// n: severity level
|
||||
// m: message (condition, etc.)
|
||||
#define PANIC(n, m) \
|
||||
do { \
|
||||
sprint(b512, "%s (%s @ %d), %d: %s\n", __func__, __FILE__, __LINE__, \
|
||||
n, #m); \
|
||||
kpanic(b512); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
** Assertions are categorized by the "sanity level" being used in this
|
||||
** compilation; each only triggers a fault if the sanity level is at or
|
||||
** above a specific value. This allows selective enabling/disabling of
|
||||
** debugging checks.
|
||||
**
|
||||
** The sanity level is set during compilation with the CPP macro
|
||||
** "SANITY". A sanity level of 0 disables conditional assertions,
|
||||
** but not the basic assert() version.
|
||||
*/
|
||||
|
||||
#ifndef SANITY
|
||||
// default sanity check level: check everything!
|
||||
#define SANITY 9999
|
||||
#endif
|
||||
|
||||
// Always-active assertions
|
||||
#define assert(x) \
|
||||
if (!(x)) { \
|
||||
PANIC(0, x); \
|
||||
}
|
||||
|
||||
// only provide these macros if the sanity check level is positive
|
||||
|
||||
#if SANITY > 0
|
||||
|
||||
#define assert1(x) \
|
||||
if (SANITY >= 1 && !(x)) { \
|
||||
PANIC(1, x); \
|
||||
}
|
||||
#define assert2(x) \
|
||||
if (SANITY >= 2 && !(x)) { \
|
||||
PANIC(2, x); \
|
||||
}
|
||||
#define assert3(x) \
|
||||
if (SANITY >= 3 && !(x)) { \
|
||||
PANIC(3, x); \
|
||||
}
|
||||
#define assert4(x) \
|
||||
if (SANITY >= 4 && !(x)) { \
|
||||
PANIC(4, x); \
|
||||
}
|
||||
// arbitrary sanity level
|
||||
#define assertN(n, x) \
|
||||
if (SANITY >= (n) && !(x)) { \
|
||||
PANIC(n, x); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define assert1(x) // do nothing
|
||||
#define assert2(x) // do nothing
|
||||
#define assert3(x) // do nothing
|
||||
#define assert4(x) // do nothing
|
||||
#define assertN(n, x) // do nothing
|
||||
|
||||
#endif /* SANITY > 0 */
|
||||
|
||||
/*
|
||||
** Tracing options are enabled by defining one or more of the T_
|
||||
** macros described in the Makefile.
|
||||
**
|
||||
** To add a tracing option:
|
||||
**
|
||||
** 1) Pick a short name for it (e.g., "PCB", "VM", ...)
|
||||
** 2) At the end of this list, add code like this, with "name"
|
||||
** replaced by your short name, and "nnnnnnnn" replaced by a
|
||||
** unique bit that will designate this tracing option:
|
||||
**
|
||||
** #ifdef T_name
|
||||
** #define TRname 0xnnnnnnnn
|
||||
** #else
|
||||
** #define TRname 0
|
||||
** #endif
|
||||
**
|
||||
** Use the next bit position following the one in last list entry.
|
||||
** 3) Add this to the end of the "TRACE" macro definition:
|
||||
**
|
||||
** | TRname
|
||||
**
|
||||
** 4) In the list of "TRACING_*" macros, add one for your option
|
||||
** (using a name that might be more descriptive) in the 'then' clause:
|
||||
**
|
||||
** #define TRACING_bettername ((TRACE & TRname) != 0)
|
||||
**
|
||||
** 5) Also add a "null" version in the 'else' clause:
|
||||
**
|
||||
** #define TRACING_bettername 0
|
||||
**
|
||||
** 6) Maybe add your T_name choice to the Makefile with an explanation
|
||||
** on the off chance you want anyone else to be able to understand
|
||||
** what it's used for. :-)
|
||||
**
|
||||
** We're making CPP work for its pay with this file.
|
||||
*/
|
||||
|
||||
// 2^0 bit
|
||||
#ifdef T_PCB
|
||||
#define TRPCB 0x00000001
|
||||
#else
|
||||
#define TRPCB 0
|
||||
#endif
|
||||
|
||||
#ifdef T_VM
|
||||
#define TRVM 0x00000002
|
||||
#else
|
||||
#define TRVM 0
|
||||
#endif
|
||||
|
||||
#ifdef T_QUE
|
||||
#define TRQUEUE 0x00000004
|
||||
#else
|
||||
#define TRQUEUE 0
|
||||
#endif
|
||||
|
||||
#ifdef T_SCH
|
||||
#define TRSCHED 0x00000008
|
||||
#else
|
||||
#define TRSCHED 0
|
||||
#endif
|
||||
|
||||
// 2^4 bit
|
||||
#ifdef T_DSP
|
||||
#define TRDISP 0x00000010
|
||||
#else
|
||||
#define TRDISP 0
|
||||
#endif
|
||||
|
||||
#ifdef T_SCALL
|
||||
#define TRSYSCALLS 0x00000020
|
||||
#else
|
||||
#define TRSYSCALLS 0
|
||||
#endif
|
||||
|
||||
#ifdef T_SRET
|
||||
#define TRSYSRETS 0x00000040
|
||||
#else
|
||||
#define TRSYSRETS 0
|
||||
#endif
|
||||
|
||||
#ifdef T_EXIT
|
||||
#define TREXIT 0x00000080
|
||||
#else
|
||||
#define TREXIT 0
|
||||
#endif
|
||||
|
||||
// 2^8 bit
|
||||
#ifdef T_INIT
|
||||
#define TRINIT 0x00000100
|
||||
#else
|
||||
#define TRINIT 0
|
||||
#endif
|
||||
|
||||
#ifdef T_KM
|
||||
#define TRKMEM 0x00000200
|
||||
#else
|
||||
#define TRKMEM 0
|
||||
#endif
|
||||
|
||||
#ifdef T_KMFR
|
||||
#define TRKMEM_F 0x00000400
|
||||
#else
|
||||
#define TRKMEM_F 0
|
||||
#endif
|
||||
|
||||
#ifdef T_KMIN
|
||||
#define TRKMEM_I 0x00000800
|
||||
#else
|
||||
#define TRKMEM_I 0
|
||||
#endif
|
||||
|
||||
// 2^12 bit
|
||||
#ifdef T_FORK
|
||||
#define TRFORK 0x00001000
|
||||
#else
|
||||
#define TRFORK 0
|
||||
#endif
|
||||
|
||||
#ifdef T_EXEC
|
||||
#define TREXEC 0x00002000
|
||||
#else
|
||||
#define TREXEC 0
|
||||
#endif
|
||||
|
||||
#ifdef T_SIO
|
||||
#define TRSIO_STAT 0x00004000
|
||||
#else
|
||||
#define TRSIO_STAT 0
|
||||
#endif
|
||||
|
||||
#ifdef T_SIOR
|
||||
#define TRSIO_RD 0x00008000
|
||||
#else
|
||||
#define TRSIO_RD 0
|
||||
#endif
|
||||
|
||||
// 2^16 bit
|
||||
#ifdef T_SIOW
|
||||
#define TRSIO_WR 0x00010000
|
||||
#else
|
||||
#define TRSIO_WR 0
|
||||
#endif
|
||||
|
||||
#ifdef T_USER
|
||||
#define TRUSER 0x00020000
|
||||
#else
|
||||
#define TRUSER 0
|
||||
#endif
|
||||
|
||||
#ifdef T_ELF
|
||||
#define TRELF 0x00040000
|
||||
#else
|
||||
#define TRELF 0
|
||||
#endif
|
||||
|
||||
// 13 bits remaining for tracing options
|
||||
// next available bit: 0x00080000
|
||||
|
||||
#define TRACE \
|
||||
(TRDISP | TREXIT | TRINIT | TRKMEM | TRKMEM_F | TRKMEM_I | TRPCB | \
|
||||
TRQUEUE | TRSCHED | TREXEC | TRSIO_RD | TRSIO_STAT | TRSIO_WR | TRFORK | \
|
||||
TRVM | TRSYSCALLS | TRSYSRETS | TRUSER | TRELF)
|
||||
|
||||
#if TRACE > 0
|
||||
|
||||
// compile-time expressions for testing trace options
|
||||
// usage: #if TRACING_thing
|
||||
#define TRACING_PCB ((TRACE & TRPCB) != 0)
|
||||
#define TRACING_VM ((TRACE & TRVM) != 0)
|
||||
#define TRACING_QUEUE ((TRACE & TRQUEUE) != 0)
|
||||
#define TRACING_SCHED ((TRACE & TRSCHED) != 0)
|
||||
#define TRACING_DISPATCH ((TRACE & TRDISPATCH) != 0)
|
||||
#define TRACING_SYSCALLS ((TRACE & TRSYSCALLS) != 0)
|
||||
#define TRACING_SYSRETS ((TRACE & TRSYSRETS) != 0)
|
||||
#define TRACING_EXIT ((TRACE & TREXIT) != 0)
|
||||
#define TRACING_INIT ((TRACE & TRINIT) != 0)
|
||||
#define TRACING_KMEM ((TRACE & TRKMEM) != 0)
|
||||
#define TRACING_KMEM_FREELIST ((TRACE & TRKMEM_F) != 0)
|
||||
#define TRACING_KMEM_INIT ((TRACE & TRKMEM_I) != 0)
|
||||
#define TRACING_FORK ((TRACE & TRFORK) != 0)
|
||||
#define TRACING_EXEC ((TRACE & TREXEC) != 0)
|
||||
#define TRACING_SIO_STAT ((TRACE & TRSIO_STAT) != 0)
|
||||
#define TRACING_SIO_ISR ((TRACE & TRSIO_ISR) != 0)
|
||||
#define TRACING_SIO_RD ((TRACE & TRSIO_RD) != 0)
|
||||
#define TRACING_SIO_WR ((TRACE & TRSIO_WR) != 0)
|
||||
#define TRACING_USER ((TRACE & TRUSER) != 0)
|
||||
#define TRACING_ELF ((TRACE & TRELF) != 0)
|
||||
|
||||
// more generic tests
|
||||
#define TRACING_SOMETHING (TRACE != 0)
|
||||
|
||||
#else
|
||||
|
||||
// TRACE == 0, so just define these all as "false"
|
||||
|
||||
#define TRACING_PCB 0
|
||||
#define TRACING_STACK 0
|
||||
#define TRACING_QUEUE 0
|
||||
#define TRACING_SCHED 0
|
||||
#define TRACING_DISPATCH 0
|
||||
#define TRACING_SYSCALLS 0
|
||||
#define TRACING_SYSRET 0
|
||||
#define TRACING_EXIT 0
|
||||
#define TRACING_INIT 0
|
||||
#define TRACING_KMEM 0
|
||||
#define TRACING_KMEM_FREELIST 0
|
||||
#define TRACING_KMEM_INIT 0
|
||||
#define TRACING_FORK 0
|
||||
#define TRACING_EXEC 0
|
||||
#define TRACING_SI_STAT 0
|
||||
#define TRACING_SIO_ISR 0
|
||||
#define TRACING_SIO_RD 0
|
||||
#define TRACING_SIO_WR 0
|
||||
#define TRACING_USER 0
|
||||
#define TRACING_ELF 0
|
||||
|
||||
#define TRACING_SOMETHING 0
|
||||
|
||||
#endif /* TRACE */
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
130
include/defs.h
130
include/defs.h
|
@ -1,130 +0,0 @@
|
|||
/**
|
||||
** @file defs.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Common definitions.
|
||||
**
|
||||
** This header file defines things which are neede by all
|
||||
** parts of the system (OS and user levels).
|
||||
**
|
||||
** Things which are kernel-specific go in the kdefs.h file;
|
||||
** things which are user-specific go in the udefs.h file.
|
||||
** The correct one of these will be automatically included
|
||||
** at the end of this file.
|
||||
*/
|
||||
|
||||
#ifndef DEFS_H_
|
||||
#define DEFS_H_
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
**
|
||||
** This section of the header file contains definitions that can be
|
||||
** used in either C or assembly-language source code.
|
||||
*/
|
||||
|
||||
// NULL pointer value
|
||||
//
|
||||
// we define this the traditional way so that
|
||||
// it's usable from both C and assembly
|
||||
|
||||
#define NULL 0
|
||||
|
||||
// predefined i/o channels
|
||||
|
||||
#define CHAN_CIO 0
|
||||
#define CHAN_SIO 1
|
||||
|
||||
// sizes of various things
|
||||
#define NUM_1KB 0x00000400 // 2^10
|
||||
#define NUM_4KB 0x00001000 // 2^12
|
||||
#define NUM_1MB 0x00100000 // 2^20
|
||||
#define NUM_4MB 0x00400000 // 2^22
|
||||
#define NUM_1GB 0x40000000 // 2^30
|
||||
#define NUM_2GB 0x80000000 // 2^31
|
||||
#define NUM_3GB 0xc0000000 // 1GB + 2GB
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
**
|
||||
** Anything that should not be visible to something other than
|
||||
** the C compiler should be put here.
|
||||
*/
|
||||
|
||||
/*
|
||||
** System error codes
|
||||
**
|
||||
** These can be returned to both system functions
|
||||
** and to user system calls.
|
||||
*/
|
||||
// success!
|
||||
#define SUCCESS (0)
|
||||
#define E_SUCCESS SUCCESS
|
||||
// generic "something went wrong"
|
||||
#define E_FAILURE (-1)
|
||||
// specific failure reasons
|
||||
#define E_BAD_PARAM (-2)
|
||||
#define E_BAD_CHAN (-3)
|
||||
#define E_NO_CHILDREN (-4)
|
||||
#define E_NO_MEMORY (-5)
|
||||
#define E_NOT_FOUND (-6)
|
||||
#define E_NO_PROCS (-7)
|
||||
|
||||
/*
|
||||
** These error codes are internal to the OS.
|
||||
*/
|
||||
#define E_EMPTY_QUEUE (-100)
|
||||
#define E_NO_PCBS (-101)
|
||||
#define E_NO_PTE (-102)
|
||||
#define E_LOAD_LIMIT (-103)
|
||||
|
||||
// exit status values
|
||||
#define EXIT_SUCCESS (0)
|
||||
#define EXIT_FAILURE (-1)
|
||||
#define EXIT_KILLED (-101)
|
||||
#define EXIT_BAD_SYSCALL (-102)
|
||||
|
||||
/*
|
||||
** Process priority values
|
||||
*/
|
||||
enum priority_e {
|
||||
PRIO_HIGH,
|
||||
PRIO_STD,
|
||||
PRIO_LOW,
|
||||
PRIO_DEFERRED
|
||||
// sentinel
|
||||
,
|
||||
N_PRIOS
|
||||
};
|
||||
|
||||
// halves of various data sizes
|
||||
|
||||
#define UI16_UPPER 0xff00
|
||||
#define UI16_LOWER 0x00ff
|
||||
|
||||
#define UI32_UPPER 0xffff0000
|
||||
#define UI32_LOWER 0x0000ffff
|
||||
|
||||
#define UI64_UPPER 0xffffffff00000000LL
|
||||
#define UI64_LOWER 0x00000000ffffffffLL
|
||||
|
||||
// Simple conversion pseudo-functions usable by everyone
|
||||
|
||||
// convert seconds to ms
|
||||
#define SEC_TO_MS(n) ((n) * 1000)
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
/*
|
||||
** Level-specific definitions
|
||||
*/
|
||||
#ifdef KERNEL_SRC
|
||||
#include <kdefs.h>
|
||||
#else
|
||||
#include <udefs.h>
|
||||
#endif /* KERNEL_SRC */
|
||||
|
||||
#endif
|
4758
include/elf.h
4758
include/elf.h
File diff suppressed because it is too large
Load diff
30
include/error.h
Normal file
30
include/error.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file errno.h
|
||||
*
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* Error codes.
|
||||
*/
|
||||
|
||||
// public error codes
|
||||
#define SUCCESS (0)
|
||||
#define E_SUCCESS SUCCESS
|
||||
#define E_FAILURE (-1)
|
||||
#define E_BAD_PARAM (-2)
|
||||
#define E_BAD_FD (-3)
|
||||
#define E_NO_CHILDREN (-4)
|
||||
#define E_NO_MEMORY (-5)
|
||||
#define E_NOT_FOUND (-6)
|
||||
#define E_NO_PROCS (-7)
|
||||
|
||||
// internal error codes
|
||||
#define E_EMPTY_QUEUE (-100)
|
||||
#define E_NO_PCBS (-101)
|
||||
#define E_NO_PTE (-102)
|
||||
#define E_LOAD_LIMIT (-103)
|
||||
|
||||
// exit status values
|
||||
#define EXIT_SUCCESS (0)
|
||||
#define EXIT_FAILURE (-1)
|
||||
#define EXIT_KILLED (-101)
|
||||
#define EXIT_BAD_SYSCALL (-102)
|
157
include/kdefs.h
157
include/kdefs.h
|
@ -1,157 +0,0 @@
|
|||
/**
|
||||
** @file kdefs.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Kernel-only declarations.
|
||||
*/
|
||||
|
||||
#ifndef KDEFS_H_
|
||||
#define KDEFS_H_
|
||||
|
||||
// debugging macros
|
||||
#include <debug.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// page sizes
|
||||
#define SZ_PAGE NUM_4KB
|
||||
#define SZ_BIGPAGE NUM_4MB
|
||||
|
||||
// kernel stack size (bytes)
|
||||
#define N_KSTKPAGES 1
|
||||
#define SZ_KSTACK (N_KSTKPAGES * SZ_PAGE)
|
||||
|
||||
// user stack size
|
||||
#define N_USTKPAGES 2
|
||||
#define SZ_USTACK (N_USTKPAGES * SZ_PAGE)
|
||||
|
||||
// declarations for modulus checking of (e.g.) sizes and addresses
|
||||
|
||||
#define LOW_9_BITS 0x00000fff
|
||||
#define LOW_22_BITS 0x003fffff
|
||||
#define HIGH_20_BITS 0xfffff000
|
||||
#define HIGH_10_BITS 0xffc00000
|
||||
|
||||
#define MOD4_BITS 0x00000003
|
||||
#define MOD4_MASK 0xfffffffc
|
||||
#define MOD4_INC 0x00000004
|
||||
#define MOD4_SHIFT 2
|
||||
|
||||
#define MOD16_BITS 0x0000000f
|
||||
#define MOD16_MASK 0xfffffff0
|
||||
#define MOD16_INC 0x00000010
|
||||
#define MOD16_SHIFT 4
|
||||
|
||||
#define MOD1K_BITS 0x000003ff
|
||||
#define MOD1K_MASK 0xfffffc00
|
||||
#define MOD1K_INC 0x00000400
|
||||
#define MOD1K_SHIFT 10
|
||||
|
||||
#define MOD4K_BITS 0x00000fff
|
||||
#define MOD4K_MASK 0xfffff000
|
||||
#define MOD4K_INC 0x00001000
|
||||
#define MOD4K_SHIFT 12
|
||||
|
||||
#define MOD1M_BITS 0x000fffff
|
||||
#define MOD1M_MASK 0xfff00000
|
||||
#define MOD1M_INC 0x00100000
|
||||
#define MOD1M_SHIFT 20
|
||||
|
||||
#define MOD4M_BITS 0x003fffff
|
||||
#define MOD4M_MASK 0xffc00000
|
||||
#define MOD4M_INC 0x00400000
|
||||
#define MOD4M_SHIFT 22
|
||||
|
||||
#define MOD1G_BITS 0x3fffffff
|
||||
#define MOD1G_MASK 0xc0000000
|
||||
#define MOD1G_INC 0x40000000
|
||||
#define MOD1G_SHIFT 30
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
// unit conversion macros
|
||||
#define B_TO_KB(x) (((uint_t)(x)) >> 10)
|
||||
#define B_TO_MB(x) (((uint_t)(x)) >> 20)
|
||||
#define B_TO_GB(x) (((uint_t)(x)) >> 30)
|
||||
|
||||
#define KB_TO_B(x) (((uint_t)(x)) << 10)
|
||||
#define KB_TO_MB(x) (((uint_t)(x)) >> 10)
|
||||
#define KB_TO_GB(x) (((uint_t)(x)) >> 20)
|
||||
|
||||
#define MB_TO_B(x) (((uint_t)(x)) << 20)
|
||||
#define MB_TO_KB(x) (((uint_t)(x)) << 10)
|
||||
#define MB_TO_GB(x) (((uint_t)(x)) >> 10)
|
||||
|
||||
#define GB_TO_B(x) (((uint_t)(x)) << 30)
|
||||
#define GB_TO_KB(x) (((uint_t)(x)) << 20)
|
||||
#define GB_TO_MB(x) (((uint_t)(x)) << 10)
|
||||
|
||||
// potetially useful compiler attributes
|
||||
#define ATTR_ALIGNED(x) __attribute__((__aligned__(x)))
|
||||
#define ATTR_PACKED __attribute__((__packed__))
|
||||
#define ATTR_UNUSED __attribute__((__unused__))
|
||||
|
||||
/*
|
||||
** Utility macros
|
||||
*/
|
||||
|
||||
//
|
||||
// macros to clear data structures
|
||||
//
|
||||
// these are usable for clearing single-valued data items (e.g.,
|
||||
// a PCB, etc.)
|
||||
#define CLEAR(v) memclr(&v, sizeof(v))
|
||||
#define CLEAR_PTR(p) memclr(p, sizeof(*p))
|
||||
|
||||
//
|
||||
// macros for access registers and system call arguments
|
||||
//
|
||||
|
||||
// REG(pcb,x) -- access a specific register in a process context
|
||||
#define REG(pcb, x) ((pcb)->context->x)
|
||||
|
||||
// RET(pcb) -- access return value register in a process context
|
||||
#define RET(pcb) ((pcb)->context->eax)
|
||||
|
||||
// ARG(pcb,n) -- access argument #n from the indicated process
|
||||
//
|
||||
// ARG(pcb,0) --> return address
|
||||
// ARG(pcb,1) --> first parameter
|
||||
// ARG(pcb,2) --> second parameter
|
||||
// etc.
|
||||
//
|
||||
// ASSUMES THE STANDARD 32-BIT ABI, WITH PARAMETERS PUSHED ONTO THE
|
||||
// STACK. IF THE PARAMETER PASSING MECHANISM CHANGES, SO MUST THIS!
|
||||
#define ARG(pcb, n) (((uint32_t *)(((pcb)->context) + 1))[(n)])
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
// general-purpose character buffer
|
||||
extern char b256[256];
|
||||
|
||||
// buffer for use by PANIC() macro
|
||||
extern char b512[512];
|
||||
|
||||
// kernel stack
|
||||
extern uint8_t kstack[SZ_KSTACK];
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
** @file klib.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** Additional support functions for the kernel.
|
||||
*/
|
||||
|
||||
#ifndef KLIB_H_
|
||||
#define KLIB_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
#include <x86/ops.h>
|
||||
|
||||
/**
|
||||
** Name: put_char_or_code( ch )
|
||||
**
|
||||
** Description: Prints a character on the console, unless it
|
||||
** is a non-printing character, in which case its hex code
|
||||
** is printed
|
||||
**
|
||||
** @param ch The character to be printed
|
||||
*/
|
||||
void put_char_or_code(int ch);
|
||||
|
||||
/**
|
||||
** Name: backtrace
|
||||
**
|
||||
** Perform a simple stack backtrace. Could be augmented to use the
|
||||
** symbol table to print function/variable names, etc., if so desired.
|
||||
**
|
||||
** @param ebp Initial EBP to use
|
||||
** @param args Number of function argument values to print
|
||||
*/
|
||||
void backtrace(uint32_t *ebp, uint_t args);
|
||||
|
||||
/**
|
||||
** Name: kpanic
|
||||
**
|
||||
** Kernel-level panic routine
|
||||
**
|
||||
** usage: kpanic( msg )
|
||||
**
|
||||
** Prefix routine for panic() - can be expanded to do other things
|
||||
** (e.g., printing a stack traceback)
|
||||
**
|
||||
** @param msg[in] String containing a relevant message to be printed,
|
||||
** or NULL
|
||||
*/
|
||||
void kpanic(const char *msg);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
138
include/kmem.h
138
include/kmem.h
|
@ -1,138 +0,0 @@
|
|||
/**
|
||||
** @file kmem.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @author Kenneth Reek
|
||||
** @author 4003-506 class of 20013
|
||||
**
|
||||
** @brief Support for dynamic memory allocation within the OS.
|
||||
**
|
||||
** This is a basic page allocator. Each allocation request returns
|
||||
** a pointer to a single 4096-byte page of memory.
|
||||
**
|
||||
** The module also supports subddivision of pages into "slices",
|
||||
** each of which is 1KB (i.e., 1/4 of a page).
|
||||
*/
|
||||
|
||||
#ifndef KMEM_H_
|
||||
#define KMEM_H_
|
||||
|
||||
#define KERNEL_SRC
|
||||
|
||||
// standard types etc.
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// Slab and slice sizes, in bytes
|
||||
|
||||
#define SZ_SLAB SZ_PAGE
|
||||
#define SZ_SLICE (SZ_SLAB >> 2)
|
||||
|
||||
// memory limits
|
||||
//
|
||||
// these determine the range of memory addresses the kmem
|
||||
// module will manage
|
||||
//
|
||||
// we won't map any memory below 1MB or above 1GB
|
||||
#define KM_LOW_CUTOFF NUM_1MB
|
||||
#define KM_HIGH_CUTOFF NUM_1GB
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: km_init
|
||||
**
|
||||
** Find what memory is present on the system and
|
||||
** construct the list of free memory blocks.
|
||||
**
|
||||
** Dependencies:
|
||||
** Must be called before any other init routine that uses
|
||||
** dynamic storage is called.
|
||||
*/
|
||||
void km_init(void);
|
||||
|
||||
/**
|
||||
** Name: km_dump
|
||||
**
|
||||
** Dump information about the free lists to the console. By default,
|
||||
** prints only the list sizes; if 'addrs' is true, also dumps the list
|
||||
** of page addresses; if 'all' is also true, dumps page addresses and
|
||||
** slice addresses.
|
||||
**
|
||||
** @param addrs Also dump page addresses
|
||||
** @param both Also dump slice addresses
|
||||
*/
|
||||
void km_dump(bool_t addrs, bool_t both);
|
||||
|
||||
/*
|
||||
** Functions that manipulate free memory blocks.
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: km_page_alloc
|
||||
**
|
||||
** Allocate a page of memory from the free list.
|
||||
**
|
||||
** @return a pointer to the beginning of the allocated page,
|
||||
** or NULL if no memory is available
|
||||
*/
|
||||
void *km_page_alloc(void);
|
||||
|
||||
/**
|
||||
** Name: km_page_free
|
||||
**
|
||||
** Returns a memory block to the list of available blocks,
|
||||
** combining it with adjacent blocks if they're present.
|
||||
**
|
||||
** CRITICAL ASSUMPTION: multi-page blocks will be freed one page
|
||||
** at a time!
|
||||
**
|
||||
** @param[in] block Pointer to the page to be returned to the free list
|
||||
*/
|
||||
void km_page_free(void *block);
|
||||
|
||||
/**
|
||||
** Name: km_slice_alloc
|
||||
**
|
||||
** Dynamically allocates a slice (1/4 of a page). If no
|
||||
** memory is available, we return NULL (unless ALLOC_FAIL_PANIC
|
||||
** was defined, in which case we panic).
|
||||
**
|
||||
** @return a pointer to the allocated slice
|
||||
*/
|
||||
void *km_slice_alloc(void);
|
||||
|
||||
/**
|
||||
** Name: km_slice_free
|
||||
**
|
||||
** Returns a slice to the list of available slices.
|
||||
**
|
||||
** We make no attempt to merge slices, as they are independent
|
||||
** blocks of memory (unlike pages).
|
||||
**
|
||||
** @param[in] block Pointer to the slice (1/4 page) to be freed
|
||||
*/
|
||||
void km_slice_free(void *block);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
314
include/lib.h
314
include/lib.h
|
@ -1,314 +0,0 @@
|
|||
/**
|
||||
** @file lib.h
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C declarations of common library functions
|
||||
**
|
||||
** These are callable from either kernel or user code. Care should be taken
|
||||
** that user code is linked against these separately from kernel code, to
|
||||
** ensure separation of the address spaces.
|
||||
*/
|
||||
|
||||
#ifndef LIB_H_
|
||||
#define LIB_H_
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** MEMORY MANIPULATION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** blkmov(dst,src,len)
|
||||
**
|
||||
** Copy a word-aligned block from src to dst. Deals with overlapping
|
||||
** buffers.
|
||||
**
|
||||
** If the buffer addresses aren't word-aligned or the length is not a
|
||||
** multiple of four, calls memmove().
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void blkmov(void *dst, const void *src, register uint32_t len);
|
||||
|
||||
/**
|
||||
** memset(buf,len,value)
|
||||
**
|
||||
** initialize all bytes of a block of memory to a specific value
|
||||
**
|
||||
** @param buf The buffer to initialize
|
||||
** @param len Buffer size (in bytes)
|
||||
** @param value Initialization value
|
||||
*/
|
||||
void memset(void *buf, register uint32_t len, register uint32_t value);
|
||||
|
||||
/**
|
||||
** memclr(buf,len)
|
||||
**
|
||||
** Initialize all bytes of a block of memory to zero
|
||||
**
|
||||
** @param buf The buffer to initialize
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memclr(void *buf, register uint32_t len);
|
||||
|
||||
/**
|
||||
** memcpy(dst,src,len)
|
||||
**
|
||||
** Copy a block from one place to another
|
||||
**
|
||||
** May not correctly deal with overlapping buffers
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memcpy(void *dst, register const void *src, register uint32_t len);
|
||||
|
||||
/**
|
||||
** memmove(dst,src,len)
|
||||
**
|
||||
** Copy a block from one place to another. Deals with overlapping
|
||||
** buffers
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Buffer size (in bytes)
|
||||
*/
|
||||
void memmove(void *dst, register const void *src, register uint32_t len);
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** STRING MANIPULATION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** str2int(str,base) - convert a string to a number in the specified base
|
||||
**
|
||||
** @param str The string to examine
|
||||
** @param base The radix to use in the conversion
|
||||
**
|
||||
** @return The converted integer
|
||||
*/
|
||||
int str2int(register const char *str, register int base);
|
||||
|
||||
/**
|
||||
** strlen(str) - return length of a NUL-terminated string
|
||||
**
|
||||
** @param str The string to examine
|
||||
**
|
||||
** @return The length of the string, or 0
|
||||
*/
|
||||
uint32_t strlen(register const char *str);
|
||||
|
||||
/**
|
||||
** strcmp(s1,s2) - compare two NUL-terminated strings
|
||||
**
|
||||
** @param s1 The first source string
|
||||
** @param s2 The second source string
|
||||
**
|
||||
** @return negative if s1 < s2, zero if equal, and positive if s1 > s2
|
||||
*/
|
||||
int strcmp(register const char *s1, register const char *s2);
|
||||
|
||||
/**
|
||||
** strcpy(dst,src) - copy a NUL-terminated string
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param src The source buffer
|
||||
**
|
||||
** @return The dst parameter
|
||||
**
|
||||
** NOTE: assumes dst is large enough to hold the copied string
|
||||
*/
|
||||
char *strcpy(register char *dst, register const char *src);
|
||||
|
||||
/**
|
||||
** strcat(dst,src) - append one string to another
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param src The source buffer
|
||||
**
|
||||
** @return The dst parameter
|
||||
**
|
||||
** NOTE: assumes dst is large enough to hold the resulting string
|
||||
*/
|
||||
char *strcat(register char *dst, register const char *src);
|
||||
|
||||
/**
|
||||
** pad(dst,extra,padchar) - generate a padding string
|
||||
**
|
||||
** @param dst Pointer to where the padding should begin
|
||||
** @param extra How many padding bytes to add
|
||||
** @param padchar What character to pad with
|
||||
**
|
||||
** @return Pointer to the first byte after the padding
|
||||
**
|
||||
** NOTE: does NOT NUL-terminate the buffer
|
||||
*/
|
||||
char *pad(char *dst, int extra, int padchar);
|
||||
|
||||
/**
|
||||
** padstr(dst,str,len,width,leftadjust,padchar - add padding characters
|
||||
** to a string
|
||||
**
|
||||
** @param dst The destination buffer
|
||||
** @param str The string to be padded
|
||||
** @param len The string length, or -1
|
||||
** @param width The desired final length of the string
|
||||
** @param leftadjust Should the string be left-justified?
|
||||
** @param padchar What character to pad with
|
||||
**
|
||||
** @return Pointer to the first byte after the padded string
|
||||
**
|
||||
** NOTE: does NOT NUL-terminate the buffer
|
||||
*/
|
||||
char *padstr(char *dst, char *str, int len, int width, int leftadjust,
|
||||
int padchar);
|
||||
|
||||
/**
|
||||
** sprint(dst,fmt,...) - formatted output into a string buffer
|
||||
**
|
||||
** @param dst The string buffer
|
||||
** @param fmt Format string
|
||||
**
|
||||
** The format string parameter is followed by zero or more additional
|
||||
** parameters which are interpreted according to the format string.
|
||||
**
|
||||
** NOTE: assumes the buffer is large enough to hold the result string
|
||||
**
|
||||
** NOTE: relies heavily on the x86 parameter passing convention
|
||||
** (parameters are pushed onto the stack in reverse order as
|
||||
** 32-bit values).
|
||||
*/
|
||||
void sprint(char *dst, char *fmt, ...);
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** CONVERSION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** cvtuns0(buf,value) - local support routine for cvtuns()
|
||||
**
|
||||
** Convert a 32-bit unsigned value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Result buffer
|
||||
** @param value Value to be converted
|
||||
**
|
||||
** @return Pointer to the first unused byte in the buffer
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
char *cvtuns0(char *buf, uint32_t value);
|
||||
|
||||
/**
|
||||
** cvtuns(buf,value)
|
||||
**
|
||||
** Convert a 32-bit unsigned value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Result buffer
|
||||
** @param value Value to be converted
|
||||
**
|
||||
** @return Length of the resulting buffer
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtuns(char *buf, uint32_t value);
|
||||
|
||||
/**
|
||||
** cvtdec0(buf,value) - local support routine for cvtdec()
|
||||
**
|
||||
** convert a 32-bit unsigned integer into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
char *cvtdec0(char *buf, int value);
|
||||
|
||||
/**
|
||||
** cvtdec(buf,value)
|
||||
**
|
||||
** convert a 32-bit signed value into a NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtdec(char *buf, int32_t value);
|
||||
|
||||
/**
|
||||
** cvthex(buf,value)
|
||||
**
|
||||
** convert a 32-bit unsigned value into a mininal-length (up to
|
||||
** 8-character) NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvthex(char *buf, uint32_t value);
|
||||
|
||||
/**
|
||||
** cvtoct(buf,value)
|
||||
**
|
||||
** convert a 32-bit unsigned value into a mininal-length (up to
|
||||
** 11-character) NUL-terminated character string
|
||||
**
|
||||
** @param buf Destination buffer
|
||||
** @param value Value to convert
|
||||
**
|
||||
** @return The number of characters placed into the buffer
|
||||
** (not including the NUL)
|
||||
**
|
||||
** NOTE: assumes buf is large enough to hold the resulting string
|
||||
*/
|
||||
int cvtoct(char *buf, uint32_t value);
|
||||
|
||||
/**
|
||||
** bound(min,value,max)
|
||||
**
|
||||
** This function confines an argument within specified bounds.
|
||||
**
|
||||
** @param min Lower bound
|
||||
** @param value Value to be constrained
|
||||
** @param max Upper bound
|
||||
**
|
||||
** @return The constrained value
|
||||
*/
|
||||
uint32_t bound(uint32_t min, uint32_t value, uint32_t max);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
/*
|
||||
** Finally, pull in the level-specific library headers
|
||||
*/
|
||||
#ifdef KERNEL_SRC
|
||||
#include <klib.h>
|
||||
#else
|
||||
#include <ulib.h>
|
||||
#endif /* KERNEL_SRC */
|
||||
|
||||
#endif
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
** @file list.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Support for a basic linked list data type.
|
||||
**
|
||||
** This module provides a very basic linked list data structure.
|
||||
** A list can contain anything that has a pointer field in the first
|
||||
** four bytes; these routines assume those bytes contain a pointer to
|
||||
** the following entry in the list, whatever that may be.
|
||||
*/
|
||||
|
||||
#ifndef LIST_H_
|
||||
#define LIST_H_
|
||||
|
||||
#define KERNEL_SRC
|
||||
|
||||
// standard types etc.
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Data types
|
||||
*/
|
||||
|
||||
// The list structure
|
||||
typedef struct list_s {
|
||||
struct list_s *next; // link to the successor
|
||||
} list_t;
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: list_add
|
||||
**
|
||||
** Add the supplied data to the beginning of the specified list.
|
||||
**
|
||||
** @param[in,out] list The address of a list_t variable
|
||||
** @param[in] data The data to prepend to the list
|
||||
*/
|
||||
void list_add(list_t *list, void *data);
|
||||
|
||||
/**
|
||||
** Name: list_remove
|
||||
**
|
||||
** Remove the first entry from a linked list.
|
||||
**
|
||||
** @param[in,out] list The address of a list_t variable
|
||||
**
|
||||
** @return a pointer to the removed data, or NULL if the list was empty
|
||||
*/
|
||||
void *list_remove(list_t *list);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
** @file params.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief System configuration settings
|
||||
**
|
||||
** This header file contains many of the "easily tunable" system
|
||||
** settings, such as clock rate, number of simultaneous user
|
||||
** processes, etc. This provides a sort of "one-stop shop" for
|
||||
** things that might be tweaked frequently.
|
||||
*/
|
||||
|
||||
#ifndef PARAMS_H_
|
||||
#define PARAMS_H_
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// Upper bound on the number of simultaneous user-level
|
||||
// processes in the system (completely arbitrary)
|
||||
#define N_PROCS 25
|
||||
|
||||
// Limit on the number of entries in argv[], INCLUDING
|
||||
// the trailing NULL pointer (also completely arbitrary)
|
||||
#define N_ARGS 10
|
||||
|
||||
// Clock frequency (Hz)
|
||||
#define CLOCK_FREQ 1000
|
||||
#define TICKS_PER_MS 1
|
||||
|
||||
#endif
|
457
include/procs.h
457
include/procs.h
|
@ -1,457 +0,0 @@
|
|||
/*
|
||||
** @file procs.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Process-related declarations
|
||||
*/
|
||||
|
||||
#ifndef PROCS_H_
|
||||
#define PROCS_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Process states
|
||||
*/
|
||||
enum state_e {
|
||||
// pre-viable
|
||||
STATE_UNUSED = 0,
|
||||
STATE_NEW,
|
||||
// runnable
|
||||
STATE_READY,
|
||||
STATE_RUNNING,
|
||||
// runnable, but waiting for some event
|
||||
STATE_SLEEPING,
|
||||
STATE_BLOCKED,
|
||||
STATE_WAITING,
|
||||
// no longer runnable
|
||||
STATE_KILLED,
|
||||
STATE_ZOMBIE
|
||||
// sentinel value
|
||||
,
|
||||
N_STATES
|
||||
};
|
||||
|
||||
// these may be handy for checking general conditions of processes
|
||||
// they depend on the order of the state names in the enum!
|
||||
#define FIRST_VIABLE STATE_READY
|
||||
#define FIRST_BLOCKED STATE_SLEEPING
|
||||
#define LAST_VIABLE STATE_WAITING
|
||||
|
||||
/*
|
||||
** Process priorities are defined in <defs.h>
|
||||
*/
|
||||
|
||||
/*
|
||||
** Quantum lengths - values are number of clock ticks
|
||||
*/
|
||||
enum quantum_e { QUANTUM_SHORT = 1, QUANTUM_STANDARD = 3, QUANTUM_LONG = 5 };
|
||||
|
||||
/*
|
||||
** PID-related definitions
|
||||
*/
|
||||
#define PID_INIT 1
|
||||
#define FIRST_USER_PID 2
|
||||
|
||||
/*
|
||||
** Process context structure
|
||||
**
|
||||
** NOTE: the order of data members here depends on the
|
||||
** register save code in isr_stubs.S!!!!
|
||||
**
|
||||
** This will be at the top of the user stack when we enter
|
||||
** an ISR. In the case of a system call, it will be followed
|
||||
** by the return address and the system call parameters.
|
||||
*/
|
||||
|
||||
typedef struct context_s {
|
||||
uint32_t ss; // pushed by isr_save
|
||||
uint32_t gs;
|
||||
uint32_t fs;
|
||||
uint32_t es;
|
||||
uint32_t ds;
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint32_t ebp;
|
||||
uint32_t esp;
|
||||
uint32_t ebx;
|
||||
uint32_t edx;
|
||||
uint32_t ecx;
|
||||
uint32_t eax;
|
||||
uint32_t vector;
|
||||
uint32_t code; // pushed by isr_save or the hardware
|
||||
uint32_t eip; // pushed by the hardware
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
} context_t;
|
||||
|
||||
#define SZ_CONTEXT sizeof(context_t)
|
||||
|
||||
/*
|
||||
** program section information for user processes
|
||||
*/
|
||||
|
||||
typedef struct section_s {
|
||||
uint_t length; // length, in some units
|
||||
uint_t addr; // location, in some units
|
||||
} section_t;
|
||||
|
||||
// note: these correspond to the PT_LOAD sections found in
|
||||
// an ELF file, not necessarily to text/data/bss
|
||||
#define SECT_L1 0
|
||||
#define SECT_L2 1
|
||||
#define SECT_L3 2
|
||||
#define SECT_STACK 3
|
||||
|
||||
// total number of section table entries in our PCB
|
||||
#define N_SECTS 4
|
||||
// number of those that can be loaded from an ELF module
|
||||
#define N_LOADABLE 3
|
||||
|
||||
/*
|
||||
** The process control block
|
||||
**
|
||||
** Fields are ordered by size to avoid padding
|
||||
**
|
||||
** Currently, this is 72 bytes long. It could be reduced to 64 (2^6)
|
||||
** bytes by making the last four fields uint16_t types; that would
|
||||
** divide nicely into 1024 bytes, giving 16 PCBs per 1/4 page of memory.
|
||||
*/
|
||||
|
||||
typedef struct pcb_s {
|
||||
// four-byte fields
|
||||
// start with these four bytes, for easy access in assembly
|
||||
context_t *context; // pointer to context save area on stack
|
||||
|
||||
// VM information
|
||||
pde_t *pdir; // page directory for this process
|
||||
section_t sects[N_SECTS]; // per-section memory information
|
||||
|
||||
// queue linkage
|
||||
struct pcb_s *next; // next PCB in queue
|
||||
|
||||
// process state information
|
||||
struct pcb_s *parent; // pointer to PCB of our parent process
|
||||
uint32_t wakeup; // wakeup time, for sleeping processes
|
||||
int32_t exit_status; // termination status, for parent's use
|
||||
|
||||
// these things may not need to be four bytes
|
||||
uint_t pid; // PID of this process
|
||||
enum state_e state; // process' current state
|
||||
enum priority_e priority; // process priority level
|
||||
uint_t ticks; // remaining ticks in this time slice
|
||||
|
||||
} pcb_t;
|
||||
|
||||
#define SZ_PCB sizeof(pcb_t)
|
||||
|
||||
/*
|
||||
** PCB queue structure (opaque to the rest of the kernel)
|
||||
*/
|
||||
typedef struct pcb_queue_s *pcb_queue_t;
|
||||
|
||||
/*
|
||||
** Queue ordering methods
|
||||
*/
|
||||
enum pcb_queue_order_e {
|
||||
O_FIFO,
|
||||
O_PRIO,
|
||||
O_PID,
|
||||
O_WAKEUP
|
||||
// sentinel
|
||||
,
|
||||
N_ORDERINGS
|
||||
};
|
||||
#define O_FIRST_STYLE O_FIFO
|
||||
#define O_LAST_STYLE O_WAKEUP
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
// public-facing queue handles
|
||||
extern pcb_queue_t pcb_freelist;
|
||||
extern pcb_queue_t ready;
|
||||
extern pcb_queue_t waiting;
|
||||
extern pcb_queue_t sleeping;
|
||||
extern pcb_queue_t zombie;
|
||||
extern pcb_queue_t sioread;
|
||||
|
||||
// pointer to the currently-running process
|
||||
extern pcb_t *current;
|
||||
|
||||
// the process table
|
||||
extern pcb_t ptable[N_PROCS];
|
||||
|
||||
// next available PID
|
||||
extern uint_t next_pid;
|
||||
|
||||
// pointer to the PCB for the 'init' process
|
||||
extern pcb_t *init_pcb;
|
||||
|
||||
// table of state name strings
|
||||
extern const char state_str[N_STATES][4];
|
||||
|
||||
// table of priority name strings
|
||||
extern const char prio_str[N_PRIOS][5];
|
||||
|
||||
// table of queue ordering name strings
|
||||
extern const char ord_str[N_ORDERINGS][5];
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: pcb_init
|
||||
**
|
||||
** Initialization for the Process module.
|
||||
*/
|
||||
void pcb_init(void);
|
||||
|
||||
/**
|
||||
** Name: pcb_alloc
|
||||
**
|
||||
** Allocate a PCB from the list of free PCBs.
|
||||
**
|
||||
** @param pcb Pointer to a pcb_t * where the PCB pointer will be returned.
|
||||
**
|
||||
** @return status of the allocation attempt
|
||||
*/
|
||||
int pcb_alloc(pcb_t **pcb);
|
||||
|
||||
/**
|
||||
** Name: pcb_free
|
||||
**
|
||||
** Return a PCB to the list of free PCBs.
|
||||
**
|
||||
** @param pcb Pointer to the PCB to be deallocated.
|
||||
*/
|
||||
void pcb_free(pcb_t *pcb);
|
||||
|
||||
/**
|
||||
** Name: pcb_zombify
|
||||
**
|
||||
** Turn the indicated process into a Zombie. This function
|
||||
** does most of the real work for exit() and kill() calls.
|
||||
** Is also called from the scheduler and dispatcher.
|
||||
**
|
||||
** @param pcb Pointer to the newly-undead PCB
|
||||
*/
|
||||
void pcb_zombify(register pcb_t *victim);
|
||||
|
||||
/**
|
||||
** Name: pcb_cleanup
|
||||
**
|
||||
** Reclaim a process' data structures
|
||||
**
|
||||
** @param pcb The PCB to reclaim
|
||||
*/
|
||||
void pcb_cleanup(pcb_t *pcb);
|
||||
|
||||
/**
|
||||
** Name: pcb_find_pid
|
||||
**
|
||||
** Locate the PCB for the process with the specified PID
|
||||
**
|
||||
** @param pid The PID to be located
|
||||
**
|
||||
** @return Pointer to the PCB, or NULL
|
||||
*/
|
||||
pcb_t *pcb_find_pid(uint_t pid);
|
||||
|
||||
/**
|
||||
** Name: pcb_find_ppid
|
||||
**
|
||||
** Locate the PCB for the process with the specified parent
|
||||
**
|
||||
** @param pid The PID to be located
|
||||
**
|
||||
** @return Pointer to the PCB, or NULL
|
||||
*/
|
||||
pcb_t *pcb_find_ppid(uint_t pid);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_reset
|
||||
**
|
||||
** Initialize a PCB queue.
|
||||
**
|
||||
** @param queue[out] The queue to be initialized
|
||||
** @param order[in] The desired ordering for the queue
|
||||
**
|
||||
** @return status of the init request
|
||||
*/
|
||||
int pcb_queue_reset(pcb_queue_t queue, enum pcb_queue_order_e style);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_empty
|
||||
**
|
||||
** Determine whether a queue is empty. Essentially just a wrapper
|
||||
** for the PCB_QUEUE_EMPTY() macro, for use outside this module.
|
||||
**
|
||||
** @param[in] queue The queue to check
|
||||
**
|
||||
** @return true if the queue is empty, else false
|
||||
*/
|
||||
bool_t pcb_queue_empty(pcb_queue_t queue);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_length
|
||||
**
|
||||
** Return the count of elements in the specified queue.
|
||||
**
|
||||
** @param[in] queue The queue to check
|
||||
**
|
||||
** @return the count (0 if the queue is empty)
|
||||
*/
|
||||
uint_t pcb_queue_length(const pcb_queue_t queue);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_insert
|
||||
**
|
||||
** Inserts a PCB into the indicated queue.
|
||||
**
|
||||
** @param queue[in,out] The queue to be used
|
||||
** @param pcb[in] The PCB to be inserted
|
||||
**
|
||||
** @return status of the insertion request
|
||||
*/
|
||||
int pcb_queue_insert(pcb_queue_t queue, pcb_t *pcb);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_peek
|
||||
**
|
||||
** Return the first PCB from the indicated queue, but don't
|
||||
** remove it from the queue
|
||||
**
|
||||
** @param queue[in] The queue to be used
|
||||
**
|
||||
** @return the PCB pointer, or NULL if the queue is empty
|
||||
*/
|
||||
pcb_t *pcb_queue_peek(const pcb_queue_t queue);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_remove
|
||||
**
|
||||
** Remove the first PCB from the indicated queue.
|
||||
**
|
||||
** @param queue[in,out] The queue to be used
|
||||
** @param pcb[out] Pointer to where the PCB pointer will be saved
|
||||
**
|
||||
** @return status of the removal request
|
||||
*/
|
||||
int pcb_queue_remove(pcb_queue_t queue, pcb_t **pcb);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_remove_this
|
||||
**
|
||||
** Remove the specified PCB from the indicated queue.
|
||||
**
|
||||
** @param queue[in,out] The queue to be used
|
||||
** @param pcb[in] Pointer to the PCB to be removed
|
||||
**
|
||||
** @return status of the removal request
|
||||
*/
|
||||
int pcb_queue_remove_this(pcb_queue_t queue, pcb_t *pcb);
|
||||
|
||||
/*
|
||||
** Scheduler routines
|
||||
*/
|
||||
|
||||
/**
|
||||
** schedule(pcb)
|
||||
**
|
||||
** Schedule the supplied process
|
||||
**
|
||||
** @param pcb Pointer to the PCB of the process to be scheduled
|
||||
*/
|
||||
void schedule(pcb_t *pcb);
|
||||
|
||||
/**
|
||||
** dispatch()
|
||||
**
|
||||
** Select the next process to receive the CPU
|
||||
*/
|
||||
void dispatch(void);
|
||||
|
||||
/*
|
||||
** Debugging/tracing routines
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: ctx_dump
|
||||
**
|
||||
** Dumps the contents of this process context to the console
|
||||
**
|
||||
** @param msg[in] An optional message to print before the dump
|
||||
** @param c[in] The context to dump out
|
||||
*/
|
||||
void ctx_dump(const char *msg, register context_t *c);
|
||||
|
||||
/**
|
||||
** Name: ctx_dump_all
|
||||
**
|
||||
** dump the process context for all active processes
|
||||
**
|
||||
** @param msg[in] Optional message to print
|
||||
*/
|
||||
void ctx_dump_all(const char *msg);
|
||||
|
||||
/**
|
||||
** Name: pcb_dump
|
||||
**
|
||||
** Dumps the contents of this PCB to the console
|
||||
**
|
||||
** @param msg[in] An optional message to print before the dump
|
||||
** @param p[in] The PCB to dump
|
||||
** @param all[in] Dump all the contents?
|
||||
*/
|
||||
void pcb_dump(const char *msg, register pcb_t *p, bool_t all);
|
||||
|
||||
/**
|
||||
** Name: pcb_queue_dump
|
||||
**
|
||||
** Dump the contents of the specified queue to the console
|
||||
**
|
||||
** @param msg[in] An optional message to print before the dump
|
||||
** @param queue[in] The queue to dump
|
||||
** @param contents[in] Also dump (some) contents?
|
||||
*/
|
||||
void pcb_queue_dump(const char *msg, pcb_queue_t queue, bool_t contents);
|
||||
|
||||
/**
|
||||
** Name: ptable_dump
|
||||
**
|
||||
** dump the contents of the "active processes" table
|
||||
**
|
||||
** @param msg[in] Optional message to print
|
||||
** @param all[in] Dump all or only part of the relevant data
|
||||
*/
|
||||
void ptable_dump(const char *msg, bool_t all);
|
||||
|
||||
/**
|
||||
** Name: ptable_dump_counts
|
||||
**
|
||||
** Prints basic information about the process table (number of
|
||||
** entries, number with each process state, etc.).
|
||||
*/
|
||||
void ptable_dump_counts(void);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
168
include/sio.h
168
include/sio.h
|
@ -1,168 +0,0 @@
|
|||
/**
|
||||
** @file sio.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief SIO definitions
|
||||
*/
|
||||
|
||||
#ifndef SIO_H_
|
||||
#define SIO_H_
|
||||
|
||||
// compatibility definitions
|
||||
#include <compat.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// sio interrupt settings
|
||||
|
||||
#define SIO_TX 0x01
|
||||
#define SIO_RX 0x02
|
||||
#define SIO_BOTH (SIO_TX | SIO_RX)
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <procs.h>
|
||||
|
||||
/*
|
||||
** PUBLIC GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
// queue for read-blocked processes
|
||||
extern QTYPE QNAME;
|
||||
|
||||
/*
|
||||
** PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/**
|
||||
** sio_init()
|
||||
**
|
||||
** Initialize the UART chip.
|
||||
*/
|
||||
void sio_init(void);
|
||||
|
||||
/**
|
||||
** sio_enable()
|
||||
**
|
||||
** Enable SIO interrupts
|
||||
**
|
||||
** usage: uint8_t old = sio_enable( uint8_t which )
|
||||
**
|
||||
** @param which Bit mask indicating which interrupt(s) to enable
|
||||
**
|
||||
** @return the prior IER setting
|
||||
*/
|
||||
uint8_t sio_enable(uint8_t which);
|
||||
|
||||
/**
|
||||
** sio_disable()
|
||||
**
|
||||
** Disable SIO interrupts
|
||||
**
|
||||
** usage: uint8_t old = sio_disable( uint8_t which )
|
||||
**
|
||||
** @param which Bit mask indicating which interrupt(s) to disable
|
||||
**
|
||||
** @return the prior IER setting
|
||||
*/
|
||||
uint8_t sio_disable(uint8_t which);
|
||||
|
||||
/**
|
||||
** sio_inq_length()
|
||||
**
|
||||
** Get the input queue length
|
||||
**
|
||||
** usage: int num = sio_inq_length()
|
||||
**
|
||||
** @return the count of characters still in the input queue
|
||||
*/
|
||||
int sio_inq_length(void);
|
||||
|
||||
/**
|
||||
** sio_readc()
|
||||
**
|
||||
** Get the next input character
|
||||
**
|
||||
** usage: int ch = sio_readc()
|
||||
**
|
||||
** @return the next character, or -1 if no character is available
|
||||
*/
|
||||
int sio_readc(void);
|
||||
|
||||
/**
|
||||
** sio_read()
|
||||
**
|
||||
** Read the entire input buffer into a user buffer of a specified size
|
||||
**
|
||||
** usage: int num = sio_read( char *buffer, int length )
|
||||
**
|
||||
** @param buf The destination buffer
|
||||
** @param length Length of the buffer
|
||||
**
|
||||
** @return the number of bytes copied, or 0 if no characters were available
|
||||
*/
|
||||
int sio_read(char *buffer, int length);
|
||||
|
||||
/**
|
||||
** sio_writec( ch )
|
||||
**
|
||||
** Write a character to the serial output
|
||||
**
|
||||
** usage: sio_writec( int ch )
|
||||
**
|
||||
** @param ch Character to be written (in the low-order 8 bits)
|
||||
*/
|
||||
void sio_writec(int ch);
|
||||
|
||||
/**
|
||||
** sio_write( ch )
|
||||
**
|
||||
** Write a buffer of characters to the serial output
|
||||
**
|
||||
** usage: int num = sio_write( const char *buffer, int length )
|
||||
**
|
||||
** @param buffer Buffer containing characters to write
|
||||
** @param length Number of characters to write
|
||||
**
|
||||
** @return the number of characters copied into the SIO output buffer
|
||||
*/
|
||||
int sio_write(const char *buffer, int length);
|
||||
|
||||
/**
|
||||
** sio_puts( buf )
|
||||
**
|
||||
** Write a NUL-terminated buffer of characters to the serial output
|
||||
**
|
||||
** usage: n = sio_puts( const char *buffer );
|
||||
**
|
||||
** @param buffer The buffer containing a NUL-terminated string
|
||||
**
|
||||
** @return the count of bytes transferred
|
||||
*/
|
||||
int sio_puts(const char *buffer);
|
||||
|
||||
/**
|
||||
** sio_dump( full )
|
||||
**
|
||||
** Dump the contents of the SIO buffers to the console
|
||||
**
|
||||
** usage: sio_dump(true) or sio_dump(false)
|
||||
**
|
||||
** @param full Boolean indicating whether or not a "full" dump
|
||||
** is being requested (which includes the contents
|
||||
** of the queues)
|
||||
*/
|
||||
void sio_dump(bool_t full);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
17
include/stdbool.h
Normal file
17
include/stdbool.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @file stdbool.h
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
* @author Warren R. Carithers
|
||||
*
|
||||
* Boolean definitions.
|
||||
*/
|
||||
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
// Boolean values
|
||||
typedef _Bool bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif /* stdbool.h */
|
16
include/stddef.h
Normal file
16
include/stddef.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @file stddef.h
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* Basic type definitions.
|
||||
*/
|
||||
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
typedef int size_t;
|
||||
typedef unsigned int usize_t;
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
#endif /* stddef.h */
|
27
include/stdint.h
Normal file
27
include/stdint.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @file stdint.h
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
* @author Warren R. Carithers
|
||||
*
|
||||
* Integer definitions.
|
||||
*/
|
||||
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
// standard integer sized types
|
||||
typedef char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
|
||||
// other integer types
|
||||
typedef unsigned char uchar_t;
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned long int ulong_t;
|
||||
|
||||
#endif /* stdint.h */
|
175
include/stdio.h
Normal file
175
include/stdio.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* @file stdio.h
|
||||
*
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* Standard I/O definitions.
|
||||
*/
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void FILE;
|
||||
|
||||
/// standard input
|
||||
#define stdin ((FILE *)1)
|
||||
/// standard output
|
||||
#define stdout ((FILE *)2)
|
||||
/// standard error
|
||||
#define stderr ((FILE *)3)
|
||||
|
||||
/// console output
|
||||
#define stdcon ((FILE *)4)
|
||||
/// serial output
|
||||
#define stduart ((FILE *)5)
|
||||
|
||||
/**
|
||||
* Prints out a char
|
||||
*
|
||||
* @param c - the char
|
||||
*/
|
||||
extern void putc(char c);
|
||||
|
||||
/**
|
||||
* Prints out a null terminated string
|
||||
*
|
||||
* @param s - the string
|
||||
*/
|
||||
extern void puts(const char *s);
|
||||
|
||||
/**
|
||||
* Prints out a char
|
||||
*
|
||||
* @param stream - stream to write to
|
||||
* @param c - the char
|
||||
*/
|
||||
extern void fputc(FILE *stream, char c);
|
||||
|
||||
/**
|
||||
* Prints out a null terminated string
|
||||
*
|
||||
* @param stream - stream to write to
|
||||
* @param s - the string
|
||||
*/
|
||||
extern void fputs(FILE *stream, const char *s);
|
||||
|
||||
/**
|
||||
* prints out a formatted string
|
||||
*
|
||||
* @param format - the format string
|
||||
* @param ... - variable args for the format
|
||||
*/
|
||||
__attribute__((format(printf, 1, 2))) extern void printf(const char *format,
|
||||
...);
|
||||
|
||||
/**
|
||||
* prints out a formatted string to a buffer
|
||||
*
|
||||
* @param s - the string to write to
|
||||
* @param format - the format string
|
||||
* @param ... - variable args for the format
|
||||
* @returns number of bytes written
|
||||
*/
|
||||
__attribute__((format(printf, 2, 3))) extern size_t
|
||||
sprintf(char *restrict s, const char *format, ...);
|
||||
|
||||
/**
|
||||
* prints out a formatted string to a buffer with a given max length
|
||||
*
|
||||
* @param s - the string to write to
|
||||
* @param maxlen - the max len of the buffer
|
||||
* @param format - the format string
|
||||
* @param ... - variable args for the format
|
||||
* @returns number of bytes written
|
||||
*/
|
||||
__attribute__((format(printf, 3, 4))) extern size_t
|
||||
snprintf(char *restrict s, size_t maxlen, const char *format, ...);
|
||||
|
||||
/**
|
||||
* prints out a formatted string
|
||||
*
|
||||
* @param format - the format string
|
||||
* @param args - variable arg list for the format
|
||||
*/
|
||||
extern void vprintf(const char *format, va_list args);
|
||||
|
||||
/**
|
||||
* prints out a formatted string to a buffer
|
||||
*
|
||||
* @param s - the string to write to
|
||||
* @param format - the format string
|
||||
* @param args - variable arg list for the format
|
||||
* @returns number of bytes written
|
||||
*/
|
||||
extern size_t vsprintf(char *restrict s, const char *format, va_list args);
|
||||
|
||||
/**
|
||||
* prints out a formatted string to a buffer with a given max length
|
||||
*
|
||||
* @param s - the string to write to
|
||||
* @param maxlen - the max len of the buffer
|
||||
* @param format - the format string
|
||||
* @param args - variable arg list for the format
|
||||
* @returns number of bytes written
|
||||
*/
|
||||
extern size_t vsnprintf(char *restrict s, size_t maxlen, const char *format,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* prints out a formatted string
|
||||
*
|
||||
* @param stream - the opened stream to print to
|
||||
* @param format - the format string
|
||||
* @param ... - variable args for the format
|
||||
*/
|
||||
__attribute__((format(printf, 2, 3))) extern void
|
||||
fprintf(FILE *stream, const char *format, ...);
|
||||
|
||||
/**
|
||||
* prints out a formatted string
|
||||
*
|
||||
* @param stream - the opened stream to print to
|
||||
* @param format - the format string
|
||||
* @param args - variable arg list for the format
|
||||
*/
|
||||
extern void vfprintf(FILE *stream, const char *format, va_list args);
|
||||
|
||||
/**
|
||||
* opens a file with a given file name
|
||||
*
|
||||
* @param filename - the name of the file to open
|
||||
* @returns the file pointer of success, NULL on error
|
||||
*/
|
||||
extern FILE *fopen(const char *filename);
|
||||
|
||||
/**
|
||||
* closes a opened file
|
||||
*
|
||||
* @param stream - the opened file stream
|
||||
*/
|
||||
extern void fclose(FILE *stream);
|
||||
|
||||
/**
|
||||
* reads data from a file into a pointer
|
||||
* @param ptr - the buffer to write into
|
||||
* @param size - the size of the block to read
|
||||
* @param n - the count of blocks to read
|
||||
* @param stream - the file stream to read from
|
||||
* @returns the number of blocks read
|
||||
*/
|
||||
extern size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
|
||||
|
||||
/**
|
||||
* writes data from a pointer into a file
|
||||
* @param ptr - the buffer to read from
|
||||
* @param size - the size of the block to write
|
||||
* @param n - the count of blocks to write
|
||||
* @param stream - the file stream to write into
|
||||
* @returns the number of blocks written
|
||||
*/
|
||||
extern size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);
|
||||
|
||||
#endif /* stdio.h */
|
197
include/stdlib.h
Normal file
197
include/stdlib.h
Normal file
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* @file stdlib.h
|
||||
*
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* Standard libaray functions
|
||||
*/
|
||||
|
||||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* converts single digit int to base 36
|
||||
* @param i - int
|
||||
* @returns c - base 36 char
|
||||
*/
|
||||
extern char itoc(int i);
|
||||
|
||||
/**
|
||||
* converts single base 36 chat into int
|
||||
* @param c - base 36 char
|
||||
* @returns i - int, or -1 if the char was invalid
|
||||
*/
|
||||
extern int ctoi(char c);
|
||||
|
||||
/**
|
||||
* Converts the initial portiion of the string pointed to by s to int.
|
||||
* @param s - the string to convert
|
||||
* @returns the number inside s or 0 on error
|
||||
*/
|
||||
extern int atoi(const char *s);
|
||||
|
||||
/**
|
||||
* Converts the initial portiion of the string pointed to by s to long.
|
||||
* @param s - the string to convert
|
||||
* @returns the number inside s or 0 on error
|
||||
*/
|
||||
extern long int atol(const char *s);
|
||||
|
||||
/**
|
||||
* Converts the initial portiion of the string pointed to by s to long long.
|
||||
* @param s - the string to convert
|
||||
* @returns the number inside s or 0 on error
|
||||
*/
|
||||
extern long long int atoll(const char *s);
|
||||
|
||||
/**
|
||||
* Converts a integer to asci inside a string with a given radix (base).
|
||||
* @param n - the number to convert
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *itoa(int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts a long to asci inside a string with a given radix (base).
|
||||
* @param n - the number to convert
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *ltoa(long int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts a long long to asci inside a string with a given radix (base).
|
||||
* @param n - the number to conver
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *lltoa(long long int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts a unsigned integer to asci inside a string with a given radix (base).
|
||||
* @param n - the number to convert
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *utoa(unsigned int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts a unsigned long to asci inside a string with a given radix (base).
|
||||
* @param n - the number to convert
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *ultoa(unsigned long int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts a unsigned long long to asci inside a string with a given radix (base).
|
||||
* @param n - the number to conver
|
||||
* @param buffer - the string buffer
|
||||
* @param radix - the base to convert
|
||||
*/
|
||||
extern char *ulltoa(unsigned long long int n, char *buffer, int radix);
|
||||
|
||||
/**
|
||||
* Converts the string in str to an int value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern int strtoi(const char *str, char **endptr, int base);
|
||||
|
||||
/**
|
||||
* Converts the string in str to a long value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern long int strtol(const char *str, char **endptr, int base);
|
||||
|
||||
/**
|
||||
* Converts the string in str to a long long value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern long long int strtoll(const char *str, char **endptr, int base);
|
||||
|
||||
/**
|
||||
* Converts the string in str to an unsigned int value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern unsigned int strtoui(const char *str, char **endptr, int base);
|
||||
|
||||
/**
|
||||
* Converts the string in str to an unsigned long value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern unsigned long int strtoul(const char *str, char **endptr, int base);
|
||||
|
||||
/**
|
||||
* Converts the string in str to an unsigned long long value based on the given base.
|
||||
* The endptr is updated to where the string was no longer valid.
|
||||
* @param str - the string buffer
|
||||
* @param endptr - the endptr
|
||||
* @param base - the base to convert to
|
||||
* @returns 0 on error or success, error if endptr is still equal to str
|
||||
*/
|
||||
extern unsigned long long int strtoull(const char *str, char **endptr,
|
||||
int base);
|
||||
|
||||
/**
|
||||
* Converts a byte count to a human readable file size of at most four characters
|
||||
* using binary suffixes.
|
||||
*
|
||||
* The following rules are applied:
|
||||
* - If the byte count is less than 1024, the count is written in decimal
|
||||
* and no suffix is applied
|
||||
* - Otherwise, repeatedly divide by 1024 until the value is under 1000.
|
||||
* - If the value has two or three decimal digits, print it followed by the
|
||||
* approprate suffix.
|
||||
* - If the value has one decimal digit, print it along with a single fractional
|
||||
* digit. This also applies if the value is zero.
|
||||
*
|
||||
* @param bytes - the bytes to convert
|
||||
* @param buf - a pointer to the buffer to store it in (which must be at least five
|
||||
* bytes long)
|
||||
* @returns - buf
|
||||
*/
|
||||
extern char *btoa(size_t bytes, char *buf);
|
||||
|
||||
/**
|
||||
* This function confines an argument within specified bounds.
|
||||
*
|
||||
* @param min - lower bound
|
||||
* @param value - value to be constrained
|
||||
* @param max - upper bound
|
||||
*
|
||||
* @returns the constrained value
|
||||
*/
|
||||
extern unsigned int bound(unsigned int min, unsigned int value,
|
||||
unsigned int max);
|
||||
|
||||
/**
|
||||
* Delays the current process by spining the cpu
|
||||
*
|
||||
* @param count how longish to spin
|
||||
*/
|
||||
extern void delay(int count);
|
||||
|
||||
#endif /* stlib.h */
|
122
include/string.h
Normal file
122
include/string.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* @file string.h
|
||||
*
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
*
|
||||
* String libaray functions
|
||||
*/
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Compare the first n bytes (interpreted as unsigned char) of the memory areas s1 and s2
|
||||
* @param s1 - the first memory area
|
||||
* @param s2 - the second memory area
|
||||
* @param n - the byte count
|
||||
* @returns an interger less than, equal to, or greater than 0 if the first n bytes
|
||||
* of s1 are less than, equal to, or greater than s2.
|
||||
*/
|
||||
extern int memcmp(const void *restrict s1, const void *restrict s2, size_t n);
|
||||
|
||||
/**
|
||||
* Copy the first n bytes from memory area src to memory area dest. The memory
|
||||
* areas must not overlap.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @param n - the byte count
|
||||
* @returns a pointer to dest
|
||||
*/
|
||||
extern void *memcpy(void *restrict dest, const void *restrict src, size_t n);
|
||||
|
||||
/**
|
||||
* Copy the first n bytes from memory area src to memory area dest. The memory
|
||||
* areas may overlap; memmove behaves as though the bytes are first copied to a
|
||||
* temporary array.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @param n - the byte count
|
||||
* @returns a pointer to dest
|
||||
*/
|
||||
extern void *memmove(void *restrict dest, const void *restrict src, size_t n);
|
||||
|
||||
/**
|
||||
* Fill the first n bytes of the memory region dest with the constant byte c.
|
||||
* @param dest - the destination
|
||||
* @param c - the byte to write
|
||||
* @param n - the byte count
|
||||
* @returns a pointer to dest
|
||||
*/
|
||||
extern void *memset(void *restrict dest, int c, size_t n);
|
||||
|
||||
/**
|
||||
* Calculates the length of the string pointed to by str, excluding
|
||||
* the terminating null byte
|
||||
* @param str - the string pointer
|
||||
* @returns the length of the string in bytes
|
||||
*/
|
||||
extern size_t strlen(const char *str);
|
||||
|
||||
/**
|
||||
* Compare null terminated string s1 and s2. The comparison is done using
|
||||
* unsigned characters.
|
||||
* @param s1 - a pointer to the first string
|
||||
* @param s2 - a pointer to the second string
|
||||
* @returns an interger less than, equal to, or greater than 0 if s1 compares less
|
||||
* than, equal to, or greater than s2
|
||||
*/
|
||||
extern int strcmp(const char *restrict s1, const char *restrict s2, size_t n);
|
||||
|
||||
/**
|
||||
* Compare at most the first n bytes of the strings s1 and s2. The comparison is
|
||||
* done using unsigned characters.
|
||||
* @param s1 - a pointer to the first string
|
||||
* @param s2 - a pointer to the second string
|
||||
* @param n - the maximum number of bytes
|
||||
* @returns an interger less than, equal to, or greater than 0 if s1 compares less
|
||||
* than, equal to, or greater than s2
|
||||
*/
|
||||
extern int strncmp(const char *restrict s1, const char *restrict s2, size_t n);
|
||||
|
||||
/**
|
||||
* Copies the string pointed to by src into the buffer pointer to by dest.
|
||||
* The dest buffer must be long enough to hold src.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @returns a pointer to dest
|
||||
*/
|
||||
extern char *strcpy(char *restrict dest, const char *restrict src);
|
||||
|
||||
/**
|
||||
* Copies the string pointed to by src into the buffer pointer to by dest.
|
||||
* The dest buffer must be long enough to hold src or size n.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @param n - the maximum number of bytes
|
||||
* @returns a pointer to dest
|
||||
*/
|
||||
extern char *strncpy(char *restrict dest, const char *restrict src, size_t n);
|
||||
|
||||
/**
|
||||
* Copies the string pointed to by src into the buffer pointed to by dest.
|
||||
* The dest buffer must be long enough to hold src.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @param n - the maximum number of bytes
|
||||
* @returns a pointer to the terminating null byte
|
||||
*/
|
||||
extern char *stpcpy(char *restrict dest, const char *restrict src);
|
||||
|
||||
/**
|
||||
* Copies the string pointed to by src into the buffer pointed to by dest.
|
||||
* The dest buffer must be long enough to hold src or size n.
|
||||
* @param dest - the destination
|
||||
* @param src - the source
|
||||
* @param n - the maximum number of bytes
|
||||
* @returns a pointer to the byte after the last character copied
|
||||
*/
|
||||
extern char *stpncpy(char *restrict dest, const char *restrict src, size_t n);
|
||||
|
||||
#endif /* string.h */
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
** SCCS ID: @(#)support.h 2.3 1/22/25
|
||||
**
|
||||
** @file support.h
|
||||
**
|
||||
** @author K. Reek
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** Declarations for functions provided in support.c, and
|
||||
** some hardware characteristics needed in the initialization.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef SUPPORT_H
|
||||
#define SUPPORT_H
|
||||
|
||||
/*
|
||||
** Delay values
|
||||
**
|
||||
** Notes: The parameter to the delay() function is ambiguous; it
|
||||
** purports to indicate a delay length, but that isn't really tied
|
||||
** to any real-world time measurement.
|
||||
**
|
||||
** On the original systems we used (dual 500MHz Intel P3 CPUs), each
|
||||
** "unit" was approximately one tenth of a second, so delay(10) would
|
||||
** delay for about one second.
|
||||
**
|
||||
** On the current machines (Intel Core i5-7500), delay(100) is about
|
||||
** 2.5 seconds, so each "unit" is roughly 0.025 seconds.
|
||||
**
|
||||
** Ultimately, just remember that THESE VALUES ARE APPROXIMATE AT BEST.
|
||||
*/
|
||||
#define DELAY_1_SEC 40
|
||||
#define DELAY_1_25_SEC 50
|
||||
#define DELAY_2_SEC 80
|
||||
#define DELAY_2_5_SEC 100
|
||||
#define DELAY_3_SEC 120
|
||||
#define DELAY_5_SEC 200
|
||||
#define DELAY_7_SEC 280
|
||||
#define DELAY_10_SEC 400
|
||||
|
||||
#ifndef ASM_SRC
|
||||
/**
|
||||
** panic
|
||||
**
|
||||
** Called when we find an unrecoverable error, this routine disables
|
||||
** interrupts, prints a description of the error and then goes into a
|
||||
** hard loop to prevent any further processing.
|
||||
**
|
||||
** @param reason NUL-terminated message to be printed.
|
||||
*/
|
||||
void panic(char *reason);
|
||||
|
||||
/**
|
||||
** init_interrupts
|
||||
**
|
||||
** (Re)initilizes the interrupt system. This includes initializing the
|
||||
** IDT and the PIC. It is up to the user to enable processor interrupts
|
||||
** when they're ready.
|
||||
*/
|
||||
void init_interrupts(void);
|
||||
|
||||
/*
|
||||
** install_isr
|
||||
**
|
||||
** Installs a second-level handler for a specific interrupt. Returns the
|
||||
** previously-installed handler for reinstallation (if desired).
|
||||
**
|
||||
** @param vector the interrupt vector number
|
||||
** @param handler the second-stage ISR function to be called by the stub
|
||||
**
|
||||
** @return a pointer to the previously-registered ISR
|
||||
*/
|
||||
void (*install_isr(int vector, void (*handler)(int, int)))(int, int);
|
||||
|
||||
/*
|
||||
** Name: delay
|
||||
**
|
||||
** See the comment above about the relative accuracy of the 'length'
|
||||
** parameter.
|
||||
*/
|
||||
void delay(int length);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
** @file syscalls.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief System call declarations
|
||||
*/
|
||||
|
||||
#ifndef SYSCALLS_H_
|
||||
#define SYSCALLS_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** system call codes
|
||||
**
|
||||
** these are used in the user-level C library stub functions,
|
||||
** and are defined here as CPP macros instead of as an enum
|
||||
** so that they can be used from assembly
|
||||
*/
|
||||
|
||||
#define SYS_exit 0
|
||||
#define SYS_waitpid 1
|
||||
#define SYS_fork 2
|
||||
#define SYS_exec 3
|
||||
#define SYS_read 4
|
||||
#define SYS_write 5
|
||||
#define SYS_getpid 6
|
||||
#define SYS_getppid 7
|
||||
#define SYS_gettime 8
|
||||
#define SYS_getprio 9
|
||||
#define SYS_setprio 10
|
||||
#define SYS_kill 11
|
||||
#define SYS_sleep 12
|
||||
|
||||
// UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED!
|
||||
#define N_SYSCALLS 13
|
||||
|
||||
// dummy system call code for testing our ISR
|
||||
#define SYS_bogus 0xbad
|
||||
|
||||
// interrupt vector entry for system calls
|
||||
#define VEC_SYSCALL 0x80
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
#ifdef KERNEL_SRC
|
||||
|
||||
/**
|
||||
** Name: sys_init
|
||||
**
|
||||
** Syscall module initialization routine
|
||||
*/
|
||||
void sys_init(void);
|
||||
|
||||
#endif /* KERNEL_SRC */
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
** @file types.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Common type declarations.
|
||||
**
|
||||
** This header file contains type declarations used throughout
|
||||
** the kernel and user code.
|
||||
*/
|
||||
|
||||
#ifndef TYPES_H_
|
||||
#define TYPES_H_
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
**
|
||||
** Anything that should not be visible to something other than
|
||||
** the C compiler should be put here.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
// standard integer sized types
|
||||
typedef char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
|
||||
// other integer types
|
||||
typedef unsigned char uchar_t;
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned long int ulong_t;
|
||||
|
||||
// Boolean values
|
||||
typedef uint8_t bool_t;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifdef KERNEL_SRC
|
||||
// we define these here instead of in vm.h in order to get around a
|
||||
// nasty chick/egg dependency between procs.h and vm.h
|
||||
typedef uint32_t pde_t; // page directory entry
|
||||
typedef uint32_t pte_t; // page table entry
|
||||
#endif /* KERNEL_SRC */
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
115
include/udefs.h
115
include/udefs.h
|
@ -1,115 +0,0 @@
|
|||
/**
|
||||
** @file udefs.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief "Userland" configuration information
|
||||
*/
|
||||
|
||||
#ifndef UDEFS_H_
|
||||
#define UDEFS_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
**
|
||||
** This section of the header file contains definitions that can be
|
||||
** used in either C or assembly-language source code.
|
||||
*/
|
||||
|
||||
// delay loop counts
|
||||
|
||||
#define DELAY_LONG 100000000
|
||||
#define DELAY_MED 4500000
|
||||
#define DELAY_SHORT 2500000
|
||||
|
||||
#define DELAY_STD DELAY_SHORT
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
// convenience macros
|
||||
|
||||
// a delay loop - kind of ugly, but it works
|
||||
|
||||
#define DELAY(n) \
|
||||
do { \
|
||||
for (int _dlc = 0; _dlc < (DELAY_##n); ++_dlc) \
|
||||
continue; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
** We need the list of program IDs so that we can request
|
||||
** their execution
|
||||
*/
|
||||
|
||||
#include <userids.h>
|
||||
|
||||
/*
|
||||
** All user main() functions have the following prototype:
|
||||
**
|
||||
** int name( int argc, char *argv[] );
|
||||
**
|
||||
** To simplify declaring them, we define a macro that expands into
|
||||
** that header. This can be used both in the implementation (followed
|
||||
** by the function body) and in places where we just need the prototype
|
||||
** (following it with a semicolon).
|
||||
*/
|
||||
|
||||
#define USERMAIN(f) int f(int argc, char *argv[])
|
||||
|
||||
/*
|
||||
** User process controls.
|
||||
**
|
||||
** To enable a specific test, define the symbol SPAWN_name here, and
|
||||
** guard the places in other code that use or refer to that test. For
|
||||
** example, test 'A' is enabled by definining SPAWN_A here, and all
|
||||
** places that refer to test 'A' are guarded with:
|
||||
**
|
||||
** #ifdef SPAWN_A
|
||||
** ... conditionally-compiled code
|
||||
** #endif
|
||||
**
|
||||
** Generally, most of these will exit with a status of 0. If a process
|
||||
** returns from its main function when it shouldn't (e.g., if it had
|
||||
** called exit() but continued to run), it will usually return a status
|
||||
** of ?.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The standard set of test programs, start by the shell (which is started
|
||||
** automatically from the initial user process)
|
||||
**
|
||||
** There is no user 'O' program, and programs 'W' through 'Z' are spawned
|
||||
** from other processes and are never spawned directly.
|
||||
*/
|
||||
|
||||
#define SPAWN_A
|
||||
#define SPAWN_B
|
||||
#define SPAWN_C
|
||||
#define SPAWN_D
|
||||
#define SPAWN_E
|
||||
#define SPAWN_F
|
||||
#define SPAWN_G
|
||||
#define SPAWN_H
|
||||
#define SPAWN_I
|
||||
#define SPAWN_J
|
||||
#define SPAWN_K
|
||||
#define SPAWN_L
|
||||
#define SPAWN_M
|
||||
#define SPAWN_N
|
||||
#define SPAWN_P
|
||||
#define SPAWN_Q
|
||||
#define SPAWN_R
|
||||
#define SPAWN_S
|
||||
#define SPAWN_T
|
||||
#define SPAWN_U
|
||||
#define SPAWN_V
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
315
include/ulib.h
315
include/ulib.h
|
@ -1,315 +0,0 @@
|
|||
/**
|
||||
** @file ulib.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Declarations for user-level library functions
|
||||
**
|
||||
** This module implements a simple collection of support functions
|
||||
** similar to the standard C library.
|
||||
*/
|
||||
|
||||
#ifndef ULIB_H_
|
||||
#define ULIB_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
** SYSTEM CALLS *********************************
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** exit - terminate the calling process
|
||||
**
|
||||
** usage: exit(status);
|
||||
**
|
||||
** @param status Termination status of this process
|
||||
**
|
||||
** Does not return.
|
||||
*/
|
||||
void exit(int32_t status);
|
||||
|
||||
/**
|
||||
** waitpid - wait for a child process to terminate
|
||||
**
|
||||
** usage: pid = waitpid(pid,&status);
|
||||
**
|
||||
** @param pid PID of the desired child, or 0 for any child
|
||||
** @param status Pointer to int32_t into which the child's status is placed,
|
||||
** or NULL
|
||||
**
|
||||
** @return The PID of the terminated child, or an error code
|
||||
**
|
||||
** If there are no children in the system, returns an error code (*status
|
||||
** is unchanged).
|
||||
**
|
||||
** If there are one or more children in the system and at least one has
|
||||
** terminated but hasn't yet been cleaned up, cleans up that process and
|
||||
** returns its information; otherwise, blocks until a child terminates.
|
||||
*/
|
||||
int waitpid(uint_t pid, int32_t *status);
|
||||
|
||||
/**
|
||||
** fork - create a duplicate of the calling process
|
||||
**
|
||||
** usage: pid = fork();
|
||||
**
|
||||
** @return parent - the pid of the new child, or an error code
|
||||
** child - 0
|
||||
*/
|
||||
int fork(void);
|
||||
|
||||
/**
|
||||
** exec - replace the memory image of the calling process
|
||||
**
|
||||
** usage: exec( what, args )
|
||||
**
|
||||
** @param what program table index of the program to exec
|
||||
** @param args the command-line argument vector
|
||||
**
|
||||
** Does not return if it succeeds; if it returns, something has
|
||||
** gone wrong.
|
||||
*/
|
||||
void exec(uint_t what, char **args);
|
||||
|
||||
/**
|
||||
** read - read into a buffer from a stream
|
||||
**
|
||||
** usage: n = read(channel,buf,length)
|
||||
**
|
||||
** @param chan I/O stream to read from
|
||||
** @param buf Buffer to read into
|
||||
** @param length Maximum capacity of the buffer
|
||||
**
|
||||
** @return The count of bytes transferred, or an error code
|
||||
*/
|
||||
int read(uint_t chan, void *buffer, uint_t length);
|
||||
|
||||
/**
|
||||
** write - write from a buffer to a stream
|
||||
**
|
||||
** usage: n = write(channel,buf,length)
|
||||
**
|
||||
** @param chan I/O stream to write to
|
||||
** @param buf Buffer to write from
|
||||
** @param length Maximum capacity of the buffer
|
||||
**
|
||||
** @return The count of bytes transferred, or an error code
|
||||
*/
|
||||
int write(uint_t chan, const void *buffer, uint_t length);
|
||||
|
||||
/**
|
||||
** getpid - get the PID of the calling process
|
||||
**
|
||||
** usage: pid = getpid()
|
||||
**
|
||||
** @return the PID of this process
|
||||
*/
|
||||
uint_t getpid(void);
|
||||
|
||||
/**
|
||||
** getppid - get the PID of the calling process' parent
|
||||
**
|
||||
** usage: pid = getppid()
|
||||
**
|
||||
** @return the PID of this process' parent
|
||||
*/
|
||||
uint_t getppid(void);
|
||||
|
||||
/**
|
||||
** gettime - get the current system time
|
||||
**
|
||||
** usage: pid = gettime()
|
||||
**
|
||||
** @return the system time
|
||||
*/
|
||||
uint32_t gettime(void);
|
||||
|
||||
/**
|
||||
** getprio - get the scheduling priority of the calling process
|
||||
**
|
||||
** usage: prio = getprio()
|
||||
**
|
||||
** @return the process' priority
|
||||
*/
|
||||
int getprio(void);
|
||||
|
||||
/**
|
||||
** setprio - set the scheduling priority of the calling process
|
||||
**
|
||||
** usage: oldprio = setprio(newprio)
|
||||
**
|
||||
** @param new the desired new priority
|
||||
**
|
||||
** @return the old priority value
|
||||
*/
|
||||
int setprio(int new);
|
||||
|
||||
/**
|
||||
** kill - terminate a process with extreme prejudice
|
||||
**
|
||||
** usage: n = kill( pid )
|
||||
**
|
||||
** @param pid the intended victim
|
||||
**
|
||||
** @return 0 on success, else an error code
|
||||
*/
|
||||
int32_t kill(uint_t pid);
|
||||
|
||||
/**
|
||||
** sleep - put the current process to sleep for some length of time
|
||||
**
|
||||
** usage: sleep(n);
|
||||
**
|
||||
** @param ms Desired sleep time (in ms), or 0 to yield the CPU
|
||||
**
|
||||
** @return the time the process spent sleeping (in ms)
|
||||
*/
|
||||
int sleep(uint32_t ms);
|
||||
|
||||
/**
|
||||
** bogus - a nonexistent system call, to test our syscall ISR
|
||||
**
|
||||
** usage: bogus()
|
||||
**
|
||||
** Does not return.
|
||||
*/
|
||||
void bogus(void);
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
** CONVENIENT "SHORTHAND" VERSIONS OF SYSCALLS **
|
||||
*************************************************
|
||||
**
|
||||
** These are library functions that perform specific common
|
||||
** variants of system calls. This helps reduce the total number
|
||||
** of system calls, keeping our baseline OS as lean and mean
|
||||
** as we can make it. :-)
|
||||
*/
|
||||
|
||||
/**
|
||||
** wait - wait for any child to exit
|
||||
**
|
||||
** usage: pid = wait(&status)
|
||||
**
|
||||
** Calls waitpid(0,status)
|
||||
**
|
||||
** @param status Pointer to int32_t into which the child's status is placed,
|
||||
** or NULL
|
||||
**
|
||||
** @return The PID of the terminated child, or an error code
|
||||
*/
|
||||
int wait(int32_t *status);
|
||||
|
||||
/**
|
||||
** spawn - create a new process running a different program
|
||||
**
|
||||
** usage: n = spawn(what,args)
|
||||
**
|
||||
** Creates a new process and then execs 'what'
|
||||
**
|
||||
** @param what Program table index of the program to spawn
|
||||
** @param args The command-line argument vector for the process
|
||||
**
|
||||
** @return The PID of the child, or an error code
|
||||
*/
|
||||
int spawn(uint_t what, char **args);
|
||||
|
||||
/**
|
||||
** cwritech(ch) - write a single character to the console
|
||||
**
|
||||
** @param ch The character to write
|
||||
**
|
||||
** @return The return value from calling write()
|
||||
*/
|
||||
int cwritech(char ch);
|
||||
|
||||
/**
|
||||
** cwrites(str) - write a NUL-terminated string to the console
|
||||
**
|
||||
** @param str The string to write
|
||||
**
|
||||
*/
|
||||
int cwrites(const char *str);
|
||||
|
||||
/**
|
||||
** cwrite(buf,leng) - write a sized buffer to the console
|
||||
**
|
||||
** @param buf The buffer to write
|
||||
** @param leng The number of bytes to write
|
||||
**
|
||||
** @return The return value from calling write()
|
||||
*/
|
||||
int cwrite(const char *buf, uint32_t leng);
|
||||
|
||||
/**
|
||||
** swritech(ch) - write a single character to the SIO
|
||||
**
|
||||
** @param ch The character to write
|
||||
**
|
||||
** @return The return value from calling write()
|
||||
*/
|
||||
int swritech(char ch);
|
||||
|
||||
/**
|
||||
** swrites(str) - write a NUL-terminated string to the SIO
|
||||
**
|
||||
** @param str The string to write
|
||||
**
|
||||
** @return The return value from calling write()
|
||||
*/
|
||||
int swrites(const char *str);
|
||||
|
||||
/**
|
||||
** swrite(buf,leng) - write a sized buffer to the SIO
|
||||
**
|
||||
** @param buf The buffer to write
|
||||
** @param leng The number of bytes to write
|
||||
**
|
||||
** @return The return value from calling write()
|
||||
*/
|
||||
int swrite(const char *buf, uint32_t leng);
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
** MISCELLANEOUS USEFUL SUPPORT FUNCTIONS *******
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
** fake_exit()
|
||||
**
|
||||
** dummy "startup" function
|
||||
**
|
||||
** calls exit(%eax) - serves as the "return to" code for
|
||||
** main() functions, in case they don't call exit() themselves
|
||||
*/
|
||||
void fake_exit(void);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
182
include/unistd.h
Normal file
182
include/unistd.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* @file unistd.h
|
||||
* @author Freya Murphy <freya@freyacat.org>
|
||||
* @author Warren R. Carithers
|
||||
*
|
||||
* Universial system definitions for userspace.
|
||||
*/
|
||||
|
||||
#ifndef _UNISTD_H
|
||||
#define _UNISTD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* System Call Definitions */
|
||||
|
||||
typedef uint_t pid_t;
|
||||
|
||||
/**
|
||||
* Terminates the calling process and does not return.
|
||||
* @param status - the status code to exit with
|
||||
*/
|
||||
__attribute__((noreturn)) extern void exit(int32_t status);
|
||||
|
||||
/**
|
||||
* Sleeps current process until a child process terminates
|
||||
*
|
||||
* @param pid - pid of the desired child, or 0 for any child
|
||||
* @param status - Pointer to int32_t into which the child's status is placed,
|
||||
* or NULL
|
||||
*
|
||||
* @return The pid of the terminated child, or an error code
|
||||
*
|
||||
* If there are no children in the system, returns an error code (*status
|
||||
* is unchanged).
|
||||
*
|
||||
* If there are one or more children in the system and at least one has
|
||||
* terminated but hasn't yet been cleaned up, cleans up that process and
|
||||
* returns its information; otherwise, blocks until a child terminates.
|
||||
*/
|
||||
extern int waitpid(pid_t pid, int32_t *status);
|
||||
|
||||
/**
|
||||
* Create a duplicate of the calling process
|
||||
*
|
||||
* @return parent - the pid of the new child, or an error code
|
||||
* child - 0
|
||||
*/
|
||||
extern int fork(void);
|
||||
|
||||
/**
|
||||
* Replace the memory image of the calling process
|
||||
*
|
||||
* @param prog - program table index of the program to exec
|
||||
* @param args - the command-line argument vector
|
||||
*
|
||||
* Does not return if it succeeds; if it returns, something has
|
||||
* gone wrong.
|
||||
*/
|
||||
extern void exec(uint_t prog, char **args);
|
||||
|
||||
/**
|
||||
* Open a stream with a given filename
|
||||
*
|
||||
* @param filename - the name of the file to open
|
||||
* @return the file descriptior of the open file or a negative error code.
|
||||
* TODO: fmurphy implement
|
||||
*/
|
||||
extern int open(char *filename);
|
||||
|
||||
/**
|
||||
* Closes a stream with the given file descriptior
|
||||
* @param fd - the file descriptior of the open stream
|
||||
* TODO: fmurphy implement
|
||||
*/
|
||||
extern void close(int fd);
|
||||
|
||||
/**
|
||||
* Read into a buffer from a stream
|
||||
*
|
||||
* @param fd - file stream to read from
|
||||
* @param buf - buffer to read into
|
||||
* @param nbytes - maximum capacity of the buffer
|
||||
*
|
||||
* @return - The count of bytes transferred, or an error code
|
||||
* TODO: fmurphy FD
|
||||
*/
|
||||
extern int read(int fd, void *buffer, size_t nbytes);
|
||||
|
||||
/**
|
||||
* Write from a buffer to a stream
|
||||
*
|
||||
* @param fd - file stream to write to
|
||||
* @param buf - buffer to write from
|
||||
* @param nbytes - maximum capacity of the buffer
|
||||
*
|
||||
* @return - The count of bytes transferred, or an error code
|
||||
* TODO: fmurphy FD
|
||||
*/
|
||||
extern int write(int fd, const void *buffer, size_t nbytes);
|
||||
|
||||
/**
|
||||
* Gets the pid of the calling process
|
||||
*
|
||||
* @return the pid of this process
|
||||
*/
|
||||
extern pid_t getpid(void);
|
||||
|
||||
/**
|
||||
* Gets the parent pid of the current process
|
||||
*
|
||||
* @return the parent pid of the current process, or 0 if init
|
||||
*/
|
||||
extern pid_t getppid(void);
|
||||
|
||||
/**
|
||||
* Gets the current system time
|
||||
*
|
||||
* @return the system time
|
||||
* TODO: CHANGE TIME TO 64bits!!
|
||||
*/
|
||||
extern ulong_t gettime(void);
|
||||
|
||||
/**
|
||||
* Gets the scheduling priority of the calling process
|
||||
*
|
||||
* @return the process' priority
|
||||
*/
|
||||
extern uint_t getprio(void);
|
||||
|
||||
/**
|
||||
* Sets the scheduling priority of the calling process
|
||||
*
|
||||
* @param new - the desired new priority
|
||||
*
|
||||
* @return the old priority value
|
||||
*/
|
||||
extern uint_t setprio(uint_t new);
|
||||
|
||||
/**
|
||||
* Terminates a process
|
||||
*
|
||||
* @param pid - the pid of the process to kill
|
||||
*
|
||||
* @return 0 on success, else an error code
|
||||
*/
|
||||
extern int32_t kill(pid_t pid);
|
||||
|
||||
/**
|
||||
* Put the current process to sleep for some length of time
|
||||
*
|
||||
* @param ms - desired sleep time (in ms), or 0 to yield the CPU
|
||||
*
|
||||
* @return the time the process spent sleeping (in ms)
|
||||
*/
|
||||
extern int sleep(uint32_t ms);
|
||||
|
||||
/**
|
||||
* Wait for any child to exit
|
||||
*
|
||||
* @param status - Pointer to int32_t into which the child's status is placed,
|
||||
* or NULL
|
||||
*
|
||||
* @return The pid of the terminated child, or an error code
|
||||
*
|
||||
* Analogous to waitpid(0,status)
|
||||
*/
|
||||
extern int wait(int32_t *status);
|
||||
|
||||
/**
|
||||
* Spawn a new process running a different program
|
||||
*
|
||||
* @param prog - program table index of the program to spawn
|
||||
* @param args - the command-line argument vector for the process
|
||||
*
|
||||
* @return The pid of the child, or an error code
|
||||
*
|
||||
* Analogous to calling fork and exec
|
||||
*/
|
||||
extern int spawn(uint_t prog, char **args);
|
||||
|
||||
#endif /* unistd.h */
|
139
include/user.h
139
include/user.h
|
@ -1,139 +0,0 @@
|
|||
/**
|
||||
** @file user.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Declarations of user-level code management routines
|
||||
*/
|
||||
|
||||
#ifndef USER_H_
|
||||
#define USER_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <procs.h>
|
||||
#include <x86/arch.h>
|
||||
|
||||
// default value for EFLAGS in new processes
|
||||
#define DEFAULT_EFLAGS (EFL_MB1 | EFL_IF)
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Blob file organization
|
||||
**
|
||||
** The file begins with a four-byte magic number and a four-byte integer
|
||||
** indicating the number of ELF files contained in the blob. This is
|
||||
** followed by an array of 32-byte file table entries, and then the contents
|
||||
** of the ELF files in the order they appear in the program file table.
|
||||
**
|
||||
** Bytes Contents
|
||||
** ----- ----------------------------
|
||||
** 0 - 3 File magic number ("BLB\0")
|
||||
** 4 - 7 Number of ELF files in blob ("n")
|
||||
** 8 - n*32+8 Program file table
|
||||
** n*32+9 - ? ELF file contents
|
||||
**
|
||||
** Each program file table entry contains the following information:
|
||||
**
|
||||
** name File name (up to 19 characters long)
|
||||
** offset Byte offset to the ELF header for this file
|
||||
** size Size of this ELF file, in bytes
|
||||
** flags Flags related to this file
|
||||
*/
|
||||
|
||||
// user program blob header
|
||||
typedef struct header_s {
|
||||
char magic[4];
|
||||
uint32_t num;
|
||||
} header_t;
|
||||
|
||||
// length of the file name field
|
||||
#define NAMELEN 20
|
||||
|
||||
// program descriptor
|
||||
typedef struct prog_s {
|
||||
char name[NAMELEN]; // truncated name (15 chars)
|
||||
uint32_t offset; // offset from the beginning of the blob
|
||||
uint32_t size; // size of this ELF module
|
||||
uint32_t flags; // miscellaneous flags
|
||||
} prog_t;
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: user_init
|
||||
**
|
||||
** Initializes the user support module.
|
||||
*/
|
||||
void user_init(void);
|
||||
|
||||
/**
|
||||
** Name: user_locate
|
||||
**
|
||||
** Locates a user program in the user code archive.
|
||||
**
|
||||
** @param what The ID of the user program to find
|
||||
**
|
||||
** @return pointer to the program table entry in the code archive, or NULL
|
||||
*/
|
||||
prog_t *user_locate(uint_t what);
|
||||
|
||||
/**
|
||||
** Name: user_duplicate
|
||||
**
|
||||
** Duplicates the memory setup for an existing process.
|
||||
**
|
||||
** @param new The PCB for the new copy of the program
|
||||
** @param old The PCB for the existing the program
|
||||
**
|
||||
** @return the status of the duplicate attempt
|
||||
*/
|
||||
int user_duplicate(pcb_t *new, pcb_t *old);
|
||||
|
||||
/**
|
||||
** Name: user_load
|
||||
**
|
||||
** Loads a user program from the user code archive into memory.
|
||||
** Allocates all needed frames and sets up the VM tables.
|
||||
**
|
||||
** @param prog A pointer to the program table entry to be loaded
|
||||
** @param pcb The PCB for the program being loaded
|
||||
** @param args The argument vector for the program
|
||||
** @param sys Is the argument vector from kernel code?
|
||||
**
|
||||
** @return the status of the load attempt
|
||||
*/
|
||||
int user_load(prog_t *prog, pcb_t *pcb, const char **args, bool_t sys);
|
||||
|
||||
/**
|
||||
** Name: user_cleanup
|
||||
**
|
||||
** "Unloads" a user program. Deallocates all memory frames and
|
||||
** cleans up the VM structures.
|
||||
**
|
||||
** @param pcb The PCB of the program to be cleaned up
|
||||
*/
|
||||
void user_cleanup(pcb_t *pcb);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
** @file userids.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief IDs for user-level programs
|
||||
**
|
||||
** NOTE: this file is automatically generated when the user.img file
|
||||
** is created. Do not edit this manually!
|
||||
*/
|
||||
|
||||
#ifndef USERIDS_H_
|
||||
#define USERIDS_H_
|
||||
|
||||
#ifndef ASM_SRC
|
||||
/*
|
||||
** These IDs are used to identify the various user programs.
|
||||
** Each call to exec() will provide one of these as the first
|
||||
** argument.
|
||||
**
|
||||
** This list should be updated if/when the collection of
|
||||
** user processes changes.
|
||||
*/
|
||||
enum users_e {
|
||||
Init,
|
||||
Idle,
|
||||
Shell,
|
||||
ProgABC,
|
||||
ProgDE,
|
||||
ProgFG,
|
||||
ProgH,
|
||||
ProgI,
|
||||
ProgJ,
|
||||
ProgKL,
|
||||
ProgMN,
|
||||
ProgP,
|
||||
ProgQ,
|
||||
ProgR,
|
||||
ProgS,
|
||||
ProgTUV,
|
||||
ProgW,
|
||||
ProgX,
|
||||
ProgY,
|
||||
ProgZ
|
||||
// sentinel
|
||||
,
|
||||
N_USERS
|
||||
};
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
501
include/vm.h
501
include/vm.h
|
@ -1,501 +0,0 @@
|
|||
/**
|
||||
** @file vm.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Virtual memory-related declarations.
|
||||
*/
|
||||
|
||||
#ifndef VM_H_
|
||||
#define VM_H_
|
||||
|
||||
#include <defs.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <procs.h>
|
||||
|
||||
/*
|
||||
** VM layout of the system
|
||||
**
|
||||
** User processes use the first 4MB of the 32-bit address space; see the
|
||||
** next comment for details.
|
||||
**
|
||||
** Kernel virtual addresses are in the "higher half" range, beginning
|
||||
** at 0x80000000. We define our mapping such that virtual address
|
||||
** 0x8nnnnnnn maps to physical address 0x0nnnnnnn, so converting between
|
||||
** the two is trivial.
|
||||
*/
|
||||
|
||||
/*
|
||||
** VM layout of process' address space
|
||||
**
|
||||
** Processes are limited to the first 4MB of the 32-bit address space:
|
||||
**
|
||||
** Address Range Contents
|
||||
** ======================= ================================
|
||||
** 0x00000000 - 0x00000fff page 0 is inaccessible
|
||||
** 0x00001000 - 0x000..fff text occupies pages 1 - N
|
||||
** 0x000..000 - 0x000..fff data occupies pages N+1 - N+d
|
||||
** 0x000..000 - 0x000..fff bss occupies pages N+d+1 - N+d+b
|
||||
** 0x000..000 - 0x003fdfff unusable
|
||||
** 0x003fe000 - 0x003fffff stack occupies last two pages
|
||||
**
|
||||
** This gives us the following page table structure:
|
||||
**
|
||||
** Page directory:
|
||||
** Entries Contents
|
||||
** ======== ==============================
|
||||
** 0 point to PMT for address space
|
||||
** 1 - 1023 invalid
|
||||
**
|
||||
** Page map table:
|
||||
** Entries Contents
|
||||
** ======== ==============================
|
||||
** 0 invalid
|
||||
** 1 - N text frames
|
||||
** N+1 - N+d data frames
|
||||
** N+d+1 - N+d+b bss frames
|
||||
** N+d+b+1 - 1021 invalid
|
||||
** 1022 - 1023 stack frames
|
||||
*/
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
// user virtual addresses
|
||||
#define USER_BASE 0x00000000
|
||||
#define USER_MAX 0x003fffff
|
||||
#define USER_TEXT 0x00001000
|
||||
#define USER_STACK 0x003fe000
|
||||
#define USER_STACK_P1 USER_STACK
|
||||
#define USER_STACK_P2 0x003ff000
|
||||
#define USER_STK_END 0x00400000
|
||||
|
||||
// how to find the addresses of the stack pages in the VM hierarchy
|
||||
// user address space is the first 4MB of virtual memory
|
||||
#define USER_PDE 0
|
||||
// the stack occupies this range of pages in the user address space
|
||||
#define USER_STK_FIRST_PTE 1022
|
||||
#define USER_STK_LAST_PTE 1023
|
||||
|
||||
// some important memory addresses
|
||||
#define KERN_BASE 0x80000000 // start of "kernel" memory
|
||||
#define EXT_BASE 0x00100000 // start of "extended" memory (1MB)
|
||||
#define DEV_BASE 0xfe000000 // "device" memory
|
||||
#define PHYS_TOP 0x3fffffff // last usable physical address (1GB - 1)
|
||||
|
||||
// where the kernel actually lives
|
||||
#define KERN_PLINK 0x00010000
|
||||
#define KERN_VLINK (KERN_BASE + KERN_PLINK)
|
||||
|
||||
// number of entries in a page directory or page table
|
||||
#define N_PDE 1024
|
||||
#define N_PTE 1024
|
||||
|
||||
// index field shift counts and masks
|
||||
#define PDIX_SHIFT 22
|
||||
#define PTIX_SHIFT 12
|
||||
#define PIX2I_MASK 0x3ff
|
||||
|
||||
// physical/virtual converters that don't use casting
|
||||
// (usable from anywhere)
|
||||
#define V2PNC(a) ((a) - KERN_BASE)
|
||||
#define P2VNC(a) ((a) + KERN_BASE)
|
||||
|
||||
// page-size address rounding macros
|
||||
#define SZ_PG_M1 MOD4K_BITS
|
||||
#define SZ_PG_MASK MOD4K_MASK
|
||||
#define PGUP(a) (((a) + SZ_PG_M1) & SZ_PG_MASK)
|
||||
#define PGDOWN(a) ((a) & SZ_PG_MASK)
|
||||
|
||||
// page directory entry bit fields
|
||||
#define PDE_P 0x00000001 // 1 = present
|
||||
#define PDE_RW 0x00000002 // 1 = writable
|
||||
#define PDE_US 0x00000004 // 1 = user and system usable
|
||||
#define PDE_PWT 0x00000008 // cache: 1 = write-through
|
||||
#define PDE_PCD 0x00000010 // cache: 1 = disabled
|
||||
#define PDE_A 0x00000020 // accessed
|
||||
#define PDE_D 0x00000040 // dirty (4MB pages)
|
||||
#define PDE_AVL1 0x00000040 // ignored (4KB pages)
|
||||
#define PDE_PS 0x00000080 // 1 = 4MB page size
|
||||
#define PDE_G 0x00000100 // global
|
||||
#define PDE_AVL2 0x00000e00 // ignored
|
||||
#define PDE_PAT 0x00001000 // (4MB pages) use page attribute table
|
||||
#define PDE_PTA 0xfffff000 // page table address field (4KB pages)
|
||||
#define PDE_FA 0xffc00000 // frame address field (4MB pages)
|
||||
|
||||
// page table entry bit fields
|
||||
#define PTE_P 0x00000001 // present
|
||||
#define PTE_RW 0x00000002 // 1 = writable
|
||||
#define PTE_US 0x00000004 // 1 = user and system usable
|
||||
#define PTE_PWT 0x00000008 // cache: 1 = write-through
|
||||
#define PTE_PCD 0x00000010 // cache: 1 = disabled
|
||||
#define PTE_A 0x00000020 // accessed
|
||||
#define PTE_D 0x00000040 // dirty
|
||||
#define PTE_PAT 0x00000080 // use page attribute table
|
||||
#define PTE_G 0x00000100 // global
|
||||
#define PTE_AVL2 0x00000e00 // ignored
|
||||
#define PTE_FA 0xfffff000 // frame address field
|
||||
|
||||
// error code bit assignments for page faults
|
||||
#define PFLT_P 0x00000001
|
||||
#define PFLT_W 0x00000002
|
||||
#define PFLT_US 0x00000004
|
||||
#define PFLT_RSVD 0x00000008
|
||||
#define PFLT_ID 0x00000010
|
||||
#define PFLT_PK 0x00000020
|
||||
#define PFLT_SS 0x00000040
|
||||
#define PFLT_HLAT 0x00000080
|
||||
#define PFLT_SGX 0x00008000
|
||||
#define PFLT_UNUSED 0xffff7f00
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
// physical/virtual converters that do use casting
|
||||
// (not usable from assembly)
|
||||
#define V2P(a) (((uint32_t)(a)) - KERN_BASE)
|
||||
#define P2V(a) (((uint32_t)(a)) + KERN_BASE)
|
||||
|
||||
// create a pde/pte from an integer frame number and permission bits
|
||||
#define MKPDE(f, p) ((pde_t)(TO_FRAME((f)) | (p)))
|
||||
#define MKPTE(f, p) ((pte_t)(TO_FRAME((f)) | (p)))
|
||||
|
||||
// is a PDE/PTE present?
|
||||
// (P bit is in the same place in both)
|
||||
#define IS_PRESENT(entry) (((entry) & PDE_P) != 0)
|
||||
|
||||
// is a PDE a 4MB page entry?
|
||||
#define IS_LARGE(pde) (((pde) & PDE_PS) != 0)
|
||||
|
||||
// is this entry "system only" or "system and user"?
|
||||
#define IS_SYSTEM(entry) (((entry) & PDE_US) == 0)
|
||||
#define IS_USER(entry) (((entry) & PDE_US) != 0)
|
||||
|
||||
// low-order nine bits of PDEs and PTEs hold "permission" flag bits
|
||||
#define PERMS_MASK MOD4K_BITS
|
||||
|
||||
// 4KB frame numbers are 20 bits wide
|
||||
#define FRAME_4K_SHIFT 12
|
||||
#define FRAME2I_4K_MASK 0x000fffff
|
||||
#define TO_4KFRAME(n) (((n) & FRAME2I_4K_MASK) << FRAME_4K_SHIFT)
|
||||
#define GET_4KFRAME(n) (((n) >> FRAME_4K_SHIFT) & FRAME2I_4K_MASK)
|
||||
#define PDE_4K_ADDR(n) ((n) & MOD4K_MASK)
|
||||
#define PTE_4K_ADDR(n) ((n) & MOD4K_MASK)
|
||||
|
||||
// 4MB frame numbers are 10 bits wide
|
||||
#define FRAME_4M_SHIFT 22
|
||||
#define FRAME2I_4M_MASK 0x000003ff
|
||||
#define TO_4MFRAME(n) (((n) & FRAME2I_4M_MASK) << FRAME_4M_SHIFT)
|
||||
#define GET_4MFRAME(n) (((n) >> FRAME_4M_SHIFT) & FRAME2I_4M_MASK)
|
||||
#define PDE_4M_ADDR(n) ((n) & MOD4M_MASK)
|
||||
#define PTE_4M_ADDR(n) ((n) & MOD4M_MASK)
|
||||
|
||||
// extract the PMT address or frame address from a table entry
|
||||
// PDEs could point to 4MB pages, or 4KB PMTs
|
||||
#define PDE_ADDR(p) \
|
||||
(IS_LARGE(p) ? (((uint32_t)p) & PDE_FA) : (((uint32_t)p) & PDE_PTA))
|
||||
// PTEs always point to 4KB pages
|
||||
#define PTE_ADDR(p) (((uint32_t)(p)) & PTE_FA)
|
||||
// everything has nine bits of permission flags
|
||||
#define PERMS(p) (((uint32_t)(p)) & PERMS_MASK)
|
||||
|
||||
// extract the table indices from a 32-bit VA
|
||||
#define PDIX(v) ((((uint32_t)(v)) >> PDIX_SHIFT) & PIX2I_MASK)
|
||||
#define PTIX(v) ((((uint32_t)(v)) >> PTIX_SHIFT) & PIX2I_MASK)
|
||||
|
||||
// extract the byte offset from a 32-bit VA
|
||||
#define OFFSET_4K(v) (((uint32_t)(v)) & MOD4K_BITS)
|
||||
#define OFFSET_4M(v) (((uint32_t)(v)) & MOD4M_BITS)
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
// page directory entries
|
||||
|
||||
// as a 32-bit word, in types.h
|
||||
// typedef uint32_t pde_t;
|
||||
|
||||
// PDE for 4KB pages
|
||||
typedef struct pdek_s {
|
||||
uint_t p : 1; // 0: present
|
||||
uint_t rw : 1; // 1: writable
|
||||
uint_t us : 1; // 2: user/supervisor
|
||||
uint_t pwt : 1; // 3: cache write-through
|
||||
uint_t pcd : 1; // 4: cache disable
|
||||
uint_t a : 1; // 5: accessed
|
||||
uint_t avl1 : 1; // 6: ignored (available)
|
||||
uint_t ps : 1; // 7: page size (must be 0)
|
||||
uint_t avl2 : 4; // 11-8: ignored (available)
|
||||
uint_t fa : 20; // 31-12: frame address
|
||||
} pdek_f_t;
|
||||
|
||||
// PDE for 4MB pages
|
||||
typedef struct pdem_s {
|
||||
uint_t p : 1; // 0: present
|
||||
uint_t rw : 1; // 1: writable
|
||||
uint_t us : 1; // 2: user/supervisor
|
||||
uint_t pwt : 1; // 3: cache write-through
|
||||
uint_t pcd : 1; // 4: cache disable
|
||||
uint_t a : 1; // 5: accessed
|
||||
uint_t d : 1; // 6: dirty
|
||||
uint_t ps : 1; // 7: page size (must be 1)
|
||||
uint_t g : 1; // 8: global
|
||||
uint_t avl : 3; // 11-9: ignored (available)
|
||||
uint_t pat : 1; // 12: page attribute table in use
|
||||
uint_t fa2 : 4; // 16-13: bits 35-32 of frame address (36-bit addrs)
|
||||
uint_t rsv : 5; // 21-17: reserved - must be zero
|
||||
uint_t fa : 10; // 31-22: bits 31-22 of frame address
|
||||
} pdem_f_t;
|
||||
|
||||
// page table entries
|
||||
|
||||
// as a 32-bit word, in types.h
|
||||
// typedef uint32_t pte_t;
|
||||
|
||||
// broken out into fields
|
||||
typedef struct pte_s {
|
||||
uint_t p : 1; // 0: present
|
||||
uint_t rw : 1; // 1: writable
|
||||
uint_t us : 1; // 2: user/supervisor
|
||||
uint_t pwt : 1; // 3: cache write-through
|
||||
uint_t pcd : 1; // 4: cache disable
|
||||
uint_t a : 1; // 5: accessed
|
||||
uint_t d : 1; // 6: dirty
|
||||
uint_t pat : 1; // 7: page attribute table in use
|
||||
uint_t g : 1; // 8: global
|
||||
uint_t avl : 3; // 11-9: ignored (available)
|
||||
uint_t fa : 20; // 31-12: frame address
|
||||
} ptef_t;
|
||||
|
||||
// page fault error code bits
|
||||
// comment: meaning when 1 / meaning when 0
|
||||
struct pfec_s {
|
||||
uint_t p : 1; // page-level protection violation / !present
|
||||
uint_t w : 1; // write / read
|
||||
uint_t us : 1; // user-mode access / supervisor-mode access
|
||||
uint_t rsvd : 1; // reserved bit violation / not
|
||||
uint_t id : 1; // instruction fetch / data fetch
|
||||
uint_t pk : 1; // protection-key violation / !pk
|
||||
uint_t ss : 1; // shadow stack access / !ss
|
||||
uint_t hlat : 1; // HLAT paging / ordinary paging or access rights
|
||||
uint_t xtr1 : 7; // unused
|
||||
uint_t sgz : 1; // SGX-specific access control violation / !SGX
|
||||
uint_t xtr2 : 16; // more unused
|
||||
};
|
||||
|
||||
typedef union pfec_u {
|
||||
uint32_t u;
|
||||
struct pfec_s s;
|
||||
} pfec_t;
|
||||
|
||||
// Mapping descriptor for VA::PA mappings
|
||||
typedef struct mapping_t {
|
||||
uint32_t va_start; // starting virtual address for this range
|
||||
uint32_t pa_start; // first physical address in the range
|
||||
uint32_t pa_end; // last physical address in the range
|
||||
uint32_t perm; // access control
|
||||
} mapping_t;
|
||||
|
||||
// Modes for dumping out page hierarchies
|
||||
enum vmmode_e {
|
||||
Simple = 0, // just count 'present' entries at each level
|
||||
OneLevel, // top-level only: count entries, decode 'present'
|
||||
TwoLevel, // count entries & decode at each level
|
||||
Full // ??? in case we need more?
|
||||
// sentinel
|
||||
,
|
||||
N_VMMODES
|
||||
};
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
// created page directory for the kernel
|
||||
extern pde_t *kpdir;
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: vm_init
|
||||
**
|
||||
** Initialize the VM module
|
||||
**
|
||||
** Note: should not be called until after the memory free list has
|
||||
** been set up.
|
||||
*/
|
||||
void vm_init(void);
|
||||
|
||||
/**
|
||||
** Name: vm_uva2kva
|
||||
**
|
||||
** Convert a user VA into a kernel address. Works for all addresses -
|
||||
** if the address is a page address, the low-order nine bits will be
|
||||
** zeroes; otherwise, they is the offset into the page, which is
|
||||
** unchanged within the address spaces.
|
||||
**
|
||||
** @param pdir Pointer to the page directory to examine
|
||||
** @param va Virtual address to check
|
||||
*/
|
||||
void *vm_uva2kva(pde_t *pdir, void *va);
|
||||
|
||||
/**
|
||||
** Name: vm_pagedup
|
||||
**
|
||||
** Duplicate a page of memory
|
||||
**
|
||||
** @param old Pointer to the first byte of a page
|
||||
**
|
||||
** @return a pointer to the new, duplicate page, or NULL
|
||||
*/
|
||||
void *vm_pagedup(void *old);
|
||||
|
||||
/**
|
||||
** Name: vm_pdedup
|
||||
**
|
||||
** Duplicate a page directory entry
|
||||
**
|
||||
** @param entry The entry to be duplicated
|
||||
**
|
||||
** @return the new entry, or -1 on error.
|
||||
*/
|
||||
pde_t vm_pdedup(pde_t entry);
|
||||
|
||||
/**
|
||||
** Name: vm_ptdup
|
||||
**
|
||||
** Duplicate a page directory entry
|
||||
**
|
||||
** @param dst Pointer to where the duplicate should go
|
||||
** @param curr Pointer to the entry to be duplicated
|
||||
**
|
||||
** @return true on success, else false
|
||||
*/
|
||||
bool_t vm_ptdup(pde_t *dst, pde_t *curr);
|
||||
|
||||
/**
|
||||
** Name: vm_getpte
|
||||
**
|
||||
** Return the address of the PTE corresponding to the virtual address
|
||||
** 'va' within the address space controlled by 'pgdir'. If there is no
|
||||
** page table for that VA and 'alloc' is true, create the necessary
|
||||
** page table entries.
|
||||
**
|
||||
** @param pdir Pointer to the page directory to be searched
|
||||
** @param va The virtual address we're looking for
|
||||
** @param alloc Should we allocate a page table if there isn't one?
|
||||
**
|
||||
** @return A pointer to the page table entry for this VA, or NULL
|
||||
*/
|
||||
pte_t *vm_getpte(pde_t *pdir, const void *va, bool_t alloc);
|
||||
|
||||
/**
|
||||
** Name: vm_mkkvm
|
||||
**
|
||||
** Create the kernel's page table hierarchy
|
||||
*/
|
||||
pde_t *vm_mkkvm(void);
|
||||
|
||||
/**
|
||||
** Name: vm_mkuvm
|
||||
**
|
||||
** Create the page table hierarchy for a user process
|
||||
*/
|
||||
pde_t *vm_mkuvm(void);
|
||||
|
||||
/**
|
||||
** Name: vm_set_kvm
|
||||
**
|
||||
** Switch the page table register to the kernel's page directory
|
||||
*/
|
||||
void vm_set_kvm(void);
|
||||
|
||||
/**
|
||||
** Name: vm_set_uvm
|
||||
**
|
||||
** Switch the page table register to the page directory for a user process.
|
||||
**
|
||||
** @param p The PCB of the user process
|
||||
*/
|
||||
void vm_set_uvm(pcb_t *p);
|
||||
|
||||
/**
|
||||
** Name: vm_add
|
||||
**
|
||||
** Add pages to the page hierarchy for a process, copying data into
|
||||
** them if necessary.
|
||||
**
|
||||
** @param pdir Pointer to the page directory to modify
|
||||
** @param wr "Writable" flag for the PTE
|
||||
** @param sys "System" flag for the PTE
|
||||
** @param va Starting VA of the range
|
||||
** @param size Amount of physical memory to allocate
|
||||
** @param data Pointer to data to copy, or NULL
|
||||
** @param bytes Number of bytes to copy
|
||||
**
|
||||
** @return status of the allocation attempt
|
||||
*/
|
||||
int vm_add(pde_t *pdir, bool_t wr, bool_t sys, void *va, uint32_t size,
|
||||
char *data, uint32_t bytes);
|
||||
|
||||
/**
|
||||
** Name: vm_free
|
||||
**
|
||||
** Deallocate a page table hierarchy and all physical memory frames
|
||||
** in the user portion.
|
||||
**
|
||||
** @param pdir Pointer to the page directory
|
||||
*/
|
||||
void vm_free(pde_t *pdir);
|
||||
|
||||
/*
|
||||
** Name: vm_map
|
||||
**
|
||||
** Create PTEs for virtual addresses starting at 'va' that refer to
|
||||
** physical addresses in the range [pa, pa+size-1]. We aren't guaranteed
|
||||
** that va is page-aligned.
|
||||
**
|
||||
** @param pdir Page directory for this address space
|
||||
** @param va The starting virtual address
|
||||
** @param pa The starting physical address
|
||||
** @param size Length of the range to be mapped
|
||||
** @param perm Permission bits for the PTEs
|
||||
*/
|
||||
int vm_map(pde_t *pdir, void *va, uint32_t pa, uint32_t size, int perm);
|
||||
|
||||
/**
|
||||
** Name: vm_uvmdup
|
||||
**
|
||||
** Create a duplicate of the user portio of an existing page table
|
||||
** hierarchy. We assume that the "new" page directory exists and
|
||||
** the system portions of it should not be touched.
|
||||
**
|
||||
** @param new New page directory
|
||||
** @param old Existing page directory
|
||||
**
|
||||
** @return status of the duplication attempt
|
||||
*/
|
||||
int vm_uvmdup(pde_t *new, pde_t *old);
|
||||
|
||||
/**
|
||||
** Name: vm_print
|
||||
**
|
||||
** Print out a paging hierarchy.
|
||||
**
|
||||
** @param pt Page table to display
|
||||
** @param dir Is it a page directory (vs. a page table)?
|
||||
** @param mode How to display the entries
|
||||
*/
|
||||
void vm_print(void *pt, bool_t dir, enum vmmode_e mode);
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
** @file vmtables.h
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief Predefined VM tables
|
||||
*/
|
||||
|
||||
#ifndef VMTABLES_H_
|
||||
#define VMTABLES_H_
|
||||
|
||||
#include <defs.h>
|
||||
#include <types.h>
|
||||
#include <vm.h>
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Initial page directory, for when the kernel is starting up
|
||||
**
|
||||
** we use large (4MB) pages here to allow us to use a one-level
|
||||
** paging hierarchy; the kernel will create a new page table
|
||||
** hierarchy once memory is initialized
|
||||
*/
|
||||
extern pde_t firstpdir[];
|
||||
|
||||
/*
|
||||
** "Identity" page map table.
|
||||
**
|
||||
** This just maps the first 4MB of physical memory. It is initialized
|
||||
** in vm_init().
|
||||
*/
|
||||
extern pte_t id_map[];
|
||||
|
||||
/*
|
||||
** Kernel address mappings, present in every page table
|
||||
*/
|
||||
extern mapping_t kmap[];
|
||||
extern const uint32_t n_kmap;
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
** @file arch.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @author K. Reek
|
||||
**
|
||||
** Definitions of constants and macros for use
|
||||
** with the x86 architecture and registers.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef X86ARCH_H_
|
||||
#define X86ARCH_H_
|
||||
|
||||
/*
|
||||
** Video stuff
|
||||
*/
|
||||
#define VID_BASE_ADDR 0xB8000
|
||||
|
||||
/*
|
||||
** Memory management
|
||||
*/
|
||||
#define SEG_PRESENT 0x80
|
||||
#define SEG_PL_0 0x00
|
||||
#define SEG_PL_1 0x20
|
||||
#define SEG_PL_2 0x40
|
||||
#define SEG_PL_3 0x50
|
||||
#define SEG_SYSTEM 0x00
|
||||
#define SEG_NON_SYSTEM 0x10
|
||||
#define SEG_32BIT 0x04
|
||||
#define DESC_IGATE 0x06
|
||||
|
||||
/*
|
||||
** Exceptions
|
||||
*/
|
||||
#define N_EXCEPTIONS 256
|
||||
|
||||
/*
|
||||
** Bit definitions in registers
|
||||
**
|
||||
** See IA-32 Intel Architecture SW Dev. Manual, Volume 3: System
|
||||
** Programming Guide, page 2-8.
|
||||
*/
|
||||
/*
|
||||
** EFLAGS
|
||||
*/
|
||||
#define EFL_RSVD 0xffc00000 /* reserved */
|
||||
#define EFL_MB0 0x00008020 /* must be zero */
|
||||
#define EFL_MB1 0x00000002 /* must be 1 */
|
||||
|
||||
#define EFL_ID 0x00200000
|
||||
#define EFL_VIP 0x00100000
|
||||
#define EFL_VIF 0x00080000
|
||||
#define EFL_AC 0x00040000
|
||||
#define EFL_VM 0x00020000
|
||||
#define EFL_RF 0x00010000
|
||||
#define EFL_NT 0x00004000
|
||||
#define EFL_IOPL 0x00003000
|
||||
#define EFL_OF 0x00000800
|
||||
#define EFL_DF 0x00000400
|
||||
#define EFL_IF 0x00000200
|
||||
#define EFL_TF 0x00000100
|
||||
#define EFL_SF 0x00000080
|
||||
#define EFL_ZF 0x00000040
|
||||
#define EFL_AF 0x00000010
|
||||
#define EFL_PF 0x00000004
|
||||
#define EFL_CF 0x00000001
|
||||
|
||||
/*
|
||||
** CR0, CR1, CR2, CR3, CR4
|
||||
**
|
||||
** IA-32 V3, page 2-12.
|
||||
*/
|
||||
#define CR0_RSVD 0x1ffaffc0
|
||||
#define CR0_PG 0x80000000
|
||||
#define CR0_CD 0x40000000
|
||||
#define CR0_NW 0x20000000
|
||||
#define CR0_AM 0x00040000
|
||||
#define CR0_WP 0x00010000
|
||||
#define CR0_NE 0x00000020
|
||||
#define CR0_ET 0x00000010
|
||||
#define CR0_TS 0x00000008
|
||||
#define CR0_EM 0x00000004
|
||||
#define CR0_MP 0x00000002
|
||||
#define CR0_PE 0x00000001
|
||||
|
||||
#define CR1_RSVD 0xffffffff
|
||||
|
||||
#define CR2_RSVD 0x00000000
|
||||
#define CR2_PF_LIN_ADDR 0xffffffff
|
||||
|
||||
#define CR3_RSVD 0x00000fe7
|
||||
#define CR3_PD_BASE 0xfffff000
|
||||
#define CR3_PCD 0x00000010
|
||||
#define CR3_PWT 0x00000008
|
||||
|
||||
#define CR4_RSVD 0xfd001000
|
||||
#define CR4_UINT 0x02000000
|
||||
#define CR4_PKS 0x01000000
|
||||
#define CR4_CET 0x00800000
|
||||
#define CR4_PKE 0x00400000
|
||||
#define CR4_SMAP 0x00200000
|
||||
#define CR4_SMEP 0x00100000
|
||||
#define CR4_KL 0x00080000
|
||||
#define CR4_OSXS 0x00040000
|
||||
#define CR4_PCID 0x00020000
|
||||
#define CR4_FSGS 0x00010000
|
||||
#define CR4_SMXE 0x00004000
|
||||
#define CR4_VMXE 0x00002000
|
||||
#define CR4_LA57 0x00001000
|
||||
#define CR4_UMIP 0x00000800
|
||||
#define CR4_OSXMMEXCPT 0x00000400
|
||||
#define CR4_OSFXSR 0x00000200
|
||||
#define CR4_PCE 0x00000100
|
||||
#define CR4_PGE 0x00000080
|
||||
#define CR4_MCE 0x00000040
|
||||
#define CR4_PAE 0x00000020
|
||||
#define CR4_PSE 0x00000010
|
||||
#define CR4_DE 0x00000008
|
||||
#define CR4_TSD 0x00000004
|
||||
#define CR4_PVI 0x00000002
|
||||
#define CR4_VME 0x00000001
|
||||
|
||||
/*
|
||||
** PMode segment selector field masks
|
||||
**
|
||||
** IA-32 V3, page 3-8.
|
||||
*/
|
||||
#define SEG_SEL_IX_MASK 0xfff8
|
||||
#define SEG_SEL_TI_MASK 0x0004
|
||||
#define SEG_SEL_RPL_MASK 0x0003
|
||||
|
||||
/*
|
||||
** Segment descriptor bytes
|
||||
**
|
||||
** IA-32 V3, page 3-10.
|
||||
**
|
||||
** Bytes:
|
||||
** 0, 1: segment limit 15:0
|
||||
** 2, 3: base address 15:0
|
||||
** 4: base address 23:16
|
||||
** 7: base address 31:24
|
||||
*/
|
||||
/*
|
||||
** Byte 5: access control bits
|
||||
** 7: present
|
||||
** 6-5: DPL
|
||||
** 4: system/user
|
||||
** 3-0: type
|
||||
*/
|
||||
#define SEG_ACCESS_P_MASK 0x80
|
||||
#define SEG_PRESENT 0x80
|
||||
#define SEG_NOT_PRESENT 0x00
|
||||
|
||||
#define SEG_ACCESS_DPL_MASK 0x60
|
||||
#define SEG_DPL_0 0x00
|
||||
#define SEG_DPL_1 0x20
|
||||
#define SEG_DPL_2 0x40
|
||||
#define SEG_DPL_3 0x60
|
||||
|
||||
#define SEG_ACCESS_S_MASK 0x10
|
||||
#define SEG_SYSTEM 0x00
|
||||
#define SEG_NON_SYSTEM 0x10
|
||||
|
||||
#define SEG_TYPE_MASK 0x0f
|
||||
#define SEG_DATA_A_BIT 0x1
|
||||
#define SEG_DATA_W_BIT 0x2
|
||||
#define SEG_DATA_E_BIT 0x4
|
||||
#define SEG_CODE_A_BIT 0x1
|
||||
#define SEG_CODE_R_BIT 0x2
|
||||
#define SEG_CODE_C_BIT 0x4
|
||||
#define SEG_DATA_RO 0x0
|
||||
#define SEG_DATA_ROA 0x1
|
||||
#define SEG_DATA_RW 0x2
|
||||
#define SEG_DATA_RWA 0x3
|
||||
#define SEG_DATA_RO_XD 0x4
|
||||
#define SEG_DATA_RO_XDA 0x5
|
||||
#define SEG_DATA_RW_XW 0x6
|
||||
#define SEG_DATA_RW_XWA 0x7
|
||||
#define SEG_CODE_XO 0x8
|
||||
#define SEG_CODE_XOA 0x9
|
||||
#define SEG_CODE_XR 0xa
|
||||
#define SEG_CODE_XRA 0xb
|
||||
#define SEG_CODE_XO_C 0xc
|
||||
#define SEG_CODE_XO_CA 0xd
|
||||
#define SEG_CODE_XR_C 0xe
|
||||
#define SEG_CODE_XR_CA 0xf
|
||||
|
||||
/*
|
||||
** Byte 6: sizes
|
||||
** 7: granularity
|
||||
** 6: d/b
|
||||
** 5: long mode
|
||||
** 4: available!
|
||||
** 3-0: upper 4 bits of limit
|
||||
** 7: base address 31:24
|
||||
*/
|
||||
#define SEG_SIZE_G_MASK 0x80
|
||||
#define SEG_GRAN_BYTE 0x00
|
||||
#define SEG_GRAN_4KBYTE 0x80
|
||||
|
||||
#define SEG_SIZE_D_B_MASK 0x40
|
||||
#define SEG_DB_16BIT 0x00
|
||||
#define SEG_DB_32BIT 0x40
|
||||
|
||||
#define SEG_SIZE_L_MASK 0x20
|
||||
#define SEG_L_64BIT 0x20
|
||||
#define SEG_L_32BIT 0x00
|
||||
|
||||
#define SEG_SIZE_AVL_MASK 0x10
|
||||
|
||||
#define SEG_SIZE_LIM_19_16_MASK 0x0f
|
||||
|
||||
/*
|
||||
** System-segment and gate-descriptor types
|
||||
**
|
||||
** IA-32 V3, page 3-15.
|
||||
*/
|
||||
// type 0: reserved
|
||||
#define SEG_SYS_16BIT_TSS_AVAIL 0x1
|
||||
#define SEG_SYS_LDT 0x2
|
||||
#define SEG_SYS_16BIT_TSS_BUSY 0x3
|
||||
#define SEG_SYS_16BIT_CALL_GATE 0x4
|
||||
#define SEG_SYS_TASK_GATE 0x5
|
||||
#define SEG_SYS_16BIT_INT_GATE 0x6
|
||||
#define SEG_SYS_16BIT_TRAP_GATE 0x7
|
||||
// type 8: reserved
|
||||
#define SEG_SYS_32BIT_TSS_AVAIL 0x9
|
||||
// type A: reserved
|
||||
#define SEG_SYS_32BIT_TSS_BUSY 0xb
|
||||
#define SEG_SYS_32BIT_CALL_GATE 0xc
|
||||
// type D: reserved
|
||||
#define SEG_SYS_32BIT_INT_GATE 0xe
|
||||
#define SEG_SYS_32BIT_TRAP_GATE 0xf
|
||||
|
||||
/*
|
||||
** IDT Descriptors
|
||||
**
|
||||
** IA-32 V3, page 5-13.
|
||||
**
|
||||
** All have a segment selector in bytes 2 and 3; Task Gate descriptors
|
||||
** have bytes 0, 1, 4, 6, and 7 reserved; others have bytes 0, 1, 6,
|
||||
** and 7 devoted to the 16 bits of the Offset, with the low nybble of
|
||||
** byte 4 reserved.
|
||||
*/
|
||||
#define IDT_PRESENT 0x8000
|
||||
#define IDT_DPL_MASK 0x6000
|
||||
#define IDT_DPL_0 0x0000
|
||||
#define IDT_DPL_1 0x2000
|
||||
#define IDT_DPL_2 0x4000
|
||||
#define IDT_DPL_3 0x6000
|
||||
#define IDT_GATE_TYPE 0x0f00
|
||||
#define IDT_TASK_GATE 0x0500
|
||||
#define IDT_INT16_GATE 0x0600
|
||||
#define IDT_INT32_GATE 0x0e00
|
||||
#define IDT_TRAP16_GATE 0x0700
|
||||
#define IDT_TRAP32_GATE 0x0f00
|
||||
|
||||
/*
|
||||
** Interrupt vectors
|
||||
*/
|
||||
// predefined by the architecture
|
||||
#define VEC_DIVIDE_ERROR 0x00
|
||||
#define VEC_DEBUG_EXCEPTION 0x01
|
||||
#define VEC_NMI_INTERRUPT 0x02
|
||||
#define VEC_BREAKPOINT 0x03
|
||||
#define VEC_OVERFLOW 0x04
|
||||
#define VEC_BOUND_RANGE_EXCEEDED 0x05
|
||||
#define VEC_INVALID_OPCODE 0x06
|
||||
#define VEC_DEVICE_NOT_AVAILABLE 0x07
|
||||
#define VEC_DOUBLE_FAULT 0x08
|
||||
#define VEC_COPROCESSOR_OVERRUN 0x09
|
||||
#define VEC_INVALID_TSS 0x0a
|
||||
#define VEC_SEGMENT_NOT_PRESENT 0x0b
|
||||
#define VEC_STACK_FAULT 0x0c
|
||||
#define VEC_GENERAL_PROTECTION 0x0d
|
||||
#define VEC_PAGE_FAULT 0x0e
|
||||
// 0x0f is reserved - unused
|
||||
#define VEC_FPU_ERROR 0x10
|
||||
#define VEC_ALIGNMENT_CHECK 0x11
|
||||
#define VEC_MACHINE_CHECK 0x12
|
||||
#define VEC_SIMD_FP_EXCEPTION 0x13
|
||||
#define VEC_VIRT_EXCEPTION 0x14
|
||||
#define VEC_CTRL_PROT_EXCEPTION 0x15
|
||||
// 0x16 through 0x1f are reserved
|
||||
|
||||
// 0x20 through 0xff are user-defined, non-reserved
|
||||
|
||||
// IRQ0 through IRQ15 will use vectors 0x20 through 0x2f
|
||||
#define VEC_TIMER 0x20
|
||||
#define VEC_KBD 0x21
|
||||
#define VEC_COM2 0x23
|
||||
#define VEC_COM1 0x24
|
||||
#define VEC_PARALLEL 0x25
|
||||
#define VEC_FLOPPY 0x26
|
||||
#define VEC_MYSTERY 0x27
|
||||
#define VEC_MOUSE 0x2c
|
||||
|
||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
** @file bios.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** BIOS-related declarations
|
||||
*/
|
||||
|
||||
#ifndef BIOS_H_
|
||||
#define BIOS_H_
|
||||
|
||||
/*
|
||||
** BIOS-related memory addresses
|
||||
*/
|
||||
#define BIOS_BDA 0x0400
|
||||
|
||||
/*
|
||||
** Selected BIOS interrupt numbers
|
||||
*/
|
||||
#define BIOS_TIMER 0x08
|
||||
#define BIOS_KBD 0x09
|
||||
#define BIOS_VIDEO 0x10
|
||||
#define BIOS_EQUIP 0x11
|
||||
#define BIOS_MSIZ 0x12
|
||||
#define BIOS_DISK 0x13
|
||||
#define BIOS_SERIAL 0x14
|
||||
#define BIOS_MISC 0x15
|
||||
#define BIOS_KBDSVC 0x16
|
||||
#define BIOS_PRTSVC 0x17
|
||||
#define BIOS_BOOT 0x19
|
||||
#define BIOS_RTCPCI 0x1a
|
||||
|
||||
// BIOS video commands (AH)
|
||||
#define BV_W_ADV 0x0e
|
||||
|
||||
// BIOS disk commands (AH)
|
||||
#define BD_RESET 0x00
|
||||
#define BD_CHECK 0x01
|
||||
#define BD_RDSECT 0x02
|
||||
#define BD_WRSECT 0x03
|
||||
#define BD_PARAMS 0x08
|
||||
|
||||
// BIOS disk commands with parameters (AX)
|
||||
#define BD_READ(n) ((BD_RDSECT << 8) | (n))
|
||||
#define BD_READ1 0x0201
|
||||
|
||||
// CMOS ports (used for masking NMIs)
|
||||
#define CMOS_ADDR 0x70
|
||||
#define CMOS_DATA 0x71
|
||||
|
||||
// important related commands
|
||||
#define NMI_ENABLE 0x00
|
||||
#define NMI_DISABLE 0x80
|
||||
|
||||
/*
|
||||
** Physical Memory Map Table (0000:2D00 - 0000:7c00)
|
||||
**
|
||||
** Primarily used with the BIOS_MISC interrupt
|
||||
*/
|
||||
#define MMAP_SEG 0x02D0
|
||||
#define MMAP_DISP 0x0000
|
||||
#define MMAP_ADDR ((MMAP_SEG << 4) + MMAP_DISP)
|
||||
#define MMAP_SECTORS 0x0a
|
||||
|
||||
#define MMAP_ENT 24 /* bytes per entry */
|
||||
#define MMAP_MAX_ENTS (BOOT_ADDR - MMAP_ADDR - 4) / 24
|
||||
|
||||
#define MMAP_CODE 0xE820 /* int 0x15 code */
|
||||
#define MMAP_MAGIC_NUM 0x534D4150 /* for 0xE820 interrupt */
|
||||
|
||||
#endif
|
|
@ -1,395 +0,0 @@
|
|||
/**
|
||||
** @file ops.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
**
|
||||
** @brief Inline escapes to assembly for efficiency
|
||||
**
|
||||
** Inspiration from:
|
||||
** Martins Mozeiko, https://gist.github.com/mmozeiko/f68ad2546bd6ab953315
|
||||
** MIT's xv6, https://github.com/mit-pdos/xv6-public
|
||||
**
|
||||
** Note: normally, GCC doesn't inline unless the optimization level is
|
||||
** over 1. This can be forced by adding
|
||||
**
|
||||
** __attribute__((always_inline))
|
||||
**
|
||||
** after the parameter list on each declaration. This is enabled by
|
||||
** defining the compile-time CPP symbol FORCE_INLINING.
|
||||
*/
|
||||
|
||||
#ifndef OPS_H_
|
||||
#define OPS_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
// control "forced" inlining
|
||||
#ifdef FORCE_INLINING
|
||||
#define OPSINLINED __attribute__((always_inline))
|
||||
#else
|
||||
#define OPSINLINED /* no-op */
|
||||
#endif /* FORCE_INLINING */
|
||||
|
||||
/****************************
|
||||
** Data movement
|
||||
****************************/
|
||||
|
||||
/**
|
||||
** Block move functions
|
||||
**
|
||||
** Variations: movsb(), movsl(), movsq()
|
||||
**
|
||||
** Description: Copy from source buffer to destination buffer
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param src Source buffer
|
||||
** @param len Byte count
|
||||
*/
|
||||
static inline void movsb(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsb"
|
||||
: "+D"(dst), "+S"(src), "+c"(len)
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
static inline void movsw(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsw"
|
||||
: "+D"(dst), "+S"(src), "+c"(len)
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
static inline void movsl(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsl"
|
||||
: "+D"(dst), "+S"(src), "+c"(len)
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
static inline void movsq(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsq"
|
||||
: "+D"(dst), "+S"(src), "+c"(len)
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
** Block store functions
|
||||
**
|
||||
** Variations: stosb(), stosw(), stosl()
|
||||
**
|
||||
** Description: Store a specific value into destination buffer
|
||||
**
|
||||
** @param dst Destination buffer
|
||||
** @param val Data to copy
|
||||
** @param len Byte count
|
||||
*/
|
||||
static inline void stosb(void *dst, uint8_t val, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep stosb"
|
||||
: "=D"(dst), "=c"(len)
|
||||
: "0"(dst), "1"(len), "a"(val)
|
||||
: "memory", "cc");
|
||||
}
|
||||
static inline void stosw(void *dst, uint16_t val, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep stos2"
|
||||
: "=D"(dst), "=c"(len)
|
||||
: "0"(dst), "1"(len), "a"(val)
|
||||
: "memory", "cc");
|
||||
}
|
||||
static inline void stosl(void *dst, uint32_t val, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep stosl"
|
||||
: "=D"(dst), "=c"(len)
|
||||
: "0"(dst), "1"(len), "a"(val)
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
/****************************
|
||||
** Special register access
|
||||
****************************/
|
||||
|
||||
/**
|
||||
** Register read functions
|
||||
**
|
||||
** Variations: r_cr0(), r_cr2(), r_cr3(), r_cr4(), r_eflags(),
|
||||
** r_ebp(), r_esp()
|
||||
**
|
||||
** Description: Reads the register indicated by its name
|
||||
**
|
||||
** @return Contents of the register
|
||||
*/
|
||||
static inline uint32_t r_cr0(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr0,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_cr2(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr2,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_cr3(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr3,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_cr4(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr4,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_eflags(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("pushfl; popl %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_ebp(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%ebp,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static inline uint32_t r_esp(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%esp,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
** Register write functions
|
||||
**
|
||||
** Variations: w_cr0(), w_cr2(), w_cr3(), w_cr4(), w_eflags()
|
||||
**
|
||||
** Description: Writes a value into the CR indicated by its name
|
||||
*/
|
||||
static inline void w_cr0(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr0" : : "r"(val));
|
||||
}
|
||||
static inline void w_cr2(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr2" : : "r"(val));
|
||||
}
|
||||
static inline void w_cr3(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr3" : : "r"(val));
|
||||
}
|
||||
static inline void w_cr4(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr4" : : "r"(val));
|
||||
}
|
||||
static inline void w_eflags(uint32_t eflags) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("pushl %0; popfl" : : "r"(eflags));
|
||||
}
|
||||
|
||||
/**
|
||||
** Descriptor table load functions
|
||||
**
|
||||
** Variations: w_gdt(), w_idt()
|
||||
**
|
||||
** Description: Load an address into the specified processor register
|
||||
**
|
||||
** @param addr The value to be loaded into the register
|
||||
*/
|
||||
static inline void w_gdt(void *addr) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("lgdt (%0)" : : "r"(addr));
|
||||
}
|
||||
static inline void w_idt(void *addr) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("lidt (%0)" : : "r"(addr));
|
||||
}
|
||||
|
||||
/**
|
||||
** CPU ID access
|
||||
**
|
||||
** Description: Retrieve CPUID information
|
||||
**
|
||||
** @param op Value to be placed into %eax for the operation
|
||||
** @param ap Pointer to where %eax contents should be saved, or NULL
|
||||
** @param bp Pointer to where %ebx contents should be saved, or NULL
|
||||
** @param cp Pointer to where %ecx contents should be saved, or NULL
|
||||
** @param dp Pointer to where %edx contents should be saved, or NULL
|
||||
*/
|
||||
static inline void cpuid(uint32_t op, uint32_t *ap, uint32_t *bp, uint32_t *cp,
|
||||
uint32_t *dp) OPSINLINED
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(op));
|
||||
if (ap)
|
||||
*ap = eax;
|
||||
if (bp)
|
||||
*bp = ebx;
|
||||
if (cp)
|
||||
*cp = ecx;
|
||||
if (dp)
|
||||
*dp = edx;
|
||||
}
|
||||
|
||||
/****************************
|
||||
** TLB management
|
||||
****************************/
|
||||
|
||||
/**
|
||||
** TLB invalidation for one page
|
||||
**
|
||||
** Description: Invalidate the TLB entry for an address
|
||||
**
|
||||
** @param addr An address within the page to be flushed
|
||||
*/
|
||||
static inline void invlpg(uint32_t addr) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("invlpg (%0)" : : "r"(addr) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
** TLB invalidation for all pages
|
||||
**
|
||||
** Description: Flush all entries from the TLB
|
||||
**
|
||||
** We do this by changing CR3.
|
||||
*/
|
||||
static inline void flushtlb(void) OPSINLINED
|
||||
{
|
||||
uint32_t cr3;
|
||||
__asm__ __volatile__("movl %%cr3,%0" : "=r"(cr3));
|
||||
__asm__ __volatile__("movl %0,%%cr2" : : "r"(cr3));
|
||||
}
|
||||
|
||||
/****************************
|
||||
** I/O instructions
|
||||
****************************/
|
||||
|
||||
/**
|
||||
** Name: inN
|
||||
**
|
||||
** Variations: inb(), inw(), inl()
|
||||
**
|
||||
** Description: Read some amount of data from the supplied I/O port
|
||||
**
|
||||
** @param port The i/o port to read from
|
||||
**
|
||||
** @return The data read from the specified port
|
||||
*/
|
||||
static inline uint8_t inb(int port) OPSINLINED
|
||||
{
|
||||
uint8_t data;
|
||||
__asm__ __volatile__("inb %w1,%0" : "=a"(data) : "d"(port));
|
||||
return data;
|
||||
}
|
||||
static inline uint16_t inw(int port) OPSINLINED
|
||||
{
|
||||
uint16_t data;
|
||||
__asm__ __volatile__("inw %w1,%0" : "=a"(data) : "d"(port));
|
||||
return data;
|
||||
}
|
||||
static inline uint32_t inl(int port) OPSINLINED
|
||||
{
|
||||
uint32_t data;
|
||||
__asm__ __volatile__("inl %w1,%0" : "=a"(data) : "d"(port));
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: outN
|
||||
**
|
||||
** Variations: outb(), outw(), outl()
|
||||
**
|
||||
** Description: Write some data to the specified I/O port
|
||||
**
|
||||
** @param port The i/o port to write to
|
||||
** @param data The data to be written to the port
|
||||
**
|
||||
** @return The data read from the specified port
|
||||
*/
|
||||
static inline void outb(int port, uint8_t data) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("outb %0,%w1" : : "a"(data), "d"(port));
|
||||
}
|
||||
static inline void outw(int port, uint16_t data) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("outw %0,%w1" : : "a"(data), "d"(port));
|
||||
}
|
||||
static inline void outl(int port, uint32_t data) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("outl %0,%w1" : : "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
/****************************
|
||||
** Miscellaneous instructions
|
||||
****************************/
|
||||
|
||||
/**
|
||||
** Name: breakpoint
|
||||
**
|
||||
** Description: Cause a breakpoint interrupt for debugging purposes
|
||||
*/
|
||||
static inline void breakpoint(void) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("int3");
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: get_ra
|
||||
**
|
||||
** Description: Get the return address for the calling function
|
||||
** (i.e., where whoever called us will go back to)
|
||||
**
|
||||
** @return The address the calling routine will return to as a uint32_t
|
||||
*/
|
||||
static inline uint32_t get_ra(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl 4(%%ebp),%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: ev_wait
|
||||
**
|
||||
** Description: Pause until something happens
|
||||
*/
|
||||
static inline void ev_wait(void) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("sti ; hlt");
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: xchgl
|
||||
**
|
||||
** Description: Perform an atomic exchange with memory
|
||||
**
|
||||
** @param addr Memory location to be modified
|
||||
** @param data Data to exchange
|
||||
**
|
||||
** @return The old contents of the memory location
|
||||
*/
|
||||
static inline uint32_t xchgl(volatile uint32_t *addr, uint32_t data) OPSINLINED
|
||||
{
|
||||
uint32_t old;
|
||||
|
||||
// + indicates a read-modify-write operand
|
||||
__asm__ __volatile__("lock; xchgl %0, %1"
|
||||
: "+m"(*addr), "=a"(old)
|
||||
: "1"(data)
|
||||
: "cc");
|
||||
return old;
|
||||
}
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
|
@ -1,136 +0,0 @@
|
|||
/**
|
||||
** @file pic.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @author K. Reek
|
||||
**
|
||||
** Definitions of constants and macros for the Intel 8259 Programmable
|
||||
** Interrupt Controller.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef X86PIC_H_
|
||||
#define X86PIC_H_
|
||||
|
||||
/*
|
||||
** Our expected configuration is two PICs, with the secondary connected
|
||||
** through the IRQ2 pin of the primary.
|
||||
*/
|
||||
/*
|
||||
** Port addresses for the command port and interrupt mask register port
|
||||
** for both the primary and secondary PICs.
|
||||
*/
|
||||
#define PIC1_CMD 0x20 // primary command
|
||||
#define PIC1_DATA (PIC1_CMD + 1) // primary data / int mask register
|
||||
#define PIC2_CMD 0xA0 // secondary command
|
||||
#define PIC2_DATA (PIC2_CMD + 1) // secondary data / int mask register
|
||||
|
||||
/*
|
||||
** Initialization Command Word (ICW) definitions
|
||||
**
|
||||
** Initialization sequence:
|
||||
** ICW1 Init command is sent to each command port.
|
||||
** ICW2 vector commands are sent to the data ports.
|
||||
** If "cascade mode" was selected, send ICW3 commands to the data ports.
|
||||
** If "need ICW4" was selected, send ICW4 commands to the data ports.
|
||||
**
|
||||
** Following that sequence, the PIC is ready to accept interrupts;
|
||||
** it will also accept Output Command Words (OCWs) to the data ports.
|
||||
**
|
||||
** PIC1_* defines are intended for the primary PIC
|
||||
** PIC2_* defines are intended for the secondary PIC
|
||||
** PIC_* defines are sent to both PICs
|
||||
*/
|
||||
/*
|
||||
** ICW1: initialization, send to command port
|
||||
*/
|
||||
#define PIC_CW1_INIT 0x10 // start initialization sequence
|
||||
#define PIC_CW1_NEED4 0x01 // ICW4 will also be set
|
||||
#define PIC_CW1_SINGLE 0x02 // select single (vs. cascade) mode
|
||||
#define PIC_CW1_INTVAL 0x04 // set call interval to 4 (vs. 8)
|
||||
#define PIC_CW1_LEVEL 0x08 // use level-triggered mode (vs. edge)
|
||||
|
||||
/*
|
||||
** ICW2: interrupt vector base offsets, send to data port
|
||||
*/
|
||||
#define PIC1_CW2_VECBASE 0x20 // IRQ0 int vector number
|
||||
#define PIC2_CW2_VECBASE 0x28 // IRQ8 int vector number
|
||||
|
||||
/*
|
||||
** ICW3: secondary::primary attachment, send to data port
|
||||
*/
|
||||
#define PIC1_CW3_SEC_IRQ2 0x04 // bit mask: secondary is on pin 2
|
||||
#define PIC2_CW3_SEC_ID 0x02 // integer: secondary id
|
||||
|
||||
/*
|
||||
** ICW4: operating mode, send to data port
|
||||
*/
|
||||
#define PIC_CW4_PM86 0x01 // 8086 mode (vs. 8080/8085)
|
||||
#define PIC_CW4_AUTOEOI 0x02 // do auto eoi's
|
||||
#define PIC_CW4_UNBUF 0x00 // unbuffered mode
|
||||
#define PIC_CW4_SEC_BUF 0x08 // put secondary in buffered mode
|
||||
#define PIC_CW4_PRI_BUF 0x0C // put primary in buffered mode
|
||||
#define PIC_CW4_SFNMODE 0x10 // "special fully nested" mode
|
||||
|
||||
/*
|
||||
** Operation Control Words (OCWs)
|
||||
**
|
||||
** After the init sequence, can send these
|
||||
*/
|
||||
/*
|
||||
** OCW1: interrupt mask; send to data port
|
||||
*/
|
||||
#define PIC_MASK_NONE 0x00 // allow all interrupts
|
||||
#define PIC_MASK_NO_IRQ0 0x01 // prevent IRQ0 interrupts
|
||||
#define PIC_MASK_NO_IRQ1 0x02 // prevent IRQ1 interrupts
|
||||
#define PIC_MASK_NO_IRQ2 0x04 // prevent IRQ2 interrupts
|
||||
#define PIC_MASK_NO_IRQ3 0x08 // prevent IRQ3 interrupts
|
||||
#define PIC_MASK_NO_IRQ4 0x10 // prevent IRQ4 interrupts
|
||||
#define PIC_MASK_NO_IRQ5 0x20 // prevent IRQ5 interrupts
|
||||
#define PIC_MASK_NO_IRQ6 0x40 // prevent IRQ6 interrupts
|
||||
#define PIC_MASK_NO_IRQ7 0x80 // prevent IRQ7 interrupts
|
||||
#define PIC_MASK_ALL 0xff // prevent all interrupts
|
||||
|
||||
/*
|
||||
** OCW2: EOI control, interrupt level; send to command port
|
||||
*/
|
||||
#define PIC_LVL_0 0x00 // act on IRQ level 0
|
||||
#define PIC_LVL_1 0x01 // act on IRQ level 1
|
||||
#define PIC_LVL_2 0x02 // act on IRQ level 2
|
||||
#define PIC_LVL_3 0x03 // act on IRQ level 3
|
||||
#define PIC_LVL_4 0x04 // act on IRQ level 4
|
||||
#define PIC_LVL_5 0x05 // act on IRQ level 5
|
||||
#define PIC_LVL_6 0x06 // act on IRQ level 6
|
||||
#define PIC_LVL_7 0x07 // act on IRQ level 7
|
||||
|
||||
#define PIC_EOI_NON_SPEC 0x20 // non-specific EOI command
|
||||
#define PIC_EOI PIC_EOI_NON_SPEC
|
||||
|
||||
#define PIC_EOI_SPEC 0x60 // specific EOI command
|
||||
#define PIC_SEOI PIC_EOI_SPEC
|
||||
#define PIC_SEOI_LVL0 (PIC_EOI_SPEC | PIC_LVL_0)
|
||||
#define PIC_SEOI_LVL1 (PIC_EOI_SPEC | PIC_LVL_1)
|
||||
#define PIC_SEOI_LVL2 (PIC_EOI_SPEC | PIC_LVL_2)
|
||||
#define PIC_SEOI_LVL3 (PIC_EOI_SPEC | PIC_LVL_3)
|
||||
#define PIC_SEOI_LVL4 (PIC_EOI_SPEC | PIC_LVL_4)
|
||||
#define PIC_SEOI_LVL5 (PIC_EOI_SPEC | PIC_LVL_5)
|
||||
#define PIC_SEOI_LVL6 (PIC_EOI_SPEC | PIC_LVL_6)
|
||||
#define PIC_SEOI_LVL7 (PIC_EOI_SPEC | PIC_LVL_7)
|
||||
|
||||
#define PIC_EOI_ROT_NONSP 0xa0 // rotate on non-spec EOI cmd
|
||||
#define PIC_EOI_SET_ROT_AUTO 0x80 // set "rotate in auto EOI mode"
|
||||
#define PIC_EOI_CLR_ROT_AUTO 0x00 // clear "rotate in auto EOI mode"
|
||||
#define PIC_EOI_ROT_SPEC 0xe0 // rotate on spec EOI cmd (+ level)
|
||||
#define PIC_EOI_SET_PRIO 0xc0 // set priority (+ level)
|
||||
#define PIC_EOI_NOP 0x40 // no operation
|
||||
|
||||
/*
|
||||
** OCW3: read requests, special mask mode; send to command port
|
||||
*/
|
||||
#define PIC_READIRR 0x0a // read the IR register
|
||||
#define PIC_READISR 0x0b // read the IS register
|
||||
#define PIC_POLL 0x0c // poll
|
||||
#define PIC_MASK_RESET 0x48 // reset special mask mode
|
||||
#define PIC_MASK_SET 0x68 // set special mask mode
|
||||
|
||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
** @file pit.h
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @author K. Reek
|
||||
**
|
||||
** Definitions of constants and macros for the
|
||||
** Intel 8254 Programmable Interval Timer
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef X86PIT_H_
|
||||
#define X86PIT_H_
|
||||
|
||||
/*
|
||||
** Hardware timer (Intel 8254 Programmable Interval Timer)
|
||||
**
|
||||
** Control word layout:
|
||||
**
|
||||
** Bit 7 6 | 5 4 | 3 2 1 | 0
|
||||
** Field SC1 SC0|RW1 RW0|M2 M1 M0 |BCD
|
||||
**
|
||||
** SC - select counter
|
||||
** RW - read/write
|
||||
** M - mode
|
||||
** BCD - binary or BCD counter
|
||||
*/
|
||||
/* Frequency settings */
|
||||
#define PIT_DEFAULT_TICKS_PER_SECOND 18 // actually 18.2065Hz
|
||||
#define PIT_DEFAULT_MS_PER_TICK (1000 / PIT_DEFAULT_TICKS_PER_SECOND)
|
||||
#define PIT_FREQ 1193182 // clock cycles/sec
|
||||
|
||||
/* Port assignments */
|
||||
#define PIT_BASE_PORT 0x40 // I/O port for the timer
|
||||
#define PIT_0_PORT (PIT_BASE_PORT)
|
||||
#define PIT_1_PORT (PIT_BASE_PORT + 1)
|
||||
#define PIT_2_PORT (PIT_BASE_PORT + 2)
|
||||
#define PIT_CONTROL_PORT (PIT_BASE_PORT + 3)
|
||||
|
||||
/* BCD field */
|
||||
#define PIT_USE_DECIMAL 0x00 // 16-bit binary counter (default)
|
||||
#define PIT_USE_BCD 0x01 // BCD counter
|
||||
|
||||
/* Timer modes */
|
||||
#define PIT_MODE_0 0x00 // int on terminal count
|
||||
#define PIT_MODE_1 0x02 // one-shot
|
||||
#define PIT_MODE_2 0x04 // divide-by-N
|
||||
#define PIT_MODE_3 0x06 // square-wave
|
||||
#define PIT_MODE_4 0x08 // software strobe
|
||||
#define PIT_MODE_5 0x0a // hardware strobe
|
||||
|
||||
/* Timer 0 settings */
|
||||
#define PIT_0_SELECT 0x00 // select timer 0
|
||||
#define PIT_0_LOAD 0x30 // load LSB, then MSB
|
||||
#define PIT_0_NDIV PIT_MODE_2 // divide-by-N counter
|
||||
#define PIT_0_SQUARE PIT_MODE_3 // square-wave mode
|
||||
#define PIT_0_ENDSIGNAL 0x00 // assert OUT at end of count
|
||||
|
||||
/* Timer 1 settings */
|
||||
#define PIT_1_SELECT 0x40 // select timer 1
|
||||
#define PIT_1_READ 0x30 // read/load LSB then MSB
|
||||
#define PIT_1_RATE 0x06 // square-wave, for USART
|
||||
|
||||
/* Timer 2 settings */
|
||||
#define PIT_2_SELECT 0x80 // select timer 1
|
||||
#define PIT_2_READ 0x30 // read/load LSB then MSB
|
||||
#define PIT_2_RATE 0x06 // square-wave, for USART
|
||||
|
||||
/* Timer read-back */
|
||||
|
||||
#define PIT_READBACK 0xc0 // perform a read-back
|
||||
#define PIT_RB_NOT_COUNT 0x20 // don't latch the count
|
||||
#define PIT_RB_NOT_STATUS 0x10 // don't latch the status
|
||||
#define PIT_RB_CHAN_2 0x08 // read back channel 2
|
||||
#define PIT_RB_CHAN_1 0x04 // read back channel 1
|
||||
#define PIT_RB_CHAN_0 0x02 // read back channel 0
|
||||
#define PIT_RB_ACCESS_MASK 0x30 // access mode field
|
||||
#define PIT_RB_OP_MASK 0x0e // oper mode field
|
||||
#define PIT_RB_BCD_MASK 0x01 // BCD mode field
|
||||
|
||||
#endif
|
|
@ -1,348 +0,0 @@
|
|||
/*
|
||||
** @file uart.h
|
||||
**
|
||||
** @author M. Reek
|
||||
** @authors K. Reek, Warren R. Carithers
|
||||
**
|
||||
** Definitions for a 16540/16550 compatible UART. Definitions are taken
|
||||
** from datasheets for the National Semiconductor INS8250, NS16450, and
|
||||
** NS16550 UART chips, and the PC87309 Super I/O legacy peripheral chip.
|
||||
**
|
||||
** The naming convention is UAx_yyy_zzzzz. "x" is either 4 or 5 (see below),
|
||||
** "yyy" is the name of the register to which this value applies, and
|
||||
** "zzzzz" is the name of the value or field.
|
||||
**
|
||||
** The UA4 prefix denotes 16540 compatible functions, available in both
|
||||
** chips. The UA5 prefix denotes 16550-only functions (primarily the FIFOs).
|
||||
**
|
||||
** For many items there are two names: one short one that matches the name
|
||||
** in the chip manual, and another that is more readable.
|
||||
*/
|
||||
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
/*********************************************************************
|
||||
***************************** I/O PORTS ******************************
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
** Base port number assigned to the device
|
||||
*/
|
||||
#define UA4_COM1_PORT 0x3f8
|
||||
#define UA4_COM2_PORT 0x2f8
|
||||
#define UA4_COM3_PORT 0x3e8
|
||||
#define UA4_COM4_PORT 0x2e8
|
||||
|
||||
// short name for the one we'll use
|
||||
#define UA4_PORT UA4_COM1_PORT
|
||||
#define UA5_PORT UA4_COM1_PORT
|
||||
|
||||
/*
|
||||
** Registers
|
||||
**
|
||||
** The 164x0 chips have the following registers. The (RO) and (WO)
|
||||
** suffixes indicate read-only and write-only access.
|
||||
**
|
||||
** Index Register(s)
|
||||
** ===== =========================================
|
||||
** 0 Receiver Data (RO), Transmitter Data (WO)
|
||||
** 1 Interrupt Enable
|
||||
** 2 Interrupt ID (RO), FIFO Control (WO)
|
||||
** 3 Line Control, Divisor Latch
|
||||
** 4 Modem Control
|
||||
** 5 Line Status
|
||||
** 6 Modem Status
|
||||
** 7 Scratch
|
||||
**
|
||||
** Registers indices are relative to the base I/O port for the
|
||||
** specific UART port being used (e.g., for COM1, the port addresses
|
||||
** are 0x3f8 through 0x3ff). When two registers share a port and have
|
||||
** different access methods (RO vs. WO), a read from the port accesses
|
||||
** the RO register and a write to the port access the WO register.
|
||||
**
|
||||
** The Line Control and Divisor Latch registers are accessed by writing
|
||||
** a byte to the port; the high-order bit determines which register is
|
||||
** accessed (0 selects Line Control, 1 selects Divisor Latch), with the
|
||||
** remaining bits selecting fields within the indicated register.
|
||||
*/
|
||||
/*
|
||||
** Receiver Data Register (read-only)
|
||||
*/
|
||||
#define UA4_RXD (UA4_PORT + 0)
|
||||
#define UA4_RX_DATA UA4_RXD
|
||||
|
||||
/*
|
||||
** Transmitter Data Register (write-only)
|
||||
*/
|
||||
#define UA4_TXD (UA4_PORT + 0)
|
||||
#define UA4_TX_DATA UA4_TXD
|
||||
|
||||
/*
|
||||
** Interrupt Enable Register
|
||||
*/
|
||||
#define UA4_IER (UA4_PORT + 1)
|
||||
#define UA4_INT_ENABLE_REG UA4_IER
|
||||
|
||||
// fields
|
||||
#define UA4_IER_RX_IE 0x01 // Rcvr High-Data-Level Int Enable
|
||||
#define UA4_IER_TX_IE 0x02 // Xmitter Low-data-level Int Enable
|
||||
#define UA4_IER_LS_IE 0x04 // Line Status Int Enable
|
||||
#define UA4_IER_MS_IE 0x08 // Modem Status Int Enable
|
||||
|
||||
// aliases
|
||||
#define UA4_IER_RX_INT_ENABLE UA4_IER_RX_IE
|
||||
#define UA4_IER_TX_INT_ENABLE UA4_IER_TX_IE
|
||||
#define UA4_IER_LINE_STATUS_INT_ENABLE UA4_IER_LS_IE
|
||||
#define UA4_IER_MODEM_STATUS_INT_ENABLE UA4_IER_MS_IE
|
||||
|
||||
/*
|
||||
** Interrupt Identification Register (read-only)
|
||||
**
|
||||
** a.k.a. Event Identification Register
|
||||
*/
|
||||
#define UA4_IIR (UA4_PORT + 2)
|
||||
#define UA4_EVENT_ID UA4_IIR
|
||||
|
||||
// fields
|
||||
#define UA4_IIR_IPF 0x01 // Interrupt Pending flag
|
||||
|
||||
#define UA4_IIR_IPR_MASK 0x06 // Interrupt Priority mask
|
||||
#define UA4_IIR_IPR0_MASK 0x02 // IPR bit 0 mask
|
||||
#define UA4_IIR_IPR1_MASK 0x04 // IPR bit 1 mask
|
||||
|
||||
#define UA5_IIR_RXFT 0x08 // RX_FIFO Timeout
|
||||
#define UA5_IIR_FEN0 0x40 // FIFOs Enabled
|
||||
#define UA5_IIR_FEN1 0x80 // FIFOs Enabled
|
||||
|
||||
// aliases
|
||||
#define UA4_IIR_INT_PENDING UA4_IIR_IPF
|
||||
#define UA4_IIR_INT_PRIORITY UA4_IIR_IPR
|
||||
#define UA5_IIR_RX_FIFO_TIMEOUT UA5_IIR_RXFT
|
||||
#define UA5_IIR_FIFO_ENABLED_0 UA5_IIR_FEN0
|
||||
#define UA5_IIR_FIFO_ENABLED_1 UA5_IIR_FEN1
|
||||
|
||||
// IIR interrupt priorities (four-bit values)
|
||||
#define UA4_IIR_INT_PRI_MASK 0x0f // Mask for extracting int priority
|
||||
#define UA4_IIR_NO_INT 0x01 // no interrupt
|
||||
#define UA4_IIR_LINE_STATUS 0x06 // line status interrupt
|
||||
#define UA4_IIR_RX 0x04 // Receiver High Data Level
|
||||
#define UA5_IIR_RX_FIFO 0x0c // Receiver FIFO timeout (16550)
|
||||
#define UA4_IIR_TX 0x02 // Transmitter Low Data level
|
||||
#define UA4_IIR_MODEM_STATUS 0x00 // Modem Status
|
||||
|
||||
// aliases
|
||||
#define UA4_IIR_NO_INT_PENDING UA4_IIR_NO_INT
|
||||
#define UA4_IIR_LINE_STATUS_INT_PENDING UA4_IIR_LINE_STATUS
|
||||
#define UA4_IIR_RX_INT_PENDING UA4_IIR_RX
|
||||
#define UA5_IIR_RX_FIFO_TIMEOUT_INT_PENDING UA5_IIR_RX_FIFO
|
||||
#define UA4_IIR_TX_INT_PENDING UA4_IIR_TX
|
||||
#define UA4_IIR_MODEM_STATUS_INT_PENDING UA4_IIR_MODEM_STATUS
|
||||
|
||||
/*
|
||||
** FIFO Control Register (16550 only, write-only)
|
||||
*/
|
||||
#define UA5_FCR (UA5_PORT + 2)
|
||||
#define UA5_FIFO_CTL UA5_FCR
|
||||
|
||||
#define UA5_FCR_FIFO_RESET 0x00 // Reset the FIFO
|
||||
#define UA5_FCR_FIFO_EN 0x01 // FIFO Enable
|
||||
#define UA5_FCR_RXSR 0x02 // Receiver Soft Reset
|
||||
#define UA5_FCR_TXSR 0x04 // Transmitter Soft Reset
|
||||
|
||||
#define UA5_FCR_TXFT_MASK 0x30 // TX_FIFO threshold level mask
|
||||
#define UA5_FCR_TXFT0_MASK 0x10 // TXFT bit 0 mask
|
||||
#define UA5_FCR_TXFT1_MASK 0x20 // TXFT bit 1 mask
|
||||
#define UA5_FCR_TX_FIFO_1 0x00 // 1 char
|
||||
#define UA5_FCR_TX_FIFO_3 0x10 // 3 char
|
||||
#define UA5_FCR_TX_FIFO_9 0x20 // 9 char
|
||||
#define UA5_FCR_TX_FIFO_13 0x30 // 13 char
|
||||
|
||||
#define UA5_FCR_RXFT_MASK 0xc0 // RX_FIFO threshold level mask
|
||||
#define UA5_FCR_RXFT0_MASK 0x40 // RXFT bit 0 mask
|
||||
#define UA5_FCR_RXFT1_MASK 0x80 // RXFT bit 1 mask
|
||||
#define UA5_FCR_RX_FIFO_1 0x00 // 1 char
|
||||
#define UA5_FCR_RX_FIFO_4 0x40 // 4 char
|
||||
#define UA5_FCR_RX_FIFO_8 0x80 // 8 char
|
||||
#define UA5_FCR_RX_FIFO_14 0xc0 // 14 char
|
||||
|
||||
// aliases
|
||||
#define UA5_FCR_FIFO_ENABLED UA5_FCR_FIFO_EN
|
||||
#define UA5_FCR_RX_SOFT_RESET UA5_FCR_RXSR
|
||||
#define UA5_FCR_TX_SOFT_RESET UA5_FCR_TXSR
|
||||
#define UA5_FCR_TX_FIFO_1_CHAR UA5_FCR_TX_FIFO_1
|
||||
#define UA5_FCR_TX_FIFO_3_CHAR UA5_FCR_TX_FIFO_3
|
||||
#define UA5_FCR_TX_FIFO_9_CHAR UA5_FCR_TX_FIFO_9
|
||||
#define UA5_FCR_TX_FIFO_13_CHAR UA5_FCR_TX_FIFO_13
|
||||
#define UA5_FCR_RX_FIFO_1_CHAR UA5_FCR_RX_FIFO_1
|
||||
#define UA5_FCR_RX_FIFO_4_CHAR UA5_FCR_RX_FIFO_4
|
||||
#define UA5_FCR_RX_FIFO_8_CHAR UA5_FCR_RX_FIFO_8
|
||||
#define UA5_FCR_RX_FIFO_14_CHAR UA5_FCR_RX_FIFO_14
|
||||
|
||||
/*
|
||||
** Line Control Register (available in all banks)
|
||||
**
|
||||
** Selected when bit 7 of the value written to the port is a 0.
|
||||
*/
|
||||
#define UA4_LCR (UA4_PORT + 3)
|
||||
#define UA4_LINE_CTL UA4_LCR
|
||||
|
||||
#define UA4_LCR_WLS_MASK 0x03 // Word Length Select mask
|
||||
#define UA4_LCR_WLS0_MASK 0x01 // WLS bit 0 mask
|
||||
#define UA4_LCR_WLS1_MASK 0x02 // WLS bit 1 mask
|
||||
#define UA4_LCR_WLS_5 0x00 // 5 bits per char
|
||||
#define UA4_LCR_WLS_6 0x01 // 6 bits per char
|
||||
#define UA4_LCR_WLS_7 0x02 // 7 bits per char
|
||||
#define UA4_LCR_WLS_8 0x03 // 8 bits per char
|
||||
|
||||
#define UA4_LCR_STB 0x04 // Stop Bits
|
||||
#define UA4_LCR_1_STOP_BIT 0x00
|
||||
#define UA4_LCR_2_STOP_BIT 0x04
|
||||
|
||||
#define UA4_LCR_PEN 0x08 // Parity Enable
|
||||
#define UA4_LCR_EPS 0x10 // Even Parity Select
|
||||
#define UA4_LCR_STKP 0x20 // Sticky Parity
|
||||
#define UA4_LCR_NO_PARITY 0x00
|
||||
#define UA4_LCR_ODD_PARITY UA4_LCR_PEN
|
||||
#define UA4_LCR_EVEN_PARITY (UA4_LCR_PEN | UA4_LCR_EPS)
|
||||
#define UA4_LCR_PARITY_LOGIC_1 (UA4_LCR_PEN | UA4_LCR_STKP)
|
||||
#define UA4_LCR_PARITY_LOGIC_0 (UA4_LCR_PEN | UA4_LCR_EPS | UA4_LCR_STKP)
|
||||
|
||||
#define UA4_LCR_SBRK 0x40 // Set Break
|
||||
#define UA4_LCR_DLAB 0x80 // Divisor Latch select bit
|
||||
|
||||
// aliases
|
||||
#define UA4_LCR_STOP_BITS UA4_LCR_STB
|
||||
#define UA4_LCR_PARITY_ENABLE UA4_LCR_PEN
|
||||
#define UA4_LCR_SET_BREAK UA4_LCR_SBRK
|
||||
#define UA4_LCR_BANK_SELECT_ENABLE UA4_LCR_BKSE
|
||||
|
||||
/*
|
||||
** Divisor Latch Registers
|
||||
** Divisor Latch Least Significant (DLL)
|
||||
** Divisor Latch Most Significant (DLM)
|
||||
**
|
||||
** These contain the lower and upper halves of the 16-bit divisor for
|
||||
** baud rate generation.
|
||||
**
|
||||
** Accessing them requires sending a command to LCR with the most
|
||||
** significant bit (0x80, the DLAB field) set. This "unlocks" the
|
||||
** Divisor Latch registers, which are accessed at UA4_PORT+0 and
|
||||
** UA4_PORT+1 (i.e., in place of the RXD/TXD and IE registers). To
|
||||
** "re-lock" the Divisor Latch registers, write a command byte to
|
||||
** LCR with 0 in the DLAB bit.
|
||||
*/
|
||||
#define UA4_DLL (UA4_PORT + 0) // Divisor Latch (least sig.)
|
||||
#define UA4_DLM (UA4_PORT + 1) // Divisor Latch (most sig.)
|
||||
|
||||
// aliases
|
||||
#define UA4_DIVISOR_LATCH_LS UA4_DLL
|
||||
#define UA4_DIVISOR_LATCH_MS UA4_DLM
|
||||
|
||||
// Baud rate divisor high and low bytes
|
||||
#define BAUD_HIGH_BYTE(x) (((x) >> 8) & 0xff)
|
||||
#define BAUD_LOW_BYTE(x) ((x) & 0xff)
|
||||
|
||||
// Baud rate divisors
|
||||
#define DL_BAUD_50 2304
|
||||
#define DL_BAUD_75 1536
|
||||
#define DL_BAUD_110 1047
|
||||
#define DL_BAUD_150 768
|
||||
#define DL_BAUD_300 384
|
||||
#define DL_BAUD_600 192
|
||||
#define DL_BAUD_1200 96
|
||||
#define DL_BAUD_1800 64
|
||||
#define DL_BAUD_2000 58
|
||||
#define DL_BAUD_2400 48
|
||||
#define DL_BAUD_3600 32
|
||||
#define DL_BAUD_4800 24
|
||||
#define DL_BAUD_7200 16
|
||||
#define DL_BAUD_9600 12
|
||||
#define DL_BAUD_14400 8
|
||||
#define DL_BAUD_19200 6
|
||||
#define DL_BAUD_28800 4
|
||||
#define DL_BAUD_38400 3
|
||||
#define DL_BAUD_57600 2
|
||||
#define DL_BAUD_115200 1
|
||||
|
||||
/*
|
||||
** Modem Control Register
|
||||
*/
|
||||
#define UA4_MCR (UA4_PORT + 4)
|
||||
#define UA4_MODEM_CTL UA4_MCR
|
||||
|
||||
#define UA4_MCR_DTR 0x01 // Data Terminal Ready
|
||||
#define UA4_MCR_RTS 0x02 // Ready to Send
|
||||
#define UA4_MCR_RILP 0x04 // Loopback Interrupt Request
|
||||
#define UA4_MCR_ISEN 0x08 // Interrupt Signal Enable
|
||||
#define UA4_MCR_DCDLP 0x08 // DCD Loopback
|
||||
#define UA4_MCR_LOOP 0x10 // Loopback Enable
|
||||
|
||||
// aliases
|
||||
#define UA4_MCR_DATA_TERMINAL_READY UA4_MCR_DTR
|
||||
#define UA4_MCR_READY_TO_SEND UA4_MCR_RTS
|
||||
#define UA4_MCR_LOOPBACK_INT_REQ UA4_MCR_RILP
|
||||
#define UA4_MCR_INT_SIGNAL_ENABLE UA4_MCR_ISEN
|
||||
#define UA4_MCR_LOOPBACK_DCD UA4_MCR_DCDLP
|
||||
#define UA4_MCR_LOOPBACK_ENABLE UA4_MCR_LOOP
|
||||
|
||||
/*
|
||||
** Line Status Register
|
||||
*/
|
||||
#define UA4_LSR (UA4_PORT + 5)
|
||||
#define UA4_LINE_STATUS UA4_LSR
|
||||
|
||||
#define UA4_LSR_RXDA 0x01 // Receiver Data Available
|
||||
#define UA4_LSR_OE 0x02 // Overrun Error
|
||||
#define UA4_LSR_PE 0x04 // Parity Error
|
||||
#define UA4_LSR_FE 0x08 // Framing Error
|
||||
#define UA4_LSR_BRK 0x10 // Break Event Detected
|
||||
#define UA4_LSR_TXRDY 0x20 // Transmitter Ready
|
||||
#define UA4_LSR_TXEMP 0x40 // Transmitter Empty
|
||||
#define UA4_LSR_ER_INF 0x80 // Error in RX_FIFO
|
||||
|
||||
// aliases
|
||||
#define UA4_LSR_RX_DATA_AVAILABLE UA4_LSR_RXDA
|
||||
#define UA4_LSR_OVERRUN_ERROR UA4_LSR_OE
|
||||
#define UA4_LSR_PARITY_ERROR UA4_LSR_PE
|
||||
#define UA4_LSR_FRAMING_ERROR UA4_LSR_FE
|
||||
#define UA4_LSR_BREAK_DETECTED UA4_LSR_BRK
|
||||
#define UA4_LSR_TX_READY UA4_LSR_TXRDY
|
||||
#define UA4_LSR_TX_EMPTY UA4_LSR_TXEMP
|
||||
#define UA4_LSR_RX_FIFO_ERROR UA4_LSR_ER_INF
|
||||
|
||||
/*
|
||||
** Modem Status Register
|
||||
*/
|
||||
#define UA4_MSR (UA4_PORT + 6)
|
||||
#define UA4_MODEM_STATUS UA4_MSR
|
||||
|
||||
#define UA4_MSR_DCTS 0x01 // Delta Clear to Send
|
||||
#define UA4_MSR_DDSR 0x02 // Delta Data Set Ready
|
||||
#define UA4_MSR_TERI 0x04 // Trailing Edge Ring Indicate
|
||||
#define UA4_MSR_DDCD 0x08 // Delta Data Carrier Detect
|
||||
#define UA4_MSR_CTS 0x10 // Clear to Send
|
||||
#define UA4_MSR_DSR 0x20 // Data Set Ready
|
||||
#define UA4_MSR_RI 0x40 // Ring Indicate
|
||||
#define UA4_MSR_DCD 0x80 // Data Carrier Detect
|
||||
|
||||
// aliases
|
||||
#define UA4_MSR_DELTA_CLEAR_TO_SEND UA4_MSR_DCTS
|
||||
#define UA4_MSR_DELTA_DATA_SET_READY UA4_MSR_DDSR
|
||||
#define UA4_MSR_TRAILING_EDGE_RING UA4_MSR_TERI
|
||||
#define UA4_MSR_DELTA_DATA_CARRIER_DETECT UA4_MSR_DDCD
|
||||
#define UA4_MSR_CLEAR_TO_SEND UA4_MSR_CTS
|
||||
#define UA4_MSR_DATA_SET_READY UA4_MSR_DSR
|
||||
#define UA4_MSR_RING_INDICATE UA4_MSR_RI
|
||||
#define UA4_MSR_DATA_CARRIER_DETECT UA4_MSR_DCD
|
||||
|
||||
/*
|
||||
** Scratch Register
|
||||
**
|
||||
** Not used by the UART; usable as a "scratchpad" register for
|
||||
** temporary storage.
|
||||
*/
|
||||
#define UA4_SCR (UA4_PORT + 7)
|
||||
#define UA4_SCRATCH UA4_UA5_SCR
|
||||
|
||||
#endif /* uart.h */
|
Loading…
Add table
Reference in a new issue