handle api_version exported from driver.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21344 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2007-06-07 12:46:20 +00:00
parent 0ce9bc6895
commit fc362b8ad7

View File

@ -134,7 +134,7 @@ struct driver_entry {
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 apiVersion);
/* the one and only allowed devfs instance */
@ -193,8 +193,27 @@ load_driver(driver_entry *driver)
// 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 defaultApiVersion = 1;
int32 *apiVersion = &defaultApiVersion;
if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void **)&apiVersion) == 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 (*apiVersion > B_CUR_DRIVER_API_VERSION) {
dprintf("%s: api_version %ld not handled\n", name, *apiVersion);
status = B_BAD_VALUE;
goto error1;
}
if (*apiVersion < 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 @@ load_driver(driver_entry *driver)
if (hooks != NULL
&& publish_device(sDeviceFileSystem, devicePaths[0],
NULL, NULL, driver, hooks) == B_OK)
NULL, NULL, driver, hooks, *apiVersion) == B_OK)
exported++;
}
@ -594,7 +613,7 @@ translate_partition_access(devfs_partition *partition, off_t &offset, size_t &si
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 @@ create_new_driver_info(device_hooks *ops)
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 @@ out:
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 apiVersion)
{
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, apiVersion = %d)\n",
path, deviceNode, info, ops, apiVersion));
if (sDeviceFileSystem == NULL) {
panic("publish_device() called before devfs mounted\n");
@ -858,7 +887,7 @@ publish_device(struct devfs *fs, const char *path, device_node_info *deviceNode,
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, apiVersion);
node->stream.u.dev.node = deviceNode;
node->stream.u.dev.driver = driver;
@ -2016,7 +2045,7 @@ pnp_devfs_register_device(device_node_handle parent)
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 @@ devfs_unpublish_device(const char *path, bool disconnect)
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);
}