|  | // Copyright 2017 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef LIB_ASYNC_DISPATCHER_H_ | 
|  | #define LIB_ASYNC_DISPATCHER_H_ | 
|  |  | 
|  | #include <zircon/compiler.h> | 
|  | #include <zircon/syscalls/port.h> | 
|  | #include <zircon/types.h> | 
|  |  | 
|  | __BEGIN_CDECLS | 
|  |  | 
|  | // Dispatcher interface for performing asynchronous operations. | 
|  | // There may be multiple implementations of this interface. | 
|  | typedef struct async_dispatcher async_dispatcher_t; | 
|  |  | 
|  | // Forward declarations for asynchronous operation structures. | 
|  | typedef struct async_guest_bell_trap async_guest_bell_trap_t; | 
|  | typedef struct async_wait async_wait_t; | 
|  | typedef struct async_task async_task_t; | 
|  | typedef struct async_receiver async_receiver_t; | 
|  | typedef struct async_irq async_irq_t; | 
|  | typedef struct async_paged_vmo async_paged_vmo_t; | 
|  |  | 
|  | // Private state owned by the asynchronous dispatcher. | 
|  | // This allows the dispatcher to associate a small amount of state with pending | 
|  | // asynchronous operations without having to allocate additional heap storage of | 
|  | // its own. | 
|  | // | 
|  | // Clients must initialize the contents of this structure to zero using | 
|  | // |ASYNC_STATE_INIT| or with calloc, memset, or a similar means. | 
|  | typedef struct { | 
|  | uintptr_t reserved[2]; | 
|  | } async_state_t; | 
|  |  | 
|  | #define ASYNC_STATE_INIT \ | 
|  | { 0u, 0u } | 
|  |  | 
|  | // Asynchronous dispatcher interface. | 
|  | // | 
|  | // Clients should not call into this interface directly: use the wrapper functions | 
|  | // declared in other header files, such as |async_begin_wait()| in <lib/async/wait.h>. | 
|  | // See the documentation of those functions for details about each method's purpose | 
|  | // and behavior. | 
|  | // | 
|  | // This interface consists of several groups of methods: | 
|  | // | 
|  | // - Timing: |now| | 
|  | // - Waiting for signals: |begin_wait|, |cancel_wait| | 
|  | // - Posting tasks: |post_task|, |cancel_task| | 
|  | // - Queuing packets: |queue_packet| | 
|  | // - Virtual machine operations: |set_guest_bell_trap| | 
|  | // | 
|  | // To preserve binary compatibility, each successive version of this interface | 
|  | // is guaranteed to be backwards-compatible with clients of earlier versions. | 
|  | // New methods must only be added by extending the structure at the end and | 
|  | // declaring a new version number.  Do not reorder the declarations or modify | 
|  | // existing versions. | 
|  | // | 
|  | // Implementations of this interface must provide valid (non-null) function pointers | 
|  | // for every method declared in the interface version they support.  Unsupported | 
|  | // methods must return |ZX_ERR_NOT_SUPPORTED| and have no other side-effects. | 
|  | // Furthermore, if an implementation supports one method of a group, such as |begin_wait|, | 
|  | // then it must also support the other methods of the group, such as |cancel_wait|. | 
|  | // | 
|  | // Many clients assume that the dispatcher interface is fully implemented and may | 
|  | // fail to work with dispatchers that do not support the methods they need. | 
|  | // Therefore general-purpose dispatcher implementations are encouraged to support | 
|  | // the whole interface to ensure broad compatibility. | 
|  | typedef uint32_t async_ops_version_t; | 
|  |  | 
|  | #define ASYNC_OPS_V1 ((async_ops_version_t)1) | 
|  | #define ASYNC_OPS_V2 ((async_ops_version_t)2) | 
|  |  | 
|  | typedef struct async_ops { | 
|  | // The interface version number, e.g. |ASYNC_OPS_V1|. | 
|  | async_ops_version_t version; | 
|  |  | 
|  | // Reserved for future expansion, set to zero. | 
|  | uint32_t reserved; | 
|  |  | 
|  | // Operations supported by |ASYNC_OPS_V1|. | 
|  | struct v1 { | 
|  | // See |async_now()| for details. | 
|  | zx_time_t (*now)(async_dispatcher_t* dispatcher); | 
|  | // See |async_begin_wait()| for details. | 
|  | zx_status_t (*begin_wait)(async_dispatcher_t* dispatcher, async_wait_t* wait); | 
|  | // See |async_cancel_wait()| for details. | 
|  | zx_status_t (*cancel_wait)(async_dispatcher_t* dispatcher, async_wait_t* wait); | 
|  | // See |async_post_task()| for details. | 
|  | zx_status_t (*post_task)(async_dispatcher_t* dispatcher, async_task_t* task); | 
|  | // See |async_cancel_task()| for details. | 
|  | zx_status_t (*cancel_task)(async_dispatcher_t* dispatcher, async_task_t* task); | 
|  | // See |async_queue_packet()| for details. | 
|  | zx_status_t (*queue_packet)(async_dispatcher_t* dispatcher, async_receiver_t* receiver, | 
|  | const zx_packet_user_t* data); | 
|  | // See |async_set_guest_bell_trap()| for details. | 
|  | zx_status_t (*set_guest_bell_trap)(async_dispatcher_t* dispatcher, | 
|  | async_guest_bell_trap_t* trap, zx_handle_t guest, | 
|  | zx_vaddr_t addr, size_t length); | 
|  | } v1; | 
|  | struct v2 { | 
|  | zx_status_t (*bind_irq)(async_dispatcher_t* dispatcher, async_irq_t* irq); | 
|  | zx_status_t (*unbind_irq)(async_dispatcher_t* dispatcher, async_irq_t* irq); | 
|  | zx_status_t (*create_paged_vmo)(async_dispatcher_t* dispatcher, async_paged_vmo_t* paged_vmo, | 
|  | uint32_t options, zx_handle_t pager, uint64_t vmo_size, | 
|  | zx_handle_t* vmo_out); | 
|  | zx_status_t (*detach_paged_vmo)(async_dispatcher_t* dispatcher, async_paged_vmo_t* paged_vmo); | 
|  | } v2; | 
|  | } async_ops_t; | 
|  |  | 
|  | struct async_dispatcher { | 
|  | const async_ops_t* ops; | 
|  | }; | 
|  |  | 
|  | __END_CDECLS | 
|  |  | 
|  | #endif  // LIB_ASYNC_DISPATCHER_H_ |