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
+44 -14
View File
@@ -134,7 +134,7 @@ struct driver_entry {
static void get_device_name(struct devfs_vnode *vnode, char *buffer, size_t size); 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, static status_t publish_device(struct devfs *fs, const char *path,
device_node_info *deviceNode, pnp_devfs_driver_info *info, 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 */ /* 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 // For a valid device driver the following exports are required
uint32 *api_version; int32 defaultApiVersion = 1;
if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void **)&api_version) != B_OK) 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); dprintf("%s: api_version missing\n", name);
device_hooks *(*find_device)(const char *); device_hooks *(*find_device)(const char *);
@@ -243,7 +262,7 @@ load_driver(driver_entry *driver)
if (hooks != NULL if (hooks != NULL
&& publish_device(sDeviceFileSystem, devicePaths[0], && publish_device(sDeviceFileSystem, devicePaths[0],
NULL, NULL, driver, hooks) == B_OK) NULL, NULL, driver, hooks, *apiVersion) == B_OK)
exported++; exported++;
} }
@@ -594,7 +613,7 @@ translate_partition_access(devfs_partition *partition, off_t &offset, size_t &si
static pnp_devfs_driver_info * 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)); pnp_devfs_driver_info *info = (pnp_devfs_driver_info *)malloc(sizeof(pnp_devfs_driver_info));
if (info == NULL) if (info == NULL)
@@ -607,14 +626,24 @@ create_new_driver_info(device_hooks *ops)
info->close = ops->close; info->close = ops->close;
info->free = ops->free; info->free = ops->free;
info->control = ops->control; info->control = ops->control;
info->select = ops->select;
info->deselect = ops->deselect;
info->read = ops->read; info->read = ops->read;
info->write = ops->write; info->write = ops->write;
// depends on api_version
info->select = NULL;
info->deselect = NULL;
info->read_pages = NULL; info->read_pages = NULL;
info->write_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; return info;
} }
@@ -817,10 +846,10 @@ out:
static status_t static status_t
publish_device(struct devfs *fs, const char *path, device_node_info *deviceNode, 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", TRACE(("publish_device(path = \"%s\", node = %p, info = %p, hooks = %p, apiVersion = %d)\n",
path, deviceNode, info, ops)); path, deviceNode, info, ops, apiVersion));
if (sDeviceFileSystem == NULL) { if (sDeviceFileSystem == NULL) {
panic("publish_device() called before devfs mounted\n"); 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) if (deviceNode != NULL)
node->stream.u.dev.info = info; node->stream.u.dev.info = info;
else 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.node = deviceNode;
node->stream.u.dev.driver = driver; node->stream.u.dev.driver = driver;
@@ -2016,7 +2045,7 @@ pnp_devfs_register_device(device_node_handle parent)
goto err2; goto err2;
//add_device(device); //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) if (status != B_OK)
goto err3; goto err3;
//nudge(); //nudge();
@@ -2267,7 +2296,8 @@ devfs_unpublish_device(const char *path, bool disconnect)
extern "C" status_t extern "C" status_t
devfs_publish_device(const char *path, void *obsolete, device_hooks *ops) 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);
} }