extern struct gimage lena_image;
// XXX: you need to have this functions in user space...
-lvaddr_t paging_map_device(lpaddr_t base, size_t size);
-lpaddr_t bsp_alloc_phys(size_t);
// not sure about these two, tough
//void cp15_invalidate_tlb(void);
//void cp15_invalidate_i_and_d_caches(void);
+static lpaddr_t* vbase_glbl;
+
static void manage_clocks(void)
{
printf("Enable the clocks in domain CD_CAM\n");
// Clock domain CAM
- lvaddr_t vbase = paging_map_device(0x4A000000, 4096);
- uint32_t offset = (0x4A009000 & ARM_L1_SECTION_MASK);
+ lvaddr_t* vbase;
+ errval_t err;
+ err = map_device_register(0x4A009000, 4096, &vbase);
+ assert(err_is_ok(err));
+ FDIF_DEBUG("vbase points to %p\n", vbase);
- omap44xx_cam_cm2_initialize(&devclk, (mackerel_addr_t)vbase+offset);
+ omap44xx_cam_cm2_initialize(&devclk, (mackerel_addr_t)vbase);
//omap44xx_cam_cm2_pm_cam_pwrstctrl_powerstate_wrf(&dev, omap44xx_cam_prm_POWERSTATE_2);
omap44xx_cam_cm2_cm_cam_clkstctrl_clktrctrl_wrf(&devclk, 0x2);
omap44xx_cam_cm2_cm_cam_fdif_clkctrl_modulemode_wrf(&devclk, 0x2);
//omap44xx_cam_cm2_cm_cam_staticdep_memif_statdep_wrf(&devclk, 0x1);
//omap44xx_cam_cm2_cm_cam_staticdep_ivahd_statdep_wrf(&devclk, 0x1);
- omap44xx_cam_cm2_pr(printbuf, PRINT_BUFFER_SIZE, &devclk);
- printf("%s\n", printbuf);
+ //omap44xx_cam_cm2_pr(printbuf, PRINT_BUFFER_SIZE, &devclk);
+ //printf("%s\n", printbuf);
printf("Handle voltage for domain: VDD_CORE_L\n");
//omap44xx_sr_mpu_srstatus_pr(printbuf, PRINT_BUFFER_SIZE-1, &devvolt);
//printf("%s\n", printbuf);
- vbase = paging_map_device(0x4A307B00, 4096);
- offset = (0x4A307B00 & ARM_L1_SECTION_MASK);
- omap44xx_device_prm_initialize(&devprm, (mackerel_addr_t)vbase+offset);
- omap44xx_device_prm_pr(printbuf, PRINT_BUFFER_SIZE, &devprm);
- printf("%s\n", printbuf);
+ err = map_device_register(0x4A307000, 4096, &vbase_glbl);
+ assert(err_is_ok(err));
+ lpaddr_t offset = (0x4A307B00 & 0xFFF);
+ omap44xx_device_prm_initialize(&devprm, (mackerel_addr_t)vbase_glbl+offset);
+ //omap44xx_device_prm_pr(printbuf, PRINT_BUFFER_SIZE, &devprm);
+ //printf("%s\n", printbuf);
// Init voltage controller
-
-
printf("Done handling voltage\n");
}
printf("Power-on the PD_CAM domain for fdif\n");
// Power domain CAM
- lvaddr_t vbase = paging_map_device(0x4A307000, 4096);
- uint32_t offset = (0x4A307000 & ARM_L1_SECTION_MASK);
+ lvaddr_t* vbase;
+ errval_t err;
+ err = map_device_register(0x4A307000, 4096, &vbase);
+ assert(err_is_ok(err));
- omap44xx_cam_prm_initialize(&dev, (mackerel_addr_t)vbase+offset);
+ omap44xx_cam_prm_initialize(&dev, (mackerel_addr_t)vbase);
omap44xx_cam_prm_pm_cam_pwrstctrl_powerstate_wrf(&dev, omap44xx_cam_prm_POWERSTATE_3);
while(omap44xx_cam_prm_pm_cam_pwrstst_powerstatest_rdf(&dev)
!= omap44xx_cam_prm_POWERSTATEST_3_r)
{}
- omap44xx_cam_prm_pr(printbuf, PRINT_BUFFER_SIZE, &dev);
- printf("%s\n", printbuf);
+ //omap44xx_cam_prm_pr(printbuf, PRINT_BUFFER_SIZE, &dev);
+ //printf("%s\n", printbuf);
// Face detect Module
- vbase = paging_map_device(0x4A10A000, 4096);
- offset = (0x4A10A000 & ARM_L1_SECTION_MASK);
+ err = map_device_register(0x4A10A000, 4096, &vbase);
+ assert(err_is_ok(err));
- omap44xx_fdif_initialize(&devfdif, (mackerel_addr_t)vbase+offset);
+ omap44xx_fdif_initialize(&devfdif, (mackerel_addr_t)vbase);
// Set this to 0x1 to force the device off the standby mode
omap44xx_fdif_fdif_sysconfig_standbymode_wrf(&devfdif, 0x2);
}
-void play_with_fdif(void) {
+int main(void) {
+ init_memory_manager();
+
manage_clocks();
manage_power();
//manage_voltage();
size_t img_size = 320*240*8; // 75 KB
size_t working_size = img_size; // 51.25 KB is enough
- volatile uint8_t* image = (void*)bsp_alloc_phys(img_size);
- void* workarea = (void*)bsp_alloc_phys(working_size);
- assert (image != NULL && workarea != NULL);
+ size_t retbytes;
+ void* workarea;
+ uint8_t* image;
+ errval_t err;
+
+ struct capref img_cap;
+ struct capref workarea_cap;
+
+ err = frame_alloc(&img_cap, img_size, &retbytes);
+ assert(err_is_ok(err));
+ assert(retbytes >= img_size);
+
+ err = frame_alloc(&workarea_cap, working_size, &retbytes);
+ assert(err_is_ok(err));
+ assert(retbytes >= working_size);
+
+ err = vspace_map_one_frame((void**)&image, img_size, img_cap,
+ NULL, NULL);
+ assert(err_is_ok(err));
+ err = vspace_map_one_frame(&workarea, working_size, workarea_cap,
+ NULL, NULL);
+ assert(err_is_ok(err));
printf("Set up the image ...\n");
printf("RGB image type: width:%d height:%d bytes/pixel:%d\n", lena_image.width, lena_image.height, lena_image.bytes_per_pixel);
-
printf("Convert to grayscale, store in image buffer...\n");
for (int i=0; i<lena_image.width*lena_image.height; i+=1) {
// Does this do cache to mem writeback?
//cp15_invalidate_tlb();
//cp15_invalidate_i_and_d_caches();
-
- omap44xx_fdif_fdif_picaddr_wr(&devfdif, (uint32_t)image); // make sure 5 least significant bits are 0!
- omap44xx_fdif_fdif_wkaddr_wr(&devfdif, (uint32_t)workarea); // make sure 5 least significant bits are 0!
+ struct frame_identity ret;
+ err = invoke_frame_identify(img_cap, &ret);
+ assert (err_is_ok(err));
+ omap44xx_fdif_fdif_picaddr_wr(&devfdif, ret.base); // make sure 5 least significant bits are 0!
+
+ err = invoke_frame_identify(workarea_cap, &ret);
+ assert (err_is_ok(err));
+ omap44xx_fdif_fdif_wkaddr_wr(&devfdif, ret.base); // make sure 5 least significant bits are 0!
omap44xx_fdif_fd_dcond_min_wrf(&devfdif, 0x0); // 40 pixel
omap44xx_fdif_fd_dcond_dir_wrf(&devfdif, 0x0); // up?
printf("Size: %d Confidence: %d Angle: %d\n", size, confidence, angle);
}
+ return 0;
}
--- /dev/null
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/capabilities.h>
+#include <barrelfish/nameservice_client.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mm/mm.h>
+#include <if/monitor_blocking_rpcclient_defs.h>
+
+#include "fdif.h"
+
+#define UNBITS_GENPA(bits) (((genpaddr_t)1) << (bits))
+
+static struct mm register_manager;
+
+/**
+ * \brief Maps a physical register location into virtual address space
+ *
+ * \param[in] address Physical address of register you want to map.
+ * \param[in] size Size of register space to map
+ * \param[out] return_address Virtual address where the register is mapped at.
+ *
+ * \retval SYS_ERR_OK return_address is valid and mapped.
+ **/
+errval_t map_device_register(lpaddr_t address, size_t size, lvaddr_t** return_address)
+{
+ struct allocated_range {
+ struct capref cr;
+ struct frame_identity id;
+ struct allocated_range* next;
+ };
+ static struct allocated_range* allocation_head = NULL;
+
+ FDIF_DEBUG("map_device_register: %"PRIxLPADDR" %zu %zu\n", address, size, log2ceil(size));
+
+ assert(address != 0);
+ assert(return_address != NULL);
+ // TODO(gz) the paging in the kernel wants these two preconditions?
+ assert(size % BASE_PAGE_SIZE == 0);
+ assert(size >= BASE_PAGE_SIZE && "ARM paging breaks when smaller");
+
+ bool insert = true;
+ struct capref devframe = NULL_CAP;
+ errval_t err = mm_alloc_range(®ister_manager, log2ceil(size),
+ address, address+size,
+ &devframe, NULL);
+ if (err_is_fail(err)) {
+ // TODO(gz) Is there a better way to handle duplicated allocations?
+ FDIF_DEBUG("mm_alloc_range failed.\n");
+ FDIF_DEBUG("Do we already have an allocation that covers this range?\n");
+ struct allocated_range* iter = allocation_head;
+ while (iter != NULL) {
+ if (address >= iter->id.base &&
+ (address + size <= (iter->id.base + UNBITS_GENPA(iter->id.bits)))) {
+ FDIF_DEBUG("Apparently, yes. We try to map that one.\n");
+ devframe = iter->cr;
+ insert = false;
+ goto map_it; // yay, recovered!
+ }
+ iter = iter->next;
+ }
+ // One way out of here might be to re-try with
+ // a bigger maxlimit?
+ DEBUG_ERR(err, "mm_alloc_range failed.\n");
+ return err;
+ }
+
+map_it:
+ err = vspace_map_one_frame_attr((void**)return_address, size,
+ devframe, VREGION_FLAGS_READ_WRITE_NOCACHE,
+ NULL, NULL);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "vspace_map_one_frame_attr failed.\n");
+ return err;
+ }
+
+ if (insert) {
+ struct allocated_range* ar = calloc(sizeof(struct allocated_range), 1);
+ ar->cr = devframe;
+ err = invoke_frame_identify(ar->cr, &ar->id);
+ if (err_is_fail(err)) {
+ free(ar);
+ DEBUG_ERR(err, "frame identity failed.\n");
+ return err;
+ }
+ // Insert into the queue to track the allocation
+ struct allocated_range** iter = &allocation_head;
+ while(*iter != NULL) {
+ iter = &(*iter)->next;
+ }
+ *iter = ar;
+ }
+
+ return SYS_ERR_OK;
+}
+
+errval_t init_memory_manager(void)
+{
+ FDIF_DEBUG("init_memory_manager\n");
+ errval_t err, error_code;
+
+ // Request I/O Cap
+ struct monitor_blocking_rpc_client *cl = get_monitor_blocking_rpc_client();
+ assert(cl != NULL);
+
+ struct capref requested_cap;
+ err = cl->vtbl.get_io_cap(cl, &requested_cap, &error_code);
+ assert(err_is_ok(err) && err_is_ok(error_code));
+
+ // Initialize the memory allocator to handle PhysAddr caps
+ static struct range_slot_allocator devframes_allocator;
+ err = range_slot_alloc_init(&devframes_allocator, 2048, NULL);
+ if (err_is_fail(err)) {
+ return err_push(err, LIB_ERR_SLOT_ALLOC_INIT);
+ }
+
+ struct frame_identity ret;
+ err = invoke_frame_identify(requested_cap, &ret);
+ assert (err_is_ok(err));
+
+ err = mm_init(®ister_manager, ObjType_DevFrame, ret.base, ret.bits,
+ 1, slab_default_refill, slot_alloc_dynamic,
+ &devframes_allocator, false);
+ if (err_is_fail(err)) {
+ return err_push(err, MM_ERR_MM_INIT);
+ }
+
+ err = mm_add(®ister_manager, requested_cap,
+ 30, 0x40000000);
+ assert(err_is_ok(err));
+
+ FDIF_DEBUG("init_memory_manager DONE\n");
+ return SYS_ERR_OK;
+}
\ No newline at end of file