FDIF functioning as a user level driver.
authorGerd Zellweger <mail@gerdzellweger.com>
Thu, 4 Jul 2013 09:53:57 +0000 (11:53 +0200)
committerGerd Zellweger <mail@gerdzellweger.com>
Tue, 16 Jul 2013 12:55:01 +0000 (14:55 +0200)
kernel/arch/omap44xx/paging.c
usr/drivers/omap44xx/fdif/Hakefile
usr/drivers/omap44xx/fdif/fdif.c
usr/drivers/omap44xx/fdif/fdif.h
usr/drivers/omap44xx/fdif/omap_startup.c [new file with mode: 0644]

index e5473dc..fbe993a 100644 (file)
@@ -381,19 +381,19 @@ caps_map_l2(struct capability* dest,
     // ARM L2 has 256 entries, but we treat a 4K page as a consecutive
     // region of L2 with a single index. 4K == 4 * 1K
     if (slot >= (256 * 4)) {
-        panic("oops");
+        panic("oops: slot >= (256 * 4)");
         return SYS_ERR_VNODE_SLOT_INVALID;
     }
 
     if (src->type != ObjType_Frame && src->type != ObjType_DevFrame) {
-        panic("oops");
+        panic("oops: src->type != ObjType_Frame && src->type != ObjType_DevFrame");
         return SYS_ERR_WRONG_MAPPING;
     }
 
     // check offset within frame
     if ((offset + BYTES_PER_PAGE > get_size(src)) ||
         ((offset % BYTES_PER_PAGE) != 0)) {
-        panic("oops");
+        panic("oops: frame offset invalid");
         return SYS_ERR_FRAME_OFFSET_INVALID;
     }
 
index 41e509f..c84bbfb 100644 (file)
 --------------------------------------------------------------------------
 
 [
-    build library { target = "fdif",
+    build application { target = "fdif",
                     cFiles = (find withSuffices [".c"]),
                     mackerelDevices = [
                         "omap/omap44xx_cam_prm",
                         "omap/omap44xx_cam_cm2",
                         "omap/omap44xx_sr_mpu",
                         "omap/omap44xx_fdif",
-                        "omap/omap44xx_device_prm" ] 
+                        "omap/omap44xx_device_prm" ],
+                    addLibraries = ["mm"]
                   }
 ]
\ No newline at end of file
index 929dbc0..4e3e035 100644 (file)
@@ -23,21 +23,24 @@ static omap44xx_device_prm_t devprm;
 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);
@@ -50,8 +53,8 @@ static void manage_clocks(void)
     //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");
@@ -62,15 +65,14 @@ static void manage_clocks(void)
     //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");
 }
 
@@ -79,24 +81,26 @@ static void manage_power(void)
     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);
@@ -109,7 +113,9 @@ static void manage_power(void)
 
 }
 
-void play_with_fdif(void) {
+int main(void) {
+    init_memory_manager();
+
     manage_clocks();
     manage_power();
     //manage_voltage();
@@ -129,13 +135,31 @@ void play_with_fdif(void) {
 
     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) {
@@ -148,9 +172,14 @@ void play_with_fdif(void) {
     // 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?
@@ -186,4 +215,5 @@ void play_with_fdif(void) {
         printf("Size: %d Confidence: %d Angle: %d\n", size, confidence, angle);
     }
 
+    return 0;
 }
index 78363bc..95fb1f5 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef FDIF_H_
+#define FDIF_H_
+
 #include <barrelfish/barrelfish.h>
 
 void play_with_fdif(void);
@@ -8,3 +11,10 @@ struct gimage {
   uint32_t       bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ 
   uint8_t    pixel_data[320 * 240];
 };
+
+errval_t map_device_register(lpaddr_t address, size_t size, lvaddr_t** return_address) ;
+errval_t init_memory_manager(void);
+
+#define FDIF_DEBUG(x...) printf("fdif: " x)
+
+#endif // FDIF_H_
\ No newline at end of file
diff --git a/usr/drivers/omap44xx/fdif/omap_startup.c b/usr/drivers/omap44xx/fdif/omap_startup.c
new file mode 100644 (file)
index 0000000..deae11a
--- /dev/null
@@ -0,0 +1,134 @@
+#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(&register_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(&register_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(&register_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