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