1.1 Release
[allwinner_tvout_manipulator.git] / src / devmem2.c
index 7793703..720aab5 100644 (file)
@@ -1,11 +1,13 @@
-/*
- * devmem2.c: Simple program to read/write from/to any location in memory.
- *
- *  Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
- *
- *
- */
-
+///////////////////////////////////////////////////////////////////////////
+// Workfile: devmem2.c (Implementation)
+// Author: Jan-Derk Bakker, Daniel Giritzer
+// Date: 2017-06-02
+// Description: Simple module to read/write from/to any location in memory.
+// Remarks: assumes a 4k page size and that sizeof(unsigned long) == 4
+// Revision: 1.2
+// Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+// Copyright (C) 2017, Daniel Giritzer (giri@nwrk.biz)
+///////////////////////////////////////////////////////////////////////////
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 
-#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
-  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
+#include "devmem2.h"
 
 #define MAP_SIZE 4096UL
 #define MAP_MASK (MAP_SIZE - 1)
 
-void writemem(address, value, int accesstype) {
-    int fd;
-    void *map_base, *virt_addr;
-       unsigned long read_result, writeval;
-       off_t target;
-       int access_type = 'w';
 
-       if(argc < 2) {
-               fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
-                       "\taddress : memory address to act upon\n"
-                       "\ttype    : access operation type : [b]yte, [h]alfword, [w]ord\n"
-                       "\tdata    : data to be written\n\n",
-                       argv[0]);
-               exit(1);
-       }
-       target = strtoul(argv[1], 0, 0);
+/////////////////////////////////////////////////
+/// \brief This function is called by the module
+///        if an error occurs.
+///
+/// \param char* Custom error Message.
+/////////////////////////////////////////////////
+static void ERROR(char* custom)
+{
+    //print custom error message
+    fprintf(stderr, "Error: %s \n", custom);
+
+    //print further information
+    fprintf(stderr, "Info: %d, %s\n",
+            errno, strerror(errno));
+}
 
-       if(argc > 2)
-               access_type = tolower(argv[2][0]);
+/////////////////////////////////////////////////
+/// \brief This function allows writing to memory
+///        on the specified address.
+///
+/// \param unsigned long Address to write to
+/// \param unsigned long Value to write
+/// \param int Access type, should be 'w' (word),
+///        'h' (halfword), 'b'(byte)
+/////////////////////////////////////////////////
+int writemem(unsigned long address, unsigned long writeval, int access_type)
+{
+    int fd;
+    void *map_base = 0;
+    void *virt_addr = 0;
 
+    off_t target = address;
 
-    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
-    printf("/dev/mem opened.\n");
-    fflush(stdout);
+    // Try to open /dev/mem
+    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
+    {
+        ERROR("Opening /dev/mem/ failed!");
+        return EXIT_FAILURE;
+    };
 
-    /* Map one page */
+    // Map one page
     map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
-    if(map_base == (void *) -1) FATAL;
-    printf("Memory mapped at address %p.\n", map_base);
-    fflush(stdout);
 
+    // Check if mapping was successful
+    if(map_base == (void *) -1)
+    {
+        //Print error on failure
+        ERROR("Mapping Memory Page Failed!");
+        return EXIT_FAILURE;
+    }
+
+    //calculate virtual address
     virt_addr = map_base + (target & MAP_MASK);
-    switch(access_type) {
-               case 'b':
-                       read_result = *((unsigned char *) virt_addr);
-                       break;
-               case 'h':
-                       read_result = *((unsigned short *) virt_addr);
-                       break;
-               case 'w':
-                       read_result = *((unsigned long *) virt_addr);
-                       break;
-               default:
-                       fprintf(stderr, "Illegal data type '%c'.\n", access_type);
-                       exit(2);
-       }
-
-       if(argc > 3) {
-               writeval = strtoul(argv[3], 0, 0);
-               switch(access_type) {
-                       case 'b':
-                               *((unsigned char *) virt_addr) = writeval;
-                               read_result = *((unsigned char *) virt_addr);
-                               break;
-                       case 'h':
-                               *((unsigned short *) virt_addr) = writeval;
-                               read_result = *((unsigned short *) virt_addr);
-                               break;
-                       case 'w':
-                               *((unsigned long *) virt_addr) = writeval;
-                               read_result = *((unsigned long *) virt_addr);
-                               break;
-               }
-               printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
-               fflush(stdout);
-       }
-
-       if(munmap(map_base, MAP_SIZE) == -1) FATAL;
+
+    //write value to memory
+    switch(access_type)
+    {
+    case 'b':
+        *((unsigned char *) virt_addr) = writeval;
+        break;
+    case 'h':
+        *((unsigned short *) virt_addr) = writeval;
+        break;
+    case 'w':
+        *((unsigned long *) virt_addr) = writeval;
+        break;
+    default:
+        ERROR("Wrong access_type set!");
+        break;
+    }
+
+    //unmap memory
+    if(munmap(map_base, MAP_SIZE) == -1)
+    {
+        ERROR("Unmapping Memory Page Failed!");
+        return EXIT_FAILURE;
+    }
+
     close(fd);
-    return 0;
+    return EXIT_SUCCESS;
 }
 
-void readmem(address, int accesstype)
+/////////////////////////////////////////////////
+/// \brief This function allows reading the memory
+///        on the specified address.
+///
+/// \param unsigned long Address to read from
+/// \param int Access type, should be 'w' (word),
+///        'h' (halfword), 'b'(byte)
+/// \param unsigned long* pointer result variable
+/////////////////////////////////////////////////
+int readmem(unsigned long address, int access_type, unsigned long *result)
 {
     int fd;
     void *map_base, *virt_addr;
-       unsigned long read_result, writeval;
-       off_t target;
-       int access_type = accesstype;
+    unsigned long read_result = 0;
+
+    off_t target = address;
 
-       target = strtoul(argv[1], 0, 0);
+    //check if result variable is a nullpointer
+    if(result == NULL)
+    {
+        //Print error on failure
+        ERROR("Result Parameter is a nullpointer!");
+        return EXIT_FAILURE;
+    }
 
 
-    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
-    printf("/dev/mem opened.\n");
-    fflush(stdout);
+    // Try to open /dev/mem
+    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
+    {
+        //Print error on failure
+        ERROR("Opening /dev/mem/ failed!");
+        return EXIT_FAILURE;
+    };
 
-    /* Map one page */
+    // Map one page
     map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
-    if(map_base == (void *) -1) FATAL;
-    printf("Memory mapped at address %p.\n", map_base);
-    fflush(stdout);
 
+    // Check if mapping was successful
+    if(map_base == (void *) -1)
+    {
+        ERROR("Mapping Memory Page Failed!");
+        return EXIT_FAILURE;
+    }
+
+    //calculate virtual address
     virt_addr = map_base + (target & MAP_MASK);
-    switch(access_type) {
-               case 'b':
-                       read_result = *((unsigned char *) virt_addr);
-                       break;
-               case 'h':
-                       read_result = *((unsigned short *) virt_addr);
-                       break;
-               case 'w':
-                       read_result = *((unsigned long *) virt_addr);
-                       break;
-               default:
-                       fprintf(stderr, "Illegal data type '%c'.\n", access_type);
-                       exit(2);
-       }
+
+    //read value
+    switch(access_type)
+    {
+    case 'b':
+        read_result = *((unsigned char *) virt_addr);
+        break;
+    case 'h':
+        read_result = *((unsigned short *) virt_addr);
+        break;
+    case 'w':
+        read_result = *((unsigned long *) virt_addr);
+        break;
+    default:
+        ERROR("Wrong access_type set!");
+        break;
+    }
+
+    // unmap memory
+    if(munmap(map_base, MAP_SIZE) == -1)
+    {
+        ERROR("Unmapping Memory Page Failed!");
+        return EXIT_FAILURE;
+    }
+
+    // return result
+    *result = read_result;
+
+    close(fd);
+    return EXIT_SUCCESS;
 }