ret->ImplInt = strlen(ret->Data);\r
ret->ImplPtr = info;\r
ret->Inode = (Uint64)dp;\r
+ ret->Flags = VFS_FFLAG_DIRECTORY;\r
\r
ret->Type = &gNativeFS_DirNodeType; \r
\r
#define DEBUG 1
#include <acess.h>
#include <threads.h>
+#include <events.h>
#include "../syscalls.h"
// === IMPORTS ===
return Proc_GetMessage(a0, a1);
);
+SYSCALL1(Syscall_WaitEvent, "i", int,
+ return Threads_WaitEvents(a0);
+);
+
const tSyscallHandler caSyscalls[] = {
Syscall_Null,
Syscall_Exit,
Syscall_SendMessage,
Syscall_GetMessage,
- Syscall_select
+ Syscall_select,
+ Syscall_WaitEvent
};
const int ciNumSyscalls = sizeof(caSyscalls)/sizeof(caSyscalls[0]);
/**
//printf("Binary_GetSymbol: RETURN 0, not found\n");
printf("--- ERROR: Unable to find symbol '%s'\n", SymbolName);
-
+
+ exit( -1 );
return 0;
}
int acess_SysGetMessage(int *SourceTID, void *Data)
{
- return _Syscall(SYS_GETMSG, "<d <d",
+// static __thread int lastlen = 1024;
+ int lastlen;
+
+ lastlen = _Syscall(SYS_GETMSG, "<d <d",
SourceTID ? sizeof(int) : 0, SourceTID,
- Data ? 4096 : 0, Data
+ Data ? 1024 : 0, Data
);
+ return lastlen;
+}
+
+int acess__SysWaitEvent(int Mask)
+{
+ return _Syscall(SYS_WAITEVENT, ">i", Mask);
}
// --- Logging
DEFSYM(_SysAllocate),
DEFSYM(_SysDebug),
- DEFSYM(_SysSetFaultHandler)
+ DEFSYM(_SysSetFaultHandler),
+ DEFSYM(_SysWaitEvent)
};
const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]);
return -1;
}
#else
- printf("AllocateMemory: mmap(%p, %lx, ...)\n", (void*)base, ByteCount);
+// printf("AllocateMemory: mmap(%p, 0x%lx, ...)\n", (void*)base, ByteCount);
tmp = mmap((void*)base, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
if( tmp == MAP_FAILED ) {
printf("ERROR: Unable to allocate memory\n");
perror("AllocateMemory");
return -1;
}
- printf("AllocateMemory: RETURN 0\n");
+// printf("AllocateMemory: RETURN 0\n");
#endif
return 0;
}
SYS_SENDMSG,
SYS_GETMSG,
SYS_SELECT,
+ SYS_WAITEVENT,
N_SYSCALLS
};
"SYS_AN_FORK",
"SYS_SENDMSG",
"SYS_GETMSG",
- "SYS_SELECT"
+ "SYS_SELECT",
+ "SYS_WAITEVENT"
};
#endif
MODULES += Storage/ATA
MODULES += Storage/FDDv2
MODULES += Network/NE2000 Network/RTL8139
+MODULES += Network/VIARhineII
MODULES += Display/VESA
-MODULES += Display/BochsGA Display/VIAVideo
+MODULES += Display/BochsGA
+#MODULES += Display/VIAVideo
MODULES += Input/PS2KbMouse
MODULES += x86/ISADMA x86/VGAText
for( i = 0; i < MAX_CALLBACKS_PER_IRQ; i++ )
{
if( gIRQ_Handlers[Num][i] == NULL ) {
- Log_Log("IRQ", "Added IRQ%i Cb#%i %p", Num, i, Callback);
+// Log_Log("IRQ", "Added IRQ%i Cb#%i %p", Num, i, Callback);
gIRQ_Handlers[Num][i] = Callback;
gaIRQ_DataPointers[Num][i] = Ptr;
return 1;
ENTER("iPages iMaxBits pPhysAddr", Pages, MaxBits, PhysAddr);
+ if(MaxBits == -1)
+ MaxBits = PHYS_BITS;
+
// Sanity Check
if(MaxBits < 12 || !PhysAddr) {
LEAVE('i', 0);
/*
- * Acess2 VM8086 Driver
+ * Acess2 Kernel (x86)
* - By John Hodge (thePowersGang)
+ *
+ * vm8086.c
+ * - Virtual 8086 Mode Monitor
*/
#define DEBUG 0
#include <acess.h>
// === CONSTANTS ===
#define TRACE_EMU 0
+#define VM8086_USER_BASE 0x1000
+
#define VM8086_MAGIC_CS 0xFFFF
#define VM8086_MAGIC_IP 0x0010
#define VM8086_STACK_SEG 0x9F00
#define VM8086_BLOCKCOUNT ((0x9F000-0x10000)/VM8086_BLOCKSIZE)
// === TYPES ===
+struct sVM8086_InternalPages
+{
+ Uint32 Bitmap; // 32 sections = 128 byte blocks
+ tVAddr VirtBase;
+ tPAddr PhysAddr;
+};
struct sVM8086_InternalData
{
- struct {
- Uint32 Bitmap; // 32 sections = 128 byte blocks
- tVAddr VirtBase;
- tPAddr PhysAddr;
- } AllocatedPages[VM8086_PAGES_PER_INST];
+ struct sVM8086_InternalPages AllocatedPages[VM8086_PAGES_PER_INST];
};
// === PROTOTYPES ===
MM_Map( i * 0x1000, i * 0x1000 );
}
MM_Map( 0, 0 ); // IVT / BDA
- // Map (but allow allocation) of 0x1000 - 0x9F000
- // - So much hack, it isn't funny
- // TODO: Remove this and replce with something less hacky
- for(i=1;i<0x9F;i++) {
- MM_Map( i * 0x1000, i * 0x1000 );
- while(MM_GetRefCount(i*0x1000))
- MM_DerefPhys( i * 0x1000 );
+ if( MM_GetRefCount(0x00000) > 2 ) {
+ Log_Notice("VM8086", "Ok, who's touched the IVT? (%i)",
+ MM_GetRefCount(0x00000));
}
MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA
+ if( MM_GetRefCount(0x9F000) > 2 ) {
+ Log_Notice("VM8086", "And who's been playing with my EBDA? (%i)",
+ MM_GetRefCount(0x9F000));
+ }
// System Stack / Stub
if( MM_Allocate( 0x100000 ) == 0 ) {
Log_Error("VM8086", "Unable to allocate memory for stack/stub");
if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS
&& Threads_GetPID() == gVM8086_WorkerPID)
{
+ int i;
if( gpVM8086_State == (void*)-1 ) {
Log_Log("VM8086", "Worker thread ready and waiting");
gpVM8086_State = NULL;
gpVM8086_State->BP = Regs->ebp;
gpVM8086_State->SI = Regs->esi; gpVM8086_State->DI = Regs->edi;
gpVM8086_State->DS = Regs->ds; gpVM8086_State->ES = Regs->es;
+
+ LOG("gpVM8086_State = %p", gpVM8086_State);
+ LOG("gpVM8086_State->Internal = %p", gpVM8086_State->Internal);
+ for( i = 0; i < VM8086_PAGES_PER_INST; i ++ ) {
+ if( !gpVM8086_State->Internal->AllocatedPages[i].VirtBase )
+ continue ;
+ MM_Deallocate( VM8086_USER_BASE + i*PAGE_SIZE );
+ }
+
gpVM8086_State = NULL;
+
// Wake the caller
Semaphore_Signal(&gVM8086_TaskComplete, 1);
}
__asm__ __volatile__ ("sti");
Semaphore_Wait(&gVM8086_TasksToDo, 1);
+ for( i = 0; i < VM8086_PAGES_PER_INST; i ++ )
+ {
+ if( !gpVM8086_State->Internal->AllocatedPages[i].VirtBase )
+ continue ;
+ MM_Map( VM8086_USER_BASE + i*PAGE_SIZE, gpVM8086_State->Internal->AllocatedPages[i].PhysAddr );
+ }
+
+
//Log_Log("VM8086", "We have a task (%p)", gpVM8086_State);
Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS;
Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP;
id = *(Uint8*)( Regs->cs*16 +(Regs->eip&0xFFFF));
Regs->eip ++;
+ Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eflags;
Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs;
Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip;
void VM8086_Free(tVM8086 *State)
{
int i;
+ // TODO: Make sure the state isn't in use currently
for( i = VM8086_PAGES_PER_INST; i --; )
MM_UnmapHWPages( State->Internal->AllocatedPages[i].VirtBase, 1);
free(State);
void *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Offset)
{
+ struct sVM8086_InternalPages *pages = State->Internal->AllocatedPages;
int i, j, base = 0;
int nBlocks, rem;
for( i = 0; i < VM8086_PAGES_PER_INST; i++ )
{
- if( State->Internal->AllocatedPages[i].VirtBase == 0 ) continue;
-
+ if( pages[i].VirtBase == 0 ) continue;
- //Log_Debug("VM8086", "AllocatedPages[%i].Bitmap = 0b%b", i, State->Internal->AllocatedPages[i].Bitmap);
+ //Log_Debug("VM8086", "pages[%i].Bitmap = 0b%b", i, pages[i].Bitmap);
rem = nBlocks;
base = 0;
// Scan the bitmap for a free block
for( j = 0; j < 32; j++ ) {
- if( State->Internal->AllocatedPages[i].Bitmap & (1 << j) ) {
+ if( pages[i].Bitmap & (1 << j) ) {
base = j+1;
rem = nBlocks;
}
if(rem == 0) // Goodie, there's a gap
{
for( j = 0; j < nBlocks; j++ )
- State->Internal->AllocatedPages[i].Bitmap |= 1 << (base + j);
- *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16 + base * 8;
+ pages[i].Bitmap |= 1 << (base + j);
+ *Segment = (VM8086_USER_BASE + i * 0x1000) / 16 + base * 8;
*Offset = 0;
- LOG("Allocated at #%i,%04x", i, base*128);
+ LOG("Allocated at #%i,%04x", i, base*8*16);
LOG(" - %x:%x", *Segment, *Offset);
- return (void*)( State->Internal->AllocatedPages[i].VirtBase + base * 128 );
+ return (void*)( pages[i].VirtBase + base * 8 * 16 );
}
}
}
// No pages with free space?, allocate a new one
for( i = 0; i < VM8086_PAGES_PER_INST; i++ )
{
- if( State->Internal->AllocatedPages[i].VirtBase == 0 ) break;
+ if( pages[i].VirtBase == 0 ) break;
}
// Darn, we can't allocate any more
if( i == VM8086_PAGES_PER_INST ) {
return NULL;
}
- State->Internal->AllocatedPages[i].VirtBase = MM_AllocDMA(
- 1, 20, &State->Internal->AllocatedPages[i].PhysAddr);
- State->Internal->AllocatedPages[i].Bitmap = 0;
+ pages[i].VirtBase = MM_AllocDMA(1, -1, &pages[i].PhysAddr);
+ if( pages[i].VirtBase == 0 ) {
+ Log_Warning("VM8086", "Unable to allocate data page");
+ return NULL;
+ }
+ pages[i].Bitmap = 0;
+ LOG("AllocatedPages[%i].VirtBase = %p", i, pages[i].VirtBase);
+ LOG("AllocatedPages[%i].PhysAddr = %P", i, pages[i].PhysAddr);
for( j = 0; j < nBlocks; j++ )
- State->Internal->AllocatedPages[i].Bitmap |= 1 << j;
- LOG("AllocatedPages[%i].Bitmap = 0b%b", i, State->Internal->AllocatedPages[i].Bitmap);
- *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16;
+ pages[i].Bitmap |= 1 << j;
+ LOG("AllocatedPages[%i].Bitmap = 0b%b", i, pages[i].Bitmap);
+ *Segment = (VM8086_USER_BASE + i * 0x1000) / 16;
*Offset = 0;
- LOG(" - %x:%x", *Segment, *Offset);
- return (void*) State->Internal->AllocatedPages[i].VirtBase;
+ LOG(" - %04x:%04x", *Segment, *Offset);
+ return (void*) pages[i].VirtBase;
}
void *VM8086_GetPointer(tVM8086 *State, Uint16 Segment, Uint16 Offset)
{
- return (void*)( KERNEL_BASE + Segment*16 + Offset );
+ Uint32 addr = Segment * 16 + Offset;
+
+ if( VM8086_USER_BASE <= addr && addr < VM8086_USER_BASE + VM8086_PAGES_PER_INST*0x1000 )
+ {
+ int pg = (addr - VM8086_USER_BASE) / 0x1000;
+ if( State->Internal->AllocatedPages[pg].VirtBase == 0)
+ return NULL;
+ else
+ return (Uint8*)State->Internal->AllocatedPages[pg].VirtBase + (addr & 0xFFF);
+ }
+ else
+ {
+ return (void*)( KERNEL_BASE + addr );
+ }
}
void VM8086_Int(tVM8086 *State, Uint8 Interrupt)
/*
+ * Acess2 Kernel (x86-64/amd64)
+ * - By John Hodge (thePowersGang)
+ *
+ * vm8086.c
+ * - Real-mode emulation (Stub until emulator is included)
*/
#include <acess.h>
#include <vm8086.h>
if( Width != mode.width || Height != mode.height )
{
Log_Warning("VTerm",
- "Selected resolution (%ix%i is not supported) by the device, using (%ix%i)",
+ "Selected resolution (%ix%i) is not supported by the device, using (%ix%i)",
giVT_RealWidth, giVT_RealHeight,
mode.width, mode.height
);
int Threads_SetUID(Uint *Errno, tUID ID);
int Threads_SetGID(Uint *Errno, tUID ID);
#endif
+void Threads_int_DumpThread(tThread *thread);
void Threads_Dump(void);
void Threads_DumpActive(void);
if( IsHeap(oldname) ) free( oldname );
cur->ThreadName = strdup(NewName);
- Log_Debug("Threads", "Thread renamed to '%s'", NewName);
+// Log_Debug("Threads", "Thread renamed to '%s'", NewName);
return 0;
}
newproc->nThreads = 1;
// Reference all handles in the VFS
VFS_ReferenceUserHandles();
+
+ newproc->FirstThread = new;
+ new->ProcessNext = NULL;
}
else {
new->Process->nThreads ++;
+ new->Process = cur->Process;
+ // TODO: Locking
+ new->ProcessNext = new->Process->FirstThread;
+ new->Process->FirstThread = new;
}
// Messages are not inherited
}
// ---
+void Threads_int_DumpThread(tThread *thread)
+{
+ Log(" %p %i (%i) - %s (CPU %i) - %i (%s)",
+ thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU,
+ thread->Status, casTHREAD_STAT[thread->Status]
+ );
+ switch(thread->Status)
+ {
+ case THREAD_STAT_MUTEXSLEEP:
+ Log(" Mutex Pointer: %p", thread->WaitPointer);
+ break;
+ case THREAD_STAT_SEMAPHORESLEEP:
+ Log(" Semaphore Pointer: %p", thread->WaitPointer);
+ Log(" Semaphore Name: %s:%s",
+ ((tSemaphore*)thread->WaitPointer)->ModName,
+ ((tSemaphore*)thread->WaitPointer)->Name
+ );
+ break;
+ case THREAD_STAT_ZOMBIE:
+ Log(" Return Status: %i", thread->RetStatus);
+ break;
+ default: break;
+ }
+ Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
+ Log(" KStack 0x%x", thread->KernelStack);
+ if( thread->bInstrTrace )
+ Log(" Tracing Enabled");
+ Proc_DumpThreadCPUState(thread);
+}
+
/**
* \fn void Threads_Dump(void)
*/
#endif
for(thread=list->Head;thread;thread=thread->Next)
{
- Log(" %p %i (%i) - %s (CPU %i)",
- thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU);
+ Threads_int_DumpThread(thread);
if(thread->Status != THREAD_STAT_ACTIVE)
Log(" ERROR State (%i) != THREAD_STAT_ACTIVE (%i)",
thread->Status, THREAD_STAT_ACTIVE);
- Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
- Log(" KStack 0x%x", thread->KernelStack);
- if( thread->bInstrTrace )
- Log(" Tracing Enabled");
- Proc_DumpThreadCPUState(thread);
}
#if SCHEDULER_TYPE == SCHED_RR_PRI
Log("All Threads:");
for(thread=gAllThreads;thread;thread=thread->GlobalNext)
{
- Log(" %p %i (%i) - %s (CPU %i)",
- thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU);
- Log(" State %i (%s)", thread->Status, casTHREAD_STAT[thread->Status]);
- switch(thread->Status)
- {
- case THREAD_STAT_MUTEXSLEEP:
- Log(" Mutex Pointer: %p", thread->WaitPointer);
- break;
- case THREAD_STAT_SEMAPHORESLEEP:
- Log(" Semaphore Pointer: %p", thread->WaitPointer);
- Log(" Semaphore Name: %s:%s",
- ((tSemaphore*)thread->WaitPointer)->ModName,
- ((tSemaphore*)thread->WaitPointer)->Name
- );
- break;
- case THREAD_STAT_ZOMBIE:
- Log(" Return Status: %i", thread->RetStatus);
- break;
- default: break;
- }
- Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
- Log(" KStack 0x%x", thread->KernelStack);
- if( thread->bInstrTrace )
- Log(" Tracing Enabled");
- Proc_DumpThreadCPUState(thread);
+ Threads_int_DumpThread(thread);
}
}
// Check BGA Version\r
version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
LOG("version = 0x%x", version);\r
+ if( version == 0xFFFF ) {\r
+ // Floating bus, nothing there\r
+ return MODULE_ERR_NOTNEEDED;\r
+ }\r
\r
// NOTE: This driver was written for BGA versions >= 0xBOC2\r
// NOTE: However, Qemu is braindead and doesn't return the actual version\r
}\r
\r
modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs);\r
+ LOG("Virtual addres of mode list from %04x:%04x is %p",\r
+ info->VideoModes.seg, info->VideoModes.ofs, modes);\r
// VM8086_Deallocate( gpVesa_BiosState, info );\r
\r
// Count Modes\r
return ;\r
}\r
\r
+ #if 0\r
#define S_LOG(s, fld, fmt) LOG(" ."#fld" = "fmt, (s).fld)\r
LOG("vbeinfo[0x%x] = {", mode->code);\r
S_LOG(*vbeinfo, attributes, "0x%02x");\r
S_LOG(*vbeinfo, segmentB, "0x%04x");\r
LOG(" .realFctPtr = %04x:%04x", vbeinfo->realFctPtr.seg, vbeinfo->realFctPtr.ofs);\r
S_LOG(*vbeinfo, pitch, "0x%04x");\r
+\r
// -- Extended\r
S_LOG(*vbeinfo, Xres, "%i");\r
S_LOG(*vbeinfo, Yres, "%i");\r
S_LOG(*vbeinfo, image_count_banked, "%i");\r
S_LOG(*vbeinfo, image_count_lfb, "%i");\r
LOG("}");\r
+ #endif\r
\r
mode->flags = FLAG_POPULATED;\r
if( !(vbeinfo->attributes & 1) ) {\r
int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data)\r
{\r
int i;\r
- int best = -1, bestFactor = 1000;\r
- int factor, tmp;\r
+ int best = -1, tmp;\r
+ unsigned int factor, bestFactor = -1;\r
\r
ENTER("idata->width idata->height idata->bpp", data->width, data->height, data->bpp);\r
\r
Vesa_int_FillModeList();\r
\r
- for(i=0;i<giVesaModeCount;i++)\r
+ for(i = 0; i < giVesaModeCount; i ++)\r
{\r
LOG("Mode %i (%ix%ix%i)", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
\r
tmp = gVesa_Modes[i].width * gVesa_Modes[i].height;\r
tmp -= data->width * data->height;\r
tmp = tmp < 0 ? -tmp : tmp;\r
- factor = tmp * 1000 / (data->width * data->height);\r
+ factor = (Uint64)tmp * 1000 / (data->width * data->height);\r
\r
if( data->bpp == 8 && gVesa_Modes[i].bpp != 8 ) continue;\r
if( data->bpp == 16 && gVesa_Modes[i].bpp != 16 ) continue;\r
--- /dev/null
+#
+#
+
+OBJ = rhine2.o
+NAME = VIARhineII
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess2 VIA Rhine II Driver (VT6102)
+ * - By John Hodge (thePowersGang)
+ */
+#define DEBUG 0
+#define VERSION ((0<<8)|10)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <api_drv_network.h>
+#include <semaphore.h>
+
+// === CONSTANTS ===
+#define VENDOR_ID 0x1106
+#define DEVICE_ID 0x3065
+
+enum eRegs
+{
+ REG_PAR0, REG_PAR1,
+ REG_PAR2, REG_PAR3,
+ REG_PAR4, REG_PAR5,
+ REG_RCR, REG_TCR,
+ REG_CR0, REG_CR1,
+ REG_rsv0, REG_rsv1,
+ REG_ISR0, REG_ISR1,
+ REG_IMR0, REG_IMR1,
+};
+
+// === TYPES ===
+typedef struct sCard
+{
+ Uint16 IOBase;
+ Uint8 IRQ;
+
+ int NumWaitingPackets;
+
+ char Name[2];
+ tVFS_Node Node;
+ Uint8 MacAddr[6];
+} tCard;
+
+// === PROTOTYPES ===
+ int Rhine2_Install(char **Options);
+char *Rhine2_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node *Rhine2_FindDir(tVFS_Node *Node, const char *Filename);
+ int Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Arg);
+Uint64 Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+Uint64 Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+ int Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Arg);
+void Rhine2_IRQHandler(int Num);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, VIARhineII, Rhine2_Install, NULL, NULL);
+tVFS_NodeType gRhine2_DirType = {
+ .ReadDir = Rhine2_ReadDir,
+ .FindDir = Rhine2_FindDir,
+ .IOCtl = Rhine2_RootIOCtl
+ };
+tDevFS_Driver gRhine2_DriverInfo = {
+ NULL, "Rhine2",
+ {
+ .NumACLs = 1,
+ .ACLs = &gVFS_ACL_EveryoneRX,
+ .Flags = VFS_FFLAG_DIRECTORY,
+ .Type = &gRhine2_DirType
+ }
+};
+ int giRhine2_CardCount;
+tCard *gaRhine2_Cards;
+
+// === CODE ===
+/**
+ * \brief Installs the PCnet3 Driver
+ */
+int Rhine2_Install(char **Options)
+{
+ int id = -1;
+ int i = 0;
+// Uint16 base;
+ tCard *card;
+
+ giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
+ Log_Debug("PCnet3", "%i cards", giRhine2_CardCount);
+
+ if( giRhine2_CardCount == 0 ) return MODULE_ERR_NOTNEEDED;
+
+ gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
+
+ while( (id = PCI_GetDevice(VENDOR_ID, DEVICE_ID, i)) != -1 )
+ {
+ card = &gaRhine2_Cards[i];
+
+ LOG("BAR0 = 0x%08x", PCI_GetBAR(id, 0));
+ LOG("BAR1 = 0x%08x", PCI_GetBAR(id, 1));
+ LOG("BAR2 = 0x%08x", PCI_GetBAR(id, 2));
+ LOG("BAR3 = 0x%08x", PCI_GetBAR(id, 3));
+ LOG("BAR4 = 0x%08x", PCI_GetBAR(id, 4));
+ LOG("BAR5 = 0x%08x", PCI_GetBAR(id, 5));
+
+// card->IOBase = base;
+// card->IRQ = PCI_GetIRQ( id );
+
+ // Install IRQ Handler
+// IRQ_AddHandler(card->IRQ, Rhine2_IRQHandler);
+
+
+
+// Log_Log("PCnet3", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x",
+// i, card->IOBase, card->IRQ,
+// card->MacAddr[0], card->MacAddr[1], card->MacAddr[2],
+// card->MacAddr[3], card->MacAddr[4], card->MacAddr[5]
+// );
+
+ i ++;
+ }
+
+ gRhine2_DriverInfo.RootNode.Size = giRhine2_CardCount;
+ DevFS_AddDevice( &gRhine2_DriverInfo );
+
+ return MODULE_ERR_OK;
+}
+
+// --- Root Functions ---
+char *Rhine2_ReadDir(tVFS_Node *Node, int Pos)
+{
+ if( Pos < 0 || Pos >= giRhine2_CardCount ) return NULL;
+
+ return strdup( gaRhine2_Cards[Pos].Name );
+}
+
+tVFS_Node *Rhine2_FindDir(tVFS_Node *Node, const char *Filename)
+{
+ //TODO: It might be an idea to supprt >10 cards
+ if(Filename[0] == '\0' || Filename[1] != '\0') return NULL;
+ if(Filename[0] < '0' || Filename[0] > '9') return NULL;
+ return &gaRhine2_Cards[ Filename[0]-'0' ].Node;
+}
+
+const char *csaRhine2_RootIOCtls[] = {DRV_IOCTLNAMES, NULL};
+int Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ ENTER("pNode iID pData", Node, ID, Data);
+ switch(ID)
+ {
+ BASE_IOCTLS(DRV_TYPE_NETWORK, "PCnet3", VERSION, csaRhine2_RootIOCtls);
+ }
+ LEAVE('i', 0);
+ return 0;
+}
+
+// --- File Functions ---
+Uint64 Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+ #if 0
+ tCard *card = Node->ImplPtr;
+ Uint16 read_ofs, pkt_length;
+ int new_read_ofs;
+
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+
+retry:
+ if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 )
+ {
+ LEAVE_RET('i', 0);
+ }
+
+ Mutex_Acquire( &card->ReadMutex );
+
+ read_ofs = inw( card->IOBase + CAPR );
+ LOG("raw read_ofs = %i", read_ofs);
+ read_ofs = (read_ofs + 0x10) & 0xFFFF;
+ LOG("read_ofs = %i", read_ofs);
+
+ pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
+
+ // Calculate new read offset
+ new_read_ofs = read_ofs + pkt_length + 4;
+ new_read_ofs = (new_read_ofs + 3) & ~3; // Align
+ if(new_read_ofs > card->ReceiveBufferLength) {
+ LOG("wrapping read_ofs");
+ new_read_ofs -= card->ReceiveBufferLength;
+ }
+ new_read_ofs -= 0x10; // I dunno
+ LOG("new_read_ofs = %i", new_read_ofs);
+
+ // Check for errors
+ if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) {
+ // Update CAPR
+ outw(card->IOBase + CAPR, new_read_ofs);
+ Mutex_Release( &card->ReadMutex );
+ goto retry; // I feel evil
+ }
+
+ // Get packet
+ if( Length > pkt_length ) Length = pkt_length;
+ memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length);
+
+ // Update CAPR
+ outw(card->IOBase + CAPR, new_read_ofs);
+
+ Mutex_Release( &card->ReadMutex );
+
+ LEAVE('i', Length);
+ #endif
+
+ return Length;
+}
+
+Uint64 Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+ #if 0
+ int td;
+ Uint32 status;
+ tCard *card = Node->ImplPtr;
+
+ if( Length > 1500 ) return 0; // MTU exceeded
+
+ ENTER("pNode XLength pBuffer", Node, Length, Buffer);
+
+ // TODO: Implement a semaphore for avaliable transmit buffers
+
+ // Find an avaliable descriptor
+ Mutex_Acquire(&card->CurTXProtector);
+ td = card->CurTXDescriptor;
+ card->CurTXDescriptor ++;
+ card->CurTXDescriptor %= 4;
+ Mutex_Release(&card->CurTXProtector);
+ // - Lock it
+ Mutex_Acquire( &card->TransmitInUse[td] );
+
+ LOG("td = %i", td);
+
+ // Transmit using descriptor `td`
+ LOG("card->PhysTransmitBuffers[td] = %P", card->PhysTransmitBuffers[td]);
+ outd(card->IOBase + TSAD0 + td*4, card->PhysTransmitBuffers[td]);
+ LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
+ // Copy to buffer
+ memcpy(card->TransmitBuffers[td], Buffer, Length);
+ // Start
+ status = 0;
+ status |= Length & 0x1FFF; // 0-12: Length
+ status |= 0 << 13; // 13: OWN bit
+ status |= (0 & 0x3F) << 16; // 16-21: Early TX threshold (zero atm, TODO: check)
+ LOG("status = 0x%08x", status);
+ outd(card->IOBase + TSD0 + td*4, status);
+
+ LEAVE('i', (int)Length);
+ #endif
+
+ return Length;
+}
+
+const char *csaRhine2_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL};
+int Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ tCard *card = Node->ImplPtr;
+ ENTER("pNode iID pData", Node, ID, Data);
+ switch(ID)
+ {
+ BASE_IOCTLS(DRV_TYPE_NETWORK, "PCnet3", VERSION, csaRhine2_NodeIOCtls);
+ case NET_IOCTL_GETMAC:
+ if( !CheckMem(Data, 6) ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ memcpy( Data, card->MacAddr, 6 );
+ LEAVE('i', 1);
+ return 1;
+ }
+ LEAVE('i', 0);
+ return 0;
+}
+
+void Rhine2_IRQHandler(int Num)
+{
+ #if 0
+ int i, j;
+ tCard *card;
+ Uint16 status;
+
+ LOG("Num = %i", Num);
+
+ for( i = 0; i < giRhine2_CardCount; i ++ )
+ {
+ card = &gaRhine2_Cards[i];
+ if( Num != card->IRQ ) break;
+
+ status = inw(card->IOBase + ISR);
+ LOG("status = 0x%02x", status);
+
+ // Transmit OK, a transmit descriptor is now free
+ if( status & FLAG_ISR_TOK )
+ {
+ for( j = 0; j < 4; j ++ )
+ {
+ if( ind(card->IOBase + TSD0 + j*4) & 0x8000 ) { // TSD TOK
+ Mutex_Release( &card->TransmitInUse[j] );
+ // TODO: Update semaphore once implemented
+ }
+ }
+ outw(card->IOBase + ISR, FLAG_ISR_TOK);
+ }
+
+ // Recieve OK, inform read
+ if( status & FLAG_ISR_ROK )
+ {
+ int read_ofs, end_ofs;
+ int packet_count = 0;
+ int len;
+
+ // Scan recieve buffer for packets
+ end_ofs = inw(card->IOBase + CBA);
+ read_ofs = card->SeenOfs;
+ LOG("read_ofs = %i, end_ofs = %i", read_ofs, end_ofs);
+ if( read_ofs > end_ofs )
+ {
+ while( read_ofs < card->ReceiveBufferLength )
+ {
+ packet_count ++;
+ len = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
+ LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x",
+ packet_count, read_ofs,
+ *(Uint16*)&card->ReceiveBuffer[read_ofs],
+ len
+ );
+ if(len > 2000) {
+ Log_Warning("PCnet3", "IRQ: Packet in buffer exceeds sanity (%i>2000)", len);
+ }
+ read_ofs += len + 4;
+ read_ofs = (read_ofs + 3) & ~3; // Align
+ }
+ read_ofs -= card->ReceiveBufferLength;
+ LOG("wrapped read_ofs");
+ }
+ while( read_ofs < end_ofs )
+ {
+ packet_count ++;
+ LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x",
+ packet_count, read_ofs,
+ *(Uint16*)&card->ReceiveBuffer[read_ofs],
+ *(Uint16*)&card->ReceiveBuffer[read_ofs+2]
+ );
+ read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+2] + 4;
+ read_ofs = (read_ofs + 3) & ~3; // Align
+ }
+ if( read_ofs != end_ofs ) {
+ Log_Warning("PCnet3", "IRQ: read_ofs (%i) != end_ofs(%i)", read_ofs, end_ofs);
+ read_ofs = end_ofs;
+ }
+ card->SeenOfs = read_ofs;
+
+ LOG("packet_count = %i, read_ofs = 0x%x", packet_count, read_ofs);
+
+ if( packet_count )
+ {
+ if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) {
+ // Oops?
+ }
+ VFS_MarkAvaliable( &card->Node, 1 );
+ }
+
+ outw(card->IOBase + ISR, FLAG_ISR_ROK);
+ }
+ }
+ #endif
+}
if( desc.ManufacturerStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr);
- LOG("ManufacturerStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("ManufacturerStr = '%s'", tmp);
+ free(tmp);
+ }
}
if( desc.ProductStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.ProductStr);
- LOG("ProductStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("ProductStr = '%s'", tmp);
+ free(tmp);
+ }
}
if( desc.SerialNumberStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr);
- LOG("SerialNumbertStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("SerialNumbertStr = '%s'", tmp);
+ free(tmp);
+ }
}
#endif
}
if(Index == 0) return strdup("");
+ str.Length = 0;
USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
+ if(str.Length == 0) return NULL;
if(str.Length < 2) {
Log_Error("USB", "String %p:%i:%i:%i descriptor is undersized (%i)",
Dev->Host, Dev->Address, Endpoint, Index, str.Length);
#include <semaphore.h>
// === CONSTANTS ===
-#define MAX_CONTROLLERS 4
+#define MAX_CONTROLLERS 8
//#define NUM_TDs 1024
#define NUM_TDs (PAGE_SIZE/sizeof(tUHCI_TD))
#define MAX_PACKET_SIZE 0x400
{
tPAddr tmp;
gaUHCI_TDPool = (void *) MM_AllocDMA(1, 32, &tmp);
+ memset(gaUHCI_TDPool, 0, PAGE_SIZE);
}
// Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
if(gaUHCI_TDPool[i]._info.bActive == 0)
{
gaUHCI_TDPool[i].Link = 1;
- gaUHCI_TDPool[i].Control = (1 << 23);
+ gaUHCI_TDPool[i].Control = TD_CTL_ACTIVE;
gaUHCI_TDPool[i]._info.bActive = 1;
gaUHCI_TDPool[i]._info.QueueIndex = 128;
Mutex_Release( &lock );
Mutex_Acquire(&lock);
// Ensure that there is an interrupt for each used frame
- TD->Control |= (1 << 24);
+ TD->Control |= TD_CTL_IOC;
TD->_info.QueueIndex = ((tVAddr)QH - (tVAddr)Cont->TDQHPage->InterruptQHs) / sizeof(tUHCI_QH);
+ LOG("TD(%p)->QueueIndex = %i", TD, TD->_info.QueueIndex);
// Update length
TD->Control &= ~0x7FF;
TD->Control |= (TD->Token >> 21) & 0x7FF;
td, Length, Type, Addr);
td->Control = (Length - 1) & 0x7FF;
- td->Control |= (1 << 23); // Active set
+ td->Control |= TD_CTL_ACTIVE; // Active set
td->Control |= (3 << 27); // 3 retries
+ // High speed device (must be explicitly enabled
+ if( Addr & 0x8000 )
+ ;
+ else
+ td->Control |= 1 << 26;
+
td->Token = ((Length - 1) & 0x7FF) << 21;
td->Token |= (bTgl & 1) << 19;
td->Token |= (Addr & 0xF) << 15;
tVAddr ptr = MM_MapTemp(td->BufferPointer);
memcpy( (void*)ptr, Data, Length );
MM_FreeTemp(ptr);
- td->Control |= (1 << 24);
+ td->Control |= TD_CTL_IOC;
}
td->_info.bFreePointer = 1;
}
if( info ) {
LOG("info = %p", info);
- td->Control |= (1 << 24);
+ td->Control |= TD_CTL_IOC;
td->_info.ExtraInfo = info;
}
{
tUHCI_TD *td, *prev = NULL;
Uint32 cur_td;
+ int nCleaned = 0;
// Disable controller
_OutWord( Cont, USBCMD, 0x0000 );
// Scan QH list
cur_td = QH->Child;
+ LOG("cur_td = 0x%08x", cur_td);
while( !(cur_td & 1) )
{
td = UHCI_int_GetTDFromPhys(Cont, cur_td);
}
// Active? Ok.
- if( td->Control & (1 << 23) ) {
+ if( td->Control & TD_CTL_ACTIVE ) {
+ LOG("%p still active", td);
prev = td;
+ cur_td = td->Link;
continue ;
}
else
prev->Link = td->Link;
cur_td = td->Link;
+ nCleaned ++;
+ }
+
+ if( nCleaned == 0 ) {
+ LOG("Nothing cleaned... what the?");
}
// re-enable controller
Threads_SetName("UHCI Interrupt Handler");
for( ;; )
{
+ int nSeen = 0;
+
LOG("zzzzz....");
// 0 = Take all
Semaphore_Wait(&gUHCI_InterruptSempahore, 0);
// Skip completely inactive TDs
if( td->_info.bActive == 0 ) continue ;
// Skip ones that are still in use
- if( td->Control & (1 << 23) ) continue ;
+ if( td->Control & TD_CTL_ACTIVE ) continue ;
+
+ nSeen ++;
// If no callback/alt buffer, mark as free and move on
if( td->_info.ExtraInfo )
// Error check
if( td->Control & 0x00FF0000 ) {
LOG("td->control(Status) = %s%s%s%s%s%s%s%s",
- td->Control & (1 << 23) ? "Active " : "",
- td->Control & (1 << 22) ? "Stalled " : "",
- td->Control & (1 << 21) ? "Data Buffer Error " : "",
- td->Control & (1 << 20) ? "Babble " : "",
- td->Control & (1 << 19) ? "NAK " : "",
- td->Control & (1 << 18) ? "CRC Error, " : "",
- td->Control & (1 << 17) ? "Bitstuff Error, " : "",
- td->Control & (1 << 16) ? "Reserved " : ""
+ td->Control & TD_CTL_ACTIVE ? "Active, " : "",
+ td->Control & TD_CTL_STALLED ? "Stalled, " : "",
+ td->Control & TD_CTL_DATABUFERR ? "Data Buffer Error, " : "",
+ td->Control & TD_CTL_BABBLE ? "Babble, " : "",
+ td->Control & TD_CTL_NAK ? "NAK, " : "",
+ td->Control & TD_CTL_CRCERR ? "CRC Error, " : "",
+ td->Control & TD_CTL_BITSTUFF ? "Bitstuff Error, " : "",
+ td->Control & TD_CTL_RESERVED ? "Reserved " : ""
);
+ LOG("From queue %i", td->_info.QueueIndex);
// Clean up QH (removing all inactive entries)
UHCI_int_CleanQH(Cont, Cont->TDQHPage->InterruptQHs + td->_info.QueueIndex);
+ td->Control = 0;
}
// Handle rescheduling of interrupt TDs
{
LOG("Re-schedule interrupt %p (offset %i)", td, td->_info.QueueIndex);
// TODO: Flip toggle?
- td->Control |= (1 << 23);
+ td->Control |= TD_CTL_ACTIVE;
// Add back into controller's interrupt list
UHCI_int_AppendTD(
Cont,
LOG("Cleaned %p (->Control = %x)", td, td->Control);
td->_info.bActive = 0;
}
+
+ if( nSeen == 0 ) {
+ LOG("Why did you wake me?");
+ }
}
}
// int frame = (_InWord(Host, FRNUM) - 1) & 0x3FF;
Uint16 status = _InWord(Host, USBSTS);
+ LOG("%p: status = 0x%04x", Ptr, status);
// Interrupt-on-completion
if( status & 1 )
{
Semaphore_Signal(&gUHCI_InterruptSempahore, 1);
}
- LOG("status = 0x%04x", status);
_OutWord(Host, USBSTS, status);
}
void *CallbackPtr;
};
+#define TD_CTL_IOC (1 << 24)
+
+#define TD_CTL_ACTIVE (1 << 23)
+#define TD_CTL_STALLED (1 << 22)
+#define TD_CTL_DATABUFERR (1 << 21)
+#define TD_CTL_BABBLE (1 << 20)
+#define TD_CTL_NAK (1 << 19)
+#define TD_CTL_CRCERR (1 << 18)
+#define TD_CTL_BITSTUFF (1 << 17)
+#define TD_CTL_RESERVED (1 << 16)
+
struct sUHCI_TD
{
/**