blob: 454671e86cb50ba6308119dd28945b8c8a989253 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "aoc_ipc_core.h"
#ifdef __KERNEL__
#include <asm/barrier.h>
#include <linux/string.h>
#define WRITE_BARRIER() wmb()
#elif defined(EFW)
#include "memory_barrier.h"
#define WRITE_BARRIER() MB()
#else
#include <stdint.h>
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
#define WRITE_BARRIER()
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define AOC_SERVICE_NAME_LENGTH 32
#define AOC_VERSION_LENGTH 48
#define AOC_SERVICE_FLAG_SYSTEM_MASK 0xffff0000
#define AOC_SERVICE_FLAG_RING 0x00010000
#define AOC_SERVICE_FLAG_RING_PUSH 0x01000000
#define AOC_SERVICE_TYPE_MASK 0x00070000
#define AOC_SERVICE_IRQ_MASK 0x00f80000
#define AOC_SERVICE_IRQ_SHIFT 19
enum AOC_SERVICE_TYPE {
AOC_SERVICE_TYPE_QUEUE = 0,
AOC_SERVICE_TYPE_RING,
AOC_SERVICE_TYPE_BUFFER,
};
#define AOC_MAGIC 0xA0C00A0C
struct aoc_control_block {
u32 magic;
u32 fw_version;
u32 hw_version;
u32 status;
u64 supported_features;
u32 services;
u32 service_size;
u32 services_offset;
u8 fw_version_name[AOC_VERSION_LENGTH];
u8 hw_version_name[AOC_VERSION_LENGTH];
u64 system_clock_offset;
} __attribute__((packed, aligned(4)));
struct aoc_ipc_memory_region {
u32 offset;
u32 size;
u32 slots;
u32 tx;
u32 rx;
u32 wp;
u32 rp;
} __attribute__((packed, aligned(4)));
enum REGION_COMM {
REGION_COMM_TX = 0,
REGION_COMM_RX,
REGION_COMM_TOT = 2
};
struct aoc_ipc_service_header {
char name[AOC_SERVICE_NAME_LENGTH];
u32 flags;
struct aoc_ipc_memory_region regions[2];
} __attribute__((packed, aligned(4)));
struct aoc_ipc_message_header {
u16 length;
u16 r1;
u16 r2;
u16 r3;
} __attribute__((packed));
size_t aoc_service_current_message_size(aoc_service *service, void *base,
aoc_direction dir);
size_t aoc_ring_bytes_available_to_read(aoc_service *service,
aoc_direction dir);
/* Returns the amount of data that can be written *without* overwriting any
* existing data. Writes will always succeed, even if this returns 0 */
size_t aoc_ring_bytes_available_to_write(aoc_service *service,
aoc_direction dir);
bool aoc_ring_flush_read_data(aoc_service *service, aoc_direction dir, size_t bytes_to_leave);
bool aoc_ring_reset_write_pointer(aoc_service *service, aoc_direction dir);
void *aoc_service_current_message_pointer(aoc_service *service, void *base, aoc_direction dir);
void *aoc_service_current_read_pointer(struct aoc_ipc_service_header *service,
void *base, aoc_direction dir);
void *aoc_service_current_write_pointer(struct aoc_ipc_service_header *service,
void *base, aoc_direction dir);
/* Convenience function to advance the indexes by 1 */
bool aoc_service_increment_write_index(aoc_service *service, aoc_direction dir);
bool aoc_service_increment_read_index(aoc_service *service, aoc_direction dir);
bool aoc_service_advance_write_index(aoc_service *service, aoc_direction dir,
u32 amount);
bool aoc_service_advance_read_index(aoc_service *service, aoc_direction dir,
u32 amount);
void *aoc_service_ring_base(aoc_service *service, void *base,
aoc_direction dir);
size_t aoc_service_ring_size(aoc_service *service, aoc_direction dir);
size_t aoc_service_ring_read_offset(aoc_service *service, aoc_direction dir);
size_t aoc_service_ring_write_offset(aoc_service *service, aoc_direction dir);
#ifdef __cplusplus
}
#endif