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 11 #ifndef UHCI_H 12 #define UHCI_H 13 14 #include "usb_p.h" 15 #include "uhci_hardware.h" 16 #include <lock.h> 17 18 #define UHCI_INTERRUPT_QUEUE 0 19 #define UHCI_LOW_SPEED_CONTROL_QUEUE 1 20 #define UHCI_FULL_SPEED_CONTROL_QUEUE 2 21 #define UHCI_BULK_QUEUE 3 22 #define UHCI_BANDWIDTH_RECLAMATION_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 status_t RemoveTransfer(uhci_qh *transfer); 44 45 addr_t PhysicalAddress(); 46 47 void PrintToStream(); 48 49 private: 50 status_t fStatus; 51 Stack *fStack; 52 uhci_qh *fQueueHead; 53 uhci_td *fStrayDescriptor; 54 uhci_qh *fQueueTop; 55 benaphore fLock; 56 }; 57 58 59 typedef struct transfer_data_s { 60 Transfer *transfer; 61 Queue *queue; 62 uhci_qh *transfer_queue; 63 uhci_td *first_descriptor; 64 uhci_td *data_descriptor; 65 bool incoming; 66 bool canceled; 67 transfer_data_s *link; 68 } transfer_data; 69 70 71 // This structure is used to create a list of 72 // descriptors per isochronous transfer 73 typedef struct isochronous_transfer_data_s { 74 Transfer *transfer; 75 // The next field is used to keep track 76 // of every isochronous descriptor as they are NOT 77 // linked to each other in a queue like in every other 78 // transfer type 79 uhci_td **descriptors; 80 uint16 last_to_process; 81 bool incoming; 82 bool is_active; 83 isochronous_transfer_data_s *link; 84 } isochronous_transfer_data; 85 86 87 class UHCI : public BusManager { 88 public: 89 UHCI(pci_info *info, Stack *stack); 90 ~UHCI(); 91 92 status_t Start(); 93 virtual status_t SubmitTransfer(Transfer *transfer); 94 virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); 95 status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force); 96 status_t SubmitRequest(Transfer *transfer); 97 status_t SubmitIsochronous(Transfer *transfer); 98 99 static status_t AddTo(Stack *stack); 100 101 // Port operations 102 status_t GetPortStatus(uint8 index, usb_port_status *status); 103 status_t SetPortFeature(uint8 index, uint16 feature); 104 status_t ClearPortFeature(uint8 index, uint16 feature); 105 106 status_t ResetPort(uint8 index); 107 108 private: 109 // Controller resets 110 void GlobalReset(); 111 status_t ControllerReset(); 112 113 // Interrupt functions 114 static int32 InterruptHandler(void *data); 115 int32 Interrupt(); 116 117 // Transfer functions 118 status_t AddPendingTransfer(Transfer *transfer, 119 Queue *queue, 120 uhci_qh *transferQueue, 121 uhci_td *firstDescriptor, 122 uhci_td *dataDescriptor, 123 bool directionIn); 124 status_t AddPendingIsochronousTransfer( 125 Transfer *transfer, 126 uhci_td **isoRequest, 127 bool directionIn); 128 129 static int32 FinishThread(void *data); 130 void FinishTransfers(); 131 132 status_t CreateFilledTransfer(Transfer *transfer, 133 uhci_td **_firstDescriptor, 134 uhci_qh **_transferQueue); 135 136 // Isochronous transfer functions 137 static int32 FinishIsochronousThread(void *data); 138 void FinishIsochronousTransfers(); 139 isochronous_transfer_data *FindIsochronousTransfer(uhci_td *descriptor); 140 141 status_t LinkIsochronousDescriptor( 142 uhci_td *descriptor, 143 uint16 frame); 144 uhci_td *UnlinkIsochronousDescriptor(uint16 frame); 145 146 // Transfer queue functions 147 uhci_qh *CreateTransferQueue(uhci_td *descriptor); 148 void FreeTransferQueue(uhci_qh *queueHead); 149 150 bool LockIsochronous(); 151 void UnlockIsochronous(); 152 153 // Descriptor functions 154 uhci_td *CreateDescriptor(Pipe *pipe, 155 uint8 direction, 156 size_t bufferSizeToAllocate); 157 status_t CreateDescriptorChain(Pipe *pipe, 158 uhci_td **firstDescriptor, 159 uhci_td **lastDescriptor, 160 uint8 direction, 161 size_t bufferSizeToAllocate); 162 163 void FreeDescriptor(uhci_td *descriptor); 164 void FreeDescriptorChain(uhci_td *topDescriptor); 165 166 void LinkDescriptors(uhci_td *first, 167 uhci_td *second); 168 169 size_t WriteDescriptorChain(uhci_td *topDescriptor, 170 iovec *vector, size_t vectorCount); 171 size_t ReadDescriptorChain(uhci_td *topDescriptor, 172 iovec *vector, size_t vectorCount, 173 uint8 *lastDataToggle); 174 size_t ReadActualLength(uhci_td *topDescriptor, 175 uint8 *lastDataToggle); 176 void WriteIsochronousDescriptorChain( 177 uhci_td **isoRequest, 178 uint32 packetCount, 179 iovec *vector); 180 void ReadIsochronousDescriptorChain( 181 isochronous_transfer_data *transfer, 182 iovec *vector); 183 184 // Register functions 185 inline void WriteReg8(uint32 reg, uint8 value); 186 inline void WriteReg16(uint32 reg, uint16 value); 187 inline void WriteReg32(uint32 reg, uint32 value); 188 inline uint8 ReadReg8(uint32 reg); 189 inline uint16 ReadReg16(uint32 reg); 190 inline uint32 ReadReg32(uint32 reg); 191 192 static pci_module_info *sPCIModule; 193 194 uint32 fRegisterBase; 195 pci_info *fPCIInfo; 196 Stack *fStack; 197 198 // Frame list memory 199 area_id fFrameArea; 200 uint32 *fFrameList; 201 202 // fFrameBandwidth[n] holds the available bandwidth 203 // of the nth frame in microseconds 204 uint16 *fFrameBandwidth; 205 206 // fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n] 207 // keeps track of the first and last isochronous transfer descriptor 208 // in the nth frame 209 uhci_td **fFirstIsochronousDescriptor; 210 uhci_td **fLastIsochronousDescriptor; 211 212 // Queues 213 int32 fQueueCount; 214 Queue **fQueues; 215 216 // Maintain a linked list of transfers 217 transfer_data *fFirstTransfer; 218 transfer_data *fLastTransfer; 219 sem_id fFinishTransfersSem; 220 thread_id fFinishThread; 221 bool fStopFinishThread; 222 223 // Maintain a linked list of isochronous transfers 224 isochronous_transfer_data *fFirstIsochronousTransfer; 225 isochronous_transfer_data *fLastIsochronousTransfer; 226 sem_id fFinishIsochronousTransfersSem; 227 thread_id fFinishIsochronousThread; 228 benaphore fIsochronousLock; 229 bool fStopFinishIsochronousThread; 230 231 // Root hub 232 UHCIRootHub *fRootHub; 233 uint8 fRootHubAddress; 234 uint8 fPortResetChange; 235 236 }; 237 238 239 class UHCIRootHub : public Hub { 240 public: 241 UHCIRootHub(Object *rootObject, 242 int8 deviceAddress); 243 244 static status_t ProcessTransfer(UHCI *uhci, 245 Transfer *transfer); 246 }; 247 248 249 #endif 250