[USBDRIVER]
[reactos.git] / reactos / drivers / usb / nt4compat / usbdriver / ehci.c
1 /**
2 * ehci.c - USB driver stack project for Windows NT 4.0
3 *
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
5 *
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "usbdriver.h"
23 #include "ehci.h"
24
25 //----------------------------------------------------------
26 // ehci routines
27 //#define DEMO
28
29 #define DEFAULT_ENDP( enDP ) \
30 ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP )
31
32 #define dev_from_endp( enDP ) \
33 ( DEFAULT_ENDP( enDP )\
34 ? ( ( PUSB_DEV )( enDP )->pusb_if )\
35 : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) )
36
37 #define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK )
38
39 #define endp_num( enDP ) \
40 ( DEFAULT_ENDP( enDP )\
41 ? 0 \
42 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) )
43
44 #define endp_dir( enDP ) \
45 ( DEFAULT_ENDP( enDP )\
46 ? 0L\
47 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? 1 : 0 )
48
49 #define dev_set_state( pdEV, staTE ) \
50 ( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) )
51
52 #define endp_max_packet_size( enDP ) \
53 ( DEFAULT_ENDP( enDP )\
54 ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \
55 ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\
56 : 8 )\
57 : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) )
58
59 #define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 )
60
61 #if 0
62 /* WTF?! */
63 #define release_adapter( padapTER ) \
64 {\
65 ( ( padapTER ) ); \
66 }
67 #else
68 #define release_adapter( padapTER ) (void)(padapTER)
69 #endif
70
71 #define get_int_idx( _urb, _idx ) \
72 {\
73 UCHAR interVAL;\
74 interVAL = ( UCHAR )( ( _urb )->pipe >> 24 );\
75 for( _idx = 1; _idx < 9; _idx++ )\
76 {\
77 interVAL >>= 1;\
78 if( !interVAL )\
79 break;\
80 }\
81 _idx --;\
82 }
83
84 #define ehci_insert_urb_to_schedule( eHCI, pURB, rET ) \
85 {\
86 SYNC_PARAM sync_param;\
87 sync_param.ehci = eHCI;\
88 sync_param.context = ( pURB );\
89 sync_param.ret = FALSE;\
90 \
91 rET = KeSynchronizeExecution( eHCI->pdev_ext->ehci_int, ehci_sync_insert_urb_schedule, &sync_param );\
92 }
93
94 #define EHCI_ERROR_INT ( STS_FATAL | STS_ERR )
95 #define EHCI_QH_ERROR( qh_contENT ) ( ( qh_contENT )->cur_qtd.status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) )
96 #define EHCI_QTD_ERROR( qtd_contENT ) ( ( qtd_contENT )->status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) )
97
98 #define EHCI_READ_PORT_ULONG( pul ) ( *pul )
99 #define EHCI_WRITE_PORT_ULONG( pul, src ) \
100 {\
101 ULONG cmd_reg;\
102 *pul = ( ULONG )src;\
103 cmd_reg = EHCI_READ_PORT_ULONG( ehci->port_base + EHCI_USBCMD );\
104 if( cmd_reg == 0 )\
105 cmd_reg++;\
106 }
107
108 #define EHCI_READ_PORT_UCHAR( pch ) ( *pch )
109 #define EHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src )
110
111 #define EHCI_READ_PORT_USHORT( psh ) ( *psh )
112 #define EHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src )
113
114 #define press_doorbell( eHCI ) \
115 {\
116 ULONG tmp;\
117 tmp = EHCI_READ_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ) );\
118 tmp |= CMD_IAAD;\
119 EHCI_WRITE_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ), tmp );\
120 }
121 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
122
123 #define qh_from_list_entry( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
124 #define qtd_from_list_entry( pentry ) ( ( PEHCI_QTD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
125 #define itd_from_list_entry( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
126 #define sitd_from_list_entry( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
127 #define fstn_from_list_entry( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
128
129 #define qh_from_schedule( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
130 #define itd_from_schedule( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
131 #define sitd_from_schedule( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
132 #define fstn_from_schedule( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
133
134 #define elem_type( ptr, from_list ) ( from_list ? ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, elem_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) \
135 : ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, sched_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) )
136
137 // #define elem_type_list_entry( pentry ) ( ( qh_from_schedule( pentry )->hw_next & 0x06 ) >> 1 )
138 #define elem_type_list_entry( pentry ) ( elem_type( pentry, TRUE ) )
139
140 #define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \
141 {\
142 parent_HUB = pDEV->parent_dev;\
143 port_IDX = pdev->port_idx;\
144 while( parent_HUB )\
145 {\
146 if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\
147 {\
148 parent_HUB = NULL;\
149 break;\
150 }\
151 if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\
152 {\
153 port_IDX = parent_HUB->port_idx;\
154 parent_HUB = parent_HUB->parent_dev;\
155 continue;\
156 }\
157 break;\
158 }\
159 }
160
161 #define init_elem_phys_part( pelnk ) RtlZeroMemory( ( PVOID )( ( ( ULONG )( pelnk )->phys_part ) & PHYS_PART_ADDR_MASK ), get_elem_phys_part_size( ( ( ( ULONG )( pelnk )->phys_part ) & 0x06 ) >> 1 ) )
162 #define REAL_INTERVAL ( 1 << pipe_content->interval )
163
164 #define elem_safe_free( ptHIS, single ) \
165 {\
166 UCHAR em_type; \
167 em_type = ( UCHAR )elem_type( ptHIS, TRUE ); \
168 if( ptHIS )\
169 {\
170 if( em_type == INIT_LIST_FLAG_QTD )\
171 {\
172 elem_pool_lock( qtd_pool, TRUE );\
173 if( single )\
174 elem_pool_free_elem( qtd_from_list_entry( ptHIS )->elem_head_link );\
175 else \
176 elem_pool_free_elems( qtd_from_list_entry( ptHIS )->elem_head_link );\
177 elem_pool_unlock( qtd_pool, TRUE );\
178 }\
179 else if( em_type == INIT_LIST_FLAG_ITD )\
180 {\
181 elem_pool_lock( itd_pool, TRUE );\
182 if( single )\
183 elem_pool_free_elem( itd_from_list_entry( ptHIS )->elem_head_link );\
184 else \
185 elem_pool_free_elems( itd_from_list_entry( ptHIS )->elem_head_link );\
186 elem_pool_unlock( itd_pool, TRUE );\
187 }\
188 else if( em_type == INIT_LIST_FLAG_SITD )\
189 {\
190 elem_pool_lock( sitd_pool, TRUE );\
191 if( single )\
192 elem_pool_free_elem( sitd_from_list_entry( ptHIS )->elem_head_link );\
193 else \
194 elem_pool_free_elems( sitd_from_list_entry( ptHIS )->elem_head_link );\
195 elem_pool_unlock( sitd_pool, TRUE );\
196 }\
197 else if( em_type == INIT_LIST_FLAG_FSTN )\
198 {\
199 elem_pool_lock( fstn_pool, TRUE );\
200 if( single )\
201 elem_pool_free_elem( fstn_from_list_entry( ptHIS )->elem_head_link );\
202 else \
203 elem_pool_free_elems( fstn_from_list_entry( ptHIS )->elem_head_link );\
204 elem_pool_unlock( fstn_pool, TRUE );\
205 }\
206 else if( em_type == INIT_LIST_FLAG_QH )\
207 {\
208 elem_pool_lock( qh_pool, TRUE );\
209 if( single )\
210 elem_pool_free_elem( qh_from_list_entry( ptHIS )->elem_head_link );\
211 else \
212 elem_pool_free_elems( qh_from_list_entry( ptHIS )->elem_head_link );\
213 elem_pool_unlock( qh_pool, TRUE );\
214 }\
215 }\
216 }
217
218 #ifndef min
219 #define min( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
220 #endif
221 #ifndef max
222 #define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
223 #endif
224
225 #define CLR_RH2_PORTSTAT( port_idx, x ) \
226 {\
227 PULONG addr; \
228 addr = ( PULONG )( ehci->port_base + port_idx ); \
229 status = EHCI_READ_PORT_ULONG( addr ); \
230 status = ( status & 0xfffffd5 ) & ~( x ); \
231 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
232 }
233
234 #define SET_RH2_PORTSTAT( port_idx, x ) \
235 {\
236 PULONG addr; \
237 addr = ( PULONG )( ehci->port_base + port_idx ); \
238 status = EHCI_READ_PORT_ULONG( addr ); \
239 if( x & PORT_PR ) \
240 status = ( status & 0xffffffd1 ) | ( x ); \
241 else \
242 status = ( status & 0xffffffd5 ) | ( x ); \
243 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
244 }
245
246 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
247 #define ehci_from_dev( dEV ) ( ehci_from_hcd( dEV->hcd ) )
248
249 #define ehci_copy_overlay( pQHC, pTDC ) \
250 {\
251 LONG td_size;\
252 PEHCI_QH pqh1;\
253 PEHCI_QTD ptd1;\
254 pqh1 = ( PEHCI_QH )( pQHC );\
255 ptd1 = ( PEHCI_QTD )( pTDC );\
256 td_size = get_elem_phys_part_size( INIT_LIST_FLAG_QTD );\
257 ( pQHC )->cur_qtd_ptr = ptd1->phys_addr;\
258 RtlZeroMemory( &( pQHC )->cur_qtd, td_size );\
259 ( pQHC )->cur_qtd.data_toggle = ( pTDC )->data_toggle;\
260 pqh1->hw_qtd_next = ptd1->phys_addr;\
261 pqh1->hw_alt_next = EHCI_PTR_TERM;\
262 }
263
264 //declarations
265 typedef struct
266 {
267 union
268 {
269 PUHCI_DEV uhci;
270 PEHCI_DEV ehci;
271 };
272 PVOID context;
273 ULONG ret;
274
275 } SYNC_PARAM, *PSYNC_PARAM;
276
277 PDEVICE_OBJECT
278 ehci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr);
279
280 BOOLEAN ehci_init_schedule(PEHCI_DEV ehci, PADAPTER_OBJECT padapter);
281
282 BOOLEAN ehci_release(PDEVICE_OBJECT pdev);
283
284 static VOID ehci_stop(PEHCI_DEV ehci);
285
286 BOOLEAN ehci_destroy_schedule(PEHCI_DEV ehci);
287
288 BOOLEAN NTAPI ehci_sync_insert_urb_schedule(PVOID context);
289
290 VOID ehci_init_hcd_interface(PEHCI_DEV ehci);
291
292 NTSTATUS ehci_rh_submit_urb(PUSB_DEV rh, PURB purb);
293
294 NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp);
295
296 VOID ehci_generic_urb_completion(PURB purb, PVOID context);
297
298 static NTSTATUS ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb);
299
300 static NTSTATUS ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb);
301
302 static NTSTATUS ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb);
303
304 static NTSTATUS ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb);
305
306 static ULONG ehci_scan_iso_error(PEHCI_DEV ehci, PURB purb);
307
308 BOOLEAN ehci_claim_bandwidth(PEHCI_DEV ehci, PURB purb, BOOLEAN claim_bw); //true to claim band-width, false to free band-width
309
310 static VOID ehci_insert_bulk_schedule(PEHCI_DEV ehci, PURB purb);
311
312 #define ehci_insert_control_schedule ehci_insert_bulk_schedule
313
314 static VOID ehci_insert_int_schedule(PEHCI_DEV ehci, PURB purb);
315
316 static VOID ehci_insert_iso_schedule(PEHCI_DEV ehci, PURB purb);
317
318 #define ehci_remove_control_from_schedule ehci_remove_bulk_from_schedule
319
320 PDEVICE_OBJECT ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr);
321
322 PDEVICE_OBJECT ehci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr);
323
324 BOOLEAN ehci_delete_device(PDEVICE_OBJECT pdev);
325
326 VOID ehci_get_capabilities(PEHCI_DEV ehci, PBYTE base);
327
328 BOOLEAN NTAPI ehci_isr(PKINTERRUPT interrupt, PVOID context);
329
330 BOOLEAN ehci_start(PHCD hcd);
331
332 extern VOID rh_timer_svc_reset_port_completion(PUSB_DEV dev, PVOID context);
333
334 extern VOID rh_timer_svc_int_completion(PUSB_DEV dev, PVOID context);
335
336 extern USB_DEV_MANAGER g_dev_mgr;
337
338 #ifndef INCLUDE_EHCI
339 ULONG debug_level = DBGLVL_MAXIMUM;
340 PDRIVER_OBJECT usb_driver_obj = NULL;
341
342 //pending endpoint pool funcs
343 VOID
344 ehci_wait_ms(PEHCI_DEV ehci, LONG ms)
345 {
346 LARGE_INTEGER lms;
347 if (ms <= 0)
348 return;
349
350 lms.QuadPart = -10 * ms;
351 KeSetTimer(&ehci->reset_timer, lms, NULL);
352
353 KeWaitForSingleObject(&ehci->reset_timer, Executive, KernelMode, FALSE, NULL);
354
355 return;
356 }
357
358 BOOLEAN
359 init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
360 {
361 int i;
362 if (pool == NULL)
363 return FALSE;
364
365 pool->pending_endp_array =
366 usb_alloc_mem(NonPagedPool, sizeof(UHCI_PENDING_ENDP) * UHCI_MAX_PENDING_ENDPS);
367 InitializeListHead(&pool->free_que);
368 pool->free_count = 0;
369 pool->total_count = UHCI_MAX_PENDING_ENDPS;
370 KeInitializeSpinLock(&pool->pool_lock);
371
372 for(i = 0; i < MAX_TIMER_SVCS; i++)
373 {
374 free_pending_endp(pool, &pool->pending_endp_array[i]);
375 }
376
377 return TRUE;
378
379 }
380
381 BOOLEAN
382 free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp)
383 {
384 if (pool == NULL || pending_endp == NULL)
385 {
386 return FALSE;
387 }
388
389 RtlZeroMemory(pending_endp, sizeof(UHCI_PENDING_ENDP));
390 InsertTailList(&pool->free_que, (PLIST_ENTRY) & pending_endp->endp_link);
391 pool->free_count++;
392
393 return TRUE;
394 }
395
396 PUHCI_PENDING_ENDP
397 alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count)
398 {
399 PUHCI_PENDING_ENDP new;
400 if (pool == NULL || count != 1)
401 return NULL;
402
403 if (pool->free_count <= 0)
404 return NULL;
405
406 new = (PUHCI_PENDING_ENDP) RemoveHeadList(&pool->free_que);
407 pool->free_count--;
408 return new;
409 }
410
411 BOOLEAN
412 destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool)
413 {
414 if (pool == NULL)
415 return FALSE;
416
417 InitializeListHead(&pool->free_que);
418 pool->free_count = pool->total_count = 0;
419 usb_free_mem(pool->pending_endp_array);
420 pool->pending_endp_array = NULL;
421
422 return TRUE;
423
424 }
425 #else
426 #define ehci_wait_ms uhci_wait_ms
427 extern VOID uhci_wait_ms(PEHCI_DEV ehci, LONG ms);
428
429 extern BOOLEAN init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool);
430
431 extern BOOLEAN free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp);
432
433 extern PUHCI_PENDING_ENDP alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count);
434
435 extern BOOLEAN destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool);
436
437 #endif
438
439 //end of pending endpoint pool funcs
440
441 static VOID NTAPI
442 ehci_cancel_pending_endp_urb(IN PVOID Parameter)
443 {
444 PLIST_ENTRY abort_list;
445 PUSB_DEV pdev;
446 PURB purb;
447 USE_BASIC_NON_PENDING_IRQL;
448
449 abort_list = (PLIST_ENTRY) Parameter;
450
451 if (abort_list == NULL)
452 return;
453
454 while (IsListEmpty(abort_list) == FALSE)
455 {
456 //these devs are protected by purb's ref-count
457 purb = (PURB) RemoveHeadList(abort_list);
458 pdev = purb->pdev;
459 // purb->status is set when they are added to abort_list
460
461 ehci_generic_urb_completion(purb, purb->context);
462
463 lock_dev(pdev, FALSE);
464 pdev->ref_count--;
465 unlock_dev(pdev, FALSE);
466 }
467 usb_free_mem(abort_list);
468 return;
469 }
470
471 static BOOLEAN
472 ehci_process_pending_endp(PEHCI_DEV ehci)
473 {
474 PUSB_DEV pdev;
475 LIST_ENTRY temp_list, abort_list;
476 PLIST_ENTRY pthis;
477 PURB purb;
478 PUSB_ENDPOINT pendp;
479 NTSTATUS can_submit = STATUS_SUCCESS;
480 PWORK_QUEUE_ITEM pwork_item;
481 PLIST_ENTRY cancel_list;
482 PUSB_DEV pparent = NULL;
483 UCHAR port_idx = 0;
484 BOOLEAN tt_needed;
485 UCHAR hub_addr = 0;
486 USE_BASIC_IRQL;
487
488 if (ehci == NULL)
489 return FALSE;
490
491 InitializeListHead(&temp_list);
492 InitializeListHead(&abort_list);
493
494 purb = NULL;
495 ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci));
496
497 lock_pending_endp_list(&ehci->pending_endp_list_lock);
498 while (IsListEmpty(&ehci->pending_endp_list) == FALSE)
499 {
500
501 ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_process_pending_endp(): pending_endp_list=0x%x\n",
502 &ehci->pending_endp_list));
503
504 tt_needed = FALSE;
505 pthis = RemoveHeadList(&ehci->pending_endp_list);
506 pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp;
507 pdev = dev_from_endp(pendp);
508 lock_dev(pdev, TRUE);
509
510 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
511 {
512 unlock_dev(pdev, TRUE);
513 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
514 //delegate to ehci_remove_device for remiving the purb queue on the endpoint
515 continue;
516 }
517 if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
518 {
519 // prepare split transaction
520 unlock_dev(pdev, TRUE);
521
522 // pparent won't be removed when pending_endp_list_lock is acquired.
523 get_parent_hs_hub(pdev, pparent, port_idx);
524
525 if (pparent == NULL)
526 {
527 TRAP();
528 ehci_dbg_print(DBGLVL_MEDIUM,
529 ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n"));
530 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
531 continue;
532 }
533
534 if (hub_lock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)) == FALSE)
535 {
536 lock_dev(pdev, TRUE);
537 if (dev_state(pdev) != USB_DEV_STATE_ZOMB)
538 {
539 // reinsert the pending-endp to the list
540 InsertTailList(&temp_list, pthis);
541 unlock_dev(pdev, TRUE);
542 }
543 else
544 {
545 // delegate to ehci_remove_device for purb removal
546 unlock_dev(pdev, TRUE);
547 free_pending_endp(&ehci->pending_endp_pool,
548 struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
549 }
550 continue;
551 }
552
553 // backup the hub address for future use
554 hub_addr = pparent->dev_addr;
555
556 lock_dev(pdev, TRUE);
557 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
558 {
559 unlock_dev(pdev, TRUE);
560 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
561 hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
562 continue;
563 }
564 tt_needed = TRUE;
565 // go on processing
566 }
567
568 if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
569 {
570 while (IsListEmpty(&pendp->urb_list) == FALSE)
571 {
572 purb = (PURB) RemoveHeadList(&pendp->urb_list);
573 purb->status = USB_STATUS_ENDPOINT_HALTED;
574 InsertTailList(&abort_list, (LIST_ENTRY *) purb);
575 }
576 InitializeListHead(&pendp->urb_list);
577 unlock_dev(pdev, TRUE);
578 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
579 if (tt_needed)
580 hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
581 continue;
582 }
583
584 if (IsListEmpty(&pendp->urb_list) == FALSE)
585 {
586 purb = (PURB) RemoveHeadList(&pendp->urb_list);
587 ASSERT(purb);
588 }
589 else
590 {
591 InitializeListHead(&pendp->urb_list);
592 unlock_dev(pdev, TRUE);
593 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
594 if (tt_needed)
595 hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
596 continue;
597 }
598
599 if (tt_needed)
600 {
601 ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr = hub_addr;
602 ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx = port_idx;
603 }
604
605 // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
606 switch (endp_type(pendp))
607 {
608 case USB_ENDPOINT_XFER_BULK:
609 {
610 can_submit = ehci_internal_submit_bulk(ehci, purb);
611 break;
612 }
613 case USB_ENDPOINT_XFER_CONTROL:
614 {
615 can_submit = ehci_internal_submit_ctrl(ehci, purb);
616 break;
617 }
618 case USB_ENDPOINT_XFER_INT:
619 {
620 can_submit = ehci_internal_submit_int(ehci, purb);
621 break;
622 }
623 case USB_ENDPOINT_XFER_ISOC:
624 {
625 can_submit = ehci_internal_submit_iso(ehci, purb);
626 break;
627 }
628 }
629
630 if (can_submit == STATUS_NO_MORE_ENTRIES)
631 {
632 //no enough bandwidth or tds
633 InsertHeadList(&pendp->urb_list, &purb->urb_link);
634 InsertTailList(&temp_list, pthis);
635 }
636 else
637 {
638 // otherwise error or success
639 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
640
641 if (can_submit != STATUS_SUCCESS)
642 {
643 //abort these URBs
644 InsertTailList(&abort_list, (LIST_ENTRY *) purb);
645 purb->status = can_submit;
646 }
647 }
648 unlock_dev(pdev, TRUE);
649 if (can_submit != STATUS_SUCCESS && tt_needed)
650 {
651 hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp));
652 }
653 }
654
655 if (IsListEmpty(&temp_list) == FALSE)
656 {
657 //re-append them to the pending_endp_list
658 ListFirst(&temp_list, pthis);
659 RemoveEntryList(&temp_list);
660 MergeList(&ehci->pending_endp_list, pthis);
661 }
662 unlock_pending_endp_list(&ehci->pending_endp_list_lock);
663
664 if (IsListEmpty(&abort_list) == FALSE)
665 {
666 PLIST_ENTRY pthis;
667 cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY));
668 ASSERT(cancel_list);
669
670 ListFirst(&abort_list, pthis);
671 RemoveEntryList(&abort_list);
672 InsertTailList(pthis, cancel_list);
673
674 pwork_item = (PWORK_QUEUE_ITEM) & cancel_list[1];
675
676 // we do not need to worry the ehci_cancel_pending_endp_urb running when the
677 // driver is unloading since purb-reference count will prevent the dev_mgr to
678 // quit till all the reference count to the dev drop to zero.
679 ExInitializeWorkItem(pwork_item, ehci_cancel_pending_endp_urb, (PVOID) cancel_list);
680 ExQueueWorkItem(pwork_item, DelayedWorkQueue);
681 }
682 return TRUE;
683 }
684
685 NTSTATUS
686 ehci_submit_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
687 {
688 int i;
689 PUHCI_PENDING_ENDP pending_endp;
690 NTSTATUS status;
691 USE_BASIC_IRQL;
692
693 if (ehci == NULL)
694 return STATUS_INVALID_PARAMETER;
695
696 if (pdev == NULL || pendp == NULL || purb == NULL)
697 {
698 // give a chance to those pending urb, especially for clearing hub tt
699 ehci_process_pending_endp(ehci);
700 return STATUS_INVALID_PARAMETER;
701 }
702
703 lock_pending_endp_list(&ehci->pending_endp_list_lock);
704 lock_dev(pdev, TRUE);
705
706 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
707 {
708 status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
709 goto LBL_OUT;
710 }
711
712 if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB)
713 {
714 unlock_dev(pdev, TRUE);
715 unlock_pending_endp_list(&ehci->pending_endp_list_lock);
716 status = ehci_rh_submit_urb(pdev, purb);
717 return status;
718 }
719
720 if (pendp)
721 purb->pendp = pendp;
722 else
723 purb->pendp = &pdev->default_endp;
724
725 if (dev_from_endp(purb->pendp) != pdev)
726 {
727 status = purb->status = STATUS_INVALID_PARAMETER;
728 goto LBL_OUT;
729 }
730
731 if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL)
732 {
733 status = purb->status = USB_STATUS_ENDPOINT_HALTED;
734 goto LBL_OUT;
735 }
736
737 if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
738 {
739 // wait one ms
740 usb_wait_ms_dpc(1);
741 }
742
743 purb->pdev = pdev;
744 purb->rest_bytes = purb->data_length;
745
746 if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK)
747 purb->bytes_to_transfer = (purb->data_length > EHCI_MAX_SIZE_TRANSFER ? EHCI_MAX_SIZE_TRANSFER : purb->data_length); //multiple transfer for large data block
748 else
749 purb->bytes_to_transfer = purb->data_length;
750
751 ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer));
752
753 purb->bytes_transfered = 0;
754 InitializeListHead(&purb->trasac_list);
755 purb->last_finished_td = &purb->trasac_list;
756 purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL);
757 purb->flags |= URB_FLAG_STATE_PENDING;
758
759
760 i = IsListEmpty(&pendp->urb_list);
761 InsertTailList(&pendp->urb_list, &purb->urb_link);
762
763 pdev->ref_count++; //for purb reference
764
765 if (i == FALSE)
766 {
767 //there is purb pending, simply queue it and return
768 status = purb->status = STATUS_PENDING;
769 goto LBL_OUT;
770 }
771 else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC)
772 {
773 //
774 //No purb waiting but purb overlap not allowed,
775 //so leave it in queue and return, will be scheduled
776 //later
777 //
778 status = purb->status = STATUS_PENDING;
779 goto LBL_OUT;
780 }
781
782 pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1);
783 if (pending_endp == NULL)
784 {
785 //panic
786 status = purb->status = STATUS_UNSUCCESSFUL;
787 goto LBL_OUT2;
788 }
789
790 pending_endp->pendp = purb->pendp;
791 InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link);
792
793 unlock_dev(pdev, TRUE);
794 unlock_pending_endp_list(&ehci->pending_endp_list_lock);
795
796 ehci_process_pending_endp(ehci);
797 return STATUS_PENDING;
798
799 LBL_OUT2:
800 pdev->ref_count--;
801 RemoveEntryList(&purb->urb_link);
802
803 LBL_OUT:
804 unlock_dev(pdev, TRUE);
805 unlock_pending_endp_list(&ehci->pending_endp_list_lock);
806 ehci_process_pending_endp(ehci);
807 return status;
808 }
809
810 static NTSTATUS
811 ehci_set_error_code(PURB purb, ULONG raw_status)
812 {
813 PURB_HS_PIPE_CONTENT pipe_content;
814
815 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
816
817 //test if the purb is canceled
818 if (purb->flags & URB_FLAG_FORCE_CANCEL)
819 {
820 purb->status = STATUS_CANCELLED;
821 }
822 else if (raw_status == 0)
823 purb->status = STATUS_SUCCESS;
824
825 else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT ||
826 pipe_content->trans_type == USB_ENDPOINT_XFER_BULK ||
827 pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL)
828 {
829
830 if (raw_status & QTD_STS_BABBLE)
831 purb->status = USB_STATUS_DATA_OVERRUN;
832
833 else if (raw_status & QTD_STS_HALT)
834 purb->status = USB_STATUS_ENDPOINT_HALTED;
835
836 else if (raw_status & QTD_STS_DBE)
837 purb->status = USB_STATUS_BUFFER_OVERRUN;
838
839 else if (raw_status & QTD_STS_XACT)
840 purb->status = USB_STATUS_CRC; // crc is included in xact err.
841
842 else if (raw_status & QTD_STS_MMF)
843 purb->status = USB_STATUS_BTSTUFF;
844
845 else
846 purb->status = STATUS_UNSUCCESSFUL;
847 }
848 else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC)
849 {
850 if (pipe_content->speed_high)
851 {
852 if (raw_status & ITD_STS_BUFERR)
853 purb->status = USB_STATUS_BUFFER_OVERRUN;
854
855 else if (raw_status & ITD_STS_BABBLE)
856 purb->status = USB_STATUS_BABBLE_DETECTED;
857
858 else if (raw_status & ITD_STS_XACTERR) // Xact Err
859 purb->status = USB_STATUS_CRC;
860
861 else
862 purb->status = STATUS_UNSUCCESSFUL;
863
864 }
865 else
866 {
867 if (raw_status & SITD_STS_ERR) // ERR is received from hub's tt
868 purb->status = USB_STATUS_ERROR;
869
870 else if (raw_status & SITD_STS_DBE)
871 purb->status = USB_STATUS_BUFFER_OVERRUN;
872
873 else if (raw_status & SITD_STS_BABBLE)
874 purb->status = USB_STATUS_BABBLE_DETECTED;
875
876 else if (raw_status & SITD_STS_XACTERR) // Xact Error
877 purb->status = USB_STATUS_CRC;
878
879 else if (raw_status & SITD_STS_MISSFRM) // missing microframe
880 purb->status = USB_STATUS_DATA_TOGGLE_MISMATCH;
881
882 else
883 purb->status = STATUS_UNSUCCESSFUL;
884 }
885 }
886 if (purb->status != STATUS_SUCCESS)
887 {
888 hcd_dbg_print(DBGLVL_MEDIUM, ("ehci_set_error_code(): error status 0x%x\n", raw_status));
889 }
890 return purb->status;
891 }
892
893 static BOOLEAN NTAPI
894 ehci_sync_remove_urb_finished(PVOID context)
895 {
896 PEHCI_DEV ehci;
897 PLIST_ENTRY pthis, pnext, ptemp;
898 PURB purb;
899 PSYNC_PARAM pparam;
900
901 pparam = (PSYNC_PARAM) context;
902 ehci = pparam->ehci;
903 ptemp = (PLIST_ENTRY) pparam->context;
904
905 if (ehci == NULL)
906 {
907 return (UCHAR) (pparam->ret = FALSE);
908 }
909
910 ListFirst(&ehci->urb_list, pthis);
911 while (pthis)
912 {
913 //remove urbs not in the schedule
914 ListNext(&ehci->urb_list, pthis, pnext);
915 purb = (PURB) pthis;
916
917 if ((purb->flags & URB_FLAG_IN_SCHEDULE) == 0)
918 {
919 //finished or canceled( not applied for split bulk ).
920 RemoveEntryList(pthis);
921 InsertTailList(ptemp, pthis);
922 }
923 pthis = pnext;
924 }
925 pparam->ret = TRUE;
926 return (UCHAR) TRUE;
927 }
928
929 VOID NTAPI
930 ehci_dpc_callback(PKDPC dpc, PVOID context, PVOID sysarg1, PVOID sysarg2)
931 {
932 PEHCI_DEV ehci;
933
934 LIST_HEAD temp_list;
935 PLIST_ENTRY pthis, pnext;
936 PURB purb;
937 PEHCI_QH pqh;
938 PEHCI_QTD ptd;
939 PUHCI_PENDING_ENDP pending_endp;
940 PUSB_DEV pdev;
941 PUSB_ENDPOINT pendp;
942
943 BOOLEAN finished;
944 LONG i;
945 ULONG ehci_status, urb_status;
946
947 SYNC_PARAM sync_param;
948 UCHAR ep_type;
949 USE_BASIC_NON_PENDING_IRQL;
950
951 ehci = (PEHCI_DEV) context;
952 if (ehci == NULL)
953 return;
954
955 ehci_status = (ULONG) sysarg1;
956
957 InitializeListHead(&temp_list);
958
959 sync_param.ehci = ehci;
960 sync_param.context = (PVOID) & temp_list;
961
962 ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci));
963 //remove finished purb from ehci's purb-list
964 KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_remove_urb_finished, &sync_param);
965
966 //release resources( itds, sitds, fstns, tds, and qhs ) allocated for the purb
967 while (IsListEmpty(&temp_list) == FALSE)
968 {
969 //not in any public queue, if do not access into dev, no race
970 //condition will occur
971 purb = (PURB) RemoveHeadList(&temp_list);
972 urb_status = purb->status;
973 ep_type = endp_type(purb->pendp);
974
975 if (ep_type == USB_ENDPOINT_XFER_ISOC)
976 {
977 // collect error for iso transfer
978 urb_status = ehci_scan_iso_error(ehci, purb);
979 }
980
981 //the only place we do not use this lock on non-pending-endp-list data
982 KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock);
983 while (IsListEmpty(&purb->trasac_list) == FALSE)
984 {
985 UCHAR em_type;
986 pthis = RemoveHeadList(&purb->trasac_list);
987 em_type = (UCHAR) elem_type(pthis, TRUE);
988
989 if (em_type == INIT_LIST_FLAG_QH)
990 {
991 pqh = qh_from_list_entry(pthis);
992 elem_safe_free(pthis, TRUE);
993 }
994 else
995 {
996 //must be an itd, sitd chain
997 InsertHeadList(&purb->trasac_list, pthis);
998 for(i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++)
999 {
1000 PEHCI_QTD_CONTENT ptdc = NULL;
1001 PEHCI_ITD_CONTENT pitdc;
1002 PEHCI_SITD_CONTENT psitdc;
1003
1004 em_type = (UCHAR) elem_type(pthis, TRUE);
1005
1006 // accumulate data transfered in tds
1007 if (em_type == INIT_LIST_FLAG_QTD)
1008 {
1009 ptd = qtd_from_list_entry(pthis);
1010 ptdc = (PEHCI_QTD_CONTENT) ptd;
1011 if ((ptdc->status & QTD_STS_ACTIVE) == 0 && ((ptdc->status & QTD_ANY_ERROR) == 0))
1012 purb->bytes_transfered += ptd->bytes_to_transfer;
1013 }
1014 else if (em_type == INIT_LIST_FLAG_ITD)
1015 {
1016 int j;
1017 pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis);
1018 for(j = 0; j < 8; j++)
1019 {
1020 if ((pitdc->status_slot[j].status & ITD_STS_ACTIVE) == 0
1021 && (pitdc->status_slot[j].status & ITD_ANY_ERROR) == 0)
1022 purb->bytes_transfered += ptdc->bytes_to_transfer;
1023 }
1024 }
1025 else if (em_type == INIT_LIST_FLAG_SITD)
1026 {
1027 psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis);
1028 if ((psitdc->status & SITD_STS_ACTIVE) == 0 && (psitdc->status & SITD_ANY_ERROR) == 0)
1029 purb->bytes_transfered += ptdc->bytes_to_transfer;
1030 }
1031 ListNext(&purb->trasac_list, pthis, pnext);
1032 pthis = pnext;
1033 }
1034
1035 // check to see if an fstn is there
1036 ListFirstPrev(&purb->trasac_list, pthis);
1037 if (elem_type(pthis, TRUE) == INIT_LIST_FLAG_FSTN)
1038 {
1039 RemoveEntryList(pthis);
1040 elem_safe_free(pthis, TRUE);
1041 }
1042
1043 ListFirst(&purb->trasac_list, pthis);
1044 RemoveEntryList(&purb->trasac_list);
1045
1046 // free the tds
1047 elem_safe_free(pthis, FALSE);
1048
1049 //termination condition
1050 InitializeListHead(&purb->trasac_list);
1051 purb->last_finished_td = NULL;
1052 }
1053 }
1054
1055 if (ep_type == USB_ENDPOINT_XFER_ISOC || ep_type == USB_ENDPOINT_XFER_INT)
1056 ehci_claim_bandwidth(ehci, purb, FALSE); //release band-width
1057
1058 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1059
1060 ehci_set_error_code(purb, urb_status);
1061
1062 pdev = dev_from_endp(purb->pendp);
1063 pendp = purb->pendp;
1064
1065 // perform clear tt buffer if error on full/low bulk/control pipe
1066 if (ep_type == USB_ENDPOINT_XFER_BULK || ep_type == USB_ENDPOINT_XFER_CONTROL)
1067 {
1068 PURB_HS_PIPE_CONTENT pipe_content;
1069 PUSB_DEV phub;
1070 UCHAR port_idx;
1071
1072 get_parent_hs_hub(pdev, phub, port_idx);
1073 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
1074
1075 if (pipe_content->speed_high == 0 && purb->status != STATUS_SUCCESS)
1076 {
1077 // lets schedule an event to clear the tt buffer
1078 hub_post_clear_tt_event(phub, port_idx, purb->pipe);
1079 }
1080 else if (pipe_content->speed_high == 0)
1081 {
1082 if (phub == NULL)
1083 TRAP();
1084 else
1085 {
1086 // release tt if no error
1087 hub_unlock_tt(phub, (UCHAR) port_idx, (UCHAR) pipe_content->trans_type);
1088 }
1089 }
1090 }
1091
1092 finished = TRUE;
1093
1094 //since the ref_count for the purb is not released, we can safely have one
1095 //pointer to dev
1096
1097 if (purb->status == USB_STATUS_BABBLE_DETECTED)
1098 {
1099 usb_dbg_print(DBGLVL_MEDIUM,
1100 ("ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n"));
1101 // ehci_start( ehci );
1102 }
1103
1104 if (ehci_status & STS_HALT) //&& !ehci->is_suspended
1105 {
1106 ehci_start(&ehci->hcd_interf);
1107 }
1108
1109 //this will let the new request in ehci_generic_urb_completion to this endp
1110 //be processed rather than queued in the pending_endp_list
1111 lock_dev(pdev, TRUE);
1112 usb_endp_busy_count_dec(pendp);
1113 unlock_dev(pdev, TRUE);
1114
1115 if (usb_success(purb->status) == FALSE)
1116 {
1117 // set error code and complete the purb and purb is invalid from this point
1118 ehci_generic_urb_completion(purb, purb->context);
1119 }
1120 else
1121 {
1122 if (ep_type == USB_ENDPOINT_XFER_BULK)
1123 {
1124 purb->rest_bytes -= purb->bytes_transfered;
1125 if (purb->rest_bytes)
1126 {
1127 finished = FALSE;
1128 }
1129 else
1130 {
1131 ehci_generic_urb_completion(purb, purb->context);
1132 }
1133 }
1134 else
1135 {
1136 ehci_generic_urb_completion(purb, purb->context);
1137 // DbgBreakPoint();
1138 //purb is now invalid
1139 }
1140 }
1141
1142 KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock);
1143 lock_dev(pdev, TRUE);
1144
1145 if (finished)
1146 pdev->ref_count--;
1147
1148 if (urb_status && ((ep_type == USB_ENDPOINT_XFER_BULK) || (ep_type == USB_ENDPOINT_XFER_INT)))
1149 {
1150 // error on int or bulk pipe, cleared in usb_reset_pipe_completion
1151 pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK;
1152 pendp->flags |= USB_ENDP_FLAG_STALL;
1153 }
1154
1155 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1156 {
1157 unlock_dev(pdev, TRUE);
1158 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1159 if (finished == FALSE)
1160 {
1161
1162 purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
1163 ehci_generic_urb_completion(purb, purb->context);
1164
1165 lock_dev(pdev, TRUE);
1166 pdev->ref_count--;
1167 unlock_dev(pdev, TRUE);
1168 }
1169 continue;
1170 }
1171
1172 if (finished && IsListEmpty(&pendp->urb_list) == TRUE)
1173 {
1174 unlock_dev(pdev, TRUE);
1175 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1176 continue;
1177 }
1178 else if (finished == TRUE)
1179 {
1180 //has purb in the endp's purb-list
1181 if (usb_endp_busy_count(pendp) > 0)
1182 {
1183 //the urbs still have chance to be sheduled but not this time
1184 unlock_dev(pdev, TRUE);
1185 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1186 continue;
1187 }
1188 }
1189
1190 if (finished == FALSE)
1191 {
1192 //a split bulk transfer, ( not the high speed split transfer )
1193 purb->bytes_transfered = 0;
1194 purb->bytes_to_transfer =
1195 EHCI_MAX_SIZE_TRANSFER > purb->rest_bytes ? purb->rest_bytes : EHCI_MAX_SIZE_TRANSFER;
1196
1197 //the purb is not finished
1198 purb->flags &= ~URB_FLAG_STATE_MASK;
1199 purb->flags |= URB_FLAG_STATE_PENDING;
1200
1201 InsertHeadList(&pendp->urb_list, &purb->urb_link);
1202 }
1203
1204 pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1);
1205 if (!pending_endp)
1206 {
1207 unlock_dev(pdev, TRUE);
1208 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1209 return;
1210 }
1211 pending_endp->pendp = pendp;
1212 InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link);
1213
1214 unlock_dev(pdev, TRUE);
1215 KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock);
1216 }
1217
1218 //ah...exhausted, let's find some in the pending_endp_list to rock
1219 ehci_process_pending_endp(ehci);
1220 return;
1221 }
1222
1223 static BOOLEAN NTAPI
1224 ehci_sync_cancel_urbs_dev(PVOID context)
1225 {
1226 //cancel all the urbs on one dev
1227 PEHCI_DEV ehci;
1228 PUSB_DEV pdev, dest_dev;
1229 PSYNC_PARAM sync_param;
1230 PLIST_ENTRY pthis, pnext;
1231 LONG count;
1232
1233 sync_param = (PSYNC_PARAM) context;
1234 dest_dev = (PUSB_DEV) sync_param->context;
1235 ehci = sync_param->ehci;
1236
1237 if (ehci == NULL || dest_dev == NULL)
1238 {
1239 return (UCHAR) (sync_param->ret = FALSE);
1240 }
1241 count = 0;
1242 ListFirst(&ehci->urb_list, pthis);
1243 while (pthis)
1244 {
1245 pdev = dev_from_endp(((PURB) pthis)->pendp);
1246 if (pdev == dest_dev)
1247 {
1248 ((PURB) pthis)->flags |= URB_FLAG_FORCE_CANCEL;
1249 }
1250 ListNext(&ehci->urb_list, pthis, pnext);
1251 pthis = pnext;
1252 count++;
1253 }
1254
1255 if (count)
1256 {
1257 // signal an int for further process
1258 press_doorbell(ehci);
1259 }
1260 return (UCHAR) (sync_param->ret = TRUE);
1261 }
1262
1263 BOOLEAN
1264 ehci_remove_device(PEHCI_DEV ehci, PUSB_DEV dev)
1265 {
1266 PUHCI_PENDING_ENDP ppending_endp;
1267 PLIST_ENTRY pthis, pnext;
1268 PURB purb;
1269 LIST_HEAD temp_list;
1270 int i, j, k;
1271 SYNC_PARAM sync_param;
1272
1273 USE_BASIC_IRQL;
1274
1275 if (ehci == NULL || dev == NULL)
1276 return FALSE;
1277
1278 InitializeListHead(&temp_list);
1279
1280 //free pending endp that has purb queued from pending endp list
1281 lock_pending_endp_list(&ehci->pending_endp_list_lock);
1282
1283 ListFirst(&ehci->pending_endp_list, pthis);
1284
1285 while (pthis)
1286 {
1287 ppending_endp = (PUHCI_PENDING_ENDP) pthis;
1288 ListNext(&ehci->pending_endp_list, pthis, pnext);
1289 if (dev_from_endp(ppending_endp->pendp) == dev)
1290 {
1291 RemoveEntryList(pthis);
1292 free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link));
1293 }
1294 pthis = pnext;
1295 }
1296 unlock_pending_endp_list(&ehci->pending_endp_list_lock);
1297
1298 //cancel all the urbs in the purb-list
1299 sync_param.ehci = ehci;
1300 sync_param.context = (PVOID) dev;
1301
1302 KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urbs_dev, &sync_param);
1303
1304 //cancel all the purb in the endp's purb-list
1305 k = 0;
1306 lock_dev(dev, FALSE);
1307 if (dev->usb_config)
1308 {
1309 //only for configed dev
1310 for(i = 0; i < dev->usb_config->if_count; i++)
1311 {
1312 for(j = 0; j < dev->usb_config->interf[i].endp_count; j++)
1313 {
1314 ListFirst(&dev->usb_config->interf[i].endp[j].urb_list, pthis);
1315 while (pthis)
1316 {
1317 ListNext(&dev->usb_config->interf[i].endp[j].urb_list, pthis, pnext);
1318
1319 RemoveEntryList(pthis);
1320 InsertHeadList(&temp_list, pthis);
1321 pthis = pnext;
1322 k++;
1323 }
1324
1325 }
1326 }
1327 }
1328 ListFirst(&dev->default_endp.urb_list, pthis);
1329
1330 while (pthis)
1331 {
1332 ListNext(&dev->default_endp.urb_list, pthis, pnext);
1333
1334 RemoveEntryList(pthis);
1335 InsertHeadList(&temp_list, pthis);
1336 pthis = pnext;
1337 k++;
1338 }
1339 unlock_dev(dev, FALSE);
1340
1341 if (IsListEmpty(&temp_list) == FALSE)
1342 {
1343 for(i = 0; i < k; i++)
1344 {
1345 //complete those urbs with error
1346 pthis = RemoveHeadList(&temp_list);
1347 purb = (PURB) pthis;
1348 purb->status = STATUS_DEVICE_DOES_NOT_EXIST;
1349 {
1350 ehci_generic_urb_completion(purb, purb->context);
1351 }
1352 }
1353 }
1354
1355 lock_dev(dev, FALSE) dev->ref_count -= k;
1356 unlock_dev(dev, FALSE);
1357
1358 return TRUE;
1359 }
1360
1361 static BOOLEAN
1362 ehci_insert_urb_schedule(PEHCI_DEV ehci, PURB purb)
1363 // must have dev_lock( ehci_process_pending_endp ) and frame_list_lock acquired
1364 {
1365 PURB_HS_PIPE_CONTENT pipe_content;
1366
1367 if (ehci == NULL || purb == NULL)
1368 return FALSE;
1369
1370 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
1371 switch (pipe_content->trans_type)
1372 {
1373 case USB_ENDPOINT_XFER_CONTROL:
1374 ehci_insert_control_schedule(ehci, purb);
1375 break;
1376 case USB_ENDPOINT_XFER_BULK:
1377 ehci_insert_bulk_schedule(ehci, purb);
1378 break;
1379 case USB_ENDPOINT_XFER_INT:
1380 ehci_insert_int_schedule(ehci, purb);
1381 break;
1382 case USB_ENDPOINT_XFER_ISOC:
1383 ehci_insert_iso_schedule(ehci, purb);
1384 break;
1385 default:
1386 return FALSE;
1387 }
1388
1389 purb->flags &= ~URB_FLAG_STATE_MASK;
1390 purb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE;
1391 InsertTailList(&ehci->urb_list, &purb->urb_link);
1392
1393 return TRUE;
1394 }
1395
1396 static BOOLEAN
1397 ehci_insert_tds_qh(PEHCI_DEV ehci, PEHCI_QH pqh, PEHCI_QTD td_chain)
1398 {
1399 if (pqh == NULL || td_chain == NULL)
1400 return FALSE;
1401
1402 UNREFERENCED_PARAMETER(ehci);
1403
1404 ehci_copy_overlay((PEHCI_QH_CONTENT) pqh, (PEHCI_QTD_CONTENT) td_chain);
1405 InsertTailList(&td_chain->elem_head_link->elem_link, &pqh->elem_head_link->elem_link);
1406 return TRUE;
1407 }
1408
1409 static BOOLEAN
1410 ehci_insert_qh_urb(PURB purb, PEHCI_QH pqh)
1411 {
1412 PLIST_ENTRY pthis, pnext;
1413 if (pqh == NULL || purb == NULL)
1414 return FALSE;
1415
1416 InsertTailList(&pqh->elem_head_link->elem_link, &purb->trasac_list);
1417 ListFirst(&purb->trasac_list, pthis) while (pthis)
1418 {
1419 // note: fstn may in this chain
1420 struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb;
1421 ListNext(&purb->trasac_list, pthis, pnext);
1422 pthis = pnext;
1423 }
1424 return TRUE;
1425 }
1426
1427 #define calc_td_count( pURB, start_aDDR, td_coUNT ) \
1428 {\
1429 LONG i, j, k;\
1430 td_coUNT = 0;\
1431 k = ( ( pURB )->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;\
1432 if( k != 0 )\
1433 {\
1434 LONG packets_per_td, packets_per_page;\
1435 packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;\
1436 packets_per_page = PAGE_SIZE / max_packet_size;\
1437 i = ( ( LONG )&( pURB )->data_buffer[ ( start_aDDR ) ] ) & ( PAGE_SIZE - 1 );\
1438 if( i )\
1439 {\
1440 i = PAGE_SIZE - i;\
1441 j = i & ( max_packet_size - 1 );\
1442 k -= ( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) / max_packet_size;\
1443 if( k < 0 )\
1444 td_coUNT = 1;\
1445 else\
1446 {\
1447 if( j )\
1448 i = packets_per_td - packets_per_page;\
1449 else\
1450 i = packets_per_td;\
1451 td_coUNT = 1 + ( k + i - 1 ) / i; \
1452 }\
1453 }\
1454 else\
1455 {\
1456 td_coUNT = ( k + packets_per_td - 1 ) / packets_per_td;\
1457 }\
1458 }\
1459 }
1460
1461 static BOOLEAN
1462 ehci_fill_td_buf_ptr(PURB purb, LONG start_addr, // start idx into purb->data_buffer
1463 PLIST_ENTRY td_list, LONG td_count, ULONG toggle)
1464 // fill the tds' bytes_to_transfer and hw_buf, return next toggle value: true 1, false 0
1465 {
1466 LONG i, j, k, data_load;
1467 LONG packets_per_td, packets_per_page, bytes_to_transfer, max_packet_size;
1468 PLIST_ENTRY pthis, pnext;
1469 PEHCI_QTD_CONTENT ptdc;
1470 PEHCI_QTD ptd;
1471 PVOID ptr;
1472
1473 if (purb == NULL || td_list == NULL || td_count == 0)
1474 return toggle;
1475
1476 max_packet_size = 1 << ((PURB_HS_PIPE_CONTENT) & purb->pipe)->max_packet_size;
1477 packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;
1478 packets_per_page = PAGE_SIZE / max_packet_size;
1479
1480 pthis = td_list;
1481 bytes_to_transfer = purb->bytes_to_transfer;
1482
1483 i = ((LONG) & (purb)->data_buffer[(start_addr)]) & (PAGE_SIZE - 1);
1484 if (i)
1485 {
1486 i = PAGE_SIZE - i;
1487 j = i & (max_packet_size - 1);
1488 }
1489 else
1490 {
1491 i = j = 0;
1492 }
1493
1494 while (bytes_to_transfer)
1495 {
1496 ptd = qtd_from_list_entry(pthis);
1497 ptd->hw_buf[0] = MmGetPhysicalAddress(&purb->data_buffer[start_addr]).LowPart;
1498 ptdc = (PEHCI_QTD_CONTENT) ptd;
1499
1500 if (i != 0)
1501 {
1502 data_load = (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) < bytes_to_transfer
1503 ? (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) : bytes_to_transfer;
1504
1505 ptdc->bytes_to_transfer = (USHORT) data_load;
1506 ptd->bytes_to_transfer = (USHORT) data_load;
1507
1508 // subtract the header part
1509 data_load -= (i < data_load ? i : data_load);
1510
1511 for(k = 1; data_load > 0; k++)
1512 {
1513 ptr = &purb->data_buffer[start_addr + i + (k - 1) * PAGE_SIZE];
1514 ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1));
1515 ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart;
1516 data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
1517 }
1518 }
1519 else
1520 {
1521 // aligned on page boundary
1522 data_load = EHCI_QTD_MAX_TRANS_SIZE < bytes_to_transfer
1523 ? EHCI_QTD_MAX_TRANS_SIZE : bytes_to_transfer;
1524
1525 ptdc->bytes_to_transfer = (USHORT) data_load;
1526 ptd->bytes_to_transfer = (USHORT) data_load;
1527
1528 data_load -= (PAGE_SIZE < data_load ? PAGE_SIZE : data_load);
1529
1530 for(k = 1; data_load > 0; k++)
1531 {
1532 ptr = &purb->data_buffer[start_addr + k * PAGE_SIZE];
1533 ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1));
1534 ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart;
1535 data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load;
1536 }
1537 }
1538 ptdc->data_toggle = toggle;
1539 if (((ptdc->bytes_to_transfer + max_packet_size - 1) / max_packet_size) & 1)
1540 {
1541 //only odd num of transactions has effect
1542 toggle ^= 1;
1543 }
1544 start_addr += ptdc->bytes_to_transfer;
1545 bytes_to_transfer -= ptdc->bytes_to_transfer;
1546 ListNext(td_list, pthis, pnext);
1547 pthis = pnext;
1548 i = j;
1549 }
1550 return toggle;
1551 }
1552
1553 static NTSTATUS
1554 ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb)
1555 //
1556 // assume that the purb has its rest_bytes and bytes_to_transfer set
1557 // and bytes_transfered is zeroed.
1558 // dev_lock must be acquired outside
1559 // purb comes from dev's endpoint purb-list. it is already removed from
1560 // the endpoint purb-list.
1561 //
1562 {
1563
1564 LONG max_packet_size, td_count, offset, bytes_to_transfer;
1565 PBYTE start_addr;
1566 PEHCI_QTD ptd;
1567 PEHCI_QH pqh;
1568 LIST_ENTRY td_list, *pthis, *pnext;
1569 BOOLEAN old_toggle, toggle, ret;
1570 UCHAR pid;
1571 LONG i, j;
1572 PURB_HS_PIPE_CONTENT pipe_content;
1573 PEHCI_QTD_CONTENT ptdc;
1574 PEHCI_QH_CONTENT pqhc;
1575 PEHCI_ELEM_LINKS pelnk;
1576 PEHCI_ELEM_LINKS plnk;
1577
1578 if (ehci == NULL || purb == NULL)
1579 return STATUS_INVALID_PARAMETER;
1580
1581 max_packet_size = endp_max_packet_size(purb->pendp);
1582 if (purb->bytes_to_transfer == 0)
1583 {
1584 return STATUS_INVALID_PARAMETER;
1585 }
1586
1587 start_addr = &purb->data_buffer[purb->data_length - purb->rest_bytes];
1588 calc_td_count(purb, purb->data_length - purb->rest_bytes, td_count);
1589
1590 elem_pool_lock(qtd_pool, TRUE);
1591 pelnk = elem_pool_alloc_elems(qtd_pool, td_count);
1592 elem_pool_unlock(qtd_pool, TRUE);
1593
1594 if (pelnk == NULL)
1595 {
1596 return STATUS_UNSUCCESSFUL;
1597 }
1598 ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
1599
1600 InitializeListHead(&td_list);
1601 InsertTailList(&ptd->elem_head_link->elem_link, &td_list);
1602
1603 ListFirst(&td_list, pthis);
1604 ListNext(&td_list, pthis, pnext);
1605
1606 offset = 0;
1607
1608 old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE;
1609 bytes_to_transfer = purb->bytes_to_transfer;
1610 ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle));
1611
1612 for(i = 1; i < 16; i++)
1613 {
1614 if ((max_packet_size >> i) == 0)
1615 break;
1616 }
1617 i--;
1618 i &= 0xf;
1619
1620 purb->pipe = 0;
1621 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
1622 pipe_content->max_packet_size = i;
1623 pipe_content->endp_addr = endp_num(purb->pendp);
1624 pipe_content->dev_addr = dev_from_endp(purb->pendp)->dev_addr;
1625 pipe_content->trans_dir = endp_dir(purb->pendp);
1626 pipe_content->trans_type = USB_ENDPOINT_XFER_BULK;
1627 pipe_content->data_toggle = toggle;
1628 pipe_content->speed_high = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0;
1629 pipe_content->speed_low = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0;
1630
1631 pid = (((ULONG) purb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT);
1632
1633 i = ((ULONG) start_addr) & (PAGE_SIZE - 1); // header part within first page
1634 if (i)
1635 {
1636 i = PAGE_SIZE - i;
1637 if (i < purb->bytes_to_transfer)
1638 j = i & (max_packet_size - 1);
1639 else
1640 j = 0;
1641 }
1642 else
1643 j = 0;
1644
1645 // fill the page pointer and toggle
1646
1647 toggle = ehci_fill_td_buf_ptr(purb, purb->data_length - purb->rest_bytes, pthis, td_count, toggle);
1648 while (pthis)
1649 {
1650 ptd = qtd_from_list_entry(pthis);
1651 ptdc = (PEHCI_QTD_CONTENT) ptd;
1652
1653 // ptdc->alt_terminal = 1;
1654 // ptdc->alt_qtd = 0;
1655 ptd->hw_alt_next = EHCI_PTR_TERM;
1656 ptdc->pid = pid;
1657
1658 // ptd->elem_head_link->purb = purb; will be filled later
1659 ptdc->err_count = 3;
1660 ptdc->status = 0x80; // active, and do_start_split for split transfer
1661 ptdc->cur_page = 0;
1662 // ptdc->data_toggle = toggle;
1663
1664 if (pnext)
1665 {
1666 ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
1667 }
1668 else
1669 {
1670 //Last one, enable ioc and short packet detect if necessary
1671 ptd->hw_next = EHCI_PTR_TERM;
1672 ptdc->ioc = TRUE;
1673 if (bytes_to_transfer < max_packet_size && (pid == QTD_PID_IN))
1674 {
1675 //ptd->status |= TD_CTRL_SPD;
1676 }
1677 }
1678
1679 pthis = pnext;
1680
1681 if (pthis)
1682 ListNext(&td_list, pthis, pnext);
1683 }
1684
1685 ListFirst(&td_list, pthis);
1686 RemoveEntryList(&td_list);
1687
1688 elem_pool_lock(qh_pool, TRUE);
1689
1690 plnk = elem_pool_alloc_elem(qh_pool);
1691 if (plnk == NULL)
1692 {
1693 // free the qtds
1694 elem_safe_free(pthis, TRUE);
1695 if (qh_pool) elem_pool_unlock(qh_pool, TRUE);
1696 return STATUS_UNSUCCESSFUL;
1697 }
1698
1699 pqh = (PEHCI_QH) ((ULONG) plnk->phys_part & PHYS_PART_ADDR_MASK);
1700 elem_pool_unlock(qh_pool, TRUE);
1701
1702 if (pqh == NULL)
1703 {
1704 // free the qtds
1705 elem_safe_free(pthis, TRUE);
1706 return STATUS_NO_MORE_ENTRIES;
1707
1708 }
1709
1710 purb->td_count = td_count;
1711 pqhc = (PEHCI_QH_CONTENT) pqh;
1712 pqh->hw_next = EHCI_PTR_TERM; // filled later
1713 pqhc->dev_addr = pipe_content->dev_addr;
1714 pqhc->inactive = 0;
1715 pqhc->endp_addr = pipe_content->endp_addr;
1716 pqhc->data_toggle = 0; //pipe_content->data_toggle;
1717 pqhc->is_async_head = 0;
1718 pqhc->max_packet_size = (1 << pipe_content->max_packet_size);
1719 pqhc->is_ctrl_endp = 0;
1720 pqhc->reload_counter = EHCI_NAK_RL_COUNT;
1721
1722 if (pipe_content->speed_high)
1723 pqhc->endp_spd = USB_SPEED_HIGH;
1724 else if (pipe_content->speed_low)
1725 pqhc->endp_spd = USB_SPEED_LOW;
1726 else
1727 pqhc->endp_spd = USB_SPEED_FULL;
1728
1729 pqh->hw_info2 = 0;
1730 pqhc->mult = 1;
1731 pqh->hw_current = 0;
1732 pqh->hw_qtd_next = 0; // filled later
1733 pqh->hw_alt_next = EHCI_PTR_TERM;
1734 pqh->hw_token = 0; //indicate to advance queue before execution
1735
1736 if (!pipe_content->speed_high)
1737 {
1738 pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
1739 pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
1740 }
1741
1742 ptd = qtd_from_list_entry(pthis);
1743 ehci_insert_tds_qh(ehci, pqh, ptd);
1744 ehci_insert_qh_urb(purb, pqh);
1745 purb->pendp->flags =
1746 (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
1747 usb_endp_busy_count_inc(purb->pendp);
1748 ehci_insert_urb_to_schedule(ehci, purb, ret);
1749
1750 if (ret == FALSE)
1751 {
1752 // undo all we have done
1753 ListFirst(&pqh->elem_head_link->elem_link, pthis);
1754
1755 RemoveEntryList(&purb->trasac_list);
1756 RemoveEntryList(&pqh->elem_head_link->elem_link); //remove qh from td_chain
1757
1758 elem_safe_free(pthis, FALSE);
1759 elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
1760
1761 InitializeListHead(&purb->trasac_list);
1762 // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback
1763 purb->pendp->flags =
1764 (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0);
1765 return STATUS_UNSUCCESSFUL;
1766 }
1767 return STATUS_SUCCESS;
1768 }
1769
1770 static NTSTATUS
1771 ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb)
1772 {
1773
1774 LIST_ENTRY td_list, *pthis, *pnext;
1775 LONG i, td_count;
1776 LONG toggle;
1777 LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx;
1778
1779 PEHCI_QTD ptd;
1780 PEHCI_QH pqh;
1781 PEHCI_QH_CONTENT pqhc;
1782 UCHAR dev_addr;
1783 BOOLEAN ret;
1784 PURB_HS_PIPE_CONTENT pipe_content;
1785 PEHCI_QTD_CONTENT ptdc;
1786 PEHCI_ELEM_LINKS pelnk;
1787 PUSB_DEV pdev;
1788
1789 if (ehci == NULL || purb == NULL)
1790 return STATUS_INVALID_PARAMETER;
1791
1792 bytes_rest = purb->rest_bytes;
1793 bytes_to_transfer = purb->bytes_to_transfer;
1794 max_packet_size = endp_max_packet_size(purb->pendp);
1795 start_idx = purb->data_length - purb->rest_bytes;
1796
1797 calc_td_count(purb, start_idx, td_count);
1798 td_count += 2; // add setup td and handshake td
1799
1800 elem_pool_lock(qtd_pool, TRUE);
1801 pelnk = elem_pool_alloc_elems(qtd_pool, td_count);
1802 elem_pool_unlock(qtd_pool, TRUE);
1803
1804 if (pelnk == NULL)
1805 {
1806 return STATUS_NO_MORE_ENTRIES;
1807 }
1808
1809 InsertTailList(&pelnk->elem_link, &td_list);
1810 ListFirst(&td_list, pthis);
1811 ListNext(&td_list, pthis, pnext);
1812
1813 ptd = qtd_from_list_entry(pthis);
1814
1815 pdev = dev_from_endp(purb->pendp);
1816 dev_addr = pdev->dev_addr;
1817
1818 if (dev_state(pdev) <= USB_DEV_STATE_RESET) //only valid for control transfer
1819 dev_addr = 0;
1820
1821 usb_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr));
1822
1823 // fill the setup packet
1824 ptdc = (PEHCI_QTD_CONTENT) ptd;
1825 ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
1826 ptd->hw_alt_next = EHCI_PTR_TERM;
1827 ptdc->status = 0x80; // active
1828 ptdc->pid = QTD_PID_SETUP;
1829 ptdc->err_count = 3;
1830 ptdc->cur_page = 0;
1831 ptdc->ioc = 0;
1832 ptdc->bytes_to_transfer = sizeof(USB_CTRL_SETUP_PACKET);
1833 ptdc->data_toggle = 0;
1834 ptd->hw_buf[0] = MmGetPhysicalAddress(purb->setup_packet).LowPart;
1835
1836 for(i = 1; i < 16; i++)
1837 {
1838 if ((max_packet_size >> i) == 0)
1839 break;
1840 }
1841 i--;
1842 i &= 0xf;
1843
1844 purb->pipe = 0;
1845 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
1846 pipe_content->max_packet_size = i;
1847 pipe_content->endp_addr = endp_num(purb->pendp);
1848 pipe_content->dev_addr = dev_addr;
1849 pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0;
1850 pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0;
1851 pipe_content->trans_type = USB_ENDPOINT_XFER_CONTROL;
1852
1853 pthis = pnext;
1854 ListNext(&td_list, pthis, pnext);
1855
1856 // all the tds's toggle and data_buffer pointer is filled here
1857 toggle = 1;
1858 ehci_fill_td_buf_ptr(purb, start_idx, pthis, td_count - 2, toggle);
1859
1860 for(i = 0; ((i < td_count - 2) && pthis); i++)
1861 {
1862 //construct tds for DATA packets of data stage.
1863 ptd = qtd_from_list_entry(pthis);
1864 ptdc = (PEHCI_QTD_CONTENT) ptd;
1865 ptd->hw_alt_next = EHCI_PTR_TERM;
1866 ptdc->status = 0x80; // active and startXSplit
1867 ptdc->pid = ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT);
1868 ptdc->err_count = 3;
1869 ptdc->cur_page = 0;
1870 ptdc->ioc = 0;
1871
1872 if (pnext)
1873 ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr;
1874 else
1875 ptd->hw_next = EHCI_PTR_TERM;
1876
1877 pthis = pnext;
1878 if (pthis)
1879 ListNext(&td_list, pthis, pnext);
1880 }
1881
1882 if (pthis)
1883 ptd->hw_next = qtd_from_list_entry(pthis)->phys_addr;
1884 else
1885 TRAP();
1886
1887 // ListFirstPrev( &td_list, pthis );
1888 ptd = qtd_from_list_entry(pthis);
1889
1890 //the last is an IN transaction
1891 ptdc = (PEHCI_QTD_CONTENT) ptd;
1892 ptd->hw_alt_next = EHCI_PTR_TERM;
1893 ptdc->status = 0x80;
1894 ptdc->pid = ((td_count > 2)
1895 ? ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_OUT : QTD_PID_IN) : QTD_PID_IN);
1896
1897 ptdc->err_count = 3;
1898 ptdc->cur_page = 0;
1899 ptdc->ioc = 1;
1900 ptdc->bytes_to_transfer = 0;
1901 ptdc->data_toggle = 1;
1902 ptd->hw_next = EHCI_PTR_TERM;
1903
1904 ListFirst(&td_list, pthis);
1905 RemoveEntryList(&td_list);
1906
1907 ptd = qtd_from_list_entry(pthis);
1908 elem_pool_lock(qh_pool, TRUE);
1909 pelnk = elem_pool_alloc_elem(qh_pool);
1910 elem_pool_unlock(qh_pool, TRUE);
1911
1912 if (pelnk == NULL)
1913 {
1914 elem_safe_free(pthis, FALSE);
1915 return STATUS_NO_MORE_ENTRIES;
1916
1917 }
1918 pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
1919 pqhc = (PEHCI_QH_CONTENT) pqh;
1920
1921 pqh->hw_alt_next = pqh->hw_next = EHCI_PTR_TERM;
1922
1923 pqhc->dev_addr = dev_addr;
1924 pqhc->inactive = 0;
1925 pqhc->endp_addr = endp_num(purb->pendp);
1926
1927 if (pipe_content->speed_high)
1928 pqhc->endp_spd = USB_SPEED_HIGH;
1929 else if (pipe_content->speed_low)
1930 pqhc->endp_spd = USB_SPEED_LOW;
1931 else
1932 pqhc->endp_spd = USB_SPEED_FULL;
1933
1934 pqhc->data_toggle = 1; // use dt from qtd
1935 pqhc->is_async_head = 0;
1936 pqhc->max_packet_size = endp_max_packet_size(purb->pendp);
1937
1938 if (pipe_content->speed_high == 0)
1939 pqhc->is_ctrl_endp = 1;
1940 else
1941 pqhc->is_ctrl_endp = 0;
1942
1943 pqhc->reload_counter = EHCI_NAK_RL_COUNT;
1944
1945 // DWORD 2
1946 pqh->hw_info2 = 0;
1947 pqhc->mult = 1;
1948
1949 if (!pipe_content->speed_high)
1950 {
1951 pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
1952 pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
1953 }
1954
1955 purb->td_count = td_count;
1956
1957 ehci_insert_tds_qh(ehci, pqh, ptd);
1958 ehci_insert_qh_urb(purb, pqh);
1959
1960 usb_endp_busy_count_inc(purb->pendp);
1961 ehci_insert_urb_to_schedule(ehci, purb, ret);
1962
1963 if (ret == FALSE)
1964 {
1965 RemoveEntryList(&purb->trasac_list);
1966 RemoveEntryList(&pqh->elem_head_link->elem_link);
1967
1968 elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
1969 elem_safe_free(pthis, FALSE);
1970
1971 InitializeListHead(&purb->trasac_list);
1972 // usb_endp_busy_count_dec( purb->pendp );
1973 return STATUS_UNSUCCESSFUL;
1974 }
1975 return STATUS_SUCCESS;
1976 }
1977
1978 static NTSTATUS
1979 ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb)
1980 {
1981 LONG i, max_packet_size;
1982 PEHCI_QTD ptd;
1983 BOOLEAN ret;
1984 PUSB_DEV pdev;
1985 PURB_HS_PIPE_CONTENT pipe_content;
1986 UCHAR mult_trans, toggle, old_toggle;
1987 PEHCI_ELEM_LINKS pelnk;
1988 PEHCI_QTD_CONTENT ptdc;
1989 PEHCI_QH pqh;
1990 PEHCI_QH_CONTENT pqhc;
1991 PEHCI_FSTN pfstn;
1992
1993 if (ehci == NULL || purb == NULL)
1994 return STATUS_INVALID_PARAMETER;
1995
1996 old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE;
1997 max_packet_size = endp_max_packet_size(purb->pendp);
1998 pdev = dev_from_endp(purb->pendp);
1999
2000 if (max_packet_size == 0 || max_packet_size > 64)
2001 return STATUS_INVALID_PARAMETER;
2002
2003 if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0)
2004 {
2005 if (max_packet_size < purb->data_length)
2006 return STATUS_INVALID_PARAMETER;
2007
2008 for(i = 1; i < 16; i++)
2009 {
2010 if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0)
2011 break;
2012 }
2013 i--;
2014 mult_trans = 1;
2015 }
2016 else
2017 {
2018 mult_trans = endp_mult_count(purb->pendp);
2019 if (max_packet_size * endp_mult_count(purb->pendp) < purb->data_length)
2020 return STATUS_INVALID_PARAMETER;
2021 i = purb->pendp->pusb_endp_desc->bInterval - 1;
2022 }
2023
2024 purb->pipe = 0;
2025 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
2026 pipe_content->interval = i;
2027 pipe_content->trans_type = USB_ENDPOINT_XFER_INT; // bit 0-1
2028 pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5
2029 pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0; // bit 6
2030 pipe_content->trans_dir = endp_dir(purb->pendp); // bit 7
2031 pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
2032 pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18
2033 pipe_content->data_toggle = 1; // bit 19
2034 pipe_content->mult_count = mult_trans;
2035
2036 // pipe_content->start_uframe : 3; // bit 28-30 will be filled later
2037
2038 for(i = 1; i <= 16; i++)
2039 {
2040 if (((ULONG) max_packet_size) >> i)
2041 continue;
2042 else
2043 break;
2044 }
2045 i--;
2046 i &= 0xf;
2047
2048 pipe_content->max_packet_size = i; // bit 20-23 log2( max_packet_size )
2049
2050 if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE)
2051 {
2052 // can not allocate bandwidth for it
2053 return STATUS_UNSUCCESSFUL;
2054 }
2055
2056 // one qtd is enough
2057 elem_pool_lock(qtd_pool, TRUE);
2058 pelnk = elem_pool_alloc_elem(qtd_pool);
2059 elem_pool_unlock(qtd_pool, TRUE);
2060
2061 if (pelnk == NULL)
2062 {
2063 ehci_claim_bandwidth(ehci, purb, FALSE);
2064 return STATUS_NO_MORE_ENTRIES;
2065 }
2066
2067 ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
2068 ptdc = (PEHCI_QTD_CONTENT) ptd;
2069 ptd->hw_next = EHCI_PTR_TERM;
2070 // DWORD 1
2071 ptd->hw_alt_next = EHCI_PTR_TERM;
2072 // DWORD 2
2073 ptdc->status = 0x80;
2074 ptdc->pid = pipe_content->trans_dir ? QTD_PID_IN : QTD_PID_OUT;
2075 ptdc->err_count = 3;
2076 ptdc->cur_page = 0;
2077 ptdc->ioc = 1;
2078 ptdc->bytes_to_transfer = purb->data_length;
2079 toggle = (UCHAR) ehci_fill_td_buf_ptr(purb, 0, &pelnk->elem_link, 1, toggle);
2080
2081 elem_pool_lock(qh_pool, TRUE);
2082 pelnk = elem_pool_alloc_elem(qh_pool);
2083 elem_pool_unlock(qh_pool, TRUE);
2084 if (pelnk == NULL)
2085 {
2086 elem_safe_free(&ptd->elem_head_link->elem_link, TRUE);
2087 InitializeListHead(&purb->trasac_list);
2088 ehci_claim_bandwidth(ehci, purb, FALSE);
2089 return STATUS_NO_MORE_ENTRIES;
2090 }
2091 pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
2092 pqhc = (PEHCI_QH_CONTENT) pqh;
2093
2094 pqh->hw_next = EHCI_PTR_TERM;
2095 pqhc->dev_addr = pdev->dev_addr;
2096 pqhc->inactive = 0;
2097 pqhc->endp_addr = endp_num(purb->pendp);
2098
2099 if (pipe_content->speed_high)
2100 pqhc->endp_spd = USB_SPEED_HIGH;
2101 else if (pipe_content->speed_low)
2102 pqhc->endp_spd = USB_SPEED_LOW;
2103 else
2104 pqhc->endp_spd = USB_SPEED_FULL;
2105
2106 pqhc->data_toggle = 0;
2107 pqhc->is_async_head = 0;
2108 pqhc->max_packet_size = endp_max_packet_size(purb->pendp);
2109 pqhc->is_ctrl_endp = 0;
2110 pqhc->reload_counter = 0;
2111
2112 // DWORD 2
2113 pqh->hw_info2 = 0;
2114 pqhc->mult = mult_trans;
2115
2116 if (pipe_content->speed_high)
2117 {
2118 if (pipe_content->interval == 0) // one poll per uframe
2119 pqhc->s_mask = 0xff;
2120 else if (pipe_content->interval == 1) // one poll every 2 uframe
2121 pqhc->s_mask = pipe_content->start_uframe == 0 ? 0x55 : 0xbb;
2122 else if (pipe_content->interval == 2)
2123 {
2124 pqhc->s_mask = 0x11;
2125 pqhc->s_mask <<= pipe_content->start_uframe;
2126 }
2127 else
2128 {
2129 pqhc->s_mask = 1 << (pipe_content->start_uframe);
2130 }
2131 pqhc->c_mask = 0;
2132 }
2133 else // full/low speed
2134 {
2135 pqhc->s_mask = 1 << pipe_content->start_uframe;
2136 if (pipe_content->start_uframe < 4)
2137 {
2138 pqhc->c_mask = 0x07 << (pipe_content->start_uframe + 2);
2139 }
2140 else if (pipe_content->start_uframe == 4)
2141 {
2142 pqhc->c_mask = 0xc1;
2143 }
2144 else if (pipe_content->start_uframe >= 5)
2145 {
2146 // we need fstn
2147 pqhc->c_mask = 0x03;
2148 if (pipe_content->start_uframe == 5)
2149 {
2150 pqhc->c_mask |= 0x80;
2151 }
2152 }
2153 if (pipe_content->start_uframe >= 4)
2154 {
2155 // chain an fstn
2156 elem_pool_lock(fstn_pool, TRUE);
2157 pelnk = elem_pool_alloc_elem(fstn_pool);
2158 elem_pool_unlock(fstn_pool, TRUE);
2159 if (pelnk == NULL)
2160 {
2161 elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
2162 elem_safe_free(&ptd->elem_head_link->elem_link, TRUE);
2163 InitializeListHead(&purb->trasac_list);
2164 ehci_claim_bandwidth(ehci, purb, FALSE);
2165 return STATUS_NO_MORE_ENTRIES;
2166 }
2167 pfstn = (PEHCI_FSTN) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK);
2168 pfstn->hw_prev = ptd->phys_addr;
2169 pfstn->elem_head_link->purb = purb;
2170 InsertTailList(&ptd->elem_head_link->elem_link, &pfstn->elem_head_link->elem_link);
2171 }
2172 pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
2173 pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
2174 }
2175
2176 // DWORD 3
2177 purb->td_count = 1;
2178
2179 InitializeListHead(&purb->trasac_list);
2180 ehci_insert_tds_qh(ehci, pqh, ptd);
2181 ehci_insert_qh_urb(purb, pqh);
2182
2183 purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle << 31);
2184 usb_endp_busy_count_inc(purb->pendp);
2185
2186 ehci_insert_urb_to_schedule(ehci, purb, ret);
2187
2188 if (ret == FALSE)
2189 {
2190 RemoveEntryList(&purb->trasac_list);
2191 RemoveEntryList(&pqh->elem_head_link->elem_link);
2192
2193 elem_safe_free(&pqh->elem_head_link->elem_link, TRUE);
2194 // an fstn may follow the td
2195 elem_safe_free(&ptd->elem_head_link->elem_link, FALSE);
2196
2197 InitializeListHead(&purb->trasac_list);
2198 ehci_claim_bandwidth(ehci, purb, FALSE);
2199
2200 purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | ((toggle ^ 1) << 31);
2201 // usb_endp_busy_count_dec( purb->pendp );
2202
2203 return STATUS_UNSUCCESSFUL;
2204 }
2205
2206 return STATUS_SUCCESS;
2207 }
2208
2209
2210 static NTSTATUS
2211 ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb)
2212 {
2213 LONG i, j, td_count, temp;
2214 PEHCI_ITD pitd;
2215 PEHCI_SITD psitd;
2216 PEHCI_SITD_CONTENT psitdc;
2217 PEHCI_ITD_CONTENT pitdc;
2218 LIST_ENTRY td_list, *pthis, *pnext, *pprev;
2219 BOOLEAN ret;
2220 PURB_HS_PIPE_CONTENT pipe_content;
2221 PUSB_DEV pdev;
2222 PEHCI_ELEM_LINKS pelnk;
2223
2224 if (ehci == NULL || purb == NULL)
2225 return STATUS_INVALID_PARAMETER;
2226
2227 if (purb->iso_frame_count == 0)
2228 return STATUS_INVALID_PARAMETER;
2229
2230 pdev = dev_from_endp(purb->pendp);
2231 purb->pipe = 0;
2232 pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe;
2233 pipe_content->trans_type = USB_ENDPOINT_XFER_ISOC; // bit 0-1
2234 pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5
2235 pipe_content->speed_low = 0; // bit 6
2236 pipe_content->trans_dir = endp_dir(purb->pendp); // bit 7
2237 pipe_content->dev_addr = pdev->dev_addr; // bit 8-14
2238 pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18
2239 pipe_content->data_toggle = 0; // bit 19
2240
2241 ret = FALSE;
2242 purb->params[0] = j = endp_max_packet_size(purb->pendp);
2243
2244 if (pipe_content->speed_high == 0)
2245 {
2246 // check to see if the frame data is too long to transfer
2247 if (purb->iso_frame_count >= (LONG) ehci->frame_count)
2248 return STATUS_INVALID_PARAMETER;
2249
2250 for(i = 0; i < (LONG) purb->iso_frame_count; i++)
2251 {
2252 if (purb->iso_packet_desc[i].length > j)
2253 return STATUS_INVALID_PARAMETER;
2254 }
2255 }
2256 else
2257 {
2258 // excess the frame count limit
2259 if (purb->iso_frame_count >= (LONG) (ehci->frame_count << 3))
2260 return STATUS_INVALID_PARAMETER;
2261
2262 for(i = 0; i < (LONG) purb->iso_frame_count; i++)
2263 {
2264 if (purb->iso_packet_desc[i].length > j * endp_mult_count(purb->pendp)) // 3 is max mult-transaction count
2265 return STATUS_INVALID_PARAMETER;
2266 }
2267
2268 pipe_content->mult_count = endp_mult_count(purb->pendp);
2269 }
2270
2271 pipe_content->max_packet_size = 0; // bit 20-23 log( max_packet_size ), not correct, should not be used
2272
2273 if (pipe_content->speed_high == 0)
2274 {
2275 for(i = 1; i < 16; i++)
2276 {
2277 if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0)
2278 break;
2279 }
2280 i--;
2281 }
2282 else
2283 {
2284 i = purb->pendp->pusb_endp_desc->bInterval - 1;
2285 }
2286
2287 pipe_content->interval = i; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed
2288
2289 if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE)
2290 return STATUS_UNSUCCESSFUL;
2291
2292 if (pipe_content->speed_high == 0)
2293 {
2294 td_count = purb->iso_frame_count;
2295
2296 // test to see if the last td needs one more sitd for pure complete-split
2297 if (pipe_content->trans_dir == 0)
2298 {
2299 j = (purb->iso_packet_desc[purb->iso_frame_count - 1].length + 187) / 188;
2300 if (purb->iso_packet_desc[purb->iso_frame_count - 1].params.start_uframe + 1 + j >= 8)
2301 {
2302 td_count++;
2303 ret = TRUE;
2304 }
2305 }
2306 elem_pool_lock(itd_pool, TRUE);
2307 pelnk = elem_pool_alloc_elems(itd_pool, td_count);
2308 elem_pool_unlock(itd_pool, TRUE);
2309
2310 }
2311 else
2312 {
2313 i = REAL_INTERVAL;
2314 if (pipe_content->interval >= 3)
2315 {
2316 td_count = purb->iso_frame_count;
2317 j = 0;
2318 }
2319 else
2320 {
2321 j = purb->iso_start_frame & 0x07;
2322 if (j == 0)
2323 {
2324 td_count = (purb->iso_frame_count + 8 / i - 1) * i / 8;
2325 }
2326 else
2327 {
2328 j = 1 + (7 - j) / i; // the leading packets from the 8-trans boundary
2329 td_count = (j >= (LONG) purb->iso_frame_count ?
2330 1 : 1 + (purb->iso_frame_count - j + 8 / i - 1) * i / 8);
2331 }
2332 }
2333
2334 elem_pool_lock(sitd_pool, TRUE);
2335 pelnk = elem_pool_alloc_elems(sitd_pool, td_count);
2336 elem_pool_unlock(sitd_pool, TRUE);
2337 }
2338
2339 if (pelnk == NULL)
2340 {
2341 ehci_claim_bandwidth(ehci, purb, FALSE);
2342 return STATUS_NO_MORE_ENTRIES;
2343 }
2344
2345 InsertTailList(&pelnk->elem_link, &td_list);
2346 ListFirst(&td_list, pthis);
2347 pprev = pthis;
2348 purb->td_count = td_count;
2349
2350 //set up offset for high speed and interval == 1
2351 if (pipe_content->speed_high && pipe_content->interval == 0)
2352 {
2353 for(i = 0; i < (LONG) purb->iso_frame_count; i++)
2354 {
2355 if (i == 0)
2356 purb->iso_packet_desc[i].offset = 0;
2357 else
2358 purb->iso_packet_desc[i].offset = purb->iso_packet_desc[i - 1].offset +
2359 purb->iso_packet_desc[i].length;
2360 }
2361 }
2362
2363 i = 0, temp = 0;
2364
2365 while (pthis)
2366 {
2367 init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link));
2368 if (pipe_content->speed_high)
2369 {
2370 LONG start_uframe, k;
2371 LONG l, pk_idx, offset, start_uf, td_length;
2372 PULONG pbuf;
2373 ULONG phys_addr[8];
2374
2375 pitd = itd_from_list_entry(pthis);
2376 pitdc = (PEHCI_ITD_CONTENT) pitd;
2377 start_uframe = purb->iso_start_frame & 0x07;
2378
2379 // will be filled later
2380 pitd->hw_next = EHCI_PTR_TERM;
2381
2382 // DWORD 9;
2383 pitdc->dev_addr = pdev->dev_addr;
2384 pitdc->endp_num = endp_num(purb->pendp);
2385
2386 pitdc->max_packet_size = endp_max_packet_size(purb->pendp);
2387 pitdc->io_dir = pipe_content->trans_dir;
2388 pitdc->mult = endp_mult_count(purb->pendp);
2389
2390 pbuf = pitd->hw_bufp;
2391 RtlZeroMemory(phys_addr, sizeof(phys_addr));
2392
2393 if (pipe_content->interval < 3)
2394 {
2395 // this indicates one itd schedules more than one uframes
2396 // for multiple transactions described by iso_packet_desc
2397 if (i == 0)
2398 k = td_count == 1 ? purb->iso_frame_count : j; // the first itd
2399 else
2400 k = (LONG) (purb->iso_frame_count - i) <= 8 / REAL_INTERVAL
2401 ? (purb->iso_frame_count - i) : 8 / REAL_INTERVAL;
2402
2403 // j is the header transactions out of the interval
2404 // aligned transactions per td
2405 if (j > 0 && i == 0) // handle the first itd
2406 start_uf = start_uframe;
2407 else
2408 start_uf = start_uframe % REAL_INTERVAL;
2409 }
2410 else
2411 {
2412 k = 1, start_uf = start_uframe & 0x07;
2413 }
2414
2415
2416 // calculate the data to transfer with this td
2417 td_length = 0;
2418 for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL)
2419 {
2420 td_length += purb->iso_packet_desc[pk_idx].length;
2421 phys_addr[l] =
2422 MmGetPhysicalAddress(&purb->data_buffer[purb->iso_packet_desc[pk_idx].offset]).LowPart;
2423 }
2424
2425 // fill the page pointer, and offset
2426 if (pipe_content->interval != 0)
2427 {
2428 for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL)
2429 {
2430 pitdc->status_slot[l].offset = phys_addr[l] & (PAGE_SIZE - 1);
2431 pbuf[l >> pipe_content->interval] |= phys_addr[l] & (~(PAGE_SIZE - 1));
2432 pitdc->status_slot[l].page_sel = l >> pipe_content->interval;
2433 pitdc->status_slot[l].status = 0x08;
2434 pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length;
2435 if (PAGE_SIZE - pitdc->status_slot[l].offset <
2436 (ULONG) purb->iso_packet_desc[pk_idx].length)
2437 {
2438 // fill the next page buf, we can not simply add
2439 // PAGE_SIZE to the phys_addr[ l ].
2440 pbuf[(l >> pipe_content->interval) + 1] |=
2441 MmGetPhysicalAddress((PBYTE)
2442 (((ULONG) & purb->
2443 data_buffer[purb->iso_packet_desc[pk_idx].
2444 offset]) & (~(PAGE_SIZE - 1))) +
2445 PAGE_SIZE).LowPart;
2446 }
2447 }
2448 }
2449 else // interval == 0
2450 {
2451 LONG m, n = 0, n2 = 0;
2452 // fill the page buffer first
2453 // calculate the page buffer needed
2454 offset = phys_addr[0] & (PAGE_SIZE - 1);
2455 if (offset != 0)
2456 {
2457 offset = PAGE_SIZE - offset;
2458 l = 1 + (td_length - offset + PAGE_SIZE - 1) / PAGE_SIZE;
2459 }
2460 else
2461 {
2462 l = (td_length + PAGE_SIZE - 1) / PAGE_SIZE;
2463 }
2464
2465 if (l > 7)
2466 TRAP();
2467
2468 // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp
2469 for(pk_idx = 0; pk_idx < l; pk_idx++)
2470 {
2471 if (pk_idx == 0)
2472 {
2473 offset = phys_addr[start_uf] & (~(PAGE_SIZE - 1));
2474 pbuf[pk_idx] |= offset;
2475 n = pk_idx;
2476 pitdc->status_slot[0].page_sel = n;
2477 n2 = start_uf;
2478 }
2479 else
2480 {
2481 // scan to find if the buf pointer already filled in the td
2482 // since interval = 1, we do not need k * REAL_INTERVAL
2483 // k is transaction count for current td,
2484 // n is hw_bufp( pbuf ) index
2485 // n2 is the last phys_addr index we stopped
2486 for(m = n2; m < start_uf + k; m++)
2487 {
2488 // we can not determine the phys_addr[ x ] is piror
2489 // to offset if it is less than offset.
2490 // because phys_addr is discrete.
2491 // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset )
2492 // continue;
2493
2494 if ((phys_addr[m] & (~(PAGE_SIZE - 1))) == (ULONG) offset)
2495 {
2496 pitdc->status_slot[m].page_sel = n;
2497 continue;
2498 }
2499 break;
2500 }
2501
2502 if (m == start_uf + k)
2503 TRAP();
2504
2505 offset = phys_addr[m] & (~(PAGE_SIZE - 1));
2506 pbuf[pk_idx] |= offset;
2507 n = pk_idx;
2508 n2 = m;
2509 pitdc->status_slot[m].page_sel = n;
2510 }
2511 }
2512 // fill offset and others
2513 for(l = start_uf, pk_idx = i; l < start_uf + k; l++, pk_idx++)
2514 {
2515 pitdc->status_slot[l].offset = (phys_addr[l] & (PAGE_SIZE - 1));
2516 pitdc->status_slot[l].status = 0x08;
2517 pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length;
2518 }
2519 // exhausted
2520 }
2521 i += k;
2522 }
2523 else // full/low speed
2524 {
2525 psitd = sitd_from_list_entry(pthis);
2526 psitdc = (PEHCI_SITD_CONTENT) psitd;
2527 psitd->hw_next = EHCI_PTR_TERM;
2528
2529 // DWORD 1;
2530 psitdc->dev_addr = pdev->dev_addr;
2531 psitdc->endp_num = endp_num(purb->pendp);
2532 psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
2533 psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
2534 psitdc->io_dir = endp_dir(purb->pendp);
2535
2536 psitdc->status &= 0x80; // in DWORD 3
2537
2538 // DWORD 2;
2539 j = (purb->iso_packet_desc[i].length + 187) / 188;
2540
2541 if (psitdc->io_dir == 0)
2542 {
2543 for(; j > 0; j--)
2544 {
2545 psitdc->s_mask |= (1 << (j - 1));
2546 }
2547 psitdc->s_mask <<= purb->iso_packet_desc[i].params.start_uframe & 0x07;
2548 psitdc->c_mask = 0;
2549 }
2550 else
2551 {
2552 LONG k;
2553
2554 psitdc->s_mask = 1 << purb->iso_packet_desc[i].params.start_uframe & 0x07;
2555 // iso split case 2b: ehci spec 1.0
2556 if (j == 6)
2557 j = 5;
2558
2559 j = j - 1 + 2; // actual complete-split count
2560
2561 psitdc->c_mask |= temp >> 8; // the previous sitd's complete split
2562 if (temp >> 8) // link back for sitd split completion
2563 {
2564 psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr;
2565 psitdc->status &= 0x82;
2566 }
2567 else
2568 {
2569 psitd->hw_backpointer = EHCI_PTR_TERM;
2570 }
2571
2572 for(k = temp = 0; k < j; k++)
2573 {
2574 temp |= 1 << k;
2575 }
2576
2577 temp <<= ((purb->iso_packet_desc[i].params.start_uframe & 0x07) + 2);
2578
2579 // only uframe zero and one have complete split for prev sitd
2580 if ((temp >> 8) > 3)
2581 TRAP();
2582
2583 psitdc->c_mask |= temp & 0xff;
2584 }
2585
2586 // DWORD 3:
2587 psitdc->c_prog_mask = 0;
2588 psitdc->bytes_to_transfer = purb->iso_packet_desc[i].length;
2589 psitdc->page_sel = 0;
2590 psitdc->ioc = 0;
2591
2592 // DWORD 4;
2593 j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[i].offset);
2594 psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart;
2595
2596 // DWORD 5;
2597 if (PAGE_SIZE - (j & (PAGE_SIZE - 1)) < (ULONG) purb->iso_packet_desc[i].length)
2598 {
2599 // need to fill another slot
2600 psitdc->page1 =
2601 MmGetPhysicalAddress((PVOID) ((j & ~(PAGE_SIZE - 1)) + PAGE_SIZE)).LowPart >> 12;
2602 }
2603
2604 if (purb->iso_packet_desc[i].length > 188)
2605 psitdc->trans_pos = 0x00;
2606 else if (purb->iso_packet_desc[i].length <= 188)
2607 psitdc->trans_pos = 0x01;
2608
2609 if (psitdc->io_dir == 0)
2610 psitdc->trans_count = (purb->iso_packet_desc[i].length + 187) / 188;
2611
2612 }
2613 ListNext(&td_list, pthis, pnext);
2614 pprev = pthis;
2615 pthis = pnext;
2616
2617 }
2618
2619 if (pipe_content->speed_high == 0)
2620 {
2621 // has an extra sitd to fill at the tail
2622 if (ret)
2623 {
2624 ListFirstPrev(&td_list, pthis);
2625 init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link));
2626
2627 psitd = sitd_from_list_entry(pthis);
2628 psitdc = (PEHCI_SITD_CONTENT) psitd;
2629 psitd->hw_next = EHCI_PTR_TERM;
2630
2631 // DWORD 1;
2632 psitdc->dev_addr = pdev->dev_addr;
2633 psitdc->endp_num = endp_num(purb->pendp);
2634 psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr;
2635 psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx;
2636 psitdc->io_dir = endp_dir(purb->pendp);
2637
2638 psitdc->status &= 0x80; // in DWORD 3
2639
2640 // DWORD 2;
2641 psitdc->s_mask = 0x04; // uframe 2, random selection
2642
2643 psitdc->c_mask = 0x70; // complete split at uframe 4, 5, 6
2644 ListFirstPrev(pthis, pprev);
2645 psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr;
2646 psitdc->status &= 0x82;
2647
2648 // DWORD 3:
2649 psitdc->c_prog_mask = 0;
2650 psitdc->bytes_to_transfer = 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length;
2651 psitdc->page_sel = 0;
2652
2653 j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[purb->iso_frame_count - 1].offset);
2654 // the last byte is overridden.
2655 j += purb->iso_packet_desc[purb->iso_frame_count - 1].length - 1;
2656 psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart;
2657 }
2658
2659 // set the interrupt
2660 ListFirstPrev(&td_list, pthis);
2661 psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis);
2662 psitdc->ioc = 1;
2663 }
2664 else
2665 {
2666 // set the ioc
2667 ListFirstPrev(&td_list, pthis);
2668 pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis);
2669 for(i = 7; i >= 0; i--)
2670 {
2671 if (pitdc->status_slot[i].status == 0x08)
2672 {
2673 pitdc->status_slot[i].ioc = 1;
2674 break;
2675 }
2676 }
2677 if (i < 0)
2678 TRAP();
2679 }
2680
2681 ListFirst(&td_list, pthis);
2682 // ListFirst( &purb->trasac_list, pthis )
2683 RemoveEntryList(&td_list);
2684 InsertTailList(pthis, &purb->trasac_list);
2685
2686 while (pthis)
2687 {
2688 // fill the purb ptr
2689 struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb;
2690 ListNext(&purb->trasac_list, pthis, pnext);
2691 pthis = pnext;
2692 }
2693
2694 //indirectly guarded by pending_endp_list_lock
2695 usb_endp_busy_count_inc(purb->pendp);
2696 ehci_insert_urb_to_schedule(ehci, purb, ret);
2697
2698 if (ret == FALSE)
2699 {
2700 // usb_endp_busy_count_dec( purb->pendp );
2701
2702 ListFirst(&purb->trasac_list, pthis);
2703 RemoveEntryList(&purb->trasac_list);
2704
2705 elem_safe_free(pthis, FALSE);
2706 ehci_claim_bandwidth(ehci, purb, FALSE);
2707 return STATUS_UNSUCCESSFUL;
2708 }
2709 return STATUS_SUCCESS;
2710 }
2711
2712 BOOLEAN NTAPI
2713 //this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule
2714 ehci_sync_insert_urb_schedule(PVOID context)
2715 {
2716 PSYNC_PARAM sync_param;
2717 PEHCI_DEV ehci;
2718 PURB purb;
2719
2720 sync_param = (PSYNC_PARAM) context;
2721 if (sync_param == NULL)
2722 return FALSE;
2723
2724 ehci = sync_param->ehci;
2725 purb = (PURB) sync_param->context;
2726
2727 if (ehci == NULL || purb == NULL)
2728 return (UCHAR) (sync_param->ret = FALSE);
2729
2730 return (UCHAR) (sync_param->ret = ehci_insert_urb_schedule(ehci, purb));
2731 }
2732
2733 static BOOLEAN NTAPI
2734 ehci_sync_cancel_urb(PVOID context)
2735 {
2736 //cancel a single purb
2737 PEHCI_DEV ehci;
2738 PSYNC_PARAM sync_param;
2739 PURB purb2, dest_urb;
2740 PLIST_ENTRY pthis, pnext;
2741 BOOLEAN found = FALSE;
2742
2743 if (context == NULL)
2744 return FALSE;
2745
2746 sync_param = (PSYNC_PARAM) context;
2747 ehci = sync_param->ehci;
2748 dest_urb = (PURB) sync_param->context;
2749
2750 if (ehci == NULL || dest_urb == NULL)
2751 return (UCHAR) (sync_param->ret = FALSE);
2752
2753 ListFirst(&ehci->urb_list, pthis);
2754 while (pthis)
2755 {
2756 purb2 = (PURB) pthis;
2757 if (purb2 == dest_urb)
2758 {
2759 found = TRUE;
2760 purb2->flags |= URB_FLAG_FORCE_CANCEL;
2761 break;
2762 }
2763 ListNext(&ehci->urb_list, pthis, pnext);
2764 pthis = pnext;
2765 }
2766
2767 if (found)
2768 {
2769 press_doorbell(ehci);
2770 }
2771 return (UCHAR) (sync_param->ret = found);
2772 }
2773
2774 NTSTATUS
2775 ehci_cancel_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
2776 //note any fields of the purb can not be referenced unless it is found in some queue
2777 {
2778 PLIST_ENTRY pthis, pnext;
2779 BOOLEAN found;
2780 PURB purb2;
2781
2782 SYNC_PARAM sync_param;
2783
2784 USE_BASIC_NON_PENDING_IRQL;
2785
2786 if (ehci == NULL || purb == NULL || pdev == NULL || pendp == NULL)
2787 return STATUS_INVALID_PARAMETER;
2788
2789 lock_dev(pdev, FALSE);
2790
2791 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
2792 {
2793 unlock_dev(pdev, FALSE);
2794 //delegate to remove device for this job
2795 return STATUS_DEVICE_DOES_NOT_EXIST;
2796 }
2797
2798 if (dev_from_endp(pendp) != pdev)
2799 {
2800 unlock_dev(pdev, FALSE);
2801 return STATUS_INVALID_PARAMETER;
2802 }
2803
2804 if (endp_state(pendp) == USB_ENDP_FLAG_STALL)
2805 {
2806 //it will be canceled in ehci_process_pending_endp
2807 unlock_dev(pdev, FALSE);
2808 return USB_STATUS_ENDPOINT_HALTED;
2809 }
2810
2811 found = FALSE;
2812 ListFirst(&pendp->urb_list, pthis);
2813 while (pthis)
2814 {
2815 purb2 = (PURB) pthis;
2816 if (purb2 == purb)
2817 {
2818 found = TRUE;
2819 RemoveEntryList(pthis);
2820 InitializeListHead(pthis);
2821 break;
2822 }
2823 ListNext(&pendp->urb_list, pthis, pnext);
2824 pthis = pnext;
2825 }
2826 unlock_dev(pdev, FALSE);
2827
2828 if (found)
2829 {
2830 purb->status = STATUS_CANCELLED;
2831
2832 ehci_generic_urb_completion(purb, purb->context);
2833
2834 lock_dev(pdev, FALSE);
2835 pdev->ref_count--;
2836 unlock_dev(pdev, FALSE);
2837 return STATUS_SUCCESS;
2838 }
2839
2840 // search the purb in the purb-list and try to cancel
2841 sync_param.ehci = ehci;
2842 sync_param.context = purb;
2843
2844 KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urb, &sync_param);
2845
2846 found = sync_param.ret;
2847
2848 if (found)
2849 return USB_STATUS_CANCELING;
2850
2851 return STATUS_INVALID_PARAMETER;
2852 }
2853
2854 VOID
2855 ehci_generic_urb_completion(PURB purb, PVOID context)
2856 {
2857 PUSB_DEV pdev;
2858 BOOLEAN is_ctrl = FALSE;
2859 USE_NON_PENDING_IRQL;
2860
2861 old_irql = KeGetCurrentIrql();
2862 if (old_irql > DISPATCH_LEVEL)
2863 TRAP();
2864
2865 if (old_irql < DISPATCH_LEVEL)
2866 KeRaiseIrql(DISPATCH_LEVEL, &old_irql);
2867
2868 pdev = purb->pdev;
2869 if (purb == NULL)
2870 goto LBL_LOWER_IRQL;
2871
2872 if (pdev == NULL)
2873 goto LBL_LOWER_IRQL;
2874
2875 lock_dev(pdev, TRUE);
2876
2877 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
2878 {
2879 // no need to do following statistics
2880 unlock_dev(pdev, TRUE);
2881 goto LBL_CLIENT_PROCESS;
2882 }
2883 if (usb_error(purb->status))
2884 {
2885 pdev->error_count++;
2886 }
2887
2888 if (purb->pendp == &pdev->default_endp)
2889 {
2890 if (usb_halted(purb->status))
2891 {
2892 pdev->time_out_count++;
2893 if (pdev->time_out_count > 3)
2894 {
2895 dev_set_state(pdev, USB_DEV_STATE_ZOMB);
2896 ehci_dbg_print(DBGLVL_MAXIMUM,
2897 ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
2898 pdev));
2899 }
2900 }
2901 else
2902 pdev->time_out_count = 0;
2903
2904 }
2905
2906 if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_CONTROL)
2907 is_ctrl = TRUE;
2908
2909 unlock_dev(pdev, TRUE);
2910
2911 LBL_CLIENT_PROCESS:
2912 if (!is_ctrl)
2913 {
2914 if (purb->completion)
2915 purb->completion(purb, context);
2916 }
2917 else
2918 {
2919 if (purb->ctrl_req_context.ctrl_stack_count == 0)
2920 {
2921 if (purb->completion)
2922 purb->completion(purb, context);
2923 }
2924 else
2925 {
2926 // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
2927 // if( pstack->urb_completion )
2928 // pstack->urb_completion( purb, pstack->context );
2929 usb_call_ctrl_completion(purb);
2930 }
2931 }
2932
2933 LBL_LOWER_IRQL:
2934 if (old_irql < DISPATCH_LEVEL)
2935 KeLowerIrql(old_irql);
2936
2937 return;
2938 }
2939
2940 NTSTATUS
2941 ehci_rh_submit_urb(PUSB_DEV pdev, PURB purb)
2942 {
2943 PUSB_DEV_MANAGER dev_mgr;
2944 PTIMER_SVC ptimer;
2945 PUSB_CTRL_SETUP_PACKET psetup;
2946 PEHCI_DEV ehci;
2947 NTSTATUS status;
2948 PHUB2_EXTENSION hub_ext;
2949 PUSB_PORT_STATUS ps, psret;
2950 LONG i;
2951 UCHAR port_count;
2952
2953 USE_NON_PENDING_IRQL;
2954 if (pdev == NULL || purb == NULL)
2955 return STATUS_INVALID_PARAMETER;
2956
2957 dev_mgr = dev_mgr_from_dev(pdev);
2958
2959 KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql);
2960 lock_dev(pdev, FALSE);
2961 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
2962 {
2963 unlock_dev(pdev, FALSE);
2964 KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql);
2965 return STATUS_DEVICE_DOES_NOT_EXIST;
2966 }
2967
2968 ehci = ehci_from_hcd(pdev->hcd);
2969 psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;
2970
2971 hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext);
2972 port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count;
2973
2974 switch (endp_type(purb->pendp))
2975 {
2976 case USB_ENDPOINT_XFER_CONTROL:
2977 {
2978 if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS)
2979 {
2980 //get-port-status
2981 if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength < 4)
2982 {
2983 purb->status = STATUS_INVALID_PARAMETER;
2984 break;
2985 }
2986
2987 i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
2988 status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
2989 ps = &hub_ext->rh_port_status[psetup->wIndex];
2990
2991 psret = (PUSB_PORT_STATUS) purb->data_buffer;
2992 ps->wPortStatus = 0;
2993
2994 if (status & PORT_CCS)
2995 {
2996 ps->wPortStatus |= USB_PORT_STAT_CONNECTION;
2997 }
2998 if (status & PORT_PE)
2999 {
3000 ps->wPortStatus |= USB_PORT_STAT_ENABLE;
3001 ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec
3002 }
3003 if (status & PORT_PR)
3004 {
3005 ps->wPortStatus |= USB_PORT_STAT_RESET;
3006 }
3007 if (status & PORT_SUSP)
3008 {
3009 ps->wPortStatus |= USB_PORT_STAT_SUSPEND;
3010 }
3011 if (PORT_USB11(status))
3012 {
3013 ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED;
3014 }
3015
3016 //always power on
3017 ps->wPortStatus |= USB_PORT_STAT_POWER;
3018
3019 //now set change field
3020 if ((status & PORT_CSC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED))
3021 {
3022 ps->wPortChange |= USB_PORT_STAT_C_CONNECTION;
3023 }
3024 if ((status & PORT_PEC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED))
3025 {
3026 ps->wPortChange |= USB_PORT_STAT_C_ENABLE;
3027 }
3028
3029 //don't touch other fields, might be filled by
3030 //other function
3031
3032 usb_dbg_print(DBGLVL_MAXIMUM,
3033 ("ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
3034 ps->wPortStatus, ps->wPortChange, ps));
3035
3036 psret->wPortChange = ps->wPortChange;
3037 psret->wPortStatus = ps->wPortStatus;
3038
3039 purb->status = STATUS_SUCCESS;
3040
3041 break;
3042 }
3043 else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE)
3044 {
3045 //clear-port-feature
3046 if (psetup->wIndex == 0 || psetup->wIndex > port_count)
3047 {
3048 purb->status = STATUS_INVALID_PARAMETER;
3049 break;
3050 }
3051
3052 i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1;
3053 ps = &hub_ext->rh_port_status[psetup->wIndex];
3054
3055 purb->status = STATUS_SUCCESS;
3056 switch (psetup->wValue)
3057 {
3058 case USB_PORT_FEAT_C_CONNECTION:
3059 {
3060 SET_RH2_PORTSTAT(i, USBPORTSC_CSC);
3061 status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
3062 usb_dbg_print(DBGLVL_MAXIMUM,
3063 ("ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex));
3064 ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
3065 break;
3066 }
3067 case USB_PORT_FEAT_C_ENABLE:
3068 {
3069 SET_RH2_PORTSTAT(i, USBPORTSC_PEC);
3070 status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
3071 usb_dbg_print(DBGLVL_MAXIMUM,
3072 ("ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex));
3073 ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE;
3074 break;
3075 }
3076 case USB_PORT_FEAT_C_RESET:
3077 {
3078 ps->wPortChange &= ~USB_PORT_STAT_C_RESET;
3079 //the reset signal is down in rh_timer_svc_reset_port_completion
3080 // enable or not is set by host controller
3081 // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
3082 usb_dbg_print(DBGLVL_MAXIMUM,
3083 ("ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
3084 psetup->wIndex));
3085 break;
3086 }
3087 case USB_PORT_FEAT_ENABLE:
3088 {
3089 ps->wPortStatus &= ~USB_PORT_STAT_ENABLE;
3090 CLR_RH2_PORTSTAT(i, USBPORTSC_PE);
3091 status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i));
3092 usb_dbg_print(DBGLVL_MAXIMUM,
3093 ("ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex));
3094 break;
3095 }
3096 default:
3097 purb->status = STATUS_UNSUCCESSFUL;
3098 }
3099 break;
3100 }
3101 else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE)
3102 {
3103 // get bus state
3104 if (psetup->wIndex == 0 || psetup->wIndex