linux/drivers/net/fddi/skfp/fplustm.c
<<
>>
Prefs
   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 * FORMAC+ Driver for tag mode
  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 <linux/bitrev.h>
  22#include <linux/etherdevice.h>
  23
  24#ifndef UNUSED
  25#ifdef  lint
  26#define UNUSED(x)       (x) = (x)
  27#else
  28#define UNUSED(x)
  29#endif
  30#endif
  31
  32#define FM_ADDRX         (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
  33#define MS2BCLK(x)      ((x)*12500L)
  34#define US2BCLK(x)      ((x)*1250L)
  35
  36/*
  37 * prototypes for static function
  38 */
  39static void build_claim_beacon(struct s_smc *smc, u_long t_request);
  40static int init_mac(struct s_smc *smc, int all);
  41static void rtm_init(struct s_smc *smc);
  42static void smt_split_up_fifo(struct s_smc *smc);
  43
  44#if (!defined(NO_SMT_PANIC) || defined(DEBUG))
  45static  char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
  46static  char cam_warning [] = "E_SMT_004: CAM still busy\n";
  47#endif
  48
  49#define DUMMY_READ()    smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
  50
  51#define CHECK_NPP() {   unsigned int k = 10000 ;\
  52                        while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
  53                        if (!k) { \
  54                                SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
  55                        }       \
  56                }
  57
  58#define CHECK_CAM() {   unsigned int k = 10 ;\
  59                        while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
  60                        if (!k) { \
  61                                SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
  62                        }       \
  63                }
  64
  65const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
  66static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};
  67static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};
  68
  69static const u_short my_said = 0xffff ; /* short address (n.u.) */
  70static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */
  71
  72/*
  73 * define my address
  74 */
  75#ifdef  USE_CAN_ADDR
  76#define MA      smc->hw.fddi_canon_addr
  77#else
  78#define MA      smc->hw.fddi_home_addr
  79#endif
  80
  81
  82/*
  83 * useful interrupt bits
  84 */
  85static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
  86static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
  87                        FM_STBURS | FM_STBURA0 ;
  88
  89        /* delete FM_SRBFL after tests */
  90static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
  91                        FM_SMYCLM ;
  92static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
  93                        FM_SERRCTR | FM_SLSTCTR |
  94                        FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
  95
  96static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
  97static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
  98
  99static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
 100                        FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
 101
 102
 103static u_long mac_get_tneg(struct s_smc *smc)
 104{
 105        u_long  tneg ;
 106
 107        tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
 108        return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
 109                0xffe00000L) ;
 110}
 111
 112void mac_update_counter(struct s_smc *smc)
 113{
 114        smc->mib.m[MAC0].fddiMACFrame_Ct =
 115                (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
 116                + (u_short) inpw(FM_A(FM_FCNTR)) ;
 117        smc->mib.m[MAC0].fddiMACLost_Ct =
 118                (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
 119                + (u_short) inpw(FM_A(FM_LCNTR)) ;
 120        smc->mib.m[MAC0].fddiMACError_Ct =
 121                (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
 122                + (u_short) inpw(FM_A(FM_ECNTR)) ;
 123        smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
 124#ifdef SMT_REAL_TOKEN_CT
 125        /*
 126         * If the token counter is emulated it is updated in smt_event.
 127         */
 128        TBD
 129#else
 130        smt_emulate_token_ct( smc, MAC0 );
 131#endif
 132}
 133
 134/*
 135 * write long value into buffer memory over memory data register (MDR),
 136 */
 137static void write_mdr(struct s_smc *smc, u_long val)
 138{
 139        CHECK_NPP() ;
 140        MDRW(val) ;
 141}
 142
 143#if 0
 144/*
 145 * read long value from buffer memory over memory data register (MDR),
 146 */
 147static u_long read_mdr(struct s_smc *smc, unsigned int addr)
 148{
 149        long p ;
 150        CHECK_NPP() ;
 151        MARR(addr) ;
 152        outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
 153        CHECK_NPP() ;   /* needed for PCI to prevent from timeing violations */
 154/*      p = MDRR() ; */ /* bad read values if the workaround */
 155                        /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
 156                        /* is used */
 157        p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
 158        p += (u_long)inpw(FM_A(FM_MDRL)) ;
 159        return p;
 160}
 161#endif
 162
 163/*
 164 * clear buffer memory
 165 */
 166static void init_ram(struct s_smc *smc)
 167{
 168        u_short i ;
 169
 170        smc->hw.fp.fifo.rbc_ram_start = 0 ;
 171        smc->hw.fp.fifo.rbc_ram_end =
 172                smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
 173        CHECK_NPP() ;
 174        MARW(smc->hw.fp.fifo.rbc_ram_start) ;
 175        for (i = smc->hw.fp.fifo.rbc_ram_start;
 176                i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
 177                write_mdr(smc,0L) ;
 178        /* Erase the last byte too */
 179        write_mdr(smc,0L) ;
 180}
 181
 182/*
 183 * set receive FIFO pointer
 184 */
 185static void set_recvptr(struct s_smc *smc)
 186{
 187        /*
 188         * initialize the pointer for receive queue 1
 189         */
 190        outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* RPR1 */
 191        outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;  /* SWPR1 */
 192        outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* WPR1 */
 193        outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;    /* EARV1 */
 194
 195        /*
 196         * initialize the pointer for receive queue 2
 197         */
 198        if (smc->hw.fp.fifo.rx2_fifo_size) {
 199                outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
 200                outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
 201                outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
 202                outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
 203        }
 204        else {
 205                outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
 206                outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
 207                outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
 208                outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
 209        }
 210}
 211
 212/*
 213 * set transmit FIFO pointer
 214 */
 215static void set_txptr(struct s_smc *smc)
 216{
 217        outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;      /* reset transmit queues */
 218
 219        /*
 220         * initialize the pointer for asynchronous transmit queue
 221         */
 222        outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* RPXA0 */
 223        outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;    /* SWPXA0 */
 224        outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* WPXA0 */
 225        outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
 226
 227        /*
 228         * initialize the pointer for synchronous transmit queue
 229         */
 230        if (smc->hw.fp.fifo.tx_s_size) {
 231                outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
 232                outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
 233                outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
 234                outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
 235        }
 236        else {
 237                outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
 238                outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
 239                outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
 240                outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
 241        }
 242}
 243
 244/*
 245 * init memory buffer management registers
 246 */
 247static void init_rbc(struct s_smc *smc)
 248{
 249        u_short rbc_ram_addr ;
 250
 251        /*
 252         * set unused pointers or permanent pointers
 253         */
 254        rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
 255
 256        outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;    /* a1-send pointer */
 257        outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
 258        outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
 259        outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
 260
 261        set_recvptr(smc) ;
 262        set_txptr(smc) ;
 263}
 264
 265/*
 266 * init rx pointer
 267 */
 268static void init_rx(struct s_smc *smc)
 269{
 270        struct s_smt_rx_queue   *queue ;
 271
 272        /*
 273         * init all tx data structures for receive queue 1
 274         */
 275        smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
 276        queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
 277        queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
 278
 279        /*
 280         * init all tx data structures for receive queue 2
 281         */
 282        smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
 283        queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
 284        queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
 285}
 286
 287/*
 288 * set the TSYNC register of the FORMAC to regulate synchronous transmission
 289 */
 290void set_formac_tsync(struct s_smc *smc, long sync_bw)
 291{
 292        outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
 293}
 294
 295/*
 296 * init all tx data structures
 297 */
 298static void init_tx(struct s_smc *smc)
 299{
 300        struct s_smt_tx_queue   *queue ;
 301
 302        /*
 303         * init all tx data structures for the synchronous queue
 304         */
 305        smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
 306        queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
 307        queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
 308
 309#ifdef ESS
 310        set_formac_tsync(smc,smc->ess.sync_bw) ;
 311#endif
 312
 313        /*
 314         * init all tx data structures for the asynchronous queue 0
 315         */
 316        smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
 317        queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
 318        queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
 319
 320
 321        llc_recover_tx(smc) ;
 322}
 323
 324static void mac_counter_init(struct s_smc *smc)
 325{
 326        int i ;
 327        u_long *ec ;
 328
 329        /*
 330         * clear FORMAC+ frame-, lost- and error counter
 331         */
 332        outpw(FM_A(FM_FCNTR),0) ;
 333        outpw(FM_A(FM_LCNTR),0) ;
 334        outpw(FM_A(FM_ECNTR),0) ;
 335        /*
 336         * clear internal error counter structure
 337         */
 338        ec = (u_long *)&smc->hw.fp.err_stats ;
 339        for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
 340                *ec++ = 0L ;
 341        smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
 342}
 343
 344/*
 345 * set FORMAC address, and t_request
 346 */
 347static  void set_formac_addr(struct s_smc *smc)
 348{
 349        long    t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
 350
 351        outpw(FM_A(FM_SAID),my_said) ;  /* set short address */
 352        outpw(FM_A(FM_LAIL),(unsigned short)((smc->hw.fddi_home_addr.a[4]<<8) +
 353                                        smc->hw.fddi_home_addr.a[5])) ;
 354        outpw(FM_A(FM_LAIC),(unsigned short)((smc->hw.fddi_home_addr.a[2]<<8) +
 355                                        smc->hw.fddi_home_addr.a[3])) ;
 356        outpw(FM_A(FM_LAIM),(unsigned short)((smc->hw.fddi_home_addr.a[0]<<8) +
 357                                        smc->hw.fddi_home_addr.a[1])) ;
 358
 359        outpw(FM_A(FM_SAGP),my_sagp) ;  /* set short group address */
 360
 361        outpw(FM_A(FM_LAGL),(unsigned short)((smc->hw.fp.group_addr.a[4]<<8) +
 362                                        smc->hw.fp.group_addr.a[5])) ;
 363        outpw(FM_A(FM_LAGC),(unsigned short)((smc->hw.fp.group_addr.a[2]<<8) +
 364                                        smc->hw.fp.group_addr.a[3])) ;
 365        outpw(FM_A(FM_LAGM),(unsigned short)((smc->hw.fp.group_addr.a[0]<<8) +
 366                                        smc->hw.fp.group_addr.a[1])) ;
 367
 368        /* set r_request regs. (MSW & LSW of TRT ) */
 369        outpw(FM_A(FM_TREQ1),(unsigned short)(t_requ>>16)) ;
 370        outpw(FM_A(FM_TREQ0),(unsigned short)t_requ) ;
 371}
 372
 373static void set_int(char *p, int l)
 374{
 375        p[0] = (char)(l >> 24) ;
 376        p[1] = (char)(l >> 16) ;
 377        p[2] = (char)(l >> 8) ;
 378        p[3] = (char)(l >> 0) ;
 379}
 380
 381/*
 382 * copy TX descriptor to buffer mem
 383 * append FC field and MAC frame
 384 * if more bit is set in descr
 385 *      append pointer to descriptor (endless loop)
 386 * else
 387 *      append 'end of chain' pointer
 388 */
 389static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
 390                        unsigned int off, int len)
 391/* u_long td;            transmit descriptor */
 392/* struct fddi_mac *mac; mac frame pointer */
 393/* unsigned int off;     start address within buffer memory */
 394/* int len ;             length of the frame including the FC */
 395{
 396        int     i ;
 397        __le32  *p ;
 398
 399        CHECK_NPP() ;
 400        MARW(off) ;             /* set memory address reg for writes */
 401
 402        p = (__le32 *) mac ;
 403        for (i = (len + 3)/4 ; i ; i--) {
 404                if (i == 1) {
 405                        /* last word, set the tag bit */
 406                        outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
 407                }
 408                write_mdr(smc,le32_to_cpu(*p)) ;
 409                p++ ;
 410        }
 411
 412        outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
 413        write_mdr(smc,td) ;     /* write over memory data reg to buffer */
 414}
 415
 416/*
 417        BEGIN_MANUAL_ENTRY(module;tests;3)
 418        How to test directed beacon frames
 419        ----------------------------------------------------------------
 420
 421        o Insert a break point in the function build_claim_beacon()
 422          before calling copy_tx_mac() for building the claim frame.
 423        o Modify the RM3_DETECT case so that the RM6_DETECT state
 424          will always entered from the RM3_DETECT state (function rmt_fsm(),
 425          rmt.c)
 426        o Compile the driver.
 427        o Set the parameter TREQ in the protocol.ini or net.cfg to a
 428          small value to make sure your station will win the claim
 429          process.
 430        o Start the driver.
 431        o When you reach the break point, modify the SA and DA address
 432          of the claim frame (e.g. SA = DA = 10005affffff).
 433        o When you see RM3_DETECT and RM6_DETECT, observe the direct
 434          beacon frames on the UPPSLANA.
 435
 436        END_MANUAL_ENTRY
 437 */
 438static void directed_beacon(struct s_smc *smc)
 439{
 440        SK_LOC_DECL(__le32,a[2]) ;
 441
 442        /*
 443         * set UNA in frame
 444         * enable FORMAC to send endless queue of directed beacon
 445         * important: the UNA starts at byte 1 (not at byte 0)
 446         */
 447        * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
 448        a[1] = 0 ;
 449        memcpy((char *)a+1, (char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr, ETH_ALEN);
 450
 451        CHECK_NPP() ;
 452         /* set memory address reg for writes */
 453        MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
 454        write_mdr(smc,le32_to_cpu(a[0])) ;
 455        outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
 456        write_mdr(smc,le32_to_cpu(a[1])) ;
 457
 458        outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
 459}
 460
 461/*
 462        setup claim & beacon pointer
 463        NOTE :
 464                special frame packets end with a pointer to their own
 465                descriptor, and the MORE bit is set in the descriptor
 466*/
 467static void build_claim_beacon(struct s_smc *smc, u_long t_request)
 468{
 469        u_int   td ;
 470        int     len ;
 471        struct fddi_mac_sf *mac ;
 472
 473        /*
 474         * build claim packet
 475         */
 476        len = 17 ;
 477        td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
 478        mac = &smc->hw.fp.mac_sfb ;
 479        mac->mac_fc = FC_CLAIM ;
 480        /* DA == SA in claim frame */
 481        mac->mac_source = mac->mac_dest = MA ;
 482        /* 2's complement */
 483        set_int((char *)mac->mac_info,(int)t_request) ;
 484
 485        copy_tx_mac(smc,td,(struct fddi_mac *)mac,
 486                smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
 487        /* set CLAIM start pointer */
 488        outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
 489
 490        /*
 491         * build beacon packet
 492         */
 493        len = 17 ;
 494        td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
 495        mac->mac_fc = FC_BEACON ;
 496        mac->mac_source = MA ;
 497        mac->mac_dest = null_addr ;             /* DA == 0 in beacon frame */
 498        set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
 499
 500        copy_tx_mac(smc,td,(struct fddi_mac *)mac,
 501                smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
 502        /* set beacon start pointer */
 503        outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
 504
 505        /*
 506         * build directed beacon packet
 507         * contains optional UNA
 508         */
 509        len = 23 ;
 510        td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
 511        mac->mac_fc = FC_BEACON ;
 512        mac->mac_source = MA ;
 513        mac->mac_dest = dbeacon_multi ;         /* multicast */
 514        set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
 515        set_int((char *) mac->mac_info+4,0) ;
 516        set_int((char *) mac->mac_info+8,0) ;
 517
 518        copy_tx_mac(smc,td,(struct fddi_mac *)mac,
 519                smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
 520
 521        /* end of claim/beacon queue */
 522        outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
 523
 524        outpw(FM_A(FM_WPXSF),0) ;
 525        outpw(FM_A(FM_RPXSF),0) ;
 526}
 527
 528static void formac_rcv_restart(struct s_smc *smc)
 529{
 530        /* enable receive function */
 531        SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
 532
 533        outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;      /* clear receive lock */
 534}
 535
 536void formac_tx_restart(struct s_smc *smc)
 537{
 538        outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
 539        outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
 540}
 541
 542static void enable_formac(struct s_smc *smc)
 543{
 544        /* set formac IMSK : 0 enables irq */
 545        outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
 546        outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
 547        outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
 548        outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
 549        outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
 550        outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
 551}
 552
 553#if 0   /* Removed because the driver should use the ASICs TX complete IRQ. */
 554        /* The FORMACs tx complete IRQ should be used any longer */
 555
 556/*
 557        BEGIN_MANUAL_ENTRY(if,func;others;4)
 558
 559        void enable_tx_irq(smc, queue)
 560        struct s_smc *smc ;
 561        u_short queue ;
 562
 563Function        DOWNCALL        (SMT, fplustm.c)
 564                enable_tx_irq() enables the FORMACs transmit complete
 565                interrupt of the queue.
 566
 567Para    queue   = QUEUE_S:      synchronous queue
 568                = QUEUE_A0:     asynchronous queue
 569
 570Note    After any ring operational change the transmit complete
 571        interrupts are disabled.
 572        The operating system dependent module must enable
 573        the transmit complete interrupt of a queue,
 574                - when it queues the first frame,
 575                  because of no transmit resources are beeing
 576                  available and
 577                - when it escapes from the function llc_restart_tx
 578                  while some frames are still queued.
 579
 580        END_MANUAL_ENTRY
 581 */
 582void enable_tx_irq(struct s_smc *smc, u_short queue)
 583/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
 584{
 585        u_short imask ;
 586
 587        imask = ~(inpw(FM_A(FM_IMSK1U))) ;
 588
 589        if (queue == 0) {
 590                outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
 591        }
 592        if (queue == 1) {
 593                outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
 594        }
 595}
 596
 597/*
 598        BEGIN_MANUAL_ENTRY(if,func;others;4)
 599
 600        void disable_tx_irq(smc, queue)
 601        struct s_smc *smc ;
 602        u_short queue ;
 603
 604Function        DOWNCALL        (SMT, fplustm.c)
 605                disable_tx_irq disables the FORMACs transmit complete
 606                interrupt of the queue
 607
 608Para    queue   = QUEUE_S:      synchronous queue
 609                = QUEUE_A0:     asynchronous queue
 610
 611Note    The operating system dependent module should disable
 612        the transmit complete interrupts if it escapes from the
 613        function llc_restart_tx and no frames are queued.
 614
 615        END_MANUAL_ENTRY
 616 */
 617void disable_tx_irq(struct s_smc *smc, u_short queue)
 618/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
 619{
 620        u_short imask ;
 621
 622        imask = ~(inpw(FM_A(FM_IMSK1U))) ;
 623
 624        if (queue == 0) {
 625                outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
 626        }
 627        if (queue == 1) {
 628                outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
 629        }
 630}
 631#endif
 632
 633static void disable_formac(struct s_smc *smc)
 634{
 635        /* clear formac IMSK : 1 disables irq */
 636        outpw(FM_A(FM_IMSK1U),MW) ;
 637        outpw(FM_A(FM_IMSK1L),MW) ;
 638        outpw(FM_A(FM_IMSK2U),MW) ;
 639        outpw(FM_A(FM_IMSK2L),MW) ;
 640        outpw(FM_A(FM_IMSK3U),MW) ;
 641        outpw(FM_A(FM_IMSK3L),MW) ;
 642}
 643
 644
 645static void mac_ring_up(struct s_smc *smc, int up)
 646{
 647        if (up) {
 648                formac_rcv_restart(smc) ;       /* enable receive function */
 649                smc->hw.mac_ring_is_up = TRUE ;
 650                llc_restart_tx(smc) ;           /* TX queue */
 651        }
 652        else {
 653                /* disable receive function */
 654                SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
 655
 656                /* abort current transmit activity */
 657                outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
 658
 659                smc->hw.mac_ring_is_up = FALSE ;
 660        }
 661}
 662
 663/*--------------------------- ISR handling ----------------------------------*/
 664/*
 665 * mac1_irq is in drvfbi.c
 666 */
 667
 668/*
 669 * mac2_irq:    status bits for the receive queue 1, and ring status
 670 *              ring status indication bits
 671 */
 672void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
 673{
 674        u_short change_s2l ;
 675        u_short change_s2u ;
 676
 677        /* (jd) 22-Feb-1999
 678         * Restart 2_DMax Timer after end of claiming or beaconing
 679         */
 680        if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
 681                queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
 682        }
 683        else if (code_s2l & (FM_STKISS)) {
 684                queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
 685        }
 686
 687        /*
 688         * XOR current st bits with the last to avoid useless RMT event queuing
 689         */
 690        change_s2l = smc->hw.fp.s2l ^ code_s2l ;
 691        change_s2u = smc->hw.fp.s2u ^ code_s2u ;
 692
 693        if ((change_s2l & FM_SRNGOP) ||
 694                (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
 695                if (code_s2l & FM_SRNGOP) {
 696                        mac_ring_up(smc,1) ;
 697                        queue_event(smc,EVENT_RMT,RM_RING_OP) ;
 698                        smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
 699                }
 700                else {
 701                        mac_ring_up(smc,0) ;
 702                        queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
 703                }
 704                goto mac2_end ;
 705        }
 706        if (code_s2l & FM_SMISFRM) {    /* missed frame */
 707                smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
 708        }
 709        if (code_s2u & (FM_SRCVOVR |    /* recv. FIFO overflow */
 710                        FM_SRBFL)) {    /* recv. buffer full */
 711                smc->hw.mac_ct.mac_r_restart_counter++ ;
 712/*              formac_rcv_restart(smc) ;       */
 713                smt_stat_counter(smc,1) ;
 714/*              goto mac2_end ;                 */
 715        }
 716        if (code_s2u & FM_SOTRBEC)
 717                queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
 718        if (code_s2u & FM_SMYBEC)
 719                queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
 720        if (change_s2u & code_s2u & FM_SLOCLM) {
 721                DB_RMTN(2, "RMT : lower claim received");
 722        }
 723        if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
 724                /*
 725                 * This is my claim and that claim is not detected as a
 726                 * duplicate one.
 727                 */
 728                queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
 729        }
 730        if (code_s2l & FM_SDUPCLM) {
 731                /*
 732                 * If a duplicate claim frame (same SA but T_Bid != T_Req)
 733                 * this flag will be set.
 734                 * In the RMT state machine we need a RM_VALID_CLAIM event
 735                 * to do the appropriate state change.
 736                 * RM(34c)
 737                 */
 738                queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
 739        }
 740        if (change_s2u & code_s2u & FM_SHICLM) {
 741                DB_RMTN(2, "RMT : higher claim received");
 742        }
 743        if ( (code_s2l & FM_STRTEXP) ||
 744             (code_s2l & FM_STRTEXR) )
 745                queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
 746        if (code_s2l & FM_SMULTDA) {
 747                /*
 748                 * The MAC has found a 2. MAC with the same address.
 749                 * Signal dup_addr_test = failed to RMT state machine.
 750                 * RM(25)
 751                 */
 752                smc->r.dup_addr_test = DA_FAILED ;
 753                queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
 754        }
 755        if (code_s2u & FM_SBEC)
 756                smc->hw.fp.err_stats.err_bec_stat++ ;
 757        if (code_s2u & FM_SCLM)
 758                smc->hw.fp.err_stats.err_clm_stat++ ;
 759        if (code_s2l & FM_STVXEXP)
 760                smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
 761        if ((code_s2u & (FM_SBEC|FM_SCLM))) {
 762                if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
 763                        mac_ring_up(smc,0) ;
 764                        queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
 765
 766                        mac_ring_up(smc,1) ;
 767                        queue_event(smc,EVENT_RMT,RM_RING_OP) ;
 768                        smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
 769                }
 770        }
 771        if (code_s2l & FM_SPHINV)
 772                smc->hw.fp.err_stats.err_phinv++ ;
 773        if (code_s2l & FM_SSIFG)
 774                smc->hw.fp.err_stats.err_sifg_det++ ;
 775        if (code_s2l & FM_STKISS)
 776                smc->hw.fp.err_stats.err_tkiss++ ;
 777        if (code_s2l & FM_STKERR)
 778                smc->hw.fp.err_stats.err_tkerr++ ;
 779        if (code_s2l & FM_SFRMCTR)
 780                smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
 781        if (code_s2l & FM_SERRCTR)
 782                smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
 783        if (code_s2l & FM_SLSTCTR)
 784                smc->mib.m[MAC0].fddiMACLost_Ct  += 0x10000L ;
 785        if (code_s2u & FM_SERRSF) {
 786                SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
 787        }
 788mac2_end:
 789        /* notice old status */
 790        smc->hw.fp.s2l = code_s2l ;
 791        smc->hw.fp.s2u = code_s2u ;
 792        outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
 793}
 794
 795/*
 796 * mac3_irq:    receive queue 2 bits and address detection bits
 797 */
 798void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
 799{
 800        UNUSED(code_s3l) ;
 801
 802        if (code_s3u & (FM_SRCVOVR2 |   /* recv. FIFO overflow */
 803                        FM_SRBFL2)) {   /* recv. buffer full */
 804                smc->hw.mac_ct.mac_r_restart_counter++ ;
 805                smt_stat_counter(smc,1);
 806        }
 807
 808
 809        if (code_s3u & FM_SRPERRQ2) {   /* parity error receive queue 2 */
 810                SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
 811        }
 812        if (code_s3u & FM_SRPERRQ1) {   /* parity error receive queue 2 */
 813                SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
 814        }
 815}
 816
 817
 818/*
 819 * take formac offline
 820 */
 821static void formac_offline(struct s_smc *smc)
 822{
 823        outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
 824
 825        /* disable receive function */
 826        SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
 827
 828        /* FORMAC+ 'Initialize Mode' */
 829        SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
 830
 831        disable_formac(smc) ;
 832        smc->hw.mac_ring_is_up = FALSE ;
 833        smc->hw.hw_state = STOPPED ;
 834}
 835
 836/*
 837 * bring formac online
 838 */
 839static void formac_online(struct s_smc *smc)
 840{
 841        enable_formac(smc) ;
 842        SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
 843                smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
 844}
 845
 846/*
 847 * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
 848 */
 849int init_fplus(struct s_smc *smc)
 850{
 851        smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
 852        smc->hw.fp.rx_mode = FM_MDAMA ;
 853        smc->hw.fp.group_addr = fddi_broadcast ;
 854        smc->hw.fp.func_addr = 0 ;
 855        smc->hw.fp.frselreg_init = 0 ;
 856
 857        init_driver_fplus(smc) ;
 858        if (smc->s.sas == SMT_DAS)
 859                smc->hw.fp.mdr3init |= FM_MENDAS ;
 860
 861        smc->hw.mac_ct.mac_nobuf_counter = 0 ;
 862        smc->hw.mac_ct.mac_r_restart_counter = 0 ;
 863
 864        smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
 865        smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
 866        smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
 867        smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
 868        smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
 869        smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
 870
 871        smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
 872        smc->hw.mac_ring_is_up = 0 ;
 873
 874        mac_counter_init(smc) ;
 875
 876        /* convert BCKL units to symbol time */
 877        smc->hw.mac_pa.t_neg = (u_long)0 ;
 878        smc->hw.mac_pa.t_pri = (u_long)0 ;
 879
 880        /* make sure all PCI settings are correct */
 881        mac_do_pci_fix(smc) ;
 882
 883        return init_mac(smc, 1);
 884        /* enable_formac(smc) ; */
 885}
 886
 887static int init_mac(struct s_smc *smc, int all)
 888{
 889        u_short t_max,x ;
 890        u_long  time=0 ;
 891
 892        /*
 893         * clear memory
 894         */
 895        outpw(FM_A(FM_MDREG1),FM_MINIT) ;       /* FORMAC+ init mode */
 896        set_formac_addr(smc) ;
 897        outpw(FM_A(FM_MDREG1),FM_MMEMACT) ;     /* FORMAC+ memory activ mode */
 898        /* Note: Mode register 2 is set here, incase parity is enabled. */
 899        outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
 900
 901        if (all) {
 902                init_ram(smc) ;
 903        }
 904        else {
 905                /*
 906                 * reset the HPI, the Master and the BMUs
 907                 */
 908                outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
 909                time = hwt_quick_read(smc) ;
 910        }
 911
 912        /*
 913         * set all pointers, frames etc
 914         */
 915        smt_split_up_fifo(smc) ;
 916
 917        init_tx(smc) ;
 918        init_rx(smc) ;
 919        init_rbc(smc) ;
 920
 921        build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
 922
 923        /* set RX threshold */
 924        /* see Errata #SN2 Phantom receive overflow */
 925        outpw(FM_A(FM_FRMTHR),14<<12) ;         /* switch on */
 926
 927        /* set formac work mode */
 928        outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
 929        outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
 930        outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
 931        outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
 932
 933        /* set timer */
 934        /*
 935         * errata #22 fplus:
 936         * T_MAX must not be FFFE
 937         * or one of FFDF, FFB8, FF91 (-0x27 etc..)
 938         */
 939        t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
 940        x = t_max/0x27 ;
 941        x *= 0x27 ;
 942        if ((t_max == 0xfffe) || (t_max - x == 0x16))
 943                t_max-- ;
 944        outpw(FM_A(FM_TMAX),(u_short)t_max) ;
 945
 946        /* BugFix for report #10204 */
 947        if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
 948                outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
 949        } else {
 950                outpw(FM_A(FM_TVX),
 951                        (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
 952        }
 953
 954        outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
 955        outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
 956        outpw(FM_A(FM_CMDREG1),FM_ICLLR);       /* clear receive lock */
 957
 958        /* Auto unlock receice threshold for receive queue 1 and 2 */
 959        outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
 960
 961        rtm_init(smc) ;                         /* RT-Monitor */
 962
 963        if (!all) {
 964                /*
 965                 * after 10ms, reset the BMUs and repair the rings
 966                 */
 967                hwt_wait_time(smc,time,MS2BCLK(10)) ;
 968                outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
 969                outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
 970                outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
 971                outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
 972                outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
 973                outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
 974                outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
 975                if (!smc->hw.hw_is_64bit) {
 976                        outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
 977                        outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
 978                        outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
 979                }
 980                smc->hw.hw_state = STOPPED ;
 981                mac_drv_repair_descr(smc) ;
 982        }
 983        smc->hw.hw_state = STARTED ;
 984
 985        return 0;
 986}
 987
 988
 989/*
 990 * called by CFM
 991 */
 992void config_mux(struct s_smc *smc, int mux)
 993{
 994        plc_config_mux(smc,mux) ;
 995
 996        SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
 997}
 998
 999/*
1000 * called by RMT
1001 * enable CLAIM/BEACON interrupts
1002 * (only called if these events are of interest, e.g. in DETECT state
1003 * the interrupt must not be permanently enabled
1004 * RMT calls this function periodically (timer driven polling)
1005 */
1006void sm_mac_check_beacon_claim(struct s_smc *smc)
1007{
1008        /* set formac IMSK : 0 enables irq */
1009        outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
1010        /* the driver must receive the directed beacons */
1011        formac_rcv_restart(smc) ;
1012        process_receive(smc) ;
1013}
1014
1015/*-------------------------- interface functions ----------------------------*/
1016/*
1017 * control MAC layer    (called by RMT)
1018 */
1019void sm_ma_control(struct s_smc *smc, int mode)
1020{
1021        switch(mode) {
1022        case MA_OFFLINE :
1023                /* Add to make the MAC offline in RM0_ISOLATED state */
1024                formac_offline(smc) ;
1025                break ;
1026        case MA_RESET :
1027                (void)init_mac(smc,0) ;
1028                break ;
1029        case MA_BEACON :
1030                formac_online(smc) ;
1031                break ;
1032        case MA_DIRECTED :
1033                directed_beacon(smc) ;
1034                break ;
1035        case MA_TREQ :
1036                /*
1037                 * no actions necessary, TREQ is already set
1038                 */
1039                break ;
1040        }
1041}
1042
1043int sm_mac_get_tx_state(struct s_smc *smc)
1044{
1045        return (inpw(FM_A(FM_STMCHN))>>4) & 7;
1046}
1047
1048/*
1049 * multicast functions
1050 */
1051
1052static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
1053                                       struct fddi_addr *user,
1054                                       struct fddi_addr *own,
1055                                       int del, int can)
1056{
1057        struct s_fpmc   *tb ;
1058        struct s_fpmc   *slot ;
1059        u_char  *p ;
1060        int i ;
1061
1062        /*
1063         * set own = can(user)
1064         */
1065        *own = *user ;
1066        if (can) {
1067                p = own->a ;
1068                for (i = 0 ; i < 6 ; i++, p++)
1069                        *p = bitrev8(*p);
1070        }
1071        slot = NULL;
1072        for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1073                if (!tb->n) {           /* not used */
1074                        if (!del && !slot)      /* if !del save first free */
1075                                slot = tb ;
1076                        continue ;
1077                }
1078                if (!ether_addr_equal((char *)&tb->a, (char *)own))
1079                        continue ;
1080                return tb;
1081        }
1082        return slot;                    /* return first free or NULL */
1083}
1084
1085/*
1086        BEGIN_MANUAL_ENTRY(if,func;others;2)
1087
1088        void mac_clear_multicast(smc)
1089        struct s_smc *smc ;
1090
1091Function        DOWNCALL        (SMT, fplustm.c)
1092                Clear all multicast entries
1093
1094        END_MANUAL_ENTRY()
1095 */
1096void mac_clear_multicast(struct s_smc *smc)
1097{
1098        struct s_fpmc   *tb ;
1099        int i ;
1100
1101        smc->hw.fp.os_slots_used = 0 ;  /* note the SMT addresses */
1102                                        /* will not be deleted */
1103        for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1104                if (!tb->perm) {
1105                        tb->n = 0 ;
1106                }
1107        }
1108}
1109
1110/*
1111        BEGIN_MANUAL_ENTRY(if,func;others;2)
1112
1113        int mac_add_multicast(smc,addr,can)
1114        struct s_smc *smc ;
1115        struct fddi_addr *addr ;
1116        int can ;
1117
1118Function        DOWNCALL        (SMC, fplustm.c)
1119                Add an entry to the multicast table
1120
1121Para    addr    pointer to a multicast address
1122        can     = 0:    the multicast address has the physical format
1123                = 1:    the multicast address has the canonical format
1124                | 0x80  permanent
1125
1126Returns 0: success
1127        1: address table full
1128
1129Note    After a 'driver reset' or a 'station set address' all
1130        entries of the multicast table are cleared.
1131        In this case the driver has to fill the multicast table again.
1132        After the operating system dependent module filled
1133        the multicast table it must call mac_update_multicast
1134        to activate the new multicast addresses!
1135
1136        END_MANUAL_ENTRY()
1137 */
1138int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
1139{
1140        SK_LOC_DECL(struct fddi_addr,own) ;
1141        struct s_fpmc   *tb ;
1142
1143        /*
1144         * check if there are free table entries
1145         */
1146        if (can & 0x80) {
1147                if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
1148                        return 1;
1149                }
1150        }
1151        else {
1152                if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
1153                        return 1;
1154                }
1155        }
1156
1157        /*
1158         * find empty slot
1159         */
1160        if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
1161                return 1;
1162        tb->n++ ;
1163        tb->a = own ;
1164        tb->perm = (can & 0x80) ? 1 : 0 ;
1165
1166        if (can & 0x80)
1167                smc->hw.fp.smt_slots_used++ ;
1168        else
1169                smc->hw.fp.os_slots_used++ ;
1170
1171        return 0;
1172}
1173
1174/*
1175 * mode
1176 */
1177
1178#define RX_MODE_PROM            0x1
1179#define RX_MODE_ALL_MULTI       0x2
1180
1181/*
1182        BEGIN_MANUAL_ENTRY(if,func;others;2)
1183
1184        void mac_update_multicast(smc)
1185        struct s_smc *smc ;
1186
1187Function        DOWNCALL        (SMT, fplustm.c)
1188                Update FORMAC multicast registers
1189
1190        END_MANUAL_ENTRY()
1191 */
1192void mac_update_multicast(struct s_smc *smc)
1193{
1194        struct s_fpmc   *tb ;
1195        u_char  *fu ;
1196        int     i ;
1197
1198        /*
1199         * invalidate the CAM
1200         */
1201        outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
1202
1203        /*
1204         * set the functional address
1205         */
1206        if (smc->hw.fp.func_addr) {
1207                fu = (u_char *) &smc->hw.fp.func_addr ;
1208                outpw(FM_A(FM_AFMASK2),0xffff) ;
1209                outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
1210                outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
1211                outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1212                outpw(FM_A(FM_AFCOMP2), 0xc000) ;
1213                outpw(FM_A(FM_AFCOMP1), 0x0000) ;
1214                outpw(FM_A(FM_AFCOMP0), 0x0000) ;
1215                outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1216        }
1217
1218        /*
1219         * set the mask and the personality register(s)
1220         */
1221        outpw(FM_A(FM_AFMASK0),0xffff) ;
1222        outpw(FM_A(FM_AFMASK1),0xffff) ;
1223        outpw(FM_A(FM_AFMASK2),0xffff) ;
1224        outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1225
1226        for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
1227                if (tb->n) {
1228                        CHECK_CAM() ;
1229
1230                        /*
1231                         * write the multicast address into the CAM
1232                         */
1233                        outpw(FM_A(FM_AFCOMP2),
1234                                (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
1235                        outpw(FM_A(FM_AFCOMP1),
1236                                (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
1237                        outpw(FM_A(FM_AFCOMP0),
1238                                (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
1239                        outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1240                }
1241        }
1242}
1243
1244/*
1245        BEGIN_MANUAL_ENTRY(if,func;others;3)
1246
1247        void mac_set_rx_mode(smc,mode)
1248        struct s_smc *smc ;
1249        int mode ;
1250
1251Function        DOWNCALL/INTERN (SMT, fplustm.c)
1252                This function enables / disables the selected receive.
1253                Don't call this function if the hardware module is
1254                used -- use mac_drv_rx_mode() instead of.
1255
1256Para    mode =  1       RX_ENABLE_ALLMULTI      enable all multicasts
1257                2       RX_DISABLE_ALLMULTI     disable "enable all multicasts"
1258                3       RX_ENABLE_PROMISC       enable promiscuous
1259                4       RX_DISABLE_PROMISC      disable promiscuous
1260                5       RX_ENABLE_NSA           enable reception of NSA frames
1261                6       RX_DISABLE_NSA          disable reception of NSA frames
1262
1263Note    The selected receive modes will be lost after 'driver reset'
1264        or 'set station address'
1265
1266        END_MANUAL_ENTRY
1267 */
1268void mac_set_rx_mode(struct s_smc *smc, int mode)
1269{
1270        switch (mode) {
1271        case RX_ENABLE_ALLMULTI :
1272                smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
1273                break ;
1274        case RX_DISABLE_ALLMULTI :
1275                smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
1276                break ;
1277        case RX_ENABLE_PROMISC :
1278                smc->hw.fp.rx_prom |= RX_MODE_PROM ;
1279                break ;
1280        case RX_DISABLE_PROMISC :
1281                smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
1282                break ;
1283        case RX_ENABLE_NSA :
1284                smc->hw.fp.nsa_mode = FM_MDAMA ;
1285                smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1286                        smc->hw.fp.nsa_mode ;
1287                break ;
1288        case RX_DISABLE_NSA :
1289                smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
1290                smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1291                        smc->hw.fp.nsa_mode ;
1292                break ;
1293        }
1294        if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
1295                smc->hw.fp.rx_mode = FM_MLIMPROM ;
1296        }
1297        else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
1298                smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
1299        }
1300        else
1301                smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
1302        SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
1303        mac_update_multicast(smc) ;
1304}
1305
1306/*
1307        BEGIN_MANUAL_ENTRY(module;tests;3)
1308        How to test the Restricted Token Monitor
1309        ----------------------------------------------------------------
1310
1311        o Insert a break point in the function rtm_irq()
1312        o Remove all stations with a restricted token monitor from the
1313          network.
1314        o Connect a UPPS ISA or EISA station to the network.
1315        o Give the FORMAC of UPPS station the command to send
1316          restricted tokens until the ring becomes instable.
1317        o Now connect your test test client.
1318        o The restricted token monitor should detect the restricted token,
1319          and your break point will be reached.
1320        o You can ovserve how the station will clean the ring.
1321
1322        END_MANUAL_ENTRY
1323 */
1324void rtm_irq(struct s_smc *smc)
1325{
1326        outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;           /* clear IRQ */
1327        if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
1328                outpw(FM_A(FM_CMDREG1),FM_ICL) ;        /* force claim */
1329                DB_RMT("RMT: fddiPATHT_Rmode expired");
1330                AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
1331                                (u_long) FDDI_SMT_EVENT,
1332                                (u_long) FDDI_RTT, smt_get_event_word(smc));
1333        }
1334        outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable RTM monitoring */
1335}
1336
1337static void rtm_init(struct s_smc *smc)
1338{
1339        outpd(ADDR(B2_RTM_INI),0) ;             /* timer = 0 */
1340        outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable IRQ */
1341}
1342
1343void rtm_set_timer(struct s_smc *smc)
1344{
1345        /*
1346         * MIB timer and hardware timer have the same resolution of 80nS
1347         */
1348        DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns",
1349               (int)smc->mib.a[PATH0].fddiPATHT_Rmode);
1350        outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
1351}
1352
1353static void smt_split_up_fifo(struct s_smc *smc)
1354{
1355
1356/*
1357        BEGIN_MANUAL_ENTRY(module;mem;1)
1358        -------------------------------------------------------------
1359        RECEIVE BUFFER MEMORY DIVERSION
1360        -------------------------------------------------------------
1361
1362        R1_RxD == SMT_R1_RXD_COUNT
1363        R2_RxD == SMT_R2_RXD_COUNT
1364
1365        SMT_R1_RXD_COUNT must be unequal zero
1366
1367                   | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
1368                   |   x      0    |  x     1-3   |   x     < 3
1369        ----------------------------------------------------------------------
1370                   |   63,75 kB    |    54,75     |     R1_RxD
1371        rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
1372                   |               |              | R1_RxD+R2_RxD
1373        ----------------------------------------------------------------------
1374                   |               |    9 kB      |     R2_RxD
1375        rx queue 2 |    0 kB       | RX_SMALL_FIFO| ------------- * 63,75 kB
1376                   |  (not used)   |              | R1_RxD+R2_RxD
1377
1378        END_MANUAL_ENTRY
1379*/
1380
1381        if (SMT_R1_RXD_COUNT == 0) {
1382                SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
1383        }
1384
1385        switch(SMT_R2_RXD_COUNT) {
1386        case 0:
1387                smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
1388                smc->hw.fp.fifo.rx2_fifo_size = 0 ;
1389                break ;
1390        case 1:
1391        case 2:
1392        case 3:
1393                smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
1394                smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
1395                break ;
1396        default:        /* this is not the real defaule */
1397                smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
1398                SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1399                smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
1400                SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1401                break ;
1402        }
1403
1404/*
1405        BEGIN_MANUAL_ENTRY(module;mem;1)
1406        -------------------------------------------------------------
1407        TRANSMIT BUFFER MEMORY DIVERSION
1408        -------------------------------------------------------------
1409
1410
1411                 | no sync bw   | sync bw available and | sync bw available and
1412                 | available    | SynchTxMode = SPLIT   | SynchTxMode = ALL
1413        -----------------------------------------------------------------------
1414        sync tx  |     0 kB     |       32 kB           |       55 kB
1415        queue    |              |   TX_MEDIUM_FIFO      |   TX_LARGE_FIFO
1416        -----------------------------------------------------------------------
1417        async tx |    64 kB     |       32 kB           |        9 k
1418        queue    | TX_FIFO_SPACE|   TX_MEDIUM_FIFO      |   TX_SMALL_FIFO
1419
1420        END_MANUAL_ENTRY
1421*/
1422
1423        /*
1424         * set the tx mode bits
1425         */
1426        if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
1427#ifdef ESS
1428                smc->hw.fp.fifo.fifo_config_mode |=
1429                        smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
1430#endif
1431        }
1432        else {
1433                smc->hw.fp.fifo.fifo_config_mode &=
1434                        ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
1435        }
1436
1437        /*
1438         * split up the FIFO
1439         */
1440        if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
1441                if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
1442                        smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
1443                        smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
1444                }
1445                else {
1446                        smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
1447                        smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
1448                }
1449        }
1450        else {
1451                        smc->hw.fp.fifo.tx_s_size = 0 ;
1452                        smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
1453        }
1454
1455        smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
1456                RX_FIFO_OFF ;
1457        smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
1458                smc->hw.fp.fifo.rx1_fifo_size ;
1459        smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
1460                smc->hw.fp.fifo.tx_s_size ;
1461        smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
1462                smc->hw.fp.fifo.tx_a0_size ;
1463
1464        DB_SMT("FIFO split: mode = %x", smc->hw.fp.fifo.fifo_config_mode);
1465        DB_SMT("rbc_ram_start = %x       rbc_ram_end =  %x",
1466               smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end);
1467        DB_SMT("rx1_fifo_start = %x      tx_s_start =   %x",
1468               smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start);
1469        DB_SMT("tx_a0_start =   %x       rx2_fifo_start =       %x",
1470               smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start);
1471}
1472
1473void formac_reinit_tx(struct s_smc *smc)
1474{
1475        /*
1476         * Split up the FIFO and reinitialize the MAC if synchronous
1477         * bandwidth becomes available but no synchronous queue is
1478         * configured.
1479         */
1480        if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
1481                (void)init_mac(smc,0) ;
1482        }
1483}
1484
1485