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 /* 23 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* Driver for Vitesse VSC7326 (Schaumburg) MAC */ 29 30 #include "gmac.h" 31 #include "elmer0.h" 32 #include "vsc7326_reg.h" 33 34 FILE_IDENT("@(#) $Id: vsc7326.c,v 1.17 2005/10/29 05:42:36 sbardone Exp $"); 35 36 /* Update fast changing statistics every 15 seconds */ 37 #define STATS_TICK_SECS 15 38 /* 30 minutes for full statistics update */ 39 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS) 40 41 #define MAX_MTU 9600 42 43 struct init_table { 44 u32 addr; 45 u32 data; 46 }; 47 48 struct _cmac_instance { 49 u32 index; 50 u32 ticks; 51 }; 52 53 #define INITBLOCK_SLEEP 0xffffffff 54 55 static void vsc_read(adapter_t *adapter, u32 addr, u32 *val) 56 { 57 u32 status, vlo, vhi; 58 int i; 59 60 MAC_LOCK(adapter->mac_lock); 61 (void) t1_tpi_read(adapter, (addr << 2) + 4, &vlo); 62 i = 0; 63 do { 64 (void) t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo); 65 (void) t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi); 66 status = (vhi << 16) | vlo; 67 i++; 68 } while (((status & 1) == 0) && (i < 50)); 69 if (i == 50) 70 CH_ERR("Invalid tpi read from MAC, breaking loop.\n"); 71 72 (void) t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo); 73 (void) t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi); 74 75 *val = (vhi << 16) | vlo; 76 77 /* CH_ERR("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", 78 ((addr&0xe000)>>13), ((addr&0x1e00)>>9), 79 ((addr&0x01fe)>>1), *val); */ 80 MAC_UNLOCK(adapter->mac_lock); 81 } 82 83 static void vsc_write(adapter_t *adapter, u32 addr, u32 data) 84 { 85 MAC_LOCK(adapter->mac_lock); 86 (void) t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF); 87 (void) t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF); 88 /* CH_ERR("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", 89 ((addr&0xe000)>>13), ((addr&0x1e00)>>9), 90 ((addr&0x01fe)>>1), data); */ 91 MAC_UNLOCK(adapter->mac_lock); 92 } 93 94 /* Hard reset the MAC. This wipes out *all* configuration. */ 95 static void vsc7326_full_reset(adapter_t* adapter) 96 { 97 u32 val; 98 u32 result = 0xffff; 99 100 (void) t1_tpi_read(adapter, A_ELMER0_GPO, &val); 101 val &= ~1; 102 (void) t1_tpi_write(adapter, A_ELMER0_GPO, val); 103 DELAY_US(2); 104 val |= 0x1; /* Enable mac MAC itself */ 105 val |= 0x800; /* Turn off the red LED */ 106 (void) t1_tpi_write(adapter, A_ELMER0_GPO, val); 107 DELAY_MS(1); 108 vsc_write(adapter, REG_SW_RESET, 0x80000001); 109 do { 110 DELAY_MS(1); 111 vsc_read(adapter, REG_SW_RESET, &result); 112 } while (result != 0x0); 113 } 114 115 static struct init_table vsc7326_reset[] = { 116 { REG_IFACE_MODE, 0x00000000 }, 117 { REG_CRC_CFG, 0x00000020 }, 118 { REG_PLL_CLK_SPEED, 0x00050c00 }, 119 { REG_PLL_CLK_SPEED, 0x00050c00 }, 120 { REG_MSCH, 0x00002f14 }, 121 { REG_SPI4_MISC, 0x00040409 }, 122 { REG_SPI4_DESKEW, 0x00080000 }, 123 { REG_SPI4_ING_SETUP2, 0x08080004 }, 124 { REG_SPI4_ING_SETUP0, 0x04111004 }, 125 { REG_SPI4_EGR_SETUP0, 0x80001a04 }, 126 { REG_SPI4_ING_SETUP1, 0x02010000 }, 127 { REG_AGE_INC(0), 0x00000000 }, 128 { REG_AGE_INC(1), 0x00000000 }, 129 { REG_ING_CONTROL, 0x0a200011 }, 130 { REG_EGR_CONTROL, 0xa0010091 }, 131 }; 132 133 static struct init_table vsc7326_portinit[4][22] = { 134 { /* Port 0 */ 135 /* FIFO setup */ 136 { REG_DBG(0), 0x000004f0 }, 137 { REG_HDX(0), 0x00073101 }, 138 { REG_TEST(0,0), 0x00000022 }, 139 { REG_TEST(1,0), 0x00000022 }, 140 { REG_TOP_BOTTOM(0,0), 0x003f0000 }, 141 { REG_TOP_BOTTOM(1,0), 0x00120000 }, 142 { REG_HIGH_LOW_WM(0,0), 0x07460757 }, 143 { REG_HIGH_LOW_WM(1,0), 0x01a01fff }, 144 { REG_CT_THRHLD(0,0), 0x00000000 }, 145 { REG_CT_THRHLD(1,0), 0x00000000 }, 146 { REG_BUCKE(0), 0x0002ffff }, 147 { REG_BUCKI(0), 0x0002ffff }, 148 { REG_TEST(0,0), 0x00000020 }, 149 { REG_TEST(1,0), 0x00000020 }, 150 /* Port config */ 151 { REG_MAX_LEN(0), 0x00002710 }, 152 { REG_PORT_FAIL(0), 0x00000002 }, 153 { REG_NORMALIZER(0), 0x00000a64 }, 154 { REG_DENORM(0), 0x00000010 }, 155 { REG_STICK_BIT(0), 0x03baa370 }, 156 { REG_DEV_SETUP(0), 0x00000083 }, 157 { REG_DEV_SETUP(0), 0x00000082 }, 158 { REG_MODE_CFG(0), 0x0200259f }, 159 }, 160 { /* Port 1 */ 161 /* FIFO setup */ 162 { REG_DBG(1), 0x000004f0 }, 163 { REG_HDX(1), 0x00073101 }, 164 { REG_TEST(0,1), 0x00000022 }, 165 { REG_TEST(1,1), 0x00000022 }, 166 { REG_TOP_BOTTOM(0,1), 0x007e003f }, 167 { REG_TOP_BOTTOM(1,1), 0x00240012 }, 168 { REG_HIGH_LOW_WM(0,1), 0x07460757 }, 169 { REG_HIGH_LOW_WM(1,1), 0x01a01fff }, 170 { REG_CT_THRHLD(0,1), 0x00000000 }, 171 { REG_CT_THRHLD(1,1), 0x00000000 }, 172 { REG_BUCKE(1), 0x0002ffff }, 173 { REG_BUCKI(1), 0x0002ffff }, 174 { REG_TEST(0,1), 0x00000020 }, 175 { REG_TEST(1,1), 0x00000020 }, 176 /* Port config */ 177 { REG_MAX_LEN(1), 0x00002710 }, 178 { REG_PORT_FAIL(1), 0x00000002 }, 179 { REG_NORMALIZER(1), 0x00000a64 }, 180 { REG_DENORM(1), 0x00000010 }, 181 { REG_STICK_BIT(1), 0x03baa370 }, 182 { REG_DEV_SETUP(1), 0x00000083 }, 183 { REG_DEV_SETUP(1), 0x00000082 }, 184 { REG_MODE_CFG(1), 0x0200259f }, 185 }, 186 { /* Port 2 */ 187 /* FIFO setup */ 188 { REG_DBG(2), 0x000004f0 }, 189 { REG_HDX(2), 0x00073101 }, 190 { REG_TEST(0,2), 0x00000022 }, 191 { REG_TEST(1,2), 0x00000022 }, 192 { REG_TOP_BOTTOM(0,2), 0x00bd007e }, 193 { REG_TOP_BOTTOM(1,2), 0x00360024 }, 194 { REG_HIGH_LOW_WM(0,2), 0x07460757 }, 195 { REG_HIGH_LOW_WM(1,2), 0x01a01fff }, 196 { REG_CT_THRHLD(0,2), 0x00000000 }, 197 { REG_CT_THRHLD(1,2), 0x00000000 }, 198 { REG_BUCKE(2), 0x0002ffff }, 199 { REG_BUCKI(2), 0x0002ffff }, 200 { REG_TEST(0,2), 0x00000020 }, 201 { REG_TEST(1,2), 0x00000020 }, 202 /* Port config */ 203 { REG_MAX_LEN(2), 0x00002710 }, 204 { REG_PORT_FAIL(2), 0x00000002 }, 205 { REG_NORMALIZER(2), 0x00000a64 }, 206 { REG_DENORM(2), 0x00000010 }, 207 { REG_STICK_BIT(2), 0x03baa370 }, 208 { REG_DEV_SETUP(2), 0x00000083 }, 209 { REG_DEV_SETUP(2), 0x00000082 }, 210 { REG_MODE_CFG(2), 0x0200259f }, 211 }, 212 { /* Port 3 */ 213 /* FIFO setup */ 214 { REG_DBG(3), 0x000004f0 }, 215 { REG_HDX(3), 0x00073101 }, 216 { REG_TEST(0,3), 0x00000022 }, 217 { REG_TEST(1,3), 0x00000022 }, 218 { REG_TOP_BOTTOM(0,3), 0x00fc00bd }, 219 { REG_TOP_BOTTOM(1,3), 0x00480036 }, 220 { REG_HIGH_LOW_WM(0,3), 0x07460757 }, 221 { REG_HIGH_LOW_WM(1,3), 0x01a01fff }, 222 { REG_CT_THRHLD(0,3), 0x00000000 }, 223 { REG_CT_THRHLD(1,3), 0x00000000 }, 224 { REG_BUCKE(3), 0x0002ffff }, 225 { REG_BUCKI(3), 0x0002ffff }, 226 { REG_TEST(0,3), 0x00000020 }, 227 { REG_TEST(1,3), 0x00000020 }, 228 /* Port config */ 229 { REG_MAX_LEN(3), 0x00002710 }, 230 { REG_PORT_FAIL(3), 0x00000002 }, 231 { REG_NORMALIZER(3), 0x00000a64 }, 232 { REG_DENORM(3), 0x00000010 }, 233 { REG_STICK_BIT(3), 0x03baa370 }, 234 { REG_DEV_SETUP(3), 0x00000083 }, 235 { REG_DEV_SETUP(3), 0x00000082 }, 236 { REG_MODE_CFG(3), 0x0200259f }, 237 }, 238 }; 239 240 static void run_table(adapter_t *adapter, struct init_table *ib, int len) 241 { 242 int i; 243 244 for (i = 0; i < len; i++) { 245 if (ib[i].addr == INITBLOCK_SLEEP) { 246 DELAY_US( ib[i].data ); 247 CH_ERR("sleep %d us\n",ib[i].data); 248 } else { 249 vsc_write( adapter, ib[i].addr, ib[i].data ); 250 } 251 } 252 } 253 254 static int bist_rd(adapter_t *adapter, int moduleid, int address) 255 { 256 int data=0; 257 u32 result=0; 258 259 if( (address != 0x0) && 260 (address != 0x1) && 261 (address != 0x2) && 262 (address != 0xd) && 263 (address != 0xe)) 264 CH_ERR("No bist address: 0x%x\n", address); 265 266 data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) | 267 ((moduleid & 0xff) << 0)); 268 vsc_write(adapter, REG_RAM_BIST_CMD, data); 269 270 DELAY_US(10); 271 272 vsc_read(adapter, REG_RAM_BIST_RESULT, &result); 273 if((result & (1<<9)) != 0x0) 274 CH_ERR("Still in bist read: 0x%x\n", result); 275 else if((result & (1<<8)) != 0x0) 276 CH_ERR("bist read error: 0x%x\n", result); 277 278 return(result & 0xff); 279 } 280 281 static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) 282 { 283 int data=0; 284 u32 result=0; 285 286 if( (address != 0x0) && 287 (address != 0x1) && 288 (address != 0x2) && 289 (address != 0xd) && 290 (address != 0xe)) 291 CH_ERR("No bist address: 0x%x\n", address); 292 293 if( value>255 ) 294 CH_ERR("Suspicious write out of range value: 0x%x\n", value); 295 296 data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) | 297 ((moduleid & 0xff) << 0)); 298 vsc_write(adapter, REG_RAM_BIST_CMD, data); 299 300 DELAY_US(5); 301 302 vsc_read(adapter, REG_RAM_BIST_CMD, &result); 303 if((result & (1<<27)) != 0x0) 304 CH_ERR("Still in bist write: 0x%x\n", result); 305 else if((result & (1<<26)) != 0x0) 306 CH_ERR("bist write error: 0x%x\n", result); 307 308 return(0); 309 } 310 311 static int run_bist(adapter_t *adapter, int moduleid) 312 { 313 /*run bist*/ 314 (void) bist_wr(adapter,moduleid, 0x00, 0x02); 315 (void) bist_wr(adapter,moduleid, 0x01, 0x01); 316 317 return(0); 318 } 319 320 static int check_bist(adapter_t *adapter, int moduleid) 321 { 322 int result=0; 323 int column=0; 324 /*check bist*/ 325 result = bist_rd(adapter,moduleid, 0x02); 326 column = ((bist_rd(adapter,moduleid, 0x0e)<<8) + 327 (bist_rd(adapter,moduleid, 0x0d))); 328 if ((result & 3) != 0x3) 329 CH_ERR("Result: 0x%x BIST error in ram %d, column: 0x%04x\n", 330 result, moduleid, column); 331 return(0); 332 } 333 334 static int enable_mem(adapter_t *adapter, int moduleid) 335 { 336 /*enable mem*/ 337 (void) bist_wr(adapter,moduleid, 0x00, 0x00); 338 return(0); 339 } 340 341 static int run_bist_all(adapter_t *adapter) 342 { 343 int port=0; 344 u32 val=0; 345 346 vsc_write(adapter, REG_MEM_BIST, 0x5); 347 vsc_read(adapter, REG_MEM_BIST, &val); 348 349 for(port=0; port<12; port++){ 350 vsc_write(adapter, REG_DEV_SETUP(port), 0x0); 351 } 352 353 DELAY_US(300); 354 vsc_write(adapter, REG_SPI4_MISC, 0x00040409); 355 DELAY_US(300); 356 357 (void) run_bist(adapter,13); 358 (void) run_bist(adapter,14); 359 (void) run_bist(adapter,20); 360 (void) run_bist(adapter,21); 361 DELAY_MS(200); 362 (void) check_bist(adapter,13); 363 (void) check_bist(adapter,14); 364 (void) check_bist(adapter,20); 365 (void) check_bist(adapter,21); 366 DELAY_US(100); 367 (void) enable_mem(adapter,13); 368 (void) enable_mem(adapter,14); 369 (void) enable_mem(adapter,20); 370 (void) enable_mem(adapter,21); 371 DELAY_US(300); 372 vsc_write(adapter, REG_SPI4_MISC, 0x60040400); 373 DELAY_US(300); 374 for(port=0; port<12; port++){ 375 vsc_write(adapter, REG_DEV_SETUP(port), 0x1); 376 } 377 DELAY_US(300); 378 vsc_write(adapter, REG_MEM_BIST, 0x0); 379 DELAY_MS(10); 380 return(0); 381 } 382 383 /* ARGSUSED */ 384 static int mac_intr_handler(struct cmac *mac) 385 { 386 return 0; 387 } 388 389 /* ARGSUSED */ 390 static int mac_intr_enable(struct cmac *mac) 391 { 392 return 0; 393 } 394 395 /* ARGSUSED */ 396 static int mac_intr_disable(struct cmac *mac) 397 { 398 return 0; 399 } 400 401 /* ARGSUSED */ 402 static int mac_intr_clear(struct cmac *mac) 403 { 404 return 0; 405 } 406 407 /* Expect MAC address to be in network byte order. */ 408 static int mac_set_address(struct cmac* mac, u8 addr[6]) 409 { 410 u32 val; 411 int port = mac->instance->index; 412 413 vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port), 414 (addr[3] << 16) | (addr[4] << 8) | addr[5]); 415 vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port), 416 (addr[0] << 16) | (addr[1] << 8) | addr[2]); 417 418 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val); 419 val &= ~0xf0000000; 420 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28)); 421 422 vsc_write(mac->adapter, REG_ING_FFILT_MASK0, 423 0xffff0000 | (addr[4] << 8) | addr[5]); 424 vsc_write(mac->adapter, REG_ING_FFILT_MASK1, 425 0xffff0000 | (addr[2] << 8) | addr[3]); 426 vsc_write(mac->adapter, REG_ING_FFILT_MASK2, 427 0xffff0000 | (addr[0] << 8) | addr[1]); 428 return 0; 429 } 430 431 static int mac_get_address(struct cmac *mac, u8 addr[6]) 432 { 433 u32 addr_lo, addr_hi; 434 int port = mac->instance->index; 435 436 vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo); 437 vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi); 438 439 addr[0] = (u8) (addr_hi >> 16); 440 addr[1] = (u8) (addr_hi >> 8); 441 addr[2] = (u8) addr_hi; 442 addr[3] = (u8) (addr_lo >> 16); 443 addr[4] = (u8) (addr_lo >> 8); 444 addr[5] = (u8) addr_lo; 445 return 0; 446 } 447 448 /* This is intended to reset a port, not the whole MAC */ 449 static int mac_reset(struct cmac *mac) 450 { 451 int index = mac->instance->index; 452 453 run_table(mac->adapter, vsc7326_portinit[index], 454 DIMOF(vsc7326_portinit[index])); 455 456 return 0; 457 } 458 459 static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm) 460 { 461 u32 v; 462 int port = mac->instance->index; 463 464 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v); 465 v |= 1 << 12; 466 467 if (t1_rx_mode_promisc(rm)) 468 v &= ~(1 << (port + 16)); 469 else 470 v |= 1 << (port + 16); 471 472 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v); 473 return 0; 474 } 475 476 static int mac_set_mtu(struct cmac *mac, int mtu) 477 { 478 int port = mac->instance->index; 479 480 if (mtu > MAX_MTU) 481 return -EINVAL; 482 483 /* max_len includes header and FCS */ 484 vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4); 485 return 0; 486 } 487 488 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, 489 int fc) 490 { 491 u32 v; 492 int enable, port = mac->instance->index; 493 494 if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 && 495 speed != SPEED_1000) 496 return -1; 497 if (duplex > 0 && duplex != DUPLEX_FULL) 498 return -1; 499 500 if (speed >= 0) { 501 vsc_read(mac->adapter, REG_MODE_CFG(port), &v); 502 enable = v & 3; /* save tx/rx enables */ 503 v &= ~0xf; 504 v |= 4; /* full duplex */ 505 if (speed == SPEED_1000) 506 v |= 8; /* GigE */ 507 enable |= v; 508 vsc_write(mac->adapter, REG_MODE_CFG(port), v); 509 510 if (speed == SPEED_1000) 511 v = 0x82; 512 else if (speed == SPEED_100) 513 v = 0x84; 514 else /* SPEED_10 */ 515 v = 0x86; 516 vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */ 517 vsc_write(mac->adapter, REG_DEV_SETUP(port), v); 518 vsc_read(mac->adapter, REG_DBG(port), &v); 519 v &= ~0xff00; 520 if (speed == SPEED_1000) 521 v |= 0x400; 522 else if (speed == SPEED_100) 523 v |= 0x2000; 524 else /* SPEED_10 */ 525 v |= 0xff00; 526 vsc_write(mac->adapter, REG_DBG(port), v); 527 528 vsc_write(mac->adapter, REG_TX_IFG(port), 529 speed == SPEED_1000 ? 5 : 0x11); 530 if (duplex == DUPLEX_HALF) 531 enable = 0x0; /* 100 or 10 */ 532 else if (speed == SPEED_1000) 533 enable = 0xc; 534 else /* SPEED_100 or 10 */ 535 enable = 0x4; 536 enable |= 0x9 << 10; /* IFG1 */ 537 enable |= 0x6 << 6; /* IFG2 */ 538 enable |= 0x1 << 4; /* VLAN */ 539 enable |= 0x3; /* RX/TX EN */ 540 vsc_write(mac->adapter, REG_MODE_CFG(port), enable); 541 542 } 543 544 vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v); 545 v &= 0xfff0ffff; 546 v |= 0x20000; /* xon/xoff */ 547 if (fc & PAUSE_RX) 548 v |= 0x40000; 549 if (fc & PAUSE_TX) 550 v |= 0x80000; 551 if (fc == (PAUSE_RX | PAUSE_TX)) 552 v |= 0x10000; 553 vsc_write(mac->adapter, REG_PAUSE_CFG(port), v); 554 return 0; 555 } 556 557 static int mac_enable(struct cmac *mac, int which) 558 { 559 u32 val; 560 int port = mac->instance->index; 561 562 vsc_read(mac->adapter, REG_MODE_CFG(port), &val); 563 if (which & MAC_DIRECTION_RX) 564 val |= 0x2; 565 if (which & MAC_DIRECTION_TX) 566 val |= 1; 567 vsc_write(mac->adapter, REG_MODE_CFG(port), val); 568 return 0; 569 } 570 571 static int mac_disable(struct cmac *mac, int which) 572 { 573 u32 val; 574 int i, port = mac->instance->index; 575 576 /* Reset the port */ 577 (void) mac_reset(mac); 578 579 vsc_read(mac->adapter, REG_MODE_CFG(port), &val); 580 if (which & MAC_DIRECTION_RX) 581 val &= ~0x2; 582 if (which & MAC_DIRECTION_TX) 583 val &= ~0x1; 584 vsc_write(mac->adapter, REG_MODE_CFG(port), val); 585 vsc_read(mac->adapter, REG_MODE_CFG(port), &val); 586 587 /* Clear stats */ 588 for (i = 0; i <= 0x3a; ++i) 589 vsc_write(mac->adapter, CRA(4, port, i), 0); 590 591 /* Clear sofware counters */ 592 memset(&mac->stats, 0, sizeof(struct cmac_statistics)); 593 594 return 0; 595 } 596 597 static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat) 598 { 599 u32 v, lo; 600 601 vsc_read(mac->adapter, addr, &v); 602 lo = *stat; 603 *stat = *stat - lo + v; 604 605 if (v == 0) 606 return; 607 608 if (v < lo) 609 *stat += (1ULL << 32); 610 } 611 612 static void port_stats_update(struct cmac *mac) 613 { 614 int port = mac->instance->index; 615 616 /* Rx stats */ 617 rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK); 618 rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad); 619 rmon_update(mac, REG_RX_UNICAST(port), &mac->stats.RxUnicastFramesOK); 620 rmon_update(mac, REG_RX_MULTICAST(port), 621 &mac->stats.RxMulticastFramesOK); 622 rmon_update(mac, REG_RX_BROADCAST(port), 623 &mac->stats.RxBroadcastFramesOK); 624 rmon_update(mac, REG_CRC(port), &mac->stats.RxFCSErrors); 625 rmon_update(mac, REG_RX_ALIGNMENT(port), &mac->stats.RxAlignErrors); 626 rmon_update(mac, REG_RX_OVERSIZE(port), 627 &mac->stats.RxFrameTooLongErrors); 628 rmon_update(mac, REG_RX_PAUSE(port), &mac->stats.RxPauseFrames); 629 rmon_update(mac, REG_RX_JABBERS(port), &mac->stats.RxJabberErrors); 630 rmon_update(mac, REG_RX_FRAGMENTS(port), &mac->stats.RxRuntErrors); 631 rmon_update(mac, REG_RX_UNDERSIZE(port), &mac->stats.RxRuntErrors); 632 rmon_update(mac, REG_RX_SYMBOL_CARRIER(port), 633 &mac->stats.RxSymbolErrors); 634 rmon_update(mac, REG_RX_SIZE_1519_TO_MAX(port), 635 &mac->stats.RxJumboFramesOK); 636 637 /* Tx stats (skip collision stats as we are full-duplex only) */ 638 rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK); 639 rmon_update(mac, REG_TX_UNICAST(port), &mac->stats.TxUnicastFramesOK); 640 rmon_update(mac, REG_TX_MULTICAST(port), 641 &mac->stats.TxMulticastFramesOK); 642 rmon_update(mac, REG_TX_BROADCAST(port), 643 &mac->stats.TxBroadcastFramesOK); 644 rmon_update(mac, REG_TX_PAUSE(port), &mac->stats.TxPauseFrames); 645 rmon_update(mac, REG_TX_UNDERRUN(port), &mac->stats.TxUnderrun); 646 rmon_update(mac, REG_TX_SIZE_1519_TO_MAX(port), 647 &mac->stats.TxJumboFramesOK); 648 } 649 650 /* 651 * This function is called periodically to accumulate the current values of the 652 * RMON counters into the port statistics. Since the counters are only 32 bits 653 * some of them can overflow in less than a minute at GigE speeds, so this 654 * function should be called every 30 seconds or so. 655 * 656 * To cut down on reading costs we update only the octet counters at each tick 657 * and do a full update at major ticks, which can be every 30 minutes or more. 658 */ 659 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac, 660 int flag) 661 { 662 if (flag == MAC_STATS_UPDATE_FULL || 663 mac->instance->ticks >= MAJOR_UPDATE_TICKS) { 664 port_stats_update(mac); 665 mac->instance->ticks = 0; 666 } else { 667 int port = mac->instance->index; 668 669 rmon_update(mac, REG_RX_OK_BYTES(port), 670 &mac->stats.RxOctetsOK); 671 rmon_update(mac, REG_RX_BAD_BYTES(port), 672 &mac->stats.RxOctetsBad); 673 rmon_update(mac, REG_TX_OK_BYTES(port), 674 &mac->stats.TxOctetsOK); 675 mac->instance->ticks++; 676 } 677 return &mac->stats; 678 } 679 680 static void mac_destroy(struct cmac *mac) 681 { 682 t1_os_free((void *)mac, sizeof(*mac) + sizeof(cmac_instance)); 683 } 684 685 #ifdef C99_NOT_SUPPORTED 686 static struct cmac_ops vsc7326_ops = { 687 mac_destroy, 688 mac_reset, 689 mac_intr_enable, 690 mac_intr_disable, 691 mac_intr_clear, 692 mac_intr_handler, 693 mac_enable, 694 mac_disable, 695 NULL, 696 NULL, 697 mac_set_mtu, 698 mac_set_rx_mode, 699 mac_set_speed_duplex_fc, 700 NULL, 701 mac_update_statistics, 702 mac_get_address, 703 mac_set_address 704 }; 705 #else 706 static struct cmac_ops vsc7326_ops = { 707 .destroy = mac_destroy, 708 .reset = mac_reset, 709 .interrupt_handler = mac_intr_handler, 710 .interrupt_enable = mac_intr_enable, 711 .interrupt_disable = mac_intr_disable, 712 .interrupt_clear = mac_intr_clear, 713 .enable = mac_enable, 714 .disable = mac_disable, 715 .set_mtu = mac_set_mtu, 716 .set_rx_mode = mac_set_rx_mode, 717 .set_speed_duplex_fc = mac_set_speed_duplex_fc, 718 .statistics_update = mac_update_statistics, 719 .macaddress_get = mac_get_address, 720 .macaddress_set = mac_set_address, 721 }; 722 #endif 723 724 static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index) 725 { 726 struct cmac *mac; 727 u32 val; 728 int i; 729 730 mac = t1_os_malloc_wait_zero(sizeof(*mac) + sizeof(cmac_instance)); 731 if (!mac) return NULL; 732 733 mac->ops = &vsc7326_ops; 734 mac->instance = (cmac_instance *)(mac + 1); 735 mac->adapter = adapter; 736 737 mac->instance->index = index; 738 mac->instance->ticks = 0; 739 740 i = 0; 741 do { 742 u32 vhi, vlo; 743 744 vhi = vlo = 0; 745 (void) t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo); 746 DELAY_US(1); 747 (void) t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi); 748 DELAY_US(5); 749 val = (vhi << 16) | vlo; 750 } while ((++i < 10000) && (val == 0xffffffff)); 751 752 return mac; 753 } 754 755 static int vsc7326_mac_reset(adapter_t *adapter) 756 { 757 vsc7326_full_reset(adapter); 758 (void) run_bist_all(adapter); 759 run_table(adapter, vsc7326_reset, DIMOF(vsc7326_reset)); 760 return 0; 761 } 762 763 struct gmac t1_vsc7326_ops = { 764 STATS_TICK_SECS, 765 vsc7326_mac_create, 766 vsc7326_mac_reset 767 }; 768