diff -r 14e513529ca5 -r b3977fb10b6e erts/emulator/beam/atom.names
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -289,6 +289,7 @@ atom name
 atom name
 atom named_table
 atom native_addresses
+atom need_driver_init
 atom Neq='=/='
 atom Neqeq='/='
 atom net_kernel
diff -r 14e513529ca5 -r b3977fb10b6e erts/emulator/beam/erl_bif_ddll.c
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -13,6 +13,9 @@
  * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  * AB. All Rights Reserved.''
  * 
+ * FFI and generic library loading support added by:
+ * Alceste Scalas <alceste@crs4.it>
+ *
  *     $Id$
  */
 /*
@@ -69,9 +72,11 @@ static void add_proc_loaded(DE_Handle *d
 static void add_proc_loaded(DE_Handle *dh, Process *proc); 
 static void add_proc_loaded_deref(DE_Handle *dh, Process *proc);
 static void set_driver_reloading(DE_Handle *dh, Process *proc, char *path, char *name, Uint flags);
-static int load_driver_entry(DE_Handle **dhp, char *path, char *name);
+static int load_driver_entry(DE_Handle **dhp, char *path, char *name,
+			     int need_driver_init);
 static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name);
-static int do_load_driver_entry(DE_Handle *dh, char *path, char *name);
+static int do_load_driver_entry(DE_Handle *dh, char *path, char *name,
+				int need_driver_init);
 #if 0
 static void unload_driver_entry(DE_Handle *dh);
 #endif
@@ -115,7 +120,8 @@ static void ddll_no_more_references(void
  *	 OptionList = [ Option ]
  *	 Option = {driver_options, DriverOptionList} | 
  *                {monitor,MonitorOption} | 
- *                {reload, ReloadOption}
+ *                {reload, ReloadOption} |
+ *                {need_driver_init, true | false}
  *	 DriverOptionList = [ DriverOption ]
  *	 DriverOption = kill_ports
  *	 MonitorOption = pending_driver | pending
@@ -156,6 +162,7 @@ BIF_RETTYPE erl_ddll_try_load_3(Process 
     int kill_ports = 0;
     int do_build_load_error = 0;
     int build_this_load_error = 0;
+    int need_driver_init = 1;
 
     for(l = options; is_list(l); l =  CDR(list_val(l))) {
 	Eterm opt = CAR(list_val(l));
@@ -198,6 +205,15 @@ BIF_RETTYPE erl_ddll_try_load_3(Process 
 		reload = 1;
 	    } else if (tp[2] == am_pending ) {
 		reload = 2;
+	    } else {
+		goto error;
+	    }
+	    break;
+	case am_need_driver_init:
+	    if (tp[2] == am_true) {
+		need_driver_init = 1;
+	    } else if (tp[2] == am_false ) {
+		need_driver_init = 0;
 	    } else {
 		goto error;
 	    }
@@ -334,7 +350,8 @@ BIF_RETTYPE erl_ddll_try_load_3(Process 
 	    soft_error_term = am_not_loaded;
 	    goto soft_error;
 	} 
-	if ((res = load_driver_entry(&dh, path, name)) !=  ERL_DE_NO_ERROR) {
+	if ((res = load_driver_entry(&dh, path, name,
+				     need_driver_init)) != ERL_DE_NO_ERROR) {
 	    build_this_load_error = res;
 	    do_build_load_error = 1;
 	    soft_error_term = am_undefined;
@@ -1540,7 +1557,8 @@ static void set_driver_reloading(DE_Hand
     dh->reload_flags = flags;
 }
 
-static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
+static int do_load_driver_entry(DE_Handle *dh, char *path, char *name,
+				int need_driver_init)
 {
     void *init_handle;
     int res;
@@ -1552,16 +1570,41 @@ static int do_load_driver_entry(DE_Handl
 	return res;
     }
     
-    if ((res = erts_sys_ddll_load_driver_init(dh->handle, 
-					      &init_handle)) != ERL_DE_NO_ERROR) {
+    if ((res = erts_sys_ddll_load_driver_init(dh->handle,
+					      &init_handle)) == ERL_DE_NO_ERROR) {
+	dp = erts_sys_ddll_call_init(init_handle);
+	if (dp == NULL) {
+	    erts_sys_ddll_close(dh->handle);
+	    return ERL_DE_LOAD_ERROR_FAILED_INIT;
+	}
+
+	/* The driver entry is "genuine" and will not need to be freed */
+	dh->need_drventry_free = 0;
+    } else if (!need_driver_init) {
+	/* 
+	 * We weren't able to load the driver initialization function,
+	 * but we don't need it (since need_driver_init is false):
+	 * let's allocate a void ErlDrvEntry, that won't allow to use
+	 * erlang:port_control/3 and friends --- but will be OK for
+	 * the FFI interface
+	 */
+
+	/* FIXME: is this allocation type correct? */
+	dp = erts_alloc(ERTS_ALC_T_DRV, sizeof(ErlDrvEntry));
+	memset(dp, 0, sizeof(ErlDrvEntry));
+	dp->driver_name = erts_alloc(ERTS_ALC_T_DRV, strlen(name) + 1);
+	strcpy(dp->driver_name, name);
+	dp->extended_marker = ERL_DRV_EXTENDED_MARKER;
+	dp->major_version = ERL_DRV_EXTENDED_MAJOR_VERSION;
+	dp->minor_version = ERL_DRV_EXTENDED_MINOR_VERSION;
+	
+	/* The driver entry will need to be freed */
+	dh->need_drventry_free = 1;
+    } else {
+	/* We require the driver init function, but we weren't able to
+	 * load it */
 	erts_sys_ddll_close(dh->handle);
 	return ERL_DE_LOAD_ERROR_NO_INIT;
-    }
-    
-    dp = erts_sys_ddll_call_init(init_handle);
-    if (dp == NULL) {
-	erts_sys_ddll_close(dh->handle);
-	return ERL_DE_LOAD_ERROR_FAILED_INIT;
     }
 
     switch (dp->extended_marker) {
@@ -1604,6 +1647,7 @@ static int do_load_driver_entry(DE_Handl
     sys_strcpy(dh->full_path, path);
     dh->flags = 0;
     dh->status = ERL_DE_OK;
+    dh->need_driver_init = need_driver_init;
     dp->handle = dh;
 
     erts_add_driver_entry(dp,1); /* io.c */
@@ -1645,6 +1689,12 @@ static int do_unload_driver_entry(DE_Han
 		erts_free(ERTS_ALC_T_DRIVER_LOCK, q->driver_lock);
 	    }
 #endif
+	    if (dh->need_drventry_free) {
+		/* The ErlDrvEntry needs to be freed, probably because it
+		 * was autogenerated by do_load_driver_entry() */
+		erts_free(ERTS_ALC_T_DRV, q->drv->driver_name);
+		erts_free(ERTS_ALC_T_DRV, q->drv);
+	    }
 	    erts_free(ERTS_ALC_T_DRV_ENTRY_LIST, (void *) q);
 	    return 1;
 	}
@@ -1653,7 +1703,8 @@ static int do_unload_driver_entry(DE_Han
     return 0;
 }
 
-static int load_driver_entry(DE_Handle **dhp, char *path, char *name)
+static int load_driver_entry(DE_Handle **dhp, char *path, char *name,
+			     int need_driver_init)
 {
     int res;
     DE_Handle *dh = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sizeof(DE_Handle));
@@ -1671,7 +1722,8 @@ static int load_driver_entry(DE_Handle *
     dh->full_path = NULL;
     dh->flags = 0;
 
-    if ((res = do_load_driver_entry(dh, path, name)) != ERL_DE_NO_ERROR) {
+    if ((res = do_load_driver_entry(dh, path, name,
+				    need_driver_init)) != ERL_DE_NO_ERROR) {
 	erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh);
 	dh = NULL;
     }
@@ -1706,7 +1758,7 @@ static int reload_driver_entry(DE_Handle
     erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh->full_path);
     dh->full_path = NULL;
 
-    loadres = do_load_driver_entry(dh, path, name);
+    loadres = do_load_driver_entry(dh, path, name, dh->need_driver_init);
     erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) path);
     erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) name);
     if (loadres == ERL_DE_NO_ERROR) {
diff -r 14e513529ca5 -r b3977fb10b6e erts/emulator/beam/global.h
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -213,6 +213,11 @@ typedef struct {
 				         full name of driver (path) */
     char         *reload_driver_name; /* ... and this contains the driver name */
     Uint         reload_flags;        /* flags for reloaded driver */
+    int          need_driver_init;    /* Does the associated
+				       * ErlDrvEntry need the driver
+				       * initialization structure? */
+    int          need_drventry_free;  /* Does the associated
+				       * ErlDrvEntry need to be freed? */
 } DE_Handle;
 
 /*
diff -r 14e513529ca5 -r b3977fb10b6e lib/kernel/src/erl_ddll.erl
--- a/lib/kernel/src/erl_ddll.erl
+++ b/lib/kernel/src/erl_ddll.erl
@@ -22,7 +22,7 @@
 
 -module(erl_ddll).
 
--export([load_driver/2, load/2, 
+-export([load_driver/2, load/2, load_library/3,
 	 unload_driver/1, unload/1, reload/2, reload_driver/2, 
 	 format_error/1,info/1,info/0, start/0, stop/0]).
 
@@ -37,6 +37,9 @@ load_driver(Path, Driver) ->
 
 load(Path, Driver) ->
     do_load_driver(Path, Driver, []).
+
+load_library(Path, Library, OptionList) ->
+    do_load_driver(Path, Library, OptionList ++ [{need_driver_init, false}]).
 
 do_load_driver(Path, Driver, DriverFlags) ->
     case erl_ddll:try_load(Path, Driver,[{monitor,pending_driver}]++DriverFlags) of
