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