xref: /haiku/src/add-ons/kernel/busses/usb/uhci.h (revision 89755088d790ff4fe36f8aa77dacb2bd15507108)
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