1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /****************************************************************************** 3 * 4 * (C)Copyright 1998,1999 SysKonnect, 5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 6 * 7 * See the file "skfddi.c" for further information. 8 * 9 * The information in this file is provided "AS IS" without warranty. 10 * 11 ******************************************************************************/ 12 13 /* 14 * FBI board dependent Driver for SMT and LLC 15 */ 16 17 #include "h/types.h" 18 #include "h/fddi.h" 19 #include "h/smc.h" 20 #include "h/supern_2.h" 21 #include "h/skfbiinc.h" 22 #include <linux/bitrev.h> 23 #include <linux/pci.h> 24 25 #ifndef lint 26 static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ; 27 #endif 28 29 /* 30 * PCM active state 31 */ 32 #define PC8_ACTIVE 8 33 34 #define LED_Y_ON 0x11 /* Used for ring up/down indication */ 35 #define LED_Y_OFF 0x10 36 37 38 #define MS2BCLK(x) ((x)*12500L) 39 40 /* 41 * valid configuration values are: 42 */ 43 44 /* 45 * xPOS_ID:xxxx 46 * | \ / 47 * | \/ 48 * | --------------------- the patched POS_ID of the Adapter 49 * | xxxx = (Vendor ID low byte, 50 * | Vendor ID high byte, 51 * | Device ID low byte, 52 * | Device ID high byte) 53 * +------------------------------ the patched oem_id must be 54 * 'S' for SK or 'I' for IBM 55 * this is a short id for the driver. 56 */ 57 #ifndef MULT_OEM 58 #ifndef OEM_CONCEPT 59 const u_char oem_id[] = "xPOS_ID:xxxx" ; 60 #else /* OEM_CONCEPT */ 61 const u_char oem_id[] = OEM_ID ; 62 #endif /* OEM_CONCEPT */ 63 #define ID_BYTE0 8 64 #define OEMID(smc,i) oem_id[ID_BYTE0 + i] 65 #else /* MULT_OEM */ 66 const struct s_oem_ids oem_ids[] = { 67 #include "oemids.h" 68 {0} 69 }; 70 #define OEMID(smc,i) smc->hw.oem_id->oi_id[i] 71 #endif /* MULT_OEM */ 72 73 /* Prototypes of external functions */ 74 #ifdef AIX 75 extern int AIX_vpdReadByte() ; 76 #endif 77 78 79 /* Prototype of a local function. */ 80 static void smt_stop_watchdog(struct s_smc *smc); 81 82 /* 83 * FDDI card reset 84 */ 85 static void card_start(struct s_smc *smc) 86 { 87 int i ; 88 #ifdef PCI 89 u_char rev_id ; 90 u_short word; 91 #endif 92 93 smt_stop_watchdog(smc) ; 94 95 #ifdef PCI 96 /* 97 * make sure no transfer activity is pending 98 */ 99 outpw(FM_A(FM_MDREG1),FM_MINIT) ; 100 outp(ADDR(B0_CTRL), CTRL_HPI_SET) ; 101 hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ; 102 /* 103 * now reset everything 104 */ 105 outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */ 106 i = (int) inp(ADDR(B0_CTRL)) ; /* do dummy read */ 107 SK_UNUSED(i) ; /* Make LINT happy. */ 108 outp(ADDR(B0_CTRL), CTRL_RST_CLR) ; 109 110 /* 111 * Reset all bits in the PCI STATUS register 112 */ 113 outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ; /* enable for writes */ 114 word = inpw(PCI_C(PCI_STATUS)) ; 115 outpw(PCI_C(PCI_STATUS), word | PCI_STATUS_ERROR_BITS); 116 outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ; /* disable writes */ 117 118 /* 119 * Release the reset of all the State machines 120 * Release Master_Reset 121 * Release HPI_SM_Reset 122 */ 123 outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ; 124 125 /* 126 * determine the adapter type 127 * Note: Do it here, because some drivers may call card_start() once 128 * at very first before any other initialization functions is 129 * executed. 130 */ 131 rev_id = inp(PCI_C(PCI_REVISION_ID)) ; 132 if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) { 133 smc->hw.hw_is_64bit = TRUE ; 134 } else { 135 smc->hw.hw_is_64bit = FALSE ; 136 } 137 138 /* 139 * Watermark initialization 140 */ 141 if (!smc->hw.hw_is_64bit) { 142 outpd(ADDR(B4_R1_F), RX_WATERMARK) ; 143 outpd(ADDR(B5_XA_F), TX_WATERMARK) ; 144 outpd(ADDR(B5_XS_F), TX_WATERMARK) ; 145 } 146 147 outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* clear the reset chips */ 148 outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */ 149 150 /* init the timer value for the watch dog 2,5 minutes */ 151 outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ; 152 153 /* initialize the ISR mask */ 154 smc->hw.is_imask = ISR_MASK ; 155 smc->hw.hw_state = STOPPED ; 156 #endif 157 GET_PAGE(0) ; /* necessary for BOOT */ 158 } 159 160 void card_stop(struct s_smc *smc) 161 { 162 smt_stop_watchdog(smc) ; 163 smc->hw.mac_ring_is_up = 0 ; /* ring down */ 164 165 #ifdef PCI 166 /* 167 * make sure no transfer activity is pending 168 */ 169 outpw(FM_A(FM_MDREG1),FM_MINIT) ; 170 outp(ADDR(B0_CTRL), CTRL_HPI_SET) ; 171 hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ; 172 /* 173 * now reset everything 174 */ 175 outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */ 176 outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* reset for all chips */ 177 outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */ 178 smc->hw.hw_state = STOPPED ; 179 #endif 180 } 181 /*--------------------------- ISR handling ----------------------------------*/ 182 183 void mac1_irq(struct s_smc *smc, u_short stu, u_short stl) 184 { 185 int restart_tx = 0 ; 186 again: 187 188 /* 189 * parity error: note encoding error is not possible in tag mode 190 */ 191 if (stl & (FM_SPCEPDS | /* parity err. syn.q.*/ 192 FM_SPCEPDA0 | /* parity err. a.q.0 */ 193 FM_SPCEPDA1)) { /* parity err. a.q.1 */ 194 SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ; 195 } 196 /* 197 * buffer underrun: can only occur if a tx threshold is specified 198 */ 199 if (stl & (FM_STBURS | /* tx buffer underrun syn.q.*/ 200 FM_STBURA0 | /* tx buffer underrun a.q.0 */ 201 FM_STBURA1)) { /* tx buffer underrun a.q.2 */ 202 SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ; 203 } 204 205 if ( (stu & (FM_SXMTABT | /* transmit abort */ 206 FM_STXABRS | /* syn. tx abort */ 207 FM_STXABRA0)) || /* asyn. tx abort */ 208 (stl & (FM_SQLCKS | /* lock for syn. q. */ 209 FM_SQLCKA0)) ) { /* lock for asyn. q. */ 210 formac_tx_restart(smc) ; /* init tx */ 211 restart_tx = 1 ; 212 stu = inpw(FM_A(FM_ST1U)) ; 213 stl = inpw(FM_A(FM_ST1L)) ; 214 stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ; 215 if (stu || stl) 216 goto again ; 217 } 218 219 if (stu & (FM_STEFRMA0 | /* end of asyn tx */ 220 FM_STEFRMS)) { /* end of sync tx */ 221 restart_tx = 1 ; 222 } 223 224 if (restart_tx) 225 llc_restart_tx(smc) ; 226 } 227 228 /* 229 * interrupt source= plc1 230 * this function is called in nwfbisr.asm 231 */ 232 void plc1_irq(struct s_smc *smc) 233 { 234 u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ; 235 236 plc_irq(smc,PB,st) ; 237 } 238 239 /* 240 * interrupt source= plc2 241 * this function is called in nwfbisr.asm 242 */ 243 void plc2_irq(struct s_smc *smc) 244 { 245 u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ; 246 247 plc_irq(smc,PA,st) ; 248 } 249 250 251 /* 252 * interrupt source= timer 253 */ 254 void timer_irq(struct s_smc *smc) 255 { 256 hwt_restart(smc); 257 smc->hw.t_stop = smc->hw.t_start; 258 smt_timer_done(smc) ; 259 } 260 261 /* 262 * return S-port (PA or PB) 263 */ 264 int pcm_get_s_port(struct s_smc *smc) 265 { 266 SK_UNUSED(smc) ; 267 return PS; 268 } 269 270 /* 271 * Station Label = "FDDI-XYZ" where 272 * 273 * X = connector type 274 * Y = PMD type 275 * Z = port type 276 */ 277 #define STATION_LABEL_CONNECTOR_OFFSET 5 278 #define STATION_LABEL_PMD_OFFSET 6 279 #define STATION_LABEL_PORT_OFFSET 7 280 281 void read_address(struct s_smc *smc, u_char *mac_addr) 282 { 283 char ConnectorType ; 284 char PmdType ; 285 int i ; 286 287 #ifdef PCI 288 for (i = 0; i < 6; i++) { /* read mac address from board */ 289 smc->hw.fddi_phys_addr.a[i] = 290 bitrev8(inp(ADDR(B2_MAC_0+i))); 291 } 292 #endif 293 294 ConnectorType = inp(ADDR(B2_CONN_TYP)) ; 295 PmdType = inp(ADDR(B2_PMD_TYP)) ; 296 297 smc->y[PA].pmd_type[PMD_SK_CONN] = 298 smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ; 299 smc->y[PA].pmd_type[PMD_SK_PMD ] = 300 smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ; 301 302 if (mac_addr) { 303 for (i = 0; i < 6 ;i++) { 304 smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ; 305 smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]); 306 } 307 return ; 308 } 309 smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ; 310 311 for (i = 0; i < 6 ;i++) { 312 smc->hw.fddi_canon_addr.a[i] = 313 bitrev8(smc->hw.fddi_phys_addr.a[i]); 314 } 315 } 316 317 /* 318 * FDDI card soft reset 319 */ 320 void init_board(struct s_smc *smc, u_char *mac_addr) 321 { 322 card_start(smc) ; 323 read_address(smc,mac_addr) ; 324 325 if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL)) 326 smc->s.sas = SMT_SAS ; /* Single att. station */ 327 else 328 smc->s.sas = SMT_DAS ; /* Dual att. station */ 329 330 if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST)) 331 smc->mib.fddiSMTBypassPresent = 0 ; 332 /* without opt. bypass */ 333 else 334 smc->mib.fddiSMTBypassPresent = 1 ; 335 /* with opt. bypass */ 336 } 337 338 /* 339 * insert or deinsert optical bypass (called by ECM) 340 */ 341 void sm_pm_bypass_req(struct s_smc *smc, int mode) 342 { 343 DB_ECMN(1, "ECM : sm_pm_bypass_req(%s)", 344 mode == BP_INSERT ? "BP_INSERT" : "BP_DEINSERT"); 345 346 if (smc->s.sas != SMT_DAS) 347 return ; 348 349 #ifdef PCI 350 switch(mode) { 351 case BP_INSERT : 352 outp(ADDR(B0_DAS),DAS_BYP_INS) ; /* insert station */ 353 break ; 354 case BP_DEINSERT : 355 outp(ADDR(B0_DAS),DAS_BYP_RMV) ; /* bypass station */ 356 break ; 357 } 358 #endif 359 } 360 361 /* 362 * check if bypass connected 363 */ 364 int sm_pm_bypass_present(struct s_smc *smc) 365 { 366 return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE; 367 } 368 369 void plc_clear_irq(struct s_smc *smc, int p) 370 { 371 SK_UNUSED(p) ; 372 373 SK_UNUSED(smc) ; 374 } 375 376 377 /* 378 * led_indication called by rmt_indication() and 379 * pcm_state_change() 380 * 381 * Input: 382 * smc: SMT context 383 * led_event: 384 * 0 Only switch green LEDs according to their respective PCM state 385 * LED_Y_OFF just switch yellow LED off 386 * LED_Y_ON just switch yello LED on 387 */ 388 static void led_indication(struct s_smc *smc, int led_event) 389 { 390 /* use smc->hw.mac_ring_is_up == TRUE 391 * as indication for Ring Operational 392 */ 393 u_short led_state ; 394 struct s_phy *phy ; 395 struct fddi_mib_p *mib_a ; 396 struct fddi_mib_p *mib_b ; 397 398 phy = &smc->y[PA] ; 399 mib_a = phy->mib ; 400 phy = &smc->y[PB] ; 401 mib_b = phy->mib ; 402 403 #ifdef PCI 404 led_state = 0 ; 405 406 /* Ring up = yellow led OFF*/ 407 if (led_event == LED_Y_ON) { 408 led_state |= LED_MY_ON ; 409 } 410 else if (led_event == LED_Y_OFF) { 411 led_state |= LED_MY_OFF ; 412 } 413 else { /* PCM state changed */ 414 /* Link at Port A/S = green led A ON */ 415 if (mib_a->fddiPORTPCMState == PC8_ACTIVE) { 416 led_state |= LED_GA_ON ; 417 } 418 else { 419 led_state |= LED_GA_OFF ; 420 } 421 422 /* Link at Port B = green led B ON */ 423 if (mib_b->fddiPORTPCMState == PC8_ACTIVE) { 424 led_state |= LED_GB_ON ; 425 } 426 else { 427 led_state |= LED_GB_OFF ; 428 } 429 } 430 431 outp(ADDR(B0_LED), led_state) ; 432 #endif /* PCI */ 433 434 } 435 436 437 void pcm_state_change(struct s_smc *smc, int plc, int p_state) 438 { 439 /* 440 * the current implementation of pcm_state_change() in the driver 441 * parts must be renamed to drv_pcm_state_change() which will be called 442 * now after led_indication. 443 */ 444 DRV_PCM_STATE_CHANGE(smc,plc,p_state) ; 445 446 led_indication(smc,0) ; 447 } 448 449 450 void rmt_indication(struct s_smc *smc, int i) 451 { 452 /* Call a driver special function if defined */ 453 DRV_RMT_INDICATION(smc,i) ; 454 455 led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ; 456 } 457 458 459 /* 460 * llc_recover_tx called by init_tx (fplus.c) 461 */ 462 void llc_recover_tx(struct s_smc *smc) 463 { 464 #ifdef LOAD_GEN 465 extern int load_gen_flag ; 466 467 load_gen_flag = 0 ; 468 #endif 469 #ifndef SYNC 470 smc->hw.n_a_send= 0 ; 471 #else 472 SK_UNUSED(smc) ; 473 #endif 474 } 475 476 #ifdef MULT_OEM 477 static int is_equal_num(char comp1[], char comp2[], int num) 478 { 479 int i ; 480 481 for (i = 0 ; i < num ; i++) { 482 if (comp1[i] != comp2[i]) 483 return 0; 484 } 485 return 1; 486 } /* is_equal_num */ 487 488 489 /* 490 * set the OEM ID defaults, and test the contents of the OEM data base 491 * The default OEM is the first ACTIVE entry in the OEM data base 492 * 493 * returns: 0 success 494 * 1 error in data base 495 * 2 data base empty 496 * 3 no active entry 497 */ 498 int set_oi_id_def(struct s_smc *smc) 499 { 500 int sel_id ; 501 int i ; 502 int act_entries ; 503 504 i = 0 ; 505 sel_id = -1 ; 506 act_entries = FALSE ; 507 smc->hw.oem_id = 0 ; 508 smc->hw.oem_min_status = OI_STAT_ACTIVE ; 509 510 /* check OEM data base */ 511 while (oem_ids[i].oi_status) { 512 switch (oem_ids[i].oi_status) { 513 case OI_STAT_ACTIVE: 514 act_entries = TRUE ; /* we have active IDs */ 515 if (sel_id == -1) 516 sel_id = i ; /* save the first active ID */ 517 case OI_STAT_VALID: 518 case OI_STAT_PRESENT: 519 i++ ; 520 break ; /* entry ok */ 521 default: 522 return 1; /* invalid oi_status */ 523 } 524 } 525 526 if (i == 0) 527 return 2; 528 if (!act_entries) 529 return 3; 530 531 /* ok, we have a valid OEM data base with an active entry */ 532 smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[sel_id] ; 533 return 0; 534 } 535 #endif /* MULT_OEM */ 536 537 void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr) 538 { 539 int i ; 540 541 for (i = 0 ; i < 6 ; i++) 542 bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]); 543 } 544 545 void smt_start_watchdog(struct s_smc *smc) 546 { 547 SK_UNUSED(smc) ; /* Make LINT happy. */ 548 549 #ifndef DEBUG 550 551 #ifdef PCI 552 if (smc->hw.wdog_used) { 553 outpw(ADDR(B2_WDOG_CRTL),TIM_START) ; /* Start timer. */ 554 } 555 #endif 556 557 #endif /* DEBUG */ 558 } 559 560 static void smt_stop_watchdog(struct s_smc *smc) 561 { 562 SK_UNUSED(smc) ; /* Make LINT happy. */ 563 #ifndef DEBUG 564 565 #ifdef PCI 566 if (smc->hw.wdog_used) { 567 outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ; /* Stop timer. */ 568 } 569 #endif 570 571 #endif /* DEBUG */ 572 } 573 574 #ifdef PCI 575 576 void mac_do_pci_fix(struct s_smc *smc) 577 { 578 SK_UNUSED(smc) ; 579 } 580 #endif /* PCI */ 581 582