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