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 #include <npi_ipp.h> 27 28 uint64_t ipp_fzc_offset[] = { 29 IPP_CONFIG_REG, 30 IPP_DISCARD_PKT_CNT_REG, 31 IPP_BAD_CKSUM_ERR_CNT_REG, 32 IPP_ECC_ERR_COUNTER_REG, 33 IPP_INT_STATUS_REG, 34 IPP_INT_MASK_REG, 35 IPP_PFIFO_RD_DATA0_REG, 36 IPP_PFIFO_RD_DATA1_REG, 37 IPP_PFIFO_RD_DATA2_REG, 38 IPP_PFIFO_RD_DATA3_REG, 39 IPP_PFIFO_RD_DATA4_REG, 40 IPP_PFIFO_WR_DATA0_REG, 41 IPP_PFIFO_WR_DATA1_REG, 42 IPP_PFIFO_WR_DATA2_REG, 43 IPP_PFIFO_WR_DATA3_REG, 44 IPP_PFIFO_WR_DATA4_REG, 45 IPP_PFIFO_RD_PTR_REG, 46 IPP_PFIFO_WR_PTR_REG, 47 IPP_DFIFO_RD_DATA0_REG, 48 IPP_DFIFO_RD_DATA1_REG, 49 IPP_DFIFO_RD_DATA2_REG, 50 IPP_DFIFO_RD_DATA3_REG, 51 IPP_DFIFO_RD_DATA4_REG, 52 IPP_DFIFO_WR_DATA0_REG, 53 IPP_DFIFO_WR_DATA1_REG, 54 IPP_DFIFO_WR_DATA2_REG, 55 IPP_DFIFO_WR_DATA3_REG, 56 IPP_DFIFO_WR_DATA4_REG, 57 IPP_DFIFO_RD_PTR_REG, 58 IPP_DFIFO_WR_PTR_REG, 59 IPP_STATE_MACHINE_REG, 60 IPP_CKSUM_STATUS_REG, 61 IPP_FFLP_CKSUM_INFO_REG, 62 IPP_DEBUG_SELECT_REG, 63 IPP_DFIFO_ECC_SYNDROME_REG, 64 IPP_DFIFO_EOPM_RD_PTR_REG, 65 IPP_ECC_CTRL_REG 66 }; 67 68 const char *ipp_fzc_name[] = { 69 "IPP_CONFIG_REG", 70 "IPP_DISCARD_PKT_CNT_REG", 71 "IPP_BAD_CKSUM_ERR_CNT_REG", 72 "IPP_ECC_ERR_COUNTER_REG", 73 "IPP_INT_STATUS_REG", 74 "IPP_INT_MASK_REG", 75 "IPP_PFIFO_RD_DATA0_REG", 76 "IPP_PFIFO_RD_DATA1_REG", 77 "IPP_PFIFO_RD_DATA2_REG", 78 "IPP_PFIFO_RD_DATA3_REG", 79 "IPP_PFIFO_RD_DATA4_REG", 80 "IPP_PFIFO_WR_DATA0_REG", 81 "IPP_PFIFO_WR_DATA1_REG", 82 "IPP_PFIFO_WR_DATA2_REG", 83 "IPP_PFIFO_WR_DATA3_REG", 84 "IPP_PFIFO_WR_DATA4_REG", 85 "IPP_PFIFO_RD_PTR_REG", 86 "IPP_PFIFO_WR_PTR_REG", 87 "IPP_DFIFO_RD_DATA0_REG", 88 "IPP_DFIFO_RD_DATA1_REG", 89 "IPP_DFIFO_RD_DATA2_REG", 90 "IPP_DFIFO_RD_DATA3_REG", 91 "IPP_DFIFO_RD_DATA4_REG", 92 "IPP_DFIFO_WR_DATA0_REG", 93 "IPP_DFIFO_WR_DATA1_REG", 94 "IPP_DFIFO_WR_DATA2_REG", 95 "IPP_DFIFO_WR_DATA3_REG", 96 "IPP_DFIFO_WR_DATA4_REG", 97 "IPP_DFIFO_RD_PTR_REG", 98 "IPP_DFIFO_WR_PTR_REG", 99 "IPP_STATE_MACHINE_REG", 100 "IPP_CKSUM_STATUS_REG", 101 "IPP_FFLP_CKSUM_INFO_REG", 102 "IPP_DEBUG_SELECT_REG", 103 "IPP_DFIFO_ECC_SYNDROME_REG", 104 "IPP_DFIFO_EOPM_RD_PTR_REG", 105 "IPP_ECC_CTRL_REG", 106 }; 107 108 npi_status_t 109 npi_ipp_dump_regs(npi_handle_t handle, uint8_t port) 110 { 111 uint64_t value, offset; 112 int num_regs, i; 113 114 ASSERT(IS_PORT_NUM_VALID(port)); 115 116 NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, 117 "\nIPP PORT Register Dump for port %d\n", port)); 118 119 num_regs = sizeof (ipp_fzc_offset) / sizeof (uint64_t); 120 for (i = 0; i < num_regs; i++) { 121 offset = IPP_REG_ADDR(port, ipp_fzc_offset[i]); 122 NXGE_REG_RD64(handle, offset, &value); 123 NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx " 124 "%s\t 0x%08llx \n", 125 offset, ipp_fzc_name[i], value)); 126 } 127 128 NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, 129 "\n IPP FZC Register Dump for port %d done\n", port)); 130 131 return (NPI_SUCCESS); 132 } 133 134 void 135 npi_ipp_read_regs(npi_handle_t handle, uint8_t port) 136 { 137 uint64_t value, offset; 138 int num_regs, i; 139 140 ASSERT(IS_PORT_NUM_VALID(port)); 141 142 NPI_DEBUG_MSG((handle.function, NPI_IPP_CTL, 143 "\nIPP PORT Register read (to clear) for port %d\n", port)); 144 145 num_regs = sizeof (ipp_fzc_offset) / sizeof (uint64_t); 146 for (i = 0; i < num_regs; i++) { 147 offset = IPP_REG_ADDR(port, ipp_fzc_offset[i]); 148 NXGE_REG_RD64(handle, offset, &value); 149 } 150 151 } 152 153 /* 154 * IPP Reset Routine 155 */ 156 npi_status_t 157 npi_ipp_reset(npi_handle_t handle, uint8_t portn) 158 { 159 uint64_t val = 0; 160 uint32_t cnt = MAX_PIO_RETRIES; 161 162 ASSERT(IS_PORT_NUM_VALID(portn)); 163 164 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 165 val |= IPP_SOFT_RESET; 166 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 167 168 do { 169 NXGE_DELAY(IPP_RESET_WAIT); 170 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 171 cnt--; 172 } while (((val & IPP_SOFT_RESET) != 0) && (cnt > 0)); 173 174 if (cnt == 0) { 175 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 176 " npi_ipp_reset" 177 " HW Error: IPP_RESET <0x%x>", val)); 178 return (NPI_FAILURE | NPI_IPP_RESET_FAILED(portn)); 179 } 180 181 return (NPI_SUCCESS); 182 } 183 184 185 /* 186 * IPP Configuration Routine 187 */ 188 npi_status_t 189 npi_ipp_config(npi_handle_t handle, config_op_t op, uint8_t portn, 190 ipp_config_t config) 191 { 192 uint64_t val = 0; 193 194 ASSERT(IS_PORT_NUM_VALID(portn)); 195 196 switch (op) { 197 198 case ENABLE: 199 case DISABLE: 200 if ((config == 0) || ((config & ~CFG_IPP_ALL) != 0)) { 201 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 202 " npi_ipp_config", 203 " Invalid Input config <0x%x>", 204 config)); 205 return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn)); 206 } 207 208 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 209 210 if (op == ENABLE) 211 val |= config; 212 else 213 val &= ~config; 214 break; 215 216 case INIT: 217 if ((config & ~CFG_IPP_ALL) != 0) { 218 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 219 " npi_ipp_config" 220 " Invalid Input config <0x%x>", 221 config)); 222 return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn)); 223 } 224 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 225 226 227 val &= (IPP_IP_MAX_PKT_BYTES_MASK); 228 val |= config; 229 break; 230 231 default: 232 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 233 " npi_ipp_config" 234 " Invalid Input op <0x%x>", op)); 235 return (NPI_FAILURE | NPI_IPP_OPCODE_INVALID(portn)); 236 } 237 238 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 239 return (NPI_SUCCESS); 240 } 241 242 npi_status_t 243 npi_ipp_set_max_pktsize(npi_handle_t handle, uint8_t portn, uint32_t bytes) 244 { 245 uint64_t val = 0; 246 247 ASSERT(IS_PORT_NUM_VALID(portn)); 248 249 if (bytes > IPP_IP_MAX_PKT_BYTES_MASK) { 250 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 251 " npi_ipp_set_max_pktsize" 252 " Invalid Input Max bytes <0x%x>", 253 bytes)); 254 return (NPI_FAILURE | NPI_IPP_MAX_PKT_BYTES_INVALID(portn)); 255 } 256 257 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 258 val &= ~(IPP_IP_MAX_PKT_BYTES_MASK << IPP_IP_MAX_PKT_BYTES_SHIFT); 259 260 val |= (bytes << IPP_IP_MAX_PKT_BYTES_SHIFT); 261 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 262 263 return (NPI_SUCCESS); 264 } 265 266 /* 267 * IPP Interrupt Configuration Routine 268 */ 269 npi_status_t 270 npi_ipp_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn, 271 ipp_iconfig_t iconfig) 272 { 273 uint64_t val = 0; 274 275 ASSERT(IS_PORT_NUM_VALID(portn)); 276 277 switch (op) { 278 case ENABLE: 279 case DISABLE: 280 281 if ((iconfig == 0) || ((iconfig & ~ICFG_IPP_ALL) != 0)) { 282 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 283 " npi_ipp_iconfig" 284 " Invalid Input iconfig <0x%x>", 285 iconfig)); 286 return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn)); 287 } 288 289 IPP_REG_RD(handle, portn, IPP_INT_MASK_REG, &val); 290 if (op == ENABLE) 291 val &= ~iconfig; 292 else 293 val |= iconfig; 294 IPP_REG_WR(handle, portn, IPP_INT_MASK_REG, val); 295 296 break; 297 case INIT: 298 299 if ((iconfig & ~ICFG_IPP_ALL) != 0) { 300 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 301 " npi_ipp_iconfig" 302 " Invalid Input iconfig <0x%x>", 303 iconfig)); 304 return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn)); 305 } 306 IPP_REG_WR(handle, portn, IPP_INT_MASK_REG, ~iconfig); 307 308 break; 309 default: 310 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 311 " npi_ipp_iconfig" 312 " Invalid Input iconfig <0x%x>", 313 iconfig)); 314 return (NPI_FAILURE | NPI_IPP_OPCODE_INVALID(portn)); 315 } 316 317 return (NPI_SUCCESS); 318 } 319 320 npi_status_t 321 npi_ipp_get_status(npi_handle_t handle, uint8_t portn, ipp_status_t *status) 322 { 323 uint64_t val; 324 325 ASSERT(IS_PORT_NUM_VALID(portn)); 326 327 IPP_REG_RD(handle, portn, IPP_INT_STATUS_REG, &val); 328 329 status->value = val; 330 return (NPI_SUCCESS); 331 } 332 333 npi_status_t 334 npi_ipp_get_pfifo_rd_ptr(npi_handle_t handle, uint8_t portn, uint16_t *rd_ptr) 335 { 336 uint64_t value; 337 338 ASSERT(IS_PORT_NUM_VALID(portn)); 339 340 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_PTR_REG, &value); 341 *rd_ptr = value & 0xfff; 342 return (NPI_SUCCESS); 343 } 344 345 npi_status_t 346 npi_ipp_get_pfifo_wr_ptr(npi_handle_t handle, uint8_t portn, uint16_t *wr_ptr) 347 { 348 uint64_t value; 349 350 ASSERT(IS_PORT_NUM_VALID(portn)); 351 352 IPP_REG_RD(handle, portn, IPP_PFIFO_WR_PTR_REG, &value); 353 *wr_ptr = value & 0xfff; 354 return (NPI_SUCCESS); 355 } 356 357 npi_status_t 358 npi_ipp_get_dfifo_rd_ptr(npi_handle_t handle, uint8_t portn, uint16_t *rd_ptr) 359 { 360 uint64_t value; 361 362 ASSERT(IS_PORT_NUM_VALID(portn)); 363 364 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_PTR_REG, &value); 365 *rd_ptr = (uint16_t)(value & ((portn < 2) ? IPP_XMAC_DFIFO_PTR_MASK : 366 IPP_BMAC_DFIFO_PTR_MASK)); 367 return (NPI_SUCCESS); 368 } 369 370 npi_status_t 371 npi_ipp_get_dfifo_wr_ptr(npi_handle_t handle, uint8_t portn, uint16_t *wr_ptr) 372 { 373 uint64_t value; 374 375 ASSERT(IS_PORT_NUM_VALID(portn)); 376 377 IPP_REG_RD(handle, portn, IPP_DFIFO_WR_PTR_REG, &value); 378 *wr_ptr = (uint16_t)(value & ((portn < 2) ? IPP_XMAC_DFIFO_PTR_MASK : 379 IPP_BMAC_DFIFO_PTR_MASK)); 380 return (NPI_SUCCESS); 381 } 382 383 npi_status_t 384 npi_ipp_write_pfifo(npi_handle_t handle, uint8_t portn, uint8_t addr, 385 uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) 386 { 387 uint64_t val; 388 389 ASSERT(IS_PORT_NUM_VALID(portn)); 390 391 if (addr >= 64) { 392 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 393 " npi_ipp_write_pfifo" 394 " Invalid PFIFO address <0x%x>", addr)); 395 return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn)); 396 } 397 398 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 399 val |= IPP_PRE_FIFO_PIO_WR_EN; 400 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 401 402 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_PTR_REG, addr); 403 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA0_REG, d0); 404 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA1_REG, d1); 405 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA2_REG, d2); 406 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA3_REG, d3); 407 IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA4_REG, d4); 408 409 val &= ~IPP_PRE_FIFO_PIO_WR_EN; 410 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 411 412 return (NPI_SUCCESS); 413 } 414 415 npi_status_t 416 npi_ipp_read_pfifo(npi_handle_t handle, uint8_t portn, uint8_t addr, 417 uint32_t *d0, uint32_t *d1, uint32_t *d2, uint32_t *d3, 418 uint32_t *d4) 419 { 420 ASSERT(IS_PORT_NUM_VALID(portn)); 421 422 if (addr >= 64) { 423 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 424 " npi_ipp_read_pfifo" 425 " Invalid PFIFO address <0x%x>", addr)); 426 return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn)); 427 } 428 429 IPP_REG_WR(handle, portn, IPP_PFIFO_RD_PTR_REG, addr); 430 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA0_REG, d0); 431 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA1_REG, d1); 432 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA2_REG, d2); 433 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA3_REG, d3); 434 IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA4_REG, d4); 435 436 return (NPI_SUCCESS); 437 } 438 439 npi_status_t 440 npi_ipp_write_dfifo(npi_handle_t handle, uint8_t portn, uint16_t addr, 441 uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) 442 { 443 uint64_t val; 444 445 ASSERT(IS_PORT_NUM_VALID(portn)); 446 447 if (addr >= 2048) { 448 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 449 " npi_ipp_write_dfifo" 450 " Invalid DFIFO address <0x%x>", addr)); 451 return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn)); 452 } 453 454 IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val); 455 val |= IPP_DFIFO_PIO_WR_EN; 456 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 457 458 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_PTR_REG, addr); 459 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA0_REG, d0); 460 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA1_REG, d1); 461 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA2_REG, d2); 462 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA3_REG, d3); 463 IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA4_REG, d4); 464 465 val &= ~IPP_DFIFO_PIO_WR_EN; 466 IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val); 467 468 return (NPI_SUCCESS); 469 } 470 471 npi_status_t 472 npi_ipp_read_dfifo(npi_handle_t handle, uint8_t portn, uint16_t addr, 473 uint32_t *d0, uint32_t *d1, uint32_t *d2, uint32_t *d3, 474 uint32_t *d4) 475 { 476 ASSERT(IS_PORT_NUM_VALID(portn)); 477 478 if (addr >= 2048) { 479 NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, 480 " npi_ipp_read_dfifo" 481 " Invalid DFIFO address <0x%x>", addr)); 482 return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn)); 483 } 484 485 IPP_REG_WR(handle, portn, IPP_DFIFO_RD_PTR_REG, addr); 486 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA0_REG, d0); 487 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA1_REG, d1); 488 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA2_REG, d2); 489 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA3_REG, d3); 490 IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA4_REG, d4); 491 492 return (NPI_SUCCESS); 493 } 494 495 npi_status_t 496 npi_ipp_get_ecc_syndrome(npi_handle_t handle, uint8_t portn, uint16_t *syndrome) 497 { 498 uint64_t val; 499 500 ASSERT(IS_PORT_NUM_VALID(portn)); 501 502 IPP_REG_RD(handle, portn, IPP_DFIFO_ECC_SYNDROME_REG, &val); 503 504 *syndrome = (uint16_t)val; 505 return (NPI_SUCCESS); 506 } 507 508 npi_status_t 509 npi_ipp_get_dfifo_eopm_rdptr(npi_handle_t handle, uint8_t portn, 510 uint16_t *rdptr) 511 { 512 uint64_t val; 513 514 ASSERT(IS_PORT_NUM_VALID(portn)); 515 516 IPP_REG_RD(handle, portn, IPP_DFIFO_EOPM_RD_PTR_REG, &val); 517 518 *rdptr = (uint16_t)val; 519 return (NPI_SUCCESS); 520 } 521 522 npi_status_t 523 npi_ipp_get_state_mach(npi_handle_t handle, uint8_t portn, uint32_t *sm) 524 { 525 uint64_t val; 526 527 ASSERT(IS_PORT_NUM_VALID(portn)); 528 529 IPP_REG_RD(handle, portn, IPP_STATE_MACHINE_REG, &val); 530 531 *sm = (uint32_t)val; 532 return (NPI_SUCCESS); 533 } 534 535 npi_status_t 536 npi_ipp_get_ecc_err_count(npi_handle_t handle, uint8_t portn, uint8_t *err_cnt) 537 { 538 ASSERT(IS_PORT_NUM_VALID(portn)); 539 540 IPP_REG_RD(handle, portn, IPP_ECC_ERR_COUNTER_REG, err_cnt); 541 542 return (NPI_SUCCESS); 543 } 544 545 npi_status_t 546 npi_ipp_get_pkt_dis_count(npi_handle_t handle, uint8_t portn, uint16_t *dis_cnt) 547 { 548 ASSERT(IS_PORT_NUM_VALID(portn)); 549 550 IPP_REG_RD(handle, portn, IPP_DISCARD_PKT_CNT_REG, dis_cnt); 551 552 return (NPI_SUCCESS); 553 } 554 555 npi_status_t 556 npi_ipp_get_cs_err_count(npi_handle_t handle, uint8_t portn, uint16_t *err_cnt) 557 { 558 ASSERT(IS_PORT_NUM_VALID(portn)); 559 560 IPP_REG_RD(handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, err_cnt); 561 562 return (NPI_SUCCESS); 563 } 564