1 /* 2 * Copyright 2004-2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Niels S. Reedijk 8 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 9 */ 10 #ifndef UHCI_H 11 #define UHCI_H 12 13 #include "usb_private.h" 14 #include "uhci_hardware.h" 15 #include <lock.h> 16 17 #define UHCI_INTERRUPT_QUEUE 0 18 #define UHCI_LOW_SPEED_CONTROL_QUEUE 1 19 #define UHCI_FULL_SPEED_CONTROL_QUEUE 2 20 #define UHCI_BULK_QUEUE 3 21 #define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4 22 #define UHCI_DEBUG_QUEUE 4 23 24 struct pci_info; 25 struct pci_device_module_info; 26 struct pci_device; 27 class UHCIRootHub; 28 29 30 class Queue { 31 public: 32 Queue(Stack *stack); 33 ~Queue(); 34 35 bool Lock(); 36 void Unlock(); 37 38 status_t InitCheck(); 39 40 status_t LinkTo(Queue *other); 41 status_t TerminateByStrayDescriptor(); 42 43 status_t AppendTransfer(uhci_qh *transfer, 44 bool lock = true); 45 status_t RemoveTransfer(uhci_qh *transfer, 46 bool lock = true); 47 48 uint32 PhysicalAddress(); 49 50 void PrintToStream(); 51 52 usb_id USBID() { return 0; }; 53 const char * TypeName() { return "uhci"; }; 54 55 private: 56 status_t fStatus; 57 Stack * fStack; 58 uhci_qh * fQueueHead; 59 uhci_td * fStrayDescriptor; 60 uhci_qh * fQueueTop; 61 mutex fLock; 62 }; 63 64 65 typedef struct transfer_data { 66 Transfer * transfer; 67 Queue * queue; 68 uhci_qh * transfer_queue; 69 uhci_td * first_descriptor; 70 uhci_td * data_descriptor; 71 bool incoming; 72 bool canceled; 73 uint16 free_after_frame; 74 transfer_data * link; 75 } transfer_data; 76 77 78 // This structure is used to create a list of 79 // descriptors per isochronous transfer 80 typedef struct isochronous_transfer_data { 81 Transfer * transfer; 82 // The next field is used to keep track 83 // of every isochronous descriptor as they are NOT 84 // linked to each other in a queue like in every other 85 // transfer type 86 uhci_td ** descriptors; 87 uint16 last_to_process; 88 bool incoming; 89 bool is_active; 90 isochronous_transfer_data * link; 91 } isochronous_transfer_data; 92 93 94 class UHCI : public BusManager { 95 public: 96 UHCI(pci_info *info, pci_device_module_info* pci, 97 pci_device* device, Stack *stack, device_node* node); 98 ~UHCI(); 99 100 status_t Start(); 101 virtual status_t SubmitTransfer(Transfer *transfer); 102 103 virtual status_t StartDebugTransfer(Transfer *transfer); 104 virtual status_t CheckDebugTransfer(Transfer *transfer); 105 virtual void CancelDebugTransfer(Transfer *transfer); 106 107 virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); 108 status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force); 109 status_t SubmitRequest(Transfer *transfer); 110 status_t SubmitIsochronous(Transfer *transfer); 111 112 // Port operations 113 status_t GetPortStatus(uint8 index, usb_port_status *status); 114 status_t SetPortFeature(uint8 index, uint16 feature); 115 status_t ClearPortFeature(uint8 index, uint16 feature); 116 117 status_t ResetPort(uint8 index); 118 119 virtual const char * TypeName() const { return "uhci"; }; 120 121 private: 122 // Controller resets 123 void GlobalReset(); 124 status_t ControllerReset(); 125 126 // Interrupt functions 127 static int32 InterruptHandler(void *data); 128 int32 Interrupt(); 129 130 // Transfer functions 131 status_t AddPendingTransfer(Transfer *transfer, 132 Queue *queue, 133 uhci_qh *transferQueue, 134 uhci_td *firstDescriptor, 135 uhci_td *dataDescriptor, 136 bool directionIn); 137 status_t AddPendingIsochronousTransfer( 138 Transfer *transfer, 139 uhci_td **isoRequest, 140 bool directionIn); 141 142 static int32 FinishThread(void *data); 143 void FinishTransfers(); 144 145 void AddToFreeList(transfer_data *transfer); 146 static int32 CleanupThread(void *data); 147 void Cleanup(); 148 149 status_t CreateFilledTransfer(Transfer *transfer, 150 uhci_td **_firstDescriptor, 151 uhci_qh **_transferQueue); 152 153 // Isochronous transfer functions 154 static int32 FinishIsochronousThread(void *data); 155 void FinishIsochronousTransfers(); 156 isochronous_transfer_data * FindIsochronousTransfer(uhci_td *descriptor); 157 158 status_t LinkIsochronousDescriptor( 159 uhci_td *descriptor, 160 uint16 frame); 161 uhci_td * UnlinkIsochronousDescriptor(uint16 frame); 162 163 // Transfer queue functions 164 uhci_qh * CreateTransferQueue(uhci_td *descriptor); 165 void FreeTransferQueue(uhci_qh *queueHead); 166 167 bool LockIsochronous(); 168 void UnlockIsochronous(); 169 170 // Descriptor functions 171 uhci_td * CreateDescriptor(Pipe *pipe, 172 uint8 direction, 173 size_t bufferSizeToAllocate); 174 status_t CreateDescriptorChain(Pipe *pipe, 175 uhci_td **firstDescriptor, 176 uhci_td **lastDescriptor, 177 uint8 direction, 178 size_t bufferSizeToAllocate); 179 180 void FreeDescriptor(uhci_td *descriptor); 181 void FreeDescriptorChain(uhci_td *topDescriptor); 182 183 void LinkDescriptors(uhci_td *first, 184 uhci_td *second); 185 186 size_t WriteDescriptorChain(uhci_td *topDescriptor, 187 iovec *vector, size_t vectorCount); 188 size_t ReadDescriptorChain(uhci_td *topDescriptor, 189 iovec *vector, size_t vectorCount, 190 uint8 *lastDataToggle); 191 size_t ReadActualLength(uhci_td *topDescriptor, 192 uint8 *lastDataToggle); 193 void WriteIsochronousDescriptorChain( 194 uhci_td **isoRequest, 195 uint32 packetCount, 196 iovec *vector); 197 void ReadIsochronousDescriptorChain( 198 isochronous_transfer_data *transfer, 199 iovec *vector); 200 201 // Register functions 202 inline void WriteReg8(uint32 reg, uint8 value); 203 inline void WriteReg16(uint32 reg, uint16 value); 204 inline void WriteReg32(uint32 reg, uint32 value); 205 inline uint8 ReadReg8(uint32 reg); 206 inline uint16 ReadReg16(uint32 reg); 207 inline uint32 ReadReg32(uint32 reg); 208 209 uint32 fRegisterBase; 210 pci_info * fPCIInfo; 211 pci_device_module_info* fPci; 212 pci_device* fDevice; 213 Stack * fStack; 214 uint32 fEnabledInterrupts; 215 216 // Frame list memory 217 area_id fFrameArea; 218 uint32 * fFrameList; 219 220 // fFrameBandwidth[n] holds the available bandwidth 221 // of the nth frame in microseconds 222 uint16 * fFrameBandwidth; 223 224 // fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n] 225 // keeps track of the first and last isochronous transfer descriptor 226 // in the nth frame 227 uhci_td ** fFirstIsochronousDescriptor; 228 uhci_td ** fLastIsochronousDescriptor; 229 230 // Queues 231 int32 fQueueCount; 232 Queue ** fQueues; 233 234 // Maintain a linked list of transfers 235 transfer_data * fFirstTransfer; 236 transfer_data * fLastTransfer; 237 sem_id fFinishTransfersSem; 238 thread_id fFinishThread; 239 bool fStopThreads; 240 Pipe * fProcessingPipe; 241 242 transfer_data * fFreeList; 243 thread_id fCleanupThread; 244 sem_id fCleanupSem; 245 int32 fCleanupCount; 246 247 // Maintain a linked list of isochronous transfers 248 isochronous_transfer_data * fFirstIsochronousTransfer; 249 isochronous_transfer_data * fLastIsochronousTransfer; 250 sem_id fFinishIsochronousTransfersSem; 251 thread_id fFinishIsochronousThread; 252 mutex fIsochronousLock; 253 254 // Root hub 255 UHCIRootHub * fRootHub; 256 uint8 fRootHubAddress; 257 uint8 fPortResetChange; 258 259 uint8 fIRQ; 260 bool fUseMSI; 261 }; 262 263 264 class UHCIRootHub : public Hub { 265 public: 266 UHCIRootHub(Object *rootObject, 267 int8 deviceAddress); 268 269 static status_t ProcessTransfer(UHCI *uhci, 270 Transfer *transfer); 271 }; 272 273 274 #endif 275