Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /******************************************************************************
0003  *
0004  *  (C)Copyright 1998,1999 SysKonnect,
0005  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0006  *
0007  *  See the file "skfddi.c" for further information.
0008  *
0009  *  The information in this file is provided "AS IS" without warranty.
0010  *
0011  ******************************************************************************/
0012 
0013 /*
0014  * FORMAC+ Driver for tag mode
0015  */
0016 
0017 #include "h/types.h"
0018 #include "h/fddi.h"
0019 #include "h/smc.h"
0020 #include "h/supern_2.h"
0021 #include <linux/bitrev.h>
0022 #include <linux/etherdevice.h>
0023 
0024 #ifndef UNUSED
0025 #ifdef  lint
0026 #define UNUSED(x)   (x) = (x)
0027 #else
0028 #define UNUSED(x)
0029 #endif
0030 #endif
0031 
0032 #define FM_ADDRX     (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
0033 #define MS2BCLK(x)  ((x)*12500L)
0034 #define US2BCLK(x)  ((x)*1250L)
0035 
0036 /*
0037  * prototypes for static function
0038  */
0039 static void build_claim_beacon(struct s_smc *smc, u_long t_request);
0040 static int init_mac(struct s_smc *smc, int all);
0041 static void rtm_init(struct s_smc *smc);
0042 static void smt_split_up_fifo(struct s_smc *smc);
0043 
0044 #if (!defined(NO_SMT_PANIC) || defined(DEBUG))
0045 static  char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
0046 static  char cam_warning [] = "E_SMT_004: CAM still busy\n";
0047 #endif
0048 
0049 #define DUMMY_READ()    smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
0050 
0051 #define CHECK_NPP() {   unsigned int k = 10000 ;\
0052             while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
0053             if (!k) { \
0054                 SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
0055             }   \
0056         }
0057 
0058 #define CHECK_CAM() {   unsigned int k = 10 ;\
0059             while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
0060             if (!k) { \
0061                 SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
0062             }   \
0063         }
0064 
0065 const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
0066 static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};
0067 static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};
0068 
0069 static const u_short my_said = 0xffff ; /* short address (n.u.) */
0070 static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */
0071 
0072 /*
0073  * define my address
0074  */
0075 #ifdef  USE_CAN_ADDR
0076 #define MA  smc->hw.fddi_canon_addr
0077 #else
0078 #define MA  smc->hw.fddi_home_addr
0079 #endif
0080 
0081 
0082 /*
0083  * useful interrupt bits
0084  */
0085 static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
0086 static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
0087             FM_STBURS | FM_STBURA0 ;
0088 
0089     /* delete FM_SRBFL after tests */
0090 static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
0091             FM_SMYCLM ;
0092 static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
0093             FM_SERRCTR | FM_SLSTCTR |
0094             FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
0095 
0096 static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
0097 static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
0098 
0099 static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
0100             FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
0101 
0102 
0103 static u_long mac_get_tneg(struct s_smc *smc)
0104 {
0105     u_long  tneg ;
0106 
0107     tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
0108     return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
0109         0xffe00000L) ;
0110 }
0111 
0112 void mac_update_counter(struct s_smc *smc)
0113 {
0114     smc->mib.m[MAC0].fddiMACFrame_Ct =
0115         (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
0116         + (u_short) inpw(FM_A(FM_FCNTR)) ;
0117     smc->mib.m[MAC0].fddiMACLost_Ct =
0118         (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
0119         + (u_short) inpw(FM_A(FM_LCNTR)) ;
0120     smc->mib.m[MAC0].fddiMACError_Ct =
0121         (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
0122         + (u_short) inpw(FM_A(FM_ECNTR)) ;
0123     smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
0124 #ifdef SMT_REAL_TOKEN_CT
0125     /*
0126      * If the token counter is emulated it is updated in smt_event.
0127      */
0128     TBD
0129 #else
0130     smt_emulate_token_ct( smc, MAC0 );
0131 #endif
0132 }
0133 
0134 /*
0135  * write long value into buffer memory over memory data register (MDR),
0136  */
0137 static void write_mdr(struct s_smc *smc, u_long val)
0138 {
0139     CHECK_NPP() ;
0140     MDRW(val) ;
0141 }
0142 
0143 #if 0
0144 /*
0145  * read long value from buffer memory over memory data register (MDR),
0146  */
0147 static u_long read_mdr(struct s_smc *smc, unsigned int addr)
0148 {
0149     long p ;
0150     CHECK_NPP() ;
0151     MARR(addr) ;
0152     outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
0153     CHECK_NPP() ;   /* needed for PCI to prevent from timeing violations */
0154 /*  p = MDRR() ; */ /* bad read values if the workaround */
0155             /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
0156             /* is used */
0157     p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
0158     p += (u_long)inpw(FM_A(FM_MDRL)) ;
0159     return p;
0160 }
0161 #endif
0162 
0163 /*
0164  * clear buffer memory
0165  */
0166 static void init_ram(struct s_smc *smc)
0167 {
0168     u_short i ;
0169 
0170     smc->hw.fp.fifo.rbc_ram_start = 0 ;
0171     smc->hw.fp.fifo.rbc_ram_end =
0172         smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
0173     CHECK_NPP() ;
0174     MARW(smc->hw.fp.fifo.rbc_ram_start) ;
0175     for (i = smc->hw.fp.fifo.rbc_ram_start;
0176         i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
0177         write_mdr(smc,0L) ;
0178     /* Erase the last byte too */
0179     write_mdr(smc,0L) ;
0180 }
0181 
0182 /*
0183  * set receive FIFO pointer
0184  */
0185 static void set_recvptr(struct s_smc *smc)
0186 {
0187     /*
0188      * initialize the pointer for receive queue 1
0189      */
0190     outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* RPR1 */
0191     outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;  /* SWPR1 */
0192     outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* WPR1 */
0193     outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;    /* EARV1 */
0194 
0195     /*
0196      * initialize the pointer for receive queue 2
0197      */
0198     if (smc->hw.fp.fifo.rx2_fifo_size) {
0199         outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
0200         outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
0201         outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
0202         outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
0203     }
0204     else {
0205         outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
0206         outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
0207         outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
0208         outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
0209     }
0210 }
0211 
0212 /*
0213  * set transmit FIFO pointer
0214  */
0215 static void set_txptr(struct s_smc *smc)
0216 {
0217     outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;  /* reset transmit queues */
0218 
0219     /*
0220      * initialize the pointer for asynchronous transmit queue
0221      */
0222     outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* RPXA0 */
0223     outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;    /* SWPXA0 */
0224     outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* WPXA0 */
0225     outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
0226 
0227     /*
0228      * initialize the pointer for synchronous transmit queue
0229      */
0230     if (smc->hw.fp.fifo.tx_s_size) {
0231         outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
0232         outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
0233         outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
0234         outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
0235     }
0236     else {
0237         outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
0238         outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
0239         outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
0240         outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
0241     }
0242 }
0243 
0244 /*
0245  * init memory buffer management registers
0246  */
0247 static void init_rbc(struct s_smc *smc)
0248 {
0249     u_short rbc_ram_addr ;
0250 
0251     /*
0252      * set unused pointers or permanent pointers
0253      */
0254     rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
0255 
0256     outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;    /* a1-send pointer */
0257     outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
0258     outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
0259     outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
0260 
0261     set_recvptr(smc) ;
0262     set_txptr(smc) ;
0263 }
0264 
0265 /*
0266  * init rx pointer
0267  */
0268 static void init_rx(struct s_smc *smc)
0269 {
0270     struct s_smt_rx_queue   *queue ;
0271 
0272     /*
0273      * init all tx data structures for receive queue 1
0274      */
0275     smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
0276     queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
0277     queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
0278 
0279     /*
0280      * init all tx data structures for receive queue 2
0281      */
0282     smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
0283     queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
0284     queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
0285 }
0286 
0287 /*
0288  * set the TSYNC register of the FORMAC to regulate synchronous transmission
0289  */
0290 void set_formac_tsync(struct s_smc *smc, long sync_bw)
0291 {
0292     outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
0293 }
0294 
0295 /*
0296  * init all tx data structures
0297  */
0298 static void init_tx(struct s_smc *smc)
0299 {
0300     struct s_smt_tx_queue   *queue ;
0301 
0302     /*
0303      * init all tx data structures for the synchronous queue
0304      */
0305     smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
0306     queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
0307     queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
0308 
0309 #ifdef ESS
0310     set_formac_tsync(smc,smc->ess.sync_bw) ;
0311 #endif
0312 
0313     /*
0314      * init all tx data structures for the asynchronous queue 0
0315      */
0316     smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
0317     queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
0318     queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
0319 
0320 
0321     llc_recover_tx(smc) ;
0322 }
0323 
0324 static void mac_counter_init(struct s_smc *smc)
0325 {
0326     int i ;
0327     u_long *ec ;
0328 
0329     /*
0330      * clear FORMAC+ frame-, lost- and error counter
0331      */
0332     outpw(FM_A(FM_FCNTR),0) ;
0333     outpw(FM_A(FM_LCNTR),0) ;
0334     outpw(FM_A(FM_ECNTR),0) ;
0335     /*
0336      * clear internal error counter structure
0337      */
0338     ec = (u_long *)&smc->hw.fp.err_stats ;
0339     for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
0340         *ec++ = 0L ;
0341     smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
0342 }
0343 
0344 /*
0345  * set FORMAC address, and t_request
0346  */
0347 static  void set_formac_addr(struct s_smc *smc)
0348 {
0349     long    t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
0350 
0351     outpw(FM_A(FM_SAID),my_said) ;  /* set short address */
0352     outpw(FM_A(FM_LAIL),(unsigned short)((smc->hw.fddi_home_addr.a[4]<<8) +
0353                     smc->hw.fddi_home_addr.a[5])) ;
0354     outpw(FM_A(FM_LAIC),(unsigned short)((smc->hw.fddi_home_addr.a[2]<<8) +
0355                     smc->hw.fddi_home_addr.a[3])) ;
0356     outpw(FM_A(FM_LAIM),(unsigned short)((smc->hw.fddi_home_addr.a[0]<<8) +
0357                     smc->hw.fddi_home_addr.a[1])) ;
0358 
0359     outpw(FM_A(FM_SAGP),my_sagp) ;  /* set short group address */
0360 
0361     outpw(FM_A(FM_LAGL),(unsigned short)((smc->hw.fp.group_addr.a[4]<<8) +
0362                     smc->hw.fp.group_addr.a[5])) ;
0363     outpw(FM_A(FM_LAGC),(unsigned short)((smc->hw.fp.group_addr.a[2]<<8) +
0364                     smc->hw.fp.group_addr.a[3])) ;
0365     outpw(FM_A(FM_LAGM),(unsigned short)((smc->hw.fp.group_addr.a[0]<<8) +
0366                     smc->hw.fp.group_addr.a[1])) ;
0367 
0368     /* set r_request regs. (MSW & LSW of TRT ) */
0369     outpw(FM_A(FM_TREQ1),(unsigned short)(t_requ>>16)) ;
0370     outpw(FM_A(FM_TREQ0),(unsigned short)t_requ) ;
0371 }
0372 
0373 static void set_int(char *p, int l)
0374 {
0375     p[0] = (char)(l >> 24) ;
0376     p[1] = (char)(l >> 16) ;
0377     p[2] = (char)(l >> 8) ;
0378     p[3] = (char)(l >> 0) ;
0379 }
0380 
0381 /*
0382  * copy TX descriptor to buffer mem
0383  * append FC field and MAC frame
0384  * if more bit is set in descr
0385  *  append pointer to descriptor (endless loop)
0386  * else
0387  *  append 'end of chain' pointer
0388  */
0389 static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
0390             unsigned int off, int len)
0391 /* u_long td;        transmit descriptor */
0392 /* struct fddi_mac *mac; mac frame pointer */
0393 /* unsigned int off;     start address within buffer memory */
0394 /* int len ;         length of the frame including the FC */
0395 {
0396     int i ;
0397     __le32  *p ;
0398 
0399     CHECK_NPP() ;
0400     MARW(off) ;     /* set memory address reg for writes */
0401 
0402     p = (__le32 *) mac ;
0403     for (i = (len + 3)/4 ; i ; i--) {
0404         if (i == 1) {
0405             /* last word, set the tag bit */
0406             outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
0407         }
0408         write_mdr(smc,le32_to_cpu(*p)) ;
0409         p++ ;
0410     }
0411 
0412     outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;  /* set the tag bit */
0413     write_mdr(smc,td) ; /* write over memory data reg to buffer */
0414 }
0415 
0416 /*
0417     BEGIN_MANUAL_ENTRY(module;tests;3)
0418     How to test directed beacon frames
0419     ----------------------------------------------------------------
0420 
0421     o Insert a break point in the function build_claim_beacon()
0422       before calling copy_tx_mac() for building the claim frame.
0423     o Modify the RM3_DETECT case so that the RM6_DETECT state
0424       will always entered from the RM3_DETECT state (function rmt_fsm(),
0425       rmt.c)
0426     o Compile the driver.
0427     o Set the parameter TREQ in the protocol.ini or net.cfg to a
0428       small value to make sure your station will win the claim
0429       process.
0430     o Start the driver.
0431     o When you reach the break point, modify the SA and DA address
0432       of the claim frame (e.g. SA = DA = 10005affffff).
0433     o When you see RM3_DETECT and RM6_DETECT, observe the direct
0434       beacon frames on the UPPSLANA.
0435 
0436     END_MANUAL_ENTRY
0437  */
0438 static void directed_beacon(struct s_smc *smc)
0439 {
0440     SK_LOC_DECL(__le32,a[2]) ;
0441 
0442     /*
0443      * set UNA in frame
0444      * enable FORMAC to send endless queue of directed beacon
0445      * important: the UNA starts at byte 1 (not at byte 0)
0446      */
0447     * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
0448     a[1] = 0 ;
0449     memcpy((char *)a+1, (char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr, ETH_ALEN);
0450 
0451     CHECK_NPP() ;
0452      /* set memory address reg for writes */
0453     MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
0454     write_mdr(smc,le32_to_cpu(a[0])) ;
0455     outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;  /* set the tag bit */
0456     write_mdr(smc,le32_to_cpu(a[1])) ;
0457 
0458     outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
0459 }
0460 
0461 /*
0462     setup claim & beacon pointer
0463     NOTE :
0464         special frame packets end with a pointer to their own
0465         descriptor, and the MORE bit is set in the descriptor
0466 */
0467 static void build_claim_beacon(struct s_smc *smc, u_long t_request)
0468 {
0469     u_int   td ;
0470     int len ;
0471     struct fddi_mac_sf *mac ;
0472 
0473     /*
0474      * build claim packet
0475      */
0476     len = 17 ;
0477     td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
0478     mac = &smc->hw.fp.mac_sfb ;
0479     mac->mac_fc = FC_CLAIM ;
0480     /* DA == SA in claim frame */
0481     mac->mac_source = mac->mac_dest = MA ;
0482     /* 2's complement */
0483     set_int((char *)mac->mac_info,(int)t_request) ;
0484 
0485     copy_tx_mac(smc,td,(struct fddi_mac *)mac,
0486         smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
0487     /* set CLAIM start pointer */
0488     outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
0489 
0490     /*
0491      * build beacon packet
0492      */
0493     len = 17 ;
0494     td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
0495     mac->mac_fc = FC_BEACON ;
0496     mac->mac_source = MA ;
0497     mac->mac_dest = null_addr ;     /* DA == 0 in beacon frame */
0498     set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
0499 
0500     copy_tx_mac(smc,td,(struct fddi_mac *)mac,
0501         smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
0502     /* set beacon start pointer */
0503     outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
0504 
0505     /*
0506      * build directed beacon packet
0507      * contains optional UNA
0508      */
0509     len = 23 ;
0510     td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
0511     mac->mac_fc = FC_BEACON ;
0512     mac->mac_source = MA ;
0513     mac->mac_dest = dbeacon_multi ;     /* multicast */
0514     set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
0515     set_int((char *) mac->mac_info+4,0) ;
0516     set_int((char *) mac->mac_info+8,0) ;
0517 
0518     copy_tx_mac(smc,td,(struct fddi_mac *)mac,
0519         smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
0520 
0521     /* end of claim/beacon queue */
0522     outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
0523 
0524     outpw(FM_A(FM_WPXSF),0) ;
0525     outpw(FM_A(FM_RPXSF),0) ;
0526 }
0527 
0528 static void formac_rcv_restart(struct s_smc *smc)
0529 {
0530     /* enable receive function */
0531     SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
0532 
0533     outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;  /* clear receive lock */
0534 }
0535 
0536 void formac_tx_restart(struct s_smc *smc)
0537 {
0538     outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;  /* clear s-frame lock */
0539     outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
0540 }
0541 
0542 static void enable_formac(struct s_smc *smc)
0543 {
0544     /* set formac IMSK : 0 enables irq */
0545     outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
0546     outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
0547     outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
0548     outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
0549     outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
0550     outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
0551 }
0552 
0553 #if 0   /* Removed because the driver should use the ASICs TX complete IRQ. */
0554     /* The FORMACs tx complete IRQ should be used any longer */
0555 
0556 /*
0557     BEGIN_MANUAL_ENTRY(if,func;others;4)
0558 
0559     void enable_tx_irq(smc, queue)
0560     struct s_smc *smc ;
0561     u_short queue ;
0562 
0563 Function    DOWNCALL    (SMT, fplustm.c)
0564         enable_tx_irq() enables the FORMACs transmit complete
0565         interrupt of the queue.
0566 
0567 Para    queue   = QUEUE_S:  synchronous queue
0568         = QUEUE_A0: asynchronous queue
0569 
0570 Note    After any ring operational change the transmit complete
0571     interrupts are disabled.
0572     The operating system dependent module must enable
0573     the transmit complete interrupt of a queue,
0574         - when it queues the first frame,
0575           because of no transmit resources are beeing
0576           available and
0577         - when it escapes from the function llc_restart_tx
0578           while some frames are still queued.
0579 
0580     END_MANUAL_ENTRY
0581  */
0582 void enable_tx_irq(struct s_smc *smc, u_short queue)
0583 /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
0584 {
0585     u_short imask ;
0586 
0587     imask = ~(inpw(FM_A(FM_IMSK1U))) ;
0588 
0589     if (queue == 0) {
0590         outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
0591     }
0592     if (queue == 1) {
0593         outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
0594     }
0595 }
0596 
0597 /*
0598     BEGIN_MANUAL_ENTRY(if,func;others;4)
0599 
0600     void disable_tx_irq(smc, queue)
0601     struct s_smc *smc ;
0602     u_short queue ;
0603 
0604 Function    DOWNCALL    (SMT, fplustm.c)
0605         disable_tx_irq disables the FORMACs transmit complete
0606         interrupt of the queue
0607 
0608 Para    queue   = QUEUE_S:  synchronous queue
0609         = QUEUE_A0: asynchronous queue
0610 
0611 Note    The operating system dependent module should disable
0612     the transmit complete interrupts if it escapes from the
0613     function llc_restart_tx and no frames are queued.
0614 
0615     END_MANUAL_ENTRY
0616  */
0617 void disable_tx_irq(struct s_smc *smc, u_short queue)
0618 /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
0619 {
0620     u_short imask ;
0621 
0622     imask = ~(inpw(FM_A(FM_IMSK1U))) ;
0623 
0624     if (queue == 0) {
0625         outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
0626     }
0627     if (queue == 1) {
0628         outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
0629     }
0630 }
0631 #endif
0632 
0633 static void disable_formac(struct s_smc *smc)
0634 {
0635     /* clear formac IMSK : 1 disables irq */
0636     outpw(FM_A(FM_IMSK1U),MW) ;
0637     outpw(FM_A(FM_IMSK1L),MW) ;
0638     outpw(FM_A(FM_IMSK2U),MW) ;
0639     outpw(FM_A(FM_IMSK2L),MW) ;
0640     outpw(FM_A(FM_IMSK3U),MW) ;
0641     outpw(FM_A(FM_IMSK3L),MW) ;
0642 }
0643 
0644 
0645 static void mac_ring_up(struct s_smc *smc, int up)
0646 {
0647     if (up) {
0648         formac_rcv_restart(smc) ;   /* enable receive function */
0649         smc->hw.mac_ring_is_up = TRUE ;
0650         llc_restart_tx(smc) ;       /* TX queue */
0651     }
0652     else {
0653         /* disable receive function */
0654         SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
0655 
0656         /* abort current transmit activity */
0657         outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
0658 
0659         smc->hw.mac_ring_is_up = FALSE ;
0660     }
0661 }
0662 
0663 /*--------------------------- ISR handling ----------------------------------*/
0664 /*
0665  * mac1_irq is in drvfbi.c
0666  */
0667 
0668 /*
0669  * mac2_irq:    status bits for the receive queue 1, and ring status
0670  *      ring status indication bits
0671  */
0672 void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
0673 {
0674     u_short change_s2l ;
0675     u_short change_s2u ;
0676 
0677     /* (jd) 22-Feb-1999
0678      * Restart 2_DMax Timer after end of claiming or beaconing
0679      */
0680     if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
0681         queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
0682     }
0683     else if (code_s2l & (FM_STKISS)) {
0684         queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
0685     }
0686 
0687     /*
0688      * XOR current st bits with the last to avoid useless RMT event queuing
0689      */
0690     change_s2l = smc->hw.fp.s2l ^ code_s2l ;
0691     change_s2u = smc->hw.fp.s2u ^ code_s2u ;
0692 
0693     if ((change_s2l & FM_SRNGOP) ||
0694         (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
0695         if (code_s2l & FM_SRNGOP) {
0696             mac_ring_up(smc,1) ;
0697             queue_event(smc,EVENT_RMT,RM_RING_OP) ;
0698             smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
0699         }
0700         else {
0701             mac_ring_up(smc,0) ;
0702             queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
0703         }
0704         goto mac2_end ;
0705     }
0706     if (code_s2l & FM_SMISFRM) {    /* missed frame */
0707         smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
0708     }
0709     if (code_s2u & (FM_SRCVOVR |    /* recv. FIFO overflow */
0710             FM_SRBFL)) {    /* recv. buffer full */
0711         smc->hw.mac_ct.mac_r_restart_counter++ ;
0712 /*      formac_rcv_restart(smc) ;   */
0713         smt_stat_counter(smc,1) ;
0714 /*      goto mac2_end ;         */
0715     }
0716     if (code_s2u & FM_SOTRBEC)
0717         queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
0718     if (code_s2u & FM_SMYBEC)
0719         queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
0720     if (change_s2u & code_s2u & FM_SLOCLM) {
0721         DB_RMTN(2, "RMT : lower claim received");
0722     }
0723     if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
0724         /*
0725          * This is my claim and that claim is not detected as a
0726          * duplicate one.
0727          */
0728         queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
0729     }
0730     if (code_s2l & FM_SDUPCLM) {
0731         /*
0732          * If a duplicate claim frame (same SA but T_Bid != T_Req)
0733          * this flag will be set.
0734          * In the RMT state machine we need a RM_VALID_CLAIM event
0735          * to do the appropriate state change.
0736          * RM(34c)
0737          */
0738         queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
0739     }
0740     if (change_s2u & code_s2u & FM_SHICLM) {
0741         DB_RMTN(2, "RMT : higher claim received");
0742     }
0743     if ( (code_s2l & FM_STRTEXP) ||
0744          (code_s2l & FM_STRTEXR) )
0745         queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
0746     if (code_s2l & FM_SMULTDA) {
0747         /*
0748          * The MAC has found a 2. MAC with the same address.
0749          * Signal dup_addr_test = failed to RMT state machine.
0750          * RM(25)
0751          */
0752         smc->r.dup_addr_test = DA_FAILED ;
0753         queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
0754     }
0755     if (code_s2u & FM_SBEC)
0756         smc->hw.fp.err_stats.err_bec_stat++ ;
0757     if (code_s2u & FM_SCLM)
0758         smc->hw.fp.err_stats.err_clm_stat++ ;
0759     if (code_s2l & FM_STVXEXP)
0760         smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
0761     if ((code_s2u & (FM_SBEC|FM_SCLM))) {
0762         if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
0763             mac_ring_up(smc,0) ;
0764             queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
0765 
0766             mac_ring_up(smc,1) ;
0767             queue_event(smc,EVENT_RMT,RM_RING_OP) ;
0768             smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
0769         }
0770     }
0771     if (code_s2l & FM_SPHINV)
0772         smc->hw.fp.err_stats.err_phinv++ ;
0773     if (code_s2l & FM_SSIFG)
0774         smc->hw.fp.err_stats.err_sifg_det++ ;
0775     if (code_s2l & FM_STKISS)
0776         smc->hw.fp.err_stats.err_tkiss++ ;
0777     if (code_s2l & FM_STKERR)
0778         smc->hw.fp.err_stats.err_tkerr++ ;
0779     if (code_s2l & FM_SFRMCTR)
0780         smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
0781     if (code_s2l & FM_SERRCTR)
0782         smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
0783     if (code_s2l & FM_SLSTCTR)
0784         smc->mib.m[MAC0].fddiMACLost_Ct  += 0x10000L ;
0785     if (code_s2u & FM_SERRSF) {
0786         SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
0787     }
0788 mac2_end:
0789     /* notice old status */
0790     smc->hw.fp.s2l = code_s2l ;
0791     smc->hw.fp.s2u = code_s2u ;
0792     outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
0793 }
0794 
0795 /*
0796  * mac3_irq:    receive queue 2 bits and address detection bits
0797  */
0798 void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
0799 {
0800     UNUSED(code_s3l) ;
0801 
0802     if (code_s3u & (FM_SRCVOVR2 |   /* recv. FIFO overflow */
0803             FM_SRBFL2)) {   /* recv. buffer full */
0804         smc->hw.mac_ct.mac_r_restart_counter++ ;
0805         smt_stat_counter(smc,1);
0806     }
0807 
0808 
0809     if (code_s3u & FM_SRPERRQ2) {   /* parity error receive queue 2 */
0810         SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
0811     }
0812     if (code_s3u & FM_SRPERRQ1) {   /* parity error receive queue 2 */
0813         SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
0814     }
0815 }
0816 
0817 
0818 /*
0819  * take formac offline
0820  */
0821 static void formac_offline(struct s_smc *smc)
0822 {
0823     outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
0824 
0825     /* disable receive function */
0826     SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
0827 
0828     /* FORMAC+ 'Initialize Mode' */
0829     SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
0830 
0831     disable_formac(smc) ;
0832     smc->hw.mac_ring_is_up = FALSE ;
0833     smc->hw.hw_state = STOPPED ;
0834 }
0835 
0836 /*
0837  * bring formac online
0838  */
0839 static void formac_online(struct s_smc *smc)
0840 {
0841     enable_formac(smc) ;
0842     SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
0843         smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
0844 }
0845 
0846 /*
0847  * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
0848  */
0849 int init_fplus(struct s_smc *smc)
0850 {
0851     smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
0852     smc->hw.fp.rx_mode = FM_MDAMA ;
0853     smc->hw.fp.group_addr = fddi_broadcast ;
0854     smc->hw.fp.func_addr = 0 ;
0855     smc->hw.fp.frselreg_init = 0 ;
0856 
0857     init_driver_fplus(smc) ;
0858     if (smc->s.sas == SMT_DAS)
0859         smc->hw.fp.mdr3init |= FM_MENDAS ;
0860 
0861     smc->hw.mac_ct.mac_nobuf_counter = 0 ;
0862     smc->hw.mac_ct.mac_r_restart_counter = 0 ;
0863 
0864     smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
0865     smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
0866     smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
0867     smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
0868     smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
0869     smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
0870 
0871     smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
0872     smc->hw.mac_ring_is_up = 0 ;
0873 
0874     mac_counter_init(smc) ;
0875 
0876     /* convert BCKL units to symbol time */
0877     smc->hw.mac_pa.t_neg = (u_long)0 ;
0878     smc->hw.mac_pa.t_pri = (u_long)0 ;
0879 
0880     /* make sure all PCI settings are correct */
0881     mac_do_pci_fix(smc) ;
0882 
0883     return init_mac(smc, 1);
0884     /* enable_formac(smc) ; */
0885 }
0886 
0887 static int init_mac(struct s_smc *smc, int all)
0888 {
0889     u_short t_max,x ;
0890     u_long  time=0 ;
0891 
0892     /*
0893      * clear memory
0894      */
0895     outpw(FM_A(FM_MDREG1),FM_MINIT) ;   /* FORMAC+ init mode */
0896     set_formac_addr(smc) ;
0897     outpw(FM_A(FM_MDREG1),FM_MMEMACT) ; /* FORMAC+ memory activ mode */
0898     /* Note: Mode register 2 is set here, incase parity is enabled. */
0899     outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
0900 
0901     if (all) {
0902         init_ram(smc) ;
0903     }
0904     else {
0905         /*
0906          * reset the HPI, the Master and the BMUs
0907          */
0908         outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
0909         time = hwt_quick_read(smc) ;
0910     }
0911 
0912     /*
0913      * set all pointers, frames etc
0914      */
0915     smt_split_up_fifo(smc) ;
0916 
0917     init_tx(smc) ;
0918     init_rx(smc) ;
0919     init_rbc(smc) ;
0920 
0921     build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
0922 
0923     /* set RX threshold */
0924     /* see Errata #SN2 Phantom receive overflow */
0925     outpw(FM_A(FM_FRMTHR),14<<12) ;     /* switch on */
0926 
0927     /* set formac work mode */
0928     outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
0929     outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
0930     outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
0931     outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
0932 
0933     /* set timer */
0934     /*
0935      * errata #22 fplus:
0936      * T_MAX must not be FFFE
0937      * or one of FFDF, FFB8, FF91 (-0x27 etc..)
0938      */
0939     t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
0940     x = t_max/0x27 ;
0941     x *= 0x27 ;
0942     if ((t_max == 0xfffe) || (t_max - x == 0x16))
0943         t_max-- ;
0944     outpw(FM_A(FM_TMAX),(u_short)t_max) ;
0945 
0946     /* BugFix for report #10204 */
0947     if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
0948         outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
0949     } else {
0950         outpw(FM_A(FM_TVX),
0951             (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
0952     }
0953 
0954     outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;  /* clear s-frame lock */
0955     outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
0956     outpw(FM_A(FM_CMDREG1),FM_ICLLR);   /* clear receive lock */
0957 
0958     /* Auto unlock receice threshold for receive queue 1 and 2 */
0959     outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
0960 
0961     rtm_init(smc) ;             /* RT-Monitor */
0962 
0963     if (!all) {
0964         /*
0965          * after 10ms, reset the BMUs and repair the rings
0966          */
0967         hwt_wait_time(smc,time,MS2BCLK(10)) ;
0968         outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
0969         outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
0970         outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
0971         outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
0972         outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
0973         outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
0974         outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
0975         if (!smc->hw.hw_is_64bit) {
0976             outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
0977             outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
0978             outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
0979         }
0980         smc->hw.hw_state = STOPPED ;
0981         mac_drv_repair_descr(smc) ;
0982     }
0983     smc->hw.hw_state = STARTED ;
0984 
0985     return 0;
0986 }
0987 
0988 
0989 /*
0990  * called by CFM
0991  */
0992 void config_mux(struct s_smc *smc, int mux)
0993 {
0994     plc_config_mux(smc,mux) ;
0995 
0996     SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
0997 }
0998 
0999 /*
1000  * called by RMT
1001  * enable CLAIM/BEACON interrupts
1002  * (only called if these events are of interest, e.g. in DETECT state
1003  * the interrupt must not be permanently enabled
1004  * RMT calls this function periodically (timer driven polling)
1005  */
1006 void sm_mac_check_beacon_claim(struct s_smc *smc)
1007 {
1008     /* set formac IMSK : 0 enables irq */
1009     outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
1010     /* the driver must receive the directed beacons */
1011     formac_rcv_restart(smc) ;
1012     process_receive(smc) ;
1013 }
1014 
1015 /*-------------------------- interface functions ----------------------------*/
1016 /*
1017  * control MAC layer    (called by RMT)
1018  */
1019 void sm_ma_control(struct s_smc *smc, int mode)
1020 {
1021     switch(mode) {
1022     case MA_OFFLINE :
1023         /* Add to make the MAC offline in RM0_ISOLATED state */
1024         formac_offline(smc) ;
1025         break ;
1026     case MA_RESET :
1027         (void)init_mac(smc,0) ;
1028         break ;
1029     case MA_BEACON :
1030         formac_online(smc) ;
1031         break ;
1032     case MA_DIRECTED :
1033         directed_beacon(smc) ;
1034         break ;
1035     case MA_TREQ :
1036         /*
1037          * no actions necessary, TREQ is already set
1038          */
1039         break ;
1040     }
1041 }
1042 
1043 int sm_mac_get_tx_state(struct s_smc *smc)
1044 {
1045     return (inpw(FM_A(FM_STMCHN))>>4) & 7;
1046 }
1047 
1048 /*
1049  * multicast functions
1050  */
1051 
1052 static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
1053                        struct fddi_addr *user,
1054                        struct fddi_addr *own,
1055                        int del, int can)
1056 {
1057     struct s_fpmc   *tb ;
1058     struct s_fpmc   *slot ;
1059     u_char  *p ;
1060     int i ;
1061 
1062     /*
1063      * set own = can(user)
1064      */
1065     *own = *user ;
1066     if (can) {
1067         p = own->a ;
1068         for (i = 0 ; i < 6 ; i++, p++)
1069             *p = bitrev8(*p);
1070     }
1071     slot = NULL;
1072     for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1073         if (!tb->n) {       /* not used */
1074             if (!del && !slot)  /* if !del save first free */
1075                 slot = tb ;
1076             continue ;
1077         }
1078         if (!ether_addr_equal((char *)&tb->a, (char *)own))
1079             continue ;
1080         return tb;
1081     }
1082     return slot;            /* return first free or NULL */
1083 }
1084 
1085 /*
1086     BEGIN_MANUAL_ENTRY(if,func;others;2)
1087 
1088     void mac_clear_multicast(smc)
1089     struct s_smc *smc ;
1090 
1091 Function    DOWNCALL    (SMT, fplustm.c)
1092         Clear all multicast entries
1093 
1094     END_MANUAL_ENTRY()
1095  */
1096 void mac_clear_multicast(struct s_smc *smc)
1097 {
1098     struct s_fpmc   *tb ;
1099     int i ;
1100 
1101     smc->hw.fp.os_slots_used = 0 ;  /* note the SMT addresses */
1102                     /* will not be deleted */
1103     for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1104         if (!tb->perm) {
1105             tb->n = 0 ;
1106         }
1107     }
1108 }
1109 
1110 /*
1111     BEGIN_MANUAL_ENTRY(if,func;others;2)
1112 
1113     int mac_add_multicast(smc,addr,can)
1114     struct s_smc *smc ;
1115     struct fddi_addr *addr ;
1116     int can ;
1117 
1118 Function    DOWNCALL    (SMC, fplustm.c)
1119         Add an entry to the multicast table
1120 
1121 Para    addr    pointer to a multicast address
1122     can = 0:    the multicast address has the physical format
1123         = 1:    the multicast address has the canonical format
1124         | 0x80  permanent
1125 
1126 Returns 0: success
1127     1: address table full
1128 
1129 Note    After a 'driver reset' or a 'station set address' all
1130     entries of the multicast table are cleared.
1131     In this case the driver has to fill the multicast table again.
1132     After the operating system dependent module filled
1133     the multicast table it must call mac_update_multicast
1134     to activate the new multicast addresses!
1135 
1136     END_MANUAL_ENTRY()
1137  */
1138 int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
1139 {
1140     SK_LOC_DECL(struct fddi_addr,own) ;
1141     struct s_fpmc   *tb ;
1142 
1143     /*
1144      * check if there are free table entries
1145      */
1146     if (can & 0x80) {
1147         if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
1148             return 1;
1149         }
1150     }
1151     else {
1152         if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
1153             return 1;
1154         }
1155     }
1156 
1157     /*
1158      * find empty slot
1159      */
1160     if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
1161         return 1;
1162     tb->n++ ;
1163     tb->a = own ;
1164     tb->perm = (can & 0x80) ? 1 : 0 ;
1165 
1166     if (can & 0x80)
1167         smc->hw.fp.smt_slots_used++ ;
1168     else
1169         smc->hw.fp.os_slots_used++ ;
1170 
1171     return 0;
1172 }
1173 
1174 /*
1175  * mode
1176  */
1177 
1178 #define RX_MODE_PROM        0x1
1179 #define RX_MODE_ALL_MULTI   0x2
1180 
1181 /*
1182     BEGIN_MANUAL_ENTRY(if,func;others;2)
1183 
1184     void mac_update_multicast(smc)
1185     struct s_smc *smc ;
1186 
1187 Function    DOWNCALL    (SMT, fplustm.c)
1188         Update FORMAC multicast registers
1189 
1190     END_MANUAL_ENTRY()
1191  */
1192 void mac_update_multicast(struct s_smc *smc)
1193 {
1194     struct s_fpmc   *tb ;
1195     u_char  *fu ;
1196     int i ;
1197 
1198     /*
1199      * invalidate the CAM
1200      */
1201     outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
1202 
1203     /*
1204      * set the functional address
1205      */
1206     if (smc->hw.fp.func_addr) {
1207         fu = (u_char *) &smc->hw.fp.func_addr ;
1208         outpw(FM_A(FM_AFMASK2),0xffff) ;
1209         outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
1210         outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
1211         outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1212         outpw(FM_A(FM_AFCOMP2), 0xc000) ;
1213         outpw(FM_A(FM_AFCOMP1), 0x0000) ;
1214         outpw(FM_A(FM_AFCOMP0), 0x0000) ;
1215         outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1216     }
1217 
1218     /*
1219      * set the mask and the personality register(s)
1220      */
1221     outpw(FM_A(FM_AFMASK0),0xffff) ;
1222     outpw(FM_A(FM_AFMASK1),0xffff) ;
1223     outpw(FM_A(FM_AFMASK2),0xffff) ;
1224     outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1225 
1226     for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
1227         if (tb->n) {
1228             CHECK_CAM() ;
1229 
1230             /*
1231              * write the multicast address into the CAM
1232              */
1233             outpw(FM_A(FM_AFCOMP2),
1234                 (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
1235             outpw(FM_A(FM_AFCOMP1),
1236                 (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
1237             outpw(FM_A(FM_AFCOMP0),
1238                 (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
1239             outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1240         }
1241     }
1242 }
1243 
1244 /*
1245     BEGIN_MANUAL_ENTRY(if,func;others;3)
1246 
1247     void mac_set_rx_mode(smc,mode)
1248     struct s_smc *smc ;
1249     int mode ;
1250 
1251 Function    DOWNCALL/INTERN (SMT, fplustm.c)
1252         This function enables / disables the selected receive.
1253         Don't call this function if the hardware module is
1254         used -- use mac_drv_rx_mode() instead of.
1255 
1256 Para    mode =  1   RX_ENABLE_ALLMULTI  enable all multicasts
1257         2   RX_DISABLE_ALLMULTI disable "enable all multicasts"
1258         3   RX_ENABLE_PROMISC   enable promiscuous
1259         4   RX_DISABLE_PROMISC  disable promiscuous
1260         5   RX_ENABLE_NSA       enable reception of NSA frames
1261         6   RX_DISABLE_NSA      disable reception of NSA frames
1262 
1263 Note    The selected receive modes will be lost after 'driver reset'
1264     or 'set station address'
1265 
1266     END_MANUAL_ENTRY
1267  */
1268 void mac_set_rx_mode(struct s_smc *smc, int mode)
1269 {
1270     switch (mode) {
1271     case RX_ENABLE_ALLMULTI :
1272         smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
1273         break ;
1274     case RX_DISABLE_ALLMULTI :
1275         smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
1276         break ;
1277     case RX_ENABLE_PROMISC :
1278         smc->hw.fp.rx_prom |= RX_MODE_PROM ;
1279         break ;
1280     case RX_DISABLE_PROMISC :
1281         smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
1282         break ;
1283     case RX_ENABLE_NSA :
1284         smc->hw.fp.nsa_mode = FM_MDAMA ;
1285         smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1286             smc->hw.fp.nsa_mode ;
1287         break ;
1288     case RX_DISABLE_NSA :
1289         smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
1290         smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1291             smc->hw.fp.nsa_mode ;
1292         break ;
1293     }
1294     if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
1295         smc->hw.fp.rx_mode = FM_MLIMPROM ;
1296     }
1297     else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
1298         smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
1299     }
1300     else
1301         smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
1302     SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
1303     mac_update_multicast(smc) ;
1304 }
1305 
1306 /*
1307     BEGIN_MANUAL_ENTRY(module;tests;3)
1308     How to test the Restricted Token Monitor
1309     ----------------------------------------------------------------
1310 
1311     o Insert a break point in the function rtm_irq()
1312     o Remove all stations with a restricted token monitor from the
1313       network.
1314     o Connect a UPPS ISA or EISA station to the network.
1315     o Give the FORMAC of UPPS station the command to send
1316       restricted tokens until the ring becomes instable.
1317     o Now connect your test client.
1318     o The restricted token monitor should detect the restricted token,
1319       and your break point will be reached.
1320     o You can ovserve how the station will clean the ring.
1321 
1322     END_MANUAL_ENTRY
1323  */
1324 void rtm_irq(struct s_smc *smc)
1325 {
1326     outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;       /* clear IRQ */
1327     if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
1328         outpw(FM_A(FM_CMDREG1),FM_ICL) ;    /* force claim */
1329         DB_RMT("RMT: fddiPATHT_Rmode expired");
1330         AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
1331                 (u_long) FDDI_SMT_EVENT,
1332                 (u_long) FDDI_RTT, smt_get_event_word(smc));
1333     }
1334     outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable RTM monitoring */
1335 }
1336 
1337 static void rtm_init(struct s_smc *smc)
1338 {
1339     outpd(ADDR(B2_RTM_INI),0) ;     /* timer = 0 */
1340     outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable IRQ */
1341 }
1342 
1343 void rtm_set_timer(struct s_smc *smc)
1344 {
1345     /*
1346      * MIB timer and hardware timer have the same resolution of 80nS
1347      */
1348     DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns",
1349            (int)smc->mib.a[PATH0].fddiPATHT_Rmode);
1350     outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
1351 }
1352 
1353 static void smt_split_up_fifo(struct s_smc *smc)
1354 {
1355 
1356 /*
1357     BEGIN_MANUAL_ENTRY(module;mem;1)
1358     -------------------------------------------------------------
1359     RECEIVE BUFFER MEMORY DIVERSION
1360     -------------------------------------------------------------
1361 
1362     R1_RxD == SMT_R1_RXD_COUNT
1363     R2_RxD == SMT_R2_RXD_COUNT
1364 
1365     SMT_R1_RXD_COUNT must be unequal zero
1366 
1367            | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
1368            |   x      0    |  x     1-3   |   x     < 3
1369     ----------------------------------------------------------------------
1370            |   63,75 kB    |    54,75     | R1_RxD
1371     rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
1372            |           |          | R1_RxD+R2_RxD
1373     ----------------------------------------------------------------------
1374            |           |    9 kB      |     R2_RxD
1375     rx queue 2 |    0 kB       | RX_SMALL_FIFO| ------------- * 63,75 kB
1376            |  (not used)   |          | R1_RxD+R2_RxD
1377 
1378     END_MANUAL_ENTRY
1379 */
1380 
1381     if (SMT_R1_RXD_COUNT == 0) {
1382         SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
1383     }
1384 
1385     switch(SMT_R2_RXD_COUNT) {
1386     case 0:
1387         smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
1388         smc->hw.fp.fifo.rx2_fifo_size = 0 ;
1389         break ;
1390     case 1:
1391     case 2:
1392     case 3:
1393         smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
1394         smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
1395         break ;
1396     default:    /* this is not the real defaule */
1397         smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
1398         SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1399         smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
1400         SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1401         break ;
1402     }
1403 
1404 /*
1405     BEGIN_MANUAL_ENTRY(module;mem;1)
1406     -------------------------------------------------------------
1407     TRANSMIT BUFFER MEMORY DIVERSION
1408     -------------------------------------------------------------
1409 
1410 
1411          | no sync bw   | sync bw available and | sync bw available and
1412          | available    | SynchTxMode = SPLIT   | SynchTxMode = ALL
1413     -----------------------------------------------------------------------
1414     sync tx  |     0 kB |   32 kB       |   55 kB
1415     queue    |      |   TX_MEDIUM_FIFO  |   TX_LARGE_FIFO
1416     -----------------------------------------------------------------------
1417     async tx |    64 kB |   32 kB       |    9 k
1418     queue    | TX_FIFO_SPACE|   TX_MEDIUM_FIFO  |   TX_SMALL_FIFO
1419 
1420     END_MANUAL_ENTRY
1421 */
1422 
1423     /*
1424      * set the tx mode bits
1425      */
1426     if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
1427 #ifdef ESS
1428         smc->hw.fp.fifo.fifo_config_mode |=
1429             smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
1430 #endif
1431     }
1432     else {
1433         smc->hw.fp.fifo.fifo_config_mode &=
1434             ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
1435     }
1436 
1437     /*
1438      * split up the FIFO
1439      */
1440     if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
1441         if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
1442             smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
1443             smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
1444         }
1445         else {
1446             smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
1447             smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
1448         }
1449     }
1450     else {
1451             smc->hw.fp.fifo.tx_s_size = 0 ;
1452             smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
1453     }
1454 
1455     smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
1456         RX_FIFO_OFF ;
1457     smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
1458         smc->hw.fp.fifo.rx1_fifo_size ;
1459     smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
1460         smc->hw.fp.fifo.tx_s_size ;
1461     smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
1462         smc->hw.fp.fifo.tx_a0_size ;
1463 
1464     DB_SMT("FIFO split: mode = %x", smc->hw.fp.fifo.fifo_config_mode);
1465     DB_SMT("rbc_ram_start = %x   rbc_ram_end =  %x",
1466            smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end);
1467     DB_SMT("rx1_fifo_start = %x  tx_s_start =   %x",
1468            smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start);
1469     DB_SMT("tx_a0_start =   %x   rx2_fifo_start =   %x",
1470            smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start);
1471 }
1472 
1473 void formac_reinit_tx(struct s_smc *smc)
1474 {
1475     /*
1476      * Split up the FIFO and reinitialize the MAC if synchronous
1477      * bandwidth becomes available but no synchronous queue is
1478      * configured.
1479      */
1480     if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
1481         (void)init_mac(smc,0) ;
1482     }
1483 }
1484