Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /******************************************************************************
0003  *
0004  *  (C)Copyright 1998,1999 SysKonnect,
0005  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0006  *
0007  *  See the file "skfddi.c" for further information.
0008  *
0009  *  The information in this file is provided "AS IS" without warranty.
0010  *
0011  ******************************************************************************/
0012 
0013 /*
0014  * FBI board dependent Driver for SMT and LLC
0015  */
0016 
0017 #include "h/types.h"
0018 #include "h/fddi.h"
0019 #include "h/smc.h"
0020 #include "h/supern_2.h"
0021 #include "h/skfbiinc.h"
0022 #include <linux/bitrev.h>
0023 #include <linux/pci.h>
0024 
0025 /*
0026  * PCM active state
0027  */
0028 #define PC8_ACTIVE  8
0029 
0030 #define LED_Y_ON    0x11    /* Used for ring up/down indication */
0031 #define LED_Y_OFF   0x10
0032 
0033 
0034 #define MS2BCLK(x)  ((x)*12500L)
0035 
0036 /*
0037  * valid configuration values are:
0038  */
0039 
0040 /*
0041  *  xPOS_ID:xxxx
0042  *  |   \  /
0043  *  |    \/
0044  *  |     --------------------- the patched POS_ID of the Adapter
0045  *  |               xxxx = (Vendor ID low byte,
0046  *  |                   Vendor ID high byte,
0047  *  |                   Device ID low byte,
0048  *  |                   Device ID high byte)
0049  *  +------------------------------ the patched oem_id must be
0050  *                  'S' for SK or 'I' for IBM
0051  *                  this is a short id for the driver.
0052  */
0053 #ifndef MULT_OEM
0054 #ifndef OEM_CONCEPT
0055 const u_char oem_id[] = "xPOS_ID:xxxx" ;
0056 #else   /* OEM_CONCEPT */
0057 const u_char oem_id[] = OEM_ID ;
0058 #endif  /* OEM_CONCEPT */
0059 #define ID_BYTE0    8
0060 #define OEMID(smc,i)    oem_id[ID_BYTE0 + i]
0061 #else   /* MULT_OEM */
0062 const struct s_oem_ids oem_ids[] = {
0063 #include "oemids.h"
0064 {0}
0065 };
0066 #define OEMID(smc,i)    smc->hw.oem_id->oi_id[i]
0067 #endif  /* MULT_OEM */
0068 
0069 /* Prototypes of external functions */
0070 #ifdef AIX
0071 extern int AIX_vpdReadByte() ;
0072 #endif
0073 
0074 
0075 /* Prototype of a local function. */
0076 static void smt_stop_watchdog(struct s_smc *smc);
0077 
0078 /*
0079  * FDDI card reset
0080  */
0081 static void card_start(struct s_smc *smc)
0082 {
0083     int i ;
0084 #ifdef  PCI
0085     u_char  rev_id ;
0086     u_short word;
0087 #endif
0088 
0089     smt_stop_watchdog(smc) ;
0090 
0091 #ifdef  PCI
0092     /*
0093      * make sure no transfer activity is pending
0094      */
0095     outpw(FM_A(FM_MDREG1),FM_MINIT) ;
0096     outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
0097     hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
0098     /*
0099      * now reset everything
0100      */
0101     outp(ADDR(B0_CTRL),CTRL_RST_SET) ;  /* reset for all chips */
0102     i = (int) inp(ADDR(B0_CTRL)) ;      /* do dummy read */
0103     SK_UNUSED(i) ;              /* Make LINT happy. */
0104     outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
0105 
0106     /*
0107      * Reset all bits in the PCI STATUS register
0108      */
0109     outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ; /* enable for writes */
0110     word = inpw(PCI_C(PCI_STATUS)) ;
0111     outpw(PCI_C(PCI_STATUS), word | PCI_STATUS_ERROR_BITS);
0112     outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ;    /* disable writes */
0113 
0114     /*
0115      * Release the reset of all the State machines
0116      * Release Master_Reset
0117      * Release HPI_SM_Reset
0118      */
0119     outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
0120 
0121     /*
0122      * determine the adapter type
0123      * Note: Do it here, because some drivers may call card_start() once
0124      *   at very first before any other initialization functions is
0125      *   executed.
0126      */
0127     rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
0128     if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
0129         smc->hw.hw_is_64bit = TRUE ;
0130     } else {
0131         smc->hw.hw_is_64bit = FALSE ;
0132     }
0133 
0134     /*
0135      * Watermark initialization
0136      */
0137     if (!smc->hw.hw_is_64bit) {
0138         outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
0139         outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
0140         outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
0141     }
0142 
0143     outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;  /* clear the reset chips */
0144     outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
0145 
0146     /* init the timer value for the watch dog 2,5 minutes */
0147     outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
0148 
0149     /* initialize the ISR mask */
0150     smc->hw.is_imask = ISR_MASK ;
0151     smc->hw.hw_state = STOPPED ;
0152 #endif
0153     GET_PAGE(0) ;       /* necessary for BOOT */
0154 }
0155 
0156 void card_stop(struct s_smc *smc)
0157 {
0158     smt_stop_watchdog(smc) ;
0159     smc->hw.mac_ring_is_up = 0 ;        /* ring down */
0160 
0161 #ifdef  PCI
0162     /*
0163      * make sure no transfer activity is pending
0164      */
0165     outpw(FM_A(FM_MDREG1),FM_MINIT) ;
0166     outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
0167     hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
0168     /*
0169      * now reset everything
0170      */
0171     outp(ADDR(B0_CTRL),CTRL_RST_SET) ;  /* reset for all chips */
0172     outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;  /* reset for all chips */
0173     outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
0174     smc->hw.hw_state = STOPPED ;
0175 #endif
0176 }
0177 /*--------------------------- ISR handling ----------------------------------*/
0178 
0179 void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
0180 {
0181     int restart_tx = 0 ;
0182 again:
0183 
0184     /*
0185      * parity error: note encoding error is not possible in tag mode
0186      */
0187     if (stl & (FM_SPCEPDS  |    /* parity err. syn.q.*/
0188            FM_SPCEPDA0 |    /* parity err. a.q.0 */
0189            FM_SPCEPDA1)) {  /* parity err. a.q.1 */
0190         SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
0191     }
0192     /*
0193      * buffer underrun: can only occur if a tx threshold is specified
0194      */
0195     if (stl & (FM_STBURS  |     /* tx buffer underrun syn.q.*/
0196            FM_STBURA0 |     /* tx buffer underrun a.q.0 */
0197            FM_STBURA1)) {   /* tx buffer underrun a.q.2 */
0198         SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
0199     }
0200 
0201     if ( (stu & (FM_SXMTABT |       /* transmit abort */
0202              FM_STXABRS |       /* syn. tx abort */
0203              FM_STXABRA0)) ||       /* asyn. tx abort */
0204          (stl & (FM_SQLCKS |        /* lock for syn. q. */
0205              FM_SQLCKA0)) ) {       /* lock for asyn. q. */
0206         formac_tx_restart(smc) ;    /* init tx */
0207         restart_tx = 1 ;
0208         stu = inpw(FM_A(FM_ST1U)) ;
0209         stl = inpw(FM_A(FM_ST1L)) ;
0210         stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
0211         if (stu || stl)
0212             goto again ;
0213     }
0214 
0215     if (stu & (FM_STEFRMA0 |    /* end of asyn tx */
0216             FM_STEFRMS)) {  /* end of sync tx */
0217         restart_tx = 1 ;
0218     }
0219 
0220     if (restart_tx)
0221         llc_restart_tx(smc) ;
0222 }
0223 
0224 /*
0225  * interrupt source= plc1
0226  * this function is called in nwfbisr.asm
0227  */
0228 void plc1_irq(struct s_smc *smc)
0229 {
0230     u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
0231 
0232     plc_irq(smc,PB,st) ;
0233 }
0234 
0235 /*
0236  * interrupt source= plc2
0237  * this function is called in nwfbisr.asm
0238  */
0239 void plc2_irq(struct s_smc *smc)
0240 {
0241     u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
0242 
0243     plc_irq(smc,PA,st) ;
0244 }
0245 
0246 
0247 /*
0248  * interrupt source= timer
0249  */
0250 void timer_irq(struct s_smc *smc)
0251 {
0252     hwt_restart(smc);
0253     smc->hw.t_stop = smc->hw.t_start;
0254     smt_timer_done(smc) ;
0255 }
0256 
0257 /*
0258  * return S-port (PA or PB)
0259  */
0260 int pcm_get_s_port(struct s_smc *smc)
0261 {
0262     SK_UNUSED(smc) ;
0263     return PS;
0264 }
0265 
0266 /*
0267  * Station Label = "FDDI-XYZ" where
0268  *
0269  *  X = connector type
0270  *  Y = PMD type
0271  *  Z = port type
0272  */
0273 #define STATION_LABEL_CONNECTOR_OFFSET  5
0274 #define STATION_LABEL_PMD_OFFSET    6
0275 #define STATION_LABEL_PORT_OFFSET   7
0276 
0277 void read_address(struct s_smc *smc, u_char *mac_addr)
0278 {
0279     char ConnectorType ;
0280     char PmdType ;
0281     int i ;
0282 
0283 #ifdef  PCI
0284     for (i = 0; i < 6; i++) {   /* read mac address from board */
0285         smc->hw.fddi_phys_addr.a[i] =
0286             bitrev8(inp(ADDR(B2_MAC_0+i)));
0287     }
0288 #endif
0289 
0290     ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
0291     PmdType = inp(ADDR(B2_PMD_TYP)) ;
0292 
0293     smc->y[PA].pmd_type[PMD_SK_CONN] =
0294     smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
0295     smc->y[PA].pmd_type[PMD_SK_PMD ] =
0296     smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
0297 
0298     if (mac_addr) {
0299         for (i = 0; i < 6 ;i++) {
0300             smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
0301             smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
0302         }
0303         return ;
0304     }
0305     smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
0306 
0307     for (i = 0; i < 6 ;i++) {
0308         smc->hw.fddi_canon_addr.a[i] =
0309             bitrev8(smc->hw.fddi_phys_addr.a[i]);
0310     }
0311 }
0312 
0313 /*
0314  * FDDI card soft reset
0315  */
0316 void init_board(struct s_smc *smc, u_char *mac_addr)
0317 {
0318     card_start(smc) ;
0319     read_address(smc,mac_addr) ;
0320 
0321     if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
0322         smc->s.sas = SMT_SAS ;  /* Single att. station */
0323     else
0324         smc->s.sas = SMT_DAS ;  /* Dual att. station */
0325 
0326     if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
0327         smc->mib.fddiSMTBypassPresent = 0 ;
0328         /* without opt. bypass */
0329     else
0330         smc->mib.fddiSMTBypassPresent = 1 ;
0331         /* with opt. bypass */
0332 }
0333 
0334 /*
0335  * insert or deinsert optical bypass (called by ECM)
0336  */
0337 void sm_pm_bypass_req(struct s_smc *smc, int mode)
0338 {
0339     DB_ECMN(1, "ECM : sm_pm_bypass_req(%s)",
0340         mode == BP_INSERT ? "BP_INSERT" : "BP_DEINSERT");
0341 
0342     if (smc->s.sas != SMT_DAS)
0343         return ;
0344 
0345 #ifdef  PCI
0346     switch(mode) {
0347     case BP_INSERT :
0348         outp(ADDR(B0_DAS),DAS_BYP_INS) ;    /* insert station */
0349         break ;
0350     case BP_DEINSERT :
0351         outp(ADDR(B0_DAS),DAS_BYP_RMV) ;    /* bypass station */
0352         break ;
0353     }
0354 #endif
0355 }
0356 
0357 /*
0358  * check if bypass connected
0359  */
0360 int sm_pm_bypass_present(struct s_smc *smc)
0361 {
0362     return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
0363 }
0364 
0365 void plc_clear_irq(struct s_smc *smc, int p)
0366 {
0367     SK_UNUSED(p) ;
0368 
0369     SK_UNUSED(smc) ;
0370 }
0371 
0372 
0373 /*
0374  * led_indication called by rmt_indication() and
0375  * pcm_state_change()
0376  *
0377  * Input:
0378  *  smc:    SMT context
0379  *  led_event:
0380  *  0   Only switch green LEDs according to their respective PCM state
0381  *  LED_Y_OFF   just switch yellow LED off
0382  *  LED_Y_ON    just switch yello LED on
0383  */
0384 static void led_indication(struct s_smc *smc, int led_event)
0385 {
0386     /* use smc->hw.mac_ring_is_up == TRUE 
0387      * as indication for Ring Operational
0388      */
0389     u_short         led_state ;
0390     struct s_phy        *phy ;
0391     struct fddi_mib_p   *mib_a ;
0392     struct fddi_mib_p   *mib_b ;
0393 
0394     phy = &smc->y[PA] ;
0395     mib_a = phy->mib ;
0396     phy = &smc->y[PB] ;
0397     mib_b = phy->mib ;
0398 
0399 #ifdef  PCI
0400         led_state = 0 ;
0401     
0402     /* Ring up = yellow led OFF*/
0403     if (led_event == LED_Y_ON) {
0404         led_state |= LED_MY_ON ;
0405     }
0406     else if (led_event == LED_Y_OFF) {
0407         led_state |= LED_MY_OFF ;
0408     }
0409     else {  /* PCM state changed */
0410         /* Link at Port A/S = green led A ON */
0411         if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {    
0412             led_state |= LED_GA_ON ;
0413         }
0414         else {
0415             led_state |= LED_GA_OFF ;
0416         }
0417         
0418         /* Link at Port B = green led B ON */
0419         if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
0420             led_state |= LED_GB_ON ;
0421         }
0422         else {
0423             led_state |= LED_GB_OFF ;
0424         }
0425     }
0426 
0427         outp(ADDR(B0_LED), led_state) ;
0428 #endif  /* PCI */
0429 
0430 }
0431 
0432 
0433 void pcm_state_change(struct s_smc *smc, int plc, int p_state)
0434 {
0435     /*
0436      * the current implementation of pcm_state_change() in the driver
0437      * parts must be renamed to drv_pcm_state_change() which will be called
0438      * now after led_indication.
0439      */
0440     DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
0441     
0442     led_indication(smc,0) ;
0443 }
0444 
0445 
0446 void rmt_indication(struct s_smc *smc, int i)
0447 {
0448     /* Call a driver special function if defined */
0449     DRV_RMT_INDICATION(smc,i) ;
0450 
0451         led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
0452 }
0453 
0454 
0455 /*
0456  * llc_recover_tx called by init_tx (fplus.c)
0457  */
0458 void llc_recover_tx(struct s_smc *smc)
0459 {
0460 #ifdef  LOAD_GEN
0461     extern  int load_gen_flag ;
0462 
0463     load_gen_flag = 0 ;
0464 #endif
0465 #ifndef SYNC
0466     smc->hw.n_a_send= 0 ;
0467 #else
0468     SK_UNUSED(smc) ;
0469 #endif
0470 }
0471 
0472 #ifdef MULT_OEM
0473 static int is_equal_num(char comp1[], char comp2[], int num)
0474 {
0475     int i ;
0476 
0477     for (i = 0 ; i < num ; i++) {
0478         if (comp1[i] != comp2[i])
0479             return 0;
0480     }
0481         return 1;
0482 }   /* is_equal_num */
0483 
0484 
0485 /*
0486  * set the OEM ID defaults, and test the contents of the OEM data base
0487  * The default OEM is the first ACTIVE entry in the OEM data base 
0488  *
0489  * returns: 0   success
0490  *      1   error in data base
0491  *      2   data base empty
0492  *      3   no active entry 
0493  */
0494 int set_oi_id_def(struct s_smc *smc)
0495 {
0496     int sel_id ;
0497     int i ;
0498     int act_entries ;
0499 
0500     i = 0 ;
0501     sel_id = -1 ;
0502     act_entries = FALSE ;
0503     smc->hw.oem_id = 0 ;
0504     smc->hw.oem_min_status = OI_STAT_ACTIVE ;
0505     
0506     /* check OEM data base */
0507     while (oem_ids[i].oi_status) {
0508         switch (oem_ids[i].oi_status) {
0509         case OI_STAT_ACTIVE:
0510             act_entries = TRUE ;    /* we have active IDs */
0511             if (sel_id == -1)
0512                 sel_id = i ;    /* save the first active ID */
0513         case OI_STAT_VALID:
0514         case OI_STAT_PRESENT:
0515             i++ ;
0516             break ;         /* entry ok */
0517         default:
0518             return 1;       /* invalid oi_status */
0519         }
0520     }
0521 
0522     if (i == 0)
0523         return 2;
0524     if (!act_entries)
0525         return 3;
0526 
0527     /* ok, we have a valid OEM data base with an active entry */
0528     smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[sel_id] ;
0529     return 0;
0530 }
0531 #endif  /* MULT_OEM */
0532 
0533 void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
0534 {
0535     int i ;
0536 
0537     for (i = 0 ; i < 6 ; i++)
0538         bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
0539 }
0540 
0541 void smt_start_watchdog(struct s_smc *smc)
0542 {
0543     SK_UNUSED(smc) ;    /* Make LINT happy. */
0544 
0545 #ifndef DEBUG
0546 
0547 #ifdef  PCI
0548     if (smc->hw.wdog_used) {
0549         outpw(ADDR(B2_WDOG_CRTL),TIM_START) ;   /* Start timer. */
0550     }
0551 #endif
0552 
0553 #endif  /* DEBUG */
0554 }
0555 
0556 static void smt_stop_watchdog(struct s_smc *smc)
0557 {
0558     SK_UNUSED(smc) ;    /* Make LINT happy. */
0559 #ifndef DEBUG
0560 
0561 #ifdef  PCI
0562     if (smc->hw.wdog_used) {
0563         outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ;    /* Stop timer. */
0564     }
0565 #endif
0566 
0567 #endif  /* DEBUG */
0568 }
0569 
0570 #ifdef  PCI
0571 
0572 void mac_do_pci_fix(struct s_smc *smc)
0573 {
0574     SK_UNUSED(smc) ;
0575 }
0576 #endif  /* PCI */
0577