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 * This file is part of the Chelsio T1 Ethernet driver. 24*d39a76e7Sxw161283 * 25*d39a76e7Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 26*d39a76e7Sxw161283 */ 27*d39a76e7Sxw161283 28*d39a76e7Sxw161283 #pragma ident "%Z%%M% %I% %E% SMI" /* mc4.c */ 29*d39a76e7Sxw161283 30*d39a76e7Sxw161283 #include "common.h" 31*d39a76e7Sxw161283 #include "regs.h" 32*d39a76e7Sxw161283 #include "mc4.h" 33*d39a76e7Sxw161283 34*d39a76e7Sxw161283 struct pemc4 { 35*d39a76e7Sxw161283 adapter_t *adapter; 36*d39a76e7Sxw161283 unsigned int size; 37*d39a76e7Sxw161283 unsigned int nwords; /* MC4 width in terms of 32-bit words */ 38*d39a76e7Sxw161283 struct pemc4_intr_counts intr_cnt; 39*d39a76e7Sxw161283 }; 40*d39a76e7Sxw161283 41*d39a76e7Sxw161283 void t1_mc4_destroy(struct pemc4 *mc4) 42*d39a76e7Sxw161283 { 43*d39a76e7Sxw161283 t1_os_free((void *)mc4, sizeof(*mc4)); 44*d39a76e7Sxw161283 } 45*d39a76e7Sxw161283 46*d39a76e7Sxw161283 #define is_MC4A(adapter) (!t1_is_T1B(adapter)) 47*d39a76e7Sxw161283 48*d39a76e7Sxw161283 /* Calculate amount of MC4 memory. */ 49*d39a76e7Sxw161283 static unsigned int __devinit mc4_calc_size(adapter_t *adapter) 50*d39a76e7Sxw161283 { 51*d39a76e7Sxw161283 u32 mc4_cfg = t1_read_reg_4(adapter, A_MC4_CFG); 52*d39a76e7Sxw161283 unsigned int width = is_MC4A(adapter) ? G_MC4A_WIDTH(mc4_cfg) : 53*d39a76e7Sxw161283 !!(mc4_cfg & F_MC4_NARROW); 54*d39a76e7Sxw161283 55*d39a76e7Sxw161283 return (256 * 1024 * 1024) >> width; 56*d39a76e7Sxw161283 } 57*d39a76e7Sxw161283 58*d39a76e7Sxw161283 /* 59*d39a76e7Sxw161283 * Write a value to a register and check that the write completed. These 60*d39a76e7Sxw161283 * writes normally complete in a cycle or two, so one read should suffice but 61*d39a76e7Sxw161283 * just in case we give them a bit of grace period. Note that the very first 62*d39a76e7Sxw161283 * read exists to flush the posted write to the device. 63*d39a76e7Sxw161283 */ 64*d39a76e7Sxw161283 static int wrreg_wait(adapter_t *adapter, unsigned int addr, u32 val) 65*d39a76e7Sxw161283 { 66*d39a76e7Sxw161283 int attempts = 2; 67*d39a76e7Sxw161283 68*d39a76e7Sxw161283 t1_write_reg_4(adapter, addr, val); 69*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, addr); /* flush */ 70*d39a76e7Sxw161283 while (attempts--) { 71*d39a76e7Sxw161283 if (!(t1_read_reg_4(adapter, addr) & F_BUSY)) 72*d39a76e7Sxw161283 return 0; 73*d39a76e7Sxw161283 if (attempts) 74*d39a76e7Sxw161283 DELAY_US(1); 75*d39a76e7Sxw161283 } 76*d39a76e7Sxw161283 CH_ERR("%s: write to MC4 register 0x%x timed out\n", 77*d39a76e7Sxw161283 adapter_name(adapter), addr); 78*d39a76e7Sxw161283 return -EIO; 79*d39a76e7Sxw161283 } 80*d39a76e7Sxw161283 81*d39a76e7Sxw161283 #define MC4_DLL_DONE (F_MASTER_DLL_LOCKED | F_MASTER_DLL_MAX_TAP_COUNT) 82*d39a76e7Sxw161283 83*d39a76e7Sxw161283 int t1_mc4_init(struct pemc4 *mc4, unsigned int mc4_clock) 84*d39a76e7Sxw161283 { 85*d39a76e7Sxw161283 int attempts; 86*d39a76e7Sxw161283 u32 val; 87*d39a76e7Sxw161283 unsigned int width, ext_mode, slow_mode; 88*d39a76e7Sxw161283 adapter_t *adapter = mc4->adapter; 89*d39a76e7Sxw161283 90*d39a76e7Sxw161283 /* Power up the FCRAMs. */ 91*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_CFG); 92*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_CFG, val | F_POWER_UP); 93*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_CFG); /* flush */ 94*d39a76e7Sxw161283 95*d39a76e7Sxw161283 if (is_MC4A(adapter)) { 96*d39a76e7Sxw161283 slow_mode = val & F_MC4A_SLOW; 97*d39a76e7Sxw161283 width = G_MC4A_WIDTH(val); 98*d39a76e7Sxw161283 99*d39a76e7Sxw161283 /* If we're not in slow mode, we are using the DLLs */ 100*d39a76e7Sxw161283 if (!slow_mode) { 101*d39a76e7Sxw161283 /* Clear Reset */ 102*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_STROBE); 103*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_STROBE, 104*d39a76e7Sxw161283 val & ~F_SLAVE_DLL_RESET); 105*d39a76e7Sxw161283 106*d39a76e7Sxw161283 /* Wait for slave DLLs to lock */ 107*d39a76e7Sxw161283 DELAY_US(2 * 512 / (mc4_clock / 1000000) + 1); 108*d39a76e7Sxw161283 } 109*d39a76e7Sxw161283 } else { 110*d39a76e7Sxw161283 slow_mode = val & F_MC4_SLOW; 111*d39a76e7Sxw161283 width = !!(val & F_MC4_NARROW); 112*d39a76e7Sxw161283 113*d39a76e7Sxw161283 /* Initializes the master DLL and slave delay lines. */ 114*d39a76e7Sxw161283 if (t1_is_asic(adapter) && !slow_mode) { 115*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_STROBE); 116*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_STROBE, 117*d39a76e7Sxw161283 val & ~F_MASTER_DLL_RESET); 118*d39a76e7Sxw161283 119*d39a76e7Sxw161283 /* Wait for the master DLL to lock. */ 120*d39a76e7Sxw161283 attempts = 100; 121*d39a76e7Sxw161283 do { 122*d39a76e7Sxw161283 DELAY_US(1); 123*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_STROBE); 124*d39a76e7Sxw161283 } while (!(val & MC4_DLL_DONE) && --attempts); 125*d39a76e7Sxw161283 if (!(val & MC4_DLL_DONE)) { 126*d39a76e7Sxw161283 CH_ERR("%s: MC4 DLL lock failed\n", 127*d39a76e7Sxw161283 adapter_name(adapter)); 128*d39a76e7Sxw161283 goto out_fail; 129*d39a76e7Sxw161283 } 130*d39a76e7Sxw161283 } 131*d39a76e7Sxw161283 } 132*d39a76e7Sxw161283 133*d39a76e7Sxw161283 mc4->nwords = 4 >> width; 134*d39a76e7Sxw161283 135*d39a76e7Sxw161283 /* Set the FCRAM output drive strength and enable DLLs if needed */ 136*d39a76e7Sxw161283 ext_mode = t1_is_asic(adapter) && !slow_mode ? 0 : 1; 137*d39a76e7Sxw161283 if (wrreg_wait(adapter, A_MC4_EXT_MODE, ext_mode)) 138*d39a76e7Sxw161283 goto out_fail; 139*d39a76e7Sxw161283 140*d39a76e7Sxw161283 /* Specify the FCRAM operating parameters */ 141*d39a76e7Sxw161283 if (wrreg_wait(adapter, A_MC4_MODE, 0x32)) 142*d39a76e7Sxw161283 goto out_fail; 143*d39a76e7Sxw161283 144*d39a76e7Sxw161283 /* Initiate an immediate refresh and wait for the write to complete. */ 145*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_REFRESH); 146*d39a76e7Sxw161283 if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE)) 147*d39a76e7Sxw161283 goto out_fail; 148*d39a76e7Sxw161283 149*d39a76e7Sxw161283 /* 2nd immediate refresh as before */ 150*d39a76e7Sxw161283 if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE)) 151*d39a76e7Sxw161283 goto out_fail; 152*d39a76e7Sxw161283 153*d39a76e7Sxw161283 /* Convert to KHz first to avoid 64-bit division. */ 154*d39a76e7Sxw161283 mc4_clock /= 1000; /* Hz->KHz */ 155*d39a76e7Sxw161283 mc4_clock = mc4_clock * 7812 + mc4_clock / 2; /* ns */ 156*d39a76e7Sxw161283 mc4_clock /= 1000000; /* KHz->MHz, ns->us */ 157*d39a76e7Sxw161283 158*d39a76e7Sxw161283 /* Enable periodic refresh. */ 159*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_REFRESH, 160*d39a76e7Sxw161283 F_REFRESH_ENABLE | V_REFRESH_DIVISOR(mc4_clock)); 161*d39a76e7Sxw161283 (void) t1_read_reg_4(adapter, A_MC4_REFRESH); /* flush */ 162*d39a76e7Sxw161283 163*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_ECC_CNTL, 164*d39a76e7Sxw161283 F_ECC_GENERATION_ENABLE | F_ECC_CHECK_ENABLE); 165*d39a76e7Sxw161283 166*d39a76e7Sxw161283 /* Use the BIST engine to clear all of the MC4 memory. */ 167*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_BIST_ADDR_BEG, 0); 168*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_BIST_ADDR_END, (mc4->size << width) - 1); 169*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_BIST_DATA, 0); 170*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_BIST_OP, V_OP(1) | 0x1f0); 171*d39a76e7Sxw161283 (void) t1_read_reg_4(adapter, A_MC4_BIST_OP); /* flush */ 172*d39a76e7Sxw161283 173*d39a76e7Sxw161283 attempts = 100; 174*d39a76e7Sxw161283 do { 175*d39a76e7Sxw161283 DELAY_MS(100); 176*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_BIST_OP); 177*d39a76e7Sxw161283 } while ((val & F_BUSY) && --attempts); 178*d39a76e7Sxw161283 if (val & F_BUSY) { 179*d39a76e7Sxw161283 CH_ERR("%s: MC4 BIST timed out\n", adapter_name(adapter)); 180*d39a76e7Sxw161283 goto out_fail; 181*d39a76e7Sxw161283 } 182*d39a76e7Sxw161283 183*d39a76e7Sxw161283 /* Enable normal memory accesses. */ 184*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_CFG); 185*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_MC4_CFG, val | F_READY); 186*d39a76e7Sxw161283 val = t1_read_reg_4(adapter, A_MC4_CFG); /* flush */ 187*d39a76e7Sxw161283 return 0; 188*d39a76e7Sxw161283 189*d39a76e7Sxw161283 out_fail: 190*d39a76e7Sxw161283 return -1; 191*d39a76e7Sxw161283 } 192*d39a76e7Sxw161283 193*d39a76e7Sxw161283 struct pemc4 * __devinit t1_mc4_create(adapter_t *adapter) 194*d39a76e7Sxw161283 { 195*d39a76e7Sxw161283 struct pemc4 *mc4 = t1_os_malloc_wait_zero(sizeof(*mc4)); 196*d39a76e7Sxw161283 197*d39a76e7Sxw161283 if (mc4) { 198*d39a76e7Sxw161283 mc4->adapter = adapter; 199*d39a76e7Sxw161283 mc4->size = mc4_calc_size(adapter); 200*d39a76e7Sxw161283 } 201*d39a76e7Sxw161283 return mc4; 202*d39a76e7Sxw161283 } 203*d39a76e7Sxw161283 204*d39a76e7Sxw161283 unsigned int t1_mc4_get_size(struct pemc4 *mc4) 205*d39a76e7Sxw161283 { 206*d39a76e7Sxw161283 return mc4->size; 207*d39a76e7Sxw161283 } 208*d39a76e7Sxw161283 209*d39a76e7Sxw161283 #define MC4_INT_MASK (F_MC4_CORR_ERR | F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR) 210*d39a76e7Sxw161283 #define MC4_INT_FATAL (F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR) 211*d39a76e7Sxw161283 212*d39a76e7Sxw161283 void t1_mc4_intr_enable(struct pemc4 *mc4) 213*d39a76e7Sxw161283 { 214*d39a76e7Sxw161283 u32 pl_intr; 215*d39a76e7Sxw161283 216*d39a76e7Sxw161283 if (t1_is_asic(mc4->adapter)) { 217*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, MC4_INT_MASK); 218*d39a76e7Sxw161283 219*d39a76e7Sxw161283 pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE); 220*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_PL_ENABLE, 221*d39a76e7Sxw161283 pl_intr | F_PL_INTR_MC4); 222*d39a76e7Sxw161283 } 223*d39a76e7Sxw161283 } 224*d39a76e7Sxw161283 225*d39a76e7Sxw161283 void t1_mc4_intr_disable(struct pemc4 *mc4) 226*d39a76e7Sxw161283 { 227*d39a76e7Sxw161283 u32 pl_intr; 228*d39a76e7Sxw161283 229*d39a76e7Sxw161283 if (t1_is_asic(mc4->adapter)) { 230*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, 0); 231*d39a76e7Sxw161283 232*d39a76e7Sxw161283 pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE); 233*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_PL_ENABLE, 234*d39a76e7Sxw161283 pl_intr & ~F_PL_INTR_MC4); 235*d39a76e7Sxw161283 } 236*d39a76e7Sxw161283 } 237*d39a76e7Sxw161283 238*d39a76e7Sxw161283 void t1_mc4_intr_clear(struct pemc4 *mc4) 239*d39a76e7Sxw161283 { 240*d39a76e7Sxw161283 if (t1_is_asic(mc4->adapter)) { 241*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, 0xffffffff); 242*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_PL_CAUSE, F_PL_INTR_MC4); 243*d39a76e7Sxw161283 } 244*d39a76e7Sxw161283 } 245*d39a76e7Sxw161283 246*d39a76e7Sxw161283 int t1_mc4_intr_handler(struct pemc4 *mc4) 247*d39a76e7Sxw161283 { 248*d39a76e7Sxw161283 adapter_t *adapter = mc4->adapter; 249*d39a76e7Sxw161283 u32 cause = t1_read_reg_4(adapter, A_MC4_INT_CAUSE); 250*d39a76e7Sxw161283 251*d39a76e7Sxw161283 if (cause & F_MC4_CORR_ERR) { 252*d39a76e7Sxw161283 mc4->intr_cnt.corr_err++; 253*d39a76e7Sxw161283 CH_WARN("%s: MC4 correctable error at addr 0x%x, " 254*d39a76e7Sxw161283 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n", 255*d39a76e7Sxw161283 adapter_name(adapter), 256*d39a76e7Sxw161283 G_MC4_CE_ADDR(t1_read_reg_4(adapter, A_MC4_CE_ADDR)), 257*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_CE_DATA0), 258*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_CE_DATA1), 259*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_CE_DATA2), 260*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_CE_DATA3), 261*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_CE_DATA4)); 262*d39a76e7Sxw161283 } 263*d39a76e7Sxw161283 264*d39a76e7Sxw161283 if (cause & F_MC4_UNCORR_ERR) { 265*d39a76e7Sxw161283 mc4->intr_cnt.uncorr_err++; 266*d39a76e7Sxw161283 CH_ALERT("%s: MC4 uncorrectable error at addr 0x%x, " 267*d39a76e7Sxw161283 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n", 268*d39a76e7Sxw161283 adapter_name(adapter), 269*d39a76e7Sxw161283 G_MC4_UE_ADDR(t1_read_reg_4(adapter, A_MC4_UE_ADDR)), 270*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_UE_DATA0), 271*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_UE_DATA1), 272*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_UE_DATA2), 273*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_UE_DATA3), 274*d39a76e7Sxw161283 t1_read_reg_4(adapter, A_MC4_UE_DATA4)); 275*d39a76e7Sxw161283 } 276*d39a76e7Sxw161283 277*d39a76e7Sxw161283 if (cause & F_MC4_ADDR_ERR) { 278*d39a76e7Sxw161283 mc4->intr_cnt.addr_err++; 279*d39a76e7Sxw161283 CH_ALERT("%s: MC4 address error\n", adapter_name(adapter)); 280*d39a76e7Sxw161283 } 281*d39a76e7Sxw161283 282*d39a76e7Sxw161283 if (cause & MC4_INT_FATAL) 283*d39a76e7Sxw161283 t1_fatal_err(adapter); 284*d39a76e7Sxw161283 285*d39a76e7Sxw161283 t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, cause); 286*d39a76e7Sxw161283 return 0; 287*d39a76e7Sxw161283 } 288*d39a76e7Sxw161283 289*d39a76e7Sxw161283 const struct pemc4_intr_counts *t1_mc4_get_intr_counts(struct pemc4 *mc4) 290*d39a76e7Sxw161283 { 291*d39a76e7Sxw161283 return &mc4->intr_cnt; 292*d39a76e7Sxw161283 } 293*d39a76e7Sxw161283 294*d39a76e7Sxw161283 /* 295*d39a76e7Sxw161283 * Read n 256-bit words from MC4 starting at word start, using backdoor 296*d39a76e7Sxw161283 * accesses. 297*d39a76e7Sxw161283 */ 298*d39a76e7Sxw161283 int t1_mc4_bd_read(struct pemc4 *mc4, unsigned int start, unsigned int n, 299*d39a76e7Sxw161283 u32 *buf) 300*d39a76e7Sxw161283 { 301*d39a76e7Sxw161283 adapter_t *adap = mc4->adapter; 302*d39a76e7Sxw161283 unsigned int size256 = mc4->size / 32, c = 8 / mc4->nwords, i; 303*d39a76e7Sxw161283 304*d39a76e7Sxw161283 if (start >= size256 || start + n > size256) 305*d39a76e7Sxw161283 return -EINVAL; 306*d39a76e7Sxw161283 307*d39a76e7Sxw161283 for (i = 8, start *= 16 * c, n *= c; n; --n, start += 16) { 308*d39a76e7Sxw161283 int attempts = 10; 309*d39a76e7Sxw161283 u32 val; 310*d39a76e7Sxw161283 311*d39a76e7Sxw161283 t1_write_reg_4(adap, A_MC4_BD_ADDR, start); 312*d39a76e7Sxw161283 t1_write_reg_4(adap, A_MC4_BD_OP, 0); 313*d39a76e7Sxw161283 val = t1_read_reg_4(adap, A_MC4_BD_OP); 314*d39a76e7Sxw161283 while ((val & F_BUSY) && attempts--) 315*d39a76e7Sxw161283 val = t1_read_reg_4(adap, A_MC4_BD_OP); 316*d39a76e7Sxw161283 317*d39a76e7Sxw161283 if (val & F_BUSY) 318*d39a76e7Sxw161283 return -EIO; 319*d39a76e7Sxw161283 320*d39a76e7Sxw161283 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA3); 321*d39a76e7Sxw161283 if (mc4->nwords >= 2) 322*d39a76e7Sxw161283 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA2); 323*d39a76e7Sxw161283 if (mc4->nwords == 4) { 324*d39a76e7Sxw161283 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA1); 325*d39a76e7Sxw161283 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA0); 326*d39a76e7Sxw161283 } 327*d39a76e7Sxw161283 if (i == 0) { 328*d39a76e7Sxw161283 i = 8; 329*d39a76e7Sxw161283 buf += 8; 330*d39a76e7Sxw161283 } 331*d39a76e7Sxw161283 } 332*d39a76e7Sxw161283 return 0; 333*d39a76e7Sxw161283 } 334