@@ -161,6 +161,22 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr);
161161//--------------------------------------------------------------------+
162162// USBH-HCD API
163163//--------------------------------------------------------------------+
164+
165+ //If your system requires separation of virtual and physical memory, implement
166+ //tuh_get_phys_addr and tuh_get_virt_addr in your application.
167+ TU_ATTR_WEAK void * tuh_get_phys_addr (void * virtual_address );
168+ TU_ATTR_WEAK void * tuh_get_virt_addr (void * physical_address );
169+ TU_ATTR_ALWAYS_INLINE static void * _phys_addr (void * virtual_address )
170+ {
171+ if (tuh_get_phys_addr ) return tuh_get_phys_addr (virtual_address );
172+ return virtual_address ;
173+ }
174+ TU_ATTR_ALWAYS_INLINE static void * _virt_addr (void * physical_address )
175+ {
176+ if (tuh_get_virt_addr ) return tuh_get_virt_addr (physical_address );
177+ return physical_address ;
178+ }
179+
164180// Initialization according to 5.1.1.4
165181bool hcd_init (uint8_t rhport )
166182{
@@ -170,7 +186,7 @@ bool hcd_init(uint8_t rhport)
170186 tu_memclr (& ohci_data , sizeof (ohci_data_t ));
171187 for (uint8_t i = 0 ; i < 32 ; i ++ )
172188 { // assign all interrupt pointers to period head ed
173- ohci_data .hcca .interrupt_table [i ] = (uint32_t ) & ohci_data .period_head_ed ;
189+ ohci_data .hcca .interrupt_table [i ] = (uint32_t ) _phys_addr ( & ohci_data .period_head_ed ) ;
174190 }
175191
176192 ohci_data .control [0 ].ed .skip = 1 ;
@@ -198,9 +214,9 @@ bool hcd_init(uint8_t rhport)
198214 while ( OHCI_REG -> command_status_bit .controller_reset ) {} // should not take longer than 10 us
199215
200216 //------------- init ohci registers -------------//
201- OHCI_REG -> control_head_ed = (uint32_t ) & ohci_data .control [0 ].ed ;
202- OHCI_REG -> bulk_head_ed = (uint32_t ) & ohci_data .bulk_head_ed ;
203- OHCI_REG -> hcca = (uint32_t ) & ohci_data .hcca ;
217+ OHCI_REG -> control_head_ed = (uint32_t ) _phys_addr ( & ohci_data .control [0 ].ed ) ;
218+ OHCI_REG -> bulk_head_ed = (uint32_t ) _phys_addr ( & ohci_data .bulk_head_ed ) ;
219+ OHCI_REG -> hcca = (uint32_t ) _phys_addr ( & ohci_data .hcca ) ;
204220
205221 OHCI_REG -> interrupt_disable = OHCI_REG -> interrupt_enable ; // disable all interrupts
206222 OHCI_REG -> interrupt_status = OHCI_REG -> interrupt_status ; // clear current set bits
@@ -327,8 +343,8 @@ static void gtd_init(ohci_gtd_t* p_td, uint8_t* data_ptr, uint16_t total_bytes)
327343 p_td -> delay_interrupt = OHCI_INT_ON_COMPLETE_NO ;
328344 p_td -> condition_code = OHCI_CCODE_NOT_ACCESSED ;
329345
330- p_td -> current_buffer_pointer = data_ptr ;
331- p_td -> buffer_end = total_bytes ? (data_ptr + total_bytes - 1 ) : data_ptr ;
346+ p_td -> current_buffer_pointer = _phys_addr ( data_ptr ) ;
347+ p_td -> buffer_end = total_bytes ? (_phys_addr ( data_ptr + total_bytes - 1 )) : ( uint8_t * ) p_td -> current_buffer_pointer ;
332348}
333349
334350static ohci_ed_t * ed_from_addr (uint8_t dev_addr , uint8_t ep_addr )
@@ -364,7 +380,7 @@ static ohci_ed_t * ed_find_free(void)
364380static void ed_list_insert (ohci_ed_t * p_pre , ohci_ed_t * p_ed )
365381{
366382 p_ed -> next = p_pre -> next ;
367- p_pre -> next = (uint32_t ) p_ed ;
383+ p_pre -> next = (uint32_t ) _phys_addr ( p_ed ) ;
368384}
369385
370386static void ed_list_remove_by_addr (ohci_ed_t * p_head , uint8_t dev_addr )
@@ -373,7 +389,7 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr)
373389
374390 while ( p_prev -> next )
375391 {
376- ohci_ed_t * ed = (ohci_ed_t * ) p_prev -> next ;
392+ ohci_ed_t * ed = (ohci_ed_t * ) _virt_addr (( void * ) p_prev -> next ) ;
377393
378394 if (ed -> dev_addr == dev_addr )
379395 {
@@ -384,14 +400,14 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr)
384400 p_prev -> next = ed -> next ;
385401
386402 // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED
387- ed -> next = (uint32_t ) p_head ;
403+ ed -> next = (uint32_t ) _phys_addr ( p_head ) ;
388404 ed -> used = 0 ;
389405 ed -> skip = 0 ;
390406 continue ;
391407 }
392408
393409 // check next valid since we could remove it
394- if (p_prev -> next ) p_prev = (ohci_ed_t * ) p_prev -> next ;
410+ if (p_prev -> next ) p_prev = (ohci_ed_t * ) _virt_addr (( void * ) p_prev -> next ) ;
395411 }
396412}
397413
@@ -410,11 +426,11 @@ static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd)
410426 // tail is always NULL
411427 if ( tu_align16 (p_ed -> td_head .address ) == 0 )
412428 { // TD queue is empty --> head = TD
413- p_ed -> td_head .address |= (uint32_t ) p_gtd ;
429+ p_ed -> td_head .address |= (uint32_t ) _phys_addr ( p_gtd ) ;
414430 }
415431 else
416432 { // TODO currently only support queue up to 2 TD each endpoint at a time
417- ((ohci_gtd_t * ) tu_align16 (p_ed -> td_head .address ))-> next = (uint32_t ) p_gtd ;
433+ ((ohci_gtd_t * ) tu_align16 (( uint32_t ) _virt_addr (( void * ) p_ed -> td_head .address ))) -> next = (uint32_t ) _phys_addr ( p_gtd ) ;
418434 }
419435}
420436
@@ -470,7 +486,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
470486 qtd -> delay_interrupt = 0 ;
471487
472488 //------------- Attach TDs list to Control Endpoint -------------//
473- ed -> td_head .address = (uint32_t ) qtd ;
489+ ed -> td_head .address = (uint32_t ) _phys_addr ( qtd ) ;
474490
475491 OHCI_REG -> command_status_bit .control_list_filled = 1 ;
476492
@@ -496,7 +512,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
496512 gtd -> data_toggle = GTD_DT_DATA1 ; // Both Data and Ack stage start with DATA1
497513 gtd -> delay_interrupt = 0 ;
498514
499- ed -> td_head .address = (uint32_t ) gtd ;
515+ ed -> td_head .address = (uint32_t ) _phys_addr ( gtd ) ;
500516
501517 OHCI_REG -> command_status_bit .control_list_filled = 1 ;
502518 }else
@@ -544,16 +560,17 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head)
544560
545561 while (td_head != NULL )
546562 {
563+ td_head = _virt_addr (td_head );
547564 uint32_t next = td_head -> next ;
548565
549566 // make current's item become reverse's first item
550567 td_head -> next = (uint32_t ) td_reverse_head ;
551- td_reverse_head = td_head ;
568+ td_reverse_head = _phys_addr ( td_head ) ;
552569
553570 td_head = (ohci_td_item_t * ) next ; // advance to next item
554571 }
555572
556- return td_reverse_head ;
573+ return _virt_addr ( td_reverse_head ) ;
557574}
558575
559576static inline bool gtd_is_control (ohci_gtd_t const * const p_qtd )
@@ -624,7 +641,7 @@ static void done_queue_isr(uint8_t hostid)
624641 hcd_event_xfer_complete (ed -> dev_addr , tu_edpt_addr (ed -> ep_number , dir ), xferred_bytes , event , true);
625642 }
626643
627- td_head = (ohci_td_item_t * ) td_head -> next ;
644+ td_head = (ohci_td_item_t * ) _virt_addr (( void * ) td_head -> next ) ;
628645 }
629646}
630647
0 commit comments