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)
MODULES += Interfaces/UDI
MODULES += Input/PS2KbMouse
MODULES += x86/ISADMA x86/VGAText
-MODULES += USB/Core
endif
ifeq ($(ARCHDIR),armv7)
#
#
-OBJ = main.o usb.o uhci.o
+OBJ = main.o usb.o
+CPPFLAGS = -Iinclude
NAME = Core
-include ../Makefile.tpl
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
+
#include <modules.h>
#include "usb.h"
-// === IMPORTS ===
-extern int UHCI_Initialise(void);
-
// === PROTOTYPES ===
int USB_Install(char **Arguments);
void USB_Cleanup(void);
.IOCtl = USB_IOCtl
}
};
-tUSBDevice *gUSB_RootHubs = NULL;
tUSBHost *gUSB_Hosts = NULL;
+tUSBHub *gUSB_Hubs = NULL;
+tUSBHub *gUSB_HubsEnd = NULL;
// === CODE ===
/**
*/
int USB_Install(char **Arguments)
{
- UHCI_Initialise();
Log_Warning("USB", "Not Complete - Devel Only");
return MODULE_ERR_OK;
}
{
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);
}
}
+++ /dev/null
-/*
- * 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");
-}
+++ /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 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
#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;
}
#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[];
};
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
--- /dev/null
+/**
+ */
+#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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+#
+#
+
+OBJ = uhci.o
+CPPFLAGS = -I../Core/include
+NAME = UHCI
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * 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");
+}
--- /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 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