--- /dev/null
+/**\r
+ * \file tpl_drv_terminal.h\r
+ * \brief Terminal Driver Interface Definitions\r
+*/\r
+#ifndef _TPL_TERMINAL_H\r
+#define _TPL_TERMINAL_H\r
+\r
+#include <tpl_drv_common.h>\r
+\r
+/**\r
+ * \enum eTplTerminal_IOCtl\r
+ * \brief Common Terminal IOCtl Calls\r
+ * \extends eTplDrv_IOCtl\r
+ */\r
+enum eTplTerminal_IOCtl {\r
+ /**\r
+ * ioctl(..., int *mode)\r
+ * \brief Get/Set the current video mode type\r
+ * see ::eTplTerminal_Modes\r
+ * \note If the mode is set the mode is changed at this call\r
+ */\r
+ TERM_IOCTL_MODETYPE = 4,\r
+ \r
+ /**\r
+ * ioctl(..., int *width)\r
+ * \brief Get/set the display width\r
+ * \param width Pointer to an integer containing the new width\r
+ * \return Current width\r
+ * \r
+ * Set `width` to NULL to just return the current width\r
+ */\r
+ TERM_IOCTL_WIDTH,\r
+ \r
+ /**\r
+ * ioctl(..., int *height)\r
+ * \brief Get/set the display height\r
+ * \param height Pointer to an integer containing the new height\r
+ * \return Current height\r
+ * \r
+ * Set \a height to NULL to just return the current height\r
+ */\r
+ TERM_IOCTL_HEIGHT,\r
+ \r
+ /**\r
+ * ioctl(..., tTerm_IOCtl_Mode *info)\r
+ * \brief Queries the current driver about it's modes\r
+ * \param info A pointer to a ::tTerm_IOCtl_Mode with .ID set to the mode index\r
+ * \return Number of modes\r
+ * \r
+ * \a info can be NULL\r
+ */\r
+ TERM_IOCTL_QUERYMODE\r
+};\r
+\r
+typedef struct sTerm_IOCtl_Mode tTerm_IOCtl_Mode;\r
+\r
+/**\r
+ * \brief Virtual Terminal Mode\r
+ * Describes a VTerm mode to the caller of ::TERM_IOCTL_QUERYMODE\r
+ */\r
+struct sTerm_IOCtl_Mode\r
+{\r
+ short ID; //!< Zero Based index of mode\r
+ short DriverID; //!< Driver's ID number (from ::tVideo_IOCtl_Mode)\r
+ Uint16 Height; //!< Height\r
+ Uint16 Width; //!< Width\r
+ Uint8 Depth; //!< Bits per cell\r
+ struct {\r
+ unsigned bText: 1; //!< Text Mode marker\r
+ unsigned unused: 7;\r
+ };\r
+};\r
+\r
+/**\r
+ * \brief Terminal Modes\r
+ */\r
+enum eTplTerminal_Modes {\r
+ /**\r
+ * \brief UTF-8 Text Mode\r
+ * Any writes to the terminal file are treated as UTF-8 encoded\r
+ * strings and reads will also return UTF-8 strings.\r
+ */\r
+ TERM_MODE_TEXT,\r
+ \r
+ /**\r
+ * \brief 32bpp Framebuffer\r
+ * Writes to the terminal file will write to the framebuffer.\r
+ * Reads will return UTF-32 characters\r
+ */\r
+ TERM_MODE_FB,\r
+ \r
+ /**\r
+ * \brief OpenGL 2D/3D\r
+ * Writes to the terminal file will send 3D commands\r
+ * Reads will return UTF-32 characters\r
+ * \note May or may not stay in the spec\r
+ */\r
+ TERM_MODE_OPENGL,\r
+ \r
+ NUM_TERM_MODES\r
+};\r
+\r
+\r
+#endif\r
--- /dev/null
+#
+#
+
+OBJ = main.o link.o arp.o ipv4.o ipv6.o
+NAME = IPStack
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Address Resolution Protocol
+ */
+#include "ipstack.h"
+#include "arp.h"
+#include "link.h"
+
+#define ARP_CACHE_SIZE 64
+
+// === IMPORTS ===
+extern tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
+extern tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
+
+// === PROTOTYPES ===
+ int ARP_Initialise();
+ int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address);
+void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
+
+// === GLOBALS ===
+struct sARP_Cache {
+ tMacAddr MAC;
+ tIPv4 IP4;
+ tIPv6 IP6;
+ Sint64 LastUpdate;
+} *gaARP_Cache;
+ int giARP_CacheSpace;
+
+// === CODE ===
+/**
+ * \fn int ARP_Initialise()
+ * \brief Initalise the ARP section
+ */
+int ARP_Initialise()
+{
+ gaARP_Cache = malloc( ARP_CACHE_SIZE * sizeof(*gaARP_Cache) );
+ memset( gaARP_Cache, 0, ARP_CACHE_SIZE * sizeof(*gaARP_Cache) );
+ giARP_CacheSpace = ARP_CACHE_SIZE;
+
+ Link_RegisterType(0x0806, ARP_int_GetPacket);
+ return 1;
+}
+
+/**
+ * \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;
+
+ req.HWType = htons(0x100); // Ethernet
+ req.Type = htons(0x0800);
+ req.HWSize = 6;
+ req.SWSize = 4;
+ req.Request = htons(1);
+ req.SourceMac = Interface->Adapter->MacAddr;
+ req.SourceIP = Interface->IP4.Address;
+ req.DestMac = cMAC_BROADCAST;
+ req.DestIP = Address;
+
+ Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, sizeof(struct sArpRequest4), &req);
+
+ return 0;
+}
+
+/**
+ * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
+ * \brief Called when an ARP packet is recieved
+ */
+void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
+{
+ int i, free = -1;
+ int oldest = 0;
+ tArpRequest4 *req4 = Buffer;
+ tArpRequest6 *req6 = Buffer;
+ tInterface *iface;
+
+ // Sanity Check Packet
+ if( Length < sizeof(tArpRequest4) ) {
+ Log("[ARP ] Recieved undersized packet");
+ return ;
+ }
+ if( ntohs(req4->Type) != 0x0800 ) {
+ Log("[ARP ] Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
+ return ;
+ }
+ if( req4->HWSize != 6 ) {
+ Log("[ARP ] Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
+ return;
+ }
+ if( !MAC_EQU(req4->SourceMac, From) ) {
+ Log("[ARP ] ARP spoofing detected", req4->HWSize);
+ return;
+ }
+
+ switch( req4->Request )
+ {
+ case 1: // You want my IP?
+ // Check what type of IP it is
+ switch( req4->SWSize )
+ {
+ case 4:
+ iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
+ if( iface )
+ {
+ IP4_SET(req4->DestIP, req4->SourceIP);
+ req4->DestMac = req4->SourceMac;
+ req4->SourceIP = iface->IP4.Address;
+ req4->SourceMac = Adapter->MacAddr;
+ req4->Request = htons(2);
+ Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
+ }
+ break;
+ case 6:
+ if( Length < sizeof(tArpRequest6) ) {
+ Log("[ARP ] Recieved undersized packet (IPv6)");
+ return ;
+ }
+ iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
+ if( iface )
+ {
+ req6->DestIP = req6->SourceIP;
+ req6->DestMac = req6->SourceMac;
+ req6->SourceIP = iface->IP6.Address;
+ req6->SourceMac = Adapter->MacAddr;
+ req6->Request = htons(2);
+ Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
+ }
+ break;
+ default:
+ Log("[ARP ] Unknown Protocol Address size (%i)", req4->SWSize);
+ return ;
+ }
+
+ break;
+
+ case 2: // Ooh! A response!
+ // Find an entry for the MAC address in the cache
+ for( i = giARP_CacheSpace; i--; )
+ {
+ if(gaARP_Cache[oldest].LastUpdate > gaARP_Cache[i].LastUpdate) {
+ oldest = i;
+ }
+ if( MAC_EQU(gaARP_Cache[i].MAC, From) ) break;
+ if( gaARP_Cache[i].LastUpdate == 0 && free==-1 ) free = i;
+ }
+ if(i + 1 == 0) {
+ if(free != -1)
+ i = free;
+ else
+ i = oldest;
+ }
+
+ // Check what type of IP it is
+ switch( req4->SWSize )
+ {
+ case 4:
+ gaARP_Cache[i].IP4 = req4->SourceIP;
+ break;
+ case 6:
+ if( Length < sizeof(tArpRequest6) ) {
+ Log("[ARP ] Recieved undersized packet (IPv6)");
+ return ;
+ }
+ gaARP_Cache[i].IP6 = req6->SourceIP;
+ break;
+ default:
+ Log("[ARP ] Unknown Protocol Address size (%i)", req4->SWSize);
+ return ;
+ }
+
+ gaARP_Cache[i].LastUpdate = now();
+ break;
+ }
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Common Header
+ */
+#ifndef _ARP_H_
+#define _ARP_H_
+
+#include "ipstack.h"
+
+typedef struct sArpRequest4 tArpRequest4;
+typedef struct sArpRequest6 tArpRequest6;
+
+struct sArpRequest4 {
+ Uint16 HWType;
+ Uint16 Type;
+ Uint8 HWSize, SWSize;
+ Uint16 Request;
+ tMacAddr SourceMac;
+ tIPv4 SourceIP;
+ tMacAddr DestMac;
+ tIPv4 DestIP;
+};
+
+struct sArpRequest6 {
+ Uint16 HWType;
+ Uint16 Type;
+ Uint8 HWSize, SWSize;
+ Uint16 Request;
+ tMacAddr SourceMac;
+ tIPv6 SourceIP;
+ tMacAddr DestMac;
+ tIPv6 DestIP;
+};
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - ICMP Handling
+ */
+#include "ipstack.h"
+#include "icmp.h"
+
+// === PROTOTYPES ===
+void ICMP_Initialise();
+void ICMP_GetPacket(tInterface *Interface, int Length, void *Buffer);
+
+// === GLOBALS ===
+
+// === CODE ===
+/**
+ * \fn void ICMP_Initialise()
+ * \brief Initialise the ICMP Layer
+ */
+void ICMP_Initialise()
+{
+
+}
+
+/**
+ * \fn void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+ * \brief Handles a packet from the IP Layer
+ */
+void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+{
+ tICMPHeader *hdr = Buffer;
+
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - ICMP Handling
+ */
+#ifndef _ICMP_H_
+#define _ICMP_H_
+
+// === TYPEDEFS ===
+typedef struct sICMPHeader tICMPHeader;
+
+// === STRUCTURES ===
+struct sICMPHeader
+{
+ Uint8 Type;
+ Uint8 Code;
+ Uint16 Checksum;
+ Uint16 ID;
+ Uint16 Sequence;
+};
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Common Header
+ */
+#ifndef _IPSTACK_H_
+#define _IPSTACK_H_
+
+#include <common.h>
+#include <vfs.h>
+
+typedef union uIPv4 tIPv4;
+typedef union uIPv6 tIPv6;
+typedef struct sMacAddr tMacAddr;
+typedef struct sAdapter tAdapter;
+typedef struct sInterface tInterface;
+
+typedef void (*tIPCallback)(tInterface *Interface, void *Address, int Length, void *Buffer);
+
+union uIPv4 {
+ Uint32 L;
+ Uint8 B[4];
+};
+
+union uIPv6 {
+ Uint32 L[4];
+ Uint8 B[16];
+};
+
+struct sMacAddr {
+ Uint8 B[6];
+};
+
+struct sInterface {
+ struct sInterface *Next;
+ tVFS_Node Node;
+ tAdapter *Adapter;
+ int Type; // 4 for IPv4 and 6 for IPv6
+ union {
+ struct {
+ tIPv6 Address;
+ int SubnetBits;
+ } IP6;
+
+ struct {
+ tIPv4 Address;
+ tIPv4 Gateway;
+ int SubnetBits;
+ } IP4;
+ };
+};
+
+/**
+ * \brief Represents a network adapter
+ */
+struct sAdapter {
+ struct sAdapter *Next;
+ char *Device;
+ int DeviceFD;
+
+ tMacAddr MacAddr;
+
+ tInterface *Interfaces;
+};
+
+static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
+
+#define MAC_SET(t,v) memcpy(&(t),&(v),sizeof(tMacAddr))
+#define IP4_SET(t,v) (t).L = (v).L;
+#define IP6_SET(t,v) memcpy(&(t),&(v),sizeof(tIPv6))
+
+#define MAC_EQU(a,b) memcmp(&(a),&(b),sizeof(tMacAddr))
+#define IP4_EQU(a,b) ((a).L==(b).L)
+#define IP6_EQU(a,b) memcmp(&(a),&(b),sizeof(tIPv6))
+
+// === FUNCTIONS ===
+#define htonb(v) (v)
+#define htons(in) BigEndian16(in)
+#define htonl(in) BigEndian32(in)
+#define ntonb(v) (v)
+#define ntohs(in) BigEndian16(in)
+#define ntohl(in) BigEndian16(in)
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - IPv4 Protcol Handling
+ */
+#include "ipstack.h"
+#include "link.h"
+#include "ipv4.h"
+
+// === PROTOTYPES ===
+ int IPv4_Initialise();
+void IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
+tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
+Uint32 IPv4_Netmask(int FixedBits);
+
+// === GLOBALS ===
+tIPCallback gaIPv4_Callbacks[256];
+
+// === CODE ===
+/**
+ * \fn int IPv4_Initialise()
+ */
+int IPv4_Initialise()
+{
+ Link_RegisterType(IPV4_ETHERNET_ID, IPv4_int_GetPacket);
+ return 1;
+}
+
+/**
+ * \fn void IPv4_int_GetPacket(tInterface *Adapter, tMacAddr From, int Length, void *Buffer)
+ * \brief Process an IPv4 Packet
+ */
+void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
+{
+ tIPv4Header *hdr = Buffer;
+ tInterface *iface;
+ char *data;
+ int dataLength;
+ if(Length < sizeof(tIPv4Header)) return;
+
+ // Check that the version IS IPv4
+ if(hdr->Version != 4) return;
+
+ // Check Header checksum
+ //TODO
+
+ // Check Packet length
+ if(hdr->TotalLength > Length) return;
+
+ // Get Interface (allowing broadcasts)
+ iface = IPv4_GetInterface(Adapter, hdr->Source, 1);
+ if(!iface) return; // Not for us? Well, let's ignore it
+
+ // Defragment
+ //TODO
+
+ dataLength = hdr->TotalLength - sizeof(tIPv4Header);
+ data = &hdr->Options[0];
+
+ // Send it on
+ gaIPv4_Callbacks[hdr->Protocol] (iface, &hdr->Source, dataLength, data);
+}
+
+/**
+ * \fn tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address)
+ * \brief Searches an adapter for a matching address
+ */
+tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
+{
+ tInterface *iface = NULL;
+ Uint32 netmask;
+
+ for( iface = Adapter->Interfaces; iface; iface = iface->Next)
+ {
+ if( iface->Type != 4 ) continue;
+ if( IP4_EQU(Address, iface->IP4.Address) )
+ return iface;
+
+ if( !Broadcast ) continue;
+
+ // Check for broadcast
+ netmask = IPv4_Netmask(iface->IP4.SubnetBits);
+ if( (Address.L & netmask) == (iface->IP4.Address.L & netmask)
+ && (Address.L & ~netmask) == (0xFFFFFFFF & ~netmask) )
+ return iface;
+ }
+ return NULL;
+}
+
+/**
+ * \brief Convert a network prefix to a netmask
+ *
+ * For example /24 will become 255.255.255.0
+ */
+Uint32 IPv4_Netmask(int FixedBits)
+{
+ Uint32 ret = 0xFFFFFFFF;
+ ret >>= (32-FixedBits);
+ ret <<= (32-FixedBits);
+ return ret;
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - IPv4 Definitions
+ */
+#ifndef _IPV4_H_
+#define _IPV4_H_
+
+#include "ipstack.h"
+
+typedef struct sIPv4Header tIPv4Header;
+
+struct sIPv4Header
+{
+ struct {
+ unsigned Version: 4; // = 4
+ unsigned HeaderLength: 4; // in 4-byte chunks
+ };
+ Uint8 DiffServices; // Differentiated Services
+ Uint16 TotalLength;
+ Uint16 Identifcation;
+
+ struct {
+ unsigned Reserved: 1;
+ unsigned DontFragment: 1;
+ unsigned MoreFragments: 1;
+ unsigned FragOffLow: 5;
+ };
+ Uint8 FragOffHi; // Number of 8-byte blocks from the original start
+
+ Uint8 TTL; // Max number of hops effectively
+ Uint8 Protocol;
+ Uint16 HeaderChecksum; // One's Complement Sum of the entire header must equal zero
+
+ tIPv4 Source;
+ tIPv4 Destination;
+
+ Uint8 Options[];
+};
+
+#define IP4PROT_ICMP 1
+#define IP4PROT_TCP 6
+#define IP4PROT_UDP 17
+
+#define IPV4_ETHERNET_ID 0x0800
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - IPv6 Protcol Handling
+ */
+#include "ipstack.h"
+#include "link.h"
+#include "ipv6.h"
+
+// === IMPORTS ===
+extern Uint32 IPv4_Netmask(int FixedBits);
+
+// === PROTOTYPES ===
+ int IPv6_Initialise();
+void IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
+tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
+
+// === CODE ===
+/**
+ * \fn int IPv6_Initialise()
+ */
+int IPv6_Initialise()
+{
+ Link_RegisterType(IPV6_ETHERNET_ID, IPv6_int_GetPacket);
+ return 1;
+}
+
+/**
+ * \fn void IPv6_int_GetPacket(tInterface *Interface, tMacAddr From, int Length, void *Buffer)
+ * \brief Process an IPv6 Packet
+ */
+void IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer)
+{
+ tIPv6Header *hdr = Buffer;
+ if(Length < sizeof(tIPv6Header)) return;
+
+ if(hdr->Version != 6) return;
+}
+
+/**
+ * \fn tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address)
+ * \brief Searches an adapter for a matching address
+ */
+tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast)
+{
+ int i, j;
+ tInterface *iface = NULL;
+ Uint32 netmask;
+
+ for( iface = Adapter->Interfaces; iface; iface = iface->Next)
+ {
+ // Skip non-IPv6 Interfaces
+ if( iface->Type != 6 ) continue;
+
+ // If the address is a perfect match, return this interface
+ if( IP6_EQU(Address, iface->IP6.Address) ) return iface;
+
+ // Check if we want to match broadcast addresses
+ if( !Broadcast ) continue;
+
+ // Check for broadcast
+ if( iface->IP6.SubnetBits > 32 && Address.L[0] != iface->IP6.Address.L[0] )
+ continue;
+ if( iface->IP6.SubnetBits > 64 && Address.L[1] != iface->IP6.Address.L[1] )
+ continue;
+ if( iface->IP6.SubnetBits > 96 && Address.L[2] != iface->IP6.Address.L[2] )
+ continue;
+
+ j = iface->IP6.SubnetBits / 32;
+ i = iface->IP6.SubnetBits % 32;
+ netmask = IPv4_Netmask( iface->IP6.SubnetBits % 32 );
+
+ // Check the last bit of the netmask
+ if( (Address.L[j] >> i) != (iface->IP6.Address.L[j] >> i) ) continue;
+
+ // Check that the host portion is one
+ if( (Address.L[j] & ~netmask) != (0xFFFFFFFF & ~netmask) ) continue;
+ if( j >= 2 && Address.L[3] != 0xFFFFFFFF) continue;
+ if( j >= 1 && Address.L[2] != 0xFFFFFFFF) continue;
+ if( j >= 0 && Address.L[1] != 0xFFFFFFFF) continue;
+
+ return iface;
+ }
+ return NULL;
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - IPv6 Definitions
+ */
+#ifndef _IPV6_H_
+#define _IPV6_H_
+
+#include "ipstack.h"
+
+typedef struct sIPv6Header tIPv6Header;
+
+struct sIPv6Header
+{
+ struct {
+ unsigned Version: 4;
+ unsigned TrafficClass: 8;
+ unsigned FlowLabel: 20;
+ };
+ Uint16 PayloadLength;
+ Uint8 NextHeader; // Type of payload data
+ Uint8 HopLimit;
+ tIPv6 Source;
+ tIPv6 Destination;
+};
+
+#define IPV6_ETHERNET_ID 0x86DD
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Link/Media Layer Interface
+ */
+#include "ipstack.h"
+#include "link.h"
+
+// === CONSTANTS ===
+#define MAX_PACKET_SIZE 2048
+
+// === GLOBALS ===
+ int giRegisteredTypes = 0;
+struct {
+ Uint16 Type;
+ tPacketCallback Callback;
+} *gaRegisteredTypes;
+
+// === CODE ===
+/**
+ * \fn void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
+ * \brief Registers a callback for a specific packet type
+ */
+void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
+{
+ int i;
+ void *tmp;
+ for( i = giRegisteredTypes; i -- ; )
+ {
+ if(gaRegisteredTypes[i].Type == Type) {
+ Warning("[NET ] Attempt to register 0x%x twice", Type);
+ return ;
+ }
+ // Ooh! Free slot!
+ if(gaRegisteredTypes[i].Callback == NULL) break;
+ }
+
+ if(i + 1 == 0)
+ {
+ tmp = realloc(gaRegisteredTypes, (giRegisteredTypes+1)*sizeof(*gaRegisteredTypes));
+ if(!tmp) Panic("[NET ] Out of heap space!");
+ i = giRegisteredTypes;
+ giRegisteredTypes ++;
+ gaRegisteredTypes = tmp;
+ }
+
+ gaRegisteredTypes[i].Callback = Callback;
+ gaRegisteredTypes[i].Type = Type;
+}
+
+/**
+ * \fn void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
+ * \brief Formats and sends a packet on the specified interface
+ */
+void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
+{
+ int bufSize = sizeof(tEthernetHeader) + Length;
+ Uint8 buf[bufSize];
+ tEthernetHeader *hdr = (void*)buf;
+
+ hdr->Dest = To;
+ hdr->Src = Adapter->MacAddr;
+ hdr->Type = htons(Type);
+
+ memcpy(hdr->Data, Buffer, Length);
+
+ VFS_Write(Adapter->DeviceFD, bufSize, buf);
+}
+
+/**
+ * \fn void Link_WatchDevice(tAdapter *Adapter)
+ * \brief Spawns a worker thread to watch the specified adapter
+ */
+void Link_WatchDevice(tAdapter *Adapter)
+{
+ int tid = Proc_SpawnWorker(); // Create a new worker thread
+
+ if(tid < 0) {
+ Panic("[NET ] Unable to create watcher thread for '%s'", Adapter->Device);
+ }
+
+ if(tid > 0) {
+ Log("[NET ] Watching '%s' using tid %i", Adapter->Device, tid);
+ return ;
+ }
+
+ // Child Thread
+ while(Adapter->DeviceFD != -1)
+ {
+ Uint8 buf[MAX_PACKET_SIZE];
+ tEthernetHeader *hdr = (void*)buf;
+ int ret, i;
+
+ // Wait for a packet
+ ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf);
+ if(ret == -1) break;
+
+ if(ret <= sizeof(tEthernetHeader)) {
+ Log("[NET ] Recieved an undersized packet");
+ continue;
+ }
+
+ // Check if there is a registered callback for this packet type
+ for( i = giRegisteredTypes; i--; )
+ {
+ if(gaRegisteredTypes[i].Type == hdr->Type) continue;
+ }
+ // No? Ignore it
+ if( i + 1 == 0 ) continue;
+
+ // Call the callback
+ gaRegisteredTypes[i].Callback(
+ Adapter,
+ hdr->Src,
+ ret - sizeof(tEthernetHeader),
+ hdr->Data
+ );
+ }
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Link/Media Layer Header
+ */
+#ifndef _LINK_H_
+#define _LINK_H_
+
+// === EXTERNAL ===
+typedef void (*tPacketCallback)(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
+
+extern void Link_RegisterType(Uint16 Type, tPacketCallback Callback);
+extern void Link_SendPacket(tAdapter *Interface, Uint16 Type, tMacAddr To, int Length, void *Buffer);
+
+// === INTERNAL ===
+typedef struct sEthernetHeader tEthernetHeader;
+typedef struct sEthernetFooter tEthernetFooter;
+struct sEthernetHeader {
+ tMacAddr Dest;
+ tMacAddr Src;
+ Uint16 Type;
+ Uint8 Data[];
+};
+
+struct sEthernetFooter {
+ //Uint32 CRC;
+};
+
+#endif
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - Address Resolution Protocol
+ */
+#include "ipstack.h"
+#include <modules.h>
+#include <fs_devfs.h>
+
+// === IMPORTS ===
+ int ARP_Initialise();
+
+// === PROTOTYPES ===
+ int IPStack_Install(char **Arguments);
+char *IPStack_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x000A, IPStack, IPStack_Install, NULL);
+tDevFS_Driver gIP_DriverInfo = {
+ NULL, "ip",
+ {
+ .NumACLs = 1,
+ .ACLs = &gVFS_ACL_EveryoneRX,
+ .Flags = VFS_FFLAG_DIRECTORY,
+ .ReadDir = IPStack_ReadDir,
+ .FindDir = IPStack_FindDir
+ }
+};
+ int giIP_NumInterfaces;
+tInterface *gIP_Interfaces = NULL;
+
+// === CODE ===
+/**
+ * \fn int IPStack_Install(char **Arguments)
+ * \brief Intialise the relevant parts of the stack and register with DevFS
+ */
+int IPStack_Install(char **Arguments)
+{
+ int i = 0;
+
+ // Install Handlers
+ ARP_Initialise();
+
+ // Parse module arguments
+ for( i = 0; Arguments[i]; i++ )
+ {
+ //if(strcmp(Arguments[i], "Device") == '=') {
+ //
+ //}
+ }
+
+ return 1;
+}
+
+/**
+ * \brief Read from the IP Stack's Device Directory
+ */
+char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
+{
+ tInterface *iface;
+ char name[5] = "ip0\0\0";
+
+ // Create the name
+ if(Pos < 10)
+ name[2] = '0' + Pos;
+ else {
+ name[2] = '0' + Pos/10;
+ name[3] = '0' + Pos%10;
+ }
+
+ // Traverse the list
+ for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
+
+ // Did we run off the end?
+ if(!iface) return NULL;
+
+ // Return the pre-generated name
+ return strdup(name);
+}
+
+/**
+ * \brief Get the node of an interface
+ */
+tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
+{
+ return NULL;
+}
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - TCP Handling
+ */
+#include "ipstack.h"
+#include "tcp.h"
+
+#define TCP_MIN_DYNPORT 0x1000
+
+// === PROTOTYPES ===
+void TCP_Initialise();
+void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port);
+void TCP_GetPacket(tInterface *Interface, int Length, void *Buffer);
+Uint16 TCP_GetUnusedPort();
+ int TCP_AllocatePort(Uint16 Port);
+ int TCP_DeallocatePort(Uint16 Port);
+
+// === GLOBALS ===
+ int giTCP_NumHalfopen = 0;
+tTCPListener *gTCP_Listeners;
+tTCPConnection *gTCP_OutbountCons;
+Uint32 gaTCP_PortBitmap[0x800];
+ int giTCP_NextOutPort = TCP_MIN_DYNPORT;
+
+// === CODE ===
+/**
+ * \fn void TCP_Initialise()
+ * \brief Initialise the TCP Layer
+ */
+void TCP_Initialise()
+{
+
+}
+
+/**
+ * \fn void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port)
+ * \brief Open a connection to another host using TCP
+ */
+void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port)
+{
+ tTCPConnection *ret = malloc( sizeof(tTCPConnection) );
+
+ ret->State = TCP_ST_CLOSED;
+ if(LocalPort == 0)
+ ret->LocalPort = TCP_GetUnusedPort();
+ else
+ ret->LocalPort = LocalPort;
+ ret->RemotePort = Port;
+
+ ret->LocalInterface = Interface;
+
+ if(Interface->Type == 6)
+ ret->RemoteIP.v6 = *(tIPv6*)Address;
+ else
+ ret->RemoteIP.v4 = *(tIPv4*)Address;
+
+ // SEND PACKET
+
+ return ret;
+}
+
+/**
+ * \fn void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+ * \brief Handles a packet from the IP Layer
+ */
+void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+{
+ tTCPHeader *hdr = Buffer;
+ tTCPListener *srv;
+ tTCPConnection *conn;
+
+ // Check Servers
+ {
+ for( srv = gTCP_Listeners; srv; srv = srv->Next )
+ {
+ // Check the interface
+ 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!
+ //TODO
+
+ return;
+ }
+
+ // Open a new connection
+ //TODO
+
+ break;
+ }
+ }
+
+
+ // Check Open Connections
+ {
+ for( conn = gTCP_OutbountCons; conn; conn = conn->Next )
+ {
+ // TODO
+ }
+ }
+}
+
+/**
+ * \fn Uint16 TCP_GetUnusedPort()
+ * \brief Gets an unused port and allocates it
+ */
+Uint16 TCP_GetUnusedPort()
+{
+ Uint16 ret;
+
+ // Get Next outbound port
+ ret = giTCP_NextOutPort++;
+ while( gaTCP_PortBitmap[ret/32] & (1 << (ret%32)) )
+ {
+ ret ++;
+ giTCP_NextOutPort++;
+ if(giTCP_NextOutPort == 0x10000) {
+ ret = giTCP_NextOutPort = TCP_MIN_DYNPORT;
+ }
+ }
+
+ // Mark the new port as used
+ gaTCP_PortBitmap[ret/32] |= 1 << (ret%32);
+
+ return ret;
+}
+
+/**
+ * \fn int TCP_AllocatePort(Uint16 Port)
+ * \brief Marks a port as used
+ */
+int TCP_AllocatePort(Uint16 Port)
+{
+ // 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;
+}
+
+/**
+ * \fn int TCP_DeallocatePort(Uint16 Port)
+ * \brief Marks a port as unused
+ */
+int TCP_DeallocatePort(Uint16 Port)
+{
+ // 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;
+}
+
--- /dev/null
+/*
+ * Acess2 IP Stack
+ * - TCP Definitions
+ */
+#ifndef _TCP_H_
+#define _TCP_H_
+
+#include "ipstack.h"
+
+typedef struct sTCPHeader tTCPHeader;
+typedef struct sTCPListener tTCPListener;
+typedef struct sTCPConnection tTCPConnection;
+
+struct sTCPHeader
+{
+ Uint16 SourcePort;
+ Uint16 DestPort;
+ Uint32 SequenceNumber;
+ Uint32 AcknowlegementNumber;
+ struct {
+ unsigned DataOffset: 4; // Size of the header in 32-bit words
+ unsigned Reserved: 4;
+ };
+ struct {
+ unsigned CWR: 1; // Congestion Window Reduced
+ unsigned ECE: 1; // ECN-Echo
+ unsigned URG: 1; // Urgent pointer is significant
+ unsigned ACK: 1; // Acknowlegement field is significant
+ unsigned PSH: 1; // Push Function
+ unsigned RST: 1; // Reset Connection
+ unsigned SYN: 1; // Synchronise Sequence Numbers
+ unsigned FIN: 1; // Last packet
+ } Flags;
+ Uint16 WindowSize;
+
+ Uint16 Checksum;
+ Uint16 UrgentPointer;
+
+ Uint8 Options[];
+};
+
+struct sTCPListener
+{
+ struct sTCPListener *Next;
+ Uint16 Port;
+ tInterface *Interface;
+ tTCPConnection *Connections;
+};
+
+struct sTCPConnection
+{
+ struct sTCPConnection *Next;
+ int State;
+ Uint16 LocalPort;
+ Uint16 RemotePort;
+
+ tInterface *LocalInterface;
+ union {
+ tIPv4 v4;
+ tIPv6 v6;
+ } RemoteIP; // Type is determined by LocalInterface->Type
+};
+
+enum eTCPConnectionState
+{
+ TCP_ST_CLOSED,
+ TCP_ST_HALFOPEN,
+ TCP_ST_OPEN
+};
+
+#endif
--- /dev/null
+#
+#
+
+OBJ = main.o uhci.o
+NAME = USB
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess2
+ * USB Stack
+ */
+#define VERSION ( (0<<8)| 5 )
+#define DEBUG 1
+#include <common.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <modules.h>
+#include "usb.h"
+
+// === IMPORTS ===
+ int UHCI_Initialise();
+
+// === PROTOTYPES ===
+ int USB_Install(char **Arguments);
+void USB_Cleanup();
+char *USB_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name);
+ int USB_IOCtl(tVFS_Node *Node, int Id, void *Data);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, USB, USB_Install, NULL, NULL);
+tDevFS_Driver gUSB_DrvInfo = {
+ NULL, "usb", {
+ .NumACLs = 1,
+ .ACLs = &gVFS_ACL_EveryoneRX,
+ .Flags = VFS_FFLAG_DIRECTORY,
+ .ReadDir = USB_ReadDir,
+ .FindDir = USB_FindDir,
+ .IOCtl = USB_IOCtl
+ }
+};
+tUSBDevice *gUSB_Devices = NULL;
+tUSBHost *gUSB_Hosts = NULL;
+
+// === CODE ===
+/**
+ * \fn int ModuleLoad()
+ * \brief Called once module is loaded
+ */
+int USB_Install(char **Arguments)
+{
+ UHCI_Initialise();
+ Warning("[USB ] Not Complete - Devel Only");
+ return 0;
+}
+
+/**
+ * \fn void USB_Cleanup()
+ * \brief Called just before module is unloaded
+ */
+void USB_Cleanup()
+{
+}
+
+/**
+ * \fn char *USB_ReadDir(tVFS_Node *Node, int Pos)
+ * \brief Read from the USB root
+ */
+char *USB_ReadDir(tVFS_Node *Node, int Pos)
+{
+ return NULL;
+}
+
+/**
+ * \fn tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
+ * \brief Locate an entry in the USB root
+ */
+tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
+{
+ return NULL;
+}
+
+/**
+ * \fn int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
+ * \brief Handles IOCtl Calls to the USB driver
+ */
+int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
+{
+ return 0;
+}
--- /dev/null
+/*\r
+ * Acess 2 USB Stack\r
+ * Universal Host Controller Interface\r
+ */\r
+#define DEBUG 1\r
+#include <common.h>\r
+#include <vfs.h>\r
+#include <drv_pci.h>\r
+#include "usb.h"\r
+#include "uhci.h"\r
+\r
+// === CONSTANTS ===\r
+#define MAX_CONTROLLERS 4\r
+#define NUM_TDs 1024\r
+\r
+// === PROTOTYPES ===\r
+ int UHCI_Initialise();\r
+void UHCI_Cleanup();\r
+ int UHCI_IOCtl(tVFS_Node *node, int id, void *data);\r
+ int UHCI_Int_InitHost(tUHCI_Controller *Host);\r
+\r
+// === GLOBALS ===
+//Uint gaFrameList[1024];\r
+tUHCI_TD gaUHCI_TDPool[NUM_TDs];\r
+tUHCI_Controller gUHCI_Controllers[MAX_CONTROLLERS];\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int UHCI_Initialise()\r
+ * \brief Called to initialise the UHCI Driver\r
+ */\r
+int UHCI_Initialise()\r
+{\r
+ int i=0, id=-1;\r
+ int ret;\r
+ Uint16 base;\r
+ \r
+ ENTER("");\r
+ \r
+ // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices\r
+ while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )\r
+ {\r
+ gUHCI_Controllers[i].PciId = id;\r
+ // Assign a port range (BAR4, Reserve 32 ports)\r
+ base = PCI_AssignPort( id, 4, 0x20 );\r
+ gUHCI_Controllers[i].IOBase = base;\r
+ \r
+ LOG("Controller PCI #%i: IO Base = 0x%x", id, base);\r
+ \r
+ // Initialise Host\r
+ ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);\r
+ // Detect an error\r
+ if(ret != 0) {\r
+ LEAVE('i', ret);\r
+ return ret;\r
+ }\r
+ \r
+ i ++;\r
+ }\r
+ if(i == MAX_CONTROLLERS) {\r
+ Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");\r
+ }\r
+ LEAVE('i', 0);\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn void UHCI_Cleanup()\r
+ * \brief Called just before module is unloaded\r
+ */\r
+void UHCI_Cleanup()\r
+{\r
+}
+
+/**
+ * \fn int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data)
+ */
+int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ return 0;
+}\r
+\r
+// === INTERNAL FUNCTIONS ===\r
+/**\r
+ * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)\r
+ * \brief Initialises a UHCI host controller\r
+ * \param Host Pointer - Host to initialise\r
+ */\r
+int UHCI_Int_InitHost(tUHCI_Controller *Host)\r
+{\r
+ ENTER("pHost", Host);\r
+ \r
+ // Allocate Frame List\r
+ Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList); // 1 Page, 32-bit\r
+ if( !Host->FrameList ) {\r
+ Warning("[UHCI ] Unable to allocate frame list, aborting");\r
+ LEAVE('i', -1);\r
+ return -1;\r
+ }\r
+ LOG("Allocated frame list 0x%x (0x%x)", Host->FrameList, Host->PhysFrameList);\r
+ memsetd( Host->FrameList, 1, 1024 ); // Clear List (Disabling all entries)\r
+ \r
+ //! \todo Properly fill frame list\r
+ \r
+ // Set frame length to 1 ms\r
+ outb( Host->IOBase + SOFMOD, 64 );\r
+ \r
+ // Set Frame List Address\r
+ outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );\r
+ \r
+ // Set Frame Number\r
+ outw( Host->IOBase + FRNUM, 0 );\r
+ \r
+ // Enable Interrupts\r
+ //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 );\r
+ \r
+ LEAVE('i', 0);\r
+ return 0;\r
+}\r
--- /dev/null
+/*
+ * AcessOS Version 1
+ * USB Stack
+ * - Universal Host Controller Interface
+ */
+#ifndef _UHCI_H_
+#define _UHCI_H_
+
+// === TYPES ===
+typedef struct sUHCI_Controller tUHCI_Controller;
+typedef struct sUHCI_TD tUHCI_TD;
+typedef struct sUHCI_QH tUHCI_QH;
+
+// === STRUCTURES ===
+struct sUHCI_Controller
+{
+ /**
+ * \brief PCI Device ID
+ */
+ Uint16 PciId;
+
+ /**
+ * \brief IO Base Address
+ */
+ Uint16 IOBase;
+
+ /**
+ * \brief Frame list
+ *
+ * 31:4 - Frame Pointer
+ * 3:2 - Reserved
+ * 1 - QH/TD Selector
+ * 0 - Terminate (Empty Pointer)
+ */
+ Uint32 *FrameList;
+
+ /**
+ * \brief Physical Address of the Frame List
+ */
+ tPAddr PhysFrameList;
+};
+
+struct sUHCI_TD
+{
+ /**
+ * \brief Next Entry in list
+ *
+ * 31:4 - Address
+ * 3 - Reserved
+ * 2 - Depth/Breadth Select
+ * 1 - QH/TD Select
+ * 0 - Terminate (Last in List)
+ */
+ Uint32 Link;
+
+ /**
+ * \brief Control and Status Field
+ *
+ * 31:30 - Reserved
+ * 29 - Short Packet Detect (Input Only)
+ * 28:27 - Number of Errors Allowed
+ * 26 - Low Speed Device (Communicating with a low speed device)
+ * 25 - Isynchonious Select
+ * 24 - Interrupt on Completion (IOC)
+ * 23:16 - Status
+ * 23 - Active
+ * 22 - Stalled
+ * 21 - Data Buffer Error
+ * 20 - Babble Detected
+ * 19 - NAK Detected
+ * 18 - CRC/Timout Error
+ * 17 - Bitstuff Error
+ * 16 - Reserved
+ * 15:11 - Reserved
+ * 10:0 - Actual Length (Number of bytes transfered)
+ */
+ Uint32 Control;
+
+ /**
+ * \brief Packet Header
+ *
+ * 31:21 - Maximum Length (0=1, Max 0x4FF, 0x7FF=0)
+ * 20 - Reserved
+ * 19 - Data Toggle
+ * 18:15 - Endpoint
+ * 14:8 - Device Address
+ * 7:0 - PID (Packet Identifcation) - Only 96, E1, 2D allowed
+ */
+ Uint32 Token;
+
+ /**
+ * \brief Pointer to the data to send
+ */
+ Uint32 BufferPointer;
+};
+
+struct sUHCI_QH
+{
+ /**
+ * \brief Next Entry in list
+ *
+ * 31:4 - Address
+ * 3:2 - Reserved
+ * 1 - QH/TD Select
+ * 0 - Terminate (Last in List)
+ */
+ Uint32 Next;
+
+
+ /**
+ * \brief Next Entry in list
+ *
+ * 31:4 - Address
+ * 3:2 - Reserved
+ * 1 - QH/TD Select
+ * 0 - Terminate (Last in List)
+ */
+ Uint32 Child;
+};
+
+// === ENUMERATIONS ===
+enum eUHCI_IOPorts {
+ /**
+ * \brief USB Command Register
+ *
+ * 15:8 - Reserved
+ * 7 - Maximum Packet Size selector (1: 64 bytes, 0: 32 bytes)
+ * 6 - Configure Flag (No Hardware Effect)
+ * 5 - Software Debug (Don't think it will be needed)
+ * 4 - Force Global Resume
+ * 3 - Enter Global Suspend Mode
+ * 2 - Global Reset (Resets all devices on the bus)
+ * 1 - Host Controller Reset (Reset just the controller)
+ * 0 - Run/Stop
+ */
+ USBCMD = 0x00,
+ /**
+ * \brief USB Status Register
+ *
+ * 15:6 - Reserved
+ * 5 - HC Halted, set to 1 when USBCMD:RS is set to 0
+ * 4 - Host Controller Process Error (Errors related to the bus)
+ * 3 - Host System Error (Errors related to the OS/PCI Bus)
+ * 2 - Resume Detect (Set if a RESUME command is sent to the Controller)
+ * 1 - USB Error Interrupt
+ * 0 - USB Interrupts (Set if a transaction with the IOC bit set is completed)
+ */
+ USBSTS = 0x02,
+ /**
+ * \brief USB Interrupt Enable Register
+ *
+ * 15:4 - Reserved
+ * 3 - Short Packet Interrupt Enable
+ * 2 - Interrupt on Complete (IOC) Enable
+ * 1 - Resume Interrupt Enable
+ * 0 - Timout / CRC Error Interrupt Enable
+ */
+ USBINTR = 0x04,
+ /**
+ * \brief Frame Number (Index into the Frame List)
+ *
+ * 15:11 - Reserved
+ * 10:0 - Index (Incremented each approx 1ms)
+ */
+ FRNUM = 0x06,
+ /**
+ * \brief Frame List Base Address
+ *
+ * 31:12 - Pysical Address >> 12
+ * 11:0 - Reserved (Set to Zero)
+ */
+ FLBASEADD = 0x08, // 32-bit
+ /**
+ * \brief Start-of-frame Modify Register
+ * \note 8-bits only
+ *
+ * Sets the size of a frame
+ * Frequency = (11936+n)/12000 kHz
+ *
+ * 7 - Reserved
+ * 6:0 -
+ */
+ SOFMOD = 0x0C, // 8bit
+ /**
+ * \brief Port Status and Controll Register (Port 1)
+ *
+ * 15:13 - Reserved
+ * 12 - Suspend
+ * 11:10 - Reserved
+ * 9 - Port Reset
+ * 8 - Low Speed Device Attached
+ * 5:4 - Line Status
+ * 3 - Port Enable/Disable Change - Used for detecting device removal
+ * 2 - Port Enable/Disable
+ * 1 - Connect Status Change
+ * 0 - Current Connect Status
+ */
+ PORTSC1 = 0x10,
+ /**
+ * \brief Port Status and Controll Register (Port 2)
+ *
+ * See ::PORTSC1
+ */
+ PORTSC2 = 0x12
+};
+
+#endif
--- /dev/null
+/*
+ * AcessOS Version 1
+ * USB Stack
+ */
+#ifndef _USB_H_
+#define _USB_H_
+
+// === TYPES ===
+typedef struct sUSBHost tUSBHost;
+typedef struct sUSBDevice tUSBDevice;
+
+// === STRUCTURES ===
+/**
+ * \brief Defines a USB Host Controller
+ */
+struct sUSBHost
+{
+ Uint16 IOBase;
+
+ int (*SendPacket)(int ID, int Length, void *Data);
+};
+
+/**
+ * \brief Defines a single device on the USB Bus
+ */
+struct sUSBDevice
+{
+ tUSBHost *Host;
+};
+
+#endif
--- /dev/null
+/*
+ * Acess2 Kernel Modules
+ * Linker Script
+ */
+
+ENTRY(ModuleEntry)
+OUTPUT_FORMAT(elf32-i386)
+
+SECTIONS
+{
+ . = 0 + SIZEOF_HEADERS;
+
+ .text : AT(ADDR(.text)) {
+ textzero = .;
+ *(.text)
+ }
+
+ .rodata ALIGN(0x1000): AT(ADDR(.rodata)) {
+ *(.rodata)
+ *(.rdata)
+ DriverInfo = .;
+ *(KMODULES)
+ }
+
+ .data ALIGN (0x1000) : AT(ADDR(.data)) {
+ *(.data)
+ }
+
+ .bss : AT(ADDR(.bss)) {
+ _sbss = .;
+ *(COMMON)
+ *(.bss)
+ _ebss = .;
+ }
+}
--- /dev/null
+/*
+ * Acess2 Library Suite
+ * - Readline
+ *
+ * Text mode entry with history
+ */
+#include <readline.h>
+#include <stdlib.h>
+
+// === GLOBALS ===
+
+// === CODE ===
+char *Readline(tReadline *Info)
+{
+ char *ret;
+ int len, pos, space = 1023;
+ char ch;
+ int scrollbackPos = Info->NumHistory;
+
+ // Preset Variables
+ ret = malloc( space+1 );
+ if(!ret) return NULL;
+ len = 0; pos = 0;
+
+ // Read In Command Line
+ do {
+ read(_stdin, 1, &ch); // Read Character from stdin (read is a blocking call)
+
+ if(ch == '\n') break;
+
+ switch(ch)
+ {
+ // Control characters
+ case '\x1B':
+ read(_stdin, 1, &ch); // Read control character
+ switch(ch)
+ {
+ //case 'D': if(pos) pos--; break;
+ //case 'C': if(pos<len) pos++; break;
+ case '[':
+ read(_stdin, 1, &ch); // Read control character
+ switch(ch)
+ {
+ case 'A': // Up
+ {
+ int oldLen = len;
+ if( scrollbackPos <= 0 ) break;
+
+ free(ret);
+ ret = strdup( Info->History[--scrollbackPos] );
+
+ len = strlen(ret);
+ while(pos--) write(_stdout, 3, "\x1B[D");
+ write(_stdout, len, ret); pos = len;
+ while(pos++ < oldLen) write(_stdout, 1, " ");
+ }
+ break;
+ case 'B': // Down
+ {
+ int oldLen = len;
+ if( scrollbackPos >= Info->NumHistory ) break;
+
+ free(ret);
+ ret = strdup( Info->History[scrollbackPos++] );
+
+ len = strlen(ret);
+ while(pos--) write(_stdout, 3, "\x1B[D");
+ write(_stdout, len, ret); pos = len;
+ while(pos++ < oldLen) write(_stdout, 1, " ");
+ }
+ break;
+ case 'D': // Left
+ if(pos == 0) break;
+ pos --;
+ write(_stdout, 3, "\x1B[D");
+ break;
+ case 'C': // Right
+ if(pos == len) break;
+ pos++;
+ write(_stdout, 3, "\x1B[C");
+ break;
+ }
+ }
+ break;
+
+ // Backspace
+ case '\b':
+ if(len <= 0) break; // Protect against underflows
+ write(_stdout, 1, &ch);
+ if(pos == len) { // Simple case of end of string
+ len --;
+ pos--;
+ }
+ else {
+ char buf[7] = "\x1B[000D";
+ buf[2] += ((len-pos+1)/100) % 10;
+ buf[3] += ((len-pos+1)/10) % 10;
+ buf[4] += (len-pos+1) % 10;
+ write(_stdout, len-pos, &ret[pos]); // Move Text
+ ch = ' '; write(_stdout, 1, &ch); ch = '\b'; // Clear deleted character
+ write(_stdout, 7, buf); // Update Cursor
+ // Alter Buffer
+ memmove(&ret[pos-1], &ret[pos], len-pos);
+ pos --;
+ len --;
+ }
+ break;
+
+ // Tab
+ case '\t':
+ //TODO: Implement Tab-Completion
+ //Currently just ignore tabs
+ break;
+
+ default:
+ // Expand Buffer
+ if(len+1 > space) {
+ space += 256;
+ ret = realloc(ret, space+1);
+ if(!ret) return NULL;
+ }
+
+ // Editing inside the buffer
+ if(pos != len) {
+ char buf[7] = "\x1B[000D";
+ buf[2] += ((len-pos)/100) % 10;
+ buf[3] += ((len-pos)/10) % 10;
+ buf[4] += (len-pos) % 10;
+ write(_stdout, 1, &ch); // Print new character
+ write(_stdout, len-pos, &ret[pos]); // Move Text
+ write(_stdout, 7, buf); // Update Cursor
+ memmove( &ret[pos+1], &ret[pos], len-pos );
+ }
+ else {
+ write(_stdout, 1, &ch);
+ }
+ ret[pos++] = ch;
+ len ++;
+ break;
+ }
+ } while(ch != '\n');
+
+ // Cap String
+ ret[len] = '\0';
+ printf("\n");
+
+ // Return length
+ //if(Length) *Length = len;
+
+ // Add to history
+ if( strcmp( Info->History[ Info->NumHistory-1 ], ret) != 0 )
+ {
+ void *tmp;
+ Info->NumHistory ++;
+ tmp = realloc( Info->History, Info->NumHistory * sizeof(char*) );
+ if(tmp != NULL)
+ {
+ Info->History = tmp;
+ Info->History[ Info->NumHistory-1 ] = strdup(ret);
+ }
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * AcessOS LibC
+ * stddef.h
+ */
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+// === CONSTANTS ===
+#ifndef NULL
+# define NULL ((void*)0)
+#endif
+
+// === TYPES ===
+#ifndef size_t
+typedef unsigned int size_t;
+#endif
+
+#endif