root/drivers/net/fddi/skfp/drvfbi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. card_start
  2. card_stop
  3. mac1_irq
  4. plc1_irq
  5. plc2_irq
  6. timer_irq
  7. pcm_get_s_port
  8. read_address
  9. init_board
  10. sm_pm_bypass_req
  11. sm_pm_bypass_present
  12. plc_clear_irq
  13. led_indication
  14. pcm_state_change
  15. rmt_indication
  16. llc_recover_tx
  17. is_equal_num
  18. set_oi_id_def
  19. driver_get_bia
  20. smt_start_watchdog
  21. smt_stop_watchdog
  22. mac_do_pci_fix

   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_regs.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_ERRBITS) ;
 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 

/* [<][>][^][v][top][bottom][index][help] */