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

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

DEFINITIONS

This source file includes following definitions.
  1. mac_get_tneg
  2. mac_update_counter
  3. write_mdr
  4. read_mdr
  5. init_ram
  6. set_recvptr
  7. set_txptr
  8. init_rbc
  9. init_rx
  10. set_formac_tsync
  11. init_tx
  12. mac_counter_init
  13. set_formac_addr
  14. set_int
  15. copy_tx_mac
  16. directed_beacon
  17. build_claim_beacon
  18. formac_rcv_restart
  19. formac_tx_restart
  20. enable_formac
  21. enable_tx_irq
  22. disable_tx_irq
  23. disable_formac
  24. mac_ring_up
  25. mac2_irq
  26. mac3_irq
  27. formac_offline
  28. formac_online
  29. init_fplus
  30. init_mac
  31. config_mux
  32. sm_mac_check_beacon_claim
  33. sm_ma_control
  34. sm_mac_get_tx_state
  35. mac_get_mc_table
  36. mac_clear_multicast
  37. mac_add_multicast
  38. mac_update_multicast
  39. mac_set_rx_mode
  40. rtm_irq
  41. rtm_init
  42. rtm_set_timer
  43. smt_split_up_fifo
  44. formac_reinit_tx

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

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