Skip to content

Commit f2a6af0

Browse files
committed
ohci: Add ability to separate physical and virtual memory
1 parent f872621 commit f2a6af0

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

src/portable/ohci/ohci.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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
165181
bool 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

334350
static 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)
364380
static 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

370386
static 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

559576
static 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

Comments
 (0)