symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py
branchnvmemory
changeset 74 eb3d0111f868
child 93 07b904f40417
equal deleted inserted replaced
73:b6aa150091ee 74:eb3d0111f868
       
     1 #
       
     2 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: syborg_nvmemorydevice.py
       
    15 # A simple non volatile memory device nvmemory.dll python wrapper
       
    16 # Represents a non volatile memory device register interface for quest OS in QEMU Syborg environment.
       
    17 #
       
    18 # Gets the following from devicetree (.dtb configuration file) 
       
    19 #       drive_size - the size of the non volatile memory array to be created if there is no such thing available when the system is started
       
    20 #       sector_size - the size of the sector for the memory device
       
    21 #       drive_image_name - the name of the image to be used
       
    22 #
       
    23 # Creates an empty image of specified size and name if there is not image available when the system is started
       
    24 #
       
    25 
       
    26 import ctypes
       
    27 import qemu
       
    28 import sys
       
    29 import os
       
    30 import array
       
    31 
       
    32 class syborg_nvmemorydevice(qemu.devclass):
       
    33     # 256 MB default empty drive size if there is no readymade image available
       
    34     DEFAULT_DRIVE_SIZE = 0x10000000
       
    35     DEVICE_SECTOR_SIZE = 0x200
       
    36     DRIVE_NAME = "qemudrive.img"
       
    37     DRIVE_PATH = "nvmemory"
       
    38     
       
    39     # Memory device registers
       
    40     R_NVMEM_ID                                = 0x0000
       
    41     R_NVMEM_TRANSACTION_OFFSET                = 0x0004
       
    42     R_NVMEM_TRANSACTION_SIZE                  = 0x0008
       
    43     R_NVMEM_TRANSACTION_DIRECTION             = 0x000c
       
    44     R_NVMEM_TRANSACTION_EXECUTE               = 0x0010
       
    45     R_NVMEM_SHARED_MEMORY_BASE                = 0x0014
       
    46     R_NVMEM_NV_MEMORY_SIZE                    = 0x0018
       
    47     R_NVMEM_SHARED_MEMORY_SIZE                = 0x001c
       
    48     R_NVMEM_STATUS                            = 0x0020
       
    49     R_NVMEM_ENABLE                            = 0x0024
       
    50     R_NVMEM_LASTREG                           = 0x0028  # not a register, address of last register
       
    51     
       
    52     NVMEM_TRANSACTION_READ              = 1
       
    53     NVMEM_TRANSACTION_WRITE             = 2
       
    54     # Variables to store the information for current transaction
       
    55     shared_memory_base                  = 0
       
    56     shared_memory_size                  = 0
       
    57     transaction_offset                  = 0
       
    58     transaction_size                    = 0
       
    59     transaction_direction               = 0
       
    60     # Variables to validate transaction
       
    61     transaction_offset_set              = 0
       
    62     transaction_size_set                = 0
       
    63     transaction_direction_set           = 0
       
    64     nvmemory_sector_count                = 0
       
    65     
       
    66     drive_size                          = 0
       
    67     sector_size                         = 0
       
    68     drive_image_name                    = ""
       
    69 
       
    70     def create(self):
       
    71         print "syborg_nvmemorydevice: create\n"
       
    72         
       
    73         # Get properties
       
    74         self.drive_size = self.properties["drive_size"]
       
    75         self.sector_size = self.properties["sector_size"]
       
    76         self.drive_image_name = self.properties["drive_image_name"]
       
    77         
       
    78         print "drive size: ", self.drive_size
       
    79         print "sector size: ", self.sector_size
       
    80         print "drive name: ", self.drive_image_name
       
    81 
       
    82         drive_path_and_name = self.DRIVE_PATH + "\\" + self.drive_image_name 
       
    83         # Save working directory
       
    84         self.working_dir = os.getcwd()
       
    85         
       
    86         # Open the nvmemory library
       
    87         try:
       
    88             self.nvmemlib = ctypes.CDLL("nvmemmory.dll")
       
    89         except:
       
    90             sys.exit("syborg_nvmemorydevice: nvmemmory.dll load failed")
       
    91         
       
    92         # Create an instance of non volatile memory handler class
       
    93         self.obj = self.nvmemlib.nvmem_create( self.sector_size )
       
    94         self.nvmemlib.nvmem_reset( self.obj )
       
    95         
       
    96         # Create drive image path
       
    97         try:
       
    98             print "syborg_nvmemorydevice: Check drive image path\n"
       
    99             os.mkdir( self.DRIVE_PATH )
       
   100         except:
       
   101             # Here we could check why we failed - usually because the path already exists \n"
       
   102             pass
       
   103         try:
       
   104             self.filehandle = os.open( drive_path_and_name, os.O_RDWR|os.O_BINARY )
       
   105             os.close( self.filehandle )
       
   106         except:
       
   107             print "syborg_nvmemorydevice: drive image not found - create\n"
       
   108             self.filehandle = open( drive_path_and_name, "wb" )
       
   109             # Initialize file with zeroes. This may take a while
       
   110             temparray = array.array("B", [0,0,0,0,0,0,0,0])
       
   111             arraylength = temparray.buffer_info()[1] * temparray.itemsize
       
   112             multiplier = self.drive_size / arraylength / 128
       
   113             temparray = temparray * multiplier
       
   114             arraylength = temparray.buffer_info()[1] * temparray.itemsize
       
   115             print "array length: ", arraylength
       
   116             index = 0
       
   117             while index < 128:
       
   118                 temparray.tofile(self.filehandle)
       
   119                 index = index+1
       
   120         
       
   121         # Create path and get handle to the raw memory array
       
   122         imagepath = self.working_dir + "\\" + drive_path_and_name
       
   123         print "imagepath: ", imagepath
       
   124         self.nvmemhandle = self.nvmemlib.nvmem_open( self.obj, imagepath )
       
   125         if( self.nvmemhandle < 0 ):
       
   126             error_msg = "syborg_nvmemorydevice: nvmem_open error: ", self.nvmemhandle
       
   127             sys.exit( error_msg )
       
   128         
       
   129         # Initialize callback and get memory sector count
       
   130         self.initialize_nvmem_callback()
       
   131         self.nvmemory_sector_count = self.nvmemlib.nvmem_get_sector_count( self.obj, self.nvmemhandle )
       
   132         print "syborg_nvmemorydevice: created\n"
       
   133             
       
   134     def updateIrq(self,new_value):
       
   135         self.set_irq_level(0, new_value)
       
   136 
       
   137     def nvmem_request_callback(self, result):
       
   138         #print "graphics_request_callback: " , result
       
   139         self.status_reg = result
       
   140         self.updateIrq(1)
       
   141         return 0
       
   142         
       
   143     def initialize_nvmem_callback(self):
       
   144         self.CALLBACKFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
       
   145         self.nvmem_callback = self.CALLBACKFUNC(self.nvmem_request_callback)
       
   146         self.nvmemlib.nvmem_set_callback( self.obj, self.nvmem_callback )
       
   147 
       
   148     def read_reg(self, offset):
       
   149         offset >>= 2
       
   150         #print "read register: 0x%x" % (offset) 
       
   151         if offset == self.R_NVMEM_ID:
       
   152             return 0xDEADBEEF
       
   153         elif offset == self.R_NVMEM_TRANSACTION_OFFSET:
       
   154             return self.transaction_offset
       
   155         elif offset == self.R_NVMEM_TRANSACTION_SIZE:
       
   156             return self.transaction_size
       
   157         elif offset == self.R_NVMEM_TRANSACTION_DIRECTION:
       
   158             return self.transaction_direction
       
   159         elif offset == self.R_NVMEM_SHARED_MEMORY_BASE:
       
   160             return self.shared_memory_base
       
   161         elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE:
       
   162             return self.shared_memory_size
       
   163         elif offset == self.R_NVMEM_NV_MEMORY_SIZE:
       
   164             return self.nvmemory_sector_count
       
   165         elif offset == self.R_NVMEM_STATUS:
       
   166             self.updateIrq(0)
       
   167             return self.status_reg
       
   168         else:
       
   169             reg_read_error = "syborg_nvmemorydevice: Illegal register read at: ", offset 
       
   170             sys.exit( reg_read_error )
       
   171 
       
   172     def write_reg(self, offset, value):
       
   173         offset >>= 2
       
   174         #print "write register: 0x%x value: 0x%x" % (offset, value) 
       
   175         if offset == self.R_NVMEM_TRANSACTION_OFFSET:
       
   176             self.transaction_offset = value
       
   177             self.transaction_offset_set = 1
       
   178         elif offset == self.R_NVMEM_TRANSACTION_SIZE:
       
   179             self.transaction_size = value
       
   180             self.transaction_size_set = 1
       
   181         elif offset == self.R_NVMEM_TRANSACTION_DIRECTION:
       
   182             self.transaction_direction = value
       
   183             self.transaction_direction_set = 1
       
   184         elif offset == self.R_NVMEM_TRANSACTION_EXECUTE:
       
   185             if( (self.transaction_offset_set == 0) | (self.transaction_size_set == 0) | (self.transaction_direction_set == 0) ):
       
   186                 error_msg = "syborg_nvmemorydevice: Illegal transaction! All the required parameters are not set" 
       
   187                 sys.exit( error_msg )
       
   188             elif(self.transaction_size == 0 ):
       
   189                 error_msg = "syborg_nvmemorydevice: Zero size transaction issued!" 
       
   190                 sys.exit( error_msg )
       
   191             else:
       
   192                 if( self.transaction_direction == self.NVMEM_TRANSACTION_READ ):
       
   193                     self.nvmemlib.nvmem_read(  self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size )
       
   194                 elif( self.transaction_direction == self.NVMEM_TRANSACTION_WRITE ):
       
   195                     self.nvmemlib.nvmem_write(  self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size )
       
   196                 else:
       
   197                     error_msg = "syborg_nvmemorydevice: Transaction direction not set!" 
       
   198                     sys.exit( error_msg )
       
   199                 self.transaction_offset_set = 0
       
   200                 self.transaction_size_set = 0
       
   201                 self.transaction_direction_set = 0
       
   202         elif offset == self.R_NVMEM_SHARED_MEMORY_BASE:
       
   203             self.shared_memory_base = value
       
   204         elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE:
       
   205             self.shared_memory_size = value
       
   206         elif offset == self.R_NVMEM_ENABLE:
       
   207             if( value > 0 ):
       
   208                 self.nvmemory_memregion = qemu.memregion( self.shared_memory_base, self.shared_memory_size )
       
   209                 self.nvmemory_sharedmemory_host_address = self.nvmemory_memregion.region_host_addr()
       
   210                 print"syborg_nvmemorydevice: host addr: 0x%08x" % (self.nvmemory_sharedmemory_host_address)
       
   211         else:
       
   212             reg_write_error = "syborg_nvmemorydevice: Illegal register write to: ", offset 
       
   213             sys.exit( reg_write_error )
       
   214 
       
   215     # Device class properties
       
   216     regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)]
       
   217     irqs = 1
       
   218     name = "syborg,nvmemorydevice"
       
   219     properties = {"drive_size":DEFAULT_DRIVE_SIZE, "sector_size":DEVICE_SECTOR_SIZE, "drive_image_name":DRIVE_NAME}
       
   220 
       
   221 qemu.register_device(syborg_nvmemorydevice)