1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78
79 #include <MsCommon.h>
80
81 #include "include/drvConfig.h"
82 #include "include/drvCompiler.h"
83 #include "include/drvErrno.h"
84 #include "include/drvPorts.h"
85 #include "include/drvTimer.h"
86 #include "include/drvList.h"
87
88 #ifdef CONFIG_USB_DEBUG
89 #define DEBUG
90 #else
91 #undef DEBUG
92 #endif
93
94
95 // USB related header files
96 #include "include/drvUSB.h"
97 #include "drvHCD.h"
98
99
100 /*-------------------------------------------------------------------*/
usb_init_urb(struct urb * m_urb)101 void usb_init_urb(struct urb *m_urb)
102 {
103 if (m_urb) {
104 memset(m_urb, 0, sizeof(*m_urb));
105 m_urb->count = (atomic_t)ATOMIC_INIT(1);
106 spin_lock_init(&m_urb->lock);
107 }
108 }
109
110 /*-------------------------------------------------------------------*/
usb_alloc_urb(int iso_packets,int mem_flags)111 struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
112 {
113 struct urb *urb;
114
115 urb = (struct urb *)kmalloc(sizeof(struct urb) +
116 iso_packets * sizeof(struct usb_iso_packet_descriptor),
117 mem_flags);
118 if (!urb) {
119 usb_err("alloc_urb: kmalloc failed%s","");
120 return NULL;
121 }
122 usb_init_urb(urb);
123 return urb;
124 }
125
126 /*-------------------------------------------------------------------*/
127
usb_free_urb(struct urb * m_urb)128 void usb_free_urb(struct urb *m_urb)
129 {
130 if (m_urb)
131 if (atomic_dec_and_test(&m_urb->count))
132 kfree(m_urb);
133 }
134
135 /*-------------------------------------------------------------------*/
136
usb_get_urb(struct urb * urb)137 struct urb * usb_get_urb(struct urb *urb)
138 {
139 if (urb) {
140 atomic_inc(&urb->count);
141 return urb;
142 } else
143 return NULL;
144 }
145
146
147 /*-------------------------------------------------------------------*/
148
usb_submit_urb(struct urb * m_urb,int mem_flags)149 int usb_submit_urb(struct urb *m_urb, int mem_flags)
150 {
151 int pipe, temp_p, max_p;
152 struct usb_device *dev;
153 struct usb_operations *op;
154 int is_out;
155
156 if (!m_urb || m_urb->hcpriv || !m_urb->complete)
157 return -EINVAL;
158 if (!(dev = m_urb->dev) ||
159 (dev->state < USB_STATE_DEFAULT) ||
160 (!dev->bus) || (dev->devnum <= 0))
161 return -ENODEV;
162 if (!(op = dev->bus->op) || !op->submit_urb)
163 return -ENODEV;
164
165 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
166 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
167 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
168 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
169 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
170 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
171 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
172 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
173 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
174 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
175
176
177
178 if (mem_flags == ASYNC_SUBMIT_QTD)
179 return op->submit_urb (m_urb, mem_flags);
180
181 m_urb->status = -EINPROGRESS;
182 m_urb->actual_length = 0;
183 m_urb->bandwidth = 0;
184
185 /* Lots of sanity checks, so HCDs can rely on clean data
186 * and don't need to duplicate tests
187 */
188 pipe = m_urb->pipe;
189 temp_p = usb_pipetype (pipe);
190 is_out = usb_pipeout (pipe);
191
192 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
193 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
194 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
195 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
196 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
197 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
198 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
199 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
200 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
201 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
202 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
203 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
204 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
205
206 if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
207 return -ENODEV;
208
209 if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
210 return -EPIPE;
211
212 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
213 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
214 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
215 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
216 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
217 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
218 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
219 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
220 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
221 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
222
223 max_p = usb_maxpacket (dev, pipe, is_out);
224 if (max_p <= 0) {
225 dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
226 __FUNCTION__,
227 usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
228 dev->bus->bus_name, dev->devpath,
229 max_p);
230 return -EMSGSIZE;
231 }
232
233 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
234 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
235 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
236 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
237 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
238 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
239 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
240 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
241 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
242 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
243 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
244 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
245
246 if (temp_p == PIPE_ISOCHRONOUS) {
247 int n, len;
248
249 /* "high bandwidth" mode, 1-3 packets/uframe? */
250 if (dev->speed == USB_SPEED_HIGH) {
251 int mult = 1 + ((max_p >> 11) & 0x03);
252 max_p &= 0x03ff;
253 max_p *= mult;
254 }
255 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
256 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
257 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
258 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
259 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
260 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
261 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
262 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
263 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
264 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
265 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
266 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
267 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
268 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
269 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
270 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
271
272 if (m_urb->number_of_packets <= 0)
273 return -EINVAL;
274 for (n = 0; n < m_urb->number_of_packets; n++) {
275 len = m_urb->iso_frame_desc [n].length;
276 if (len < 0 || len > max_p)
277 return -EMSGSIZE;
278 m_urb->iso_frame_desc [n].status = (U32) -EXDEV;
279 m_urb->iso_frame_desc [n].actual_length = 0;
280 }
281 }
282
283 /* the I/O buffer must be mapped/unmapped, except when length=0 */
284 if (m_urb->transfer_buffer_length < 0)
285 return -EMSGSIZE;
286
287 #ifdef DEBUG
288 {
289 U32 orig_flags = m_urb->transfer_flags;
290 U32 allowed;
291
292 /* enforce simple/standard policy */
293 allowed = URB_ASYNC_UNLINK; // affects later unlinks
294 allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
295 allowed |= URB_NO_INTERRUPT;
296
297 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
298 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
299 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
300 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
301 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
302 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
303 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
304 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
305 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
306 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
307 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
308 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
309 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
310 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
311 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
312 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
313
314 switch (temp_p) {
315 case PIPE_BULK:
316 if (is_out)
317 allowed |= URB_ZERO_PACKET;
318 /* FALLTHROUGH */
319 case PIPE_CONTROL:
320 allowed |= URB_NO_FSBR; /* only affects UHCI */
321 /* FALLTHROUGH */
322 default: /* all non-iso endpoints */
323 if (!is_out)
324 allowed |= URB_SHORT_NOT_OK;
325 break;
326 case PIPE_ISOCHRONOUS:
327 allowed |= URB_ISO_ASAP;
328 break;
329 }
330 m_urb->transfer_flags &= allowed;
331
332 /* fail if submitter gave bogus flags */
333 if (m_urb->transfer_flags != orig_flags) {
334 err ("BOGUS urb flags, %x --> %x",
335 orig_flags, m_urb->transfer_flags);
336 return -EINVAL;
337 }
338 }
339 #endif
340 switch (temp_p) {
341 case PIPE_ISOCHRONOUS:
342 case PIPE_INTERRUPT:
343 if (m_urb->interval <= 0)
344 return -EINVAL;
345 switch (dev->speed) {
346 case USB_SPEED_HIGH: /* units are microframes */
347 // NOTE usb handles 2^15
348 if (m_urb->interval > (1024 * 8))
349 m_urb->interval = 1024 * 8;
350 temp_p = 1024 * 8;
351 break;
352 case USB_SPEED_FULL: /* units are frames/msec */
353 case USB_SPEED_LOW:
354 if (temp_p == PIPE_INTERRUPT) {
355 // PIPE_INTERRUPT
356 if (m_urb->interval > 255)
357 return -EINVAL;
358 // NOTE ohci only handles up to 32
359 temp_p = 128;
360 } else {
361 // PIPE_ISOCHRONOUS
362 if (m_urb->interval > 1024)
363 m_urb->interval = 1024;
364 // NOTE usb and ohci handle up to 2^15
365 temp_p = 1024;
366 }
367 break;
368 default:
369 return -EINVAL;
370 }
371 while (temp_p > m_urb->interval)
372 temp_p >>= 1;
373 m_urb->interval = temp_p;
374 }
375
376 return op->submit_urb (m_urb, mem_flags);
377 }
378
379 /*-------------------------------------------------------------------*/
380
usb_unlink_urb(struct urb * m_urb)381 int usb_unlink_urb(struct urb *m_urb)
382 {
383 if (m_urb && m_urb->dev && m_urb->dev->bus && m_urb->dev->bus->op)
384 return m_urb->dev->bus->op->unlink_urb(m_urb);
385 else
386 return -ENODEV;
387 }
388
389