2 * ehci.c - USB driver stack project for Windows NT 4.0
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
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.
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.
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
22 #include "usbdriver.h"
25 //----------------------------------------------------------
29 #define DEFAULT_ENDP( enDP ) \
30 ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP )
32 #define dev_from_endp( enDP ) \
33 ( DEFAULT_ENDP( enDP )\
34 ? ( ( PUSB_DEV )( enDP )->pusb_if )\
35 : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) )
37 #define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK )
39 #define endp_num( enDP ) \
40 ( DEFAULT_ENDP( enDP )\
42 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) )
44 #define endp_dir( enDP ) \
45 ( DEFAULT_ENDP( enDP )\
47 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? 1 : 0 )
49 #define dev_set_state( pdEV, staTE ) \
50 ( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) )
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\
57 : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) )
59 #define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 )
61 #define release_adapter( padapTER ) HalPutDmaAdapter(padapTER)
63 #define get_int_idx( _urb, _idx ) \
66 interVAL = ( UCHAR )( ( _urb )->pipe >> 24 );\
67 for( _idx = 1; _idx < 9; _idx++ )\
76 #define ehci_insert_urb_to_schedule( eHCI, pURB, rET ) \
78 SYNC_PARAM sync_param;\
79 sync_param.ehci = eHCI;\
80 sync_param.context = ( pURB );\
81 sync_param.ret = FALSE;\
83 rET = KeSynchronizeExecution( eHCI->pdev_ext->ehci_int, ehci_sync_insert_urb_schedule, &sync_param );\
86 #define EHCI_ERROR_INT ( STS_FATAL | STS_ERR )
87 #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 ) )
88 #define EHCI_QTD_ERROR( qtd_contENT ) ( ( qtd_contENT )->status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) )
90 #define EHCI_READ_PORT_ULONG( pul ) ( *pul )
91 #define EHCI_WRITE_PORT_ULONG( pul, src ) \
95 cmd_reg = EHCI_READ_PORT_ULONG( ehci->port_base + EHCI_USBCMD );\
100 #define EHCI_READ_PORT_UCHAR( pch ) ( *pch )
101 #define EHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src )
103 #define EHCI_READ_PORT_USHORT( psh ) ( *psh )
104 #define EHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src )
106 #define press_doorbell( eHCI ) \
109 tmp = EHCI_READ_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ) );\
111 EHCI_WRITE_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ), tmp );\
113 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
115 #define qh_from_list_entry( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
116 #define qtd_from_list_entry( pentry ) ( ( PEHCI_QTD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
117 #define itd_from_list_entry( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
118 #define sitd_from_list_entry( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
119 #define fstn_from_list_entry( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
121 #define qh_from_schedule( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
122 #define itd_from_schedule( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
123 #define sitd_from_schedule( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
124 #define fstn_from_schedule( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
126 #define elem_type( ptr, from_list ) ( from_list ? ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, elem_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) \
127 : ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, sched_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) )
129 // #define elem_type_list_entry( pentry ) ( ( qh_from_schedule( pentry )->hw_next & 0x06 ) >> 1 )
130 #define elem_type_list_entry( pentry ) ( elem_type( pentry, TRUE ) )
132 #define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \
134 parent_HUB = pDEV->parent_dev;\
135 port_IDX = pdev->port_idx;\
138 if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\
143 if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\
145 port_IDX = parent_HUB->port_idx;\
146 parent_HUB = parent_HUB->parent_dev;\
153 #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 ) )
154 #define REAL_INTERVAL ( 1 << pipe_content->interval )
156 #define elem_safe_free( ptHIS, single ) \
159 em_type = ( UCHAR )elem_type( ptHIS, TRUE ); \
162 if( em_type == INIT_LIST_FLAG_QTD )\
164 elem_pool_lock( qtd_pool, TRUE );\
166 elem_pool_free_elem( qtd_from_list_entry( ptHIS )->elem_head_link );\
168 elem_pool_free_elems( qtd_from_list_entry( ptHIS )->elem_head_link );\
169 elem_pool_unlock( qtd_pool, TRUE );\
171 else if( em_type == INIT_LIST_FLAG_ITD )\
173 elem_pool_lock( itd_pool, TRUE );\
175 elem_pool_free_elem( itd_from_list_entry( ptHIS )->elem_head_link );\
177 elem_pool_free_elems( itd_from_list_entry( ptHIS )->elem_head_link );\
178 elem_pool_unlock( itd_pool, TRUE );\
180 else if( em_type == INIT_LIST_FLAG_SITD )\
182 elem_pool_lock( sitd_pool, TRUE );\
184 elem_pool_free_elem( sitd_from_list_entry( ptHIS )->elem_head_link );\
186 elem_pool_free_elems( sitd_from_list_entry( ptHIS )->elem_head_link );\
187 elem_pool_unlock( sitd_pool, TRUE );\
189 else if( em_type == INIT_LIST_FLAG_FSTN )\
191 elem_pool_lock( fstn_pool, TRUE );\
193 elem_pool_free_elem( fstn_from_list_entry( ptHIS )->elem_head_link );\
195 elem_pool_free_elems( fstn_from_list_entry( ptHIS )->elem_head_link );\
196 elem_pool_unlock( fstn_pool, TRUE );\
198 else if( em_type == INIT_LIST_FLAG_QH )\
200 elem_pool_lock( qh_pool, TRUE );\
202 elem_pool_free_elem( qh_from_list_entry( ptHIS )->elem_head_link );\
204 elem_pool_free_elems( qh_from_list_entry( ptHIS )->elem_head_link );\
205 elem_pool_unlock( qh_pool, TRUE );\
211 #define min( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
214 #define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
217 #define CLR_RH2_PORTSTAT( port_idx, x ) \
220 addr = ( PULONG )( ehci->port_base + port_idx ); \
221 status = EHCI_READ_PORT_ULONG( addr ); \
222 status = ( status & 0xfffffd5 ) & ~( x ); \
223 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
226 #define SET_RH2_PORTSTAT( port_idx, x ) \
229 addr = ( PULONG )( ehci->port_base + port_idx ); \
230 status = EHCI_READ_PORT_ULONG( addr ); \
232 status = ( status & 0xffffffd1 ) | ( x ); \
234 status = ( status & 0xffffffd5 ) | ( x ); \
235 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
238 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
239 #define ehci_from_dev( dEV ) ( ehci_from_hcd( dEV->hcd ) )
241 #define ehci_copy_overlay( pQHC, pTDC ) \
246 pqh1 = ( PEHCI_QH )( pQHC );\
247 ptd1 = ( PEHCI_QTD )( pTDC );\
248 td_size = get_elem_phys_part_size( INIT_LIST_FLAG_QTD );\
249 ( pQHC )->cur_qtd_ptr = ptd1->phys_addr;\
250 RtlZeroMemory( &( pQHC )->cur_qtd, td_size );\
251 ( pQHC )->cur_qtd.data_toggle = ( pTDC )->data_toggle;\
252 pqh1->hw_qtd_next = ptd1->phys_addr;\
253 pqh1->hw_alt_next = EHCI_PTR_TERM;\
267 } SYNC_PARAM
, *PSYNC_PARAM
;
270 ehci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
);
272 BOOLEAN
ehci_init_schedule(PEHCI_DEV ehci
, PADAPTER_OBJECT padapter
);
274 BOOLEAN
ehci_release(PDEVICE_OBJECT pdev
, PUSB_DEV_MANAGER dev_mgr
);
276 static VOID
ehci_stop(PEHCI_DEV ehci
);
278 BOOLEAN
ehci_destroy_schedule(PEHCI_DEV ehci
);
280 BOOLEAN NTAPI
ehci_sync_insert_urb_schedule(PVOID context
);
282 VOID
ehci_init_hcd_interface(PEHCI_DEV ehci
);
284 NTSTATUS
ehci_rh_submit_urb(PUSB_DEV rh
, PURB purb
);
286 NTSTATUS
ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp
);
288 VOID
ehci_generic_urb_completion(PURB purb
, PVOID context
);
290 static NTSTATUS
ehci_internal_submit_bulk(PEHCI_DEV ehci
, PURB purb
);
292 static NTSTATUS
ehci_internal_submit_int(PEHCI_DEV ehci
, PURB purb
);
294 static NTSTATUS
ehci_internal_submit_ctrl(PEHCI_DEV ehci
, PURB purb
);
296 static NTSTATUS
ehci_internal_submit_iso(PEHCI_DEV ehci
, PURB purb
);
298 static ULONG
ehci_scan_iso_error(PEHCI_DEV ehci
, PURB purb
);
300 BOOLEAN
ehci_claim_bandwidth(PEHCI_DEV ehci
, PURB purb
, BOOLEAN claim_bw
); //true to claim band-width, false to free band-width
302 static VOID
ehci_insert_bulk_schedule(PEHCI_DEV ehci
, PURB purb
);
304 #define ehci_insert_control_schedule ehci_insert_bulk_schedule
306 static VOID
ehci_insert_int_schedule(PEHCI_DEV ehci
, PURB purb
);
308 static VOID
ehci_insert_iso_schedule(PEHCI_DEV ehci
, PURB purb
);
310 #define ehci_remove_control_from_schedule ehci_remove_bulk_from_schedule
312 PDEVICE_OBJECT
ehci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, PUSB_DEV_MANAGER dev_mgr
);
314 PDEVICE_OBJECT
ehci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
);
316 BOOLEAN
ehci_delete_device(PDEVICE_OBJECT pdev
, PUSB_DEV_MANAGER dev_mgr
);
318 VOID
ehci_get_capabilities(PEHCI_DEV ehci
, PBYTE base
);
320 BOOLEAN NTAPI
ehci_isr(PKINTERRUPT interrupt
, PVOID context
);
322 BOOLEAN
ehci_start(PHCD hcd
);
324 extern VOID
rh_timer_svc_reset_port_completion(PUSB_DEV dev
, PVOID context
);
326 extern VOID
rh_timer_svc_int_completion(PUSB_DEV dev
, PVOID context
);
328 extern USB_DEV_MANAGER g_dev_mgr
;
331 ULONG debug_level
= DBGLVL_MAXIMUM
;
332 PDRIVER_OBJECT usb_driver_obj
= NULL
;
334 //pending endpoint pool funcs
336 ehci_wait_ms(PEHCI_DEV ehci
, LONG ms
)
342 lms
.QuadPart
= -10 * ms
;
343 KeSetTimer(&ehci
->reset_timer
, lms
, NULL
);
345 KeWaitForSingleObject(&ehci
->reset_timer
, Executive
, KernelMode
, FALSE
, NULL
);
351 init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
)
357 pool
->pending_endp_array
=
358 usb_alloc_mem(NonPagedPool
, sizeof(UHCI_PENDING_ENDP
) * UHCI_MAX_PENDING_ENDPS
);
359 InitializeListHead(&pool
->free_que
);
360 pool
->free_count
= 0;
361 pool
->total_count
= UHCI_MAX_PENDING_ENDPS
;
362 KeInitializeSpinLock(&pool
->pool_lock
);
364 for(i
= 0; i
< MAX_TIMER_SVCS
; i
++)
366 free_pending_endp(pool
, &pool
->pending_endp_array
[i
]);
374 free_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, PUHCI_PENDING_ENDP pending_endp
)
376 if (pool
== NULL
|| pending_endp
== NULL
)
381 RtlZeroMemory(pending_endp
, sizeof(UHCI_PENDING_ENDP
));
382 InsertTailList(&pool
->free_que
, (PLIST_ENTRY
) & pending_endp
->endp_link
);
389 alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, LONG count
)
391 PUHCI_PENDING_ENDP
new;
392 if (pool
== NULL
|| count
!= 1)
395 if (pool
->free_count
<= 0)
398 new = (PUHCI_PENDING_ENDP
) RemoveHeadList(&pool
->free_que
);
404 destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
)
409 InitializeListHead(&pool
->free_que
);
410 pool
->free_count
= pool
->total_count
= 0;
411 usb_free_mem(pool
->pending_endp_array
);
412 pool
->pending_endp_array
= NULL
;
418 #define ehci_wait_ms uhci_wait_ms
419 extern VOID
uhci_wait_ms(PEHCI_DEV ehci
, LONG ms
);
421 extern BOOLEAN
init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
);
423 extern BOOLEAN
free_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, PUHCI_PENDING_ENDP pending_endp
);
425 extern PUHCI_PENDING_ENDP
alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, LONG count
);
427 extern BOOLEAN
destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
);
431 //end of pending endpoint pool funcs
434 ehci_cancel_pending_endp_urb(IN PVOID Parameter
)
436 PLIST_ENTRY abort_list
;
439 USE_BASIC_NON_PENDING_IRQL
;
441 abort_list
= (PLIST_ENTRY
) Parameter
;
443 if (abort_list
== NULL
)
446 while (IsListEmpty(abort_list
) == FALSE
)
448 //these devs are protected by purb's ref-count
449 purb
= (PURB
) RemoveHeadList(abort_list
);
451 // purb->status is set when they are added to abort_list
453 ehci_generic_urb_completion(purb
, purb
->context
);
455 lock_dev(pdev
, FALSE
);
457 unlock_dev(pdev
, FALSE
);
459 usb_free_mem(abort_list
);
464 ehci_process_pending_endp(PEHCI_DEV ehci
)
467 LIST_ENTRY temp_list
, abort_list
;
471 NTSTATUS can_submit
= STATUS_SUCCESS
;
472 PWORK_QUEUE_ITEM pwork_item
;
473 PLIST_ENTRY cancel_list
;
474 PUSB_DEV pparent
= NULL
;
483 InitializeListHead(&temp_list
);
484 InitializeListHead(&abort_list
);
487 ehci_dbg_print(DBGLVL_MEDIUM
, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci
));
489 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
490 while (IsListEmpty(&ehci
->pending_endp_list
) == FALSE
)
493 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_process_pending_endp(): pending_endp_list=0x%x\n",
494 &ehci
->pending_endp_list
));
497 pthis
= RemoveHeadList(&ehci
->pending_endp_list
);
498 pendp
= ((PUHCI_PENDING_ENDP
) pthis
)->pendp
;
499 pdev
= dev_from_endp(pendp
);
500 lock_dev(pdev
, TRUE
);
502 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
504 unlock_dev(pdev
, TRUE
);
505 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
506 //delegate to ehci_remove_device for remiving the purb queue on the endpoint
509 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
511 // prepare split transaction
512 unlock_dev(pdev
, TRUE
);
514 // pparent won't be removed when pending_endp_list_lock is acquired.
515 get_parent_hs_hub(pdev
, pparent
, port_idx
);
520 ehci_dbg_print(DBGLVL_MEDIUM
,
521 ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n"));
522 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
526 if (hub_lock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
)) == FALSE
)
528 lock_dev(pdev
, TRUE
);
529 if (dev_state(pdev
) != USB_DEV_STATE_ZOMB
)
531 // reinsert the pending-endp to the list
532 InsertTailList(&temp_list
, pthis
);
533 unlock_dev(pdev
, TRUE
);
537 // delegate to ehci_remove_device for purb removal
538 unlock_dev(pdev
, TRUE
);
539 free_pending_endp(&ehci
->pending_endp_pool
,
540 struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
545 // backup the hub address for future use
546 hub_addr
= pparent
->dev_addr
;
548 lock_dev(pdev
, TRUE
);
549 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
551 unlock_dev(pdev
, TRUE
);
552 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
553 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
560 if (endp_state(pendp
) == USB_ENDP_FLAG_STALL
)
562 while (IsListEmpty(&pendp
->urb_list
) == FALSE
)
564 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
565 purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
566 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
568 InitializeListHead(&pendp
->urb_list
);
569 unlock_dev(pdev
, TRUE
);
570 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
572 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
576 if (IsListEmpty(&pendp
->urb_list
) == FALSE
)
578 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
583 InitializeListHead(&pendp
->urb_list
);
584 unlock_dev(pdev
, TRUE
);
585 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
587 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
593 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
= hub_addr
;
594 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
= port_idx
;
597 // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
598 switch (endp_type(pendp
))
600 case USB_ENDPOINT_XFER_BULK
:
602 can_submit
= ehci_internal_submit_bulk(ehci
, purb
);
605 case USB_ENDPOINT_XFER_CONTROL
:
607 can_submit
= ehci_internal_submit_ctrl(ehci
, purb
);
610 case USB_ENDPOINT_XFER_INT
:
612 can_submit
= ehci_internal_submit_int(ehci
, purb
);
615 case USB_ENDPOINT_XFER_ISOC
:
617 can_submit
= ehci_internal_submit_iso(ehci
, purb
);
622 if (can_submit
== STATUS_NO_MORE_ENTRIES
)
624 //no enough bandwidth or tds
625 InsertHeadList(&pendp
->urb_list
, &purb
->urb_link
);
626 InsertTailList(&temp_list
, pthis
);
630 // otherwise error or success
631 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
633 if (can_submit
!= STATUS_SUCCESS
)
636 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
637 purb
->status
= can_submit
;
640 unlock_dev(pdev
, TRUE
);
641 if (can_submit
!= STATUS_SUCCESS
&& tt_needed
)
643 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
647 if (IsListEmpty(&temp_list
) == FALSE
)
649 //re-append them to the pending_endp_list
650 ListFirst(&temp_list
, pthis
);
651 RemoveEntryList(&temp_list
);
652 MergeList(&ehci
->pending_endp_list
, pthis
);
654 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
656 if (IsListEmpty(&abort_list
) == FALSE
)
659 cancel_list
= (PLIST_ENTRY
) usb_alloc_mem(NonPagedPool
, sizeof(WORK_QUEUE_ITEM
) + sizeof(LIST_ENTRY
));
662 ListFirst(&abort_list
, pthis
);
663 RemoveEntryList(&abort_list
);
664 InsertTailList(pthis
, cancel_list
);
666 pwork_item
= (PWORK_QUEUE_ITEM
) & cancel_list
[1];
668 // we do not need to worry the ehci_cancel_pending_endp_urb running when the
669 // driver is unloading since purb-reference count will prevent the dev_mgr to
670 // quit till all the reference count to the dev drop to zero.
671 ExInitializeWorkItem(pwork_item
, ehci_cancel_pending_endp_urb
, (PVOID
) cancel_list
);
672 ExQueueWorkItem(pwork_item
, DelayedWorkQueue
);
678 ehci_submit_urb(PEHCI_DEV ehci
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
681 PUHCI_PENDING_ENDP pending_endp
;
686 return STATUS_INVALID_PARAMETER
;
688 if (pdev
== NULL
|| pendp
== NULL
|| purb
== NULL
)
690 // give a chance to those pending urb, especially for clearing hub tt
691 ehci_process_pending_endp(ehci
);
692 return STATUS_INVALID_PARAMETER
;
695 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
696 lock_dev(pdev
, TRUE
);
698 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
700 status
= purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
704 if (dev_class(pdev
) == USB_DEV_CLASS_ROOT_HUB
)
706 unlock_dev(pdev
, TRUE
);
707 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
708 status
= ehci_rh_submit_urb(pdev
, purb
);
715 purb
->pendp
= &pdev
->default_endp
;
717 if (dev_from_endp(purb
->pendp
) != pdev
)
719 status
= purb
->status
= STATUS_INVALID_PARAMETER
;
723 if (endp_state(purb
->pendp
) == USB_ENDP_FLAG_STALL
)
725 status
= purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
729 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
736 purb
->rest_bytes
= purb
->data_length
;
738 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_BULK
)
739 purb
->bytes_to_transfer
= (purb
->data_length
> EHCI_MAX_SIZE_TRANSFER
? EHCI_MAX_SIZE_TRANSFER
: purb
->data_length
); //multiple transfer for large data block
741 purb
->bytes_to_transfer
= purb
->data_length
;
743 ehci_dbg_print(DBGLVL_MEDIUM
, ("ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb
->bytes_to_transfer
));
745 purb
->bytes_transfered
= 0;
746 InitializeListHead(&purb
->trasac_list
);
747 purb
->last_finished_td
= &purb
->trasac_list
;
748 purb
->flags
&= ~(URB_FLAG_STATE_MASK
| URB_FLAG_IN_SCHEDULE
| URB_FLAG_FORCE_CANCEL
);
749 purb
->flags
|= URB_FLAG_STATE_PENDING
;
752 i
= IsListEmpty(&pendp
->urb_list
);
753 InsertTailList(&pendp
->urb_list
, &purb
->urb_link
);
755 pdev
->ref_count
++; //for purb reference
759 //there is purb pending, simply queue it and return
760 status
= purb
->status
= STATUS_PENDING
;
763 else if (usb_endp_busy_count(purb
->pendp
) && endp_type(purb
->pendp
) != USB_ENDPOINT_XFER_ISOC
)
766 //No purb waiting but purb overlap not allowed,
767 //so leave it in queue and return, will be scheduled
770 status
= purb
->status
= STATUS_PENDING
;
774 pending_endp
= alloc_pending_endp(&ehci
->pending_endp_pool
, 1);
775 if (pending_endp
== NULL
)
778 status
= purb
->status
= STATUS_UNSUCCESSFUL
;
782 pending_endp
->pendp
= purb
->pendp
;
783 InsertTailList(&ehci
->pending_endp_list
, &pending_endp
->endp_link
);
785 unlock_dev(pdev
, TRUE
);
786 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
788 ehci_process_pending_endp(ehci
);
789 return STATUS_PENDING
;
793 RemoveEntryList(&purb
->urb_link
);
796 unlock_dev(pdev
, TRUE
);
797 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
798 ehci_process_pending_endp(ehci
);
803 ehci_set_error_code(PURB purb
, ULONG raw_status
)
805 PURB_HS_PIPE_CONTENT pipe_content
;
807 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
809 //test if the purb is canceled
810 if (purb
->flags
& URB_FLAG_FORCE_CANCEL
)
812 purb
->status
= STATUS_CANCELLED
;
814 else if (raw_status
== 0)
815 purb
->status
= STATUS_SUCCESS
;
817 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
||
818 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
819 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
822 if (raw_status
& QTD_STS_BABBLE
)
823 purb
->status
= USB_STATUS_DATA_OVERRUN
;
825 else if (raw_status
& QTD_STS_HALT
)
826 purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
828 else if (raw_status
& QTD_STS_DBE
)
829 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
831 else if (raw_status
& QTD_STS_XACT
)
832 purb
->status
= USB_STATUS_CRC
; // crc is included in xact err.
834 else if (raw_status
& QTD_STS_MMF
)
835 purb
->status
= USB_STATUS_BTSTUFF
;
838 purb
->status
= STATUS_UNSUCCESSFUL
;
840 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
842 if (pipe_content
->speed_high
)
844 if (raw_status
& ITD_STS_BUFERR
)
845 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
847 else if (raw_status
& ITD_STS_BABBLE
)
848 purb
->status
= USB_STATUS_BABBLE_DETECTED
;
850 else if (raw_status
& ITD_STS_XACTERR
) // Xact Err
851 purb
->status
= USB_STATUS_CRC
;
854 purb
->status
= STATUS_UNSUCCESSFUL
;
859 if (raw_status
& SITD_STS_ERR
) // ERR is received from hub's tt
860 purb
->status
= USB_STATUS_ERROR
;
862 else if (raw_status
& SITD_STS_DBE
)
863 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
865 else if (raw_status
& SITD_STS_BABBLE
)
866 purb
->status
= USB_STATUS_BABBLE_DETECTED
;
868 else if (raw_status
& SITD_STS_XACTERR
) // Xact Error
869 purb
->status
= USB_STATUS_CRC
;
871 else if (raw_status
& SITD_STS_MISSFRM
) // missing microframe
872 purb
->status
= USB_STATUS_DATA_TOGGLE_MISMATCH
;
875 purb
->status
= STATUS_UNSUCCESSFUL
;
878 if (purb
->status
!= STATUS_SUCCESS
)
880 hcd_dbg_print(DBGLVL_MEDIUM
, ("ehci_set_error_code(): error status 0x%x\n", raw_status
));
886 ehci_sync_remove_urb_finished(PVOID context
)
889 PLIST_ENTRY pthis
, pnext
, ptemp
;
893 pparam
= (PSYNC_PARAM
) context
;
895 ptemp
= (PLIST_ENTRY
) pparam
->context
;
899 return (UCHAR
) (pparam
->ret
= FALSE
);
902 ListFirst(&ehci
->urb_list
, pthis
);
905 //remove urbs not in the schedule
906 ListNext(&ehci
->urb_list
, pthis
, pnext
);
909 if ((purb
->flags
& URB_FLAG_IN_SCHEDULE
) == 0)
911 //finished or canceled( not applied for split bulk ).
912 RemoveEntryList(pthis
);
913 InsertTailList(ptemp
, pthis
);
922 ehci_dpc_callback(PKDPC dpc
, PVOID context
, PVOID sysarg1
, PVOID sysarg2
)
927 PLIST_ENTRY pthis
, pnext
;
931 PUHCI_PENDING_ENDP pending_endp
;
937 ULONG ehci_status
, urb_status
;
939 SYNC_PARAM sync_param
;
941 USE_BASIC_NON_PENDING_IRQL
;
943 ehci
= (PEHCI_DEV
) context
;
947 ehci_status
= (ULONG
) sysarg1
;
949 InitializeListHead(&temp_list
);
951 sync_param
.ehci
= ehci
;
952 sync_param
.context
= (PVOID
) & temp_list
;
954 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci
));
955 //remove finished purb from ehci's purb-list
956 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_remove_urb_finished
, &sync_param
);
958 //release resources( itds, sitds, fstns, tds, and qhs ) allocated for the purb
959 while (IsListEmpty(&temp_list
) == FALSE
)
961 //not in any public queue, if do not access into dev, no race
962 //condition will occur
963 purb
= (PURB
) RemoveHeadList(&temp_list
);
964 urb_status
= purb
->status
;
965 ep_type
= endp_type(purb
->pendp
);
967 if (ep_type
== USB_ENDPOINT_XFER_ISOC
)
969 // collect error for iso transfer
970 urb_status
= ehci_scan_iso_error(ehci
, purb
);
973 //the only place we do not use this lock on non-pending-endp-list data
974 KeAcquireSpinLockAtDpcLevel(&ehci
->pending_endp_list_lock
);
975 while (IsListEmpty(&purb
->trasac_list
) == FALSE
)
978 pthis
= RemoveHeadList(&purb
->trasac_list
);
979 em_type
= (UCHAR
) elem_type(pthis
, TRUE
);
981 if (em_type
== INIT_LIST_FLAG_QH
)
983 pqh
= qh_from_list_entry(pthis
);
984 elem_safe_free(pthis
, TRUE
);
988 //must be an itd, sitd chain
989 InsertHeadList(&purb
->trasac_list
, pthis
);
990 for(i
= 0, purb
->bytes_transfered
= 0; i
< purb
->td_count
; i
++)
992 PEHCI_QTD_CONTENT ptdc
= NULL
;
993 PEHCI_ITD_CONTENT pitdc
;
994 PEHCI_SITD_CONTENT psitdc
;
996 em_type
= (UCHAR
) elem_type(pthis
, TRUE
);
998 // accumulate data transfered in tds
999 if (em_type
== INIT_LIST_FLAG_QTD
)
1001 ptd
= qtd_from_list_entry(pthis
);
1002 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1003 if ((ptdc
->status
& QTD_STS_ACTIVE
) == 0 && ((ptdc
->status
& QTD_ANY_ERROR
) == 0))
1004 purb
->bytes_transfered
+= ptd
->bytes_to_transfer
;
1006 else if (em_type
== INIT_LIST_FLAG_ITD
)
1009 pitdc
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
1010 for(j
= 0; j
< 8; j
++)
1012 if ((pitdc
->status_slot
[j
].status
& ITD_STS_ACTIVE
) == 0
1013 && (pitdc
->status_slot
[j
].status
& ITD_ANY_ERROR
) == 0)
1014 purb
->bytes_transfered
+= ptdc
->bytes_to_transfer
;
1017 else if (em_type
== INIT_LIST_FLAG_SITD
)
1019 psitdc
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
1020 if ((psitdc
->status
& SITD_STS_ACTIVE
) == 0 && (psitdc
->status
& SITD_ANY_ERROR
) == 0)
1021 purb
->bytes_transfered
+= ptdc
->bytes_to_transfer
;
1023 ListNext(&purb
->trasac_list
, pthis
, pnext
);
1027 // check to see if an fstn is there
1028 ListFirstPrev(&purb
->trasac_list
, pthis
);
1029 if (elem_type(pthis
, TRUE
) == INIT_LIST_FLAG_FSTN
)
1031 RemoveEntryList(pthis
);
1032 elem_safe_free(pthis
, TRUE
);
1035 ListFirst(&purb
->trasac_list
, pthis
);
1036 RemoveEntryList(&purb
->trasac_list
);
1039 elem_safe_free(pthis
, FALSE
);
1041 //termination condition
1042 InitializeListHead(&purb
->trasac_list
);
1043 purb
->last_finished_td
= NULL
;
1047 if (ep_type
== USB_ENDPOINT_XFER_ISOC
|| ep_type
== USB_ENDPOINT_XFER_INT
)
1048 ehci_claim_bandwidth(ehci
, purb
, FALSE
); //release band-width
1050 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1052 ehci_set_error_code(purb
, urb_status
);
1054 pdev
= dev_from_endp(purb
->pendp
);
1055 pendp
= purb
->pendp
;
1057 // perform clear tt buffer if error on full/low bulk/control pipe
1058 if (ep_type
== USB_ENDPOINT_XFER_BULK
|| ep_type
== USB_ENDPOINT_XFER_CONTROL
)
1060 PURB_HS_PIPE_CONTENT pipe_content
;
1064 get_parent_hs_hub(pdev
, phub
, port_idx
);
1065 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1067 if (pipe_content
->speed_high
== 0 && purb
->status
!= STATUS_SUCCESS
)
1069 // lets schedule an event to clear the tt buffer
1070 hub_post_clear_tt_event(phub
, port_idx
, purb
->pipe
);
1072 else if (pipe_content
->speed_high
== 0)
1078 // release tt if no error
1079 hub_unlock_tt(phub
, (UCHAR
) port_idx
, (UCHAR
) pipe_content
->trans_type
);
1086 //since the ref_count for the purb is not released, we can safely have one
1089 if (purb
->status
== USB_STATUS_BABBLE_DETECTED
)
1091 usb_dbg_print(DBGLVL_MEDIUM
,
1092 ("ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n"));
1093 // ehci_start( ehci );
1096 if (ehci_status
& STS_HALT
) //&& !ehci->is_suspended
1098 ehci_start(&ehci
->hcd_interf
);
1101 //this will let the new request in ehci_generic_urb_completion to this endp
1102 //be processed rather than queued in the pending_endp_list
1103 lock_dev(pdev
, TRUE
);
1104 usb_endp_busy_count_dec(pendp
);
1105 unlock_dev(pdev
, TRUE
);
1107 if (usb_success(purb
->status
) == FALSE
)
1109 // set error code and complete the purb and purb is invalid from this point
1110 ehci_generic_urb_completion(purb
, purb
->context
);
1114 if (ep_type
== USB_ENDPOINT_XFER_BULK
)
1116 purb
->rest_bytes
-= purb
->bytes_transfered
;
1117 if (purb
->rest_bytes
)
1123 ehci_generic_urb_completion(purb
, purb
->context
);
1128 ehci_generic_urb_completion(purb
, purb
->context
);
1130 //purb is now invalid
1134 KeAcquireSpinLockAtDpcLevel(&ehci
->pending_endp_list_lock
);
1135 lock_dev(pdev
, TRUE
);
1140 if (urb_status
&& ((ep_type
== USB_ENDPOINT_XFER_BULK
) || (ep_type
== USB_ENDPOINT_XFER_INT
)))
1142 // error on int or bulk pipe, cleared in usb_reset_pipe_completion
1143 pendp
->flags
&= ~USB_ENDP_FLAG_STAT_MASK
;
1144 pendp
->flags
|= USB_ENDP_FLAG_STALL
;
1147 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1149 unlock_dev(pdev
, TRUE
);
1150 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1151 if (finished
== FALSE
)
1154 purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1155 ehci_generic_urb_completion(purb
, purb
->context
);
1157 lock_dev(pdev
, TRUE
);
1159 unlock_dev(pdev
, TRUE
);
1164 if (finished
&& IsListEmpty(&pendp
->urb_list
) == TRUE
)
1166 unlock_dev(pdev
, TRUE
);
1167 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1170 else if (finished
== TRUE
)
1172 //has purb in the endp's purb-list
1173 if (usb_endp_busy_count(pendp
) > 0)
1175 //the urbs still have chance to be sheduled but not this time
1176 unlock_dev(pdev
, TRUE
);
1177 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1182 if (finished
== FALSE
)
1184 //a split bulk transfer, ( not the high speed split transfer )
1185 purb
->bytes_transfered
= 0;
1186 purb
->bytes_to_transfer
=
1187 EHCI_MAX_SIZE_TRANSFER
> purb
->rest_bytes
? purb
->rest_bytes
: EHCI_MAX_SIZE_TRANSFER
;
1189 //the purb is not finished
1190 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
1191 purb
->flags
|= URB_FLAG_STATE_PENDING
;
1193 InsertHeadList(&pendp
->urb_list
, &purb
->urb_link
);
1196 pending_endp
= alloc_pending_endp(&ehci
->pending_endp_pool
, 1);
1199 unlock_dev(pdev
, TRUE
);
1200 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1203 pending_endp
->pendp
= pendp
;
1204 InsertTailList(&ehci
->pending_endp_list
, &pending_endp
->endp_link
);
1206 unlock_dev(pdev
, TRUE
);
1207 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1210 //ah...exhausted, let's find some in the pending_endp_list to rock
1211 ehci_process_pending_endp(ehci
);
1215 static BOOLEAN NTAPI
1216 ehci_sync_cancel_urbs_dev(PVOID context
)
1218 //cancel all the urbs on one dev
1220 PUSB_DEV pdev
, dest_dev
;
1221 PSYNC_PARAM sync_param
;
1222 PLIST_ENTRY pthis
, pnext
;
1225 sync_param
= (PSYNC_PARAM
) context
;
1226 dest_dev
= (PUSB_DEV
) sync_param
->context
;
1227 ehci
= sync_param
->ehci
;
1229 if (ehci
== NULL
|| dest_dev
== NULL
)
1231 return (UCHAR
) (sync_param
->ret
= FALSE
);
1234 ListFirst(&ehci
->urb_list
, pthis
);
1237 pdev
= dev_from_endp(((PURB
) pthis
)->pendp
);
1238 if (pdev
== dest_dev
)
1240 ((PURB
) pthis
)->flags
|= URB_FLAG_FORCE_CANCEL
;
1242 ListNext(&ehci
->urb_list
, pthis
, pnext
);
1249 // signal an int for further process
1250 press_doorbell(ehci
);
1252 return (UCHAR
) (sync_param
->ret
= TRUE
);
1256 ehci_remove_device(PEHCI_DEV ehci
, PUSB_DEV dev
)
1258 PUHCI_PENDING_ENDP ppending_endp
;
1259 PLIST_ENTRY pthis
, pnext
;
1261 LIST_HEAD temp_list
;
1263 SYNC_PARAM sync_param
;
1267 if (ehci
== NULL
|| dev
== NULL
)
1270 InitializeListHead(&temp_list
);
1272 //free pending endp that has purb queued from pending endp list
1273 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1275 ListFirst(&ehci
->pending_endp_list
, pthis
);
1279 ppending_endp
= (PUHCI_PENDING_ENDP
) pthis
;
1280 ListNext(&ehci
->pending_endp_list
, pthis
, pnext
);
1281 if (dev_from_endp(ppending_endp
->pendp
) == dev
)
1283 RemoveEntryList(pthis
);
1284 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
1288 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1290 //cancel all the urbs in the purb-list
1291 sync_param
.ehci
= ehci
;
1292 sync_param
.context
= (PVOID
) dev
;
1294 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_cancel_urbs_dev
, &sync_param
);
1296 //cancel all the purb in the endp's purb-list
1298 lock_dev(dev
, FALSE
);
1299 if (dev
->usb_config
)
1301 //only for configed dev
1302 for(i
= 0; i
< dev
->usb_config
->if_count
; i
++)
1304 for(j
= 0; j
< dev
->usb_config
->interf
[i
].endp_count
; j
++)
1306 ListFirst(&dev
->usb_config
->interf
[i
].endp
[j
].urb_list
, pthis
);
1309 ListNext(&dev
->usb_config
->interf
[i
].endp
[j
].urb_list
, pthis
, pnext
);
1311 RemoveEntryList(pthis
);
1312 InsertHeadList(&temp_list
, pthis
);
1320 ListFirst(&dev
->default_endp
.urb_list
, pthis
);
1324 ListNext(&dev
->default_endp
.urb_list
, pthis
, pnext
);
1326 RemoveEntryList(pthis
);
1327 InsertHeadList(&temp_list
, pthis
);
1331 unlock_dev(dev
, FALSE
);
1333 if (IsListEmpty(&temp_list
) == FALSE
)
1335 for(i
= 0; i
< k
; i
++)
1337 //complete those urbs with error
1338 pthis
= RemoveHeadList(&temp_list
);
1339 purb
= (PURB
) pthis
;
1340 purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1342 ehci_generic_urb_completion(purb
, purb
->context
);
1347 lock_dev(dev
, FALSE
) dev
->ref_count
-= k
;
1348 unlock_dev(dev
, FALSE
);
1354 ehci_insert_urb_schedule(PEHCI_DEV ehci
, PURB purb
)
1355 // must have dev_lock( ehci_process_pending_endp ) and frame_list_lock acquired
1357 PURB_HS_PIPE_CONTENT pipe_content
;
1359 if (ehci
== NULL
|| purb
== NULL
)
1362 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1363 switch (pipe_content
->trans_type
)
1365 case USB_ENDPOINT_XFER_CONTROL
:
1366 ehci_insert_control_schedule(ehci
, purb
);
1368 case USB_ENDPOINT_XFER_BULK
:
1369 ehci_insert_bulk_schedule(ehci
, purb
);
1371 case USB_ENDPOINT_XFER_INT
:
1372 ehci_insert_int_schedule(ehci
, purb
);
1374 case USB_ENDPOINT_XFER_ISOC
:
1375 ehci_insert_iso_schedule(ehci
, purb
);
1381 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
1382 purb
->flags
|= URB_FLAG_STATE_IN_PROCESS
| URB_FLAG_IN_SCHEDULE
;
1383 InsertTailList(&ehci
->urb_list
, &purb
->urb_link
);
1389 ehci_insert_tds_qh(PEHCI_DEV ehci
, PEHCI_QH pqh
, PEHCI_QTD td_chain
)
1391 if (pqh
== NULL
|| td_chain
== NULL
)
1394 UNREFERENCED_PARAMETER(ehci
);
1396 ehci_copy_overlay((PEHCI_QH_CONTENT
) pqh
, (PEHCI_QTD_CONTENT
) td_chain
);
1397 InsertTailList(&td_chain
->elem_head_link
->elem_link
, &pqh
->elem_head_link
->elem_link
);
1402 ehci_insert_qh_urb(PURB purb
, PEHCI_QH pqh
)
1404 PLIST_ENTRY pthis
, pnext
;
1405 if (pqh
== NULL
|| purb
== NULL
)
1408 InsertTailList(&pqh
->elem_head_link
->elem_link
, &purb
->trasac_list
);
1409 ListFirst(&purb
->trasac_list
, pthis
) while (pthis
)
1411 // note: fstn may in this chain
1412 struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->purb
= purb
;
1413 ListNext(&purb
->trasac_list
, pthis
, pnext
);
1419 #define calc_td_count( pURB, start_aDDR, td_coUNT ) \
1423 k = ( ( pURB )->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;\
1426 LONG packets_per_td, packets_per_page;\
1427 packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;\
1428 packets_per_page = PAGE_SIZE / max_packet_size;\
1429 i = ( ( LONG )&( pURB )->data_buffer[ ( start_aDDR ) ] ) & ( PAGE_SIZE - 1 );\
1433 j = i & ( max_packet_size - 1 );\
1434 k -= ( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) / max_packet_size;\
1440 i = packets_per_td - packets_per_page;\
1442 i = packets_per_td;\
1443 td_coUNT = 1 + ( k + i - 1 ) / i; \
1448 td_coUNT = ( k + packets_per_td - 1 ) / packets_per_td;\
1454 ehci_fill_td_buf_ptr(PURB purb
, LONG start_addr
, // start idx into purb->data_buffer
1455 PLIST_ENTRY td_list
, LONG td_count
, ULONG toggle
)
1456 // fill the tds' bytes_to_transfer and hw_buf, return next toggle value: true 1, false 0
1458 LONG i
, j
, k
, data_load
;
1459 LONG packets_per_td
, packets_per_page
, bytes_to_transfer
, max_packet_size
;
1460 PLIST_ENTRY pthis
, pnext
;
1461 PEHCI_QTD_CONTENT ptdc
;
1465 if (purb
== NULL
|| td_list
== NULL
|| td_count
== 0)
1468 max_packet_size
= 1 << ((PURB_HS_PIPE_CONTENT
) & purb
->pipe
)->max_packet_size
;
1469 packets_per_td
= EHCI_QTD_MAX_TRANS_SIZE
/ max_packet_size
;
1470 packets_per_page
= PAGE_SIZE
/ max_packet_size
;
1473 bytes_to_transfer
= purb
->bytes_to_transfer
;
1475 i
= ((LONG
) & (purb
)->data_buffer
[(start_addr
)]) & (PAGE_SIZE
- 1);
1479 j
= i
& (max_packet_size
- 1);
1486 while (bytes_to_transfer
)
1488 ptd
= qtd_from_list_entry(pthis
);
1489 ptd
->hw_buf
[0] = MmGetPhysicalAddress(&purb
->data_buffer
[start_addr
]).LowPart
;
1490 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1494 data_load
= (LONG
) (EHCI_QTD_MAX_TRANS_SIZE
- PAGE_SIZE
+ i
- j
) < bytes_to_transfer
1495 ? (LONG
) (EHCI_QTD_MAX_TRANS_SIZE
- PAGE_SIZE
+ i
- j
) : bytes_to_transfer
;
1497 ptdc
->bytes_to_transfer
= (USHORT
) data_load
;
1498 ptd
->bytes_to_transfer
= (USHORT
) data_load
;
1500 // subtract the header part
1501 data_load
-= (i
< data_load
? i
: data_load
);
1503 for(k
= 1; data_load
> 0; k
++)
1505 ptr
= &purb
->data_buffer
[start_addr
+ i
+ (k
- 1) * PAGE_SIZE
];
1506 ptr
= (PVOID
) (((ULONG
) ptr
) & ~(PAGE_SIZE
- 1));
1507 ptd
->hw_buf
[k
] = MmGetPhysicalAddress(ptr
).LowPart
;
1508 data_load
-= PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
;
1513 // aligned on page boundary
1514 data_load
= EHCI_QTD_MAX_TRANS_SIZE
< bytes_to_transfer
1515 ? EHCI_QTD_MAX_TRANS_SIZE
: bytes_to_transfer
;
1517 ptdc
->bytes_to_transfer
= (USHORT
) data_load
;
1518 ptd
->bytes_to_transfer
= (USHORT
) data_load
;
1520 data_load
-= (PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
);
1522 for(k
= 1; data_load
> 0; k
++)
1524 ptr
= &purb
->data_buffer
[start_addr
+ k
* PAGE_SIZE
];
1525 ptr
= (PVOID
) (((ULONG
) ptr
) & ~(PAGE_SIZE
- 1));
1526 ptd
->hw_buf
[k
] = MmGetPhysicalAddress(ptr
).LowPart
;
1527 data_load
-= PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
;
1530 ptdc
->data_toggle
= toggle
;
1531 if (((ptdc
->bytes_to_transfer
+ max_packet_size
- 1) / max_packet_size
) & 1)
1533 //only odd num of transactions has effect
1536 start_addr
+= ptdc
->bytes_to_transfer
;
1537 bytes_to_transfer
-= ptdc
->bytes_to_transfer
;
1538 ListNext(td_list
, pthis
, pnext
);
1546 ehci_internal_submit_bulk(PEHCI_DEV ehci
, PURB purb
)
1548 // assume that the purb has its rest_bytes and bytes_to_transfer set
1549 // and bytes_transfered is zeroed.
1550 // dev_lock must be acquired outside
1551 // purb comes from dev's endpoint purb-list. it is already removed from
1552 // the endpoint purb-list.
1556 LONG max_packet_size
, td_count
, offset
, bytes_to_transfer
;
1560 LIST_ENTRY td_list
, *pthis
, *pnext
;
1561 BOOLEAN old_toggle
, toggle
, ret
;
1564 PURB_HS_PIPE_CONTENT pipe_content
;
1565 PEHCI_QTD_CONTENT ptdc
;
1566 PEHCI_QH_CONTENT pqhc
;
1567 PEHCI_ELEM_LINKS pelnk
;
1568 PEHCI_ELEM_LINKS plnk
;
1570 if (ehci
== NULL
|| purb
== NULL
)
1571 return STATUS_INVALID_PARAMETER
;
1573 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1574 if (purb
->bytes_to_transfer
== 0)
1576 return STATUS_INVALID_PARAMETER
;
1579 start_addr
= &purb
->data_buffer
[purb
->data_length
- purb
->rest_bytes
];
1580 calc_td_count(purb
, purb
->data_length
- purb
->rest_bytes
, td_count
);
1582 elem_pool_lock(qtd_pool
, TRUE
);
1583 pelnk
= elem_pool_alloc_elems(qtd_pool
, td_count
);
1584 elem_pool_unlock(qtd_pool
, TRUE
);
1588 return STATUS_UNSUCCESSFUL
;
1590 ptd
= (PEHCI_QTD
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1592 InitializeListHead(&td_list
);
1593 InsertTailList(&ptd
->elem_head_link
->elem_link
, &td_list
);
1595 ListFirst(&td_list
, pthis
);
1596 ListNext(&td_list
, pthis
, pnext
);
1600 old_toggle
= toggle
= (purb
->pendp
->flags
& USB_ENDP_FLAG_DATATOGGLE
) ? TRUE
: FALSE
;
1601 bytes_to_transfer
= purb
->bytes_to_transfer
;
1602 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle
));
1604 for(i
= 1; i
< 16; i
++)
1606 if ((max_packet_size
>> i
) == 0)
1613 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1614 pipe_content
->max_packet_size
= i
;
1615 pipe_content
->endp_addr
= endp_num(purb
->pendp
);
1616 pipe_content
->dev_addr
= dev_from_endp(purb
->pendp
)->dev_addr
;
1617 pipe_content
->trans_dir
= endp_dir(purb
->pendp
);
1618 pipe_content
->trans_type
= USB_ENDPOINT_XFER_BULK
;
1619 pipe_content
->data_toggle
= toggle
;
1620 pipe_content
->speed_high
= (dev_from_endp(purb
->pendp
)->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0;
1621 pipe_content
->speed_low
= (dev_from_endp(purb
->pendp
)->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0;
1623 pid
= (((ULONG
) purb
->pendp
->pusb_endp_desc
->bEndpointAddress
& USB_DIR_IN
) ? QTD_PID_IN
: QTD_PID_OUT
);
1625 i
= ((ULONG
) start_addr
) & (PAGE_SIZE
- 1); // header part within first page
1629 if (i
< purb
->bytes_to_transfer
)
1630 j
= i
& (max_packet_size
- 1);
1637 // fill the page pointer and toggle
1639 toggle
= ehci_fill_td_buf_ptr(purb
, purb
->data_length
- purb
->rest_bytes
, pthis
, td_count
, toggle
);
1642 ptd
= qtd_from_list_entry(pthis
);
1643 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1645 // ptdc->alt_terminal = 1;
1646 // ptdc->alt_qtd = 0;
1647 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1650 // ptd->elem_head_link->purb = purb; will be filled later
1651 ptdc
->err_count
= 3;
1652 ptdc
->status
= 0x80; // active, and do_start_split for split transfer
1654 // ptdc->data_toggle = toggle;
1658 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1662 //Last one, enable ioc and short packet detect if necessary
1663 ptd
->hw_next
= EHCI_PTR_TERM
;
1665 if (bytes_to_transfer
< max_packet_size
&& (pid
== QTD_PID_IN
))
1667 //ptd->status |= TD_CTRL_SPD;
1674 ListNext(&td_list
, pthis
, pnext
);
1677 ListFirst(&td_list
, pthis
);
1678 RemoveEntryList(&td_list
);
1680 elem_pool_lock(qh_pool
, TRUE
);
1682 plnk
= elem_pool_alloc_elem(qh_pool
);
1686 elem_safe_free(pthis
, TRUE
);
1687 if (qh_pool
) elem_pool_unlock(qh_pool
, TRUE
);
1688 return STATUS_UNSUCCESSFUL
;
1691 pqh
= (PEHCI_QH
) ((ULONG
) plnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1692 elem_pool_unlock(qh_pool
, TRUE
);
1697 elem_safe_free(pthis
, TRUE
);
1698 return STATUS_NO_MORE_ENTRIES
;
1702 purb
->td_count
= td_count
;
1703 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
1704 pqh
->hw_next
= EHCI_PTR_TERM
; // filled later
1705 pqhc
->dev_addr
= pipe_content
->dev_addr
;
1707 pqhc
->endp_addr
= pipe_content
->endp_addr
;
1708 pqhc
->data_toggle
= 0; //pipe_content->data_toggle;
1709 pqhc
->is_async_head
= 0;
1710 pqhc
->max_packet_size
= (1 << pipe_content
->max_packet_size
);
1711 pqhc
->is_ctrl_endp
= 0;
1712 pqhc
->reload_counter
= EHCI_NAK_RL_COUNT
;
1714 if (pipe_content
->speed_high
)
1715 pqhc
->endp_spd
= USB_SPEED_HIGH
;
1716 else if (pipe_content
->speed_low
)
1717 pqhc
->endp_spd
= USB_SPEED_LOW
;
1719 pqhc
->endp_spd
= USB_SPEED_FULL
;
1723 pqh
->hw_current
= 0;
1724 pqh
->hw_qtd_next
= 0; // filled later
1725 pqh
->hw_alt_next
= EHCI_PTR_TERM
;
1726 pqh
->hw_token
= 0; //indicate to advance queue before execution
1728 if (!pipe_content
->speed_high
)
1730 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
1731 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
1734 ptd
= qtd_from_list_entry(pthis
);
1735 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
1736 ehci_insert_qh_urb(purb
, pqh
);
1737 purb
->pendp
->flags
=
1738 (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (toggle
? USB_ENDP_FLAG_DATATOGGLE
: 0);
1739 usb_endp_busy_count_inc(purb
->pendp
);
1740 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
1744 // undo all we have done
1745 ListFirst(&pqh
->elem_head_link
->elem_link
, pthis
);
1747 RemoveEntryList(&purb
->trasac_list
);
1748 RemoveEntryList(&pqh
->elem_head_link
->elem_link
); //remove qh from td_chain
1750 elem_safe_free(pthis
, FALSE
);
1751 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
1753 InitializeListHead(&purb
->trasac_list
);
1754 // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback
1755 purb
->pendp
->flags
=
1756 (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (old_toggle
? USB_ENDP_FLAG_DATATOGGLE
: 0);
1757 return STATUS_UNSUCCESSFUL
;
1759 return STATUS_SUCCESS
;
1763 ehci_internal_submit_ctrl(PEHCI_DEV ehci
, PURB purb
)
1766 LIST_ENTRY td_list
, *pthis
, *pnext
;
1769 LONG max_packet_size
, bytes_to_transfer
, bytes_rest
, start_idx
;
1773 PEHCI_QH_CONTENT pqhc
;
1776 PURB_HS_PIPE_CONTENT pipe_content
;
1777 PEHCI_QTD_CONTENT ptdc
;
1778 PEHCI_ELEM_LINKS pelnk
;
1781 if (ehci
== NULL
|| purb
== NULL
)
1782 return STATUS_INVALID_PARAMETER
;
1784 bytes_rest
= purb
->rest_bytes
;
1785 bytes_to_transfer
= purb
->bytes_to_transfer
;
1786 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1787 start_idx
= purb
->data_length
- purb
->rest_bytes
;
1789 calc_td_count(purb
, start_idx
, td_count
);
1790 td_count
+= 2; // add setup td and handshake td
1792 elem_pool_lock(qtd_pool
, TRUE
);
1793 pelnk
= elem_pool_alloc_elems(qtd_pool
, td_count
);
1794 elem_pool_unlock(qtd_pool
, TRUE
);
1798 return STATUS_NO_MORE_ENTRIES
;
1801 InsertTailList(&pelnk
->elem_link
, &td_list
);
1802 ListFirst(&td_list
, pthis
);
1803 ListNext(&td_list
, pthis
, pnext
);
1805 ptd
= qtd_from_list_entry(pthis
);
1807 pdev
= dev_from_endp(purb
->pendp
);
1808 dev_addr
= pdev
->dev_addr
;
1810 if (dev_state(pdev
) <= USB_DEV_STATE_RESET
) //only valid for control transfer
1813 usb_dbg_print(DBGLVL_MAXIMUM
, ("ehci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr
));
1815 // fill the setup packet
1816 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1817 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1818 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1819 ptdc
->status
= 0x80; // active
1820 ptdc
->pid
= QTD_PID_SETUP
;
1821 ptdc
->err_count
= 3;
1824 ptdc
->bytes_to_transfer
= sizeof(USB_CTRL_SETUP_PACKET
);
1825 ptdc
->data_toggle
= 0;
1826 ptd
->hw_buf
[0] = MmGetPhysicalAddress(purb
->setup_packet
).LowPart
;
1828 for(i
= 1; i
< 16; i
++)
1830 if ((max_packet_size
>> i
) == 0)
1837 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1838 pipe_content
->max_packet_size
= i
;
1839 pipe_content
->endp_addr
= endp_num(purb
->pendp
);
1840 pipe_content
->dev_addr
= dev_addr
;
1841 pipe_content
->speed_low
= (pdev
->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0;
1842 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0;
1843 pipe_content
->trans_type
= USB_ENDPOINT_XFER_CONTROL
;
1846 ListNext(&td_list
, pthis
, pnext
);
1848 // all the tds's toggle and data_buffer pointer is filled here
1850 ehci_fill_td_buf_ptr(purb
, start_idx
, pthis
, td_count
- 2, toggle
);
1852 for(i
= 0; ((i
< td_count
- 2) && pthis
); i
++)
1854 //construct tds for DATA packets of data stage.
1855 ptd
= qtd_from_list_entry(pthis
);
1856 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1857 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1858 ptdc
->status
= 0x80; // active and startXSplit
1859 ptdc
->pid
= ((purb
->setup_packet
[0] & USB_DIR_IN
) ? QTD_PID_IN
: QTD_PID_OUT
);
1860 ptdc
->err_count
= 3;
1865 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1867 ptd
->hw_next
= EHCI_PTR_TERM
;
1871 ListNext(&td_list
, pthis
, pnext
);
1875 ptd
->hw_next
= qtd_from_list_entry(pthis
)->phys_addr
;
1879 // ListFirstPrev( &td_list, pthis );
1880 ptd
= qtd_from_list_entry(pthis
);
1882 //the last is an IN transaction
1883 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1884 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1885 ptdc
->status
= 0x80;
1886 ptdc
->pid
= ((td_count
> 2)
1887 ? ((purb
->setup_packet
[0] & USB_DIR_IN
) ? QTD_PID_OUT
: QTD_PID_IN
) : QTD_PID_IN
);
1889 ptdc
->err_count
= 3;
1892 ptdc
->bytes_to_transfer
= 0;
1893 ptdc
->data_toggle
= 1;
1894 ptd
->hw_next
= EHCI_PTR_TERM
;
1896 ListFirst(&td_list
, pthis
);
1897 RemoveEntryList(&td_list
);
1899 ptd
= qtd_from_list_entry(pthis
);
1900 elem_pool_lock(qh_pool
, TRUE
);
1901 pelnk
= elem_pool_alloc_elem(qh_pool
);
1902 elem_pool_unlock(qh_pool
, TRUE
);
1906 elem_safe_free(pthis
, FALSE
);
1907 return STATUS_NO_MORE_ENTRIES
;
1910 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1911 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
1913 pqh
->hw_alt_next
= pqh
->hw_next
= EHCI_PTR_TERM
;
1915 pqhc
->dev_addr
= dev_addr
;
1917 pqhc
->endp_addr
= endp_num(purb
->pendp
);
1919 if (pipe_content
->speed_high
)
1920 pqhc
->endp_spd
= USB_SPEED_HIGH
;
1921 else if (pipe_content
->speed_low
)
1922 pqhc
->endp_spd
= USB_SPEED_LOW
;
1924 pqhc
->endp_spd
= USB_SPEED_FULL
;
1926 pqhc
->data_toggle
= 1; // use dt from qtd
1927 pqhc
->is_async_head
= 0;
1928 pqhc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
1930 if (pipe_content
->speed_high
== 0)
1931 pqhc
->is_ctrl_endp
= 1;
1933 pqhc
->is_ctrl_endp
= 0;
1935 pqhc
->reload_counter
= EHCI_NAK_RL_COUNT
;
1941 if (!pipe_content
->speed_high
)
1943 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
1944 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
1947 purb
->td_count
= td_count
;
1949 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
1950 ehci_insert_qh_urb(purb
, pqh
);
1952 usb_endp_busy_count_inc(purb
->pendp
);
1953 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
1957 RemoveEntryList(&purb
->trasac_list
);
1958 RemoveEntryList(&pqh
->elem_head_link
->elem_link
);
1960 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
1961 elem_safe_free(pthis
, FALSE
);
1963 InitializeListHead(&purb
->trasac_list
);
1964 // usb_endp_busy_count_dec( purb->pendp );
1965 return STATUS_UNSUCCESSFUL
;
1967 return STATUS_SUCCESS
;
1971 ehci_internal_submit_int(PEHCI_DEV ehci
, PURB purb
)
1973 LONG i
, max_packet_size
;
1977 PURB_HS_PIPE_CONTENT pipe_content
;
1978 UCHAR mult_trans
, toggle
, old_toggle
;
1979 PEHCI_ELEM_LINKS pelnk
;
1980 PEHCI_QTD_CONTENT ptdc
;
1982 PEHCI_QH_CONTENT pqhc
;
1985 if (ehci
== NULL
|| purb
== NULL
)
1986 return STATUS_INVALID_PARAMETER
;
1988 old_toggle
= toggle
= (purb
->pendp
->flags
& USB_ENDP_FLAG_DATATOGGLE
) ? TRUE
: FALSE
;
1989 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1990 pdev
= dev_from_endp(purb
->pendp
);
1992 if (max_packet_size
== 0 || max_packet_size
> 64)
1993 return STATUS_INVALID_PARAMETER
;
1995 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
1997 if (max_packet_size
< purb
->data_length
)
1998 return STATUS_INVALID_PARAMETER
;
2000 for(i
= 1; i
< 16; i
++)
2002 if ((((ULONG
) purb
->pendp
->pusb_endp_desc
->bInterval
) >> i
) == 0)
2010 mult_trans
= endp_mult_count(purb
->pendp
);
2011 if (max_packet_size
* endp_mult_count(purb
->pendp
) < purb
->data_length
)
2012 return STATUS_INVALID_PARAMETER
;
2013 i
= purb
->pendp
->pusb_endp_desc
->bInterval
- 1;
2017 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
2018 pipe_content
->interval
= i
;
2019 pipe_content
->trans_type
= USB_ENDPOINT_XFER_INT
; // bit 0-1
2020 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0; // bit 5
2021 pipe_content
->speed_low
= (pdev
->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0; // bit 6
2022 pipe_content
->trans_dir
= endp_dir(purb
->pendp
); // bit 7
2023 pipe_content
->dev_addr
= pdev
->dev_addr
; // bit 8-14
2024 pipe_content
->endp_addr
= endp_num(purb
->pendp
); // bit 15-18
2025 pipe_content
->data_toggle
= 1; // bit 19
2026 pipe_content
->mult_count
= mult_trans
;
2028 // pipe_content->start_uframe : 3; // bit 28-30 will be filled later
2030 for(i
= 1; i
<= 16; i
++)
2032 if (((ULONG
) max_packet_size
) >> i
)
2040 pipe_content
->max_packet_size
= i
; // bit 20-23 log2( max_packet_size )
2042 if (ehci_claim_bandwidth(ehci
, purb
, TRUE
) == FALSE
)
2044 // can not allocate bandwidth for it
2045 return STATUS_UNSUCCESSFUL
;
2048 // one qtd is enough
2049 elem_pool_lock(qtd_pool
, TRUE
);
2050 pelnk
= elem_pool_alloc_elem(qtd_pool
);
2051 elem_pool_unlock(qtd_pool
, TRUE
);
2055 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2056 return STATUS_NO_MORE_ENTRIES
;
2059 ptd
= (PEHCI_QTD
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2060 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
2061 ptd
->hw_next
= EHCI_PTR_TERM
;
2063 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
2065 ptdc
->status
= 0x80;
2066 ptdc
->pid
= pipe_content
->trans_dir
? QTD_PID_IN
: QTD_PID_OUT
;
2067 ptdc
->err_count
= 3;
2070 ptdc
->bytes_to_transfer
= purb
->data_length
;
2071 toggle
= (UCHAR
) ehci_fill_td_buf_ptr(purb
, 0, &pelnk
->elem_link
, 1, toggle
);
2073 elem_pool_lock(qh_pool
, TRUE
);
2074 pelnk
= elem_pool_alloc_elem(qh_pool
);
2075 elem_pool_unlock(qh_pool
, TRUE
);
2078 elem_safe_free(&ptd
->elem_head_link
->elem_link
, TRUE
);
2079 InitializeListHead(&purb
->trasac_list
);
2080 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2081 return STATUS_NO_MORE_ENTRIES
;
2083 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2084 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
2086 pqh
->hw_next
= EHCI_PTR_TERM
;
2087 pqhc
->dev_addr
= pdev
->dev_addr
;
2089 pqhc
->endp_addr
= endp_num(purb
->pendp
);
2091 if (pipe_content
->speed_high
)
2092 pqhc
->endp_spd
= USB_SPEED_HIGH
;
2093 else if (pipe_content
->speed_low
)
2094 pqhc
->endp_spd
= USB_SPEED_LOW
;
2096 pqhc
->endp_spd
= USB_SPEED_FULL
;
2098 pqhc
->data_toggle
= 0;
2099 pqhc
->is_async_head
= 0;
2100 pqhc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
2101 pqhc
->is_ctrl_endp
= 0;
2102 pqhc
->reload_counter
= 0;
2106 pqhc
->mult
= mult_trans
;
2108 if (pipe_content
->speed_high
)
2110 if (pipe_content
->interval
== 0) // one poll per uframe
2111 pqhc
->s_mask
= 0xff;
2112 else if (pipe_content
->interval
== 1) // one poll every 2 uframe
2113 pqhc
->s_mask
= pipe_content
->start_uframe
== 0 ? 0x55 : 0xbb;
2114 else if (pipe_content
->interval
== 2)
2116 pqhc
->s_mask
= 0x11;
2117 pqhc
->s_mask
<<= pipe_content
->start_uframe
;
2121 pqhc
->s_mask
= 1 << (pipe_content
->start_uframe
);
2125 else // full/low speed
2127 pqhc
->s_mask
= 1 << pipe_content
->start_uframe
;
2128 if (pipe_content
->start_uframe
< 4)
2130 pqhc
->c_mask
= 0x07 << (pipe_content
->start_uframe
+ 2);
2132 else if (pipe_content
->start_uframe
== 4)
2134 pqhc
->c_mask
= 0xc1;
2136 else if (pipe_content
->start_uframe
>= 5)
2139 pqhc
->c_mask
= 0x03;
2140 if (pipe_content
->start_uframe
== 5)
2142 pqhc
->c_mask
|= 0x80;
2145 if (pipe_content
->start_uframe
>= 4)
2148 elem_pool_lock(fstn_pool
, TRUE
);
2149 pelnk
= elem_pool_alloc_elem(fstn_pool
);
2150 elem_pool_unlock(fstn_pool
, TRUE
);
2153 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
2154 elem_safe_free(&ptd
->elem_head_link
->elem_link
, TRUE
);
2155 InitializeListHead(&purb
->trasac_list
);
2156 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2157 return STATUS_NO_MORE_ENTRIES
;
2159 pfstn
= (PEHCI_FSTN
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2160 pfstn
->hw_prev
= ptd
->phys_addr
;
2161 pfstn
->elem_head_link
->purb
= purb
;
2162 InsertTailList(&ptd
->elem_head_link
->elem_link
, &pfstn
->elem_head_link
->elem_link
);
2164 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2165 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2171 InitializeListHead(&purb
->trasac_list
);
2172 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
2173 ehci_insert_qh_urb(purb
, pqh
);
2175 purb
->pendp
->flags
= (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (toggle
<< 31);
2176 usb_endp_busy_count_inc(purb
->pendp
);
2178 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
2182 RemoveEntryList(&purb
->trasac_list
);
2183 RemoveEntryList(&pqh
->elem_head_link
->elem_link
);
2185 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
2186 // an fstn may follow the td
2187 elem_safe_free(&ptd
->elem_head_link
->elem_link
, FALSE
);
2189 InitializeListHead(&purb
->trasac_list
);
2190 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2192 purb
->pendp
->flags
= (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | ((toggle
^ 1) << 31);
2193 // usb_endp_busy_count_dec( purb->pendp );
2195 return STATUS_UNSUCCESSFUL
;
2198 return STATUS_SUCCESS
;
2203 ehci_internal_submit_iso(PEHCI_DEV ehci
, PURB purb
)
2205 LONG i
, j
, td_count
, temp
;
2208 PEHCI_SITD_CONTENT psitdc
;
2209 PEHCI_ITD_CONTENT pitdc
;
2210 LIST_ENTRY td_list
, *pthis
, *pnext
, *pprev
;
2212 PURB_HS_PIPE_CONTENT pipe_content
;
2214 PEHCI_ELEM_LINKS pelnk
;
2216 if (ehci
== NULL
|| purb
== NULL
)
2217 return STATUS_INVALID_PARAMETER
;
2219 if (purb
->iso_frame_count
== 0)
2220 return STATUS_INVALID_PARAMETER
;
2222 pdev
= dev_from_endp(purb
->pendp
);
2224 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
2225 pipe_content
->trans_type
= USB_ENDPOINT_XFER_ISOC
; // bit 0-1
2226 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0; // bit 5
2227 pipe_content
->speed_low
= 0; // bit 6
2228 pipe_content
->trans_dir
= endp_dir(purb
->pendp
); // bit 7
2229 pipe_content
->dev_addr
= pdev
->dev_addr
; // bit 8-14
2230 pipe_content
->endp_addr
= endp_num(purb
->pendp
); // bit 15-18
2231 pipe_content
->data_toggle
= 0; // bit 19
2234 purb
->params
[0] = j
= endp_max_packet_size(purb
->pendp
);
2236 if (pipe_content
->speed_high
== 0)
2238 // check to see if the frame data is too long to transfer
2239 if (purb
->iso_frame_count
>= (LONG
) ehci
->frame_count
)
2240 return STATUS_INVALID_PARAMETER
;
2242 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2244 if (purb
->iso_packet_desc
[i
].length
> j
)
2245 return STATUS_INVALID_PARAMETER
;
2250 // excess the frame count limit
2251 if (purb
->iso_frame_count
>= (LONG
) (ehci
->frame_count
<< 3))
2252 return STATUS_INVALID_PARAMETER
;
2254 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2256 if (purb
->iso_packet_desc
[i
].length
> j
* endp_mult_count(purb
->pendp
)) // 3 is max mult-transaction count
2257 return STATUS_INVALID_PARAMETER
;
2260 pipe_content
->mult_count
= endp_mult_count(purb
->pendp
);
2263 pipe_content
->max_packet_size
= 0; // bit 20-23 log( max_packet_size ), not correct, should not be used
2265 if (pipe_content
->speed_high
== 0)
2267 for(i
= 1; i
< 16; i
++)
2269 if ((((ULONG
) purb
->pendp
->pusb_endp_desc
->bInterval
) >> i
) == 0)
2276 i
= purb
->pendp
->pusb_endp_desc
->bInterval
- 1;
2279 pipe_content
->interval
= i
; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed
2281 if (ehci_claim_bandwidth(ehci
, purb
, TRUE
) == FALSE
)
2282 return STATUS_UNSUCCESSFUL
;
2284 if (pipe_content
->speed_high
== 0)
2286 td_count
= purb
->iso_frame_count
;
2288 // test to see if the last td needs one more sitd for pure complete-split
2289 if (pipe_content
->trans_dir
== 0)
2291 j
= (purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].length
+ 187) / 188;
2292 if (purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].params
.start_uframe
+ 1 + j
>= 8)
2298 elem_pool_lock(itd_pool
, TRUE
);
2299 pelnk
= elem_pool_alloc_elems(itd_pool
, td_count
);
2300 elem_pool_unlock(itd_pool
, TRUE
);
2306 if (pipe_content
->interval
>= 3)
2308 td_count
= purb
->iso_frame_count
;
2313 j
= purb
->iso_start_frame
& 0x07;
2316 td_count
= (purb
->iso_frame_count
+ 8 / i
- 1) * i
/ 8;
2320 j
= 1 + (7 - j
) / i
; // the leading packets from the 8-trans boundary
2321 td_count
= (j
>= (LONG
) purb
->iso_frame_count
?
2322 1 : 1 + (purb
->iso_frame_count
- j
+ 8 / i
- 1) * i
/ 8);
2326 elem_pool_lock(sitd_pool
, TRUE
);
2327 pelnk
= elem_pool_alloc_elems(sitd_pool
, td_count
);
2328 elem_pool_unlock(sitd_pool
, TRUE
);
2333 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2334 return STATUS_NO_MORE_ENTRIES
;
2337 InsertTailList(&pelnk
->elem_link
, &td_list
);
2338 ListFirst(&td_list
, pthis
);
2340 purb
->td_count
= td_count
;
2342 //set up offset for high speed and interval == 1
2343 if (pipe_content
->speed_high
&& pipe_content
->interval
== 0)
2345 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2348 purb
->iso_packet_desc
[i
].offset
= 0;
2350 purb
->iso_packet_desc
[i
].offset
= purb
->iso_packet_desc
[i
- 1].offset
+
2351 purb
->iso_packet_desc
[i
].length
;
2359 init_elem_phys_part(struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
));
2360 if (pipe_content
->speed_high
)
2362 LONG start_uframe
, k
;
2363 LONG l
, pk_idx
, offset
, start_uf
, td_length
;
2367 pitd
= itd_from_list_entry(pthis
);
2368 pitdc
= (PEHCI_ITD_CONTENT
) pitd
;
2369 start_uframe
= purb
->iso_start_frame
& 0x07;
2371 // will be filled later
2372 pitd
->hw_next
= EHCI_PTR_TERM
;
2375 pitdc
->dev_addr
= pdev
->dev_addr
;
2376 pitdc
->endp_num
= endp_num(purb
->pendp
);
2378 pitdc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
2379 pitdc
->io_dir
= pipe_content
->trans_dir
;
2380 pitdc
->mult
= endp_mult_count(purb
->pendp
);
2382 pbuf
= pitd
->hw_bufp
;
2383 RtlZeroMemory(phys_addr
, sizeof(phys_addr
));
2385 if (pipe_content
->interval
< 3)
2387 // this indicates one itd schedules more than one uframes
2388 // for multiple transactions described by iso_packet_desc
2390 k
= td_count
== 1 ? purb
->iso_frame_count
: j
; // the first itd
2392 k
= (LONG
) (purb
->iso_frame_count
- i
) <= 8 / REAL_INTERVAL
2393 ? (purb
->iso_frame_count
- i
) : 8 / REAL_INTERVAL
;
2395 // j is the header transactions out of the interval
2396 // aligned transactions per td
2397 if (j
> 0 && i
== 0) // handle the first itd
2398 start_uf
= start_uframe
;
2400 start_uf
= start_uframe
% REAL_INTERVAL
;
2404 k
= 1, start_uf
= start_uframe
& 0x07;
2408 // calculate the data to transfer with this td
2410 for(l
= start_uf
, pk_idx
= i
; pk_idx
< i
+ k
; pk_idx
++, l
+= REAL_INTERVAL
)
2412 td_length
+= purb
->iso_packet_desc
[pk_idx
].length
;
2414 MmGetPhysicalAddress(&purb
->data_buffer
[purb
->iso_packet_desc
[pk_idx
].offset
]).LowPart
;
2417 // fill the page pointer, and offset
2418 if (pipe_content
->interval
!= 0)
2420 for(l
= start_uf
, pk_idx
= i
; pk_idx
< i
+ k
; pk_idx
++, l
+= REAL_INTERVAL
)
2422 pitdc
->status_slot
[l
].offset
= phys_addr
[l
] & (PAGE_SIZE
- 1);
2423 pbuf
[l
>> pipe_content
->interval
] |= phys_addr
[l
] & (~(PAGE_SIZE
- 1));
2424 pitdc
->status_slot
[l
].page_sel
= l
>> pipe_content
->interval
;
2425 pitdc
->status_slot
[l
].status
= 0x08;
2426 pitdc
->status_slot
[l
].trans_length
= purb
->iso_packet_desc
[pk_idx
].length
;
2427 if (PAGE_SIZE
- pitdc
->status_slot
[l
].offset
<
2428 (ULONG
) purb
->iso_packet_desc
[pk_idx
].length
)
2430 // fill the next page buf, we can not simply add
2431 // PAGE_SIZE to the phys_addr[ l ].
2432 pbuf
[(l
>> pipe_content
->interval
) + 1] |=
2433 MmGetPhysicalAddress((PBYTE
)
2435 data_buffer
[purb
->iso_packet_desc
[pk_idx
].
2436 offset
]) & (~(PAGE_SIZE
- 1))) +
2441 else // interval == 0
2443 LONG m
, n
= 0, n2
= 0;
2444 // fill the page buffer first
2445 // calculate the page buffer needed
2446 offset
= phys_addr
[0] & (PAGE_SIZE
- 1);
2449 offset
= PAGE_SIZE
- offset
;
2450 l
= 1 + (td_length
- offset
+ PAGE_SIZE
- 1) / PAGE_SIZE
;
2454 l
= (td_length
+ PAGE_SIZE
- 1) / PAGE_SIZE
;
2460 // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp
2461 for(pk_idx
= 0; pk_idx
< l
; pk_idx
++)
2465 offset
= phys_addr
[start_uf
] & (~(PAGE_SIZE
- 1));
2466 pbuf
[pk_idx
] |= offset
;
2468 pitdc
->status_slot
[0].page_sel
= n
;
2473 // scan to find if the buf pointer already filled in the td
2474 // since interval = 1, we do not need k * REAL_INTERVAL
2475 // k is transaction count for current td,
2476 // n is hw_bufp( pbuf ) index
2477 // n2 is the last phys_addr index we stopped
2478 for(m
= n2
; m
< start_uf
+ k
; m
++)
2480 // we can not determine the phys_addr[ x ] is piror
2481 // to offset if it is less than offset.
2482 // because phys_addr is discrete.
2483 // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset )
2486 if ((phys_addr
[m
] & (~(PAGE_SIZE
- 1))) == (ULONG
) offset
)
2488 pitdc
->status_slot
[m
].page_sel
= n
;
2494 if (m
== start_uf
+ k
)
2497 offset
= phys_addr
[m
] & (~(PAGE_SIZE
- 1));
2498 pbuf
[pk_idx
] |= offset
;
2501 pitdc
->status_slot
[m
].page_sel
= n
;
2504 // fill offset and others
2505 for(l
= start_uf
, pk_idx
= i
; l
< start_uf
+ k
; l
++, pk_idx
++)
2507 pitdc
->status_slot
[l
].offset
= (phys_addr
[l
] & (PAGE_SIZE
- 1));
2508 pitdc
->status_slot
[l
].status
= 0x08;
2509 pitdc
->status_slot
[l
].trans_length
= purb
->iso_packet_desc
[pk_idx
].length
;
2515 else // full/low speed
2517 psitd
= sitd_from_list_entry(pthis
);
2518 psitdc
= (PEHCI_SITD_CONTENT
) psitd
;
2519 psitd
->hw_next
= EHCI_PTR_TERM
;
2522 psitdc
->dev_addr
= pdev
->dev_addr
;
2523 psitdc
->endp_num
= endp_num(purb
->pendp
);
2524 psitdc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2525 psitdc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2526 psitdc
->io_dir
= endp_dir(purb
->pendp
);
2528 psitdc
->status
&= 0x80; // in DWORD 3
2531 j
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
2533 if (psitdc
->io_dir
== 0)
2537 psitdc
->s_mask
|= (1 << (j
- 1));
2539 psitdc
->s_mask
<<= purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07;
2546 psitdc
->s_mask
= 1 << purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07;
2547 // iso split case 2b: ehci spec 1.0
2551 j
= j
- 1 + 2; // actual complete-split count
2553 psitdc
->c_mask
|= temp
>> 8; // the previous sitd's complete split
2554 if (temp
>> 8) // link back for sitd split completion
2556 psitd
->hw_backpointer
= sitd_from_list_entry(pprev
)->phys_addr
;
2557 psitdc
->status
&= 0x82;
2561 psitd
->hw_backpointer
= EHCI_PTR_TERM
;
2564 for(k
= temp
= 0; k
< j
; k
++)
2569 temp
<<= ((purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07) + 2);
2571 // only uframe zero and one have complete split for prev sitd
2572 if ((temp
>> 8) > 3)
2575 psitdc
->c_mask
|= temp
& 0xff;
2579 psitdc
->c_prog_mask
= 0;
2580 psitdc
->bytes_to_transfer
= purb
->iso_packet_desc
[i
].length
;
2581 psitdc
->page_sel
= 0;
2585 j
= (ULONG
) ((PBYTE
) purb
->data_buffer
+ purb
->iso_packet_desc
[i
].offset
);
2586 psitd
->hw_tx_results2
= MmGetPhysicalAddress((PVOID
) j
).LowPart
;
2589 if (PAGE_SIZE
- (j
& (PAGE_SIZE
- 1)) < (ULONG
) purb
->iso_packet_desc
[i
].length
)
2591 // need to fill another slot
2593 MmGetPhysicalAddress((PVOID
) ((j
& ~(PAGE_SIZE
- 1)) + PAGE_SIZE
)).LowPart
>> 12;
2596 if (purb
->iso_packet_desc
[i
].length
> 188)
2597 psitdc
->trans_pos
= 0x00;
2598 else if (purb
->iso_packet_desc
[i
].length
<= 188)
2599 psitdc
->trans_pos
= 0x01;
2601 if (psitdc
->io_dir
== 0)
2602 psitdc
->trans_count
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
2605 ListNext(&td_list
, pthis
, pnext
);
2611 if (pipe_content
->speed_high
== 0)
2613 // has an extra sitd to fill at the tail
2616 ListFirstPrev(&td_list
, pthis
);
2617 init_elem_phys_part(struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
));
2619 psitd
= sitd_from_list_entry(pthis
);
2620 psitdc
= (PEHCI_SITD_CONTENT
) psitd
;
2621 psitd
->hw_next
= EHCI_PTR_TERM
;
2624 psitdc
->dev_addr
= pdev
->dev_addr
;
2625 psitdc
->endp_num
= endp_num(purb
->pendp
);
2626 psitdc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2627 psitdc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2628 psitdc
->io_dir
= endp_dir(purb
->pendp
);
2630 psitdc
->status
&= 0x80; // in DWORD 3
2633 psitdc
->s_mask
= 0x04; // uframe 2, random selection
2635 psitdc
->c_mask
= 0x70; // complete split at uframe 4, 5, 6
2636 ListFirstPrev(pthis
, pprev
);
2637 psitd
->hw_backpointer
= sitd_from_list_entry(pprev
)->phys_addr
;
2638 psitdc
->status
&= 0x82;
2641 psitdc
->c_prog_mask
= 0;
2642 psitdc
->bytes_to_transfer
= 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length;
2643 psitdc
->page_sel
= 0;
2645 j
= (ULONG
) ((PBYTE
) purb
->data_buffer
+ purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].offset
);
2646 // the last byte is overridden.
2647 j
+= purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].length
- 1;
2648 psitd
->hw_tx_results2
= MmGetPhysicalAddress((PVOID
) j
).LowPart
;
2651 // set the interrupt
2652 ListFirstPrev(&td_list
, pthis
);
2653 psitdc
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
2659 ListFirstPrev(&td_list
, pthis
);
2660 pitdc
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
2661 for(i
= 7; i
>= 0; i
--)
2663 if (pitdc
->status_slot
[i
].status
== 0x08)
2665 pitdc
->status_slot
[i
].ioc
= 1;
2673 ListFirst(&td_list
, pthis
);
2674 // ListFirst( &purb->trasac_list, pthis )
2675 RemoveEntryList(&td_list
);
2676 InsertTailList(pthis
, &purb
->trasac_list
);
2680 // fill the purb ptr
2681 struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->purb
= purb
;
2682 ListNext(&purb
->trasac_list
, pthis
, pnext
);
2686 //indirectly guarded by pending_endp_list_lock
2687 usb_endp_busy_count_inc(purb
->pendp
);
2688 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
2692 // usb_endp_busy_count_dec( purb->pendp );
2694 ListFirst(&purb
->trasac_list
, pthis
);
2695 RemoveEntryList(&purb
->trasac_list
);
2697 elem_safe_free(pthis
, FALSE
);
2698 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2699 return STATUS_UNSUCCESSFUL
;
2701 return STATUS_SUCCESS
;
2705 //this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule
2706 ehci_sync_insert_urb_schedule(PVOID context
)
2708 PSYNC_PARAM sync_param
;
2712 sync_param
= (PSYNC_PARAM
) context
;
2713 if (sync_param
== NULL
)
2716 ehci
= sync_param
->ehci
;
2717 purb
= (PURB
) sync_param
->context
;
2719 if (ehci
== NULL
|| purb
== NULL
)
2720 return (UCHAR
) (sync_param
->ret
= FALSE
);
2722 return (UCHAR
) (sync_param
->ret
= ehci_insert_urb_schedule(ehci
, purb
));
2725 static BOOLEAN NTAPI
2726 ehci_sync_cancel_urb(PVOID context
)
2728 //cancel a single purb
2730 PSYNC_PARAM sync_param
;
2731 PURB purb2
, dest_urb
;
2732 PLIST_ENTRY pthis
, pnext
;
2733 BOOLEAN found
= FALSE
;
2735 if (context
== NULL
)
2738 sync_param
= (PSYNC_PARAM
) context
;
2739 ehci
= sync_param
->ehci
;
2740 dest_urb
= (PURB
) sync_param
->context
;
2742 if (ehci
== NULL
|| dest_urb
== NULL
)
2743 return (UCHAR
) (sync_param
->ret
= FALSE
);
2745 ListFirst(&ehci
->urb_list
, pthis
);
2748 purb2
= (PURB
) pthis
;
2749 if (purb2
== dest_urb
)
2752 purb2
->flags
|= URB_FLAG_FORCE_CANCEL
;
2755 ListNext(&ehci
->urb_list
, pthis
, pnext
);
2761 press_doorbell(ehci
);
2763 return (UCHAR
) (sync_param
->ret
= found
);
2767 ehci_cancel_urb(PEHCI_DEV ehci
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
2768 //note any fields of the purb can not be referenced unless it is found in some queue
2770 PLIST_ENTRY pthis
, pnext
;
2774 SYNC_PARAM sync_param
;
2776 USE_BASIC_NON_PENDING_IRQL
;
2778 if (ehci
== NULL
|| purb
== NULL
|| pdev
== NULL
|| pendp
== NULL
)
2779 return STATUS_INVALID_PARAMETER
;
2781 lock_dev(pdev
, FALSE
);
2783 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2785 unlock_dev(pdev
, FALSE
);
2786 //delegate to remove device for this job
2787 return STATUS_DEVICE_DOES_NOT_EXIST
;
2790 if (dev_from_endp(pendp
) != pdev
)
2792 unlock_dev(pdev
, FALSE
);
2793 return STATUS_INVALID_PARAMETER
;
2796 if (endp_state(pendp
) == USB_ENDP_FLAG_STALL
)
2798 //it will be canceled in ehci_process_pending_endp
2799 unlock_dev(pdev
, FALSE
);
2800 return USB_STATUS_ENDPOINT_HALTED
;
2804 ListFirst(&pendp
->urb_list
, pthis
);
2807 purb2
= (PURB
) pthis
;
2811 RemoveEntryList(pthis
);
2812 InitializeListHead(pthis
);
2815 ListNext(&pendp
->urb_list
, pthis
, pnext
);
2818 unlock_dev(pdev
, FALSE
);
2822 purb
->status
= STATUS_CANCELLED
;
2824 ehci_generic_urb_completion(purb
, purb
->context
);
2826 lock_dev(pdev
, FALSE
);
2828 unlock_dev(pdev
, FALSE
);
2829 return STATUS_SUCCESS
;
2832 // search the purb in the purb-list and try to cancel
2833 sync_param
.ehci
= ehci
;
2834 sync_param
.context
= purb
;
2836 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_cancel_urb
, &sync_param
);
2838 found
= sync_param
.ret
;
2841 return USB_STATUS_CANCELING
;
2843 return STATUS_INVALID_PARAMETER
;
2847 ehci_generic_urb_completion(PURB purb
, PVOID context
)
2850 BOOLEAN is_ctrl
= FALSE
;
2851 USE_NON_PENDING_IRQL
;
2853 old_irql
= KeGetCurrentIrql();
2854 if (old_irql
> DISPATCH_LEVEL
)
2857 if (old_irql
< DISPATCH_LEVEL
)
2858 KeRaiseIrql(DISPATCH_LEVEL
, &old_irql
);
2862 goto LBL_LOWER_IRQL
;
2865 goto LBL_LOWER_IRQL
;
2867 lock_dev(pdev
, TRUE
);
2869 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2871 // no need to do following statistics
2872 unlock_dev(pdev
, TRUE
);
2873 goto LBL_CLIENT_PROCESS
;
2875 if (usb_error(purb
->status
))
2877 pdev
->error_count
++;
2880 if (purb
->pendp
== &pdev
->default_endp
)
2882 if (usb_halted(purb
->status
))
2884 pdev
->time_out_count
++;
2885 if (pdev
->time_out_count
> 3)
2887 dev_set_state(pdev
, USB_DEV_STATE_ZOMB
);
2888 ehci_dbg_print(DBGLVL_MAXIMUM
,
2889 ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
2894 pdev
->time_out_count
= 0;
2898 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_CONTROL
)
2901 unlock_dev(pdev
, TRUE
);
2906 if (purb
->completion
)
2907 purb
->completion(purb
, context
);
2911 if (purb
->ctrl_req_context
.ctrl_stack_count
== 0)
2913 if (purb
->completion
)
2914 purb
->completion(purb
, context
);
2918 // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
2919 // if( pstack->urb_completion )
2920 // pstack->urb_completion( purb, pstack->context );
2921 usb_call_ctrl_completion(purb
);
2926 if (old_irql
< DISPATCH_LEVEL
)
2927 KeLowerIrql(old_irql
);
2933 ehci_rh_submit_urb(PUSB_DEV pdev
, PURB purb
)
2935 PUSB_DEV_MANAGER dev_mgr
;
2937 PUSB_CTRL_SETUP_PACKET psetup
;
2940 PHUB2_EXTENSION hub_ext
;
2941 PUSB_PORT_STATUS ps
, psret
;
2945 USE_NON_PENDING_IRQL
;
2946 if (pdev
== NULL
|| purb
== NULL
)
2947 return STATUS_INVALID_PARAMETER
;
2949 dev_mgr
= dev_mgr_from_dev(pdev
);
2951 KeAcquireSpinLock(&dev_mgr
->timer_svc_list_lock
, &old_irql
);
2952 lock_dev(pdev
, FALSE
);
2953 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2955 unlock_dev(pdev
, FALSE
);
2956 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
2957 return STATUS_DEVICE_DOES_NOT_EXIST
;
2960 ehci
= ehci_from_hcd(pdev
->hcd
);
2961 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2963 hub_ext
= ((PHUB2_EXTENSION
) pdev
->dev_ext
);
2964 port_count
= (UCHAR
) ((PEHCI_HCS_CONTENT
) & ehci
->ehci_caps
.hcs_params
)->port_count
;
2966 switch (endp_type(purb
->pendp
))
2968 case USB_ENDPOINT_XFER_CONTROL
:
2970 if (psetup
->bmRequestType
== 0xa3 && psetup
->bRequest
== USB_REQ_GET_STATUS
)
2973 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
< 4)
2975 purb
->status
= STATUS_INVALID_PARAMETER
;
2979 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
2980 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
2981 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
2983 psret
= (PUSB_PORT_STATUS
) purb
->data_buffer
;
2984 ps
->wPortStatus
= 0;
2986 if (status
& PORT_CCS
)
2988 ps
->wPortStatus
|= USB_PORT_STAT_CONNECTION
;
2990 if (status
& PORT_PE
)
2992 ps
->wPortStatus
|= USB_PORT_STAT_ENABLE
;
2993 ps
->wPortStatus
|= USB_PORT_STAT_HIGH_SPEED
; // ehci spec
2995 if (status
& PORT_PR
)
2997 ps
->wPortStatus
|= USB_PORT_STAT_RESET
;
2999 if (status
& PORT_SUSP
)
3001 ps
->wPortStatus
|= USB_PORT_STAT_SUSPEND
;
3003 if (PORT_USB11(status
))
3005 ps
->wPortStatus
|= USB_PORT_STAT_LOW_SPEED
;
3009 ps
->wPortStatus
|= USB_PORT_STAT_POWER
;
3011 //now set change field
3012 if ((status
& PORT_CSC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
3014 ps
->wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
3016 if ((status
& PORT_PEC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
3018 ps
->wPortChange
|= USB_PORT_STAT_C_ENABLE
;
3021 //don't touch other fields, might be filled by
3024 usb_dbg_print(DBGLVL_MAXIMUM
,
3025 ("ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
3026 ps
->wPortStatus
, ps
->wPortChange
, ps
));
3028 psret
->wPortChange
= ps
->wPortChange
;
3029 psret
->wPortStatus
= ps
->wPortStatus
;
3031 purb
->status
= STATUS_SUCCESS
;
3035 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_CLEAR_FEATURE
)
3037 //clear-port-feature
3038 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
)
3040 purb
->status
= STATUS_INVALID_PARAMETER
;
3044 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3045 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
3047 purb
->status
= STATUS_SUCCESS
;
3048 switch (psetup
->wValue
)
3050 case USB_PORT_FEAT_C_CONNECTION
:
3052 SET_RH2_PORTSTAT(i
, USBPORTSC_CSC
);
3053 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3054 usb_dbg_print(DBGLVL_MAXIMUM
,
3055 ("ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup
->wIndex
));
3056 ps
->wPortChange
&= ~USB_PORT_STAT_C_CONNECTION
;
3059 case USB_PORT_FEAT_C_ENABLE
:
3061 SET_RH2_PORTSTAT(i
, USBPORTSC_PEC
);
3062 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3063 usb_dbg_print(DBGLVL_MAXIMUM
,
3064 ("ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup
->wIndex
));
3065 ps
->wPortChange
&= ~USB_PORT_STAT_C_ENABLE
;
3068 case USB_PORT_FEAT_C_RESET
:
3070 ps
->wPortChange
&= ~USB_PORT_STAT_C_RESET
;
3071 //the reset signal is down in rh_timer_svc_reset_port_completion
3072 // enable or not is set by host controller
3073 // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
3074 usb_dbg_print(DBGLVL_MAXIMUM
,
3075 ("ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
3079 case USB_PORT_FEAT_ENABLE
:
3081 ps
->wPortStatus
&= ~USB_PORT_STAT_ENABLE
;
3082 CLR_RH2_PORTSTAT(i
, USBPORTSC_PE
);
3083 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3084 usb_dbg_print(DBGLVL_MAXIMUM
,
3085 ("ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup
->wIndex
));
3089 purb
->status
= STATUS_UNSUCCESSFUL
;
3093 else if (psetup
->bmRequestType
== 0xd3 && psetup
->bRequest
== HUB_REQ_GET_STATE
)
3096 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
== 0)
3098 purb
->status
= STATUS_INVALID_PARAMETER
;
3102 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3103 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3104 purb
->data_buffer
[0] = (status
& USBPORTSC_LS
);
3106 // reverse the order
3107 purb
->data_buffer
[0] ^= 0x3;
3108 purb
->status
= STATUS_SUCCESS
;
3111 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_SET_FEATURE
)
3114 if (psetup
->wValue
!= USB_PORT_FEAT_RESET
)
3116 purb
->status
= STATUS_INVALID_PARAMETER
;
3117 ehci_dbg_print(DBGLVL_MAXIMUM
,
3118 ("ehci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup
->wValue
));
3122 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3124 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
3127 purb
->status
= STATUS_NO_MEMORY
;
3131 ptimer
->threshold
= 0; // within [ 50ms, 60ms ], one tick is 10 ms
3132 ptimer
->context
= (ULONG
) purb
;
3133 ptimer
->pdev
= pdev
;
3134 ptimer
->func
= rh_timer_svc_reset_port_completion
;
3137 pdev
->ref_count
+= 2; //one for timer and one for purb
3139 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3140 usb_dbg_print(DBGLVL_MAXIMUM
,
3141 ("ehci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup
->wIndex
, status
));
3142 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
3143 purb
->status
= STATUS_PENDING
;
3147 purb
->status
= STATUS_INVALID_PARAMETER
;
3151 case USB_ENDPOINT_XFER_INT
:
3153 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
3156 purb
->status
= STATUS_NO_MEMORY
;
3159 ptimer
->threshold
= RH_INTERVAL
;
3160 ptimer
->context
= (ULONG
) purb
;
3161 ptimer
->pdev
= pdev
;
3162 ptimer
->func
= rh_timer_svc_int_completion
;
3165 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
3167 usb_dbg_print(DBGLVL_MAXIMUM
,
3168 ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev
->ref_count
));
3169 pdev
->ref_count
+= 2; //one for timer and one for purb
3171 purb
->status
= STATUS_PENDING
;
3174 case USB_ENDPOINT_XFER_BULK
:
3175 case USB_ENDPOINT_XFER_ISOC
:
3178 purb
->status
= STATUS_INVALID_PARAMETER
;
3182 unlock_dev(pdev
, FALSE
);
3183 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
3184 return purb
->status
;
3187 //must have rh dev_lock acquired
3189 ehci_rh_reset_port(PHCD hcd
, UCHAR port_idx
)
3199 ehci
= ehci_from_hcd(hcd
);
3200 port_count
= (UCHAR
) ((PEHCI_HCS_CONTENT
) & ehci
->ehci_caps
.hcs_params
)->port_count
;
3202 if (port_idx
< 1 || port_idx
> port_count
)
3205 i
= (ULONG
) (EHCI_PORTSC
+ 4 * (port_idx
- 1));
3207 // assert the reset signal,(implicitly disable the port)
3208 SET_RH2_PORTSTAT(i
, PORT_PR
);
3210 usb_wait_ms_dpc(50);
3211 // clear the reset signal, delay port enable till clearing port feature
3212 CLR_RH2_PORTSTAT(i
, PORT_PR
);
3214 // wait the port stable
3217 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3218 if (!(status
& PORT_PE
))
3220 // release the ownership from ehci to companion hc
3221 status
|= PORT_OWNER
;
3222 EHCI_WRITE_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
), status
);
3223 // the host controller will set PORTSC automatically
3226 usb_wait_us_dpc(10);
3227 // SET_RH_PORTSTAT( i, PORT_PE );
3229 //recovery time 10ms
3230 usb_wait_ms_dpc(10);
3232 // clear PORT_PEC and PORT_PCC
3233 SET_RH2_PORTSTAT(i
, 0x0a);
3235 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3236 usb_dbg_print(DBGLVL_MAXIMUM
, ("ehci_rh_reset_port(): status after written=0x%x\n", status
));
3241 ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp
)
3243 PEHCI_DEVICE_EXTENSION pdev_ext
;
3244 PUSB_DEV_MANAGER dev_mgr
;
3247 pdev_ext
= DeviceObject
->DeviceExtension
;
3248 ehci
= pdev_ext
->ehci
;
3250 dev_mgr
= ehci
->hcd_interf
.hcd_get_dev_mgr(&ehci
->hcd_interf
);
3251 return dev_mgr_dispatch(dev_mgr
, irp
);
3254 //the following are for hcd interface methods
3256 ehci_set_dev_mgr(PHCD hcd
, PUSB_DEV_MANAGER dev_mgr
)
3258 hcd
->dev_mgr
= dev_mgr
;
3262 ehci_get_dev_mgr(PHCD hcd
)
3264 return hcd
->dev_mgr
;
3268 ehci_get_type(PHCD hcd
)
3270 return HCD_TYPE_EHCI
; // ( hcd->flags & HCD_TYPE_MASK );
3274 ehci_set_id(PHCD hcd
, UCHAR id
)
3276 hcd
->flags
&= ~HCD_ID_MASK
;
3277 hcd
->flags
|= (HCD_ID_MASK
& id
);
3281 ehci_get_id(PHCD hcd
)
3283 return (UCHAR
) (hcd
->flags
& HCD_ID_MASK
);
3288 ehci_alloc_addr(PHCD hcd
)
3294 for(i
= 1; i
< MAX_DEVS
; i
++)
3296 if (hcd
->dev_addr_map
[i
>> 3] & (1 << (i
& 7)))
3309 hcd
->dev_addr_map
[i
>> 3] |= (1 << (i
& 7));
3315 ehci_free_addr(PHCD hcd
, UCHAR addr
)
3323 hcd
->dev_addr_map
[addr
>> 3] &= ~(1 << (addr
& 7));
3329 ehci_submit_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
3331 return ehci_submit_urb(ehci_from_hcd(hcd
), pdev
, pendp
, purb
);
3335 ehci_get_root_hub(PHCD hcd
)
3337 return ehci_from_hcd(hcd
)->root_hub
;
3341 ehci_set_root_hub(PHCD hcd
, PUSB_DEV root_hub
)
3343 if (hcd
== NULL
|| root_hub
== NULL
)
3345 ehci_from_hcd(hcd
)->root_hub
= root_hub
;
3350 ehci_remove_device2(PHCD hcd
, PUSB_DEV pdev
)
3352 if (hcd
== NULL
|| pdev
== NULL
)
3355 return ehci_remove_device(ehci_from_hcd(hcd
), pdev
);
3359 ehci_hcd_release(PHCD hcd
)
3362 PEHCI_DEVICE_EXTENSION pdev_ext
;
3367 ehci
= ehci_from_hcd(hcd
);
3368 pdev_ext
= ehci
->pdev_ext
;
3369 return ehci_release(pdev_ext
->pdev_obj
, hcd
->dev_mgr
);
3373 ehci_cancel_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
3377 return STATUS_INVALID_PARAMETER
;
3379 ehci
= ehci_from_hcd(hcd
);
3380 return ehci_cancel_urb(ehci
, pdev
, pendp
, purb
);
3384 ehci_rh_get_dev_change(PHCD hcd
, PBYTE buf
) //must have the rh dev_lock acquired
3393 ehci
= ehci_from_hcd(hcd
);
3394 port_count
= HCS_N_PORTS(ehci
->ehci_caps
.hcs_params
);
3395 for(i
= 0; i
< port_count
; i
++)
3397 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_PORTSC
+ (i
<< 2)));
3398 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_rh_get_dev_change(): erh port%d status=0x%x\n", i
, status
));
3400 if (status
& (PORT_PEC
| PORT_CSC
| PORT_OCC
))
3402 buf
[(i
+ 1) >> 3] |= (1 << ((i
+ 1) & 7));
3409 ehci_hcd_dispatch(PHCD hcd
, LONG disp_code
, PVOID param
)
3414 return STATUS_INVALID_PARAMETER
;
3415 ehci
= ehci_from_hcd(hcd
);
3418 case HCD_DISP_READ_PORT_COUNT
:
3421 return STATUS_INVALID_PARAMETER
;
3422 *((PUCHAR
) param
) = (UCHAR
) HCS_N_PORTS(ehci
->ehci_caps
.hcs_params
);
3423 return STATUS_SUCCESS
;
3425 case HCD_DISP_READ_RH_DEV_CHANGE
:
3427 if (ehci_rh_get_dev_change(hcd
, param
) == FALSE
)
3428 return STATUS_INVALID_PARAMETER
;
3429 return STATUS_SUCCESS
;
3432 return STATUS_NOT_IMPLEMENTED
;
3435 //------------------------------------------------------------------------------
3436 // EHCI routines follows
3438 VOID
ehci_init_int8_qh(PEHCI_QH_CONTENT qh
);
3441 ehci_cal_cpu_freq(PVOID context
)
3448 ehci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, PUSB_DEV_MANAGER dev_mgr
)
3450 LONG bus
, i
, j
, ret
= 0;
3451 PCI_SLOT_NUMBER slot_num
;
3452 PPCI_COMMON_CONFIG pci_config
;
3453 PDEVICE_OBJECT pdev
;
3454 BYTE buffer
[sizeof(PCI_COMMON_CONFIG
)];
3455 PEHCI_DEVICE_EXTENSION pdev_ext
;
3458 slot_num
.u
.AsULONG
= 0;
3459 pci_config
= (PPCI_COMMON_CONFIG
) buffer
;
3462 //scan the PCI buses to find ehci controller
3463 for (bus
= 0; bus
<= PCI_MAX_BRIDGE_NUMBER
; bus
++) //Yes, it should be <=
3465 for(i
= 0; i
<= PCI_MAX_DEVICES
; i
++)
3467 slot_num
.u
.bits
.DeviceNumber
= i
;
3468 for(j
= 0; j
<= PCI_MAX_FUNCTION
; j
++)
3470 slot_num
.u
.bits
.FunctionNumber
= j
;
3472 ret
= HalGetBusData(PCIConfiguration
,
3473 bus
, slot_num
.u
.AsULONG
, pci_config
, PCI_COMMON_HDR_LENGTH
);
3475 if (ret
== 0) /*no this bus */
3478 if (ret
== 2) /*no device on the slot */
3481 if (pci_config
->BaseClass
== 0x0c && pci_config
->SubClass
== 0x03
3482 && pci_config
->ProgIf
== 0x20)
3484 //well, we find our usb host controller( EHCI ), create device
3485 pdev
= ehci_alloc(drvr_obj
, reg_path
, ((bus
<< 8) | (i
<< 3) | j
), dev_mgr
);
3503 DbgPrint("Found %d EHCI controllers\n", count
);
3507 pdev_ext
= pdev
->DeviceExtension
;
3510 // acquire higher irql to eliminate pre-empty
3511 KeSynchronizeExecution(pdev_ext
->ehci_int
, ehci_cal_cpu_freq
, NULL
);
3518 ehci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
)
3521 LONG frd_num
, prd_num
;
3522 PDEVICE_OBJECT pdev
;
3523 PEHCI_DEVICE_EXTENSION pdev_ext
;
3524 ULONG vector
, addr_space
;
3529 DEVICE_DESCRIPTION dev_desc
;
3530 CM_PARTIAL_RESOURCE_DESCRIPTOR
*pprd
;
3531 PCI_SLOT_NUMBER slot_num
;
3535 pdev
= ehci_create_device(drvr_obj
, dev_mgr
);
3540 pdev_ext
= pdev
->DeviceExtension
;
3542 pdev_ext
->pci_addr
= bus_addr
;
3543 bus
= (bus_addr
>> 8);
3545 slot_num
.u
.AsULONG
= 0;
3546 slot_num
.u
.bits
.DeviceNumber
= ((bus_addr
& 0xff) >> 3);
3547 slot_num
.u
.bits
.FunctionNumber
= (bus_addr
& 0x07);
3549 //now create adapter object
3550 RtlZeroMemory(&dev_desc
, sizeof(dev_desc
));
3552 dev_desc
.Version
= DEVICE_DESCRIPTION_VERSION
;
3553 dev_desc
.Master
= TRUE
;
3554 dev_desc
.ScatterGather
= TRUE
;
3555 dev_desc
.Dma32BitAddresses
= TRUE
;
3556 dev_desc
.BusNumber
= bus
;
3557 dev_desc
.InterfaceType
= PCIBus
;
3558 dev_desc
.MaximumLength
= EHCI_MAX_SIZE_TRANSFER
;
3560 pdev_ext
->map_regs
= 2; // we do not use it seriously
3562 pdev_ext
->padapter
= HalGetAdapter(&dev_desc
, &pdev_ext
->map_regs
);
3564 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_alloc(): padapter=0x%x\n", pdev_ext
->padapter
));
3565 if (pdev_ext
->padapter
== NULL
)
3568 ehci_delete_device(pdev
, dev_mgr
);
3572 DbgPrint("ehci_alloc(): reg_path=0x%x, \n \
3573 ehci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
3574 ehci_alloc(): slot_num=0x%x, &res_list=0x%x \n \
3575 ehci_alloc(): adapter=0x%x \n", (DWORD
) reg_path
, (DWORD
) PCIBus
, (DWORD
) bus
, (DWORD
) bus_addr
, (DWORD
) slot_num
.u
.AsULONG
, (DWORD
) & pdev_ext
->res_list
, pdev_ext
->padapter
);
3577 //let's allocate resources for this device
3578 DbgPrint("ehci_alloc(): about to assign slot res\n");
3579 if ((status
= HalAssignSlotResources(reg_path
, NULL
, //no class name yet
3580 drvr_obj
, NULL
, //no support of another ehci controller
3582 bus
, slot_num
.u
.AsULONG
, &pdev_ext
->res_list
)) != STATUS_SUCCESS
)
3584 DbgPrint("ehci_alloc(): error assign slot res, 0x%x\n", status
);
3585 release_adapter(pdev_ext
->padapter
);
3586 pdev_ext
->padapter
= NULL
;
3587 ehci_delete_device(pdev
, dev_mgr
);
3591 //parse the resource list
3592 for(frd_num
= 0; frd_num
< (LONG
) pdev_ext
->res_list
->Count
; frd_num
++)
3594 for(prd_num
= 0; prd_num
< (LONG
) pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.Count
;
3597 pprd
= &pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.PartialDescriptors
[prd_num
];
3598 if (pprd
->Type
== CmResourceTypePort
)
3600 RtlCopyMemory(&pdev_ext
->res_port
, &pprd
->u
.Port
, sizeof(pprd
->u
.Port
));
3603 else if (pprd
->Type
== CmResourceTypeInterrupt
)
3605 RtlCopyMemory(&pdev_ext
->res_interrupt
, &pprd
->u
.Interrupt
, sizeof(pprd
->u
.Interrupt
));
3607 else if (pprd
->Type
== CmResourceTypeMemory
)
3609 RtlCopyMemory(&pdev_ext
->res_memory
, &pprd
->u
.Memory
, sizeof(pprd
->u
.Memory
));
3614 //for port, translate them to system address
3616 if (HalTranslateBusAddress(PCIBus
, bus
, pdev_ext
->res_port
.Start
, &addr_space
, //io space
3617 &pdev_ext
->ehci
->ehci_reg_base
) != (BOOLEAN
) TRUE
)
3619 DbgPrint("ehci_alloc(): error, can not translate bus address\n");
3620 release_adapter(pdev_ext
->padapter
);
3621 pdev_ext
->padapter
= NULL
;
3622 ehci_delete_device(pdev
, dev_mgr
);
3626 DbgPrint("ehci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
3627 addr_space
, pdev_ext
->ehci
->ehci_reg_base
.u
.LowPart
);
3629 if (addr_space
== 0)
3631 //port has been mapped to memory space
3632 pdev_ext
->ehci
->port_mapped
= TRUE
;
3633 pdev_ext
->ehci
->port_base
= (PBYTE
) MmMapIoSpace(pdev_ext
->ehci
->ehci_reg_base
,
3634 pdev_ext
->res_port
.Length
, FALSE
);
3636 //fatal error can not map the registers
3637 if (pdev_ext
->ehci
->port_base
== NULL
)
3639 release_adapter(pdev_ext
->padapter
);
3640 pdev_ext
->padapter
= NULL
;
3641 ehci_delete_device(pdev
, dev_mgr
);
3648 pdev_ext
->ehci
->port_mapped
= FALSE
;
3649 pdev_ext
->ehci
->port_base
= (PBYTE
) pdev_ext
->ehci
->ehci_reg_base
.LowPart
;
3652 //before we connect the interrupt, we have to init ehci
3653 pdev_ext
->ehci
->pdev_ext
= pdev_ext
;
3656 // i = ( ( PEHCI_HCS_CONTENT )( &pdev_ext->ehci->ehci_caps.hcs_params ) )->length;
3658 ehci_get_capabilities(pdev_ext
->ehci
, pdev_ext
->ehci
->port_base
);
3659 i
= pdev_ext
->ehci
->ehci_caps
.length
;
3660 pdev_ext
->ehci
->port_base
+= i
;
3662 if (ehci_init_schedule(pdev_ext
->ehci
, pdev_ext
->padapter
) == FALSE
)
3664 release_adapter(pdev_ext
->padapter
);
3665 pdev_ext
->padapter
= NULL
;
3666 ehci_delete_device(pdev
, dev_mgr
);
3670 InitializeListHead(&pdev_ext
->ehci
->urb_list
);
3671 KeInitializeSpinLock(&pdev_ext
->ehci
->pending_endp_list_lock
);
3672 InitializeListHead(&pdev_ext
->ehci
->pending_endp_list
);
3674 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_alloc(): pending_endp_list=0x%x\n",
3675 &pdev_ext
->ehci
->pending_endp_list
));
3677 init_pending_endp_pool(&pdev_ext
->ehci
->pending_endp_pool
);
3679 KeInitializeTimer(&pdev_ext
->ehci
->reset_timer
);
3681 vector
= HalGetInterruptVector(PCIBus
,
3683 pdev_ext
->res_interrupt
.level
,
3684 pdev_ext
->res_interrupt
.vector
, &irql
, &affinity
);
3686 KeInitializeDpc(&pdev_ext
->ehci_dpc
, ehci_dpc_callback
, (PVOID
) pdev_ext
->ehci
);
3688 //connect the interrupt
3689 DbgPrint("ehci_alloc(): the int=0x%x\n", vector
);
3690 if (IoConnectInterrupt(&pdev_ext
->ehci_int
, ehci_isr
, pdev_ext
->ehci
, NULL
, //&pdev_ext->ehci->frame_list_lock,
3691 vector
, irql
, irql
, LevelSensitive
, TRUE
, //share the vector
3692 affinity
, FALSE
) //No float save
3695 ehci_release(pdev
, dev_mgr
);
3703 ehci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
)
3706 PDEVICE_OBJECT pdev
;
3707 PEHCI_DEVICE_EXTENSION pdev_ext
;
3709 UNICODE_STRING dev_name
;
3710 UNICODE_STRING symb_name
;
3712 STRING string
, another_string
;
3713 CHAR str_dev_name
[64], str_symb_name
[64];
3716 if (drvr_obj
== NULL
)
3719 //note: hcd count wont increment till the hcd is registered in dev_mgr
3720 sprintf(str_dev_name
, "%s%d", EHCI_DEVICE_NAME
, dev_mgr
->hcd_count
);
3721 sprintf(str_symb_name
, "%s%d", EHCI_DOS_DEVICE_NAME
, dev_mgr
->hcd_count
);
3723 RtlInitString(&string
, str_dev_name
);
3724 RtlAnsiStringToUnicodeString(&dev_name
, &string
, TRUE
);
3727 status
= IoCreateDevice(drvr_obj
,
3728 sizeof(EHCI_DEVICE_EXTENSION
) + sizeof(EHCI_DEV
),
3729 &dev_name
, FILE_EHCI_DEV_TYPE
, 0, FALSE
, &pdev
);
3731 if (status
!= STATUS_SUCCESS
|| pdev
== NULL
)
3733 RtlFreeUnicodeString(&dev_name
);
3734 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_create_device(): error create device 0x%x\n", status
));
3738 pdev_ext
= pdev
->DeviceExtension
;
3739 RtlZeroMemory(pdev_ext
, sizeof(EHCI_DEVICE_EXTENSION
) + sizeof(EHCI_DEV
));
3741 pdev_ext
->dev_ext_hdr
.type
= NTDEV_TYPE_HCD
;
3742 pdev_ext
->dev_ext_hdr
.dispatch
= ehci_dispatch_irp
;
3743 pdev_ext
->dev_ext_hdr
.start_io
= NULL
; //we do not support startio
3744 pdev_ext
->dev_ext_hdr
.dev_mgr
= dev_mgr
;
3746 pdev_ext
->pdev_obj
= pdev
;
3747 pdev_ext
->pdrvr_obj
= drvr_obj
;
3749 pdev_ext
->ehci
= (PEHCI_DEV
) & (pdev_ext
[1]);
3751 RtlInitString(&another_string
, str_symb_name
);
3752 RtlAnsiStringToUnicodeString(&symb_name
, &another_string
, TRUE
);
3753 //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME );
3755 IoCreateSymbolicLink(&symb_name
, &dev_name
);
3757 ehci_dbg_print(DBGLVL_MAXIMUM
,
3758 ("ehci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev
,
3759 pdev_ext
, pdev_ext
->ehci
, dev_mgr
));
3761 RtlFreeUnicodeString(&dev_name
);
3762 RtlFreeUnicodeString(&symb_name
);
3764 //register with dev_mgr though it is not initilized
3765 ehci_init_hcd_interface(pdev_ext
->ehci
);
3766 hcd_id
= dev_mgr_register_hcd(dev_mgr
, &pdev_ext
->ehci
->hcd_interf
);
3768 pdev_ext
->ehci
->hcd_interf
.hcd_set_id(&pdev_ext
->ehci
->hcd_interf
, hcd_id
);
3769 pdev_ext
->ehci
->hcd_interf
.hcd_set_dev_mgr(&pdev_ext
->ehci
->hcd_interf
, dev_mgr
);
3776 ehci_init_hcd_interface(PEHCI_DEV ehci
)
3778 ehci
->hcd_interf
.hcd_set_dev_mgr
= ehci_set_dev_mgr
;
3779 ehci
->hcd_interf
.hcd_get_dev_mgr
= ehci_get_dev_mgr
;
3780 ehci
->hcd_interf
.hcd_get_type
= ehci_get_type
;
3781 ehci
->hcd_interf
.hcd_set_id
= ehci_set_id
;
3782 ehci
->hcd_interf
.hcd_get_id
= ehci_get_id
;
3783 ehci
->hcd_interf
.hcd_alloc_addr
= ehci_alloc_addr
;
3784 ehci
->hcd_interf
.hcd_free_addr
= ehci_free_addr
;
3785 ehci
->hcd_interf
.hcd_submit_urb
= ehci_submit_urb2
;
3786 ehci
->hcd_interf
.hcd_generic_urb_completion
= ehci_generic_urb_completion
;
3787 ehci
->hcd_interf
.hcd_get_root_hub
= ehci_get_root_hub
;
3788 ehci
->hcd_interf
.hcd_set_root_hub
= ehci_set_root_hub
;
3789 ehci
->hcd_interf
.hcd_remove_device
= ehci_remove_device2
;
3790 ehci
->hcd_interf
.hcd_rh_reset_port
= ehci_rh_reset_port
;
3791 ehci
->hcd_interf
.hcd_release
= ehci_hcd_release
;
3792 ehci
->hcd_interf
.hcd_cancel_urb
= ehci_cancel_urb2
;
3793 ehci
->hcd_interf
.hcd_start
= ehci_start
;
3794 ehci
->hcd_interf
.hcd_dispatch
= ehci_hcd_dispatch
;
3796 ehci
->hcd_interf
.flags
= HCD_TYPE_EHCI
; //hcd types | hcd id
3800 ehci_init_schedule(PEHCI_DEV ehci
, PADAPTER_OBJECT padapter
)
3802 PEHCI_DEVICE_EXTENSION pdev_ext
;
3805 PEHCI_QH_CONTENT pqh_content
;
3807 PEHCI_ELEM_LINKS pelnk
;
3812 pdev_ext
= ehci
->pdev_ext
;
3813 if (pdev_ext
== NULL
)
3816 // padapter = pdev_ext->padapter;
3817 if (ehci
->frame_count
== 0)
3818 ehci
->frame_count
= EHCI_DEFAULT_FRAMES
;
3821 for(i
= 0; i
< 5; i
++)
3823 ret
= elem_pool_init_pool(&ehci
->elem_pools
[i
], i
, padapter
);
3832 elem_pool_destroy_pool(&ehci
->elem_pools
[i
]);
3836 // allocate periodic frame list
3838 HalAllocateCommonBuffer(padapter
,
3839 sizeof(ULONG
) * ehci
->frame_count
, &ehci
->frame_list_phys_addr
, FALSE
);
3840 if (ehci
->frame_list
== NULL
)
3843 RtlZeroMemory(ehci
->frame_list
, sizeof(ULONG
) * ehci
->frame_count
);
3844 ehci
->frame_list_cpu
= usb_alloc_mem(NonPagedPool
, sizeof(LIST_HEAD
) * ehci
->frame_count
);
3846 if (ehci
->frame_list_cpu
== NULL
)
3849 for(i
= 0; i
< (LONG
) ehci
->frame_count
; i
++)
3851 InitializeListHead(&ehci
->frame_list_cpu
[i
].td_link
);
3854 for(i
= 0; i
< 8; i
++)
3856 InitializeListHead(&ehci
->periodic_list_cpu
[i
]);
3859 InitializeListHead(&ehci
->async_list_cpu
);
3861 // init frame band budget array
3862 ehci
->frame_bw
= usb_alloc_mem(NonPagedPool
, sizeof(USHORT
) * ehci
->frame_count
* 8);
3863 if (ehci
->frame_bw
== NULL
)
3866 for(i
= 0; i
< (LONG
) ehci
->frame_count
* 8; i
++)
3868 ehci
->frame_bw
[i
] = EHCI_MAX_SYNC_BUS_TIME
;
3870 ehci
->min_bw
= EHCI_MAX_SYNC_BUS_TIME
;
3872 // chain the 1ms interrupt qh to the schedule
3873 if ((pelnk
= elem_pool_alloc_elem(&ehci
->elem_pools
[EHCI_QH_POOL_IDX
])) == NULL
)
3876 pqh_content
= (PEHCI_QH_CONTENT
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
3877 ehci_init_int8_qh(pqh_content
);
3879 // chain qh to the shadow list
3880 InsertTailList(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], &pelnk
->sched_link
);
3882 // chain it to the periodic schedule, we use it as a docking point
3883 // for req of 8- uframes request
3884 pqh
= (PEHCI_QH
) pqh_content
;
3886 for(i
= 0; i
< (LONG
) ehci
->frame_count
; i
++)
3888 ehci
->frame_list
[i
] = pqh
->phys_addr
;
3892 /*if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) ) == NULL )
3895 pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
3896 pfstn->hw_next = EHCI_PTR_TERM;
3897 pfstn->hw_prev = EHCI_PTR_TERM | ( INIT_LIST_FLAG_QH << 1 );
3898 InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ], &pelnk->sched_link );
3899 pqh->hw_next = pfstn->phys_addr; */
3901 // allocate for async list head
3902 if ((pelnk
= elem_pool_alloc_elem(&ehci
->elem_pools
[EHCI_QH_POOL_IDX
])) == NULL
)
3905 // init the async list head
3906 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
3907 pqh_content
= (PEHCI_QH_CONTENT
) pqh
;
3908 ehci_init_int8_qh(pqh_content
);
3909 pqh
->hw_next
= pqh
->phys_addr
;
3910 pqh_content
->s_mask
= 0;
3911 pqh_content
->is_async_head
= 1;
3912 pqh_content
->endp_addr
= 0;
3913 ehci
->skel_async_qh
= pqh
;
3914 InsertTailList(&ehci
->async_list_cpu
, &pqh
->elem_head_link
->sched_link
);
3918 ehci_destroy_schedule(ehci
);
3923 ehci_destroy_schedule(PEHCI_DEV ehci
)
3930 usb_free_mem(ehci
->frame_bw
);
3931 ehci
->frame_bw
= NULL
;
3933 if (ehci
->frame_list_cpu
)
3934 usb_free_mem(ehci
->frame_list_cpu
);
3935 ehci
->frame_list_cpu
= NULL
;
3937 if (ehci
->frame_list
)
3938 HalFreeCommonBuffer(ehci
->pdev_ext
->padapter
,
3939 sizeof(ULONG
) * ehci
->frame_count
,
3940 ehci
->frame_list_phys_addr
, ehci
->frame_list
, FALSE
);
3942 ehci
->frame_list
= NULL
;
3943 ehci
->frame_list_phys_addr
.LowPart
= 0;
3944 ehci
->frame_list_phys_addr
.HighPart
= 0;
3946 for(i
= 0; i
< 5; i
++)
3947 elem_pool_destroy_pool(&ehci
->elem_pools
[i
]);
3953 ehci_init_int8_qh(PEHCI_QH_CONTENT qh
)
3958 qh
->terminal
= EHCI_PTR_TERM
;
3964 qh
->dev_addr
= 126; // a fake addr
3966 qh
->endp_addr
= 1; // a fake endp
3967 qh
->endp_spd
= USB_SPEED_HIGH
;
3968 qh
->data_toggle
= 0;
3969 qh
->is_async_head
= 0;
3970 qh
->max_packet_size
= 64;
3971 qh
->is_ctrl_endp
= 0;
3972 qh
->reload_counter
= 0;
3975 qh
->s_mask
= 0x80; // we are interrupt qh
3982 qh
->cur_qtd_ptr
= 0; // a terminal
3985 // !active and !halted
3986 RtlZeroMemory(&qh
->cur_qtd
, get_elem_phys_part_size(INIT_LIST_FLAG_QTD
));
3987 qh
->cur_qtd
.alt_terminal
= 1; // don't use this
3988 qh
->cur_qtd
.terminal
= 1;
3989 qh
->cur_qtd
.status
= QTD_STS_HALT
;
3993 ehci_get_capabilities(PEHCI_DEV ehci
, PBYTE base
)
3994 // fetch capabilities register from ehci
3997 PEHCI_HCS_CONTENT phcs
;
4003 pcap
= &ehci
->ehci_caps
;
4004 pcap
->length
= EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 0));
4005 pcap
->reserved
= EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 1));
4006 pcap
->hci_version
= EHCI_READ_PORT_USHORT((PUSHORT
) (base
+ 2));
4007 pcap
->hcs_params
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ 4));
4008 pcap
->hcc_params
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ 8));
4010 phcs
= (PEHCI_HCS_CONTENT
) & pcap
->hcs_params
;
4011 if (phcs
->port_rout_rules
)
4013 for(i
= 0; i
< 8; i
++)
4014 pcap
->portroute
[i
] = EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 12 + i
));
4020 ehci_delete_device(PDEVICE_OBJECT pdev
, PUSB_DEV_MANAGER dev_mgr
)
4023 UNICODE_STRING symb_name
;
4024 CHAR str_symb_name
[64];
4025 PEHCI_DEVICE_EXTENSION pdev_ext
;
4030 pdev_ext
= pdev
->DeviceExtension
;
4032 sprintf(str_symb_name
,
4033 "%s%d", EHCI_DOS_DEVICE_NAME
, pdev_ext
->ehci
->hcd_interf
.hcd_get_id(&pdev_ext
->ehci
->hcd_interf
));
4035 RtlInitString(&string
, str_symb_name
);
4036 RtlAnsiStringToUnicodeString(&symb_name
, &string
, TRUE
);
4037 IoDeleteSymbolicLink(&symb_name
);
4038 RtlFreeUnicodeString(&symb_name
);
4040 dev_mgr_deregister_hcd(dev_mgr
, pdev_ext
->ehci
->hcd_interf
.hcd_get_id(&pdev_ext
->ehci
->hcd_interf
));
4042 if (pdev_ext
->res_list
)
4043 ExFreePool(pdev_ext
->res_list
); // not allocated by usb_alloc_mem
4045 IoDeleteDevice(pdev
);
4046 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_delete_device(): device deleted\n"));
4051 ehci_stop(PEHCI_DEV ehci
)
4054 PEHCI_USBCMD_CONTENT usbcmd
;
4057 base
= ehci
->port_base
;
4058 // turn off all the interrupt
4059 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBINTR
), 0);
4060 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4061 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4062 usbcmd
->run_stop
= 0;
4063 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4067 ehci_release(PDEVICE_OBJECT pdev
, PUSB_DEV_MANAGER dev_mgr
)
4069 PEHCI_DEVICE_EXTENSION pdev_ext
;
4075 pdev_ext
= pdev
->DeviceExtension
;
4077 if (pdev_ext
== NULL
)
4080 ehci
= pdev_ext
->ehci
;
4086 if (pdev_ext
->ehci_int
)
4088 IoDisconnectInterrupt(pdev_ext
->ehci_int
);
4089 pdev_ext
->ehci_int
= NULL
;
4093 destroy_pending_endp_pool(&pdev_ext
->ehci
->pending_endp_pool
);
4095 ehci_destroy_schedule(ehci
);
4097 release_adapter(pdev_ext
->padapter
);
4098 pdev_ext
->padapter
= NULL
;
4100 ehci_delete_device(pdev
, dev_mgr
);
4107 ehci_start(PHCD hcd
)
4111 PEHCI_USBCMD_CONTENT usbcmd
;
4117 ehci
= struct_ptr(hcd
, EHCI_DEV
, hcd_interf
);
4118 base
= ehci
->port_base
;
4120 // stop the controller
4121 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4122 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4123 usbcmd
->run_stop
= 0;
4124 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4126 // wait the controller stop( ehci spec, 16 microframe )
4129 // reset the controller
4130 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4131 usbcmd
->hcreset
= TRUE
;
4132 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4136 // interval.QuadPart = -100 * 10000; // 10 ms
4137 // KeDelayExecutionThread( KernelMode, FALSE, &interval );
4138 KeStallExecutionProcessor(10);
4139 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4140 if (!usbcmd
->hcreset
)
4144 // prepare the registers
4145 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_CTRLDSSEGMENT
), 0);
4147 // turn on all the int
4148 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBINTR
),
4149 EHCI_USBINTR_INTE
| EHCI_USBINTR_ERR
| EHCI_USBINTR_ASYNC
| EHCI_USBINTR_HSERR
4150 // EHCI_USBINTR_FLROVR | \ // it is noisy
4151 // EHCI_USBINTR_PC | // we detect it by polling
4153 // write the list base reg
4154 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_PERIODICLISTBASE
), ehci
->frame_list_phys_addr
.LowPart
);
4156 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_ASYNCLISTBASE
), ehci
->skel_async_qh
->phys_addr
& ~(0x1f));
4158 usbcmd
->int_threshold
= 1;
4159 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4162 usbcmd
->run_stop
= 1;
4163 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4165 // set the configuration flag
4166 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_CONFIGFLAG
), 1);
4168 // enable the list traversaling
4169 usbcmd
->async_enable
= 1;
4170 usbcmd
->periodic_enable
= 1;
4171 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4177 ehci_run_stop(PEHCI_DEV ehci
, BOOLEAN start
)
4179 PEHCI_USBCMD_CONTENT usbcmd
;
4180 PEHCI_USBSTS_CONTENT usbsts
;
4187 base
= ehci
->port_base
;
4188 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4189 usbsts
= (PEHCI_USBSTS_CONTENT
) & tmp
;
4191 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBSTS
));
4192 if (start
&& usbsts
->hc_halted
== 0)
4195 usb_dbg_print(DBGLVL_MEDIUM
, ("ehci_run_stop(): WARNING: hc running, can not start again\n"));
4198 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4199 usbcmd
->run_stop
= start
? 1 : 0;
4200 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4202 usb_wait_ms_dpc(2); //ehci spec 16 microframes
4206 ehci_find_min_bandwidth(PEHCI_DEV ehci
)
4212 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
++)
4214 ehci
->min_bw
= ehci
->min_bw
< ehci
->frame_bw
[i
] ? ehci
->min_bw
: ehci
->frame_bw
[i
];
4220 ehci_claim_bw_for_int(PEHCI_DEV ehci
, PURB purb
, BOOLEAN release
)
4221 // should have pending_endp_list_lock acquired, and purb->pipe prepared
4223 PURB_HS_PIPE_CONTENT pipe_content
;
4225 ULONG interval
, bus_time
, ss_time
, cs_time
;
4227 ULONG max_packet_size
;
4229 if (ehci
== NULL
|| purb
== NULL
)
4232 if (purb
->pipe
== 0)
4236 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4237 interval
= REAL_INTERVAL
;
4238 if (pipe_content
->speed_high
== 0)
4240 // translate to high speed uframe count
4244 if (interval
> (ehci
->frame_count
<< 3))
4245 interval
= (ehci
->frame_count
<< 3);
4247 max_packet_size
= (1 << pipe_content
->max_packet_size
);
4248 if (pipe_content
->speed_high
)
4250 // this is a high speed endp
4252 bus_time
= usb_calc_bus_time(USB_SPEED_HIGH
,
4253 (pipe_content
->trans_dir
) << 7,
4254 FALSE
, min(purb
->data_length
, (LONG
) max_packet_size
));
4256 // multiple transactions per uframe
4257 if (purb
->data_length
> (LONG
) max_packet_size
)
4259 bus_time
*= (purb
->data_length
) / max_packet_size
;
4260 bus_time
+= usb_calc_bus_time(USB_SPEED_HIGH
,
4261 (pipe_content
->trans_dir
) << 7,
4262 FALSE
, purb
->data_length
% max_packet_size
);
4264 bus_time
= (bus_time
+ 1) >> 1;
4268 for(i
= pipe_content
->start_uframe
+ (purb
->int_start_frame
<< 3);
4269 i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4271 ehci
->frame_bw
[i
] += (USHORT
) bus_time
;
4275 if (bus_time
< ehci
->min_bw
)
4277 // start the poll from uframe zero of each frame
4279 pipe_content
->start_uframe
= 0;
4280 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4282 ehci
->frame_bw
[i
] -= (USHORT
) bus_time
;
4283 if (ehci
->frame_bw
[i
] < ehci
->min_bw
)
4284 ehci
->min_bw
= ehci
->frame_bw
[i
];
4287 else // bother to find a pattern
4289 for(j
= 0; j
< (LONG
) interval
; j
++)
4291 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4293 if (ehci
->frame_bw
[i
] < bus_time
)
4296 if (i
> (LONG
) (ehci
->frame_count
<< 3))
4304 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4306 ehci
->frame_bw
[i
] -= (USHORT
) bus_time
;
4307 if (ehci
->frame_bw
[i
] < ehci
->min_bw
)
4308 ehci
->min_bw
= ehci
->frame_bw
[i
];
4310 pipe_content
->start_uframe
= j
& 7;
4311 purb
->int_start_frame
= j
>> 3;
4315 else // full/low speed pipe
4317 // split condition is considered
4318 if (pipe_content
->trans_dir
)
4320 // an input interrupt, with handshake
4321 // 55 is 144 - 90 + 1, turnaround time is one byte not the worst case 90 bytes,
4322 // refer to ehci-1.0 table 4-5 p64
4323 ss_time
= 231 * 25 / 12;
4324 // cs_time = ( 55 * 8 + ( LONG )( ( ( 19 + 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
4325 cs_time
= (55 * 8 + (LONG
) (((7 * 8 * purb
->data_length
) / 6))) * 25 / 12;
4329 // according to ehci-1.0 table 4-5 p64
4330 ss_time
= (49 * 8 + (LONG
) (((7 * 8 * purb
->data_length
) / 6))) * 25 / 12;
4331 // 287 = 237 + 48( handshake ) + 8( turn around time )
4332 cs_time
= 287 * 25 / 12;
4334 ss_time
>>= 1, cs_time
>>= 1;
4337 for(i
= pipe_content
->start_uframe
+ (purb
->int_start_frame
<< 3);
4338 i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4340 ehci
->frame_bw
[i
] += (USHORT
) ss_time
;
4341 ehci
->frame_bw
[i
+ 2] += (USHORT
) cs_time
;
4342 ehci
->frame_bw
[i
+ 3] += (USHORT
) cs_time
;
4343 if ((i
& 0x07) != 0x06)
4344 ehci
->frame_bw
[i
+ 4] += (USHORT
) cs_time
;
4348 if (ss_time
< ehci
->min_bw
&& cs_time
< ehci
->min_bw
)
4350 pipe_content
->start_uframe
= 0;
4352 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4354 ehci
->frame_bw
[i
] -= (USHORT
) ss_time
;
4355 ehci
->min_bw
= min(ehci
->frame_bw
[i
], ehci
->min_bw
);
4356 ehci
->frame_bw
[i
+ 2] -= (USHORT
) cs_time
;
4357 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 2], ehci
->min_bw
);
4358 ehci
->frame_bw
[i
+ 3] -= (USHORT
) cs_time
;
4359 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 3], ehci
->min_bw
);
4360 if ((i
& 0x07) != 0x06)
4362 ehci
->frame_bw
[i
+ 4] -= (USHORT
) cs_time
;
4363 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 4], ehci
->min_bw
);
4369 for(j
= 0; j
< (LONG
) interval
; j
++)
4371 if ((j
& 0x7) == 7) // start-split not allowed at this uframe
4374 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4376 if (ehci
->frame_bw
[i
] < ss_time
)
4378 if (ehci
->frame_bw
[i
+ 2] < cs_time
)
4380 if (ehci
->frame_bw
[i
+ 3] < cs_time
)
4383 if (ehci
->frame_bw
[i
+ 4] < cs_time
)
4386 if (i
> (LONG
) (ehci
->frame_count
<< 3))
4393 pipe_content
->start_uframe
= j
& 7;
4394 purb
->int_start_frame
= j
>> 3;
4396 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4398 ehci
->frame_bw
[i
] -= (USHORT
) ss_time
;
4399 ehci
->min_bw
= min(ehci
->frame_bw
[i
], ehci
->min_bw
);
4400 ehci
->frame_bw
[i
+ 2] -= (USHORT
) cs_time
;
4401 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 2], ehci
->min_bw
);
4402 ehci
->frame_bw
[i
+ 3] -= (USHORT
) cs_time
;
4403 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 3], ehci
->min_bw
);
4406 ehci
->frame_bw
[i
+ 4] -= (USHORT
) cs_time
;
4407 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 4], ehci
->min_bw
);
4418 ehci_find_min_bandwidth(ehci
);
4424 ehci_get_cache_policy(PEHCI_DEV ehci
)
4426 PEHCI_HCC_CONTENT hcc_content
;
4428 hcc_content
= (PEHCI_HCC_CONTENT
) & ehci
->ehci_caps
;
4429 if (hcc_content
->iso_sched_threshold
>= 8)
4431 if (hcc_content
->iso_sched_threshold
== 0)
4433 return hcc_content
->iso_sched_threshold
+ 2;
4436 // 25/12 is bus-time per bit ( 1000 / 480 )
4437 #define BEST_BUDGET_TIME_UFRAME ( ( 188 * 7 / 6 ) * 25 / 12 )
4439 // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
4440 // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
4441 #define iso_max_data_load( dir ) ( dir == USB_DIR_IN ? \
4442 ( ( 188 * 8 - 231 - 8 - 67 + ( 8 - 1 ) ) / 8 ) : ( 188 - 49 ) )
4444 #define iso_uframes_data_load( dir, data_load, uf_cnt )
4447 ehci_claim_bw_for_iso(PEHCI_DEV ehci
, PURB purb
, BOOLEAN release
)
4449 PURB_HS_PIPE_CONTENT pipe_content
;
4451 ULONG interval
, bus_time
, ss_time
, cs_time
, remainder
;
4453 ULONG cur_uframe
, start_uframe
= 0, max_time
, max_packet_size
;
4455 if (ehci
== NULL
|| purb
== NULL
)
4458 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4459 base
= ehci
->port_base
;
4460 cur_uframe
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_FRINDEX
)) + 1;
4463 max_packet_size
= purb
->params
[0]; //( 1 << pipe_content->max_packet_size );
4465 if (pipe_content
->speed_high
)
4467 interval
= REAL_INTERVAL
;
4468 if (purb
->iso_frame_count
== 0 || purb
->iso_frame_count
+ 2 * 8 > (LONG
) (ehci
->frame_count
<< 3))
4471 for(i
= 0, max_time
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4473 bus_time
= usb_calc_bus_time(USB_SPEED_HIGH
,
4474 (pipe_content
->trans_dir
) << 7,
4475 TRUE
, min(purb
->iso_packet_desc
[i
].length
, (LONG
) max_packet_size
));
4476 // NOTE: we did not use endp_mult_count here, because the comparison is enough
4477 // to calculate the bandwidth
4478 if (purb
->iso_packet_desc
[i
].length
> (LONG
) max_packet_size
)
4480 // multiple transactions per uframe
4481 bus_time
*= purb
->iso_packet_desc
[i
].length
/ max_packet_size
;
4482 bus_time
+= usb_calc_bus_time(USB_SPEED_HIGH
,
4483 (pipe_content
->trans_dir
) << 7,
4484 TRUE
, purb
->iso_packet_desc
[i
].length
% max_packet_size
);
4486 bus_time
= (bus_time
+ 1) >> 1;
4487 max_time
= max(bus_time
, max_time
);
4488 purb
->iso_packet_desc
[i
].bus_time
= bus_time
;
4493 // it is a release operation
4494 for(i
= purb
->iso_start_frame
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4495 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4497 ehci
->frame_bw
[i
] += (USHORT
) purb
->iso_packet_desc
[k
].bus_time
;
4499 ehci_find_min_bandwidth(ehci
);
4503 if (max_time
< ehci
->min_bw
)
4505 start_uframe
= cur_uframe
+ ehci_get_cache_policy(ehci
); // avoid cache
4506 for(i
= start_uframe
, j
= 0; j
< (LONG
) purb
->iso_frame_count
;
4507 i
= (i
+ interval
) % (ehci
->frame_count
<< 3), j
++)
4509 ehci
->frame_bw
[i
] -= (USHORT
) purb
->iso_packet_desc
[j
].bus_time
;
4510 ehci
->min_bw
= min(ehci
->frame_bw
[j
], ehci
->min_bw
);
4512 purb
->iso_start_frame
= start_uframe
;
4515 else // max_time >= ehci->min_bw
4517 for(j
= 0; j
< (LONG
) interval
; j
++)
4519 start_uframe
= cur_uframe
+ ehci_get_cache_policy(ehci
) + j
;
4520 for(i
= start_uframe
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4521 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4523 if (ehci
->frame_bw
[i
] < (USHORT
) purb
->iso_packet_desc
[k
].bus_time
)
4529 if (k
< (LONG
) purb
->iso_frame_count
)
4536 // allocate the bandwidth
4537 for(i
= start_uframe
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4538 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4540 ehci
->frame_bw
[i
] -= (USHORT
) purb
->iso_packet_desc
[k
].bus_time
;
4541 ehci
->min_bw
= min(ehci
->min_bw
, ehci
->frame_bw
[i
]);
4543 purb
->iso_start_frame
= start_uframe
;
4547 else // not high speed endpoint
4550 if (purb
->iso_frame_count
== 0 || purb
->iso_frame_count
+ 2 > (LONG
) ehci
->frame_count
)
4553 if (max_packet_size
> 1023)
4559 // calculate for each frame
4560 // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
4561 // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
4562 // bit-stuffing is for high speed bus transfer
4565 if (pipe_content
->trans_dir
)
4567 // an input transfer, no handshake
4568 ss_time
= 231 * 25 / 12;
4569 // cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
4570 cs_time
= (231 + 8 + 67 + (LONG
) (((7 * 8 * 188) / 6))) * 25 / 12;
4574 // an output transfer according to ehci-1.0 table 4-5 p64
4575 // ss_time = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
4576 ss_time
= (49 * 8 + (LONG
) (((7 * 8 * 188) / 6))) * 25 / 12;
4578 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4580 // remainder = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12;
4582 (49 * 8 + (LONG
) (((7 * 8 * (purb
->iso_packet_desc
[i
].length
% 188)) / 6))) * 25 / 12;
4584 purb
->iso_packet_desc
[i
].params
.bus_time
= (USHORT
) remainder
;
4590 cur_uframe
= (cur_uframe
+ 7) & (~0x07);
4592 j
= ehci
->frame_count
<< 3;
4595 if (pipe_content
->trans_dir
)
4597 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4599 ehci
->frame_bw
[purb
->iso_packet_desc
[i
].params
.start_uframe
] += (USHORT
) ss_time
;
4600 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4602 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4605 // two extra complete-split
4606 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4607 ehci
->frame_bw
[(cur_uframe
+ 0x13 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4612 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4614 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4616 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3) + k
) % j
] += (USHORT
) ss_time
;
4620 ehci_find_min_bandwidth(ehci
);
4623 // search for available bw
4624 if (ss_time
< ehci
->min_bw
&& cs_time
< ehci
->min_bw
)
4626 if (pipe_content
->trans_dir
)
4628 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4630 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3)) % j
] -= (USHORT
) ss_time
;
4631 ehci
->min_bw
= min(ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3)) % j
], ehci
->min_bw
);
4633 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4635 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4637 min(ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
], ehci
->min_bw
);
4640 // two extra complete-split
4641 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4642 ehci
->min_bw
= min(ehci
->frame_bw
[cur_uframe
+ 0x12 + (i
<< 3) + k
], ehci
->min_bw
);
4643 ehci
->frame_bw
[(cur_uframe
+ 0x13 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4644 ehci
->min_bw
= min(ehci
->frame_bw
[cur_uframe
+ 0x13 + (i
<< 3) + k
], ehci
->min_bw
);
4649 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4651 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4653 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3) + k
) % j
] -= (USHORT
) ss_time
;
4655 min(ehci
->frame_bw
[(cur_uframe
+ 0x11 + (i
<< 3) + k
) % j
], ehci
->min_bw
);
4659 purb
->iso_start_frame
= 0;
4660 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4663 purb
->iso_packet_desc
[i
].params
.start_uframe
= (USHORT
) (cur_uframe
+ 0x10);
4665 purb
->iso_packet_desc
[i
].params
.start_uframe
=
4666 purb
->iso_packet_desc
[i
- 1].params
.start_uframe
+ 0x8;
4670 else // take the pain to find one
4675 for(j
= (cur_uframe
>> 3) + 2; j
!= (LONG
) (cur_uframe
>> 3); j
= (j
+ 1) % ehci
->frame_count
)
4679 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4681 large
= purb
->iso_packet_desc
[i
].length
> 579;
4682 base
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
4687 if (pipe_content
->trans_dir
)
4689 // input split iso, for those large than 579, schedule it at the uframe boundary
4690 for(temp
= 0; temp
< (large
== FALSE
) ? (8 - base
- 1) : 1; temp
++)
4692 k
= (((j
+ i
) << 3) + temp
) % (ehci
->frame_count
<< 3);
4693 if (ehci
->frame_bw
[k
] > ss_time
)
4700 frame_bw
[(((j
+ i
) << 3) + 1 + temp
+ k
) % (ehci
->frame_count
<< 3)] <
4705 if (k
> 0) // not available
4708 // the first following extra cs
4709 k
= (((j
+ i
) << 3) + 2 + temp
+ base
) % (ehci
->frame_count
<< 3);
4710 if (ehci
->frame_bw
[k
] < cs_time
)
4715 // very large one does not have this second extra cs
4716 if (ehci
->frame_bw
[(k
+ 1) % (ehci
->frame_count
<< 3)] < cs_time
)
4721 if (temp
== 8 - 1 - base
) // no bandwidth for ss
4726 // note: 8 - 1 - base has different meaning from the above
4727 // it is to avoid the ss on H-Frame 7, but the above one is
4728 // the latency of the classic bus.
4729 for(temp
= 0; temp
< 8 - 1 - base
; temp
++)
4731 if (ehci
->frame_bw
[((j
+ i
) << 3) % (ehci
->frame_count
<< 3) + temp
] > ss_time
)
4734 for(k
= temp
; k
< temp
+ base
; k
++)
4736 if (ehci
->frame_bw
[((j
+ i
) << 3) % (ehci
->frame_count
<< 3) + k
] < ss_time
)
4741 if (temp
== 8 - 1 - base
)
4745 purb
->iso_packet_desc
[i
].params
.start_uframe
=
4746 (USHORT
) ((((j
+ i
) << 3) + temp
) % (ehci
->frame_count
<< 3));
4749 if (i
< (LONG
) purb
->iso_frame_count
)
4751 // skip to the next section
4752 j
= (j
+ i
) % (ehci
->frame_count
<< 3);
4758 // FIXME: Should we claim bw for the last complete split sitd? this is not done
4762 if (pipe_content
->trans_dir
)
4765 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4767 j
= purb
->iso_packet_desc
[i
].length
;
4768 temp
= (purb
->iso_packet_desc
[i
].params
.start_uframe
) % (ehci
->frame_count
<< 3);
4769 ehci
->frame_bw
[temp
] -= (USHORT
) ss_time
;
4770 for(k
= 0; k
< (j
+ 187) / 188; j
++)
4772 ehci
->frame_bw
[temp
+ 2 + k
] -= (USHORT
) cs_time
;
4774 ehci
->frame_bw
[temp
+ 2 + k
] -= (USHORT
) cs_time
;
4775 if ((j
+ 187) / 188 < 6) //ehci restriction
4777 ehci
->frame_bw
[temp
+ 3 + k
] -= (USHORT
) cs_time
;
4783 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4785 j
= purb
->iso_packet_desc
[i
].length
;
4786 temp
= (purb
->iso_packet_desc
[i
].params
.start_uframe
) % (ehci
->frame_count
<< 3);
4787 for(k
= 0; k
< j
/ 188; j
++)
4789 ehci
->frame_bw
[temp
+ k
] -= (USHORT
) ss_time
;
4792 ehci
->frame_bw
[temp
+ k
] -= purb
->iso_packet_desc
[i
].params
.bus_time
;
4802 ehci_claim_bandwidth(PEHCI_DEV ehci
, PURB purb
, BOOLEAN claim_bw
) //true to claim band-width, false to free band-width
4803 // should have pending_endp_list_lock acquired, and purb->pipe prepared
4805 PURB_HS_PIPE_CONTENT pipe_content
;
4808 if (ehci
== NULL
|| purb
== NULL
)
4812 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4813 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
4815 ret
= ehci_claim_bw_for_iso(ehci
, purb
, claim_bw
? FALSE
: TRUE
);
4817 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
4819 ret
= ehci_claim_bw_for_int(ehci
, purb
, claim_bw
? FALSE
: TRUE
);
4827 ehci_can_remove(PURB purb
, BOOLEAN door_bell_rings
, ULONG cur_frame
)
4828 // test if the purb can be removed from the schedule, by current frame index and
4831 PURB_HS_PIPE_CONTENT pipe_content
;
4834 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4835 interval
= REAL_INTERVAL
;
4837 switch (purb
->flags
& URB_FLAG_STATE_MASK
)
4839 case URB_FLAG_STATE_PENDING
:
4845 case URB_FLAG_STATE_IN_PROCESS
:
4849 case URB_FLAG_STATE_DOORBELL
:
4851 if ((pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
4852 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
) && door_bell_rings
== TRUE
)
4856 else if ((pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
4857 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
))
4867 case URB_FLAG_STATE_WAIT_FRAME
:
4869 // need more processing
4870 if ((purb
->flags
& URB_FLAG_FORCE_CANCEL
) == 0)
4875 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
4877 return door_bell_rings
;
4879 else // isochronous can not be canceled
4889 NTSTATUS
ehci_remove_urb_from_schedule(PEHCI_DEV ehci
, PURB purb
);
4892 ehci_deactivate_urb(PURB purb
)
4894 PURB_HS_PIPE_CONTENT pipe_content
;
4895 PLIST_ENTRY pthis
, pnext
;
4896 PEHCI_QH_CONTENT pqh_content
;
4897 PEHCI_QTD_CONTENT pqtd_content
;
4902 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4903 switch (pipe_content
->trans_type
)
4905 case USB_ENDPOINT_XFER_CONTROL
:
4906 case USB_ENDPOINT_XFER_BULK
:
4907 case USB_ENDPOINT_XFER_INT
:
4909 ListFirst(&purb
->trasac_list
, pthis
);
4910 pqh_content
= (PEHCI_QH_CONTENT
) qh_from_list_entry(pthis
);
4911 ListNext(&purb
->trasac_list
, pthis
, pnext
);
4914 pqtd_content
= (PEHCI_QTD_CONTENT
) qtd_from_list_entry(pthis
);
4915 if (pqtd_content
->status
& QTD_STS_ACTIVE
)
4917 pqtd_content
->status
&= ~QTD_STS_ACTIVE
;
4919 ListNext(&purb
->trasac_list
, pthis
, pnext
);
4926 case USB_ENDPOINT_XFER_ISOC
:
4937 ehci_insert_bulk_schedule(PEHCI_DEV ehci
, PURB purb
)
4938 // list head is only a handle, the qh and qtd are following it.
4940 PLIST_ENTRY list_head
;
4941 PEHCI_QH pqh
, pqhprev
, pqhnext
;
4942 PLIST_ENTRY pthis
, pprev
, pnext
;
4944 if (ehci
== NULL
|| purb
== NULL
)
4947 list_head
= &purb
->trasac_list
;
4948 ListFirst(list_head
, pthis
);
4952 if (elem_type_list_entry(pthis
) != INIT_LIST_FLAG_QH
)
4955 pqh
= qh_from_list_entry(pthis
);
4957 ListFirstPrev(&ehci
->async_list_cpu
, pprev
);
4958 pqhprev
= qh_from_schedule(pprev
);
4961 ListFirst(&ehci
->async_list_cpu
, pnext
);
4962 pqhnext
= qh_from_schedule(pnext
);
4964 if (pprev
== &ehci
->async_list_cpu
)
4966 // always a qh in async list
4970 pqh
->hw_next
= pqhnext
->phys_addr
;
4971 InsertTailList(&ehci
->async_list_cpu
, &pqh
->elem_head_link
->sched_link
);
4972 pqhprev
->hw_next
= pqh
->phys_addr
;
4977 ehci_remove_bulk_from_schedule(PEHCI_DEV ehci
, PURB purb
)
4978 // executed in isr, and have frame_list_lock acquired, so
4979 // never try to acquire any spin-lock
4980 // remove the bulk purb from schedule, and mark it not in
4983 PLIST_ENTRY list_head
;
4984 PEHCI_QH pqh
, pqhprev
, pqhnext
;
4985 PEHCI_QH_CONTENT pqhc
;
4986 PLIST_ENTRY pthis
, pprev
, pnext
;
4988 if (ehci
== NULL
|| purb
== NULL
)
4991 list_head
= &purb
->trasac_list
;
4992 ListFirst(list_head
, pthis
);
4998 pqh
= qh_from_list_entry(pthis
);
4999 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
5001 if (pqhc
->is_async_head
)
5004 ListFirst(&pqh
->elem_head_link
->sched_link
, pnext
);
5005 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5007 if (pprev
== &ehci
->async_list_cpu
)
5009 // we will at least have a qh with H-bit 1 in the async-list
5012 else if (pnext
== &ehci
->async_list_cpu
)
5014 // remove the last one
5015 pqhprev
= qh_from_schedule(pprev
);
5016 ListFirst(&ehci
->async_list_cpu
, pnext
);
5017 pqhnext
= qh_from_schedule(pnext
);
5018 pqhprev
->hw_next
= pqhnext
->phys_addr
;
5022 pqhprev
= qh_from_schedule(pprev
);
5023 pqhnext
= qh_from_schedule(pnext
);
5024 pqhprev
->hw_next
= pqhnext
->phys_addr
;
5026 RemoveEntryList(&pqh
->elem_head_link
->sched_link
);
5032 ehci_insert_fstn_schedule(PEHCI_DEV ehci
, PURB purb
)
5035 PURB_HS_PIPE_CONTENT pipe_content
, pc
;
5036 PLIST_ENTRY pthis
, list_head
, pnext
= NULL
, pprev
;
5041 ULONG interval
, start_frame
, start_uframe
;
5044 if (ehci
== NULL
|| purb
== NULL
)
5047 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5048 interval
= (1 << (pipe_content
->interval
+ 3));
5049 list_head
= &purb
->trasac_list
;
5050 start_frame
= purb
->int_start_frame
;
5051 start_uframe
= (start_frame
<< 3) + 1; //( start_frame << 3 ) + pipe_content->start_uframe;
5053 if ((start_frame
<< 3) >= interval
)
5056 ListFirstPrev(list_head
, pprev
);
5058 if (elem_type_list_entry(pprev
) != INIT_LIST_FLAG_FSTN
)
5064 pfstn
= fstn_from_list_entry(pprev
);
5068 ListFirst(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
);
5070 // skip the first one
5071 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5077 purb1
= qh_from_schedule(pthis
)->elem_head_link
->purb
;
5078 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5084 if ((1 << (pc
->interval
+ 3)) > (LONG
) interval
)
5089 else if ((1 << (pc
->interval
+ 3) < (LONG
) interval
))
5093 else if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5095 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5099 else if (pc
->start_uframe
<= 1)
5101 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5115 InsertTailList(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
],
5116 &pfstn
->elem_head_link
->sched_link
);
5120 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5122 InsertHeadList(&fstn_from_schedule(pprev
)->elem_head_link
->sched_link
,
5123 &pfstn
->elem_head_link
->sched_link
);
5127 InsertHeadList(&qh_from_schedule(pprev
)->elem_head_link
->sched_link
,
5128 &pfstn
->elem_head_link
->sched_link
);
5131 pfstn
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5132 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5137 for(i
= start_frame
; i
< (LONG
) start_frame
+ 1; i
+= (interval
>> 3))
5139 list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5140 ListFirst(list_head
, pthis
);
5145 // skip itds and sitds
5146 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_ITD
||
5147 elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_SITD
)
5149 ListNext(list_head
, pthis
, pnext
);
5159 // find the insertion point
5162 pqhnext
= qh_from_schedule(pthis
);
5163 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5164 purb1
= fstn_from_schedule(pthis
)->elem_head_link
->purb
;
5166 purb1
= pqhnext
->elem_head_link
->purb
;
5171 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5172 u
= 1 << (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5176 ListNext(list_head
, pthis
, pnext
);
5181 else if (u
== interval
)
5184 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5185 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5187 ListNext(list_head
, pthis
, pnext
);
5195 else if (u
< interval
)
5201 if (pprev
== list_head
)
5203 // insert to the list head
5204 pnext
= pfstn
->elem_head_link
->sched_link
.Flink
= list_head
->Flink
;
5205 list_head
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5206 pfstn
->hw_next
= ehci
->frame_list
[i
]; // point to following node
5207 ehci
->frame_list
[i
] = pfstn
->phys_addr
;
5211 pnext
= pfstn
->elem_head_link
->sched_link
.Flink
= pprev
->Flink
;
5212 pprev
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5214 // fstn can be handled correctly
5215 pfstn
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5216 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5219 // the pointer to next node of this fstn is alway same across the frame list.
5220 for(i
= start_frame
+ (interval
>> 3); i
< (LONG
) ehci
->frame_count
; i
+= (interval
>> 3))
5222 pprev
= list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5223 ListFirst(list_head
, pthis
);
5232 ListNext(list_head
, pthis
, pthis
);
5235 pprev
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5236 if (pprev
== list_head
)
5237 ehci
->frame_list
[i
] = pfstn
->phys_addr
;
5239 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5245 ehci_remove_fstn_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5247 PURB_HS_PIPE_CONTENT pipe_content
;
5248 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
;
5251 ULONG interval
, start_frame
, start_uframe
;
5254 if (ehci
== NULL
|| purb
== NULL
)
5257 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5258 interval
= (1 << (pipe_content
->interval
+ 3));
5259 list_head
= &purb
->trasac_list
;
5260 start_frame
= purb
->int_start_frame
;
5263 if ((start_frame
<< 3) >= interval
)
5267 ListFirstPrev(list_head
, pprev
);
5268 if (elem_type_list_entry(pprev
) != INIT_LIST_FLAG_FSTN
)
5274 pfstn
= fstn_from_list_entry(pprev
);
5282 ListFirstPrev(&pfstn
->elem_head_link
->sched_link
, pprev
);
5283 qh_from_schedule(pprev
)->hw_next
= pfstn
->hw_next
;
5284 RemoveEntryList(&pfstn
->elem_head_link
->sched_link
);
5288 for(i
= start_frame
; i
< (LONG
) ehci
->frame_count
; i
++)
5290 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pthis
);
5296 pprev
= &ehci
->frame_list_cpu
[i
].td_link
;
5297 while (pthis
&& pthis
!= &pfstn
->elem_head_link
->sched_link
)
5300 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pthis
, pnext
);
5308 qh_from_schedule(pprev
)->hw_next
= pfstn
->hw_next
;
5309 pprev
->Flink
= pfstn
->elem_head_link
->sched_link
.Flink
;
5316 ehci_insert_int_schedule(PEHCI_DEV ehci
, PURB purb
)
5318 PURB_HS_PIPE_CONTENT pipe_content
, pc
;
5319 PLIST_ENTRY pthis
, list_head
, pnext
= NULL
, pprev
;
5320 PEHCI_ELEM_LINKS elem_link
;
5321 PEHCI_QH pqh
, pqhprev
, pqhnext
;
5324 ULONG interval
, u
, start_frame
, start_uframe
;
5328 if (ehci
== NULL
|| purb
== NULL
)
5331 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5332 interval
= REAL_INTERVAL
;
5333 start_uframe
= (purb
->int_start_frame
<< 3) + pipe_content
->start_uframe
;
5334 start_frame
= purb
->int_start_frame
;
5336 list_head
= &purb
->trasac_list
;
5338 ListFirst(list_head
, pthis
);
5342 pqh
= qh_from_list_entry(pthis
);
5344 if (!pipe_content
->speed_high
)
5346 interval
= (interval
<< 3);
5347 ListFirstPrev(list_head
, pprev
);
5348 if (elem_type_list_entry(pprev
) == INIT_LIST_FLAG_FSTN
)
5354 pqhprev
= pqhnext
= NULL
;
5357 list_head
= &ehci
->periodic_list_cpu
[EHCI_SCHED_FSTN_INDEX
];
5358 ListFirst(list_head
, pthis
);
5359 InsertTailList(list_head
, &pqh
->elem_head_link
->sched_link
);
5360 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5361 pqh
->hw_next
= EHCI_PTR_TERM
;
5364 fstn_from_schedule(pthis
)->hw_next
= pqh
->phys_addr
;
5368 qh_from_schedule(pthis
)->hw_next
= pqh
->phys_addr
;
5371 else // interval == 2 or 4 or 8
5373 list_head
= &ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
];
5374 ListFirst(list_head
, pthis
);
5378 elem_link
= struct_ptr(pthis
, EHCI_ELEM_LINKS
, sched_link
);
5379 purb1
= elem_link
->purb
;
5380 pc
= (PURB_HS_PIPE_CONTENT
) purb1
->pipe
;
5381 u
= (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5385 ListFirstPrev(pthis
, pprev
);
5388 else if (interval
> u
)
5390 ListNext(list_head
, pthis
, pnext
);
5395 // FIXME: is this right to fix fstn's start_uf 1???
5396 else if (start_uframe
<=
5397 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5398 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5400 ListNext(list_head
, pthis
, pnext
);
5405 else // interval is equal, and start_uframe is greater
5407 ListFirstPrev(pthis
, pprev
);
5413 // at least one dummy qh is there
5416 else if (pnext
== NULL
)
5418 // the last one in this chain, fstn can be handled correctly
5419 InsertTailList(list_head
, &pqh
->elem_head_link
->sched_link
);
5420 pqhprev
= qh_from_schedule(pprev
);
5421 pqh
->hw_next
= pqhprev
->hw_next
;
5422 pqhprev
->hw_next
= pqh
->phys_addr
;
5426 pqhprev
= qh_from_schedule(pprev
);
5427 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_QH
)
5429 InsertHeadList(&pqhprev
->elem_head_link
->sched_link
, &pqh
->elem_head_link
->sched_link
);
5431 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5433 InsertHeadList(&fstn_from_schedule(pprev
)->elem_head_link
->sched_link
,
5434 &pqh
->elem_head_link
->sched_link
);
5436 pqh
->hw_next
= pqhprev
->hw_next
;
5437 pqhprev
->hw_next
= pqh
->phys_addr
;
5441 else // interval >= 16
5443 if ((start_frame
<< 3) >= interval
)
5446 for(i
= start_frame
; i
< (LONG
) start_frame
+ 1; i
+= (interval
>> 3))
5448 list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5449 ListFirst(list_head
, pthis
);
5454 // skip itds and sitds
5455 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_ITD
||
5456 elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_SITD
)
5458 ListNext(list_head
, pthis
, pnext
);
5468 // find the insertion point
5470 pqhnext
= qh_from_schedule(pthis
);
5471 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5472 purb1
= fstn_from_schedule(pthis
)->elem_head_link
->purb
;
5474 purb1
= pqhnext
->elem_head_link
->purb
;
5479 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5480 u
= 1 << (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5484 ListNext(list_head
, pthis
, pnext
);
5489 else if (u
== interval
)
5492 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5493 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5495 ListNext(list_head
, pthis
, pnext
);
5503 else if (u
< interval
)
5508 if (pprev
== list_head
)
5510 // insert to the list head
5511 pnext
= pqh
->elem_head_link
->sched_link
.Flink
= list_head
->Flink
;
5512 list_head
->Flink
= &pqh
->elem_head_link
->sched_link
;
5513 pqh
->hw_next
= ehci
->frame_list
[i
]; // point to following node
5514 ehci
->frame_list
[i
] = pqh
->phys_addr
;
5518 pnext
= pqh
->elem_head_link
->sched_link
.Flink
= pprev
->Flink
;
5519 pprev
->Flink
= &pqh
->elem_head_link
->sched_link
;
5521 // fstn can be handled correctly
5522 pqh
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5523 qh_from_schedule(pprev
)->hw_next
= pqh
->phys_addr
;
5526 for(i
= start_frame
+ (interval
>> 3); i
< (LONG
) ehci
->frame_count
; i
+= (interval
>> 3))
5528 pprev
= list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5529 ListFirst(list_head
, pthis
);
5538 ListNext(list_head
, pthis
, pthis
);
5541 pprev
->Flink
= &pqh
->elem_head_link
->sched_link
;
5542 if (pprev
== list_head
)
5543 ehci
->frame_list
[i
] = pqh
->phys_addr
;
5545 qh_from_schedule(pprev
)->hw_next
= pqh
->phys_addr
;
5550 ehci_insert_fstn_schedule(ehci
, purb
);
5556 ehci_remove_int_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5558 PURB_HS_PIPE_CONTENT pipe_content
;
5559 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
, pcur
;
5560 PEHCI_QH pqh
, pqhprev
;
5562 ULONG interval
, start_frame
, start_uframe
;
5565 if (ehci
== NULL
|| purb
== NULL
)
5568 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5569 interval
= REAL_INTERVAL
;
5570 start_uframe
= (purb
->int_start_frame
<< 3) + pipe_content
->start_uframe
;
5571 start_frame
= purb
->int_start_frame
;
5573 ListFirst(&purb
->trasac_list
, pthis
);
5577 pqh
= qh_from_list_entry(pthis
);
5578 list_head
= &purb
->trasac_list
;
5580 if (IsListEmpty(list_head
))
5586 if (!pipe_content
->speed_high
)
5588 interval
= (interval
<< 3);
5591 if (interval
>= 256 * 8)
5596 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5597 RemoveEntryList(&pqh
->elem_head_link
->sched_link
);
5600 pqhprev
= qh_from_schedule(pprev
);
5601 pqhprev
->hw_next
= pqh
->hw_next
;
5605 ListFirst(&ehci
->frame_list_cpu
[EHCI_SCHED_FSTN_INDEX
].td_link
, list_head
);
5606 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5608 fstn_from_schedule(list_head
)->hw_next
= pqh
->hw_next
;
5612 qh_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5616 else if (interval
>= 16)
5618 ListFirst(list_head
, pthis
);
5619 pthis
= &pqh
->elem_head_link
->sched_link
;
5621 for(i
= start_uframe
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
5623 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pcur
);
5625 while (pthis
!= pcur
&& pcur
)
5627 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pcur
, pnext
);
5637 else if (pprev
== NULL
)
5639 // the first one in the frame list
5640 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
->Flink
;
5641 ehci
->frame_list
[i
] = qh_from_schedule(pthis
)->hw_next
;
5645 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_QH
)
5647 qh_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5648 pqh
->elem_head_link
->sched_link
.Flink
;
5649 qh_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5651 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_ITD
)
5653 itd_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5654 pqh
->elem_head_link
->sched_link
.Flink
;
5655 itd_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5657 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_SITD
)
5659 sitd_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5660 pqh
->elem_head_link
->sched_link
.Flink
;
5661 sitd_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5663 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5665 fstn_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5666 pqh
->elem_head_link
->sched_link
.Flink
;
5667 fstn_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5675 ListFirstPrev(&purb
->trasac_list
, pprev
);
5676 if (elem_type_list_entry(pprev
) == INIT_LIST_FLAG_FSTN
)
5677 ehci_remove_fstn_from_schedule(ehci
, purb
);
5682 ehci_insert_iso_schedule(PEHCI_DEV ehci
, PURB purb
)
5684 PURB_HS_PIPE_CONTENT pipe_content
;
5685 PLIST_ENTRY pthis
, list_head
, pnext
;
5687 ULONG interval
, start_frame
;
5690 if (ehci
== NULL
|| purb
== NULL
)
5693 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5696 if (pipe_content
->speed_high
)
5697 interval
= REAL_INTERVAL
;
5699 start_frame
= purb
->iso_start_frame
;
5701 ListFirst(&purb
->trasac_list
, pthis
);
5708 list_head
= &purb
->trasac_list
;
5709 if (IsListEmpty(list_head
))
5718 if (pipe_content
->speed_high
)
5720 itd_from_list_entry(pthis
)->elem_head_link
->sched_link
.Flink
=
5721 ehci
->frame_list_cpu
[i
].td_link
.Flink
;
5722 itd_from_list_entry(pthis
)->hw_next
= ehci
->frame_list
[i
];
5724 ehci
->frame_list
[i
] = itd_from_list_entry(pthis
)->phys_addr
;
5725 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
;
5729 sitd_from_list_entry(pthis
)->elem_head_link
->sched_link
.Flink
=
5730 ehci
->frame_list_cpu
[i
].td_link
.Flink
;
5731 sitd_from_list_entry(pthis
)->hw_next
= ehci
->frame_list
[i
];
5733 ehci
->frame_list
[i
] = sitd_from_list_entry(pthis
)->phys_addr
;
5734 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
;
5737 ListNext(list_head
, pthis
, pnext
);
5743 i
+= (interval
>> 3);
5749 ehci_remove_iso_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5751 PURB_HS_PIPE_CONTENT pipe_content
;
5752 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
, pcur
;
5754 ULONG interval
, start_frame
;
5757 if (ehci
== NULL
|| purb
== NULL
)
5760 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5763 if (pipe_content
->speed_high
)
5764 interval
= REAL_INTERVAL
;
5766 start_frame
= purb
->iso_start_frame
;
5768 ListFirst(&purb
->trasac_list
, pthis
);
5775 list_head
= &purb
->trasac_list
;
5776 if (IsListEmpty(list_head
))
5785 // for the possible existance of sitd back pointer, we can not use for(...)
5786 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pcur
);
5787 pprev
= &ehci
->frame_list_cpu
[i
].td_link
;
5792 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pcur
, pnext
);
5804 pprev
->Flink
= pcur
->Flink
;
5805 if (pprev
!= &ehci
->frame_list_cpu
[i
].td_link
)
5806 qh_from_schedule(pprev
)->hw_next
= qh_from_schedule(pcur
)->hw_next
;
5808 ehci
->frame_list
[i
] = qh_from_schedule(pcur
)->hw_next
;
5810 ListNext(list_head
, pthis
, pnext
);
5816 i
+= (interval
>> 3);
5822 ehci_isr_removing_urb(PEHCI_DEV ehci
, PURB purb
, BOOLEAN doorbell_rings
, ULONG cur_frame
)
5826 PURB_HS_PIPE_CONTENT pipe_content
;
5827 PEHCI_ITD_CONTENT pitd_content
;
5828 PEHCI_SITD_CONTENT psitd_content
;
5829 PEHCI_QH_CONTENT pqh_content
;
5830 PEHCI_QTD_CONTENT pqtd_content
;
5833 if (purb
== NULL
|| ehci
== NULL
)
5834 return STATUS_INVALID_PARAMETER
;
5836 if ((purb
->flags
& URB_FLAG_STATE_MASK
) == URB_FLAG_STATE_FINISHED
)
5837 return STATUS_SUCCESS
;
5840 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5842 switch (purb
->flags
& URB_FLAG_STATE_MASK
)
5844 case URB_FLAG_STATE_IN_PROCESS
:
5846 // determine the removal type: complete, error or cancel
5847 ListFirst(&purb
->trasac_list
, pthis
);
5848 if (purb
->flags
& URB_FLAG_FORCE_CANCEL
)
5854 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5855 pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
||
5856 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
5859 (PEHCI_QH_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5860 phys_part
& PHYS_PART_ADDR_MASK
);
5861 if (EHCI_QH_ERROR(pqh_content
))
5863 purb
->status
= pqh_content
->cur_qtd
.status
;
5868 pqtd_content
= &pqh_content
->cur_qtd
;
5869 if (pqtd_content
->terminal
&& ((pqtd_content
->status
& QTD_STS_ACTIVE
) == 0))
5873 // else, not finished
5876 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
5878 // FIXME: do we need to check if current frame falls out of the
5879 // frame range of iso transfer
5880 // inspect the last td to determine if finished
5881 ListFirstPrev(&purb
->trasac_list
, pthis
);
5884 if (pipe_content
->speed_high
)
5887 (PEHCI_ITD_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5888 phys_part
& PHYS_PART_ADDR_MASK
);
5889 for(i
= 0; i
< 8; i
++)
5891 if (pitd_content
->status_slot
[i
].trans_length
&&
5892 pitd_content
->status_slot
[i
].status
& 0x08)
5899 // the itds are all inactive
5906 (PEHCI_SITD_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5907 phys_part
& PHYS_PART_ADDR_MASK
);
5908 if ((psitd_content
->status
& 0x80) == 0)
5914 else // empty transaction list in purb
5917 else // unknown transfer type
5920 } // end of not force cancel
5923 return STATUS_SUCCESS
;
5929 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5930 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
)
5932 ehci_remove_bulk_from_schedule(ehci
, purb
);
5933 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5934 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5936 press_doorbell(ehci
);
5937 return STATUS_SUCCESS
;
5939 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
5941 ehci_remove_iso_from_schedule(ehci
, purb
);
5943 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5945 ehci_remove_int_from_schedule(ehci
, purb
);
5947 else // unknown transfer type
5950 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5951 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
5953 // notify dpc the purb can be completed;
5954 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
5957 return STATUS_SUCCESS
;
5961 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5962 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
)
5964 ehci_deactivate_urb(purb
);
5965 ehci_remove_bulk_from_schedule(ehci
, purb
);
5966 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5967 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5968 press_doorbell(ehci
);
5970 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5972 ehci_remove_int_from_schedule(ehci
, purb
);
5974 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5975 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
5976 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
5978 else // unknown transfer or iso transfer
5980 return STATUS_SUCCESS
;
5984 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5985 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5986 pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5988 ehci_deactivate_urb(purb
);
5989 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5990 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
5991 ehci_remove_bulk_from_schedule(ehci
, purb
);
5993 ehci_remove_int_from_schedule(ehci
, purb
);
5995 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5996 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5998 press_doorbell(ehci
);
6001 else // unknown transfer or iso transfer
6004 return STATUS_SUCCESS
;
6010 case URB_FLAG_STATE_DOORBELL
:
6012 if (doorbell_rings
== FALSE
)
6013 return STATUS_SUCCESS
;
6015 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
6016 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
6017 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
6018 return STATUS_SUCCESS
;
6021 return STATUS_SUCCESS
;
6025 ehci_scan_iso_error(PEHCI_DEV ehci
, PURB purb
)
6026 // we only report the first error of the ITDs, purb->status is the status code
6027 // return the raw status for ehci_set_error_code
6029 PURB_HS_PIPE_CONTENT pipe_content
;
6030 PEHCI_SITD_CONTENT psitd_content
;
6031 PEHCI_ITD_CONTENT pitd_content
;
6032 PLIST_ENTRY pthis
, pnext
;
6035 if (ehci
== NULL
|| purb
== NULL
)
6038 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
6039 if (pipe_content
->trans_type
!= USB_ENDPOINT_XFER_ISOC
)
6044 ListFirst(&purb
->trasac_list
, pthis
);
6045 if (pipe_content
->speed_high
)
6049 pitd_content
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
6050 for(i
= 0; i
< 8; i
++)
6052 if (pitd_content
->status_slot
[i
].status
& ITD_ANY_ERROR
)
6058 return purb
->status
= pitd_content
->status_slot
[i
].status
;
6060 ListNext(&purb
->trasac_list
, pthis
, pnext
);
6068 psitd_content
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
6069 if (psitd_content
->status
& SITD_ANY_ERROR
)
6072 if (psitd_content
->s_mask
== 0x04 &&
6073 psitd_content
->c_mask
== 0x70 && psitd_content
->bytes_to_transfer
== 1)
6074 return purb
->status
= 0;
6076 return purb
->status
= psitd_content
->status
;
6078 ListNext(&purb
->trasac_list
, pthis
, pnext
);
6086 ehci_isr(PKINTERRUPT interrupt
, PVOID context
)
6087 // we can not use endp here for it is within the dev scope, and
6088 // we can not acquire the dev-lock, fortunately we saved some
6089 // info in purb->pipe in ehci_internal_submit_XXX.
6097 PLIST_ENTRY pthis
, pnext
;
6099 BOOLEAN door_bell_rings
;
6102 * Read the interrupt status, and write it back to clear the
6105 ehci
= (PEHCI_DEV
) context
;
6109 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_USBSTS
));
6110 cur_frame
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_FRINDEX
));
6112 status
&= (EHCI_ERROR_INT
| STS_INT
| STS_IAA
);
6113 if (!status
) /* shared interrupt, not mine */
6115 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): not our int\n"));
6120 EHCI_WRITE_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_USBSTS
), status
);
6122 if (status
& EHCI_ERROR_INT
)
6124 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): current ehci status=0x%x\n", status
));
6128 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): congratulations, no error occurs\n"));
6132 if (status
& STS_FATAL
)
6134 DbgPrint("ehci_isr(): host system error, PCI problems?\n");
6139 if (status
& STS_HALT
) //&& !ehci->is_suspended
6141 DbgPrint("ehci_isr(): host controller halted. very bad\n");
6142 /* FIXME: Reset the controller, fix the offending TD */
6143 // reset is performed in dpc
6147 door_bell_rings
= ((status
& STS_IAA
) != 0);
6149 // scan to remove those due
6151 urb_count
= dbg_count_list(&ehci
->urb_list
);
6152 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): urb# in process is %d\n", urb_count
));
6155 ListFirst(&ehci
->urb_list
, pthis
);
6158 purb
= (PURB
) pthis
;
6159 ehci_isr_removing_urb(ehci
, purb
, door_bell_rings
, cur_frame
);
6160 ListNext(&ehci
->urb_list
, pthis
, pnext
);
6164 KeInsertQueueDpc(&ehci
->pdev_ext
->ehci_dpc
, (PVOID
) status
, 0);
6168 #ifndef INCLUDE_EHCI
6170 ehci_unload(IN PDRIVER_OBJECT DriverObject
)
6172 PDEVICE_OBJECT pdev
;
6173 PEHCI_DEVICE_EXTENSION pdev_ext
;
6174 PUSB_DEV_MANAGER dev_mgr
;
6177 pdev
= DriverObject
->DeviceObject
;
6182 pdev_ext
= pdev
->DeviceExtension
;
6183 if (pdev_ext
== NULL
)
6186 dev_mgr
= &g_dev_mgr
;
6187 if (dev_mgr
== NULL
)
6190 // set the termination flag
6192 dev_mgr
->term_flag
= TRUE
;
6194 // wake up the thread if it is
6196 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
6197 KeWaitForSingleObject(dev_mgr
->pthread
, Executive
, KernelMode
, TRUE
, NULL
);
6198 ObDereferenceObject(dev_mgr
->pthread
);
6199 dev_mgr
->pthread
= NULL
;
6201 dev_mgr_release_hcd(dev_mgr
);
6206 generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
)
6208 PDEVEXT_HEADER dev_ext
;
6210 dev_ext
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
6212 if (dev_ext
&& dev_ext
->dispatch
)
6213 return dev_ext
->dispatch(dev_obj
, irp
);
6215 irp
->IoStatus
.Information
= 0;
6217 EXIT_DISPATCH(STATUS_UNSUCCESSFUL
, irp
);
6221 generic_start_io(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
)
6223 PDEVEXT_HEADER dev_ext
;
6227 IoAcquireCancelSpinLock(&old_irql
);
6228 if (irp
!= dev_obj
->CurrentIrp
|| irp
->Cancel
)
6230 IoReleaseCancelSpinLock(old_irql
);
6235 IoSetCancelRoutine(irp
, NULL
);
6236 IoReleaseCancelSpinLock(old_irql
);
6239 dev_ext
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
6241 if (dev_ext
&& dev_ext
->start_io
)
6243 dev_ext
->start_io(dev_obj
, irp
);
6247 irp
->IoStatus
.Information
= 0;
6248 irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
6250 IoStartNextPacket(dev_obj
, FALSE
);
6251 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
6256 DriverEntry(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegistryPath
)
6258 NTSTATUS ntStatus
= STATUS_SUCCESS
;
6262 // should be done before any debug output is done.
6263 // read our debug verbosity level from the registry
6264 //NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path
6265 // L"DebugLevel", // REG_DWORD ValueName
6266 // &gDebugLevel ); // Value receiver
6268 // debug_level = DBGLVL_MAXIMUM;
6271 ehci_dbg_print_cond(DBGLVL_MINIMUM
, DEBUG_UHCI
,
6272 ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath
->Buffer
));
6274 // Remember our driver object, for when we create our child PDO
6275 usb_driver_obj
= DriverObject
;
6278 // Create dispatch points for create, close, unload
6279 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = generic_dispatch_irp
;
6280 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = generic_dispatch_irp
;
6281 DriverObject
->DriverUnload
= ehci_unload
;
6283 // User mode DeviceIoControl() calls will be routed here
6284 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = generic_dispatch_irp
;
6285 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = generic_dispatch_irp
;
6287 // User mode ReadFile()/WriteFile() calls will be routed here
6288 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = generic_dispatch_irp
;
6289 DriverObject
->MajorFunction
[IRP_MJ_READ
] = generic_dispatch_irp
;
6291 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = generic_dispatch_irp
;
6292 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = generic_dispatch_irp
;
6293 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = generic_dispatch_irp
;
6295 DriverObject
->DriverStartIo
= generic_start_io
;
6296 // routines for handling system PNP and power management requests
6297 //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp;
6299 // The Functional Device Object (FDO) will not be created for PNP devices until
6300 // this routine is called upon device plug-in.
6301 RtlZeroMemory(&g_dev_mgr
, sizeof(USB_DEV_MANAGER
));
6302 g_dev_mgr
.usb_driver_obj
= DriverObject
;
6304 ehci_probe(DriverObject
, RegistryPath
, &g_dev_mgr
);
6306 if (dev_mgr_strobe(&g_dev_mgr
) == FALSE
)
6308 dev_mgr_release_hcd(&g_dev_mgr
);
6309 return STATUS_UNSUCCESSFUL
;
6312 dev_mgr_start_hcd(&g_dev_mgr
);
6313 ehci_dbg_print_cond(DBGLVL_DEFAULT
, DEBUG_UHCI
, ("DriverEntry(): exiting... (%x)\n", ntStatus
));
6314 return STATUS_SUCCESS
;
6318 //note: the initialization will be in the following order
6322 // to kill dev_mgr_thread:
6323 // dev_mgr->term_flag = TRUE;
6324 // KeSetEvent( &dev_mgr->wake_up_event );
6325 // this piece of code must run at passive-level