1 /*
2 * Copyright 2005-2013, 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 * Michael Lotz <mmlr@mlotz.ch>
9 * Siarzhuk Zharski <imker@gmx.li>
10 */
11 #ifndef OHCI_H
12 #define OHCI_H
13
14 #include "usb_private.h"
15 #include "ohci_hardware.h"
16 #include <lock.h>
17
18 struct pci_info;
19 struct pci_device_module_info;
20 struct pci_device;
21 class OHCIRootHub;
22
23 typedef struct transfer_data {
24 Transfer * transfer;
25 ohci_endpoint_descriptor * endpoint;
26 ohci_general_td * first_descriptor;
27 ohci_general_td * data_descriptor;
28 ohci_general_td * last_descriptor;
29 bool incoming;
30 bool canceled;
31 transfer_data * link;
32 } transfer_data;
33
34
35 class OHCI : public BusManager {
36 public:
37 OHCI(pci_info *info, pci_device_module_info* pci,
38 pci_device* device, Stack *stack, device_node* node);
39 ~OHCI();
40
41 status_t Start();
42 virtual status_t SubmitTransfer(Transfer *transfer);
43 virtual status_t CancelQueuedTransfers(Pipe *pipe,
44 bool force);
45
46 virtual status_t NotifyPipeChange(Pipe *pipe,
47 usb_change change);
48
49 // Port operations
PortCount()50 uint8 PortCount() { return fPortCount; };
51 status_t GetPortStatus(uint8 index,
52 usb_port_status *status);
53 status_t SetPortFeature(uint8 index, uint16 feature);
54 status_t ClearPortFeature(uint8 index, uint16 feature);
55
56 status_t ResetPort(uint8 index);
57
TypeName()58 virtual const char * TypeName() const { return "ohci"; };
59
60 private:
61 // Interrupt functions
62 static int32 _InterruptHandler(void *data);
63 int32 _Interrupt();
64
65 // Transfer functions
66 status_t _AddPendingTransfer(Transfer *transfer,
67 ohci_endpoint_descriptor *endpoint,
68 ohci_general_td *firstDescriptor,
69 ohci_general_td *dataDescriptor,
70 ohci_general_td *lastDescriptor,
71 bool directionIn);
72 status_t _AddPendingIsochronousTransfer(
73 Transfer *transfer,
74 ohci_endpoint_descriptor *endpoint,
75 ohci_isochronous_td *firstDescriptor,
76 ohci_isochronous_td *lastDescriptor,
77 bool directionIn);
78
79 status_t _UnlinkTransfer(transfer_data *transfer);
80
81 static int32 _FinishThread(void *data);
82 void _FinishTransfers();
83 bool _FinishIsochronousTransfer(
84 transfer_data *transfer,
85 transfer_data **_lastTransfer);
86
87 status_t _SubmitRequest(Transfer *transfer);
88 status_t _SubmitTransfer(Transfer *transfer);
89 status_t _SubmitIsochronousTransfer(
90 Transfer *transfer);
91
92 void _SwitchEndpointTail(
93 ohci_endpoint_descriptor *endpoint,
94 ohci_general_td *first,
95 ohci_general_td *last);
96 void _SwitchIsochronousEndpointTail(
97 ohci_endpoint_descriptor *endpoint,
98 ohci_isochronous_td *first,
99 ohci_isochronous_td *last);
100
101 void _RemoveTransferFromEndpoint(
102 transfer_data *transfer);
103
104 // Endpoint related methods
105 ohci_endpoint_descriptor * _AllocateEndpoint();
106 void _FreeEndpoint(
107 ohci_endpoint_descriptor *endpoint);
108 status_t _InsertEndpointForPipe(Pipe *pipe);
109 status_t _RemoveEndpointForPipe(Pipe *pipe);
110 ohci_endpoint_descriptor * _FindInterruptEndpoint(uint8 interval);
111
112 // Transfer descriptor related methods
113 ohci_general_td * _CreateGeneralDescriptor(
114 size_t bufferSize);
115 void _FreeGeneralDescriptor(
116 ohci_general_td *descriptor);
117 status_t _CreateDescriptorChain(
118 ohci_general_td **firstDescriptor,
119 ohci_general_td **lastDescriptor,
120 uint32 direction,
121 size_t bufferSize);
122 void _FreeDescriptorChain(
123 ohci_general_td *topDescriptor);
124
125 ohci_isochronous_td * _CreateIsochronousDescriptor(
126 size_t bufferSize);
127 void _FreeIsochronousDescriptor(
128 ohci_isochronous_td *descriptor);
129 status_t _CreateIsochronousDescriptorChain(
130 ohci_isochronous_td **firstDescriptor,
131 ohci_isochronous_td **lastDescriptor,
132 Transfer *transfer);
133 void _FreeIsochronousDescriptorChain(
134 ohci_isochronous_td *topDescriptor);
135
136 size_t _WriteDescriptorChain(
137 ohci_general_td *topDescriptor,
138 generic_io_vec *vector, size_t vectorCount,
139 bool physical);
140 size_t _ReadDescriptorChain(
141 ohci_general_td *topDescriptor,
142 generic_io_vec *vector, size_t vectorCount,
143 bool physical);
144
145 size_t _WriteIsochronousDescriptorChain(
146 ohci_isochronous_td *topDescriptor,
147 generic_io_vec *vector, size_t vectorCount,
148 bool physical);
149 void _ReadIsochronousDescriptorChain(
150 ohci_isochronous_td *topDescriptor,
151 generic_io_vec *vector, size_t vectorCount,
152 bool physical);
153
154 size_t _ReadActualLength(
155 ohci_general_td *topDescriptor);
156
157 void _LinkDescriptors(ohci_general_td *first,
158 ohci_general_td *second);
159 void _LinkIsochronousDescriptors(
160 ohci_isochronous_td *first,
161 ohci_isochronous_td *second,
162 ohci_isochronous_td *nextDone);
163
164 bool _AllocateIsochronousBandwidth(uint16 frame,
165 uint16 size);
166 void _ReleaseIsochronousBandwidth(
167 uint16 startFrame, uint16 count);
168
169 status_t _GetStatusOfConditionCode(
170 uint8 conditionCode);
171 // Private locking
172 bool _LockEndpoints();
173 void _UnlockEndpoints();
174
175 // Register functions
176 inline void _WriteReg(uint32 reg, uint32 value);
177 inline uint32 _ReadReg(uint32 reg);
178
179 // Debug functions
180 void _PrintEndpoint(
181 ohci_endpoint_descriptor *endpoint);
182 void _PrintDescriptorChain(
183 ohci_general_td *topDescriptor);
184 void _PrintDescriptorChain(
185 ohci_isochronous_td *topDescriptor);
186
187 pci_info * fPCIInfo;
188 pci_device_module_info* fPci;
189 pci_device* fDevice;
190 Stack * fStack;
191
192 uint8 * fOperationalRegisters;
193 area_id fRegisterArea;
194
195 // Host Controller Communication Area related stuff
196 area_id fHccaArea;
197 ohci_hcca * fHcca;
198 ohci_endpoint_descriptor ** fInterruptEndpoints;
199
200 // Endpoint management
201 mutex fEndpointLock;
202 ohci_endpoint_descriptor * fDummyControl;
203 ohci_endpoint_descriptor * fDummyBulk;
204 ohci_endpoint_descriptor * fDummyIsochronous;
205
206 // Maintain a linked list of transfer
207 transfer_data * fFirstTransfer;
208 transfer_data * fLastTransfer;
209 sem_id fFinishTransfersSem;
210 thread_id fFinishThread;
211 bool fStopFinishThread;
212 Pipe * fProcessingPipe;
213 // frame bandwidth watchdogs array
214 uint16 * fFrameBandwidth;
215
216 // Root Hub
217 OHCIRootHub * fRootHub;
218 uint8 fRootHubAddress;
219
220 // Port management
221 uint8 fPortCount;
222
223 uint32 fIRQ;
224 bool fUseMSI;
225 };
226
227
228 class OHCIRootHub : public Hub {
229 public:
230 OHCIRootHub(Object *rootObject,
231 int8 deviceAddress);
232
233 static status_t ProcessTransfer(OHCI *ohci,
234 Transfer *transfer);
235 };
236
237
238 #endif // OHCI_H
239