Commit | Line | Data |
---|---|---|
800f879a AT |
1 | /* |
2 | * Copyright 2010-2017 Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License, version 2, | |
6 | * as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * Disclaimer: The codes contained in these modules may be specific to | |
14 | * the Intel Software Development Platform codenamed Knights Ferry, | |
15 | * and the Intel product codenamed Knights Corner, and are not backward | |
16 | * compatible with other Intel products. Additionally, Intel will NOT | |
17 | * support the codes or instruction set in future products. | |
18 | * | |
19 | * Intel offers no warranty of any kind regarding the code. This code is | |
20 | * licensed on an "AS IS" basis and Intel is not obligated to provide | |
21 | * any support, assistance, installation, training, or other services | |
22 | * of any kind. Intel is also not obligated to provide any updates, | |
23 | * enhancements or extensions. Intel specifically disclaims any warranty | |
24 | * of merchantability, non-infringement, fitness for any particular | |
25 | * purpose, and any other warranty. | |
26 | * | |
27 | * Further, Intel disclaims all liability of any kind, including but | |
28 | * not limited to liability for infringement of any proprietary rights, | |
29 | * relating to the use of the code, even if Intel is notified of the | |
30 | * possibility of such liability. Except as expressly stated in an Intel | |
31 | * license agreement provided with this code and agreed upon with Intel, | |
32 | * no license, express or implied, by estoppel or otherwise, to any | |
33 | * intellectual property rights is granted herein. | |
34 | */ | |
35 | ||
36 | /* | |
37 | Description: This is a generic ring buffer implementation to be used by | |
38 | anyone who needs a ring buffer. The ring buffer is maipulated | |
39 | using Read and Write functions. These functions perform all of | |
40 | the necessary space checks and only complete the operation if | |
41 | if the requested number of items can be read or written. A | |
42 | return value of false indicates that either the ring buffer | |
43 | contains less then the requested number of items (for Read) or | |
44 | there isn't enough space left in the ring buffer (for Write). | |
45 | */ | |
46 | ||
47 | #ifndef _MICHOST_RING_BUFFER_DEFINE | |
48 | ||
49 | #define _MICHOST_RING_BUFFER_DEFINE | |
50 | ||
51 | // | |
52 | // Requirements: | |
53 | // Ring base should be already aligned properly | |
54 | // Ring size should be just multiple of the alignment size | |
55 | // All packets should be at least multiple of 4 bytes for the purpose of padding | |
56 | // | |
57 | ||
58 | #define RINGBUFFER_ALIGNMENT_SIZE 64 // in byte | |
59 | ||
60 | typedef struct _ringbuffer | |
61 | { | |
62 | uint8_t *ringbuff_ptr; | |
63 | volatile uint32_t *readptr; // Points to the read offset | |
64 | volatile uint32_t *writeptr; // Points to the write offset | |
65 | uint32_t ringbuffsize; | |
66 | uint32_t curr_readoffset; // cache it to improve performance. | |
67 | uint32_t curr_writeoffset; // cache it to improve performance. | |
68 | uint32_t old_readoffset; | |
69 | uint32_t old_writeoffset; | |
70 | } ringbuffer; | |
71 | ||
72 | // Commands common across all ring buffers | |
73 | typedef enum _rb_cmdopcode | |
74 | { | |
75 | // note: don't use 0, because the ring buffer | |
76 | // is initialized to a bunch of 0's that aren't really commands. | |
77 | MIC_RBCT_ERROR = 0x0, // an error has occurred if encountered | |
78 | MIC_RBCT_NOP, // Used to skip empty space in the ringbuffer. | |
79 | MIC_RBCT_DMAEXEC, // DMA buffer to transfer/execute | |
80 | MIC_RBCT_SHUTDOWN, // bus power-down eminent | |
81 | MIC_RBCT_CREATESTDPROCESS, // Launches an executable on the ramdisk. | |
82 | MIC_RBCT_CREATENATIVEPROCESS, // Launches a native process. | |
83 | // NRFIX : not implemented. If native apps are launched by loading shared | |
84 | // libraries(DLLs) into a standard stub app then this command goes away. | |
85 | MIC_RBCT_DESTROYPROCESS, // Destroys a process. | |
86 | MIC_RBCT_VIRTUALALLOC, // Creates a uOS virtual address range | |
87 | MIC_RBCT_MAPHOSTMEMORY, // Used by implement host kernel mode driver services | |
88 | MIC_RBCT_UNMAPHOSTMEMORY, // Unmaps host memory | |
89 | MIC_RBCT_UOSESCAPE, // Used to pass uOS escapes from the host | |
90 | MIC_RBCT_RESERVED1, // Reserved for future use | |
91 | MIC_RBCT_RESERVED2, // Reserved for future use | |
92 | MIC_RBCT_UPLOADSTDAPPLICATION, // Uploads a standard application to the uOS | |
93 | MIC_RBCT_CREATEUOSRESOURCE, // Creates a DPT page cache | |
94 | MIC_RBCT_DESTROYUOSRESOURCE, // Destroys a DPT page cache | |
95 | MIC_RBCT_RESERVE_RING_BANDWIDTH_DBOX_TRAFFIC, // Reserves a ring bandwidth for DBOX traffic | |
96 | ||
97 | // Following commands are from MIC->Host (CRBT => CPU ring buffer.) | |
98 | MIC_CRBT_LOG_INFO, // Host logs information sent by the uOS. | |
99 | ||
100 | // Always make these the last ones in the list | |
101 | #if defined(MIC_DEBUG) || defined(ENABLE_GFXDEBUG) | |
102 | MIC_RBCT_READPHYSICALMEMORY = 0x8000, // Used by debug tools to read memory on the device | |
103 | MIC_RBCT_WRITEPHYSICALMEMORY, // Used by debug tools to write memory on the device | |
104 | #endif // defined(MIC_DEBUG) || defined(ENABLE_GFXDEBUG) | |
105 | MIC_RBCT_CMD_MAX // No valid OpCodes above this one | |
106 | }ringbuff_cmdop; | |
107 | ||
108 | typedef struct _ringbuff_cmdhdr | |
109 | { | |
110 | ringbuff_cmdop opcode:16; | |
111 | uint32_t size:16; | |
112 | }ringbuff_cmdhdr; | |
113 | ||
114 | #ifdef __cplusplus | |
115 | extern "C" { | |
116 | #endif | |
117 | ||
118 | //--------------------------------- | |
119 | // methods used by both | |
120 | //--------------------------------- | |
121 | // initialize cached ring buffer structure | |
122 | void rb_initialize(ringbuffer* ringbuff, volatile uint32_t* readptr, | |
123 | volatile uint32_t* writeptr, void *buff, const uint32_t size); | |
124 | ||
125 | //--------------------------------- | |
126 | // writer-only methods | |
127 | //--------------------------------- | |
128 | // write a new command. Must follow with fence/MMIO, then RingBufferCommit() | |
129 | int rb_write(ringbuffer* ringbuff, ringbuff_cmdhdr* cmd_header); | |
130 | // After write(), do an mfence(), an MMIO write to serialize, then Commit() | |
131 | void rb_commit(ringbuffer* ringbuff); | |
132 | // used on power state change to reset cached pointers | |
133 | void rb_reset(ringbuffer* ringbuff); | |
134 | // used to determine the largest possible command that could be sent next | |
135 | uint32_t rb_get_available_space(ringbuffer* ringbuff); | |
136 | ||
137 | // TODO: It may be more optimal to have "Reserve" function exposed to the client | |
138 | // instead of requiring it to create a command that will be copied into the ring buffer. | |
139 | ||
140 | ||
141 | //--------------------------------- | |
142 | // reader-only methods | |
143 | //--------------------------------- | |
144 | // uses (updates) the cached read pointer to get the next command, so writer doesn't | |
145 | // see the command as consumed | |
146 | ringbuff_cmdhdr* rb_get_next_cmd(ringbuffer* ringbuff); | |
147 | // updates the control block read pointer, which will be visible to the writer so it | |
148 | // can re-use the space | |
149 | void rb_update_readptr(ringbuffer* ringbuff, ringbuff_cmdhdr* cmd_header); | |
150 | // reader skips all commands, updating its next read offset | |
151 | void rb_skip_to_offset(ringbuffer* ringbuff, uint32_t new_readptr); | |
152 | ||
153 | // uOS used this method to determine if RingBuffer is empty or not before attempting | |
154 | // to fetch command out of ring buffer If ringbuffer is empty, means uOS would have | |
155 | // fetched it earlier. | |
156 | uint32_t rb_empty(ringbuffer* ringbuff); | |
157 | ||
158 | // only used by host simulator | |
159 | void rb_sync(ringbuffer* ringbuff); | |
160 | ||
161 | #ifdef __cplusplus | |
162 | } | |
163 | #endif | |
164 | ||
165 | #ifdef __LINUX_GPL__ | |
166 | //============================================================================== | |
167 | // FUNCTION: AlignLow | |
168 | // | |
169 | // DESCRIPTION: Returns trunk(in_data / in_granularity) * in_granularity | |
170 | // | |
171 | // PARAMETERS: | |
172 | // in_data - Data to be aligned | |
173 | // in_granularity - Alignment chunk size - must be a power of 2 | |
174 | #if defined(__cplusplus) | |
175 | template <typename TData> | |
176 | #else // no C++ | |
177 | #define TData uint64_t | |
178 | #endif // if C++ | |
179 | ||
180 | static inline TData AlignLow(TData in_data, uintptr_t in_granularity) | |
181 | { | |
182 | TData mask = (TData)(in_granularity-1); // 64 -> 0x3f | |
183 | ||
184 | // floor to granularity | |
185 | TData low = in_data & ~mask; | |
186 | ||
187 | return low; | |
188 | } | |
189 | ||
190 | #if !defined(__cplusplus) | |
191 | #undef TData | |
192 | #endif // if no C++ | |
193 | #endif // __LINUX_GPL_ | |
194 | ||
195 | #endif //_MICHOST_RING_BUFFER_DEFINE |