Modules/USB - A little more work
[tpg/acess2.git] / Modules / USB / Core / uhci.c
1 /*
2  * Acess 2 USB Stack
3  * Universal Host Controller Interface
4  */
5 #define DEBUG   1
6 #include <acess.h>
7 #include <vfs.h>
8 #include <drv_pci.h>
9 #include "usb.h"
10 #include "uhci.h"
11
12 // === CONSTANTS ===
13 #define MAX_CONTROLLERS 4
14 #define NUM_TDs 1024
15
16 // === PROTOTYPES ===
17  int    UHCI_Initialise();
18 void    UHCI_Cleanup();
19  int    UHCI_IOCtl(tVFS_Node *node, int id, void *data);
20  int    UHCI_Int_InitHost(tUHCI_Controller *Host);
21
22 // === GLOBALS ===
23 tUHCI_TD        gaUHCI_TDPool[NUM_TDs];
24 tUHCI_Controller        gUHCI_Controllers[MAX_CONTROLLERS];
25
26 // === CODE ===
27 /**
28  * \fn int UHCI_Initialise()
29  * \brief Called to initialise the UHCI Driver
30  */
31 int UHCI_Initialise(const char **Arguments)
32 {
33          int    i=0, id=-1;
34          int    ret;
35         
36         ENTER("");
37         
38         // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
39         while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
40         {
41                 tUHCI_Controller        *cinfo = &gUHCI_Controllers[i];
42                 // NOTE: Check "protocol" from PCI?
43                 
44                 cinfo->PciId = id;
45                 // Assign a port range (BAR4, Reserve 32 ports)
46                 cinfo->IOBase = PCI_GetBAR(id, 4);
47                 if( !(cinfo->IOBase & 1) ) {
48                         Log_Warning("UHCI", "MMIO is not supported");
49                         continue ;
50                 }
51                 cinfo->IRQNum = PCI_GetIRQ(id);
52                 
53                 Log_Debug("UHCI", "Controller PCI #%i: IO Base = 0x%x, IRQ %i",
54                         id, cinfo->IOBase, cinfo->IRQNum);
55                 
56                 // Initialise Host
57                 ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);
58                 // Detect an error
59                 if(ret != 0) {
60                         LEAVE('i', ret);
61                         return ret;
62                 }
63                 
64                 i ++;
65         }
66         if(i == MAX_CONTROLLERS) {
67                 Log_Warning("UHCI", "Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");
68         }
69         LEAVE('i', i);
70         return i;
71 }
72
73 /**
74  * \fn void UHCI_Cleanup()
75  * \brief Called just before module is unloaded
76  */
77 void UHCI_Cleanup()
78 {
79 }
80
81 /**
82  * \brief Sends a packet to the bus
83  */
84 int UHCI_SendPacket(int ControllerID, enum eUSB_TransferType Type, void *Data, size_t Length)
85 {
86         //tUHCI_TD      *td = UHCI_AllocateTD();
87         return 0;
88 }
89
90 // === INTERNAL FUNCTIONS ===
91 /**
92  * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)
93  * \brief Initialises a UHCI host controller
94  * \param Host  Pointer - Host to initialise
95  */
96 int UHCI_Int_InitHost(tUHCI_Controller *Host)
97 {
98         ENTER("pHost", Host);
99         
100         outw( Host->IOBase + USBCMD, 4 );       // GRESET
101         // TODO: Wait for at least 10ms
102         outw( Host->IOBase + USBCMD, 0 );       // GRESET
103         
104         // Allocate Frame List
105         // - 1 Page, 32-bit address
106         // - 1 page = 1024  4 byte entries
107         Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList);
108         if( !Host->FrameList ) {
109                 Log_Warning("UHCI", "Unable to allocate frame list, aborting");
110                 LEAVE('i', -1);
111                 return -1;
112         }
113         LOG("Allocated frame list 0x%x (0x%x)", Host->FrameList, Host->PhysFrameList);
114         memsetd( Host->FrameList, 1, 1024 );    // Clear List (Disabling all entries)
115         
116         //! \todo Properly fill frame list
117         
118         // Set frame length to 1 ms
119         outb( Host->IOBase + SOFMOD, 64 );
120         
121         // Set Frame List Address
122         outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );
123         
124         // Set Frame Number
125         outw( Host->IOBase + FRNUM, 0 );
126         
127         // Enable Interrupts
128         //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 );
129         
130         LEAVE('i', 0);
131         return 0;
132 }

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