[haiku-development] devfs: handle api_version (fwd)

  • From: "François Revol" <revol@xxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 07 Jun 2007 11:08:05 +0200 CEST

sf.net seems to think it's spam... eh

------ Forwarded Message: ------
To: "OpenBeOS-kernel" <open-beos-kernel-devel@xxxxxxxxxxxxxxxxxxxxx>
From: "François Revol" <revol@xxxxxxx>
Subject: devfs: handle api_version
Date: Thu, 07 Jun 2007 10:46:12 +0200 CEST

This patch should fix handling of unexisting/set-to-1 api_version from
drivers.
We currently assume it's always there and == 2 and copy the [de]select
hooks regardless.

As version 1 drivers are pre-R4 it's probably not that useful to
support those, and I could just make it reject api_version not here or
==1 instead.
It would avoid adding all that, so I didn't commit it yet, thoughts ?

François.


Index: src/system/kernel/fs/devfs.cpp
===================================================================
--- src/system/kernel/fs/devfs.cpp      (revision 21343)
+++ src/system/kernel/fs/devfs.cpp      (working copy)
@@ -134,7 +134,7 @@
 static void get_device_name(struct devfs_vnode *vnode, char *buffer, size_t 
size);
 static status_t publish_device(struct devfs *fs, const char *path,
                                        device_node_info *deviceNode, 
pnp_devfs_driver_info *info,
-                                       driver_entry *driver, device_hooks 
*ops);
+                                       driver_entry *driver, device_hooks 
*ops, int32 api_version);
 
 
 /* the one and only allowed devfs instance */
@@ -193,8 +193,27 @@
 
        // For a valid device driver the following exports are required
 
-       uint32 *api_version;
-       if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void 
**)&api_version) != B_OK)
+       int32 default_api_version = 1;
+       int32 *api_version = &default_api_version;
+       if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void 
**)&api_version) == B_OK) {
+               // According to Be newsletter, vol II, issue 36,
+               // version 2 added readv/writev, which we don't support, but 
also select/deselect.
+               // So we must make sure not to use invalid pointers in 
publish_device.
+#if B_CUR_DRIVER_API_VERSION != 2
+               // just in case someone decides to bump up the api version
+#error Add checks here for new vs old api version!
+#endif
+               if (*api_version > B_CUR_DRIVER_API_VERSION) {
+                       dprintf("%s: api_version %ld not handled\n", name, 
*api_version);
+                       status = B_BAD_VALUE;
+                       goto error1;
+               }
+               if (*api_version < 1) {
+                       dprintf("%s: api_version invalid\n", name);
+                       status = B_BAD_VALUE;
+                       goto error1;
+               }
+       } else
                dprintf("%s: api_version missing\n", name);
 
        device_hooks *(*find_device)(const char *);
@@ -243,7 +262,7 @@
 
                if (hooks != NULL
                        && publish_device(sDeviceFileSystem, devicePaths[0],
-                                       NULL, NULL, driver, hooks) == B_OK)
+                                       NULL, NULL, driver, hooks, 
*api_version) == B_OK)
                        exported++;
        }
 
@@ -594,7 +613,7 @@
 
 
 static pnp_devfs_driver_info *
-create_new_driver_info(device_hooks *ops)
+create_new_driver_info(device_hooks *ops, int32 version)
 {
        pnp_devfs_driver_info *info = (pnp_devfs_driver_info 
*)malloc(sizeof(pnp_devfs_driver_info));
        if (info == NULL)
@@ -607,14 +626,24 @@
        info->close = ops->close;
        info->free = ops->free;
        info->control = ops->control;
-       info->select = ops->select;
-       info->deselect = ops->deselect;
        info->read = ops->read;
        info->write = ops->write;
+               // depends on api_version
+       info->select = NULL;
+       info->deselect = NULL;
 
        info->read_pages = NULL;
        info->write_pages = NULL;
-               // old devices can't know to do physical page access
+               // old devices can't know how to do physical page access
+       
+       if (version >= 2) {
+               info->select = ops->select;
+               info->deselect = ops->deselect;
+               
+               // ops->readv;
+               // ops->writev;
+               // we don't implement scatter-gather atm, so ignore those.
+       }
 
        return info;
 }
@@ -817,10 +846,10 @@
 
 static status_t
 publish_device(struct devfs *fs, const char *path, device_node_info 
*deviceNode,
-       pnp_devfs_driver_info *info, driver_entry *driver, device_hooks *ops)
+       pnp_devfs_driver_info *info, driver_entry *driver, device_hooks *ops, 
int32 api_version)
 {
-       TRACE(("publish_device(path = \"%s\", node = %p, info = %p, hooks = 
%p)\n",
-               path, deviceNode, info, ops));
+       TRACE(("publish_device(path = \"%s\", node = %p, info = %p, hooks = %p, 
api_version = %d)\n",
+               path, deviceNode, info, ops, api_version));
 
        if (sDeviceFileSystem == NULL) {
                panic("publish_device() called before devfs mounted\n");
@@ -858,7 +887,7 @@
        if (deviceNode != NULL)
                node->stream.u.dev.info = info;
        else
-               node->stream.u.dev.info = create_new_driver_info(ops);
+               node->stream.u.dev.info = create_new_driver_info(ops, 
api_version);
 
        node->stream.u.dev.node = deviceNode;
        node->stream.u.dev.driver = driver;
@@ -2016,7 +2045,7 @@
                goto err2;
 
        //add_device(device);
-       status = publish_device(sDeviceFileSystem, filename, node, info, NULL, 
NULL);
+       status = publish_device(sDeviceFileSystem, filename, node, info, NULL, 
NULL, 0);
        if (status != B_OK)
                goto err3;
        //nudge();
@@ -2267,7 +2296,8 @@
 extern "C" status_t
 devfs_publish_device(const char *path, void *obsolete, device_hooks *ops)
 {
-       return publish_device(sDeviceFileSystem, path, NULL, NULL, NULL, ops);
+       // post R5: assume version 2
+       return publish_device(sDeviceFileSystem, path, NULL, NULL, NULL, ops, 
2);
 }
 
 

Other related posts: