-BUILD_NUM = 1398
+BUILD_NUM = 1407
#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
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);
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:
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;
# 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;
* \note The id field of \a info is not for use with ::TERM_IOCTL_MODETYPE\r
* This field is just for indexing the mode to get its information.\r
*/\r
- TERM_IOCTL_QUERYMODE\r
+ TERM_IOCTL_QUERYMODE,\r
+ \r
+ /**\r
+ * ioctl(...)\r
+ * \brief Forces the current terminal to be shown\r
+ */\r
+ TERM_IOCTL_FORCESHOW\r
};\r
\r
/**\r
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
+++ /dev/null
-#
-#
-
-OBJ = main.o mbr.o
-NAME = ATA
-
--include ../Makefile.tpl
+++ /dev/null
-/*
- * Acess2 IDE Harddisk Driver
- * - main.c
- */
-#ifndef _COMMON_H_
-#define _COMMON_H_
-
-#include <acess.h>
-#include <vfs.h>
-
-// === 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
+++ /dev/null
-/*
- * Acess2 IDE Harddisk Driver
- * - main.c
- */
-#define DEBUG 0
-#include <acess.h>
-#include <modules.h>
-#include <vfs.h>
-#include <fs_devfs.h>
-#include <drv_pci.h>
-#include <tpl_drv_common.h>
-#include <tpl_drv_disk.h>
-#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;
-}
+++ /dev/null
-/*
- * Acess2 IDE Harddisk Driver
- * - MBR Parsing Code
- * mbr.c
- */
-#define DEBUG 0
-#include <acess.h>
-#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;
-}
+++ /dev/null
-#
-#
-
-OBJ = bochsvbe.o
-NAME = BochsGA
-
--include ../Makefile.tpl
+++ /dev/null
-/**\r
- * \file drv_bochsvbe.c\r
- * \brief BGA (Bochs Graphic Adapter) Driver\r
- * \note for Acess2\r
- * \warning This driver does NOT support the Bochs PCI VGA driver\r
-*/\r
-#define DEBUG 0\r
-#include <acess.h>\r
-#include <errno.h>\r
-#include <modules.h>\r
-#include <vfs.h>\r
-#include <fs_devfs.h>\r
-#include <drv_pci.h>\r
-#include <tpl_drv_video.h>\r
-\r
-#define INT\r
-\r
-// === TYPEDEFS ===\r
-typedef struct {\r
- Uint16 width;\r
- Uint16 height;\r
- Uint16 bpp;\r
- Uint16 flags;\r
- Uint32 fbSize;\r
-} t_bga_mode;\r
-\r
-// === CONSTANTS ===\r
-enum eMode_Flags {\r
- MODEFLAG_TEXT = 1\r
-};\r
-#define BGA_LFB_MAXSIZE (1024*768*4)\r
-#define VBE_DISPI_BANK_ADDRESS 0xA0000\r
-#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000\r
-#define VBE_DISPI_IOPORT_INDEX 0x01CE\r
-#define VBE_DISPI_IOPORT_DATA 0x01CF\r
-#define VBE_DISPI_DISABLED 0x00\r
-#define VBE_DISPI_ENABLED 0x01\r
-#define VBE_DISPI_LFB_ENABLED 0x40\r
-#define VBE_DISPI_NOCLEARMEM 0x80\r
-enum {\r
- VBE_DISPI_INDEX_ID,\r
- VBE_DISPI_INDEX_XRES,\r
- VBE_DISPI_INDEX_YRES,\r
- VBE_DISPI_INDEX_BPP,\r
- VBE_DISPI_INDEX_ENABLE,\r
- VBE_DISPI_INDEX_BANK,\r
- VBE_DISPI_INDEX_VIRT_WIDTH,\r
- VBE_DISPI_INDEX_VIRT_HEIGHT,\r
- VBE_DISPI_INDEX_X_OFFSET,\r
- VBE_DISPI_INDEX_Y_OFFSET\r
-};\r
-\r
-\r
-// === PROTOTYPES ===\r
-// Driver\r
- int BGA_Install(char **Arguments);\r
-void BGA_Uninstall();\r
-// Internal\r
-void BGA_int_WriteRegister(Uint16 reg, Uint16 value);\r
-Uint16 BGA_int_ReadRegister(Uint16 reg);\r
-void BGA_int_SetBank(Uint16 bank);\r
-void BGA_int_SetMode(Uint16 width, Uint16 height);\r
- int BGA_int_UpdateMode(int id);\r
- int BGA_int_FindMode(tVideo_IOCtl_Mode *info);\r
- int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info);\r
- int BGA_int_MapFB(void *Dest);\r
-// Filesystem\r
-Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
-Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
- int BGA_Ioctl(tVFS_Node *node, int id, void *data);\r
-\r
-// === GLOBALS ===\r
-MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL);\r
-tDevFS_Driver gBGA_DriverStruct = {\r
- NULL, "BochsGA",\r
- {\r
- .Read = BGA_Read,\r
- .Write = BGA_Write,\r
- .IOCtl = BGA_Ioctl\r
- }\r
-};\r
- int giBGA_CurrentMode = -1;\r
-tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1};\r
- int giBGA_DriverId = -1;\r
-Uint *gBGA_Framebuffer;\r
-t_bga_mode gBGA_Modes[] = {\r
- {},\r
- { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480\r
- {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600\r
- {640,480,8, 0, 640*480},\r
- {640,480,32, 0, 640*480*4},\r
- {800,600,8, 0, 800*600},\r
- {800,600,32, 0, 800*600*4},\r
-};\r
-#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int BGA_Install(char **Arguments)\r
- */\r
-int BGA_Install(char **Arguments)\r
-{\r
- int bga_version = 0;\r
- \r
- // Check BGA Version\r
- bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
- // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable\r
- if(bga_version < 0xB0C4 || bga_version > 0xB0C5) {\r
- Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version);\r
- return 0;\r
- }\r
- \r
- // Install Device\r
- giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct );\r
- if(giBGA_DriverId == -1) {\r
- Warning("[BGA ] Unable to register with DevFS, maybe already loaded?");\r
- return 0;\r
- }\r
- \r
- // Map Framebuffer to hardware address\r
- gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb)\r
- \r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn void BGA_Uninstall()\r
- */\r
-void BGA_Uninstall()\r
-{\r
- //DevFS_DelDevice( giBGA_DriverId );\r
- MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
-}\r
-\r
-/**\r
- * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
- * \brief Read from the framebuffer\r
- */\r
-Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
-{\r
- // Check Mode\r
- if(giBGA_CurrentMode == -1) return -1;\r
- \r
- // Check Offset and Length against Framebuffer Size\r
- if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize)\r
- return -1;\r
- \r
- // Copy from Framebuffer\r
- memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len);\r
- return len;\r
-}\r
-\r
-/**\r
- * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
- * \brief Write to the framebuffer\r
- */\r
-Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
-{ \r
- ENTER("xoff xlen", off, len);\r
- \r
- // Check Mode\r
- if(giBGA_CurrentMode == -1) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- // Check Input against Frambuffer Size\r
- if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- // Text Mode\r
- if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT )\r
- {\r
- tVT_Char *chars = buffer;\r
- int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
- int x, y;\r
- Uint32 *dest;\r
- \r
- off /= sizeof(tVT_Char);\r
- dest = (void*)gBGA_Framebuffer;\r
- x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
- y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight;\r
- dest += y * pitch;\r
- dest += x * giVT_CharWidth;\r
- len /= sizeof(tVT_Char);\r
- while(len--)\r
- {\r
- VT_Font_Render(\r
- chars->Ch,\r
- dest, pitch,\r
- VT_Colour12to24(chars->BGCol),\r
- VT_Colour12to24(chars->FGCol)\r
- );\r
- \r
- dest += giVT_CharWidth;\r
- \r
- chars ++;\r
- x += giVT_CharWidth;\r
- if( x >= pitch ) {\r
- x = 0;\r
- y += giVT_CharHeight;\r
- dest += pitch*(giVT_CharHeight-1);\r
- }\r
- }\r
- }\r
- else\r
- {\r
- Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off);\r
- \r
- LOG("buffer = %p\n", buffer);\r
- LOG("Updating Framebuffer (%p to %p)\n", \r
- destBuf, destBuf + (Uint)len);\r
- \r
- \r
- // Copy to Frambuffer\r
- memcpy(destBuf, buffer, len);\r
- \r
- LOG("BGA Framebuffer updated\n");\r
- }\r
- \r
- LEAVE('i', len);\r
- return len;\r
-}\r
-\r
-/**\r
- * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
- * \brief Handle messages to the device\r
- */\r
-INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
-{\r
- int ret = -2;\r
- ENTER("pNode iId pData", node, ID, Data);\r
- \r
- switch(ID)\r
- {\r
- case DRV_IOCTL_TYPE:\r
- ret = DRV_TYPE_VIDEO;\r
- break;\r
- case DRV_IOCTL_IDENT:\r
- memcpy(Data, "BGA1", 4);\r
- ret = 1;\r
- break;\r
- case DRV_IOCTL_VERSION:\r
- ret = 0x100;\r
- break;\r
- case DRV_IOCTL_LOOKUP: // TODO: Implement\r
- ret = 0;\r
- break;\r
- \r
- case VIDEO_IOCTL_GETSETMODE:\r
- if( Data )\r
- ret = BGA_int_UpdateMode(*(int*)(Data));\r
- else\r
- ret = giBGA_CurrentMode;\r
- break;\r
- \r
- case VIDEO_IOCTL_FINDMODE:\r
- ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data);\r
- break;\r
- \r
- case VIDEO_IOCTL_MODEINFO:\r
- ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
- break;\r
- \r
- // Request Access to LFB\r
- case VIDEO_IOCTL_REQLFB:\r
- ret = BGA_int_MapFB( *(void**)Data );\r
- break;\r
- \r
- case VIDEO_IOCTL_SETCURSOR:\r
- gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x;\r
- gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y;\r
- break;\r
- \r
- default:\r
- LEAVE('i', -2);\r
- return -2;\r
- }\r
- \r
- LEAVE('i', ret);\r
- return ret;\r
-}\r
-\r
-//== Internal Functions ==\r
-/**\r
- * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
- * \brief Writes to a BGA register\r
- */\r
-void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
-{\r
- outw(VBE_DISPI_IOPORT_INDEX, reg);\r
- outw(VBE_DISPI_IOPORT_DATA, value);\r
-}\r
-\r
-INT Uint16 BGA_int_ReadRegister(Uint16 reg)\r
-{\r
- outw(VBE_DISPI_IOPORT_INDEX, reg);\r
- return inw(VBE_DISPI_IOPORT_DATA);\r
-}\r
-\r
-#if 0\r
-INT void BGA_int_SetBank(Uint16 bank)\r
-{\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank);\r
-}\r
-#endif\r
-\r
-/**\r
- * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp)\r
- * \brief Sets the video mode from the dimensions and bpp given\r
- */\r
-void BGA_int_SetMode(Uint16 width, Uint16 height)\r
-{\r
- ENTER("iwidth iheight ibpp", width, height, bpp);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32);\r
- BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED);\r
- //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM);\r
- LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_UpdateMode(int id)\r
- * \brief Set current vide mode given a mode id\r
- */\r
-int BGA_int_UpdateMode(int id)\r
-{\r
- // Sanity Check\r
- if(id < 0 || id >= BGA_MODE_COUNT) return -1;\r
- \r
- // Check if it is a text mode\r
- if( gBGA_Modes[id].flags & MODEFLAG_TEXT )\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width*giVT_CharWidth,\r
- gBGA_Modes[id].height*giVT_CharHeight);\r
- else // Graphics?\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width,\r
- gBGA_Modes[id].height);\r
- \r
- giBGA_CurrentMode = id;\r
- return id;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
- * \brief Find a mode matching the given options\r
- */\r
-int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
-{\r
- int i;\r
- int best = 0, bestFactor = 1000;\r
- int factor, tmp;\r
- int rqdProduct = info->width * info->height * info->bpp;\r
- \r
- ENTER("pinfo", info);\r
- LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp);\r
- \r
- for(i = 0; i < BGA_MODE_COUNT; i++)\r
- {\r
- #if DEBUG >= 2\r
- LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp);\r
- #endif\r
- \r
- // Check if this mode is the same type as what we want\r
- if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) )\r
- continue;\r
- \r
- // Ooh! A perfect match\r
- if(gBGA_Modes[i].width == info->width\r
- && gBGA_Modes[i].height == info->height\r
- && gBGA_Modes[i].bpp == info->bpp)\r
- {\r
- #if DEBUG >= 2\r
- LogF("Perfect!\n");\r
- #endif\r
- best = i;\r
- break;\r
- }\r
- \r
- // If not, how close are we?\r
- tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp;\r
- tmp -= rqdProduct;\r
- tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp)\r
- factor = tmp * 100 / rqdProduct;\r
- \r
- #if DEBUG >= 2\r
- LogF("factor = %i\n", factor);\r
- #endif\r
- \r
- if(factor < bestFactor)\r
- {\r
- bestFactor = factor;\r
- best = i;\r
- }\r
- }\r
- \r
- info->id = best;\r
- info->width = gBGA_Modes[best].width;\r
- info->height = gBGA_Modes[best].height;\r
- info->bpp = gBGA_Modes[best].bpp;\r
- \r
- info->flags = 0;\r
- if(gBGA_Modes[best].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
- return best;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
- * \brief Get mode information\r
- */\r
-int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
-{\r
- // Sanity Check\r
- //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
- // return -EINVAL;\r
- //}\r
- \r
- if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1;\r
- \r
- info->width = gBGA_Modes[info->id].width;\r
- info->height = gBGA_Modes[info->id].height;\r
- info->bpp = gBGA_Modes[info->id].bpp;\r
- \r
- info->flags = 0;\r
- if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn int BGA_int_MapFB(void *Dest)\r
- * \brief Map the framebuffer into a process's space\r
- * \param Dest User address to load to\r
- */\r
-int BGA_int_MapFB(void *Dest)\r
-{\r
- Uint i;\r
- Uint pages;\r
- \r
- // Sanity Check\r
- if((Uint)Dest > 0xC0000000) return 0;\r
- if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported\r
- \r
- // Count required pages\r
- pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12;\r
- \r
- // Check if there is space\r
- for( i = 0; i < pages; i++ )\r
- {\r
- if(MM_GetPhysAddr( (Uint)Dest + (i << 12) ))\r
- return 0;\r
- }\r
- \r
- // Map\r
- for( i = 0; i < pages; i++ )\r
- MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) );\r
- \r
- return 1;\r
-}\r
--- /dev/null
+#
+#
+
+OBJ = bochsvbe.o
+NAME = BochsGA
+
+-include ../Makefile.tpl
--- /dev/null
+/**\r
+ * \file drv_bochsvbe.c\r
+ * \brief BGA (Bochs Graphic Adapter) Driver\r
+ * \note for Acess2\r
+ * \warning This driver does NOT support the Bochs PCI VGA driver\r
+*/\r
+#define DEBUG 0\r
+#include <acess.h>\r
+#include <errno.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <drv_pci.h>\r
+#include <tpl_drv_video.h>\r
+\r
+#define INT\r
+\r
+// === TYPEDEFS ===\r
+typedef struct {\r
+ Uint16 width;\r
+ Uint16 height;\r
+ Uint16 bpp;\r
+ Uint16 flags;\r
+ Uint32 fbSize;\r
+} t_bga_mode;\r
+\r
+// === CONSTANTS ===\r
+enum eMode_Flags {\r
+ MODEFLAG_TEXT = 1\r
+};\r
+#define BGA_LFB_MAXSIZE (1024*768*4)\r
+#define VBE_DISPI_BANK_ADDRESS 0xA0000\r
+#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000\r
+#define VBE_DISPI_IOPORT_INDEX 0x01CE\r
+#define VBE_DISPI_IOPORT_DATA 0x01CF\r
+#define VBE_DISPI_DISABLED 0x00\r
+#define VBE_DISPI_ENABLED 0x01\r
+#define VBE_DISPI_LFB_ENABLED 0x40\r
+#define VBE_DISPI_NOCLEARMEM 0x80\r
+enum {\r
+ VBE_DISPI_INDEX_ID,\r
+ VBE_DISPI_INDEX_XRES,\r
+ VBE_DISPI_INDEX_YRES,\r
+ VBE_DISPI_INDEX_BPP,\r
+ VBE_DISPI_INDEX_ENABLE,\r
+ VBE_DISPI_INDEX_BANK,\r
+ VBE_DISPI_INDEX_VIRT_WIDTH,\r
+ VBE_DISPI_INDEX_VIRT_HEIGHT,\r
+ VBE_DISPI_INDEX_X_OFFSET,\r
+ VBE_DISPI_INDEX_Y_OFFSET\r
+};\r
+\r
+\r
+// === PROTOTYPES ===\r
+// Driver\r
+ int BGA_Install(char **Arguments);\r
+void BGA_Uninstall();\r
+// Internal\r
+void BGA_int_WriteRegister(Uint16 reg, Uint16 value);\r
+Uint16 BGA_int_ReadRegister(Uint16 reg);\r
+void BGA_int_SetBank(Uint16 bank);\r
+void BGA_int_SetMode(Uint16 width, Uint16 height);\r
+ int BGA_int_UpdateMode(int id);\r
+ int BGA_int_FindMode(tVideo_IOCtl_Mode *info);\r
+ int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info);\r
+ int BGA_int_MapFB(void *Dest);\r
+// Filesystem\r
+Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+ int BGA_Ioctl(tVFS_Node *node, int id, void *data);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL);\r
+tDevFS_Driver gBGA_DriverStruct = {\r
+ NULL, "BochsGA",\r
+ {\r
+ .Read = BGA_Read,\r
+ .Write = BGA_Write,\r
+ .IOCtl = BGA_Ioctl\r
+ }\r
+};\r
+ int giBGA_CurrentMode = -1;\r
+tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1};\r
+ int giBGA_DriverId = -1;\r
+Uint *gBGA_Framebuffer;\r
+t_bga_mode gBGA_Modes[] = {\r
+ {},\r
+ { 80,25, 12, MODEFLAG_TEXT, 80*25*8}, // 640 x 480\r
+ {100,37, 12, MODEFLAG_TEXT, 100*37*8}, // 800 x 600\r
+ {640,480,8, 0, 640*480},\r
+ {640,480,32, 0, 640*480*4},\r
+ {800,600,8, 0, 800*600},\r
+ {800,600,32, 0, 800*600*4},\r
+};\r
+#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int BGA_Install(char **Arguments)\r
+ */\r
+int BGA_Install(char **Arguments)\r
+{\r
+ int bga_version = 0;\r
+ \r
+ // Check BGA Version\r
+ bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
+ // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable\r
+ if(bga_version < 0xB0C4 || bga_version > 0xB0C5) {\r
+ Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version);\r
+ return 0;\r
+ }\r
+ \r
+ // Install Device\r
+ giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct );\r
+ if(giBGA_DriverId == -1) {\r
+ Warning("[BGA ] Unable to register with DevFS, maybe already loaded?");\r
+ return 0;\r
+ }\r
+ \r
+ // Map Framebuffer to hardware address\r
+ gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb)\r
+ \r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn void BGA_Uninstall()\r
+ */\r
+void BGA_Uninstall()\r
+{\r
+ //DevFS_DelDevice( giBGA_DriverId );\r
+ MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
+}\r
+\r
+/**\r
+ * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+ * \brief Read from the framebuffer\r
+ */\r
+Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+ // Check Mode\r
+ if(giBGA_CurrentMode == -1) return -1;\r
+ \r
+ // Check Offset and Length against Framebuffer Size\r
+ if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize)\r
+ return -1;\r
+ \r
+ // Copy from Framebuffer\r
+ memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len);\r
+ return len;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *Buffer)\r
+{ \r
+ ENTER("xoff xlen", off, len);\r
+ \r
+ // Check Mode\r
+ if(giBGA_CurrentMode == -1) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ \r
+ // Check Input against Frambuffer Size\r
+ if(off + len > gBGA_Modes[giBGA_CurrentMode].fbSize) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ \r
+ // Text Mode\r
+ if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT )\r
+ {\r
+ tVT_Char *chars = Buffer;\r
+ int pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
+ int x, y;\r
+ Uint32 *dest;\r
+ \r
+ off /= sizeof(tVT_Char);\r
+ dest = (void*)gBGA_Framebuffer;\r
+ x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
+ y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight;\r
+ dest += y * pitch;\r
+ dest += x * giVT_CharWidth;\r
+ len /= sizeof(tVT_Char);\r
+ while(len--)\r
+ {\r
+ VT_Font_Render(\r
+ chars->Ch,\r
+ dest, pitch,\r
+ VT_Colour12to24(chars->BGCol),\r
+ VT_Colour12to24(chars->FGCol)\r
+ );\r
+ \r
+ dest += giVT_CharWidth;\r
+ \r
+ chars ++;\r
+ x += giVT_CharWidth;\r
+ if( x >= pitch ) {\r
+ x = 0;\r
+ y += giVT_CharHeight;\r
+ dest += pitch*(giVT_CharHeight-1);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Uint8 *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off);\r
+ \r
+ Log("buffer = %p", Buffer);\r
+ Log("Updating Framebuffer (%p to %p)",\r
+ destBuf, destBuf + (Uint)len);\r
+ \r
+ \r
+ // Copy to Frambuffer\r
+ memcpy(destBuf, Buffer, len);\r
+ \r
+ Log("BGA Framebuffer updated");\r
+ }\r
+ \r
+ LEAVE('i', len);\r
+ return len;\r
+}\r
+\r
+/**\r
+ * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+ * \brief Handle messages to the device\r
+ */\r
+INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+{\r
+ int ret = -2;\r
+ ENTER("pNode iId pData", node, ID, Data);\r
+ \r
+ switch(ID)\r
+ {\r
+ case DRV_IOCTL_TYPE:\r
+ ret = DRV_TYPE_VIDEO;\r
+ break;\r
+ case DRV_IOCTL_IDENT:\r
+ memcpy(Data, "BGA1", 4);\r
+ ret = 1;\r
+ break;\r
+ case DRV_IOCTL_VERSION:\r
+ ret = 0x100;\r
+ break;\r
+ case DRV_IOCTL_LOOKUP: // TODO: Implement\r
+ ret = 0;\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_GETSETMODE:\r
+ if( Data )\r
+ ret = BGA_int_UpdateMode(*(int*)(Data));\r
+ else\r
+ ret = giBGA_CurrentMode;\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_FINDMODE:\r
+ ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data);\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_MODEINFO:\r
+ ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
+ break;\r
+ \r
+ // Request Access to LFB\r
+ case VIDEO_IOCTL_REQLFB:\r
+ ret = BGA_int_MapFB( *(void**)Data );\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_SETCURSOR:\r
+ gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x;\r
+ gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y;\r
+ break;\r
+ \r
+ default:\r
+ LEAVE('i', -2);\r
+ return -2;\r
+ }\r
+ \r
+ LEAVE('i', ret);\r
+ return ret;\r
+}\r
+\r
+//== Internal Functions ==\r
+/**\r
+ * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
+ * \brief Writes to a BGA register\r
+ */\r
+void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
+{\r
+ outw(VBE_DISPI_IOPORT_INDEX, reg);\r
+ outw(VBE_DISPI_IOPORT_DATA, value);\r
+}\r
+\r
+INT Uint16 BGA_int_ReadRegister(Uint16 reg)\r
+{\r
+ outw(VBE_DISPI_IOPORT_INDEX, reg);\r
+ return inw(VBE_DISPI_IOPORT_DATA);\r
+}\r
+\r
+#if 0\r
+INT void BGA_int_SetBank(Uint16 bank)\r
+{\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank);\r
+}\r
+#endif\r
+\r
+/**\r
+ * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp)\r
+ * \brief Sets the video mode from the dimensions and bpp given\r
+ */\r
+void BGA_int_SetMode(Uint16 width, Uint16 height)\r
+{\r
+ ENTER("iwidth iheight ibpp", width, height, bpp);\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES, width);\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES, height);\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32);\r
+ BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED);\r
+ //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM);\r
+ LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_UpdateMode(int id)\r
+ * \brief Set current vide mode given a mode id\r
+ */\r
+int BGA_int_UpdateMode(int id)\r
+{\r
+ // Sanity Check\r
+ if(id < 0 || id >= BGA_MODE_COUNT) return -1;\r
+ \r
+ // Check if it is a text mode\r
+ if( gBGA_Modes[id].flags & MODEFLAG_TEXT )\r
+ BGA_int_SetMode(\r
+ gBGA_Modes[id].width*giVT_CharWidth,\r
+ gBGA_Modes[id].height*giVT_CharHeight);\r
+ else // Graphics?\r
+ BGA_int_SetMode(\r
+ gBGA_Modes[id].width,\r
+ gBGA_Modes[id].height);\r
+ \r
+ giBGA_CurrentMode = id;\r
+ return id;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
+ * \brief Find a mode matching the given options\r
+ */\r
+int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
+{\r
+ int i;\r
+ int best = 0, bestFactor = 1000;\r
+ int factor, tmp;\r
+ int rqdProduct = info->width * info->height * info->bpp;\r
+ \r
+ ENTER("pinfo", info);\r
+ LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp);\r
+ \r
+ for(i = 0; i < BGA_MODE_COUNT; i++)\r
+ {\r
+ #if DEBUG >= 2\r
+ LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp);\r
+ #endif\r
+ \r
+ // Check if this mode is the same type as what we want\r
+ if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) )\r
+ continue;\r
+ \r
+ // Ooh! A perfect match\r
+ if(gBGA_Modes[i].width == info->width\r
+ && gBGA_Modes[i].height == info->height\r
+ && gBGA_Modes[i].bpp == info->bpp)\r
+ {\r
+ #if DEBUG >= 2\r
+ LogF("Perfect!\n");\r
+ #endif\r
+ best = i;\r
+ break;\r
+ }\r
+ \r
+ // If not, how close are we?\r
+ tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp;\r
+ tmp -= rqdProduct;\r
+ tmp = tmp < 0 ? -tmp : tmp; // tmp = ABS(tmp)\r
+ factor = tmp * 100 / rqdProduct;\r
+ \r
+ #if DEBUG >= 2\r
+ LogF("factor = %i\n", factor);\r
+ #endif\r
+ \r
+ if(factor < bestFactor)\r
+ {\r
+ bestFactor = factor;\r
+ best = i;\r
+ }\r
+ }\r
+ \r
+ info->id = best;\r
+ info->width = gBGA_Modes[best].width;\r
+ info->height = gBGA_Modes[best].height;\r
+ info->bpp = gBGA_Modes[best].bpp;\r
+ \r
+ info->flags = 0;\r
+ if(gBGA_Modes[best].flags & MODEFLAG_TEXT)\r
+ info->flags |= VIDEO_FLAG_TEXT;\r
+ \r
+ return best;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
+ * \brief Get mode information\r
+ */\r
+int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
+{\r
+ // Sanity Check\r
+ //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
+ // return -EINVAL;\r
+ //}\r
+ \r
+ if(info->id < 0 || info->id >= BGA_MODE_COUNT) return -1;\r
+ \r
+ info->width = gBGA_Modes[info->id].width;\r
+ info->height = gBGA_Modes[info->id].height;\r
+ info->bpp = gBGA_Modes[info->id].bpp;\r
+ \r
+ info->flags = 0;\r
+ if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT)\r
+ info->flags |= VIDEO_FLAG_TEXT;\r
+ \r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_MapFB(void *Dest)\r
+ * \brief Map the framebuffer into a process's space\r
+ * \param Dest User address to load to\r
+ */\r
+int BGA_int_MapFB(void *Dest)\r
+{\r
+ Uint i;\r
+ Uint pages;\r
+ \r
+ // Sanity Check\r
+ if((Uint)Dest > 0xC0000000) return 0;\r
+ if(gBGA_Modes[giBGA_CurrentMode].bpp < 15) return 0; // Only non-pallete modes are supported\r
+ \r
+ // Count required pages\r
+ pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12;\r
+ \r
+ // Check if there is space\r
+ for( i = 0; i < pages; i++ )\r
+ {\r
+ if(MM_GetPhysAddr( (Uint)Dest + (i << 12) ))\r
+ return 0;\r
+ }\r
+ \r
+ // Map\r
+ for( i = 0; i < pages; i++ )\r
+ MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) );\r
+ \r
+ return 1;\r
+}\r
--- /dev/null
+-include ../../Makefile.tpl
+++ /dev/null
-#
-#
-
-OBJ = fdd.o
-NAME = FDD
-
--include ../Makefile.tpl
+++ /dev/null
-/*\r
- * AcessOS 0.1\r
- * Floppy Disk Access Code\r
- */\r
-#define DEBUG 0\r
-#include <acess.h>\r
-#include <modules.h>\r
-#include <fs_devfs.h>\r
-#include <tpl_drv_disk.h>\r
-#include <dma.h>\r
-#include <iocache.h>\r
-\r
-#define WARN 0\r
-\r
-// === CONSTANTS ===\r
-// --- Current Version\r
-#define FDD_VERSION ((0<<8)|(75))\r
-\r
-// --- Options\r
-#define USE_CACHE 0 // Use Sector Cache\r
-#define CACHE_SIZE 32 // Number of cachable sectors\r
-#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation\r
-#define MOTOR_ON_DELAY 500 // Miliseconds\r
-#define MOTOR_OFF_DELAY 2000 // Miliseconds\r
-\r
-// === TYPEDEFS ===\r
-/**\r
- * \brief Representation of a floppy drive\r
- */\r
-typedef struct {\r
- int type;\r
- volatile int motorState; //2 - On, 1 - Spinup, 0 - Off\r
- int track[2];\r
- int timer;\r
- tVFS_Node Node;\r
- #if !USE_CACHE\r
- tIOCache *CacheHandle;\r
- #endif\r
-} t_floppyDevice;\r
-\r
-/**\r
- * \brief Cached Sector\r
- */\r
-typedef struct {\r
- Uint64 timestamp;\r
- Uint16 disk;\r
- Uint16 sector; // Allows 32Mb of addressable space (Plenty for FDD)\r
- Uint8 data[512];\r
-} t_floppySector;\r
-\r
-// === CONSTANTS ===\r
-static const char *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" };\r
-static const int cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 };\r
-static const short cPORTBASE[] = { 0x3F0, 0x370 };\r
-\r
-enum FloppyPorts {\r
- PORT_STATUSA = 0x0,\r
- PORT_STATUSB = 0x1,\r
- PORT_DIGOUTPUT = 0x2,\r
- PORT_MAINSTATUS = 0x4,\r
- PORT_DATARATE = 0x4,\r
- PORT_DATA = 0x5,\r
- PORT_DIGINPUT = 0x7,\r
- PORT_CONFIGCTRL = 0x7\r
-};\r
-\r
-enum FloppyCommands {\r
- FIX_DRIVE_DATA = 0x03,\r
- HECK_DRIVE_STATUS = 0x04,\r
- CALIBRATE_DRIVE = 0x07,\r
- CHECK_INTERRUPT_STATUS = 0x08,\r
- SEEK_TRACK = 0x0F,\r
- READ_SECTOR_ID = 0x4A,\r
- FORMAT_TRACK = 0x4D,\r
- READ_TRACK = 0x42,\r
- READ_SECTOR = 0x66,\r
- WRITE_SECTOR = 0xC5,\r
- WRITE_DELETE_SECTOR = 0xC9,\r
- READ_DELETE_SECTOR = 0xCC,\r
-};\r
-\r
-// === PROTOTYPES ===\r
-// --- Filesystem\r
- int FDD_Install(char **Arguments);\r
-char *FDD_ReadDir(tVFS_Node *Node, int pos);\r
-tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name);\r
- int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
-Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
-// --- 1st Level Disk Access\r
-Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk);\r
-// --- Raw Disk Access\r
- int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer);\r
- int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer);\r
-// --- Helpers\r
-void FDD_IRQHandler(int Num);\r
-void FDD_WaitIRQ();\r
-void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl);\r
-inline void FDD_AquireSpinlock();\r
-inline void FDD_FreeSpinlock();\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock();\r
-inline void FDD_FreeCacheSpinlock();\r
-#endif\r
-void FDD_int_SendByte(int base, char byte);\r
- int FDD_int_GetByte(int base);\r
-void FDD_Reset(int id);\r
-void FDD_Recalibrate(int disk);\r
- int FDD_int_SeekTrack(int disk, int head, int track);\r
-void FDD_int_TimerCallback(int arg);\r
-void FDD_int_StopMotor(int disk);\r
-void FDD_int_StartMotor(int disk);\r
- int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt);\r
-\r
-// === GLOBALS ===\r
-MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL);\r
-t_floppyDevice gFDD_Devices[2];\r
-volatile int fdd_inUse = 0;\r
-volatile int fdd_irq6 = 0;\r
-tDevFS_Driver gFDD_DriverInfo = {\r
- NULL, "fdd",\r
- {\r
- .Size = -1,\r
- .NumACLs = 1,\r
- .ACLs = &gVFS_ACL_EveryoneRX,\r
- .Flags = VFS_FFLAG_DIRECTORY,\r
- .ReadDir = FDD_ReadDir,\r
- .FindDir = FDD_FindDir,\r
- .IOCtl = FDD_IOCtl\r
- }\r
-};\r
-#if USE_CACHE\r
-int siFDD_CacheInUse = 0;\r
-int siFDD_SectorCacheSize = CACHE_SIZE;\r
-t_floppySector sFDD_SectorCache[CACHE_SIZE];\r
-#endif\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int FDD_Install(char **Arguments)\r
- * \brief Installs floppy driver\r
- */\r
-int FDD_Install(char **Arguments)\r
-{\r
- Uint8 data;\r
- \r
- // Determine Floppy Types (From CMOS)\r
- outb(0x70, 0x10);\r
- data = inb(0x71);\r
- gFDD_Devices[0].type = data >> 4;\r
- gFDD_Devices[1].type = data & 0xF;\r
- gFDD_Devices[0].track[0] = -1;\r
- gFDD_Devices[1].track[1] = -1;\r
- \r
- Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
- \r
- // Clear FDD IRQ Flag\r
- FDD_SensInt(0x3F0, NULL, NULL);\r
- // Install IRQ6 Handler\r
- IRQ_AddHandler(6, FDD_IRQHandler);\r
- // Reset Primary FDD Controller\r
- FDD_Reset(0);\r
- \r
- // Initialise Root Node\r
- gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime\r
- = gFDD_DriverInfo.RootNode.ATime = now();\r
- \r
- // Initialise Child Nodes\r
- gFDD_Devices[0].Node.Inode = 0;\r
- gFDD_Devices[0].Node.Flags = 0;\r
- gFDD_Devices[0].Node.NumACLs = 0;\r
- gFDD_Devices[0].Node.Read = FDD_ReadFS;\r
- gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS;\r
- memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node));\r
- \r
- gFDD_Devices[1].Node.Inode = 1;\r
- \r
- // Set Lengths\r
- gFDD_Devices[0].Node.Size = cFDD_SIZES[data >> 4];\r
- gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF];\r
- \r
- // Create Sector Cache\r
- #if USE_CACHE\r
- //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE);\r
- //siFDD_SectorCacheSize = CACHE_SIZE;\r
- #else\r
- if( cFDD_SIZES[data >> 4] ) {\r
- gFDD_Devices[0].CacheHandle = IOCache_Create(\r
- FDD_WriteSector, 0, 512,\r
- gFDD_Devices[0].Node.Size / (512*4)\r
- ); // Cache is 1/4 the size of the disk\r
- }\r
- if( cFDD_SIZES[data & 15] ) {\r
- gFDD_Devices[1].CacheHandle = IOCache_Create(\r
- FDD_WriteSector, 0, 512,\r
- gFDD_Devices[1].Node.Size / (512*4)\r
- ); // Cache is 1/4 the size of the disk\r
- }\r
- #endif\r
- \r
- // Register with devfs\r
- DevFS_AddDevice(&gFDD_DriverInfo);\r
- \r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
- * \brief Read Directory\r
- */\r
-char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
-{\r
- char name[2] = "0\0";\r
- //Update Accessed Time\r
- //gFDD_DrvInfo.rootNode.atime = now();\r
- \r
- //Check for bounds\r
- if(pos >= 2 || pos < 0)\r
- return NULL;\r
- \r
- if(gFDD_Devices[pos].type == 0)\r
- return VFS_SKIP;\r
- \r
- name[0] += pos;\r
- \r
- //Return\r
- return strdup(name);\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename);\r
- * \brief Find File Routine (for vfs_node)\r
- */\r
-tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *Filename)\r
-{\r
- int i;\r
- \r
- ENTER("sFilename", Filename);\r
- \r
- // Sanity check string\r
- if(Filename == NULL) {\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Check string length (should be 1)\r
- if(Filename[0] == '\0' || Filename[1] != '\0') {\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Get First character\r
- i = Filename[0] - '0';\r
- \r
- // Check for 1st disk and if it is present return\r
- if(i == 0 && gFDD_Devices[0].type != 0) {\r
- LEAVE('p', &gFDD_Devices[0].Node);\r
- return &gFDD_Devices[0].Node;\r
- }\r
- \r
- // Check for 2nd disk and if it is present return\r
- if(i == 1 && gFDD_Devices[1].type != 0) {\r
- LEAVE('p', &gFDD_Devices[1].Node);\r
- return &gFDD_Devices[1].Node;\r
- }\r
- \r
- // Else return null\r
- LEAVE('n');\r
- return NULL;\r
-}\r
-\r
-static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL};\r
-/**\r
- * \fn int FDD_IOCtl(tVFS_Node *Node, int id, void *data)\r
- * \brief Stub ioctl function\r
- */\r
-int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
-{\r
- switch(ID)\r
- {\r
- case DRV_IOCTL_TYPE: return DRV_TYPE_DISK;\r
- case DRV_IOCTL_IDENT: return ModUtil_SetIdent(Data, "FDD");\r
- case DRV_IOCTL_VERSION: return FDD_VERSION;\r
- case DRV_IOCTL_LOOKUP: return ModUtil_LookupString((char**)casIOCTLS, Data);\r
- \r
- case DISK_IOCTL_GETBLOCKSIZE: return 512; \r
- \r
- default:\r
- return 0;\r
- }\r
-}\r
-\r
-/**\r
- * \fn Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
- * \brief Read Data from a disk\r
-*/\r
-Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
-{\r
- int i = 0;\r
- int disk;\r
- //Uint32 buf[128];\r
- \r
- ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
- \r
- if(Node == NULL) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- if(Node->Inode != 0 && Node->Inode != 1) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- disk = Node->Inode;\r
- \r
- // Update Accessed Time\r
- Node->ATime = now();\r
- \r
- #if 0\r
- if((Offset & 0x1FF) || (Length & 0x1FF))\r
- {\r
- // Un-Aligned Offset/Length\r
- int startOff = Offset >> 9;\r
- int sectOff = Offset & 0x1FF;\r
- int sectors = (Length + 0x1FF) >> 9;\r
- \r
- LOG("Non-aligned Read");\r
- \r
- //Read Starting Sector\r
- if(!FDD_ReadSector(disk, startOff, buf))\r
- return 0;\r
- memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length);\r
- \r
- // If the data size is one sector or less\r
- if(Length <= 512-sectOff)\r
- {\r
- LEAVE('X', Length);\r
- return Length; //Return\r
- }\r
- Buffer += 512-sectOff;\r
- \r
- //Read Middle Sectors\r
- for( i = 1; i < sectors - 1; i++ )\r
- {\r
- if(!FDD_ReadSector(disk, startOff+i, buf)) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- memcpy(Buffer, buf, 512);\r
- Buffer += 512;\r
- }\r
- \r
- //Read End Sectors\r
- if(!FDD_ReadSector(disk, startOff+i, buf))\r
- return 0;\r
- memcpy(Buffer, buf, (len&0x1FF)-sectOff);\r
-
- LEAVE('X', Length);\r
- return Length;\r
- }\r
- else\r
- {\r
- int count = Length >> 9;\r
- int sector = Offset >> 9;\r
- LOG("Aligned Read");\r
- //Aligned Offset and Length - Simple Code\r
- for( i = 0; i < count; i ++ )\r
- {\r
- FDD_ReadSector(disk, sector, buf);\r
- memcpy(buffer, buf, 512);\r
- buffer += 512;\r
- sector++;\r
- }
- LEAVE('i', Length);\r
- return Length;\r
- }\r
- #endif\r
- \r
- i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk);\r
- LEAVE('i', i);\r
- return i;\r
-}\r
-\r
-/**\r
- * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk)\r
- * \brief Reads \a Count contiguous sectors from a disk\r
- * \param SectorAddr Address of the first sector\r
- * \param Count Number of sectors to read\r
- * \param Buffer Destination Buffer\r
- * \param Disk Disk Number\r
- * \return Number of sectors read\r
- * \note Used as a ::DrvUtil_ReadBlock helper\r
- */\r
-Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk)\r
-{\r
- Uint ret = 0;\r
- while(Count --)\r
- {\r
- if( FDD_ReadSector(Disk, SectorAddr, Buffer) != 1 )\r
- return ret;\r
- \r
- Buffer = (void*)( (tVAddr)Buffer + 512 );\r
- SectorAddr ++;\r
- ret ++;\r
- }\r
- return ret;\r
-}\r
-\r
-/**\r
- * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
- * \fn Read a sector from disk\r
-*/\r
-int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
-{\r
- int cyl, head, sec;\r
- int spt, base;\r
- int i;\r
- int lba = SectorAddr;\r
- \r
- ENTER("idisk Xlba pbuf", disk, lba, buf);\r
- \r
- #if USE_CACHE\r
- FDD_AquireCacheSpinlock();\r
- for( i = 0; i < siFDD_SectorCacheSize; i++ )\r
- {\r
- if(sFDD_SectorCache[i].timestamp == 0) continue;\r
- if(sFDD_SectorCache[i].disk == Disk\r
- && sFDD_SectorCache[i].sector == lba) {\r
- LOG("Found %i in cache %i", lba, i);\r
- memcpy(Buffer, sFDD_SectorCache[i].data, 512);\r
- sFDD_SectorCache[i].timestamp = now();\r
- FDD_FreeCacheSpinlock();\r
- LEAVE('i', 1);\r
- return 1;\r
- }\r
- }\r
- LOG("Read %i from Disk", lba);\r
- FDD_FreeCacheSpinlock();\r
- #else\r
- if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
- LEAVE('i', 1);\r
- return 1;\r
- }\r
- #endif\r
- \r
- base = cPORTBASE[Disk>>1];\r
- \r
- LOG("Calculating Disk Dimensions");\r
- // Get CHS position\r
- if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- \r
- // Remove Old Timer\r
- Time_RemoveTimer(gFDD_Devices[Disk].timer);\r
- // Check if Motor is on\r
- if(gFDD_Devices[Disk].motorState == 0) {\r
- FDD_int_StartMotor(Disk);\r
- }\r
- \r
- LOG("Wait for Motor Spinup");\r
- \r
- // Wait for spinup\r
- while(gFDD_Devices[Disk].motorState == 1) Threads_Yield();\r
- \r
- LOG("C:%i,H:%i,S:%i", cyl, head, sec);\r
- LOG("Acquire Spinlock");\r
- \r
- FDD_AquireSpinlock();\r
- \r
- // Seek to track\r
- outb(base+CALIBRATE_DRIVE, 0);\r
- i = 0;\r
- while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield();\r
- //FDD_SensInt(base, NULL, NULL); // Wait for IRQ\r
- \r
- LOG("Setting DMA for read");\r
- \r
- //Read Data from DMA\r
- DMA_SetChannel(2, 512, 1); // Read 512 Bytes\r
- \r
- LOG("Sending read command");\r
- \r
- //Threads_Wait(100); // Wait for Head to settle\r
- Time_Delay(100);\r
- FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6\r
- FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
- FDD_int_SendByte(base, (Uint8)cyl);\r
- FDD_int_SendByte(base, (Uint8)head);\r
- FDD_int_SendByte(base, (Uint8)sec);\r
- FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val})\r
- FDD_int_SendByte(base, spt); // SPT\r
- FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default)\r
- FDD_int_SendByte(base, 0xFF); // Data Length\r
- \r
- // Wait for IRQ\r
- LOG("Waiting for Data to be read");\r
- FDD_WaitIRQ();\r
- \r
- // Read Data from DMA\r
- LOG(" FDD_ReadSector: Reading Data");\r
- DMA_ReadData(2, 512, Buffer);\r
- \r
- // Clear Input Buffer\r
- LOG("Clearing Input Buffer");\r
- FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
- FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
- \r
- LOG("Realeasing Spinlock and Setting motor to stop");\r
- // Release Spinlock\r
- FDD_FreeSpinlock();\r
- \r
- //Set timer to turn off motor affter a gap\r
- gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer
-\r
- #if USE_CACHE\r
- {\r
- FDD_AquireCacheSpinlock();\r
- int oldest = 0;\r
- for(i=0;i<siFDD_SectorCacheSize;i++)\r
- {\r
- if(sFDD_SectorCache[i].timestamp == 0) {\r
- oldest = i;\r
- break;\r
- }\r
- if(sFDD_SectorCache[i].timestamp < sFDD_SectorCache[oldest].timestamp)\r
- oldest = i;\r
- }\r
- sFDD_SectorCache[oldest].timestamp = now();\r
- sFDD_SectorCache[oldest].disk = Disk;\r
- sFDD_SectorCache[oldest].sector = lba;\r
- memcpy(sFDD_SectorCache[oldest].data, Buffer, 512);\r
- FDD_FreeCacheSpinlock();\r
- }\r
- #else\r
- IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );\r
- #endif\r
-
- LEAVE('i', 1);\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
- * \brief Write a sector to the floppy disk\r
- * \note Not Implemented\r
- */\r
-int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
-{\r
- Warning("[FDD ] Read Only at the moment");\r
- return -1;\r
-}\r
-\r
-/**\r
- * \fn int FDD_int_SeekTrack(int disk, int track)\r
- * \brief Seek disk to selected track\r
- */\r
-int FDD_int_SeekTrack(int disk, int head, int track)\r
-{\r
- Uint8 sr0, cyl;\r
- int base;\r
- \r
- base = cPORTBASE[disk>>1];\r
- \r
- // Check if seeking is needed\r
- if(gFDD_Devices[disk].track[head] == track)\r
- return 1;\r
- \r
- // - Seek Head 0\r
- FDD_int_SendByte(base, SEEK_TRACK);\r
- FDD_int_SendByte(base, (head<<2)|(disk&1));\r
- FDD_int_SendByte(base, track); // Send Seek command\r
- FDD_WaitIRQ();\r
- FDD_SensInt(base, &sr0, &cyl); // Wait for IRQ\r
- if((sr0 & 0xF0) != 0x20) {
- LOG("sr0 = 0x%x", sr0);
- return 0; //Check Status
- }\r
- if(cyl != track) return 0;\r
- \r
- // Set Track in structure\r
- gFDD_Devices[disk].track[head] = track;\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)\r
- * \brief Get Dimensions of a disk\r
- */\r
-int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)\r
-{\r
- switch(type) {\r
- case 0:\r
- return 0;\r
- \r
- // 360Kb 5.25"\r
- case 1:\r
- *spt = 9;\r
- *s = (lba % 9) + 1;\r
- *c = lba / 18;\r
- *h = (lba / 9) & 1;\r
- break;\r
- \r
- // 1220Kb 5.25"\r
- case 2:\r
- *spt = 15;\r
- *s = (lba % 15) + 1;\r
- *c = lba / 30;\r
- *h = (lba / 15) & 1;\r
- break;\r
- \r
- // 720Kb 3.5"\r
- case 3:\r
- *spt = 9;\r
- *s = (lba % 9) + 1;\r
- *c = lba / 18;\r
- *h = (lba / 9) & 1;\r
- break;\r
- \r
- // 1440Kb 3.5"\r
- case 4:\r
- *spt = 18;\r
- *s = (lba % 18) + 1;\r
- *c = lba / 36;\r
- *h = (lba / 18) & 1;\r
- //Log("1440k - lba=%i(0x%x), *s=%i,*c=%i,*h=%i", lba, lba, *s, *c, *h);\r
- break;\r
- \r
- // 2880Kb 3.5"\r
- case 5:\r
- *spt = 36;\r
- *s = (lba % 36) + 1;\r
- *c = lba / 72;\r
- *h = (lba / 32) & 1;\r
- break;\r
- \r
- default:\r
- return -2;\r
- }\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn void FDD_IRQHandler(int Num)\r
- * \brief Handles IRQ6\r
- */\r
-void FDD_IRQHandler(int Num)\r
-{\r
- fdd_irq6 = 1;\r
-}\r
-\r
-/**\r
- * \fn FDD_WaitIRQ()\r
- * \brief Wait for an IRQ6\r
- */\r
-void FDD_WaitIRQ()\r
-{\r
- // Wait for IRQ\r
- while(!fdd_irq6) Threads_Yield();\r
- fdd_irq6 = 0;\r
-}\r
-\r
-void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)\r
-{\r
- FDD_int_SendByte(base, CHECK_INTERRUPT_STATUS);\r
- if(sr0) *sr0 = FDD_int_GetByte(base);\r
- else FDD_int_GetByte(base);\r
- if(cyl) *cyl = FDD_int_GetByte(base);\r
- else FDD_int_GetByte(base);\r
-}\r
-\r
-void FDD_AquireSpinlock()\r
-{\r
- while(fdd_inUse)\r
- Threads_Yield();\r
- fdd_inUse = 1;\r
-}\r
-\r
-inline void FDD_FreeSpinlock()\r
-{\r
- fdd_inUse = 0;\r
-}\r
-\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock()\r
-{\r
- while(siFDD_CacheInUse) Threads_Yield();\r
- siFDD_CacheInUse = 1;\r
-}\r
-inline void FDD_FreeCacheSpinlock()\r
-{\r
- siFDD_CacheInUse = 0;\r
-}\r
-#endif\r
-\r
-/**\r
- * void FDD_int_SendByte(int base, char byte)\r
- * \brief Sends a command to the controller\r
- */\r
-void FDD_int_SendByte(int base, char byte)\r
-{\r
- volatile int state;\r
- int timeout = 128;\r
- for( ; timeout--; )\r
- {\r
- state = inb(base + PORT_MAINSTATUS);\r
- if ((state & 0xC0) == 0x80)\r
- {\r
- outb(base + PORT_DATA, byte);\r
- return;\r
- }\r
- inb(0x80); //Delay\r
- }\r
- #if WARN\r
- Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
- #endif\r
-}\r
-\r
-/**\r
- * int FDD_int_GetByte(int base, char byte)\r
- * \brief Receive data from fdd controller\r
- */\r
-int FDD_int_GetByte(int base)\r
-{\r
- volatile int state;\r
- int timeout;\r
- for( timeout = 128; timeout--; )\r
- {\r
- state = inb((base + PORT_MAINSTATUS));\r
- if ((state & 0xd0) == 0xd0)\r
- return inb(base + PORT_DATA);\r
- inb(0x80);\r
- }\r
- return -1;\r
-}\r
-\r
-/**\r
- * \brief Recalibrate the specified disk\r
- */\r
-void FDD_Recalibrate(int disk)\r
-{\r
- ENTER("idisk", disk);\r
- \r
- LOG("Starting Motor");\r
- FDD_int_StartMotor(disk);\r
- // Wait for Spinup\r
- while(gFDD_Devices[disk].motorState == 1) Threads_Yield();\r
- \r
- LOG("Sending Calibrate Command");\r
- FDD_int_SendByte(cPORTBASE[disk>>1], CALIBRATE_DRIVE);\r
- FDD_int_SendByte(cPORTBASE[disk>>1], disk&1);\r
- \r
- LOG("Waiting for IRQ");\r
- FDD_WaitIRQ();\r
- FDD_SensInt(cPORTBASE[disk>>1], NULL, NULL);\r
- \r
- LOG("Stopping Motor");\r
- FDD_int_StopMotor(disk);\r
- LEAVE('-');\r
-}\r
-\r
-/**\r
- * \brief Reset the specified FDD controller\r
- */\r
-void FDD_Reset(int id)\r
-{\r
- int base = cPORTBASE[id];\r
- \r
- ENTER("iID", id);\r
- \r
- outb(base + PORT_DIGOUTPUT, 0); // Stop Motors & Disable FDC\r
- outb(base + PORT_DIGOUTPUT, 0x0C); // Re-enable FDC (DMA and Enable)\r
- \r
- LOG("Awaiting IRQ");\r
- \r
- FDD_WaitIRQ();\r
- FDD_SensInt(base, NULL, NULL);\r
- \r
- LOG("Setting Driver Info");\r
- outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s\r
- FDD_int_SendByte(base, FIX_DRIVE_DATA); // Step and Head Load Times\r
- FDD_int_SendByte(base, 0xDF); // Step Rate Time, Head Unload Time (Nibble each)\r
- FDD_int_SendByte(base, 0x02); // Head Load Time >> 1\r
- while(FDD_int_SeekTrack(0, 0, 1) == 0); // set track\r
- while(FDD_int_SeekTrack(0, 1, 1) == 0); // set track\r
- \r
- LOG("Recalibrating Disk");\r
- FDD_Recalibrate((id<<1)|0);\r
- FDD_Recalibrate((id<<1)|1);
-\r
- LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn void FDD_int_TimerCallback()\r
- * \brief Called by timer\r
- */\r
-void FDD_int_TimerCallback(int arg)\r
-{\r
- ENTER("iarg", arg);\r
- if(gFDD_Devices[arg].motorState == 1)\r
- gFDD_Devices[arg].motorState = 2;\r
- Time_RemoveTimer(gFDD_Devices[arg].timer);\r
- gFDD_Devices[arg].timer = -1;\r
- LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn void FDD_int_StartMotor(char disk)\r
- * \brief Starts FDD Motor\r
- */\r
-void FDD_int_StartMotor(int disk)\r
-{\r
- Uint8 state;\r
- state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
- state |= 1 << (4+disk);\r
- outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
- gFDD_Devices[disk].motorState = 1;\r
- gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk);\r
-}\r
-\r
-/**\r
- * \fn void FDD_int_StopMotor(int disk)\r
- * \brief Stops FDD Motor\r
- */\r
-void FDD_int_StopMotor(int disk)\r
-{\r
- Uint8 state;\r
- state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
- state &= ~( 1 << (4+disk) );\r
- outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
- gFDD_Devices[disk].motorState = 0;\r
-}\r
-\r
-/**\r
- * \fn void ModuleUnload()\r
- * \brief Prepare the module for removal\r
- */\r
-void ModuleUnload()\r
-{\r
- int i;\r
- FDD_AquireSpinlock();\r
- for(i=0;i<4;i++) {\r
- Time_RemoveTimer(gFDD_Devices[i].timer);\r
- FDD_int_StopMotor(i);\r
- }\r
- //IRQ_Clear(6);\r
-}\r
+++ /dev/null
-#
-#
-
-OBJ = ext2.o read.o dir.o write.o
-NAME = FS_Ext2
-
--include ../Makefile.tpl
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*\r
- * Acess OS\r
- * Ext2 Driver Version 1\r
- */\r
-/**\r
- * \file fs/ext2.c\r
- * \brief Second Extended Filesystem Driver\r
- * \todo Implement file full write support\r
- */\r
-#define DEBUG 1\r
-#define VERBOSE 0\r
-#include "ext2_common.h"\r
-#include <modules.h>\r
-\r
-// === PROTOTYPES ===\r
- int Ext2_Install(char **Arguments);\r
-// Interface Functions\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options);\r
-void Ext2_Unmount(tVFS_Node *Node);\r
-void Ext2_CloseFile(tVFS_Node *Node);\r
-// Internal Helpers\r
- int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\r
-tExt2_Disk gExt2_disks[6];\r
- int giExt2_count = 0;\r
-tVFS_Driver gExt2_FSInfo = {\r
- "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
- };\r
-\r
-// === CODE ===\r
-\r
-/**\r
- * \fn int Ext2_Install(char **Arguments)\r
- * \brief Install the Ext2 Filesystem Driver\r
- */\r
-int Ext2_Install(char **Arguments)\r
-{\r
- VFS_AddDriver( &gExt2_FSInfo );\r
- return 1;\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
- \brief Initializes a device to be read by by the driver\r
- \param Device String - Device to read from\r
- \param Options NULL Terminated array of option strings\r
- \return Root Node\r
-*/\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
-{\r
- tExt2_Disk *disk;\r
- int fd;\r
- int groupCount;\r
- tExt2_SuperBlock sb;\r
- tExt2_Inode inode;\r
- \r
- ENTER("sDevice pOptions", Device, Options);\r
- \r
- // Open Disk\r
- fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device\r
- if(fd == -1) {\r
- Warning("[EXT2 ] Unable to open '%s'", Device);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Read Superblock at offset 1024\r
- VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock\r
- \r
- // Sanity Check Magic value\r
- if(sb.s_magic != 0xEF53) {\r
- Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Get Group count\r
- groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
- LOG("groupCount = %i", groupCount);\r
- \r
- // Allocate Disk Information\r
- disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
- if(!disk) {\r
- Warning("[EXT2 ] Unable to allocate disk structure");\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- disk->FD = fd;\r
- memcpy(&disk->SuperBlock, &sb, 1024);\r
- disk->GroupCount = groupCount;\r
- \r
- // Get an inode cache handle\r
- disk->CacheID = Inode_GetHandle();\r
- \r
- // Get Block Size\r
- LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
- disk->BlockSize = 1024 << sb.s_log_block_size;\r
- \r
- // Read Group Information\r
- VFS_ReadAt(\r
- disk->FD,\r
- sb.s_first_data_block * disk->BlockSize + 1024,\r
- sizeof(tExt2_Group)*groupCount,\r
- disk->Groups\r
- );\r
- \r
- #if VERBOSE\r
- LOG("Block Group 0");\r
- LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
- LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
- LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
- LOG("Block Group 1");\r
- LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
- LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
- LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
- #endif\r
- \r
- // Get root Inode\r
- Ext2_int_ReadInode(disk, 2, &inode);\r
- \r
- // Create Root Node\r
- memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
- disk->RootNode.Inode = 2; // Root inode ID\r
- disk->RootNode.ImplPtr = disk; // Save disk pointer\r
- disk->RootNode.Size = -1; // Fill in later (on readdir)\r
- disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
- \r
- disk->RootNode.ReadDir = Ext2_ReadDir;\r
- disk->RootNode.FindDir = Ext2_FindDir;\r
- //disk->RootNode.Relink = Ext2_Relink;\r
- \r
- // Complete root node\r
- disk->RootNode.UID = inode.i_uid;\r
- disk->RootNode.GID = inode.i_gid;\r
- disk->RootNode.NumACLs = 1;\r
- disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
- \r
- #if DEBUG\r
- LOG("inode.i_size = 0x%x", inode.i_size);\r
- LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
- #endif\r
- \r
- LEAVE('p', &disk->RootNode);\r
- return &disk->RootNode;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_Unmount(tVFS_Node *Node)\r
- * \brief Close a mounted device\r
- */\r
-void Ext2_Unmount(tVFS_Node *Node)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- \r
- VFS_Close( disk->FD );\r
- Inode_ClearCache( disk->CacheID );\r
- memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
- free(disk);\r
-}\r
-\r
-/**\r
- * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
- * \brief Close a file (Remove it from the cache)\r
- */\r
-void Ext2_CloseFile(tVFS_Node *Node)\r
-{\r
- tExt2_Disk *disk = Node->ImplPtr;\r
- Inode_UncacheNode(disk->CacheID, Node->Inode);\r
- return ;\r
-}\r
-\r
-//==================================\r
-//= INTERNAL FUNCTIONS =\r
-//==================================\r
-\r
-\r
-/**\r
- * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
- * \brief Gets the inode descriptor for a node\r
- * \param Node node to get the Inode of\r
- * \param Inode Destination\r
- */\r
-int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
-{\r
- return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
-}\r
-\r
-/**\r
- * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
- * \brief Read an inode into memory\r
- */\r
-int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
-{\r
- int group, subId;\r
- \r
- //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
- //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
- \r
- if(InodeId == 0) return 0;\r
- \r
- InodeId --; // Inodes are numbered starting at 1\r
- \r
- group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
- subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
- \r
- //LOG("group=%i, subId = %i", group, subId);\r
- \r
- // Read Inode\r
- VFS_ReadAt(Disk->FD,\r
- Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
- sizeof(tExt2_Inode),\r
- Inode);\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
- * \brief Get the address of a block from an inode's list\r
- * \param Disk Disk information structure\r
- * \param Blocks Pointer to an inode's block list\r
- * \param BlockNum Block index in list\r
- */\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
-{\r
- Uint32 *iBlocks;\r
- // Direct Blocks\r
- if(BlockNum < 12)\r
- return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
- \r
- // Single Indirect Blocks\r
- iBlocks = malloc( Disk->BlockSize );\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- \r
- BlockNum -= 12;\r
- if(BlockNum < 256) {\r
- BlockNum = iBlocks[BlockNum];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
- }\r
- \r
- // Double Indirect Blocks\r
- if(BlockNum < 256*256)\r
- {\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- BlockNum = iBlocks[BlockNum%256];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
- }\r
- // Triple Indirect Blocks\r
- VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
- BlockNum = iBlocks[BlockNum%256];\r
- free(iBlocks);\r
- return (Uint64)BlockNum * Disk->BlockSize;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
- * \brief Allocate an inode (from the current group preferably)\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param Parent Inode ID of the parent (used to locate the child nearby)\r
- */\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
-{\r
-// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
- return 0;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
- * \brief Updates the superblock\r
- */\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
-{\r
- int bpg = Disk->SuperBlock.s_blocks_per_group;\r
- int ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
- int i;\r
- \r
- // Update Primary\r
- VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
- \r
- // Secondaries\r
- // at Block Group 1, 3^n, 5^n, 7^n\r
- \r
- // 1\r
- if(ngrp <= 1) return;\r
- VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
- \r
- // Powers of 3\r
- for( i = 3; i < ngrp; i *= 3 )\r
- VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
- \r
- // Powers of 5\r
- for( i = 5; i < ngrp; i *= 5 )\r
- VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
- \r
- // Powers of 7\r
- for( i = 7; i < ngrp; i *= 7 )\r
- VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-}\r
+++ /dev/null
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file ext2_common.h
- * \brief Second Extended Filesystem Driver
- */
-#ifndef _EXT2_COMMON_H
-#define _EXT2_COMMON_H
-#include <acess.h>
-#include <vfs.h>
-#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
+++ /dev/null
-/**\r
- * Acess2\r
- * \file ext2fs.h\r
- * \brief EXT2 Filesystem Driver\r
- */\r
-#ifndef _EXT2FS_H_\r
-#define _EXT2FS_H_\r
-\r
-/**\r
- \name Inode Flag Values\r
- \{\r
-*/\r
-#define EXT2_S_IFMT 0xF000 //!< Format Mask\r
-#define EXT2_S_IFSOCK 0xC000 //!< Socket\r
-#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link\r
-#define EXT2_S_IFREG 0x8000 //!< Regular File\r
-#define EXT2_S_IFBLK 0x6000 //!< Block Device\r
-#define EXT2_S_IFDIR 0x4000 //!< Directory\r
-#define EXT2_S_IFCHR 0x2000 //!< Character Device\r
-#define EXT2_S_IFIFO 0x1000 //!< FIFO\r
-#define EXT2_S_ISUID 0x0800 //!< SUID\r
-#define EXT2_S_ISGID 0x0400 //!< SGID\r
-#define EXT2_S_ISVTX 0x0200 //!< sticky bit\r
-#define EXT2_S_IRWXU 0700 //!< user access rights mask\r
-#define EXT2_S_IRUSR 0400 //!< Owner Read\r
-#define EXT2_S_IWUSR 0200 //!< Owner Write\r
-#define EXT2_S_IXUSR 0100 //!< Owner Execute\r
-#define EXT2_S_IRWXG 0070 //!< Group Access rights mask\r
-#define EXT2_S_IRGRP 0040 //!< Group Read\r
-#define EXT2_S_IWGRP 0020 //!< Group Write\r
-#define EXT2_S_IXGRP 0010 //!< Group Execute\r
-#define EXT2_S_IRWXO 0007 //!< Global Access rights mask\r
-#define EXT2_S_IROTH 0004 //!< Global Read\r
-#define EXT2_S_IWOTH 0002 //!< Global Write\r
-#define EXT2_S_IXOTH 0001 //!< Global Execute\r
-//! \}\r
-\r
-#define EXT2_NAME_LEN 255 //!< Maximum Name Length\r
-\r
-// === TYPEDEFS ===\r
-typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
-typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
-typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
-typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
-\r
-// === STRUCTURES ===\r
-/**\r
- * \brief EXT2 Superblock Structure\r
- */\r
-struct ext2_super_block_s {\r
- Uint32 s_inodes_count; //!< Inodes count\r
- Uint32 s_blocks_count; //!< Blocks count\r
- Uint32 s_r_blocks_count; //!< Reserved blocks count\r
- Uint32 s_free_blocks_count; //!< Free blocks count\r
- Uint32 s_free_inodes_count; //!< Free inodes count\r
- Uint32 s_first_data_block; //!< First Data Block\r
- Uint32 s_log_block_size; //!< Block size\r
- Sint32 s_log_frag_size; //!< Fragment size\r
- Uint32 s_blocks_per_group; //!< Number Blocks per group\r
- Uint32 s_frags_per_group; //!< Number Fragments per group\r
- Uint32 s_inodes_per_group; //!< Number Inodes per group\r
- Uint32 s_mtime; //!< Mount time\r
- Uint32 s_wtime; //!< Write time\r
- Uint16 s_mnt_count; //!< Mount count\r
- Sint16 s_max_mnt_count; //!< Maximal mount count\r
- Uint16 s_magic; //!< Magic signature\r
- Uint16 s_state; //!< File system state\r
- Uint16 s_errors; //!< Behaviour when detecting errors\r
- Uint16 s_pad; //!< Padding\r
- Uint32 s_lastcheck; //!< time of last check\r
- Uint32 s_checkinterval; //!< max. time between checks\r
- Uint32 s_creator_os; //!< Formatting OS\r
- Uint32 s_rev_level; //!< Revision level\r
- Uint16 s_def_resuid; //!< Default uid for reserved blocks\r
- Uint16 s_def_resgid; //!< Default gid for reserved blocks\r
- Uint32 s_reserved[235]; //!< Padding to the end of the block\r
-};\r
-\r
-/**\r
- * \struct ext2_inode_s\r
- * \brief EXT2 Inode Definition\r
- */\r
-struct ext2_inode_s {\r
- Uint16 i_mode; //!< File mode\r
- Uint16 i_uid; //!< Owner Uid\r
- Uint32 i_size; //!< Size in bytes\r
- Uint32 i_atime; //!< Access time\r
- Uint32 i_ctime; //!< Creation time\r
- Uint32 i_mtime; //!< Modification time\r
- Uint32 i_dtime; //!< Deletion Time\r
- Uint16 i_gid; //!< Group Id\r
- Uint16 i_links_count; //!< Links count\r
- Uint32 i_blocks; //!< Number of blocks allocated for the file\r
- Uint32 i_flags; //!< File flags\r
- union {\r
- Uint32 linux_reserved1; //!< Linux: Reserved\r
- Uint32 hurd_translator; //!< HURD: Translator\r
- Uint32 masix_reserved1; //!< Masix: Reserved\r
- } osd1; //!< OS dependent 1\r
- Uint32 i_block[15]; //!< Pointers to blocks\r
- Uint32 i_version; //!< File version (for NFS)\r
- Uint32 i_file_acl; //!< File ACL\r
- Uint32 i_dir_acl; //!< Directory ACL / Extended File Size\r
- Uint32 i_faddr; //!< Fragment address\r
- union {\r
- struct {\r
- Uint8 l_i_frag; //!< Fragment number\r
- Uint8 l_i_fsize; //!< Fragment size\r
- Uint16 i_pad1; //!< Padding\r
- Uint32 l_i_reserved2[2]; //!< Reserved\r
- } linux2;\r
- struct {\r
- Uint8 h_i_frag; //!< Fragment number\r
- Uint8 h_i_fsize; //!< Fragment size\r
- Uint16 h_i_mode_high; //!< Mode High Bits\r
- Uint16 h_i_uid_high; //!< UID High Bits\r
- Uint16 h_i_gid_high; //!< GID High Bits\r
- Uint32 h_i_author; //!< Creator ID\r
- } hurd2;\r
- struct {\r
- Uint8 m_i_frag; //!< Fragment number\r
- Uint8 m_i_fsize; //!< Fragment size\r
- Uint16 m_pad1; //!< Padding\r
- Uint32 m_i_reserved2[2]; //!< reserved\r
- } masix2;\r
- } osd2; //!< OS dependent 2\r
-};\r
-\r
-/**\r
- * \struct ext2_group_desc_s\r
- * \brief EXT2 Group Descriptor\r
- */\r
-struct ext2_group_desc_s {\r
- Uint32 bg_block_bitmap; //!< Blocks bitmap block\r
- Uint32 bg_inode_bitmap; //!< Inodes bitmap block\r
- Uint32 bg_inode_table; //!< Inodes table block\r
- Uint16 bg_free_blocks_count; //!< Free blocks count\r
- Uint16 bg_free_inodes_count; //!< Free inodes count\r
- Uint16 bg_used_dirs_count; //!< Directories count\r
- Uint16 bg_pad; //!< Padding\r
- Uint32 bg_reserved[3]; //!< Reserved\r
-};\r
-\r
-/**\r
- * \brief EXT2 Directory Entry\r
- * \note The name may take up less than 255 characters\r
- */\r
-struct ext2_dir_entry_s {\r
- Uint32 inode; //!< Inode number\r
- Uint16 rec_len; //!< Directory entry length\r
- Uint8 name_len; //!< Short Name Length\r
- Uint8 type; //!< File Type\r
- char name[]; //!< File name\r
-};\r
-\r
-#endif\r
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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;
-}
--- /dev/null
+#
+#
+
+OBJ = ext2.o read.o dir.o write.o
+NAME = FS_Ext2
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*\r
+ * Acess OS\r
+ * Ext2 Driver Version 1\r
+ */\r
+/**\r
+ * \file fs/ext2.c\r
+ * \brief Second Extended Filesystem Driver\r
+ * \todo Implement file full write support\r
+ */\r
+#define DEBUG 1\r
+#define VERBOSE 0\r
+#include "ext2_common.h"\r
+#include <modules.h>\r
+\r
+// === PROTOTYPES ===\r
+ int Ext2_Install(char **Arguments);\r
+// Interface Functions\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options);\r
+void Ext2_Unmount(tVFS_Node *Node);\r
+void Ext2_CloseFile(tVFS_Node *Node);\r
+// Internal Helpers\r
+ int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\r
+tExt2_Disk gExt2_disks[6];\r
+ int giExt2_count = 0;\r
+tVFS_Driver gExt2_FSInfo = {\r
+ "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
+ };\r
+\r
+// === CODE ===\r
+\r
+/**\r
+ * \fn int Ext2_Install(char **Arguments)\r
+ * \brief Install the Ext2 Filesystem Driver\r
+ */\r
+int Ext2_Install(char **Arguments)\r
+{\r
+ VFS_AddDriver( &gExt2_FSInfo );\r
+ return 1;\r
+}\r
+\r
+/**\r
+ \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+ \brief Initializes a device to be read by by the driver\r
+ \param Device String - Device to read from\r
+ \param Options NULL Terminated array of option strings\r
+ \return Root Node\r
+*/\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+{\r
+ tExt2_Disk *disk;\r
+ int fd;\r
+ int groupCount;\r
+ tExt2_SuperBlock sb;\r
+ tExt2_Inode inode;\r
+ \r
+ ENTER("sDevice pOptions", Device, Options);\r
+ \r
+ // Open Disk\r
+ fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device\r
+ if(fd == -1) {\r
+ Warning("[EXT2 ] Unable to open '%s'", Device);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Read Superblock at offset 1024\r
+ VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock\r
+ \r
+ // Sanity Check Magic value\r
+ if(sb.s_magic != 0xEF53) {\r
+ Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
+ VFS_Close(fd);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Get Group count\r
+ groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
+ LOG("groupCount = %i", groupCount);\r
+ \r
+ // Allocate Disk Information\r
+ disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
+ if(!disk) {\r
+ Warning("[EXT2 ] Unable to allocate disk structure");\r
+ VFS_Close(fd);\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ disk->FD = fd;\r
+ memcpy(&disk->SuperBlock, &sb, 1024);\r
+ disk->GroupCount = groupCount;\r
+ \r
+ // Get an inode cache handle\r
+ disk->CacheID = Inode_GetHandle();\r
+ \r
+ // Get Block Size\r
+ LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
+ disk->BlockSize = 1024 << sb.s_log_block_size;\r
+ \r
+ // Read Group Information\r
+ VFS_ReadAt(\r
+ disk->FD,\r
+ sb.s_first_data_block * disk->BlockSize + 1024,\r
+ sizeof(tExt2_Group)*groupCount,\r
+ disk->Groups\r
+ );\r
+ \r
+ #if VERBOSE\r
+ LOG("Block Group 0");\r
+ LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
+ LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
+ LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
+ LOG("Block Group 1");\r
+ LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
+ LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
+ LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
+ #endif\r
+ \r
+ // Get root Inode\r
+ Ext2_int_ReadInode(disk, 2, &inode);\r
+ \r
+ // Create Root Node\r
+ memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
+ disk->RootNode.Inode = 2; // Root inode ID\r
+ disk->RootNode.ImplPtr = disk; // Save disk pointer\r
+ disk->RootNode.Size = -1; // Fill in later (on readdir)\r
+ disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
+ \r
+ disk->RootNode.ReadDir = Ext2_ReadDir;\r
+ disk->RootNode.FindDir = Ext2_FindDir;\r
+ //disk->RootNode.Relink = Ext2_Relink;\r
+ \r
+ // Complete root node\r
+ disk->RootNode.UID = inode.i_uid;\r
+ disk->RootNode.GID = inode.i_gid;\r
+ disk->RootNode.NumACLs = 1;\r
+ disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
+ \r
+ #if DEBUG\r
+ LOG("inode.i_size = 0x%x", inode.i_size);\r
+ LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
+ #endif\r
+ \r
+ LEAVE('p', &disk->RootNode);\r
+ return &disk->RootNode;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_Unmount(tVFS_Node *Node)\r
+ * \brief Close a mounted device\r
+ */\r
+void Ext2_Unmount(tVFS_Node *Node)\r
+{\r
+ tExt2_Disk *disk = Node->ImplPtr;\r
+ \r
+ VFS_Close( disk->FD );\r
+ Inode_ClearCache( disk->CacheID );\r
+ memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
+ free(disk);\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
+ * \brief Close a file (Remove it from the cache)\r
+ */\r
+void Ext2_CloseFile(tVFS_Node *Node)\r
+{\r
+ tExt2_Disk *disk = Node->ImplPtr;\r
+ Inode_UncacheNode(disk->CacheID, Node->Inode);\r
+ return ;\r
+}\r
+\r
+//==================================\r
+//= INTERNAL FUNCTIONS =\r
+//==================================\r
+\r
+\r
+/**\r
+ * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
+ * \brief Gets the inode descriptor for a node\r
+ * \param Node node to get the Inode of\r
+ * \param Inode Destination\r
+ */\r
+int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
+{\r
+ return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
+}\r
+\r
+/**\r
+ * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+ * \brief Read an inode into memory\r
+ */\r
+int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+{\r
+ int group, subId;\r
+ \r
+ //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
+ //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+ \r
+ if(InodeId == 0) return 0;\r
+ \r
+ InodeId --; // Inodes are numbered starting at 1\r
+ \r
+ group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+ subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+ \r
+ //LOG("group=%i, subId = %i", group, subId);\r
+ \r
+ // Read Inode\r
+ VFS_ReadAt(Disk->FD,\r
+ Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+ sizeof(tExt2_Inode),\r
+ Inode);\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+ * \brief Get the address of a block from an inode's list\r
+ * \param Disk Disk information structure\r
+ * \param Blocks Pointer to an inode's block list\r
+ * \param BlockNum Block index in list\r
+ */\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+{\r
+ Uint32 *iBlocks;\r
+ // Direct Blocks\r
+ if(BlockNum < 12)\r
+ return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
+ \r
+ // Single Indirect Blocks\r
+ iBlocks = malloc( Disk->BlockSize );\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ \r
+ BlockNum -= 12;\r
+ if(BlockNum < 256) {\r
+ BlockNum = iBlocks[BlockNum];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+ }\r
+ \r
+ // Double Indirect Blocks\r
+ if(BlockNum < 256*256)\r
+ {\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ BlockNum = iBlocks[BlockNum%256];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+ }\r
+ // Triple Indirect Blocks\r
+ VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+ BlockNum = iBlocks[BlockNum%256];\r
+ free(iBlocks);\r
+ return (Uint64)BlockNum * Disk->BlockSize;\r
+}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+ * \brief Allocate an inode (from the current group preferably)\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param Parent Inode ID of the parent (used to locate the child nearby)\r
+ */\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+{\r
+// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+ * \brief Updates the superblock\r
+ */\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+{\r
+ int bpg = Disk->SuperBlock.s_blocks_per_group;\r
+ int ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
+ int i;\r
+ \r
+ // Update Primary\r
+ VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
+ \r
+ // Secondaries\r
+ // at Block Group 1, 3^n, 5^n, 7^n\r
+ \r
+ // 1\r
+ if(ngrp <= 1) return;\r
+ VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 3\r
+ for( i = 3; i < ngrp; i *= 3 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 5\r
+ for( i = 5; i < ngrp; i *= 5 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+ \r
+ // Powers of 7\r
+ for( i = 7; i < ngrp; i *= 7 )\r
+ VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+}\r
--- /dev/null
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file ext2_common.h
+ * \brief Second Extended Filesystem Driver
+ */
+#ifndef _EXT2_COMMON_H
+#define _EXT2_COMMON_H
+#include <acess.h>
+#include <vfs.h>
+#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
--- /dev/null
+/**\r
+ * Acess2\r
+ * \file ext2fs.h\r
+ * \brief EXT2 Filesystem Driver\r
+ */\r
+#ifndef _EXT2FS_H_\r
+#define _EXT2FS_H_\r
+\r
+/**\r
+ \name Inode Flag Values\r
+ \{\r
+*/\r
+#define EXT2_S_IFMT 0xF000 //!< Format Mask\r
+#define EXT2_S_IFSOCK 0xC000 //!< Socket\r
+#define EXT2_S_IFLNK 0xA000 //!< Symbolic Link\r
+#define EXT2_S_IFREG 0x8000 //!< Regular File\r
+#define EXT2_S_IFBLK 0x6000 //!< Block Device\r
+#define EXT2_S_IFDIR 0x4000 //!< Directory\r
+#define EXT2_S_IFCHR 0x2000 //!< Character Device\r
+#define EXT2_S_IFIFO 0x1000 //!< FIFO\r
+#define EXT2_S_ISUID 0x0800 //!< SUID\r
+#define EXT2_S_ISGID 0x0400 //!< SGID\r
+#define EXT2_S_ISVTX 0x0200 //!< sticky bit\r
+#define EXT2_S_IRWXU 0700 //!< user access rights mask\r
+#define EXT2_S_IRUSR 0400 //!< Owner Read\r
+#define EXT2_S_IWUSR 0200 //!< Owner Write\r
+#define EXT2_S_IXUSR 0100 //!< Owner Execute\r
+#define EXT2_S_IRWXG 0070 //!< Group Access rights mask\r
+#define EXT2_S_IRGRP 0040 //!< Group Read\r
+#define EXT2_S_IWGRP 0020 //!< Group Write\r
+#define EXT2_S_IXGRP 0010 //!< Group Execute\r
+#define EXT2_S_IRWXO 0007 //!< Global Access rights mask\r
+#define EXT2_S_IROTH 0004 //!< Global Read\r
+#define EXT2_S_IWOTH 0002 //!< Global Write\r
+#define EXT2_S_IXOTH 0001 //!< Global Execute\r
+//! \}\r
+\r
+#define EXT2_NAME_LEN 255 //!< Maximum Name Length\r
+\r
+// === TYPEDEFS ===\r
+typedef struct ext2_inode_s tExt2_Inode; //!< Inode Type\r
+typedef struct ext2_super_block_s tExt2_SuperBlock; //!< Superblock Type\r
+typedef struct ext2_group_desc_s tExt2_Group; //!< Group Descriptor Type\r
+typedef struct ext2_dir_entry_s tExt2_DirEnt; //!< Directory Entry Type\r
+\r
+// === STRUCTURES ===\r
+/**\r
+ * \brief EXT2 Superblock Structure\r
+ */\r
+struct ext2_super_block_s {\r
+ Uint32 s_inodes_count; //!< Inodes count\r
+ Uint32 s_blocks_count; //!< Blocks count\r
+ Uint32 s_r_blocks_count; //!< Reserved blocks count\r
+ Uint32 s_free_blocks_count; //!< Free blocks count\r
+ Uint32 s_free_inodes_count; //!< Free inodes count\r
+ Uint32 s_first_data_block; //!< First Data Block\r
+ Uint32 s_log_block_size; //!< Block size\r
+ Sint32 s_log_frag_size; //!< Fragment size\r
+ Uint32 s_blocks_per_group; //!< Number Blocks per group\r
+ Uint32 s_frags_per_group; //!< Number Fragments per group\r
+ Uint32 s_inodes_per_group; //!< Number Inodes per group\r
+ Uint32 s_mtime; //!< Mount time\r
+ Uint32 s_wtime; //!< Write time\r
+ Uint16 s_mnt_count; //!< Mount count\r
+ Sint16 s_max_mnt_count; //!< Maximal mount count\r
+ Uint16 s_magic; //!< Magic signature\r
+ Uint16 s_state; //!< File system state\r
+ Uint16 s_errors; //!< Behaviour when detecting errors\r
+ Uint16 s_pad; //!< Padding\r
+ Uint32 s_lastcheck; //!< time of last check\r
+ Uint32 s_checkinterval; //!< max. time between checks\r
+ Uint32 s_creator_os; //!< Formatting OS\r
+ Uint32 s_rev_level; //!< Revision level\r
+ Uint16 s_def_resuid; //!< Default uid for reserved blocks\r
+ Uint16 s_def_resgid; //!< Default gid for reserved blocks\r
+ Uint32 s_reserved[235]; //!< Padding to the end of the block\r
+};\r
+\r
+/**\r
+ * \struct ext2_inode_s\r
+ * \brief EXT2 Inode Definition\r
+ */\r
+struct ext2_inode_s {\r
+ Uint16 i_mode; //!< File mode\r
+ Uint16 i_uid; //!< Owner Uid\r
+ Uint32 i_size; //!< Size in bytes\r
+ Uint32 i_atime; //!< Access time\r
+ Uint32 i_ctime; //!< Creation time\r
+ Uint32 i_mtime; //!< Modification time\r
+ Uint32 i_dtime; //!< Deletion Time\r
+ Uint16 i_gid; //!< Group Id\r
+ Uint16 i_links_count; //!< Links count\r
+ Uint32 i_blocks; //!< Number of blocks allocated for the file\r
+ Uint32 i_flags; //!< File flags\r
+ union {\r
+ Uint32 linux_reserved1; //!< Linux: Reserved\r
+ Uint32 hurd_translator; //!< HURD: Translator\r
+ Uint32 masix_reserved1; //!< Masix: Reserved\r
+ } osd1; //!< OS dependent 1\r
+ Uint32 i_block[15]; //!< Pointers to blocks\r
+ Uint32 i_version; //!< File version (for NFS)\r
+ Uint32 i_file_acl; //!< File ACL\r
+ Uint32 i_dir_acl; //!< Directory ACL / Extended File Size\r
+ Uint32 i_faddr; //!< Fragment address\r
+ union {\r
+ struct {\r
+ Uint8 l_i_frag; //!< Fragment number\r
+ Uint8 l_i_fsize; //!< Fragment size\r
+ Uint16 i_pad1; //!< Padding\r
+ Uint32 l_i_reserved2[2]; //!< Reserved\r
+ } linux2;\r
+ struct {\r
+ Uint8 h_i_frag; //!< Fragment number\r
+ Uint8 h_i_fsize; //!< Fragment size\r
+ Uint16 h_i_mode_high; //!< Mode High Bits\r
+ Uint16 h_i_uid_high; //!< UID High Bits\r
+ Uint16 h_i_gid_high; //!< GID High Bits\r
+ Uint32 h_i_author; //!< Creator ID\r
+ } hurd2;\r
+ struct {\r
+ Uint8 m_i_frag; //!< Fragment number\r
+ Uint8 m_i_fsize; //!< Fragment size\r
+ Uint16 m_pad1; //!< Padding\r
+ Uint32 m_i_reserved2[2]; //!< reserved\r
+ } masix2;\r
+ } osd2; //!< OS dependent 2\r
+};\r
+\r
+/**\r
+ * \struct ext2_group_desc_s\r
+ * \brief EXT2 Group Descriptor\r
+ */\r
+struct ext2_group_desc_s {\r
+ Uint32 bg_block_bitmap; //!< Blocks bitmap block\r
+ Uint32 bg_inode_bitmap; //!< Inodes bitmap block\r
+ Uint32 bg_inode_table; //!< Inodes table block\r
+ Uint16 bg_free_blocks_count; //!< Free blocks count\r
+ Uint16 bg_free_inodes_count; //!< Free inodes count\r
+ Uint16 bg_used_dirs_count; //!< Directories count\r
+ Uint16 bg_pad; //!< Padding\r
+ Uint32 bg_reserved[3]; //!< Reserved\r
+};\r
+\r
+/**\r
+ * \brief EXT2 Directory Entry\r
+ * \note The name may take up less than 255 characters\r
+ */\r
+struct ext2_dir_entry_s {\r
+ Uint32 inode; //!< Inode number\r
+ Uint16 rec_len; //!< Directory entry length\r
+ Uint8 name_len; //!< Short Name Length\r
+ Uint8 type; //!< File Type\r
+ char name[]; //!< File name\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+-include ../../Makefile.tpl
--- /dev/null
+-include ../../Makefile.tpl
--- /dev/null
+#
+#
+
+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
--- /dev/null
+/**
+ * \file buf.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file cb.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file imc.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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__);
+}
--- /dev/null
+/**
+ * \file physio/meta_bus.h
+ */
+#ifndef _PHYSIO_META_BUS_H_
+#define _PHYSIO_META_BUS_H_
+
+#include <udi.h>
+#include <udi_physio.h>
+
+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
--- /dev/null
+/**
+ * \file physio/meta_intr.h
+ */
+#ifndef _PHYSIO_META_INTR_H_
+#define _PHYSIO_META_INTR_H_
+
+#include <udi.h>
+#include <udi_physio.h>
+#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
--- /dev/null
+/**
+ * \file physio/pio.h
+ */
+#ifndef _PHYSIO_PIO_H_
+#define _PHYSIO_PIO_H_
+
+#include <udi.h>
+#include <udi_physio.h>
+
+
+typedef _udi_handle_t udi_pio_handle_t;
+/* Null handle value for udi_pio_handle_t */
+#define UDI_NULL_PIO_HANDLE _NULL_HANDLE
+
+#endif
--- /dev/null
+/**
+ * \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 <acess.h>
+
+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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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 <<meta>>_<<role>>_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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \file udi_physio.h
+ */
+#ifndef _UDI_PHYSIO_H_
+#define _UDI_PHYSIO_H_
+
+#include <udi.h>
+
+// === 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 <physio/meta_intr.h>
+#include <physio/meta_bus.h>
+
+
+#endif
--- /dev/null
+/**
+ * \file logging.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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);
--- /dev/null
+/*
+ * Acess2 UDI Layer
+ */
+#define DEBUG 0
+#define VERSION ((0<<8)|1)
+#include <acess.h>
+#include <modules.h>
+#include <udi.h>
+
+// === 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;
+}
--- /dev/null
+/**
+ * \file mem.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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);
+}
--- /dev/null
+/**
+ * \file meta_gio.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file meta_mgmt.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file physio.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+#include <udi_physio.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file physio/meta_bus.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+#include <udi_physio.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file physio/meta_intr.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+#include <udi_physio.h>
+
+// === 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();
+}
--- /dev/null
+/**
+ * \file logging.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <common.h>
+#include <udi.h>
+#include <udi_physio.h>
+
+// === CODE ===
+void udi_bus_bind_req(udi_bus_bind_cb_t *cb)
+{
+}
+
+void udi_bus_unbind_req(udi_bus_bind_cb_t *cb)
+{
+}
--- /dev/null
+/**
+ * \file strmem.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+
+// === 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;
+}
_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)
+++ /dev/null
-#
-#
-
-OBJ = ne2000.o
-NAME = NE2000
-
--include ../Makefile.tpl
+++ /dev/null
-/* Acess2
- * NE2000 Driver
- *
- * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
- */
-#define DEBUG 0
-#define VERSION ((0<<8)|50)
-#include <acess.h>
-#include <modules.h>
-#include <fs_devfs.h>
-#include <drv_pci.h>
-#include <tpl_drv_network.h>
-
-// === 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);
-}
--- /dev/null
+-include ../../Makefile.tpl
--- /dev/null
+#
+#
+
+OBJ = ne2000.o
+NAME = NE2000
+
+-include ../Makefile.tpl
--- /dev/null
+/* Acess2
+ * NE2000 Driver
+ *
+ * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
+ */
+#define DEBUG 0
+#define VERSION ((0<<8)|50)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <tpl_drv_network.h>
+
+// === 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);
+}
--- /dev/null
+#
+#
+
+OBJ = main.o mbr.o
+NAME = ATA
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess2 IDE Harddisk Driver
+ * - main.c
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <acess.h>
+#include <vfs.h>
+
+// === 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
--- /dev/null
+/*
+ * Acess2 IDE Harddisk Driver
+ * - main.c
+ */
+#define DEBUG 0
+#include <acess.h>
+#include <modules.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <tpl_drv_common.h>
+#include <tpl_drv_disk.h>
+#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;
+}
--- /dev/null
+/*
+ * Acess2 IDE Harddisk Driver
+ * - MBR Parsing Code
+ * mbr.c
+ */
+#define DEBUG 0
+#include <acess.h>
+#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;
+}
--- /dev/null
+#
+#
+
+OBJ = fdd.o
+NAME = FDD
+
+-include ../Makefile.tpl
--- /dev/null
+/*\r
+ * AcessOS 0.1\r
+ * Floppy Disk Access Code\r
+ */\r
+#define DEBUG 0\r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <fs_devfs.h>\r
+#include <tpl_drv_disk.h>\r
+#include <dma.h>\r
+#include <iocache.h>\r
+\r
+#define WARN 0\r
+\r
+// === CONSTANTS ===\r
+// --- Current Version\r
+#define FDD_VERSION ((0<<8)|(75))\r
+\r
+// --- Options\r
+#define USE_CACHE 0 // Use Sector Cache\r
+#define CACHE_SIZE 32 // Number of cachable sectors\r
+#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation\r
+#define MOTOR_ON_DELAY 500 // Miliseconds\r
+#define MOTOR_OFF_DELAY 2000 // Miliseconds\r
+\r
+// === TYPEDEFS ===\r
+/**\r
+ * \brief Representation of a floppy drive\r
+ */\r
+typedef struct {\r
+ int type;\r
+ volatile int motorState; //2 - On, 1 - Spinup, 0 - Off\r
+ int track[2];\r
+ int timer;\r
+ tVFS_Node Node;\r
+ #if !USE_CACHE\r
+ tIOCache *CacheHandle;\r
+ #endif\r
+} t_floppyDevice;\r
+\r
+/**\r
+ * \brief Cached Sector\r
+ */\r
+typedef struct {\r
+ Uint64 timestamp;\r
+ Uint16 disk;\r
+ Uint16 sector; // Allows 32Mb of addressable space (Plenty for FDD)\r
+ Uint8 data[512];\r
+} t_floppySector;\r
+\r
+// === CONSTANTS ===\r
+static const char *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" };\r
+static const int cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 };\r
+static const short cPORTBASE[] = { 0x3F0, 0x370 };\r
+\r
+enum FloppyPorts {\r
+ PORT_STATUSA = 0x0,\r
+ PORT_STATUSB = 0x1,\r
+ PORT_DIGOUTPUT = 0x2,\r
+ PORT_MAINSTATUS = 0x4,\r
+ PORT_DATARATE = 0x4,\r
+ PORT_DATA = 0x5,\r
+ PORT_DIGINPUT = 0x7,\r
+ PORT_CONFIGCTRL = 0x7\r
+};\r
+\r
+enum FloppyCommands {\r
+ FIX_DRIVE_DATA = 0x03,\r
+ HECK_DRIVE_STATUS = 0x04,\r
+ CALIBRATE_DRIVE = 0x07,\r
+ CHECK_INTERRUPT_STATUS = 0x08,\r
+ SEEK_TRACK = 0x0F,\r
+ READ_SECTOR_ID = 0x4A,\r
+ FORMAT_TRACK = 0x4D,\r
+ READ_TRACK = 0x42,\r
+ READ_SECTOR = 0x66,\r
+ WRITE_SECTOR = 0xC5,\r
+ WRITE_DELETE_SECTOR = 0xC9,\r
+ READ_DELETE_SECTOR = 0xCC,\r
+};\r
+\r
+// === PROTOTYPES ===\r
+// --- Filesystem\r
+ int FDD_Install(char **Arguments);\r
+char *FDD_ReadDir(tVFS_Node *Node, int pos);\r
+tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name);\r
+ int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
+Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+// --- 1st Level Disk Access\r
+Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk);\r
+// --- Raw Disk Access\r
+ int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer);\r
+ int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer);\r
+// --- Helpers\r
+void FDD_IRQHandler(int Num);\r
+void FDD_WaitIRQ();\r
+void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl);\r
+inline void FDD_AquireSpinlock();\r
+inline void FDD_FreeSpinlock();\r
+#if USE_CACHE\r
+inline void FDD_AquireCacheSpinlock();\r
+inline void FDD_FreeCacheSpinlock();\r
+#endif\r
+void FDD_int_SendByte(int base, char byte);\r
+ int FDD_int_GetByte(int base);\r
+void FDD_Reset(int id);\r
+void FDD_Recalibrate(int disk);\r
+ int FDD_int_SeekTrack(int disk, int head, int track);\r
+void FDD_int_TimerCallback(int arg);\r
+void FDD_int_StopMotor(int disk);\r
+void FDD_int_StartMotor(int disk);\r
+ int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL);\r
+t_floppyDevice gFDD_Devices[2];\r
+volatile int fdd_inUse = 0;\r
+volatile int fdd_irq6 = 0;\r
+tDevFS_Driver gFDD_DriverInfo = {\r
+ NULL, "fdd",\r
+ {\r
+ .Size = -1,\r
+ .NumACLs = 1,\r
+ .ACLs = &gVFS_ACL_EveryoneRX,\r
+ .Flags = VFS_FFLAG_DIRECTORY,\r
+ .ReadDir = FDD_ReadDir,\r
+ .FindDir = FDD_FindDir,\r
+ .IOCtl = FDD_IOCtl\r
+ }\r
+};\r
+#if USE_CACHE\r
+int siFDD_CacheInUse = 0;\r
+int siFDD_SectorCacheSize = CACHE_SIZE;\r
+t_floppySector sFDD_SectorCache[CACHE_SIZE];\r
+#endif\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int FDD_Install(char **Arguments)\r
+ * \brief Installs floppy driver\r
+ */\r
+int FDD_Install(char **Arguments)\r
+{\r
+ Uint8 data;\r
+ \r
+ // Determine Floppy Types (From CMOS)\r
+ outb(0x70, 0x10);\r
+ data = inb(0x71);\r
+ gFDD_Devices[0].type = data >> 4;\r
+ gFDD_Devices[1].type = data & 0xF;\r
+ gFDD_Devices[0].track[0] = -1;\r
+ gFDD_Devices[1].track[1] = -1;\r
+ \r
+ Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
+ \r
+ // Clear FDD IRQ Flag\r
+ FDD_SensInt(0x3F0, NULL, NULL);\r
+ // Install IRQ6 Handler\r
+ IRQ_AddHandler(6, FDD_IRQHandler);\r
+ // Reset Primary FDD Controller\r
+ FDD_Reset(0);\r
+ \r
+ // Initialise Root Node\r
+ gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime\r
+ = gFDD_DriverInfo.RootNode.ATime = now();\r
+ \r
+ // Initialise Child Nodes\r
+ gFDD_Devices[0].Node.Inode = 0;\r
+ gFDD_Devices[0].Node.Flags = 0;\r
+ gFDD_Devices[0].Node.NumACLs = 0;\r
+ gFDD_Devices[0].Node.Read = FDD_ReadFS;\r
+ gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS;\r
+ memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node));\r
+ \r
+ gFDD_Devices[1].Node.Inode = 1;\r
+ \r
+ // Set Lengths\r
+ gFDD_Devices[0].Node.Size = cFDD_SIZES[data >> 4];\r
+ gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF];\r
+ \r
+ // Create Sector Cache\r
+ #if USE_CACHE\r
+ //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE);\r
+ //siFDD_SectorCacheSize = CACHE_SIZE;\r
+ #else\r
+ if( cFDD_SIZES[data >> 4] ) {\r
+ gFDD_Devices[0].CacheHandle = IOCache_Create(\r
+ FDD_WriteSector, 0, 512,\r
+ gFDD_Devices[0].Node.Size / (512*4)\r
+ ); // Cache is 1/4 the size of the disk\r
+ }\r
+ if( cFDD_SIZES[data & 15] ) {\r
+ gFDD_Devices[1].CacheHandle = IOCache_Create(\r
+ FDD_WriteSector, 0, 512,\r
+ gFDD_Devices[1].Node.Size / (512*4)\r
+ ); // Cache is 1/4 the size of the disk\r
+ }\r
+ #endif\r
+ \r
+ // Register with devfs\r
+ DevFS_AddDevice(&gFDD_DriverInfo);\r
+ \r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
+ * \brief Read Directory\r
+ */\r
+char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
+{\r
+ char name[2] = "0\0";\r
+ //Update Accessed Time\r
+ //gFDD_DrvInfo.rootNode.atime = now();\r
+ \r
+ //Check for bounds\r
+ if(pos >= 2 || pos < 0)\r
+ return NULL;\r
+ \r
+ if(gFDD_Devices[pos].type == 0)\r
+ return VFS_SKIP;\r
+ \r
+ name[0] += pos;\r
+ \r
+ //Return\r
+ return strdup(name);\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename);\r
+ * \brief Find File Routine (for vfs_node)\r
+ */\r
+tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *Filename)\r
+{\r
+ int i;\r
+ \r
+ ENTER("sFilename", Filename);\r
+ \r
+ // Sanity check string\r
+ if(Filename == NULL) {\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Check string length (should be 1)\r
+ if(Filename[0] == '\0' || Filename[1] != '\0') {\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Get First character\r
+ i = Filename[0] - '0';\r
+ \r
+ // Check for 1st disk and if it is present return\r
+ if(i == 0 && gFDD_Devices[0].type != 0) {\r
+ LEAVE('p', &gFDD_Devices[0].Node);\r
+ return &gFDD_Devices[0].Node;\r
+ }\r
+ \r
+ // Check for 2nd disk and if it is present return\r
+ if(i == 1 && gFDD_Devices[1].type != 0) {\r
+ LEAVE('p', &gFDD_Devices[1].Node);\r
+ return &gFDD_Devices[1].Node;\r
+ }\r
+ \r
+ // Else return null\r
+ LEAVE('n');\r
+ return NULL;\r
+}\r
+\r
+static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL};\r
+/**\r
+ * \fn int FDD_IOCtl(tVFS_Node *Node, int id, void *data)\r
+ * \brief Stub ioctl function\r
+ */\r
+int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+ switch(ID)\r
+ {\r
+ case DRV_IOCTL_TYPE: return DRV_TYPE_DISK;\r
+ case DRV_IOCTL_IDENT: return ModUtil_SetIdent(Data, "FDD");\r
+ case DRV_IOCTL_VERSION: return FDD_VERSION;\r
+ case DRV_IOCTL_LOOKUP: return ModUtil_LookupString((char**)casIOCTLS, Data);\r
+ \r
+ case DISK_IOCTL_GETBLOCKSIZE: return 512; \r
+ \r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+/**\r
+ * \fn Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+ * \brief Read Data from a disk\r
+*/\r
+Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+ int i = 0;\r
+ int disk;\r
+ //Uint32 buf[128];\r
+ \r
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
+ \r
+ if(Node == NULL) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ \r
+ if(Node->Inode != 0 && Node->Inode != 1) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ \r
+ disk = Node->Inode;\r
+ \r
+ // Update Accessed Time\r
+ Node->ATime = now();\r
+ \r
+ #if 0\r
+ if((Offset & 0x1FF) || (Length & 0x1FF))\r
+ {\r
+ // Un-Aligned Offset/Length\r
+ int startOff = Offset >> 9;\r
+ int sectOff = Offset & 0x1FF;\r
+ int sectors = (Length + 0x1FF) >> 9;\r
+ \r
+ LOG("Non-aligned Read");\r
+ \r
+ //Read Starting Sector\r
+ if(!FDD_ReadSector(disk, startOff, buf))\r
+ return 0;\r
+ memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length);\r
+ \r
+ // If the data size is one sector or less\r
+ if(Length <= 512-sectOff)\r
+ {\r
+ LEAVE('X', Length);\r
+ return Length; //Return\r
+ }\r
+ Buffer += 512-sectOff;\r
+ \r
+ //Read Middle Sectors\r
+ for( i = 1; i < sectors - 1; i++ )\r
+ {\r
+ if(!FDD_ReadSector(disk, startOff+i, buf)) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ memcpy(Buffer, buf, 512);\r
+ Buffer += 512;\r
+ }\r
+ \r
+ //Read End Sectors\r
+ if(!FDD_ReadSector(disk, startOff+i, buf))\r
+ return 0;\r
+ memcpy(Buffer, buf, (len&0x1FF)-sectOff);\r
+
+ LEAVE('X', Length);\r
+ return Length;\r
+ }\r
+ else\r
+ {\r
+ int count = Length >> 9;\r
+ int sector = Offset >> 9;\r
+ LOG("Aligned Read");\r
+ //Aligned Offset and Length - Simple Code\r
+ for( i = 0; i < count; i ++ )\r
+ {\r
+ FDD_ReadSector(disk, sector, buf);\r
+ memcpy(buffer, buf, 512);\r
+ buffer += 512;\r
+ sector++;\r
+ }
+ LEAVE('i', Length);\r
+ return Length;\r
+ }\r
+ #endif\r
+ \r
+ i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk);\r
+ LEAVE('i', i);\r
+ return i;\r
+}\r
+\r
+/**\r
+ * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk)\r
+ * \brief Reads \a Count contiguous sectors from a disk\r
+ * \param SectorAddr Address of the first sector\r
+ * \param Count Number of sectors to read\r
+ * \param Buffer Destination Buffer\r
+ * \param Disk Disk Number\r
+ * \return Number of sectors read\r
+ * \note Used as a ::DrvUtil_ReadBlock helper\r
+ */\r
+Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk)\r
+{\r
+ Uint ret = 0;\r
+ while(Count --)\r
+ {\r
+ if( FDD_ReadSector(Disk, SectorAddr, Buffer) != 1 )\r
+ return ret;\r
+ \r
+ Buffer = (void*)( (tVAddr)Buffer + 512 );\r
+ SectorAddr ++;\r
+ ret ++;\r
+ }\r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+ * \fn Read a sector from disk\r
+*/\r
+int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+{\r
+ int cyl, head, sec;\r
+ int spt, base;\r
+ int i;\r
+ int lba = SectorAddr;\r
+ \r
+ ENTER("idisk Xlba pbuf", disk, lba, buf);\r
+ \r
+ #if USE_CACHE\r
+ FDD_AquireCacheSpinlock();\r
+ for( i = 0; i < siFDD_SectorCacheSize; i++ )\r
+ {\r
+ if(sFDD_SectorCache[i].timestamp == 0) continue;\r
+ if(sFDD_SectorCache[i].disk == Disk\r
+ && sFDD_SectorCache[i].sector == lba) {\r
+ LOG("Found %i in cache %i", lba, i);\r
+ memcpy(Buffer, sFDD_SectorCache[i].data, 512);\r
+ sFDD_SectorCache[i].timestamp = now();\r
+ FDD_FreeCacheSpinlock();\r
+ LEAVE('i', 1);\r
+ return 1;\r
+ }\r
+ }\r
+ LOG("Read %i from Disk", lba);\r
+ FDD_FreeCacheSpinlock();\r
+ #else\r
+ if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
+ LEAVE('i', 1);\r
+ return 1;\r
+ }\r
+ #endif\r
+ \r
+ base = cPORTBASE[Disk>>1];\r
+ \r
+ LOG("Calculating Disk Dimensions");\r
+ // Get CHS position\r
+ if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) {\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ \r
+ // Remove Old Timer\r
+ Time_RemoveTimer(gFDD_Devices[Disk].timer);\r
+ // Check if Motor is on\r
+ if(gFDD_Devices[Disk].motorState == 0) {\r
+ FDD_int_StartMotor(Disk);\r
+ }\r
+ \r
+ LOG("Wait for Motor Spinup");\r
+ \r
+ // Wait for spinup\r
+ while(gFDD_Devices[Disk].motorState == 1) Threads_Yield();\r
+ \r
+ LOG("C:%i,H:%i,S:%i", cyl, head, sec);\r
+ LOG("Acquire Spinlock");\r
+ \r
+ FDD_AquireSpinlock();\r
+ \r
+ // Seek to track\r
+ outb(base+CALIBRATE_DRIVE, 0);\r
+ i = 0;\r
+ while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield();\r
+ //FDD_SensInt(base, NULL, NULL); // Wait for IRQ\r
+ \r
+ LOG("Setting DMA for read");\r
+ \r
+ //Read Data from DMA\r
+ DMA_SetChannel(2, 512, 1); // Read 512 Bytes\r
+ \r
+ LOG("Sending read command");\r
+ \r
+ //Threads_Wait(100); // Wait for Head to settle\r
+ Time_Delay(100);\r
+ FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6\r
+ FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
+ FDD_int_SendByte(base, (Uint8)cyl);\r
+ FDD_int_SendByte(base, (Uint8)head);\r
+ FDD_int_SendByte(base, (Uint8)sec);\r
+ FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val})\r
+ FDD_int_SendByte(base, spt); // SPT\r
+ FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default)\r
+ FDD_int_SendByte(base, 0xFF); // Data Length\r
+ \r
+ // Wait for IRQ\r
+ LOG("Waiting for Data to be read");\r
+ FDD_WaitIRQ();\r
+ \r
+ // Read Data from DMA\r
+ LOG(" FDD_ReadSector: Reading Data");\r
+ DMA_ReadData(2, 512, Buffer);\r
+ \r
+ // Clear Input Buffer\r
+ LOG("Clearing Input Buffer");\r
+ FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
+ FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
+ \r
+ LOG("Realeasing Spinlock and Setting motor to stop");\r
+ // Release Spinlock\r
+ FDD_FreeSpinlock();\r
+ \r
+ //Set timer to turn off motor affter a gap\r
+ gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer
+\r
+ #if USE_CACHE\r
+ {\r
+ FDD_AquireCacheSpinlock();\r
+ int oldest = 0;\r
+ for(i=0;i<siFDD_SectorCacheSize;i++)\r
+ {\r
+ if(sFDD_SectorCache[i].timestamp == 0) {\r
+ oldest = i;\r
+ break;\r
+ }\r
+ if(sFDD_SectorCache[i].timestamp < sFDD_SectorCache[oldest].timestamp)\r
+ oldest = i;\r
+ }\r
+ sFDD_SectorCache[oldest].timestamp = now();\r
+ sFDD_SectorCache[oldest].disk = Disk;\r
+ sFDD_SectorCache[oldest].sector = lba;\r
+ memcpy(sFDD_SectorCache[oldest].data, Buffer, 512);\r
+ FDD_FreeCacheSpinlock();\r
+ }\r
+ #else\r
+ IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );\r
+ #endif\r
+
+ LEAVE('i', 1);\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
+ * \brief Write a sector to the floppy disk\r
+ * \note Not Implemented\r
+ */\r
+int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
+{\r
+ Warning("[FDD ] Read Only at the moment");\r
+ return -1;\r
+}\r
+\r
+/**\r
+ * \fn int FDD_int_SeekTrack(int disk, int track)\r
+ * \brief Seek disk to selected track\r
+ */\r
+int FDD_int_SeekTrack(int disk, int head, int track)\r
+{\r
+ Uint8 sr0, cyl;\r
+ int base;\r
+ \r
+ base = cPORTBASE[disk>>1];\r
+ \r
+ // Check if seeking is needed\r
+ if(gFDD_Devices[disk].track[head] == track)\r
+ return 1;\r
+ \r
+ // - Seek Head 0\r
+ FDD_int_SendByte(base, SEEK_TRACK);\r
+ FDD_int_SendByte(base, (head<<2)|(disk&1));\r
+ FDD_int_SendByte(base, track); // Send Seek command\r
+ FDD_WaitIRQ();\r
+ FDD_SensInt(base, &sr0, &cyl); // Wait for IRQ\r
+ if((sr0 & 0xF0) != 0x20) {
+ LOG("sr0 = 0x%x", sr0);
+ return 0; //Check Status
+ }\r
+ if(cyl != track) return 0;\r
+ \r
+ // Set Track in structure\r
+ gFDD_Devices[disk].track[head] = track;\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)\r
+ * \brief Get Dimensions of a disk\r
+ */\r
+int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)\r
+{\r
+ switch(type) {\r
+ case 0:\r
+ return 0;\r
+ \r
+ // 360Kb 5.25"\r
+ case 1:\r
+ *spt = 9;\r
+ *s = (lba % 9) + 1;\r
+ *c = lba / 18;\r
+ *h = (lba / 9) & 1;\r
+ break;\r
+ \r
+ // 1220Kb 5.25"\r
+ case 2:\r
+ *spt = 15;\r
+ *s = (lba % 15) + 1;\r
+ *c = lba / 30;\r
+ *h = (lba / 15) & 1;\r
+ break;\r
+ \r
+ // 720Kb 3.5"\r
+ case 3:\r
+ *spt = 9;\r
+ *s = (lba % 9) + 1;\r
+ *c = lba / 18;\r
+ *h = (lba / 9) & 1;\r
+ break;\r
+ \r
+ // 1440Kb 3.5"\r
+ case 4:\r
+ *spt = 18;\r
+ *s = (lba % 18) + 1;\r
+ *c = lba / 36;\r
+ *h = (lba / 18) & 1;\r
+ //Log("1440k - lba=%i(0x%x), *s=%i,*c=%i,*h=%i", lba, lba, *s, *c, *h);\r
+ break;\r
+ \r
+ // 2880Kb 3.5"\r
+ case 5:\r
+ *spt = 36;\r
+ *s = (lba % 36) + 1;\r
+ *c = lba / 72;\r
+ *h = (lba / 32) & 1;\r
+ break;\r
+ \r
+ default:\r
+ return -2;\r
+ }\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn void FDD_IRQHandler(int Num)\r
+ * \brief Handles IRQ6\r
+ */\r
+void FDD_IRQHandler(int Num)\r
+{\r
+ fdd_irq6 = 1;\r
+}\r
+\r
+/**\r
+ * \fn FDD_WaitIRQ()\r
+ * \brief Wait for an IRQ6\r
+ */\r
+void FDD_WaitIRQ()\r
+{\r
+ // Wait for IRQ\r
+ while(!fdd_irq6) Threads_Yield();\r
+ fdd_irq6 = 0;\r
+}\r
+\r
+void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)\r
+{\r
+ FDD_int_SendByte(base, CHECK_INTERRUPT_STATUS);\r
+ if(sr0) *sr0 = FDD_int_GetByte(base);\r
+ else FDD_int_GetByte(base);\r
+ if(cyl) *cyl = FDD_int_GetByte(base);\r
+ else FDD_int_GetByte(base);\r
+}\r
+\r
+void FDD_AquireSpinlock()\r
+{\r
+ while(fdd_inUse)\r
+ Threads_Yield();\r
+ fdd_inUse = 1;\r
+}\r
+\r
+inline void FDD_FreeSpinlock()\r
+{\r
+ fdd_inUse = 0;\r
+}\r
+\r
+#if USE_CACHE\r
+inline void FDD_AquireCacheSpinlock()\r
+{\r
+ while(siFDD_CacheInUse) Threads_Yield();\r
+ siFDD_CacheInUse = 1;\r
+}\r
+inline void FDD_FreeCacheSpinlock()\r
+{\r
+ siFDD_CacheInUse = 0;\r
+}\r
+#endif\r
+\r
+/**\r
+ * void FDD_int_SendByte(int base, char byte)\r
+ * \brief Sends a command to the controller\r
+ */\r
+void FDD_int_SendByte(int base, char byte)\r
+{\r
+ volatile int state;\r
+ int timeout = 128;\r
+ for( ; timeout--; )\r
+ {\r
+ state = inb(base + PORT_MAINSTATUS);\r
+ if ((state & 0xC0) == 0x80)\r
+ {\r
+ outb(base + PORT_DATA, byte);\r
+ return;\r
+ }\r
+ inb(0x80); //Delay\r
+ }\r
+ #if WARN\r
+ Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
+ #endif\r
+}\r
+\r
+/**\r
+ * int FDD_int_GetByte(int base, char byte)\r
+ * \brief Receive data from fdd controller\r
+ */\r
+int FDD_int_GetByte(int base)\r
+{\r
+ volatile int state;\r
+ int timeout;\r
+ for( timeout = 128; timeout--; )\r
+ {\r
+ state = inb((base + PORT_MAINSTATUS));\r
+ if ((state & 0xd0) == 0xd0)\r
+ return inb(base + PORT_DATA);\r
+ inb(0x80);\r
+ }\r
+ return -1;\r
+}\r
+\r
+/**\r
+ * \brief Recalibrate the specified disk\r
+ */\r
+void FDD_Recalibrate(int disk)\r
+{\r
+ ENTER("idisk", disk);\r
+ \r
+ LOG("Starting Motor");\r
+ FDD_int_StartMotor(disk);\r
+ // Wait for Spinup\r
+ while(gFDD_Devices[disk].motorState == 1) Threads_Yield();\r
+ \r
+ LOG("Sending Calibrate Command");\r
+ FDD_int_SendByte(cPORTBASE[disk>>1], CALIBRATE_DRIVE);\r
+ FDD_int_SendByte(cPORTBASE[disk>>1], disk&1);\r
+ \r
+ LOG("Waiting for IRQ");\r
+ FDD_WaitIRQ();\r
+ FDD_SensInt(cPORTBASE[disk>>1], NULL, NULL);\r
+ \r
+ LOG("Stopping Motor");\r
+ FDD_int_StopMotor(disk);\r
+ LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \brief Reset the specified FDD controller\r
+ */\r
+void FDD_Reset(int id)\r
+{\r
+ int base = cPORTBASE[id];\r
+ \r
+ ENTER("iID", id);\r
+ \r
+ outb(base + PORT_DIGOUTPUT, 0); // Stop Motors & Disable FDC\r
+ outb(base + PORT_DIGOUTPUT, 0x0C); // Re-enable FDC (DMA and Enable)\r
+ \r
+ LOG("Awaiting IRQ");\r
+ \r
+ FDD_WaitIRQ();\r
+ FDD_SensInt(base, NULL, NULL);\r
+ \r
+ LOG("Setting Driver Info");\r
+ outb(base + PORT_DATARATE, 0); // Set data rate to 500K/s\r
+ FDD_int_SendByte(base, FIX_DRIVE_DATA); // Step and Head Load Times\r
+ FDD_int_SendByte(base, 0xDF); // Step Rate Time, Head Unload Time (Nibble each)\r
+ FDD_int_SendByte(base, 0x02); // Head Load Time >> 1\r
+ while(FDD_int_SeekTrack(0, 0, 1) == 0); // set track\r
+ while(FDD_int_SeekTrack(0, 1, 1) == 0); // set track\r
+ \r
+ LOG("Recalibrating Disk");\r
+ FDD_Recalibrate((id<<1)|0);\r
+ FDD_Recalibrate((id<<1)|1);
+\r
+ LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \fn void FDD_int_TimerCallback()\r
+ * \brief Called by timer\r
+ */\r
+void FDD_int_TimerCallback(int arg)\r
+{\r
+ ENTER("iarg", arg);\r
+ if(gFDD_Devices[arg].motorState == 1)\r
+ gFDD_Devices[arg].motorState = 2;\r
+ Time_RemoveTimer(gFDD_Devices[arg].timer);\r
+ gFDD_Devices[arg].timer = -1;\r
+ LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \fn void FDD_int_StartMotor(char disk)\r
+ * \brief Starts FDD Motor\r
+ */\r
+void FDD_int_StartMotor(int disk)\r
+{\r
+ Uint8 state;\r
+ state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
+ state |= 1 << (4+disk);\r
+ outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
+ gFDD_Devices[disk].motorState = 1;\r
+ gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk);\r
+}\r
+\r
+/**\r
+ * \fn void FDD_int_StopMotor(int disk)\r
+ * \brief Stops FDD Motor\r
+ */\r
+void FDD_int_StopMotor(int disk)\r
+{\r
+ Uint8 state;\r
+ state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
+ state &= ~( 1 << (4+disk) );\r
+ outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
+ gFDD_Devices[disk].motorState = 0;\r
+}\r
+\r
+/**\r
+ * \fn void ModuleUnload()\r
+ * \brief Prepare the module for removal\r
+ */\r
+void ModuleUnload()\r
+{\r
+ int i;\r
+ FDD_AquireSpinlock();\r
+ for(i=0;i<4;i++) {\r
+ Time_RemoveTimer(gFDD_Devices[i].timer);\r
+ FDD_int_StopMotor(i);\r
+ }\r
+ //IRQ_Clear(6);\r
+}\r
--- /dev/null
+-include ../../Makefile.tpl
+++ /dev/null
-#
-#
-
-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
+++ /dev/null
-/**
- * \file buf.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file cb.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file imc.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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__);
-}
+++ /dev/null
-/**
- * \file physio/meta_bus.h
- */
-#ifndef _PHYSIO_META_BUS_H_
-#define _PHYSIO_META_BUS_H_
-
-#include <udi.h>
-#include <udi_physio.h>
-
-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
+++ /dev/null
-/**
- * \file physio/meta_intr.h
- */
-#ifndef _PHYSIO_META_INTR_H_
-#define _PHYSIO_META_INTR_H_
-
-#include <udi.h>
-#include <udi_physio.h>
-#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
+++ /dev/null
-/**
- * \file physio/pio.h
- */
-#ifndef _PHYSIO_PIO_H_
-#define _PHYSIO_PIO_H_
-
-#include <udi.h>
-#include <udi_physio.h>
-
-
-typedef _udi_handle_t udi_pio_handle_t;
-/* Null handle value for udi_pio_handle_t */
-#define UDI_NULL_PIO_HANDLE _NULL_HANDLE
-
-#endif
+++ /dev/null
-/**
- * \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 <acess.h>
-
-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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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 <<meta>>_<<role>>_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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \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
+++ /dev/null
-/**
- * \file udi_physio.h
- */
-#ifndef _UDI_PHYSIO_H_
-#define _UDI_PHYSIO_H_
-
-#include <udi.h>
-
-// === 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 <physio/meta_intr.h>
-#include <physio/meta_bus.h>
-
-
-#endif
+++ /dev/null
-/**
- * \file logging.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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);
+++ /dev/null
-/*
- * Acess2 UDI Layer
- */
-#define DEBUG 0
-#define VERSION ((0<<8)|1)
-#include <acess.h>
-#include <modules.h>
-#include <udi.h>
-
-// === 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;
-}
+++ /dev/null
-/**
- * \file mem.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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);
-}
+++ /dev/null
-/**
- * \file meta_gio.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file meta_mgmt.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file physio.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-#include <udi_physio.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file physio/meta_bus.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-#include <udi_physio.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file physio/meta_intr.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-#include <udi_physio.h>
-
-// === 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();
-}
+++ /dev/null
-/**
- * \file logging.c
- * \author John Hodge (thePowersGang)
- */
-#include <common.h>
-#include <udi.h>
-#include <udi_physio.h>
-
-// === CODE ===
-void udi_bus_bind_req(udi_bus_bind_cb_t *cb)
-{
-}
-
-void udi_bus_unbind_req(udi_bus_bind_cb_t *cb)
-{
-}
+++ /dev/null
-/**
- * \file strmem.c
- * \author John Hodge (thePowersGang)
- */
-#include <acess.h>
-#include <udi.h>
-
-// === 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;
-}
*/
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;
}
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;
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);
TERM_IOCTL_MODETYPE = 4,
TERM_IOCTL_WIDTH,
TERM_IOCTL_HEIGHT,
- TERM_IOCTL_QUERYMODE
+ TERM_IOCTL_QUERYMODE,
+ TERM_IOCTL_FORCESHOW
};