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); }