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_device_module_info; 17 struct pci_device; 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 EHCI(pci_info *info, pci_device_module_info* pci, 55 pci_device* device, Stack *stack, device_node *node); 56 ~EHCI(); 57 58 status_t Start(); 59 60 virtual status_t StartDebugTransfer(Transfer *transfer); 61 virtual status_t CheckDebugTransfer(Transfer *transfer); 62 void LinkAsyncDebugQueueHead(ehci_qh *queueHead); 63 void LinkPeriodicDebugQueueHead( 64 ehci_qh *queueHead, Pipe *pipe); 65 virtual void CancelDebugTransfer(Transfer *transfer); 66 void CleanupDebugTransfer(Transfer *transfer); 67 68 virtual status_t SubmitTransfer(Transfer *transfer); 69 status_t SubmitIsochronous(Transfer *transfer); 70 71 virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); 72 status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force); 73 74 virtual status_t NotifyPipeChange(Pipe *pipe, 75 usb_change change); 76 77 // Port operations for root hub 78 uint8 PortCount() { return fPortCount; } 79 status_t GetPortStatus(uint8 index, usb_port_status *status); 80 status_t SetPortFeature(uint8 index, uint16 feature); 81 status_t ClearPortFeature(uint8 index, uint16 feature); 82 83 status_t ResetPort(uint8 index); 84 status_t SuspendPort(uint8 index); 85 86 virtual const char * TypeName() const { return "ehci"; } 87 88 private: 89 // Controller resets 90 status_t ControllerReset(); 91 status_t LightReset(); 92 93 // Interrupt functions 94 static int32 InterruptHandler(void *data); 95 int32 Interrupt(); 96 static int32 InterruptPollThread(void *data); 97 98 // Transfer management 99 status_t AddPendingTransfer(Transfer *transfer, 100 ehci_qh *queueHead, 101 ehci_qtd *dataDescriptor, 102 bool directionIn); 103 status_t AddPendingIsochronousTransfer( 104 Transfer *transfer, 105 ehci_itd **isoRequest, uint32 lastIndex, 106 bool directionIn, addr_t bufferPhy, 107 void *bufferLog, size_t bufferSize); 108 status_t CancelAllPendingTransfers(); 109 110 111 static int32 FinishThread(void *data); 112 void FinishTransfers(); 113 static int32 CleanupThread(void *data); 114 void Cleanup(); 115 116 // Isochronous transfer functions 117 static int32 FinishIsochronousThread(void *data); 118 void FinishIsochronousTransfers(); 119 isochronous_transfer_data * FindIsochronousTransfer(ehci_itd *itd); 120 void LinkITDescriptors(ehci_itd *itd, 121 ehci_itd **last); 122 void LinkSITDescriptors(ehci_sitd *sitd, 123 ehci_sitd **last); 124 void UnlinkITDescriptors(ehci_itd *itd, 125 ehci_itd **last); 126 void UnlinkSITDescriptors(ehci_sitd *sitd, 127 ehci_sitd **last); 128 129 // Queue Head functions 130 ehci_qh * CreateQueueHead(); 131 status_t InitQueueHead(ehci_qh *queueHead, 132 Pipe *pipe); 133 void FreeQueueHead(ehci_qh *queueHead); 134 135 status_t LinkQueueHead(ehci_qh *queueHead); 136 status_t LinkInterruptQueueHead(ehci_qh *queueHead, 137 Pipe *pipe); 138 status_t UnlinkQueueHead(ehci_qh *queueHead, 139 ehci_qh **freeList); 140 141 // Queue functions 142 status_t FillQueueWithRequest(Transfer *transfer, 143 ehci_qh *queueHead, 144 ehci_qtd **dataDescriptor, 145 bool *directionIn, 146 bool prepareKernelAccess); 147 status_t FillQueueWithData(Transfer *transfer, 148 ehci_qh *queueHead, 149 ehci_qtd **dataDescriptor, 150 bool *directionIn, 151 bool prepareKernelAccess); 152 153 bool LockIsochronous(); 154 void UnlockIsochronous(); 155 156 // Descriptor functions 157 ehci_qtd * CreateDescriptor( 158 size_t bufferSizeToAllocate, 159 uint8 pid); 160 status_t CreateDescriptorChain(Pipe *pipe, 161 ehci_qtd **firstDescriptor, 162 ehci_qtd **lastDescriptor, 163 ehci_qtd *strayDescriptor, 164 size_t bufferSizeToAllocate, 165 uint8 pid); 166 ehci_itd* CreateItdDescriptor(); 167 ehci_sitd* CreateSitdDescriptor(); 168 169 void FreeDescriptor(ehci_qtd *descriptor); 170 void FreeDescriptorChain(ehci_qtd *topDescriptor); 171 void FreeDescriptor(ehci_itd *descriptor); 172 void FreeDescriptor(ehci_sitd *descriptor); 173 void FreeIsochronousData( 174 isochronous_transfer_data *data); 175 176 void LinkDescriptors(ehci_qtd *first, 177 ehci_qtd *last, ehci_qtd *alt); 178 179 size_t WriteDescriptorChain( 180 ehci_qtd *topDescriptor, 181 generic_io_vec *vector, size_t vectorCount, 182 bool physical); 183 size_t ReadDescriptorChain(ehci_qtd *topDescriptor, 184 generic_io_vec *vector, size_t vectorCount, 185 bool physical, bool *nextDataToggle); 186 size_t ReadActualLength(ehci_qtd *topDescriptor, 187 bool *nextDataToggle); 188 size_t WriteIsochronousDescriptorChain( 189 isochronous_transfer_data *transfer); 190 size_t ReadIsochronousDescriptorChain( 191 isochronous_transfer_data *transfer); 192 193 // Operational register functions 194 inline void WriteOpReg(uint32 reg, uint32 value); 195 inline uint32 ReadOpReg(uint32 reg); 196 197 // Capability register functions 198 inline uint8 ReadCapReg8(uint32 reg); 199 inline uint16 ReadCapReg16(uint32 reg); 200 inline uint32 ReadCapReg32(uint32 reg); 201 202 uint8 * fCapabilityRegisters; 203 uint8 * fOperationalRegisters; 204 area_id fRegisterArea; 205 pci_info * fPCIInfo; 206 pci_device_module_info* fPci; 207 pci_device* fDevice; 208 Stack * fStack; 209 uint32 fEnabledInterrupts; 210 uint32 fThreshold; 211 212 // Periodic transfer framelist and interrupt entries 213 area_id fPeriodicFrameListArea; 214 uint32 * fPeriodicFrameList; 215 interrupt_entry * fInterruptEntries; 216 ehci_itd ** fItdEntries; 217 ehci_sitd ** fSitdEntries; 218 219 // Async transfer queue management 220 ehci_qh * fAsyncQueueHead; 221 sem_id fAsyncAdvanceSem; 222 223 // Maintain a linked list of transfers 224 transfer_data * fFirstTransfer; 225 transfer_data * fLastTransfer; 226 sem_id fFinishTransfersSem; 227 thread_id fFinishThread; 228 Pipe * fProcessingPipe; 229 230 ehci_qh * fFreeListHead; 231 sem_id fCleanupSem; 232 thread_id fCleanupThread; 233 bool fStopThreads; 234 int32 fNextStartingFrame; 235 236 // fFrameBandwidth[n] holds the available bandwidth 237 // of the nth frame in microseconds 238 uint16 * fFrameBandwidth; 239 240 // Maintain a linked list of isochronous transfers 241 isochronous_transfer_data * fFirstIsochronousTransfer; 242 isochronous_transfer_data * fLastIsochronousTransfer; 243 sem_id fFinishIsochronousTransfersSem; 244 thread_id fFinishIsochronousThread; 245 mutex fIsochronousLock; 246 247 // Root Hub 248 EHCIRootHub * fRootHub; 249 uint8 fRootHubAddress; 250 251 // Port management 252 uint8 fPortCount; 253 uint16 fPortResetChange; 254 uint16 fPortSuspendChange; 255 256 // Interrupt polling 257 thread_id fInterruptPollThread; 258 uint8 fIRQ; 259 bool fUseMSI; 260 }; 261 262 263 class EHCIRootHub : public Hub { 264 public: 265 EHCIRootHub(Object *rootObject, 266 int8 deviceAddress); 267 268 static status_t ProcessTransfer(EHCI *ehci, 269 Transfer *transfer); 270 }; 271 272 273 #endif // !EHCI_H 274