/* * mmi.h * SAM device-model API * * Copyright (C) 2001-2005 Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SAM_MMI_H #define _SAM_MMI_H #pragma ident "@(#)1.26 03/12/05 SAM-mmi.h" #include #ifdef __cplusplus extern "C" { #endif #if 0 } #endif /* opaque type definitions for MMI device models */ typedef void * mmi_instance_t; typedef void * mmi_module_t; typedef enum {mmi_false=0, mmi_true=1} mmi_bool_t; /* device operation in SAM * * 1. The simulator reads in the simulation configuration file containing "sysconf" lines at startup * 2. Each sysconf line specifies a module-type name, an instance name and a set of properties in the form name=value * For example: * sysconf mydev dev0 baseaddr=0xffc00040 parent=bus0 debug=true logfile=mydev.0.log * 3. The sysconf parser loads the mydev.so object (unless it is already loaded) * 4. The sysconf parser calls the instance creator function in mydev.so to create the "dev0" instance * 5. The dev0 instance creator retrieves its sysconf arguments using mmi_argc and mmi_argv calls and processes them * 6. The dev0 instance creator maps its device registers into the SAM address space using mmi_map_physio */ /* An MMI device model is a shared object loaded using dlopen(). * In SAM, this mechanism requires an _init function in the shared object: * * extern "C" void _init() * * This function must be defined. For example: * * extern "C" void _init() { * // mmi initialization code goes here * } * There are alternative means of automatically invoking an initialization function in a shared object * For example, the constructor of a static object in the shared object written using C++ * * In any event, SAM does not explicitly call a function in the shared object after dlopen(). * The _init() function is implicitly invoked by dlopen(). */ /* Functions returning mmi_bool_t return an SUCCESS status (true=no error). * An error typically indicates invalid arguments are being passed */ /* Devices are instantiated by SAM when specified in the config file. * For each device instance, the device model needs to provide an INSTANCE CREATOR function * which performs the instantiation. * * The instance creator function is invoked from SAM * with the modname (device class name) and the instance-name */ typedef void (*mmi_instance_creator) (const char *modname, const char *instance_name); mmi_bool_t mmi_register_instance_creator(const char * modname, mmi_instance_creator creatorfn); /* the instance_creator function can retrieve its own handle (mmi_instance_t) by calling the mmi_register_instance * function. This function is also used to provide a help string specific to this instance. * This call is optional; the mmi_get_instance() call can be used to get the device's own handle. The help string is * set to the name of the instance by default. This not being too helpful, device models are encouraged to provide * a useful short help string. This help string is displayed in response to UI commands for listing all device nodes. */ mmi_instance_t mmi_register_instance(const char * modname, const char * instancename, const char * short_help); /* Register a function that can respond to the modinfo UI command by printing out relevant module instance information */ typedef void (*mmi_modinfo_cb) (mmi_instance_t cb_instance); /* this_instance can be obtained using the mmi_get_instance call * defined below, and the instance_name parameter of the instance * creator fn */ mmi_bool_t mmi_register_modinfo_cb(mmi_instance_t this_instance, mmi_modinfo_cb modinfo_fn); /* These calls use the mmi_instance_t handle provided by the mmi_register_instance function above. * They return the arguments specified on the sysconf line for this device instance */ int mmi_argc(mmi_instance_t this_instance); char * mmi_argv(mmi_instance_t this_instance, int index); /* A function of type mmi_access needs to be provided by the device model to handle accesses (load/store) to * device registers in response to instructions executed by the simulated CPU. * * The mmi_map_physio function is used to register this function with the simulator. The device-model provides a pointer * to user data which is returned in the call to the access function. This function should return an error indication (0 for success, some non-zero value for failure */ typedef int (*mmi_access) (uint32_t cpuid, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask); /* These calls lets the instance map/unmap its registers onto the physical address space of the simulated CPUs */ int mmi_map_physio (uint64_t base, uint64_t size, void* obj, mmi_access access_fn); void mmi_unmap_physio(uint64_t base, uint64_t size, void* obj); /* Memory access functions for devices: devices can do block read/write into simulated memory using mmi_memread and mmi_memwrite calls */ void mmi_memread(uint64_t paddr, uint8_t * data, uint64_t size); void mmi_memwrite(uint64_t paddr, const uint8_t * data, uint64_t size); /* interrupts: interrupts are not directly delivered to CPUs by devices. Instead, * they are passed on up the device hierarchy through a bus and/or a bridge. The bridge model * implements interrupt delivery to the appropriate CPU. We do not address this in MMI */ /* Interacting with other devices */ /* * When a device is instantiated/deleted in response to a sysconf directive, * a device module can receive about this config change by registering a config callback * function. * * A config event can be of the type: instance-added, instance-deleted and config-init-done * config-init-done refers to simulated system being initialized and ready to execute instructions. * instance_deleted is deprecated and obsolete. Simulator should not delete a device instance. * registering a config callback results in the callback function * being called for config events that have occurred in the past as * well as those that occur subsequently. */ typedef enum {MMI_CONFIG_NEW_MODULE, MMI_CONFIG_DELETE_MODULE, MMI_CONFIG_INIT_DONE} mmi_config_t; typedef void (*mmi_config_cb) (void *callback_data, mmi_instance_t target, const char * target_name, mmi_config_t); mmi_bool_t mmi_register_config_cb(mmi_instance_t this_instance, mmi_config_cb config_fn); // get a device-instance handle by name mmi_instance_t mmi_get_instance(const char * instancename); // register a call-back function with the simulator to respond to mmi_get_interface calls from other modules typedef void* (*mmi_interface_cb) (void *callback_data, const char *name); mmi_bool_t mmi_register_interface_cb(mmi_instance_t this_instance, mmi_interface_cb); // get a named interface from another device instance (eg pcie_device from pcie_bus). // the return value should be typecast to the mutually-agreed-upon interface type void * mmi_get_interface(mmi_instance_t instance, const char * interface_name); /* old mmi functions (for backwards compatibility - eg the SN sync-device model) */ mmi_bool_t mmi_unregister_instance_creator(mmi_instance_t instance); /* these have been deprecated in favor of mmi_map_physio (see above) */ typedef int (*mmi_io_action) (void *cb_data, uint64_t paddr, uint64_t *buf, int size, uint8_t bytemask, void *cpuptr); int mmi_register_io_action (mmi_module_t *module, mmi_io_action ld_handler, mmi_io_action st_handler); /* interrupt functions - these are described in the MMI documentation */ int mmi_interrupt_packet (int dest_cpuid, void *src, int src_iscpu, uint64_t *idata); int mmi_interrupt_vector (int dest_cpuid, void *src, int src_iscpu, uint32_t vnum, int traptype); #if 0 { #endif #ifdef __cplusplus } // extern "C" #endif #endif // _SAM_MMI_H