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