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