/*@only@*//*@null@*/wwd_result_t wwd_bus_read_frame( wiced_buffer_t* buffer ) { uint32_t intstatus; void *p0 = NULL; uint16_t *hwtag; intstatus = read_intstatus(); /* Handle DMA interrupts */ if (intstatus & I_XI) { dma_tx_reclaim(); } if ( rxactive_dma( ) == 0 ) { refill_dma( ); if ( rxactive_dma( ) != 0 ) { int_enab(); } } /* Handle DMA errors */ if (intstatus & I_ERRORS) { refill_dma( ); WPRINT_WWD_DEBUG(("RX errors: intstatus: 0x%x\n", (unsigned int)intstatus)); } /* Handle DMA receive interrupt */ p0 = read_dma_packet( &hwtag ); if ( p0 == NULL) { if ( rxactive_dma( ) != 0 ) { int_enab(); } return WWD_NO_PACKET_TO_RECEIVE; } *buffer = p0; host_buffer_add_remove_at_front( buffer, - (int)sizeof(wwd_buffer_header_t) ); wwd_sdpcm_update_credit((uint8_t*)hwtag); refill_dma( ); /* where are buffers from dma_rx and dma_getnextrxp created? */ return WWD_SUCCESS; }
wwd_result_t wwd_process_clm_data(void) { wwd_result_t ret = WWD_SUCCESS; uint32_t clm_blob_size; uint32_t datalen; unsigned int size2alloc, data_offset; unsigned char *chunk_buf; uint16_t dl_flag = DL_BEGIN; unsigned int cumulative_len = 0; unsigned int chunk_len; uint32_t size_read; /* clm file size is the initial datalen value which is decremented */ clm_blob_size = resource_get_size( &wifi_firmware_clm_blob ); datalen = clm_blob_size; data_offset = offsetof(wl_dload_data_t, data); size2alloc = data_offset + MAX_CHUNK_LEN; if ((chunk_buf = (unsigned char *)malloc(size2alloc)) != NULL) { memset(chunk_buf, 0, size2alloc); do { if (datalen >= MAX_CHUNK_LEN) chunk_len = MAX_CHUNK_LEN; else chunk_len = datalen; // check size_read is full value also and resource read return if ((ret = resource_read(&wifi_firmware_clm_blob, cumulative_len, chunk_len, &size_read, chunk_buf + data_offset)) != WWD_SUCCESS) { break; } if (size_read != chunk_len) { wiced_assert("During CLM download, resource_read() returned less of the file than should be available\n", 1 == 0); ret = WWD_CLM_BLOB_DLOAD_ERROR; break; } cumulative_len += chunk_len; if (datalen - chunk_len == 0) dl_flag |= DL_END; ret = wwd_download2dongle(WWD_STA_INTERFACE, IOVAR_STR_CLMLOAD, dl_flag, DL_TYPE_CLM, chunk_buf, data_offset + chunk_len); dl_flag &= (uint16_t)~DL_BEGIN; datalen = datalen - chunk_len; } while ((datalen > 0) && (ret == WWD_SUCCESS)); free(chunk_buf); if ( ret != WWD_SUCCESS ) { wwd_result_t ret_clmload_status; wiced_buffer_t buffer; wiced_buffer_t response; void *data; WPRINT_WWD_DEBUG(("clmload (%ld byte file) failed with return %d; ", clm_blob_size, ret)); data = (int*)wwd_sdpcm_get_iovar_buffer( &buffer, 4, IOVAR_STR_CLMLOAD_STATUS ); CHECK_IOCTL_BUFFER( data ); ret_clmload_status = wwd_sdpcm_send_iovar( SDPCM_GET, buffer, &response, WWD_STA_INTERFACE ); if ( ret_clmload_status != WWD_SUCCESS ) { WPRINT_WWD_DEBUG(("clmload_status failed with return %d\n", ret_clmload_status)); } else { uint32_t *clmload_status = (uint32_t *)host_buffer_get_current_piece_data_pointer( response ); if ( clmload_status != NULL ) { WPRINT_WWD_DEBUG(("clmload_status is %lu\n", *clmload_status)); host_buffer_release( response, WWD_NETWORK_RX ); } } } } else { ret = WWD_MALLOC_FAILURE; } return ret; }
/** The WWD Thread function * * This is the main loop of the WWD Thread. * It simply calls @ref wwd_thread_poll_all to send/receive all waiting packets, then goes * to sleep. The sleep has a 100ms timeout, causing the send/receive queues to be * checked 10 times per second in case an interrupt is missed. * Once the quit flag has been set, flags/mutexes are cleaned up, and the function exits. * * @param thread_input : unused parameter needed to match thread prototype. * */ static void wwd_thread_func( wwd_thread_arg_t /*@unused@*/thread_input ) /*@globals killed wwd_transceive_semaphore@*/ /*@modifies wwd_wlan_status, wwd_bus_interrupt, wwd_thread_quit_flag, wwd_inited, wwd_thread@*/ { int8_t rx_status; int8_t tx_status; wwd_result_t wwd_result; UNUSED_PARAMETER(thread_input); WWD_LOG(("Started Wiced Thread\n")); /* Interrupts may be enabled inside thread. To make sure none lost set flag now. */ wwd_inited = WICED_TRUE; while ( wwd_thread_quit_flag != WICED_TRUE ) { /* If was in deep sleep and needs wakeup, then wake first */ if ( WICED_TRUE == wwd_wifi_ds1_needs_wake( ) ) { wwd_result = wwd_wifi_ds1_finish_wake( ); if ( WWD_SUCCESS != wwd_result ) { WPRINT_WWD_ERROR(("Err %d:Unable to do ds1 wake", wwd_result)); } } /* Check if we were woken by interrupt */ if ( ( wwd_bus_interrupt == WICED_TRUE ) || ( WWD_BUS_USE_STATUS_REPORT_SCHEME ) ) { wwd_bus_interrupt = WICED_FALSE; /* Check if the interrupt indicated there is a packet to read */ if ( wwd_bus_packet_available_to_read( ) != 0) { /* Receive all available packets */ do { rx_status = wwd_thread_receive_one_packet( ); } while ( rx_status != 0 ); } } /* Send all queued packets */ do { tx_status = wwd_thread_send_one_packet( ); } while (tx_status != 0); /* Sleep till WLAN do something */ wwd_wait_for_wlan_event( &wwd_transceive_semaphore ); WWD_LOG(("Wiced Thread: Woke\n")); } /* Set flag before releasing objects */ wwd_inited = WICED_FALSE; /* Reset the quit flag */ wwd_thread_quit_flag = WICED_FALSE; /* Delete the semaphore */ (void) host_rtos_deinit_semaphore( &wwd_transceive_semaphore ); /* Ignore return - not much can be done about failure */ wwd_sdpcm_quit( ); WWD_LOG(("Stopped Wiced Thread\n")); if ( WWD_SUCCESS != host_rtos_finish_thread( &wwd_thread ) ) { WPRINT_WWD_DEBUG(("Could not close WWD thread\n")); } }