1 /* 2 * Copyright 2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 #ifndef EHCI_H 9 #define EHCI_H 10 11 #include "usb_private.h" 12 #include "ehci_hardware.h" 13 14 15 struct pci_info; 16 struct pci_module_info; 17 struct pci_x86_module_info; 18 19 class EHCIRootHub; 20 21 22 typedef struct transfer_data { 23 Transfer * transfer; 24 ehci_qh * queue_head; 25 ehci_qtd * data_descriptor; 26 bool incoming; 27 bool canceled; 28 transfer_data * link; 29 } transfer_data; 30 31 32 // This structure is used to create a list of 33 // descriptors per isochronous transfer 34 typedef struct isochronous_transfer_data { 35 Transfer * transfer; 36 // The next field is used to keep track 37 // of every isochronous descriptor as they are NOT 38 // linked to each other in a queue like in every other 39 // transfer type 40 ehci_itd ** descriptors; 41 uint16 last_to_process; 42 bool incoming; 43 bool is_active; 44 isochronous_transfer_data * link; 45 46 size_t buffer_size; 47 void * buffer_log; 48 addr_t buffer_phy; 49 } isochronous_transfer_data; 50 51 52 class EHCI : public BusManager { 53 public: 54 static status_t AddTo(Stack *stack); 55 56 EHCI(pci_info *info, Stack *stack); 57 ~EHCI(); 58 59 status_t Start(); 60 61 virtual status_t StartDebugTransfer(Transfer *transfer); 62 virtual status_t CheckDebugTransfer(Transfer *transfer); 63 void LinkAsyncDebugQueueHead(ehci_qh *queueHead); 64 void LinkPeriodicDebugQueueHead( 65 ehci_qh *queueHead, Pipe *pipe); 66 virtual void CancelDebugTransfer(Transfer *transfer); 67 void CleanupDebugTransfer(Transfer *transfer); 68 69 virtual status_t SubmitTransfer(Transfer *transfer); 70 status_t SubmitIsochronous(Transfer *transfer); 71 72 virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); 73 status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force); 74 75 virtual status_t NotifyPipeChange(Pipe *pipe, 76 usb_change change); 77 78 // Port operations for root hub 79 uint8 PortCount() { return fPortCount; } 80 status_t GetPortStatus(uint8 index, usb_port_status *status); 81 status_t SetPortFeature(uint8 index, uint16 feature); 82 status_t ClearPortFeature(uint8 index, uint16 feature); 83 84 status_t ResetPort(uint8 index); 85 status_t SuspendPort(uint8 index); 86 87 virtual const char * TypeName() const { return "ehci"; } 88 89 private: 90 // Controller resets 91 status_t ControllerReset(); 92 status_t LightReset(); 93 94 // Interrupt functions 95 static int32 InterruptHandler(void *data); 96 int32 Interrupt(); 97 static int32 InterruptPollThread(void *data); 98 99 // Transfer management 100 status_t AddPendingTransfer(Transfer *transfer, 101 ehci_qh *queueHead, 102 ehci_qtd *dataDescriptor, 103 bool directionIn); 104 status_t AddPendingIsochronousTransfer( 105 Transfer *transfer, 106 ehci_itd **isoRequest, uint32 lastIndex, 107 bool directionIn, addr_t bufferPhy, 108 void *bufferLog, size_t bufferSize); 109 status_t CancelAllPendingTransfers(); 110 111 112 static int32 FinishThread(void *data); 113 void FinishTransfers(); 114 static int32 CleanupThread(void *data); 115 void Cleanup(); 116 117 // Isochronous transfer functions 118 static int32 FinishIsochronousThread(void *data); 119 void FinishIsochronousTransfers(); 120 isochronous_transfer_data * FindIsochronousTransfer(ehci_itd *itd); 121 void LinkITDescriptors(ehci_itd *itd, 122 ehci_itd **last); 123 void LinkSITDescriptors(ehci_sitd *sitd, 124 ehci_sitd **last); 125 void UnlinkITDescriptors(ehci_itd *itd, 126 ehci_itd **last); 127 void UnlinkSITDescriptors(ehci_sitd *sitd, 128 ehci_sitd **last); 129 130 // Queue Head functions 131 ehci_qh * CreateQueueHead(); 132 status_t InitQueueHead(ehci_qh *queueHead, 133 Pipe *pipe); 134 void FreeQueueHead(ehci_qh *queueHead); 135 136 status_t LinkQueueHead(ehci_qh *queueHead); 137 status_t LinkInterruptQueueHead(ehci_qh *queueHead, 138 Pipe *pipe); 139 status_t UnlinkQueueHead(ehci_qh *queueHead, 140 ehci_qh **freeList); 141 142 // Queue functions 143 status_t FillQueueWithRequest(Transfer *transfer, 144 ehci_qh *queueHead, 145 ehci_qtd **dataDescriptor, 146 bool *directionIn, 147 bool prepareKernelAccess); 148 status_t FillQueueWithData(Transfer *transfer, 149 ehci_qh *queueHead, 150 ehci_qtd **dataDescriptor, 151 bool *directionIn, 152 bool prepareKernelAccess); 153 154 bool LockIsochronous(); 155 void UnlockIsochronous(); 156 157 // Descriptor functions 158 ehci_qtd * CreateDescriptor( 159 size_t bufferSizeToAllocate, 160 uint8 pid); 161 status_t CreateDescriptorChain(Pipe *pipe, 162 ehci_qtd **firstDescriptor, 163 ehci_qtd **lastDescriptor, 164 ehci_qtd *strayDescriptor, 165 size_t bufferSizeToAllocate, 166 uint8 pid); 167 ehci_itd* CreateItdDescriptor(); 168 ehci_sitd* CreateSitdDescriptor(); 169 170 void FreeDescriptor(ehci_qtd *descriptor); 171 void FreeDescriptorChain(ehci_qtd *topDescriptor); 172 void FreeDescriptor(ehci_itd *descriptor); 173 void FreeDescriptor(ehci_sitd *descriptor); 174 void FreeIsochronousData( 175 isochronous_transfer_data *data); 176 177 void LinkDescriptors(ehci_qtd *first, 178 ehci_qtd *last, ehci_qtd *alt); 179 180 size_t WriteDescriptorChain( 181 ehci_qtd *topDescriptor, 182 iovec *vector, size_t vectorCount); 183 size_t ReadDescriptorChain(ehci_qtd *topDescriptor, 184 iovec *vector, size_t vectorCount, 185 bool *nextDataToggle); 186 size_t ReadActualLength(ehci_qtd *topDescriptor, 187 bool *nextDataToggle); 188 size_t WriteIsochronousDescriptorChain( 189 isochronous_transfer_data *transfer, 190 uint32 packetCount, 191 iovec *vector); 192 size_t ReadIsochronousDescriptorChain( 193 isochronous_transfer_data *transfer); 194 195 // Operational register functions 196 inline void WriteOpReg(uint32 reg, uint32 value); 197 inline uint32 ReadOpReg(uint32 reg); 198 199 // Capability register functions 200 inline uint8 ReadCapReg8(uint32 reg); 201 inline uint16 ReadCapReg16(uint32 reg); 202 inline uint32 ReadCapReg32(uint32 reg); 203 204 static pci_module_info * sPCIModule; 205 static pci_x86_module_info * sPCIx86Module; 206 207 uint8 * fCapabilityRegisters; 208 uint8 * fOperationalRegisters; 209 area_id fRegisterArea; 210 pci_info * fPCIInfo; 211 Stack * fStack; 212 uint32 fEnabledInterrupts; 213 uint32 fThreshold; 214 215 // Periodic transfer framelist and interrupt entries 216 area_id fPeriodicFrameListArea; 217 uint32 * fPeriodicFrameList; 218 interrupt_entry * fInterruptEntries; 219 ehci_itd ** fItdEntries; 220 ehci_sitd ** fSitdEntries; 221 222 // Async transfer queue management 223 ehci_qh * fAsyncQueueHead; 224 sem_id fAsyncAdvanceSem; 225 226 // Maintain a linked list of transfers 227 transfer_data * fFirstTransfer; 228 transfer_data * fLastTransfer; 229 sem_id fFinishTransfersSem; 230 thread_id fFinishThread; 231 Pipe * fProcessingPipe; 232 233 ehci_qh * fFreeListHead; 234 sem_id fCleanupSem; 235 thread_id fCleanupThread; 236 bool fStopThreads; 237 int32 fNextStartingFrame; 238 239 // fFrameBandwidth[n] holds the available bandwidth 240 // of the nth frame in microseconds 241 uint16 * fFrameBandwidth; 242 243 // Maintain a linked list of isochronous transfers 244 isochronous_transfer_data * fFirstIsochronousTransfer; 245 isochronous_transfer_data * fLastIsochronousTransfer; 246 sem_id fFinishIsochronousTransfersSem; 247 thread_id fFinishIsochronousThread; 248 mutex fIsochronousLock; 249 250 // Root Hub 251 EHCIRootHub * fRootHub; 252 uint8 fRootHubAddress; 253 254 // Port management 255 uint8 fPortCount; 256 uint16 fPortResetChange; 257 uint16 fPortSuspendChange; 258 259 // Interrupt polling 260 thread_id fInterruptPollThread; 261 uint8 fIRQ; 262 bool fUseMSI; 263 }; 264 265 266 class EHCIRootHub : public Hub { 267 public: 268 EHCIRootHub(Object *rootObject, 269 int8 deviceAddress); 270 271 static status_t ProcessTransfer(EHCI *ehci, 272 Transfer *transfer); 273 }; 274 275 276 #endif // !EHCI_H 277