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