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 // Endpoint related methods 115 ohci_endpoint_descriptor *_AllocateEndpoint(); 116 void _FreeEndpoint( 117 ohci_endpoint_descriptor *endpoint); 118 status_t _InsertEndpointForPipe(Pipe *pipe); 119 status_t _RemoveEndpointForPipe(Pipe *pipe); 120 void _RemoveTransferFromEndpoint( 121 transfer_data *transfer); 122 ohci_endpoint_descriptor *_FindInterruptEndpoint(uint8 interval); 123 124 // Transfer descriptor related methods 125 ohci_general_td *_CreateGeneralDescriptor( 126 size_t bufferSize); 127 status_t _CreateDescriptorChain( 128 ohci_general_td **firstDescriptor, 129 ohci_general_td **lastDescriptor, 130 uint8 direction, 131 size_t bufferSize); 132 133 void _FreeGeneralDescriptor( 134 ohci_general_td *descriptor); 135 void _FreeDescriptorChain( 136 ohci_general_td *topDescriptor); 137 138 void _LinkDescriptors(ohci_general_td *first, 139 ohci_general_td *second); 140 141 ohci_isochronous_td *_CreateIsochronousDescriptor(); 142 void _FreeIsochronousDescriptor( 143 ohci_isochronous_td *descriptor); 144 145 size_t _WriteDescriptorChain( 146 ohci_general_td *topDescriptor, 147 iovec *vector, 148 size_t vectorCount); 149 150 // Hash tables related methods 151 void _AddDescriptorToHash( 152 ohci_general_td *descriptor); 153 void _RemoveDescriptorFromHash( 154 ohci_general_td *descriptor); 155 ohci_general_td *_FindDescriptorInHash( 156 uint32 physicalAddress); 157 158 void _AddIsoDescriptorToHash( 159 ohci_isochronous_td *descriptor); 160 void _RemoveIsoDescriptorFromHash( 161 ohci_isochronous_td *descriptor); 162 ohci_isochronous_td *_FindIsoDescriptorInHash( 163 uint32 physicalAddress); 164 165 166 // Register functions 167 inline void _WriteReg(uint32 reg, uint32 value); 168 inline uint32 _ReadReg(uint32 reg); 169 170 static pci_module_info *sPCIModule; 171 pci_info *fPCIInfo; 172 Stack *fStack; 173 174 uint32 *fOperationalRegisters; 175 area_id fRegisterArea; 176 177 // Host Controller Communication Area related stuff 178 area_id fHccaArea; 179 ohci_hcca *fHcca; 180 ohci_endpoint_descriptor **fInterruptEndpoints; 181 182 // Dummy endpoints 183 ohci_endpoint_descriptor *fDummyControl; 184 ohci_endpoint_descriptor *fDummyBulk; 185 ohci_endpoint_descriptor *fDummyIsochronous; 186 187 // Maintain a linked list of transfer 188 transfer_data *fFirstTransfer; 189 transfer_data *fLastTransfer; 190 sem_id fFinishTransfersSem; 191 thread_id fFinishThread; 192 bool fStopFinishThread; 193 194 // Hash table 195 ohci_general_td **fHashGenericTable; 196 ohci_isochronous_td **fHashIsochronousTable; 197 198 // Root Hub 199 OHCIRootHub *fRootHub; 200 uint8 fRootHubAddress; 201 202 // Port management 203 uint8 fPortCount; 204 }; 205 206 207 class OHCIRootHub : public Hub { 208 public: 209 OHCIRootHub(Object *rootObject, 210 int8 deviceAddress); 211 212 static status_t ProcessTransfer(OHCI *ohci, 213 Transfer *transfer); 214 }; 215 216 217 #endif // OHCI_H 218