/*- * Copyright (c) 2016 Alexander Motin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _NTB_H_ #define _NTB_H_ #include "ntb_if.h" SYSCTL_DECL(_hw_ntb); int ntb_register_device(device_t ntb); int ntb_unregister_device(device_t ntb); int ntb_child_location(device_t dev, device_t child, struct sbuf *sb); int ntb_print_child(device_t dev, device_t child); bus_dma_tag_t ntb_get_dma_tag(device_t bus, device_t child); /* * ntb_link_event() - notify driver context of a change in link status * @ntb: NTB device context * * Notify the driver context that the link status may have changed. The driver * should call intb_link_is_up() to get the current status. */ void ntb_link_event(device_t ntb); /* * ntb_db_event() - notify driver context of a doorbell event * @ntb: NTB device context * @vector: Interrupt vector number * * Notify the driver context of a doorbell event. If hardware supports * multiple interrupt vectors for doorbells, the vector number indicates which * vector received the interrupt. The vector number is relative to the first * vector used for doorbells, starting at zero, and must be less than * ntb_db_vector_count(). The driver may call ntb_db_read() to check which * doorbell bits need service, and ntb_db_vector_mask() to determine which of * those bits are associated with the vector number. */ void ntb_db_event(device_t ntb, uint32_t vec); /** * ntb_port_number() - get the local port number * @ntb: NTB device context. * * Hardware driver returns local port number in compliance with topology. * * Return: the local port number */ int ntb_port_number(device_t ntb); /** * ntb_port_count() - get the number of peer device ports * @ntb: NTB device context. * * By default hardware driver supports just one peer device. * * Return: the number of peer ports */ int ntb_peer_port_count(device_t ntb); /** * ntb_peer_port_number() - get the peer port by given index * @ntb: NTB device context. * @idx: Peer port index (should be zero for now). * * By default hardware driver supports just one peer device, so this method * shall return the corresponding value. * * Return: the peer device port or an error number */ int ntb_peer_port_number(device_t ntb, int pidx); /* * ntb_peer_port_idx() - get the peer device port index by given port * number * @ntb: NTB device context. * @port: Peer port number * * By default hardware driver supports just one peer device, so given a * valid peer port number, the return value shall be zero. * * Return: the peer port index or an error number */ int ntb_peer_port_idx(device_t ntb, int port); /* * ntb_link_is_up() - get the current ntb link state * @ntb: NTB device context * @speed: OUT - The link speed expressed as PCIe generation number * @width: OUT - The link width expressed as the number of PCIe lanes * * RETURNS: true or false based on the hardware link state */ bool ntb_link_is_up(device_t ntb, enum ntb_speed *speed, enum ntb_width *width); /* * ntb_link_enable() - enable the link on the secondary side of the ntb * @ntb: NTB device context * @max_speed: The maximum link speed expressed as PCIe generation number[0] * @max_width: The maximum link width expressed as the number of PCIe lanes[0] * * Enable the link on the secondary side of the ntb. This can only be done * from the primary side of the ntb in primary or b2b topology. The ntb device * should train the link to its maximum speed and width, or the requested speed * and width, whichever is smaller, if supported. * * Return: Zero on success, otherwise an error number. * * [0]: Only NTB_SPEED_AUTO and NTB_WIDTH_AUTO are valid inputs; other speed * and width input will be ignored. */ int ntb_link_enable(device_t ntb, enum ntb_speed speed, enum ntb_width width); /* * ntb_link_disable() - disable the link on the secondary side of the ntb * @ntb: NTB device context * * Disable the link on the secondary side of the ntb. This can only be done * from the primary side of the ntb in primary or b2b topology. The ntb device * should disable the link. Returning from this call must indicate that a * barrier has passed, though with no more writes may pass in either direction * across the link, except if this call returns an error number. * * Return: Zero on success, otherwise an error number. */ int ntb_link_disable(device_t ntb); /* * get enable status of the link on the secondary side of the ntb */ bool ntb_link_enabled(device_t ntb); /* * ntb_set_ctx() - associate a driver context with an ntb device * @ntb: NTB device context * @ctx: Driver context * @ctx_ops: Driver context operations * * Associate a driver context and operations with a ntb device. The context is * provided by the client driver, and the driver may associate a different * context with each ntb device. * * Return: Zero if the context is associated, otherwise an error number. */ int ntb_set_ctx(device_t ntb, void *ctx, const struct ntb_ctx_ops *ctx_ops); /* * ntb_set_ctx() - get a driver context associated with an ntb device * @ntb: NTB device context * @ctx_ops: Driver context operations * * Get a driver context and operations associated with a ntb device. */ void * ntb_get_ctx(device_t ntb, const struct ntb_ctx_ops **ctx_ops); /* * ntb_clear_ctx() - disassociate any driver context from an ntb device * @ntb: NTB device context * * Clear any association that may exist between a driver context and the ntb * device. */ void ntb_clear_ctx(device_t ntb); /* * ntb_mw_count() - Get the number of memory windows available for KPI * consumers. * * (Excludes any MW wholly reserved for register access.) */ uint8_t ntb_mw_count(device_t ntb); /* * ntb_mw_get_range() - get the range of a memory window * @ntb: NTB device context * @idx: Memory window number * @base: OUT - the base address for mapping the memory window * @size: OUT - the size for mapping the memory window * @align: OUT - the base alignment for translating the memory window * @align_size: OUT - the size alignment for translating the memory window * * Get the range of a memory window. NULL may be given for any output * parameter if the value is not needed. The base and size may be used for * mapping the memory window, to access the peer memory. The alignment and * size may be used for translating the memory window, for the peer to access * memory on the local system. * * Return: Zero on success, otherwise an error number. */ int ntb_mw_get_range(device_t ntb, unsigned mw_idx, vm_paddr_t *base, caddr_t *vbase, size_t *size, size_t *align, size_t *align_size, bus_addr_t *plimit); /* * ntb_mw_set_trans() - set the translation of a memory window * @ntb: NTB device context * @idx: Memory window number * @addr: The dma address local memory to expose to the peer * @size: The size of the local memory to expose to the peer * * Set the translation of a memory window. The peer may access local memory * through the window starting at the address, up to the size. The address * must be aligned to the alignment specified by ntb_mw_get_range(). The size * must be aligned to the size alignment specified by ntb_mw_get_range(). The * address must be below the plimit specified by ntb_mw_get_range() (i.e. for * 32-bit BARs). * * Return: Zero on success, otherwise an error number. */ int ntb_mw_set_trans(device_t ntb, unsigned mw_idx, bus_addr_t addr, size_t size); /* * ntb_mw_clear_trans() - clear the translation of a memory window * @ntb: NTB device context * @idx: Memory window number * * Clear the translation of a memory window. The peer may no longer access * local memory through the window. * * Return: Zero on success, otherwise an error number. */ int ntb_mw_clear_trans(device_t ntb, unsigned mw_idx); /* * ntb_mw_get_wc - Get the write-combine status of a memory window * * Returns: Zero on success, setting *wc; otherwise an error number (e.g. if * idx is an invalid memory window). * * Mode is a VM_MEMATTR_* type. */ int ntb_mw_get_wc(device_t ntb, unsigned mw_idx, vm_memattr_t *mode); /* * ntb_mw_set_wc - Set the write-combine status of a memory window * * If 'mode' matches the current status, this does nothing and succeeds. Mode * is a VM_MEMATTR_* type. * * Returns: Zero on success, setting the caching attribute on the virtual * mapping of the BAR; otherwise an error number (e.g. if idx is an invalid * memory window, or if changing the caching attribute fails). */ int ntb_mw_set_wc(device_t ntb, unsigned mw_idx, vm_memattr_t mode); /* * ntb_spad_count() - get the total scratch regs usable * @ntb: pointer to ntb_softc instance * * This function returns the max 32bit scratchpad registers usable by the * upper layer. * * RETURNS: total number of scratch pad registers available */ uint8_t ntb_spad_count(device_t ntb); /* * ntb_spad_clear() - zero local scratch registers * @ntb: pointer to ntb_softc instance * * This functions overwrites all local scratchpad registers with zeroes. */ void ntb_spad_clear(device_t ntb); /* * ntb_spad_write() - write to the secondary scratchpad register * @ntb: pointer to ntb_softc instance * @idx: index to the scratchpad register, 0 based * @val: the data value to put into the register * * This function allows writing of a 32bit value to the indexed scratchpad * register. The register resides on the secondary (external) side. * * RETURNS: An appropriate ERRNO error value on error, or zero for success. */ int ntb_spad_write(device_t ntb, unsigned int idx, uint32_t val); /* * ntb_spad_read() - read from the primary scratchpad register * @ntb: pointer to ntb_softc instance * @idx: index to scratchpad register, 0 based * @val: pointer to 32bit integer for storing the register value * * This function allows reading of the 32bit scratchpad register on * the primary (internal) side. * * RETURNS: An appropriate ERRNO error value on error, or zero for success. */ int ntb_spad_read(device_t ntb, unsigned int idx, uint32_t *val); /* * ntb_peer_spad_write() - write to the secondary scratchpad register * @ntb: pointer to ntb_softc instance * @idx: index to the scratchpad register, 0 based * @val: the data value to put into the register * * This function allows writing of a 32bit value to the indexed scratchpad * register. The register resides on the secondary (external) side. * * RETURNS: An appropriate ERRNO error value on error, or zero for success. */ int ntb_peer_spad_write(device_t ntb, unsigned int idx, uint32_t val); /* * ntb_peer_spad_read() - read from the primary scratchpad register * @ntb: pointer to ntb_softc instance * @idx: index to scratchpad register, 0 based * @val: pointer to 32bit integer for storing the register value * * This function allows reading of the 32bit scratchpad register on * the primary (internal) side. * * RETURNS: An appropriate ERRNO error value on error, or zero for success. */ int ntb_peer_spad_read(device_t ntb, unsigned int idx, uint32_t *val); /* * ntb_db_valid_mask() - get a mask of doorbell bits supported by the ntb * @ntb: NTB device context * * Hardware may support different number or arrangement of doorbell bits. * * Return: A mask of doorbell bits supported by the ntb. */ uint64_t ntb_db_valid_mask(device_t ntb); /* * ntb_db_vector_count() - get the number of doorbell interrupt vectors * @ntb: NTB device context. * * Hardware may support different number of interrupt vectors. * * Return: The number of doorbell interrupt vectors. */ int ntb_db_vector_count(device_t ntb); /* * ntb_db_vector_mask() - get a mask of doorbell bits serviced by a vector * @ntb: NTB device context * @vector: Doorbell vector number * * Each interrupt vector may have a different number or arrangement of bits. * * Return: A mask of doorbell bits serviced by a vector. */ uint64_t ntb_db_vector_mask(device_t ntb, uint32_t vector); /* * ntb_peer_db_addr() - address and size of the peer doorbell register * @ntb: NTB device context. * @db_addr: OUT - The address of the peer doorbell register. * @db_size: OUT - The number of bytes to write the peer doorbell register. * * Return the address of the peer doorbell register. This may be used, for * example, by drivers that offload memory copy operations to a dma engine. * The drivers may wish to ring the peer doorbell at the completion of memory * copy operations. For efficiency, and to simplify ordering of operations * between the dma memory copies and the ringing doorbell, the driver may * append one additional dma memory copy with the doorbell register as the * destination, after the memory copy operations. * * Return: Zero on success, otherwise an error number. * * Note that writing the peer doorbell via a memory window will *not* generate * an interrupt on the remote host; that must be done separately. */ int ntb_peer_db_addr(device_t ntb, bus_addr_t *db_addr, vm_size_t *db_size); /* * ntb_db_clear() - clear bits in the local doorbell register * @ntb: NTB device context. * @db_bits: Doorbell bits to clear. * * Clear bits in the local doorbell register, arming the bits for the next * doorbell. * * Return: Zero on success, otherwise an error number. */ void ntb_db_clear(device_t ntb, uint64_t bits); /* * ntb_db_clear_mask() - clear bits in the local doorbell mask * @ntb: NTB device context. * @db_bits: Doorbell bits to clear. * * Clear bits in the local doorbell mask register, allowing doorbell interrupts * from being generated for those doorbell bits. If a doorbell bit is already * set at the time the mask is cleared, and the corresponding mask bit is * changed from set to clear, then the ntb driver must ensure that * ntb_db_event() is called. If the hardware does not generate the interrupt * on clearing the mask bit, then the driver must call ntb_db_event() anyway. * * Return: Zero on success, otherwise an error number. */ void ntb_db_clear_mask(device_t ntb, uint64_t bits); /* * ntb_db_read() - read the local doorbell register * @ntb: NTB device context. * * Read the local doorbell register, and return the bits that are set. * * Return: The bits currently set in the local doorbell register. */ uint64_t ntb_db_read(device_t ntb); /* * ntb_db_set_mask() - set bits in the local doorbell mask * @ntb: NTB device context. * @db_bits: Doorbell mask bits to set. * * Set bits in the local doorbell mask register, preventing doorbell interrupts * from being generated for those doorbell bits. Bits that were already set * must remain set. * * Return: Zero on success, otherwise an error number. */ void ntb_db_set_mask(device_t ntb, uint64_t bits); /* * ntb_peer_db_set() - Set the doorbell on the secondary/external side * @ntb: pointer to ntb_softc instance * @bit: doorbell bits to ring * * This function allows triggering of a doorbell on the secondary/external * side that will initiate an interrupt on the remote host */ void ntb_peer_db_set(device_t ntb, uint64_t bits); #endif /* _NTB_H_ */