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