/* * hl_gw.c -- Hostlink gateway, low-level hostlink functions. * * Copyright (c) 2024 Synopsys Inc. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * */ #include "hl_gw.h" #define HL_VERSION 1 /* * Maximum message size without service information, * see also HL_PAYLOAD_RESERVED. */ #ifndef HL_IOCHUNK #define HL_IOCHUNK 1024 #endif /* * Each syscall argument have 4 bytes of service information in hostlink * protocol (2 bytes for type and 2 for size). Here we reserve space for * 32 arguments. */ #define HL_PAYLOAD_RESERVED (32 * 4) /* "No message here" mark. */ #define HL_NOADDRESS 0xFFFFFFFF /* Hostlink gateway structure. */ struct _hl_hdr { uint32_t version; /* Current version is 1. */ uint32_t target2host_addr; /* Packet address from target to host. */ uint32_t host2target_addr; /* Packet address from host to target. */ uint32_t buf_addr; /* Address for host to write answer. */ uint32_t payload_size; /* Buffer size without packet header. */ uint32_t options; /* For future use. */ uint32_t break_to_mon_addr; /* For future use. */ } __uncached __packed; /* Hostlink packet header. */ struct _hl_pkt_hdr { uint32_t packet_id; /* Packet id. Always set to 1 here. */ uint32_t total_size; /* Size of packet including header. */ uint32_t priority; /* For future use. */ uint32_t type; /* For future use. */ uint32_t checksum; /* For future use. */ } __uncached __packed; /* Main hostlink structure. */ struct _hl { volatile struct _hl_hdr hdr; /* General hostlink information. */ /* Start of the hostlink buffer. */ volatile struct _hl_pkt_hdr pkt_hdr; volatile char payload[HL_IOCHUNK + HL_PAYLOAD_RESERVED]; } __aligned (HL_MAX_DCACHE_LINE) __uncached __packed; /* * Main structure. Do not rename because simulator will look for the * '__HOSTLINK__' symbol. */ volatile struct _hl __HOSTLINK__ = { .hdr = { .version = 1 , .target2host_addr = HL_NOADDRESS } }; /* Get hostlink payload pointer. */ volatile __uncached void * _hl_payload (void) { return (volatile __uncached void *) &__HOSTLINK__.payload[0]; } /* Get hostlink payload size (iochunk + reserved space). */ static uint32_t _hl_payload_size (void) { return sizeof (__HOSTLINK__.payload); } /* Get used space size in the payload. */ static uint32_t _hl_payload_used (volatile __uncached void *p) { return (volatile __uncached char *) p - (volatile __uncached char *) _hl_payload (); } /* Fill hostlink packet header. */ static void _hl_pkt_init (volatile __uncached struct _hl_pkt_hdr *pkt, int size) { pkt->packet_id = 1; pkt->total_size = ALIGN (size, 4) + sizeof (*pkt); pkt->priority = 0; pkt->type = 0; pkt->checksum = 0; } /* Get hostlink iochunk size. */ uint32_t _hl_iochunk_size (void) { return HL_IOCHUNK; } /* Get free space size in the payload. */ uint32_t _hl_payload_left (volatile __uncached void *p) { return _hl_payload_size () - _hl_payload_used (p); } /* Send hostlink packet to the host. */ void _hl_send (volatile __uncached void *p) { volatile __uncached struct _hl_hdr *hdr = &__HOSTLINK__.hdr; volatile __uncached struct _hl_pkt_hdr *pkt_hdr = &__HOSTLINK__.pkt_hdr; _hl_pkt_init (pkt_hdr, _hl_payload_used (p)); hdr->buf_addr = (uint32_t) pkt_hdr; hdr->payload_size = _hl_payload_size (); hdr->host2target_addr = HL_NOADDRESS; hdr->version = HL_VERSION; hdr->options = 0; hdr->break_to_mon_addr = 0; /* This tells the debugger we have a command. * It is responsibility of debugger to set this back to HL_NOADDRESS * after receiving the packet. * Please note that we don't wait here because some implementations * use _hl_blockedPeek() function as a signal that we send a messege. */ hdr->target2host_addr = hdr->buf_addr; } /* * Wait for host response and return pointer to hostlink payload. * Symbol _hl_blockedPeek() is used by the simulator as message signal. */ volatile __uncached char * __noinline _hl_blockedPeek (void) { while (__HOSTLINK__.hdr.host2target_addr == HL_NOADDRESS) { /* TODO: Timeout. */ } return _hl_payload (); } /* Get message from host. */ volatile __uncached char * _hl_recv (void) { return _hl_blockedPeek (); } /* Mark hostlink buffer as "No message here". */ void _hl_delete (void) { __HOSTLINK__.hdr.target2host_addr = HL_NOADDRESS; }