+++ /dev/null
-/*
- * Acess2 EDI Layer
- */
-#define DEBUG 0
-#define VERSION ((0<<8)|1)
-#include <acess.h>
-#include <modules.h>
-#include <fs_devfs.h>
-#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);