}
/**
- * \brief Sends a packet to the bus
+ * \brief Send a transaction to the USB bus
+ * \param ControllerID Controller
+ * \param Fcn Function Address
+ * \param Endpt Endpoint
*/
-int UHCI_SendPacket(int ControllerID, enum eUSB_TransferType Type, void *Data, size_t Length)
+int UHCI_int_SendTransaction(int ControllerID, int Fcn, int Endpt, int DataTgl, Uint8 Type, void *Data, size_t Length)
{
- //tUHCI_TD *td = UHCI_AllocateTD();
+ tUHCI_Controller *cont = &gUHCI_Controllers[ControllerID];
+ tUHCI_TD *td;
+
+ if( Length > 0x400 ) return -1; // Controller allows up to 0x500, but USB doesn't
+
+ td = UHCI_Int_AllocateTD(cont);
+
+ td->Link = 0;
+ td->Control = (Length - 1) & 0x7FF;
+ td->Token = ((Length - 1) & 0x7FF) << 21;
+ td->Token |= (DataTgl & 1) << 19;
+ td->Token |= (Endpt & 0xF) << 15;
+ td->Token |= (Fcn & 0xFF) << 8;
+ td->Token |= Type;
+
+ if( ((tVAddr)Data & PAGE_SIZE) + Length > PAGE_SIZE ) {
+ Log_Warning("UHCI", "TODO: Support non single page transfers");
+// td->BufferPointer =
+ return 1;
+ }
+ else {
+ td->BufferPointer = MM_GetPhysAddr(Data);
+ }
+
+ UHCI_int_AppendTD(td);
+
+ // Wait until done, then return
return 0;
}
+int UHCI_DataIN(int ControllerID, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length)
+{
+ return UHCI_int_SendPacket(ControllerID, Fcn, Endpt, DataTgl, 0x69, Data, Length);
+}
+
+int UHCI_DataOUT(int ControllerID, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length)
+{
+ return UHCI_int_SendPacket(ControllerID, Fcn, Endpt, DataTgl, 0xE1, Data, Length);
+}
+
+int UHCI_SendSetup(int ControllerID, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length)
+{
+ return UHCI_int_SendPacket(ControllerID, Fcn, Endpt, DataTgl, 0x2D, Data, Length);
+}
+
// === INTERNAL FUNCTIONS ===
/**
* \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)
* 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
// === CODE ===
-void USB_MakeToken(void *Buf, int PID, int Addr, int EndP)
+int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
{
- Uint8 *tok = Buf;
- int crc = 0;
+ 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
- tok[0] = PID & 0xFF;
- tok[1] = (Addr & 0x7F) | ((EndP&1)<<7);
- tok[2] = ((EndP >> 1) & 0x7) | crc;
+ Host->SendSETUP(Host, 0, 0, 0, data, 8);
}
-
-#if 0
-void USB_SendData(int Controller, int Dev, int Endpoint, void *Data, int Length)
-{
- Uint8 buf[Length+3+2/*?*/];
-
- USB_MakeToken(buf, PID_DATA0, Dev, Endpoint);
-
- switch(Controller & 0xF00)
- {
- case 1: // UHCI
- UHCI_SendPacket(Controller & 0xFF);
- break;
- }
-}
-#endif
typedef struct sUSBHost tUSBHost;
typedef struct sUSBDevice tUSBDevice;
-// === CONSTANTS ===
-enum eUSB_TransferType
-{
- TRANSTYPE_ISYNCH, // Constant, Low latency, low bandwidth, no transmission retries
- TRANSTYPE_INTERRUPT, // -- NEVER SENT -- Spontanious, Low latency, low bandwith
- TRANSTYPE_CONTROL, // Device control
- TRANSTYPE_BULK // High latency, high bandwidth
-};
-
-enum eUSB_PIDs
-{
- /**
- * \name Token
- * \{
- */
- PID_OUT = 0xE1,
- PID_IN = 0x69,
- PID_SOF = 0xA5,
- PID_SETUP = 0x2D,
- /**
- * \}
- */
-
- /**
- * \name Data
- * \{
- */
- PID_DATA0 = 0xC3,
- PID_DATA1 = 0x4B,
- PID_DATA2 = 0x87, // USB2 only
- PID_MDATA = 0x0F, // USB2 only
- /**
- * \}
- */
-
- /**
- * \name Handshake
- * \{
- */
- PID_ACK = 0xD2,
- PID_NAK = 0x5A,
- PID_STALL = 0x1E,
- PID_NYET = 0x96,
- /**
- * \}
- */
-
- /**
- * \name Special
- * \{
- */
- PID_PRE = 0x3C, PID_ERR = 0x3C,
- PID_SPLIT = 0x78,
- PID_PING = 0xB4,
- PID_RESVD = 0xF0,
- /**
- * \}
- */
-};
-
-// === FUNCTIONS ===
-/**
- * \note 00101 - X^5+X^2+1
- */
-extern Uint8 USB_TokenCRC(void *Data, int len);
-/**
- * \note X^16 + X15 + X^2 + 1
- */
-extern Uint16 USB_DataCRC(void *Data, int len);
-
// === STRUCTURES ===
/**
* \brief Defines a USB Host Controller
*/
struct sUSBHost
{
- Uint16 IOBase;
-
- int (*SendPacket)(int ID, int Length, void *Data);
+ int (*SendIN)(void *Ptr, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length);
+ int (*SendOUT)(void *Ptr, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length);
+ int (*SendSETUP)(void *Ptr, int Fcn, int Endpt, int DataTgl, void *Data, size_t Length);
};
/**
struct sUSBDevice
{
tUSBHost *Host;
+
+ int Address;
+
int MaxControl;
int MaxBulk;
int MaxISync;