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