OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [skfp/] [fplustm.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.