-BUILD_NUM = 1438
+BUILD_NUM = 1447
void IRQ_Handler(tRegs *Regs)
{
int i;
-
+
Regs->int_num -= 0xF0; // Adjust
-
+
//Log("IRQ_Handler: (Regs={int_num:%i})", Regs->int_num);
-
+
for( i = 0; i < MAX_CALLBACKS_PER_IRQ; i++ )
{
//Log(" IRQ_Handler: Call %p", gIRQ_Handlers[Regs->int_num][i]);
if( gIRQ_Handlers[Regs->int_num][i] )
gIRQ_Handlers[Regs->int_num][i](Regs->int_num);
}
-
+
//Log(" IRQ_Handler: Resetting");
if(Regs->int_num >= 8)
outb(0xA0, 0x20); // ACK IRQ (Secondary PIC)
for( i = 0; i < MAX_CALLBACKS_PER_IRQ; i++ )
{
if( gIRQ_Handlers[Num][i] == NULL ) {
+ Log("IRQ_AddHandler: Added IRQ%i Cb#%i %p", Num, i, Callback);
gIRQ_Handlers[Num][i] = Callback;
return 1;
}
}
-
+
+ Warning("IRQ_AddHandler - No free callbacks on IRQ%i", Num);
return 0;
}
{
if(giDebug_KTerm != -1)
VFS_Write(giDebug_KTerm, 1, &ch);
-
+
#if DEBUG_TO_SERIAL
if(!gbDebug_SerialSetup) {
- outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
- outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
- outb(SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
- outb(SERIAL_PORT + 1, 0x00); // (hi byte)
- outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
- outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
- outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
gbDebug_SerialSetup = 1;
}
while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
outb(SERIAL_PORT, ch);
#endif
-
+
#if DEBUG_TO_E9
__asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
#endif
char *p = NULL;
int isLongLong = 0;
Uint64 arg;
-
+
while((c = *format++) != 0)
{
// Non control character
E9(c);
continue;
}
-
+
c = *format++;
-
+
// Literal %
if(c == '%') {
E9('%');
continue;
}
-
+
// Pointer
if(c == 'p') {
Uint ptr = va_arg(*args, Uint);
itoa(p, ptr, 16, BITS/4, '0');
goto printString;
}
-
+
// Get Argument
arg = va_arg(*args, Uint);
-
+
// Padding
if(c == '0') {
pad = '0';
c = *format++;
} else
pad = ' ';
-
+
// Minimum length
minSize = 1;
if('1' <= c && c <= '9')
c = *format++;
}
}
-
+
// Long (default)
isLongLong = 0;
if(c == 'l') {
isLongLong = 1;
}
}
-
+
p = tmpBuf;
switch (c) {
case 'd':
if(arg) E9_Str("True");
else E9_Str("False");
break;
-
+
case 's':
p = (char*)(Uint)arg;
printString:
if(!p) p = "(null)";
while(*p) E9(*p++);
break;
-
+
// Single Character / Array
case 'c':
if(minSize == 1) {
if(!p) goto printString;
while(minSize--) E9(*p++);
break;
-
+
default: E9(arg); break;
}
}
void LogF(char *Fmt, ...)
{
va_list args;
-
+
va_start(args, Fmt);
-
+
E9_Fmt(Fmt, &args);
-
+
va_end(args);
}
/**
void Log(char *Fmt, ...)
{
va_list args;
-
+
E9_Str("Log: ");
va_start(args, Fmt);
E9_Fmt(Fmt, &args);
E9_Fmt(Fmt, &args);
va_end(args);
E9('\n');
-
+
Threads_Dump();
-
+
__asm__ __volatile__ ("xchg %bx, %bx");
__asm__ __volatile__ ("cli;\n\thlt");
for(;;) __asm__ __volatile__ ("hlt");
va_list args;
int i = gDebug_Level ++;
int pos;
-
+
va_start(args, ArgTypes);
-
+
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": (");
-
+
while(*ArgTypes)
{
pos = strpos(ArgTypes, ' ');
if(pos != -1) {
E9(','); E9(' ');
}
-
+
if(pos == -1) break;
ArgTypes = &ArgTypes[pos+1];
}
-
+
va_end(args);
E9(')'); E9('\n');
}
{
va_list args;
int i = gDebug_Level;
-
+
va_start(args, Fmt);
-
+
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": ");
E9_Fmt(Fmt, &args);
-
+
va_end(args);
E9('\n');
}
{
va_list args;
int i = --gDebug_Level;
-
+
va_start(args, RetType);
-
+
if( i == -1 ) {
gDebug_Level = 0;
i = 0;
}
// Indenting
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": RETURN");
-
+
// No Return
if(RetType == '-') {
E9('\n');
return;
}
-
+
E9(' ');
switch(RetType)
{
case 'X': E9_Fmt("0x%llx", &args); break;
}
E9('\n');
-
+
va_end(args);
}
Uint pos = 0;
E9_Str(Header);
LogF(" (Hexdump of %p)\n", Data);
-
+
while(Length >= 16)
{
Log("%04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
cdat += 16;
pos += 16;
}
-
+
LogF("Log: %04x: ", pos);
while(Length)
{
{
IRQ_AddHandler(1, KB_IRQHandler);
DevFS_AddDevice( &gKB_DevInfo );
+ //Log("KB_Install: Installed");
return 1;
}
// int keyNum;
//if( inportb(0x64) & 0x20 ) return;
-
+
scancode = inb(0x60); // Read from the keyboard's data buffer
+ Log("KB_IRQHandler: scancode = 0x%02x", scancode);
+
// Ignore ACKs
if(scancode == 0xFA) {
// Oh man! This is anachic (I'm leaving it here to represent the
- // mess that acess once was
+ // mess that Acess once was)
//kb_lastChar = KB_ACK;
return;
}
-
+
// Layer +1
if(scancode == 0xE0) {
giKB_KeyLayer = 1;
giKB_KeyLayer = 2;
return;
}
-
+
#if KB_ALT_SCANCODES
if(scancode == 0xF0)
{
gbKB_KeyUp = 1;
}
#endif
-
+
// Translate
ch = gpKB_Map[giKB_KeyLayer][scancode];
//keyNum = giKB_KeyLayer * 256 + scancode;
// Check for unknown key
if(!ch && !gbKB_KeyUp)
Warning("UNK %i %x", giKB_KeyLayer, scancode);
-
+
// Key Up?
if (gbKB_KeyUp)
{
gbKB_KeyUp = 0;
gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
-
+
#if USE_KERNEL_MAGIC
if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
if(ch == KEY_LALT) gbKB_MagicState &= ~2;
#endif
-
+
if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
-
+
// Call callback
if(ch != 0 && gKB_Callback)
gKB_Callback( ch & 0x80000000 );
-
+
// Reset Layer
giKB_KeyLayer = 0;
return;
// Set shift key bits
if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
-
+
// Check for Caps Lock
if(ch == KEY_CAPSLOCK) {
gbKB_CapsState = !gbKB_CapsState;
KB_UpdateLEDs();
}
-
+
// Reset Layer
giKB_KeyLayer = 0;
// Ignore Non-Printable Characters
if(ch == 0) return;
-
+
// --- Check for Kernel Magic Combos
#if USE_KERNEL_MAGIC
if(ch == KEY_LCTRL) gbKB_MagicState |= 1;
}
}
#endif
-
+
// Is shift pressed
// - Darn ugly hacks !(!x) means (bool)x
if( !(!gbKB_ShiftState) ^ gbKB_CapsState)
break;
}
}
-
+
if(gKB_Callback && ch != 0) gKB_Callback(ch);
}
void KB_UpdateLEDs()
{
Uint8 leds;
-
+
leds = (gbKB_CapsState ? 4 : 0);
-
+
while( inb(0x64) & 2 ); // Wait for bit 2 to unset
outb(0x60, 0xED); // Send update command
-
+
while( inb(0x64) & 2 ); // Wait for bit 2 to unset
outb(0x60, leds);
}
case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
case DRV_IOCTL_VERSION: return 0x100;
case DRV_IOCTL_LOOKUP: return 0;
-
+
// Sets the Keyboard Callback
case KB_IOCTL_SETCALLBACK:
// Sanity Check
// Set Callback
gKB_Callback = Data;
return 1;
-
+
default:
return 0;
}
void Heap_Dump();
// === GLOBALS ===
- int giHeapSpinlock;
+ int glHeap;
void *gHeapStart;
void *gHeapEnd;
Bytes = (Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + BLOCK_SIZE-1) & ~(BLOCK_SIZE-1);
// Lock Heap
- LOCK(&giHeapSpinlock);
+ LOCK(&glHeap);
// Traverse Heap
for( head = gHeapStart;
Warning("Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
Heap_Dump();
#endif
+ RELEASE(&glHeap);
return NULL;
}
Warning("Magic of heap address %p is invalid (0x%x)", head, head->Magic);
Heap_Dump();
#endif
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
return NULL;
}
// Perfect fit
if(head->Size == Bytes) {
head->Magic = MAGIC_USED;
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
#if DEBUG_TRACE
LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
#endif
best = Heap_Extend( Bytes );
// Check for errors
if(!best) {
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
return NULL;
}
// Check size
if(best->Size == Bytes) {
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
#if DEBUG_TRACE
LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
#endif
best->Size = Bytes; // Update size in old header
best->Magic = MAGIC_USED; // Mark block as used
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
#if DEBUG_TRACE
LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
#endif
}
// Lock
- LOCK( &giHeapSpinlock );
+ LOCK( &glHeap );
// Mark as free
head->Magic = MAGIC_FREE;
Heap_Merge( head );
// Release
- RELEASE( &giHeapSpinlock );
+ RELEASE( &glHeap );
}
/**
//! These are the official lookup names of the core calls
#define DRV_IOCTLNAMES "type", "ident", "version", "lookup"
+#define BASE_IOCTLS(_type, _ident, _version, _ioctls) \
+ case DRV_IOCTL_TYPE: LEAVE('i', (_type)); return (_type);\
+ case DRV_IOCTL_IDENT: {\
+ int tmp = ModUtil_SetIdent(Data, (_ident));\
+ LEAVE('i', tmp); return tmp;\
+ }\
+ case DRV_IOCTL_VERSION: LEAVE('x', (_version)); return (_version);\
+ case DRV_IOCTL_LOOKUP:{\
+ int tmp = ModUtil_LookupString( (char**)(_ioctls), (char*)Data );\
+ LEAVE('i', tmp);\
+ return tmp;\
+ }
+
/**
* \enum eTplDrv_Type
* \brief Driver Types returned by DRV_IOCTL_TYPE
// === PROTOTYPES ===
int ARP_Initialise();
- int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address);
+tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address);
void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
// === GLOBALS ===
{
int lastID;
int i;
+ struct sArpRequest4 req;
ENTER("pInterface xAddress", Interface, Address);
RELEASE( &glARP_Cache4 );
lastID = giARP_LastUpdateID;
- ARP_int_Resolve4(Interface, Address);
- for(;;)
- {
- while(lastID == giARP_LastUpdateID) Threads_Yield();
- lastID = giARP_LastUpdateID;
-
- LOCK( &glARP_Cache4 );
- for( i = 0; i < giARP_Cache4Space; i++ )
- {
- if(gaARP_Cache4[i].IP.L != Address.L) continue;
-
- RELEASE( &glARP_Cache4 );
- return gaARP_Cache4[i].MAC;
- }
- RELEASE( &glARP_Cache4 );
- }
-}
-
-/**
- * \fn int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address)
- * \brief Request the network to resolve an IPv4 Address
- * \return Boolean Success
- */
-int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address)
-{
- struct sArpRequest4 req;
+ // Create request
Log("[ARP4 ] Asking for address %i.%i.%i.%i",
Address.B[0], Address.B[1], Address.B[2], Address.B[3]
);
- req.HWType = htons(0x100); // Ethernet
+ req.HWType = htons(1); // Ethernet
req.Type = htons(0x0800);
req.HWSize = 6;
req.SWSize = 4;
req.DestMac = cMAC_BROADCAST;
req.DestIP = Address;
+ // Send Request
Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, sizeof(struct sArpRequest4), &req);
- return 0;
+ // Wait for a reply
+ for(;;)
+ {
+ while(lastID == giARP_LastUpdateID) Threads_Yield();
+ lastID = giARP_LastUpdateID;
+
+ LOCK( &glARP_Cache4 );
+ for( i = 0; i < giARP_Cache4Space; i++ )
+ {
+ if(gaARP_Cache4[i].IP.L != Address.L) continue;
+
+ RELEASE( &glARP_Cache4 );
+ return gaARP_Cache4[i].MAC;
+ }
+ RELEASE( &glARP_Cache4 );
+ }
}
/**
// === PROTOTYPES ===
void TCP_Initialise();
void TCP_StartConnection(tTCPConnection *Conn);
+void TCP_SendPacket( tTCPConnection *Conn, size_t Length, tTCPHeader *Data );
void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header);
Uint16 TCP_GetUnusedPort();
void TCP_StartConnection(tTCPConnection *Conn)
{
tTCPHeader hdr;
-
- hdr->SourcePort = Conn->LocalPort;
- hdr->DestPort = Conn->RemotePort;
+
+ hdr.SourcePort = Conn->LocalPort;
+ hdr.DestPort = Conn->RemotePort;
Conn->NextSequenceSend = rand();
- hdr->SequenceNumber = Conn->NextSequenceSend;
- hdr->DataOffset = (sizeof(tTCPHeader)+3)/4;
- hdr->Flags = TCP_FLAG_SYN;
- hdr->WindowSize = 0; // TODO
- hdr->Checksum = 0; // TODO
- hdr->UrgentPointer = 0;
+ hdr.SequenceNumber = Conn->NextSequenceSend;
+ hdr.DataOffset = (sizeof(tTCPHeader)+3)/4;
+ hdr.Flags = TCP_FLAG_SYN;
+ hdr.WindowSize = 0; // TODO
+ hdr.Checksum = 0; // TODO
+ hdr.UrgentPointer = 0;
// SEND PACKET
TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr );
return ;
{
size_t buflen;
Uint32 *buf;
- switch( Conn->Interface.Type )
+ switch( Conn->Interface->Type )
{
- case 4:
+ case 4: // Append IPv4 Pseudo Header
buflen = 4 + 4 + 4 + ((Length+1)&1);
buf = malloc( buflen );
- buf[0] = Conn->Interface.IP4.Address.L;
+ buf[0] = Conn->Interface->IP4.Address.L;
buf[1] = Conn->RemoteIP.v4.L;
buf[2] = (htons(Length)<<16) | (6<<8) | 0;
Data->Checksum = 0;
- memcpy( &buf[3], Data, buflen );
+ memcpy( &buf[3], Data, Length );
Data->Checksum = IPv4_Checksum( buf, buflen );
free(buf);
- IPv4_SendPacket(Conn->Interface, Conn->RemoteIP.v4, IP4PROT_TCP, 0, sizeof(tTCPHeader), &hdr);
+ IPv4_SendPacket(Conn->Interface, Conn->RemoteIP.v4, IP4PROT_TCP, 0, buflen, buf);
break;
}
}
tTCPHeader *hdr = Buffer;
tTCPListener *srv;
tTCPConnection *conn;
-
+
Log("[TCP ] sizeof(tTCPHeader) = %i", sizeof(tTCPHeader));
Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort));
Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort));
Log("[TCP ] WindowSize = %i", htons(hdr->WindowSize));
Log("[TCP ] Checksum = 0x%x", htons(hdr->Checksum));
Log("[TCP ] UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
-
+
// Check Servers
{
for( srv = gTCP_Listeners; srv; srv = srv->Next )
if(srv->Interface && srv->Interface != Interface) continue;
// Check the destination port
if(srv->Port != hdr->DestPort) continue;
-
+
// Is this in an established connection?
for( conn = srv->Connections; conn; conn = conn->Next )
{
// Check that it is coming in on the same interface
if(conn->Interface != Interface) continue;
-
+
// Check Source Port
if(conn->RemotePort != hdr->SourcePort) continue;
-
+
// Check Source IP
if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
continue;
if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
continue;
-
+
// We have a response!
- TCP_INT_HandleConnectionPacket(conn, hdr)
-
+ TCP_INT_HandleConnectionPacket(conn, hdr);
+
return;
}
-
+
// Open a new connection (well, check that it's a SYN)
//TODO
-
+
break;
}
}
-
-
+
+
// Check Open Connections
{
for( conn = gTCP_OutbountCons; conn; conn = conn->Next )
{
// Check that it is coming in on the same interface
if(conn->Interface != Interface) continue;
-
+
// Check Source Port
if(conn->RemotePort != hdr->SourcePort) continue;
-
+
// Check Source IP
if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
continue;
if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
continue;
-
- TCP_INT_HandleConnectionPacket(conn, hdr)
+
+ TCP_INT_HandleConnectionPacket(conn, hdr);
}
}
}
*/
void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header)
{
-
+
}
/**
Uint16 TCP_GetUnusedPort()
{
Uint16 ret;
-
+
// Get Next outbound port
ret = giTCP_NextOutPort++;
while( gaTCP_PortBitmap[ret/32] & (1 << (ret%32)) )
ret = giTCP_NextOutPort = TCP_MIN_DYNPORT;
}
}
-
+
// Mark the new port as used
gaTCP_PortBitmap[ret/32] |= 1 << (ret%32);
-
+
return ret;
}
// Check if the port has already been allocated
if( gaTCP_PortBitmap[Port/32] & (1 << (Port%32)) )
return 0;
-
+
// Allocate
gaTCP_PortBitmap[Port/32] |= 1 << (Port%32);
-
+
return 1;
}
// Check if the port has already been allocated
if( !(gaTCP_PortBitmap[Port/32] & (1 << (Port%32))) )
return 0;
-
+
// Allocate
gaTCP_PortBitmap[Port/32] &= ~(1 << (Port%32));
-
+
return 1;
}
tVFS_Node *TCP_Server_Init(tInterface *Interface)
{
tTCPListener *srv = malloc( sizeof(tTCPListener) );
-
+
srv->Interface = Interface;
srv->Port = 0;
srv->NextID = 0;
srv->Node.FindDir = TCP_Server_FindDir;
srv->Node.IOCtl = TCP_Server_IOCtl;
srv->Node.Close = TCP_Server_Close;
-
+
LOCK(&glTCP_Listeners);
srv->Next = gTCP_Listeners;
gTCP_Listeners = srv;
RELEASE(&glTCP_Listeners);
-
+
return &srv->Node;
}
tTCPListener *srv = Node->ImplPtr;
tTCPConnection *conn;
char *ret;
-
+
while( srv->NewConnections == NULL ) Threads_Yield();
-
+
conn = srv->NewConnections;
srv->NewConnections = conn->Next;
-
+
ret = malloc(9);
- itoa(ret, conn->ImplInt, 16, '0', 8);
+ itoa(ret, Node->ImplInt, 16, '0', 8);
return ret;
}
int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
{
tTCPListener *srv = Node->ImplPtr;
-
+
switch(ID)
{
case 4: // Get/Set Port
if(!Data) // Get Port
return srv->Port;
-
+
if(srv->Port) // Wait, you can't CHANGE the port
return -1;
-
+
if(!CheckMem(Data, sizeof(Uint16))) // Sanity check
return -1;
-
+
// Permissions check
if(Threads_GetUID() != 0
&& *(Uint16*)Data != 0
&& *(Uint16*)Data < 1024)
return -1;
-
+
// TODO: Check if a port is in use
-
+
// Set Port
srv->Port = *(Uint16*)Data;
if(srv->Port == 0) // Allocate a random port
tVFS_Node *TCP_Client_Init(tInterface *Interface)
{
tTCPConnection *conn = malloc( sizeof(tTCPConnection) );
-
+
conn->State = TCP_ST_CLOSED;
conn->Interface = Interface;
conn->LocalPort = 0;
conn->RemotePort = 0;
memset( &conn->RemoteIP, 0, sizeof(conn->RemoteIP) );
-
+
conn->Node.ImplPtr = conn;
conn->Node.NumACLs = 1;
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
conn->Node.Write = TCP_Client_Write;
conn->Node.IOCtl = TCP_Client_IOCtl;
conn->Node.Close = TCP_Client_Close;
-
+
LOCK(&glTCP_OutbountCons);
conn->Next = gTCP_OutbountCons;
gTCP_OutbountCons = conn;
RELEASE(&glTCP_OutbountCons);
-
+
return &conn->Node;
}
return 0;
}
+/**
+ * \brief Control a client socket
+ */
int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
{
tTCPConnection *conn = Node->ImplPtr;
-
+
switch(ID)
{
case 4: // Get/Set local port
return -1;
if(!CheckMem(Data, sizeof(Uint16)))
return -1;
-
+
if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024)
return -1;
-
+
conn->LocalPort = *(Uint16*)Data;
return 0;
-
+
case 5: // Get/Set remote port
if(!Data) return conn->RemotePort;
if(conn->State != TCP_ST_CLOSED) return -1;
if(!CheckMem(Data, sizeof(Uint16))) return -1;
conn->RemotePort = *(Uint16*)Data;
return 0;
-
+
case 6: // Set Remote IP
if( conn->State != TCP_ST_CLOSED )
return -1;
conn->RemoteIP.v6 = *(tIPv6*)Data;
}
return 0;
-
+
case 7: // Connect
if(conn->LocalPort == -1)
conn->LocalPort = TCP_GetUnusedPort();
if(conn->RemotePort == -1)
return 0;
-
+
TCP_StartConnection(conn);
return 1;
}
-
+
return 0;
}
int NextID; //!< Name of the next connection
tSpinlock lConnections; //!< Spinlock for connections
tTCPConnection *Connections; //!< Connections (linked list)
- volatile tTCPConnection *NewConnections;
+ tTCPConnection *volatile NewConnections;
};
struct sTCPConnection
* - UDP Handling
*/
#include "ipstack.h"
+#include <tpl_drv_common.h>
#include "udp.h"
+#define UDP_ALLOC_BASE 0xC000
+
// === PROTOTYPES ===
void UDP_Initialise();
void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
-// --- Channel
+// --- Listening Server
+tVFS_Node *UDP_Server_Init(tInterface *Interface);
+char *UDP_Server_ReadDir(tVFS_Node *Node, int ID);
+tVFS_Node UDP_Server_FindDir(tVFS_Node *Node, char *Name);
+ int UDP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
+void UDP_Server_Close(tVFS_Node *Node);
+// --- Client Channels
tVFS_Node *UDP_Channel_Init(tInterface *Interface);
Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data);
void UDP_Channel_Close(tVFS_Node *Node);
+// --- Helpers
+Uint16 UDP_int_AllocatePort();
+ int UDP_int_MarkPortAsUsed(Uint16 Port);
+void UDP_int_FreePort(Uint16 Port);
// === GLOBALS ===
+tSpinlock glUDP_Channels;
+tUDPChannel *gpUDP_Channels;
+tSpinlock glUDP_Ports;
+Uint32 gUDP_Ports[0x10000/32];
+//tSocketFile gUDP_ServerFile = {NULL, "udps", UDP_Server_Init};
+tSocketFile gUDP_ClientFile = {NULL, "udpc", UDP_Channel_Init};
// === CODE ===
/**
*/
void UDP_Initialise()
{
+ IPStack_AddFile(&gUDP_ClientFile);
IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
}
void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
{
tUDPHeader *hdr = Buffer;
+ tUDPChannel *chan;
+ tUDPPacket *pack;
+ int len;
Log("[UDP ] hdr->SourcePort = %i", ntohs(hdr->SourcePort));
Log("[UDP ] hdr->DestPort = %i", ntohs(hdr->DestPort));
Log("[UDP ] hdr->Length = %i", ntohs(hdr->Length));
Log("[UDP ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
+
+ // Check registered connections
+ LOCK(&glUDP_Channels);
+ for(chan = gpUDP_Channels;
+ chan;
+ chan = chan->Next)
+ {
+ if(chan->Interface != Interface) continue;
+ if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
+ if(chan->RemotePort != ntohs(hdr->SourcePort)) continue;
+
+ if(Interface->Type == 4) {
+ if(IP4_EQU(chan->RemoteAddr.v4, *(tIPv4*)Address)) continue;
+ }
+ else if(Interface->Type == 6) {
+ if(IP6_EQU(chan->RemoteAddr.v6, *(tIPv6*)Address)) continue;
+ }
+ else {
+ Warning("[UDP ] Address type %i unknown", Interface->Type);
+ RELEASE(&glUDP_Channels);
+ return ;
+ }
+
+ // Create the cached packet
+ len = ntohs(hdr->Length);
+ pack = malloc(sizeof(tUDPPacket) + len);
+ pack->Next = NULL;
+ pack->Length = len;
+ memcpy(pack->Data, hdr->Data, len);
+
+ // Add the packet to the channel's queue
+ LOCK(&chan->lQueue);
+ if(chan->Queue)
+ chan->QueueEnd->Next = pack;
+ else
+ chan->QueueEnd = chan->Queue = pack;
+ RELEASE(&chan->lQueue);
+ RELEASE(&glUDP_Channels);
+ return ;
+ }
+
+ // TODO: Server/Listener
+
+ RELEASE(&glUDP_Channels);
+}
+
+/**
+ * \brief Send a packet
+ * \param Channel Channel to send the packet from
+ * \param Data Packet data
+ * \param Length Length in bytes of packet data
+ */
+void UDP_SendPacket(tUDPChannel *Channel, void *Data, size_t Length)
+{
+ tUDPHeader *hdr;
+
+ switch(Channel->Interface->Type)
+ {
+ case 4:
+ // Create the packet
+ hdr = malloc(sizeof(tUDPHeader)+Length);
+ hdr->SourcePort = htons( Channel->LocalPort );
+ hdr->DestPort = htons( Channel->RemotePort );
+ hdr->Length = htons( Length );
+ hdr->Checksum = 0; // Checksum can be zero on IPv4
+ memcpy(hdr->Data, Data, Length);
+ // Pass on the the IPv4 Layer
+ IPv4_SendPacket(Channel->Interface, Channel->RemoteAddr.v4, IP4PROT_UDP, 0, sizeof(tUDPHeader)+Length, hdr);
+ // Free allocated packet
+ free(hdr);
+ break;
+ }
+}
+
+// --- Client Channels
+tVFS_Node *UDP_Channel_Init(tInterface *Interface)
+{
+ tUDPChannel *new;
+ new = calloc( sizeof(tUDPChannel), 1 );
+ new->Interface = Interface;
+ new->Node.ImplPtr = new;
+ new->Node.NumACLs = 1;
+ new->Node.ACLs = &gVFS_ACL_EveryoneRW;
+ new->Node.Read = UDP_Channel_Read;
+ new->Node.Write = UDP_Channel_Write;
+ new->Node.IOCtl = UDP_Channel_IOCtl;
+ new->Node.Close = UDP_Channel_Close;
+
+ LOCK(&glUDP_Channels);
+ new->Next = gpUDP_Channels;
+ gpUDP_Channels = new;
+ RELEASE(&glUDP_Channels);
+
+ return &new->Node;
+}
+
+/**
+ * \brief Read from the channel file (wait for a packet)
+ */
+Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+ tUDPChannel *chan = Node->ImplPtr;
+ tUDPPacket *pack;
+
+ if(chan->LocalPort == 0) return 0;
+ if(chan->RemotePort == 0) return 0;
+
+ while(chan->Queue == NULL) Threads_Yield();
+
+ for(;;)
+ {
+ LOCK(&chan->lQueue);
+ if(chan->Queue == NULL) {
+ RELEASE(&chan->lQueue);
+ continue;
+ }
+ pack = chan->Queue;
+ chan->Queue = pack->Next;
+ if(!chan->Queue) chan->QueueEnd = NULL;
+ RELEASE(&chan->lQueue);
+ break;
+ }
+
+ // Clip length to packet length
+ if(Length > pack->Length) Length = pack->Length;
+ // Copy packet data from cache
+ memcpy(Buffer, pack->Data, Length);
+ // Free cached packet
+ free(pack);
+
+ return Length;
+}
+
+/**
+ * \brief Write to the channel file (send a packet)
+ */
+Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+ tUDPChannel *chan = Node->ImplPtr;
+ if(chan->RemotePort == 0) return 0;
+
+ UDP_SendPacket(chan, Buffer, (size_t)Length);
+
+ return 0;
+}
+
+/**
+ * \brief Names for channel IOCtl Calls
+ */
+static const char *casIOCtls_Channel[] = {
+ DRV_IOCTLNAMES,
+ "getset_localport",
+ "getset_remoteport",
+ "set_remoteaddr",
+ NULL
+ };
+/**
+ * \brief Channel IOCtls
+ */
+int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ tUDPChannel *chan = Node->ImplPtr;
+ ENTER("pNode iID pData", Node, ID, Data);
+ switch(ID)
+ {
+ BASE_IOCTLS(DRV_TYPE_MISC, "UDP Channel", 0x100, casIOCtls_Channel);
+
+ case 4: // getset_localport (returns bool success)
+ if(!Data) LEAVE_RET('i', chan->LocalPort);
+ if(!CheckMem( Data, sizeof(Uint16) ) ) {
+ LOG("Invalid pointer %p", Data);
+ LEAVE_RET('i', -1);
+ }
+ // Set port
+ chan->LocalPort = *(Uint16*)Data;
+ // Permissions check (Ports lower than 1024 are root-only)
+ if(chan->LocalPort != 0 && chan->LocalPort < 1024) {
+ if( Threads_GetUID() != 0 ) {
+ LOG("Attempt by non-superuser to listen on port %i", chan->LocalPort);
+ chan->LocalPort = 0;
+ LEAVE_RET('i', -1);
+ }
+ }
+ // Allocate a random port if requested
+ if( chan->LocalPort == 0 )
+ chan->LocalPort = UDP_int_AllocatePort();
+ else
+ {
+ // Else, mark the requested port as used
+ if( UDP_int_MarkPortAsUsed(chan->LocalPort) == 0 ) {
+ LOG("Port %i us currently in use", chan->LocalPort);
+ chan->LocalPort = 0;
+ LEAVE_RET('i', 0);
+ }
+ LEAVE_RET('i', 1);
+ }
+ LEAVE_RET('i', 1);
+
+ case 5: // getset_remoteport (returns bool success)
+ if(!Data) LEAVE_RET('i', chan->RemotePort);
+ if(!CheckMem( Data, sizeof(Uint16) ) ) {
+ LOG("Invalid pointer %p", Data);
+ LEAVE_RET('i', -1);
+ }
+ chan->RemotePort = *(Uint16*)Data;
+ return 1;
+
+ case 6: // set_remoteaddr (returns bool success)
+ switch(chan->Interface->Type)
+ {
+ case 4:
+ if(!CheckMem(Data, sizeof(tIPv4))) {
+ LOG("Invalid pointer %p", Data);
+ LEAVE_RET('i', -1);
+ }
+ chan->RemoteAddr.v4 = *(tIPv4*)Data;
+ break;
+ }
+ break;
+ }
+ LEAVE_RET('i', 0);
+}
+
+/**
+ * \brief Close and destroy an open channel
+ */
+void UDP_Channel_Close(tVFS_Node *Node)
+{
+ tUDPChannel *chan = Node->ImplPtr;
+ tUDPChannel *prev;
+
+ // Remove from the main list first
+ LOCK(&glUDP_Channels);
+ if(gpUDP_Channels == chan)
+ gpUDP_Channels = gpUDP_Channels->Next;
+ else
+ {
+ for(prev = gpUDP_Channels;
+ prev->Next && prev->Next != chan;
+ prev = prev->Next);
+ if(!prev->Next)
+ Warning("[UDP ] Bookeeping Fail, channel %p is not in main list", chan);
+ else
+ prev->Next = prev->Next->Next;
+ }
+ RELEASE(&glUDP_Channels);
+
+ // Clear Queue
+ LOCK(&chan->lQueue);
+ while(chan->Queue)
+ {
+ tUDPPacket *tmp;
+ tmp = chan->Queue;
+ chan->Queue = tmp->Next;
+ free(tmp);
+ }
+ RELEASE(&chan->lQueue);
+
+ // Free channel structure
+ free(chan);
+}
+
+/**
+ * \return Port Number on success, or zero on failure
+ */
+Uint16 UDP_int_AllocatePort()
+{
+ int i;
+ LOCK(&glUDP_Ports);
+ // Fast Search
+ for( i = UDP_ALLOC_BASE; i < 0x10000; i += 32 )
+ if( gUDP_Ports[i/32] != 0xFFFFFFFF )
+ break;
+ if(i == 0x10000) return 0;
+ for( ;; i++ )
+ {
+ if( !(gUDP_Ports[i/32] & (1 << (i%32))) )
+ return i;
+ }
+ RELEASE(&glUDP_Ports);
+}
+
+/**
+ * \brief Allocate a specific port
+ * \return Boolean Success
+ */
+int UDP_int_MarkPortAsUsed(Uint16 Port)
+{
+ LOCK(&glUDP_Ports);
+ if( gUDP_Ports[Port/32] & (1 << (Port%32)) ) {
+ return 0;
+ RELEASE(&glUDP_Ports);
+ }
+ gUDP_Ports[Port/32] |= 1 << (Port%32);
+ RELEASE(&glUDP_Ports);
+ return 1;
+}
+
+/**
+ * \brief Free an allocated port
+ */
+void UDP_int_FreePort(Uint16 Port)
+{
+ LOCK(&glUDP_Ports);
+ gUDP_Ports[Port/32] &= ~(1 << (Port%32));
+ RELEASE(&glUDP_Ports);
}
#include "ipv4.h"
typedef struct sUDPHeader tUDPHeader;
+typedef struct sUDPPacket tUDPPacket;
+typedef struct sUDPChannel tUDPChannel;
struct sUDPHeader
{
Uint8 Data[];
};
+struct sUDPPacket
+{
+ struct sUDPPacket *Next;
+ size_t Length;
+ Uint8 Data[];
+};
+
+struct sUDPChannel
+{
+ struct sUDPChannel *Next;
+ tInterface *Interface;
+ Uint16 LocalPort;
+ union {
+ tIPv4 v4;
+ tIPv6 v6;
+ } RemoteAddr;
+ Uint16 RemotePort;
+ tVFS_Node Node;
+ tSpinlock lQueue;
+ tUDPPacket * volatile Queue;
+ tUDPPacket *QueueEnd;
+};
+
#endif
* Acess2 IDE Harddisk Driver
* - main.c
*/
-#define DEBUG 0
+#define DEBUG 1
#include <acess.h>
#include <modules.h>
#include <vfs.h>
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;
}
{
int ent;
tPAddr addr;
-
+
ENTER("");
-
+
// Get IDE Controller's PCI Entry
ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
LOG("ent = %i", ent);
// 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;
}
void ATA_SetupVFS()
{
int i, j, k;
-
+
// Count number of nodes needed
giATA_NumNodes = 0;
for( i = 0; i < MAX_ATA_DISKS; i++ )
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++ )
for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ )
gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node;
}
-
+
gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
}
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
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
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;
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;
}
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;
return NULL;
return &gATA_Disks[Name[0]-'A'].Node;
}
-
+
// Partitions
if(Name[1] < '0' || '9' < Name[1]) return NULL;
if(Name[2] == '\0') { // <= 9
// > 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;
-
+
}
/**
{
int disk = Node->Inode >> 8;
int part = Node->Inode & 0xFF;
-
+
// Raw Disk Access
if(part == 0xFF)
{
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);
}
{
int disk = Node->Inode >> 8;
int part = Node->Inode & 0xFF;
-
+
// Raw Disk Access
if(part == 0xFF)
{
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);
int ret;
Uint offset;
Uint done = 0;
-
+
// Pass straight on to ATA_ReadDMAPage if we can
if(Count <= MAX_DMA_SECTORS)
{
if(ret == 0) return 0;
return Count;
}
-
+
// Else we will have to break up the transfer
offset = 0;
while(Count > 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;
int ret;
Uint offset;
Uint done = 0;
-
+
// Pass straight on to ATA_WriteDMA if we can
if(Count <= MAX_DMA_SECTORS)
{
if(ret == 0) return 0;
return Count;
}
-
+
// Else we will have to break up the transfer
offset = 0;
while(Count > 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;
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)",
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+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
// 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 ) {
//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;
}
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+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+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;
}
void ATA_IRQHandlerPri(int unused)
{
Uint8 val;
-
+
// IRQ bit set for Primary Controller
val = ATA_int_BusMasterReadByte( 0x2 );
LOG("IRQ val = 0x%x", val);
Uint8 val;
// IRQ bit set for Secondary Controller
val = ATA_int_BusMasterReadByte( 0xA );
+ LOG("IRQ val = 0x%x", val);
if(val & 4) {
LOG("IRQ hit (val = 0x%x)", val);
ATA_int_BusMasterWriteByte( 0xA, 4 );
*/
void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
{
-
+
if( gATA_BusMasterBase & 1 )
outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
else
// Main Loop
for(;;)
{
- yield();
+ Messages_PollIPC();
+ //yield();
}
return 0;
}
void Messages_PollIPC()
{
int len;
- int tid = 0;
+ pid_t tid = 0;
char staticBuf[STATICBUF_SIZE];
tAxWin_Message *msg;
// Wait for a message
- while( (len = SysGetMessage(&tid, NULL)) )
- yield();
+ while( (len = SysGetMessage(&tid, NULL)) == 0 )
+ sleep();
// Allocate the space for it
if( len <= STATICBUF_SIZE )
while( readdir(dp, filename) )
{
if(filename[0] == '.') continue;
- if(filename[0] != 'i' || filename[1] != 'p') continue;
fd = open(path, OPENFLAG_READ);
if(fd == -1) {
tmp = AddInterface(Device);
if( tmp < 0 ) return tmp;
- sprintf(path, IPSTACK_ROOT"/ip%i", tmp);
+ sprintf(path, IPSTACK_ROOT"/%i", tmp);
fd = open(path, OPENFLAG_READ);
if( fd == -1 ) {
MAKEDEP = $(CC) -M
ASFLAGS = -felf
-CPPFLAGS = -I../../include/
+CPPFLAGS = -I$(ACESSDIR)/Usermode/include/
CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)
LDFLAGS = -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain -x -L.. -lacess
#include <stdint.h>
// === CONSTANTS ===
+#ifndef NULL
+# define NULL ((void*)0)
+#endif
+
#define OPENFLAG_EXEC 0x01
#define OPENFLAG_READ 0x02
#define OPENFLAG_WRITE 0x04
#define OPENFLAG_NOLINK 0x40
-#define OPENFLAG_CREATE 0x40
+#define OPENFLAG_CREATE 0x80
#ifndef SEEK_CUR
# define SEEK_SET 1
# define SEEK_CUR 0
#define FILEFLAG_SYMLINK 0x20
// === TYPES ===
+typedef uint pid_t;
+
struct s_sysACL {
union {
struct {
extern int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options);
// --- IPC ---
-extern int SysSendMessage(int dest, int length, void *Data);
-extern int SysGetMessage(int *src, void *Data);
+extern int SysSendMessage(pid_t dest, uint length, void *Data);
+extern int SysGetMessage(pid_t *src, void *Data);
// --- MEMORY ---
uint64_t _SysGetPhys(uint vaddr);
#ifndef _AXWIN_MESSAGES_H
#define _AXWIN_MESSAGES_H
+#include <stdint.h>
+
typedef struct sAxWin_Message tAxWin_Message;
/**
// Server Requests
MSG_SREQ_PING,
// - Windows
- MSG_SREQ_NEWWINDOW,
+ MSG_SREQ_NEWWINDOW, // (short x, y, w, h, uint32_t flags)
MSG_SREQ_GETFLAGS, MSG_SREQ_SETFLAGS,
MSG_SREQ_GETRECT, MSG_SREQ_SETRECT,
// - Drawing
// Server Responses
MSG_SRSP_PONG,
+ MSG_SRSP_WINDOW, // Returns the new window ID
MSG_SRSP_IMG, // Returns the image ID
NUM_MSG
};
+// --- Server Requests (Requests from the client of the server)
/**
- * \brief New Window Request structure
+ * \brief Server Request - Ping (Get Server Version)
*/
-struct sAxWin_Req_NewWindow
+struct sAxWin_SReq_Ping
{
-
};
+/**
+ * \brief Server Request - New Window
+ * \see eAxWin_Messages.MSG_SREQ_NEWWINDOW
+ */
+struct sAxWin_SReq_NewWindow
+{
+ uint16_t X, Y, W, H;
+ uint32_t Flags;
+};
+
+
+// --- Server Responses
+/**
+ * \brief Server Response - Pong
+ * \see eAxWin_Messages.MSG_SRSP_PONG
+ */
+struct sAxWin_SRsp_Pong
+{
+ uint8_t Major;
+ uint8_t Minor;
+ uint16_t Build;
+};
+
+/**
+ * \brief Server Response - New Window
+ * \see eAxWin_Messages.MSG_SRSP_NEWWINDOW
+ */
+struct sAxWin_SRsp_NewWindow
+{
+ uint32_t Handle;
+};
+
+
+// === Core Message Structure
/**
* \brief Overarching Message Structure
* \note sizeof(tAxWin_Message) is never valid
{
uint16_t ID;
uint16_t Size; //!< Size in DWORDS
+ union
+ {
+ struct sAxWin_SReq_Ping SReq_Pong;
+ struct sAxWin_SReq_NewWindow SReq_NewWindow;
+
+ // Server Responses
+ struct sAxWin_SRsp_Pong SRsp_Pong;
+ struct sAxWin_SRsp_NewWindow SRsp_Window;
+ };
};
#endif