From 872dbea3900b09c78092d3cdf035513f400bcfe8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 27 Mar 2010 09:59:42 +0800 Subject: [PATCH] Cleanup Commit - Adding a hell of a lot of files to the tree > EDI Interface (Incomplete) > AxWin Shell (Incomplete, Needs to be rewritten) > AxWin library and headers - Restructuring AxWin to be non-windowed - Changes to IpStack - Fixes to kernel logging - Added APIDoc files - Cleaning up ifconfig and other helpers --- Kernel/Makefile.BuildNum | 2 +- Kernel/include/acess.h | 10 + Kernel/include/apidoc/arch_x86.h | 38 ++ Kernel/lib.c | 19 +- Kernel/logging.c | 56 +- Makefile.cfg | 2 +- Modules/Filesystems/InitRD/.gitignore | 1 + Modules/IPStack/ipstack.h | 1 + Modules/IPStack/main.c | 16 +- Modules/Interfaces/EDI/Makefile | 10 + Modules/Interfaces/EDI/edi/acess-edi.h | 41 ++ Modules/Interfaces/EDI/edi/edi.h | 114 ++++ Modules/Interfaces/EDI/edi/edi_devices.h | 135 +++++ Modules/Interfaces/EDI/edi/edi_dma_streams.h | 52 ++ Modules/Interfaces/EDI/edi/edi_interrupts.h | 65 +++ .../Interfaces/EDI/edi/edi_memory_mapping.h | 86 +++ Modules/Interfaces/EDI/edi/edi_objects.h | 257 +++++++++ Modules/Interfaces/EDI/edi/edi_port_io.h | 90 ++++ Modules/Interfaces/EDI/edi/edi_pthreads.h | 175 ++++++ Modules/Interfaces/EDI/edi/helpers.h | 20 + Modules/Interfaces/EDI/edi_int.inc.c | 195 +++++++ Modules/Interfaces/EDI/edi_io.inc.c | 391 ++++++++++++++ Modules/Interfaces/EDI/main.c | 496 ++++++++++++++++++ .../axwin2_src/Shell_src/Makefile | 12 + .../Applications/axwin2_src/Shell_src/main.c | 30 ++ Usermode/Applications/axwin2_src/WM/common.h | 3 + Usermode/Applications/axwin2_src/WM/wm.h | 34 ++ Usermode/Applications/ifconfig_src/main.c | 7 + Usermode/Libraries/Makefile.tpl | 18 + Usermode/Libraries/libaxwin2.so_src/Makefile | 13 + Usermode/Libraries/libaxwin2.so_src/common.h | 26 + Usermode/Libraries/libaxwin2.so_src/main.c | 18 + .../Libraries/libaxwin2.so_src/messages.c | 65 +++ Usermode/Libraries/libaxwin2.so_src/windows.c | 70 +++ Usermode/include/axwin/axwin.h | 37 ++ Usermode/include/axwin/messages.h | 23 +- 36 files changed, 2579 insertions(+), 49 deletions(-) create mode 100644 Kernel/include/apidoc/arch_x86.h create mode 100644 Modules/Filesystems/InitRD/.gitignore create mode 100644 Modules/Interfaces/EDI/Makefile create mode 100644 Modules/Interfaces/EDI/edi/acess-edi.h create mode 100644 Modules/Interfaces/EDI/edi/edi.h create mode 100644 Modules/Interfaces/EDI/edi/edi_devices.h create mode 100644 Modules/Interfaces/EDI/edi/edi_dma_streams.h create mode 100644 Modules/Interfaces/EDI/edi/edi_interrupts.h create mode 100644 Modules/Interfaces/EDI/edi/edi_memory_mapping.h create mode 100644 Modules/Interfaces/EDI/edi/edi_objects.h create mode 100644 Modules/Interfaces/EDI/edi/edi_port_io.h create mode 100644 Modules/Interfaces/EDI/edi/edi_pthreads.h create mode 100644 Modules/Interfaces/EDI/edi/helpers.h create mode 100644 Modules/Interfaces/EDI/edi_int.inc.c create mode 100644 Modules/Interfaces/EDI/edi_io.inc.c create mode 100644 Modules/Interfaces/EDI/main.c create mode 100644 Usermode/Applications/axwin2_src/Shell_src/Makefile create mode 100644 Usermode/Applications/axwin2_src/Shell_src/main.c create mode 100644 Usermode/Applications/axwin2_src/WM/wm.h create mode 100644 Usermode/Libraries/Makefile.tpl create mode 100644 Usermode/Libraries/libaxwin2.so_src/Makefile create mode 100644 Usermode/Libraries/libaxwin2.so_src/common.h create mode 100644 Usermode/Libraries/libaxwin2.so_src/main.c create mode 100644 Usermode/Libraries/libaxwin2.so_src/messages.c create mode 100644 Usermode/Libraries/libaxwin2.so_src/windows.c create mode 100644 Usermode/include/axwin/axwin.h diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index b9b1128c..fa878fd1 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1563 +BUILD_NUM = 1586 diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index 9363dc0d..d4ea289a 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -101,6 +101,15 @@ extern void System_Init(char *ArgString); // --- IRQs --- extern int IRQ_AddHandler(int Num, void (*Callback)(int)); +// --- Logging --- +extern void Log_KernelPanic(char *Ident, char *Message, ...); +extern void Log_Panic(char *Ident, char *Message, ...); +extern void Log_Error(char *Ident, char *Message, ...); +extern void Log_Warning(char *Ident, char *Message, ...); +extern void Log_Log(char *Ident, char *Message, ...); +extern void Log_Notice(char *Ident, char *Message, ...); +extern void Log_Debug(char *Ident, char *Message, ...); + // --- Debug --- /** * \name Debugging and Errors @@ -300,6 +309,7 @@ extern int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list a extern int sprintf(char *__s, const char *__format, ...); extern Uint strlen(const char *Str); extern char *strcpy(char *__dest, const char *__src); +extern char *strncpy(char *__dest, const char *__src, size_t max); extern int strcmp(const char *__str1, const char *__str2); extern int strncmp(const char *Str1, const char *Str2, size_t num); extern int strucmp(const char *Str1, const char *Str2); diff --git a/Kernel/include/apidoc/arch_x86.h b/Kernel/include/apidoc/arch_x86.h new file mode 100644 index 00000000..7818c8c5 --- /dev/null +++ b/Kernel/include/apidoc/arch_x86.h @@ -0,0 +1,38 @@ +/** + * \file apidoc/arch_x86.h + * \brief x86(-64) Specific Functions + * \author John Hodge (thePowersGang) + * + * \section toc Table of Contents + * - \ref portio "Port IO" + * - \ref dma "DMA - Direct Memory Access" + * + * \section portio Port IO + * The x86 architecture has two memory spaces, the first is the system + * memory accessable using standard loads and stores. The second is the + * 16-bit IO Bus. This bus is accessed using the \a in and \a out opcodes + * and is used to configure devices attached to the system. + * A driver should not use \a in and \a out directly, but instead use + * the provided \a in* and \a out* functions to access the IO Bus. + * This allows the kernel to run a driver in userspace if requested without + * the binary needing to be altered. + * + * \section dma DMA - Direct Memory Access + */ + +/** + * \name IO Bus Access + * \{ + */ +extern Uint8 inb(Uint16 Port); //!< Read 1 byte from the IO Bus +extern Uint16 inw(Uint16 Port); //!< Read 2 bytes from the IO Bus +extern Uint32 inl(Uint16 Port); //!< Read 4 bytes from the IO Bus +extern Uint64 inq(Uint16 Port); //!< Read 8 bytes from the IO Bus\ + +extern void outb(Uint16 Port, Uint8 Value); //!< Write 1 byte to the IO Bus +extern void outw(Uint16 Port, Uint16 Value); //!< Write 2 bytes to the IO Bus +extern void outl(Uint16 Port, Uint32 Value); //!< Write 4 bytes to the IO Bus +extern void outq(Uint16 Port, Uint64 Value); //!< Write 8 bytes to the IO Bus +/** + * \} + */ diff --git a/Kernel/lib.c b/Kernel/lib.c index 62500fe9..eea64e0a 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -156,7 +156,14 @@ void itoa(char *buf, Uint num, int base, int minLength, char pad) buf[i] = 0; } -#define PUTCH(c) do{if(pos==__maxlen)break;if(__s){__s[pos++]=(c);}else{pos++;}}while(0) +/** + * \brief Append a character the the vsnprintf output + */ +#define PUTCH(c) do{\ + char ch=(c);\ + if(pos==__maxlen){return pos;}\ + if(__s){__s[pos++]=ch;}else{pos++;}\ + }while(0) int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) { char c, pad = ' '; @@ -167,12 +174,15 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) Uint64 val; size_t pos = 0; + Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)\n", __s, __maxlen, __format); + while((c = *__format++) != 0) { // Non control character if(c != '%') { PUTCH(c); continue; } c = *__format++; + //Log("pos = %i", pos); // Literal % if(c == '%') { PUTCH('%'); continue; } @@ -188,6 +198,8 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) // Get Argument val = va_arg(args, Uint); + //Log("val = %x", val); + // - Padding if(c == '0') { @@ -258,6 +270,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) case 's': p = (char*)(Uint)val; printString: + //Log("p = '%s'", p); if(!p) p = "(null)"; while(*p) PUTCH(*p++); break; @@ -274,14 +287,10 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) PUTCH( (Uint8)val ); break; } - - if(pos == __maxlen) - break; } if(__s && pos != __maxlen) __s[pos] = '\0'; - return pos; } diff --git a/Kernel/logging.c b/Kernel/logging.c index 567f64e3..ad63a21c 100644 --- a/Kernel/logging.c +++ b/Kernel/logging.c @@ -21,7 +21,7 @@ enum eLogLevels LOG_LEVEL_DEBUG, NUM_LOG_LEVELS }; -const char csaLevelCodes[] = {'k','p','f','e','w','n','l','d'}; +const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"}; // === TYPES === typedef struct sLogEntry @@ -29,7 +29,7 @@ typedef struct sLogEntry struct sLogEntry *Next; struct sLogEntry *LevelNext; Sint64 Time; - Uint64 Ident; + char Ident[8]; int Level; int Length; char Data[]; @@ -47,10 +47,19 @@ void Log_KernelPanic(char *Ident, char *Message, ...); void Log_Panic(char *Ident, char *Message, ...); void Log_Error(char *Ident, char *Message, ...); void Log_Warning(char *Ident, char *Message, ...); -void Log_Log(char *Ident, char *Message, ...); void Log_Notice(char *Ident, char *Message, ...); +void Log_Log(char *Ident, char *Message, ...); void Log_Debug(char *Ident, char *Message, ...); -static Uint64 Log_Int_GetIdent(const char *Str); +//static Uint64 Log_Int_GetIdent(const char *Str); + +// === EXPORTS === +EXPORT(Log_KernelPanic); +EXPORT(Log_Panic); +EXPORT(Log_Error); +EXPORT(Log_Warning); +EXPORT(Log_Notice); +EXPORT(Log_Log); +EXPORT(Log_Debug); // === GLOBALS === tSpinlock glLog; @@ -65,19 +74,23 @@ void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args) { int len; tLogEntry *ent; - Uint64 ident = Log_Int_GetIdent(Ident); if( Level >= NUM_LOG_LEVELS ) return; len = vsnprintf(NULL, 256, Format, Args); + Log("len = %i", len); + ent = malloc(sizeof(tLogEntry)+len+1); ent->Time = now(); - ent->Ident = ident; + strncpy(ent->Ident, Ident, 7); ent->Level = Level; ent->Length = len; vsnprintf( ent->Data, 256, Format, Args ); + Log("ent->Ident = '%s'", ent->Ident); + Log("ent->Data = '%s'", ent->Data); + LOCK( &glLog ); ent->Next = gLog.Tail; @@ -105,10 +118,10 @@ void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args) */ void Log_Int_PrintMessage(tLogEntry *Entry) { - LogF("%018%c [%8s] %s\n", + LogF("%018i% [%8s] %s\n", Entry->Time, csaLevelCodes[Entry->Level], - &Entry->Ident, + Entry->Ident, Entry->Data ); } @@ -190,30 +203,3 @@ void Log_Debug(char *Ident, char *Message, ...) Log_AddEvent(Ident, LOG_LEVEL_DEBUG, Message, args); va_end(args); } - -/** - * \brief Converts a string into a 64-bit ident - */ -static Uint64 Log_Int_GetIdent(const char *Str) -{ - Uint64 ret = 0; - int i; - char ch; - - for( i = 0; Str[i] && i < 7; i++ ) - { - ch = Str[i]; - - if(ch < ' ') - ch = '?'; - else if(ch > '~') - ch = '?'; - - ret |= (Uint64)ch << 8*i; - } - - for( ; i < 7; i++ ) - ret |= 0x20 << (8*i); - - return ret; -} diff --git a/Makefile.cfg b/Makefile.cfg index 4de3cd04..e4ae222e 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -30,7 +30,7 @@ MODULES += Network/NE2000 #MODULES += Display/BochsGA MODULES += Filesystems/Ext2 MODULES += Filesystems/FAT -#MODULES += IPStack +MODULES += IPStack DYNMODS = USB Interfaces/UDI #DISTROOT = /mnt/AcessHDD/Acess2 diff --git a/Modules/Filesystems/InitRD/.gitignore b/Modules/Filesystems/InitRD/.gitignore new file mode 100644 index 00000000..a3115058 --- /dev/null +++ b/Modules/Filesystems/InitRD/.gitignore @@ -0,0 +1 @@ +files.c diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index 54d8fb82..95f93c47 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -61,6 +61,7 @@ struct sAdapter { int NRef; tMacAddr MacAddr; + int DeviceLen; char Device[]; }; diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index e3803208..9b132ec8 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -268,6 +268,7 @@ static const char *casIOCtls_Iface[] = { "get_address", "set_address", "getset_subnet", "get_gateway", "set_gateway", + "get_device", "ping", NULL }; @@ -465,11 +466,23 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data) } break; + /* + * get_device + * - Gets the name of the attached device + */ + case 10: + if( Data == NULL ) + LEAVE_RET('i', iface->Adapter->DeviceLen); + if( !CheckMem( Data, iface->Adapter->DeviceLen+1 ) ) + LEAVE_RET('i', -1); + strcpy( Data, iface->Adapter->Device ); + return iface->Adapter->DeviceLen; + /* * ping * - Send an ICMP Echo */ - case 10: + case 11: switch(iface->Type) { case 0: @@ -588,6 +601,7 @@ tAdapter *IPStack_GetAdapter(char *Path) // Fill Structure strcpy( dev->Device, Path ); dev->NRef = 1; + dev->DeviceLen = strlen(Path); // Open Device dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE ); diff --git a/Modules/Interfaces/EDI/Makefile b/Modules/Interfaces/EDI/Makefile new file mode 100644 index 00000000..a93a8b7c --- /dev/null +++ b/Modules/Interfaces/EDI/Makefile @@ -0,0 +1,10 @@ +# +# EDI - Extensible Driver Interface +# +# Acess Interface + + +OBJ = main.o edi.o +NAME = EDI + +-include ../Makefile.tpl diff --git a/Modules/Interfaces/EDI/edi/acess-edi.h b/Modules/Interfaces/EDI/edi/acess-edi.h new file mode 100644 index 00000000..40713886 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/acess-edi.h @@ -0,0 +1,41 @@ +/*! \file acess-edi.h + * \brief Acess Specific EDI Objects + * + * Contains documentation and information for + * - Timers + */ + +/* Copyright (c) 2006 John Hodge + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#ifndef ACESS_EDI_H +#define ACESS_EDI_H + +#include "edi_objects.h" + +/// \brief Name of Acess EDI Time Class +#define ACESS_TIMER_CLASS "ACESSEDI-TIMER" + +#ifndef IMPLEMENTING_EDI +/*! \brief int32_t ACESSEDI-TIMER.init_timer(uint32_t Delay, void (*Callback)(int), int Arg); + * + * Takes a timer pointer and intialises the timer object to fire after \a Delay ms + * When the timer fires, \a Callback is called with \a Arg passed to it. + */ +EDI_DEFVAR int32_t (*init_timer)(object_pointer port_object, uint32_t Delay, void (*fcn)(int), int arg); + +/*! \brief void ACESSEDI-TIMER.disable_timer(); + * + * Disables the timer and prevents it from firing + * After this has been called, the timer can then be initialised again. + */ +EDI_DEFVAR void (*disable_timer)(object_pointer port_object); + + +#endif // defined(IMPLEMENTING_EDI) + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi.h b/Modules/Interfaces/EDI/edi/edi.h new file mode 100644 index 00000000..273f7a3d --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi.h @@ -0,0 +1,114 @@ +#ifndef EDI_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_H +/*! \file edi.h + * \brief The unitive EDI header to include others, start EDI, and stop EDI. + * + * Data structures and algorithms this header represents: + * DATA STRUCTURE: CLASS QUOTAS - The runtime and the driver have the right to set a quota on how many objects of a given class + * owned by that party the other may construct. These quotas are kept internally by the driver or runtime, are optional and are + * exposed to the other party via the quota() function (for quotas of runtime-owned classes) and the k_quota() function pointer given + * to the runtime by the driver. + * + * ALGORITHMS: INITIALIZATION AND SHUTDOWN - On initialization of the runtime's EDI environment for this driver it calls the + * driver's driver_init() routine (which must match driver_init_t) to initialize the driver with a list of EDI objects the runtime + * thinks the driver should run with. The driver then initializes. This can include calling edi_negotiate_resources() to try and + * obtain more or different objects. Eventually driver_init() returns an edi_initialization_t structure containing its quota + * function and the list of classes belonging to the driver which the runtime can construct. Either the driver or the runtime can + * shut down EDI by calling edi_shutdown(), which in turn calls the driver's driver_finish() routine. On shutdown all objects, of + * classes belonging to both the runtime and driver, are destroyed. */ + +#include "edi_objects.h" +#include "edi_dma_streams.h" +#include "edi_pthreads.h" +#include "edi_port_io.h" +#include "edi_memory_mapping.h" +#include "edi_devices.h" +#include "edi_interrupts.h" + +/*! \brief A pointer to a function the runtime can call if it fails to construct one of the driver's classes to find out what the + * runtime's quota is for that class. + * + * A pointer to a function which takes an edi_string_t as a parameter and returns in int32_t. This function follows the same + * semantics as the quota() function, returning the number of objects of the given class that can be constructed, -1 for infinity or + * -2 for an erroneous class name. It is used to tell the runtime the location of such a function in the driver so that the runtime + * can check quotas on driver-owned classes. */ +typedef int32_t (*k_quota_t)(edi_string_t resource_class); +/*!\struct edi_initialization_t + * \brief Structure containing driver classes available to the runtime and the driver's quota function after the driver has initialized. + * + * Structure containing driver classes available to runtime, the driver's quota function and the driver's name provided to the runtime + * after the driver has initialized. driver_bus, vendor_id, and device_id are all optional fields which coders should consider + * supplementary information. Kernels can require these fields if they so please, but doing so for devices which don't run on a Vendor + * ID/Product ID supporting bus is rather unwise. */ +typedef struct { + /*!\brief The number of driver classes in the driver_classes array. */ + int32_t num_driver_classes; + /*!\brief An array of declarations of driver classes available to the runtime. + * + * This array should not necessarily contain the entire list of EDI classes implemented by the driver. Instead, it should + * contain a list of those classes which the driver has correctly initialized itself to provide instances of with full + * functionality. */ + edi_class_declaration_t *driver_classes; + /*!\brief The driver's quota function. */ + k_quota_t k_quota; + /*!\brief The driver's name. */ + edi_string_t driver_name; + /*!\brief The bus of the device this driver wants to drive, if applicable. + * + * The driver does not have to supply this field, and can also supply "MULTIPLE BUSES" here to indicate that it drives devices + * on multiple buses. */ + edi_string_t driver_bus; + /*!\brief The driver's vendor ID, if applicable. + * + * The driver does not need to supply this field, and should supply -1 to indicate that it does not wish to. */ + int16_t vendor_id; + /*!\brief The driver's device ID, if applicable. + * + * The driver does not need to supply this field, but can supply it along with vendor_id. If either vendor_id or this field are + * set to -1 the runtime should consider this field not supplied. */ + int16_t driver_id; +} edi_initialization_t; +/*!\brief A pointer to a driver's initialization function. + * + * The protocol for the driver's initialization function. The runtime gives the driver a set of EDI objects representing the + * resources it thinks the driver should run with. This function returns an edi_initialization_t structure containing declarations + * of the EDI classes the driver can make available to the runtime after initialization. If any member of that structure contains 0 + * or NULL, it is considered invalid and the runtime should destroy the driver without calling its driver_finish() routine. */ +typedef edi_initialization_t (*driver_init_t)(int32_t num_resources,edi_object_metadata_t *resources); +/*!\brief Requests more resources from the runtime. Can be called during driver initialization. + * + * Called to negotiate with the runtime for the right to create further EDI objects/obtain further resources owned by the runtime. + * When the driver calls this routine, the runtime decides whether to grant more resources. If yes, this call returns true, and the + * driver can proceed to try and create the objects it desires, in addition to destroying EDI objects it doesn't want. Otherwise, + * it returns false. + * The driver must deal with whatever value this routine returns. */ +bool edi_negotiate_resources(); + +/*! \brief Returns the driver's quota of objects for a given runtime-owned class. + * + * This function takes an edi_string_t with the name of a runtime-owned class in it and returns the number of objects of that class + * which drivers can construct, -1 for infinity, or -2 for an erroneous class name. */ +int32_t quota(edi_string_t resource_class); +/*! \brief Sends a string to the operating systems debug output or logging facilities. */ +void edi_debug_write(uint32_t debug_string_length, char *debug_string); +/*! \brief This call destroys all objects and shuts down the entire EDI environment of the driver. + * + * This function shuts down EDI as described in INITIALIZATION AND SHUTDOWN above. All objects are destroyed, EDI functions can no + * longer be successfully called, etc. This function only succeeds when EDI has already been initialized, so it returns -1 when EDI + * hasn't been, 1 on success, or 0 for all other errors. */ +int32_t shutdown_edi(void); + +/*!\brief A pointer to the driver's finishing/shutdown function. + * + * The protocol for the driver's shutting down. This function should do anything the driver wants done before it dies. */ +typedef void (*driver_finish_t)(); + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_devices.h b/Modules/Interfaces/EDI/edi/edi_devices.h new file mode 100644 index 00000000..245e01f3 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_devices.h @@ -0,0 +1,135 @@ +#ifndef EDI_DEVICES_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +/* Edited by thePowersGang (John Hodge) June 2009 + * - Add #ifdef EDI_MAIN_FILE + */ + +#define EDI_DEVICES_H + +/*! \file edi_devices.h + * \brief Declaration and description of simple classes for implementation by EDI drivers to represent hardware devices. + * + * Data structures and algorithms this header represents: + * + * DATA STRUCTURE AND ALGORITHM: BASIC DEVICES - There are two functions, select() for waiting on devices and ioctl() for + * controlling them, common to many POSIX devices. Implementations of EDI-CHARACTER-DEVICE or EDI-BLOCK-DEVICE may implement either of + * these or both, and users of such objects much query for the methods to see if they're supported. Obviously, runtime or driver + * developers don't *need* to support these. + * + * DATA STRUCTURE AND ALGORITHM: CHARACTER DEVICES - The class EDI-CHARACTER-DEVICE provides a very basic interface to character + * devices, which read and write streams of characters. As such, this class only provides read() and write(). The calls attempt a + * likeness to POSIX. + * + * DATA STRUCTURE AND ALGORITHM: BLOCK DEVICES - The class EDI-BLOCK-DEVICE provides a very basic interface to block devices, which + * can read(), write() and seek() to blocks of a specific size in an array of blocks with a specific size. Its declarations and + * semantics should behave like those of most POSIX operating systems. + * + * Note that EDI runtimes should not implement these classes. Their declarations are provided for drivers to implement. */ + +#include "edi_objects.h" + +/* Methods common to all EDI device classes specified in this header. */ + +/*!\brief EAGAIN returned by functions for block and character devices. + * + * Means that the amount of data the device has ready is less than count. */ +#define EAGAIN -1 +/*!\brief EBADOBJ returned by functions for block and character devices. + * + * Means that the object passed as the method's this point was not a valid object of the needed class. */ +#define EBADOBJ -2 +/*!\brief EINVAL returned by functions for block and character devices. + * + * Means that the method got passed invalid parameters. */ +#ifdef EINVAL +# undef EINVAL +#endif +#define EINVAL -3 + +/*!\brief select() type to wait until device is writable. */ +#define EDI_SELECT_WRITABLE 0 +/*!\brief select() type to wait until device is readable. */ +#define EDI_SELECT_READABLE 1 + +/*!\brief Argument to seek(). Sets the block offset (ie: the "current block" index) to the given whence value. */ +#define EDI_SEEK_SET 0 +/*!\brief Argument to seek(). Sets the block offset (ie: the "current block" index) to its current value + whence. */ +#define EDI_SEEK_CURRENT 1 + +#ifdef EDI_MAIN_FILE +/*!\brief Arguments to EDI's basic select() function. */ +edi_variable_declaration_t select_arguments[2] = {{"pointer void","device",1}, + {"unsigned int32_t","select_type",1}}; +/*!\brief Declaration of EDI's basic select() function. + * + * Contrary to the POSIX version, this select() puts its error codes in its return value. */ +edi_function_declaration_t select_declaration = {"int32_t","edi_device_select",0,2,select_arguments,NULL}; +#else +extern edi_function_declaration_t select_declaration; // Declare for non main files +#endif + +#ifdef EDI_MAIN_FILE +/*!\brief Arguments to EDI's basic ioctl() function. */ +edi_variable_declaration_t ioctl_arguments[3] = {{"pointer void","device",1},{"int32_t","request",1},{"pointer void","argp",1}}; +/*!\brief Declaration of EDI's basic ioctl() function. + * + * Contrary to the POSIX version, this ioctl() puts its error codes in its return value. */ +edi_function_declaration_t ioctl_declaration = {"int32_t","edi_device_ioctl",0,3,ioctl_arguments,NULL}; +#else +extern edi_class_declaration_t ioctl_declaration; // Declare for non main files +#endif + +#ifdef EDI_MAIN_FILE +/*!\brief Declaration of the arguments EDI-CHARACTER-DEVICE's read() and write() methods. */ +edi_variable_declaration_t chardev_read_write_arguments[3] = {{"pointer void","chardev",1}, + {"pointer void","buffer",1}, + {"unsigned int32_t","char_count",1}}; +/*!\brief Declarations of the methods of EDI-CHARACTER-DEVICE, read() and write(). + * + * The code pointers of these function declarations are all given as NULL. Driver developers implementing EDI-CHARACTER-DEVICE should + * fill in these entries with pointers to their own functions. */ +EDI_DEFVAR edi_function_declaration_t chardev_methods[2]= {{"int32_t","edi_chardev_read",0,3,chardev_read_write_arguments,NULL}, + {"int32_t","edi_chardev_write",0,3,chardev_read_write_arguments,NULL}}; +/*!\brief Declaration of the EDI-CHARACTER-DEVICE class. + * + * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent + * before passing the filled-in structure to the EDI runtime. */ +EDI_DEFVAR edi_class_declaration_t chardev_class = {"EDI-CHARACTER-DEVICE",0,2,chardev_methods,NULL,NULL,NULL}; +#else +extern edi_class_declaration_t chardev_class; // Declare for non main files +#endif + +#ifdef EDI_MAIN_FILE +/*!\brief Arguments to EDI-BLOCK-DEVICE's read() and write() methods. */ +edi_variable_declaration_t blockdev_read_write_arguments[3] = {{"pointer void","blockdev",1}, + {"pointer void","buffer",1}, + {"unsigned int32_t","blocks",1}}; +/*!\brief Arguments to EDI-BLOCK-DEVICE's seek() method. */ +edi_variable_declaration_t blockdev_seek_arguments[3] = {{"pointer void","blockdev",1}, + {"int32_t","offset",1}, + {"int32_t","whence",1}}; +/*!\brief Declaration of the methods of EDI-BLOCK-DEVICE, read(), write(), seek(), and get_block_size(). + * + * The code pointers of these function declarations are all given as NULL. Driver developers implementing EDI-BLOCK-DEVICE should fill + * these entries in with pointers to their own functions. */ +edi_function_declaration_t blockdev_methods[4] = {{"int32_t","edi_blockdev_read",0,3,blockdev_read_write_arguments,NULL}, + {"int32_t","edi_blockdev_write",0,3,blockdev_read_write_arguments,NULL}, + {"int32_t","edi_blockdev_seek",0,3,blockdev_seek_arguments,NULL}, + {"unsigned int32_t","edi_blockdev_get_block_size",0,0,NULL,NULL}}; +/*!\brief Declaration of the EDI-BLOCK-DEVICE class. + * + * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent + * before passing the filled-in structure to the EDI runtime. */ +edi_class_declaration_t blockdev_class = {"EDI-BLOCK-DEVICE",0,4,blockdev_methods,NULL,NULL,NULL}; +#else +extern edi_class_declaration_t blockdev_class; // Declare for non main files +#endif + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_dma_streams.h b/Modules/Interfaces/EDI/edi/edi_dma_streams.h new file mode 100644 index 00000000..8ab80ccb --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_dma_streams.h @@ -0,0 +1,52 @@ +#ifndef EDI_DMA_STREAMS_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_DMA_STREAMS_H + +/*! \file edi_dma_streams.h + * \brief EDI's stream subclass for handling Direct Memory Access hardware. + * + * Data structures and algorithms this header represents: + * + * DATA STRUCTURE: DMA STREAMS - DMA streams are objects of the class EDI-STREAM-DMA used to pass data between a buffer of + * memory and the computer's DMA hardware. It is the responsibility of the object to allocate memory for its stream memory buffer + * which can be used with DMA hardware and to program the DMA hardware for transmissions. DMA streams can be bidirectional if the + * correct DMA mode is used. */ + +#include "edi_objects.h" + +#define DMA_STREAM_CLASS "EDI-STREAM-DMA" + +/*! \brief The name of the EDI DMA stream class. + * + * An edi_string_t with the class name "EDI-STREAM-DMA" in it. */ +#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI) +const edi_string_t dma_stream_class = DMA_STREAM_CLASS; +#else +extern const edi_string_t dma_stream_class; +#endif + +#ifndef IMPLEMENTING_EDI +/*! \brief int32_t EDI-STREAM-DMA.init_dma_stream(unsigned int32_t channel,unsigned int32_t mode,unsigned int32_t buffer_pages); + * + * Pointer to the init_dma_stream() method of class EDI-STREAM-DMA, which initializes a DMA stream with a DMA channel, DMA mode, and + * the number of DMA-accessible memory pages to keep as a buffer. It will only work once per stream object. It's possible return + * values are 1 for sucess, -1 for invalid DMA channel, -2 for invalid DMA mode, -3 for inability to allocate enough buffer pages and + * 0 for all other errors. */ +EDI_DEFVAR int32_t (*init_dma_stream)(object_pointer stream, uint32_t channel, uint32_t mode, uint32_t buffer_pages); +/*! \brief int32_t EDI-STREAM-DMA.transmit(data_pointer *anchor,unsigned int32 num_bytes,bool sending); + * + * Pointer to the dma_stream_transmit() method of class EDI-STREAM-DMA, which transmits the given number of bytes of data through + * the DMA stream to/from the given anchor (either source or destination), in the given direction. It returns 1 on success, -1 on + * an uninitialized or invalid DMA stream object, -2 when the anchor was NULL or otherwise invalid, -3 if the DMA stream can't + * transmit in the given direction, and 0 for all other errors. */ +EDI_DEFVAR int32_t (*dma_stream_transmit)(object_pointer stream, data_pointer anchor, uint32_t num_bytes, bool sending); +#endif + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_interrupts.h b/Modules/Interfaces/EDI/edi/edi_interrupts.h new file mode 100644 index 00000000..ef2ffc9f --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_interrupts.h @@ -0,0 +1,65 @@ +#ifndef EDI_INTERRUPTS_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_INTERRUPTS_H + +/*! \file edi_interrupts.h + * \brief Declaration and description of EDI's interrupt handling class. + * + * Data structures and algorithms this header represents: + * DATA STRUCTURE AND ALGORITHM: INTERRUPT OBJECTS - The class EDI-INTERRUPT encapsulates the handling of machine interrupts. + * It is initialized with an interrupt number to handle and a handler routine to call when that interrupt occurs. Only a couple of + * guarantees are made to the driver regarding the runtime's implementation of interrupt handling: 1) That the driver's handler is + * called for every time the interrupt associated with a valid and initialized interrupt object occurs, in the order of the + * occurences, 2) That the runtime handle the architecture-specific (general to the entire machine, not just this device) + * end-of-interrupt code when the driver is called without first returning from the machine interrupt. Note that the runtime hands + * out interrupt numbers at its own discretion and policy. */ + +#include "edi_objects.h" + +/*! \brief Macro constant containing the name of the interrupt class + */ +#define INTERRUPTS_CLASS "EDI-INTERRUPT" +/*! \brief The name of EDI's interrupt-handling class. + * + * An edi_string_t holding the name of the runtime-implemented interrupt object class. It's value is "EDI-INTERRUPT". */ +#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI) +const edi_string_t interrupts_class = INTERRUPTS_CLASS; +#else +extern const edi_string_t interrupts_class; +#endif + +/*! \brief A pointer to an interrupt handling function. + * + * A pointer to a function called to handle interrupts. Its unsigned int32_t parameter is the interrupt number that is being + * handled. */ +typedef void (*interrupt_handler_t)(uint32_t interrupt_number); + +#ifndef IMPLEMENTING_EDI +/*! \brief Initializes an interrupt object with an interrupt number and a pointer to a handler function. + * + * A pointer to the init_interrupt() method of class EDI-INTERRUPT. This method initializes a newly-created interrupt object with an + * interrupt number and a pointer to the driver's handler of type interrupt_handler_t. It can only be called once per object, and + * returns 1 on success, fails with -1 when the interrupt number is invalid or unacceptable to the runtime, fails with -2 when the + * pointer to the driver's interrupt handler is invalid, and fails with -3 for all other errors. */ +EDI_DEFVAR int32_t (*init_interrupt)(object_pointer interrupt, uint32_t interrupt_number, interrupt_handler_t handler); +/*! \brief Get this interrupt object's interrupt number. */ +EDI_DEFVAR uint32_t (*interrupt_get_irq)(object_pointer interrupt); +/*! \brief Set a new handler for this interrupt object. */ +EDI_DEFVAR void (*interrupt_set_handler)(object_pointer interrupt, interrupt_handler_t handler); +/*! \brief Return from this interrupt, letting the runtime run any necessary End-Of-Interrupt code. + * + * A pointer to the interrupt_return() method of class EDI-INTERRUPT. This method returns from the interrupt designated by the + * calling interrupt object. If there is a machine-wide end-of-interrupt procedure and the driver was called during the handling of + * the machine interrupt (as opposed to delaying the handling and letting the runtime EOI), the runtime runs it during this method. + * This method has no return value, since once it's called control leaves the calling thread. */ +EDI_DEFVAR void (*interrupt_return)(object_pointer interrupt); +#endif + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_memory_mapping.h b/Modules/Interfaces/EDI/edi/edi_memory_mapping.h new file mode 100644 index 00000000..ba8dff35 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_memory_mapping.h @@ -0,0 +1,86 @@ +#ifndef EDI_MEMORY_MAPPING_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_MEMORY_MAPPING_H + +/*! \file edi_memory_mapping.h + * \brief Declaration and description of EDI's class for mapping physical pages into the driver's address space. + * + * Data structures and algorithms this header represents: + * ALGORITHM: MEMORY MAPPINGS - Memory mapping objects of the class EDI-MEMORY-MAPPING are used to give virtual (driver-visible) + * addresses to sections of physical memory. These can either be memory mappings belonging to hardware devices or plain RAM which + * the driver wants page-aligned. A memory mapping object is initialized with the physical address for the memory mapping and the + * number of pages the mapping takes up, or simply the desired length of the a physically contiguous buffer in pages. The class's + * two methods map the section of memory into and out of the driver's virtual address space. */ + +#include "edi_objects.h" + +/*! \brief The name of EDI's memory mapping class. + * + * An edi_string_t with the name of the memory mapping class, "EDI-MEMORY-MAPPING". */ +#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI) +const edi_string_t memory_mapping_class = "EDI-MEMORY-MAPPING"; +#else +extern const edi_string_t memory_mapping_class; +#endif + +/*! \brief Flag representing Strong Uncacheable caching method. */ +#define CACHING_STRONG_UNCACHEABLE 0 +/*! \brief Flag representing Uncacheable caching method. */ +#define CACHING_UNCACHEABLE 1 +/*! \brief Flag representing Write combining caching method. */ +#define CACHING_WRITE_COMBINING 2 +/*! \brief Flag representing Write Through caching method. */ +#define CACHING_WRITE_THROUGH 3 +/*! \brief Flag representing Write Back caching method. */ +#define CACHING_WRITE_BACK 3 +/*! \brief Flag representing Write Protected caching method. */ +#define CACHING_WRITE_PROTECTED 3 + +#ifndef IMPLEMENTING_EDI +/*! \brief Initialize an EDI-MEMORY-MAPPING object with a physical address range. + * + * This method takes the start_physical_address of a memory mapping and the number of pages in that mapping and uses these arguments + * to initialize an EDI-MEMORY-MAPPING object. It can only be called once per object. It returns 1 when successful, -1 when an + * invalid physical address is given (one that the runtime knows is neither a physical memory mapping belonging to a device nor + * normal RAM), -2 when the number of pages requested is bad (for the same reasons as the starting address can be bad), and 0 for + * all other errors. + * + * Note that this method can't be invoked on an object which has already initialized via init_memory_mapping_with_pages(). */ +EDI_DEFVAR int32_t (*init_memory_mapping_with_address)(object_pointer mapping, data_pointer start_physical_address, uint32_t pages); +/*! \brief Initialize an EDI-MEMORY-MAPPING object by requesting a number of new physical pages. + * + * This method takes a desired number of physical pages for a memory mapping, and uses that number to initialize an + * EDI-MEMORY-MAPPING object by creating a buffer of contiguous physical pages. It can only be called once per object. It returns + * 1 when successful, -1 when the request for pages cannot be fulfilled, and 0 for all other errors. + * + * Note that this method cannot be called if init_memory_mapping_with_address() has already been used on the given object. */ +EDI_DEFVAR int32_t (*init_memory_mapping_with_pages)(object_pointer mapping, uint32_t pages); +/*! \brief Map the memory-mapping into this driver's visible address space. + * + * This asks the runtime to map a given memory mapping into the driver's virtual address space. Its parameter is the address of a + * data_pointer to place the virtual address of the mapping into. This method returns 1 on success, -1 on an invalid argument, -2 + * for an uninitialized object, and 0 for all other errors. */ +EDI_DEFVAR int32_t (*map_in_mapping)(object_pointer mapping, data_pointer *address_mapped_to); +/*! \brief Unmap the memory mapping from this driver's visible address space. + * + * This method tries to map the given memory mapping out of the driver's virtual address space. It returns 1 for success, -1 + * for an uninitialized memory mapping object, -2 if the mapping isn't mapped into the driver's address space already, and 0 + * for all other errors. */ +EDI_DEFVAR int32_t (*map_out_mapping)(object_pointer mapping); + +/*! \brief Set the caching flags for a memory mapping. */ +EDI_DEFVAR void (*mapping_set_caching_method)(object_pointer mapping, uint32_t caching_method); +/*! \brief Get the current caching method for a memory mapping. */ +EDI_DEFVAR uint32_t (*mapping_get_caching_method)(object_pointer mapping); +/*! \brief Flush write-combining buffers on CPU to make sure changes to memory mapping actually get written. Only applies to a Write Combining caching method (I think.).*/ +EDI_DEFVAR void (*flush_write_combining_mapping)(object_pointer mapping); +#endif + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_objects.h b/Modules/Interfaces/EDI/edi/edi_objects.h new file mode 100644 index 00000000..0e479517 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_objects.h @@ -0,0 +1,257 @@ +#ifndef EDI_OBJECTS_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_OBJECTS_H + +/*! \file edi_objects.h + * \brief The header file for basic EDI types and the object system. + * + * This file contains declarations of EDI's primitive data types, as well as structures and functions for with the object system. + * It represents these data structures and algorithms: + * + * DATA STRUCTURE: THE CLASS LIST - EDI implementing runtime's must keep an internal list of classes implemented by the runtime + * and separate lists of classes implemented by each driver. Whoever implements a class is said to "own" that class. The + * internal format of this list is up to the runtime coders, but it must be possible to recreate the original list of + * edi_class_declaration structures the driver declared to the runtime from it. This list is declared to the runtime in an + * initialization function in the header edi.h. The object_class member of an edi_object_metadata structure must point to that + * object's class's entry in this list. + * + * ALGORITHM AND DATA STRUCTURE: CLASSES AND INHERITANCE - Classes are described using edi_class_declaration_t structures and + * follow very simple rules. All data is private and EDI provides no way to access instance data, so there are no member + * variable declarations. However, if the data isn't memory-protected (for example, driver data on the driver heap) EDI allows + * the possibility of pointer access to data, since runtime and driver coders could make use of that behavior. Classes may have + * one ancestor by declaring so in their class declaration structure, and if child methods are different then parent methods + * the children always override their parents. An EDI runtime must also be able to check the existence and ownership of a given + * class given its name in an edi_string_t. + * + * ALGORITHM: OBJECT CREATION AND DESTRUCTION - An EDI runtime should be able to call the constructor of a named class, put the + * resulting object_pointer into an edi_object_metadata_t and return that structure. The runtime should also be able to call an + * object's class's destructor when given a pointer to a valid edi_metadata_t for an already-existing object. Data equivalent + * to an edi_object_metadata_t should also be tracked by the runtime for every object in existence in case of sudden EDI shutdown + * (see edi.h). + * + * ALGORITHM: RUNTIME TYPE INFORMATION - When passed the data_pointer member of an edi_object_metadata_t to a valid object, an + * EDI runtime must be able to return an edi_string_t containing the name of that object's class and to return function_pointers + * to methods when the required information to find the correct method is given by calling a class's method getting function.*/ + +/* If the EDI headers are linked with the standard C library, they use its type definitions. Otherwise, equivalent definitions are + * made.*/ +#if __STDC_VERSION__ == 199901L +# include +# include +#else +# ifndef NULL +# define NULL ((void*)0) +# endif +typedef unsigned char bool; +# define true 1 +# define false 0 +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +#endif + +/*! \brief Define a variable in the header + */ +#ifdef EDI_MAIN_FILE +# define EDI_DEFVAR +#else +# define EDI_DEFVAR extern +#endif + +/*! \brief A pointer to the in-memory instance of an object. + * + * This type is sized just like a general C pointer type (whatever*) for the target architecture. It's passed as a first parameter + * to all methods, thus allowing EDI classes to be implemented as C++ classes and providing some protection from confusing objects + * with normal pointers. Equivalent to a C++ this pointer or an Object Pascal Self argument. */ +typedef void *object_pointer; +/*! \brief A basic pointer type pointing to arbitrary data in an arbitrary location. */ +typedef void *data_pointer; +/*! \brief A basic function pointer type. + * + * A pointer to a piece of code which can be called and return to its caller, used to distinguish between pointers to code and + * pointers to data. Its size is hardware-dependent. */ +typedef void (*function_pointer)(void); +/*! \brief The length of an EDI string without its null character. */ +#define EDI_STRING_LENGTH 31 +/*! \brief A type representing a 31-character long string with a terminating NULL character at the end. All of EDI uses this type + * for strings. + * + * A null-terminated string type which stores characters in int8s. It allows for 31 characters in each string, with the final + * character being the NULL terminator. Functions which use this type must check that its final character is NULL, a string which + * doesn't not have this property is invalid and insecure. I (the author of EDI) know and understand that this form of a string + * suffers from C programmer's disease, but I can't use anything else without either making string use far buggier or dragging + * everyone onto a better language than C. */ +typedef int8_t edi_string_t[0x20]; +/*! \brief A type representing a pointer form of #edi_string_t suitable for function returns + */ +typedef int8_t *edi_string_ptr_t; + +/*! \var EDI_BASE_TYPES + * \brief A constant array of edi_string_t's holding every available EDI primitive type. */ +/*! \var EDI_TYPE_MODIFIERS + * \brief A constant array of edi_string_t's holding available modifiers for EDI primitive types. */ +#ifdef IMPLEMENTING_EDI + const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg","edi_string_t"}; + const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"}; +#else + //extern const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg", "edi_string_t"}; + //extern const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"}; + extern const edi_string_t EDI_BASE_TYPES[9]; + extern const edi_string_t EDI_TYPE_MODIFIERS[2]; +#endif + +/*! \struct edi_object_metadata_t + * \brief A packed structure holding all data to identify an object to the EDI object system. */ +typedef struct { + /*! \brief Points to the instance data of the object represented by this structure. + * + * An object_pointer to the object this structure refers to. The this pointer, so to speak. */ + object_pointer object; + /*! \brief Points the internal record kept by the runtime describing the object's class. + * + * Points to wherever the runtime has stored the class data this object was built from. The class data doesn't need to be + * readable to the driver, and so this pointer can point to an arbitrary runtime-reachable location. */ + data_pointer object_class; +} edi_object_metadata_t; + +/*! \struct edi_variable_declaration_t + * \brief The data structure used to describe a variable declaration to the EDI object system. + * + * The data structure used to describe a variable declaration to the EDI object system. The context of the declaration depends on + * where the data structure appears, ie: alone, in a class declaration, in a parameter list, etc. */ +typedef struct { + /*! \brief The type of the declared variable. + * + * The type of the variable, which must be a valid EDI primitive type as specified in the constant EDI_BASE_TYPES and + * possibly modified by a modifier specified in the constant EDI_TYPE_MODIFIERS. */ + edi_string_t type; + /*! \brief The name of the declared variable. */ + edi_string_t name; + /*! \brief Number of array entries if this variable is an array declaration. + * + * An int32_t specifying the number of variables of 'type' in the array 'name'. For a single variable this value should + * simply be set to 1, for values greater than 1 a packed array of contiguous variables is being declared, and a value of 0 + * is invalid. */ + int32_t array_length; +} edi_variable_declaration_t; + +/*! \struct edi_function_declaration_t + * \brief The data structure used to declare a function to the EDI object system. */ +typedef struct { + /*! \brief The return type of the function. The same type rules which govern variable definitions apply here. */ + edi_string_t return_type; + /*! \brief The name of the declared function. */ + edi_string_t name; + /*! \brief The version number of the function, used to tell different implementations of the same function apart. */ + uint32_t version; + /*! \brief The number of arguments passed to the function. + * + * The number of entries in the member arguments that the object system should care about. Caring about less misses + * parameters to functions, caring about more results in buffer overflows. */ + uint32_t num_arguments; + /*! \brief An array of the declared function's arguments. + * + * A pointer to an array num_arguments long containing edi_variable_declaration_t's for each argument to the declared + * function.*/ + edi_variable_declaration_t *arguments; + /*!\brief A pointer to the declared function's code in memory. */ + function_pointer code; +} edi_function_declaration_t; + +/*! \brief A pointer to a function for constructing instances of a class. + * + * A pointer to a function which takes no parameters and returns an object_pointer pointing to the newly made instance of a class. + * It is the constructor's responsibility to allocate memory for the new object. Each EDI class needs one of these. */ +typedef object_pointer (*edi_constructor_t)(void); +/*! \brief A pointer to a function for destroying instances of a class. + * + * A pointer to a function which takes an object_pointer as a parameter and returns void. This is the destructor counterpart to a + * class's edi_constructor_t, it destroys the object pointed to by its parameter and frees the object's memory. Every class must + * have one */ +typedef void (*edi_destructor_t)(object_pointer); + +/*! \brief Information the driver must give the runtime about its classes so EDI can construct them and call their methods. + * + * A structure used to declare a class to an EDI runtime so instances of it can be constructed by the EDI object system. */ +typedef struct { + /*! \brief The name of the class declared by the structure. */ + edi_string_t name; + /*! \brief The version of the class. This number is used to tell identically named but differently + * implemented classes apart.*/ + uint32_t version; + /*! \brief The number of methods in the 'methods' function declaration array. */ + uint32_t num_methods; + /*! \brief An array of edi_function_declaration_t declaring the methods of this class. */ + edi_function_declaration_t *methods; + /*! \brief Allocates the memory for a new object of the declared class and constructs the object. Absolutely required.*/ + edi_constructor_t constructor; + /*! \brief Destroys the given object of the declared class and frees its memory. Absolutely required. */ + edi_destructor_t destructor; + /*! \brief A pointer to another EDI class declaration structure specifying the declared class's parent class. + * + * Points to a parent class declared in another class declaration. It can be NULL to mean this class has no parent. */ + struct edi_class_declaration_t *parent; +} edi_class_declaration_t; + +/*! \brief Checks the existence of the named class. + * + * This checks for the existence on THE CLASS LIST of the class named by its edi_string_t parameter and returns a signed int32_t. If + * the class isn't found (ie: it doesn't exist as far as EDI is concerned) -1 is returned, if the class is owned by the driver + * (implemented by the driver and declared to the runtime by the driver) 0, and if the class is owned by the runtime (implemented by + * the runtime) 1. */ +int32_t check_class_existence(edi_string_t class_name); +/*! \brief Constructs an object of the named class and returns its object_pointer and a data_pointer to its class data. + * + * Given a valid class name in an edi_string_t this function constructs the specified class and returns an edi_metadata_t describing + * the new object as detailed in OBJECT CREATION AND DESTRUCTION. If the construction fails it returns a structure full of NULL + * pointers. */ +edi_object_metadata_t construct_object(edi_string_t class_name); +/*! \brief Destroys the given object using its class data. + * + * As specified in OBJECT CREATION AND DESTRUCTION this function should destroy an object when given its valid edi_metadata_t. The + * destruction is accomplished by calling the class's destructor. */ +void destroy_object(edi_object_metadata_t object); +/*! \brief Obtains a function pointer to a named method of a given class. + * + * When given a valid data_pointer object_class from an edi_object_metadata_t and an edi_string_t representing the name of the + * desired method retrieves a function_pointer to the method's machine code in memory. If the desired method isn't found, NULL is + * returned. */ +function_pointer get_method_by_name(data_pointer object_class,edi_string_t method_name); +/*! \brief Obtains a function pointer to a method given by a declaration of the given class if the class's method matches the + * declaration. + * + * Works just like get_method_by_name(), but by giving an edi_function_declaration_t for the desired method instead of just its name. + * Performs detailed checking against THE CLASS LIST to make sure that the method returned exactly matches the declaration passed + * in. */ +function_pointer get_method_by_declaration(data_pointer object_class,edi_function_declaration_t declaration); + +/* Runtime typing information. */ +/*! \brief Returns the name of the class specified by a pointer to class data. + * + * Given the data_pointer to an object's class data as stored in an edi_object_metadata_t retrieves the name of the object's class + * and returns it in an edi_string_t. */ +edi_string_ptr_t get_object_class(data_pointer object_class); +/*! \brief Returns the name of a class's parent class. + * + * When given an edi_string_t with a class name in it, returns another edi_string_t containing the name of the class's parent, or an + * empty string. */ +edi_string_ptr_t get_class_parent(edi_string_t some_class); +/*! \brief Returns the internal class data of a named class (if it exists) or NULL. + * + * When given an edi_string_t with a valid class name in it, returns a pointer to the runtime's internal class data for that class. + * Otherwise, it returns NULL. */ +data_pointer get_internal_class(edi_string_t some_class); + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_port_io.h b/Modules/Interfaces/EDI/edi/edi_port_io.h new file mode 100644 index 00000000..a2a1773d --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_port_io.h @@ -0,0 +1,90 @@ +#ifndef EDI_PORT_IO_H + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +/* Modified by thePowersGang (John Hodge) + * - Surround variable definitions with an #ifdef IMPLEMENTING_EDI + */ + +#define EDI_PORT_IO_H + +/*! \file edi_port_io.h + * \brief Declaration and description of EDI's port I/O class. + * + * Data structures and algorithms this header represents: + * + * DATA STRUCTURE AND ALGORITHM: PORT I/O OBJECTS - A class named "EDI-IO-PORT" is defined as an encapsulation of the port I/O + * used on some machine architectures. Each object of this class represents a single I/O port which can be read from and written to + * in various sizes. Each port can be held by one object only at a time. */ + +#include "edi_objects.h" + +/*! \brief Macro to create methods for reading from ports. + * + * This macro creates four similar methods, differing in the size of the type they read from the I/O port held by the object. Their + * parameter is a pointer to the output type, which is filled with the value read from the I/O port. They return 1 for success, -1 + * for an uninitialized I/O port object, and 0 for other errors. */ +#define port_read_method(type,name) int32_t (*name)(object_pointer port_object, type *out) +/*! \brief Macro to create methods for writing to ports. + * + * This macro creates four more similar methods, differing in the size of the type they write to the I/O port held by the object. + * Their parameter is the value to write to the port. They return 1 for success, -1 for an uninitialized I/O port object and 0 for + * other errors. */ +#define port_write_method(type,name) int32_t (*name)(object_pointer port_object, type in) + +/*! \brief Name of EDI I/O port class. (Constant) + * + * A CPP constant with the value of #io_port_class */ +#define IO_PORT_CLASS "EDI-IO-PORT" +/*! \brief Name of EDI I/O port class. + * + * An edi_string_t containing the class name "EDI-IO-PORT". */ +#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI) +const edi_string_t io_port_class = IO_PORT_CLASS; +#else +extern const edi_string_t io_port_class; +#endif + +#ifndef IMPLEMENTING_EDI +/*! \brief int32_t EDI-IO-PORT.init_io_port(unsigned int16_t port); + * + * This method takes an unsigned int16_t representing a particular I/O port and initializes the invoked EDI-IO-PORT object with it. + * The method returns 1 if successful, -1 if the I/O port could not be obtained for the object, and 0 for all other errors. */ +EDI_DEFVAR int32_t (*init_io_port)(object_pointer port_object, uint16_t port); +/*! \brief Get the port number from a port object. */ +EDI_DEFVAR uint16_t (*get_port_number)(object_pointer port); +/*! \brief Method created by port_read_method() in order to read bytes (int8s) from I/O ports. */ +EDI_DEFVAR int32_t (*read_byte_io_port)(object_pointer port_object, int8_t *out); +/*! \brief Method created by port_read_method() in order to read words (int16s) from I/O ports. */ +EDI_DEFVAR int32_t (*read_word_io_port)(object_pointer port_object, int16_t *out); +/*! \brief Method created by port_read_method() in order to read longwords (int32s) from I/O ports. */ +EDI_DEFVAR int32_t (*read_long_io_port)(object_pointer port_object, int32_t *out); +/*! \brief Method created by port_read_method() in order to read long longwords (int64s) from I/O ports. */ +EDI_DEFVAR int32_t (*read_longlong_io_port)(object_pointer port_object,int64_t *out); +/*! \brief Method of EDI-IO-PORT to read long strings of data from I/O ports. + * + * Reads arbitrarily long strings of data from the given I/O port. Returns 1 for success, -1 for an uninitialized port object, -2 + * for a bad pointer to the destination buffer, and 0 for all other errors. */ +EDI_DEFVAR int32_t (*read_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *out); +/*! \brief Method created by port_write_method() in order to write bytes (int8s) to I/O ports. */ +EDI_DEFVAR int32_t (*write_byte_io_port)(object_pointer port_object, int8_t in); +/*! \brief Method created by port_write_method() in order to write words (int16s) to I/O ports. */ +EDI_DEFVAR int32_t (*write_word_io_port)(object_pointer port_object, int16_t in); +/*! \brief Method created by port_write_method() in order to write longwords (int32s) to I/O ports. */ +EDI_DEFVAR int32_t (*write_long_io_port)(object_pointer port_object, int32_t in); +/*! \brief Method created by port_write_method() in order to write long longwords (int64s) to I/O ports. */ +EDI_DEFVAR int32_t (*write_longlong_io_port)(object_pointer port_object, int64_t in); +/*! \brief Method of EDI-IO-PORT to write long strings of data to I/O ports. + * + * Writes arbitrarily long strings of data to the given I/O port. Returns 1 for success, -1 for an uninitialized port object, -2 + * for a bad pointer to the source buffer, and 0 for all other errors. */ +EDI_DEFVAR int32_t (*write_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *in); + +#endif // defined(IMPLEMENTING_EDI) + +#endif diff --git a/Modules/Interfaces/EDI/edi/edi_pthreads.h b/Modules/Interfaces/EDI/edi/edi_pthreads.h new file mode 100644 index 00000000..c21fa751 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/edi_pthreads.h @@ -0,0 +1,175 @@ +#ifndef EDI_PTHREADS + +/* Copyright (c) 2006 Eli Gottlieb. + * Permission is granted to copy, distribute and/or modify this document + * under the terms of the GNU Free Documentation License, Version 1.2 + * or any later version published by the Free Software Foundation; + * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + * Texts. A copy of the license is included in the file entitled "COPYING". */ + +#define EDI_PTHREADS +/*!\file edi_pthreads.h + * \brief A basic subset of POSIX Threads functionality, providing threading and thread synchronization. + * + * A very basic POSIX Threads interface. Note that pthreads are not a class, because none of these calls really gels with + * object-oriented programming. Also, if drivers aren't processes or threads under the implementing operating system a small + * threading system must be implemented in-runtime just to multiplex the pthreads of EDI drivers. Sorry about that. + * + * Data structures and algorithms this header represents: + * + * ALGORITHM AND DATA STRUCTURE: POSIX Threading - The runtime must provide enough of a POSIX threading interface to implement + * the calls described here. The actual multithreading must be performed by the runtime, and the runtime can implement that + * multithreading however it likes as long as the given POSIX Threads subset works. There is, however, a caveat: since the runtime + * calls the driver like it would a library, the driver must perceive all calls made to it by the runtime as running under one thread. + * From this thread the driver can create others. Such behavior is a quirk of EDI, and does not come from the POSIX standard. + * However, it is necessary to provide the driver with a thread for its own main codepaths. For further details on a given POSIX + * Threading routine, consult its Unix manual page. */ + +#include "edi_objects.h" + +/* Placeholder type definitions. Users of the PThreads interface only ever need to define pointers to these types. */ +/*!\brief Opaque POSIX Threading thread attribute type. */ +typedef void pthread_attr_t; +/*!\brief Opaque POSIX Threading mutex (mutual exclusion semaphore) type. */ +typedef void pthread_mutex_t; +/*!\brief Opaque POSIX Threading mutex attribute type. */ +typedef void pthread_mutex_attr_t; + +/*!\struct sched_param + * \brief POSIX Threading scheduler parameters for a thread. */ +typedef struct { + /*!\brief The priority of the thread. */ + int32_t sched_priority; +} sched_param; + +/*!\brief POSIX Threading thread identifier. */ +typedef uint32_t pthread_t; +/*!\brief POSIX Threading thread function type. + * + * A function pointer to a thread function, with the required signature of a thread function. A thread function takes one untyped + * pointer as an argument and returns an untyped pointer. Such a function is a thread's main routine: it's started with the thread, + * and the thread exits if it returns. */ +typedef void *(*pthread_function_t)(void*); + +/*!\brief Insufficient resources. */ +#define EAGAIN -1 +/*!\brief Invalid parameter. */ +#define EINVAL -2 +/*!\brief Permission denied. */ +#define EPERM -3 +/*!\brief Operation not supported. */ +#define ENOTSUP -4 +/*!\brief Priority scheduling for POSIX/multiple schedulers is not implemented. */ +#define ENOSYS -5 +/*!\brief Out of memory. */ +#define ENOMEM -6 +/*!\brief Deadlock. Crap. */ +#define EDEADLK -7 +/*!\brief Busy. Mutex already locked. */ +#define EBUSY -8 + +/*!\brief Scheduling policy for regular, non-realtime scheduling. The default. */ +#define SCHED_OTHER 0 +/*!\brief Real-time, first-in first-out scheduling policy. Requires special (superuser, where such a thing exists) permissions. */ +#define SCHED_FIFO 1 +/*!\brief Real-time, round-robin scheduling policy. Requires special (superuser, where such a thing exists) permissions. */ +#define SCHED_RR 0 + +/*!\brief Creates a new thread with the given attributes, thread function and arguments, giving back the thread ID of the new + * thread. + * + * pthread_create() creates a new thread of control that executes concurrently with the calling thread. The new thread applies the + * function start_routine, passing it arg as its argument. The attr argument specifies thread attributes to apply to the new thread; + * it can also be NULL for the default thread attributes (joinable with default scheduling policy). On success this function returns + * 0 and places the identifier of the new thread into thread_id. On an error, pthread_create() can return EAGAIN if insufficient + * runtime resources are available to create the requested thread, EINVAL a value specified by attributes is invalid, or EPERM if the + * caller doesn't have permissions to set the given attributes. + * + * For further information: man 3 pthread_create */ +int32_t pthread_create(pthread_t *thread_id, const pthread_attr_t *attributes, pthread_function_t thread_function, void *arguments); +/*!\brief Terminates the execution of the calling thread. The thread's exit code with by status, and this routine never returns. */ +void pthread_exit(void *status); +/*!\brief Returns the thread identifier of the calling thread. */ +pthread_t pthread_self(); +/*!\brief Compares two thread identifiers. + * + * Determines of the given two thread identifiers refer to the same thread. If so, returns non-zero. Otherwise, 0 is returned. */ +int32_t pthread_equal(pthread_t thread1, pthread_t thread2); +/*!\brief Used by the calling thread to relinquish use of the processor. The thread then waits in the run queue to be scheduled + * again. */ +void pthread_yield(); + +/*!\brief Gets the scheduling policy of the given attributes. + * + * Places the scheduling policy for attributes into policy. Returns 0 on success, EINVAL if attributes was invalid, and ENOSYS if + * priority scheduling/multiple scheduler support is not implemented. */ +int32_t pthread_attr_getschedpolicy(const pthread_attr_t *attributes, int32_t *policy); +/*!\brief Sets the scheduling policy of the given attributes. + * + * Requests a switch of scheduling policy to policy for the given attributes. Can return 0 for success, EINVAL if the given policy + * is not one of SCHED_OTHER, SCHED_FIFO or SCHED_RR or ENOTSUP if policy is either SCHED_FIFO or SCHED_RR and the driver is not + * running with correct privileges. */ +int32_t pthread_attr_setschedpolicy(pthread_attr_t *attributes, int32_t policy); + +/*!\brief Gets the scheduling paramaters (priority) from the given attributes. + * + * On success, stores scheduling parameters in param from attributes, and returns 0. Otherwise, returns non-zero error code, such + * as EINVAL if the attributes object is invalid. */ +int32_t pthread_attr_getschedparam(const pthread_attr_t *attributes, sched_param *param); +/*!\brief Sets the scheduling parameters (priority) of the given attributes. + * + * Requests that the runtime set the scheduling parameters (priority) of attributes from param. Returns 0 for success, EINVAL for an + * invalid attributes object, ENOSYS when multiple schedulers/priority scheduling is not implemented, and ENOTSUP when the value of + * param isn't supported/allowed. */ +int32_t pthread_attr_setschedparam(pthread_attr_t *attributes, const sched_param *param); + +/*!\brief The thread obtains its scheduling properties explicitly from its attributes structure. */ +#define PTHREAD_EXPLICIT_SCHED 1 +/*!\brief The thread inherits its scheduling properties from its parent thread. */ +#define PTHREAD_INHERIT_SCHED 0 + +/*!\brief Returns the inheritsched attribute of the given attributes. + * + * On success, returns 0 and places the inheritsched attribute from attributes into inherit. This attribute specifies where the + * thread's scheduling properites shall come from, and can be set to PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED. On failure it + * returns EINVAL if attributes was invalid or ENOSYS if multiple schedulers/priority scheduling isn't implemented. */ +int32_t pthread_attr_getinheritsched(const pthread_attr_t *attributes, int32_t *inherit); +/*!\brief Sets the inheritsched attribute of the given attributes. + * + * On success, places inherit into the inheritsched attribute of attributes and returns 0. inherit must either contain + * PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED. On failure, this routine returns EINVAL if attributes is invalid, ENOSYS when + * multiple schedulers/priority scheduling isn't implemented, and ENOSUP if the inheritsched attribute isn't supported. */ +int32_t pthread_attr_setinheritsched(pthread_attr_t *attributes, int32_t inherit); + +/*!\brief Creates a new POSIX Threads mutex, which will initially be unlocked. + * + * Creates a new mutex with the given attributes. If attributes is NULL, the default attributes will be used. The mutex starts out + * unlocked. On success, the new mutex resides in the mutex structure pointed to by mutex, and this routine routines 0. On failure, + * it returns EAGAIN if the system lacked sufficient non-memory resources to initialize the mutex, EBUSY if the given mutex is + * already initialized and in use, EINVAL if either parameter is invalid, and ENOMEM if the system lacks the memory for a new + * mutex. Note: All EDI mutexes are created with the default attributes, and are of type PTHREAD_MUTEX_ERRORCHECK. This means + * undefined behavior can never result from an badly placed function call. */ +int32_t pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutex_attr_t *attributes); +/*!\brief Locks the given mutex. + * + * Locks the given mutex. If the mutex is already locked, blocks the calling thread until it can acquire the lock. When this + * routine returns successfully, it will return 0 and the calling thread will own the lock of the mutex. If the call fails, it can + * return EINVAL when mutex is invalid or EDEADLK if the calling thread already owns the mutex. */ +int32_t pthread_mutex_lock(pthread_mutex_t *mutex); +/*!\brief Unlocks the given mutex. + * + * Unlocks the given mutex, returning 0 on success. On failure, it can return EINVAL when mutex is invalid or EPERM when the + * calling thread doesn't own the mutex. */ +int32_t pthread_mutex_unlock(pthread_mutex_t *mutex); +/*!\brief Tries to lock the given mutex, returning immediately even if the mutex is already locked. + * + * Attempts to lock the given mutex, but returns immediately if it can't acquire a lock. Returns 0 when it has acquired a lock, + * EBUSY if the mutex is already locked, or EINVAL if mutex is invalid. */ +int32_t pthread_mutex_trylock(pthread_mutex_t *mutex); +/*!\brief Destroys the given mutex, or at least the internal structure of it. + * + * Deletes the given mutex, making mutex invalid until it should be initialized by pthread_mutex_init(). Returns 0 on success, + * EINVAL when mutex is invalid, or EBUSY when mutex is locked or referenced by another thread. */ +int32_t pthread_mutex_destroy (pthread_mutex_t *mutex); + +#endif diff --git a/Modules/Interfaces/EDI/edi/helpers.h b/Modules/Interfaces/EDI/edi/helpers.h new file mode 100644 index 00000000..d7bc1388 --- /dev/null +++ b/Modules/Interfaces/EDI/edi/helpers.h @@ -0,0 +1,20 @@ +#ifndef HELPERS_H + +#define HELPERS_H + +#include + +// Locally Defined +bool edi_string_equal(edi_string_t x,edi_string_t y); +bool descends_from(data_pointer object_class,edi_string_t desired_class); +data_pointer get_actual_class(edi_string_t ancestor,int32_t num_objects,edi_object_metadata_t *objects); + +// Local Copy/set +void *memcpyd(void *dest, void *src, unsigned int count); + +// Implementation Defined Common functions +void *memcpy(void *dest, void *src, unsigned int count); +void *memmove(void *dest, void *src, unsigned int count); +void *realloc(void *ptr, unsigned int size); + +#endif diff --git a/Modules/Interfaces/EDI/edi_int.inc.c b/Modules/Interfaces/EDI/edi_int.inc.c new file mode 100644 index 00000000..0ab3359e --- /dev/null +++ b/Modules/Interfaces/EDI/edi_int.inc.c @@ -0,0 +1,195 @@ +/* + * AcessOS EDI Interface + * - IRQ Class + * + * By John Hodge (thePowersGang) + * + * This file has been released into the public domain. + * You are free to use it as you wish. + */ +#include "edi/edi.h" + +// === TYPES === +typedef struct { + uint16_t State; // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap) + uint16_t Num; + interrupt_handler_t Handler; +} tEdiIRQ; + +// === PROTOTYPES === +void EDI_Int_IRQ_Handler(tRegs *Regs); + +// === GLOBALS === +tEdiIRQ gEdi_IRQObjects[16]; + +// === FUNCTIONS === +/** + * \fn object_pointer Edi_Int_IRQ_Construct(void) + * \brief Creates a new IRQ Object + * \return Pointer to object + */ +object_pointer Edi_Int_IRQ_Construct(void) +{ + int i; + // Search for a free irq + for( i = 0; i < 16; i ++ ) + { + if(gEdi_IRQObjects[i].State) continue; + gEdi_IRQObjects[i].State = 1; + gEdi_IRQObjects[i].Num = 0; + gEdi_IRQObjects[i].Handler = NULL; + return &gEdi_IRQObjects[i]; + } + return NULL; +} + +/** + * \fn void Edi_Int_IRQ_Destruct(object_pointer Object) + * \brief Destruct an IRQ Object + * \param Object Object to destroy + */ +void Edi_Int_IRQ_Destruct(object_pointer Object) +{ + tEdiIRQ *obj; + + VALIDATE_PTR(Object,); + obj = GET_DATA(Object); + + if( !obj->State ) return; + + if( obj->Handler ) + irq_uninstall_handler( obj->Num ); + + if( obj->State & 0x8000 ) { // If in heap, free + free(Object); + } else { // Otherwise, mark as unallocated + obj->State = 0; + } +} + +/** + * \fn int32_t Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler) + * \brief Initialises an IRQ + * \param Object Object Pointer (this) + * \param Num IRQ Number to use + * \param Handler Callback for IRQ + */ +int32_t Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler) +{ + tEdiIRQ *obj; + + //LogF("Edi_Int_IRQ_InitInt: (Object=0x%x, Num=%i, Handler=0x%x)\n", Object, Num, Handler); + + VALIDATE_PTR(Object,0); + obj = GET_DATA(Object); + + if( !obj->State ) return 0; + + if(Num > 15) return 0; + + // Install the IRQ if a handler is passed + if(Handler) { + if( !irq_install_handler(Num, Edi_Int_IRQ_Handler) ) + return 0; + obj->Handler = Handler; + } + + obj->Num = Num; + obj->State &= ~0x3FFF; + obj->State |= 2; // Set initialised flag + return 1; +} + +/** + * \fn uint16_t Edi_Int_IRQ_GetInt(object_pointer Object) + * \brief Returns the irq number associated with the object + * \param Object IRQ Object to get number from + * \return IRQ Number + */ +uint16_t Edi_Int_IRQ_GetInt(object_pointer Object) +{ + tEdiIRQ *obj; + + VALIDATE_PTR(Object,0); + obj = GET_DATA(Object); + + if( !obj->State ) return 0; + return obj->Num; +} + +/** + * \fn void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler) + * \brief Set the IRQ handler for an IRQ object + * \param Object IRQ Object to alter + * \param Handler Function to use as handler + */ +void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler) +{ + tEdiIRQ *obj; + + // Get Data Pointer + VALIDATE_PTR(Object,); + obj = GET_DATA(Object); + + // Sanity Check arguments + if( !obj->State ) return ; + + // Only register the mediator if it is not already + if( Handler && !obj->Handler ) + if( !irq_install_handler(obj->Num, Edi_Int_IRQ_Handler) ) + return ; + obj->Handler = Handler; +} + +/** + * \fn void EDI_Int_IRQ_Return(object_pointer Object) + * \brief Return from interrupt + * \param Object IRQ Object + * \note Due to the structure of acess interrupts, this is a dummy + */ +void EDI_Int_IRQ_Return(object_pointer Object) +{ +} + +/** + * \fn void Edi_Int_IRQ_Handler(struct regs *Regs) + * \brief EDI IRQ Handler - Calls the handler + * \param Regs Register state at IRQ call + */ +void Edi_Int_IRQ_Handler(struct regs *Regs) +{ + int i; + for( i = 0; i < 16; i ++ ) + { + if(!gEdi_IRQObjects[i].State) continue; // Unused, Skip + if(gEdi_IRQObjects[i].Num != Regs->int_no) continue; // Another IRQ, Skip + if(!gEdi_IRQObjects[i].Handler) continue; // No Handler, Skip + gEdi_IRQObjects[i].Handler( Regs->int_no ); // Call Handler + return; + } +} + + +// === CLASS DECLARATION === +static edi_function_declaration_t scEdi_Int_Functions_IRQ[] = { + {"int32_t", "init_interrupt", 1, 3, NULL, //scEdi_Int_Variables_IO[0], + (function_pointer)Edi_Int_IRQ_InitInt + }, + {"uint32_t", "interrupt_get_irq", 1, 1, NULL, //scEdi_Int_Variables_IO[1], + (function_pointer)Edi_Int_IRQ_GetInt + }, + {"void", "interrupt_set_handler", 1, 2, NULL, //scEdi_Int_Variables_IO[2], + (function_pointer)Edi_Int_IRQ_GetInt + }, + {"void", "interrupt_return", 1, 1, NULL, //scEdi_Int_Variables_IO[3], + (function_pointer)Edi_Int_IRQ_GetInt + } + }; +static edi_class_declaration_t scEdi_Int_Class_IRQ = + { + INTERRUPTS_CLASS, 1, 12, + scEdi_Int_Functions_IRQ, + Edi_Int_IRQ_Construct, + Edi_Int_IRQ_Destruct, + NULL + }; diff --git a/Modules/Interfaces/EDI/edi_io.inc.c b/Modules/Interfaces/EDI/edi_io.inc.c new file mode 100644 index 00000000..8a6ef22e --- /dev/null +++ b/Modules/Interfaces/EDI/edi_io.inc.c @@ -0,0 +1,391 @@ +/* + * AcessOS EDI Interface + * - IO Port Class + * + * By John Hodge (thePowersGang) + * + * This file has been released into the public domain. + * You are free to use it as you wish. + */ +#include "edi/edi.h" + +// === TYPES === +typedef struct { + uint16_t State; // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap) + uint16_t Num; +} tEdiPort; + +// === GLOBALS === +#define NUM_PREALLOC_PORTS 128 +tEdiPort gEdi_PortObjects[NUM_PREALLOC_PORTS]; + +// === FUNCTIONS === +/** + * \fn object_pointer Edi_Int_IO_Construct(void) + * \brief Creates a new IO Port Object + * \return Pointer to object + */ +object_pointer Edi_Int_IO_Construct(void) +{ + tEdiPort *ret; + int i; + // Search for a free preallocated port + for( i = 0; i < NUM_PREALLOC_PORTS; i ++ ) + { + if(gEdi_PortObjects[i].State) continue; + gEdi_PortObjects[i].State = 1; + gEdi_PortObjects[i].Num = 0; + return &gEdi_PortObjects[i]; + } + // Else, use heap space + ret = malloc( sizeof(tEdiPort) ); + ret->State = 0x8001; + ret->Num = 0; + return ret; +} + +/** + * \fn void Edi_Int_IO_Destruct(object_pointer Object) + * \brief Destruct an IO Port Object + * \param Object Object to destroy + */ +void Edi_Int_IO_Destruct(object_pointer Object) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object,); + obj = GET_DATA(Object); + + if(obj->State & 0x8000) { // If in heap, free + free(Object); + } else { // Otherwise, mark as unallocated + obj->State = 0; + } +} + +/** + * \fn int32_t Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port) + * \brief Initialises an IO Port + * \param Object Object Pointer (this) + * \param Port Port Number to use + */ +int32_t Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + + if( !obj->State ) return 0; + obj->Num = Port; + obj->State &= ~0x3FFF; + obj->State |= 2; // Set initialised flag + return 1; +} + +/** + * \fn uint16_t Edi_Int_IO_GetPortNum(object_pointer Object) + * \brief Returns the port number associated with the object + * \param Object Port Object to get number from + * \return Port Number + */ +uint16_t Edi_Int_IO_GetPortNum(object_pointer Object) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + // Check if valid + if( !obj->State ) return 0; + // Return Port No + return obj->Num; +} + +/** + * \fn int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out) + * \brief Read a byte from an IO port + * \param Object Port Object + * \param out Pointer to put read data + */ +int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "inb %%dx, %%al" : "=a" (*out) : "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out) + * \brief Read a word from an IO port + * \param Object Port Object + * \param out Pointer to put read data + */ +int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out) +{ + + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "inw %%dx, %%ax" : "=a" (*out) : "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out) + * \brief Read a double word from an IO port + * \param Object Port Object + * \param out Pointer to put read data + */ +int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out) +{ + + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out) : "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out) + * \brief Read a quad word from an IO port + * \param Object Port Object + * \param out Pointer to put read data + */ +int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out) +{ + uint32_t *out32 = (uint32_t*)out; + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out32) : "d" ( obj->Num ) ); + __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*(out32+1)) : "d" ( obj->Num+4 ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out) + * \brief Read a byte from an IO port + * \param Object Port Object + * \param Length Number of bytes to read + * \param out Pointer to put read data + */ +int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "rep insb" : : "c" (Length), "D" (out), "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in) + * \brief Write a byte from an IO port + * \param Object Port Object + * \param in Data to write + */ +int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "outb %%al, %%dx" : : "a" (in), "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in) + * \brief Write a word from an IO port + * \param Object Port Object + * \param in Data to write + */ +int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "outw %%ax, %%dx" : : "a" (in), "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in) + * \brief Write a double word from an IO port + * \param Object Port Object + * \param in Data to write + */ +int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (in), "d" ( obj->Num ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in) + * \brief Write a quad word from an IO port + * \param Object Port Object + * \param in Data to write + */ +int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in) +{ + uint32_t *in32 = (uint32_t*)∈ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*in32), "d" ( obj->Num ) ); + __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*(in32+1)), "d" ( obj->Num+4 ) ); + + return 1; +} + +/** + * \fn int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in) + * \brief Read a byte from an IO port + * \param Object Port Object + * \param Length Number of bytes to write + * \param in Pointer to of data to write + */ +int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in) +{ + tEdiPort *obj; + // Get Data Pointer + VALIDATE_PTR(Object, 0); + obj = GET_DATA(Object); + if( !obj->State ) return 0; + if( obj->State & 1 ) return -1; // Unintialised + + __asm__ __volatile__ ( "rep outsb" : : "c" (Length), "D" (in), "d" ( obj->Num ) ); + + return 1; +} + +// === CLASS DECLARATION === +/*static edi_variable_declaration_t *scEdi_Int_Variables_IO[] = { + { + {"pointer", "port_object", 0}, + {"uint16_t", "port", 0} + }, + { + {"pointer", "port_object", 0} + }, + { + {"pointer", "port_object", 0}, + {"pointer int8_t", "out", 0} + } +};*/ +static edi_function_declaration_t scEdi_Int_Functions_IO[] = { + {"int32_t", "init_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[0], + (function_pointer)Edi_Int_IO_InitPort + }, + {"uint16_t", "get_port_number", 1, 1, NULL, //scEdi_Int_Variables_IO[1], + (function_pointer)Edi_Int_IO_GetPortNum + }, + {"int32_t", "read_byte_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[2], + (function_pointer)Edi_Int_IO_ReadByte + }, + {"int32_t", "read_word_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"pointer int16_t", "out", 0} + }*/, + (function_pointer)Edi_Int_IO_ReadWord + }, + {"int32_t", "read_long_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"pointer int32_t", "out", 0} + }*/, + (function_pointer)Edi_Int_IO_ReadDWord + }, + {"int32_t", "read_longlong_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"pointer int64_t", "out", 0} + }*/, + (function_pointer)Edi_Int_IO_ReadQWord + }, + {"int32_t", "read_string_io_port", 1, 3, NULL/*{ + {"pointer", "port_object", 0}, + {"int32_T", "data_length", 0}, + {"pointer int64_t", "out", 0} + }*/, + (function_pointer)Edi_Int_IO_ReadString + }, + + {"int32_t", "write_byte_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"int8_t", "in", 0} + }*/, + (function_pointer)Edi_Int_IO_WriteByte}, + {"int32_t", "write_word_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"int16_t", "in", 0} + }*/, + (function_pointer)Edi_Int_IO_WriteWord}, + {"int32_t", "write_long_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"int32_t", "in", 0} + }*/, + (function_pointer)Edi_Int_IO_WriteDWord}, + {"int32_t", "write_longlong_io_port", 1, 2, NULL/*{ + {"pointer", "port_object", 0}, + {"int64_t", "in", 0} + }*/, + (function_pointer)Edi_Int_IO_WriteQWord} + }; +static edi_class_declaration_t scEdi_Int_Class_IO = + { + IO_PORT_CLASS, 1, 12, + scEdi_Int_Functions_IO, + Edi_Int_IO_Construct, + Edi_Int_IO_Destruct, + NULL + }; diff --git a/Modules/Interfaces/EDI/main.c b/Modules/Interfaces/EDI/main.c new file mode 100644 index 00000000..c3d0272a --- /dev/null +++ b/Modules/Interfaces/EDI/main.c @@ -0,0 +1,496 @@ +/* + * Acess2 EDI Layer + */ +#define DEBUG 0 +#define VERSION ((0<<8)|1) +#include +#include +#include +#define IMPLEMENTING_EDI 1 +#include "edi/edi.h" + +#define VALIDATE_PTR(_ptr,_err) do{if(!(_ptr))return _err; }while(0) +#define GET_DATA(_ptr) (Object) + +#include "edi_io.inc.c" +#include "edi_int.inc.c" + +// === STRUCTURES === +typedef struct sAcessEdiDriver { + struct sAcessEdiDriver *Next; + tDevFS_Driver Driver; + int FileCount; + struct { + char *Name; + tVFS_Node Node; + } *Files; + edi_object_metadata_t *Objects; + edi_initialization_t Init; + driver_finish_t Finish; +} tAcessEdiDriver; + +// === PROTOTYPES === + int EDI_Install(char **Arguments); + int EDI_DetectDriver(void *Base); + int EDI_LoadDriver(void *Base); +vfs_node *EDI_FS_ReadDir(vfs_node *Node, int Pos); +vfs_node *EDI_FS_FindDir(vfs_node *Node, char *Name); + int EDI_FS_CharRead(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + int EDI_FS_CharWrite(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + int EDI_FS_IOCtl(vfs_node *Node, int Id, void *Data); +data_pointer EDI_GetInternalClass(edi_string_t ClassName); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, EDI, EDI_Install, NULL, NULL); +tModuleLoader gEDI_Loader = { + NULL, "EDI", EDI_DetectDriver, EDI_LoadDriver, NULL +}; +tSpinlock glEDI_Drivers; +tAcessEdiDriver *gEdi_Drivers = NULL; +edi_class_declaration_t *gcEdi_IntClasses[] = { + &scEdi_Int_Class_IO, &scEdi_Int_Class_IRQ +}; +#define NUM_INT_CLASSES (sizeof(gcEdi_IntClasses)/sizeof(gcEdi_IntClasses[0])) +char *csCharNumbers[] = {"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"}; +char *csBlockNumbers[] = {"blk0", "blk1", "blk2", "blk3", "blk4", "blk5", "blk6", "blk7", "blk8", "blk9"}; + +// === CODE === +/** + * \fn int EDI_Install(char **Arguments) + * \brief Stub intialisation routine + */ +int EDI_Install(char **Arguments) +{ + Module_RegisterLoader( &gEDI_Loader ); + return 1; +} + +/** + * \brief Detects if a driver should be loaded by the EDI subsystem + */ +int EDI_DetectDriver(void *Base) +{ + if( Binary_FindSymbol(BASE, "driver_init", NULL) == 0 ) + return 0; + + return 1; +} + +/** + * \fn int Edi_LoadDriver(void *Base) + * \brief Load an EDI Driver from a loaded binary + * \param Base Binary Handle + * \return 0 on success, non zero on error + */ +int EDI_LoadDriver(void *Base) +{ + driver_init_t init; + driver_finish_t finish; + tAcessEdiDriver *info; + int i, j; + int devfsId; + edi_class_declaration_t *classes; + + ENTER("pBase", Base); + + // Get Functions + if( !Binary_FindSymbol(Base, "driver_init", (Uint*)&init) + || !Binary_FindSymbol(Base, "driver_finish", (Uint*)&finish) ) + { + Warning("[EDI ] Driver %p does not provide both `driver_init` and `driver_finish`\n", Base); + Binary_Unload(Base); + return 0; + } + + // Allocate Driver Information + info = malloc( sizeof(tAcessEdiDriver) ); + info->Finish = finish; + + // Initialise Driver + info->Init = init( 0, NULL ); // TODO: Implement Resources + + LOG("info->Init.driver_name = '%s'", info->Init.driver_name); + LOG("info->Init.num_driver_classes = %i", info->Init.num_driver_classes); + + // Count mappable classes + classes = info->Init.driver_classes; + info->FileCount = 0; + info->Objects = NULL; + for( i = 0, j = 0; i < info->Init.num_driver_classes; i++ ) + { + if( strncmp(classes[i].name, "EDI-CHARACTER-DEVICE", 32) == 0 ) + { + data_pointer *obj; + // Initialise Object Instances + for( ; (obj = classes[i].constructor()); j++ ) { + LOG("%i - Constructed '%s'", j, classes[i].name); + info->FileCount ++; + info->Objects = realloc(info->Objects, sizeof(*info->Objects)*info->FileCount); + info->Objects[j].object = obj; + info->Objects[j].object_class = &classes[i]; + } + } + else + LOG("%i - %s", i, classes[i].name); + } + + if(info->FileCount) + { + int iNumChar = 0; + // Create VFS Nodes + info->Files = malloc( info->FileCount * sizeof(*info->Files) ); + memset(info->Files, 0, info->FileCount * sizeof(*info->Files)); + j = 0; + for( j = 0; j < info->FileCount; j++ ) + { + classes = info->Objects[j].object_class; + if( strncmp(classes->name, "EDI-CHARACTER-DEVICE", 32) == 0 ) + { + LOG("%i - %s", j, csCharNumbers[iNumChar]); + info->Files[j].Name = csCharNumbers[iNumChar]; + info->Files[j].Node.NumACLs = 1; + info->Files[j].Node.ACLs = &gVFS_ACL_EveryoneRW; + info->Files[j].Node.ImplPtr = &info->Objects[j]; + info->Files[j].Node.Read = EDI_FS_CharRead; + info->Files[j].Node.Write = EDI_FS_CharWrite; + info->Files[j].Node.IOCtl = EDI_FS_IOCtl; + info->Files[j].Node.CTime = + info->Files[j].Node.MTime = + info->Files[j].Node.ATime = now(); + + iNumChar ++; + continue; + } + } + + // Create DevFS Driver + info->Driver.ioctl = EDI_FS_IOCtl; + memsetda(&info->Driver.rootNode, 0, sizeof(vfs_node) / 4); + info->Driver.Name = info->Init.driver_name; + info->Driver.RootNode.Flags = VFS_FFLAG_DIRECTORY; + info->Driver.RootNode.NumACLs = 1; + info->Driver.RootNode.ACLs = &gVFS_ACL_EveryoneRX; + info->Driver.RootNode.Length = info->FileCount; + info->Driver.RootNode.ImplPtr = info; + info->Driver.RootNode.ReadDir = EDI_FS_ReadDir; + info->Driver.RootNode.FindDir = EDI_FS_FindDir; + info->Driver.RootNode.IOCtl = EDI_FS_IOCtl; + + // Register + devfsId = dev_addDevice( &info->Driver ); + if(devfsId == -1) { + free(info->Files); // Free Files + info->Finish(); // Clean up driver + free(info); // Free info structure + Binary_Unload(iDriverBase); // Unload library + return -3; // Return error + } + } + + // Append to loaded list; + LOCK(&glEDI_Drivers); + info->Next = gEDI_Drivers; + gEDI_Drivers = info; + RELEASE(&glEDI_Drivers); + + LogF("[EDI ] Loaded Driver '%s' (%s)\n", info->Init.driver_name, Path); + LEAVE('i', 1); + return 1; +} + +// --- Filesystem Interaction --- +/** + * \brief Read from a drivers class list + * \param Node Driver's Root Node + * \param Pos Index of file to get + */ +char *EDI_FS_ReadDir(tVFS_Node *Node, int Pos) +{ + tAcessEdiDriver *info; + + // Sanity Check + if(!Node) return NULL; + + // Get Information Structure + info = (void *) Node->ImplPtr; + if(!info) return NULL; + + // Check Position + if(Pos < 0) return NULL; + if(Pos >= info->FileCount) return NULL; + + return strdup( info->Files[Pos].Name ); +} + +/** + * \fn tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name) + * \brief Find a named file in a driver + * \param Node Driver's Root Node + * \param Name Name of file to find + */ +tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name) +{ + tAcessEdiDriver *info; + int i; + + // Sanity Check + if(!Node) return NULL; + if(!Name) return NULL; + + // Get Information Structure + info = (void *) Node->ImplPtr; + if(!info) return NULL; + + for( i = 0; i < info->FileCount; i++ ) + { + if(strcmp(info->Files[i].name, Name) == 0) + return &info->Files[i].Node; + } + + return NULL; +} + +/** + * \fn Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read from an EDI Character Device + * \param Node File Node + * \param Offset Offset into file (ignored) + * \param Length Number of characters to read + * \param Buffer Destination for data + * \return Number of characters read + */ +Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + edi_object_metadata_t *meta; + edi_class_declaration_t *class; + + // Sanity Check + if(!Node || !Buffer) return 0; + if(Length <= 0) return 0; + // Get Object Metadata + meta = (void *) Node->ImplPtr; + if(!meta) return 0; + + // Get Class + class = meta->object_class; + if(!class) return 0; + + // Read from object + if( ((tAnyFunction) class->methods[0].code)( meta->object, Buffer, Length )) + return Length; + + return 0; +} + +/** + * \fn Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Write to an EDI Character Device + * \param Node File Node + * \param Offset Offset into file (ignored) + * \param Length Number of characters to write + * \param Buffer Source for data + * \return Number of characters written + */ +Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + edi_object_metadata_t *meta; + edi_class_declaration_t *class; + + // Sanity Check + if(!Node || !Buffer) return 0; + if(Length <= 0) return 0; + // Get Object Metadata + meta = (void *) Node->ImplPtr; + if(!meta) return 0; + + // Get Class + class = meta->object_class; + if(!class) return 0; + + // Write to object + if( ((tAnyFunction) class->methods[1].code)( meta->object, Buffer, Length )) + return Length; + + return 0; +} + +/** + * \fn int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief Perfom an IOCtl call on the object + */ +int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + return 0; +} + +// --- EDI Functions --- +/** + * \fn data_pointer EDI_GetDefinedClass(edi_string_t ClassName) + * \brief Gets the structure of a driver defined class + * \param ClassName Name of class to find + * \return Class definition or NULL + */ +data_pointer EDI_GetDefinedClass(edi_string_t ClassName) +{ + int i; + tAcessEdiDriver *drv; + edi_class_declaration_t *classes; + + for(drv = gEdi_Drivers; + drv; + drv = drv->Next ) + { + classes = drv->Init.driver_classes; + for( i = 0; i < drv->Init.num_driver_classes; i++ ) + { + if( strncmp(classes[i].name, ClassName, 32) == 0 ) + return &classes[i]; + } + } + return NULL; +} + +/** + * \fn int32_t EDI_CheckClassExistence(edi_string_t ClassName) + * \brief Checks if a class exists + * \param ClassName Name of class + * \return 1 if the class exists, -1 otherwise + */ +int32_t EDI_CheckClassExistence(edi_string_t ClassName) +{ + //LogF("check_class_existence: (ClassName='%s')\n", ClassName); + if(EDI_GetInternalClass(ClassName)) + return 1; + + if(EDI_GetDefinedClass(ClassName)) // Driver Defined + return 1; + + return -1; +} + +/** + * \fn edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName) + * \brief Construct an instance of an class (an object) + * \param ClassName Name of the class to construct + */ +edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName) +{ + edi_object_metadata_t ret = {0, 0}; + edi_class_declaration_t *class; + + //LogF("EDI_ConstructObject: (ClassName='%s')\n", ClassName); + + // Get class definition + if( !(class = EDI_GetInternalClass(ClassName)) ) // Internal + if( !(class = EDI_GetDefinedClass(ClassName)) ) // Driver Defined + return ret; // Return ERROR + + // Initialise + ret.object = class->constructor(); + if( !ret.object ) + return ret; // Return ERROR + + // Set declaration pointer + ret.object_class = class; + + //LogF("EDI_ConstructObject: RETURN {0x%x,0x%x}\n", ret.object, ret.object_class); + return ret; +} + +/** + * \fn void EDI_DestroyObject(edi_object_metadata_t Object) + * \brief Destroy an instance of a class + * \param Object Object to destroy + */ +void EDI_DestroyObject(edi_object_metadata_t Object) +{ + if( !Object.object ) return; + if( !Object.object_class ) return; + + ((edi_class_declaration_t*)(Object.object_class))->destructor( &Object ); +} + +/** + * \fn function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName) + * \brief Get a method of a class by it's name + * \param ObjectClass Pointer to a ::edi_object_metadata_t of the object + * \param MethodName Name of the desired method + * \return Function address or NULL + */ +function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName) +{ + edi_class_declaration_t *dec = ObjectClass; + int i; + + //LogF("get_method_by_name: (ObjectClass=0x%x, MethodName='%s')\n", ObjectClass, MethodName); + + if(!ObjectClass) return NULL; + + for(i = 0; i < dec->num_methods; i++) + { + if(strncmp(MethodName, dec->methods[i].name, 32) == 0) + return dec->methods[i].code; + } + return NULL; +} + +#if 0 +function_pointer get_method_by_declaration(data_pointer Class, edi_function_declaration_t Declaration); +#endif + +/** + * \fn edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName) + * \brief Get the parent of the named class + * \todo Implement + */ +edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName) +{ + WarningEx("EDI", "`get_class_parent` is unimplemented"); + return NULL; +} + +/** + * \fn data_pointer EDI_GetInternalClass(edi_string_t ClassName) + * \brief Get a builtin class + * \param ClassName Name of class to find + * \return Pointer to the ::edi_class_declaration_t of the class + */ +data_pointer EDI_GetInternalClass(edi_string_t ClassName) +{ + int i; + //LogF("get_internal_class: (ClassName='%s')\n", ClassName); + for( i = 0; i < NUM_INT_CLASSES; i++ ) + { + if( strncmp( gcEdi_IntClasses[i]->name, ClassName, 32 ) == 0 ) { + return gcEdi_IntClasses[i]; + } + } + //LogF("get_internal_class: RETURN NULL\n"); + return NULL; +} + +/** + * \fn edi_string_ptr_t EDI_GetObjectClass(data_pointer Object) + * \brief Get the name of the object of \a Object + * \param Object Object to get name of + * \return Pointer to the class name + */ +edi_string_ptr_t EDI_GetObjectClass(data_pointer ObjectClass) +{ + edi_object_metadata_t *Metadata = ObjectClass; + // Sanity Check + if(!ObjectClass) return NULL; + if(!(edi_class_declaration_t*) Metadata->object_class) return NULL; + + // Return Class Name + return ((edi_class_declaration_t*) Metadata->object_class)->name; +} + +// === EXPORTS === +EXPORTAS(EDI_CheckClassExistence, check_class_existence); +EXPORTAS(EDI_ConstructObject, construct_object); +EXPORTAS(EDI_DestroyObject, destroy_object); +EXPORTAS(EDI_GetMethodByName, get_method_by_name); +EXPORTAS(EDI_GetClassParent, get_class_parent); +EXPORTAS(EDI_GetInternalClass, get_internal_class); +EXPORTAS(EDI_GetObjectClass, get_object_class); diff --git a/Usermode/Applications/axwin2_src/Shell_src/Makefile b/Usermode/Applications/axwin2_src/Shell_src/Makefile new file mode 100644 index 00000000..18c4ab1e --- /dev/null +++ b/Usermode/Applications/axwin2_src/Shell_src/Makefile @@ -0,0 +1,12 @@ +# Project: Acess GUI Default Shell + +-include ../../Makefile.cfg + +CPPFLAGS += -I../include +LDFLAGS += -laxwin2 + +DIR = Apps/AxWin/1.0 +BIN = ../Shell +OBJ = main.o + +-include ../../Makefile.tpl diff --git a/Usermode/Applications/axwin2_src/Shell_src/main.c b/Usermode/Applications/axwin2_src/Shell_src/main.c new file mode 100644 index 00000000..b357dea5 --- /dev/null +++ b/Usermode/Applications/axwin2_src/Shell_src/main.c @@ -0,0 +1,30 @@ +/* + * Acess2 GUI Shell + * - By John Hodge (thePowersGang) + */ +#include + +// === PROTOTYPES === + int main(int argc, char *argv[]); + int Menubar_HandleMessage(tAxWin_Message *Message); + +// === GLOBALS === +tAxWin_Handle ghMenubarWindow; + +// === CODE === +int main(int argc, char *argv[]) +{ + // Create Window + ghMenubarWindow = AxWin_CreateWindow(0, 0, -1, -1, WINFLAG_NOBORDER, Menubar_HandleMessage); + + AxWin_MessageLoop(); + + return 0; +} + +/** + */ +int Menubar_HandleMessage(tAxWin_Message *Message) +{ + return 0; +} diff --git a/Usermode/Applications/axwin2_src/WM/common.h b/Usermode/Applications/axwin2_src/WM/common.h index 0b3e8fc0..13379fa1 100644 --- a/Usermode/Applications/axwin2_src/WM/common.h +++ b/Usermode/Applications/axwin2_src/WM/common.h @@ -9,6 +9,9 @@ #include #include +#include "wm.h" + +// === GLOBALS === extern char *gsTerminalDevice; extern char *gsMouseDevice; diff --git a/Usermode/Applications/axwin2_src/WM/wm.h b/Usermode/Applications/axwin2_src/WM/wm.h new file mode 100644 index 00000000..e7b6bee9 --- /dev/null +++ b/Usermode/Applications/axwin2_src/WM/wm.h @@ -0,0 +1,34 @@ + +#ifndef _WM_H_ +#define _WM_H_ + +typedef struct sElement +{ + struct sElement *NextSibling; + + short CachedX; + short CachedY; + short CachedW; + short CachedH; + + struct sElement *FirstChild; +} tElement; + +typedef struct sTab +{ + char *Name; + + tElement *RootElement; +} tTab; + +typedef struct sApplication +{ + pid_t PID; + + int nTabs; + tTab *Tabs; + + char Name[]; +} tApplication; + +#endif diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index 1cff6d98..ba788383 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -70,6 +70,13 @@ void DumpInterfaces(int DumpAll) type = ioctl(fd, 4, NULL); printf("%s:\t", filename); + { + int len = ioctl(fd, ioctl(fd, 3, "get_device"), NULL); + char *buf = malloc(len+1); + ioctl(fd, ioctl(fd, 3, "get_device"), buf); + printf("'%s'\t", buf); + free(buf); + } switch(type) { case 0: diff --git a/Usermode/Libraries/Makefile.tpl b/Usermode/Libraries/Makefile.tpl new file mode 100644 index 00000000..709aaac0 --- /dev/null +++ b/Usermode/Libraries/Makefile.tpl @@ -0,0 +1,18 @@ +# Acess 2 SQLite 3 Library +# + +.PHONY: all clean install + +all: $(BIN) + +clean: + $(RM) $(BIN) $(OBJ) + +install: $(BIN) + $(xCP) $(BIN) $(DISTROOT)/Libs/ + +$(BIN): $(OBJ) + $(LD) $(LDFLAGS) -o $(BIN) $(OBJ) + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< diff --git a/Usermode/Libraries/libaxwin2.so_src/Makefile b/Usermode/Libraries/libaxwin2.so_src/Makefile new file mode 100644 index 00000000..55291404 --- /dev/null +++ b/Usermode/Libraries/libaxwin2.so_src/Makefile @@ -0,0 +1,13 @@ +# Acess 2 - AxWin GUI Library +# + +include ../Makefile.cfg + +CPPFLAGS += +CFLAGS += -Wall +LDFLAGS += -lc -soname libaxwin2.so + +OBJ = main.o messages.o windows.o +BIN = ../libaxwin2.so + +include ../Makefile.tpl diff --git a/Usermode/Libraries/libaxwin2.so_src/common.h b/Usermode/Libraries/libaxwin2.so_src/common.h new file mode 100644 index 00000000..28d28390 --- /dev/null +++ b/Usermode/Libraries/libaxwin2.so_src/common.h @@ -0,0 +1,26 @@ +/* + * AxWin Window Manager Interface Library + * By John Hodge (thePowersGang) + * This file is published under the terms of the Acess Licence. See the + * file COPYING for details. + * + * common.h - Internal Variable and Constant definitions + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +// === Includes === +#include +#include +#include + +// === Constants === +enum eAxWin_Modes +{ + AXWIN_MODE_IPC +}; + +// === Variables === +extern int giAxWin_Mode; + +#endif diff --git a/Usermode/Libraries/libaxwin2.so_src/main.c b/Usermode/Libraries/libaxwin2.so_src/main.c new file mode 100644 index 00000000..1a12561b --- /dev/null +++ b/Usermode/Libraries/libaxwin2.so_src/main.c @@ -0,0 +1,18 @@ +/* + * AxWin Window Manager Interface Library + * By John Hodge (thePowersGang) + * This file is published under the terms of the Acess Licence. See the + * file COPYING for details. + * + * main.c - Library Initialisation + */ +#include "common.h" + +// === GLOBALS === + int giAxWin_Mode = 0; + +// === CODE === +int SoMain() +{ + return 0; +} diff --git a/Usermode/Libraries/libaxwin2.so_src/messages.c b/Usermode/Libraries/libaxwin2.so_src/messages.c new file mode 100644 index 00000000..d0fc5dac --- /dev/null +++ b/Usermode/Libraries/libaxwin2.so_src/messages.c @@ -0,0 +1,65 @@ +/* + * AxWin Window Manager Interface Library + * By John Hodge (thePowersGang) + * This file is published under the terms of the Acess Licence. See the + * file COPYING for details. + * + * messages.c - Message Handling + */ +#include "common.h" + +// === PROTOTYPES === + int AxWin_MessageLoop(); +tAxWin_Message *AxWin_WaitForMessage(); + int AxWin_HandleMessage(tAxWin_Message *Message); + +// === CODE === +/** + * \brief Loop forever, checking and waiting for messages + */ +int AxWin_MessageLoop() +{ + tAxWin_Message *msg; + int ret; + for(;;) + { + msg = AxWin_WaitForMessage(); + ret = AxWin_HandleMessage(msg); + + if(ret < 0) return 0; + } + return 0; +} + +/** + * \brief Wait for a message + */ +tAxWin_Message *AxWin_WaitForMessage() +{ + int length; + pid_t src; + tAxWin_Message *ret; + + switch( giAxWin_Mode ) + { + case AXWIN_MODE_IPC: + while( (length = SysGetMessage(&src, NULL)) == 0 ) sleep(); + ret = malloc(length); + SysGetMessage(NULL, ret); + break; + default: + break; + } + return 0; +} + +/** + * \brief Handles a recieved message + */ +int AxWin_HandleMessage(tAxWin_Message *Message) +{ + switch(Message->ID) + { + default: return 0; + } +} diff --git a/Usermode/Libraries/libaxwin2.so_src/windows.c b/Usermode/Libraries/libaxwin2.so_src/windows.c new file mode 100644 index 00000000..a37bfbbe --- /dev/null +++ b/Usermode/Libraries/libaxwin2.so_src/windows.c @@ -0,0 +1,70 @@ +/* + * AxWin Window Manager Interface Library + * By John Hodge (thePowersGang) + * This file is published under the terms of the Acess Licence. See the + * file COPYING for details. + * + * window.c - Window Control + */ +#include "common.h" + +// === TYPES & STRUCTURES === +struct sAxWin_Window +{ + struct sAxWin_Window *Next; + uint32_t WmHandle; + tAxWin_MessageCallback Callback; +}; + +// === PROTOTYPES === +tAxWin_Handle AxWin_CreateWindow( + int16_t X, int16_t Y, int16_t W, int16_t H, + uint32_t Flags, tAxWin_MessageCallback *Callback + ); + +// === GLOBALS === +//mutex_t glProcessWindows; +tAxWin_Window *gProcessWindows; + +// === CODE === +tAxWin_Handle AxWin_CreateWindow( + int16_t X, int16_t Y, + int16_t W, int16_t H, + uint32_t Flags, tAxWin_MessageCallback *Callback) +{ + tAxWin_Message req; + tAxWin_Message *msg; + tAxWin_Window *win; + + req.ID = MSG_SREQ_NEWWINDOW; + req.Size = 1 + sizeof(struct sAxWin_SReq_NewWindow)/4; + req.SReq_NewWindow.X = X; + req.SReq_NewWindow.Y = Y; + req.SReq_NewWindow.W = W; + req.SReq_NewWindow.H = H; + req.SReq_NewWindow.Flags = Flags; + + AxWin_SendMessage(&msg); + + for(;;) + { + msg = AxWin_WaitForMessage(); + + if(msg.ID == MSG_SRSP_WINDOW) + break; + + AxWin_HandleMessage(msg); + free(msg); + } + + win = malloc(sizeof(tAxWin_Window)); + win->WmHandle = msg->SRsp_Window.Handle; + win->Callback = Callback; + + //mutex_acquire(glProcessWindows); + win->Next = gProcessWindows; + gProcessWindows = win; + //mutex_release(glProcessWindows); + + return 0; +} diff --git a/Usermode/include/axwin/axwin.h b/Usermode/include/axwin/axwin.h new file mode 100644 index 00000000..ee160b80 --- /dev/null +++ b/Usermode/include/axwin/axwin.h @@ -0,0 +1,37 @@ +/** + * \file axwin.h + * \author John Hodge (thePowersGang) + * \brief AxWin Core functions + */ +#ifndef _AXWIN_AXWIN_H +#define _AXWIN_AXWIN_H + +// === Core Types === +typedef unsigned int tAxWin_Handle; + +// === Messaging === +#include "messages.h" +extern int AxWin_MessageLoop(); + +// === Window Control === +/** + * \brief Window Type + * \note Opaque Type + */ +typedef struct sAxWin_Window tAxWin_Window; + +typedef int tAxWin_MessageCallback(tAxWin_Message *); + +/** + * \brief Window Flags + * \{ + */ +#define WINFLAG_NOBORDER 0x100 +/** + * \} + */ +extern tAxWin_Window AxWin_CreateWindow( + int16_t X, int16_t Y, int16_t W, int16_t H, + uint32_t Flags, tAxWin_MessageCallback *Callback); + +#endif diff --git a/Usermode/include/axwin/messages.h b/Usermode/include/axwin/messages.h index e4ed1fe2..b27583ef 100644 --- a/Usermode/include/axwin/messages.h +++ b/Usermode/include/axwin/messages.h @@ -18,10 +18,23 @@ enum eAxWin_Messages // Server Requests MSG_SREQ_PING, // - Windows - MSG_SREQ_NEWWINDOW, // (short x, y, w, h, uint32_t flags) - MSG_SREQ_GETFLAGS, MSG_SREQ_SETFLAGS, - MSG_SREQ_GETRECT, MSG_SREQ_SETRECT, + MSG_SREQ_REGISTER, // bool (char[] Name) - Registers this PID with the Window Manager + + MSG_SREQ_ADDTAB, // ELEMENT (char[] Name) - Adds a tab to the window + MSG_SREQ_DELTAB, // void (TAB Tab) - Closes a tab + + MSG_SREQ_NEWDIALOG, // ELEMENT (ELEMENT Parent, char[] Name) - Creates a dialog + MSG_SREQ_DELDIALOG, // void (ELEMENT Dialog) - Closes a dialog + + MSG_SREQ_SETNAME, // void (ELEMENT Element, char[] Name) + MSG_SREQ_GETNAME, // char[] (ELEMENT Element) + + // - Builtin Elements + MSG_SREQ_INSERT, // void (ELEMENT Parent, eAxWin_Controls Type, u32 Flags) + // - Drawing + // All drawing functions take an ELEMENT as their first parameter. + // This must be either a Tab, Dialog or Canvas control MSG_SREQ_SETCOL, MSG_SREQ_PSET, MSG_SREQ_LINE, MSG_SREQ_CURVE, @@ -30,9 +43,7 @@ enum eAxWin_Messages MSG_SREQ_SETFONT, MSG_SREQ_PUTTEXT, // Server Responses - MSG_SRSP_PONG, - MSG_SRSP_WINDOW, // Returns the new window ID - MSG_SRSP_IMG, // Returns the image ID + MSG_SRSP_RETURN, // {int RequestID, void[] Return Value} - Returns a value from a server request NUM_MSG }; -- 2.20.1