1*d39a76e7Sxw161283 /* 2*d39a76e7Sxw161283 * CDDL HEADER START 3*d39a76e7Sxw161283 * 4*d39a76e7Sxw161283 * The contents of this file are subject to the terms of the 5*d39a76e7Sxw161283 * Common Development and Distribution License (the "License"). 6*d39a76e7Sxw161283 * You may not use this file except in compliance with the License. 7*d39a76e7Sxw161283 * 8*d39a76e7Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d39a76e7Sxw161283 * or http://www.opensolaris.org/os/licensing. 10*d39a76e7Sxw161283 * See the License for the specific language governing permissions 11*d39a76e7Sxw161283 * and limitations under the License. 12*d39a76e7Sxw161283 * 13*d39a76e7Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each 14*d39a76e7Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d39a76e7Sxw161283 * If applicable, add the following below this CDDL HEADER, with the 16*d39a76e7Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying 17*d39a76e7Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner] 18*d39a76e7Sxw161283 * 19*d39a76e7Sxw161283 * CDDL HEADER END 20*d39a76e7Sxw161283 */ 21*d39a76e7Sxw161283 22*d39a76e7Sxw161283 /* 23*d39a76e7Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 24*d39a76e7Sxw161283 */ 25*d39a76e7Sxw161283 26*d39a76e7Sxw161283 #pragma ident "%Z%%M% %I% %E% SMI" /* ulp.c */ 27*d39a76e7Sxw161283 28*d39a76e7Sxw161283 #include "common.h" 29*d39a76e7Sxw161283 #include "regs.h" 30*d39a76e7Sxw161283 #include "ulp.h" 31*d39a76e7Sxw161283 32*d39a76e7Sxw161283 struct peulp { 33*d39a76e7Sxw161283 adapter_t *adapter; 34*d39a76e7Sxw161283 struct ulp_intr_counts intr_counts; 35*d39a76e7Sxw161283 }; 36*d39a76e7Sxw161283 37*d39a76e7Sxw161283 #define ULP_INTR_MASK (F_HREG_PAR_ERR | F_EGRS_DATA_PAR_ERR | \ 38*d39a76e7Sxw161283 F_INGRS_DATA_PAR_ERR | F_PM_INTR | F_PM_E2C_SYNC_ERR | \ 39*d39a76e7Sxw161283 F_PM_C2E_SYNC_ERR | F_PM_E2C_EMPTY_ERR | \ 40*d39a76e7Sxw161283 F_PM_C2E_EMPTY_ERR | V_PM_PAR_ERR(M_PM_PAR_ERR) | \ 41*d39a76e7Sxw161283 F_PM_E2C_WRT_FULL | F_PM_C2E_WRT_FULL) 42*d39a76e7Sxw161283 43*d39a76e7Sxw161283 void t1_ulp_intr_enable(struct peulp *ulp) 44*d39a76e7Sxw161283 { 45*d39a76e7Sxw161283 /* Only ASIC boards support PL_ULP block. */ 46*d39a76e7Sxw161283 if (t1_is_asic(ulp->adapter)) { 47*d39a76e7Sxw161283 u32 pl_intr = t1_read_reg_4(ulp->adapter, A_PL_ENABLE); 48*d39a76e7Sxw161283 49*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_ULP_INT_ENABLE, ULP_INTR_MASK); 50*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_PL_ENABLE, 51*d39a76e7Sxw161283 pl_intr | F_PL_INTR_ULP); 52*d39a76e7Sxw161283 } 53*d39a76e7Sxw161283 } 54*d39a76e7Sxw161283 55*d39a76e7Sxw161283 void t1_ulp_intr_clear(struct peulp *ulp) 56*d39a76e7Sxw161283 { 57*d39a76e7Sxw161283 if (t1_is_asic(ulp->adapter)) { 58*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_PL_CAUSE, F_PL_INTR_ULP); 59*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_ULP_INT_CAUSE, 0xffffffff); 60*d39a76e7Sxw161283 } 61*d39a76e7Sxw161283 } 62*d39a76e7Sxw161283 63*d39a76e7Sxw161283 void t1_ulp_intr_disable(struct peulp *ulp) 64*d39a76e7Sxw161283 { 65*d39a76e7Sxw161283 if (t1_is_asic(ulp->adapter)) { 66*d39a76e7Sxw161283 u32 pl_intr = t1_read_reg_4(ulp->adapter, A_PL_ENABLE); 67*d39a76e7Sxw161283 68*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_PL_ENABLE, 69*d39a76e7Sxw161283 pl_intr & ~F_PL_INTR_ULP); 70*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_ULP_INT_ENABLE, 0); 71*d39a76e7Sxw161283 } 72*d39a76e7Sxw161283 } 73*d39a76e7Sxw161283 74*d39a76e7Sxw161283 int t1_ulp_intr_handler(struct peulp *ulp) 75*d39a76e7Sxw161283 { 76*d39a76e7Sxw161283 u32 cause = t1_read_reg_4(ulp->adapter, A_ULP_INT_CAUSE); 77*d39a76e7Sxw161283 78*d39a76e7Sxw161283 if (cause & F_HREG_PAR_ERR) 79*d39a76e7Sxw161283 ulp->intr_counts.region_table_parity_err++; 80*d39a76e7Sxw161283 81*d39a76e7Sxw161283 if (cause & F_EGRS_DATA_PAR_ERR) 82*d39a76e7Sxw161283 ulp->intr_counts.egress_tp2ulp_data_parity_err++; 83*d39a76e7Sxw161283 84*d39a76e7Sxw161283 if (cause & F_INGRS_DATA_PAR_ERR) 85*d39a76e7Sxw161283 ulp->intr_counts.ingress_tp2ulp_data_parity_err++; 86*d39a76e7Sxw161283 87*d39a76e7Sxw161283 if (cause & F_PM_INTR) 88*d39a76e7Sxw161283 ulp->intr_counts.pm_intr++; 89*d39a76e7Sxw161283 90*d39a76e7Sxw161283 if (cause & F_PM_E2C_SYNC_ERR) 91*d39a76e7Sxw161283 ulp->intr_counts.pm_e2c_cmd_payload_sync_err++; 92*d39a76e7Sxw161283 93*d39a76e7Sxw161283 if (cause & F_PM_C2E_SYNC_ERR) 94*d39a76e7Sxw161283 ulp->intr_counts.pm_c2e_cmd_payload_sync_err++; 95*d39a76e7Sxw161283 96*d39a76e7Sxw161283 if (cause & F_PM_E2C_EMPTY_ERR) 97*d39a76e7Sxw161283 ulp->intr_counts.pm_e2c_fifo_read_empty_err++; 98*d39a76e7Sxw161283 99*d39a76e7Sxw161283 if (cause & F_PM_C2E_EMPTY_ERR) 100*d39a76e7Sxw161283 ulp->intr_counts.pm_c2e_fifo_read_empty_err++; 101*d39a76e7Sxw161283 102*d39a76e7Sxw161283 if (G_PM_PAR_ERR(cause)) 103*d39a76e7Sxw161283 ulp->intr_counts.pm_parity_err++; 104*d39a76e7Sxw161283 105*d39a76e7Sxw161283 if (cause & F_PM_E2C_WRT_FULL) 106*d39a76e7Sxw161283 ulp->intr_counts.pm_e2c_fifo_write_full_err++; 107*d39a76e7Sxw161283 108*d39a76e7Sxw161283 if (cause & F_PM_C2E_WRT_FULL) 109*d39a76e7Sxw161283 ulp->intr_counts.pm_c2e_fifo_write_full_err++; 110*d39a76e7Sxw161283 111*d39a76e7Sxw161283 if (cause & ULP_INTR_MASK) 112*d39a76e7Sxw161283 t1_fatal_err(ulp->adapter); 113*d39a76e7Sxw161283 114*d39a76e7Sxw161283 /* Clear status */ 115*d39a76e7Sxw161283 t1_write_reg_4(ulp->adapter, A_ULP_INT_CAUSE, cause); 116*d39a76e7Sxw161283 return 0; 117*d39a76e7Sxw161283 } 118*d39a76e7Sxw161283 119*d39a76e7Sxw161283 int t1_ulp_init(struct peulp *ulp, unsigned int pm_tx_base) 120*d39a76e7Sxw161283 { 121*d39a76e7Sxw161283 int i; 122*d39a76e7Sxw161283 adapter_t *adapter = ulp->adapter; 123*d39a76e7Sxw161283 124*d39a76e7Sxw161283 /* 125*d39a76e7Sxw161283 * Initialize ULP Region Table. 126*d39a76e7Sxw161283 * 127*d39a76e7Sxw161283 * The region table memory has read enable tied to one, so data is 128*d39a76e7Sxw161283 * read out every cycle. The address to this memory is not defined 129*d39a76e7Sxw161283 * at reset and gets set first time when first ulp pdu is handled. 130*d39a76e7Sxw161283 * So after reset an undefined location is accessed, and since it is 131*d39a76e7Sxw161283 * read before any meaningful data is written to it there can be a 132*d39a76e7Sxw161283 * parity error. 133*d39a76e7Sxw161283 */ 134*d39a76e7Sxw161283 for (i = 0; i < 256; i++) { 135*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_HREG_INDEX, i); 136*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_HREG_DATA, 0); 137*d39a76e7Sxw161283 } 138*d39a76e7Sxw161283 139*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_ULIMIT, pm_tx_base); 140*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_TAGMASK, (pm_tx_base << 1) - 1); 141*d39a76e7Sxw161283 142*d39a76e7Sxw161283 if (!t1_is_T1B(adapter)) { 143*d39a76e7Sxw161283 /* region table is not used */ 144*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_HREG_INDEX, 0); 145*d39a76e7Sxw161283 /* enable page size in pagepod */ 146*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_ULP_PIO_CTRL, 1); 147*d39a76e7Sxw161283 } 148*d39a76e7Sxw161283 return 0; 149*d39a76e7Sxw161283 } 150*d39a76e7Sxw161283 151*d39a76e7Sxw161283 struct peulp *t1_ulp_create(adapter_t *adapter) 152*d39a76e7Sxw161283 { 153*d39a76e7Sxw161283 struct peulp *ulp = t1_os_malloc_wait_zero(sizeof(*ulp)); 154*d39a76e7Sxw161283 155*d39a76e7Sxw161283 if (ulp) 156*d39a76e7Sxw161283 ulp->adapter = adapter; 157*d39a76e7Sxw161283 return ulp; 158*d39a76e7Sxw161283 } 159*d39a76e7Sxw161283 160*d39a76e7Sxw161283 void t1_ulp_destroy(struct peulp * ulp) 161*d39a76e7Sxw161283 { 162*d39a76e7Sxw161283 t1_os_free((void *)ulp, sizeof(*ulp)); 163*d39a76e7Sxw161283 } 164*d39a76e7Sxw161283 165*d39a76e7Sxw161283 const struct ulp_intr_counts *t1_ulp_get_intr_counts(struct peulp *ulp) 166*d39a76e7Sxw161283 { 167*d39a76e7Sxw161283 return &ulp->intr_counts; 168*d39a76e7Sxw161283 } 169