* Copyright 2004-2011, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* Niels S. Reedijk
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
*/
#ifndef UHCI_H
#define UHCI_H
#include "usb_private.h"
#include "uhci_hardware.h"
#include <lock.h>
#define UHCI_INTERRUPT_QUEUE 0
#define UHCI_LOW_SPEED_CONTROL_QUEUE 1
#define UHCI_FULL_SPEED_CONTROL_QUEUE 2
#define UHCI_BULK_QUEUE 3
#define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4
#define UHCI_DEBUG_QUEUE 4
struct pci_info;
struct pci_device_module_info;
struct pci_device;
class UHCIRootHub;
class Queue {
public:
Queue(Stack *stack);
~Queue();
bool Lock();
void Unlock();
status_t InitCheck();
status_t LinkTo(Queue *other);
status_t TerminateByStrayDescriptor();
status_t AppendTransfer(uhci_qh *transfer,
bool lock = true);
status_t RemoveTransfer(uhci_qh *transfer,
bool lock = true);
uint32 PhysicalAddress();
void PrintToStream();
usb_id USBID() { return 0; };
const char * TypeName() { return "uhci"; };
private:
status_t fStatus;
Stack * fStack;
uhci_qh * fQueueHead;
uhci_td * fStrayDescriptor;
uhci_qh * fQueueTop;
mutex fLock;
};
typedef struct transfer_data {
Transfer * transfer;
Queue * queue;
uhci_qh * transfer_queue;
uhci_td * first_descriptor;
uhci_td * data_descriptor;
bool incoming;
bool canceled;
uint16 free_after_frame;
transfer_data * link;
} transfer_data;
typedef struct isochronous_transfer_data {
Transfer * transfer;
uhci_td ** descriptors;
uint16 last_to_process;
bool incoming;
bool is_active;
isochronous_transfer_data * link;
} isochronous_transfer_data;
class UHCI : public BusManager {
public:
UHCI(pci_info *info, pci_device_module_info* pci,
pci_device* device, Stack *stack, device_node* node);
~UHCI();
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
virtual status_t StartDebugTransfer(Transfer *transfer);
virtual status_t CheckDebugTransfer(Transfer *transfer);
virtual void CancelDebugTransfer(Transfer *transfer);
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
status_t SubmitRequest(Transfer *transfer);
status_t SubmitIsochronous(Transfer *transfer);
status_t GetPortStatus(uint8 index, usb_port_status *status);
status_t SetPortFeature(uint8 index, uint16 feature);
status_t ClearPortFeature(uint8 index, uint16 feature);
status_t ResetPort(uint8 index);
virtual const char * TypeName() const { return "uhci"; };
private:
void GlobalReset();
status_t ControllerReset();
static int32 InterruptHandler(void *data);
int32 Interrupt();
status_t AddPendingTransfer(Transfer *transfer,
Queue *queue,
uhci_qh *transferQueue,
uhci_td *firstDescriptor,
uhci_td *dataDescriptor,
bool directionIn);
status_t AddPendingIsochronousTransfer(
Transfer *transfer,
uhci_td **isoRequest,
bool directionIn);
static int32 FinishThread(void *data);
void FinishTransfers();
void AddToFreeList(transfer_data *transfer);
static int32 CleanupThread(void *data);
void Cleanup();
status_t CreateFilledTransfer(Transfer *transfer,
uhci_td **_firstDescriptor,
uhci_qh **_transferQueue);
static int32 FinishIsochronousThread(void *data);
void FinishIsochronousTransfers();
isochronous_transfer_data * FindIsochronousTransfer(uhci_td *descriptor);
status_t LinkIsochronousDescriptor(
uhci_td *descriptor,
uint16 frame);
uhci_td * UnlinkIsochronousDescriptor(uint16 frame);
uhci_qh * CreateTransferQueue(uhci_td *descriptor);
void FreeTransferQueue(uhci_qh *queueHead);
bool LockIsochronous();
void UnlockIsochronous();
uhci_td * CreateDescriptor(Pipe *pipe,
uint8 direction,
size_t bufferSizeToAllocate);
status_t CreateDescriptorChain(Pipe *pipe,
uhci_td **firstDescriptor,
uhci_td **lastDescriptor,
uint8 direction,
size_t bufferSizeToAllocate);
void FreeDescriptor(uhci_td *descriptor);
void FreeDescriptorChain(uhci_td *topDescriptor);
void LinkDescriptors(uhci_td *first,
uhci_td *second);
size_t WriteDescriptorChain(uhci_td *topDescriptor,
generic_io_vec *vector, size_t vectorCount, bool physical);
size_t ReadDescriptorChain(uhci_td *topDescriptor,
generic_io_vec *vector, size_t vectorCount, bool physical,
uint8 *lastDataToggle);
size_t ReadActualLength(uhci_td *topDescriptor,
uint8 *lastDataToggle);
void WriteIsochronousDescriptorChain(
uhci_td **isoRequest,
uint32 packetCount,
generic_io_vec *vector);
void ReadIsochronousDescriptorChain(
isochronous_transfer_data *transfer,
generic_io_vec *vector);
inline void WriteReg8(uint32 reg, uint8 value);
inline void WriteReg16(uint32 reg, uint16 value);
inline void WriteReg32(uint32 reg, uint32 value);
inline uint8 ReadReg8(uint32 reg);
inline uint16 ReadReg16(uint32 reg);
inline uint32 ReadReg32(uint32 reg);
uint32 fRegisterBase;
pci_info * fPCIInfo;
pci_device_module_info* fPci;
pci_device* fDevice;
Stack * fStack;
uint32 fEnabledInterrupts;
area_id fFrameArea;
uint32 * fFrameList;
uint16 * fFrameBandwidth;
uhci_td ** fFirstIsochronousDescriptor;
uhci_td ** fLastIsochronousDescriptor;
int32 fQueueCount;
Queue ** fQueues;
transfer_data * fFirstTransfer;
transfer_data * fLastTransfer;
sem_id fFinishTransfersSem;
thread_id fFinishThread;
bool fStopThreads;
Pipe * fProcessingPipe;
transfer_data * fFreeList;
thread_id fCleanupThread;
sem_id fCleanupSem;
int32 fCleanupCount;
isochronous_transfer_data * fFirstIsochronousTransfer;
isochronous_transfer_data * fLastIsochronousTransfer;
sem_id fFinishIsochronousTransfersSem;
thread_id fFinishIsochronousThread;
mutex fIsochronousLock;
UHCIRootHub * fRootHub;
uint8 fRootHubAddress;
uint8 fPortResetChange;
uint32 fIRQ;
bool fUseMSI;
};
class UHCIRootHub : public Hub {
public:
UHCIRootHub(Object *rootObject,
int8 deviceAddress);
static status_t ProcessTransfer(UHCI *uhci,
Transfer *transfer);
};
#endif