1e07dc26bSmrg/*
2e07dc26bSmrg * Copyright (C) 2006-2017 Oracle Corporation
3e07dc26bSmrg *
4e07dc26bSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5e07dc26bSmrg * copy of this software and associated documentation files (the "Software"),
6e07dc26bSmrg * to deal in the Software without restriction, including without limitation
7e07dc26bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e07dc26bSmrg * and/or sell copies of the Software, and to permit persons to whom the
9e07dc26bSmrg * Software is furnished to do so, subject to the following conditions:
10e07dc26bSmrg *
11e07dc26bSmrg * The above copyright notice and this permission notice shall be included in
12e07dc26bSmrg * all copies or substantial portions of the Software.
13e07dc26bSmrg *
14e07dc26bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e07dc26bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e07dc26bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17e07dc26bSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18e07dc26bSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19e07dc26bSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20e07dc26bSmrg * OTHER DEALINGS IN THE SOFTWARE.
21e07dc26bSmrg */
22e07dc26bSmrg
23e07dc26bSmrg
24e07dc26bSmrg#ifndef ___VBox_Graphics_HGSMI_h
25e07dc26bSmrg#define ___VBox_Graphics_HGSMI_h
26e07dc26bSmrg
27e07dc26bSmrg#include "VBoxVideoIPRT.h"
28e07dc26bSmrg
29e07dc26bSmrg#include "HGSMIDefs.h"
30e07dc26bSmrg#include "HGSMIChannels.h"
31e07dc26bSmrg#include "HGSMIMemAlloc.h"
32e07dc26bSmrg
33e07dc26bSmrg/*
34e07dc26bSmrg * Basic mechanism for the HGSMI is to prepare and pass data buffer to the host and the guest.
35e07dc26bSmrg * Data inside these buffers are opaque for the HGSMI and are interpreted by higher levels.
36e07dc26bSmrg *
37e07dc26bSmrg * Every shared memory buffer passed between the guest/host has the following structure:
38e07dc26bSmrg *
39e07dc26bSmrg * HGSMIBUFFERHEADER header;
40e07dc26bSmrg * uint8_t data[header.u32BufferSize];
41e07dc26bSmrg * HGSMIBUFFERTAIL tail;
42e07dc26bSmrg *
43e07dc26bSmrg * Note: Offset of the 'header' in the memory is used for virtual hardware IO.
44e07dc26bSmrg *
45e07dc26bSmrg * Buffers are verifyed using the offset and the content of the header and the tail,
46e07dc26bSmrg * which are constant during a call.
47e07dc26bSmrg *
48e07dc26bSmrg * Invalid buffers are ignored.
49e07dc26bSmrg *
50e07dc26bSmrg * Actual 'data' is not verifyed, as it is expected that the data can be changed by the
51e07dc26bSmrg * called function.
52e07dc26bSmrg *
53e07dc26bSmrg * Since only the offset of the buffer is passed in a IO operation, the header and tail
54e07dc26bSmrg * must contain:
55e07dc26bSmrg *     * size of data in this buffer;
56e07dc26bSmrg *     * checksum for buffer verification.
57e07dc26bSmrg *
58e07dc26bSmrg * For segmented transfers:
59e07dc26bSmrg *     * the sequence identifier;
60e07dc26bSmrg *     * offset of the current segment in the sequence;
61e07dc26bSmrg *     * total bytes in the transfer.
62e07dc26bSmrg *
63e07dc26bSmrg * Additionally contains:
64e07dc26bSmrg *     * the channel ID;
65e07dc26bSmrg *     * the channel information.
66e07dc26bSmrg */
67e07dc26bSmrg
68e07dc26bSmrgtypedef struct HGSMIHEAP
69e07dc26bSmrg{
70e07dc26bSmrg    HGSMIAREA area; /* Description. */
71e07dc26bSmrg    HGSMIMADATA ma; /* Memory allocator */
72e07dc26bSmrg} HGSMIHEAP;
73e07dc26bSmrg
74e07dc26bSmrg/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
75e07dc26bSmrg#define HGSMI_NUMBER_OF_CHANNELS 0x100
76e07dc26bSmrg
77e07dc26bSmrg/* Channel handler called when the guest submits a buffer. */
78e07dc26bSmrgtypedef DECLCALLBACK(int) FNHGSMICHANNELHANDLER(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer);
79e07dc26bSmrgtypedef FNHGSMICHANNELHANDLER *PFNHGSMICHANNELHANDLER;
80e07dc26bSmrg
81e07dc26bSmrg/* Information about a handler: pfn + context. */
82e07dc26bSmrgtypedef struct _HGSMICHANNELHANDLER
83e07dc26bSmrg{
84e07dc26bSmrg    PFNHGSMICHANNELHANDLER pfnHandler;
85e07dc26bSmrg    void *pvHandler;
86e07dc26bSmrg} HGSMICHANNELHANDLER;
87e07dc26bSmrg
88e07dc26bSmrg/* Channel description. */
89e07dc26bSmrgtypedef struct _HGSMICHANNEL
90e07dc26bSmrg{
91e07dc26bSmrg    HGSMICHANNELHANDLER handler;       /* The channel handler. */
92e07dc26bSmrg    const char *pszName;               /* NULL for hardcoded channels or RTStrDup'ed name. */
93e07dc26bSmrg    uint8_t u8Channel;                 /* The channel id, equal to the channel index in the array. */
94e07dc26bSmrg    uint8_t u8Flags;                   /* HGSMI_CH_F_* */
95e07dc26bSmrg} HGSMICHANNEL;
96e07dc26bSmrg
97e07dc26bSmrgtypedef struct _HGSMICHANNELINFO
98e07dc26bSmrg{
99e07dc26bSmrg    HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS]; /* Channel handlers indexed by the channel id.
100e07dc26bSmrg                                                      * The array is accessed under the instance lock.
101e07dc26bSmrg                                                      */
102e07dc26bSmrg}  HGSMICHANNELINFO;
103e07dc26bSmrg
104e07dc26bSmrg
105e07dc26bSmrgRT_C_DECLS_BEGIN
106e07dc26bSmrg
107e07dc26bSmrgDECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void *pvBuffer)
108e07dc26bSmrg{
109e07dc26bSmrg    return (HGSMIBUFFERHEADER *)pvBuffer;
110e07dc26bSmrg}
111e07dc26bSmrg
112e07dc26bSmrgDECLINLINE(uint8_t *) HGSMIBufferDataFromPtr(void *pvBuffer)
113e07dc26bSmrg{
114e07dc26bSmrg    return (uint8_t *)pvBuffer + sizeof(HGSMIBUFFERHEADER);
115e07dc26bSmrg}
116e07dc26bSmrg
117e07dc26bSmrgDECLINLINE(HGSMIBUFFERTAIL *) HGSMIBufferTailFromPtr(void *pvBuffer,
118e07dc26bSmrg                                                     uint32_t u32DataSize)
119e07dc26bSmrg{
120e07dc26bSmrg    return (HGSMIBUFFERTAIL *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize);
121e07dc26bSmrg}
122e07dc26bSmrg
123e07dc26bSmrgDECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void)
124e07dc26bSmrg{
125e07dc26bSmrg    return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
126e07dc26bSmrg}
127e07dc26bSmrg
128e07dc26bSmrgDECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromData(const void *pvData)
129e07dc26bSmrg{
130e07dc26bSmrg    return (HGSMIBUFFERHEADER *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER));
131e07dc26bSmrg}
132e07dc26bSmrg
133e07dc26bSmrgDECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize)
134e07dc26bSmrg{
135e07dc26bSmrg    return HGSMIBufferMinimumSize() + u32DataSize;
136e07dc26bSmrg}
137e07dc26bSmrg
138e07dc26bSmrgDECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea,
139e07dc26bSmrg                                             const void *pv)
140e07dc26bSmrg{
141e07dc26bSmrg    return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base);
142e07dc26bSmrg}
143e07dc26bSmrg
144e07dc26bSmrgDECLINLINE(void *) HGSMIOffsetToPointer(const HGSMIAREA *pArea,
145e07dc26bSmrg                                        HGSMIOFFSET offBuffer)
146e07dc26bSmrg{
147e07dc26bSmrg    return pArea->pu8Base + (offBuffer - pArea->offBase);
148e07dc26bSmrg}
149e07dc26bSmrg
150e07dc26bSmrgDECLINLINE(uint8_t *) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea,
151e07dc26bSmrg                                                HGSMIOFFSET offBuffer)
152e07dc26bSmrg{
153e07dc26bSmrg    void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
154e07dc26bSmrg    return HGSMIBufferDataFromPtr(pvBuffer);
155e07dc26bSmrg}
156e07dc26bSmrg
157e07dc26bSmrgDECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea,
158e07dc26bSmrg                                                  void *pvData)
159e07dc26bSmrg{
160e07dc26bSmrg    HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
161e07dc26bSmrg    return HGSMIPointerToOffset(pArea, pHeader);
162e07dc26bSmrg}
163e07dc26bSmrg
164e07dc26bSmrgDECLINLINE(uint8_t *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea,
165e07dc26bSmrg                                                         HGSMIOFFSET offBuffer,
166e07dc26bSmrg                                                         uint16_t *pu16ChannelInfo)
167e07dc26bSmrg{
168e07dc26bSmrg    HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer(pArea, offBuffer);
169e07dc26bSmrg    *pu16ChannelInfo = pHeader->u16ChannelInfo;
170e07dc26bSmrg    return HGSMIBufferDataFromPtr(pHeader);
171e07dc26bSmrg}
172e07dc26bSmrg
173e07dc26bSmrguint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
174e07dc26bSmrg                       const HGSMIBUFFERHEADER *pHeader,
175e07dc26bSmrg                       const HGSMIBUFFERTAIL *pTail);
176e07dc26bSmrg
177e07dc26bSmrgint HGSMIAreaInitialize(HGSMIAREA *pArea,
178e07dc26bSmrg                        void *pvBase,
179e07dc26bSmrg                        HGSMISIZE cbArea,
180e07dc26bSmrg                        HGSMIOFFSET offBase);
181e07dc26bSmrg
182e07dc26bSmrgvoid HGSMIAreaClear(HGSMIAREA *pArea);
183e07dc26bSmrg
184e07dc26bSmrgDECLINLINE(bool) HGSMIAreaContainsOffset(const HGSMIAREA *pArea, HGSMIOFFSET off)
185e07dc26bSmrg{
186e07dc26bSmrg    return off >= pArea->offBase && off - pArea->offBase < pArea->cbArea;
187e07dc26bSmrg}
188e07dc26bSmrg
189e07dc26bSmrgDECLINLINE(bool) HGSMIAreaContainsPointer(const HGSMIAREA *pArea, const void *pv)
190e07dc26bSmrg{
191e07dc26bSmrg    return (uintptr_t)pv >= (uintptr_t)pArea->pu8Base && (uintptr_t)pv - (uintptr_t)pArea->pu8Base < pArea->cbArea;
192e07dc26bSmrg}
193e07dc26bSmrg
194e07dc26bSmrgHGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
195e07dc26bSmrg                                        HGSMIBUFFERHEADER *pHeader,
196e07dc26bSmrg                                        HGSMISIZE cbBuffer,
197e07dc26bSmrg                                        uint8_t u8Channel,
198e07dc26bSmrg                                        uint16_t u16ChannelInfo);
199e07dc26bSmrg
200e07dc26bSmrgint HGSMIHeapSetup(HGSMIHEAP *pHeap,
201e07dc26bSmrg                   void *pvBase,
202e07dc26bSmrg                   HGSMISIZE cbArea,
203e07dc26bSmrg                   HGSMIOFFSET offBase,
204e07dc26bSmrg                   const HGSMIENV *pEnv);
205e07dc26bSmrg
206e07dc26bSmrgvoid HGSMIHeapDestroy(HGSMIHEAP *pHeap);
207e07dc26bSmrg
208e07dc26bSmrgvoid *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
209e07dc26bSmrg                           HGSMISIZE cbBuffer);
210e07dc26bSmrg
211e07dc26bSmrgvoid HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
212e07dc26bSmrg                         void *pvBuf);
213e07dc26bSmrg
214e07dc26bSmrgvoid *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
215e07dc26bSmrg                     HGSMISIZE cbData,
216e07dc26bSmrg                     uint8_t u8Channel,
217e07dc26bSmrg                     uint16_t u16ChannelInfo);
218e07dc26bSmrg
219e07dc26bSmrgvoid HGSMIHeapFree(HGSMIHEAP *pHeap,
220e07dc26bSmrg                   void *pvData);
221e07dc26bSmrg
222e07dc26bSmrgDECLINLINE(const HGSMIAREA *) HGSMIHeapArea(HGSMIHEAP *pHeap)
223e07dc26bSmrg{
224e07dc26bSmrg    return &pHeap->area;
225e07dc26bSmrg}
226e07dc26bSmrg
227e07dc26bSmrgDECLINLINE(HGSMIOFFSET) HGSMIHeapOffset(HGSMIHEAP *pHeap)
228e07dc26bSmrg{
229e07dc26bSmrg    return HGSMIHeapArea(pHeap)->offBase;
230e07dc26bSmrg}
231e07dc26bSmrg
232e07dc26bSmrgDECLINLINE(HGSMISIZE) HGSMIHeapSize(HGSMIHEAP *pHeap)
233e07dc26bSmrg{
234e07dc26bSmrg    return HGSMIHeapArea(pHeap)->cbArea;
235e07dc26bSmrg}
236e07dc26bSmrg
237e07dc26bSmrgDECLINLINE(HGSMIOFFSET) HGSMIHeapBufferOffset(HGSMIHEAP *pHeap,
238e07dc26bSmrg                                              void *pvData)
239e07dc26bSmrg{
240e07dc26bSmrg    return HGSMIBufferOffsetFromData(HGSMIHeapArea(pHeap), pvData);
241e07dc26bSmrg}
242e07dc26bSmrg
243e07dc26bSmrgHGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
244e07dc26bSmrg                                   uint8_t u8Channel);
245e07dc26bSmrg
246e07dc26bSmrgint HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
247e07dc26bSmrg                         uint8_t u8Channel,
248e07dc26bSmrg                         const char *pszName,
249e07dc26bSmrg                         PFNHGSMICHANNELHANDLER pfnChannelHandler,
250e07dc26bSmrg                         void *pvChannelHandler);
251e07dc26bSmrg
252e07dc26bSmrgint HGSMIBufferProcess(const HGSMIAREA *pArea,
253e07dc26bSmrg                       HGSMICHANNELINFO *pChannelInfo,
254e07dc26bSmrg                       HGSMIOFFSET offBuffer);
255e07dc26bSmrgRT_C_DECLS_END
256e07dc26bSmrg
257e07dc26bSmrg#endif /* !___VBox_Graphics_HGSMI_h */
258e07dc26bSmrg
259