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