From 6c5a509b5e14e097ca537c539bc9babe3b8f0c4c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 10 Nov 2009 13:21:38 +0800 Subject: [PATCH] Adding several modules to the Tree, plus some files that escaped earlier - Added the in-progress IP Stack - Added the in-progress USB Stack - Added module's linker script - Added tpl_drv_terminal.h (Terminal Emulator defintions) - Added libreadline (my own version) - Added Usermode/stddef.h --- Kernel/include/tpl_drv_terminal.h | 104 ++++++++++ Modules/IPStack/Makefile | 7 + Modules/IPStack/arp.c | 177 ++++++++++++++++ Modules/IPStack/arp.h | 35 ++++ Modules/IPStack/icmp.c | 32 +++ Modules/IPStack/icmp.h | 21 ++ Modules/IPStack/ipstack.h | 83 ++++++++ Modules/IPStack/ipv4.c | 100 +++++++++ Modules/IPStack/ipv4.h | 46 +++++ Modules/IPStack/ipv6.c | 84 ++++++++ Modules/IPStack/ipv6.h | 28 +++ Modules/IPStack/link.c | 118 +++++++++++ Modules/IPStack/link.h | 28 +++ Modules/IPStack/main.c | 87 ++++++++ Modules/IPStack/tcp.c | 175 ++++++++++++++++ Modules/IPStack/tcp.h | 71 +++++++ Modules/USB/Makefile | 7 + Modules/USB/main.c | 83 ++++++++ Modules/USB/uhci.c | 119 +++++++++++ Modules/USB/uhci.h | 207 +++++++++++++++++++ Modules/USB/usb.h | 31 +++ Modules/link.ld | 35 ++++ Usermode/Libraries/libreadline.so_src/main.c | 164 +++++++++++++++ Usermode/include/stddef.h | 18 ++ 24 files changed, 1860 insertions(+) create mode 100644 Kernel/include/tpl_drv_terminal.h create mode 100644 Modules/IPStack/Makefile create mode 100644 Modules/IPStack/arp.c create mode 100644 Modules/IPStack/arp.h create mode 100644 Modules/IPStack/icmp.c create mode 100644 Modules/IPStack/icmp.h create mode 100644 Modules/IPStack/ipstack.h create mode 100644 Modules/IPStack/ipv4.c create mode 100644 Modules/IPStack/ipv4.h create mode 100644 Modules/IPStack/ipv6.c create mode 100644 Modules/IPStack/ipv6.h create mode 100644 Modules/IPStack/link.c create mode 100644 Modules/IPStack/link.h create mode 100644 Modules/IPStack/main.c create mode 100644 Modules/IPStack/tcp.c create mode 100644 Modules/IPStack/tcp.h create mode 100644 Modules/USB/Makefile create mode 100644 Modules/USB/main.c create mode 100644 Modules/USB/uhci.c create mode 100644 Modules/USB/uhci.h create mode 100644 Modules/USB/usb.h create mode 100644 Modules/link.ld create mode 100644 Usermode/Libraries/libreadline.so_src/main.c create mode 100644 Usermode/include/stddef.h diff --git a/Kernel/include/tpl_drv_terminal.h b/Kernel/include/tpl_drv_terminal.h new file mode 100644 index 00000000..639d181f --- /dev/null +++ b/Kernel/include/tpl_drv_terminal.h @@ -0,0 +1,104 @@ +/** + * \file tpl_drv_terminal.h + * \brief Terminal Driver Interface Definitions +*/ +#ifndef _TPL_TERMINAL_H +#define _TPL_TERMINAL_H + +#include + +/** + * \enum eTplTerminal_IOCtl + * \brief Common Terminal IOCtl Calls + * \extends eTplDrv_IOCtl + */ +enum eTplTerminal_IOCtl { + /** + * ioctl(..., int *mode) + * \brief Get/Set the current video mode type + * see ::eTplTerminal_Modes + * \note If the mode is set the mode is changed at this call + */ + TERM_IOCTL_MODETYPE = 4, + + /** + * ioctl(..., int *width) + * \brief Get/set the display width + * \param width Pointer to an integer containing the new width + * \return Current width + * + * Set `width` to NULL to just return the current width + */ + TERM_IOCTL_WIDTH, + + /** + * ioctl(..., int *height) + * \brief Get/set the display height + * \param height Pointer to an integer containing the new height + * \return Current height + * + * Set \a height to NULL to just return the current height + */ + TERM_IOCTL_HEIGHT, + + /** + * ioctl(..., tTerm_IOCtl_Mode *info) + * \brief Queries the current driver about it's modes + * \param info A pointer to a ::tTerm_IOCtl_Mode with .ID set to the mode index + * \return Number of modes + * + * \a info can be NULL + */ + TERM_IOCTL_QUERYMODE +}; + +typedef struct sTerm_IOCtl_Mode tTerm_IOCtl_Mode; + +/** + * \brief Virtual Terminal Mode + * Describes a VTerm mode to the caller of ::TERM_IOCTL_QUERYMODE + */ +struct sTerm_IOCtl_Mode +{ + short ID; //!< Zero Based index of mode + short DriverID; //!< Driver's ID number (from ::tVideo_IOCtl_Mode) + Uint16 Height; //!< Height + Uint16 Width; //!< Width + Uint8 Depth; //!< Bits per cell + struct { + unsigned bText: 1; //!< Text Mode marker + unsigned unused: 7; + }; +}; + +/** + * \brief Terminal Modes + */ +enum eTplTerminal_Modes { + /** + * \brief UTF-8 Text Mode + * Any writes to the terminal file are treated as UTF-8 encoded + * strings and reads will also return UTF-8 strings. + */ + TERM_MODE_TEXT, + + /** + * \brief 32bpp Framebuffer + * Writes to the terminal file will write to the framebuffer. + * Reads will return UTF-32 characters + */ + TERM_MODE_FB, + + /** + * \brief OpenGL 2D/3D + * Writes to the terminal file will send 3D commands + * Reads will return UTF-32 characters + * \note May or may not stay in the spec + */ + TERM_MODE_OPENGL, + + NUM_TERM_MODES +}; + + +#endif diff --git a/Modules/IPStack/Makefile b/Modules/IPStack/Makefile new file mode 100644 index 00000000..6226f4f4 --- /dev/null +++ b/Modules/IPStack/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o link.o arp.o ipv4.o ipv6.o +NAME = IPStack + +-include ../Makefile.tpl diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c new file mode 100644 index 00000000..cc194e90 --- /dev/null +++ b/Modules/IPStack/arp.c @@ -0,0 +1,177 @@ +/* + * 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; + } +} diff --git a/Modules/IPStack/arp.h b/Modules/IPStack/arp.h new file mode 100644 index 00000000..64f07c3e --- /dev/null +++ b/Modules/IPStack/arp.h @@ -0,0 +1,35 @@ +/* + * 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 diff --git a/Modules/IPStack/icmp.c b/Modules/IPStack/icmp.c new file mode 100644 index 00000000..bd9c05f4 --- /dev/null +++ b/Modules/IPStack/icmp.c @@ -0,0 +1,32 @@ +/* + * 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; + +} diff --git a/Modules/IPStack/icmp.h b/Modules/IPStack/icmp.h new file mode 100644 index 00000000..73a641fb --- /dev/null +++ b/Modules/IPStack/icmp.h @@ -0,0 +1,21 @@ +/* + * 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 diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h new file mode 100644 index 00000000..8b846ab3 --- /dev/null +++ b/Modules/IPStack/ipstack.h @@ -0,0 +1,83 @@ +/* + * Acess2 IP Stack + * - Common Header + */ +#ifndef _IPSTACK_H_ +#define _IPSTACK_H_ + +#include +#include + +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 diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c new file mode 100644 index 00000000..d57b124d --- /dev/null +++ b/Modules/IPStack/ipv4.c @@ -0,0 +1,100 @@ +/* + * 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; +} diff --git a/Modules/IPStack/ipv4.h b/Modules/IPStack/ipv4.h new file mode 100644 index 00000000..67b3dc83 --- /dev/null +++ b/Modules/IPStack/ipv4.h @@ -0,0 +1,46 @@ +/* + * 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 diff --git a/Modules/IPStack/ipv6.c b/Modules/IPStack/ipv6.c new file mode 100644 index 00000000..31aedcb3 --- /dev/null +++ b/Modules/IPStack/ipv6.c @@ -0,0 +1,84 @@ +/* + * 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; +} diff --git a/Modules/IPStack/ipv6.h b/Modules/IPStack/ipv6.h new file mode 100644 index 00000000..a98561db --- /dev/null +++ b/Modules/IPStack/ipv6.h @@ -0,0 +1,28 @@ +/* + * 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 diff --git a/Modules/IPStack/link.c b/Modules/IPStack/link.c new file mode 100644 index 00000000..fb219847 --- /dev/null +++ b/Modules/IPStack/link.c @@ -0,0 +1,118 @@ +/* + * 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 + ); + } +} diff --git a/Modules/IPStack/link.h b/Modules/IPStack/link.h new file mode 100644 index 00000000..c662f141 --- /dev/null +++ b/Modules/IPStack/link.h @@ -0,0 +1,28 @@ +/* + * 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 diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c new file mode 100644 index 00000000..aaeeb9af --- /dev/null +++ b/Modules/IPStack/main.c @@ -0,0 +1,87 @@ +/* + * Acess2 IP Stack + * - Address Resolution Protocol + */ +#include "ipstack.h" +#include +#include + +// === 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; +} diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c new file mode 100644 index 00000000..b8c17584 --- /dev/null +++ b/Modules/IPStack/tcp.c @@ -0,0 +1,175 @@ +/* + * 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; +} + diff --git a/Modules/IPStack/tcp.h b/Modules/IPStack/tcp.h new file mode 100644 index 00000000..fb515acb --- /dev/null +++ b/Modules/IPStack/tcp.h @@ -0,0 +1,71 @@ +/* + * 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 diff --git a/Modules/USB/Makefile b/Modules/USB/Makefile new file mode 100644 index 00000000..b4f400a5 --- /dev/null +++ b/Modules/USB/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o uhci.o +NAME = USB + +-include ../Makefile.tpl diff --git a/Modules/USB/main.c b/Modules/USB/main.c new file mode 100644 index 00000000..0bdcc246 --- /dev/null +++ b/Modules/USB/main.c @@ -0,0 +1,83 @@ +/* + * Acess2 + * USB Stack + */ +#define VERSION ( (0<<8)| 5 ) +#define DEBUG 1 +#include +#include +#include +#include +#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; +} diff --git a/Modules/USB/uhci.c b/Modules/USB/uhci.c new file mode 100644 index 00000000..65037ef0 --- /dev/null +++ b/Modules/USB/uhci.c @@ -0,0 +1,119 @@ +/* + * Acess 2 USB Stack + * Universal Host Controller Interface + */ +#define DEBUG 1 +#include +#include +#include +#include "usb.h" +#include "uhci.h" + +// === CONSTANTS === +#define MAX_CONTROLLERS 4 +#define NUM_TDs 1024 + +// === PROTOTYPES === + int UHCI_Initialise(); +void UHCI_Cleanup(); + int UHCI_IOCtl(tVFS_Node *node, int id, void *data); + int UHCI_Int_InitHost(tUHCI_Controller *Host); + +// === GLOBALS === +//Uint gaFrameList[1024]; +tUHCI_TD gaUHCI_TDPool[NUM_TDs]; +tUHCI_Controller gUHCI_Controllers[MAX_CONTROLLERS]; + +// === CODE === +/** + * \fn int UHCI_Initialise() + * \brief Called to initialise the UHCI Driver + */ +int UHCI_Initialise() +{ + int i=0, id=-1; + int ret; + Uint16 base; + + ENTER(""); + + // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices + while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS ) + { + gUHCI_Controllers[i].PciId = id; + // Assign a port range (BAR4, Reserve 32 ports) + base = PCI_AssignPort( id, 4, 0x20 ); + gUHCI_Controllers[i].IOBase = base; + + LOG("Controller PCI #%i: IO Base = 0x%x", id, base); + + // Initialise Host + ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]); + // Detect an error + if(ret != 0) { + LEAVE('i', ret); + return ret; + } + + i ++; + } + if(i == MAX_CONTROLLERS) { + Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest"); + } + LEAVE('i', 0); + return 0; +} + +/** + * \fn void UHCI_Cleanup() + * \brief Called just before module is unloaded + */ +void UHCI_Cleanup() +{ +} + +/** + * \fn int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data) + */ +int UHCI_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + return 0; +} + +// === INTERNAL FUNCTIONS === +/** + * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host) + * \brief Initialises a UHCI host controller + * \param Host Pointer - Host to initialise + */ +int UHCI_Int_InitHost(tUHCI_Controller *Host) +{ + ENTER("pHost", Host); + + // Allocate Frame List + Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList); // 1 Page, 32-bit + if( !Host->FrameList ) { + Warning("[UHCI ] Unable to allocate frame list, aborting"); + LEAVE('i', -1); + return -1; + } + LOG("Allocated frame list 0x%x (0x%x)", Host->FrameList, Host->PhysFrameList); + memsetd( Host->FrameList, 1, 1024 ); // Clear List (Disabling all entries) + + //! \todo Properly fill frame list + + // Set frame length to 1 ms + outb( Host->IOBase + SOFMOD, 64 ); + + // Set Frame List Address + outd( Host->IOBase + FLBASEADD, Host->PhysFrameList ); + + // Set Frame Number + outw( Host->IOBase + FRNUM, 0 ); + + // Enable Interrupts + //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 ); + + LEAVE('i', 0); + return 0; +} diff --git a/Modules/USB/uhci.h b/Modules/USB/uhci.h new file mode 100644 index 00000000..df7854b8 --- /dev/null +++ b/Modules/USB/uhci.h @@ -0,0 +1,207 @@ +/* + * 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 diff --git a/Modules/USB/usb.h b/Modules/USB/usb.h new file mode 100644 index 00000000..3e503ec4 --- /dev/null +++ b/Modules/USB/usb.h @@ -0,0 +1,31 @@ +/* + * 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 diff --git a/Modules/link.ld b/Modules/link.ld new file mode 100644 index 00000000..503f63d6 --- /dev/null +++ b/Modules/link.ld @@ -0,0 +1,35 @@ +/* + * 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 = .; + } +} diff --git a/Usermode/Libraries/libreadline.so_src/main.c b/Usermode/Libraries/libreadline.so_src/main.c new file mode 100644 index 00000000..e145bc0c --- /dev/null +++ b/Usermode/Libraries/libreadline.so_src/main.c @@ -0,0 +1,164 @@ +/* + * Acess2 Library Suite + * - Readline + * + * Text mode entry with history + */ +#include +#include + +// === 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(posHistory[--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; +} diff --git a/Usermode/include/stddef.h b/Usermode/include/stddef.h new file mode 100644 index 00000000..88e19f6a --- /dev/null +++ b/Usermode/include/stddef.h @@ -0,0 +1,18 @@ +/* + * 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 -- 2.20.1