From: John Hodge Date: Tue, 2 Feb 2010 00:16:30 +0000 (+0800) Subject: Reorganised the modules directory, started serious work on GUI support X-Git-Tag: rel0.06~311 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=0dbc91f0676576b954aa95dafdb434ce19bc805c;p=tpg%2Facess2.git Reorganised the modules directory, started serious work on GUI support - Cleaning up and bugfixing VTerm graphics support --- diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 3ef05eab..3cd471cb 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1398 +BUILD_NUM = 1407 diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 76b7f1e8..716a5531 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -19,8 +19,8 @@ #define MAX_INPUT_CHARS32 64 #define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) #define VT_SCROLLBACK 1 // 2 Screens of text -#define DEFAULT_OUTPUT "VGA" -//#define DEFAULT_OUTPUT "BochsGA" +//#define DEFAULT_OUTPUT "VGA" +#define DEFAULT_OUTPUT "BochsGA" #define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 @@ -348,6 +348,28 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) case TERM_MODE_TEXT: VT_int_PutString(term, Buffer, Length); break; + case TERM_MODE_FB: + if( term->RealWidth > term->Width || term->RealHeight > term->Height ) + { + #if 0 + int x, y, h; + x = Offset/4; y = x / term->Width; x %= term->Width; + w = Length/4+x; h = w / term->Width; w %= term->Width; + while(h--) + { + VFS_WriteAt( giVT_OutputDevHandle, + (x+y*term->RealWidth)*4, + term->Width * 4, + Buffer + ); + Buffer = (void*)( (Uint)Buffer + term->Width*term->Height*4 ); + } + #endif + return 0; + } + else { + return VFS_WriteAt( giVT_OutputDevHandle, Offset, Length, Buffer ); + } } //LEAVE('i', 0); @@ -364,6 +386,10 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) tVTerm *term = Node->ImplPtr; ENTER("pNode iId pData", Node, Id, Data); + if(Id >= DRV_IOCTL_LOOKUP) { + if( Threads_GetUID() != 0 ) return -1; + } + switch(Id) { case DRV_IOCTL_TYPE: @@ -407,6 +433,11 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) Log("VT_Terminal_IOCtl - RETURN term->Height = %i", term->Height); LEAVE('i', term->Height); return term->Height; + + case TERM_IOCTL_FORCESHOW: + VT_SetTerminal( Node->Inode ); + LEAVE('i', 1); + return 1; } LEAVE('i', -1); return -1; diff --git a/Kernel/include/modules.h b/Kernel/include/modules.h index 591dbf92..d53f7749 100644 --- a/Kernel/include/modules.h +++ b/Kernel/include/modules.h @@ -17,9 +17,12 @@ # error "Unknown architecture when determining MODULE_ARCH_ID ('" #ARCHDIR "')" #endif -#define MODULE_DEFINE(_flags,_ver,_ident,_entry,_deinit,_deps...) char *_DriverDeps_##_ident[]={_deps};\ - tModule __attribute__ ((section ("KMODULES"),unused)) _DriverInfo_##_ident=\ - {MODULE_MAGIC,MODULE_ARCH_ID,_flags,_ver,NULL,#_ident,_entry,_deinit,_DriverDeps_##_ident} +#define MODULE_DEFINE(_flags,_ver,_ident,_entry,_deinit,_deps...) \ + char *EXPAND_CONCAT(_DriverDeps_,_ident)[]={_deps};\ + tModule __attribute__ ((section ("KMODULES"),unused))\ + EXPAND_CONCAT(_DriverInfo_,_ident)=\ + {MODULE_MAGIC,MODULE_ARCH_ID,_flags,_ver,NULL,EXPAND_STR(_ident),\ + _entry,_deinit,EXPAND_CONCAT(_DriverDeps_,_ident)} typedef struct sModule { Uint32 Magic; diff --git a/Kernel/include/tpl_drv_terminal.h b/Kernel/include/tpl_drv_terminal.h index 907cc142..21ba2909 100644 --- a/Kernel/include/tpl_drv_terminal.h +++ b/Kernel/include/tpl_drv_terminal.h @@ -59,7 +59,13 @@ enum eTplTerminal_IOCtl { * \note The id field of \a info is not for use with ::TERM_IOCTL_MODETYPE * This field is just for indexing the mode to get its information. */ - TERM_IOCTL_QUERYMODE + TERM_IOCTL_QUERYMODE, + + /** + * ioctl(...) + * \brief Forces the current terminal to be shown + */ + TERM_IOCTL_FORCESHOW }; /** diff --git a/Makefile.cfg b/Makefile.cfg index be0194f0..348206fb 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -25,8 +25,12 @@ endif FILESYSTEMS = fat DRIVERS = -MODULES = ATA FS_Ext2 FDD NE2000 BochsGA IPStack -DYNMODS = USB UDI +MODULES = Storage/ATA Storage/FDD +MODULES += Network/NE2000 +MODULES += Display/BochsGA +MODULES += Filesystems/FS_Ext2 +MODULES += IPStack +DYNMODS = USB Interfaces/UDI #DISTROOT = /mnt/AcessHDD/Acess2 #DISTROOT = ~/Projects/Acess2/Filesystem diff --git a/Modules/ATA/Makefile b/Modules/ATA/Makefile deleted file mode 100644 index 05e66af6..00000000 --- a/Modules/ATA/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = main.o mbr.o -NAME = ATA - --include ../Makefile.tpl diff --git a/Modules/ATA/common.h b/Modules/ATA/common.h deleted file mode 100644 index 18e62a8d..00000000 --- a/Modules/ATA/common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Acess2 IDE Harddisk Driver - * - main.c - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include -#include - -// === CONSTANTS === -#define MAX_ATA_DISKS 4 -#define SECTOR_SIZE 512 -#define MAX_DMA_SECTORS (0x1000 / SECTOR_SIZE) - -#define IDE_PRI_BASE 0x1F0 -#define IDE_SEC_BASE 0x170 - -#define IDE_PRDT_LAST 0x8000 -/** - \enum HddControls - \brief Commands to be sent to HDD_CMD -*/ -enum HddControls { - HDD_PIO_R28 = 0x20, - HDD_PIO_R48 = 0x24, - HDD_DMA_R48 = 0x25, - HDD_PIO_W28 = 0x30, - HDD_PIO_W48 = 0x34, - HDD_DMA_W48 = 0x35, - HDD_DMA_R28 = 0xC8, - HDD_DMA_W28 = 0xCA, -}; - -// === STRUCTURES === -typedef struct -{ - Uint8 BootCode[0x1BE]; - struct { - Uint8 Boot; - Uint8 Unused1; // Also CHS Start - Uint16 StartHi; // Also CHS Start - Uint8 SystemID; - Uint8 Unused2; // Also CHS Length - Uint16 LengthHi; // Also CHS Length - Uint32 LBAStart; - Uint32 LBALength; - } __attribute__ ((packed)) Parts[4]; - Uint16 BootFlag; // = 0xAA 55 -} __attribute__ ((packed)) tMBR; - -typedef struct -{ - Uint64 Start; - Uint64 Length; - char Name[4]; - tVFS_Node Node; -} tATA_Partition; - -typedef struct -{ - Uint64 Sectors; - char Name[2]; - tVFS_Node Node; - int NumPartitions; - tATA_Partition *Partitions; -} tATA_Disk; - -// === GLOBALS === -extern tATA_Disk gATA_Disks[]; - -// === FUNCTIONS === -extern void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); -extern int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); -extern int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); - -#endif diff --git a/Modules/ATA/main.c b/Modules/ATA/main.c deleted file mode 100644 index 41f08738..00000000 --- a/Modules/ATA/main.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * Acess2 IDE Harddisk Driver - * - main.c - */ -#define DEBUG 0 -#include -#include -#include -#include -#include -#include -#include -#include "common.h" - -// --- Flags --- -#define START_BEFORE_CMD 0 - -// === STRUCTURES === -typedef struct -{ - Uint32 PBufAddr; - Uint16 Bytes; - Uint16 Flags; -} __attribute__ ((packed)) tPRDT_Ent; -typedef struct -{ - Uint16 Flags; // 1 - Uint16 Usused1[9]; // 10 - char SerialNum[20]; // 20 - Uint16 Usused2[3]; // 23 - char FirmwareVer[8]; // 27 - char ModelNumber[40]; // 47 - Uint16 SectPerInt; // 48 - AND with 0xFF to get true value; - Uint16 Unused3; // 49 - Uint16 Capabilities[2]; // 51 - Uint16 Unused4[2]; // 53 - Uint16 ValidExtData; // 54 - Uint16 Unused5[5]; // 59 - Uint16 SizeOfRWMultiple; // 60 - Uint32 Sectors28; // 62 - Uint16 Unused6[100-62]; - Uint64 Sectors48; - Uint16 Unused7[256-104]; -} __attribute__ ((packed)) tIdentify; - -// === IMPORTS === -extern void ATA_ParseMBR(int Disk); - -// === PROTOTYPES === - int ATA_Install(); - int ATA_SetupIO(); -void ATA_SetupPartitions(); -void ATA_SetupVFS(); - int ATA_ScanDisk(int Disk); -void ATA_ParseGPT(int Disk); -void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); -Uint16 ATA_GetBasePort(int Disk); -// Filesystem Interface -char *ATA_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name); -Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); - int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data); -// Read/Write Interface/Quantiser -Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk); -Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk); -// Read/Write DMA - int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); - int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); -// IRQs -void ATA_IRQHandlerPri(int unused); -void ATA_IRQHandlerSec(int unused); -// Controller IO -Uint8 ATA_int_BusMasterReadByte(int Ofs); -void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value); -void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value); - -// === GLOBALS === -MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, NULL); -tDevFS_Driver gATA_DriverInfo = { - NULL, "ata", - { - .NumACLs = 1, - .Size = -1, - .Flags = VFS_FFLAG_DIRECTORY, - .ACLs = &gVFS_ACL_EveryoneRX, - .ReadDir = ATA_ReadDir, - .FindDir = ATA_FindDir - } -}; -tATA_Disk gATA_Disks[MAX_ATA_DISKS]; - int giATA_NumNodes; -tVFS_Node **gATA_Nodes; -Uint16 gATA_BusMasterBase = 0; -Uint8 *gATA_BusMasterBasePtr = 0; - int gATA_IRQPri = 14; - int gATA_IRQSec = 15; - int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller -Uint8 gATA_Buffers[2][4096] __attribute__ ((section(".padata"))); - int gaATA_IRQs[2] = {0}; -tPRDT_Ent gATA_PRDTs[2] = { - {0, 512, IDE_PRDT_LAST}, - {0, 512, IDE_PRDT_LAST} -}; - -// === CODE === -/** - * \fn int ATA_Install() - */ -int ATA_Install() -{ - int ret; - - ret = ATA_SetupIO(); - if(ret != 1) return ret; - - ATA_SetupPartitions(); - - ATA_SetupVFS(); - - if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 ) - return MODULE_INIT_FAILURE; - - return MODULE_INIT_SUCCESS; -} - -/** - * \fn int ATA_SetupIO() - * \brief Sets up the ATA controller's DMA mode - */ -int ATA_SetupIO() -{ - int ent; - tPAddr addr; - - ENTER(""); - - // Get IDE Controller's PCI Entry - ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1); - LOG("ent = %i", ent); - gATA_BusMasterBase = PCI_GetBAR4( ent ); - if( gATA_BusMasterBase == 0 ) { - Warning("It seems that there is no Bus Master Controller on this machine. Get one"); - LEAVE('i', MODULE_INIT_FAILURE); - return MODULE_INIT_FAILURE; - } - if( !(gATA_BusMasterBase & 1) ) - { - if( gATA_BusMasterBase < 0x100000 ) - gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase); - else - gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) ); - LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr); - } - else { - // Bit 0 is left set as a flag to other functions - LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1); - } - - IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri ); - IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec ); - - gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] ); - gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] ); - - LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr); - - addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] ); - LOG("addr = 0x%x", addr); - ATA_int_BusMasterWriteDWord(4, addr); - addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] ); - LOG("addr = 0x%x", addr); - ATA_int_BusMasterWriteDWord(12, addr); - - outb(IDE_PRI_BASE+1, 1); - outb(IDE_SEC_BASE+1, 1); - - LEAVE('i', MODULE_INIT_SUCCESS); - return MODULE_INIT_SUCCESS; -} - -/** - * \fn void ATA_SetupPartitions() - */ -void ATA_SetupPartitions() -{ - int i; - for( i = 0; i < MAX_ATA_DISKS; i ++ ) - { - if( !ATA_ScanDisk(i) ) { - gATA_Disks[i].Name[0] = '\0'; // Mark as unused - continue; - } - } -} - -/** - * \fn void ATA_SetupVFS() - * \brief Sets up the ATA drivers VFS information and registers with DevFS - */ -void ATA_SetupVFS() -{ - int i, j, k; - - // Count number of nodes needed - giATA_NumNodes = 0; - for( i = 0; i < MAX_ATA_DISKS; i++ ) - { - if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore - giATA_NumNodes ++; - giATA_NumNodes += gATA_Disks[i].NumPartitions; - } - - // Allocate Node space - gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) ); - - // Set nodes - k = 0; - for( i = 0; i < MAX_ATA_DISKS; i++ ) - { - if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore - gATA_Nodes[ k++ ] = &gATA_Disks[i].Node; - for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ ) - gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node; - } - - gATA_DriverInfo.RootNode.Size = giATA_NumNodes; -} - -/** - * \fn int ATA_ScanDisk(int Disk) - */ -int ATA_ScanDisk(int Disk) -{ - Uint16 buf[256]; - tIdentify *identify = (void*)buf; - tMBR *mbr = (void*)buf; - Uint16 base; - Uint8 val; - int i; - tVFS_Node *node; - - ENTER("iDisk", Disk); - - base = ATA_GetBasePort( Disk ); - - LOG("base = 0x%x", base); - - // Send Disk Selector - if(Disk == 1 || Disk == 3) - outb(base+6, 0xB0); - else - outb(base+6, 0xA0); - - // Send IDENTIFY - outb(base+7, 0xEC); - val = inb(base+7); // Read status - if(val == 0) { - LEAVE('i', 0); - return 0; // Disk does not exist - } - - // Poll until BSY clears and DRQ sets or ERR is set - while( ((val & 0x80) || !(val & 0x08)) && !(val & 1)) val = inb(base+7); - - if(val & 1) { - LEAVE('i', 0); - return 0; // Error occured, so return false - } - - // Read Data - for(i=0;i<256;i++) buf[i] = inw(base); - - // Populate Disk Structure - if(identify->Sectors48 != 0) - gATA_Disks[ Disk ].Sectors = identify->Sectors48; - else - gATA_Disks[ Disk ].Sectors = identify->Sectors28; - - - LOG("gATA_Disks[ Disk ].Sectors = 0x%x", gATA_Disks[ Disk ].Sectors); - - if( gATA_Disks[ Disk ].Sectors / (2048*1024) ) - Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk, - gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024)); - else if( gATA_Disks[ Disk ].Sectors / 2048 ) - Log("Disk %i: 0x%llx Sectors (%i MiB)", Disk, - gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2048); - else - Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk, - gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2); - - // Create Name - gATA_Disks[ Disk ].Name[0] = 'A'+Disk; - gATA_Disks[ Disk ].Name[1] = '\0'; - - // Get pointer to vfs node and populate it - node = &gATA_Disks[ Disk ].Node; - node->Size = gATA_Disks[Disk].Sectors * SECTOR_SIZE; - node->NumACLs = 0; // Means Superuser only can access it - node->Inode = (Disk << 8) | 0xFF; - node->ImplPtr = gATA_Disks[ Disk ].Name; - - node->ATime = node->MTime - = node->CTime = now(); - - node->Read = ATA_ReadFS; - node->Write = ATA_WriteFS; - node->IOCtl = ATA_IOCtl; - - - // --- Scan Partitions --- - LOG("Reading MBR"); - // Read Boot Sector - ATA_ReadDMA( Disk, 0, 1, mbr ); - - // Check for a GPT table - if(mbr->Parts[0].SystemID == 0xEE) - ATA_ParseGPT(Disk); - else // No? Just parse the MBR - ATA_ParseMBR(Disk); - - LEAVE('i', 0); - return 1; -} - -/** - * \fn void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length) - * \brief Fills a parition's information structure - */ -void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length) -{ - ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length); - Part->Start = Start; - Part->Length = Length; - Part->Name[0] = 'A'+Disk; - if(Num >= 10) { - Part->Name[1] = '1'+Num/10; - Part->Name[2] = '1'+Num%10; - Part->Name[3] = '\0'; - } else { - Part->Name[1] = '1'+Num; - Part->Name[2] = '\0'; - } - Part->Node.NumACLs = 0; // Only root can read/write raw block devices - Part->Node.Inode = (Disk << 8) | Num; - Part->Node.ImplPtr = Part->Name; - - Part->Node.Read = ATA_ReadFS; - Part->Node.Write = ATA_WriteFS; - Part->Node.IOCtl = ATA_IOCtl; - LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node); - LEAVE('-'); -} - -/** - * \fn void ATA_ParseGPT(int Disk) - * \brief Parses the GUID Partition Table - */ -void ATA_ParseGPT(int Disk) -{ - ///\todo Support GPT Disks - Warning("GPT Disks are currently unsupported"); -} - -/** - * \fn Uint16 ATA_GetPortBase(int Disk) - * \brief Returns the base port for a given disk - */ -Uint16 ATA_GetBasePort(int Disk) -{ - switch(Disk) - { - case 0: case 1: return IDE_PRI_BASE; - case 2: case 3: return IDE_SEC_BASE; - } - return 0; -} - -/** - * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos) - */ -char *ATA_ReadDir(tVFS_Node *Node, int Pos) -{ - if(Pos >= giATA_NumNodes || Pos < 0) return NULL; - return strdup( gATA_Nodes[Pos]->ImplPtr ); -} - -/** - * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) - */ -tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) -{ - int part; - // Check first character - if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS) - return NULL; - // Raw Disk - if(Name[1] == '\0') { - if( gATA_Disks[Name[0]-'A'].Sectors == 0 ) - return NULL; - return &gATA_Disks[Name[0]-'A'].Node; - } - - // Partitions - if(Name[1] < '0' || '9' < Name[1]) return NULL; - if(Name[2] == '\0') { // <= 9 - part = Name[1] - '0'; - part --; - return &gATA_Disks[Name[0]-'A'].Partitions[part].Node; - } - // > 9 - if('0' > Name[2] || '9' < Name[2]) return NULL; - if(Name[3] != '\0') return NULL; - - part = (Name[1] - '0') * 10; - part += Name[2] - '0'; - part --; - return &gATA_Disks[Name[0]-'A'].Partitions[part].Node; - -} - -/** - * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - */ -Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - int disk = Node->Inode >> 8; - int part = Node->Inode & 0xFF; - - // Raw Disk Access - if(part == 0xFF) - { - if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) - return 0; - if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE ) - Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset; - } - // Partition - else - { - if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) - return 0; - if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) - Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset; - Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE; - } - - //Log("ATA_ReadFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer); - return DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk); -} - -/** - * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - */ -Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - int disk = Node->Inode >> 8; - int part = Node->Inode & 0xFF; - - // Raw Disk Access - if(part == 0xFF) - { - if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) - return 0; - if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE ) - Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset; - } - // Partition - else - { - if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) - return 0; - if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) - Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset; - Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE; - } - - Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer); - Debug_HexDump("ATA_WriteFS", Buffer, Length); - return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk); -} - -/** - * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) - * \brief IO Control Funtion - */ -int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) -{ - switch(Id) - { - case DRV_IOCTL_TYPE: return DRV_TYPE_DISK; - } - return 0; -} - -// --- Disk Access --- -/** - * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) - */ -Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) -{ - int ret; - Uint offset; - Uint done = 0; - - // Pass straight on to ATA_ReadDMAPage if we can - if(Count <= MAX_DMA_SECTORS) - { - ret = ATA_ReadDMA(Disk, Address, Count, Buffer); - if(ret == 0) return 0; - return Count; - } - - // Else we will have to break up the transfer - offset = 0; - while(Count > MAX_DMA_SECTORS) - { - ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset); - // Check for errors - if(ret != 1) return done; - // Change Position - done += MAX_DMA_SECTORS; - Count -= MAX_DMA_SECTORS; - offset += MAX_DMA_SECTORS*SECTOR_SIZE; - } - - ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset); - if(ret != 1) return 0; - return done+Count; -} - -/** - * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) - */ -Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) -{ - int ret; - Uint offset; - Uint done = 0; - - // Pass straight on to ATA_WriteDMA if we can - if(Count <= MAX_DMA_SECTORS) - { - ret = ATA_WriteDMA(Disk, Address, Count, Buffer); - if(ret == 0) return 0; - return Count; - } - - // Else we will have to break up the transfer - offset = 0; - while(Count > MAX_DMA_SECTORS) - { - ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset); - // Check for errors - if(ret != 1) return done; - // Change Position - done += MAX_DMA_SECTORS; - Count -= MAX_DMA_SECTORS; - offset += MAX_DMA_SECTORS*SECTOR_SIZE; - } - - ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset); - if(ret != 1) return 0; - return done+Count; -} - -/** - * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) - */ -int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) -{ - int cont = (Disk>>1)&1; // Controller ID - int disk = Disk & 1; - Uint16 base; - - ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer); - - // Check if the count is small enough - if(Count > MAX_DMA_SECTORS) { - Warning("Passed too many sectors for a bulk DMA read (%i > %i)", - Count, MAX_DMA_SECTORS); - LEAVE('i'); - return 0; - } - - // Get exclusive access to the disk controller - LOCK( &giaATA_ControllerLock[ cont ] ); - - // Set Size - gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; - - // Get Port Base - base = ATA_GetBasePort(Disk); - - // Reset IRQ Flag - gaATA_IRQs[cont] = 0; - - // Set up transfer - outb(base+0x01, 0x00); - if( Address > 0x0FFFFFFF ) // Use LBA48 - { - outb(base+0x6, 0x40 | (disk << 4)); - outb(base+0x2, 0 >> 8); // Upper Sector Count - outb(base+0x3, Address >> 24); // Low 2 Addr - outb(base+0x3, Address >> 28); // Mid 2 Addr - outb(base+0x3, Address >> 32); // High 2 Addr - } - else - { - outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr - } - - outb(base+0x02, (Uint8) Count); // Sector Count - outb(base+0x03, (Uint8) Address); // Low Addr - outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr - outb(base+0x05, (Uint8) (Address >> 16)); // High Addr - - LOG("Starting Transfer"); - #if START_BEFORE_CMD - // Start transfer - ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start - if( Address > 0x0FFFFFFF ) - outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) - else - outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) - #else - if( Address > 0x0FFFFFFF ) - outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) - else - outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) - // Start transfer - ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start - #endif - - // Wait for transfer to complete - //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 ); - while( gaATA_IRQs[cont] == 0 ) { - //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 ); - //LOG("val = 0x%02x", val); - Threads_Yield(); - } - - // Complete Transfer - ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop - - LOG("Transfer Completed & Acknowledged"); - - // Copy to destination buffer - memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE ); - - // Release controller lock - RELEASE( &giaATA_ControllerLock[ cont ] ); - - LEAVE('i', 1); - return 1; -} - -/** - * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) - */ -int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) -{ - int cont = (Disk>>1)&1; // Controller ID - int disk = Disk & 1; - Uint16 base; - - // Check if the count is small enough - if(Count > MAX_DMA_SECTORS) return 0; - - // Get exclusive access to the disk controller - LOCK( &giaATA_ControllerLock[ cont ] ); - - // Set Size - gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; - - // Get Port Base - base = ATA_GetBasePort(Disk); - - // Set up transfer - outb(base+0x01, 0x00); - if( Address > 0x0FFFFFFF ) // Use LBA48 - { - outb(base+0x6, 0x40 | (disk << 4)); - outb(base+0x2, 0 >> 8); // Upper Sector Count - outb(base+0x3, Address >> 24); // Low 2 Addr - outb(base+0x3, Address >> 28); // Mid 2 Addr - outb(base+0x3, Address >> 32); // High 2 Addr - } - else - { - outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr - } - - outb(base+0x02, (Uint8) Count); // Sector Count - outb(base+0x03, (Uint8) Address); // Low Addr - outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr - outb(base+0x05, (Uint8) (Address >> 16)); // High Addr - if( Address > 0x0FFFFFFF ) - outb(base+0x07, HDD_DMA_W48); // Write Command (LBA48) - else - outb(base+0x07, HDD_DMA_W28); // Write Command (LBA28) - - // Reset IRQ Flag - gaATA_IRQs[cont] = 0; - - // Copy to output buffer - memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE ); - - // Start transfer - ATA_int_BusMasterWriteByte( cont << 3, 1 ); // Write and start - - // Wait for transfer to complete - while( gaATA_IRQs[cont] == 0 ) Threads_Yield(); - - // Complete Transfer - ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop - - // Release controller lock - RELEASE( &giaATA_ControllerLock[ cont ] ); - - return 1; -} - -/** - * \fn void ATA_IRQHandlerPri(int unused) - */ -void ATA_IRQHandlerPri(int unused) -{ - Uint8 val; - - // IRQ bit set for Primary Controller - val = ATA_int_BusMasterReadByte( 0x2 ); - LOG("IRQ val = 0x%x", val); - if(val & 4) { - LOG("IRQ hit (val = 0x%x)", val); - ATA_int_BusMasterWriteByte( 0x2, 4 ); - gaATA_IRQs[0] = 1; - return ; - } -} - -/** - * \fn void ATA_IRQHandlerSec(int unused) - */ -void ATA_IRQHandlerSec(int unused) -{ - Uint8 val; - // IRQ bit set for Secondary Controller - val = ATA_int_BusMasterReadByte( 0xA ); - if(val & 4) { - LOG("IRQ hit (val = 0x%x)", val); - ATA_int_BusMasterWriteByte( 0xA, 4 ); - gaATA_IRQs[1] = 1; - return ; - } -} - -/** - * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs) - */ -Uint8 ATA_int_BusMasterReadByte(int Ofs) -{ - if( gATA_BusMasterBase & 1 ) - return inb( (gATA_BusMasterBase & ~1) + Ofs ); - else - return *(Uint8*)(gATA_BusMasterBasePtr + Ofs); -} - -/** - * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) - * \brief Writes a byte to a Bus Master Register - */ -void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) -{ - if( gATA_BusMasterBase & 1 ) - outb( (gATA_BusMasterBase & ~1) + Ofs, Value ); - else - *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value; -} - -/** - * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) - * \brief Writes a dword to a Bus Master Register - */ -void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) -{ - - if( gATA_BusMasterBase & 1 ) - outd( (gATA_BusMasterBase & ~1) + Ofs, Value ); - else - *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value; -} diff --git a/Modules/ATA/mbr.c b/Modules/ATA/mbr.c deleted file mode 100644 index 45ade88a..00000000 --- a/Modules/ATA/mbr.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Acess2 IDE Harddisk Driver - * - MBR Parsing Code - * mbr.c - */ -#define DEBUG 0 -#include -#include "common.h" - -// === PROTOTYPES === -Uint64 ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length); - -// === GLOBALS === - -// === CODE === -/** - * \fn void ATA_ParseMBR(int Disk) - */ -void ATA_ParseMBR(int Disk) -{ - int i, j = 0, k = 4; - tMBR mbr; - Uint64 extendedLBA; - Uint64 base, len; - - ENTER("iDisk", Disk); - - // Read Boot Sector - ATA_ReadDMA( Disk, 0, 1, &mbr ); - - // Count Partitions - gATA_Disks[Disk].NumPartitions = 0; - extendedLBA = 0; - for( i = 0; i < 4; i ++ ) - { - if( mbr.Parts[i].SystemID == 0 ) continue; - if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 // LBA 28 - || mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 // LBA 48 - ) - { - if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) { - LOG("Extended Partition"); - if(extendedLBA != 0) { - Warning("Disk %i has multiple extended partitions, ignoring rest", Disk); - continue; - } - extendedLBA = mbr.Parts[i].LBAStart; - continue; - } - LOG("Primary Partition"); - - gATA_Disks[Disk].NumPartitions ++; - continue; - } - // Invalid Partition, so don't count it - } - while(extendedLBA != 0) - { - extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len); - if( extendedLBA == -1 ) return ; - gATA_Disks[Disk].NumPartitions ++; - } - LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions); - - // Create patition array - gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) ); - - // --- Fill Partition Info --- - extendedLBA = 0; - for( j = 0, i = 0; i < 4; i ++ ) - { - Log("mbr.Parts[%i].SystemID = 0x%02x", i, mbr.Parts[i].SystemID); - if( mbr.Parts[i].SystemID == 0 ) continue; - if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28 - { - base = mbr.Parts[i].LBAStart; - len = mbr.Parts[i].LBALength; - } - else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) // LBA 58 - { - base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart; - len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength; - } - else - continue; - - if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) { - if(extendedLBA != 0) { - Warning("Disk %i has multiple extended partitions, ignoring rest", Disk); - continue; - } - extendedLBA = base; - continue; - } - // Create Partition - ATA_int_MakePartition( - &gATA_Disks[Disk].Partitions[j], Disk, j, - base, len - ); - j ++; - - } - // Scan extended partitions - while(extendedLBA != 0) - { - extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len); - ATA_int_MakePartition( - &gATA_Disks[Disk].Partitions[j], Disk, k, base, len - ); - } - - LEAVE('-'); -} - -/** - * \brief Reads an extended partition - * \return LBA of next Extended, -1 on error, 0 for last - */ -Uint64 ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length) -{ - Uint64 link = 0; - int bFoundPart = 0;; - int i; - tMBR mbr; - Uint64 base, len; - - if( ATA_ReadDMA( Disk, Addr, 1, &mbr ) != 0 ) - return -1; // Stop on Errors - - - for( i = 0; i < 4; i ++ ) - { - if( mbr.Parts[i].SystemID == 0 ) continue; - - // LBA 24 - if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) { - base = mbr.Parts[i].LBAStart; - len = mbr.Parts[i].LBALength; - } - // LBA 48 - else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) { - base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart; - len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength; - } - else { - Warning("Unknown partition type, Disk %i 0x%llx Part %i", - Disk, Addr, i); - return -1; - } - - switch(mbr.Parts[i].SystemID) - { - case 0xF: - case 0x5: - if(link != 0) { - Warning("Disk %i has two forward links in the extended partition", - Disk); - return -1; - } - link = base; - break; - default: - if(bFoundPart) { - Warning("Disk %i has more than one partition in the extended partition at 0x%llx", - Disk, Addr); - return -1; - } - bFoundPart = 1; - *Base = base; - *Length = len; - break; - } - } - - if(!bFoundPart) { - Warning("No partition in extended partiton, Disk %i 0x%llx", - Disk, Addr); - return -1; - } - - return link; -} diff --git a/Modules/BochsGA/Makefile b/Modules/BochsGA/Makefile deleted file mode 100644 index 2df219af..00000000 --- a/Modules/BochsGA/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = bochsvbe.o -NAME = BochsGA - --include ../Makefile.tpl diff --git a/Modules/BochsGA/bochsvbe.c b/Modules/BochsGA/bochsvbe.c deleted file mode 100644 index 5fe82f5b..00000000 --- a/Modules/BochsGA/bochsvbe.c +++ /dev/null @@ -1,467 +0,0 @@ -/** - * \file drv_bochsvbe.c - * \brief BGA (Bochs Graphic Adapter) Driver - * \note for Acess2 - * \warning This driver does NOT support the Bochs PCI VGA driver -*/ -#define DEBUG 0 -#include -#include -#include -#include -#include -#include -#include - -#define INT - -// === TYPEDEFS === -typedef struct { - Uint16 width; - Uint16 height; - Uint16 bpp; - Uint16 flags; - Uint32 fbSize; -} t_bga_mode; - -// === CONSTANTS === -enum eMode_Flags { - MODEFLAG_TEXT = 1 -}; -#define BGA_LFB_MAXSIZE (1024*768*4) -#define VBE_DISPI_BANK_ADDRESS 0xA0000 -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 -#define VBE_DISPI_IOPORT_INDEX 0x01CE -#define VBE_DISPI_IOPORT_DATA 0x01CF -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 -enum { - VBE_DISPI_INDEX_ID, - VBE_DISPI_INDEX_XRES, - VBE_DISPI_INDEX_YRES, - VBE_DISPI_INDEX_BPP, - VBE_DISPI_INDEX_ENABLE, - VBE_DISPI_INDEX_BANK, - VBE_DISPI_INDEX_VIRT_WIDTH, - VBE_DISPI_INDEX_VIRT_HEIGHT, - VBE_DISPI_INDEX_X_OFFSET, - VBE_DISPI_INDEX_Y_OFFSET -}; - - -// === PROTOTYPES === -// Driver - int BGA_Install(char **Arguments); -void BGA_Uninstall(); -// Internal -void BGA_int_WriteRegister(Uint16 reg, Uint16 value); -Uint16 BGA_int_ReadRegister(Uint16 reg); -void BGA_int_SetBank(Uint16 bank); -void BGA_int_SetMode(Uint16 width, Uint16 height); - int BGA_int_UpdateMode(int id); - int BGA_int_FindMode(tVideo_IOCtl_Mode *info); - int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info); - int BGA_int_MapFB(void *Dest); -// Filesystem -Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); -Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); - int BGA_Ioctl(tVFS_Node *node, int id, void *data); - -// === GLOBALS === -MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL); -tDevFS_Driver gBGA_DriverStruct = { - NULL, "BochsGA", - { - .Read = BGA_Read, - .Write = BGA_Write, - .IOCtl = BGA_Ioctl - } -}; - int giBGA_CurrentMode = -1; -tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1}; - int giBGA_DriverId = -1; -Uint *gBGA_Framebuffer; -t_bga_mode gBGA_Modes[] = { - {}, - { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480 - {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600 - {640,480,8, 0, 640*480}, - {640,480,32, 0, 640*480*4}, - {800,600,8, 0, 800*600}, - {800,600,32, 0, 800*600*4}, -}; -#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0])) - -// === CODE === -/** - * \fn int BGA_Install(char **Arguments) - */ -int BGA_Install(char **Arguments) -{ - int bga_version = 0; - - // Check BGA Version - bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID); - // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable - if(bga_version < 0xB0C4 || bga_version > 0xB0C5) { - Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version); - return 0; - } - - // Install Device - giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct ); - if(giBGA_DriverId == -1) { - Warning("[BGA ] Unable to register with DevFS, maybe already loaded?"); - return 0; - } - - // Map Framebuffer to hardware address - gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb) - - return 1; -} - -/** - * \fn void BGA_Uninstall() - */ -void BGA_Uninstall() -{ - //DevFS_DelDevice( giBGA_DriverId ); - MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 ); -} - -/** - * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) - * \brief Read from the framebuffer - */ -Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) -{ - // Check Mode - if(giBGA_CurrentMode == -1) return -1; - - // Check Offset and Length against Framebuffer Size - if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) - return -1; - - // Copy from Framebuffer - memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len); - return len; -} - -/** - * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) - * \brief Write to the framebuffer - */ -Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) -{ - ENTER("xoff xlen", off, len); - - // Check Mode - if(giBGA_CurrentMode == -1) { - LEAVE('i', -1); - return -1; - } - - // Check Input against Frambuffer Size - if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) { - LEAVE('i', -1); - return -1; - } - - // Text Mode - if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT ) - { - tVT_Char *chars = buffer; - int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth; - int x, y; - Uint32 *dest; - - off /= sizeof(tVT_Char); - dest = (void*)gBGA_Framebuffer; - x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth; - y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight; - dest += y * pitch; - dest += x * giVT_CharWidth; - len /= sizeof(tVT_Char); - while(len--) - { - VT_Font_Render( - chars->Ch, - dest, pitch, - VT_Colour12to24(chars->BGCol), - VT_Colour12to24(chars->FGCol) - ); - - dest += giVT_CharWidth; - - chars ++; - x += giVT_CharWidth; - if( x >= pitch ) { - x = 0; - y += giVT_CharHeight; - dest += pitch*(giVT_CharHeight-1); - } - } - } - else - { - Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off); - - LOG("buffer = %p\n", buffer); - LOG("Updating Framebuffer (%p to %p)\n", - destBuf, destBuf + (Uint)len); - - - // Copy to Frambuffer - memcpy(destBuf, buffer, len); - - LOG("BGA Framebuffer updated\n"); - } - - LEAVE('i', len); - return len; -} - -/** - * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) - * \brief Handle messages to the device - */ -INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) -{ - int ret = -2; - ENTER("pNode iId pData", node, ID, Data); - - switch(ID) - { - case DRV_IOCTL_TYPE: - ret = DRV_TYPE_VIDEO; - break; - case DRV_IOCTL_IDENT: - memcpy(Data, "BGA1", 4); - ret = 1; - break; - case DRV_IOCTL_VERSION: - ret = 0x100; - break; - case DRV_IOCTL_LOOKUP: // TODO: Implement - ret = 0; - break; - - case VIDEO_IOCTL_GETSETMODE: - if( Data ) - ret = BGA_int_UpdateMode(*(int*)(Data)); - else - ret = giBGA_CurrentMode; - break; - - case VIDEO_IOCTL_FINDMODE: - ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data); - break; - - case VIDEO_IOCTL_MODEINFO: - ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data); - break; - - // Request Access to LFB - case VIDEO_IOCTL_REQLFB: - ret = BGA_int_MapFB( *(void**)Data ); - break; - - case VIDEO_IOCTL_SETCURSOR: - gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x; - gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y; - break; - - default: - LEAVE('i', -2); - return -2; - } - - LEAVE('i', ret); - return ret; -} - -//== Internal Functions == -/** - * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value) - * \brief Writes to a BGA register - */ -void BGA_int_WriteRegister(Uint16 reg, Uint16 value) -{ - outw(VBE_DISPI_IOPORT_INDEX, reg); - outw(VBE_DISPI_IOPORT_DATA, value); -} - -INT Uint16 BGA_int_ReadRegister(Uint16 reg) -{ - outw(VBE_DISPI_IOPORT_INDEX, reg); - return inw(VBE_DISPI_IOPORT_DATA); -} - -#if 0 -INT void BGA_int_SetBank(Uint16 bank) -{ - BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank); -} -#endif - -/** - * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp) - * \brief Sets the video mode from the dimensions and bpp given - */ -void BGA_int_SetMode(Uint16 width, Uint16 height) -{ - ENTER("iwidth iheight ibpp", width, height, bpp); - BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); - BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width); - BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height); - BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32); - BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED); - //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM); - LEAVE('-'); -} - -/** - * \fn int BGA_int_UpdateMode(int id) - * \brief Set current vide mode given a mode id - */ -int BGA_int_UpdateMode(int id) -{ - // Sanity Check - if(id < 0 || id >= BGA_MODE_COUNT) return -1; - - // Check if it is a text mode - if( gBGA_Modes[id].flags & MODEFLAG_TEXT ) - BGA_int_SetMode( - gBGA_Modes[id].width*giVT_CharWidth, - gBGA_Modes[id].height*giVT_CharHeight); - else // Graphics? - BGA_int_SetMode( - gBGA_Modes[id].width, - gBGA_Modes[id].height); - - giBGA_CurrentMode = id; - return id; -} - -/** - * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info) - * \brief Find a mode matching the given options - */ -int BGA_int_FindMode(tVideo_IOCtl_Mode *info) -{ - int i; - int best = 0, bestFactor = 1000; - int factor, tmp; - int rqdProduct = info->width * info->height * info->bpp; - - ENTER("pinfo", info); - LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp); - - for(i = 0; i < BGA_MODE_COUNT; i++) - { - #if DEBUG >= 2 - LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp); - #endif - - // Check if this mode is the same type as what we want - if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) ) - continue; - - // Ooh! A perfect match - if(gBGA_Modes[i].width == info->width - && gBGA_Modes[i].height == info->height - && gBGA_Modes[i].bpp == info->bpp) - { - #if DEBUG >= 2 - LogF("Perfect!\n"); - #endif - best = i; - break; - } - - // If not, how close are we? - tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp; - tmp -= rqdProduct; - tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp) - factor = tmp * 100 / rqdProduct; - - #if DEBUG >= 2 - LogF("factor = %i\n", factor); - #endif - - if(factor < bestFactor) - { - bestFactor = factor; - best = i; - } - } - - info->id = best; - info->width = gBGA_Modes[best].width; - info->height = gBGA_Modes[best].height; - info->bpp = gBGA_Modes[best].bpp; - - info->flags = 0; - if(gBGA_Modes[best].flags & MODEFLAG_TEXT) - info->flags |= VIDEO_FLAG_TEXT; - - return best; -} - -/** - * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) - * \brief Get mode information - */ -int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) -{ - // Sanity Check - //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { - // return -EINVAL; - //} - - if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1; - - info->width = gBGA_Modes[info->id].width; - info->height = gBGA_Modes[info->id].height; - info->bpp = gBGA_Modes[info->id].bpp; - - info->flags = 0; - if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT) - info->flags |= VIDEO_FLAG_TEXT; - - return 1; -} - -/** - * \fn int BGA_int_MapFB(void *Dest) - * \brief Map the framebuffer into a process's space - * \param Dest User address to load to - */ -int BGA_int_MapFB(void *Dest) -{ - Uint i; - Uint pages; - - // Sanity Check - if((Uint)Dest > 0xC0000000) return 0; - if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported - - // Count required pages - pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12; - - // Check if there is space - for( i = 0; i < pages; i++ ) - { - if(MM_GetPhysAddr( (Uint)Dest + (i << 12) )) - return 0; - } - - // Map - for( i = 0; i < pages; i++ ) - MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) ); - - return 1; -} diff --git a/Modules/Display/BochsGA/Makefile b/Modules/Display/BochsGA/Makefile new file mode 100644 index 00000000..2df219af --- /dev/null +++ b/Modules/Display/BochsGA/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = bochsvbe.o +NAME = BochsGA + +-include ../Makefile.tpl diff --git a/Modules/Display/BochsGA/bochsvbe.c b/Modules/Display/BochsGA/bochsvbe.c new file mode 100644 index 00000000..06d362cb --- /dev/null +++ b/Modules/Display/BochsGA/bochsvbe.c @@ -0,0 +1,467 @@ +/** + * \file drv_bochsvbe.c + * \brief BGA (Bochs Graphic Adapter) Driver + * \note for Acess2 + * \warning This driver does NOT support the Bochs PCI VGA driver +*/ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include +#include + +#define INT + +// === TYPEDEFS === +typedef struct { + Uint16 width; + Uint16 height; + Uint16 bpp; + Uint16 flags; + Uint32 fbSize; +} t_bga_mode; + +// === CONSTANTS === +enum eMode_Flags { + MODEFLAG_TEXT = 1 +}; +#define BGA_LFB_MAXSIZE (1024*768*4) +#define VBE_DISPI_BANK_ADDRESS 0xA0000 +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 +enum { + VBE_DISPI_INDEX_ID, + VBE_DISPI_INDEX_XRES, + VBE_DISPI_INDEX_YRES, + VBE_DISPI_INDEX_BPP, + VBE_DISPI_INDEX_ENABLE, + VBE_DISPI_INDEX_BANK, + VBE_DISPI_INDEX_VIRT_WIDTH, + VBE_DISPI_INDEX_VIRT_HEIGHT, + VBE_DISPI_INDEX_X_OFFSET, + VBE_DISPI_INDEX_Y_OFFSET +}; + + +// === PROTOTYPES === +// Driver + int BGA_Install(char **Arguments); +void BGA_Uninstall(); +// Internal +void BGA_int_WriteRegister(Uint16 reg, Uint16 value); +Uint16 BGA_int_ReadRegister(Uint16 reg); +void BGA_int_SetBank(Uint16 bank); +void BGA_int_SetMode(Uint16 width, Uint16 height); + int BGA_int_UpdateMode(int id); + int BGA_int_FindMode(tVideo_IOCtl_Mode *info); + int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info); + int BGA_int_MapFB(void *Dest); +// Filesystem +Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); +Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); + int BGA_Ioctl(tVFS_Node *node, int id, void *data); + +// === GLOBALS === +MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL); +tDevFS_Driver gBGA_DriverStruct = { + NULL, "BochsGA", + { + .Read = BGA_Read, + .Write = BGA_Write, + .IOCtl = BGA_Ioctl + } +}; + int giBGA_CurrentMode = -1; +tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1}; + int giBGA_DriverId = -1; +Uint *gBGA_Framebuffer; +t_bga_mode gBGA_Modes[] = { + {}, + { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480 + {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600 + {640,480,8, 0, 640*480}, + {640,480,32, 0, 640*480*4}, + {800,600,8, 0, 800*600}, + {800,600,32, 0, 800*600*4}, +}; +#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0])) + +// === CODE === +/** + * \fn int BGA_Install(char **Arguments) + */ +int BGA_Install(char **Arguments) +{ + int bga_version = 0; + + // Check BGA Version + bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID); + // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable + if(bga_version < 0xB0C4 || bga_version > 0xB0C5) { + Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version); + return 0; + } + + // Install Device + giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct ); + if(giBGA_DriverId == -1) { + Warning("[BGA ] Unable to register with DevFS, maybe already loaded?"); + return 0; + } + + // Map Framebuffer to hardware address + gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb) + + return 1; +} + +/** + * \fn void BGA_Uninstall() + */ +void BGA_Uninstall() +{ + //DevFS_DelDevice( giBGA_DriverId ); + MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 ); +} + +/** + * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) + * \brief Read from the framebuffer + */ +Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) +{ + // Check Mode + if(giBGA_CurrentMode == -1) return -1; + + // Check Offset and Length against Framebuffer Size + if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) + return -1; + + // Copy from Framebuffer + memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len); + return len; +} + +/** + * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) + * \brief Write to the framebuffer + */ +Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *Buffer) +{ + ENTER("xoff xlen", off, len); + + // Check Mode + if(giBGA_CurrentMode == -1) { + LEAVE('i', -1); + return -1; + } + + // Check Input against Frambuffer Size + if(off + len > gBGA_Modes[giBGA_CurrentMode].fbSize) { + LEAVE('i', -1); + return -1; + } + + // Text Mode + if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT ) + { + tVT_Char *chars = Buffer; + int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth; + int x, y; + Uint32 *dest; + + off /= sizeof(tVT_Char); + dest = (void*)gBGA_Framebuffer; + x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth; + y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight; + dest += y * pitch; + dest += x * giVT_CharWidth; + len /= sizeof(tVT_Char); + while(len--) + { + VT_Font_Render( + chars->Ch, + dest, pitch, + VT_Colour12to24(chars->BGCol), + VT_Colour12to24(chars->FGCol) + ); + + dest += giVT_CharWidth; + + chars ++; + x += giVT_CharWidth; + if( x >= pitch ) { + x = 0; + y += giVT_CharHeight; + dest += pitch*(giVT_CharHeight-1); + } + } + } + else + { + Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off); + + Log("buffer = %p", Buffer); + Log("Updating Framebuffer (%p to %p)", + destBuf, destBuf + (Uint)len); + + + // Copy to Frambuffer + memcpy(destBuf, Buffer, len); + + Log("BGA Framebuffer updated"); + } + + LEAVE('i', len); + return len; +} + +/** + * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) + * \brief Handle messages to the device + */ +INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data) +{ + int ret = -2; + ENTER("pNode iId pData", node, ID, Data); + + switch(ID) + { + case DRV_IOCTL_TYPE: + ret = DRV_TYPE_VIDEO; + break; + case DRV_IOCTL_IDENT: + memcpy(Data, "BGA1", 4); + ret = 1; + break; + case DRV_IOCTL_VERSION: + ret = 0x100; + break; + case DRV_IOCTL_LOOKUP: // TODO: Implement + ret = 0; + break; + + case VIDEO_IOCTL_GETSETMODE: + if( Data ) + ret = BGA_int_UpdateMode(*(int*)(Data)); + else + ret = giBGA_CurrentMode; + break; + + case VIDEO_IOCTL_FINDMODE: + ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data); + break; + + case VIDEO_IOCTL_MODEINFO: + ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data); + break; + + // Request Access to LFB + case VIDEO_IOCTL_REQLFB: + ret = BGA_int_MapFB( *(void**)Data ); + break; + + case VIDEO_IOCTL_SETCURSOR: + gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x; + gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y; + break; + + default: + LEAVE('i', -2); + return -2; + } + + LEAVE('i', ret); + return ret; +} + +//== Internal Functions == +/** + * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value) + * \brief Writes to a BGA register + */ +void BGA_int_WriteRegister(Uint16 reg, Uint16 value) +{ + outw(VBE_DISPI_IOPORT_INDEX, reg); + outw(VBE_DISPI_IOPORT_DATA, value); +} + +INT Uint16 BGA_int_ReadRegister(Uint16 reg) +{ + outw(VBE_DISPI_IOPORT_INDEX, reg); + return inw(VBE_DISPI_IOPORT_DATA); +} + +#if 0 +INT void BGA_int_SetBank(Uint16 bank) +{ + BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank); +} +#endif + +/** + * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp) + * \brief Sets the video mode from the dimensions and bpp given + */ +void BGA_int_SetMode(Uint16 width, Uint16 height) +{ + ENTER("iwidth iheight ibpp", width, height, bpp); + BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); + BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width); + BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height); + BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32); + BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED); + //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM); + LEAVE('-'); +} + +/** + * \fn int BGA_int_UpdateMode(int id) + * \brief Set current vide mode given a mode id + */ +int BGA_int_UpdateMode(int id) +{ + // Sanity Check + if(id < 0 || id >= BGA_MODE_COUNT) return -1; + + // Check if it is a text mode + if( gBGA_Modes[id].flags & MODEFLAG_TEXT ) + BGA_int_SetMode( + gBGA_Modes[id].width*giVT_CharWidth, + gBGA_Modes[id].height*giVT_CharHeight); + else // Graphics? + BGA_int_SetMode( + gBGA_Modes[id].width, + gBGA_Modes[id].height); + + giBGA_CurrentMode = id; + return id; +} + +/** + * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info) + * \brief Find a mode matching the given options + */ +int BGA_int_FindMode(tVideo_IOCtl_Mode *info) +{ + int i; + int best = 0, bestFactor = 1000; + int factor, tmp; + int rqdProduct = info->width * info->height * info->bpp; + + ENTER("pinfo", info); + LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp); + + for(i = 0; i < BGA_MODE_COUNT; i++) + { + #if DEBUG >= 2 + LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp); + #endif + + // Check if this mode is the same type as what we want + if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) ) + continue; + + // Ooh! A perfect match + if(gBGA_Modes[i].width == info->width + && gBGA_Modes[i].height == info->height + && gBGA_Modes[i].bpp == info->bpp) + { + #if DEBUG >= 2 + LogF("Perfect!\n"); + #endif + best = i; + break; + } + + // If not, how close are we? + tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp; + tmp -= rqdProduct; + tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp) + factor = tmp * 100 / rqdProduct; + + #if DEBUG >= 2 + LogF("factor = %i\n", factor); + #endif + + if(factor < bestFactor) + { + bestFactor = factor; + best = i; + } + } + + info->id = best; + info->width = gBGA_Modes[best].width; + info->height = gBGA_Modes[best].height; + info->bpp = gBGA_Modes[best].bpp; + + info->flags = 0; + if(gBGA_Modes[best].flags & MODEFLAG_TEXT) + info->flags |= VIDEO_FLAG_TEXT; + + return best; +} + +/** + * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) + * \brief Get mode information + */ +int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info) +{ + // Sanity Check + //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) { + // return -EINVAL; + //} + + if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1; + + info->width = gBGA_Modes[info->id].width; + info->height = gBGA_Modes[info->id].height; + info->bpp = gBGA_Modes[info->id].bpp; + + info->flags = 0; + if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT) + info->flags |= VIDEO_FLAG_TEXT; + + return 1; +} + +/** + * \fn int BGA_int_MapFB(void *Dest) + * \brief Map the framebuffer into a process's space + * \param Dest User address to load to + */ +int BGA_int_MapFB(void *Dest) +{ + Uint i; + Uint pages; + + // Sanity Check + if((Uint)Dest > 0xC0000000) return 0; + if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported + + // Count required pages + pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12; + + // Check if there is space + for( i = 0; i < pages; i++ ) + { + if(MM_GetPhysAddr( (Uint)Dest + (i << 12) )) + return 0; + } + + // Map + for( i = 0; i < pages; i++ ) + MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) ); + + return 1; +} diff --git a/Modules/Display/Makefile.tpl b/Modules/Display/Makefile.tpl new file mode 100644 index 00000000..80c6d4dd --- /dev/null +++ b/Modules/Display/Makefile.tpl @@ -0,0 +1 @@ +-include ../../Makefile.tpl diff --git a/Modules/FDD/Makefile b/Modules/FDD/Makefile deleted file mode 100644 index 15965531..00000000 --- a/Modules/FDD/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = fdd.o -NAME = FDD - --include ../Makefile.tpl diff --git a/Modules/FDD/fdd.c b/Modules/FDD/fdd.c deleted file mode 100644 index 6b55f17b..00000000 --- a/Modules/FDD/fdd.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - * AcessOS 0.1 - * Floppy Disk Access Code - */ -#define DEBUG 0 -#include -#include -#include -#include -#include -#include - -#define WARN 0 - -// === CONSTANTS === -// --- Current Version -#define FDD_VERSION ((0<<8)|(75)) - -// --- Options -#define USE_CACHE 0 // Use Sector Cache -#define CACHE_SIZE 32 // Number of cachable sectors -#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation -#define MOTOR_ON_DELAY 500 // Miliseconds -#define MOTOR_OFF_DELAY 2000 // Miliseconds - -// === TYPEDEFS === -/** - * \brief Representation of a floppy drive - */ -typedef struct { - int type; - volatile int motorState; //2 - On, 1 - Spinup, 0 - Off - int track[2]; - int timer; - tVFS_Node Node; - #if !USE_CACHE - tIOCache *CacheHandle; - #endif -} t_floppyDevice; - -/** - * \brief Cached Sector - */ -typedef struct { - Uint64 timestamp; - Uint16 disk; - Uint16 sector; // Allows 32Mb of addressable space (Plenty for FDD) - Uint8 data[512]; -} t_floppySector; - -// === CONSTANTS === -static const char *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" }; -static const int cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 }; -static const short cPORTBASE[] = { 0x3F0, 0x370 }; - -enum FloppyPorts { - PORT_STATUSA = 0x0, - PORT_STATUSB = 0x1, - PORT_DIGOUTPUT = 0x2, - PORT_MAINSTATUS = 0x4, - PORT_DATARATE = 0x4, - PORT_DATA = 0x5, - PORT_DIGINPUT = 0x7, - PORT_CONFIGCTRL = 0x7 -}; - -enum FloppyCommands { - FIX_DRIVE_DATA = 0x03, - HECK_DRIVE_STATUS = 0x04, - CALIBRATE_DRIVE = 0x07, - CHECK_INTERRUPT_STATUS = 0x08, - SEEK_TRACK = 0x0F, - READ_SECTOR_ID = 0x4A, - FORMAT_TRACK = 0x4D, - READ_TRACK = 0x42, - READ_SECTOR = 0x66, - WRITE_SECTOR = 0xC5, - WRITE_DELETE_SECTOR = 0xC9, - READ_DELETE_SECTOR = 0xCC, -}; - -// === PROTOTYPES === -// --- Filesystem - int FDD_Install(char **Arguments); -char *FDD_ReadDir(tVFS_Node *Node, int pos); -tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name); - int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data); -Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); -// --- 1st Level Disk Access -Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk); -// --- Raw Disk Access - int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer); - int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer); -// --- Helpers -void FDD_IRQHandler(int Num); -void FDD_WaitIRQ(); -void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl); -inline void FDD_AquireSpinlock(); -inline void FDD_FreeSpinlock(); -#if USE_CACHE -inline void FDD_AquireCacheSpinlock(); -inline void FDD_FreeCacheSpinlock(); -#endif -void FDD_int_SendByte(int base, char byte); - int FDD_int_GetByte(int base); -void FDD_Reset(int id); -void FDD_Recalibrate(int disk); - int FDD_int_SeekTrack(int disk, int head, int track); -void FDD_int_TimerCallback(int arg); -void FDD_int_StopMotor(int disk); -void FDD_int_StartMotor(int disk); - int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt); - -// === GLOBALS === -MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL); -t_floppyDevice gFDD_Devices[2]; -volatile int fdd_inUse = 0; -volatile int fdd_irq6 = 0; -tDevFS_Driver gFDD_DriverInfo = { - NULL, "fdd", - { - .Size = -1, - .NumACLs = 1, - .ACLs = &gVFS_ACL_EveryoneRX, - .Flags = VFS_FFLAG_DIRECTORY, - .ReadDir = FDD_ReadDir, - .FindDir = FDD_FindDir, - .IOCtl = FDD_IOCtl - } -}; -#if USE_CACHE -int siFDD_CacheInUse = 0; -int siFDD_SectorCacheSize = CACHE_SIZE; -t_floppySector sFDD_SectorCache[CACHE_SIZE]; -#endif - -// === CODE === -/** - * \fn int FDD_Install(char **Arguments) - * \brief Installs floppy driver - */ -int FDD_Install(char **Arguments) -{ - Uint8 data; - - // Determine Floppy Types (From CMOS) - outb(0x70, 0x10); - data = inb(0x71); - gFDD_Devices[0].type = data >> 4; - gFDD_Devices[1].type = data & 0xF; - gFDD_Devices[0].track[0] = -1; - gFDD_Devices[1].track[1] = -1; - - Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]); - - // Clear FDD IRQ Flag - FDD_SensInt(0x3F0, NULL, NULL); - // Install IRQ6 Handler - IRQ_AddHandler(6, FDD_IRQHandler); - // Reset Primary FDD Controller - FDD_Reset(0); - - // Initialise Root Node - gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime - = gFDD_DriverInfo.RootNode.ATime = now(); - - // Initialise Child Nodes - gFDD_Devices[0].Node.Inode = 0; - gFDD_Devices[0].Node.Flags = 0; - gFDD_Devices[0].Node.NumACLs = 0; - gFDD_Devices[0].Node.Read = FDD_ReadFS; - gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS; - memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node)); - - gFDD_Devices[1].Node.Inode = 1; - - // Set Lengths - gFDD_Devices[0].Node.Size = cFDD_SIZES[data >> 4]; - gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF]; - - // Create Sector Cache - #if USE_CACHE - //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE); - //siFDD_SectorCacheSize = CACHE_SIZE; - #else - if( cFDD_SIZES[data >> 4] ) { - gFDD_Devices[0].CacheHandle = IOCache_Create( - FDD_WriteSector, 0, 512, - gFDD_Devices[0].Node.Size / (512*4) - ); // Cache is 1/4 the size of the disk - } - if( cFDD_SIZES[data & 15] ) { - gFDD_Devices[1].CacheHandle = IOCache_Create( - FDD_WriteSector, 0, 512, - gFDD_Devices[1].Node.Size / (512*4) - ); // Cache is 1/4 the size of the disk - } - #endif - - // Register with devfs - DevFS_AddDevice(&gFDD_DriverInfo); - - return 1; -} - -/** - * \fn char *FDD_ReadDir(tVFS_Node *Node, int pos) - * \brief Read Directory - */ -char *FDD_ReadDir(tVFS_Node *Node, int pos) -{ - char name[2] = "0\0"; - //Update Accessed Time - //gFDD_DrvInfo.rootNode.atime = now(); - - //Check for bounds - if(pos >= 2 || pos < 0) - return NULL; - - if(gFDD_Devices[pos].type == 0) - return VFS_SKIP; - - name[0] += pos; - - //Return - return strdup(name); -} - -/** - * \fn tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename); - * \brief Find File Routine (for vfs_node) - */ -tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *Filename) -{ - int i; - - ENTER("sFilename", Filename); - - // Sanity check string - if(Filename == NULL) { - LEAVE('n'); - return NULL; - } - - // Check string length (should be 1) - if(Filename[0] == '\0' || Filename[1] != '\0') { - LEAVE('n'); - return NULL; - } - - // Get First character - i = Filename[0] - '0'; - - // Check for 1st disk and if it is present return - if(i == 0 && gFDD_Devices[0].type != 0) { - LEAVE('p', &gFDD_Devices[0].Node); - return &gFDD_Devices[0].Node; - } - - // Check for 2nd disk and if it is present return - if(i == 1 && gFDD_Devices[1].type != 0) { - LEAVE('p', &gFDD_Devices[1].Node); - return &gFDD_Devices[1].Node; - } - - // Else return null - LEAVE('n'); - return NULL; -} - -static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL}; -/** - * \fn int FDD_IOCtl(tVFS_Node *Node, int id, void *data) - * \brief Stub ioctl function - */ -int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data) -{ - switch(ID) - { - case DRV_IOCTL_TYPE: return DRV_TYPE_DISK; - case DRV_IOCTL_IDENT: return ModUtil_SetIdent(Data, "FDD"); - case DRV_IOCTL_VERSION: return FDD_VERSION; - case DRV_IOCTL_LOOKUP: return ModUtil_LookupString((char**)casIOCTLS, Data); - - case DISK_IOCTL_GETBLOCKSIZE: return 512; - - default: - return 0; - } -} - -/** - * \fn Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Read Data from a disk -*/ -Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - int i = 0; - int disk; - //Uint32 buf[128]; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - if(Node == NULL) { - LEAVE('i', -1); - return -1; - } - - if(Node->Inode != 0 && Node->Inode != 1) { - LEAVE('i', -1); - return -1; - } - - disk = Node->Inode; - - // Update Accessed Time - Node->ATime = now(); - - #if 0 - if((Offset & 0x1FF) || (Length & 0x1FF)) - { - // Un-Aligned Offset/Length - int startOff = Offset >> 9; - int sectOff = Offset & 0x1FF; - int sectors = (Length + 0x1FF) >> 9; - - LOG("Non-aligned Read"); - - //Read Starting Sector - if(!FDD_ReadSector(disk, startOff, buf)) - return 0; - memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length); - - // If the data size is one sector or less - if(Length <= 512-sectOff) - { - LEAVE('X', Length); - return Length; //Return - } - Buffer += 512-sectOff; - - //Read Middle Sectors - for( i = 1; i < sectors - 1; i++ ) - { - if(!FDD_ReadSector(disk, startOff+i, buf)) { - LEAVE('i', -1); - return -1; - } - memcpy(Buffer, buf, 512); - Buffer += 512; - } - - //Read End Sectors - if(!FDD_ReadSector(disk, startOff+i, buf)) - return 0; - memcpy(Buffer, buf, (len&0x1FF)-sectOff); - - LEAVE('X', Length); - return Length; - } - else - { - int count = Length >> 9; - int sector = Offset >> 9; - LOG("Aligned Read"); - //Aligned Offset and Length - Simple Code - for( i = 0; i < count; i ++ ) - { - FDD_ReadSector(disk, sector, buf); - memcpy(buffer, buf, 512); - buffer += 512; - sector++; - } - LEAVE('i', Length); - return Length; - } - #endif - - i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk); - LEAVE('i', i); - return i; -} - -/** - * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk) - * \brief Reads \a Count contiguous sectors from a disk - * \param SectorAddr Address of the first sector - * \param Count Number of sectors to read - * \param Buffer Destination Buffer - * \param Disk Disk Number - * \return Number of sectors read - * \note Used as a ::DrvUtil_ReadBlock helper - */ -Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk) -{ - Uint ret = 0; - while(Count --) - { - if( FDD_ReadSector(Disk, SectorAddr, Buffer) != 1 ) - return ret; - - Buffer = (void*)( (tVAddr)Buffer + 512 ); - SectorAddr ++; - ret ++; - } - return ret; -} - -/** - * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) - * \fn Read a sector from disk -*/ -int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) -{ - int cyl, head, sec; - int spt, base; - int i; - int lba = SectorAddr; - - ENTER("idisk Xlba pbuf", disk, lba, buf); - - #if USE_CACHE - FDD_AquireCacheSpinlock(); - for( i = 0; i < siFDD_SectorCacheSize; i++ ) - { - if(sFDD_SectorCache[i].timestamp == 0) continue; - if(sFDD_SectorCache[i].disk == Disk - && sFDD_SectorCache[i].sector == lba) { - LOG("Found %i in cache %i", lba, i); - memcpy(Buffer, sFDD_SectorCache[i].data, 512); - sFDD_SectorCache[i].timestamp = now(); - FDD_FreeCacheSpinlock(); - LEAVE('i', 1); - return 1; - } - } - LOG("Read %i from Disk", lba); - FDD_FreeCacheSpinlock(); - #else - if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) { - LEAVE('i', 1); - return 1; - } - #endif - - base = cPORTBASE[Disk>>1]; - - LOG("Calculating Disk Dimensions"); - // Get CHS position - if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) { - LEAVE('i', -1); - return -1; - } - - // Remove Old Timer - Time_RemoveTimer(gFDD_Devices[Disk].timer); - // Check if Motor is on - if(gFDD_Devices[Disk].motorState == 0) { - FDD_int_StartMotor(Disk); - } - - LOG("Wait for Motor Spinup"); - - // Wait for spinup - while(gFDD_Devices[Disk].motorState == 1) Threads_Yield(); - - LOG("C:%i,H:%i,S:%i", cyl, head, sec); - LOG("Acquire Spinlock"); - - FDD_AquireSpinlock(); - - // Seek to track - outb(base+CALIBRATE_DRIVE, 0); - i = 0; - while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield(); - //FDD_SensInt(base, NULL, NULL); // Wait for IRQ - - LOG("Setting DMA for read"); - - //Read Data from DMA - DMA_SetChannel(2, 512, 1); // Read 512 Bytes - - LOG("Sending read command"); - - //Threads_Wait(100); // Wait for Head to settle - Time_Delay(100); - FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6 - FDD_int_SendByte(base, (head << 2) | (Disk&1)); - FDD_int_SendByte(base, (Uint8)cyl); - FDD_int_SendByte(base, (Uint8)head); - FDD_int_SendByte(base, (Uint8)sec); - FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val}) - FDD_int_SendByte(base, spt); // SPT - FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default) - FDD_int_SendByte(base, 0xFF); // Data Length - - // Wait for IRQ - LOG("Waiting for Data to be read"); - FDD_WaitIRQ(); - - // Read Data from DMA - LOG(" FDD_ReadSector: Reading Data"); - DMA_ReadData(2, 512, Buffer); - - // Clear Input Buffer - LOG("Clearing Input Buffer"); - FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); - FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); - - LOG("Realeasing Spinlock and Setting motor to stop"); - // Release Spinlock - FDD_FreeSpinlock(); - - //Set timer to turn off motor affter a gap - gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer - - #if USE_CACHE - { - FDD_AquireCacheSpinlock(); - int oldest = 0; - for(i=0;i>1]; - - // Check if seeking is needed - if(gFDD_Devices[disk].track[head] == track) - return 1; - - // - Seek Head 0 - FDD_int_SendByte(base, SEEK_TRACK); - FDD_int_SendByte(base, (head<<2)|(disk&1)); - FDD_int_SendByte(base, track); // Send Seek command - FDD_WaitIRQ(); - FDD_SensInt(base, &sr0, &cyl); // Wait for IRQ - if((sr0 & 0xF0) != 0x20) { - LOG("sr0 = 0x%x", sr0); - return 0; //Check Status - } - if(cyl != track) return 0; - - // Set Track in structure - gFDD_Devices[disk].track[head] = track; - return 1; -} - -/** - * \fn int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt) - * \brief Get Dimensions of a disk - */ -int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt) -{ - switch(type) { - case 0: - return 0; - - // 360Kb 5.25" - case 1: - *spt = 9; - *s = (lba % 9) + 1; - *c = lba / 18; - *h = (lba / 9) & 1; - break; - - // 1220Kb 5.25" - case 2: - *spt = 15; - *s = (lba % 15) + 1; - *c = lba / 30; - *h = (lba / 15) & 1; - break; - - // 720Kb 3.5" - case 3: - *spt = 9; - *s = (lba % 9) + 1; - *c = lba / 18; - *h = (lba / 9) & 1; - break; - - // 1440Kb 3.5" - case 4: - *spt = 18; - *s = (lba % 18) + 1; - *c = lba / 36; - *h = (lba / 18) & 1; - //Log("1440k - lba=%i(0x%x), *s=%i,*c=%i,*h=%i", lba, lba, *s, *c, *h); - break; - - // 2880Kb 3.5" - case 5: - *spt = 36; - *s = (lba % 36) + 1; - *c = lba / 72; - *h = (lba / 32) & 1; - break; - - default: - return -2; - } - return 1; -} - -/** - * \fn void FDD_IRQHandler(int Num) - * \brief Handles IRQ6 - */ -void FDD_IRQHandler(int Num) -{ - fdd_irq6 = 1; -} - -/** - * \fn FDD_WaitIRQ() - * \brief Wait for an IRQ6 - */ -void FDD_WaitIRQ() -{ - // Wait for IRQ - while(!fdd_irq6) Threads_Yield(); - fdd_irq6 = 0; -} - -void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl) -{ - FDD_int_SendByte(base, CHECK_INTERRUPT_STATUS); - if(sr0) *sr0 = FDD_int_GetByte(base); - else FDD_int_GetByte(base); - if(cyl) *cyl = FDD_int_GetByte(base); - else FDD_int_GetByte(base); -} - -void FDD_AquireSpinlock() -{ - while(fdd_inUse) - Threads_Yield(); - fdd_inUse = 1; -} - -inline void FDD_FreeSpinlock() -{ - fdd_inUse = 0; -} - -#if USE_CACHE -inline void FDD_AquireCacheSpinlock() -{ - while(siFDD_CacheInUse) Threads_Yield(); - siFDD_CacheInUse = 1; -} -inline void FDD_FreeCacheSpinlock() -{ - siFDD_CacheInUse = 0; -} -#endif - -/** - * void FDD_int_SendByte(int base, char byte) - * \brief Sends a command to the controller - */ -void FDD_int_SendByte(int base, char byte) -{ - volatile int state; - int timeout = 128; - for( ; timeout--; ) - { - state = inb(base + PORT_MAINSTATUS); - if ((state & 0xC0) == 0x80) - { - outb(base + PORT_DATA, byte); - return; - } - inb(0x80); //Delay - } - #if WARN - Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base); - #endif -} - -/** - * int FDD_int_GetByte(int base, char byte) - * \brief Receive data from fdd controller - */ -int FDD_int_GetByte(int base) -{ - volatile int state; - int timeout; - for( timeout = 128; timeout--; ) - { - state = inb((base + PORT_MAINSTATUS)); - if ((state & 0xd0) == 0xd0) - return inb(base + PORT_DATA); - inb(0x80); - } - return -1; -} - -/** - * \brief Recalibrate the specified disk - */ -void FDD_Recalibrate(int disk) -{ - ENTER("idisk", disk); - - LOG("Starting Motor"); - FDD_int_StartMotor(disk); - // Wait for Spinup - while(gFDD_Devices[disk].motorState == 1) Threads_Yield(); - - LOG("Sending Calibrate Command"); - FDD_int_SendByte(cPORTBASE[disk>>1], CALIBRATE_DRIVE); - FDD_int_SendByte(cPORTBASE[disk>>1], disk&1); - - LOG("Waiting for IRQ"); - FDD_WaitIRQ(); - FDD_SensInt(cPORTBASE[disk>>1], NULL, NULL); - - LOG("Stopping Motor"); - FDD_int_StopMotor(disk); - LEAVE('-'); -} - -/** - * \brief Reset the specified FDD controller - */ -void FDD_Reset(int id) -{ - int base = cPORTBASE[id]; - - ENTER("iID", id); - - outb(base + PORT_DIGOUTPUT, 0); // Stop Motors & Disable FDC - outb(base + PORT_DIGOUTPUT, 0x0C); // Re-enable FDC (DMA and Enable) - - LOG("Awaiting IRQ"); - - FDD_WaitIRQ(); - FDD_SensInt(base, NULL, NULL); - - LOG("Setting Driver Info"); - outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s - FDD_int_SendByte(base, FIX_DRIVE_DATA); // Step and Head Load Times - FDD_int_SendByte(base, 0xDF); // Step Rate Time, Head Unload Time (Nibble each) - FDD_int_SendByte(base, 0x02); // Head Load Time >> 1 - while(FDD_int_SeekTrack(0, 0, 1) == 0); // set track - while(FDD_int_SeekTrack(0, 1, 1) == 0); // set track - - LOG("Recalibrating Disk"); - FDD_Recalibrate((id<<1)|0); - FDD_Recalibrate((id<<1)|1); - - LEAVE('-'); -} - -/** - * \fn void FDD_int_TimerCallback() - * \brief Called by timer - */ -void FDD_int_TimerCallback(int arg) -{ - ENTER("iarg", arg); - if(gFDD_Devices[arg].motorState == 1) - gFDD_Devices[arg].motorState = 2; - Time_RemoveTimer(gFDD_Devices[arg].timer); - gFDD_Devices[arg].timer = -1; - LEAVE('-'); -} - -/** - * \fn void FDD_int_StartMotor(char disk) - * \brief Starts FDD Motor - */ -void FDD_int_StartMotor(int disk) -{ - Uint8 state; - state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT ); - state |= 1 << (4+disk); - outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state ); - gFDD_Devices[disk].motorState = 1; - gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk); -} - -/** - * \fn void FDD_int_StopMotor(int disk) - * \brief Stops FDD Motor - */ -void FDD_int_StopMotor(int disk) -{ - Uint8 state; - state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT ); - state &= ~( 1 << (4+disk) ); - outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state ); - gFDD_Devices[disk].motorState = 0; -} - -/** - * \fn void ModuleUnload() - * \brief Prepare the module for removal - */ -void ModuleUnload() -{ - int i; - FDD_AquireSpinlock(); - for(i=0;i<4;i++) { - Time_RemoveTimer(gFDD_Devices[i].timer); - FDD_int_StopMotor(i); - } - //IRQ_Clear(6); -} diff --git a/Modules/FS_Ext2/Makefile b/Modules/FS_Ext2/Makefile deleted file mode 100644 index 806e638c..00000000 --- a/Modules/FS_Ext2/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = ext2.o read.o dir.o write.o -NAME = FS_Ext2 - --include ../Makefile.tpl diff --git a/Modules/FS_Ext2/dir.c b/Modules/FS_Ext2/dir.c deleted file mode 100644 index 5fe89336..00000000 --- a/Modules/FS_Ext2/dir.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file dir.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include "ext2_common.h" - - -// === PROTOTYPES === -char *Ext2_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); - int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name); - -// === CODE === -/** - \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos) - \brief Reads a directory entry -*/ -char *Ext2_ReadDir(tVFS_Node *Node, int Pos) -{ - tExt2_Inode inode; - char namebuf[EXT2_NAME_LEN+1]; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0, ofs = 0; - int entNum = 0; - tExt2_Disk *disk = Node->ImplPtr; - Uint size; - - ENTER("pNode iPos", Node, Pos); - - // Read directory's inode - Ext2_int_GetInode(Node, &inode); - size = inode.i_size; - - LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); - - // Find Entry - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - while(Pos -- && size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - // Check for the end of the list - if(size <= 0) { - LEAVE('n'); - return NULL; - } - - // Read Entry - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); - //LOG("dirent.inode = %i", dirent.inode); - //LOG("dirent.rec_len = %i", dirent.rec_len); - //LOG("dirent.name_len = %i", dirent.name_len); - VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); - namebuf[ dirent.name_len ] = '\0'; // Cap off string - - - // Ignore . and .. (these are done in the VFS) - if( (namebuf[0] == '.' && namebuf[1] == '\0') - || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) { - LEAVE('p', VFS_SKIP); - return VFS_SKIP; // Skip - } - - LEAVE('s', namebuf); - // Create new node - return strdup(namebuf); -} - -/** - \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename) - \brief Gets information about a file - \param node vfs node - Parent Node - \param filename String - Name of file - \return VFS Node of file -*/ -tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - char namebuf[EXT2_NAME_LEN+1]; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0, ofs = 0; - int entNum = 0; - Uint size; - - // Read directory's inode - Ext2_int_GetInode(Node, &inode); - size = inode.i_size; - - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - // Find File - while(size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); - namebuf[ dirent.name_len ] = '\0'; // Cap off string - // If it matches, create a node and return it - if(strcmp(namebuf, Filename) == 0) - return Ext2_int_CreateNode( disk, dirent.inode, namebuf ); - // Increment pointers - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - // Check for end of block - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - return NULL; -} - -/** - * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) - * \brief Create a new node - */ -int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) -{ - return 0; -} - -// ---- INTERNAL FUNCTIONS ---- -/** - * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) - * \brief Create a new VFS Node - */ -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) -{ - tExt2_Inode inode; - tVFS_Node retNode; - tVFS_Node *tmpNode; - - if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) - return NULL; - - if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) - return tmpNode; - - - // Set identifiers - retNode.Inode = InodeID; - retNode.ImplPtr = Disk; - - // Set file length - retNode.Size = inode.i_size; - - // Set Access Permissions - retNode.UID = inode.i_uid; - retNode.GID = inode.i_gid; - retNode.NumACLs = 3; - retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); - - // Set Function Pointers - retNode.Read = Ext2_Read; - retNode.Write = Ext2_Write; - retNode.Close = Ext2_CloseFile; - - switch(inode.i_mode & EXT2_S_IFMT) - { - // Symbolic Link - case EXT2_S_IFLNK: - retNode.Flags = VFS_FFLAG_SYMLINK; - break; - // Regular File - case EXT2_S_IFREG: - retNode.Flags = 0; - retNode.Size |= (Uint64)inode.i_dir_acl << 32; - break; - // Directory - case EXT2_S_IFDIR: - retNode.ReadDir = Ext2_ReadDir; - retNode.FindDir = Ext2_FindDir; - retNode.MkNod = Ext2_MkNod; - //retNode.Relink = Ext2_Relink; - retNode.Flags = VFS_FFLAG_DIRECTORY; - break; - // Unknown, Write protect and hide it to be safe - default: - retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN; - break; - } - - // Check if the file should be hidden - //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN; - - // Set Timestamps - retNode.ATime = now(); - retNode.MTime = inode.i_mtime * 1000; - retNode.CTime = inode.i_ctime * 1000; - - // Save in node cache and return saved node - return Inode_CacheNode(Disk->CacheID, &retNode); -} diff --git a/Modules/FS_Ext2/ext2.c b/Modules/FS_Ext2/ext2.c deleted file mode 100644 index 81dcef0b..00000000 --- a/Modules/FS_Ext2/ext2.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file fs/ext2.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include "ext2_common.h" -#include - -// === PROTOTYPES === - int Ext2_Install(char **Arguments); -// Interface Functions -tVFS_Node *Ext2_InitDevice(char *Device, char **Options); -void Ext2_Unmount(tVFS_Node *Node); -void Ext2_CloseFile(tVFS_Node *Node); -// Internal Helpers - int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); -Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); -Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent); -void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); - -// === SEMI-GLOBALS === -MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL); -tExt2_Disk gExt2_disks[6]; - int giExt2_count = 0; -tVFS_Driver gExt2_FSInfo = { - "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL - }; - -// === CODE === - -/** - * \fn int Ext2_Install(char **Arguments) - * \brief Install the Ext2 Filesystem Driver - */ -int Ext2_Install(char **Arguments) -{ - VFS_AddDriver( &gExt2_FSInfo ); - return 1; -} - -/** - \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options) - \brief Initializes a device to be read by by the driver - \param Device String - Device to read from - \param Options NULL Terminated array of option strings - \return Root Node -*/ -tVFS_Node *Ext2_InitDevice(char *Device, char **Options) -{ - tExt2_Disk *disk; - int fd; - int groupCount; - tExt2_SuperBlock sb; - tExt2_Inode inode; - - ENTER("sDevice pOptions", Device, Options); - - // Open Disk - fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device - if(fd == -1) { - Warning("[EXT2 ] Unable to open '%s'", Device); - LEAVE('n'); - return NULL; - } - - // Read Superblock at offset 1024 - VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock - - // Sanity Check Magic value - if(sb.s_magic != 0xEF53) { - Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device); - VFS_Close(fd); - LEAVE('n'); - return NULL; - } - - // Get Group count - groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); - LOG("groupCount = %i", groupCount); - - // Allocate Disk Information - disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); - if(!disk) { - Warning("[EXT2 ] Unable to allocate disk structure"); - VFS_Close(fd); - LEAVE('n'); - return NULL; - } - disk->FD = fd; - memcpy(&disk->SuperBlock, &sb, 1024); - disk->GroupCount = groupCount; - - // Get an inode cache handle - disk->CacheID = Inode_GetHandle(); - - // Get Block Size - LOG("s_log_block_size = 0x%x", sb.s_log_block_size); - disk->BlockSize = 1024 << sb.s_log_block_size; - - // Read Group Information - VFS_ReadAt( - disk->FD, - sb.s_first_data_block * disk->BlockSize + 1024, - sizeof(tExt2_Group)*groupCount, - disk->Groups - ); - - #if VERBOSE - LOG("Block Group 0"); - LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap); - LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap); - LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table); - LOG("Block Group 1"); - LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap); - LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap); - LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table); - #endif - - // Get root Inode - Ext2_int_ReadInode(disk, 2, &inode); - - // Create Root Node - memset(&disk->RootNode, 0, sizeof(tVFS_Node)); - disk->RootNode.Inode = 2; // Root inode ID - disk->RootNode.ImplPtr = disk; // Save disk pointer - disk->RootNode.Size = -1; // Fill in later (on readdir) - disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; - - disk->RootNode.ReadDir = Ext2_ReadDir; - disk->RootNode.FindDir = Ext2_FindDir; - //disk->RootNode.Relink = Ext2_Relink; - - // Complete root node - disk->RootNode.UID = inode.i_uid; - disk->RootNode.GID = inode.i_gid; - disk->RootNode.NumACLs = 1; - disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; - - #if DEBUG - LOG("inode.i_size = 0x%x", inode.i_size); - LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); - #endif - - LEAVE('p', &disk->RootNode); - return &disk->RootNode; -} - -/** - * \fn void Ext2_Unmount(tVFS_Node *Node) - * \brief Close a mounted device - */ -void Ext2_Unmount(tVFS_Node *Node) -{ - tExt2_Disk *disk = Node->ImplPtr; - - VFS_Close( disk->FD ); - Inode_ClearCache( disk->CacheID ); - memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); - free(disk); -} - -/** - * \fn void Ext2_CloseFile(tVFS_Node *Node) - * \brief Close a file (Remove it from the cache) - */ -void Ext2_CloseFile(tVFS_Node *Node) -{ - tExt2_Disk *disk = Node->ImplPtr; - Inode_UncacheNode(disk->CacheID, Node->Inode); - return ; -} - -//================================== -//= INTERNAL FUNCTIONS = -//================================== - - -/** - * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) - * \brief Gets the inode descriptor for a node - * \param Node node to get the Inode of - * \param Inode Destination - */ -int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) -{ - return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); -} - -/** - * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) - * \brief Read an inode into memory - */ -int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) -{ - int group, subId; - - //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode); - //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode); - - if(InodeId == 0) return 0; - - InodeId --; // Inodes are numbered starting at 1 - - group = InodeId / Disk->SuperBlock.s_inodes_per_group; - subId = InodeId % Disk->SuperBlock.s_inodes_per_group; - - //LOG("group=%i, subId = %i", group, subId); - - // Read Inode - VFS_ReadAt(Disk->FD, - Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId, - sizeof(tExt2_Inode), - Inode); - return 1; -} - -/** - * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) - * \brief Get the address of a block from an inode's list - * \param Disk Disk information structure - * \param Blocks Pointer to an inode's block list - * \param BlockNum Block index in list - */ -Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) -{ - Uint32 *iBlocks; - // Direct Blocks - if(BlockNum < 12) - return (Uint64)Blocks[BlockNum] * Disk->BlockSize; - - // Single Indirect Blocks - iBlocks = malloc( Disk->BlockSize ); - VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks); - - BlockNum -= 12; - if(BlockNum < 256) { - BlockNum = iBlocks[BlockNum]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; - } - - // Double Indirect Blocks - if(BlockNum < 256*256) - { - VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks); - BlockNum = iBlocks[BlockNum%256]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; - } - // Triple Indirect Blocks - VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks); - VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks); - BlockNum = iBlocks[BlockNum%256]; - free(iBlocks); - return (Uint64)BlockNum * Disk->BlockSize; -} - -/** - * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) - * \brief Allocate an inode (from the current group preferably) - * \param Disk EXT2 Disk Information Structure - * \param Parent Inode ID of the parent (used to locate the child nearby) - */ -Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) -{ -// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group; - return 0; -} - -/** - * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) - * \brief Updates the superblock - */ -void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) -{ - int bpg = Disk->SuperBlock.s_blocks_per_group; - int ngrp = Disk->SuperBlock.s_blocks_count / bpg; - int i; - - // Update Primary - VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock); - - // Secondaries - // at Block Group 1, 3^n, 5^n, 7^n - - // 1 - if(ngrp <= 1) return; - VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); - - // Powers of 3 - for( i = 3; i < ngrp; i *= 3 ) - VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); - - // Powers of 5 - for( i = 5; i < ngrp; i *= 5 ) - VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); - - // Powers of 7 - for( i = 7; i < ngrp; i *= 7 ) - VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); -} diff --git a/Modules/FS_Ext2/ext2_common.h b/Modules/FS_Ext2/ext2_common.h deleted file mode 100644 index 2e2babae..00000000 --- a/Modules/FS_Ext2/ext2_common.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file ext2_common.h - * \brief Second Extended Filesystem Driver - */ -#ifndef _EXT2_COMMON_H -#define _EXT2_COMMON_H -#include -#include -#include "ext2fs.h" - -#define EXT2_UPDATE_WRITEBACK 1 - -// === STRUCTURES === -typedef struct { - int FD; - int CacheID; - tVFS_Node RootNode; - - tExt2_SuperBlock SuperBlock; - int BlockSize; - - int GroupCount; - tExt2_Group Groups[]; -} tExt2_Disk; - -// === FUNCTIONS === -// --- Common --- -extern void Ext2_CloseFile(tVFS_Node *Node); -extern int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); -extern Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); -extern void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); -// --- Dir --- -extern char *Ext2_ReadDir(tVFS_Node *Node, int Pos); -extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); -extern int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); -// --- Read --- -extern Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); -extern int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); -// --- Write --- -extern Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); - -#endif diff --git a/Modules/FS_Ext2/ext2fs.h b/Modules/FS_Ext2/ext2fs.h deleted file mode 100644 index 8fd87ce4..00000000 --- a/Modules/FS_Ext2/ext2fs.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Acess2 - * \file ext2fs.h - * \brief EXT2 Filesystem Driver - */ -#ifndef _EXT2FS_H_ -#define _EXT2FS_H_ - -/** - \name Inode Flag Values - \{ -*/ -#define EXT2_S_IFMT 0xF000 //!< Format Mask -#define EXT2_S_IFSOCK 0xC000 //!< Socket -#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link -#define EXT2_S_IFREG 0x8000 //!< Regular File -#define EXT2_S_IFBLK 0x6000 //!< Block Device -#define EXT2_S_IFDIR 0x4000 //!< Directory -#define EXT2_S_IFCHR 0x2000 //!< Character Device -#define EXT2_S_IFIFO 0x1000 //!< FIFO -#define EXT2_S_ISUID 0x0800 //!< SUID -#define EXT2_S_ISGID 0x0400 //!< SGID -#define EXT2_S_ISVTX 0x0200 //!< sticky bit -#define EXT2_S_IRWXU 0700 //!< user access rights mask -#define EXT2_S_IRUSR 0400 //!< Owner Read -#define EXT2_S_IWUSR 0200 //!< Owner Write -#define EXT2_S_IXUSR 0100 //!< Owner Execute -#define EXT2_S_IRWXG 0070 //!< Group Access rights mask -#define EXT2_S_IRGRP 0040 //!< Group Read -#define EXT2_S_IWGRP 0020 //!< Group Write -#define EXT2_S_IXGRP 0010 //!< Group Execute -#define EXT2_S_IRWXO 0007 //!< Global Access rights mask -#define EXT2_S_IROTH 0004 //!< Global Read -#define EXT2_S_IWOTH 0002 //!< Global Write -#define EXT2_S_IXOTH 0001 //!< Global Execute -//! \} - -#define EXT2_NAME_LEN 255 //!< Maximum Name Length - -// === TYPEDEFS === -typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type -typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type -typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type -typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type - -// === STRUCTURES === -/** - * \brief EXT2 Superblock Structure - */ -struct ext2_super_block_s { - Uint32 s_inodes_count; //!< Inodes count - Uint32 s_blocks_count; //!< Blocks count - Uint32 s_r_blocks_count; //!< Reserved blocks count - Uint32 s_free_blocks_count; //!< Free blocks count - Uint32 s_free_inodes_count; //!< Free inodes count - Uint32 s_first_data_block; //!< First Data Block - Uint32 s_log_block_size; //!< Block size - Sint32 s_log_frag_size; //!< Fragment size - Uint32 s_blocks_per_group; //!< Number Blocks per group - Uint32 s_frags_per_group; //!< Number Fragments per group - Uint32 s_inodes_per_group; //!< Number Inodes per group - Uint32 s_mtime; //!< Mount time - Uint32 s_wtime; //!< Write time - Uint16 s_mnt_count; //!< Mount count - Sint16 s_max_mnt_count; //!< Maximal mount count - Uint16 s_magic; //!< Magic signature - Uint16 s_state; //!< File system state - Uint16 s_errors; //!< Behaviour when detecting errors - Uint16 s_pad; //!< Padding - Uint32 s_lastcheck; //!< time of last check - Uint32 s_checkinterval; //!< max. time between checks - Uint32 s_creator_os; //!< Formatting OS - Uint32 s_rev_level; //!< Revision level - Uint16 s_def_resuid; //!< Default uid for reserved blocks - Uint16 s_def_resgid; //!< Default gid for reserved blocks - Uint32 s_reserved[235]; //!< Padding to the end of the block -}; - -/** - * \struct ext2_inode_s - * \brief EXT2 Inode Definition - */ -struct ext2_inode_s { - Uint16 i_mode; //!< File mode - Uint16 i_uid; //!< Owner Uid - Uint32 i_size; //!< Size in bytes - Uint32 i_atime; //!< Access time - Uint32 i_ctime; //!< Creation time - Uint32 i_mtime; //!< Modification time - Uint32 i_dtime; //!< Deletion Time - Uint16 i_gid; //!< Group Id - Uint16 i_links_count; //!< Links count - Uint32 i_blocks; //!< Number of blocks allocated for the file - Uint32 i_flags; //!< File flags - union { - Uint32 linux_reserved1; //!< Linux: Reserved - Uint32 hurd_translator; //!< HURD: Translator - Uint32 masix_reserved1; //!< Masix: Reserved - } osd1; //!< OS dependent 1 - Uint32 i_block[15]; //!< Pointers to blocks - Uint32 i_version; //!< File version (for NFS) - Uint32 i_file_acl; //!< File ACL - Uint32 i_dir_acl; //!< Directory ACL / Extended File Size - Uint32 i_faddr; //!< Fragment address - union { - struct { - Uint8 l_i_frag; //!< Fragment number - Uint8 l_i_fsize; //!< Fragment size - Uint16 i_pad1; //!< Padding - Uint32 l_i_reserved2[2]; //!< Reserved - } linux2; - struct { - Uint8 h_i_frag; //!< Fragment number - Uint8 h_i_fsize; //!< Fragment size - Uint16 h_i_mode_high; //!< Mode High Bits - Uint16 h_i_uid_high; //!< UID High Bits - Uint16 h_i_gid_high; //!< GID High Bits - Uint32 h_i_author; //!< Creator ID - } hurd2; - struct { - Uint8 m_i_frag; //!< Fragment number - Uint8 m_i_fsize; //!< Fragment size - Uint16 m_pad1; //!< Padding - Uint32 m_i_reserved2[2]; //!< reserved - } masix2; - } osd2; //!< OS dependent 2 -}; - -/** - * \struct ext2_group_desc_s - * \brief EXT2 Group Descriptor - */ -struct ext2_group_desc_s { - Uint32 bg_block_bitmap; //!< Blocks bitmap block - Uint32 bg_inode_bitmap; //!< Inodes bitmap block - Uint32 bg_inode_table; //!< Inodes table block - Uint16 bg_free_blocks_count; //!< Free blocks count - Uint16 bg_free_inodes_count; //!< Free inodes count - Uint16 bg_used_dirs_count; //!< Directories count - Uint16 bg_pad; //!< Padding - Uint32 bg_reserved[3]; //!< Reserved -}; - -/** - * \brief EXT2 Directory Entry - * \note The name may take up less than 255 characters - */ -struct ext2_dir_entry_s { - Uint32 inode; //!< Inode number - Uint16 rec_len; //!< Directory entry length - Uint8 name_len; //!< Short Name Length - Uint8 type; //!< File Type - char name[]; //!< File name -}; - -#endif diff --git a/Modules/FS_Ext2/read.c b/Modules/FS_Ext2/read.c deleted file mode 100644 index cb6649a6..00000000 --- a/Modules/FS_Ext2/read.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file read.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include "ext2_common.h" - -// === PROTOTYPES === -Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); - int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); - -// === CODE === -/** - * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Read from a file - */ -Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - Uint64 base; - Uint block; - Uint64 remLen; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - // Get Inode - Ext2_int_GetInode(Node, &inode); - - // Sanity Checks - if(Offset >= inode.i_size) { - LEAVE('i', 0); - return 0; - } - if(Offset + Length > inode.i_size) - Length = inode.i_size - Offset; - - block = Offset / disk->BlockSize; - Offset = Offset / disk->BlockSize; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - if(base == 0) { - Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); - LEAVE('i', 0); - return 0; - } - - // Read only block - if(Length <= disk->BlockSize - Offset) - { - VFS_ReadAt( disk->FD, base+Offset, Length, Buffer); - LEAVE('X', Length); - return Length; - } - - // Read first block - remLen = Length; - VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer); - remLen -= disk->BlockSize - Offset; - Buffer += disk->BlockSize - Offset; - block ++; - - // Read middle blocks - while(remLen > disk->BlockSize) - { - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - if(base == 0) { - Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); - LEAVE('i', 0); - return 0; - } - VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer); - Buffer += disk->BlockSize; - remLen -= disk->BlockSize; - block ++; - } - - // Read last block - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_ReadAt( disk->FD, base, remLen, Buffer); - - LEAVE('X', Length); - return Length; -} diff --git a/Modules/FS_Ext2/write.c b/Modules/FS_Ext2/write.c deleted file mode 100644 index f3fdc6b3..00000000 --- a/Modules/FS_Ext2/write.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file write.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include "ext2_common.h" - -// === PROTOYPES === -Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); -Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock); - -// === CODE === -/** - * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Write to a file - */ -Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - Uint64 base; - Uint64 retLen; - Uint block; - Uint64 allocSize; - int bNewBlocks = 0; - - Debug_HexDump("Ext2_Write", Buffer, Length); - - Ext2_int_GetInode(Node, &inode); - - // Get the ammount of space already allocated - // - Round size up to block size - // - block size is a power of two, so this will work - allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1); - - // Are we writing to inside the allocated space? - if( Offset < allocSize ) - { - // Will we go out of it? - if(Offset + Length > allocSize) { - bNewBlocks = 1; - retLen = allocSize - Offset; - } else - retLen = Length; - - // Within the allocated space - block = Offset / disk->BlockSize; - Offset %= disk->BlockSize; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - - // Write only block (if only one) - if(Offset + retLen <= disk->BlockSize) { - VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer); - if(!bNewBlocks) return Length; - goto addBlocks; // Ugh! A goto, but it seems unavoidable - } - - // Write First Block - VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer); - Buffer += disk->BlockSize-Offset; - retLen -= disk->BlockSize-Offset; - block ++; - - // Write middle blocks - while(retLen > disk->BlockSize) - { - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer); - Buffer += disk->BlockSize; - retLen -= disk->BlockSize; - block ++; - } - - // Write last block - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_WriteAt(disk->FD, base, retLen, Buffer); - if(!bNewBlocks) return Length; // Writing in only allocated space - } - -addBlocks: - ///\todo Implement block allocation - Warning("[EXT2] File extending is not yet supported"); - - return 0; -} - -/** - * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) - * \brief Allocate a block from the best possible location - * \param Disk EXT2 Disk Information Structure - * \param PrevBlock Previous block ID in the file - */ -Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) -{ - int bpg = Disk->SuperBlock.s_blocks_per_group; - Uint blockgroup = PrevBlock / bpg; - Uint bitmap[Disk->BlockSize/sizeof(Uint)]; - Uint bitsperblock = 8*Disk->BlockSize; - int i, j = 0; - Uint block; - - // Are there any free blocks? - if(Disk->SuperBlock.s_free_blocks_count == 0) return 0; - - if(Disk->Groups[blockgroup].bg_free_blocks_count > 0) - { - // Search block group's bitmap - for(i = 0; i < bpg; i++) - { - // Get the block in the bitmap block - j = i & (bitsperblock-1); - - // Read in if needed - if(j == 0) { - VFS_ReadAt( - Disk->FD, - (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, - Disk->BlockSize, - bitmap - ); - } - - // Fast Check - if( bitmap[j/32] == -1 ) { - j = (j + 31) & ~31; - continue; - } - - // Is the bit set? - if( bitmap[j/32] & (1 << (j%32)) ) - continue; - - // Ooh! We found one - break; - } - if( i < bpg ) { - Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist"); - goto checkAll; // Search the entire filesystem for a free block - // Goto needed for neatness - } - - // Mark as used - bitmap[j/32] |= (1 << (j%32)); - VFS_WriteAt( - Disk->FD, - (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, - Disk->BlockSize, - bitmap - ); - block = i; - Disk->Groups[blockgroup].bg_free_blocks_count --; - #if EXT2_UPDATE_WRITEBACK - //Ext2_int_UpdateBlockGroup(blockgroup); - #endif - } - else - { - checkAll: - Warning("[EXT2 ] TODO - Implement using blocks outside the current block group"); - return 0; - } - - // Reduce global count - Disk->SuperBlock.s_free_blocks_count --; - #if EXT2_UPDATE_WRITEBACK - Ext2_int_UpdateSuperblock(Disk); - #endif - - return block; -} diff --git a/Modules/Filesystems/FS_Ext2/Makefile b/Modules/Filesystems/FS_Ext2/Makefile new file mode 100644 index 00000000..806e638c --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = ext2.o read.o dir.o write.o +NAME = FS_Ext2 + +-include ../Makefile.tpl diff --git a/Modules/Filesystems/FS_Ext2/dir.c b/Modules/Filesystems/FS_Ext2/dir.c new file mode 100644 index 00000000..5fe89336 --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/dir.c @@ -0,0 +1,228 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file dir.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + + +// === PROTOTYPES === +char *Ext2_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); + int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name); + +// === CODE === +/** + \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos) + \brief Reads a directory entry +*/ +char *Ext2_ReadDir(tVFS_Node *Node, int Pos) +{ + tExt2_Inode inode; + char namebuf[EXT2_NAME_LEN+1]; + tExt2_DirEnt dirent; + Uint64 Base; // Block's Base Address + int block = 0, ofs = 0; + int entNum = 0; + tExt2_Disk *disk = Node->ImplPtr; + Uint size; + + ENTER("pNode iPos", Node, Pos); + + // Read directory's inode + Ext2_int_GetInode(Node, &inode); + size = inode.i_size; + + LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); + + // Find Entry + // Get First Block + // - Do this ourselves as it is a simple operation + Base = inode.i_block[0] * disk->BlockSize; + while(Pos -- && size > 0) + { + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); + ofs += dirent.rec_len; + size -= dirent.rec_len; + entNum ++; + + if(ofs >= disk->BlockSize) { + block ++; + if( ofs > disk->BlockSize ) { + Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring", + entNum-1, Node->Inode); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + // Check for the end of the list + if(size <= 0) { + LEAVE('n'); + return NULL; + } + + // Read Entry + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); + //LOG("dirent.inode = %i", dirent.inode); + //LOG("dirent.rec_len = %i", dirent.rec_len); + //LOG("dirent.name_len = %i", dirent.name_len); + VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); + namebuf[ dirent.name_len ] = '\0'; // Cap off string + + + // Ignore . and .. (these are done in the VFS) + if( (namebuf[0] == '.' && namebuf[1] == '\0') + || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) { + LEAVE('p', VFS_SKIP); + return VFS_SKIP; // Skip + } + + LEAVE('s', namebuf); + // Create new node + return strdup(namebuf); +} + +/** + \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename) + \brief Gets information about a file + \param node vfs node - Parent Node + \param filename String - Name of file + \return VFS Node of file +*/ +tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + char namebuf[EXT2_NAME_LEN+1]; + tExt2_DirEnt dirent; + Uint64 Base; // Block's Base Address + int block = 0, ofs = 0; + int entNum = 0; + Uint size; + + // Read directory's inode + Ext2_int_GetInode(Node, &inode); + size = inode.i_size; + + // Get First Block + // - Do this ourselves as it is a simple operation + Base = inode.i_block[0] * disk->BlockSize; + // Find File + while(size > 0) + { + VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); + VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf ); + namebuf[ dirent.name_len ] = '\0'; // Cap off string + // If it matches, create a node and return it + if(strcmp(namebuf, Filename) == 0) + return Ext2_int_CreateNode( disk, dirent.inode, namebuf ); + // Increment pointers + ofs += dirent.rec_len; + size -= dirent.rec_len; + entNum ++; + + // Check for end of block + if(ofs >= disk->BlockSize) { + block ++; + if( ofs > disk->BlockSize ) { + Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring", + entNum-1, Node->Inode); + } + ofs = 0; + Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + } + } + + return NULL; +} + +/** + * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) + * \brief Create a new node + */ +int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags) +{ + return 0; +} + +// ---- INTERNAL FUNCTIONS ---- +/** + * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) + * \brief Create a new VFS Node + */ +tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name) +{ + tExt2_Inode inode; + tVFS_Node retNode; + tVFS_Node *tmpNode; + + if( !Ext2_int_ReadInode(Disk, InodeID, &inode) ) + return NULL; + + if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) ) + return tmpNode; + + + // Set identifiers + retNode.Inode = InodeID; + retNode.ImplPtr = Disk; + + // Set file length + retNode.Size = inode.i_size; + + // Set Access Permissions + retNode.UID = inode.i_uid; + retNode.GID = inode.i_gid; + retNode.NumACLs = 3; + retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid); + + // Set Function Pointers + retNode.Read = Ext2_Read; + retNode.Write = Ext2_Write; + retNode.Close = Ext2_CloseFile; + + switch(inode.i_mode & EXT2_S_IFMT) + { + // Symbolic Link + case EXT2_S_IFLNK: + retNode.Flags = VFS_FFLAG_SYMLINK; + break; + // Regular File + case EXT2_S_IFREG: + retNode.Flags = 0; + retNode.Size |= (Uint64)inode.i_dir_acl << 32; + break; + // Directory + case EXT2_S_IFDIR: + retNode.ReadDir = Ext2_ReadDir; + retNode.FindDir = Ext2_FindDir; + retNode.MkNod = Ext2_MkNod; + //retNode.Relink = Ext2_Relink; + retNode.Flags = VFS_FFLAG_DIRECTORY; + break; + // Unknown, Write protect and hide it to be safe + default: + retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN; + break; + } + + // Check if the file should be hidden + //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN; + + // Set Timestamps + retNode.ATime = now(); + retNode.MTime = inode.i_mtime * 1000; + retNode.CTime = inode.i_ctime * 1000; + + // Save in node cache and return saved node + return Inode_CacheNode(Disk->CacheID, &retNode); +} diff --git a/Modules/Filesystems/FS_Ext2/ext2.c b/Modules/Filesystems/FS_Ext2/ext2.c new file mode 100644 index 00000000..81dcef0b --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/ext2.c @@ -0,0 +1,309 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file fs/ext2.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" +#include + +// === PROTOTYPES === + int Ext2_Install(char **Arguments); +// Interface Functions +tVFS_Node *Ext2_InitDevice(char *Device, char **Options); +void Ext2_Unmount(tVFS_Node *Node); +void Ext2_CloseFile(tVFS_Node *Node); +// Internal Helpers + int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent); +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); + +// === SEMI-GLOBALS === +MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL); +tExt2_Disk gExt2_disks[6]; + int giExt2_count = 0; +tVFS_Driver gExt2_FSInfo = { + "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL + }; + +// === CODE === + +/** + * \fn int Ext2_Install(char **Arguments) + * \brief Install the Ext2 Filesystem Driver + */ +int Ext2_Install(char **Arguments) +{ + VFS_AddDriver( &gExt2_FSInfo ); + return 1; +} + +/** + \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options) + \brief Initializes a device to be read by by the driver + \param Device String - Device to read from + \param Options NULL Terminated array of option strings + \return Root Node +*/ +tVFS_Node *Ext2_InitDevice(char *Device, char **Options) +{ + tExt2_Disk *disk; + int fd; + int groupCount; + tExt2_SuperBlock sb; + tExt2_Inode inode; + + ENTER("sDevice pOptions", Device, Options); + + // Open Disk + fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device + if(fd == -1) { + Warning("[EXT2 ] Unable to open '%s'", Device); + LEAVE('n'); + return NULL; + } + + // Read Superblock at offset 1024 + VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock + + // Sanity Check Magic value + if(sb.s_magic != 0xEF53) { + Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device); + VFS_Close(fd); + LEAVE('n'); + return NULL; + } + + // Get Group count + groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); + LOG("groupCount = %i", groupCount); + + // Allocate Disk Information + disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); + if(!disk) { + Warning("[EXT2 ] Unable to allocate disk structure"); + VFS_Close(fd); + LEAVE('n'); + return NULL; + } + disk->FD = fd; + memcpy(&disk->SuperBlock, &sb, 1024); + disk->GroupCount = groupCount; + + // Get an inode cache handle + disk->CacheID = Inode_GetHandle(); + + // Get Block Size + LOG("s_log_block_size = 0x%x", sb.s_log_block_size); + disk->BlockSize = 1024 << sb.s_log_block_size; + + // Read Group Information + VFS_ReadAt( + disk->FD, + sb.s_first_data_block * disk->BlockSize + 1024, + sizeof(tExt2_Group)*groupCount, + disk->Groups + ); + + #if VERBOSE + LOG("Block Group 0"); + LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap); + LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap); + LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table); + LOG("Block Group 1"); + LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap); + LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap); + LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table); + #endif + + // Get root Inode + Ext2_int_ReadInode(disk, 2, &inode); + + // Create Root Node + memset(&disk->RootNode, 0, sizeof(tVFS_Node)); + disk->RootNode.Inode = 2; // Root inode ID + disk->RootNode.ImplPtr = disk; // Save disk pointer + disk->RootNode.Size = -1; // Fill in later (on readdir) + disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; + + disk->RootNode.ReadDir = Ext2_ReadDir; + disk->RootNode.FindDir = Ext2_FindDir; + //disk->RootNode.Relink = Ext2_Relink; + + // Complete root node + disk->RootNode.UID = inode.i_uid; + disk->RootNode.GID = inode.i_gid; + disk->RootNode.NumACLs = 1; + disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; + + #if DEBUG + LOG("inode.i_size = 0x%x", inode.i_size); + LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); + #endif + + LEAVE('p', &disk->RootNode); + return &disk->RootNode; +} + +/** + * \fn void Ext2_Unmount(tVFS_Node *Node) + * \brief Close a mounted device + */ +void Ext2_Unmount(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + + VFS_Close( disk->FD ); + Inode_ClearCache( disk->CacheID ); + memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); + free(disk); +} + +/** + * \fn void Ext2_CloseFile(tVFS_Node *Node) + * \brief Close a file (Remove it from the cache) + */ +void Ext2_CloseFile(tVFS_Node *Node) +{ + tExt2_Disk *disk = Node->ImplPtr; + Inode_UncacheNode(disk->CacheID, Node->Inode); + return ; +} + +//================================== +//= INTERNAL FUNCTIONS = +//================================== + + +/** + * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) + * \brief Gets the inode descriptor for a node + * \param Node node to get the Inode of + * \param Inode Destination + */ +int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode) +{ + return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode); +} + +/** + * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) + * \brief Read an inode into memory + */ +int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode) +{ + int group, subId; + + //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode); + //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode); + + if(InodeId == 0) return 0; + + InodeId --; // Inodes are numbered starting at 1 + + group = InodeId / Disk->SuperBlock.s_inodes_per_group; + subId = InodeId % Disk->SuperBlock.s_inodes_per_group; + + //LOG("group=%i, subId = %i", group, subId); + + // Read Inode + VFS_ReadAt(Disk->FD, + Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId, + sizeof(tExt2_Inode), + Inode); + return 1; +} + +/** + * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) + * \brief Get the address of a block from an inode's list + * \param Disk Disk information structure + * \param Blocks Pointer to an inode's block list + * \param BlockNum Block index in list + */ +Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum) +{ + Uint32 *iBlocks; + // Direct Blocks + if(BlockNum < 12) + return (Uint64)Blocks[BlockNum] * Disk->BlockSize; + + // Single Indirect Blocks + iBlocks = malloc( Disk->BlockSize ); + VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks); + + BlockNum -= 12; + if(BlockNum < 256) { + BlockNum = iBlocks[BlockNum]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + + // Double Indirect Blocks + if(BlockNum < 256*256) + { + VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; + } + // Triple Indirect Blocks + VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks); + VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks); + BlockNum = iBlocks[BlockNum%256]; + free(iBlocks); + return (Uint64)BlockNum * Disk->BlockSize; +} + +/** + * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) + * \brief Allocate an inode (from the current group preferably) + * \param Disk EXT2 Disk Information Structure + * \param Parent Inode ID of the parent (used to locate the child nearby) + */ +Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent) +{ +// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group; + return 0; +} + +/** + * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) + * \brief Updates the superblock + */ +void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk) +{ + int bpg = Disk->SuperBlock.s_blocks_per_group; + int ngrp = Disk->SuperBlock.s_blocks_count / bpg; + int i; + + // Update Primary + VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock); + + // Secondaries + // at Block Group 1, 3^n, 5^n, 7^n + + // 1 + if(ngrp <= 1) return; + VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 3 + for( i = 3; i < ngrp; i *= 3 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 5 + for( i = 5; i < ngrp; i *= 5 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); + + // Powers of 7 + for( i = 7; i < ngrp; i *= 7 ) + VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock); +} diff --git a/Modules/Filesystems/FS_Ext2/ext2_common.h b/Modules/Filesystems/FS_Ext2/ext2_common.h new file mode 100644 index 00000000..2e2babae --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/ext2_common.h @@ -0,0 +1,46 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file ext2_common.h + * \brief Second Extended Filesystem Driver + */ +#ifndef _EXT2_COMMON_H +#define _EXT2_COMMON_H +#include +#include +#include "ext2fs.h" + +#define EXT2_UPDATE_WRITEBACK 1 + +// === STRUCTURES === +typedef struct { + int FD; + int CacheID; + tVFS_Node RootNode; + + tExt2_SuperBlock SuperBlock; + int BlockSize; + + int GroupCount; + tExt2_Group Groups[]; +} tExt2_Disk; + +// === FUNCTIONS === +// --- Common --- +extern void Ext2_CloseFile(tVFS_Node *Node); +extern int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode); +extern Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum); +extern void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk); +// --- Dir --- +extern char *Ext2_ReadDir(tVFS_Node *Node, int Pos); +extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName); +extern int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags); +// --- Read --- +extern Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +extern int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); +// --- Write --- +extern Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); + +#endif diff --git a/Modules/Filesystems/FS_Ext2/ext2fs.h b/Modules/Filesystems/FS_Ext2/ext2fs.h new file mode 100644 index 00000000..8fd87ce4 --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/ext2fs.h @@ -0,0 +1,156 @@ +/** + * Acess2 + * \file ext2fs.h + * \brief EXT2 Filesystem Driver + */ +#ifndef _EXT2FS_H_ +#define _EXT2FS_H_ + +/** + \name Inode Flag Values + \{ +*/ +#define EXT2_S_IFMT 0xF000 //!< Format Mask +#define EXT2_S_IFSOCK 0xC000 //!< Socket +#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link +#define EXT2_S_IFREG 0x8000 //!< Regular File +#define EXT2_S_IFBLK 0x6000 //!< Block Device +#define EXT2_S_IFDIR 0x4000 //!< Directory +#define EXT2_S_IFCHR 0x2000 //!< Character Device +#define EXT2_S_IFIFO 0x1000 //!< FIFO +#define EXT2_S_ISUID 0x0800 //!< SUID +#define EXT2_S_ISGID 0x0400 //!< SGID +#define EXT2_S_ISVTX 0x0200 //!< sticky bit +#define EXT2_S_IRWXU 0700 //!< user access rights mask +#define EXT2_S_IRUSR 0400 //!< Owner Read +#define EXT2_S_IWUSR 0200 //!< Owner Write +#define EXT2_S_IXUSR 0100 //!< Owner Execute +#define EXT2_S_IRWXG 0070 //!< Group Access rights mask +#define EXT2_S_IRGRP 0040 //!< Group Read +#define EXT2_S_IWGRP 0020 //!< Group Write +#define EXT2_S_IXGRP 0010 //!< Group Execute +#define EXT2_S_IRWXO 0007 //!< Global Access rights mask +#define EXT2_S_IROTH 0004 //!< Global Read +#define EXT2_S_IWOTH 0002 //!< Global Write +#define EXT2_S_IXOTH 0001 //!< Global Execute +//! \} + +#define EXT2_NAME_LEN 255 //!< Maximum Name Length + +// === TYPEDEFS === +typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type +typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type +typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type +typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type + +// === STRUCTURES === +/** + * \brief EXT2 Superblock Structure + */ +struct ext2_super_block_s { + Uint32 s_inodes_count; //!< Inodes count + Uint32 s_blocks_count; //!< Blocks count + Uint32 s_r_blocks_count; //!< Reserved blocks count + Uint32 s_free_blocks_count; //!< Free blocks count + Uint32 s_free_inodes_count; //!< Free inodes count + Uint32 s_first_data_block; //!< First Data Block + Uint32 s_log_block_size; //!< Block size + Sint32 s_log_frag_size; //!< Fragment size + Uint32 s_blocks_per_group; //!< Number Blocks per group + Uint32 s_frags_per_group; //!< Number Fragments per group + Uint32 s_inodes_per_group; //!< Number Inodes per group + Uint32 s_mtime; //!< Mount time + Uint32 s_wtime; //!< Write time + Uint16 s_mnt_count; //!< Mount count + Sint16 s_max_mnt_count; //!< Maximal mount count + Uint16 s_magic; //!< Magic signature + Uint16 s_state; //!< File system state + Uint16 s_errors; //!< Behaviour when detecting errors + Uint16 s_pad; //!< Padding + Uint32 s_lastcheck; //!< time of last check + Uint32 s_checkinterval; //!< max. time between checks + Uint32 s_creator_os; //!< Formatting OS + Uint32 s_rev_level; //!< Revision level + Uint16 s_def_resuid; //!< Default uid for reserved blocks + Uint16 s_def_resgid; //!< Default gid for reserved blocks + Uint32 s_reserved[235]; //!< Padding to the end of the block +}; + +/** + * \struct ext2_inode_s + * \brief EXT2 Inode Definition + */ +struct ext2_inode_s { + Uint16 i_mode; //!< File mode + Uint16 i_uid; //!< Owner Uid + Uint32 i_size; //!< Size in bytes + Uint32 i_atime; //!< Access time + Uint32 i_ctime; //!< Creation time + Uint32 i_mtime; //!< Modification time + Uint32 i_dtime; //!< Deletion Time + Uint16 i_gid; //!< Group Id + Uint16 i_links_count; //!< Links count + Uint32 i_blocks; //!< Number of blocks allocated for the file + Uint32 i_flags; //!< File flags + union { + Uint32 linux_reserved1; //!< Linux: Reserved + Uint32 hurd_translator; //!< HURD: Translator + Uint32 masix_reserved1; //!< Masix: Reserved + } osd1; //!< OS dependent 1 + Uint32 i_block[15]; //!< Pointers to blocks + Uint32 i_version; //!< File version (for NFS) + Uint32 i_file_acl; //!< File ACL + Uint32 i_dir_acl; //!< Directory ACL / Extended File Size + Uint32 i_faddr; //!< Fragment address + union { + struct { + Uint8 l_i_frag; //!< Fragment number + Uint8 l_i_fsize; //!< Fragment size + Uint16 i_pad1; //!< Padding + Uint32 l_i_reserved2[2]; //!< Reserved + } linux2; + struct { + Uint8 h_i_frag; //!< Fragment number + Uint8 h_i_fsize; //!< Fragment size + Uint16 h_i_mode_high; //!< Mode High Bits + Uint16 h_i_uid_high; //!< UID High Bits + Uint16 h_i_gid_high; //!< GID High Bits + Uint32 h_i_author; //!< Creator ID + } hurd2; + struct { + Uint8 m_i_frag; //!< Fragment number + Uint8 m_i_fsize; //!< Fragment size + Uint16 m_pad1; //!< Padding + Uint32 m_i_reserved2[2]; //!< reserved + } masix2; + } osd2; //!< OS dependent 2 +}; + +/** + * \struct ext2_group_desc_s + * \brief EXT2 Group Descriptor + */ +struct ext2_group_desc_s { + Uint32 bg_block_bitmap; //!< Blocks bitmap block + Uint32 bg_inode_bitmap; //!< Inodes bitmap block + Uint32 bg_inode_table; //!< Inodes table block + Uint16 bg_free_blocks_count; //!< Free blocks count + Uint16 bg_free_inodes_count; //!< Free inodes count + Uint16 bg_used_dirs_count; //!< Directories count + Uint16 bg_pad; //!< Padding + Uint32 bg_reserved[3]; //!< Reserved +}; + +/** + * \brief EXT2 Directory Entry + * \note The name may take up less than 255 characters + */ +struct ext2_dir_entry_s { + Uint32 inode; //!< Inode number + Uint16 rec_len; //!< Directory entry length + Uint8 name_len; //!< Short Name Length + Uint8 type; //!< File Type + char name[]; //!< File name +}; + +#endif diff --git a/Modules/Filesystems/FS_Ext2/read.c b/Modules/Filesystems/FS_Ext2/read.c new file mode 100644 index 00000000..cb6649a6 --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/read.c @@ -0,0 +1,89 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file read.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + +// === PROTOTYPES === +Uint64 Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); + int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode); + +// === CODE === +/** + * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read from a file + */ +Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint block; + Uint64 remLen; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + // Get Inode + Ext2_int_GetInode(Node, &inode); + + // Sanity Checks + if(Offset >= inode.i_size) { + LEAVE('i', 0); + return 0; + } + if(Offset + Length > inode.i_size) + Length = inode.i_size - Offset; + + block = Offset / disk->BlockSize; + Offset = Offset / disk->BlockSize; + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + if(base == 0) { + Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); + LEAVE('i', 0); + return 0; + } + + // Read only block + if(Length <= disk->BlockSize - Offset) + { + VFS_ReadAt( disk->FD, base+Offset, Length, Buffer); + LEAVE('X', Length); + return Length; + } + + // Read first block + remLen = Length; + VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer); + remLen -= disk->BlockSize - Offset; + Buffer += disk->BlockSize - Offset; + block ++; + + // Read middle blocks + while(remLen > disk->BlockSize) + { + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + if(base == 0) { + Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode); + LEAVE('i', 0); + return 0; + } + VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer); + Buffer += disk->BlockSize; + remLen -= disk->BlockSize; + block ++; + } + + // Read last block + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_ReadAt( disk->FD, base, remLen, Buffer); + + LEAVE('X', Length); + return Length; +} diff --git a/Modules/Filesystems/FS_Ext2/write.c b/Modules/Filesystems/FS_Ext2/write.c new file mode 100644 index 00000000..f3fdc6b3 --- /dev/null +++ b/Modules/Filesystems/FS_Ext2/write.c @@ -0,0 +1,176 @@ +/* + * Acess OS + * Ext2 Driver Version 1 + */ +/** + * \file write.c + * \brief Second Extended Filesystem Driver + * \todo Implement file full write support + */ +#define DEBUG 1 +#define VERBOSE 0 +#include "ext2_common.h" + +// === PROTOYPES === +Uint64 Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock); + +// === CODE === +/** + * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Write to a file + */ +Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tExt2_Disk *disk = Node->ImplPtr; + tExt2_Inode inode; + Uint64 base; + Uint64 retLen; + Uint block; + Uint64 allocSize; + int bNewBlocks = 0; + + Debug_HexDump("Ext2_Write", Buffer, Length); + + Ext2_int_GetInode(Node, &inode); + + // Get the ammount of space already allocated + // - Round size up to block size + // - block size is a power of two, so this will work + allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1); + + // Are we writing to inside the allocated space? + if( Offset < allocSize ) + { + // Will we go out of it? + if(Offset + Length > allocSize) { + bNewBlocks = 1; + retLen = allocSize - Offset; + } else + retLen = Length; + + // Within the allocated space + block = Offset / disk->BlockSize; + Offset %= disk->BlockSize; + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + + // Write only block (if only one) + if(Offset + retLen <= disk->BlockSize) { + VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer); + if(!bNewBlocks) return Length; + goto addBlocks; // Ugh! A goto, but it seems unavoidable + } + + // Write First Block + VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer); + Buffer += disk->BlockSize-Offset; + retLen -= disk->BlockSize-Offset; + block ++; + + // Write middle blocks + while(retLen > disk->BlockSize) + { + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer); + Buffer += disk->BlockSize; + retLen -= disk->BlockSize; + block ++; + } + + // Write last block + base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + VFS_WriteAt(disk->FD, base, retLen, Buffer); + if(!bNewBlocks) return Length; // Writing in only allocated space + } + +addBlocks: + ///\todo Implement block allocation + Warning("[EXT2] File extending is not yet supported"); + + return 0; +} + +/** + * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) + * \brief Allocate a block from the best possible location + * \param Disk EXT2 Disk Information Structure + * \param PrevBlock Previous block ID in the file + */ +Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock) +{ + int bpg = Disk->SuperBlock.s_blocks_per_group; + Uint blockgroup = PrevBlock / bpg; + Uint bitmap[Disk->BlockSize/sizeof(Uint)]; + Uint bitsperblock = 8*Disk->BlockSize; + int i, j = 0; + Uint block; + + // Are there any free blocks? + if(Disk->SuperBlock.s_free_blocks_count == 0) return 0; + + if(Disk->Groups[blockgroup].bg_free_blocks_count > 0) + { + // Search block group's bitmap + for(i = 0; i < bpg; i++) + { + // Get the block in the bitmap block + j = i & (bitsperblock-1); + + // Read in if needed + if(j == 0) { + VFS_ReadAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + } + + // Fast Check + if( bitmap[j/32] == -1 ) { + j = (j + 31) & ~31; + continue; + } + + // Is the bit set? + if( bitmap[j/32] & (1 << (j%32)) ) + continue; + + // Ooh! We found one + break; + } + if( i < bpg ) { + Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist"); + goto checkAll; // Search the entire filesystem for a free block + // Goto needed for neatness + } + + // Mark as used + bitmap[j/32] |= (1 << (j%32)); + VFS_WriteAt( + Disk->FD, + (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock, + Disk->BlockSize, + bitmap + ); + block = i; + Disk->Groups[blockgroup].bg_free_blocks_count --; + #if EXT2_UPDATE_WRITEBACK + //Ext2_int_UpdateBlockGroup(blockgroup); + #endif + } + else + { + checkAll: + Warning("[EXT2 ] TODO - Implement using blocks outside the current block group"); + return 0; + } + + // Reduce global count + Disk->SuperBlock.s_free_blocks_count --; + #if EXT2_UPDATE_WRITEBACK + Ext2_int_UpdateSuperblock(Disk); + #endif + + return block; +} diff --git a/Modules/Filesystems/Makefile.tpl b/Modules/Filesystems/Makefile.tpl new file mode 100644 index 00000000..80c6d4dd --- /dev/null +++ b/Modules/Filesystems/Makefile.tpl @@ -0,0 +1 @@ +-include ../../Makefile.tpl diff --git a/Modules/Interfaces/Makefile.tpl b/Modules/Interfaces/Makefile.tpl new file mode 100644 index 00000000..80c6d4dd --- /dev/null +++ b/Modules/Interfaces/Makefile.tpl @@ -0,0 +1 @@ +-include ../../Makefile.tpl diff --git a/Modules/Interfaces/UDI/Makefile b/Modules/Interfaces/UDI/Makefile new file mode 100644 index 00000000..4c199f18 --- /dev/null +++ b/Modules/Interfaces/UDI/Makefile @@ -0,0 +1,10 @@ +# +# + +CPPFLAGS = -I./include +OBJ = main.o logging.o strmem.o imc.o mem.o buf.o cb.o +OBJ += meta_mgmt.o meta_gio.o +OBJ += physio.o physio/meta_bus.o physio/meta_intr.o +NAME = UDI + +-include ../Makefile.tpl diff --git a/Modules/Interfaces/UDI/buf.c b/Modules/Interfaces/UDI/buf.c new file mode 100644 index 00000000..3255911d --- /dev/null +++ b/Modules/Interfaces/UDI/buf.c @@ -0,0 +1,56 @@ +/** + * \file buf.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_buf_copy); +EXPORT(udi_buf_write); +EXPORT(udi_buf_read); +EXPORT(udi_buf_free); + +// === CODE === +void udi_buf_copy( + udi_buf_copy_call_t *callback, + udi_cb_t *gcb, + udi_buf_t *src_buf, + udi_size_t src_off, + udi_size_t src_len, + udi_buf_t *dst_buf, + udi_size_t dst_off, + udi_size_t dst_len, + udi_buf_path_t path_handle + ) +{ + UNIMPLEMENTED(); +} + +void udi_buf_write( + udi_buf_write_call_t *callback, + udi_cb_t *gcb, + const void *src_mem, + udi_size_t src_len, + udi_buf_t *dst_buf, + udi_size_t dst_off, + udi_size_t dst_len, + udi_buf_path_t path_handle + ) +{ + UNIMPLEMENTED(); +} + +void udi_buf_read( + udi_buf_t *src_buf, + udi_size_t src_off, + udi_size_t src_len, + void *dst_mem ) +{ + UNIMPLEMENTED(); +} + +void udi_buf_free(udi_buf_t *buf) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/cb.c b/Modules/Interfaces/UDI/cb.c new file mode 100644 index 00000000..78be97bd --- /dev/null +++ b/Modules/Interfaces/UDI/cb.c @@ -0,0 +1,59 @@ +/** + * \file cb.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_cb_alloc); +EXPORT(udi_cb_alloc_dynamic); +EXPORT(udi_cb_alloc_batch); +EXPORT(udi_cb_free); +EXPORT(udi_cancel); + +// === CODE === +void udi_cb_alloc ( + udi_cb_alloc_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_channel_t default_channel + ) +{ + UNIMPLEMENTED(); +} + +void udi_cb_alloc_dynamic( + udi_cb_alloc_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_channel_t default_channel, + udi_size_t inline_size, + udi_layout_t *inline_layout + ) +{ + UNIMPLEMENTED(); +} + +void udi_cb_alloc_batch( + udi_cb_alloc_batch_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_index_t count, + udi_boolean_t with_buf, + udi_size_t buf_size, + udi_buf_path_t path_handle + ) +{ + UNIMPLEMENTED(); +} + +void udi_cb_free(udi_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/imc.c b/Modules/Interfaces/UDI/imc.c new file mode 100644 index 00000000..cd15e070 --- /dev/null +++ b/Modules/Interfaces/UDI/imc.c @@ -0,0 +1,69 @@ +/** + * \file imc.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_channel_anchor); +EXPORT(udi_channel_spawn); +EXPORT(udi_channel_set_context); +EXPORT(udi_channel_op_abort); +EXPORT(udi_channel_close); +EXPORT(udi_channel_event_ind); +EXPORT(udi_channel_event_complete); + +// === CODE === +/** + */ +void udi_channel_anchor( + udi_channel_anchor_call_t *callback, udi_cb_t *gcb, + udi_channel_t channel, udi_index_t ops_idx, void *channel_context + ) +{ + Warning("%s Unimplemented", __func__); +} + +/** + */ +extern void udi_channel_spawn( + udi_channel_spawn_call_t *callback, udi_cb_t *gcb, + udi_channel_t channel, udi_index_t spawn_idx, + udi_index_t ops_idx, void *channel_context + ) +{ + Warning("%s Unimplemented", __func__); +} + +/** + * + */ +void udi_channel_set_context( + udi_channel_t target_channel, void *channel_context + ) +{ + Warning("%s Unimplemented", __func__); +} + +void udi_channel_op_abort( + udi_channel_t target_channel, udi_cb_t *orig_cb + ) +{ + Warning("%s Unimplemented", __func__); +} + +void udi_channel_close(udi_channel_t channel) +{ + Warning("%s Unimplemented", __func__); +} + +void udi_channel_event_ind(udi_channel_event_cb_t *cb) +{ + udi_channel_event_complete(cb, UDI_OK); +} + +void udi_channel_event_complete(udi_channel_event_cb_t *cb, udi_status_t status) +{ + Warning("%s Unimplemented", __func__); +} diff --git a/Modules/Interfaces/UDI/include/physio/meta_bus.h b/Modules/Interfaces/UDI/include/physio/meta_bus.h new file mode 100644 index 00000000..7b88ece8 --- /dev/null +++ b/Modules/Interfaces/UDI/include/physio/meta_bus.h @@ -0,0 +1,74 @@ +/** + * \file physio/meta_bus.h + */ +#ifndef _PHYSIO_META_BUS_H_ +#define _PHYSIO_META_BUS_H_ + +#include +#include + +typedef const struct udi_bus_device_ops_s udi_bus_device_ops_t; +typedef const struct udi_bus_bridge_ops_s udi_bus_bridge_ops_t; +typedef struct udi_bus_bind_cb_s udi_bus_bind_cb_t; +typedef void udi_bus_unbind_req_op_t(udi_bus_bind_cb_t *cb); +typedef void udi_bus_unbind_ack_op_t(udi_bus_bind_cb_t *cb); +typedef void udi_bus_bind_req_op_t(udi_bus_bind_cb_t *cb); +typedef void udi_bus_bind_ack_op_t( + udi_bus_bind_cb_t *cb, + udi_dma_constraints_t dma_constraints, + udi_ubit8_t preferred_endianness, + udi_status_t status + ); + + +struct udi_bus_device_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_bus_bind_ack_op_t *bus_bind_ack_op; + udi_bus_unbind_ack_op_t *bus_unbind_ack_op; + udi_intr_attach_ack_op_t *intr_attach_ack_op; + udi_intr_detach_ack_op_t *intr_detach_ack_op; +}; +/* Bus Device Ops Vector Number */ +#define UDI_BUS_DEVICE_OPS_NUM 1 + +struct udi_bus_bridge_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_bus_bind_req_op_t *bus_bind_req_op; + udi_bus_unbind_req_op_t *bus_unbind_req_op; + udi_intr_attach_req_op_t *intr_attach_req_op; + udi_intr_detach_req_op_t *intr_detach_req_op; +}; +/* Bus Bridge Ops Vector Number */ +#define UDI_BUS_BRIDGE_OPS_NUM + +struct udi_bus_bind_cb_s +{ + udi_cb_t gcb; +}; +/* Bus Bind Control Block Group Number */ +#define UDI_BUS_BIND_CB_NUM 1 + + +extern void udi_bus_bind_req(udi_bus_bind_cb_t *cb); + +extern void udi_bus_bind_ack( + udi_bus_bind_cb_t *cb, + udi_dma_constraints_t dma_constraints, + udi_ubit8_t preferred_endianness, + udi_status_t status + ); +/* Values for preferred_endianness */ +#define UDI_DMA_BIG_ENDIAN (1U<<5) +#define UDI_DMA_LITTLE_ENDIAN (1U<<6) +#define UDI_DMA_ANY_ENDIAN (1U<<0) + +extern void udi_bus_unbind_req(udi_bus_bind_cb_t *cb); +extern void udi_bus_unbind_ack(udi_bus_bind_cb_t *cb); + + + + + +#endif diff --git a/Modules/Interfaces/UDI/include/physio/meta_intr.h b/Modules/Interfaces/UDI/include/physio/meta_intr.h new file mode 100644 index 00000000..d5dd3941 --- /dev/null +++ b/Modules/Interfaces/UDI/include/physio/meta_intr.h @@ -0,0 +1,100 @@ +/** + * \file physio/meta_intr.h + */ +#ifndef _PHYSIO_META_INTR_H_ +#define _PHYSIO_META_INTR_H_ + +#include +#include +#include "pio.h" + +typedef struct udi_intr_attach_cb_s udi_intr_attach_cb_t; +typedef void udi_intr_attach_req_op_t(udi_intr_attach_cb_t *intr_attach_cb); +typedef void udi_intr_attach_ack_op_t( + udi_intr_attach_cb_t *intr_attach_cb, + udi_status_t status + ); +typedef struct udi_intr_detach_cb_s udi_intr_detach_cb_t; +typedef void udi_intr_detach_req_op_t(udi_intr_detach_cb_t *intr_detach_cb); +typedef void udi_intr_detach_ack_op_t(udi_intr_detach_cb_t *intr_detach_cb); +typedef const struct udi_intr_handler_ops_s udi_intr_handler_ops_t; +typedef const struct udi_intr_dispatcher_ops_s udi_intr_dispatcher_ops_t; +typedef struct udi_intr_event_cb_s udi_intr_event_cb_t; +typedef void udi_intr_event_ind_op_t(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags); +typedef void udi_intr_event_rdy_op_t(udi_intr_event_cb_t *intr_event_cb); + + +struct udi_intr_attach_cb_s +{ + udi_cb_t gcb; + udi_index_t interrupt_idx; + udi_ubit8_t min_event_pend; + udi_pio_handle_t preprocessing_handle; +}; +/* Bridge Attach Control Block Group Number */ +#define UDI_BUS_INTR_ATTACH_CB_NUM 2 + +struct udi_intr_detach_cb_s +{ + udi_cb_t gcb; + udi_index_t interrupt_idx; +}; +/* Bridge Detach Control Block Group Number */ +#define UDI_BUS_INTR_DETACH_CB_NUM 3 + +struct udi_intr_handler_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_intr_event_ind_op_t *intr_event_ind_op; +}; +/* Interrupt Handler Ops Vector Number */ +#define UDI_BUS_INTR_HANDLER_OPS_NUM 3 + +struct udi_intr_dispatcher_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_intr_event_rdy_op_t *intr_event_rdy_op; +}; +/* Interrupt Dispatcher Ops Vector Number */ +#define UDI_BUS_INTR_DISPATCH_OPS_NUM 4 + +struct udi_intr_event_cb_s +{ + udi_cb_t gcb; + udi_buf_t *event_buf; + udi_ubit16_t intr_result; +}; +/* Flag values for interrupt handling */ +#define UDI_INTR_UNCLAIMED (1U<<0) +#define UDI_INTR_NO_EVENT (1U<<1) +/* Bus Interrupt Event Control Block Group Number */ +#define UDI_BUS_INTR_EVENT_CB_NUM 4 + + + +extern void udi_intr_attach_req(udi_intr_attach_cb_t *intr_attach_cb); +extern void udi_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status); +extern void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status); + +extern void udi_intr_detach_req(udi_intr_detach_cb_t *intr_detach_cb); +extern void udi_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb); +extern void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb); + + +extern void udi_intr_event_ind(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags); +/** + * \brief Values for ::udi_intr_event_ind \a flags + * \{ + */ +#define UDI_INTR_MASKING_NOT_REQUIRED (1U<<0) +#define UDI_INTR_OVERRUN_OCCURRED (1U<<1) +#define UDI_INTR_PREPROCESSED (1U<<2) +/** + * \} + */ + +extern void udi_intr_event_rdy(udi_intr_event_cb_t *intr_event_cb); + + + +#endif diff --git a/Modules/Interfaces/UDI/include/physio/pio.h b/Modules/Interfaces/UDI/include/physio/pio.h new file mode 100644 index 00000000..1ce305f2 --- /dev/null +++ b/Modules/Interfaces/UDI/include/physio/pio.h @@ -0,0 +1,15 @@ +/** + * \file physio/pio.h + */ +#ifndef _PHYSIO_PIO_H_ +#define _PHYSIO_PIO_H_ + +#include +#include + + +typedef _udi_handle_t udi_pio_handle_t; +/* Null handle value for udi_pio_handle_t */ +#define UDI_NULL_PIO_HANDLE _NULL_HANDLE + +#endif diff --git a/Modules/Interfaces/UDI/include/udi.h b/Modules/Interfaces/UDI/include/udi.h new file mode 100644 index 00000000..fa5cac30 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi.h @@ -0,0 +1,154 @@ +/** + * \file udi.h + */ +#ifndef _UDI_ARCH_H_ +#define _UDI_ARCH_H_ + +// Use the core acess file to use the specific size types (plus va_arg) +#include + +typedef Sint8 udi_sbit8_t; /* signed 8-bit: -2^7..2^7-1 */ +typedef Sint16 udi_sbit16_t; /* signed 16-bit: -2^15..2^15-1 */ +typedef Sint32 udi_sbit32_t; /* signed 32-bit: -2^31..2^31-1 */ +typedef Uint8 udi_ubit8_t; /* unsigned 8-bit: 0..28-1 */ +typedef Uint16 udi_ubit16_t; /* unsigned 16-bit: 0..216-1 */ +typedef Uint32 udi_ubit32_t; /* unsigned 32-bit: 0..232-1 */ + +typedef udi_ubit8_t udi_boolean_t; /* 0=False; 1..28-1=True */ +#define FALSE 0 +#define TRUE 1 + +typedef size_t udi_size_t; /* buffer size */ +typedef size_t udi_index_t; /* zero-based index type */ + +typedef void *_udi_handle_t; +#define _NULL_HANDLE NULL + +/* Channel Handle */ +typedef _udi_handle_t *udi_channel_t; +#define UDI_NULL_CHANNEL _NULL_HANDLE + +/** + * \brief Buffer Path + */ +typedef _udi_handle_t udi_buf_path_t; +#define UDI_NULL_BUF_PATH _NULL_HANDLE + +typedef _udi_handle_t udi_origin_t; +#define UDI_NULL_ORIGIN _NULL_HANDLE + +typedef Sint64 udi_timestamp_t; + +#define UDI_HANDLE_IS_NULL(handle, handle_type) (handle == NULL) +#define UDI_HANDLE_ID(handle, handle_type) ((Uint32)handle) + +/** + * \name va_arg wrapper + * \{ + */ +#define UDI_VA_ARG(pvar, type, va_code) va_arg(pvar,type) +#define UDI_VA_UBIT8_T +#define UDI_VA_SBIT8_T +#define UDI_VA_UBIT16_T +#define UDI_VA_SBIT16_T +#define UDI_VA_UBIT32_T +#define UDI_VA_SBIT32_T +#define UDI_VA_BOOLEAN_T +#define UDI_VA_INDEX_T +#define UDI_VA_SIZE_T +#define UDI_VA_STATUS_T +#define UDI_VA_CHANNEL_T +#define UDI_VA_ORIGIN_T +#define UDI_VA_POINTER +/** + * \} + */ + +/** + * \brief Status Type + */ +typedef udi_ubit32_t udi_status_t; + +/** + * \name Values and Flags for udi_status_t + * \{ + */ +#define UDI_STATUS_CODE_MASK 0x0000FFFF +#define UDI_STAT_META_SPECIFIC 0x00008000 +#define UDI_SPECIFIC_STATUS_MASK 0x00007FFF +#define UDI_CORRELATE_OFFSET 16 +#define UDI_CORRELATE_MASK 0xFFFF0000 +/* Common Status Values */ +#define UDI_OK 0 +#define UDI_STAT_NOT_SUPPORTED 1 +#define UDI_STAT_NOT_UNDERSTOOD 2 +#define UDI_STAT_INVALID_STATE 3 +#define UDI_STAT_MISTAKEN_IDENTITY 4 +#define UDI_STAT_ABORTED 5 +#define UDI_STAT_TIMEOUT 6 +#define UDI_STAT_BUSY 7 +#define UDI_STAT_RESOURCE_UNAVAIL 8 +#define UDI_STAT_HW_PROBLEM 9 +#define UDI_STAT_NOT_RESPONDING 10 +#define UDI_STAT_DATA_UNDERRUN 11 +#define UDI_STAT_DATA_OVERRUN 12 +#define UDI_STAT_DATA_ERROR 13 +#define UDI_STAT_PARENT_DRV_ERROR 14 +#define UDI_STAT_CANNOT_BIND 15 +#define UDI_STAT_CANNOT_BIND_EXCL 16 +#define UDI_STAT_TOO_MANY_PARENTS 17 +#define UDI_STAT_BAD_PARENT_TYPE 18 +#define UDI_STAT_TERMINATED 19 +#define UDI_STAT_ATTR_MISMATCH 20 +/** + * \} + */ + +/** + * \name Data Layout Specifiers + * \{ + */ +typedef const udi_ubit8_t udi_layout_t; +/* Specific-Length Layout Type Codes */ +#define UDI_DL_UBIT8_T 1 +#define UDI_DL_SBIT8_T 2 +#define UDI_DL_UBIT16_T 3 +#define UDI_DL_SBIT16_T 4 +#define UDI_DL_UBIT32_T 5 +#define UDI_DL_SBIT32_T 6 +#define UDI_DL_BOOLEAN_T 7 +#define UDI_DL_STATUS_T 8 +/* Abstract Element Layout Type Codes */ +#define UDI_DL_INDEX_T 20 +/* Opaque Handle Element Layout Type Codes */ +#define UDI_DL_CHANNEL_T 30 +#define UDI_DL_ORIGIN_T 32 +/* Indirect Element Layout Type Codes */ +#define UDI_DL_BUF 40 +#define UDI_DL_CB 41 +#define UDI_DL_INLINE_UNTYPED 42 +#define UDI_DL_INLINE_DRIVER_TYPED 43 +#define UDI_DL_MOVABLE_UNTYPED 44 +/* Nested Element Layout Type Codes */ +#define UDI_DL_INLINE_TYPED 50 +#define UDI_DL_MOVABLE_TYPED 51 +#define UDI_DL_ARRAY 52 +#define UDI_DL_END 0 +/** + * \} + */ + + +// === INCLUDE SUB-SECTIONS === +#include "udi/cb.h" // Control Blocks +#include "udi/log.h" // Logging +#include "udi/attr.h" // Attributes +#include "udi/strmem.h" // String/Memory +#include "udi/buf.h" // Buffers +#include "udi/mem.h" // Memory Management +#include "udi/imc.h" // Inter-module Communication +#include "udi/meta_mgmt.h" // Management Metalanguage +#include "udi/meta_gio.h" // General IO Metalanguage +#include "udi/init.h" // Init + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/attr.h b/Modules/Interfaces/UDI/include/udi/attr.h new file mode 100644 index 00000000..a63ce8a7 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/attr.h @@ -0,0 +1,41 @@ +/** + * \file udi_attr.h + */ +#ifndef _UDI_ATTR_H_ +#define _UDI_ATTR_H_ + +typedef struct udi_instance_attr_list_s udi_instance_attr_list_t; +typedef udi_ubit8_t udi_instance_attr_type_t; + +/* Instance attribute limits */ +#define UDI_MAX_ATTR_NAMELEN 32 +#define UDI_MAX_ATTR_SIZE 64 + +/** + * \brief Instance Attribute + */ +struct udi_instance_attr_list_s +{ + char attr_name[UDI_MAX_ATTR_NAMELEN]; + udi_ubit8_t attr_value[UDI_MAX_ATTR_SIZE]; + udi_ubit8_t attr_length; + udi_instance_attr_type_t attr_type; +}; + + +/** + * \brief Instance Attribute Types + * \see ::udi_instance_attr_type_t + */ +enum +{ + UDI_ATTR_NONE, + UDI_ATTR_STRING, + UDI_ATTR_ARRAY8, + UDI_ATTR_UBIT32, + UDI_ATTR_BOOLEAN, + UDI_ATTR_FILE +}; + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/buf.h b/Modules/Interfaces/UDI/include/udi/buf.h new file mode 100644 index 00000000..fa2428b7 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/buf.h @@ -0,0 +1,105 @@ +/** + * \file udi_buf.h + */ +#ifndef _UDI_BUF_H_ +#define _UDI_BUF_H_ + + +typedef struct udi_buf_s udi_buf_t; +typedef struct udi_xfer_constraints_s udi_xfer_constraints_t; +typedef void udi_buf_copy_call_t(udi_cb_t *gcb, udi_buf_t *new_dst_buf); +typedef void udi_buf_write_call_t(udi_cb_t *gcb, udi_buf_t *new_dst_buf); + +/** + * \brief Describes a buffer + * \note Semi-Opaque + */ +struct udi_buf_s +{ + udi_size_t buf_size; + Uint8 Data[]; //!< ENVIRONMENT ONLY +}; + +/** + * \brief + */ +struct udi_xfer_constraints_s +{ + udi_ubit32_t udi_xfer_max; + udi_ubit32_t udi_xfer_typical; + udi_ubit32_t udi_xfer_granularity; + udi_boolean_t udi_xfer_one_piece; + udi_boolean_t udi_xfer_exact_size; + udi_boolean_t udi_xfer_no_reorder; +}; + +// --- MACROS --- +/** + * \brief Allocates a buffer + */ +#define UDI_BUF_ALLOC(callback, gcb, init_data, size, path_handle) \ + udi_buf_write(callback, gcb, init_data, size, NULL, 0, 0, path_handle) + +/** + * \brief Inserts data into a buffer + */ +#define UDI_BUF_INSERT(callback, gcb, new_data, size, dst_buf, dst_off) \ + udi_buf_write(callback, gcb, new_data, size, dst_buf, dst_off, 0, UDI_NULL_BUF_PATH) + +/** + * \brief Removes data from a buffer (data afterwards will be moved forewards) + */ +#define UDI_BUF_DELETE(callback, gcb, size, dst_buf, dst_off) \ + udi_buf_write(callback, gcb, NULL, 0, dst_buf, dst_off, size, UDI_NULL_BUF_PATH) + +/** + * \brief Duplicates \a src_buf + */ +#define UDI_BUF_DUP(callback, gcb, src_buf, path_handle) \ + udi_buf_copy(callback, gcb, src_buf, 0, (src_buf)->buf_size, NULL, 0, 0, path_handle) + + +/** + * \brief Copies data from one buffer to another + */ +extern void udi_buf_copy( + udi_buf_copy_call_t *callback, + udi_cb_t *gcb, + udi_buf_t *src_buf, + udi_size_t src_off, + udi_size_t src_len, + udi_buf_t *dst_buf, + udi_size_t dst_off, + udi_size_t dst_len, + udi_buf_path_t path_handle ); + +/** + * \brief Copies data from driver space to a buffer + */ +extern void udi_buf_write( + udi_buf_write_call_t *callback, + udi_cb_t *gcb, + const void *src_mem, + udi_size_t src_len, + udi_buf_t *dst_buf, + udi_size_t dst_off, + udi_size_t dst_len, + udi_buf_path_t path_handle + ); + +/** + * \brief Reads data from a buffer into driver space + */ +extern void udi_buf_read( + udi_buf_t *src_buf, + udi_size_t src_off, + udi_size_t src_len, + void *dst_mem ); + +/** + * \brief Frees a buffer + */ +extern void udi_buf_free(udi_buf_t *buf); + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/cb.h b/Modules/Interfaces/UDI/include/udi/cb.h new file mode 100644 index 00000000..76db5c6e --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/cb.h @@ -0,0 +1,77 @@ +/** + * \file udi_cb.h + */ +#ifndef _UDI_CB_H_ +#define _UDI_CB_H_ + +typedef struct udi_cb_s udi_cb_t; +typedef void udi_cb_alloc_call_t(udi_cb_t *gcb, udi_cb_t *new_cb); +typedef void udi_cb_alloc_batch_call_t(udi_cb_t *gcb, udi_cb_t *first_new_cb); +typedef void udi_cancel_call_t(udi_cb_t *gcb); + +#define UDI_GCB(mcb) (&(mcb)->gcb) +#define UDI_MCB(gcb, cb_type) ((cb_type *)(gcb)) + +/** + * \brief Describes a generic control block + * \note Semi-opaque + */ +struct udi_cb_s +{ + /** + * \brief Channel associated with the control block + */ + udi_channel_t channel; + /** + * \brief Current state + * \note Driver changable + */ + void *context; + /** + * \brief CB's scratch area + */ + void *scratch; + /** + * \brief ??? + */ + void *initiator_context; + /** + * \brief Request Handle? + */ + udi_origin_t origin; +}; + +extern void udi_cb_alloc ( + udi_cb_alloc_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_channel_t default_channel + ); + +extern void udi_cb_alloc_dynamic( + udi_cb_alloc_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_channel_t default_channel, + udi_size_t inline_size, + udi_layout_t *inline_layout + ); + +extern void udi_cb_alloc_batch( + udi_cb_alloc_batch_call_t *callback, + udi_cb_t *gcb, + udi_index_t cb_idx, + udi_index_t count, + udi_boolean_t with_buf, + udi_size_t buf_size, + udi_buf_path_t path_handle + ); + +extern void udi_cb_free(udi_cb_t *cb); + +extern void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb); + + + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/imc.h b/Modules/Interfaces/UDI/include/udi/imc.h new file mode 100644 index 00000000..e5b3f3bb --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/imc.h @@ -0,0 +1,92 @@ +/** + * \file udi_imc.h + * \brief Inter-Module Communication + */ +#ifndef _UDI_IMC_H_ +#define _UDI_IMC_H_ + +typedef void udi_channel_anchor_call_t(udi_cb_t *gcb, udi_channel_t anchored_channel); +typedef void udi_channel_spawn_call_t(udi_cb_t *gcb, udi_channel_t new_channel); + +typedef struct udi_channel_event_cb_s udi_channel_event_cb_t; + +typedef void udi_channel_event_ind_op_t(udi_channel_event_cb_t *cb); + +/** + * \brief Anchors a channel end to the current region + */ +extern void udi_channel_anchor( + udi_channel_anchor_call_t *callback, udi_cb_t *gcb, + udi_channel_t channel, udi_index_t ops_idx, void *channel_context + ); + +/** + * \brief Created a new channel between two regions + */ +extern void udi_channel_spawn( + udi_channel_spawn_call_t *callback, + udi_cb_t *gcb, + udi_channel_t channel, + udi_index_t spawn_idx, + udi_index_t ops_idx, + void *channel_context + ); + +/** + * \brief Attaches a new context pointer to the current channel + */ +extern void udi_channel_set_context( + udi_channel_t target_channel, + void *channel_context + ); +/** + * \brief + */ +extern void udi_channel_op_abort( + udi_channel_t target_channel, + udi_cb_t *orig_cb + ); + +/** + * \brief Closes an open channel + */ +extern void udi_channel_close(udi_channel_t channel); + +/** + * \brief Describes a channel event + */ +struct udi_channel_event_cb_s +{ + udi_cb_t gcb; + udi_ubit8_t event; + union { + struct { + udi_cb_t *bind_cb; + } internal_bound; + struct { + udi_cb_t *bind_cb; + udi_ubit8_t parent_ID; + udi_buf_path_t *path_handles; + } parent_bound; + udi_cb_t *orig_cb; + } params; +}; +/* Channel event types */ +#define UDI_CHANNEL_CLOSED 0 +#define UDI_CHANNEL_BOUND 1 +#define UDI_CHANNEL_OP_ABORTED 2 + +/** + * \brief Proxy function + */ +extern void udi_channel_event_ind(udi_channel_event_cb_t *cb); + +/** + * \brief Called when channel event is completed + */ +extern void udi_channel_event_complete( + udi_channel_event_cb_t *cb, udi_status_t status + ); + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/init.h b/Modules/Interfaces/UDI/include/udi/init.h new file mode 100644 index 00000000..f405d036 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/init.h @@ -0,0 +1,315 @@ +/** + * \file udi_init.h + */ +#ifndef _UDI_INIT_H_ +#define _UDI_INIT_H_ + +typedef struct udi_init_s udi_init_t; +typedef struct udi_primary_init_s udi_primary_init_t; +typedef struct udi_secondary_init_s udi_secondary_init_t; +typedef struct udi_ops_init_s udi_ops_init_t; +typedef struct udi_cb_init_s udi_cb_init_t; +typedef struct udi_cb_select_s udi_cb_select_t; +typedef struct udi_gcb_init_s udi_gcb_init_t; + +typedef struct udi_init_context_s udi_init_context_t; +typedef struct udi_limits_s udi_limits_t; +typedef struct udi_chan_context_s udi_chan_context_t; +typedef struct udi_child_chan_context_s udi_child_chan_context_t; + +typedef void udi_op_t(void); +typedef udi_op_t * const udi_ops_vector_t; + +/** + * \brief UDI Initialisation Structure + * + * Defines how to initialise and use a UDI driver + */ +struct udi_init_s +{ + /** + * \brief Defines the primary region + * \note For secondary modules this must be NULL + */ + udi_primary_init_t *primary_init_info; + + /** + * \brief Defines all secondary regions + * Pointer to a list (so, essentially an array) of ::udi_secondary_init_t + * It is terminated by an entry with ::udi_secondary_init_t.region_idx + * set to zero. + * \note If NULL, it is to be treated as an empty list + */ + udi_secondary_init_t *secondary_init_list; + + /** + * \brief Channel operations + * Pointer to a ::udi_ops_init_t.ops_idx == 0 terminated list that + * defines the channel opterations usage for each ops vector implemented + * in this module. + * \note Must contain at least one entry for each metalanguage used + */ + udi_ops_init_t *ops_init_list; + + /** + * \brief Control Blocks + */ + udi_cb_init_t *cb_init_list; + + /** + * \brief Generic Control Blocks + */ + udi_gcb_init_t *gcb_init_list; + + /** + * \brief Overrides for control blocks + * Allows a control block to override the ammount of scratch space it + * gets for a specific ops vector. + */ + udi_cb_select_t *cb_select_list; +}; + + +/** + * \name Flags for ::udi_primary_init_t.mgmt_op_flags + * \{ + */ + +/** + * \brief Tells the environment that this operation may take some time + * Used as a hint in scheduling tasks + */ +#define UDI_OP_LONG_EXEC 0x01 + +/** + * \} + */ + +/** + * \brief Describes the Primary Region + * Tells the environment how to set up the driver's primary region. + */ +struct udi_primary_init_s +{ + /** + * \brief Management Ops Vector + * Pointer to a list of functions for the Management Metalanguage + */ + udi_mgmt_ops_t *mgmt_ops; + + /** + * \brief Flags for \a mgmt_ops + * Each entry in \a mgmt_ops is acommanied by an entry in this array. + * Each entry contains the flags that apply to the specified ops vector. + * \see UDI_OP_LONG_EXEC + */ + const udi_ubit8_t *mgmt_op_flags; + + /** + * \brief Scratch space size + * Specifies the number of bytes to allocate for each control block + * passed by the environment. + * \note must not exceed ::UDI_MAX_SCRATCH + */ + udi_size_t mgmt_scratch_requirement; + + /** + * \todo What is this? + */ + udi_ubit8_t enumeration_attr_list_length; + + /** + * \brief Size in bytes to allocate to each instance of the primary + * region + * Essentially the size of the driver's instance state + * \note Must be at least sizeof(udi_init_context_t) and not more + * than UDI_MIN_ALLOC_LIMIT + */ + udi_size_t rdata_size; + + /** + * \brief Size in bytes to allocate for each call to ::udi_enumerate_req + * \note Must not exceed UDI_MIN_ALLOC_LIMIT + */ + udi_size_t child_data_size; + + /** + * \brief Number of path handles for each parent bound to this driver + * \todo What the hell are path handles? + */ + udi_ubit8_t per_parent_paths; +}; + +/** + * \brief Tells the environment how to create a secondary region + */ +struct udi_secondary_init_s +{ + /** + * \brief Region Index + * Non-zero driver-dependent index value that identifies the region + * \note This corresponds to a "region" declaration in the udiprops.txt + * file. + */ + udi_index_t region_idx; + /** + * \brief Number of bytes to allocate + * + * \note Again, must be between sizeof(udi_init_context_t) and + * UDI_MIN_ALLOC_LIMIT + */ + udi_size_t rdata_size; +}; + +/** + * \brief Defines channel endpoints (ways of communicating with the driver) + * + */ +struct udi_ops_init_s +{ + /** + * \brief ops index number + * Used to uniquely this entry + * \note If this is zero, it marks the end of the list + */ + udi_index_t ops_idx; + /** + * \brief Metalanguage Index + * Defines what metalanguage is used + */ + udi_index_t meta_idx; + /** + * \brief Metalanguage Operation + * Defines what metalanguage operation is used + */ + udi_index_t meta_ops_num; + /** + * \brief Size of the context area + * \note If non-zero, must be at least + */ + udi_size_t chan_context_size; + /** + * \brief Pointer to the operations + * Pointer to a <>_<>_ops_t structure + */ + udi_ops_vector_t *ops_vector; + /** + * \brief Flags for each entry in \a ops_vector + */ + const udi_ubit8_t *op_flags; +}; + +/** + * \brief Defines control blocks + * Much the same as ::udi_ops_init_t + */ +struct udi_cb_init_s +{ + udi_index_t cb_idx; + udi_index_t meta_idx; + udi_index_t meta_cb_num; + udi_size_t scratch_requirement; + /** + * \brief Size of inline memory + */ + udi_size_t inline_size; + /** + * \brief Layout of inline memory + */ + udi_layout_t *inline_layout; +}; + +/** + * \brief Overrides the scratch size for an operation + */ +struct udi_cb_select_s +{ + udi_index_t ops_idx; + udi_index_t cb_idx; +}; + +/** + * \brief General Control Blocks + * These control blocks can only be used as general data storage, not + * for any channel operations. + */ +struct udi_gcb_init_s +{ + udi_index_t cb_idx; + udi_size_t scratch_requirement; +}; + + +// === +// === +/** + * \brief Environement Imposed Limits + */ +struct udi_limits_s +{ + /** + * \brief Maximum legal ammount of memory that can be allocated + */ + udi_size_t max_legal_alloc; + + /** + * \brief Maximum ammount of guaranteed memory + */ + udi_size_t max_safe_alloc; + /** + * \brief Maximum size of the final string from ::udi_trace_write + * or ::udi_log_write + */ + udi_size_t max_trace_log_formatted_len; + /** + * \brief Maximum legal size of an instanct attribute value + */ + udi_size_t max_instance_attr_len; + /** + * \brief Minumum time difference (in nanoseconds between unique values + * returned by ::udi_time_current + */ + udi_ubit32_t min_curtime_res; + /** + * \brief Minimum resolution of timers + * \see ::udi_timer_start_repeating, ::udi_timer_start + */ + udi_ubit32_t min_timer_res; +} PACKED; + +/** + * \brief Primary Region Context data + */ +struct udi_init_context_s +{ + udi_index_t region_idx; + udi_limits_t limits; +}; + +/** + * \brief Channel context data + */ +struct udi_chan_context_s +{ + /** + * \brief Pointer to the driver instance's initial region data + */ + void *rdata; +} PACKED; + +/** + * \brief Child Channel context + */ +struct udi_child_chan_context_s +{ + /** + * \brief Pointer to the driver instance's initial region data + */ + void *rdata; + /** + * \brief Some sort of unique ID number + */ + udi_ubit32_t child_ID; +}; + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/log.h b/Modules/Interfaces/UDI/include/udi/log.h new file mode 100644 index 00000000..dccb1246 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/log.h @@ -0,0 +1,31 @@ +/** + * \file udi_log.h + */ +#ifndef _UDI_LOG_H_ +#define _UDI_LOG_H_ + +/** + * \brief Trace Event + */ +typedef udi_ubit32_t udi_trevent_t; + +/** + * \brief Log Callback + */ +typedef void udi_log_write_call_t(udi_cb_t *gcb, udi_status_t correlated_status); + +/** + * \name Log Severities + * \brief Values for severity + * \{ + */ +#define UDI_LOG_DISASTER 1 +#define UDI_LOG_ERROR 2 +#define UDI_LOG_WARNING 3 +#define UDI_LOG_INFORMATION 4 +/** + * \} + */ + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/mem.h b/Modules/Interfaces/UDI/include/udi/mem.h new file mode 100644 index 00000000..d29f25ed --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/mem.h @@ -0,0 +1,38 @@ +/** + * \file udi_mem.h + */ +#ifndef _UDI_MEM_H_ +#define _UDI_MEM_H_ + +/** + * \brief Callback type for ::udi_mem_alloc + */ +typedef void udi_mem_alloc_call_t(udi_cb_t *gcb, void *new_mem); + +/** + * \brief Allocate memory + */ +extern void udi_mem_alloc( + udi_mem_alloc_call_t *callback, + udi_cb_t *gcb, + udi_size_t size, + udi_ubit8_t flags + ); + +/** + * \brief Values for ::udi_mem_alloc \a flags + * \{ + */ +#define UDI_MEM_NOZERO (1U<<0) //!< No need to zero the memory +#define UDI_MEM_MOVABLE (1U<<1) //!< Globally accessable memory? +/** + * \} + */ + +/** + * \brief Free allocated memory + */ +extern void udi_mem_free(void *target_mem); + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/meta_gio.h b/Modules/Interfaces/UDI/include/udi/meta_gio.h new file mode 100644 index 00000000..d1cf86fd --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/meta_gio.h @@ -0,0 +1,120 @@ +/** + * \file udi_meta_gio.h + */ +#ifndef _UDI_META_GIO_H_ +#define _UDI_META_GIO_H_ + +typedef const struct udi_gio_provider_ops_s udi_gio_provider_ops_t; +typedef const struct udi_gio_client_ops_s udi_gio_client_ops_t; +typedef struct udi_gio_bind_cb_s udi_gio_bind_cb_t; +typedef struct udi_gio_xfer_cb_s udi_gio_xfer_cb_t; +typedef struct udi_gio_rw_params_s udi_gio_rw_params_t; +typedef struct udi_gio_event_cb_s udi_gio_event_cb_t; + +typedef void udi_gio_bind_req_op_t(udi_gio_bind_cb_t *cb); +typedef void udi_gio_unbind_req_op_t(udi_gio_bind_cb_t *cb); +typedef void udi_gio_xfer_req_op_t(udi_gio_bind_cb_t *cb); +typedef void udi_gio_event_res_op_t(udi_gio_bind_cb_t *cb); + +typedef void udi_gio_bind_ack_op_t( + udi_gio_bind_cb_t *cb, + udi_ubit32_t device_size_lo, + udi_ubit32_t device_size_hi, + udi_status_t status + ); +typedef void udi_gio_unbind_ack_op_t(udi_gio_bind_cb_t *cb); +typedef void udi_gio_xfer_ack_op_t(udi_gio_bind_cb_t *cb); +typedef void udi_gio_xfer_nak_op_t(udi_gio_bind_cb_t *cb, udi_status_t status); +typedef void udi_gio_event_ind_op_t(udi_gio_bind_cb_t *cb); + +typedef udi_ubit8_t udi_gio_op_t; +/* Limit values for udi_gio_op_t */ +#define UDI_GIO_OP_CUSTOM 16 +#define UDI_GIO_OP_MAX 64 +/* Direction flag values for op */ +#define UDI_GIO_DIR_READ (1U<<6) +#define UDI_GIO_DIR_WRITE (1U<<7) +/* Standard Operation Codes */ +#define UDI_GIO_OP_READ UDI_GIO_DIR_READ +#define UDI_GIO_OP_WRITE UDI_GIO_DIR_WRITE + + + +struct udi_gio_provider_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_gio_bind_req_op_t *gio_bind_req_op; + udi_gio_unbind_req_op_t *gio_unbind_req_op; + udi_gio_xfer_req_op_t *gio_xfer_req_op; + udi_gio_event_res_op_t *gio_event_res_op; +}; +/* Ops Vector Number */ +#define UDI_GIO_PROVIDER_OPS_NUM 1 + +struct udi_gio_client_ops_s +{ + udi_channel_event_ind_op_t *channel_event_ind_op; + udi_gio_bind_ack_op_t *gio_bind_ack_op; + udi_gio_unbind_ack_op_t *gio_unbind_ack_op; + udi_gio_xfer_ack_op_t *gio_xfer_ack_op; + udi_gio_xfer_nak_op_t *gio_xfer_nak_op; + udi_gio_event_ind_op_t *gio_event_ind_op; +}; +/* Ops Vector Number */ +#define UDI_GIO_CLIENT_OPS_NUM 2 + +struct udi_gio_bind_cb_s +{ + udi_cb_t gcb; + udi_xfer_constraints_t xfer_constraints; +}; +/* Control Block Group Number */ +#define UDI_GIO_BIND_CB_NUM 1 + + +struct udi_gio_xfer_cb_s +{ + udi_cb_t gcb; + udi_gio_op_t op; + void *tr_params; + udi_buf_t *data_buf; +}; +/* Control Block Group Number */ +#define UDI_GIO_XFER_CB_NUM 2 + +struct udi_gio_rw_params_s +{ + udi_ubit32_t offset_lo; + udi_ubit32_t offset_hi; +}; + +struct udi_gio_event_cb_s +{ + udi_cb_t gcb; + udi_ubit8_t event_code; + void *event_params; +}; +/* Control Block Group Number */ +#define UDI_GIO_EVENT_CB_NUM 3 + + +extern void udi_gio_bind_req(udi_gio_bind_cb_t *cb); +extern void udi_gio_bind_ack( + udi_gio_bind_cb_t *cb, + udi_ubit32_t device_size_lo, + udi_ubit32_t device_size_hi, + udi_status_t status + ); + +extern void udi_gio_unbind_req(udi_gio_bind_cb_t *cb); +extern void udi_gio_unbind_ack(udi_gio_bind_cb_t *cb); + +extern void udi_gio_xfer_req(udi_gio_xfer_cb_t *cb); +extern void udi_gio_xfer_ack(udi_gio_xfer_cb_t *cb); +extern void udi_gio_xfer_nak(udi_gio_xfer_cb_t *cb, udi_status_t status); + +extern void udi_gio_event_res(udi_gio_event_cb_t *cb); +extern void udi_gio_event_ind(udi_gio_event_cb_t *cb); +extern void udi_gio_event_res_unused(udi_gio_event_cb_t *cb); + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/meta_mgmt.h b/Modules/Interfaces/UDI/include/udi/meta_mgmt.h new file mode 100644 index 00000000..97eccf2d --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/meta_mgmt.h @@ -0,0 +1,156 @@ +/** + * \file udi_meta_mgmt.h + */ +#ifndef _UDI_META_MGMT_H_ +#define _UDI_META_MGMT_H_ + +typedef struct udi_mgmt_ops_s udi_mgmt_ops_t; +typedef struct udi_mgmt_cb_s udi_mgmt_cb_t; +typedef struct udi_usage_cb_s udi_usage_cb_t; +typedef struct udi_filter_element_s udi_filter_element_t; +typedef struct udi_enumerate_cb_s udi_enumerate_cb_t; + +/** + * \name Specify Usage + * \{ + */ +typedef void udi_usage_ind_op_t(udi_usage_cb_t *cb, udi_ubit8_t resource_level); +/* Values for resource_level */ +#define UDI_RESOURCES_CRITICAL 1 +#define UDI_RESOURCES_LOW 2 +#define UDI_RESOURCES_NORMAL 3 +#define UDI_RESOURCES_PLENTIFUL 4 +/* Proxy */ +extern void udi_static_usage(udi_usage_cb_t *cb, udi_ubit8_t resource_level); +/** + * \} + */ + +typedef void udi_usage_res_op_t(udi_usage_cb_t *cb); + +/** + * \name Enumerate this driver + * \{ + */ +typedef void udi_enumerate_req_op_t(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level); +/* Values for enumeration_level */ +#define UDI_ENUMERATE_START 1 +#define UDI_ENUMERATE_START_RESCAN 2 +#define UDI_ENUMERATE_NEXT 3 +#define UDI_ENUMERATE_NEW 4 +#define UDI_ENUMERATE_DIRECTED 5 +#define UDI_ENUMERATE_RELEASE 6 +/* Proxy */ +extern void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level); +/** + * \} + */ + +/** + * \name Enumeration Acknowlagement + * \{ + */ +typedef void udi_enumerate_ack_op_t(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_result, udi_index_t ops_idx); +/* Values for enumeration_result */ +#define UDI_ENUMERATE_OK 0 +#define UDI_ENUMERATE_LEAF 1 +#define UDI_ENUMERATE_DONE 2 +#define UDI_ENUMERATE_RESCAN 3 +#define UDI_ENUMERATE_REMOVED 4 +#define UDI_ENUMERATE_REMOVED_SELF 5 +#define UDI_ENUMERATE_RELEASED 6 +#define UDI_ENUMERATE_FAILED 255 +/** + * \} + */ + +/** + * \name + * \{ + */ +typedef void udi_devmgmt_req_op_t(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID); + +typedef void udi_devmgmt_ack_op_t(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status); +/** + * \} + */ +typedef void udi_final_cleanup_req_op_t(udi_mgmt_cb_t *cb); +typedef void udi_final_cleanup_ack_op_t(udi_mgmt_cb_t *cb); + + + + + +struct udi_mgmt_ops_s +{ + udi_usage_ind_op_t *usage_ind_op; + udi_enumerate_req_op_t *enumerate_req_op; + udi_devmgmt_req_op_t *devmgmt_req_op; + udi_final_cleanup_req_op_t *final_cleanup_req_op; +}; + +struct udi_mgmt_cb_s +{ + udi_cb_t gcb; +}; + +struct udi_usage_cb_s +{ + udi_cb_t gcb; + udi_trevent_t trace_mask; + udi_index_t meta_idx; +}; + + +struct udi_filter_element_s +{ + char attr_name[UDI_MAX_ATTR_NAMELEN]; + udi_ubit8_t attr_min[UDI_MAX_ATTR_SIZE]; + udi_ubit8_t attr_min_len; + udi_ubit8_t attr_max[UDI_MAX_ATTR_SIZE]; + udi_ubit8_t attr_max_len; + udi_instance_attr_type_t attr_type; + udi_ubit32_t attr_stride; +}; +struct udi_enumerate_cb_s +{ + udi_cb_t gcb; + udi_ubit32_t child_ID; + void *child_data; + udi_instance_attr_list_t *attr_list; + udi_ubit8_t attr_valid_length; + const udi_filter_element_t *filter_list; + udi_ubit8_t filter_list_length; + udi_ubit8_t parent_ID; +}; +/* Special parent_ID filter values */ +#define UDI_ANY_PARENT_ID 0 + +/** + * \brief + */ +extern void udi_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID ); +/** + * \brief Values for ::udi_devmgmt_req \a mgmt_op + */ +enum eDMGMT +{ + UDI_DMGMT_PREPARE_TO_SUSPEND = 1, + UDI_DMGMT_SUSPEND, + UDI_DMGMT_SHUTDOWN, + UDI_DMGMT_PARENT_SUSPENDED, + UDI_DMGMT_RESUME, + UDI_DMGMT_UNBIND +}; + +extern void udi_devmgmt_ack(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status); +//!\brief Values for flags +#define UDI_DMGMT_NONTRANSPARENT (1U<<0) +//!\brief Meta-Specific Status Codes +#define UDI_DMGMT_STAT_ROUTING_CHANGE (UDI_STAT_META_SPECIFIC|1) + +extern void udi_final_cleanup_req(udi_mgmt_cb_t *cb); +extern void udi_final_cleanup_ack(udi_mgmt_cb_t *cb); + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi/strmem.h b/Modules/Interfaces/UDI/include/udi/strmem.h new file mode 100644 index 00000000..f540a3ea --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi/strmem.h @@ -0,0 +1,44 @@ +/** + * \file udi_strmem.h + */ +#ifndef _UDI_STRMEM_H_ +#define _UDI_STRMEM_H_ + +/** + * \brief Gets the length of a C style string + */ +extern udi_size_t udi_strlen(const char *s); + +/** + * \brief Appends to a string + */ +extern char *udi_strcat(char *s1, const char *s2); +extern char *udi_strncat(char *s1, const char *s2, udi_size_t n); + +/** + * \brief Compares Strings/Memory + */ +extern udi_sbit8_t udi_strcmp(const char *s1, const char *s2); +extern udi_sbit8_t udi_strncmp(const char *s1, const char *s2, udi_size_t n); +extern udi_sbit8_t udi_memcmp(const void *s1, const void *s2, udi_size_t n); + +extern char *udi_strcpy(char *s1, const char *s2); +extern char *udi_strncpy(char *s1, const char *s2, udi_size_t n); +extern void *udi_memcpy(void *s1, const void *s2, udi_size_t n); +extern void *udi_memmove(void *s1, const void *s2, udi_size_t n); + +extern char *udi_strncpy_rtrim(char *s1, const char *s2, udi_size_t n); + +extern char *udi_strchr(const char *s, char c); +extern char *udi_strrchr(const char *s, char c); +extern void *udi_memchr (const void *s, udi_ubit8_t c, udi_size_t n); + +extern void *udi_memset(void *s, udi_ubit8_t c, udi_size_t n); +extern udi_ubit32_t udi_strtou32(const char *s, char **endptr, int base); + + +extern udi_size_t udi_snprintf(char *s, udi_size_t max_bytes, const char *format, ...); + + + +#endif diff --git a/Modules/Interfaces/UDI/include/udi_physio.h b/Modules/Interfaces/UDI/include/udi_physio.h new file mode 100644 index 00000000..1397b1c0 --- /dev/null +++ b/Modules/Interfaces/UDI/include/udi_physio.h @@ -0,0 +1,144 @@ +/** + * \file udi_physio.h + */ +#ifndef _UDI_PHYSIO_H_ +#define _UDI_PHYSIO_H_ + +#include + +// === TYPEDEFS === +// DMA Core +typedef _udi_handle_t udi_dma_handle_t; +#define UDI_NULL_DMA_HANDLE _NULL_HANDLE +typedef Uint64 udi_busaddr64_t; //!< \note Opaque +typedef struct udi_scgth_element_32_s udi_scgth_element_32_t; +typedef struct udi_scgth_element_64_s udi_scgth_element_64_t; +typedef struct udi_scgth_s udi_scgth_t; +typedef _udi_handle_t udi_dma_constraints_t; +#define UDI_NULL_DMA_CONSTRAINTS _NULL_HANDLE +/** + * \name DMA constraints attributes + * \{ + */ +typedef udi_ubit8_t udi_dma_constraints_attr_t; +/* DMA Convenience Attribute Codes */ +#define UDI_DMA_ADDRESSABLE_BITS 100 +#define UDI_DMA_ALIGNMENT_BITS 101 +/* DMA Constraints on the Entire Transfer */ +#define UDI_DMA_DATA_ADDRESSABLE_BITS 110 +#define UDI_DMA_NO_PARTIAL 111 +/* DMA Constraints on the Scatter/Gather List */ +#define UDI_DMA_SCGTH_MAX_ELEMENTS 120 +#define UDI_DMA_SCGTH_FORMAT 121 +#define UDI_DMA_SCGTH_ENDIANNESS 122 +#define UDI_DMA_SCGTH_ADDRESSABLE_BITS 123 +#define UDI_DMA_SCGTH_MAX_SEGMENTS 124 +/* DMA Constraints on Scatter/Gather Segments */ +#define UDI_DMA_SCGTH_ALIGNMENT_BITS 130 +#define UDI_DMA_SCGTH_MAX_EL_PER_SEG 131 +#define UDI_DMA_SCGTH_PREFIX_BYTES 132 +/* DMA Constraints on Scatter/Gather Elements */ +#define UDI_DMA_ELEMENT_ALIGNMENT_BITS 140 +#define UDI_DMA_ELEMENT_LENGTH_BITS 141 +#define UDI_DMA_ELEMENT_GRANULARITY_BITS 142 +/* DMA Constraints for Special Addressing */ +#define UDI_DMA_ADDR_FIXED_BITS 150 +#define UDI_DMA_ADDR_FIXED_TYPE 151 +#define UDI_DMA_ADDR_FIXED_VALUE_LO 152 +#define UDI_DMA_ADDR_FIXED_VALUE_HI 153 +/* DMA Constraints on DMA Access Behavior */ +#define UDI_DMA_SEQUENTIAL 160 +#define UDI_DMA_SLOP_IN_BITS 161 +#define UDI_DMA_SLOP_OUT_BITS 162 +#define UDI_DMA_SLOP_OUT_EXTRA 163 +#define UDI_DMA_SLOP_BARRIER_BITS 164 +/* Values for UDI_DMA_SCGTH_ENDIANNESS */ +#define UDI_DMA_LITTLE_ENDIAN (1U<<6) +#define UDI_DMA_BIG_ENDIAN (1U<<5) +/* Values for UDI_DMA_ADDR_FIXED_TYPE */ +#define UDI_DMA_FIXED_ELEMENT 1 +/** + * \} + */ +// DMA Constraints Management +typedef struct udi_dma_constraints_attr_spec_s udi_dma_constraints_attr_spec_t; +typedef void udi_dma_constraints_attr_set_call_t( + udi_cb_t *gcb, udi_dma_constraints_t new_constraints, udi_status_t status + ); +typedef struct udi_dma_limits_s udi_dma_limits_t; + + +// === STRUCTURES === +// --- DMA Constraints Management --- +struct udi_dma_constraints_attr_spec_s +{ + udi_dma_constraints_attr_t attr_type; + udi_ubit32_t attr_value; +}; +// --- DMA Core --- +struct udi_dma_limits_s +{ + udi_size_t max_legal_contig_alloc; + udi_size_t max_safe_contig_alloc; + udi_size_t cache_line_size; +}; +struct udi_scgth_element_32_s +{ + udi_ubit32_t block_busaddr; + udi_ubit32_t block_length; +}; +struct udi_scgth_element_64_s +{ + udi_busaddr64_t block_busaddr; + udi_ubit32_t block_length; + udi_ubit32_t el_reserved; +}; +/* Extension Flag */ +#define UDI_SCGTH_EXT 0x80000000 +struct udi_scgth_s +{ + udi_ubit16_t scgth_num_elements; + udi_ubit8_t scgth_format; + udi_boolean_t scgth_must_swap; + union { + udi_scgth_element_32_t *el32p; + udi_scgth_element_64_t *el64p; + } scgth_elements; + union { + udi_scgth_element_32_t el32; + udi_scgth_element_64_t el64; + } scgth_first_segment; +}; +/* Values for scgth_format */ +#define UDI_SCGTH_32 (1U<<0) +#define UDI_SCGTH_64 (1U<<1) +#define UDI_SCGTH_DMA_MAPPED (1U<<6) +#define UDI_SCGTH_DRIVER_MAPPED (1U<<7) + + + +// === FUNCTIONS === +// --- DMA Constraints Management --- +extern void udi_dma_constraints_attr_set( + udi_dma_constraints_attr_set_call_t *callback, + udi_cb_t *gcb, + udi_dma_constraints_t src_constraints, + const udi_dma_constraints_attr_spec_t *attr_list, + udi_ubit16_t list_length, + udi_ubit8_t flags + ); +/* Constraints Flags */ +#define UDI_DMA_CONSTRAINTS_COPY (1U<<0) + +extern void udi_dma_constraints_attr_reset( + udi_dma_constraints_t constraints, + udi_dma_constraints_attr_t attr_type + ); + +extern void udi_dma_constraints_free(udi_dma_constraints_t constraints); + +#include +#include + + +#endif diff --git a/Modules/Interfaces/UDI/logging.c b/Modules/Interfaces/UDI/logging.c new file mode 100644 index 00000000..2e58e373 --- /dev/null +++ b/Modules/Interfaces/UDI/logging.c @@ -0,0 +1,18 @@ +/** + * \file logging.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === PROTOTYPES === + +// === CODE === +void udi_log_write( udi_log_write_call_t *callback, udi_cb_t *gcb, + udi_trevent_t trace_event, udi_ubit8_t severity, udi_index_t meta_idx, + udi_status_t original_status, udi_ubit32_t msgnum, ... ) +{ + Log("UDI Log"); +} + +EXPORT(udi_log_write); diff --git a/Modules/Interfaces/UDI/main.c b/Modules/Interfaces/UDI/main.c new file mode 100644 index 00000000..d114bdc9 --- /dev/null +++ b/Modules/Interfaces/UDI/main.c @@ -0,0 +1,114 @@ +/* + * Acess2 UDI Layer + */ +#define DEBUG 0 +#define VERSION ((0<<8)|1) +#include +#include +#include + +// === PROTOTYPES === + int UDI_Install(char **Arguments); + int UDI_DetectDriver(void *Base); + int UDI_LoadDriver(void *Base); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL); +tModuleLoader gUDI_Loader = { + NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL +}; + +// === CODE === +/** + * \fn int UDI_Install(char **Arguments) + * \brief Stub intialisation routine + */ +int UDI_Install(char **Arguments) +{ + Module_RegisterLoader( &gUDI_Loader ); + return 1; +} + +/** + * \brief Detects if a driver should be loaded by the UDI subsystem + */ +int UDI_DetectDriver(void *Base) +{ + if( Binary_FindSymbol(Base, "udi_init_info", NULL) == 0) { + return 0; + } + + return 1; +} + +/** + * \fn int UDI_LoadDriver(void *Base) + */ +int UDI_LoadDriver(void *Base) +{ + udi_init_t *info; + char *udiprops = NULL; + int udiprops_size = 0; + int i; + // int j; + + Log("UDI_LoadDriver: (Base=%p)", Base); + + if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) { + Binary_Unload(Base); + return 0; + } + + if( Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops) == 0 ) { + Warning("[UDI ] _udiprops is not defined, this is usually bad"); + } + else { + Binary_FindSymbol(Base, "_udiprops_size", (Uint*)&udiprops_size); + Log("udiprops = %p, udiprops_size = 0x%x", udiprops, udiprops_size); + } + + + Log("primary_init_info = %p = {", info->primary_init_info); + { + Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops); + Log(" .usage_ind_op: %p() - 0x%02x", + info->primary_init_info->mgmt_ops->usage_ind_op, + info->primary_init_info->mgmt_op_flags[0] + ); + Log(" .enumerate_req_op: %p() - 0x%02x", + info->primary_init_info->mgmt_ops->enumerate_req_op, + info->primary_init_info->mgmt_op_flags[1] + ); + Log(" .devmgmt_req_op: %p() - 0x%02x", + info->primary_init_info->mgmt_ops->devmgmt_req_op, + info->primary_init_info->mgmt_op_flags[2] + ); + Log(" .final_cleanup_req_op: %p() - 0x%02x", + info->primary_init_info->mgmt_ops->final_cleanup_req_op, + info->primary_init_info->mgmt_op_flags[3] + ); + Log(" }"); + Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement); + Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length); + Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size); + Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size); + Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths); + } + Log("}"); + Log("secondary_init_list = %p", info->secondary_init_list); + Log("ops_init_list = %p", info->ops_init_list); + + for( i = 0; info->ops_init_list[i].ops_idx; i++ ) + { + Log("info->ops_init_list[%i] = {", i); + Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx); + Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx); + Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num); + Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size); + Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector); + Log(" .op_flags = %p", info->ops_init_list[i].op_flags); + Log("}"); + } + + return 0; +} diff --git a/Modules/Interfaces/UDI/mem.c b/Modules/Interfaces/UDI/mem.c new file mode 100644 index 00000000..a09d54c5 --- /dev/null +++ b/Modules/Interfaces/UDI/mem.c @@ -0,0 +1,32 @@ +/** + * \file mem.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_mem_alloc); +EXPORT(udi_mem_free); + +// === CODE === +void udi_mem_alloc( + udi_mem_alloc_call_t *callback, + udi_cb_t *gcb, + udi_size_t size, + udi_ubit8_t flags + ) +{ + void *buf = malloc(size); + if(buf) + { + if( !(flags & UDI_MEM_NOZERO) ) + memset(buf, 0, size); + } + callback(gcb, buf); +} + +void udi_mem_free(void *target_mem) +{ + free(target_mem); +} diff --git a/Modules/Interfaces/UDI/meta_gio.c b/Modules/Interfaces/UDI/meta_gio.c new file mode 100644 index 00000000..1618c27f --- /dev/null +++ b/Modules/Interfaces/UDI/meta_gio.c @@ -0,0 +1,68 @@ +/** + * \file meta_gio.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_gio_bind_req); +EXPORT(udi_gio_bind_ack); +EXPORT(udi_gio_unbind_req); +EXPORT(udi_gio_unbind_ack); +EXPORT(udi_gio_xfer_req); +EXPORT(udi_gio_xfer_ack); +EXPORT(udi_gio_xfer_nak); +EXPORT(udi_gio_event_res); +EXPORT(udi_gio_event_ind); +EXPORT(udi_gio_event_res_unused); + +// === CODE === +void udi_gio_bind_req(udi_gio_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_bind_ack( + udi_gio_bind_cb_t *cb, + udi_ubit32_t device_size_lo, + udi_ubit32_t device_size_hi, + udi_status_t status + ) +{ + UNIMPLEMENTED(); +} + +void udi_gio_unbind_req(udi_gio_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_unbind_ack(udi_gio_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_gio_xfer_req(udi_gio_xfer_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_xfer_ack(udi_gio_xfer_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_xfer_nak(udi_gio_xfer_cb_t *cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_gio_event_res(udi_gio_event_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_event_ind(udi_gio_event_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_gio_event_res_unused(udi_gio_event_cb_t *cb) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/meta_mgmt.c b/Modules/Interfaces/UDI/meta_mgmt.c new file mode 100644 index 00000000..45a02c46 --- /dev/null +++ b/Modules/Interfaces/UDI/meta_mgmt.c @@ -0,0 +1,49 @@ +/** + * \file meta_mgmt.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_devmgmt_req); +EXPORT(udi_devmgmt_ack); +EXPORT(udi_final_cleanup_req); +EXPORT(udi_final_cleanup_ack); +EXPORT(udi_static_usage); +EXPORT(udi_enumerate_no_children); + +// === CODE === +void udi_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID ) +{ + ENTER("pcb imgmt_op iparent_ID", cb, mgmt_op, parent_ID); + LEAVE('-'); +} + +void udi_devmgmt_ack(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status) +{ + ENTER("pcb xflags istatus", cb, flags, status); + LEAVE('-'); +} + +void udi_final_cleanup_req(udi_mgmt_cb_t *cb) +{ + ENTER("pcb", cb); + LEAVE('-'); +} + +void udi_final_cleanup_ack(udi_mgmt_cb_t *cb) +{ + ENTER("pcb", cb); + LEAVE('-'); +} + +void udi_static_usage(udi_usage_cb_t *cb, udi_ubit8_t resource_level) +{ + UNIMPLEMENTED(); +} + +void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/physio.c b/Modules/Interfaces/UDI/physio.c new file mode 100644 index 00000000..881c9f40 --- /dev/null +++ b/Modules/Interfaces/UDI/physio.c @@ -0,0 +1,25 @@ +/** + * \file physio.c + * \author John Hodge (thePowersGang) + */ +#include +#include +#include + +// === EXPORTS === +EXPORT(udi_dma_constraints_attr_reset); +EXPORT(udi_dma_constraints_free); + +// === CODE === +void udi_dma_constraints_attr_reset( + udi_dma_constraints_t constraints, + udi_dma_constraints_attr_t attr_type + ) +{ + UNIMPLEMENTED(); +} + +void udi_dma_constraints_free(udi_dma_constraints_t constraints) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/physio/meta_bus.c b/Modules/Interfaces/UDI/physio/meta_bus.c new file mode 100644 index 00000000..e1e6a47d --- /dev/null +++ b/Modules/Interfaces/UDI/physio/meta_bus.c @@ -0,0 +1,38 @@ +/** + * \file physio/meta_bus.c + * \author John Hodge (thePowersGang) + */ +#include +#include +#include + +// === EXPORTS === +EXPORT(udi_bus_unbind_req); +EXPORT(udi_bus_unbind_ack); +EXPORT(udi_bus_bind_req); +EXPORT(udi_bus_bind_ack); + +// === CODE === +void udi_bus_unbind_req(udi_bus_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} +void udi_bus_unbind_ack(udi_bus_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_bus_bind_req(udi_bus_bind_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_bus_bind_ack( + udi_bus_bind_cb_t *cb, + udi_dma_constraints_t dma_constraints, + udi_ubit8_t preferred_endianness, + udi_status_t status + ) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/physio/meta_intr.c b/Modules/Interfaces/UDI/physio/meta_intr.c new file mode 100644 index 00000000..f4f50961 --- /dev/null +++ b/Modules/Interfaces/UDI/physio/meta_intr.c @@ -0,0 +1,48 @@ +/** + * \file physio/meta_intr.c + * \author John Hodge (thePowersGang) + */ +#include +#include +#include + +// === EXPORTS === +EXPORT(udi_intr_attach_req); +EXPORT(udi_intr_attach_ack); +EXPORT(udi_intr_attach_ack_unused); +EXPORT(udi_intr_detach_req); +EXPORT(udi_intr_detach_ack); +EXPORT(udi_intr_detach_ack_unused); +EXPORT(udi_intr_event_ind); + +// === CODE === +void udi_intr_attach_req(udi_intr_attach_cb_t *intr_attach_cb) +{ + UNIMPLEMENTED(); +} +void udi_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} +void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_intr_detach_req(udi_intr_detach_cb_t *intr_detach_cb) +{ + UNIMPLEMENTED(); +} +void udi_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb) +{ + UNIMPLEMENTED(); +} +void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb) +{ + UNIMPLEMENTED(); +} + +void udi_intr_event_ind(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags) +{ + UNIMPLEMENTED(); +} diff --git a/Modules/Interfaces/UDI/physio_main.c b/Modules/Interfaces/UDI/physio_main.c new file mode 100644 index 00000000..f5e7aa04 --- /dev/null +++ b/Modules/Interfaces/UDI/physio_main.c @@ -0,0 +1,16 @@ +/** + * \file logging.c + * \author John Hodge (thePowersGang) + */ +#include +#include +#include + +// === CODE === +void udi_bus_bind_req(udi_bus_bind_cb_t *cb) +{ +} + +void udi_bus_unbind_req(udi_bus_bind_cb_t *cb) +{ +} diff --git a/Modules/Interfaces/UDI/strmem.c b/Modules/Interfaces/UDI/strmem.c new file mode 100644 index 00000000..4ab1e208 --- /dev/null +++ b/Modules/Interfaces/UDI/strmem.c @@ -0,0 +1,16 @@ +/** + * \file strmem.c + * \author John Hodge (thePowersGang) + */ +#include +#include + +// === EXPORTS === +EXPORT(udi_snprintf); + +// === CODE === +udi_size_t udi_snprintf(char *s, udi_size_t max_bytes, const char *format, ...) +{ + s[0] = '\0'; + return 0; +} diff --git a/Modules/Makefile.tpl b/Modules/Makefile.tpl index ae6d5748..964f5cec 100644 --- a/Modules/Makefile.tpl +++ b/Modules/Makefile.tpl @@ -5,6 +5,7 @@ _CPPFLAGS := $(CPPFLAGS) CFGFILES = +CFGFILES += $(shell test -f ../../../Makefile.cfg && echo ../../../Makefile.cfg) CFGFILES += $(shell test -f ../../Makefile.cfg && echo ../../Makefile.cfg) CFGFILES += $(shell test -f ../Makefile.cfg && echo ../Makefile.cfg) CFGFILES += $(shell test -f Makefile.cfg && echo Makefile.cfg) diff --git a/Modules/NE2000/Makefile b/Modules/NE2000/Makefile deleted file mode 100644 index 7e740227..00000000 --- a/Modules/NE2000/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# - -OBJ = ne2000.o -NAME = NE2000 - --include ../Makefile.tpl diff --git a/Modules/NE2000/ne2000.c b/Modules/NE2000/ne2000.c deleted file mode 100644 index 76e4379f..00000000 --- a/Modules/NE2000/ne2000.c +++ /dev/null @@ -1,502 +0,0 @@ -/* Acess2 - * NE2000 Driver - * - * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc - */ -#define DEBUG 0 -#define VERSION ((0<<8)|50) -#include -#include -#include -#include -#include - -// === CONSTANTS === -#define MEM_START 0x40 -#define MEM_END 0xC0 -#define RX_FIRST (MEM_START) -#define RX_LAST (MEM_START+RX_BUF_SIZE-1) -#define RX_BUF_SIZE 0x40 -#define TX_FIRST (MEM_START+RX_BUF_SIZE) -#define TX_LAST (MEM_END) -#define TX_BUF_SIZE 0x40 -#define MAX_PACKET_QUEUE 10 - -static const struct { - Uint16 Vendor; - Uint16 Device; -} csaCOMPAT_DEVICES[] = { - {0x10EC, 0x8029}, // Realtek 8029 - {0x10EC, 0x8129} // Realtek 8129 -}; -#define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0])) - -enum eNe2k_Page0Read { - CMD = 0, //!< the master command register - CLDA0, //!< Current Local DMA Address 0 - CLDA1, //!< Current Local DMA Address 1 - BNRY, //!< Boundary Pointer (for ringbuffer) - TSR, //!< Transmit Status Register - NCR, //!< collisions counter - FIFO, //!< (for what purpose ??) - ISR, //!< Interrupt Status Register - CRDA0, //!< Current Remote DMA Address 0 - CRDA1, //!< Current Remote DMA Address 1 - RSR = 0xC //!< Receive Status Register -}; - -enum eNe2k_Page0Write { - PSTART = 1, //!< page start (init only) - PSTOP, //!< page stop (init only) - TPSR = 4, //!< transmit page start address - TBCR0, //!< transmit byte count (low) - TBCR1, //!< transmit byte count (high) - RSAR0 = 8, //!< remote start address (lo) - RSAR1, //!< remote start address (hi) - RBCR0, //!< remote byte count (lo) - RBCR1, //!< remote byte count (hi) - RCR, //!< receive config register - TCR, //!< transmit config register - DCR, //!< data config register (init) - IMR //!< interrupt mask register (init) -}; - -enum eNe2k_Page1Read { - CURR = 7 //!< current page -}; - -// === TYPES === -typedef struct sNe2k_Card { - Uint16 IOBase; //!< IO Port Address from PCI - Uint8 IRQ; //!< IRQ Assigned from PCI - - int NumWaitingPackets; - int NextRXPage; - - int NextMemPage; //!< Next Card Memory page to use - - Uint8 Buffer[RX_BUF_SIZE]; - - char Name[2]; // "0" - tVFS_Node Node; - Uint8 MacAddr[6]; -} tCard; - -// === PROTOTYPES === - int Ne2k_Install(char **Arguments); -char *Ne2k_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name); - int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data); -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); -void Ne2k_IRQHandler(int IntNum); - -// === GLOBALS === -MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL); -tDevFS_Driver gNe2k_DriverInfo = { - NULL, "ne2k", - { - .NumACLs = 1, - .ACLs = &gVFS_ACL_EveryoneRX, - .Flags = VFS_FFLAG_DIRECTORY, - .ReadDir = Ne2k_ReadDir, - .FindDir = Ne2k_FindDir, - .IOCtl = Ne2k_IOCtl - } -}; -Uint16 gNe2k_BaseAddress; - int giNe2k_CardCount = 0; -tCard *gpNe2k_Cards = NULL; - -// === CODE === -/** - * \fn int Ne2k_Install(char **Options) - * \brief Installs the NE2000 Driver - */ -int Ne2k_Install(char **Options) -{ - int i, j, k; - int count, id, base; - - // --- Scan PCI Bus --- - // Count Cards - giNe2k_CardCount = 0; - for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) - { - giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); - } - - // Enumerate Cards - k = 0; - gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) ); - - for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) - { - count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); - for( j = 0; j < count; j ++,k ++ ) - { - id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j ); - // Create Structure - base = PCI_AssignPort( id, 0, 0x20 ); - gpNe2k_Cards[ k ].IOBase = base; - gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id ); - gpNe2k_Cards[ k ].NextMemPage = 64; - gpNe2k_Cards[ k ].NextRXPage = RX_FIRST; - - // Install IRQ Handler - IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler); - - // Reset Card - outb( base + 0x1F, inb(base + 0x1F) ); - while( (inb( base+ISR ) & 0x80) == 0 ); - outb( base + ISR, 0x80 ); - - // Initialise Card - outb( base + CMD, 0x40|0x21 ); // Page 1, No DMA, Stop - outb( base + CURR, RX_FIRST ); // Current RX page - outb( base + CMD, 0x21 ); // No DMA and Stop - outb( base + DCR, 0x49 ); // Set WORD mode - outb( base + IMR, 0x00 ); - outb( base + ISR, 0xFF ); - outb( base + RCR, 0x20 ); // Reciever to Monitor - outb( base + TCR, 0x02 ); // Transmitter OFF (TCR.LB = 1, Internal Loopback) - outb( base + RBCR0, 6*4 ); // Remote Byte Count - outb( base + RBCR1, 0 ); - outb( base + RSAR0, 0 ); // Clear Source Address - outb( base + RSAR1, 0 ); - outb( base + CMD, 0x0A ); // Remote Read, Start - - // Read MAC Address - gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);// inb(base+0x10); - - outb( base+PSTART, RX_FIRST); // Set Receive Start - outb( base+BNRY, RX_LAST-1); // Set Boundary Page - outb( base+PSTOP, RX_LAST); // Set Stop Page - outb( base+ISR, 0xFF ); // Clear all ints - outb( base+CMD, 0x22 ); // No DMA, Start - outb( base+IMR, 0x3F ); // Set Interupt Mask - outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches - outb( base+TCR, 0x00 ); // Set Normal Transmitter mode - outb( base+TPSR, 0x40); // Set Transmit Start - // Set MAC Address - /* - Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]); - Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]); - Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]); - Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]); - Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]); - Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]); - */ - - Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x", - k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase); - Log("MAC Address %x:%x:%x:%x:%x:%x", - gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1], - gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3], - gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5] - ); - - // Set VFS Node - gpNe2k_Cards[ k ].Name[0] = '0'+k; - gpNe2k_Cards[ k ].Name[1] = '\0'; - gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ]; - gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only - gpNe2k_Cards[ k ].Node.CTime = now(); - gpNe2k_Cards[ k ].Node.Write = Ne2k_Write; - gpNe2k_Cards[ k ].Node.Read = Ne2k_Read; - gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl; - } - } - - gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount; - DevFS_AddDevice( &gNe2k_DriverInfo ); - return 1; -} - -/** - * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) - */ -char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) -{ - char ret[2]; - if(Pos < 0 || Pos >= giNe2k_CardCount) return NULL; - ret[0] = '0'+Pos; - ret[1] = '\0'; - return strdup(ret); -} - -/** - * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) - */ -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) -{ - if(Name[0] == '\0' || Name[1] != '\0') return NULL; - - return &gpNe2k_Cards[ Name[0]-'0' ].Node; -} - -static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL }; -/** - * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) - * \brief IOCtl calls for a network device - */ -int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) -{ - int tmp; - ENTER("pNode iID pData", Node, ID, Data); - switch( ID ) - { - case DRV_IOCTL_TYPE: - LEAVE('i', DRV_TYPE_NETWORK); - return DRV_TYPE_NETWORK; - - case DRV_IOCTL_IDENT: - tmp = ModUtil_SetIdent(Data, "Ne2k"); - LEAVE('i', tmp); - return tmp; - - case DRV_IOCTL_VERSION: - LEAVE('x', VERSION); - return VERSION; - - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls, Data ); - LEAVE('i', tmp); - return tmp; - } - - // If this is the root, return - if( Node == &gNe2k_DriverInfo.RootNode ) { - LEAVE('i', 0); - return 0; - } - - // Device specific settings - switch( ID ) - { - case NET_IOCTL_GETMAC: - if( !CheckMem(Data, 6) ) { - LEAVE('i', -1); - return -1; - } - memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 ); - LEAVE('i', 1); - return 1; - } - LEAVE('i', 0); - return 0; -} - -/** - * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Send a packet from the network card - */ -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tCard *Card = (tCard*)Node->ImplPtr; - Uint16 *buf = Buffer; - int rem = Length; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - // Sanity Check Length - if(Length > TX_BUF_SIZE) { - LEAVE('i', 0); - return 0; - } - - // Make sure that the card is in page 0 - outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA - - // Clear Remote DMA Flag - outb(Card->IOBase + ISR, 0x40); // Bit 6 - - // Send Size - Remote Byte Count Register - outb(Card->IOBase + TBCR0, Length & 0xFF); - outb(Card->IOBase + TBCR1, Length >> 8); - - // Send Size - Remote Byte Count Register - outb(Card->IOBase + RBCR0, Length & 0xFF); - outb(Card->IOBase + RBCR1, Length >> 8); - - // Set up transfer - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length)); // Page Offset - // Start - //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2); // Page 0, Transmit Packet, TXP, Start - outb(Card->IOBase + CMD, 0|0x10|0x2); // Page 0, Remote Write, Start - - // Send Data - for(rem = Length; rem; rem -= 2) - outw(Card->IOBase + 0x10, *buf++); - - while( inb(Card->IOBase + ISR) == 0 ) // Wait for Remote DMA Complete - ; //Proc_Yield(); - - outb( Card->IOBase + ISR, 0x40 ); // ACK Interrupt - - // Send Packet - outb(Card->IOBase + CMD, 0|0x10|0x4|0x2); - - // Complete DMA - //outb(Card->IOBase + CMD, 0|0x20); - - LEAVE('i', Length); - return Length; -} - -/** - * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) - * \brief Wait for and read a packet from the network card - */ -Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) -{ - tCard *Card = (tCard*)Node->ImplPtr; - Uint8 page; - Uint8 data[256]; - int i; - struct { - Uint8 Status; - Uint8 NextPacketPage; - Uint16 Length; // Little Endian - } *pktHdr; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - - while(Card->NumWaitingPackets == 0) Threads_Yield(); - - // Make sure that the card is in page 0 - outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA - - // Get BOUNDARY - page = Card->NextRXPage; - - // Set up transfer - outb(Card->IOBase + RBCR0, 0); - outb(Card->IOBase + RBCR1, 1); // 256-bytes - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, page); // Page Number - - outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start - - // Clear Remote DMA Flag - outb(Card->IOBase + ISR, 0x40); // Bit 6 - - // Read data - for(i = 0; i < 128; i ++) - ((Uint16*)data)[i] = inw(Card->IOBase + 0x10); - - pktHdr = (void*)data; - //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length); - - // Have we read all the required bytes yet? - if(pktHdr->Length < 256 - 4) - { - if(Length > pktHdr->Length) - Length = pktHdr->Length; - memcpy(Buffer, &data[4], Length); - page ++; - if(page == RX_LAST+1) page = RX_FIRST; - } - // No? oh damn, now we need to allocate a buffer - else { - int j = 256/2; - char *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 ); - - if(!buf) { - LEAVE('i', -1); - return -1; - } - - memcpy(buf, data, 256); - - page ++; - while(page != pktHdr->NextPacketPage) - { - if(page == RX_LAST+1) page = RX_FIRST; - - outb(Card->IOBase + RBCR0, 0); - outb(Card->IOBase + RBCR1, 1); // 256-bytes - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, page); // Page Number - outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start - - for(i = 0; i < 128; i ++) - ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10); - j += 128; - page ++; - } - - if(Length > pktHdr->Length) - Length = pktHdr->Length; - memcpy(Buffer, &buf[4], Length); - } - - // Write BNRY - if(page == RX_FIRST) - outb( Card->IOBase + BNRY, RX_LAST ); - else - outb( Card->IOBase + BNRY, page-1 ); - // Set next RX Page and decrement the waiting list - Card->NextRXPage = page; - Card->NumWaitingPackets --; - - LEAVE('i', Length); - return Length; -} - -/** - * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) - */ -Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) -{ - Uint8 ret = Card->NextMemPage; - - Card->NextMemPage += (Length + 0xFF) >> 8; - if(Card->NextMemPage >= TX_LAST) { - Card->NextMemPage -= TX_BUF_SIZE; - } - - return ret; -} - -/** - * \fn void Ne2k_IRQHandler(int IntNum) - */ -void Ne2k_IRQHandler(int IntNum) -{ - int i; - Uint8 byte; - for( i = 0; i < giNe2k_CardCount; i++ ) - { - if(gpNe2k_Cards[i].IRQ == IntNum) - { - byte = inb( gpNe2k_Cards[i].IOBase + ISR ); - - // 0: Packet recieved (no error) - if( byte & 1 ) - { - gpNe2k_Cards[i].NumWaitingPackets ++; - if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE ) - gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE; - } - // 1: Packet sent (no error) - // 2: Recieved with error - // 3: Transmission Halted (Excessive Collisions) - // 4: Recieve Buffer Exhausted - // 5: - // 6: Remote DMA Complete - // 7: Reset - //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte); - outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All - return ; - } - } - Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum); -} diff --git a/Modules/Network/Makefile.tpl b/Modules/Network/Makefile.tpl new file mode 100644 index 00000000..80c6d4dd --- /dev/null +++ b/Modules/Network/Makefile.tpl @@ -0,0 +1 @@ +-include ../../Makefile.tpl diff --git a/Modules/Network/NE2000/Makefile b/Modules/Network/NE2000/Makefile new file mode 100644 index 00000000..7e740227 --- /dev/null +++ b/Modules/Network/NE2000/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = ne2000.o +NAME = NE2000 + +-include ../Makefile.tpl diff --git a/Modules/Network/NE2000/ne2000.c b/Modules/Network/NE2000/ne2000.c new file mode 100644 index 00000000..76e4379f --- /dev/null +++ b/Modules/Network/NE2000/ne2000.c @@ -0,0 +1,502 @@ +/* Acess2 + * NE2000 Driver + * + * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc + */ +#define DEBUG 0 +#define VERSION ((0<<8)|50) +#include +#include +#include +#include +#include + +// === CONSTANTS === +#define MEM_START 0x40 +#define MEM_END 0xC0 +#define RX_FIRST (MEM_START) +#define RX_LAST (MEM_START+RX_BUF_SIZE-1) +#define RX_BUF_SIZE 0x40 +#define TX_FIRST (MEM_START+RX_BUF_SIZE) +#define TX_LAST (MEM_END) +#define TX_BUF_SIZE 0x40 +#define MAX_PACKET_QUEUE 10 + +static const struct { + Uint16 Vendor; + Uint16 Device; +} csaCOMPAT_DEVICES[] = { + {0x10EC, 0x8029}, // Realtek 8029 + {0x10EC, 0x8129} // Realtek 8129 +}; +#define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0])) + +enum eNe2k_Page0Read { + CMD = 0, //!< the master command register + CLDA0, //!< Current Local DMA Address 0 + CLDA1, //!< Current Local DMA Address 1 + BNRY, //!< Boundary Pointer (for ringbuffer) + TSR, //!< Transmit Status Register + NCR, //!< collisions counter + FIFO, //!< (for what purpose ??) + ISR, //!< Interrupt Status Register + CRDA0, //!< Current Remote DMA Address 0 + CRDA1, //!< Current Remote DMA Address 1 + RSR = 0xC //!< Receive Status Register +}; + +enum eNe2k_Page0Write { + PSTART = 1, //!< page start (init only) + PSTOP, //!< page stop (init only) + TPSR = 4, //!< transmit page start address + TBCR0, //!< transmit byte count (low) + TBCR1, //!< transmit byte count (high) + RSAR0 = 8, //!< remote start address (lo) + RSAR1, //!< remote start address (hi) + RBCR0, //!< remote byte count (lo) + RBCR1, //!< remote byte count (hi) + RCR, //!< receive config register + TCR, //!< transmit config register + DCR, //!< data config register (init) + IMR //!< interrupt mask register (init) +}; + +enum eNe2k_Page1Read { + CURR = 7 //!< current page +}; + +// === TYPES === +typedef struct sNe2k_Card { + Uint16 IOBase; //!< IO Port Address from PCI + Uint8 IRQ; //!< IRQ Assigned from PCI + + int NumWaitingPackets; + int NextRXPage; + + int NextMemPage; //!< Next Card Memory page to use + + Uint8 Buffer[RX_BUF_SIZE]; + + char Name[2]; // "0" + tVFS_Node Node; + Uint8 MacAddr[6]; +} tCard; + +// === PROTOTYPES === + int Ne2k_Install(char **Arguments); +char *Ne2k_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name); + int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data); +Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); +void Ne2k_IRQHandler(int IntNum); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL); +tDevFS_Driver gNe2k_DriverInfo = { + NULL, "ne2k", + { + .NumACLs = 1, + .ACLs = &gVFS_ACL_EveryoneRX, + .Flags = VFS_FFLAG_DIRECTORY, + .ReadDir = Ne2k_ReadDir, + .FindDir = Ne2k_FindDir, + .IOCtl = Ne2k_IOCtl + } +}; +Uint16 gNe2k_BaseAddress; + int giNe2k_CardCount = 0; +tCard *gpNe2k_Cards = NULL; + +// === CODE === +/** + * \fn int Ne2k_Install(char **Options) + * \brief Installs the NE2000 Driver + */ +int Ne2k_Install(char **Options) +{ + int i, j, k; + int count, id, base; + + // --- Scan PCI Bus --- + // Count Cards + giNe2k_CardCount = 0; + for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) + { + giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); + } + + // Enumerate Cards + k = 0; + gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) ); + + for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) + { + count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); + for( j = 0; j < count; j ++,k ++ ) + { + id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j ); + // Create Structure + base = PCI_AssignPort( id, 0, 0x20 ); + gpNe2k_Cards[ k ].IOBase = base; + gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id ); + gpNe2k_Cards[ k ].NextMemPage = 64; + gpNe2k_Cards[ k ].NextRXPage = RX_FIRST; + + // Install IRQ Handler + IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler); + + // Reset Card + outb( base + 0x1F, inb(base + 0x1F) ); + while( (inb( base+ISR ) & 0x80) == 0 ); + outb( base + ISR, 0x80 ); + + // Initialise Card + outb( base + CMD, 0x40|0x21 ); // Page 1, No DMA, Stop + outb( base + CURR, RX_FIRST ); // Current RX page + outb( base + CMD, 0x21 ); // No DMA and Stop + outb( base + DCR, 0x49 ); // Set WORD mode + outb( base + IMR, 0x00 ); + outb( base + ISR, 0xFF ); + outb( base + RCR, 0x20 ); // Reciever to Monitor + outb( base + TCR, 0x02 ); // Transmitter OFF (TCR.LB = 1, Internal Loopback) + outb( base + RBCR0, 6*4 ); // Remote Byte Count + outb( base + RBCR1, 0 ); + outb( base + RSAR0, 0 ); // Clear Source Address + outb( base + RSAR1, 0 ); + outb( base + CMD, 0x0A ); // Remote Read, Start + + // Read MAC Address + gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);// inb(base+0x10); + + outb( base+PSTART, RX_FIRST); // Set Receive Start + outb( base+BNRY, RX_LAST-1); // Set Boundary Page + outb( base+PSTOP, RX_LAST); // Set Stop Page + outb( base+ISR, 0xFF ); // Clear all ints + outb( base+CMD, 0x22 ); // No DMA, Start + outb( base+IMR, 0x3F ); // Set Interupt Mask + outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches + outb( base+TCR, 0x00 ); // Set Normal Transmitter mode + outb( base+TPSR, 0x40); // Set Transmit Start + // Set MAC Address + /* + Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]); + Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]); + Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]); + Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]); + Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]); + Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]); + */ + + Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x", + k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase); + Log("MAC Address %x:%x:%x:%x:%x:%x", + gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1], + gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3], + gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5] + ); + + // Set VFS Node + gpNe2k_Cards[ k ].Name[0] = '0'+k; + gpNe2k_Cards[ k ].Name[1] = '\0'; + gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ]; + gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only + gpNe2k_Cards[ k ].Node.CTime = now(); + gpNe2k_Cards[ k ].Node.Write = Ne2k_Write; + gpNe2k_Cards[ k ].Node.Read = Ne2k_Read; + gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl; + } + } + + gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount; + DevFS_AddDevice( &gNe2k_DriverInfo ); + return 1; +} + +/** + * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) + */ +char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) +{ + char ret[2]; + if(Pos < 0 || Pos >= giNe2k_CardCount) return NULL; + ret[0] = '0'+Pos; + ret[1] = '\0'; + return strdup(ret); +} + +/** + * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) + */ +tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) +{ + if(Name[0] == '\0' || Name[1] != '\0') return NULL; + + return &gpNe2k_Cards[ Name[0]-'0' ].Node; +} + +static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL }; +/** + * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) + * \brief IOCtl calls for a network device + */ +int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + int tmp; + ENTER("pNode iID pData", Node, ID, Data); + switch( ID ) + { + case DRV_IOCTL_TYPE: + LEAVE('i', DRV_TYPE_NETWORK); + return DRV_TYPE_NETWORK; + + case DRV_IOCTL_IDENT: + tmp = ModUtil_SetIdent(Data, "Ne2k"); + LEAVE('i', tmp); + return tmp; + + case DRV_IOCTL_VERSION: + LEAVE('x', VERSION); + return VERSION; + + case DRV_IOCTL_LOOKUP: + tmp = ModUtil_LookupString( (char**)casIOCtls, Data ); + LEAVE('i', tmp); + return tmp; + } + + // If this is the root, return + if( Node == &gNe2k_DriverInfo.RootNode ) { + LEAVE('i', 0); + return 0; + } + + // Device specific settings + switch( ID ) + { + case NET_IOCTL_GETMAC: + if( !CheckMem(Data, 6) ) { + LEAVE('i', -1); + return -1; + } + memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 ); + LEAVE('i', 1); + return 1; + } + LEAVE('i', 0); + return 0; +} + +/** + * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Send a packet from the network card + */ +Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tCard *Card = (tCard*)Node->ImplPtr; + Uint16 *buf = Buffer; + int rem = Length; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + // Sanity Check Length + if(Length > TX_BUF_SIZE) { + LEAVE('i', 0); + return 0; + } + + // Make sure that the card is in page 0 + outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA + + // Clear Remote DMA Flag + outb(Card->IOBase + ISR, 0x40); // Bit 6 + + // Send Size - Remote Byte Count Register + outb(Card->IOBase + TBCR0, Length & 0xFF); + outb(Card->IOBase + TBCR1, Length >> 8); + + // Send Size - Remote Byte Count Register + outb(Card->IOBase + RBCR0, Length & 0xFF); + outb(Card->IOBase + RBCR1, Length >> 8); + + // Set up transfer + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length)); // Page Offset + // Start + //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2); // Page 0, Transmit Packet, TXP, Start + outb(Card->IOBase + CMD, 0|0x10|0x2); // Page 0, Remote Write, Start + + // Send Data + for(rem = Length; rem; rem -= 2) + outw(Card->IOBase + 0x10, *buf++); + + while( inb(Card->IOBase + ISR) == 0 ) // Wait for Remote DMA Complete + ; //Proc_Yield(); + + outb( Card->IOBase + ISR, 0x40 ); // ACK Interrupt + + // Send Packet + outb(Card->IOBase + CMD, 0|0x10|0x4|0x2); + + // Complete DMA + //outb(Card->IOBase + CMD, 0|0x20); + + LEAVE('i', Length); + return Length; +} + +/** + * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Wait for and read a packet from the network card + */ +Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tCard *Card = (tCard*)Node->ImplPtr; + Uint8 page; + Uint8 data[256]; + int i; + struct { + Uint8 Status; + Uint8 NextPacketPage; + Uint16 Length; // Little Endian + } *pktHdr; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + while(Card->NumWaitingPackets == 0) Threads_Yield(); + + // Make sure that the card is in page 0 + outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA + + // Get BOUNDARY + page = Card->NextRXPage; + + // Set up transfer + outb(Card->IOBase + RBCR0, 0); + outb(Card->IOBase + RBCR1, 1); // 256-bytes + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, page); // Page Number + + outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start + + // Clear Remote DMA Flag + outb(Card->IOBase + ISR, 0x40); // Bit 6 + + // Read data + for(i = 0; i < 128; i ++) + ((Uint16*)data)[i] = inw(Card->IOBase + 0x10); + + pktHdr = (void*)data; + //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length); + + // Have we read all the required bytes yet? + if(pktHdr->Length < 256 - 4) + { + if(Length > pktHdr->Length) + Length = pktHdr->Length; + memcpy(Buffer, &data[4], Length); + page ++; + if(page == RX_LAST+1) page = RX_FIRST; + } + // No? oh damn, now we need to allocate a buffer + else { + int j = 256/2; + char *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 ); + + if(!buf) { + LEAVE('i', -1); + return -1; + } + + memcpy(buf, data, 256); + + page ++; + while(page != pktHdr->NextPacketPage) + { + if(page == RX_LAST+1) page = RX_FIRST; + + outb(Card->IOBase + RBCR0, 0); + outb(Card->IOBase + RBCR1, 1); // 256-bytes + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, page); // Page Number + outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start + + for(i = 0; i < 128; i ++) + ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10); + j += 128; + page ++; + } + + if(Length > pktHdr->Length) + Length = pktHdr->Length; + memcpy(Buffer, &buf[4], Length); + } + + // Write BNRY + if(page == RX_FIRST) + outb( Card->IOBase + BNRY, RX_LAST ); + else + outb( Card->IOBase + BNRY, page-1 ); + // Set next RX Page and decrement the waiting list + Card->NextRXPage = page; + Card->NumWaitingPackets --; + + LEAVE('i', Length); + return Length; +} + +/** + * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) + */ +Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) +{ + Uint8 ret = Card->NextMemPage; + + Card->NextMemPage += (Length + 0xFF) >> 8; + if(Card->NextMemPage >= TX_LAST) { + Card->NextMemPage -= TX_BUF_SIZE; + } + + return ret; +} + +/** + * \fn void Ne2k_IRQHandler(int IntNum) + */ +void Ne2k_IRQHandler(int IntNum) +{ + int i; + Uint8 byte; + for( i = 0; i < giNe2k_CardCount; i++ ) + { + if(gpNe2k_Cards[i].IRQ == IntNum) + { + byte = inb( gpNe2k_Cards[i].IOBase + ISR ); + + // 0: Packet recieved (no error) + if( byte & 1 ) + { + gpNe2k_Cards[i].NumWaitingPackets ++; + if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE ) + gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE; + } + // 1: Packet sent (no error) + // 2: Recieved with error + // 3: Transmission Halted (Excessive Collisions) + // 4: Recieve Buffer Exhausted + // 5: + // 6: Remote DMA Complete + // 7: Reset + //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte); + outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All + return ; + } + } + Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum); +} diff --git a/Modules/Storage/ATA/Makefile b/Modules/Storage/ATA/Makefile new file mode 100644 index 00000000..05e66af6 --- /dev/null +++ b/Modules/Storage/ATA/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o mbr.o +NAME = ATA + +-include ../Makefile.tpl diff --git a/Modules/Storage/ATA/common.h b/Modules/Storage/ATA/common.h new file mode 100644 index 00000000..18e62a8d --- /dev/null +++ b/Modules/Storage/ATA/common.h @@ -0,0 +1,77 @@ +/* + * Acess2 IDE Harddisk Driver + * - main.c + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include + +// === CONSTANTS === +#define MAX_ATA_DISKS 4 +#define SECTOR_SIZE 512 +#define MAX_DMA_SECTORS (0x1000 / SECTOR_SIZE) + +#define IDE_PRI_BASE 0x1F0 +#define IDE_SEC_BASE 0x170 + +#define IDE_PRDT_LAST 0x8000 +/** + \enum HddControls + \brief Commands to be sent to HDD_CMD +*/ +enum HddControls { + HDD_PIO_R28 = 0x20, + HDD_PIO_R48 = 0x24, + HDD_DMA_R48 = 0x25, + HDD_PIO_W28 = 0x30, + HDD_PIO_W48 = 0x34, + HDD_DMA_W48 = 0x35, + HDD_DMA_R28 = 0xC8, + HDD_DMA_W28 = 0xCA, +}; + +// === STRUCTURES === +typedef struct +{ + Uint8 BootCode[0x1BE]; + struct { + Uint8 Boot; + Uint8 Unused1; // Also CHS Start + Uint16 StartHi; // Also CHS Start + Uint8 SystemID; + Uint8 Unused2; // Also CHS Length + Uint16 LengthHi; // Also CHS Length + Uint32 LBAStart; + Uint32 LBALength; + } __attribute__ ((packed)) Parts[4]; + Uint16 BootFlag; // = 0xAA 55 +} __attribute__ ((packed)) tMBR; + +typedef struct +{ + Uint64 Start; + Uint64 Length; + char Name[4]; + tVFS_Node Node; +} tATA_Partition; + +typedef struct +{ + Uint64 Sectors; + char Name[2]; + tVFS_Node Node; + int NumPartitions; + tATA_Partition *Partitions; +} tATA_Disk; + +// === GLOBALS === +extern tATA_Disk gATA_Disks[]; + +// === FUNCTIONS === +extern void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); +extern int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); +extern int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); + +#endif diff --git a/Modules/Storage/ATA/main.c b/Modules/Storage/ATA/main.c new file mode 100644 index 00000000..41f08738 --- /dev/null +++ b/Modules/Storage/ATA/main.c @@ -0,0 +1,793 @@ +/* + * Acess2 IDE Harddisk Driver + * - main.c + */ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +// --- Flags --- +#define START_BEFORE_CMD 0 + +// === STRUCTURES === +typedef struct +{ + Uint32 PBufAddr; + Uint16 Bytes; + Uint16 Flags; +} __attribute__ ((packed)) tPRDT_Ent; +typedef struct +{ + Uint16 Flags; // 1 + Uint16 Usused1[9]; // 10 + char SerialNum[20]; // 20 + Uint16 Usused2[3]; // 23 + char FirmwareVer[8]; // 27 + char ModelNumber[40]; // 47 + Uint16 SectPerInt; // 48 - AND with 0xFF to get true value; + Uint16 Unused3; // 49 + Uint16 Capabilities[2]; // 51 + Uint16 Unused4[2]; // 53 + Uint16 ValidExtData; // 54 + Uint16 Unused5[5]; // 59 + Uint16 SizeOfRWMultiple; // 60 + Uint32 Sectors28; // 62 + Uint16 Unused6[100-62]; + Uint64 Sectors48; + Uint16 Unused7[256-104]; +} __attribute__ ((packed)) tIdentify; + +// === IMPORTS === +extern void ATA_ParseMBR(int Disk); + +// === PROTOTYPES === + int ATA_Install(); + int ATA_SetupIO(); +void ATA_SetupPartitions(); +void ATA_SetupVFS(); + int ATA_ScanDisk(int Disk); +void ATA_ParseGPT(int Disk); +void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); +Uint16 ATA_GetBasePort(int Disk); +// Filesystem Interface +char *ATA_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name); +Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data); +// Read/Write Interface/Quantiser +Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk); +Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk); +// Read/Write DMA + int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); + int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); +// IRQs +void ATA_IRQHandlerPri(int unused); +void ATA_IRQHandlerSec(int unused); +// Controller IO +Uint8 ATA_int_BusMasterReadByte(int Ofs); +void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value); +void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value); + +// === GLOBALS === +MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, NULL); +tDevFS_Driver gATA_DriverInfo = { + NULL, "ata", + { + .NumACLs = 1, + .Size = -1, + .Flags = VFS_FFLAG_DIRECTORY, + .ACLs = &gVFS_ACL_EveryoneRX, + .ReadDir = ATA_ReadDir, + .FindDir = ATA_FindDir + } +}; +tATA_Disk gATA_Disks[MAX_ATA_DISKS]; + int giATA_NumNodes; +tVFS_Node **gATA_Nodes; +Uint16 gATA_BusMasterBase = 0; +Uint8 *gATA_BusMasterBasePtr = 0; + int gATA_IRQPri = 14; + int gATA_IRQSec = 15; + int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller +Uint8 gATA_Buffers[2][4096] __attribute__ ((section(".padata"))); + int gaATA_IRQs[2] = {0}; +tPRDT_Ent gATA_PRDTs[2] = { + {0, 512, IDE_PRDT_LAST}, + {0, 512, IDE_PRDT_LAST} +}; + +// === CODE === +/** + * \fn int ATA_Install() + */ +int ATA_Install() +{ + int ret; + + ret = ATA_SetupIO(); + if(ret != 1) return ret; + + ATA_SetupPartitions(); + + ATA_SetupVFS(); + + if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 ) + return MODULE_INIT_FAILURE; + + return MODULE_INIT_SUCCESS; +} + +/** + * \fn int ATA_SetupIO() + * \brief Sets up the ATA controller's DMA mode + */ +int ATA_SetupIO() +{ + int ent; + tPAddr addr; + + ENTER(""); + + // Get IDE Controller's PCI Entry + ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1); + LOG("ent = %i", ent); + gATA_BusMasterBase = PCI_GetBAR4( ent ); + if( gATA_BusMasterBase == 0 ) { + Warning("It seems that there is no Bus Master Controller on this machine. Get one"); + LEAVE('i', MODULE_INIT_FAILURE); + return MODULE_INIT_FAILURE; + } + if( !(gATA_BusMasterBase & 1) ) + { + if( gATA_BusMasterBase < 0x100000 ) + gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase); + else + gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) ); + LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr); + } + else { + // Bit 0 is left set as a flag to other functions + LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1); + } + + IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri ); + IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec ); + + gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] ); + gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] ); + + LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr); + + addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] ); + LOG("addr = 0x%x", addr); + ATA_int_BusMasterWriteDWord(4, addr); + addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] ); + LOG("addr = 0x%x", addr); + ATA_int_BusMasterWriteDWord(12, addr); + + outb(IDE_PRI_BASE+1, 1); + outb(IDE_SEC_BASE+1, 1); + + LEAVE('i', MODULE_INIT_SUCCESS); + return MODULE_INIT_SUCCESS; +} + +/** + * \fn void ATA_SetupPartitions() + */ +void ATA_SetupPartitions() +{ + int i; + for( i = 0; i < MAX_ATA_DISKS; i ++ ) + { + if( !ATA_ScanDisk(i) ) { + gATA_Disks[i].Name[0] = '\0'; // Mark as unused + continue; + } + } +} + +/** + * \fn void ATA_SetupVFS() + * \brief Sets up the ATA drivers VFS information and registers with DevFS + */ +void ATA_SetupVFS() +{ + int i, j, k; + + // Count number of nodes needed + giATA_NumNodes = 0; + for( i = 0; i < MAX_ATA_DISKS; i++ ) + { + if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore + giATA_NumNodes ++; + giATA_NumNodes += gATA_Disks[i].NumPartitions; + } + + // Allocate Node space + gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) ); + + // Set nodes + k = 0; + for( i = 0; i < MAX_ATA_DISKS; i++ ) + { + if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore + gATA_Nodes[ k++ ] = &gATA_Disks[i].Node; + for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ ) + gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node; + } + + gATA_DriverInfo.RootNode.Size = giATA_NumNodes; +} + +/** + * \fn int ATA_ScanDisk(int Disk) + */ +int ATA_ScanDisk(int Disk) +{ + Uint16 buf[256]; + tIdentify *identify = (void*)buf; + tMBR *mbr = (void*)buf; + Uint16 base; + Uint8 val; + int i; + tVFS_Node *node; + + ENTER("iDisk", Disk); + + base = ATA_GetBasePort( Disk ); + + LOG("base = 0x%x", base); + + // Send Disk Selector + if(Disk == 1 || Disk == 3) + outb(base+6, 0xB0); + else + outb(base+6, 0xA0); + + // Send IDENTIFY + outb(base+7, 0xEC); + val = inb(base+7); // Read status + if(val == 0) { + LEAVE('i', 0); + return 0; // Disk does not exist + } + + // Poll until BSY clears and DRQ sets or ERR is set + while( ((val & 0x80) || !(val & 0x08)) && !(val & 1)) val = inb(base+7); + + if(val & 1) { + LEAVE('i', 0); + return 0; // Error occured, so return false + } + + // Read Data + for(i=0;i<256;i++) buf[i] = inw(base); + + // Populate Disk Structure + if(identify->Sectors48 != 0) + gATA_Disks[ Disk ].Sectors = identify->Sectors48; + else + gATA_Disks[ Disk ].Sectors = identify->Sectors28; + + + LOG("gATA_Disks[ Disk ].Sectors = 0x%x", gATA_Disks[ Disk ].Sectors); + + if( gATA_Disks[ Disk ].Sectors / (2048*1024) ) + Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk, + gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024)); + else if( gATA_Disks[ Disk ].Sectors / 2048 ) + Log("Disk %i: 0x%llx Sectors (%i MiB)", Disk, + gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2048); + else + Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk, + gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2); + + // Create Name + gATA_Disks[ Disk ].Name[0] = 'A'+Disk; + gATA_Disks[ Disk ].Name[1] = '\0'; + + // Get pointer to vfs node and populate it + node = &gATA_Disks[ Disk ].Node; + node->Size = gATA_Disks[Disk].Sectors * SECTOR_SIZE; + node->NumACLs = 0; // Means Superuser only can access it + node->Inode = (Disk << 8) | 0xFF; + node->ImplPtr = gATA_Disks[ Disk ].Name; + + node->ATime = node->MTime + = node->CTime = now(); + + node->Read = ATA_ReadFS; + node->Write = ATA_WriteFS; + node->IOCtl = ATA_IOCtl; + + + // --- Scan Partitions --- + LOG("Reading MBR"); + // Read Boot Sector + ATA_ReadDMA( Disk, 0, 1, mbr ); + + // Check for a GPT table + if(mbr->Parts[0].SystemID == 0xEE) + ATA_ParseGPT(Disk); + else // No? Just parse the MBR + ATA_ParseMBR(Disk); + + LEAVE('i', 0); + return 1; +} + +/** + * \fn void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length) + * \brief Fills a parition's information structure + */ +void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length) +{ + ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length); + Part->Start = Start; + Part->Length = Length; + Part->Name[0] = 'A'+Disk; + if(Num >= 10) { + Part->Name[1] = '1'+Num/10; + Part->Name[2] = '1'+Num%10; + Part->Name[3] = '\0'; + } else { + Part->Name[1] = '1'+Num; + Part->Name[2] = '\0'; + } + Part->Node.NumACLs = 0; // Only root can read/write raw block devices + Part->Node.Inode = (Disk << 8) | Num; + Part->Node.ImplPtr = Part->Name; + + Part->Node.Read = ATA_ReadFS; + Part->Node.Write = ATA_WriteFS; + Part->Node.IOCtl = ATA_IOCtl; + LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node); + LEAVE('-'); +} + +/** + * \fn void ATA_ParseGPT(int Disk) + * \brief Parses the GUID Partition Table + */ +void ATA_ParseGPT(int Disk) +{ + ///\todo Support GPT Disks + Warning("GPT Disks are currently unsupported"); +} + +/** + * \fn Uint16 ATA_GetPortBase(int Disk) + * \brief Returns the base port for a given disk + */ +Uint16 ATA_GetBasePort(int Disk) +{ + switch(Disk) + { + case 0: case 1: return IDE_PRI_BASE; + case 2: case 3: return IDE_SEC_BASE; + } + return 0; +} + +/** + * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos) + */ +char *ATA_ReadDir(tVFS_Node *Node, int Pos) +{ + if(Pos >= giATA_NumNodes || Pos < 0) return NULL; + return strdup( gATA_Nodes[Pos]->ImplPtr ); +} + +/** + * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) + */ +tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) +{ + int part; + // Check first character + if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS) + return NULL; + // Raw Disk + if(Name[1] == '\0') { + if( gATA_Disks[Name[0]-'A'].Sectors == 0 ) + return NULL; + return &gATA_Disks[Name[0]-'A'].Node; + } + + // Partitions + if(Name[1] < '0' || '9' < Name[1]) return NULL; + if(Name[2] == '\0') { // <= 9 + part = Name[1] - '0'; + part --; + return &gATA_Disks[Name[0]-'A'].Partitions[part].Node; + } + // > 9 + if('0' > Name[2] || '9' < Name[2]) return NULL; + if(Name[3] != '\0') return NULL; + + part = (Name[1] - '0') * 10; + part += Name[2] - '0'; + part --; + return &gATA_Disks[Name[0]-'A'].Partitions[part].Node; + +} + +/** + * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + */ +Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + int disk = Node->Inode >> 8; + int part = Node->Inode & 0xFF; + + // Raw Disk Access + if(part == 0xFF) + { + if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) + return 0; + if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE ) + Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset; + } + // Partition + else + { + if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) + return 0; + if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) + Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset; + Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE; + } + + //Log("ATA_ReadFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer); + return DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk); +} + +/** + * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + */ +Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + int disk = Node->Inode >> 8; + int part = Node->Inode & 0xFF; + + // Raw Disk Access + if(part == 0xFF) + { + if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) + return 0; + if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE ) + Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset; + } + // Partition + else + { + if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) + return 0; + if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) + Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset; + Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE; + } + + Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer); + Debug_HexDump("ATA_WriteFS", Buffer, Length); + return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk); +} + +/** + * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief IO Control Funtion + */ +int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_DISK; + } + return 0; +} + +// --- Disk Access --- +/** + * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) + */ +Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) +{ + int ret; + Uint offset; + Uint done = 0; + + // Pass straight on to ATA_ReadDMAPage if we can + if(Count <= MAX_DMA_SECTORS) + { + ret = ATA_ReadDMA(Disk, Address, Count, Buffer); + if(ret == 0) return 0; + return Count; + } + + // Else we will have to break up the transfer + offset = 0; + while(Count > MAX_DMA_SECTORS) + { + ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset); + // Check for errors + if(ret != 1) return done; + // Change Position + done += MAX_DMA_SECTORS; + Count -= MAX_DMA_SECTORS; + offset += MAX_DMA_SECTORS*SECTOR_SIZE; + } + + ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset); + if(ret != 1) return 0; + return done+Count; +} + +/** + * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) + */ +Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) +{ + int ret; + Uint offset; + Uint done = 0; + + // Pass straight on to ATA_WriteDMA if we can + if(Count <= MAX_DMA_SECTORS) + { + ret = ATA_WriteDMA(Disk, Address, Count, Buffer); + if(ret == 0) return 0; + return Count; + } + + // Else we will have to break up the transfer + offset = 0; + while(Count > MAX_DMA_SECTORS) + { + ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset); + // Check for errors + if(ret != 1) return done; + // Change Position + done += MAX_DMA_SECTORS; + Count -= MAX_DMA_SECTORS; + offset += MAX_DMA_SECTORS*SECTOR_SIZE; + } + + ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset); + if(ret != 1) return 0; + return done+Count; +} + +/** + * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) + */ +int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) +{ + int cont = (Disk>>1)&1; // Controller ID + int disk = Disk & 1; + Uint16 base; + + ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer); + + // Check if the count is small enough + if(Count > MAX_DMA_SECTORS) { + Warning("Passed too many sectors for a bulk DMA read (%i > %i)", + Count, MAX_DMA_SECTORS); + LEAVE('i'); + return 0; + } + + // Get exclusive access to the disk controller + LOCK( &giaATA_ControllerLock[ cont ] ); + + // Set Size + gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; + + // Get Port Base + base = ATA_GetBasePort(Disk); + + // Reset IRQ Flag + gaATA_IRQs[cont] = 0; + + // Set up transfer + outb(base+0x01, 0x00); + if( Address > 0x0FFFFFFF ) // Use LBA48 + { + outb(base+0x6, 0x40 | (disk << 4)); + outb(base+0x2, 0 >> 8); // Upper Sector Count + outb(base+0x3, Address >> 24); // Low 2 Addr + outb(base+0x3, Address >> 28); // Mid 2 Addr + outb(base+0x3, Address >> 32); // High 2 Addr + } + else + { + outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr + } + + outb(base+0x02, (Uint8) Count); // Sector Count + outb(base+0x03, (Uint8) Address); // Low Addr + outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr + outb(base+0x05, (Uint8) (Address >> 16)); // High Addr + + LOG("Starting Transfer"); + #if START_BEFORE_CMD + // Start transfer + ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start + if( Address > 0x0FFFFFFF ) + outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) + else + outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) + #else + if( Address > 0x0FFFFFFF ) + outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) + else + outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) + // Start transfer + ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start + #endif + + // Wait for transfer to complete + //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 ); + while( gaATA_IRQs[cont] == 0 ) { + //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 ); + //LOG("val = 0x%02x", val); + Threads_Yield(); + } + + // Complete Transfer + ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop + + LOG("Transfer Completed & Acknowledged"); + + // Copy to destination buffer + memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE ); + + // Release controller lock + RELEASE( &giaATA_ControllerLock[ cont ] ); + + LEAVE('i', 1); + return 1; +} + +/** + * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) + */ +int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) +{ + int cont = (Disk>>1)&1; // Controller ID + int disk = Disk & 1; + Uint16 base; + + // Check if the count is small enough + if(Count > MAX_DMA_SECTORS) return 0; + + // Get exclusive access to the disk controller + LOCK( &giaATA_ControllerLock[ cont ] ); + + // Set Size + gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; + + // Get Port Base + base = ATA_GetBasePort(Disk); + + // Set up transfer + outb(base+0x01, 0x00); + if( Address > 0x0FFFFFFF ) // Use LBA48 + { + outb(base+0x6, 0x40 | (disk << 4)); + outb(base+0x2, 0 >> 8); // Upper Sector Count + outb(base+0x3, Address >> 24); // Low 2 Addr + outb(base+0x3, Address >> 28); // Mid 2 Addr + outb(base+0x3, Address >> 32); // High 2 Addr + } + else + { + outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr + } + + outb(base+0x02, (Uint8) Count); // Sector Count + outb(base+0x03, (Uint8) Address); // Low Addr + outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr + outb(base+0x05, (Uint8) (Address >> 16)); // High Addr + if( Address > 0x0FFFFFFF ) + outb(base+0x07, HDD_DMA_W48); // Write Command (LBA48) + else + outb(base+0x07, HDD_DMA_W28); // Write Command (LBA28) + + // Reset IRQ Flag + gaATA_IRQs[cont] = 0; + + // Copy to output buffer + memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE ); + + // Start transfer + ATA_int_BusMasterWriteByte( cont << 3, 1 ); // Write and start + + // Wait for transfer to complete + while( gaATA_IRQs[cont] == 0 ) Threads_Yield(); + + // Complete Transfer + ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop + + // Release controller lock + RELEASE( &giaATA_ControllerLock[ cont ] ); + + return 1; +} + +/** + * \fn void ATA_IRQHandlerPri(int unused) + */ +void ATA_IRQHandlerPri(int unused) +{ + Uint8 val; + + // IRQ bit set for Primary Controller + val = ATA_int_BusMasterReadByte( 0x2 ); + LOG("IRQ val = 0x%x", val); + if(val & 4) { + LOG("IRQ hit (val = 0x%x)", val); + ATA_int_BusMasterWriteByte( 0x2, 4 ); + gaATA_IRQs[0] = 1; + return ; + } +} + +/** + * \fn void ATA_IRQHandlerSec(int unused) + */ +void ATA_IRQHandlerSec(int unused) +{ + Uint8 val; + // IRQ bit set for Secondary Controller + val = ATA_int_BusMasterReadByte( 0xA ); + if(val & 4) { + LOG("IRQ hit (val = 0x%x)", val); + ATA_int_BusMasterWriteByte( 0xA, 4 ); + gaATA_IRQs[1] = 1; + return ; + } +} + +/** + * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs) + */ +Uint8 ATA_int_BusMasterReadByte(int Ofs) +{ + if( gATA_BusMasterBase & 1 ) + return inb( (gATA_BusMasterBase & ~1) + Ofs ); + else + return *(Uint8*)(gATA_BusMasterBasePtr + Ofs); +} + +/** + * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) + * \brief Writes a byte to a Bus Master Register + */ +void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) +{ + if( gATA_BusMasterBase & 1 ) + outb( (gATA_BusMasterBase & ~1) + Ofs, Value ); + else + *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value; +} + +/** + * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) + * \brief Writes a dword to a Bus Master Register + */ +void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) +{ + + if( gATA_BusMasterBase & 1 ) + outd( (gATA_BusMasterBase & ~1) + Ofs, Value ); + else + *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value; +} diff --git a/Modules/Storage/ATA/mbr.c b/Modules/Storage/ATA/mbr.c new file mode 100644 index 00000000..45ade88a --- /dev/null +++ b/Modules/Storage/ATA/mbr.c @@ -0,0 +1,182 @@ +/* + * Acess2 IDE Harddisk Driver + * - MBR Parsing Code + * mbr.c + */ +#define DEBUG 0 +#include +#include "common.h" + +// === PROTOTYPES === +Uint64 ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length); + +// === GLOBALS === + +// === CODE === +/** + * \fn void ATA_ParseMBR(int Disk) + */ +void ATA_ParseMBR(int Disk) +{ + int i, j = 0, k = 4; + tMBR mbr; + Uint64 extendedLBA; + Uint64 base, len; + + ENTER("iDisk", Disk); + + // Read Boot Sector + ATA_ReadDMA( Disk, 0, 1, &mbr ); + + // Count Partitions + gATA_Disks[Disk].NumPartitions = 0; + extendedLBA = 0; + for( i = 0; i < 4; i ++ ) + { + if( mbr.Parts[i].SystemID == 0 ) continue; + if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 // LBA 28 + || mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 // LBA 48 + ) + { + if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) { + LOG("Extended Partition"); + if(extendedLBA != 0) { + Warning("Disk %i has multiple extended partitions, ignoring rest", Disk); + continue; + } + extendedLBA = mbr.Parts[i].LBAStart; + continue; + } + LOG("Primary Partition"); + + gATA_Disks[Disk].NumPartitions ++; + continue; + } + // Invalid Partition, so don't count it + } + while(extendedLBA != 0) + { + extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len); + if( extendedLBA == -1 ) return ; + gATA_Disks[Disk].NumPartitions ++; + } + LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions); + + // Create patition array + gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) ); + + // --- Fill Partition Info --- + extendedLBA = 0; + for( j = 0, i = 0; i < 4; i ++ ) + { + Log("mbr.Parts[%i].SystemID = 0x%02x", i, mbr.Parts[i].SystemID); + if( mbr.Parts[i].SystemID == 0 ) continue; + if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28 + { + base = mbr.Parts[i].LBAStart; + len = mbr.Parts[i].LBALength; + } + else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) // LBA 58 + { + base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart; + len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength; + } + else + continue; + + if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) { + if(extendedLBA != 0) { + Warning("Disk %i has multiple extended partitions, ignoring rest", Disk); + continue; + } + extendedLBA = base; + continue; + } + // Create Partition + ATA_int_MakePartition( + &gATA_Disks[Disk].Partitions[j], Disk, j, + base, len + ); + j ++; + + } + // Scan extended partitions + while(extendedLBA != 0) + { + extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len); + ATA_int_MakePartition( + &gATA_Disks[Disk].Partitions[j], Disk, k, base, len + ); + } + + LEAVE('-'); +} + +/** + * \brief Reads an extended partition + * \return LBA of next Extended, -1 on error, 0 for last + */ +Uint64 ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length) +{ + Uint64 link = 0; + int bFoundPart = 0;; + int i; + tMBR mbr; + Uint64 base, len; + + if( ATA_ReadDMA( Disk, Addr, 1, &mbr ) != 0 ) + return -1; // Stop on Errors + + + for( i = 0; i < 4; i ++ ) + { + if( mbr.Parts[i].SystemID == 0 ) continue; + + // LBA 24 + if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) { + base = mbr.Parts[i].LBAStart; + len = mbr.Parts[i].LBALength; + } + // LBA 48 + else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) { + base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart; + len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength; + } + else { + Warning("Unknown partition type, Disk %i 0x%llx Part %i", + Disk, Addr, i); + return -1; + } + + switch(mbr.Parts[i].SystemID) + { + case 0xF: + case 0x5: + if(link != 0) { + Warning("Disk %i has two forward links in the extended partition", + Disk); + return -1; + } + link = base; + break; + default: + if(bFoundPart) { + Warning("Disk %i has more than one partition in the extended partition at 0x%llx", + Disk, Addr); + return -1; + } + bFoundPart = 1; + *Base = base; + *Length = len; + break; + } + } + + if(!bFoundPart) { + Warning("No partition in extended partiton, Disk %i 0x%llx", + Disk, Addr); + return -1; + } + + return link; +} diff --git a/Modules/Storage/FDD/Makefile b/Modules/Storage/FDD/Makefile new file mode 100644 index 00000000..15965531 --- /dev/null +++ b/Modules/Storage/FDD/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = fdd.o +NAME = FDD + +-include ../Makefile.tpl diff --git a/Modules/Storage/FDD/fdd.c b/Modules/Storage/FDD/fdd.c new file mode 100644 index 00000000..6b55f17b --- /dev/null +++ b/Modules/Storage/FDD/fdd.c @@ -0,0 +1,849 @@ +/* + * AcessOS 0.1 + * Floppy Disk Access Code + */ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include + +#define WARN 0 + +// === CONSTANTS === +// --- Current Version +#define FDD_VERSION ((0<<8)|(75)) + +// --- Options +#define USE_CACHE 0 // Use Sector Cache +#define CACHE_SIZE 32 // Number of cachable sectors +#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation +#define MOTOR_ON_DELAY 500 // Miliseconds +#define MOTOR_OFF_DELAY 2000 // Miliseconds + +// === TYPEDEFS === +/** + * \brief Representation of a floppy drive + */ +typedef struct { + int type; + volatile int motorState; //2 - On, 1 - Spinup, 0 - Off + int track[2]; + int timer; + tVFS_Node Node; + #if !USE_CACHE + tIOCache *CacheHandle; + #endif +} t_floppyDevice; + +/** + * \brief Cached Sector + */ +typedef struct { + Uint64 timestamp; + Uint16 disk; + Uint16 sector; // Allows 32Mb of addressable space (Plenty for FDD) + Uint8 data[512]; +} t_floppySector; + +// === CONSTANTS === +static const char *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" }; +static const int cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 }; +static const short cPORTBASE[] = { 0x3F0, 0x370 }; + +enum FloppyPorts { + PORT_STATUSA = 0x0, + PORT_STATUSB = 0x1, + PORT_DIGOUTPUT = 0x2, + PORT_MAINSTATUS = 0x4, + PORT_DATARATE = 0x4, + PORT_DATA = 0x5, + PORT_DIGINPUT = 0x7, + PORT_CONFIGCTRL = 0x7 +}; + +enum FloppyCommands { + FIX_DRIVE_DATA = 0x03, + HECK_DRIVE_STATUS = 0x04, + CALIBRATE_DRIVE = 0x07, + CHECK_INTERRUPT_STATUS = 0x08, + SEEK_TRACK = 0x0F, + READ_SECTOR_ID = 0x4A, + FORMAT_TRACK = 0x4D, + READ_TRACK = 0x42, + READ_SECTOR = 0x66, + WRITE_SECTOR = 0xC5, + WRITE_DELETE_SECTOR = 0xC9, + READ_DELETE_SECTOR = 0xCC, +}; + +// === PROTOTYPES === +// --- Filesystem + int FDD_Install(char **Arguments); +char *FDD_ReadDir(tVFS_Node *Node, int pos); +tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name); + int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data); +Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); +// --- 1st Level Disk Access +Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk); +// --- Raw Disk Access + int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer); + int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer); +// --- Helpers +void FDD_IRQHandler(int Num); +void FDD_WaitIRQ(); +void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl); +inline void FDD_AquireSpinlock(); +inline void FDD_FreeSpinlock(); +#if USE_CACHE +inline void FDD_AquireCacheSpinlock(); +inline void FDD_FreeCacheSpinlock(); +#endif +void FDD_int_SendByte(int base, char byte); + int FDD_int_GetByte(int base); +void FDD_Reset(int id); +void FDD_Recalibrate(int disk); + int FDD_int_SeekTrack(int disk, int head, int track); +void FDD_int_TimerCallback(int arg); +void FDD_int_StopMotor(int disk); +void FDD_int_StartMotor(int disk); + int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt); + +// === GLOBALS === +MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL); +t_floppyDevice gFDD_Devices[2]; +volatile int fdd_inUse = 0; +volatile int fdd_irq6 = 0; +tDevFS_Driver gFDD_DriverInfo = { + NULL, "fdd", + { + .Size = -1, + .NumACLs = 1, + .ACLs = &gVFS_ACL_EveryoneRX, + .Flags = VFS_FFLAG_DIRECTORY, + .ReadDir = FDD_ReadDir, + .FindDir = FDD_FindDir, + .IOCtl = FDD_IOCtl + } +}; +#if USE_CACHE +int siFDD_CacheInUse = 0; +int siFDD_SectorCacheSize = CACHE_SIZE; +t_floppySector sFDD_SectorCache[CACHE_SIZE]; +#endif + +// === CODE === +/** + * \fn int FDD_Install(char **Arguments) + * \brief Installs floppy driver + */ +int FDD_Install(char **Arguments) +{ + Uint8 data; + + // Determine Floppy Types (From CMOS) + outb(0x70, 0x10); + data = inb(0x71); + gFDD_Devices[0].type = data >> 4; + gFDD_Devices[1].type = data & 0xF; + gFDD_Devices[0].track[0] = -1; + gFDD_Devices[1].track[1] = -1; + + Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]); + + // Clear FDD IRQ Flag + FDD_SensInt(0x3F0, NULL, NULL); + // Install IRQ6 Handler + IRQ_AddHandler(6, FDD_IRQHandler); + // Reset Primary FDD Controller + FDD_Reset(0); + + // Initialise Root Node + gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime + = gFDD_DriverInfo.RootNode.ATime = now(); + + // Initialise Child Nodes + gFDD_Devices[0].Node.Inode = 0; + gFDD_Devices[0].Node.Flags = 0; + gFDD_Devices[0].Node.NumACLs = 0; + gFDD_Devices[0].Node.Read = FDD_ReadFS; + gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS; + memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node)); + + gFDD_Devices[1].Node.Inode = 1; + + // Set Lengths + gFDD_Devices[0].Node.Size = cFDD_SIZES[data >> 4]; + gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF]; + + // Create Sector Cache + #if USE_CACHE + //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE); + //siFDD_SectorCacheSize = CACHE_SIZE; + #else + if( cFDD_SIZES[data >> 4] ) { + gFDD_Devices[0].CacheHandle = IOCache_Create( + FDD_WriteSector, 0, 512, + gFDD_Devices[0].Node.Size / (512*4) + ); // Cache is 1/4 the size of the disk + } + if( cFDD_SIZES[data & 15] ) { + gFDD_Devices[1].CacheHandle = IOCache_Create( + FDD_WriteSector, 0, 512, + gFDD_Devices[1].Node.Size / (512*4) + ); // Cache is 1/4 the size of the disk + } + #endif + + // Register with devfs + DevFS_AddDevice(&gFDD_DriverInfo); + + return 1; +} + +/** + * \fn char *FDD_ReadDir(tVFS_Node *Node, int pos) + * \brief Read Directory + */ +char *FDD_ReadDir(tVFS_Node *Node, int pos) +{ + char name[2] = "0\0"; + //Update Accessed Time + //gFDD_DrvInfo.rootNode.atime = now(); + + //Check for bounds + if(pos >= 2 || pos < 0) + return NULL; + + if(gFDD_Devices[pos].type == 0) + return VFS_SKIP; + + name[0] += pos; + + //Return + return strdup(name); +} + +/** + * \fn tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename); + * \brief Find File Routine (for vfs_node) + */ +tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *Filename) +{ + int i; + + ENTER("sFilename", Filename); + + // Sanity check string + if(Filename == NULL) { + LEAVE('n'); + return NULL; + } + + // Check string length (should be 1) + if(Filename[0] == '\0' || Filename[1] != '\0') { + LEAVE('n'); + return NULL; + } + + // Get First character + i = Filename[0] - '0'; + + // Check for 1st disk and if it is present return + if(i == 0 && gFDD_Devices[0].type != 0) { + LEAVE('p', &gFDD_Devices[0].Node); + return &gFDD_Devices[0].Node; + } + + // Check for 2nd disk and if it is present return + if(i == 1 && gFDD_Devices[1].type != 0) { + LEAVE('p', &gFDD_Devices[1].Node); + return &gFDD_Devices[1].Node; + } + + // Else return null + LEAVE('n'); + return NULL; +} + +static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL}; +/** + * \fn int FDD_IOCtl(tVFS_Node *Node, int id, void *data) + * \brief Stub ioctl function + */ +int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + switch(ID) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_DISK; + case DRV_IOCTL_IDENT: return ModUtil_SetIdent(Data, "FDD"); + case DRV_IOCTL_VERSION: return FDD_VERSION; + case DRV_IOCTL_LOOKUP: return ModUtil_LookupString((char**)casIOCTLS, Data); + + case DISK_IOCTL_GETBLOCKSIZE: return 512; + + default: + return 0; + } +} + +/** + * \fn Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read Data from a disk +*/ +Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + int i = 0; + int disk; + //Uint32 buf[128]; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + if(Node == NULL) { + LEAVE('i', -1); + return -1; + } + + if(Node->Inode != 0 && Node->Inode != 1) { + LEAVE('i', -1); + return -1; + } + + disk = Node->Inode; + + // Update Accessed Time + Node->ATime = now(); + + #if 0 + if((Offset & 0x1FF) || (Length & 0x1FF)) + { + // Un-Aligned Offset/Length + int startOff = Offset >> 9; + int sectOff = Offset & 0x1FF; + int sectors = (Length + 0x1FF) >> 9; + + LOG("Non-aligned Read"); + + //Read Starting Sector + if(!FDD_ReadSector(disk, startOff, buf)) + return 0; + memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length); + + // If the data size is one sector or less + if(Length <= 512-sectOff) + { + LEAVE('X', Length); + return Length; //Return + } + Buffer += 512-sectOff; + + //Read Middle Sectors + for( i = 1; i < sectors - 1; i++ ) + { + if(!FDD_ReadSector(disk, startOff+i, buf)) { + LEAVE('i', -1); + return -1; + } + memcpy(Buffer, buf, 512); + Buffer += 512; + } + + //Read End Sectors + if(!FDD_ReadSector(disk, startOff+i, buf)) + return 0; + memcpy(Buffer, buf, (len&0x1FF)-sectOff); + + LEAVE('X', Length); + return Length; + } + else + { + int count = Length >> 9; + int sector = Offset >> 9; + LOG("Aligned Read"); + //Aligned Offset and Length - Simple Code + for( i = 0; i < count; i ++ ) + { + FDD_ReadSector(disk, sector, buf); + memcpy(buffer, buf, 512); + buffer += 512; + sector++; + } + LEAVE('i', Length); + return Length; + } + #endif + + i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk); + LEAVE('i', i); + return i; +} + +/** + * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk) + * \brief Reads \a Count contiguous sectors from a disk + * \param SectorAddr Address of the first sector + * \param Count Number of sectors to read + * \param Buffer Destination Buffer + * \param Disk Disk Number + * \return Number of sectors read + * \note Used as a ::DrvUtil_ReadBlock helper + */ +Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk) +{ + Uint ret = 0; + while(Count --) + { + if( FDD_ReadSector(Disk, SectorAddr, Buffer) != 1 ) + return ret; + + Buffer = (void*)( (tVAddr)Buffer + 512 ); + SectorAddr ++; + ret ++; + } + return ret; +} + +/** + * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) + * \fn Read a sector from disk +*/ +int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) +{ + int cyl, head, sec; + int spt, base; + int i; + int lba = SectorAddr; + + ENTER("idisk Xlba pbuf", disk, lba, buf); + + #if USE_CACHE + FDD_AquireCacheSpinlock(); + for( i = 0; i < siFDD_SectorCacheSize; i++ ) + { + if(sFDD_SectorCache[i].timestamp == 0) continue; + if(sFDD_SectorCache[i].disk == Disk + && sFDD_SectorCache[i].sector == lba) { + LOG("Found %i in cache %i", lba, i); + memcpy(Buffer, sFDD_SectorCache[i].data, 512); + sFDD_SectorCache[i].timestamp = now(); + FDD_FreeCacheSpinlock(); + LEAVE('i', 1); + return 1; + } + } + LOG("Read %i from Disk", lba); + FDD_FreeCacheSpinlock(); + #else + if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) { + LEAVE('i', 1); + return 1; + } + #endif + + base = cPORTBASE[Disk>>1]; + + LOG("Calculating Disk Dimensions"); + // Get CHS position + if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) { + LEAVE('i', -1); + return -1; + } + + // Remove Old Timer + Time_RemoveTimer(gFDD_Devices[Disk].timer); + // Check if Motor is on + if(gFDD_Devices[Disk].motorState == 0) { + FDD_int_StartMotor(Disk); + } + + LOG("Wait for Motor Spinup"); + + // Wait for spinup + while(gFDD_Devices[Disk].motorState == 1) Threads_Yield(); + + LOG("C:%i,H:%i,S:%i", cyl, head, sec); + LOG("Acquire Spinlock"); + + FDD_AquireSpinlock(); + + // Seek to track + outb(base+CALIBRATE_DRIVE, 0); + i = 0; + while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield(); + //FDD_SensInt(base, NULL, NULL); // Wait for IRQ + + LOG("Setting DMA for read"); + + //Read Data from DMA + DMA_SetChannel(2, 512, 1); // Read 512 Bytes + + LOG("Sending read command"); + + //Threads_Wait(100); // Wait for Head to settle + Time_Delay(100); + FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6 + FDD_int_SendByte(base, (head << 2) | (Disk&1)); + FDD_int_SendByte(base, (Uint8)cyl); + FDD_int_SendByte(base, (Uint8)head); + FDD_int_SendByte(base, (Uint8)sec); + FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val}) + FDD_int_SendByte(base, spt); // SPT + FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default) + FDD_int_SendByte(base, 0xFF); // Data Length + + // Wait for IRQ + LOG("Waiting for Data to be read"); + FDD_WaitIRQ(); + + // Read Data from DMA + LOG(" FDD_ReadSector: Reading Data"); + DMA_ReadData(2, 512, Buffer); + + // Clear Input Buffer + LOG("Clearing Input Buffer"); + FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); + FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); + + LOG("Realeasing Spinlock and Setting motor to stop"); + // Release Spinlock + FDD_FreeSpinlock(); + + //Set timer to turn off motor affter a gap + gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer + + #if USE_CACHE + { + FDD_AquireCacheSpinlock(); + int oldest = 0; + for(i=0;i>1]; + + // Check if seeking is needed + if(gFDD_Devices[disk].track[head] == track) + return 1; + + // - Seek Head 0 + FDD_int_SendByte(base, SEEK_TRACK); + FDD_int_SendByte(base, (head<<2)|(disk&1)); + FDD_int_SendByte(base, track); // Send Seek command + FDD_WaitIRQ(); + FDD_SensInt(base, &sr0, &cyl); // Wait for IRQ + if((sr0 & 0xF0) != 0x20) { + LOG("sr0 = 0x%x", sr0); + return 0; //Check Status + } + if(cyl != track) return 0; + + // Set Track in structure + gFDD_Devices[disk].track[head] = track; + return 1; +} + +/** + * \fn int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt) + * \brief Get Dimensions of a disk + */ +int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt) +{ + switch(type) { + case 0: + return 0; + + // 360Kb 5.25" + case 1: + *spt = 9; + *s = (lba % 9) + 1; + *c = lba / 18; + *h = (lba / 9) & 1; + break; + + // 1220Kb 5.25" + case 2: + *spt = 15; + *s = (lba % 15) + 1; + *c = lba / 30; + *h = (lba / 15) & 1; + break; + + // 720Kb 3.5" + case 3: + *spt = 9; + *s = (lba % 9) + 1; + *c = lba / 18; + *h = (lba / 9) & 1; + break; + + // 1440Kb 3.5" + case 4: + *spt = 18; + *s = (lba % 18) + 1; + *c = lba / 36; + *h = (lba / 18) & 1; + //Log("1440k - lba=%i(0x%x), *s=%i,*c=%i,*h=%i", lba, lba, *s, *c, *h); + break; + + // 2880Kb 3.5" + case 5: + *spt = 36; + *s = (lba % 36) + 1; + *c = lba / 72; + *h = (lba / 32) & 1; + break; + + default: + return -2; + } + return 1; +} + +/** + * \fn void FDD_IRQHandler(int Num) + * \brief Handles IRQ6 + */ +void FDD_IRQHandler(int Num) +{ + fdd_irq6 = 1; +} + +/** + * \fn FDD_WaitIRQ() + * \brief Wait for an IRQ6 + */ +void FDD_WaitIRQ() +{ + // Wait for IRQ + while(!fdd_irq6) Threads_Yield(); + fdd_irq6 = 0; +} + +void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl) +{ + FDD_int_SendByte(base, CHECK_INTERRUPT_STATUS); + if(sr0) *sr0 = FDD_int_GetByte(base); + else FDD_int_GetByte(base); + if(cyl) *cyl = FDD_int_GetByte(base); + else FDD_int_GetByte(base); +} + +void FDD_AquireSpinlock() +{ + while(fdd_inUse) + Threads_Yield(); + fdd_inUse = 1; +} + +inline void FDD_FreeSpinlock() +{ + fdd_inUse = 0; +} + +#if USE_CACHE +inline void FDD_AquireCacheSpinlock() +{ + while(siFDD_CacheInUse) Threads_Yield(); + siFDD_CacheInUse = 1; +} +inline void FDD_FreeCacheSpinlock() +{ + siFDD_CacheInUse = 0; +} +#endif + +/** + * void FDD_int_SendByte(int base, char byte) + * \brief Sends a command to the controller + */ +void FDD_int_SendByte(int base, char byte) +{ + volatile int state; + int timeout = 128; + for( ; timeout--; ) + { + state = inb(base + PORT_MAINSTATUS); + if ((state & 0xC0) == 0x80) + { + outb(base + PORT_DATA, byte); + return; + } + inb(0x80); //Delay + } + #if WARN + Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base); + #endif +} + +/** + * int FDD_int_GetByte(int base, char byte) + * \brief Receive data from fdd controller + */ +int FDD_int_GetByte(int base) +{ + volatile int state; + int timeout; + for( timeout = 128; timeout--; ) + { + state = inb((base + PORT_MAINSTATUS)); + if ((state & 0xd0) == 0xd0) + return inb(base + PORT_DATA); + inb(0x80); + } + return -1; +} + +/** + * \brief Recalibrate the specified disk + */ +void FDD_Recalibrate(int disk) +{ + ENTER("idisk", disk); + + LOG("Starting Motor"); + FDD_int_StartMotor(disk); + // Wait for Spinup + while(gFDD_Devices[disk].motorState == 1) Threads_Yield(); + + LOG("Sending Calibrate Command"); + FDD_int_SendByte(cPORTBASE[disk>>1], CALIBRATE_DRIVE); + FDD_int_SendByte(cPORTBASE[disk>>1], disk&1); + + LOG("Waiting for IRQ"); + FDD_WaitIRQ(); + FDD_SensInt(cPORTBASE[disk>>1], NULL, NULL); + + LOG("Stopping Motor"); + FDD_int_StopMotor(disk); + LEAVE('-'); +} + +/** + * \brief Reset the specified FDD controller + */ +void FDD_Reset(int id) +{ + int base = cPORTBASE[id]; + + ENTER("iID", id); + + outb(base + PORT_DIGOUTPUT, 0); // Stop Motors & Disable FDC + outb(base + PORT_DIGOUTPUT, 0x0C); // Re-enable FDC (DMA and Enable) + + LOG("Awaiting IRQ"); + + FDD_WaitIRQ(); + FDD_SensInt(base, NULL, NULL); + + LOG("Setting Driver Info"); + outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s + FDD_int_SendByte(base, FIX_DRIVE_DATA); // Step and Head Load Times + FDD_int_SendByte(base, 0xDF); // Step Rate Time, Head Unload Time (Nibble each) + FDD_int_SendByte(base, 0x02); // Head Load Time >> 1 + while(FDD_int_SeekTrack(0, 0, 1) == 0); // set track + while(FDD_int_SeekTrack(0, 1, 1) == 0); // set track + + LOG("Recalibrating Disk"); + FDD_Recalibrate((id<<1)|0); + FDD_Recalibrate((id<<1)|1); + + LEAVE('-'); +} + +/** + * \fn void FDD_int_TimerCallback() + * \brief Called by timer + */ +void FDD_int_TimerCallback(int arg) +{ + ENTER("iarg", arg); + if(gFDD_Devices[arg].motorState == 1) + gFDD_Devices[arg].motorState = 2; + Time_RemoveTimer(gFDD_Devices[arg].timer); + gFDD_Devices[arg].timer = -1; + LEAVE('-'); +} + +/** + * \fn void FDD_int_StartMotor(char disk) + * \brief Starts FDD Motor + */ +void FDD_int_StartMotor(int disk) +{ + Uint8 state; + state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT ); + state |= 1 << (4+disk); + outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state ); + gFDD_Devices[disk].motorState = 1; + gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk); +} + +/** + * \fn void FDD_int_StopMotor(int disk) + * \brief Stops FDD Motor + */ +void FDD_int_StopMotor(int disk) +{ + Uint8 state; + state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT ); + state &= ~( 1 << (4+disk) ); + outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state ); + gFDD_Devices[disk].motorState = 0; +} + +/** + * \fn void ModuleUnload() + * \brief Prepare the module for removal + */ +void ModuleUnload() +{ + int i; + FDD_AquireSpinlock(); + for(i=0;i<4;i++) { + Time_RemoveTimer(gFDD_Devices[i].timer); + FDD_int_StopMotor(i); + } + //IRQ_Clear(6); +} diff --git a/Modules/Storage/Makefile.tpl b/Modules/Storage/Makefile.tpl new file mode 100644 index 00000000..80c6d4dd --- /dev/null +++ b/Modules/Storage/Makefile.tpl @@ -0,0 +1 @@ +-include ../../Makefile.tpl diff --git a/Modules/UDI/Makefile b/Modules/UDI/Makefile deleted file mode 100644 index 4c199f18..00000000 --- a/Modules/UDI/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# - -CPPFLAGS = -I./include -OBJ = main.o logging.o strmem.o imc.o mem.o buf.o cb.o -OBJ += meta_mgmt.o meta_gio.o -OBJ += physio.o physio/meta_bus.o physio/meta_intr.o -NAME = UDI - --include ../Makefile.tpl diff --git a/Modules/UDI/buf.c b/Modules/UDI/buf.c deleted file mode 100644 index 3255911d..00000000 --- a/Modules/UDI/buf.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * \file buf.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_buf_copy); -EXPORT(udi_buf_write); -EXPORT(udi_buf_read); -EXPORT(udi_buf_free); - -// === CODE === -void udi_buf_copy( - udi_buf_copy_call_t *callback, - udi_cb_t *gcb, - udi_buf_t *src_buf, - udi_size_t src_off, - udi_size_t src_len, - udi_buf_t *dst_buf, - udi_size_t dst_off, - udi_size_t dst_len, - udi_buf_path_t path_handle - ) -{ - UNIMPLEMENTED(); -} - -void udi_buf_write( - udi_buf_write_call_t *callback, - udi_cb_t *gcb, - const void *src_mem, - udi_size_t src_len, - udi_buf_t *dst_buf, - udi_size_t dst_off, - udi_size_t dst_len, - udi_buf_path_t path_handle - ) -{ - UNIMPLEMENTED(); -} - -void udi_buf_read( - udi_buf_t *src_buf, - udi_size_t src_off, - udi_size_t src_len, - void *dst_mem ) -{ - UNIMPLEMENTED(); -} - -void udi_buf_free(udi_buf_t *buf) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/cb.c b/Modules/UDI/cb.c deleted file mode 100644 index 78be97bd..00000000 --- a/Modules/UDI/cb.c +++ /dev/null @@ -1,59 +0,0 @@ -/** - * \file cb.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_cb_alloc); -EXPORT(udi_cb_alloc_dynamic); -EXPORT(udi_cb_alloc_batch); -EXPORT(udi_cb_free); -EXPORT(udi_cancel); - -// === CODE === -void udi_cb_alloc ( - udi_cb_alloc_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_channel_t default_channel - ) -{ - UNIMPLEMENTED(); -} - -void udi_cb_alloc_dynamic( - udi_cb_alloc_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_channel_t default_channel, - udi_size_t inline_size, - udi_layout_t *inline_layout - ) -{ - UNIMPLEMENTED(); -} - -void udi_cb_alloc_batch( - udi_cb_alloc_batch_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_index_t count, - udi_boolean_t with_buf, - udi_size_t buf_size, - udi_buf_path_t path_handle - ) -{ - UNIMPLEMENTED(); -} - -void udi_cb_free(udi_cb_t *cb) -{ - UNIMPLEMENTED(); -} - -void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/imc.c b/Modules/UDI/imc.c deleted file mode 100644 index cd15e070..00000000 --- a/Modules/UDI/imc.c +++ /dev/null @@ -1,69 +0,0 @@ -/** - * \file imc.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_channel_anchor); -EXPORT(udi_channel_spawn); -EXPORT(udi_channel_set_context); -EXPORT(udi_channel_op_abort); -EXPORT(udi_channel_close); -EXPORT(udi_channel_event_ind); -EXPORT(udi_channel_event_complete); - -// === CODE === -/** - */ -void udi_channel_anchor( - udi_channel_anchor_call_t *callback, udi_cb_t *gcb, - udi_channel_t channel, udi_index_t ops_idx, void *channel_context - ) -{ - Warning("%s Unimplemented", __func__); -} - -/** - */ -extern void udi_channel_spawn( - udi_channel_spawn_call_t *callback, udi_cb_t *gcb, - udi_channel_t channel, udi_index_t spawn_idx, - udi_index_t ops_idx, void *channel_context - ) -{ - Warning("%s Unimplemented", __func__); -} - -/** - * - */ -void udi_channel_set_context( - udi_channel_t target_channel, void *channel_context - ) -{ - Warning("%s Unimplemented", __func__); -} - -void udi_channel_op_abort( - udi_channel_t target_channel, udi_cb_t *orig_cb - ) -{ - Warning("%s Unimplemented", __func__); -} - -void udi_channel_close(udi_channel_t channel) -{ - Warning("%s Unimplemented", __func__); -} - -void udi_channel_event_ind(udi_channel_event_cb_t *cb) -{ - udi_channel_event_complete(cb, UDI_OK); -} - -void udi_channel_event_complete(udi_channel_event_cb_t *cb, udi_status_t status) -{ - Warning("%s Unimplemented", __func__); -} diff --git a/Modules/UDI/include/physio/meta_bus.h b/Modules/UDI/include/physio/meta_bus.h deleted file mode 100644 index 7b88ece8..00000000 --- a/Modules/UDI/include/physio/meta_bus.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * \file physio/meta_bus.h - */ -#ifndef _PHYSIO_META_BUS_H_ -#define _PHYSIO_META_BUS_H_ - -#include -#include - -typedef const struct udi_bus_device_ops_s udi_bus_device_ops_t; -typedef const struct udi_bus_bridge_ops_s udi_bus_bridge_ops_t; -typedef struct udi_bus_bind_cb_s udi_bus_bind_cb_t; -typedef void udi_bus_unbind_req_op_t(udi_bus_bind_cb_t *cb); -typedef void udi_bus_unbind_ack_op_t(udi_bus_bind_cb_t *cb); -typedef void udi_bus_bind_req_op_t(udi_bus_bind_cb_t *cb); -typedef void udi_bus_bind_ack_op_t( - udi_bus_bind_cb_t *cb, - udi_dma_constraints_t dma_constraints, - udi_ubit8_t preferred_endianness, - udi_status_t status - ); - - -struct udi_bus_device_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_bus_bind_ack_op_t *bus_bind_ack_op; - udi_bus_unbind_ack_op_t *bus_unbind_ack_op; - udi_intr_attach_ack_op_t *intr_attach_ack_op; - udi_intr_detach_ack_op_t *intr_detach_ack_op; -}; -/* Bus Device Ops Vector Number */ -#define UDI_BUS_DEVICE_OPS_NUM 1 - -struct udi_bus_bridge_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_bus_bind_req_op_t *bus_bind_req_op; - udi_bus_unbind_req_op_t *bus_unbind_req_op; - udi_intr_attach_req_op_t *intr_attach_req_op; - udi_intr_detach_req_op_t *intr_detach_req_op; -}; -/* Bus Bridge Ops Vector Number */ -#define UDI_BUS_BRIDGE_OPS_NUM - -struct udi_bus_bind_cb_s -{ - udi_cb_t gcb; -}; -/* Bus Bind Control Block Group Number */ -#define UDI_BUS_BIND_CB_NUM 1 - - -extern void udi_bus_bind_req(udi_bus_bind_cb_t *cb); - -extern void udi_bus_bind_ack( - udi_bus_bind_cb_t *cb, - udi_dma_constraints_t dma_constraints, - udi_ubit8_t preferred_endianness, - udi_status_t status - ); -/* Values for preferred_endianness */ -#define UDI_DMA_BIG_ENDIAN (1U<<5) -#define UDI_DMA_LITTLE_ENDIAN (1U<<6) -#define UDI_DMA_ANY_ENDIAN (1U<<0) - -extern void udi_bus_unbind_req(udi_bus_bind_cb_t *cb); -extern void udi_bus_unbind_ack(udi_bus_bind_cb_t *cb); - - - - - -#endif diff --git a/Modules/UDI/include/physio/meta_intr.h b/Modules/UDI/include/physio/meta_intr.h deleted file mode 100644 index d5dd3941..00000000 --- a/Modules/UDI/include/physio/meta_intr.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * \file physio/meta_intr.h - */ -#ifndef _PHYSIO_META_INTR_H_ -#define _PHYSIO_META_INTR_H_ - -#include -#include -#include "pio.h" - -typedef struct udi_intr_attach_cb_s udi_intr_attach_cb_t; -typedef void udi_intr_attach_req_op_t(udi_intr_attach_cb_t *intr_attach_cb); -typedef void udi_intr_attach_ack_op_t( - udi_intr_attach_cb_t *intr_attach_cb, - udi_status_t status - ); -typedef struct udi_intr_detach_cb_s udi_intr_detach_cb_t; -typedef void udi_intr_detach_req_op_t(udi_intr_detach_cb_t *intr_detach_cb); -typedef void udi_intr_detach_ack_op_t(udi_intr_detach_cb_t *intr_detach_cb); -typedef const struct udi_intr_handler_ops_s udi_intr_handler_ops_t; -typedef const struct udi_intr_dispatcher_ops_s udi_intr_dispatcher_ops_t; -typedef struct udi_intr_event_cb_s udi_intr_event_cb_t; -typedef void udi_intr_event_ind_op_t(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags); -typedef void udi_intr_event_rdy_op_t(udi_intr_event_cb_t *intr_event_cb); - - -struct udi_intr_attach_cb_s -{ - udi_cb_t gcb; - udi_index_t interrupt_idx; - udi_ubit8_t min_event_pend; - udi_pio_handle_t preprocessing_handle; -}; -/* Bridge Attach Control Block Group Number */ -#define UDI_BUS_INTR_ATTACH_CB_NUM 2 - -struct udi_intr_detach_cb_s -{ - udi_cb_t gcb; - udi_index_t interrupt_idx; -}; -/* Bridge Detach Control Block Group Number */ -#define UDI_BUS_INTR_DETACH_CB_NUM 3 - -struct udi_intr_handler_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_intr_event_ind_op_t *intr_event_ind_op; -}; -/* Interrupt Handler Ops Vector Number */ -#define UDI_BUS_INTR_HANDLER_OPS_NUM 3 - -struct udi_intr_dispatcher_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_intr_event_rdy_op_t *intr_event_rdy_op; -}; -/* Interrupt Dispatcher Ops Vector Number */ -#define UDI_BUS_INTR_DISPATCH_OPS_NUM 4 - -struct udi_intr_event_cb_s -{ - udi_cb_t gcb; - udi_buf_t *event_buf; - udi_ubit16_t intr_result; -}; -/* Flag values for interrupt handling */ -#define UDI_INTR_UNCLAIMED (1U<<0) -#define UDI_INTR_NO_EVENT (1U<<1) -/* Bus Interrupt Event Control Block Group Number */ -#define UDI_BUS_INTR_EVENT_CB_NUM 4 - - - -extern void udi_intr_attach_req(udi_intr_attach_cb_t *intr_attach_cb); -extern void udi_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status); -extern void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status); - -extern void udi_intr_detach_req(udi_intr_detach_cb_t *intr_detach_cb); -extern void udi_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb); -extern void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb); - - -extern void udi_intr_event_ind(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags); -/** - * \brief Values for ::udi_intr_event_ind \a flags - * \{ - */ -#define UDI_INTR_MASKING_NOT_REQUIRED (1U<<0) -#define UDI_INTR_OVERRUN_OCCURRED (1U<<1) -#define UDI_INTR_PREPROCESSED (1U<<2) -/** - * \} - */ - -extern void udi_intr_event_rdy(udi_intr_event_cb_t *intr_event_cb); - - - -#endif diff --git a/Modules/UDI/include/physio/pio.h b/Modules/UDI/include/physio/pio.h deleted file mode 100644 index 1ce305f2..00000000 --- a/Modules/UDI/include/physio/pio.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * \file physio/pio.h - */ -#ifndef _PHYSIO_PIO_H_ -#define _PHYSIO_PIO_H_ - -#include -#include - - -typedef _udi_handle_t udi_pio_handle_t; -/* Null handle value for udi_pio_handle_t */ -#define UDI_NULL_PIO_HANDLE _NULL_HANDLE - -#endif diff --git a/Modules/UDI/include/udi.h b/Modules/UDI/include/udi.h deleted file mode 100644 index fa5cac30..00000000 --- a/Modules/UDI/include/udi.h +++ /dev/null @@ -1,154 +0,0 @@ -/** - * \file udi.h - */ -#ifndef _UDI_ARCH_H_ -#define _UDI_ARCH_H_ - -// Use the core acess file to use the specific size types (plus va_arg) -#include - -typedef Sint8 udi_sbit8_t; /* signed 8-bit: -2^7..2^7-1 */ -typedef Sint16 udi_sbit16_t; /* signed 16-bit: -2^15..2^15-1 */ -typedef Sint32 udi_sbit32_t; /* signed 32-bit: -2^31..2^31-1 */ -typedef Uint8 udi_ubit8_t; /* unsigned 8-bit: 0..28-1 */ -typedef Uint16 udi_ubit16_t; /* unsigned 16-bit: 0..216-1 */ -typedef Uint32 udi_ubit32_t; /* unsigned 32-bit: 0..232-1 */ - -typedef udi_ubit8_t udi_boolean_t; /* 0=False; 1..28-1=True */ -#define FALSE 0 -#define TRUE 1 - -typedef size_t udi_size_t; /* buffer size */ -typedef size_t udi_index_t; /* zero-based index type */ - -typedef void *_udi_handle_t; -#define _NULL_HANDLE NULL - -/* Channel Handle */ -typedef _udi_handle_t *udi_channel_t; -#define UDI_NULL_CHANNEL _NULL_HANDLE - -/** - * \brief Buffer Path - */ -typedef _udi_handle_t udi_buf_path_t; -#define UDI_NULL_BUF_PATH _NULL_HANDLE - -typedef _udi_handle_t udi_origin_t; -#define UDI_NULL_ORIGIN _NULL_HANDLE - -typedef Sint64 udi_timestamp_t; - -#define UDI_HANDLE_IS_NULL(handle, handle_type) (handle == NULL) -#define UDI_HANDLE_ID(handle, handle_type) ((Uint32)handle) - -/** - * \name va_arg wrapper - * \{ - */ -#define UDI_VA_ARG(pvar, type, va_code) va_arg(pvar,type) -#define UDI_VA_UBIT8_T -#define UDI_VA_SBIT8_T -#define UDI_VA_UBIT16_T -#define UDI_VA_SBIT16_T -#define UDI_VA_UBIT32_T -#define UDI_VA_SBIT32_T -#define UDI_VA_BOOLEAN_T -#define UDI_VA_INDEX_T -#define UDI_VA_SIZE_T -#define UDI_VA_STATUS_T -#define UDI_VA_CHANNEL_T -#define UDI_VA_ORIGIN_T -#define UDI_VA_POINTER -/** - * \} - */ - -/** - * \brief Status Type - */ -typedef udi_ubit32_t udi_status_t; - -/** - * \name Values and Flags for udi_status_t - * \{ - */ -#define UDI_STATUS_CODE_MASK 0x0000FFFF -#define UDI_STAT_META_SPECIFIC 0x00008000 -#define UDI_SPECIFIC_STATUS_MASK 0x00007FFF -#define UDI_CORRELATE_OFFSET 16 -#define UDI_CORRELATE_MASK 0xFFFF0000 -/* Common Status Values */ -#define UDI_OK 0 -#define UDI_STAT_NOT_SUPPORTED 1 -#define UDI_STAT_NOT_UNDERSTOOD 2 -#define UDI_STAT_INVALID_STATE 3 -#define UDI_STAT_MISTAKEN_IDENTITY 4 -#define UDI_STAT_ABORTED 5 -#define UDI_STAT_TIMEOUT 6 -#define UDI_STAT_BUSY 7 -#define UDI_STAT_RESOURCE_UNAVAIL 8 -#define UDI_STAT_HW_PROBLEM 9 -#define UDI_STAT_NOT_RESPONDING 10 -#define UDI_STAT_DATA_UNDERRUN 11 -#define UDI_STAT_DATA_OVERRUN 12 -#define UDI_STAT_DATA_ERROR 13 -#define UDI_STAT_PARENT_DRV_ERROR 14 -#define UDI_STAT_CANNOT_BIND 15 -#define UDI_STAT_CANNOT_BIND_EXCL 16 -#define UDI_STAT_TOO_MANY_PARENTS 17 -#define UDI_STAT_BAD_PARENT_TYPE 18 -#define UDI_STAT_TERMINATED 19 -#define UDI_STAT_ATTR_MISMATCH 20 -/** - * \} - */ - -/** - * \name Data Layout Specifiers - * \{ - */ -typedef const udi_ubit8_t udi_layout_t; -/* Specific-Length Layout Type Codes */ -#define UDI_DL_UBIT8_T 1 -#define UDI_DL_SBIT8_T 2 -#define UDI_DL_UBIT16_T 3 -#define UDI_DL_SBIT16_T 4 -#define UDI_DL_UBIT32_T 5 -#define UDI_DL_SBIT32_T 6 -#define UDI_DL_BOOLEAN_T 7 -#define UDI_DL_STATUS_T 8 -/* Abstract Element Layout Type Codes */ -#define UDI_DL_INDEX_T 20 -/* Opaque Handle Element Layout Type Codes */ -#define UDI_DL_CHANNEL_T 30 -#define UDI_DL_ORIGIN_T 32 -/* Indirect Element Layout Type Codes */ -#define UDI_DL_BUF 40 -#define UDI_DL_CB 41 -#define UDI_DL_INLINE_UNTYPED 42 -#define UDI_DL_INLINE_DRIVER_TYPED 43 -#define UDI_DL_MOVABLE_UNTYPED 44 -/* Nested Element Layout Type Codes */ -#define UDI_DL_INLINE_TYPED 50 -#define UDI_DL_MOVABLE_TYPED 51 -#define UDI_DL_ARRAY 52 -#define UDI_DL_END 0 -/** - * \} - */ - - -// === INCLUDE SUB-SECTIONS === -#include "udi/cb.h" // Control Blocks -#include "udi/log.h" // Logging -#include "udi/attr.h" // Attributes -#include "udi/strmem.h" // String/Memory -#include "udi/buf.h" // Buffers -#include "udi/mem.h" // Memory Management -#include "udi/imc.h" // Inter-module Communication -#include "udi/meta_mgmt.h" // Management Metalanguage -#include "udi/meta_gio.h" // General IO Metalanguage -#include "udi/init.h" // Init - -#endif diff --git a/Modules/UDI/include/udi/attr.h b/Modules/UDI/include/udi/attr.h deleted file mode 100644 index a63ce8a7..00000000 --- a/Modules/UDI/include/udi/attr.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * \file udi_attr.h - */ -#ifndef _UDI_ATTR_H_ -#define _UDI_ATTR_H_ - -typedef struct udi_instance_attr_list_s udi_instance_attr_list_t; -typedef udi_ubit8_t udi_instance_attr_type_t; - -/* Instance attribute limits */ -#define UDI_MAX_ATTR_NAMELEN 32 -#define UDI_MAX_ATTR_SIZE 64 - -/** - * \brief Instance Attribute - */ -struct udi_instance_attr_list_s -{ - char attr_name[UDI_MAX_ATTR_NAMELEN]; - udi_ubit8_t attr_value[UDI_MAX_ATTR_SIZE]; - udi_ubit8_t attr_length; - udi_instance_attr_type_t attr_type; -}; - - -/** - * \brief Instance Attribute Types - * \see ::udi_instance_attr_type_t - */ -enum -{ - UDI_ATTR_NONE, - UDI_ATTR_STRING, - UDI_ATTR_ARRAY8, - UDI_ATTR_UBIT32, - UDI_ATTR_BOOLEAN, - UDI_ATTR_FILE -}; - - -#endif diff --git a/Modules/UDI/include/udi/buf.h b/Modules/UDI/include/udi/buf.h deleted file mode 100644 index fa2428b7..00000000 --- a/Modules/UDI/include/udi/buf.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * \file udi_buf.h - */ -#ifndef _UDI_BUF_H_ -#define _UDI_BUF_H_ - - -typedef struct udi_buf_s udi_buf_t; -typedef struct udi_xfer_constraints_s udi_xfer_constraints_t; -typedef void udi_buf_copy_call_t(udi_cb_t *gcb, udi_buf_t *new_dst_buf); -typedef void udi_buf_write_call_t(udi_cb_t *gcb, udi_buf_t *new_dst_buf); - -/** - * \brief Describes a buffer - * \note Semi-Opaque - */ -struct udi_buf_s -{ - udi_size_t buf_size; - Uint8 Data[]; //!< ENVIRONMENT ONLY -}; - -/** - * \brief - */ -struct udi_xfer_constraints_s -{ - udi_ubit32_t udi_xfer_max; - udi_ubit32_t udi_xfer_typical; - udi_ubit32_t udi_xfer_granularity; - udi_boolean_t udi_xfer_one_piece; - udi_boolean_t udi_xfer_exact_size; - udi_boolean_t udi_xfer_no_reorder; -}; - -// --- MACROS --- -/** - * \brief Allocates a buffer - */ -#define UDI_BUF_ALLOC(callback, gcb, init_data, size, path_handle) \ - udi_buf_write(callback, gcb, init_data, size, NULL, 0, 0, path_handle) - -/** - * \brief Inserts data into a buffer - */ -#define UDI_BUF_INSERT(callback, gcb, new_data, size, dst_buf, dst_off) \ - udi_buf_write(callback, gcb, new_data, size, dst_buf, dst_off, 0, UDI_NULL_BUF_PATH) - -/** - * \brief Removes data from a buffer (data afterwards will be moved forewards) - */ -#define UDI_BUF_DELETE(callback, gcb, size, dst_buf, dst_off) \ - udi_buf_write(callback, gcb, NULL, 0, dst_buf, dst_off, size, UDI_NULL_BUF_PATH) - -/** - * \brief Duplicates \a src_buf - */ -#define UDI_BUF_DUP(callback, gcb, src_buf, path_handle) \ - udi_buf_copy(callback, gcb, src_buf, 0, (src_buf)->buf_size, NULL, 0, 0, path_handle) - - -/** - * \brief Copies data from one buffer to another - */ -extern void udi_buf_copy( - udi_buf_copy_call_t *callback, - udi_cb_t *gcb, - udi_buf_t *src_buf, - udi_size_t src_off, - udi_size_t src_len, - udi_buf_t *dst_buf, - udi_size_t dst_off, - udi_size_t dst_len, - udi_buf_path_t path_handle ); - -/** - * \brief Copies data from driver space to a buffer - */ -extern void udi_buf_write( - udi_buf_write_call_t *callback, - udi_cb_t *gcb, - const void *src_mem, - udi_size_t src_len, - udi_buf_t *dst_buf, - udi_size_t dst_off, - udi_size_t dst_len, - udi_buf_path_t path_handle - ); - -/** - * \brief Reads data from a buffer into driver space - */ -extern void udi_buf_read( - udi_buf_t *src_buf, - udi_size_t src_off, - udi_size_t src_len, - void *dst_mem ); - -/** - * \brief Frees a buffer - */ -extern void udi_buf_free(udi_buf_t *buf); - - -#endif diff --git a/Modules/UDI/include/udi/cb.h b/Modules/UDI/include/udi/cb.h deleted file mode 100644 index 76db5c6e..00000000 --- a/Modules/UDI/include/udi/cb.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file udi_cb.h - */ -#ifndef _UDI_CB_H_ -#define _UDI_CB_H_ - -typedef struct udi_cb_s udi_cb_t; -typedef void udi_cb_alloc_call_t(udi_cb_t *gcb, udi_cb_t *new_cb); -typedef void udi_cb_alloc_batch_call_t(udi_cb_t *gcb, udi_cb_t *first_new_cb); -typedef void udi_cancel_call_t(udi_cb_t *gcb); - -#define UDI_GCB(mcb) (&(mcb)->gcb) -#define UDI_MCB(gcb, cb_type) ((cb_type *)(gcb)) - -/** - * \brief Describes a generic control block - * \note Semi-opaque - */ -struct udi_cb_s -{ - /** - * \brief Channel associated with the control block - */ - udi_channel_t channel; - /** - * \brief Current state - * \note Driver changable - */ - void *context; - /** - * \brief CB's scratch area - */ - void *scratch; - /** - * \brief ??? - */ - void *initiator_context; - /** - * \brief Request Handle? - */ - udi_origin_t origin; -}; - -extern void udi_cb_alloc ( - udi_cb_alloc_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_channel_t default_channel - ); - -extern void udi_cb_alloc_dynamic( - udi_cb_alloc_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_channel_t default_channel, - udi_size_t inline_size, - udi_layout_t *inline_layout - ); - -extern void udi_cb_alloc_batch( - udi_cb_alloc_batch_call_t *callback, - udi_cb_t *gcb, - udi_index_t cb_idx, - udi_index_t count, - udi_boolean_t with_buf, - udi_size_t buf_size, - udi_buf_path_t path_handle - ); - -extern void udi_cb_free(udi_cb_t *cb); - -extern void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb); - - - - -#endif diff --git a/Modules/UDI/include/udi/imc.h b/Modules/UDI/include/udi/imc.h deleted file mode 100644 index e5b3f3bb..00000000 --- a/Modules/UDI/include/udi/imc.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * \file udi_imc.h - * \brief Inter-Module Communication - */ -#ifndef _UDI_IMC_H_ -#define _UDI_IMC_H_ - -typedef void udi_channel_anchor_call_t(udi_cb_t *gcb, udi_channel_t anchored_channel); -typedef void udi_channel_spawn_call_t(udi_cb_t *gcb, udi_channel_t new_channel); - -typedef struct udi_channel_event_cb_s udi_channel_event_cb_t; - -typedef void udi_channel_event_ind_op_t(udi_channel_event_cb_t *cb); - -/** - * \brief Anchors a channel end to the current region - */ -extern void udi_channel_anchor( - udi_channel_anchor_call_t *callback, udi_cb_t *gcb, - udi_channel_t channel, udi_index_t ops_idx, void *channel_context - ); - -/** - * \brief Created a new channel between two regions - */ -extern void udi_channel_spawn( - udi_channel_spawn_call_t *callback, - udi_cb_t *gcb, - udi_channel_t channel, - udi_index_t spawn_idx, - udi_index_t ops_idx, - void *channel_context - ); - -/** - * \brief Attaches a new context pointer to the current channel - */ -extern void udi_channel_set_context( - udi_channel_t target_channel, - void *channel_context - ); -/** - * \brief - */ -extern void udi_channel_op_abort( - udi_channel_t target_channel, - udi_cb_t *orig_cb - ); - -/** - * \brief Closes an open channel - */ -extern void udi_channel_close(udi_channel_t channel); - -/** - * \brief Describes a channel event - */ -struct udi_channel_event_cb_s -{ - udi_cb_t gcb; - udi_ubit8_t event; - union { - struct { - udi_cb_t *bind_cb; - } internal_bound; - struct { - udi_cb_t *bind_cb; - udi_ubit8_t parent_ID; - udi_buf_path_t *path_handles; - } parent_bound; - udi_cb_t *orig_cb; - } params; -}; -/* Channel event types */ -#define UDI_CHANNEL_CLOSED 0 -#define UDI_CHANNEL_BOUND 1 -#define UDI_CHANNEL_OP_ABORTED 2 - -/** - * \brief Proxy function - */ -extern void udi_channel_event_ind(udi_channel_event_cb_t *cb); - -/** - * \brief Called when channel event is completed - */ -extern void udi_channel_event_complete( - udi_channel_event_cb_t *cb, udi_status_t status - ); - - -#endif diff --git a/Modules/UDI/include/udi/init.h b/Modules/UDI/include/udi/init.h deleted file mode 100644 index f405d036..00000000 --- a/Modules/UDI/include/udi/init.h +++ /dev/null @@ -1,315 +0,0 @@ -/** - * \file udi_init.h - */ -#ifndef _UDI_INIT_H_ -#define _UDI_INIT_H_ - -typedef struct udi_init_s udi_init_t; -typedef struct udi_primary_init_s udi_primary_init_t; -typedef struct udi_secondary_init_s udi_secondary_init_t; -typedef struct udi_ops_init_s udi_ops_init_t; -typedef struct udi_cb_init_s udi_cb_init_t; -typedef struct udi_cb_select_s udi_cb_select_t; -typedef struct udi_gcb_init_s udi_gcb_init_t; - -typedef struct udi_init_context_s udi_init_context_t; -typedef struct udi_limits_s udi_limits_t; -typedef struct udi_chan_context_s udi_chan_context_t; -typedef struct udi_child_chan_context_s udi_child_chan_context_t; - -typedef void udi_op_t(void); -typedef udi_op_t * const udi_ops_vector_t; - -/** - * \brief UDI Initialisation Structure - * - * Defines how to initialise and use a UDI driver - */ -struct udi_init_s -{ - /** - * \brief Defines the primary region - * \note For secondary modules this must be NULL - */ - udi_primary_init_t *primary_init_info; - - /** - * \brief Defines all secondary regions - * Pointer to a list (so, essentially an array) of ::udi_secondary_init_t - * It is terminated by an entry with ::udi_secondary_init_t.region_idx - * set to zero. - * \note If NULL, it is to be treated as an empty list - */ - udi_secondary_init_t *secondary_init_list; - - /** - * \brief Channel operations - * Pointer to a ::udi_ops_init_t.ops_idx == 0 terminated list that - * defines the channel opterations usage for each ops vector implemented - * in this module. - * \note Must contain at least one entry for each metalanguage used - */ - udi_ops_init_t *ops_init_list; - - /** - * \brief Control Blocks - */ - udi_cb_init_t *cb_init_list; - - /** - * \brief Generic Control Blocks - */ - udi_gcb_init_t *gcb_init_list; - - /** - * \brief Overrides for control blocks - * Allows a control block to override the ammount of scratch space it - * gets for a specific ops vector. - */ - udi_cb_select_t *cb_select_list; -}; - - -/** - * \name Flags for ::udi_primary_init_t.mgmt_op_flags - * \{ - */ - -/** - * \brief Tells the environment that this operation may take some time - * Used as a hint in scheduling tasks - */ -#define UDI_OP_LONG_EXEC 0x01 - -/** - * \} - */ - -/** - * \brief Describes the Primary Region - * Tells the environment how to set up the driver's primary region. - */ -struct udi_primary_init_s -{ - /** - * \brief Management Ops Vector - * Pointer to a list of functions for the Management Metalanguage - */ - udi_mgmt_ops_t *mgmt_ops; - - /** - * \brief Flags for \a mgmt_ops - * Each entry in \a mgmt_ops is acommanied by an entry in this array. - * Each entry contains the flags that apply to the specified ops vector. - * \see UDI_OP_LONG_EXEC - */ - const udi_ubit8_t *mgmt_op_flags; - - /** - * \brief Scratch space size - * Specifies the number of bytes to allocate for each control block - * passed by the environment. - * \note must not exceed ::UDI_MAX_SCRATCH - */ - udi_size_t mgmt_scratch_requirement; - - /** - * \todo What is this? - */ - udi_ubit8_t enumeration_attr_list_length; - - /** - * \brief Size in bytes to allocate to each instance of the primary - * region - * Essentially the size of the driver's instance state - * \note Must be at least sizeof(udi_init_context_t) and not more - * than UDI_MIN_ALLOC_LIMIT - */ - udi_size_t rdata_size; - - /** - * \brief Size in bytes to allocate for each call to ::udi_enumerate_req - * \note Must not exceed UDI_MIN_ALLOC_LIMIT - */ - udi_size_t child_data_size; - - /** - * \brief Number of path handles for each parent bound to this driver - * \todo What the hell are path handles? - */ - udi_ubit8_t per_parent_paths; -}; - -/** - * \brief Tells the environment how to create a secondary region - */ -struct udi_secondary_init_s -{ - /** - * \brief Region Index - * Non-zero driver-dependent index value that identifies the region - * \note This corresponds to a "region" declaration in the udiprops.txt - * file. - */ - udi_index_t region_idx; - /** - * \brief Number of bytes to allocate - * - * \note Again, must be between sizeof(udi_init_context_t) and - * UDI_MIN_ALLOC_LIMIT - */ - udi_size_t rdata_size; -}; - -/** - * \brief Defines channel endpoints (ways of communicating with the driver) - * - */ -struct udi_ops_init_s -{ - /** - * \brief ops index number - * Used to uniquely this entry - * \note If this is zero, it marks the end of the list - */ - udi_index_t ops_idx; - /** - * \brief Metalanguage Index - * Defines what metalanguage is used - */ - udi_index_t meta_idx; - /** - * \brief Metalanguage Operation - * Defines what metalanguage operation is used - */ - udi_index_t meta_ops_num; - /** - * \brief Size of the context area - * \note If non-zero, must be at least - */ - udi_size_t chan_context_size; - /** - * \brief Pointer to the operations - * Pointer to a <>_<>_ops_t structure - */ - udi_ops_vector_t *ops_vector; - /** - * \brief Flags for each entry in \a ops_vector - */ - const udi_ubit8_t *op_flags; -}; - -/** - * \brief Defines control blocks - * Much the same as ::udi_ops_init_t - */ -struct udi_cb_init_s -{ - udi_index_t cb_idx; - udi_index_t meta_idx; - udi_index_t meta_cb_num; - udi_size_t scratch_requirement; - /** - * \brief Size of inline memory - */ - udi_size_t inline_size; - /** - * \brief Layout of inline memory - */ - udi_layout_t *inline_layout; -}; - -/** - * \brief Overrides the scratch size for an operation - */ -struct udi_cb_select_s -{ - udi_index_t ops_idx; - udi_index_t cb_idx; -}; - -/** - * \brief General Control Blocks - * These control blocks can only be used as general data storage, not - * for any channel operations. - */ -struct udi_gcb_init_s -{ - udi_index_t cb_idx; - udi_size_t scratch_requirement; -}; - - -// === -// === -/** - * \brief Environement Imposed Limits - */ -struct udi_limits_s -{ - /** - * \brief Maximum legal ammount of memory that can be allocated - */ - udi_size_t max_legal_alloc; - - /** - * \brief Maximum ammount of guaranteed memory - */ - udi_size_t max_safe_alloc; - /** - * \brief Maximum size of the final string from ::udi_trace_write - * or ::udi_log_write - */ - udi_size_t max_trace_log_formatted_len; - /** - * \brief Maximum legal size of an instanct attribute value - */ - udi_size_t max_instance_attr_len; - /** - * \brief Minumum time difference (in nanoseconds between unique values - * returned by ::udi_time_current - */ - udi_ubit32_t min_curtime_res; - /** - * \brief Minimum resolution of timers - * \see ::udi_timer_start_repeating, ::udi_timer_start - */ - udi_ubit32_t min_timer_res; -} PACKED; - -/** - * \brief Primary Region Context data - */ -struct udi_init_context_s -{ - udi_index_t region_idx; - udi_limits_t limits; -}; - -/** - * \brief Channel context data - */ -struct udi_chan_context_s -{ - /** - * \brief Pointer to the driver instance's initial region data - */ - void *rdata; -} PACKED; - -/** - * \brief Child Channel context - */ -struct udi_child_chan_context_s -{ - /** - * \brief Pointer to the driver instance's initial region data - */ - void *rdata; - /** - * \brief Some sort of unique ID number - */ - udi_ubit32_t child_ID; -}; - -#endif diff --git a/Modules/UDI/include/udi/log.h b/Modules/UDI/include/udi/log.h deleted file mode 100644 index dccb1246..00000000 --- a/Modules/UDI/include/udi/log.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * \file udi_log.h - */ -#ifndef _UDI_LOG_H_ -#define _UDI_LOG_H_ - -/** - * \brief Trace Event - */ -typedef udi_ubit32_t udi_trevent_t; - -/** - * \brief Log Callback - */ -typedef void udi_log_write_call_t(udi_cb_t *gcb, udi_status_t correlated_status); - -/** - * \name Log Severities - * \brief Values for severity - * \{ - */ -#define UDI_LOG_DISASTER 1 -#define UDI_LOG_ERROR 2 -#define UDI_LOG_WARNING 3 -#define UDI_LOG_INFORMATION 4 -/** - * \} - */ - - -#endif diff --git a/Modules/UDI/include/udi/mem.h b/Modules/UDI/include/udi/mem.h deleted file mode 100644 index d29f25ed..00000000 --- a/Modules/UDI/include/udi/mem.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * \file udi_mem.h - */ -#ifndef _UDI_MEM_H_ -#define _UDI_MEM_H_ - -/** - * \brief Callback type for ::udi_mem_alloc - */ -typedef void udi_mem_alloc_call_t(udi_cb_t *gcb, void *new_mem); - -/** - * \brief Allocate memory - */ -extern void udi_mem_alloc( - udi_mem_alloc_call_t *callback, - udi_cb_t *gcb, - udi_size_t size, - udi_ubit8_t flags - ); - -/** - * \brief Values for ::udi_mem_alloc \a flags - * \{ - */ -#define UDI_MEM_NOZERO (1U<<0) //!< No need to zero the memory -#define UDI_MEM_MOVABLE (1U<<1) //!< Globally accessable memory? -/** - * \} - */ - -/** - * \brief Free allocated memory - */ -extern void udi_mem_free(void *target_mem); - - -#endif diff --git a/Modules/UDI/include/udi/meta_gio.h b/Modules/UDI/include/udi/meta_gio.h deleted file mode 100644 index d1cf86fd..00000000 --- a/Modules/UDI/include/udi/meta_gio.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file udi_meta_gio.h - */ -#ifndef _UDI_META_GIO_H_ -#define _UDI_META_GIO_H_ - -typedef const struct udi_gio_provider_ops_s udi_gio_provider_ops_t; -typedef const struct udi_gio_client_ops_s udi_gio_client_ops_t; -typedef struct udi_gio_bind_cb_s udi_gio_bind_cb_t; -typedef struct udi_gio_xfer_cb_s udi_gio_xfer_cb_t; -typedef struct udi_gio_rw_params_s udi_gio_rw_params_t; -typedef struct udi_gio_event_cb_s udi_gio_event_cb_t; - -typedef void udi_gio_bind_req_op_t(udi_gio_bind_cb_t *cb); -typedef void udi_gio_unbind_req_op_t(udi_gio_bind_cb_t *cb); -typedef void udi_gio_xfer_req_op_t(udi_gio_bind_cb_t *cb); -typedef void udi_gio_event_res_op_t(udi_gio_bind_cb_t *cb); - -typedef void udi_gio_bind_ack_op_t( - udi_gio_bind_cb_t *cb, - udi_ubit32_t device_size_lo, - udi_ubit32_t device_size_hi, - udi_status_t status - ); -typedef void udi_gio_unbind_ack_op_t(udi_gio_bind_cb_t *cb); -typedef void udi_gio_xfer_ack_op_t(udi_gio_bind_cb_t *cb); -typedef void udi_gio_xfer_nak_op_t(udi_gio_bind_cb_t *cb, udi_status_t status); -typedef void udi_gio_event_ind_op_t(udi_gio_bind_cb_t *cb); - -typedef udi_ubit8_t udi_gio_op_t; -/* Limit values for udi_gio_op_t */ -#define UDI_GIO_OP_CUSTOM 16 -#define UDI_GIO_OP_MAX 64 -/* Direction flag values for op */ -#define UDI_GIO_DIR_READ (1U<<6) -#define UDI_GIO_DIR_WRITE (1U<<7) -/* Standard Operation Codes */ -#define UDI_GIO_OP_READ UDI_GIO_DIR_READ -#define UDI_GIO_OP_WRITE UDI_GIO_DIR_WRITE - - - -struct udi_gio_provider_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_gio_bind_req_op_t *gio_bind_req_op; - udi_gio_unbind_req_op_t *gio_unbind_req_op; - udi_gio_xfer_req_op_t *gio_xfer_req_op; - udi_gio_event_res_op_t *gio_event_res_op; -}; -/* Ops Vector Number */ -#define UDI_GIO_PROVIDER_OPS_NUM 1 - -struct udi_gio_client_ops_s -{ - udi_channel_event_ind_op_t *channel_event_ind_op; - udi_gio_bind_ack_op_t *gio_bind_ack_op; - udi_gio_unbind_ack_op_t *gio_unbind_ack_op; - udi_gio_xfer_ack_op_t *gio_xfer_ack_op; - udi_gio_xfer_nak_op_t *gio_xfer_nak_op; - udi_gio_event_ind_op_t *gio_event_ind_op; -}; -/* Ops Vector Number */ -#define UDI_GIO_CLIENT_OPS_NUM 2 - -struct udi_gio_bind_cb_s -{ - udi_cb_t gcb; - udi_xfer_constraints_t xfer_constraints; -}; -/* Control Block Group Number */ -#define UDI_GIO_BIND_CB_NUM 1 - - -struct udi_gio_xfer_cb_s -{ - udi_cb_t gcb; - udi_gio_op_t op; - void *tr_params; - udi_buf_t *data_buf; -}; -/* Control Block Group Number */ -#define UDI_GIO_XFER_CB_NUM 2 - -struct udi_gio_rw_params_s -{ - udi_ubit32_t offset_lo; - udi_ubit32_t offset_hi; -}; - -struct udi_gio_event_cb_s -{ - udi_cb_t gcb; - udi_ubit8_t event_code; - void *event_params; -}; -/* Control Block Group Number */ -#define UDI_GIO_EVENT_CB_NUM 3 - - -extern void udi_gio_bind_req(udi_gio_bind_cb_t *cb); -extern void udi_gio_bind_ack( - udi_gio_bind_cb_t *cb, - udi_ubit32_t device_size_lo, - udi_ubit32_t device_size_hi, - udi_status_t status - ); - -extern void udi_gio_unbind_req(udi_gio_bind_cb_t *cb); -extern void udi_gio_unbind_ack(udi_gio_bind_cb_t *cb); - -extern void udi_gio_xfer_req(udi_gio_xfer_cb_t *cb); -extern void udi_gio_xfer_ack(udi_gio_xfer_cb_t *cb); -extern void udi_gio_xfer_nak(udi_gio_xfer_cb_t *cb, udi_status_t status); - -extern void udi_gio_event_res(udi_gio_event_cb_t *cb); -extern void udi_gio_event_ind(udi_gio_event_cb_t *cb); -extern void udi_gio_event_res_unused(udi_gio_event_cb_t *cb); - -#endif diff --git a/Modules/UDI/include/udi/meta_mgmt.h b/Modules/UDI/include/udi/meta_mgmt.h deleted file mode 100644 index 97eccf2d..00000000 --- a/Modules/UDI/include/udi/meta_mgmt.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * \file udi_meta_mgmt.h - */ -#ifndef _UDI_META_MGMT_H_ -#define _UDI_META_MGMT_H_ - -typedef struct udi_mgmt_ops_s udi_mgmt_ops_t; -typedef struct udi_mgmt_cb_s udi_mgmt_cb_t; -typedef struct udi_usage_cb_s udi_usage_cb_t; -typedef struct udi_filter_element_s udi_filter_element_t; -typedef struct udi_enumerate_cb_s udi_enumerate_cb_t; - -/** - * \name Specify Usage - * \{ - */ -typedef void udi_usage_ind_op_t(udi_usage_cb_t *cb, udi_ubit8_t resource_level); -/* Values for resource_level */ -#define UDI_RESOURCES_CRITICAL 1 -#define UDI_RESOURCES_LOW 2 -#define UDI_RESOURCES_NORMAL 3 -#define UDI_RESOURCES_PLENTIFUL 4 -/* Proxy */ -extern void udi_static_usage(udi_usage_cb_t *cb, udi_ubit8_t resource_level); -/** - * \} - */ - -typedef void udi_usage_res_op_t(udi_usage_cb_t *cb); - -/** - * \name Enumerate this driver - * \{ - */ -typedef void udi_enumerate_req_op_t(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level); -/* Values for enumeration_level */ -#define UDI_ENUMERATE_START 1 -#define UDI_ENUMERATE_START_RESCAN 2 -#define UDI_ENUMERATE_NEXT 3 -#define UDI_ENUMERATE_NEW 4 -#define UDI_ENUMERATE_DIRECTED 5 -#define UDI_ENUMERATE_RELEASE 6 -/* Proxy */ -extern void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level); -/** - * \} - */ - -/** - * \name Enumeration Acknowlagement - * \{ - */ -typedef void udi_enumerate_ack_op_t(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_result, udi_index_t ops_idx); -/* Values for enumeration_result */ -#define UDI_ENUMERATE_OK 0 -#define UDI_ENUMERATE_LEAF 1 -#define UDI_ENUMERATE_DONE 2 -#define UDI_ENUMERATE_RESCAN 3 -#define UDI_ENUMERATE_REMOVED 4 -#define UDI_ENUMERATE_REMOVED_SELF 5 -#define UDI_ENUMERATE_RELEASED 6 -#define UDI_ENUMERATE_FAILED 255 -/** - * \} - */ - -/** - * \name - * \{ - */ -typedef void udi_devmgmt_req_op_t(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID); - -typedef void udi_devmgmt_ack_op_t(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status); -/** - * \} - */ -typedef void udi_final_cleanup_req_op_t(udi_mgmt_cb_t *cb); -typedef void udi_final_cleanup_ack_op_t(udi_mgmt_cb_t *cb); - - - - - -struct udi_mgmt_ops_s -{ - udi_usage_ind_op_t *usage_ind_op; - udi_enumerate_req_op_t *enumerate_req_op; - udi_devmgmt_req_op_t *devmgmt_req_op; - udi_final_cleanup_req_op_t *final_cleanup_req_op; -}; - -struct udi_mgmt_cb_s -{ - udi_cb_t gcb; -}; - -struct udi_usage_cb_s -{ - udi_cb_t gcb; - udi_trevent_t trace_mask; - udi_index_t meta_idx; -}; - - -struct udi_filter_element_s -{ - char attr_name[UDI_MAX_ATTR_NAMELEN]; - udi_ubit8_t attr_min[UDI_MAX_ATTR_SIZE]; - udi_ubit8_t attr_min_len; - udi_ubit8_t attr_max[UDI_MAX_ATTR_SIZE]; - udi_ubit8_t attr_max_len; - udi_instance_attr_type_t attr_type; - udi_ubit32_t attr_stride; -}; -struct udi_enumerate_cb_s -{ - udi_cb_t gcb; - udi_ubit32_t child_ID; - void *child_data; - udi_instance_attr_list_t *attr_list; - udi_ubit8_t attr_valid_length; - const udi_filter_element_t *filter_list; - udi_ubit8_t filter_list_length; - udi_ubit8_t parent_ID; -}; -/* Special parent_ID filter values */ -#define UDI_ANY_PARENT_ID 0 - -/** - * \brief - */ -extern void udi_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID ); -/** - * \brief Values for ::udi_devmgmt_req \a mgmt_op - */ -enum eDMGMT -{ - UDI_DMGMT_PREPARE_TO_SUSPEND = 1, - UDI_DMGMT_SUSPEND, - UDI_DMGMT_SHUTDOWN, - UDI_DMGMT_PARENT_SUSPENDED, - UDI_DMGMT_RESUME, - UDI_DMGMT_UNBIND -}; - -extern void udi_devmgmt_ack(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status); -//!\brief Values for flags -#define UDI_DMGMT_NONTRANSPARENT (1U<<0) -//!\brief Meta-Specific Status Codes -#define UDI_DMGMT_STAT_ROUTING_CHANGE (UDI_STAT_META_SPECIFIC|1) - -extern void udi_final_cleanup_req(udi_mgmt_cb_t *cb); -extern void udi_final_cleanup_ack(udi_mgmt_cb_t *cb); - - -#endif diff --git a/Modules/UDI/include/udi/strmem.h b/Modules/UDI/include/udi/strmem.h deleted file mode 100644 index f540a3ea..00000000 --- a/Modules/UDI/include/udi/strmem.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * \file udi_strmem.h - */ -#ifndef _UDI_STRMEM_H_ -#define _UDI_STRMEM_H_ - -/** - * \brief Gets the length of a C style string - */ -extern udi_size_t udi_strlen(const char *s); - -/** - * \brief Appends to a string - */ -extern char *udi_strcat(char *s1, const char *s2); -extern char *udi_strncat(char *s1, const char *s2, udi_size_t n); - -/** - * \brief Compares Strings/Memory - */ -extern udi_sbit8_t udi_strcmp(const char *s1, const char *s2); -extern udi_sbit8_t udi_strncmp(const char *s1, const char *s2, udi_size_t n); -extern udi_sbit8_t udi_memcmp(const void *s1, const void *s2, udi_size_t n); - -extern char *udi_strcpy(char *s1, const char *s2); -extern char *udi_strncpy(char *s1, const char *s2, udi_size_t n); -extern void *udi_memcpy(void *s1, const void *s2, udi_size_t n); -extern void *udi_memmove(void *s1, const void *s2, udi_size_t n); - -extern char *udi_strncpy_rtrim(char *s1, const char *s2, udi_size_t n); - -extern char *udi_strchr(const char *s, char c); -extern char *udi_strrchr(const char *s, char c); -extern void *udi_memchr (const void *s, udi_ubit8_t c, udi_size_t n); - -extern void *udi_memset(void *s, udi_ubit8_t c, udi_size_t n); -extern udi_ubit32_t udi_strtou32(const char *s, char **endptr, int base); - - -extern udi_size_t udi_snprintf(char *s, udi_size_t max_bytes, const char *format, ...); - - - -#endif diff --git a/Modules/UDI/include/udi_physio.h b/Modules/UDI/include/udi_physio.h deleted file mode 100644 index 1397b1c0..00000000 --- a/Modules/UDI/include/udi_physio.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * \file udi_physio.h - */ -#ifndef _UDI_PHYSIO_H_ -#define _UDI_PHYSIO_H_ - -#include - -// === TYPEDEFS === -// DMA Core -typedef _udi_handle_t udi_dma_handle_t; -#define UDI_NULL_DMA_HANDLE _NULL_HANDLE -typedef Uint64 udi_busaddr64_t; //!< \note Opaque -typedef struct udi_scgth_element_32_s udi_scgth_element_32_t; -typedef struct udi_scgth_element_64_s udi_scgth_element_64_t; -typedef struct udi_scgth_s udi_scgth_t; -typedef _udi_handle_t udi_dma_constraints_t; -#define UDI_NULL_DMA_CONSTRAINTS _NULL_HANDLE -/** - * \name DMA constraints attributes - * \{ - */ -typedef udi_ubit8_t udi_dma_constraints_attr_t; -/* DMA Convenience Attribute Codes */ -#define UDI_DMA_ADDRESSABLE_BITS 100 -#define UDI_DMA_ALIGNMENT_BITS 101 -/* DMA Constraints on the Entire Transfer */ -#define UDI_DMA_DATA_ADDRESSABLE_BITS 110 -#define UDI_DMA_NO_PARTIAL 111 -/* DMA Constraints on the Scatter/Gather List */ -#define UDI_DMA_SCGTH_MAX_ELEMENTS 120 -#define UDI_DMA_SCGTH_FORMAT 121 -#define UDI_DMA_SCGTH_ENDIANNESS 122 -#define UDI_DMA_SCGTH_ADDRESSABLE_BITS 123 -#define UDI_DMA_SCGTH_MAX_SEGMENTS 124 -/* DMA Constraints on Scatter/Gather Segments */ -#define UDI_DMA_SCGTH_ALIGNMENT_BITS 130 -#define UDI_DMA_SCGTH_MAX_EL_PER_SEG 131 -#define UDI_DMA_SCGTH_PREFIX_BYTES 132 -/* DMA Constraints on Scatter/Gather Elements */ -#define UDI_DMA_ELEMENT_ALIGNMENT_BITS 140 -#define UDI_DMA_ELEMENT_LENGTH_BITS 141 -#define UDI_DMA_ELEMENT_GRANULARITY_BITS 142 -/* DMA Constraints for Special Addressing */ -#define UDI_DMA_ADDR_FIXED_BITS 150 -#define UDI_DMA_ADDR_FIXED_TYPE 151 -#define UDI_DMA_ADDR_FIXED_VALUE_LO 152 -#define UDI_DMA_ADDR_FIXED_VALUE_HI 153 -/* DMA Constraints on DMA Access Behavior */ -#define UDI_DMA_SEQUENTIAL 160 -#define UDI_DMA_SLOP_IN_BITS 161 -#define UDI_DMA_SLOP_OUT_BITS 162 -#define UDI_DMA_SLOP_OUT_EXTRA 163 -#define UDI_DMA_SLOP_BARRIER_BITS 164 -/* Values for UDI_DMA_SCGTH_ENDIANNESS */ -#define UDI_DMA_LITTLE_ENDIAN (1U<<6) -#define UDI_DMA_BIG_ENDIAN (1U<<5) -/* Values for UDI_DMA_ADDR_FIXED_TYPE */ -#define UDI_DMA_FIXED_ELEMENT 1 -/** - * \} - */ -// DMA Constraints Management -typedef struct udi_dma_constraints_attr_spec_s udi_dma_constraints_attr_spec_t; -typedef void udi_dma_constraints_attr_set_call_t( - udi_cb_t *gcb, udi_dma_constraints_t new_constraints, udi_status_t status - ); -typedef struct udi_dma_limits_s udi_dma_limits_t; - - -// === STRUCTURES === -// --- DMA Constraints Management --- -struct udi_dma_constraints_attr_spec_s -{ - udi_dma_constraints_attr_t attr_type; - udi_ubit32_t attr_value; -}; -// --- DMA Core --- -struct udi_dma_limits_s -{ - udi_size_t max_legal_contig_alloc; - udi_size_t max_safe_contig_alloc; - udi_size_t cache_line_size; -}; -struct udi_scgth_element_32_s -{ - udi_ubit32_t block_busaddr; - udi_ubit32_t block_length; -}; -struct udi_scgth_element_64_s -{ - udi_busaddr64_t block_busaddr; - udi_ubit32_t block_length; - udi_ubit32_t el_reserved; -}; -/* Extension Flag */ -#define UDI_SCGTH_EXT 0x80000000 -struct udi_scgth_s -{ - udi_ubit16_t scgth_num_elements; - udi_ubit8_t scgth_format; - udi_boolean_t scgth_must_swap; - union { - udi_scgth_element_32_t *el32p; - udi_scgth_element_64_t *el64p; - } scgth_elements; - union { - udi_scgth_element_32_t el32; - udi_scgth_element_64_t el64; - } scgth_first_segment; -}; -/* Values for scgth_format */ -#define UDI_SCGTH_32 (1U<<0) -#define UDI_SCGTH_64 (1U<<1) -#define UDI_SCGTH_DMA_MAPPED (1U<<6) -#define UDI_SCGTH_DRIVER_MAPPED (1U<<7) - - - -// === FUNCTIONS === -// --- DMA Constraints Management --- -extern void udi_dma_constraints_attr_set( - udi_dma_constraints_attr_set_call_t *callback, - udi_cb_t *gcb, - udi_dma_constraints_t src_constraints, - const udi_dma_constraints_attr_spec_t *attr_list, - udi_ubit16_t list_length, - udi_ubit8_t flags - ); -/* Constraints Flags */ -#define UDI_DMA_CONSTRAINTS_COPY (1U<<0) - -extern void udi_dma_constraints_attr_reset( - udi_dma_constraints_t constraints, - udi_dma_constraints_attr_t attr_type - ); - -extern void udi_dma_constraints_free(udi_dma_constraints_t constraints); - -#include -#include - - -#endif diff --git a/Modules/UDI/logging.c b/Modules/UDI/logging.c deleted file mode 100644 index 2e58e373..00000000 --- a/Modules/UDI/logging.c +++ /dev/null @@ -1,18 +0,0 @@ -/** - * \file logging.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === PROTOTYPES === - -// === CODE === -void udi_log_write( udi_log_write_call_t *callback, udi_cb_t *gcb, - udi_trevent_t trace_event, udi_ubit8_t severity, udi_index_t meta_idx, - udi_status_t original_status, udi_ubit32_t msgnum, ... ) -{ - Log("UDI Log"); -} - -EXPORT(udi_log_write); diff --git a/Modules/UDI/main.c b/Modules/UDI/main.c deleted file mode 100644 index d114bdc9..00000000 --- a/Modules/UDI/main.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Acess2 UDI Layer - */ -#define DEBUG 0 -#define VERSION ((0<<8)|1) -#include -#include -#include - -// === PROTOTYPES === - int UDI_Install(char **Arguments); - int UDI_DetectDriver(void *Base); - int UDI_LoadDriver(void *Base); - -// === GLOBALS === -MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL); -tModuleLoader gUDI_Loader = { - NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL -}; - -// === CODE === -/** - * \fn int UDI_Install(char **Arguments) - * \brief Stub intialisation routine - */ -int UDI_Install(char **Arguments) -{ - Module_RegisterLoader( &gUDI_Loader ); - return 1; -} - -/** - * \brief Detects if a driver should be loaded by the UDI subsystem - */ -int UDI_DetectDriver(void *Base) -{ - if( Binary_FindSymbol(Base, "udi_init_info", NULL) == 0) { - return 0; - } - - return 1; -} - -/** - * \fn int UDI_LoadDriver(void *Base) - */ -int UDI_LoadDriver(void *Base) -{ - udi_init_t *info; - char *udiprops = NULL; - int udiprops_size = 0; - int i; - // int j; - - Log("UDI_LoadDriver: (Base=%p)", Base); - - if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) { - Binary_Unload(Base); - return 0; - } - - if( Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops) == 0 ) { - Warning("[UDI ] _udiprops is not defined, this is usually bad"); - } - else { - Binary_FindSymbol(Base, "_udiprops_size", (Uint*)&udiprops_size); - Log("udiprops = %p, udiprops_size = 0x%x", udiprops, udiprops_size); - } - - - Log("primary_init_info = %p = {", info->primary_init_info); - { - Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops); - Log(" .usage_ind_op: %p() - 0x%02x", - info->primary_init_info->mgmt_ops->usage_ind_op, - info->primary_init_info->mgmt_op_flags[0] - ); - Log(" .enumerate_req_op: %p() - 0x%02x", - info->primary_init_info->mgmt_ops->enumerate_req_op, - info->primary_init_info->mgmt_op_flags[1] - ); - Log(" .devmgmt_req_op: %p() - 0x%02x", - info->primary_init_info->mgmt_ops->devmgmt_req_op, - info->primary_init_info->mgmt_op_flags[2] - ); - Log(" .final_cleanup_req_op: %p() - 0x%02x", - info->primary_init_info->mgmt_ops->final_cleanup_req_op, - info->primary_init_info->mgmt_op_flags[3] - ); - Log(" }"); - Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement); - Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length); - Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size); - Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size); - Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths); - } - Log("}"); - Log("secondary_init_list = %p", info->secondary_init_list); - Log("ops_init_list = %p", info->ops_init_list); - - for( i = 0; info->ops_init_list[i].ops_idx; i++ ) - { - Log("info->ops_init_list[%i] = {", i); - Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx); - Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx); - Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num); - Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size); - Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector); - Log(" .op_flags = %p", info->ops_init_list[i].op_flags); - Log("}"); - } - - return 0; -} diff --git a/Modules/UDI/mem.c b/Modules/UDI/mem.c deleted file mode 100644 index a09d54c5..00000000 --- a/Modules/UDI/mem.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * \file mem.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_mem_alloc); -EXPORT(udi_mem_free); - -// === CODE === -void udi_mem_alloc( - udi_mem_alloc_call_t *callback, - udi_cb_t *gcb, - udi_size_t size, - udi_ubit8_t flags - ) -{ - void *buf = malloc(size); - if(buf) - { - if( !(flags & UDI_MEM_NOZERO) ) - memset(buf, 0, size); - } - callback(gcb, buf); -} - -void udi_mem_free(void *target_mem) -{ - free(target_mem); -} diff --git a/Modules/UDI/meta_gio.c b/Modules/UDI/meta_gio.c deleted file mode 100644 index 1618c27f..00000000 --- a/Modules/UDI/meta_gio.c +++ /dev/null @@ -1,68 +0,0 @@ -/** - * \file meta_gio.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_gio_bind_req); -EXPORT(udi_gio_bind_ack); -EXPORT(udi_gio_unbind_req); -EXPORT(udi_gio_unbind_ack); -EXPORT(udi_gio_xfer_req); -EXPORT(udi_gio_xfer_ack); -EXPORT(udi_gio_xfer_nak); -EXPORT(udi_gio_event_res); -EXPORT(udi_gio_event_ind); -EXPORT(udi_gio_event_res_unused); - -// === CODE === -void udi_gio_bind_req(udi_gio_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_bind_ack( - udi_gio_bind_cb_t *cb, - udi_ubit32_t device_size_lo, - udi_ubit32_t device_size_hi, - udi_status_t status - ) -{ - UNIMPLEMENTED(); -} - -void udi_gio_unbind_req(udi_gio_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_unbind_ack(udi_gio_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} - -void udi_gio_xfer_req(udi_gio_xfer_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_xfer_ack(udi_gio_xfer_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_xfer_nak(udi_gio_xfer_cb_t *cb, udi_status_t status) -{ - UNIMPLEMENTED(); -} - -void udi_gio_event_res(udi_gio_event_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_event_ind(udi_gio_event_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_gio_event_res_unused(udi_gio_event_cb_t *cb) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/meta_mgmt.c b/Modules/UDI/meta_mgmt.c deleted file mode 100644 index 45a02c46..00000000 --- a/Modules/UDI/meta_mgmt.c +++ /dev/null @@ -1,49 +0,0 @@ -/** - * \file meta_mgmt.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_devmgmt_req); -EXPORT(udi_devmgmt_ack); -EXPORT(udi_final_cleanup_req); -EXPORT(udi_final_cleanup_ack); -EXPORT(udi_static_usage); -EXPORT(udi_enumerate_no_children); - -// === CODE === -void udi_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID ) -{ - ENTER("pcb imgmt_op iparent_ID", cb, mgmt_op, parent_ID); - LEAVE('-'); -} - -void udi_devmgmt_ack(udi_mgmt_cb_t *cb, udi_ubit8_t flags, udi_status_t status) -{ - ENTER("pcb xflags istatus", cb, flags, status); - LEAVE('-'); -} - -void udi_final_cleanup_req(udi_mgmt_cb_t *cb) -{ - ENTER("pcb", cb); - LEAVE('-'); -} - -void udi_final_cleanup_ack(udi_mgmt_cb_t *cb) -{ - ENTER("pcb", cb); - LEAVE('-'); -} - -void udi_static_usage(udi_usage_cb_t *cb, udi_ubit8_t resource_level) -{ - UNIMPLEMENTED(); -} - -void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/physio.c b/Modules/UDI/physio.c deleted file mode 100644 index 881c9f40..00000000 --- a/Modules/UDI/physio.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * \file physio.c - * \author John Hodge (thePowersGang) - */ -#include -#include -#include - -// === EXPORTS === -EXPORT(udi_dma_constraints_attr_reset); -EXPORT(udi_dma_constraints_free); - -// === CODE === -void udi_dma_constraints_attr_reset( - udi_dma_constraints_t constraints, - udi_dma_constraints_attr_t attr_type - ) -{ - UNIMPLEMENTED(); -} - -void udi_dma_constraints_free(udi_dma_constraints_t constraints) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/physio/meta_bus.c b/Modules/UDI/physio/meta_bus.c deleted file mode 100644 index e1e6a47d..00000000 --- a/Modules/UDI/physio/meta_bus.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * \file physio/meta_bus.c - * \author John Hodge (thePowersGang) - */ -#include -#include -#include - -// === EXPORTS === -EXPORT(udi_bus_unbind_req); -EXPORT(udi_bus_unbind_ack); -EXPORT(udi_bus_bind_req); -EXPORT(udi_bus_bind_ack); - -// === CODE === -void udi_bus_unbind_req(udi_bus_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} -void udi_bus_unbind_ack(udi_bus_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} - -void udi_bus_bind_req(udi_bus_bind_cb_t *cb) -{ - UNIMPLEMENTED(); -} - -void udi_bus_bind_ack( - udi_bus_bind_cb_t *cb, - udi_dma_constraints_t dma_constraints, - udi_ubit8_t preferred_endianness, - udi_status_t status - ) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/physio/meta_intr.c b/Modules/UDI/physio/meta_intr.c deleted file mode 100644 index f4f50961..00000000 --- a/Modules/UDI/physio/meta_intr.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * \file physio/meta_intr.c - * \author John Hodge (thePowersGang) - */ -#include -#include -#include - -// === EXPORTS === -EXPORT(udi_intr_attach_req); -EXPORT(udi_intr_attach_ack); -EXPORT(udi_intr_attach_ack_unused); -EXPORT(udi_intr_detach_req); -EXPORT(udi_intr_detach_ack); -EXPORT(udi_intr_detach_ack_unused); -EXPORT(udi_intr_event_ind); - -// === CODE === -void udi_intr_attach_req(udi_intr_attach_cb_t *intr_attach_cb) -{ - UNIMPLEMENTED(); -} -void udi_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) -{ - UNIMPLEMENTED(); -} -void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) -{ - UNIMPLEMENTED(); -} - -void udi_intr_detach_req(udi_intr_detach_cb_t *intr_detach_cb) -{ - UNIMPLEMENTED(); -} -void udi_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb) -{ - UNIMPLEMENTED(); -} -void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb) -{ - UNIMPLEMENTED(); -} - -void udi_intr_event_ind(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags) -{ - UNIMPLEMENTED(); -} diff --git a/Modules/UDI/physio_main.c b/Modules/UDI/physio_main.c deleted file mode 100644 index f5e7aa04..00000000 --- a/Modules/UDI/physio_main.c +++ /dev/null @@ -1,16 +0,0 @@ -/** - * \file logging.c - * \author John Hodge (thePowersGang) - */ -#include -#include -#include - -// === CODE === -void udi_bus_bind_req(udi_bus_bind_cb_t *cb) -{ -} - -void udi_bus_unbind_req(udi_bus_bind_cb_t *cb) -{ -} diff --git a/Modules/UDI/strmem.c b/Modules/UDI/strmem.c deleted file mode 100644 index 4ab1e208..00000000 --- a/Modules/UDI/strmem.c +++ /dev/null @@ -1,16 +0,0 @@ -/** - * \file strmem.c - * \author John Hodge (thePowersGang) - */ -#include -#include - -// === EXPORTS === -EXPORT(udi_snprintf); - -// === CODE === -udi_size_t udi_snprintf(char *s, udi_size_t max_bytes, const char *format, ...) -{ - s[0] = '\0'; - return 0; -} diff --git a/Usermode/Applications/login_src/database_tpl.c b/Usermode/Applications/login_src/database_tpl.c index 0f794694..ddead96d 100644 --- a/Usermode/Applications/login_src/database_tpl.c +++ b/Usermode/Applications/login_src/database_tpl.c @@ -22,11 +22,11 @@ tUserInfo gUserInfo; */ int ValidateUser(char *Username, char *Password) { - printf("Username: %s\n", Username); if(Username == NULL) return -1; if(Password == NULL) return -1; if(strcmp(Username, "root") == 0) return 0; if(strcmp(Username, "tpg") == 0) return 1; + if(strcmp(Username, "gui") == 0) return 2; return -1; } @@ -47,6 +47,11 @@ tUserInfo *GetUserInfo(int UID) case 1: gUserInfo.Home = "/Acess/Users/tpg"; break; + case 2: + gUserInfo.UID = 0; //HACK! + gUserInfo.Home = "/Acess/Users/gui"; + gUserInfo.Shell = "/Acess/Apps/AxWin/1.0/AxWinWM"; + break; default: gUserInfo.Home = "/Acess/Users/Guest"; break; diff --git a/Usermode/Applications/login_src/main.c b/Usermode/Applications/login_src/main.c index 391d5bcc..2866dbd6 100644 --- a/Usermode/Applications/login_src/main.c +++ b/Usermode/Applications/login_src/main.c @@ -57,7 +57,8 @@ int main(int argc, char *argv[]) child_argv[0] = uinfo->Shell; // Set Environment setgid(uinfo->GID); - setuid(uid); + //setuid(uid); + setuid(uinfo->UID); execve(uinfo->Shell, child_argv, child_envp); exit(-1); diff --git a/Usermode/include/acess/devices/terminal.h b/Usermode/include/acess/devices/terminal.h index 2fc460bd..8397d182 100644 --- a/Usermode/include/acess/devices/terminal.h +++ b/Usermode/include/acess/devices/terminal.h @@ -10,7 +10,8 @@ enum eDrv_Terminal { TERM_IOCTL_MODETYPE = 4, TERM_IOCTL_WIDTH, TERM_IOCTL_HEIGHT, - TERM_IOCTL_QUERYMODE + TERM_IOCTL_QUERYMODE, + TERM_IOCTL_FORCESHOW };