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