/* queue an irp to the device */ static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, const async_data_t *async_data, int blocking ) { obj_handle_t handle = 0; if (blocking && !(handle = alloc_handle( current->process, irp, SYNCHRONIZE, 0 ))) return 0; if (!(irp->async = fd_queue_async( file->fd, async_data, ASYNC_TYPE_WAIT ))) { if (handle) close_handle( current->process, handle ); return 0; } irp->user_arg = async_data->arg; add_irp_to_queue( file, irp, current ); set_error( STATUS_PENDING ); return handle; }
static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data, int blocking, const void *data, data_size_t size ) { struct device *device = get_fd_user( fd ); struct ioctl_call *ioctl; obj_handle_t handle; if (!device->manager) /* it has been deleted */ { set_error( STATUS_FILE_DELETED ); return 0; } if (!(ioctl = create_ioctl( device, code, data, size, get_reply_max_size() ))) return 0; ioctl->thread = (struct thread *)grab_object( current ); ioctl->user_arg = async_data->arg; if (!(handle = alloc_handle( current->process, ioctl, SYNCHRONIZE, 0 ))) { release_object( ioctl ); return 0; } if (!(ioctl->async = fd_queue_async( device->fd, async_data, ASYNC_TYPE_WAIT ))) { close_handle( current->process, handle ); release_object( ioctl ); return 0; } list_add_tail( &device->requests, &ioctl->dev_entry ); list_add_tail( &device->manager->requests, &ioctl->mgr_entry ); if (list_head( &device->manager->requests ) == &ioctl->mgr_entry) /* first one */ wake_up( &device->manager->obj, 0 ); /* don't release ioctl since it is now queued in the device */ set_error( STATUS_PENDING ); return handle; }