Modules/USB - Working on a structure for the USB subsystem
authorJohn Hodge <[email protected]>
Fri, 25 Nov 2011 01:53:00 +0000 (09:53 +0800)
committerJohn Hodge <[email protected]>
Fri, 25 Nov 2011 01:53:00 +0000 (09:53 +0800)
15 files changed:
Makefile.cfg
Modules/USB/Core/Makefile
Modules/USB/Core/include/usb_core.h [new file with mode: 0644]
Modules/USB/Core/include/usb_host.h [new file with mode: 0644]
Modules/USB/Core/include/usb_hub.h [new file with mode: 0644]
Modules/USB/Core/main.c
Modules/USB/Core/uhci.c [deleted file]
Modules/USB/Core/uhci.h [deleted file]
Modules/USB/Core/usb.c
Modules/USB/Core/usb.h
Modules/USB/Core/usb_proto.h [new file with mode: 0644]
Modules/USB/HID/hid.h [new file with mode: 0644]
Modules/USB/UHCI/Makefile [new file with mode: 0644]
Modules/USB/UHCI/uhci.c [new file with mode: 0644]
Modules/USB/UHCI/uhci.h [new file with mode: 0644]

index 3b1bfd5..d36dca5 100644 (file)
@@ -54,10 +54,10 @@ MODULES += Storage/FDDv2
 MODULES += Network/NE2000 Network/RTL8139
 MODULES += Display/VESA
 MODULES += Display/BochsGA
-#MODULES += Interfaces/UDI
 MODULES += Input/PS2KbMouse
 MODULES += x86/ISADMA x86/VGAText
-MODULES += USB/Core
+MODULES += USB/Core USB/UHCI
+#MODULES += Interfaces/UDI
 endif
 
 ifeq ($(ARCHDIR),x86_64)
@@ -68,7 +68,6 @@ MODULES += Display/BochsGA
 MODULES += Interfaces/UDI
 MODULES += Input/PS2KbMouse
 MODULES += x86/ISADMA x86/VGAText
-MODULES += USB/Core
 endif
 
 ifeq ($(ARCHDIR),armv7)
index b4cd323..7e8c30d 100644 (file)
@@ -1,7 +1,8 @@
 #
 #
 
-OBJ = main.o usb.o uhci.o
+OBJ = main.o usb.o
+CPPFLAGS = -Iinclude
 NAME = Core
 
 -include ../Makefile.tpl
diff --git a/Modules/USB/Core/include/usb_core.h b/Modules/USB/Core/include/usb_core.h
new file mode 100644 (file)
index 0000000..9169b0f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Acess2 USB Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * usb_core.h
+ * - Core USB IO Header 
+ */
+#ifndef _USB_CORE_H_
+#define _USB_CORE_H_
+
+typedef struct sUSBDevice      tUSBDevice;
+typedef struct sUSBDriver      tUSBDriver;
+
+/**
+ */
+struct sUSBDriver
+{
+       tUSBDriver      *Next;
+       
+       const char      *Name;
+       
+       // TODO: Check class codes and provide other identifcation options
+       Uint32  ClassCode;
+
+       void    (*Connected)(tUSBDevice *Dev);
+       void    (*Disconnected)(tUSBDevice *Dev);
+
+        int    MaxEndpoints;   
+       struct {
+               // 0: Bulk, 1: Control, 2: Interrupt
+                int    Type;
+               // Data availiable Callback
+               void    (*Interrupt)(tUSBDevice *Dev, int Length, void *Data);
+       } Endpoints[];
+};
+
+extern void    *USB_GetDeviceDataPtr(tUSBDevice *Dev);
+extern void    USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr);
+
+extern void    USB_SendData(tUSBDevice *Dev, int Endpoint, int Length, void *Data);
+
+#endif
+
diff --git a/Modules/USB/Core/include/usb_host.h b/Modules/USB/Core/include/usb_host.h
new file mode 100644 (file)
index 0000000..7dc7924
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Acess2 USB Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * usb_host.h
+ * - USB Host Controller Interface
+ */
+#ifndef _USB_HOST_H_
+#define _USB_HOST_H_
+
+#include "usb_core.h"
+#include "usb_hub.h"
+
+typedef struct sUSBHostDef     tUSBHostDef;
+
+/**
+ * \brief Defines a USB Host Controller type
+ */
+struct sUSBHostDef
+{
+       void    *(*SendIN)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+       void    *(*SendOUT)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+       void    *(*SendSETUP)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+       
+       void    (*CheckPorts)(void *Ptr);
+};
+
+extern tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts);
+
+#endif
+
diff --git a/Modules/USB/Core/include/usb_hub.h b/Modules/USB/Core/include/usb_hub.h
new file mode 100644 (file)
index 0000000..f48936b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Acess2 USB Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * usb_hub.h
+ * - Core Hub Definitions
+ */
+#ifndef _USB_HUB_H_
+#define _USB_HUB_H_
+
+#include "usb_core.h"
+
+typedef struct sUSBHub tUSBHub;
+
+typedef void   (*tUSB_HubPoll)(tUSBHub *Hub, tUSBDevice *HubDev);
+
+/**
+ * \brief Register a device as a hub
+ * 
+ * Used by the hub class initialisation routine.
+ */
+extern tUSBHub USB_RegisterHub(tUSBDevice *Device, int nPorts, tUSB_HubPoll PollCallback);
+
+extern void    USB_DeviceConnected(tUSBHub *Hub, int Port);
+extern void    USB_DeviceDisconnected(tUSBHub *Hub, int Port);
+
+#endif
+
index 9a6458e..baf1332 100644 (file)
@@ -10,9 +10,6 @@
 #include <modules.h>
 #include "usb.h"
 
-// === IMPORTS ===
-extern int     UHCI_Initialise(void);
-
 // === PROTOTYPES ===
  int   USB_Install(char **Arguments);
 void   USB_Cleanup(void);
@@ -32,8 +29,9 @@ tDevFS_Driver gUSB_DrvInfo = {
                .IOCtl = USB_IOCtl
        }
 };
-tUSBDevice     *gUSB_RootHubs = NULL;
 tUSBHost       *gUSB_Hosts = NULL;
+tUSBHub        *gUSB_Hubs = NULL;
+tUSBHub        *gUSB_HubsEnd = NULL;
 
 // === CODE ===
 /**
@@ -41,7 +39,6 @@ tUSBHost      *gUSB_Hosts = NULL;
  */
 int USB_Install(char **Arguments)
 {
-       UHCI_Initialise();
        Log_Warning("USB", "Not Complete - Devel Only");
        return MODULE_ERR_OK;
 }
@@ -53,15 +50,12 @@ int USB_PollThread(void *unused)
 {
        for(;;)
        {
-               for( tUSBHost *host = gUSB_Hosts; host; host = host->Next )
-               {
-                       // host->CheckPorts(host);
-               }
-
-               for( tUSBDevice *dev = gUSB_RootHubs; dev; dev = dev->Next )
+               for( tUSBHub *hub = gUSB_Hubs; hub; hub = hub->Next )
                {
-                       
+                       hub->CheckPorts(hub, hub->Device);
                }
+               // TODO: Fine tune
+               Time_Delay(250);
        }
 }
 
diff --git a/Modules/USB/Core/uhci.c b/Modules/USB/Core/uhci.c
deleted file mode 100644 (file)
index f50324f..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Acess 2 USB Stack
- * Universal Host Controller Interface
- */
-#define DEBUG  1
-#include <acess.h>
-#include <vfs.h>
-#include <drv_pci.h>
-#include <modules.h>
-#include "usb.h"
-#include "uhci.h"
-
-// === CONSTANTS ===
-#define        MAX_CONTROLLERS 4
-#define NUM_TDs        1024
-
-// === PROTOTYPES ===
- int   UHCI_Initialise();
-void   UHCI_Cleanup();
-tUHCI_TD       *UHCI_int_AllocateTD(tUHCI_Controller *Cont);
-void   UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD);
-void   *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length);
-void   *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
-void   *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
-void   *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
- int   UHCI_Int_InitHost(tUHCI_Controller *Host);
-void   UHCI_InterruptHandler(int IRQ, void *Ptr);
-
-// === GLOBALS ===
-tUHCI_TD       gaUHCI_TDPool[NUM_TDs];
-tUHCI_Controller       gUHCI_Controllers[MAX_CONTROLLERS];
-tUSBHost       gUHCI_HostDef = {
-       .SendIN = UHCI_DataIN,
-       .SendOUT = UHCI_DataOUT,
-       .SendSETUP = UHCI_SendSetup,
-       };
-
-// === CODE ===
-/**
- * \fn int UHCI_Initialise()
- * \brief Called to initialise the UHCI Driver
- */
-int UHCI_Initialise(const char **Arguments)
-{
-        int    i=0, id=-1;
-        int    ret;
-       
-       ENTER("");
-       
-       // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
-       while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
-       {
-               tUHCI_Controller        *cinfo = &gUHCI_Controllers[i];
-               // NOTE: Check "protocol" from PCI?
-               
-               cinfo->PciId = id;
-               // Assign a port range (BAR4, Reserve 32 ports)
-               cinfo->IOBase = PCI_GetBAR(id, 4);
-               if( !(cinfo->IOBase & 1) ) {
-                       Log_Warning("UHCI", "MMIO is not supported");
-                       continue ;
-               }
-               cinfo->IRQNum = PCI_GetIRQ(id);
-               
-               Log_Debug("UHCI", "Controller PCI #%i: IO Base = 0x%x, IRQ %i",
-                       id, cinfo->IOBase, cinfo->IRQNum);
-               
-               IRQ_AddHandler(cinfo->IRQNum, UHCI_InterruptHandler, cinfo);
-       
-               // Initialise Host
-               ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);
-               // Detect an error
-               if(ret != 0) {
-                       LEAVE('i', ret);
-                       return ret;
-               }
-               
-               USB_RegisterHost(&gUHCI_HostDef, cinfo);
-
-               i ++;
-       }
-       if(i == MAX_CONTROLLERS) {
-               Log_Warning("UHCI", "Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");
-       }
-       LEAVE('i', MODULE_ERR_OK);
-       return MODULE_ERR_OK;
-}
-
-/**
- * \fn void UHCI_Cleanup()
- * \brief Called just before module is unloaded
- */
-void UHCI_Cleanup()
-{
-}
-
-tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont)
-{
-        int    i;
-       for(i = 0; i < NUM_TDs; i ++)
-       {
-               if(gaUHCI_TDPool[i].Link == 0) {
-                       gaUHCI_TDPool[i].Link = 1;
-                       return &gaUHCI_TDPool[i];
-               }
-       }
-       return NULL;
-}
-
-void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD)
-{
-       Log_Warning("UHCI", "TODO: Implement AppendTD");
-}
-
-/**
- * \brief Send a transaction to the USB bus
- * \param Cont Controller pointer
- * \param Addr Function Address * 16 + Endpoint
- * \param bTgl Data toggle value
- */
-void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length)
-{
-       tUHCI_TD        *td;
-
-       if( Length > 0x400 )    return NULL;    // Controller allows up to 0x500, but USB doesn't
-
-       td = UHCI_int_AllocateTD(Cont);
-
-       td->Link = 1;
-       td->Control = (Length - 1) & 0x7FF;
-       td->Token  = ((Length - 1) & 0x7FF) << 21;
-       td->Token |= (bTgl & 1) << 19;
-       td->Token |= (Addr & 0xF) << 15;
-       td->Token |= ((Addr/16) & 0xFF) << 8;
-       td->Token |= Type;
-
-       // TODO: Ensure 32-bit paddr
-       if( ((tVAddr)Data & PAGE_SIZE) + Length > PAGE_SIZE ) {
-               Log_Warning("UHCI", "TODO: Support non single page transfers");
-//             td->BufferPointer = 
-               return NULL;
-       }
-       else {
-               td->BufferPointer = MM_GetPhysAddr( (tVAddr)Data );
-       }
-
-       if( bIOC ) {
-//             td->Control
-       }
-
-       UHCI_int_AppendTD(Cont, td);
-
-       return td;
-}
-
-void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
-{
-       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x69, DataTgl, bIOC, Data, Length);
-}
-
-void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
-{
-       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0xE1, DataTgl, bIOC, Data, Length);
-}
-
-void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
-{
-       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, bIOC, Data, Length);
-}
-
-// === 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);
-
-       outw( Host->IOBase + USBCMD, 4 );       // GRESET
-       Time_Delay(10);
-       // TODO: Wait for at least 10ms
-       outw( Host->IOBase + USBCMD, 0 );       // GRESET
-       
-       // Allocate Frame List
-       // - 1 Page, 32-bit address
-       // - 1 page = 1024  4 byte entries
-       Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList);
-       if( !Host->FrameList ) {
-               Log_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
-       outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );
-       outw( Host->IOBase + FRNUM, 0 );
-       
-       // Enable Interrupts
-       outw( Host->IOBase + USBINTR, 0x000F );
-       PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 );
-
-       outw( Host->IOBase + USBCMD, 0x0001 );
-
-       LEAVE('i', 0);
-       return 0;
-}
-
-void UHCI_CheckPortUpdate(tUHCI_Controller *Host)
-{
-       // Enable ports
-       for( int i = 0; i < 2; i ++ )
-       {
-                int    port = Host->IOBase + PORTSC1 + i*2;
-               // Check for port change
-               if( !(inw(port) & 0x0002) )     continue;
-               outw(port, 0x0002);
-               
-               // Check if the port is connected
-               if( !(inw(port) & 1) )
-               {
-                       // TODO: Tell the USB code it's gone?
-                       continue;
-               }
-               else
-               {
-                       LOG("Port %i has something", i);
-                       // Reset port (set bit 9)
-                       outw( port, 0x0100 );
-                       Time_Delay(50); // 50ms delay
-                       outw( port, inw(port) & ~0x0100 );
-                       // Enable port
-                       Time_Delay(50); // 50ms delay
-                       outw( port, inw(port) & 0x0004 );
-               }
-       }
-}
-
-void UHCI_InterruptHandler(int IRQ, void *Ptr)
-{
-       Log_Debug("UHCI", "UHIC Interrupt");
-}
diff --git a/Modules/USB/Core/uhci.h b/Modules/USB/Core/uhci.h
deleted file mode 100644 (file)
index 968ce43..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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 IRQ Number assigned to the device
-        */
-        int    IRQNum;
-       
-       /**
-        * \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
-        *
-        * 0x96 = Data IN
-        * 0xE1 = Data Out
-        * 0x2D = Setup
-        */
-       Uint32  Token;
-       
-       /**
-        * \brief Pointer to the data to send
-        */
-       Uint32  BufferPointer;
-
-       /**
-        * \brief Avaliable for use by software
-        */
-       Uint32  Avaliable[4];
-};
-
-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
index ab9a489..de884e4 100644 (file)
@@ -7,24 +7,57 @@
 #include <vfs.h>
 #include <drv_pci.h>
 #include "usb.h"
+#include "usb_proto.h"
 
+// === STRUCTURES ===
 
 // === CODE ===
-void USB_RegisterHost(tUSBHost *HostDef, void *ControllerPtr)
+tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
 {
        // TODO:
+       return NULL;
+}
+
+void USB_DeviceConnected(tUSBHub *Hub, int Port)
+{
+       if( Port >= Hub->nPorts )       return ;
+       if( Hub->Devices[Port] )        return ;
+
+       // 0. Perform port init? (done in hub?) 
+       // 1. Assign an address
+       
+       // 2. Get device information
+}
+
+void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
+{
+       
+}
+
+void *USB_GetDeviceDataPtr(tUSBDevice *Dev) { return Dev->Data; }
+void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr) { Dev->Data = Ptr; }
+
+int USB_int_AllocateAddress(tUSBHost *Host)
+{
+        int    i;
+       for( i = 1; i < 128; i ++ )
+       {
+               if(Host->AddressBitmap[i/8] & (1 << i))
+                       continue ;
+               return i;
+       }
+       return 0;
 }
 
 int USB_int_SendSetupSetAddress(tUSBHost *Host, void *Ptr, int Address)
 {
-       Uint8   data[8];
-       data[0] = 0;    // bmRequestType
-       data[1] = 5;    // SET_ADDRESS
-       data[2] = Address & 0x7F;       // wValue (low)
-       data[3] = 0;    // wValue (high)
-       data[4] = 0;    // wLength
-       data[6] = 0;    // wLength
+       struct sDeviceRequest   req;
+       req.ReqType = 0;        // bmRequestType
+       req.Request = 5;        // SET_ADDRESS
+       req.Value = Address & 0x7F;     // wValue
+       req.Index = 0;  // wIndex
+       req.Length = 0; // wLength
        
        // Addr 0:0, Data Toggle = 0, no interrupt
-       return Host->SendSETUP(Ptr, 0, 0, 0, FALSE, data, 8) == NULL;
+       return Host->HostDef->SendSETUP(Ptr, 0, 0, 0, FALSE, &req, sizeof(req)) == NULL;
 }
index 9bc45c8..65bba9d 100644 (file)
@@ -5,37 +5,23 @@
 #ifndef _USB_H_
 #define _USB_H_
 
-// === TYPES ===
+#include <usb_core.h>
+#include <usb_hub.h>
+#include <usb_host.h>
+
 typedef struct sUSBHost        tUSBHost;
-typedef struct sUSBHub tUSBHub;
-typedef struct sUSBDevice      tUSBDevice;
 
 // === STRUCTURES ===
-/**
- * \brief Defines a USB Host Controller type
- */
-struct sUSBHost
-{
-       tUSBHost        *Next;
-
-       void    (*CheckPorts)(void *Ptr);
-
-       void    *(*SendIN)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
-       void    *(*SendOUT)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
-       void    *(*SendSETUP)(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
-};
-
 /**
  * \brief USB Hub data
  */
 struct sUSBHub
 {
-       /**
-        * \brief Host controller used
-        */
-       tUSBHost        *HostDef;
-       void    *Controller;
-
+       tUSBHub *Next;
+       tUSBDevice      *Device;
+       
+       tUSB_HubPoll    CheckPorts;
+       
         int    nPorts;
        tUSBDevice      *Devices[];
 };
@@ -46,19 +32,28 @@ struct sUSBHub
 struct sUSBDevice
 {
        tUSBDevice      *Next;
-       tUSBDevice      *Hub;
+       tUSBDevice      *ParentHub;
 
+       /**
+        * \brief Host controller used
+        */
+       tUSBHost        *Host;
         int    Address;
        
-        int    Type;
+       tUSBDriver      *Driver;
+       void    *Data;
+};
+
+struct sUSBHost
+{
+       struct sUSBHost *Next;
+       
+       tUSBHostDef     *HostDef;
+       void    *Ptr;
        
-       union {
-               tUSBHub Hub;
-               char    Impl[0];
-       }       Data;
+       Uint8   AddressBitmap[128/8];
 };
 
-extern void    USB_RegisterHost(tUSBHost *HostDef, void *ControllerPtr);
 extern void    USB_NewDevice(tUSBHub *Hub);
 
 #endif
diff --git a/Modules/USB/Core/usb_proto.h b/Modules/USB/Core/usb_proto.h
new file mode 100644 (file)
index 0000000..3a98e47
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ */
+#ifndef _USB_PROTO_H_
+#define _USB_PROTO_H_
+
+struct sDeviceRequest
+{
+       Uint8   ReqType;
+       Uint8   Request;
+       Uint16  Value;
+       Uint16  Index;
+       Uint16  Length;
+};
+
+/*
+ */
+struct sDescriptor_Device
+{
+       Uint8   Length;
+       Uint8   Type;   // =
+       Uint16  USBVersion;     // BCD, 0x210 = 2.10
+       Uint8   DeviceClass;
+       Uint8   DeviceSubClass;
+       Uint8   DeviceProtocol;
+       Uint8   MaxPacketSize;
+       
+       Uint16  VendorID;
+       Uint16  ProductID;
+       
+       Uint8   ManufacturerStr;
+       Uint8   ProductStr;
+       Uint8   SerialNumberStr;
+       
+       Uint8   NumConfigurations;
+};
+
+#endif
+
diff --git a/Modules/USB/HID/hid.h b/Modules/USB/HID/hid.h
new file mode 100644 (file)
index 0000000..373496e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Acess2 USB Stack HID Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * hid.h
+ * - Core header
+ */
+#ifndef _HID_H_
+#define _HID_H_
+
+// Report Descriptor Types
+// - 0: Main
+//  > 8: Input - Axis/Button etc
+//  > 9: Output - LED/Position
+//  > B: Feature -
+//  > A: Collection - Group of Input/Output/Feature
+//  > C: End collection
+// - 1: Global (Not restored on main)
+// - 2: Local
+//  > 
+// - 3: Reserved/Unused
+
+// I/O/F Data Values
+#define HID_IOF_CONSTANT       0x001   //!< Host Read-only
+#define HID_IOF_VARIABLE       0x002   //!< 
+
+struct sLongItem
+{
+       Uint8   Header; // 0xFE (Tag 15, Type 3, Size 2)
+       Uint8   DataSize;
+       Uint8   Tag;
+};
+
+struct sDescriptor_HID
+{
+       Uint8   Length;
+       Uint8   Type;   // 
+       Uint16  Version;        // 0x0111 = 1.11
+       Uint8   CountryCode;
+       Uint8   NumDescriptors; // >= 1
+       struct {
+               Uint8   DescType;
+               Uint16  DescLen;
+       } Descriptors[];
+}
+
+#endif
diff --git a/Modules/USB/UHCI/Makefile b/Modules/USB/UHCI/Makefile
new file mode 100644 (file)
index 0000000..798159a
--- /dev/null
@@ -0,0 +1,8 @@
+#
+#
+
+OBJ = uhci.o
+CPPFLAGS = -I../Core/include
+NAME = UHCI
+
+-include ../Makefile.tpl
diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c
new file mode 100644 (file)
index 0000000..8e41e27
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Acess 2 USB Stack
+ * Universal Host Controller Interface
+ */
+#define DEBUG  1
+#define VERSION        VER2(0,5)
+#include <acess.h>
+#include <vfs.h>
+#include <drv_pci.h>
+#include <modules.h>
+#include <usb_host.h>
+#include "uhci.h"
+
+// === CONSTANTS ===
+#define        MAX_CONTROLLERS 4
+#define NUM_TDs        1024
+
+// === PROTOTYPES ===
+ int   UHCI_Initialise();
+void   UHCI_Cleanup();
+tUHCI_TD       *UHCI_int_AllocateTD(tUHCI_Controller *Cont);
+void   UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD);
+void   *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length);
+void   *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+void   *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+void   *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length);
+void   UHCI_Hub_Poll(tUSBHub *Hub, tUSBDevice *Dev);
+ int   UHCI_Int_InitHost(tUHCI_Controller *Host);
+void   UHCI_CheckPortUpdate(tUHCI_Controller *Host);
+void   UHCI_InterruptHandler(int IRQ, void *Ptr);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, USB_UHCI, UHCI_Initialise, NULL, "USB_Core", NULL);
+tUHCI_TD       gaUHCI_TDPool[NUM_TDs];
+tUHCI_Controller       gUHCI_Controllers[MAX_CONTROLLERS];
+tUSBHostDef    gUHCI_HostDef = {
+       .SendIN = UHCI_DataIN,
+       .SendOUT = UHCI_DataOUT,
+       .SendSETUP = UHCI_SendSetup,
+       .CheckPorts = (void*)UHCI_CheckPortUpdate
+       };
+
+// === CODE ===
+/**
+ * \fn int UHCI_Initialise()
+ * \brief Called to initialise the UHCI Driver
+ */
+int UHCI_Initialise(const char **Arguments)
+{
+        int    i=0, id=-1;
+        int    ret;
+       
+       ENTER("");
+       
+       // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
+       while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
+       {
+               tUHCI_Controller        *cinfo = &gUHCI_Controllers[i];
+               // NOTE: Check "protocol" from PCI?
+               
+               cinfo->PciId = id;
+               // Assign a port range (BAR4, Reserve 32 ports)
+               cinfo->IOBase = PCI_GetBAR(id, 4);
+               if( !(cinfo->IOBase & 1) ) {
+                       Log_Warning("UHCI", "MMIO is not supported");
+                       continue ;
+               }
+               cinfo->IRQNum = PCI_GetIRQ(id);
+               
+               Log_Debug("UHCI", "Controller PCI #%i: IO Base = 0x%x, IRQ %i",
+                       id, cinfo->IOBase, cinfo->IRQNum);
+               
+               IRQ_AddHandler(cinfo->IRQNum, UHCI_InterruptHandler, cinfo);
+       
+               // Initialise Host
+               ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);
+               // Detect an error
+               if(ret != 0) {
+                       LEAVE('i', ret);
+                       return ret;
+               }
+               
+               cinfo->RootHub = USB_RegisterHost(&gUHCI_HostDef, cinfo, 2);
+
+               i ++;
+       }
+       if(i == MAX_CONTROLLERS) {
+               Log_Warning("UHCI", "Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");
+       }
+       LEAVE('i', MODULE_ERR_OK);
+       return MODULE_ERR_OK;
+}
+
+/**
+ * \fn void UHCI_Cleanup()
+ * \brief Called just before module is unloaded
+ */
+void UHCI_Cleanup()
+{
+}
+
+tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont)
+{
+        int    i;
+       for(i = 0; i < NUM_TDs; i ++)
+       {
+               if(gaUHCI_TDPool[i].Link == 0) {
+                       gaUHCI_TDPool[i].Link = 1;
+                       return &gaUHCI_TDPool[i];
+               }
+       }
+       return NULL;
+}
+
+void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD)
+{
+       Log_Warning("UHCI", "TODO: Implement AppendTD");
+}
+
+/**
+ * \brief Send a transaction to the USB bus
+ * \param Cont Controller pointer
+ * \param Addr Function Address * 16 + Endpoint
+ * \param bTgl Data toggle value
+ */
+void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length)
+{
+       tUHCI_TD        *td;
+
+       if( Length > 0x400 )    return NULL;    // Controller allows up to 0x500, but USB doesn't
+
+       td = UHCI_int_AllocateTD(Cont);
+
+       td->Link = 1;
+       td->Control = (Length - 1) & 0x7FF;
+       td->Token  = ((Length - 1) & 0x7FF) << 21;
+       td->Token |= (bTgl & 1) << 19;
+       td->Token |= (Addr & 0xF) << 15;
+       td->Token |= ((Addr/16) & 0xFF) << 8;
+       td->Token |= Type;
+
+       // TODO: Ensure 32-bit paddr
+       if( ((tVAddr)Data & PAGE_SIZE) + Length > PAGE_SIZE ) {
+               Log_Warning("UHCI", "TODO: Support non single page transfers");
+//             td->BufferPointer = 
+               return NULL;
+       }
+       else {
+               td->BufferPointer = MM_GetPhysAddr( (tVAddr)Data );
+       }
+
+       if( bIOC ) {
+//             td->Control
+       }
+
+       UHCI_int_AppendTD(Cont, td);
+
+       return td;
+}
+
+void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
+{
+       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x69, DataTgl, bIOC, Data, Length);
+}
+
+void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
+{
+       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0xE1, DataTgl, bIOC, Data, Length);
+}
+
+void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length)
+{
+       return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, bIOC, Data, Length);
+}
+
+void UHCI_Hub_Poll(tUSBHub *Hub, tUSBDevice *Dev)
+{
+       tUHCI_Controller        *cont = USB_GetDeviceDataPtr(Dev);
+       
+       UHCI_CheckPortUpdate(cont);
+}
+
+// === 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);
+
+       outw( Host->IOBase + USBCMD, 4 );       // GRESET
+       Time_Delay(10);
+       // TODO: Wait for at least 10ms
+       outw( Host->IOBase + USBCMD, 0 );       // GRESET
+       
+       // Allocate Frame List
+       // - 1 Page, 32-bit address
+       // - 1 page = 1024  4 byte entries
+       Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList);
+       if( !Host->FrameList ) {
+               Log_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
+       outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );
+       outw( Host->IOBase + FRNUM, 0 );
+       
+       // Enable Interrupts
+       outw( Host->IOBase + USBINTR, 0x000F );
+       PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 );
+
+       outw( Host->IOBase + USBCMD, 0x0001 );
+
+       LEAVE('i', 0);
+       return 0;
+}
+
+void UHCI_CheckPortUpdate(tUHCI_Controller *Host)
+{
+       // Enable ports
+       for( int i = 0; i < 2; i ++ )
+       {
+                int    port = Host->IOBase + PORTSC1 + i*2;
+               // Check for port change
+               if( !(inw(port) & 0x0002) )     continue;
+               outw(port, 0x0002);
+               
+               // Check if the port is connected
+               if( !(inw(port) & 1) )
+               {
+                       // Tell the USB code it's gone.
+                       USB_DeviceDisconnected(Host->RootHub, i);
+                       continue;
+               }
+               else
+               {
+                       LOG("Port %i has something", i);
+                       // Reset port (set bit 9)
+                       outw( port, 0x0100 );
+                       Time_Delay(50); // 50ms delay
+                       outw( port, inw(port) & ~0x0100 );
+                       // Enable port
+                       Time_Delay(50); // 50ms delay
+                       outw( port, inw(port) & 0x0004 );
+                       // Tell USB there's a new device
+                       USB_DeviceConnected(Host->RootHub, i);
+               }
+       }
+}
+
+void UHCI_InterruptHandler(int IRQ, void *Ptr)
+{
+       Log_Debug("UHCI", "UHIC Interrupt");
+}
diff --git a/Modules/USB/UHCI/uhci.h b/Modules/USB/UHCI/uhci.h
new file mode 100644 (file)
index 0000000..7d88d35
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * 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 IRQ Number assigned to the device
+        */
+        int    IRQNum;
+       
+       /**
+        * \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;
+
+       tUSBHub *RootHub;
+};
+
+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
+        *
+        * 0x96 = Data IN
+        * 0xE1 = Data Out
+        * 0x2D = Setup
+        */
+       Uint32  Token;
+       
+       /**
+        * \brief Pointer to the data to send
+        */
+       Uint32  BufferPointer;
+
+       /**
+        * \brief Avaliable for use by software
+        */
+       Uint32  Avaliable[4];
+};
+
+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

UCC git Repository :: git.ucc.asn.au