1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _NPI_RX_RD64_H 27 #define _NPI_RX_RD64_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #include <npi.h> 34 35 /* 36 * RXDMA_REG_READ64 37 * 38 * Read a 64-bit value from a DMC register. 39 * 40 * This is the old, rather convoluted, macro: 41 * 42 * #define RXDMA_REG_READ64(handle, reg, channel, data_p) { \ 43 * NXGE_REG_RD64(handle, (NXGE_RXDMA_OFFSET(reg, \ 44 * handle.is_vraddr, channel)), (data_p)) 45 * 46 * There are 4 versions of NXGE_REG_RD64: 47 * ------------------------------------------------------------- 48 * #if defined(REG_TRACE) 49 * #define NXGE_REG_RD64(handle, offset, val_p) { \ 50 * *(val_p) = NXGE_NPI_PIO_READ64(handle, offset); \ 51 * npi_rtrace_update(handle, B_FALSE, &npi_rtracebuf, (uint32_t)offset, \ 52 * (uint64_t)(*(val_p))); \ 53 * } 54 * #elif defined(REG_SHOW) 55 * #define NXGE_REG_RD64(handle, offset, val_p) {\ 56 * *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\ 57 * rt_show_reg(0xbadbad, B_FALSE, (uint32_t)offset, (uint64_t)(*(val_p)));\ 58 * } 59 * #elif defined(AXIS_DEBUG) && !defined(LEGION) 60 * #define NXGE_REG_RD64(handle, offset, val_p) {\ 61 * int n; \ 62 * for (n = 0; n < AXIS_WAIT_LOOP; n++) { \ 63 * *(val_p) = 0; \ 64 * *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\ 65 * if (*(val_p) != (~0)) { \ 66 * break; \ 67 * } \ 68 * drv_usecwait(AXIS_WAIT_PER_LOOP); \ 69 * if (n < 20) { \ 70 * cmn_err(CE_WARN, "NXGE_REG_RD64: loop %d " \ 71 * "REG 0x%x(0x%llx)", \ 72 * n, offset, *val_p);\ 73 * } \ 74 * } \ 75 * if (n >= AXIS_WAIT_LOOP) { \ 76 * cmn_err(CE_WARN, "(FATAL)NXGE_REG_RD64 on offset 0x%x " \ 77 * "with -1!!!", offset); \ 78 * } \ 79 * } 80 * #else 81 * #define NXGE_REG_RD64(handle, offset, val_p) {\ 82 * *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\ 83 * } 84 * #endif 85 * 86 * There are 2 versions of NXGE_NPI_PIO_READ64: 87 * ------------------------------------------------------------- 88 * #if defined(__i386) 89 * #define NXGE_NPI_PIO_READ64(npi_handle, offset) \ 90 * (ddi_get64(NPI_REGH(npi_handle), \ 91 * (uint64_t *)(NPI_REGP(npi_handle) + (uint32_t)offset))) 92 * #else 93 * #define NXGE_NPI_PIO_READ64(npi_handle, offset) \ 94 * (ddi_get64(NPI_REGH(npi_handle), \ 95 * (uint64_t *)(NPI_REGP(npi_handle) + offset))) 96 * #endif 97 * 98 * ------------------------------------------------------------- 99 * #define NPI_REGH(npi_handle) (npi_handle.regh) 100 * #define NPI_REGP(npi_handle) (npi_handle.regp) 101 * 102 * Now let's tackle NXGE_RXDMA_OFFSET 103 * ------------------------------------------------------------- 104 * #define NXGE_RXDMA_OFFSET(x, v, channel) (x + \ 105 * (!v ? DMC_OFFSET(channel) : \ 106 * RDMC_PIOVADDR_OFFSET(channel))) 107 * 108 * ------------------------------------------------------------- 109 * #define DMC_OFFSET(channel) (DMA_CSR_SIZE * channel) 110 * 111 * #define TDMC_PIOVADDR_OFFSET(channel) (2 * DMA_CSR_SIZE * channel) 112 * ------------------------------------------------------------- 113 * #define RDMC_PIOVADDR_OFFSET(channel) \ 114 * (TDMC_OFFSET(channel) + DMA_CSR_SIZE) 115 * ------------------------------------------------------------- 116 * #define DMA_CSR_SIZE 512 117 * 118 * #define TDMC_OFFSET(channel) (TX_RNG_CFIG + DMA_CSR_SIZE * channel) 119 * #define TX_RNG_CFIG (DMC + 0x40000) 120 * ------------------------------------------------------------- 121 * This definition is clearly wrong! I think this was intended: 122 * 123 * #define RDMC_PIOVADDR_OFFSET(channel) \ 124 * (TDMC_PIOVADDR__OFFSET(channel) + DMA_CSR_SIZE) 125 * ------------------------------------------------------------- 126 * 127 * Finally, we have the full macro: 128 * ------------------------------------------------------------- 129 * #define RXDMA_REG_READ64(handle, reg, channel, data_p) { \ 130 * NXGE_REG_RD64(handle, (NXGE_RXDMA_OFFSET(reg, \ 131 * handle.is_vraddr, channel)), (data_p)) 132 * 133 * *data_p = ddi_get64(handle.regh, (uint64_t*)(handle.regp + 134 * ((0x600000+0x00000) + 135 * (!handle.is_vraddr ? 136 * (512 * channel) : 137 * 0x600000 + 0x40000 + (512 * channel) + 512))); 138 */ 139 140 static void RXDMA_REG_READ64(npi_handle_t, uint64_t, int, uint64_t *); 141 #pragma inline(RXDMA_REG_READ64) 142 143 /* 144 * RXDMA_REG_READ64 145 * 146 * Read a 64-bit value from a DMC register. 147 * 148 * Arguments: 149 * handle The NPI handle to use. 150 * offset The offset into the DMA CSR (the register). 151 * channel The channel, which is used as a multiplicand. 152 * value Where to put the 64-bit value to be read. 153 * 154 * Notes: 155 * If handle.regp is a virtual address (the address of a VR), 156 * we have to subtract the value DMC right off the bat. DMC 157 * is defined as 0x600000, which works in a non-virtual address 158 * space, but not in a VR. In a VR, a DMA CSR's space begins 159 * at zero (0). So, since every call to RXMDA_REG_READ64 uses 160 * a register macro which adds in DMC, we have to subtract it. 161 * 162 * The rest of it is pretty straighforward. In a VR, a channel is 163 * logical, not absolute; and every DMA CSR is 512 bytes big; 164 * furthermore, a subpage of a VR is always ordered with the 165 * transmit CSRs first, followed by the receive CSRs. That is, 166 * a 512 byte space of Tx CSRs, followed by a 512 byte space of 167 * Rx CSRs. Hence this calculation: 168 * 169 * offset += ((channel << 1) + 1) << DMA_CSR_SLL; 170 * 171 * Here's an example: 172 * 173 * RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, value); 174 * Let's say channel is 3 175 * #define RX_DMA_CTL_STAT_REG (DMC + 0x00070) 176 * offset = 0x600070 177 * offset &= 0xff = 0x70 178 * offset += ((3 << 1) + 1) << 9 179 * 3 << 1 = 6 180 * 6 + 1 = 7 181 * 7 << 9 = 0xe00 182 * offset += 0xe00 = 0xe70 183 * 184 * Therefore, our register's (virtual) PIO address is 0xe70. 185 * 186 * cf. Table 10-6 on page 181 of the Neptune PRM, v 1.4: 187 * 188 * E00 - FFF CSRs for bound logical receive DMA channel 3. 189 * 190 * In a non-virtual environment, you simply multiply the absolute 191 * channel number by 512 bytes, and get the correct offset to 192 * the register you're looking for. That is, the RX_DMA_CTL_STAT CSR, 193 * is, as are all of these registers, in a table where each channel 194 * is offset 512 bytes from the previous channel (count 16 step 512). 195 * 196 * offset += (channel << DMA_CSR_SLL); // channel<<9 = channel*512 197 * 198 * Here's an example: 199 * 200 * RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, value); 201 * Let's say channel is 3 202 * #define RX_DMA_CTL_STAT_REG (DMC + 0x00070) 203 * offset = 0x600070 204 * offset += (3 << 9) 205 * 3 << 9 = 0x600 206 * offset += 0x600 = 0x600670 207 * 208 * Therefore, our register's PIO address is 0x600670. 209 * 210 * cf. Table 12-42 on page 234 of the Neptune PRM, v 1.4: 211 * RX_DMA_CTL_STAT (DMC + [0x]00070) (count 16 step [0x]200) 212 * 213 * Context: 214 * Guest domain 215 * 216 */ 217 extern const char *nxge_rx2str(int); 218 219 void 220 RXDMA_REG_READ64( 221 npi_handle_t handle, 222 uint64_t offset, 223 int channel, 224 uint64_t *value) 225 { 226 #if defined(NPI_REG_TRACE) 227 const char *name = nxge_rx2str((int)offset); 228 #endif 229 if (handle.is_vraddr) { 230 offset &= DMA_CSR_MASK; 231 offset += (((channel << 1) + 1) << DMA_CSR_SLL); 232 } else { 233 offset += (channel << DMA_CSR_SLL); 234 } 235 236 #if defined(__i386) 237 *value = ddi_get64(handle.regh, 238 (uint64_t *)(handle.regp + (uint32_t)offset)); 239 #else 240 *value = ddi_get64(handle.regh, (uint64_t *)(handle.regp + offset)); 241 #endif 242 243 #if defined(NPI_REG_TRACE) 244 npi_trace_update(handle, B_FALSE, &npi_rtracebuf, 245 name, (uint32_t)offset, *value); 246 #elif defined(REG_SHOW) 247 /* 248 * Since we don't have a valid RTBUF index to show, send 0xBADBAD. 249 */ 250 rt_show_reg(0xbadbad, B_FALSE, (uint32_t)offset, *value); 251 #endif 252 } 253 254 #ifdef __cplusplus 255 } 256 #endif 257 258 #endif /* _NPI_RX_RD64_H */ 259