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_TX_WR64_H 27 #define _NPI_TX_WR64_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #include <npi.h> 34 35 static void TXDMA_REG_WRITE64(npi_handle_t, uint64_t, int, uint64_t); 36 #pragma inline(TXDMA_REG_WRITE64) 37 38 /* 39 * TXDMA_REG_WRITE64 40 * 41 * Write a 64-bit value to a DMC register. 42 * 43 * Arguments: 44 * handle The NPI handle to use. 45 * offset The offset into the DMA CSR (the register). 46 * channel The channel, which is used as a multiplicand. 47 * value The 64-bit value to write. 48 * 49 * Notes: 50 * For reference, here is the old macro: 51 * 52 * #define TXDMA_REG_WRITE64(handle, reg, channel, data) \ 53 * NXGE_REG_WR64(handle, \ 54 * NXGE_TXDMA_OFFSET(reg, handle.is_vraddr, channel), data) 55 * 56 * If handle.regp is a virtual address (the address of a VR), 57 * we have to subtract the value DMC right off the bat. DMC 58 * is defined as 0x600000, which works in a non-virtual address 59 * space, but not in a VR. In a VR, a DMA CSR's space begins 60 * at zero (0). So, since every call to RXMDA_REG_READ64 uses 61 * a register macro which adds in DMC, we have to subtract it. 62 * 63 * The rest of it is pretty straighforward. In a VR, a channel is 64 * logical, not absolute; and every DMA CSR is 512 bytes big; 65 * furthermore, a subpage of a VR is always ordered with the 66 * transmit CSRs first, followed by the receive CSRs. That is, 67 * a 512 byte space of Tx CSRs, followed by a 512 byte space of 68 * Rx CSRs. Hence this calculation: 69 * 70 * offset += ((channel << 1) << DMA_CSR_SLL); 71 * 72 * Here's an example: 73 * 74 * TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, value); 75 * Let's say channel is 3 76 * #define TX_CS_REG (DMC + 0x40028) 77 * offset = 0x640028 78 * offset &= 0xff = 0x28 79 * offset += ((3 << 1) << 9) 80 * 3 << 1 = 6 81 * 6 << 9 = 0xc00 82 * offset += 0xc00 = 0xc28 83 * 84 * Therefore, our register's (virtual) PIO address is 0xc28. 85 * 86 * cf. Table 10-6 on page 181 of the Neptune PRM, v 1.4: 87 * 88 * C00 - dFF CSRs for bound logical transmit DMA channel 3. 89 * 90 * In a non-virtual environment, you simply multiply the absolute 91 * channel number by 512 bytes, and get the correct offset to 92 * the register you're looking for. That is, the RX_DMA_CTL_STAT CSR, 93 * is, as are all of these registers, in a table where each channel 94 * is offset 512 bytes from the previous channel (count 16 step 512). 95 * 96 * offset += (channel << DMA_CSR_SLL); // channel<<9 = channel*512 97 * 98 * Here's an example: 99 * 100 * TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, value); 101 * Let's say channel is 3 102 * #define TX_CS_REG (DMC + 0x40028) 103 * offset = 0x640028 104 * offset += (3 << 9) 105 * 3 << 9 = 0x600 106 * offset += 0x600 = 0x640628 107 * 108 * Therefore, our register's PIO address is 0x640628. 109 * 110 * cf. Table 13-15 on page 265 of the Neptune PRM, v 1.4: 111 * TX_CS (DMC + 4002816) (count 24 step 0x200) 112 * 113 * Context: 114 * Any domain 115 * 116 */ 117 extern const char *nxge_tx2str(int); 118 119 void 120 TXDMA_REG_WRITE64( 121 npi_handle_t handle, 122 uint64_t offset, 123 int channel, 124 uint64_t value) 125 { 126 #if defined(NPI_REG_TRACE) 127 const char *name = nxge_tx2str((int)offset); 128 #endif 129 if (handle.is_vraddr) { 130 offset &= DMA_CSR_MASK; 131 offset += ((channel << 1) << DMA_CSR_SLL); 132 } else { 133 offset += (channel << DMA_CSR_SLL); 134 } 135 136 #if defined(__i386) 137 ddi_put64(handle.regh, 138 (uint64_t *)(handle.regp + (uint32_t)offset), value); 139 #else 140 ddi_put64(handle.regh, 141 (uint64_t *)(handle.regp + offset), value); 142 #endif 143 144 #if defined(NPI_REG_TRACE) 145 npi_trace_update(handle, B_TRUE, &npi_rtracebuf, 146 name, (uint32_t)offset, value); 147 #elif defined(REG_SHOW) 148 /* 149 * Since we don't have a valid RTBUF index to show, send 0xBADBAD. 150 */ 151 rt_show_reg(0xbadbad, B_TRUE, (uint32_t)offset, value); 152 #endif 153 } 154 155 #ifdef __cplusplus 156 } 157 #endif 158 159 #endif /* _NPI_TX_WR64_H */ 160