Files
haiku-beta6/src/add-ons/kernel/busses/usb/uhci.h
T
2012-08-06 12:29:12 +01:00

273 lines
7.4 KiB
C++

/*
* Copyright 2004-2011, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
* Niels S. Reedijk
* Salvatore Benedetto <[email protected]>
*/
#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_module_info;
class UHCIRootHub;
class DebugTransfer;
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;
// This structure is used to create a list of
// descriptors per isochronous transfer
typedef struct isochronous_transfer_data {
Transfer * transfer;
// The next field is used to keep track
// of every isochronous descriptor as they are NOT
// linked to each other in a queue like in every other
// transfer type
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, Stack *stack);
~UHCI();
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
status_t StartDebugTransfer(DebugTransfer *transfer);
status_t CheckDebugTransfer(DebugTransfer *transfer,
bool &_stillPending);
void CancelDebugTransfer(
DebugTransfer *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);
static status_t AddTo(Stack *stack);
// Port operations
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:
// Controller resets
void GlobalReset();
status_t ControllerReset();
// Interrupt functions
static int32 InterruptHandler(void *data);
int32 Interrupt();
// Transfer functions
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);
// Isochronous transfer functions
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);
// Transfer queue functions
uhci_qh * CreateTransferQueue(uhci_td *descriptor);
void FreeTransferQueue(uhci_qh *queueHead);
bool LockIsochronous();
void UnlockIsochronous();
// Descriptor functions
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,
iovec *vector, size_t vectorCount);
size_t ReadDescriptorChain(uhci_td *topDescriptor,
iovec *vector, size_t vectorCount,
uint8 *lastDataToggle);
size_t ReadActualLength(uhci_td *topDescriptor,
uint8 *lastDataToggle);
void WriteIsochronousDescriptorChain(
uhci_td **isoRequest,
uint32 packetCount,
iovec *vector);
void ReadIsochronousDescriptorChain(
isochronous_transfer_data *transfer,
iovec *vector);
// Register functions
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);
static pci_module_info * sPCIModule;
uint32 fRegisterBase;
pci_info * fPCIInfo;
Stack * fStack;
uint32 fEnabledInterrupts;
// Frame list memory
area_id fFrameArea;
uint32 * fFrameList;
// fFrameBandwidth[n] holds the available bandwidth
// of the nth frame in microseconds
uint16 * fFrameBandwidth;
// fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n]
// keeps track of the first and last isochronous transfer descriptor
// in the nth frame
uhci_td ** fFirstIsochronousDescriptor;
uhci_td ** fLastIsochronousDescriptor;
// Queues
int32 fQueueCount;
Queue ** fQueues;
// Maintain a linked list of transfers
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;
// Maintain a linked list of isochronous transfers
isochronous_transfer_data * fFirstIsochronousTransfer;
isochronous_transfer_data * fLastIsochronousTransfer;
sem_id fFinishIsochronousTransfersSem;
thread_id fFinishIsochronousThread;
mutex fIsochronousLock;
// Root hub
UHCIRootHub * fRootHub;
uint8 fRootHubAddress;
uint8 fPortResetChange;
};
class UHCIRootHub : public Hub {
public:
UHCIRootHub(Object *rootObject,
int8 deviceAddress);
static status_t ProcessTransfer(UHCI *uhci,
Transfer *transfer);
};
#endif