1 /* 2 * Copyright 2005-2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jan-Rixt Van Hoye 7 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 8 */ 9 10 #ifndef OHCI_H 11 #define OHCI_H 12 13 #include "usb_p.h" 14 #include "ohci_hardware.h" 15 #include <lock.h> 16 17 struct pci_info; 18 struct pci_module_info; 19 class OHCIRootHub; 20 21 typedef struct transfer_data_s { 22 Transfer *transfer; 23 ohci_endpoint_descriptor *endpoint; 24 ohci_general_td *first_descriptor; 25 ohci_general_td *data_descriptor; 26 bool incoming; 27 bool canceled; 28 transfer_data_s *link; 29 } transfer_data; 30 31 // -------------------------------------- 32 // OHCI:: Software isonchronous 33 // transfer descriptor 34 // -------------------------------------- 35 typedef struct hcd_soft_itransfer 36 { 37 ohci_isochronous_td itd; 38 struct hcd_soft_itransfer *nextitd; // mirrors nexttd in ITD 39 struct hcd_soft_itransfer *dnext; // next in done list 40 addr_t physaddr; // physical address to the host controller isonchronous transfer 41 //LIST_ENTRY(hcd_soft_itransfer) hnext; 42 uint16 flags; // flags 43 #ifdef DIAGNOSTIC 44 char isdone; // is the transfer done? 45 #endif 46 }hcd_soft_itransfer; 47 48 #define OHCI_SITD_SIZE ((sizeof (struct hcd_soft_itransfer) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN) 49 #define OHCI_SITD_CHUNK 64 50 51 #define OHCI_NUMBER_OF_ENDPOINTS (2 * OHCI_NUMBER_OF_INTERRUPTS - 1) 52 53 // Note: the controller returns only the physical 54 // address of the first processed descriptor of 55 // an heterogeneous list (isochronous + generic). Unfortunately 56 // we don't have a way to know whether the descriptor is 57 // generic or isochronous, either way to translate the address back to 58 // kernel address. The physical address is used as the hash value. 59 // (Kindly borrowed from *BSD) 60 61 #define OHCI_HASH_SIZE 128 62 #define HASH(x) (((x) >> 4) % OHCI_HASH_SIZE) 63 64 65 class OHCI : public BusManager 66 { 67 public: 68 69 OHCI(pci_info *info, Stack *stack); 70 ~OHCI(); 71 72 status_t Start(); 73 virtual status_t SubmitTransfer(Transfer *transfer); 74 virtual status_t CancelQueuedTransfers(Pipe *pipe, 75 bool force); 76 77 virtual status_t NotifyPipeChange(Pipe *pipe, 78 usb_change change); 79 80 static status_t AddTo(Stack *stack); 81 82 // Port operations 83 uint8 PortCount() { return fPortCount; }; 84 status_t GetPortStatus(uint8 index, 85 usb_port_status *status); 86 status_t SetPortFeature(uint8 index, uint16 feature); 87 status_t ClearPortFeature(uint8 index, uint16 feature); 88 89 status_t ResetPort(uint8 index); 90 91 92 private: 93 // Interrupt functions 94 static int32 _InterruptHandler(void *data); 95 int32 _Interrupt(); 96 97 // Transfer functions 98 status_t _AddPendingTransfer(Transfer *transfer, 99 ohci_endpoint_descriptor *endpoint, 100 ohci_general_td *first, 101 ohci_general_td *data, 102 bool directionIn); 103 status_t _CancelQueuedIsochronousTransfers( 104 Pipe *pipe, bool force); 105 status_t _UnlinkTransfer(transfer_data *transfer); 106 107 static int32 _FinishThread(void *data); 108 void _FinishTransfer(); 109 110 status_t _SubmitControlRequest(Transfer *transfer); 111 status_t _SubmitBulkTransfer(Transfer *transfer); 112 status_t _SubmitPeriodicTransfer(Transfer *transfer); 113 114 status_t _AppendChainDescriptorsToEndpoint( 115 ohci_endpoint_descriptor *endpoint, 116 ohci_general_td *first, 117 ohci_general_td *last); 118 void _RemoveTransferFromEndpoint( 119 transfer_data *); 120 121 // Endpoint related methods 122 ohci_endpoint_descriptor *_AllocateEndpoint(); 123 void _FreeEndpoint( 124 ohci_endpoint_descriptor *endpoint); 125 status_t _InsertEndpointForPipe(Pipe *pipe); 126 status_t _RemoveEndpointForPipe(Pipe *pipe); 127 ohci_endpoint_descriptor *_FindInterruptEndpoint(uint8 interval); 128 129 // Transfer descriptor related methods 130 ohci_general_td *_CreateGeneralDescriptor( 131 size_t bufferSize); 132 status_t _CreateDescriptorChain( 133 ohci_general_td **firstDescriptor, 134 ohci_general_td **lastDescriptor, 135 uint8 direction, 136 size_t bufferSize); 137 138 void _FreeGeneralDescriptor( 139 ohci_general_td *descriptor); 140 void _FreeDescriptorChain( 141 ohci_general_td *topDescriptor); 142 143 void _LinkDescriptors(ohci_general_td *first, 144 ohci_general_td *second); 145 146 ohci_isochronous_td *_CreateIsochronousDescriptor(); 147 void _FreeIsochronousDescriptor( 148 ohci_isochronous_td *descriptor); 149 150 size_t _WriteDescriptorChain( 151 ohci_general_td *topDescriptor, 152 iovec *vector, 153 size_t vectorCount); 154 155 // Hash tables related methods 156 void _AddDescriptorToHash( 157 ohci_general_td *descriptor); 158 void _RemoveDescriptorFromHash( 159 ohci_general_td *descriptor); 160 ohci_general_td *_FindDescriptorInHash( 161 uint32 physicalAddress); 162 163 void _AddIsoDescriptorToHash( 164 ohci_isochronous_td *descriptor); 165 void _RemoveIsoDescriptorFromHash( 166 ohci_isochronous_td *descriptor); 167 ohci_isochronous_td *_FindIsoDescriptorInHash( 168 uint32 physicalAddress); 169 170 171 // Register functions 172 inline void _WriteReg(uint32 reg, uint32 value); 173 inline uint32 _ReadReg(uint32 reg); 174 175 static pci_module_info *sPCIModule; 176 pci_info *fPCIInfo; 177 Stack *fStack; 178 179 uint32 *fOperationalRegisters; 180 area_id fRegisterArea; 181 182 // Host Controller Communication Area related stuff 183 area_id fHccaArea; 184 ohci_hcca *fHcca; 185 ohci_endpoint_descriptor **fInterruptEndpoints; 186 187 // Dummy endpoints 188 ohci_endpoint_descriptor *fDummyControl; 189 ohci_endpoint_descriptor *fDummyBulk; 190 ohci_endpoint_descriptor *fDummyIsochronous; 191 192 // Maintain a linked list of transfer 193 transfer_data *fFirstTransfer; 194 transfer_data *fLastTransfer; 195 sem_id fFinishTransfersSem; 196 thread_id fFinishThread; 197 bool fStopFinishThread; 198 199 // Hash table 200 ohci_general_td **fHashGenericTable; 201 ohci_isochronous_td **fHashIsochronousTable; 202 203 // Root Hub 204 OHCIRootHub *fRootHub; 205 uint8 fRootHubAddress; 206 207 // Port management 208 uint8 fPortCount; 209 }; 210 211 212 class OHCIRootHub : public Hub { 213 public: 214 OHCIRootHub(Object *rootObject, 215 int8 deviceAddress); 216 217 static status_t ProcessTransfer(OHCI *ohci, 218 Transfer *transfer); 219 }; 220 221 222 #endif // OHCI_H 223