-------------------------------------------------------------------------------
- Only first configuration can be selected for attached device
- Only one device can be handled at a time, no hub functionality
-- DDEKit does not implement resource deallocation for corresponding thread
- creation (see ddekit_thread_terminate, ddekit_thread_create) thus resources
- are spilled
- Driver assumes that there is no preemption for DDEKit threading
- URBs are enqueued in DDEKit but not in USBD itself
- DDEKit way of handling interface numbers is not explicitly defined, bitmask
formatting for it, is therefore hardcoded into USBD
- Waiting for USB0 clock to leave IDLEST.Disable state, by nanosleep, was
- removed, as this should be implemented for all clocks in clkconf_set
\ No newline at end of file
+ removed, as this should be implemented for all clocks in clkconf_set
+- Control transfers can only be performed with EP0
\ No newline at end of file
* hcd_os_regs_init *
*===========================================================================*/
void *
-hcd_os_regs_init(unsigned long base_addr, unsigned long addr_len)
+hcd_os_regs_init(hcd_addr phys_addr, unsigned long addr_len)
{
/* Memory range where we need privileged access */
struct minix_mem_range mr;
virt_reg_base = NULL;
/* Must have been set before */
- USB_ASSERT(0 != base_addr, "Invalid base address!");
+ USB_ASSERT(0 != phys_addr, "Invalid base address!");
USB_ASSERT(0 != addr_len, "Invalid base length!");
/* Set memory range for peripheral */
- mr.mr_base = base_addr;
- mr.mr_limit = base_addr + addr_len;
+ mr.mr_base = phys_addr;
+ mr.mr_limit = phys_addr + addr_len;
/* Try getting access to memory range */
if (EXIT_SUCCESS == sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr)) {
/* And map it where we want it */
- virt_reg_base = vm_map_phys(SELF, (void *)base_addr, addr_len);
+ virt_reg_base = vm_map_phys(SELF, (void *)phys_addr, addr_len);
/* Check for mapping errors to allow us returning NULL */
if (MAP_FAILED == virt_reg_base) {
* hcd_os_regs_deinit *
*===========================================================================*/
int
-hcd_os_regs_deinit(unsigned long base_addr, unsigned long addr_len)
+hcd_os_regs_deinit(hcd_addr virt_addr, unsigned long addr_len)
{
DEBUG_DUMP;
/* To keep USBD return value convention */
- return (0 == vm_unmap_phys(SELF, (void*)base_addr, addr_len)) ?
+ return (0 == vm_unmap_phys(SELF, (void*)virt_addr, addr_len)) ?
EXIT_SUCCESS : EXIT_FAILURE;
}
hcd_tree_cleanup(&(this_device->config_tree));
- /* TODO: Spilled resources */
- /* DDEKit does no resource deallocation, when terminating thread */
ddekit_thread_terminate(this_device->thread);
ddekit_sem_deinit(this_device->lock);
static void _ddekit_thread_start(ddekit_thread_t *th);
static void _ddekit_thread_sleep(unsigned long until);
+static void _ddekit_dump_queues(void);
/*****************************************************************************
* _ddekit_thread_start *
}
+/*****************************************************************************
+ * _ddekit_dump_queues *
+ ****************************************************************************/
+static void
+_ddekit_dump_queues(void)
+{
+#if DDEBUG >= DDEBUG_VERBOSE
+ ddekit_thread_t * current_thread;
+ int i;
+
+ for (i = 0; i < DDEKIT_THREAD_PRIOS; i++) {
+ current_thread = ready_queue[i];
+
+ ddekit_printf("Ready queue #%d: ", i);
+
+ while (NULL != current_thread) {
+ ddekit_printf("0x%08X ", (int)current_thread);
+ current_thread = current_thread->next;
+ }
+
+ ddekit_printf("\n");
+ }
+
+ {
+ current_thread = sleep_queue;
+
+ ddekit_printf("Sleep queue: ");
+
+ while (NULL != current_thread) {
+ ddekit_printf("0x%08X ", (int)current_thread);
+ current_thread = current_thread->next;
+ }
+
+ ddekit_printf("\n");
+ }
+
+ ddekit_printf("Current thread: 0x%08X\n", (int)current);
+#endif
+}
+
/*****************************************************************************
* DDEKIT public thread API (ddekit/thread.h) *
****************************************************************************/
/*****************************************************************************
* ddekit_thread_terminate *
****************************************************************************/
-void ddekit_thread_terminate(ddekit_thread_t *thread)
+void
+ddekit_thread_terminate(ddekit_thread_t * thread)
{
- /* todo */
+ if (thread == ddekit_thread_myself()) {
+ /* TODO: Whether or not this is an error, is to be decided.
+ * Memory (especially stack) freeing should be somehow
+ * postponed when such termination is legal. */
+ ddekit_panic("Thread attempted termination of itself!\n");
+ }
+
+ _ddekit_thread_dequeue(thread);
+
+ ddekit_sem_deinit(thread->sleep_sem);
+
+ ddekit_simple_free(thread->stack);
+
+ ddekit_simple_free(thread);
}
/*****************************************************************************
****************************************************************************/
void _ddekit_thread_enqueue(ddekit_thread_t *th)
{
-
- DDEBUG_MSG_VERBOSE("enqueueing thread: id: %d name %s, prio: %d",
- th->id, th->name, th->prio);
+ DDEBUG_MSG_VERBOSE("Enqueuing thread 0x%08X: id %d, name %s, prio %d",
+ (int)th, th->id, th->name, th->prio);
#if DDEBUG >= 4
_ddekit_print_backtrace(th);
}
}
+/*****************************************************************************
+ * _ddekit_thread_dequeue *
+ ****************************************************************************/
+void
+_ddekit_thread_dequeue(ddekit_thread_t * th)
+{
+ ddekit_thread_t * current_thread;
+ ddekit_thread_t * previous_thread;
+
+ DDEBUG_MSG_VERBOSE("Dequeuing thread 0x%08X: id %d, name %s, prio %d",
+ (int)th, th->id, th->name, th->prio);
+
+ ddekit_assert((th->prio < DDEKIT_THREAD_PRIOS) && (th->prio >= 0));
+
+ /* Dump queues when debugging */
+ _ddekit_dump_queues();
+
+ /* Check ready queue (based on thread's priority) for thread */
+ current_thread = ready_queue[th->prio];
+ previous_thread = NULL;
+
+ while (NULL != current_thread) {
+
+ /* On match... */
+ if (th == current_thread) {
+
+ if (previous_thread) {
+ /* ...fix previous element to remove current */
+ previous_thread->next = current_thread->next;
+ } else {
+ /* ...alter queue start to reflect removal */
+ ready_queue[th->prio] = current_thread->next;
+ }
+
+ /* Thread found and dequeued */
+ DDEBUG_MSG_VERBOSE("Dequeued 'ready[%d]': 0x%08X",
+ th->prio, (int)th);
+ return;
+ }
+
+ /* Next thread */
+ previous_thread = current_thread;
+ current_thread = current_thread->next;
+ }
+
+ /* When previous loop fails, check if thread is sleeping */
+ current_thread = sleep_queue;
+ previous_thread = NULL;
+
+ while (NULL != current_thread) {
+
+ /* On match... */
+ if (th == current_thread) {
+
+ if (previous_thread) {
+ /* ...fix previous element to remove current */
+ previous_thread->next = current_thread->next;
+ } else {
+ /* ...alter queue start to reflect removal */
+ sleep_queue = current_thread->next;
+ }
+
+ /* Thread found and dequeued */
+ DDEBUG_MSG_VERBOSE("Dequeued 'sleep': 0x%08X", (int)th);
+ return;
+ }
+
+ /* Next thread */
+ previous_thread = current_thread;
+ current_thread = current_thread->next;
+ }
+
+ /* Thread may exist and not be enqueued at
+ * all (is bound to semaphore for instance) */
+ DDEBUG_MSG_VERBOSE("Thread 0x%08X was not enqueued!", (int)th);
+}
+
/*****************************************************************************
* _ddekit_thread_set_myprio *
****************************************************************************/