git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21552 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-07-04 17:33:22 +00:00
parent 470ca87e4d
commit d5a279fef8
+94 -56
View File
@@ -131,10 +131,11 @@ 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, int32 apiVersion); driver_entry *driver, device_hooks *ops, int32 apiVersion);
/* the one and only allowed devfs instance */ /* the one and only allowed devfs instance */
@@ -195,10 +196,8 @@ load_driver(driver_entry *driver)
int32 defaultApiVersion = 1; int32 defaultApiVersion = 1;
int32 *apiVersion = &defaultApiVersion; int32 *apiVersion = &defaultApiVersion;
if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void **)&apiVersion) == B_OK) { if (get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA,
// According to Be newsletter, vol II, issue 36, (void **)&apiVersion) == B_OK) {
// 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 #if B_CUR_DRIVER_API_VERSION != 2
// just in case someone decides to bump up the api version // just in case someone decides to bump up the api version
#error Add checks here for new vs old api version! #error Add checks here for new vs old api version!
@@ -218,8 +217,10 @@ load_driver(driver_entry *driver)
device_hooks *(*find_device)(const char *); device_hooks *(*find_device)(const char *);
const char **(*publish_devices)(void); const char **(*publish_devices)(void);
if (get_image_symbol(image, "publish_devices", B_SYMBOL_TYPE_TEXT, (void **)&publish_devices) != B_OK if (get_image_symbol(image, "publish_devices", B_SYMBOL_TYPE_TEXT,
|| get_image_symbol(image, "find_device", B_SYMBOL_TYPE_TEXT, (void **)&find_device) != B_OK) { (void **)&publish_devices) != B_OK
|| get_image_symbol(image, "find_device", B_SYMBOL_TYPE_TEXT,
(void **)&find_device) != B_OK) {
dprintf("%s: mandatory driver symbol(s) missing!\n", name); dprintf("%s: mandatory driver symbol(s) missing!\n", name);
status = B_BAD_VALUE; status = B_BAD_VALUE;
goto error1; goto error1;
@@ -298,13 +299,14 @@ error1:
} }
/** This is no longer part of the public kernel API, so we just export the symbol */ /*! This is no longer part of the public kernel API, so we just export the
symbol
*/
status_t load_driver_symbols(const char *driverName); status_t load_driver_symbols(const char *driverName);
status_t status_t
load_driver_symbols(const char *driverName) load_driver_symbols(const char *driverName)
{ {
// This will be globally done for the whole kernel via the settings file. // This is done globally for the whole kernel via the settings file.
// We don't have to do anything here. // We don't have to do anything here.
return B_OK; return B_OK;
@@ -399,7 +401,8 @@ devfs_create_vnode(struct devfs *fs, devfs_vnode *parent, const char *name)
static status_t static status_t
devfs_delete_vnode(struct devfs *fs, struct devfs_vnode *vnode, bool force_delete) devfs_delete_vnode(struct devfs *fs, struct devfs_vnode *vnode,
bool force_delete)
{ {
// cant delete it if it's in a directory or is a directory // cant delete it if it's in a directory or is a directory
// and has children // and has children
@@ -437,7 +440,8 @@ update_dir_cookies(struct devfs_vnode *dir, struct devfs_vnode *vnode)
{ {
struct devfs_dir_cookie *cookie = NULL; struct devfs_dir_cookie *cookie = NULL;
while ((cookie = (devfs_dir_cookie *)list_get_next_item(&dir->stream.u.dir.cookies, cookie)) != NULL) { while ((cookie = (devfs_dir_cookie *)list_get_next_item(
&dir->stream.u.dir.cookies, cookie)) != NULL) {
if (cookie->current == vnode) if (cookie->current == vnode)
cookie->current = vnode->dir_next; cookie->current = vnode->dir_next;
} }
@@ -494,8 +498,10 @@ devfs_insert_in_dir(struct devfs_vnode *dir, struct devfs_vnode *vnode)
vnode->parent = dir; vnode->parent = dir;
dir->modification_time = time(NULL); dir->modification_time = time(NULL);
notify_entry_created(sDeviceFileSystem->id, dir->id, vnode->name, vnode->id); notify_entry_created(sDeviceFileSystem->id, dir->id, vnode->name,
notify_stat_changed(sDeviceFileSystem->id, dir->id, B_STAT_MODIFICATION_TIME); vnode->id);
notify_stat_changed(sDeviceFileSystem->id, dir->id,
B_STAT_MODIFICATION_TIME);
return B_OK; return B_OK;
} }
@@ -519,8 +525,10 @@ devfs_remove_from_dir(struct devfs_vnode *dir, struct devfs_vnode *removeNode)
vnode->dir_next = NULL; vnode->dir_next = NULL;
dir->modification_time = time(NULL); dir->modification_time = time(NULL);
notify_entry_removed(sDeviceFileSystem->id, dir->id, vnode->name, vnode->id); notify_entry_removed(sDeviceFileSystem->id, dir->id, vnode->name,
notify_stat_changed(sDeviceFileSystem->id, dir->id, B_STAT_MODIFICATION_TIME); vnode->id);
notify_stat_changed(sDeviceFileSystem->id, dir->id,
B_STAT_MODIFICATION_TIME);
return B_OK; return B_OK;
} }
} }
@@ -547,7 +555,8 @@ add_partition(struct devfs *fs, struct devfs_vnode *device,
return B_BAD_VALUE; return B_BAD_VALUE;
// create partition // create partition
struct devfs_partition *partition = (struct devfs_partition *)malloc(sizeof(struct devfs_partition)); struct devfs_partition *partition = (struct devfs_partition *)malloc(
sizeof(struct devfs_partition));
if (partition == NULL) if (partition == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -597,7 +606,8 @@ err1:
static inline void static inline void
translate_partition_access(devfs_partition *partition, off_t &offset, size_t &size) translate_partition_access(devfs_partition *partition, off_t &offset,
size_t &size)
{ {
if (offset < 0) if (offset < 0)
offset = 0; offset = 0;
@@ -615,7 +625,8 @@ 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, int32 version) 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)
return NULL; return NULL;
@@ -637,9 +648,12 @@ create_new_driver_info(device_hooks *ops, int32 version)
// old devices can't know how to do physical page access // old devices can't know how to do physical page access
if (version >= 2) { if (version >= 2) {
// According to Be newsletter, vol II, issue 36,
// version 2 added readv/writev, which we don't support, but also
// select/deselect.
info->select = ops->select; info->select = ops->select;
info->deselect = ops->deselect; info->deselect = ops->deselect;
// ops->readv; // ops->readv;
// ops->writev; // ops->writev;
// we don't implement scatter-gather atm, so ignore those. // we don't implement scatter-gather atm, so ignore those.
@@ -650,7 +664,8 @@ create_new_driver_info(device_hooks *ops, int32 version)
static status_t static status_t
get_node_for_path(struct devfs *fs, const char *path, struct devfs_vnode **_node) get_node_for_path(struct devfs *fs, const char *path,
struct devfs_vnode **_node)
{ {
return vfs_get_fs_node_from_path(fs->id, path, true, (void **)_node); return vfs_get_fs_node_from_path(fs->id, path, true, (void **)_node);
} }
@@ -846,9 +861,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, int32 apiVersion) pnp_devfs_driver_info *info, driver_entry *driver, device_hooks *ops,
int32 apiVersion)
{ {
TRACE(("publish_device(path = \"%s\", node = %p, info = %p, hooks = %p, apiVersion = %d)\n", TRACE(("publish_device(path = \"%s\", node = %p, info = %p, hooks = %p, apiVersion = %ld)\n",
path, deviceNode, info, ops, apiVersion)); path, deviceNode, info, ops, apiVersion));
if (sDeviceFileSystem == NULL) { if (sDeviceFileSystem == NULL) {
@@ -1539,7 +1555,8 @@ devfs_read_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie,
struct devfs_vnode *nextChildNode = NULL; struct devfs_vnode *nextChildNode = NULL;
int32 nextState = cookie->state; int32 nextState = cookie->state;
TRACE(("devfs_read_dir: vnode %p, cookie %p, buffer %p, size %ld\n", _vnode, cookie, dirent, bufferSize)); TRACE(("devfs_read_dir: vnode %p, cookie %p, buffer %p, size %ld\n",
_vnode, cookie, dirent, bufferSize));
if (!S_ISDIR(vnode->stream.type)) if (!S_ISDIR(vnode->stream.type))
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -1613,10 +1630,9 @@ devfs_rewind_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie)
} }
/** Forwards the opcode to the device driver, but also handles some devfs specific /*! Forwards the opcode to the device driver, but also handles some devfs
* functionality, like partitions. specific functionality, like partitions.
*/ */
static status_t static status_t
devfs_ioctl(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, ulong op, devfs_ioctl(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, ulong op,
void *buffer, size_t length) void *buffer, size_t length)
@@ -1628,13 +1644,14 @@ devfs_ioctl(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, ulong op,
TRACE(("devfs_ioctl: vnode %p, cookie %p, op %ld, buf %p, len %ld\n", TRACE(("devfs_ioctl: vnode %p, cookie %p, op %ld, buf %p, len %ld\n",
_vnode, _cookie, op, buffer, length)); _vnode, _cookie, op, buffer, length));
// we are actually checking for a *device* here, we don't make the distinction // we are actually checking for a *device* here, we don't make the
// between char and block devices // distinction between char and block devices
if (S_ISCHR(vnode->stream.type)) { if (S_ISCHR(vnode->stream.type)) {
switch (op) { switch (op) {
case B_GET_GEOMETRY: case B_GET_GEOMETRY:
{ {
struct devfs_partition *partition = vnode->stream.u.dev.partition; struct devfs_partition *partition
= vnode->stream.u.dev.partition;
if (partition == NULL) if (partition == NULL)
break; break;
@@ -1670,13 +1687,15 @@ devfs_ioctl(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, ulong op,
case B_GET_PARTITION_INFO: case B_GET_PARTITION_INFO:
{ {
struct devfs_partition *partition = vnode->stream.u.dev.partition; struct devfs_partition *partition
= vnode->stream.u.dev.partition;
if (!S_ISCHR(vnode->stream.type) if (!S_ISCHR(vnode->stream.type)
|| partition == NULL || partition == NULL
|| length != sizeof(partition_info)) || length != sizeof(partition_info))
return B_BAD_VALUE; return B_BAD_VALUE;
return user_memcpy(buffer, &partition->info, sizeof(partition_info)); return user_memcpy(buffer, &partition->info,
sizeof(partition_info));
} }
case B_SET_PARTITION: case B_SET_PARTITION:
@@ -1730,8 +1749,8 @@ devfs_set_flags(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, int flags)
if (!S_ISCHR(vnode->stream.type)) if (!S_ISCHR(vnode->stream.type))
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
return vnode->stream.u.dev.info->control(cookie->device_cookie, flags & O_NONBLOCK ? return vnode->stream.u.dev.info->control(cookie->device_cookie,
B_SET_NONBLOCKING_IO : B_SET_BLOCKING_IO, NULL, 0); flags & O_NONBLOCK ? B_SET_NONBLOCKING_IO : B_SET_BLOCKING_IO, NULL, 0);
} }
@@ -1803,10 +1822,13 @@ devfs_read_pages(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, off_t pos,
|| cookie == NULL) || cookie == NULL)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
if (vnode->stream.u.dev.partition) if (vnode->stream.u.dev.partition) {
translate_partition_access(vnode->stream.u.dev.partition, pos, *_numBytes); translate_partition_access(vnode->stream.u.dev.partition, pos,
*_numBytes);
}
return vnode->stream.u.dev.info->read_pages(cookie->device_cookie, pos, vecs, count, _numBytes); return vnode->stream.u.dev.info->read_pages(cookie->device_cookie, pos,
vecs, count, _numBytes);
} }
@@ -1824,10 +1846,13 @@ devfs_write_pages(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, off_t pos,
|| cookie == NULL) || cookie == NULL)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
if (vnode->stream.u.dev.partition) if (vnode->stream.u.dev.partition) {
translate_partition_access(vnode->stream.u.dev.partition, pos, *_numBytes); translate_partition_access(vnode->stream.u.dev.partition, pos,
*_numBytes);
}
return vnode->stream.u.dev.info->write_pages(cookie->device_cookie, pos, vecs, count, _numBytes); return vnode->stream.u.dev.info->write_pages(cookie->device_cookie, pos,
vecs, count, _numBytes);
} }
@@ -1836,7 +1861,8 @@ devfs_read_stat(fs_volume _fs, fs_vnode _vnode, struct stat *stat)
{ {
struct devfs_vnode *vnode = (struct devfs_vnode *)_vnode; struct devfs_vnode *vnode = (struct devfs_vnode *)_vnode;
TRACE(("devfs_read_stat: vnode %p (%Ld), stat %p\n", vnode, vnode->id, stat)); TRACE(("devfs_read_stat: vnode %p (%Ld), stat %p\n", vnode, vnode->id,
stat));
stat->st_ino = vnode->id; stat->st_ino = vnode->id;
stat->st_size = 0; stat->st_size = 0;
@@ -1878,12 +1904,14 @@ devfs_read_stat(fs_volume _fs, fs_vnode _vnode, struct stat *stat)
static status_t static status_t
devfs_write_stat(fs_volume _fs, fs_vnode _vnode, const struct stat *stat, uint32 statMask) devfs_write_stat(fs_volume _fs, fs_vnode _vnode, const struct stat *stat,
uint32 statMask)
{ {
struct devfs *fs = (struct devfs *)_fs; struct devfs *fs = (struct devfs *)_fs;
struct devfs_vnode *vnode = (struct devfs_vnode *)_vnode; struct devfs_vnode *vnode = (struct devfs_vnode *)_vnode;
TRACE(("devfs_write_stat: vnode %p (0x%Lx), stat %p\n", vnode, vnode->id, stat)); TRACE(("devfs_write_stat: vnode %p (0x%Lx), stat %p\n", vnode, vnode->id,
stat));
// we cannot change the size of anything // we cannot change the size of anything
if (statMask & FS_WRITE_STAT_SIZE) if (statMask & FS_WRITE_STAT_SIZE)
@@ -1891,8 +1919,10 @@ devfs_write_stat(fs_volume _fs, fs_vnode _vnode, const struct stat *stat, uint32
RecursiveLocker locker(&fs->lock); RecursiveLocker locker(&fs->lock);
if (statMask & FS_WRITE_STAT_MODE) if (statMask & FS_WRITE_STAT_MODE) {
vnode->stream.type = (vnode->stream.type & ~S_IUMSK) | (stat->st_mode & S_IUMSK); vnode->stream.type = (vnode->stream.type & ~S_IUMSK)
| (stat->st_mode & S_IUMSK);
}
if (statMask & FS_WRITE_STAT_UID) if (statMask & FS_WRITE_STAT_UID)
vnode->uid = stat->st_uid; vnode->uid = stat->st_uid;
@@ -1990,7 +2020,8 @@ file_system_module_info gDeviceFileSystem = {
&devfs_create_dir, &devfs_create_dir,
NULL, // remove_dir NULL, // remove_dir
&devfs_open_dir, &devfs_open_dir,
&devfs_close, // same as for files - it does nothing for directories, anyway &devfs_close,
// same as for files - it does nothing for directories, anyway
&devfs_free_dir_cookie, &devfs_free_dir_cookie,
&devfs_read_dir, &devfs_read_dir,
&devfs_rewind_dir, &devfs_rewind_dir,
@@ -2024,7 +2055,8 @@ pnp_devfs_register_device(device_node_handle parent)
TRACE(("pnp_devfs_probe()\n")); TRACE(("pnp_devfs_probe()\n"));
if (sDeviceManager->get_attr_string(parent, PNP_DEVFS_FILENAME, &filename, true) != B_OK) { if (sDeviceManager->get_attr_string(parent, PNP_DEVFS_FILENAME,
&filename, true) != B_OK) {
dprintf("devfs: Item containing file name is missing\n"); dprintf("devfs: Item containing file name is missing\n");
status = B_ERROR; status = B_ERROR;
goto err1; goto err1;
@@ -2032,20 +2064,24 @@ pnp_devfs_register_device(device_node_handle parent)
TRACE(("Adding %s\n", filename)); TRACE(("Adding %s\n", filename));
status = sDeviceManager->register_device(parent, pnp_devfs_attrs, NULL, &node); status = sDeviceManager->register_device(parent, pnp_devfs_attrs, NULL,
&node);
if (status != B_OK || node == NULL) if (status != B_OK || node == NULL)
goto err1; goto err1;
// ToDo: this is a hack to get things working (init_driver() only works for registered nodes) // ToDo: this is a hack to get things working (init_driver() only
// works for registered nodes)
parent->registered = true; parent->registered = true;
pnp_devfs_driver_info *info; pnp_devfs_driver_info *info;
status = sDeviceManager->init_driver(parent, NULL, (driver_module_info **)&info, NULL); status = sDeviceManager->init_driver(parent, NULL,
(driver_module_info **)&info, NULL);
if (status != B_OK) if (status != B_OK)
goto err2; goto err2;
//add_device(device); //add_device(device);
status = publish_device(sDeviceFileSystem, filename, node, info, NULL, NULL, 0); status = publish_device(sDeviceFileSystem, filename, node, info, NULL,
NULL, 0);
if (status != B_OK) if (status != B_OK)
goto err3; goto err3;
//nudge(); //nudge();
@@ -2127,7 +2163,8 @@ pnp_devfs_std_ops(int32 op, ...)
{ {
switch (op) { switch (op) {
case B_MODULE_INIT: case B_MODULE_INIT:
return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager); return get_module(B_DEVICE_MANAGER_MODULE_NAME,
(module_info **)&sDeviceManager);
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
put_module(B_DEVICE_MANAGER_MODULE_NAME); put_module(B_DEVICE_MANAGER_MODULE_NAME);
@@ -2264,7 +2301,8 @@ devfs_publish_partition(const char *path, const partition_info *info)
return B_BAD_VALUE; return B_BAD_VALUE;
devfs_vnode *device; devfs_vnode *device;
status_t status = get_node_for_path(sDeviceFileSystem, info->device, &device); status_t status = get_node_for_path(sDeviceFileSystem, info->device,
&device);
if (status != B_OK) if (status != B_OK)
return status; return status;