diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py Thu May 27 00:38:17 2010 +0300 @@ -0,0 +1,221 @@ +# +# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: syborg_nvmemorydevice.py +# A simple non volatile memory device nvmemory.dll python wrapper +# Represents a non volatile memory device register interface for quest OS in QEMU Syborg environment. +# +# Gets the following from devicetree (.dtb configuration file) +# 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 +# sector_size - the size of the sector for the memory device +# drive_image_name - the name of the image to be used +# +# Creates an empty image of specified size and name if there is not image available when the system is started +# + +import ctypes +import qemu +import sys +import os +import array + +class syborg_nvmemorydevice(qemu.devclass): + # 256 MB default empty drive size if there is no readymade image available + DEFAULT_DRIVE_SIZE = 0x10000000 + DEVICE_SECTOR_SIZE = 0x200 + DRIVE_NAME = "qemudrive.img" + DRIVE_PATH = "nvmemory" + + # Memory device registers + R_NVMEM_ID = 0x0000 + R_NVMEM_TRANSACTION_OFFSET = 0x0004 + R_NVMEM_TRANSACTION_SIZE = 0x0008 + R_NVMEM_TRANSACTION_DIRECTION = 0x000c + R_NVMEM_TRANSACTION_EXECUTE = 0x0010 + R_NVMEM_SHARED_MEMORY_BASE = 0x0014 + R_NVMEM_NV_MEMORY_SIZE = 0x0018 + R_NVMEM_SHARED_MEMORY_SIZE = 0x001c + R_NVMEM_STATUS = 0x0020 + R_NVMEM_ENABLE = 0x0024 + R_NVMEM_LASTREG = 0x0028 # not a register, address of last register + + NVMEM_TRANSACTION_READ = 1 + NVMEM_TRANSACTION_WRITE = 2 + # Variables to store the information for current transaction + shared_memory_base = 0 + shared_memory_size = 0 + transaction_offset = 0 + transaction_size = 0 + transaction_direction = 0 + # Variables to validate transaction + transaction_offset_set = 0 + transaction_size_set = 0 + transaction_direction_set = 0 + nvmemory_sector_count = 0 + + drive_size = 0 + sector_size = 0 + drive_image_name = "" + + def create(self): + print "syborg_nvmemorydevice: create\n" + + # Get properties + self.drive_size = self.properties["drive_size"] + self.sector_size = self.properties["sector_size"] + self.drive_image_name = self.properties["drive_image_name"] + + print "drive size: ", self.drive_size + print "sector size: ", self.sector_size + print "drive name: ", self.drive_image_name + + drive_path_and_name = self.DRIVE_PATH + "\\" + self.drive_image_name + # Save working directory + self.working_dir = os.getcwd() + + # Open the nvmemory library + try: + self.nvmemlib = ctypes.CDLL("nvmemmory.dll") + except: + sys.exit("syborg_nvmemorydevice: nvmemmory.dll load failed") + + # Create an instance of non volatile memory handler class + self.obj = self.nvmemlib.nvmem_create( self.sector_size ) + self.nvmemlib.nvmem_reset( self.obj ) + + # Create drive image path + try: + print "syborg_nvmemorydevice: Check drive image path\n" + os.mkdir( self.DRIVE_PATH ) + except: + # Here we could check why we failed - usually because the path already exists \n" + pass + try: + self.filehandle = os.open( drive_path_and_name, os.O_RDWR|os.O_BINARY ) + os.close( self.filehandle ) + except: + print "syborg_nvmemorydevice: drive image not found - create\n" + self.filehandle = open( drive_path_and_name, "wb" ) + # Initialize file with zeroes. This may take a while + temparray = array.array("B", [0,0,0,0,0,0,0,0]) + arraylength = temparray.buffer_info()[1] * temparray.itemsize + multiplier = self.drive_size / arraylength / 128 + temparray = temparray * multiplier + arraylength = temparray.buffer_info()[1] * temparray.itemsize + print "array length: ", arraylength + index = 0 + while index < 128: + temparray.tofile(self.filehandle) + index = index+1 + + # Create path and get handle to the raw memory array + imagepath = self.working_dir + "\\" + drive_path_and_name + print "imagepath: ", imagepath + self.nvmemhandle = self.nvmemlib.nvmem_open( self.obj, imagepath ) + if( self.nvmemhandle < 0 ): + error_msg = "syborg_nvmemorydevice: nvmem_open error: ", self.nvmemhandle + sys.exit( error_msg ) + + # Initialize callback and get memory sector count + self.initialize_nvmem_callback() + self.nvmemory_sector_count = self.nvmemlib.nvmem_get_sector_count( self.obj, self.nvmemhandle ) + print "syborg_nvmemorydevice: created\n" + + def updateIrq(self,new_value): + self.set_irq_level(0, new_value) + + def nvmem_request_callback(self, result): + #print "graphics_request_callback: " , result + self.status_reg = result + self.updateIrq(1) + return 0 + + def initialize_nvmem_callback(self): + self.CALLBACKFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) + self.nvmem_callback = self.CALLBACKFUNC(self.nvmem_request_callback) + self.nvmemlib.nvmem_set_callback( self.obj, self.nvmem_callback ) + + def read_reg(self, offset): + offset >>= 2 + #print "read register: 0x%x" % (offset) + if offset == self.R_NVMEM_ID: + return 0xDEADBEEF + elif offset == self.R_NVMEM_TRANSACTION_OFFSET: + return self.transaction_offset + elif offset == self.R_NVMEM_TRANSACTION_SIZE: + return self.transaction_size + elif offset == self.R_NVMEM_TRANSACTION_DIRECTION: + return self.transaction_direction + elif offset == self.R_NVMEM_SHARED_MEMORY_BASE: + return self.shared_memory_base + elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE: + return self.shared_memory_size + elif offset == self.R_NVMEM_NV_MEMORY_SIZE: + return self.nvmemory_sector_count + elif offset == self.R_NVMEM_STATUS: + self.updateIrq(0) + return self.status_reg + else: + reg_read_error = "syborg_nvmemorydevice: Illegal register read at: ", offset + sys.exit( reg_read_error ) + + def write_reg(self, offset, value): + offset >>= 2 + #print "write register: 0x%x value: 0x%x" % (offset, value) + if offset == self.R_NVMEM_TRANSACTION_OFFSET: + self.transaction_offset = value + self.transaction_offset_set = 1 + elif offset == self.R_NVMEM_TRANSACTION_SIZE: + self.transaction_size = value + self.transaction_size_set = 1 + elif offset == self.R_NVMEM_TRANSACTION_DIRECTION: + self.transaction_direction = value + self.transaction_direction_set = 1 + elif offset == self.R_NVMEM_TRANSACTION_EXECUTE: + if( (self.transaction_offset_set == 0) | (self.transaction_size_set == 0) | (self.transaction_direction_set == 0) ): + error_msg = "syborg_nvmemorydevice: Illegal transaction! All the required parameters are not set" + sys.exit( error_msg ) + elif(self.transaction_size == 0 ): + error_msg = "syborg_nvmemorydevice: Zero size transaction issued!" + sys.exit( error_msg ) + else: + if( self.transaction_direction == self.NVMEM_TRANSACTION_READ ): + self.nvmemlib.nvmem_read( self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size ) + elif( self.transaction_direction == self.NVMEM_TRANSACTION_WRITE ): + self.nvmemlib.nvmem_write( self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size ) + else: + error_msg = "syborg_nvmemorydevice: Transaction direction not set!" + sys.exit( error_msg ) + self.transaction_offset_set = 0 + self.transaction_size_set = 0 + self.transaction_direction_set = 0 + elif offset == self.R_NVMEM_SHARED_MEMORY_BASE: + self.shared_memory_base = value + elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE: + self.shared_memory_size = value + elif offset == self.R_NVMEM_ENABLE: + if( value > 0 ): + self.nvmemory_memregion = qemu.memregion( self.shared_memory_base, self.shared_memory_size ) + self.nvmemory_sharedmemory_host_address = self.nvmemory_memregion.region_host_addr() + print"syborg_nvmemorydevice: host addr: 0x%08x" % (self.nvmemory_sharedmemory_host_address) + else: + reg_write_error = "syborg_nvmemorydevice: Illegal register write to: ", offset + sys.exit( reg_write_error ) + + # Device class properties + regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] + irqs = 1 + name = "syborg,nvmemorydevice" + properties = {"drive_size":DEFAULT_DRIVE_SIZE, "sector_size":DEVICE_SECTOR_SIZE, "drive_image_name":DRIVE_NAME} + +qemu.register_device(syborg_nvmemorydevice)