Sync with trunk head
[reactos.git] / drivers / usb / nt4compat / usbdriver / td.h
1 /*
2 * NOTE!!!: part of the code is pasted from linux/driver/usb/uhci.h
3 */
4
5 #ifndef __UHCI_H__
6 #define __UHCI_H__
7
8 #define LIST_HEAD LIST_ENTRY
9 #define PLIST_HEAD PLIST_ENTRY
10 #define BYTE UCHAR
11 #define PBYTE PUCHAR
12 #define WORD USHORT
13 #define DWORD ULONG
14
15 #ifndef LOWORD
16 #define LOWORD(l) ( (WORD) ( ( l ) & 0xffff ) )
17 #endif
18 #ifndef HIWORD
19 #define HIWORD(l) ( (WORD) ( ( l ) >> 16 ) )
20 #endif
21
22 #define PCI_MAX_FUNCTIONS 8
23
24
25 #define UHCI_MAX_POOL_TDS 1024 //8 pages of 4k
26 #define UHCI_MAX_POOL_QHS 256 //1 page of 4k
27 #define UHCI_MAX_ANT_TDS 0x20e82
28
29 #define UHCI_MAX_TD_POOLS 8
30 #define UHCI_MAX_TDS_PER_TRANSFER UHCI_MAX_POOL_TDS
31
32 #define UHCI_FULL_SPEED_BANDWIDHT ( 12 * 1000 * 1000 )
33 #define UHCI_LOW_SPEED_BANDWIDHT ( 15 * 100 * 1000 )
34 /*
35 * Universal Host Controller Interface data structures and defines
36 */
37
38 /* Command register */
39 #define USBCMD 0
40 #define USBCMD_RS 0x0001 /* Run/Stop */
41 #define USBCMD_HCRESET 0x0002 /* Host reset */
42 #define USBCMD_GRESET 0x0004 /* Global reset */
43 #define USBCMD_EGSM 0x0008 /* Global Suspend Mode */
44 #define USBCMD_FGR 0x0010 /* Force Global Resume */
45 #define USBCMD_SWDBG 0x0020 /* SW Debug mode */
46 #define USBCMD_CF 0x0040 /* Config Flag (sw only) */
47 #define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */
48
49 /* Status register */
50 #define USBSTS 2
51 #define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */
52 #define USBSTS_ERROR 0x0002 /* Interrupt due to error */
53 #define USBSTS_RD 0x0004 /* Resume Detect */
54 #define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */
55 #define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */
56 #define USBSTS_HCH 0x0020 /* HC Halted */
57
58 /* Interrupt enable register */
59 #define USBINTR 4
60 #define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */
61 #define USBINTR_RESUME 0x0002 /* Resume interrupt enable */
62 #define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */
63 #define USBINTR_SP 0x0008 /* Short packet interrupt enable */
64
65 #define USBFRNUM 6
66 #define USBFLBASEADD 8
67 #define USBSOF 12
68
69 /* USB port status and control registers */
70 #define USBPORTSC1 16
71 #define USBPORTSC2 18
72 #define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */
73 #define USBPORTSC_CSC 0x0002 /* Connect Status Change */
74 #define USBPORTSC_PE 0x0004 /* Port Enable */
75 #define USBPORTSC_PEC 0x0008 /* Port Enable Change */
76 #define USBPORTSC_LS 0x0020 /* Line Status */
77 #define USBPORTSC_RD 0x0040 /* Resume Detect */
78 #define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */
79 #define USBPORTSC_PR 0x0200 /* Port Reset */
80 #define USBPORTSC_SUSP 0x1000 /* Suspend */
81
82 /* Legacy support register */
83 #define USBLEGSUP 0xc0
84 #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
85 #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
86 #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
87
88
89 #define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
90
91 #define UHCI_PTR_BITS 0x000F
92 #define UHCI_PTR_TERM 0x0001
93 #define UHCI_PTR_QH 0x0002
94 #define UHCI_PTR_DEPTH 0x0004
95
96 #define UHCI_MAX_FRAMES 1024 /* in the frame list [array] */
97 #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */
98 #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */
99
100
101 //from linux's uhci.h
102 #define UHCI_MAX_SKELTDS 10
103 #define skel_int1_td skel_td[0]
104 #define skel_int2_td skel_td[1]
105 #define skel_int4_td skel_td[2]
106 #define skel_int8_td skel_td[3]
107 #define skel_int16_td skel_td[4]
108 #define skel_int32_td skel_td[5]
109 #define skel_int64_td skel_td[6]
110 #define skel_int128_td skel_td[7]
111 #define skel_int256_td skel_td[8]
112 #define skel_term_td skel_td[9] /* To work around PIIX UHCI bug */
113
114 #define UHCI_MAX_SKELQHS 4
115 #define skel_ls_control_qh skel_qh[0]
116 #define skel_hs_control_qh skel_qh[1]
117 #define skel_bulk_qh skel_qh[2]
118 #define skel_term_qh skel_qh[3]
119
120
121
122 struct URB;
123
124 /*
125 * for TD <status>:
126 */
127 #define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */
128 #define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */
129 #define TD_CTRL_C_ERR_SHIFT 27
130 #define TD_CTRL_LS (1 << 26) /* Low Speed Device */
131 #define TD_CTRL_IOS (1 << 25) /* Isochronous Select */
132 #define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */
133 #define TD_CTRL_ACTIVE (1 << 23) /* TD Active */
134 #define TD_CTRL_STALLED (1 << 22) /* TD Stalled */
135 #define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */
136 #define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */
137 #define TD_CTRL_NAK (1 << 19) /* NAK Received */
138 #define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */
139 #define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */
140 #define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */
141
142 #define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
143 TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | TD_CTRL_BITSTUFF)
144
145 #define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000)
146 #define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
147
148 /*
149 * for TD <info>: (a.k.a. Token)
150 */
151 #define TD_TOKEN_TOGGLE 19
152 #define TD_PID 0xFF
153
154 #define uhci_maxlen(token) ((token) >> 21)
155 #define uhci_expected_length(info) (((info >> 21) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
156 #define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1)
157 #define uhci_endpoint(token) (((token) >> 15) & 0xf)
158 #define uhci_devaddr(token) (((token) >> 8) & 0x7f)
159 #define uhci_devep(token) (((token) >> 8) & 0x7ff)
160 #define uhci_packetid(token) ((token) & 0xff)
161 #define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN)
162 #define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN)
163
164 /*
165 * The documentation says "4 dwords for hardware, 4 dwords for software".
166 *
167 * That's silly, the hardware doesn't care. The hardware only cares that
168 * the hardware words are 16-byte aligned, and we can have any amount of
169 * sw space after the TD entry as far as I can tell.
170 *
171 * But let's just go with the documentation, at least for 32-bit machines.
172 * On 64-bit machines we probably want to take advantage of the fact that
173 * hw doesn't really care about the size of the sw-only area.
174 *
175 * Alas, not anymore, we have more than 4 dwords for software, woops.
176 * Everything still works tho, surprise! -jerdfelt
177 */
178
179 #define UHCI_ITEM_FLAG_TYPE 0x3
180 #define UHCI_ITEM_FLAG_TD 0x0
181 #define UHCI_ITEM_FLAG_QH 0x1
182
183 #ifndef offsetof
184 #define offsetof( s, m ) ( ( ULONG )( &( ( s* )0 )->m ) )
185 #endif
186
187 #define struct_ptr( meMBER_ptr, stRUCT_name, meMBER_name ) \
188 ( ( stRUCT_name* ) ( ( (CHAR*)( meMBER_ptr ) ) - offsetof( stRUCT_name, meMBER_name ) ) )
189
190 #define dev_state( pdEV ) ( ( pdEV )->flags & USB_DEV_STATE_MASK )
191
192 #define dev_class( pdev ) ( pdev->flags & USB_DEV_CLASS_MASK )
193
194 #define uhci_from_hcd( hCD ) ( struct_ptr( ( hCD ), UHCI_DEV, hcd_interf ) )
195 #define uhci_from_dev( dEV ) ( struct_ptr( ( dEV->hcd ), UHCI_DEV, hcd_interf ) )
196
197 typedef struct _TD_EXTENSION
198 {
199 LIST_ENTRY vert_link; // urb will use this to link qh and tds
200 LIST_ENTRY hori_link;
201 ULONG flags;
202 struct _UHCI_TD *ptd; //link to is companion td, constant since initialized
203
204 } TD_EXTENSION, *PTD_EXTENSION;
205
206 typedef struct _UHCI_TD
207 {
208 /* Hardware fields */
209 ULONG link;
210 ULONG status;
211 ULONG info;
212 ULONG buffer;
213
214 /* Software fields */
215 ULONG phy_addr;
216 PTD_EXTENSION ptde;
217 struct _URB *purb;
218 struct _UHCI_TD_POOL *pool; //pool this td belongs to
219
220 } UHCI_TD, *PUHCI_TD;
221
222 typedef struct _UHCI_TD_POOL
223 {
224
225 LIST_ENTRY pool_link; //link to next and prev td pool
226 PUHCI_TD td_array[ sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE ]; //would be allcated in common buffer
227 PHYSICAL_ADDRESS logic_addr[ sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE ]; //logical addr of the array
228
229 PTD_EXTENSION tde_array;
230 LIST_ENTRY free_que; //list of free tds
231 LONG free_count; //free tds in this pool
232 LONG total_count; //total count of the tds
233 PADAPTER_OBJECT padapter;
234
235 } UHCI_TD_POOL, *PUHCI_TD_POOL;
236
237 BOOLEAN
238 init_td_pool(
239 PUHCI_TD_POOL pool
240 );
241
242 BOOLEAN
243 free_td_to_pool(
244 PUHCI_TD_POOL pool,
245 PUHCI_TD ptd
246 ); //add tds till pnext == NULL
247
248 PUHCI_TD
249 alloc_td_from_pool(
250 PUHCI_TD_POOL ptd_pool
251 ); //null if failed]
252
253 BOOLEAN
254 is_pool_free(
255 PUHCI_TD_POOL pool
256 ); //test whether the pool is all free
257
258 BOOLEAN
259 is_pool_full(
260 PUHCI_TD_POOL pool
261 );
262
263 BOOLEAN
264 destroy_td_pool(
265 PUHCI_TD_POOL pool
266 );
267
268 typedef struct _UHCI_TD_POOL_LIST
269 {
270 LIST_ENTRY busy_pools;
271 KSPIN_LOCK pool_lock;
272 LONG free_tds; //free tds in all the pool
273 LONG free_count; //free pool count
274 LIST_ENTRY free_pools;
275 UHCI_TD_POOL pool_array[UHCI_MAX_TD_POOLS]; //max transfer is 640k
276
277 } UHCI_TD_POOL_LIST, *PUHCI_TD_POOL_LIST;
278
279 BOOLEAN
280 init_td_pool_list(
281 PUHCI_TD_POOL_LIST pool_list,
282 PADAPTER_OBJECT padapter
283 );
284
285 BOOLEAN
286 destroy_td_pool_list(
287 PUHCI_TD_POOL_LIST pool_list
288 );
289
290 BOOLEAN
291 expand_pool_list(
292 PUHCI_TD_POOL_LIST pool_list,
293 LONG pool_count
294 ); //private
295
296 BOOLEAN
297 collect_garbage(
298 PUHCI_TD_POOL_LIST pool_list
299 );
300
301 LONG
302 get_free_tds(
303 PUHCI_TD_POOL_LIST pool_list
304 ); //private
305
306 LONG
307 get_max_free_tds(
308 PUHCI_TD_POOL_LIST pool_list
309 ); //private
310
311 BOOLEAN
312 can_transfer(
313 PUHCI_TD_POOL_LIST pool_list,
314 LONG td_count);
315
316 BOOLEAN
317 free_td(
318 PUHCI_TD_POOL_LIST pool_list,
319 PUHCI_TD ptd
320 ); //add tds till pnext == NULL
321
322 PUHCI_TD
323 alloc_td(
324 PUHCI_TD_POOL_LIST pool_list
325 ); //null if failed
326
327 VOID
328 lock_td_pool(
329 PUHCI_TD_POOL_LIST pool_list,
330 BOOLEAN at_dpc
331 );
332
333 VOID
334 unlock_td_pool(
335 PUHCI_TD_POOL_LIST pool_list,
336 BOOLEAN at_dpc
337 );
338
339 typedef struct _UHCI_QH
340 {
341 /* Hardware fields */
342 ULONG link; // Next queue
343 ULONG element; // Queue element pointer
344
345 /* Software fields */
346 ULONG phy_addr; //constant since initialized
347 struct _QH_EXTENSION *pqhe;
348
349 } UHCI_QH, *PUHCI_QH;
350
351 typedef struct _QH_EXTENSION
352 {
353
354 LIST_ENTRY vert_link;
355 LIST_ENTRY hori_link;
356 ULONG flags;
357 PUHCI_QH pqh; //constant since initialized
358 struct _URB *purb;
359
360 } QH_EXTENSION, *PQH_EXTENSION;
361
362 typedef struct _UHCI_QH_POOL
363 {
364
365 PUHCI_QH qh_array;
366 PHYSICAL_ADDRESS logic_addr; //logical addr of the array
367
368 PQH_EXTENSION qhe_array;
369 LIST_ENTRY free_que;
370 LONG free_count;
371 LONG total_count;
372 KSPIN_LOCK pool_lock;
373 PADAPTER_OBJECT padapter; //we need this garbage for allocation
374
375 } UHCI_QH_POOL, *PUHCI_QH_POOL;
376
377
378 BOOLEAN
379 init_qh_pool(
380 PUHCI_QH_POOL pool,
381 PADAPTER_OBJECT padapter
382 );
383
384 BOOLEAN
385 free_qh(
386 PUHCI_QH_POOL pool,
387 PUHCI_QH ptd
388 ); //add qhs till pnext == NULL
389
390 PUHCI_QH
391 alloc_qh(
392 PUHCI_QH_POOL pool
393 ); //null if failed
394
395 BOOLEAN
396 destroy_qh_pool(
397 PUHCI_QH_POOL pool
398 );
399
400 VOID
401 lock_qh_pool(
402 PUHCI_QH_POOL pool,
403 BOOLEAN at_dpc
404 );
405
406 VOID
407 unlock_qh_pool(
408 PUHCI_QH_POOL pool,
409 BOOLEAN at_dpc
410 );
411
412 /*
413 * Search tree for determining where <interval> fits in the
414 * skelqh[] skeleton.
415 *
416 * An interrupt request should be placed into the slowest skelqh[]
417 * which meets the interval/period/frequency requirement.
418 * An interrupt request is allowed to be faster than <interval> but not slower.
419 *
420 * For a given <interval>, this function returns the appropriate/matching
421 * skelqh[] index value.
422 *
423 * NOTE: For UHCI, we don't really need int256_qh since the maximum interval
424 * is 255 ms. However, we do need an int1_qh since 1 is a valid interval
425 * and we should meet that frequency when requested to do so.
426 * This will require some change(s) to the UHCI skeleton.
427 */
428 #if 0
429 static int __interval_to_skel(int interval)
430 {
431 if (interval < 16) {
432 if (interval < 4) {
433 if (interval < 2)
434 return 0; /* int1 for 0-1 ms */
435 return 1; /* int2 for 2-3 ms */
436 }
437 if (interval < 8)
438 return 2; /* int4 for 4-7 ms */
439 return 3; /* int8 for 8-15 ms */
440 }
441 if (interval < 64) {
442 if (interval < 32)
443 return 4; /* int16 for 16-31 ms */
444 return 5; /* int32 for 32-63 ms */
445 }
446 if (interval < 128)
447 return 6; /* int64 for 64-127 ms */
448 return 7; /* int128 for 128-255 ms (Max.) */
449 }
450 #endif
451
452 #define USB_ENDP_FLAG_BUSY_MASK 0x0000ff00
453 #define USB_ENDP_FLAG_STAT_MASK 0xff
454 #define USB_ENDP_FLAG_STALL 0x01
455 #define USB_ENDP_FLAG_DATATOGGLE 0x80000000
456 #define USB_ENDP_FLAG_DEFAULT_ENDP 0x40000000
457
458 #define usb_endp_busy_count( peNDP ) \
459 ( ( ( peNDP )->flags & USB_ENDP_FLAG_BUSY_MASK ) >> 8 )
460
461 #define usb_endp_busy_count_inc( peNDP ) \
462 ( peNDP->flags = ( ( ( ( usb_endp_busy_count( peNDP ) + 1 ) << 8 ) & USB_ENDP_FLAG_BUSY_MASK ) | \
463 ( ( peNDP )->flags & ~USB_ENDP_FLAG_BUSY_MASK ) ) )
464
465 #define usb_endp_busy_count_dec( peNDP ) \
466 ( peNDP->flags = ( ( ( ( usb_endp_busy_count( peNDP ) - 1 ) << 8 ) & USB_ENDP_FLAG_BUSY_MASK )| \
467 ( ( peNDP )->flags & ~USB_ENDP_FLAG_BUSY_MASK ) ) )
468
469 typedef struct _USB_ENDPOINT
470 {
471 ULONG flags; //toggle | busy-count | stall | default-endp; busy count( usually 1 when busy, may be greater if iso endp )
472 LIST_ENTRY urb_list; //pending urb queue
473
474 struct _USB_INTERFACE *pusb_if;
475 struct _USB_ENDPOINT_DESC *pusb_endp_desc;
476
477 } USB_ENDPOINT, *PUSB_ENDPOINT;
478
479 #define MAX_ENDPS_PER_IF 10
480
481 typedef struct _USB_INTERFACE
482 {
483 UCHAR endp_count;
484 USB_ENDPOINT endp[MAX_ENDPS_PER_IF];
485
486
487 struct _USB_CONFIGURATION *pusb_config;
488 PUSB_INTERFACE_DESC pusb_if_desc;
489
490 struct _USB_DRIVER *pif_drv; //for hub_dev use
491 PVOID if_ext;
492 LONG if_ext_size;
493 UCHAR altif_count;
494 LIST_ENTRY altif_list;
495
496
497 } USB_INTERFACE, *PUSB_INTERFACE;
498
499 #define MAX_INTERFACES_PER_CONFIG 4
500 #define MAX_CONFIGS_PER_DEV 4
501
502 typedef struct _USB_CONFIGURATION
503 {
504 //only for active configuration
505 struct _USB_CONFIGURATION_DESC *pusb_config_desc;
506 UCHAR if_count;
507 USB_INTERFACE interf[MAX_INTERFACES_PER_CONFIG];
508 struct _USB_DEV *pusb_dev;
509
510 } USB_CONFIGURATION, *PUSB_CONFIGURATION;
511
512 #define USE_IRQL \
513 KIRQL _pending_endp_lock_old_irql=0, _pending_endp_list_lock_old_irql=0, _dev_lock_old_irql=0, old_irql=0;
514
515 #define USE_BASIC_IRQL \
516 KIRQL _pending_endp_list_lock_old_irql=0, _dev_lock_old_irql=0;
517
518 #define USE_NON_PENDING_IRQL \
519 KIRQL _dev_lock_old_irql=0, old_irql=0;
520
521 #define USE_BASIC_NON_PENDING_IRQL \
522 KIRQL _dev_lock_old_irql=0;
523
524
525 #define USB_DEV_STATE_MASK ( 0xff << 8 )
526 #define USB_DEV_STATE_POWERED ( 0x01 << 8 )
527 #define USB_DEV_STATE_RESET ( 0x02 << 8 )
528 #define USB_DEV_STATE_ADDRESSED ( 0x03 << 8 )
529 #define USB_DEV_STATE_FIRST_CONFIG ( 0x04 << 8 )
530 #define USB_DEV_STATE_RECONFIG ( 0x05 << 8 )
531 #define USB_DEV_STATE_CONFIGURED ( 0x06 << 8 )
532 #define USB_DEV_STATE_SUSPENDED ( 0x07 << 8 )
533 #define USB_DEV_STATE_BEFORE_ZOMB ( 0x08 << 8 )
534 #define USB_DEV_STATE_ZOMB ( 0x09 << 8 )
535
536 #define USB_DEV_CLASS_MASK ( 0xff << 16 )
537 #define USB_DEV_CLASS_HUB ( USB_CLASS_HUB << 16 )
538 #define USB_DEV_CLASS_MASSSTOR ( USB_CLASS_MASS_STORAGE << 16 )
539 #define USB_DEV_CLASS_ROOT_HUB ( ( USB_CLASS_VENDOR_SPEC - 2 ) << 16 )
540 #define USB_DEV_CLASS_SCANNER ( ( USB_DEV_CLASS_ROOT_HUB - 1 ) << 16 )
541
542 #define USB_DEV_FLAG_HIGH_SPEED 0x20 // high speed dev for usb2.0
543 #define USB_DEV_FLAG_LOW_SPEED 0x40 // note: this bit is shared in urb->pipe
544 #define USB_DEV_FLAG_IF_DEV 0x01 // this dev is a virtual dev, that is a interface
545
546 #define lock_dev( pdev, at_dpc ) \
547 {\
548 KIRQL cur_irql;\
549 cur_irql = KeGetCurrentIrql();\
550 if( cur_irql == DISPATCH_LEVEL )\
551 {\
552 KeAcquireSpinLockAtDpcLevel( &pdev->dev_lock );\
553 _dev_lock_old_irql = DISPATCH_LEVEL;\
554 }\
555 else if( cur_irql < DISPATCH_LEVEL )\
556 KeAcquireSpinLock( &pdev->dev_lock, &_dev_lock_old_irql );\
557 else\
558 TRAP();\
559 }
560
561 #define unlock_dev( pdev, from_dpc ) \
562 {\
563 if( _dev_lock_old_irql == DISPATCH_LEVEL )\
564 KeReleaseSpinLockFromDpcLevel( &pdev->dev_lock );\
565 else if( _dev_lock_old_irql < DISPATCH_LEVEL )\
566 KeReleaseSpinLock( &pdev->dev_lock, _dev_lock_old_irql );\
567 else\
568 TRAP();\
569 }
570
571 typedef struct _USB_DEV
572 {
573 LIST_ENTRY dev_link; //for dev-list
574
575 KSPIN_LOCK dev_lock;
576 PDEVICE_OBJECT dev_obj;
577 ULONG flags; //class | cur_state | low speed
578 LONG ref_count; //client count
579
580 UCHAR dev_addr; //usb addr
581 ULONG dev_id; //will be used to compose dev handle
582
583 struct _USB_DEV *parent_dev;
584 UCHAR port_idx; //parent hub's port idx, to which the dev attached
585
586 struct _HCD *hcd; //point to the hcd the dev belongs to
587
588 USB_ENDPOINT default_endp; //control endp. its interfac pointer is to the first interface
589
590 LONG desc_buf_size;
591 PUCHAR desc_buf;
592 struct _USB_DEVICE_DESC *pusb_dev_desc;
593
594 UCHAR active_config_idx;
595 PUSB_CONFIGURATION usb_config; //the active configuration
596
597 struct _USB_DRIVER *dev_driver;
598 PVOID dev_ext;
599 LONG dev_ext_size;
600
601 LONG time_out_count; //default pipe error counter, three time-outs will cause the dev not function
602 LONG error_count; //usb transfer error counter for statics only
603
604 } USB_DEV, *PUSB_DEV;
605
606 // pending endpoint pool definitions
607
608 #define UHCI_MAX_PENDING_ENDPS 32
609
610 typedef struct _UHCI_PENDING_ENDP
611 {
612 LIST_ENTRY endp_link;
613 PUSB_ENDPOINT pendp;
614
615 } UHCI_PENDING_ENDP, *PUHCI_PENDING_ENDP;
616
617 typedef struct _UHCI_PENDING_ENDP_POOL
618 {
619 PUHCI_PENDING_ENDP pending_endp_array;
620 LIST_ENTRY free_que;
621 LONG free_count;
622 LONG total_count;
623 KSPIN_LOCK pool_lock;
624
625 } UHCI_PENDING_ENDP_POOL, *PUHCI_PENDING_ENDP_POOL;
626
627 BOOLEAN
628 init_pending_endp_pool(
629 PUHCI_PENDING_ENDP_POOL pool
630 );
631
632 BOOLEAN
633 free_pending_endp(
634 PUHCI_PENDING_ENDP_POOL pool,
635 PUHCI_PENDING_ENDP pending_endp
636 );
637
638 PUHCI_PENDING_ENDP
639 alloc_pending_endp(
640 PUHCI_PENDING_ENDP_POOL pool,
641 LONG count
642 );
643
644 BOOLEAN
645 destroy_pending_endp_pool(
646 PUHCI_PENDING_ENDP_POOL pool
647 );
648
649 // pool type is PUHCI_PENDING_ENDP_POOL
650 #define lock_pending_endp_pool( pool ) \
651 {\
652 KeAcquireSpinLock( &pool->pool_lock, &_pending_endp_lock_old_irql );\
653 }
654
655 #define unlock_pending_endp_pool( pool ) \
656 {\
657 KeReleaseSpinLock( &pool->pool_lock, &_pending_endp_lock_old_irql );\
658 }
659
660
661 // end of pending endpoint pool
662 typedef struct _FRAME_LIST_CPU_ENTRY
663 {
664 LIST_ENTRY td_link;
665
666 } FRAME_LIST_CPU_ENTRY, *PFRAME_LIST_CPU_ENTRY;
667
668 #define uhci_public_res_lock pending_endp_list_lock
669 #define uhci_status( _uhci_ ) ( READ_PORT_USHORT( ( PUSHORT )( ( _uhci_ )->port_base + USBSTS ) ) )
670
671 typedef struct _UHCI
672 {
673 PHYSICAL_ADDRESS uhci_reg_base; // io space
674 BOOLEAN port_mapped;
675 PBYTE port_base;
676
677 PHYSICAL_ADDRESS io_buf_logic_addr;
678 PBYTE io_buf;
679
680 PHYSICAL_ADDRESS frame_list_logic_addr;
681
682 KSPIN_LOCK frame_list_lock; //run at DIRQL
683 PULONG frame_list;
684 PFRAME_LIST_CPU_ENTRY frame_list_cpu;
685 LIST_HEAD urb_list; //active urb-list
686 PUHCI_TD skel_td[UHCI_MAX_SKELTDS];
687 PUHCI_QH skel_qh[UHCI_MAX_SKELQHS]; //skeltons
688
689
690
691 UHCI_TD_POOL_LIST td_pool;
692 UHCI_QH_POOL qh_pool;
693
694
695 //for iso and int bandwidth claim, bandwidth schedule
696 KSPIN_LOCK pending_endp_list_lock; //lock to access the following two
697 LIST_HEAD pending_endp_list;
698 UHCI_PENDING_ENDP_POOL pending_endp_pool;
699 PLONG frame_bw;
700 LONG fsbr_cnt; //used to record number of fsbr users
701
702 KTIMER reset_timer; //used to reset the host controller
703
704 //struct _USB_DEV_MANAGER dev_mgr; //it is in hcd_interf
705 struct _DEVICE_EXTENSION *pdev_ext;
706
707 PUSB_DEV root_hub; //root hub
708 HCD hcd_interf;
709
710 } UHCI_DEV, *PUHCI_DEV;
711
712 #define lock_pending_endp_list( list_lock ) \
713 {\
714 KeAcquireSpinLock( list_lock, &_pending_endp_list_lock_old_irql );\
715 }
716
717 #define unlock_pending_endp_list( list_lock ) \
718 {\
719 KeReleaseSpinLock( list_lock, _pending_endp_list_lock_old_irql );\
720 }
721 typedef struct _UHCI_INTERRUPT
722 {
723 ULONG level;
724 ULONG vector;
725 ULONG affinity;
726
727 } UHCI_INTERRUPT, *PUHCI_INTERRUPT;
728
729 typedef struct _UHCI_PORT
730 {
731 PHYSICAL_ADDRESS Start;
732 ULONG Length;
733
734 } UHCI_PORT, *PUHCI_PORT;
735
736 typedef NTSTATUS ( *PDISPATCH_ROUTINE )( PDEVICE_OBJECT dev_obj, PIRP irp );
737
738 #define NTDEV_TYPE_HCD 1
739 #define NTDEV_TYPE_CLIENT_DEV 2
740
741 typedef struct _DEVEXT_HEADER
742 {
743 ULONG type;
744 PDISPATCH_ROUTINE dispatch;
745 PDRIVER_STARTIO start_io;
746
747 struct _USB_DEV_MANAGER *dev_mgr; //mainly for use by cancel irp
748
749 } DEVEXT_HEADER, *PDEVEXT_HEADER;
750
751 typedef struct _DEVICE_EXTENSION
752 {
753 //struct _USB_DEV_MANAGER *pdev_mgr;
754 DEVEXT_HEADER dev_ext_hdr;
755 PDEVICE_OBJECT pdev_obj;
756 PDRIVER_OBJECT pdrvr_obj;
757 PUHCI_DEV uhci;
758
759 //device resources
760 PADAPTER_OBJECT padapter;
761 ULONG map_regs;
762 PCM_RESOURCE_LIST res_list;
763 ULONG pci_addr; // bus number | slot number | funciton number
764 UHCI_INTERRUPT res_interrupt;
765 UHCI_PORT res_port;
766
767 PKINTERRUPT uhci_int;
768 KDPC uhci_dpc;
769
770 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
771
772 //helper macro
773 #define ListFirst( heAD, firST) \
774 {\
775 if( IsListEmpty( ( heAD ) ) )\
776 firST = NULL;\
777 else\
778 firST = ( heAD )->Flink;\
779 }
780
781 #define ListNext( heAD, curreNT, neXT) \
782 {\
783 if( IsListEmpty( ( heAD ) ) == FALSE )\
784 {\
785 neXT = (curreNT)->Flink;\
786 if( neXT == heAD )\
787 neXT = NULL;\
788 }\
789 else\
790 neXT = NULL;\
791 }
792
793 #define ListPrev( heAD, curreNT, prEV) \
794 {\
795 if( IsListEmpty( ( heAD ) ) == FALSE )\
796 {\
797 prEV = (curreNT)->Blink;\
798 if( prEV == heAD )\
799 prEV = NULL;\
800 else\
801 prEV = NULL;\
802 }
803
804 #define ListFirstPrev( heAD, firST) \
805 {\
806 if( IsListEmpty( ( heAD ) ) )\
807 firST = NULL;\
808 else\
809 firST = ( heAD )->Blink;\
810 }
811
812 #define MergeList( liST1, liST2 )\
813 {\
814 PLIST_ENTRY taIL1, taIL2;\
815 if( IsListEmpty( liST2 ) == TRUE )\
816 {\
817 InsertTailList( liST1, liST2 );\
818 }\
819 else if( IsListEmpty( liST1 ) == TRUE )\
820 {\
821 InsertTailList( liST2, liST1 );\
822 }\
823 else\
824 {\
825 ListFirstPrev( liST1, taIL1 );\
826 ListFirstPrev( liST2, taIL2 );\
827 \
828 taIL1->Flink = ( liST2 );\
829 ( liST2 )->Blink = taIL1;\
830 \
831 taIL2->Flink = ( liST1 );\
832 ( liST1 )->Blink = taIL2;\
833 }\
834 }
835
836 PUHCI_TD
837 alloc_tds(
838 PUHCI_TD_POOL_LIST pool_list,
839 LONG count
840 );
841
842 VOID
843 free_tds(
844 PUHCI_TD_POOL_LIST pool_list,
845 PUHCI_TD ptd
846 );
847
848 BOOLEAN
849 uhci_init(
850 PUHCI_DEV uhci,
851 PADAPTER_OBJECT padapter
852 );
853
854 BOOLEAN
855 uhci_destroy(
856 PUHCI_DEV uhci
857 );
858
859 // funcitons exported to dev-manager
860 BOOLEAN
861 uhci_add_device(
862 PUHCI_DEV uhci,
863 PUSB_DEV dev
864 );
865
866 BOOLEAN
867 uhci_remove_device(
868 PUHCI_DEV uhci,
869 PUSB_DEV dev
870 );
871
872 //helpers
873 VOID NTAPI
874 uhci_dpc_callback(
875 PKDPC dpc,
876 PVOID context,
877 PVOID sysarg1,
878 PVOID sysarg2
879 );
880
881 #if 0
882 static VOID
883 uhci_flush_adapter_buf()
884 {
885 #ifdef _X86
886 __asm invd;
887 #endif
888 }
889 #endif
890
891 NTSTATUS
892 uhci_submit_urb(
893 PUHCI_DEV uhci,
894 PUSB_DEV pdev,
895 PUSB_ENDPOINT pendp,
896 struct _URB *urb
897 );
898
899 //must have dev_lock acquired
900 NTSTATUS
901 uhci_internal_submit_bulk(
902 PUHCI_DEV uhci,
903 struct _URB *urb
904 );
905
906 NTSTATUS
907 uhci_internal_submit_iso(
908 PUHCI_DEV uhci,
909 struct _URB *urb
910 );
911
912 NTSTATUS
913 uhci_internal_submit_ctrl(
914 PUHCI_DEV uhci,
915 struct _URB *urb
916 );
917
918 NTSTATUS
919 uhci_internal_submit_int(
920 PUHCI_DEV uhci,
921 struct _URB *urb
922 );
923
924 BOOLEAN
925 uhci_remove_bulk_from_schedule(
926 PUHCI_DEV uhci,
927 struct _URB *urb
928 );
929
930 #define uhci_remove_ctrl_from_schedule uhci_remove_bulk_from_schedule
931
932 BOOLEAN
933 uhci_remove_iso_from_schedule(
934 PUHCI_DEV uhci,
935 struct _URB *urb
936 );
937
938 BOOLEAN
939 uhci_remove_int_from_schedule(
940 PUHCI_DEV uhci,
941 struct _URB *urb
942 );
943
944 BOOLEAN
945 uhci_remove_urb_from_schedule(
946 PUHCI_DEV uhci,
947 struct _URB *urb
948 );
949
950 BOOLEAN
951 uhci_is_xfer_finished( //will set urb error code here
952 struct _URB *urb
953 );
954
955 NTSTATUS
956 uhci_set_error_code(
957 struct _URB *urb,
958 ULONG raw_status
959 );
960
961 BOOLEAN
962 uhci_insert_tds_qh(
963 PUHCI_QH pqh,
964 PUHCI_TD td_chain
965 );
966
967 BOOLEAN
968 uhci_insert_qh_urb(
969 struct _URB *urb,
970 PUHCI_QH qh_chain
971 );
972
973 BOOLEAN
974 uhci_insert_urb_schedule(
975 PUHCI_DEV uhci,
976 struct _URB *urb
977 );
978
979 BOOLEAN
980 uhci_claim_bandwidth(
981 PUHCI_DEV uhci,
982 struct _URB *urb,
983 BOOLEAN claim_bw
984 );
985
986 BOOLEAN
987 uhci_process_pending_endp(
988 PUHCI_DEV uhci
989 );
990
991 NTSTATUS
992 uhci_cancel_urb(
993 PUHCI_DEV uhci,
994 PUSB_DEV pdev,
995 PUSB_ENDPOINT endp,
996 struct _URB *urb
997 );
998
999 VOID
1000 uhci_generic_urb_completion(
1001 struct _URB *urb,
1002 PVOID context
1003 );
1004
1005 // the following are NT driver definitions
1006
1007 // NT device name
1008 #define UHCI_DEVICE_NAME "\\Device\\UHCI"
1009
1010 // File system device name. When you execute a CreateFile call to open the
1011 // device, use "\\.\GpdDev", or, given C's conversion of \\ to \, use
1012 // "\\\\.\\GpdDev"
1013
1014 #define DOS_DEVICE_NAME "\\DosDevices\\UHCI"
1015
1016
1017 #define CLR_RH_PORTSTAT( port_idx, x ) \
1018 {\
1019 PUSHORT addr; \
1020 addr = ( PUSHORT )( uhci->port_base + port_idx ); \
1021 status = READ_PORT_USHORT( addr ); \
1022 status = ( status & 0xfff5 ) & ~( x ); \
1023 WRITE_PORT_USHORT( addr, ( USHORT )status ); \
1024 }
1025
1026 #define SET_RH_PORTSTAT( port_idx, x ) \
1027 {\
1028 PUSHORT addr; \
1029 addr = ( PUSHORT )( uhci->port_base + port_idx ); \
1030 status = READ_PORT_USHORT( addr ); \
1031 status = ( status & 0xfff5 ) | ( x ); \
1032 WRITE_PORT_USHORT( addr, ( USHORT )status ); \
1033 }
1034
1035 //this is for dispatch routine
1036 #define EXIT_DISPATCH( nTstatUs, iRp)\
1037 {\
1038 if( nTstatUs != STATUS_PENDING)\
1039 {\
1040 iRp->IoStatus.Status = nTstatUs;\
1041 IoCompleteRequest( iRp, IO_NO_INCREMENT);\
1042 return nTstatUs;\
1043 }\
1044 IoMarkIrpPending( iRp);\
1045 return nTstatUs;\
1046 }
1047
1048 #endif
1049