]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/liquidio/base/lio_mem_ops.c
MFH @ r323558.
[FreeBSD/FreeBSD.git] / sys / dev / liquidio / base / lio_mem_ops.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Cavium, Inc. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*$FreeBSD$*/
34
35 #include "lio_bsd.h"
36 #include "lio_common.h"
37 #include "lio_droq.h"
38 #include "lio_iq.h"
39 #include "lio_response_manager.h"
40 #include "lio_device.h"
41 #include "lio_mem_ops.h"
42
43 #define MEMOPS_IDX   LIO_MAX_BAR1_MAP_INDEX
44
45 #if BYTE_ORDER == BIG_ENDIAN
46 static inline void
47 lio_toggle_bar1_swapmode(struct octeon_device *oct, uint32_t idx)
48 {
49         uint32_t mask;
50
51         mask = oct->fn_list.bar1_idx_read(oct, idx);
52         mask = (mask & 0x2) ? (mask & ~2) : (mask | 2);
53         oct->fn_list.bar1_idx_write(oct, idx, mask);
54 }
55
56 #else   /* BYTE_ORDER != BIG_ENDIAN */
57 #define lio_toggle_bar1_swapmode(oct, idx)
58 #endif  /* BYTE_ORDER == BIG_ENDIAN */
59
60 static inline void
61 lio_write_bar1_mem8(struct octeon_device *oct, uint32_t reg, uint64_t val)
62 {
63
64         bus_space_write_1(oct->mem_bus_space[1].tag,
65                           oct->mem_bus_space[1].handle, reg, val);
66 }
67
68 static inline uint64_t
69 lio_read_bar1_mem64(struct octeon_device *oct, uint32_t reg)
70 {
71
72         return (bus_space_read_8(oct->mem_bus_space[1].tag,
73                                  oct->mem_bus_space[1].handle, reg));
74 }
75
76 static inline void
77 lio_write_bar1_mem64(struct octeon_device *oct, uint32_t reg, uint64_t val)
78 {
79
80         bus_space_write_8(oct->mem_bus_space[1].tag,
81                           oct->mem_bus_space[1].handle, reg, val);
82 }
83
84 static void
85 lio_pci_fastwrite(struct octeon_device *oct, uint32_t offset,
86                   uint8_t *hostbuf, uint32_t len)
87 {
88
89         while ((len) && ((unsigned long)offset) & 7) {
90                 lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
91                 len--;
92         }
93
94         lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
95
96         while (len >= 8) {
97                 lio_write_bar1_mem64(oct, offset, *((uint64_t *)hostbuf));
98                 offset += 8;
99                 hostbuf += 8;
100                 len -= 8;
101         }
102
103         lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
104
105         while (len--)
106                 lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
107 }
108
109 static inline uint64_t
110 lio_read_bar1_mem8(struct octeon_device *oct, uint32_t reg)
111 {
112
113         return (bus_space_read_1(oct->mem_bus_space[1].tag,
114                                  oct->mem_bus_space[1].handle, reg));
115 }
116
117 static void
118 lio_pci_fastread(struct octeon_device *oct, uint32_t offset,
119                  uint8_t *hostbuf, uint32_t len)
120 {
121
122         while ((len) && ((unsigned long)offset) & 7) {
123                 *(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
124                 len--;
125         }
126
127         lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
128
129         while (len >= 8) {
130                 *((uint64_t *)hostbuf) = lio_read_bar1_mem64(oct, offset);
131                 offset += 8;
132                 hostbuf += 8;
133                 len -= 8;
134         }
135
136         lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
137
138         while (len--)
139                 *(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
140 }
141
142 /* Core mem read/write with temporary bar1 settings. */
143 /* op = 1 to read, op = 0 to write. */
144 static void
145 lio_pci_rw_core_mem(struct octeon_device *oct, uint64_t addr,
146                     uint8_t *hostbuf, uint32_t len, uint32_t op)
147 {
148         uint64_t        static_mapping_base;
149         uint32_t        copy_len = 0, index_reg_val = 0;
150         uint32_t        offset;
151
152         static_mapping_base = oct->console_nb_info.dram_region_base;
153
154         if (static_mapping_base && static_mapping_base ==
155             (addr & 0xFFFFFFFFFFC00000ULL)) {
156                 int     bar1_index = oct->console_nb_info.bar1_index;
157
158                 offset = (bar1_index << 22) + (addr & 0x3fffff);
159
160                 if (op)
161                         lio_pci_fastread(oct, offset, hostbuf, len);
162                 else
163                         lio_pci_fastwrite(oct, offset, hostbuf, len);
164
165                 return;
166         }
167         mtx_lock(&oct->mem_access_lock);
168
169         /* Save the original index reg value. */
170         index_reg_val = oct->fn_list.bar1_idx_read(oct, MEMOPS_IDX);
171         do {
172                 oct->fn_list.bar1_idx_setup(oct, addr, MEMOPS_IDX, 1);
173                 offset = (MEMOPS_IDX << 22) + (addr & 0x3fffff);
174
175                 /*
176                  * If operation crosses a 4MB boundary, split the transfer
177                  * at the 4MB boundary.
178                  */
179                 if (((addr + len - 1) & ~(0x3fffff)) != (addr & ~(0x3fffff))) {
180                         copy_len = (uint32_t)(((addr & ~(0x3fffff)) +
181                                                (MEMOPS_IDX << 22)) - addr);
182                 } else {
183                         copy_len = len;
184                 }
185
186                 if (op) {       /* read from core */
187                         lio_pci_fastread(oct, offset, hostbuf,
188                                          copy_len);
189                 } else {
190                         lio_pci_fastwrite(oct, offset, hostbuf,
191                                           copy_len);
192                 }
193
194                 len -= copy_len;
195                 addr += copy_len;
196                 hostbuf += copy_len;
197
198         } while (len);
199
200         oct->fn_list.bar1_idx_write(oct, MEMOPS_IDX, index_reg_val);
201
202         mtx_unlock(&oct->mem_access_lock);
203 }
204
205 void
206 lio_pci_read_core_mem(struct octeon_device *oct, uint64_t coreaddr,
207                       uint8_t *buf, uint32_t len)
208 {
209
210         lio_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
211 }
212
213 void
214 lio_pci_write_core_mem(struct octeon_device *oct, uint64_t coreaddr,
215                        uint8_t *buf, uint32_t len)
216 {
217
218         lio_pci_rw_core_mem(oct, coreaddr, buf, len, 0);
219 }
220
221 uint64_t
222 lio_read_device_mem64(struct octeon_device *oct, uint64_t coreaddr)
223 {
224         __be64  ret;
225
226         lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 8, 1);
227
228         return (be64toh(ret));
229 }
230
231 uint32_t
232 lio_read_device_mem32(struct octeon_device *oct, uint64_t coreaddr)
233 {
234         __be32  ret;
235
236         lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 4, 1);
237
238         return (be32toh(ret));
239 }
240
241 void
242 lio_write_device_mem32(struct octeon_device *oct, uint64_t coreaddr,
243                        uint32_t val)
244 {
245         __be32  t = htobe32(val);
246
247         lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&t, 4, 0);
248 }