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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [skfp/] [hwmtm.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
#ifndef lint
18
static char const ID_sccs[] = "@(#)hwmtm.c      1.40 99/05/31 (C) SK" ;
19
#endif
20
 
21
#define HWMTM
22
 
23
#ifndef FDDI
24
#define FDDI
25
#endif
26
 
27
#include "h/types.h"
28
#include "h/fddi.h"
29
#include "h/smc.h"
30
#include "h/supern_2.h"
31
#include "h/skfbiinc.h"
32
 
33
/*
34
        -------------------------------------------------------------
35
        DOCUMENTATION
36
        -------------------------------------------------------------
37
        BEGIN_MANUAL_ENTRY(DOCUMENTATION)
38
 
39
                        T B D
40
 
41
        END_MANUAL_ENTRY
42
*/
43
/*
44
        -------------------------------------------------------------
45
        LOCAL VARIABLES:
46
        -------------------------------------------------------------
47
*/
48
#ifdef COMMON_MB_POOL
49
static  SMbuf *mb_start = 0 ;
50
static  SMbuf *mb_free = 0 ;
51
static  int mb_init = FALSE ;
52
static  int call_count = 0 ;
53
#endif
54
 
55
/*
56
        -------------------------------------------------------------
57
        EXTERNE VARIABLES:
58
        -------------------------------------------------------------
59
*/
60
 
61
#ifdef  DEBUG
62
#ifndef DEBUG_BRD
63
extern  struct smt_debug        debug ;
64
#endif
65
#endif
66
 
67
#ifdef  NDIS_OS2
68
extern  u_char  offDepth ;
69
extern  u_char  force_irq_pending ;
70
#endif
71
 
72
/*
73
        -------------------------------------------------------------
74
        LOCAL FUNCTIONS:
75
        -------------------------------------------------------------
76
*/
77
 
78
static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
79
static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
80
static void init_txd_ring(struct s_smc *smc);
81
static void init_rxd_ring(struct s_smc *smc);
82
static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
83
static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
84
                              int count);
85
static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
86
static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
87
static SMbuf* get_llc_rx(struct s_smc *smc);
88
static SMbuf* get_txd_mb(struct s_smc *smc);
89
static void mac_drv_clear_txd(struct s_smc *smc);
90
 
91
/*
92
        -------------------------------------------------------------
93
        EXTERNAL FUNCTIONS:
94
        -------------------------------------------------------------
95
*/
96
/*      The external SMT functions are listed in cmtdef.h */
97
 
98
extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
99
extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
100
extern void init_board(struct s_smc *smc, u_char *mac_addr);
101
extern void mac_drv_fill_rxd(struct s_smc *smc);
102
extern void plc1_irq(struct s_smc *smc);
103
extern void mac_drv_tx_complete(struct s_smc *smc,
104
                                volatile struct s_smt_fp_txd *txd);
105
extern void plc2_irq(struct s_smc *smc);
106
extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
107
extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
108
extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
109
extern void timer_irq(struct s_smc *smc);
110
extern void mac_drv_rx_complete(struct s_smc *smc,
111
                                volatile struct s_smt_fp_rxd *rxd,
112
                                int frag_count, int len);
113
extern void mac_drv_requeue_rxd(struct s_smc *smc,
114
                                volatile struct s_smt_fp_rxd *rxd,
115
                                int frag_count);
116
extern void init_plc(struct s_smc *smc);
117
extern void mac_drv_clear_rxd(struct s_smc *smc,
118
                              volatile struct s_smt_fp_rxd *rxd, int frag_count);
119
 
120
#ifdef  USE_OS_CPY
121
extern void hwm_cpy_rxd2mb(void);
122
extern void hwm_cpy_txd2mb(void);
123
#endif
124
 
125
#ifdef  ALL_RX_COMPLETE
126
extern void mac_drv_all_receives_complete(void);
127
#endif
128
 
129
extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
130
extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
131
 
132
#ifdef  NDIS_OS2
133
extern void post_proc(void);
134
#else
135
extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
136
                         int flag);
137
#endif
138
 
139
extern int init_fplus(struct s_smc *smc);
140
extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
141
                           int la_len);
142
 
143
/*
144
        -------------------------------------------------------------
145
        PUBLIC FUNCTIONS:
146
        -------------------------------------------------------------
147
*/
148
void process_receive(struct s_smc *smc);
149
void fddi_isr(struct s_smc *smc);
150
void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
151
void init_driver_fplus(struct s_smc *smc);
152
void mac_drv_rx_mode(struct s_smc *smc, int mode);
153
void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
154
void mac_drv_clear_tx_queue(struct s_smc *smc);
155
void mac_drv_clear_rx_queue(struct s_smc *smc);
156
void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
157
                 int frame_status);
158
void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
159
                 int frame_status);
160
 
161
int mac_drv_init(struct s_smc *smc);
162
int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
163
                int frame_status);
164
 
165
u_int mac_drv_check_space(void);
166
 
167
SMbuf* smt_get_mbuf(struct s_smc *smc);
168
 
169
#ifdef DEBUG
170
        void mac_drv_debug_lev(void);
171
#endif
172
 
173
/*
174
        -------------------------------------------------------------
175
        MACROS:
176
        -------------------------------------------------------------
177
*/
178
#ifndef UNUSED
179
#ifdef  lint
180
#define UNUSED(x)       (x) = (x)
181
#else
182
#define UNUSED(x)
183
#endif
184
#endif
185
 
186
#ifdef  USE_CAN_ADDR
187
#define MA              smc->hw.fddi_canon_addr.a
188
#define GROUP_ADDR_BIT  0x01
189
#else
190
#define MA              smc->hw.fddi_home_addr.a
191
#define GROUP_ADDR_BIT  0x80
192
#endif
193
 
194
#define RXD_TXD_COUNT   (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
195
                        SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
196
 
197
#ifdef  MB_OUTSIDE_SMC
198
#define EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
199
                        MAX_MBUF*sizeof(SMbuf))
200
#define EXT_VIRT_MEM_2  ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
201
#else
202
#define EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
203
#endif
204
 
205
        /*
206
         * define critical read for 16 Bit drivers
207
         */
208
#if     defined(NDIS_OS2) || defined(ODI2)
209
#define CR_READ(var)    ((var) & 0xffff0000 | ((var) & 0xffff))
210
#else
211
#define CR_READ(var)    (u_long)(var)
212
#endif
213
 
214
#define IMASK_SLOW      (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
215
                         IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
216
                         IS_R1_C | IS_XA_C | IS_XS_C)
217
 
218
/*
219
        -------------------------------------------------------------
220
        INIT- AND SMT FUNCTIONS:
221
        -------------------------------------------------------------
222
*/
223
 
224
 
225
/*
226
 *      BEGIN_MANUAL_ENTRY(mac_drv_check_space)
227
 *      u_int mac_drv_check_space()
228
 *
229
 *      function        DOWNCALL        (drvsr.c)
230
 *                      This function calculates the needed non virtual
231
 *                      memory for MBufs, RxD and TxD descriptors etc.
232
 *                      needed by the driver.
233
 *
234
 *      return          u_int   memory in bytes
235
 *
236
 *      END_MANUAL_ENTRY
237
 */
238
u_int mac_drv_check_space(void)
239
{
240
#ifdef  MB_OUTSIDE_SMC
241
#ifdef  COMMON_MB_POOL
242
        call_count++ ;
243
        if (call_count == 1) {
244
                return(EXT_VIRT_MEM) ;
245
        }
246
        else {
247
                return(EXT_VIRT_MEM_2) ;
248
        }
249
#else
250
        return (EXT_VIRT_MEM) ;
251
#endif
252
#else
253
        return (0) ;
254
#endif
255
}
256
 
257
/*
258
 *      BEGIN_MANUAL_ENTRY(mac_drv_init)
259
 *      void mac_drv_init(smc)
260
 *
261
 *      function        DOWNCALL        (drvsr.c)
262
 *                      In this function the hardware module allocates it's
263
 *                      memory.
264
 *                      The operating system dependent module should call
265
 *                      mac_drv_init once, after the adatper is detected.
266
 *      END_MANUAL_ENTRY
267
 */
268
int mac_drv_init(struct s_smc *smc)
269
{
270
        if (sizeof(struct s_smt_fp_rxd) % 16) {
271
                SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
272
        }
273
        if (sizeof(struct s_smt_fp_txd) % 16) {
274
                SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
275
        }
276
 
277
        /*
278
         * get the required memory for the RxDs and TxDs
279
         */
280
        if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
281
                mac_drv_get_desc_mem(smc,(u_int)
282
                (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
283
                return(1) ;     /* no space the hwm modul can't work */
284
        }
285
 
286
        /*
287
         * get the memory for the SMT MBufs
288
         */
289
#ifndef MB_OUTSIDE_SMC
290
        smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
291
#else
292
#ifndef COMMON_MB_POOL
293
        if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
294
                MAX_MBUF*sizeof(SMbuf)))) {
295
                return(1) ;     /* no space the hwm modul can't work */
296
        }
297
#else
298
        if (!mb_start) {
299
                if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
300
                        MAX_MBUF*sizeof(SMbuf)))) {
301
                        return(1) ;     /* no space the hwm modul can't work */
302
                }
303
        }
304
#endif
305
#endif
306
        return (0) ;
307
}
308
 
309
/*
310
 *      BEGIN_MANUAL_ENTRY(init_driver_fplus)
311
 *      init_driver_fplus(smc)
312
 *
313
 * Sets hardware modul specific values for the mode register 2
314
 * (e.g. the byte alignment for the received frames, the position of the
315
 *       least significant byte etc.)
316
 *      END_MANUAL_ENTRY
317
 */
318
void init_driver_fplus(struct s_smc *smc)
319
{
320
        smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
321
 
322
#ifdef  PCI
323
        smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
324
#endif
325
        smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
326
 
327
#ifdef  USE_CAN_ADDR
328
        /* enable address bit swapping */
329
        smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
330
#endif
331
}
332
 
333
static u_long init_descr_ring(struct s_smc *smc,
334
                              union s_fp_descr volatile *start,
335
                              int count)
336
{
337
        int i ;
338
        union s_fp_descr volatile *d1 ;
339
        union s_fp_descr volatile *d2 ;
340
        u_long  phys ;
341
 
342
        DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ;
343
        for (i=count-1, d1=start; i ; i--) {
344
                d2 = d1 ;
345
                d1++ ;          /* descr is owned by the host */
346
                d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
347
                d2->r.rxd_next = &d1->r ;
348
                phys = mac_drv_virt2phys(smc,(void *)d1) ;
349
                d2->r.rxd_nrdadr = AIX_REVERSE(phys) ;
350
        }
351
        DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
352
        d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
353
        d1->r.rxd_next = &start->r ;
354
        phys = mac_drv_virt2phys(smc,(void *)start) ;
355
        d1->r.rxd_nrdadr = AIX_REVERSE(phys) ;
356
 
357
        for (i=count, d1=start; i ; i--) {
358
                DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
359
                d1++;
360
        }
361
        return(phys) ;
362
}
363
 
364
static void init_txd_ring(struct s_smc *smc)
365
{
366
        struct s_smt_fp_txd volatile *ds ;
367
        struct s_smt_tx_queue *queue ;
368
        u_long  phys ;
369
 
370
        /*
371
         * initialize the transmit descriptors
372
         */
373
        ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
374
                SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
375
        queue = smc->hw.fp.tx[QUEUE_A0] ;
376
        DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
377
        (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
378
                HWM_ASYNC_TXD_COUNT) ;
379
        phys = AIX_REVERSE(ds->txd_ntdadr) ;
380
        ds++ ;
381
        queue->tx_curr_put = queue->tx_curr_get = ds ;
382
        ds-- ;
383
        queue->tx_free = HWM_ASYNC_TXD_COUNT ;
384
        queue->tx_used = 0 ;
385
        outpd(ADDR(B5_XA_DA),phys) ;
386
 
387
        ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
388
                HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
389
        queue = smc->hw.fp.tx[QUEUE_S] ;
390
        DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
391
        (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
392
                HWM_SYNC_TXD_COUNT) ;
393
        phys = AIX_REVERSE(ds->txd_ntdadr) ;
394
        ds++ ;
395
        queue->tx_curr_put = queue->tx_curr_get = ds ;
396
        queue->tx_free = HWM_SYNC_TXD_COUNT ;
397
        queue->tx_used = 0 ;
398
        outpd(ADDR(B5_XS_DA),phys) ;
399
}
400
 
401
static void init_rxd_ring(struct s_smc *smc)
402
{
403
        struct s_smt_fp_rxd volatile *ds ;
404
        struct s_smt_rx_queue *queue ;
405
        u_long  phys ;
406
 
407
        /*
408
         * initialize the receive descriptors
409
         */
410
        ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
411
        queue = smc->hw.fp.rx[QUEUE_R1] ;
412
        DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
413
        (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
414
                SMT_R1_RXD_COUNT) ;
415
        phys = AIX_REVERSE(ds->rxd_nrdadr) ;
416
        ds++ ;
417
        queue->rx_curr_put = queue->rx_curr_get = ds ;
418
        queue->rx_free = SMT_R1_RXD_COUNT ;
419
        queue->rx_used = 0 ;
420
        outpd(ADDR(B4_R1_DA),phys) ;
421
}
422
 
423
/*
424
 *      BEGIN_MANUAL_ENTRY(init_fddi_driver)
425
 *      void init_fddi_driver(smc,mac_addr)
426
 *
427
 * initializes the driver and it's variables
428
 *
429
 *      END_MANUAL_ENTRY
430
 */
431
void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
432
{
433
        SMbuf   *mb ;
434
        int     i ;
435
 
436
        init_board(smc,mac_addr) ;
437
        (void)init_fplus(smc) ;
438
 
439
        /*
440
         * initialize the SMbufs for the SMT
441
         */
442
#ifndef COMMON_MB_POOL
443
        mb = smc->os.hwm.mbuf_pool.mb_start ;
444
        smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
445
        for (i = 0; i < MAX_MBUF; i++) {
446
                mb->sm_use_count = 1 ;
447
                smt_free_mbuf(smc,mb)   ;
448
                mb++ ;
449
        }
450
#else
451
        mb = mb_start ;
452
        if (!mb_init) {
453
                mb_free = 0 ;
454
                for (i = 0; i < MAX_MBUF; i++) {
455
                        mb->sm_use_count = 1 ;
456
                        smt_free_mbuf(smc,mb)   ;
457
                        mb++ ;
458
                }
459
                mb_init = TRUE ;
460
        }
461
#endif
462
 
463
        /*
464
         * initialize the other variables
465
         */
466
        smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
467
        smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
468
        smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
469
        smc->os.hwm.pass_llc_promisc = TRUE ;
470
        smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
471
        smc->os.hwm.detec_count = 0 ;
472
        smc->os.hwm.rx_break = 0 ;
473
        smc->os.hwm.rx_len_error = 0 ;
474
        smc->os.hwm.isr_flag = FALSE ;
475
 
476
        /*
477
         * make sure that the start pointer is 16 byte aligned
478
         */
479
        i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;
480
        if (i != 16) {
481
                DB_GEN("i = %d",i,0,3) ;
482
                smc->os.hwm.descr_p = (union s_fp_descr volatile *)
483
                        ((char *)smc->os.hwm.descr_p+i) ;
484
        }
485
        DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ;
486
 
487
        init_txd_ring(smc) ;
488
        init_rxd_ring(smc) ;
489
        mac_drv_fill_rxd(smc) ;
490
 
491
        init_plc(smc) ;
492
}
493
 
494
 
495
SMbuf *smt_get_mbuf(struct s_smc *smc)
496
{
497
        register SMbuf  *mb ;
498
 
499
#ifndef COMMON_MB_POOL
500
        mb = smc->os.hwm.mbuf_pool.mb_free ;
501
#else
502
        mb = mb_free ;
503
#endif
504
        if (mb) {
505
#ifndef COMMON_MB_POOL
506
                smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
507
#else
508
                mb_free = mb->sm_next ;
509
#endif
510
                mb->sm_off = 8 ;
511
                mb->sm_use_count = 1 ;
512
        }
513
        DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
514
        return (mb) ;   /* May be NULL */
515
}
516
 
517
void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
518
{
519
 
520
        if (mb) {
521
                mb->sm_use_count-- ;
522
                DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ;
523
                /*
524
                 * If the use_count is != zero the MBuf is queued
525
                 * more than once and must not queued into the
526
                 * free MBuf queue
527
                 */
528
                if (!mb->sm_use_count) {
529
                        DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;
530
#ifndef COMMON_MB_POOL
531
                        mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
532
                        smc->os.hwm.mbuf_pool.mb_free = mb ;
533
#else
534
                        mb->sm_next = mb_free ;
535
                        mb_free = mb ;
536
#endif
537
                }
538
        }
539
        else
540
                SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
541
}
542
 
543
 
544
/*
545
 *      BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)
546
 *      void mac_drv_repair_descr(smc)
547
 *
548
 * function     called from SMT (HWM / hwmtm.c)
549
 *              The BMU is idle when this function is called.
550
 *              Mac_drv_repair_descr sets up the physical address
551
 *              for all receive and transmit queues where the BMU
552
 *              should continue.
553
 *              It may be that the BMU was reseted during a fragmented
554
 *              transfer. In this case there are some fragments which will
555
 *              never completed by the BMU. The OWN bit of this fragments
556
 *              must be switched to be owned by the host.
557
 *
558
 *              Give a start command to the receive BMU.
559
 *              Start the transmit BMUs if transmit frames pending.
560
 *
561
 *      END_MANUAL_ENTRY
562
 */
563
void mac_drv_repair_descr(struct s_smc *smc)
564
{
565
        u_long  phys ;
566
 
567
        if (smc->hw.hw_state != STOPPED) {
568
                SK_BREAK() ;
569
                SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
570
                return ;
571
        }
572
 
573
        /*
574
         * repair tx queues: don't start
575
         */
576
        phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
577
        outpd(ADDR(B5_XA_DA),phys) ;
578
        if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
579
                outpd(ADDR(B0_XA_CSR),CSR_START) ;
580
        }
581
        phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
582
        outpd(ADDR(B5_XS_DA),phys) ;
583
        if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
584
                outpd(ADDR(B0_XS_CSR),CSR_START) ;
585
        }
586
 
587
        /*
588
         * repair rx queues
589
         */
590
        phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
591
        outpd(ADDR(B4_R1_DA),phys) ;
592
        outpd(ADDR(B0_R1_CSR),CSR_START) ;
593
}
594
 
595
static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
596
{
597
        int i ;
598
        int tx_used ;
599
        u_long phys ;
600
        u_long tbctrl ;
601
        struct s_smt_fp_txd volatile *t ;
602
 
603
        SK_UNUSED(smc) ;
604
 
605
        t = queue->tx_curr_get ;
606
        tx_used = queue->tx_used ;
607
        for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
608
                t = t->txd_next ;
609
        }
610
        phys = AIX_REVERSE(t->txd_ntdadr) ;
611
 
612
        t = queue->tx_curr_get ;
613
        while (tx_used) {
614
                DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
615
                tbctrl = AIX_REVERSE(t->txd_tbctrl) ;
616
 
617
                if (tbctrl & BMU_OWN) {
618
                        if (tbctrl & BMU_STF) {
619
                                break ;         /* exit the loop */
620
                        }
621
                        else {
622
                                /*
623
                                 * repair the descriptor
624
                                 */
625
                                t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
626
                        }
627
                }
628
                phys = AIX_REVERSE(t->txd_ntdadr) ;
629
                DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
630
                t = t->txd_next ;
631
                tx_used-- ;
632
        }
633
        return(phys) ;
634
}
635
 
636
/*
637
 * Repairs the receive descriptor ring and returns the physical address
638
 * where the BMU should continue working.
639
 *
640
 *      o The physical address where the BMU was stopped has to be
641
 *        determined. This is the next RxD after rx_curr_get with an OWN
642
 *        bit set.
643
 *      o The BMU should start working at beginning of the next frame.
644
 *        RxDs with an OWN bit set but with a reset STF bit should be
645
 *        skipped and owned by the driver (OWN = 0).
646
 */
647
static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
648
{
649
        int i ;
650
        int rx_used ;
651
        u_long phys ;
652
        u_long rbctrl ;
653
        struct s_smt_fp_rxd volatile *r ;
654
 
655
        SK_UNUSED(smc) ;
656
 
657
        r = queue->rx_curr_get ;
658
        rx_used = queue->rx_used ;
659
        for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
660
                r = r->rxd_next ;
661
        }
662
        phys = AIX_REVERSE(r->rxd_nrdadr) ;
663
 
664
        r = queue->rx_curr_get ;
665
        while (rx_used) {
666
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
667
                rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;
668
 
669
                if (rbctrl & BMU_OWN) {
670
                        if (rbctrl & BMU_STF) {
671
                                break ;         /* exit the loop */
672
                        }
673
                        else {
674
                                /*
675
                                 * repair the descriptor
676
                                 */
677
                                r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
678
                        }
679
                }
680
                phys = AIX_REVERSE(r->rxd_nrdadr) ;
681
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
682
                r = r->rxd_next ;
683
                rx_used-- ;
684
        }
685
        return(phys) ;
686
}
687
 
688
 
689
/*
690
        -------------------------------------------------------------
691
        INTERRUPT SERVICE ROUTINE:
692
        -------------------------------------------------------------
693
*/
694
 
695
/*
696
 *      BEGIN_MANUAL_ENTRY(fddi_isr)
697
 *      void fddi_isr(smc)
698
 *
699
 * function     DOWNCALL        (drvsr.c)
700
 *              interrupt service routine, handles the interrupt requests
701
 *              generated by the FDDI adapter.
702
 *
703
 * NOTE:        The operating system dependent module must garantee that the
704
 *              interrupts of the adapter are disabled when it calls fddi_isr.
705
 *
706
 *      About the USE_BREAK_ISR mechanismn:
707
 *
708
 *      The main requirement of this mechanismn is to force an timer IRQ when
709
 *      leaving process_receive() with leave_isr set. process_receive() may
710
 *      be called at any time from anywhere!
711
 *      To be sure we don't miss such event we set 'force_irq' per default.
712
 *      We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND
713
 *      'force_irq' are set. 'force_irq' may be reset if a receive complete
714
 *      IRQ is pending.
715
 *
716
 *      END_MANUAL_ENTRY
717
 */
718
void fddi_isr(struct s_smc *smc)
719
{
720
        u_long          is ;            /* ISR source */
721
        u_short         stu, stl ;
722
        SMbuf           *mb ;
723
 
724
#ifdef  USE_BREAK_ISR
725
        int     force_irq ;
726
#endif
727
 
728
#ifdef  ODI2
729
        if (smc->os.hwm.rx_break) {
730
                mac_drv_fill_rxd(smc) ;
731
                if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
732
                        smc->os.hwm.rx_break = 0 ;
733
                        process_receive(smc) ;
734
                }
735
                else {
736
                        smc->os.hwm.detec_count = 0 ;
737
                        smt_force_irq(smc) ;
738
                }
739
        }
740
#endif
741
        smc->os.hwm.isr_flag = TRUE ;
742
 
743
#ifdef  USE_BREAK_ISR
744
        force_irq = TRUE ;
745
        if (smc->os.hwm.leave_isr) {
746
                smc->os.hwm.leave_isr = FALSE ;
747
                process_receive(smc) ;
748
        }
749
#endif
750
 
751
        while ((is = GET_ISR() & ISR_MASK)) {
752
                NDD_TRACE("CH0B",is,0,0) ;
753
                DB_GEN("ISA = 0x%x",is,0,7) ;
754
 
755
                if (is & IMASK_SLOW) {
756
                        NDD_TRACE("CH1b",is,0,0) ;
757
                        if (is & IS_PLINT1) {   /* PLC1 */
758
                                plc1_irq(smc) ;
759
                        }
760
                        if (is & IS_PLINT2) {   /* PLC2 */
761
                                plc2_irq(smc) ;
762
                        }
763
                        if (is & IS_MINTR1) {   /* FORMAC+ STU1(U/L) */
764
                                stu = inpw(FM_A(FM_ST1U)) ;
765
                                stl = inpw(FM_A(FM_ST1L)) ;
766
                                DB_GEN("Slow transmit complete",0,0,6) ;
767
                                mac1_irq(smc,stu,stl) ;
768
                        }
769
                        if (is & IS_MINTR2) {   /* FORMAC+ STU2(U/L) */
770
                                stu= inpw(FM_A(FM_ST2U)) ;
771
                                stl= inpw(FM_A(FM_ST2L)) ;
772
                                DB_GEN("Slow receive complete",0,0,6) ;
773
                                DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
774
                                mac2_irq(smc,stu,stl) ;
775
                        }
776
                        if (is & IS_MINTR3) {   /* FORMAC+ STU3(U/L) */
777
                                stu= inpw(FM_A(FM_ST3U)) ;
778
                                stl= inpw(FM_A(FM_ST3L)) ;
779
                                DB_GEN("FORMAC Mode Register 3",0,0,6) ;
780
                                mac3_irq(smc,stu,stl) ;
781
                        }
782
                        if (is & IS_TIMINT) {   /* Timer 82C54-2 */
783
                                timer_irq(smc) ;
784
#ifdef  NDIS_OS2
785
                                force_irq_pending = 0 ;
786
#endif
787
                                /*
788
                                 * out of RxD detection
789
                                 */
790
                                if (++smc->os.hwm.detec_count > 4) {
791
                                        /*
792
                                         * check out of RxD condition
793
                                         */
794
                                         process_receive(smc) ;
795
                                }
796
                        }
797
                        if (is & IS_TOKEN) {    /* Restricted Token Monitor */
798
                                rtm_irq(smc) ;
799
                        }
800
                        if (is & IS_R1_P) {     /* Parity error rx queue 1 */
801
                                /* clear IRQ */
802
                                outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
803
                                SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
804
                        }
805
                        if (is & IS_R1_C) {     /* Encoding error rx queue 1 */
806
                                /* clear IRQ */
807
                                outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
808
                                SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
809
                        }
810
                        if (is & IS_XA_C) {     /* Encoding error async tx q */
811
                                /* clear IRQ */
812
                                outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
813
                                SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
814
                        }
815
                        if (is & IS_XS_C) {     /* Encoding error sync tx q */
816
                                /* clear IRQ */
817
                                outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
818
                                SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
819
                        }
820
                }
821
 
822
                /*
823
                 *      Fast Tx complete Async/Sync Queue (BMU service)
824
                 */
825
                if (is & (IS_XS_F|IS_XA_F)) {
826
                        DB_GEN("Fast tx complete queue",0,0,6) ;
827
                        /*
828
                         * clear IRQ, Note: no IRQ is lost, because
829
                         *      we always service both queues
830
                         */
831
                        outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
832
                        outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
833
                        mac_drv_clear_txd(smc) ;
834
                        llc_restart_tx(smc) ;
835
                }
836
 
837
                /*
838
                 *      Fast Rx Complete (BMU service)
839
                 */
840
                if (is & IS_R1_F) {
841
                        DB_GEN("Fast receive complete",0,0,6) ;
842
                        /* clear IRQ */
843
#ifndef USE_BREAK_ISR
844
                        outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
845
                        process_receive(smc) ;
846
#else
847
                        process_receive(smc) ;
848
                        if (smc->os.hwm.leave_isr) {
849
                                force_irq = FALSE ;
850
                        } else {
851
                                outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
852
                                process_receive(smc) ;
853
                        }
854
#endif
855
                }
856
 
857
#ifndef NDIS_OS2
858
                while ((mb = get_llc_rx(smc))) {
859
                        smt_to_llc(smc,mb) ;
860
                }
861
#else
862
                if (offDepth)
863
                        post_proc() ;
864
 
865
                while (!offDepth && (mb = get_llc_rx(smc))) {
866
                        smt_to_llc(smc,mb) ;
867
                }
868
 
869
                if (!offDepth && smc->os.hwm.rx_break) {
870
                        process_receive(smc) ;
871
                }
872
#endif
873
                if (smc->q.ev_get != smc->q.ev_put) {
874
                        NDD_TRACE("CH2a",0,0,0) ;
875
                        ev_dispatcher(smc) ;
876
                }
877
#ifdef  NDIS_OS2
878
                post_proc() ;
879
                if (offDepth) {         /* leave fddi_isr because */
880
                        break ;         /* indications not allowed */
881
                }
882
#endif
883
#ifdef  USE_BREAK_ISR
884
                if (smc->os.hwm.leave_isr) {
885
                        break ;         /* leave fddi_isr */
886
                }
887
#endif
888
 
889
                /* NOTE: when the isr is left, no rx is pending */
890
        }       /* end of interrupt source polling loop */
891
 
892
#ifdef  USE_BREAK_ISR
893
        if (smc->os.hwm.leave_isr && force_irq) {
894
                smt_force_irq(smc) ;
895
        }
896
#endif
897
        smc->os.hwm.isr_flag = FALSE ;
898
        NDD_TRACE("CH0E",0,0,0) ;
899
}
900
 
901
 
902
/*
903
        -------------------------------------------------------------
904
        RECEIVE FUNCTIONS:
905
        -------------------------------------------------------------
906
*/
907
 
908
#ifndef NDIS_OS2
909
/*
910
 *      BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)
911
 *      void mac_drv_rx_mode(smc,mode)
912
 *
913
 * function     DOWNCALL        (fplus.c)
914
 *              Corresponding to the parameter mode, the operating system
915
 *              dependent module can activate several receive modes.
916
 *
917
 * para mode    = 1:    RX_ENABLE_ALLMULTI      enable all multicasts
918
 *              = 2:    RX_DISABLE_ALLMULTI     disable "enable all multicasts"
919
 *              = 3:    RX_ENABLE_PROMISC       enable promiscuous
920
 *              = 4:    RX_DISABLE_PROMISC      disable promiscuous
921
 *              = 5:    RX_ENABLE_NSA           enable rec. of all NSA frames
922
 *                      (disabled after 'driver reset' & 'set station address')
923
 *              = 6:    RX_DISABLE_NSA          disable rec. of all NSA frames
924
 *
925
 *              = 21:   RX_ENABLE_PASS_SMT      ( see description )
926
 *              = 22:   RX_DISABLE_PASS_SMT     (  "       "      )
927
 *              = 23:   RX_ENABLE_PASS_NSA      (  "       "      )
928
 *              = 24:   RX_DISABLE_PASS_NSA     (  "       "      )
929
 *              = 25:   RX_ENABLE_PASS_DB       (  "       "      )
930
 *              = 26:   RX_DISABLE_PASS_DB      (  "       "      )
931
 *              = 27:   RX_DISABLE_PASS_ALL     (  "       "      )
932
 *              = 28:   RX_DISABLE_LLC_PROMISC  (  "       "      )
933
 *              = 29:   RX_ENABLE_LLC_PROMISC   (  "       "      )
934
 *
935
 *
936
 *              RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT
937
 *
938
 *              If the operating system dependent module activates the
939
 *              mode RX_ENABLE_PASS_SMT, the hardware module
940
 *              duplicates all SMT frames with the frame control
941
 *              FC_SMT_INFO and passes them to the LLC receive channel
942
 *              by calling mac_drv_rx_init.
943
 *              The SMT Frames which are sent by the local SMT and the NSA
944
 *              frames whose A- and C-Indicator is not set are also duplicated
945
 *              and passed.
946
 *              The receive mode RX_DISABLE_PASS_SMT disables the passing
947
 *              of SMT frames.
948
 *
949
 *              RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA
950
 *
951
 *              If the operating system dependent module activates the
952
 *              mode RX_ENABLE_PASS_NSA, the hardware module
953
 *              duplicates all NSA frames with frame control FC_SMT_NSA
954
 *              and a set A-Indicator and passed them to the LLC
955
 *              receive channel by calling mac_drv_rx_init.
956
 *              All NSA Frames which are sent by the local SMT
957
 *              are also duplicated and passed.
958
 *              The receive mode RX_DISABLE_PASS_NSA disables the passing
959
 *              of NSA frames with the A- or C-Indicator set.
960
 *
961
 * NOTE:        For fear that the hardware module receives NSA frames with
962
 *              a reset A-Indicator, the operating system dependent module
963
 *              has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA
964
 *              before activate the RX_ENABLE_PASS_NSA mode and after every
965
 *              'driver reset' and 'set station address'.
966
 *
967
 *              RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB
968
 *
969
 *              If the operating system dependent module activates the
970
 *              mode RX_ENABLE_PASS_DB, direct BEACON frames
971
 *              (FC_BEACON frame control) are passed to the LLC receive
972
 *              channel by mac_drv_rx_init.
973
 *              The receive mode RX_DISABLE_PASS_DB disables the passing
974
 *              of direct BEACON frames.
975
 *
976
 *              RX_DISABLE_PASS_ALL
977
 *
978
 *              Disables all special receives modes. It is equal to
979
 *              call mac_drv_set_rx_mode successively with the
980
 *              parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,
981
 *              RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.
982
 *
983
 *              RX_ENABLE_LLC_PROMISC
984
 *
985
 *              (default) all received LLC frames and all SMT/NSA/DBEACON
986
 *              frames depending on the attitude of the flags
987
 *              PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the
988
 *              LLC layer
989
 *
990
 *              RX_DISABLE_LLC_PROMISC
991
 *
992
 *              all received SMT/NSA/DBEACON frames depending on the
993
 *              attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON
994
 *              will be delivered to the LLC layer.
995
 *              all received LLC frames with a directed address, Multicast
996
 *              or Broadcast address will be delivered to the LLC
997
 *              layer too.
998
 *
999
 *      END_MANUAL_ENTRY
1000
 */
1001
void mac_drv_rx_mode(struct s_smc *smc, int mode)
1002
{
1003
        switch(mode) {
1004
        case RX_ENABLE_PASS_SMT:
1005
                smc->os.hwm.pass_SMT = TRUE ;
1006
                break ;
1007
        case RX_DISABLE_PASS_SMT:
1008
                smc->os.hwm.pass_SMT = FALSE ;
1009
                break ;
1010
        case RX_ENABLE_PASS_NSA:
1011
                smc->os.hwm.pass_NSA = TRUE ;
1012
                break ;
1013
        case RX_DISABLE_PASS_NSA:
1014
                smc->os.hwm.pass_NSA = FALSE ;
1015
                break ;
1016
        case RX_ENABLE_PASS_DB:
1017
                smc->os.hwm.pass_DB = TRUE ;
1018
                break ;
1019
        case RX_DISABLE_PASS_DB:
1020
                smc->os.hwm.pass_DB = FALSE ;
1021
                break ;
1022
        case RX_DISABLE_PASS_ALL:
1023
                smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
1024
                smc->os.hwm.pass_DB = FALSE ;
1025
                smc->os.hwm.pass_llc_promisc = TRUE ;
1026
                mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
1027
                break ;
1028
        case RX_DISABLE_LLC_PROMISC:
1029
                smc->os.hwm.pass_llc_promisc = FALSE ;
1030
                break ;
1031
        case RX_ENABLE_LLC_PROMISC:
1032
                smc->os.hwm.pass_llc_promisc = TRUE ;
1033
                break ;
1034
        case RX_ENABLE_ALLMULTI:
1035
        case RX_DISABLE_ALLMULTI:
1036
        case RX_ENABLE_PROMISC:
1037
        case RX_DISABLE_PROMISC:
1038
        case RX_ENABLE_NSA:
1039
        case RX_DISABLE_NSA:
1040
        default:
1041
                mac_set_rx_mode(smc,mode) ;
1042
                break ;
1043
        }
1044
}
1045
#endif  /* ifndef NDIS_OS2 */
1046
 
1047
/*
1048
 * process receive queue
1049
 */
1050
void process_receive(struct s_smc *smc)
1051
{
1052
        int i ;
1053
        int n ;
1054
        int frag_count ;                /* number of RxDs of the curr rx buf */
1055
        int used_frags ;                /* number of RxDs of the curr frame */
1056
        struct s_smt_rx_queue *queue ;  /* points to the queue ctl struct */
1057
        struct s_smt_fp_rxd volatile *r ;       /* rxd pointer */
1058
        struct s_smt_fp_rxd volatile *rxd ;     /* first rxd of rx frame */
1059
        u_long rbctrl ;                 /* receive buffer control word */
1060
        u_long rfsw ;                   /* receive frame status word */
1061
        u_short rx_used ;
1062
        u_char far *virt ;
1063
        char far *data ;
1064
        SMbuf *mb ;
1065
        u_char fc ;                     /* Frame control */
1066
        int len ;                       /* Frame length */
1067
 
1068
        smc->os.hwm.detec_count = 0 ;
1069
        queue = smc->hw.fp.rx[QUEUE_R1] ;
1070
        NDD_TRACE("RHxB",0,0,0) ;
1071
        for ( ; ; ) {
1072
                r = queue->rx_curr_get ;
1073
                rx_used = queue->rx_used ;
1074
                frag_count = 0 ;
1075
 
1076
#ifdef  USE_BREAK_ISR
1077
                if (smc->os.hwm.leave_isr) {
1078
                        goto rx_end ;
1079
                }
1080
#endif
1081
#ifdef  NDIS_OS2
1082
                if (offDepth) {
1083
                        smc->os.hwm.rx_break = 1 ;
1084
                        goto rx_end ;
1085
                }
1086
                smc->os.hwm.rx_break = 0 ;
1087
#endif
1088
#ifdef  ODI2
1089
                if (smc->os.hwm.rx_break) {
1090
                        goto rx_end ;
1091
                }
1092
#endif
1093
                n = 0 ;
1094
                do {
1095
                        DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
1096
                        DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1097
                        rbctrl = CR_READ(r->rxd_rbctrl) ;
1098
                        rbctrl = AIX_REVERSE(rbctrl) ;
1099
 
1100
                        if (rbctrl & BMU_OWN) {
1101
                                NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
1102
                                DB_RX("End of RxDs",0,0,4) ;
1103
                                goto rx_end ;
1104
                        }
1105
                        /*
1106
                         * out of RxD detection
1107
                         */
1108
                        if (!rx_used) {
1109
                                SK_BREAK() ;
1110
                                SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
1111
                                /* Either we don't have an RxD or all
1112
                                 * RxDs are filled. Therefore it's allowed
1113
                                 * for to set the STOPPED flag */
1114
                                smc->hw.hw_state = STOPPED ;
1115
                                mac_drv_clear_rx_queue(smc) ;
1116
                                smc->hw.hw_state = STARTED ;
1117
                                mac_drv_fill_rxd(smc) ;
1118
                                smc->os.hwm.detec_count = 0 ;
1119
                                goto rx_end ;
1120
                        }
1121
                        rfsw = AIX_REVERSE(r->rxd_rfsw) ;
1122
                        if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
1123
                                /*
1124
                                 * The BMU_STF bit is deleted, 1 frame is
1125
                                 * placed into more than 1 rx buffer
1126
                                 *
1127
                                 * skip frame by setting the rx len to 0
1128
                                 *
1129
                                 * if fragment count == 0
1130
                                 *      The missing STF bit belongs to the
1131
                                 *      current frame, search for the
1132
                                 *      EOF bit to complete the frame
1133
                                 * else
1134
                                 *      the fragment belongs to the next frame,
1135
                                 *      exit the loop and process the frame
1136
                                 */
1137
                                SK_BREAK() ;
1138
                                rfsw = 0 ;
1139
                                if (frag_count) {
1140
                                        break ;
1141
                                }
1142
                        }
1143
                        n += rbctrl & 0xffff ;
1144
                        r = r->rxd_next ;
1145
                        frag_count++ ;
1146
                        rx_used-- ;
1147
                } while (!(rbctrl & BMU_EOF)) ;
1148
                used_frags = frag_count ;
1149
                DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;
1150
 
1151
                /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
1152
                /* BMU_ST_BUF will not be changed by the ASIC */
1153
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1154
                while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
1155
                        DB_RX("Check STF bit in %x",(void *)r,0,5) ;
1156
                        r = r->rxd_next ;
1157
                        DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1158
                        frag_count++ ;
1159
                        rx_used-- ;
1160
                }
1161
                DB_RX("STF bit found",0,0,5) ;
1162
 
1163
                /*
1164
                 * The received frame is finished for the process receive
1165
                 */
1166
                rxd = queue->rx_curr_get ;
1167
                queue->rx_curr_get = r ;
1168
                queue->rx_free += frag_count ;
1169
                queue->rx_used = rx_used ;
1170
 
1171
                /*
1172
                 * ASIC Errata no. 7 (STF - Bit Bug)
1173
                 */
1174
                rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;
1175
 
1176
                for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
1177
                        DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
1178
                        dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
1179
                }
1180
                smc->hw.fp.err_stats.err_valid++ ;
1181
                smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
1182
 
1183
                /* the length of the data including the FC */
1184
                len = (rfsw & RD_LENGTH) - 4 ;
1185
 
1186
                DB_RX("frame length = %d",len,0,4) ;
1187
                /*
1188
                 * check the frame_lenght and all error flags
1189
                 */
1190
                if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
1191
                        if (rfsw & RD_S_MSRABT) {
1192
                                DB_RX("Frame aborted by the FORMAC",0,0,2) ;
1193
                                smc->hw.fp.err_stats.err_abort++ ;
1194
                        }
1195
                        /*
1196
                         * check frame status
1197
                         */
1198
                        if (rfsw & RD_S_SEAC2) {
1199
                                DB_RX("E-Indicator set",0,0,2) ;
1200
                                smc->hw.fp.err_stats.err_e_indicator++ ;
1201
                        }
1202
                        if (rfsw & RD_S_SFRMERR) {
1203
                                DB_RX("CRC error",0,0,2) ;
1204
                                smc->hw.fp.err_stats.err_crc++ ;
1205
                        }
1206
                        if (rfsw & RX_FS_IMPL) {
1207
                                DB_RX("Implementer frame",0,0,2) ;
1208
                                smc->hw.fp.err_stats.err_imp_frame++ ;
1209
                        }
1210
                        goto abort_frame ;
1211
                }
1212
                if (len > FDDI_RAW_MTU-4) {
1213
                        DB_RX("Frame too long error",0,0,2) ;
1214
                        smc->hw.fp.err_stats.err_too_long++ ;
1215
                        goto abort_frame ;
1216
                }
1217
                /*
1218
                 * SUPERNET 3 Bug: FORMAC delivers status words
1219
                 * of aborded frames to the BMU
1220
                 */
1221
                if (len <= 4) {
1222
                        DB_RX("Frame length = 0",0,0,2) ;
1223
                        goto abort_frame ;
1224
                }
1225
 
1226
                if (len != (n-4)) {
1227
                        DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
1228
                        smc->os.hwm.rx_len_error++ ;
1229
                        goto abort_frame ;
1230
                }
1231
 
1232
                /*
1233
                 * Check SA == MA
1234
                 */
1235
                virt = (u_char far *) rxd->rxd_virt ;
1236
                DB_RX("FC = %x",*virt,0,2) ;
1237
                if (virt[12] == MA[5] &&
1238
                    virt[11] == MA[4] &&
1239
                    virt[10] == MA[3] &&
1240
                    virt[9] == MA[2] &&
1241
                    virt[8] == MA[1] &&
1242
                    (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
1243
                        goto abort_frame ;
1244
                }
1245
 
1246
                /*
1247
                 * test if LLC frame
1248
                 */
1249
                if (rfsw & RX_FS_LLC) {
1250
                        /*
1251
                         * if pass_llc_promisc is disable
1252
                         *      if DA != Multicast or Broadcast or DA!=MA
1253
                         *              abort the frame
1254
                         */
1255
                        if (!smc->os.hwm.pass_llc_promisc) {
1256
                                if(!(virt[1] & GROUP_ADDR_BIT)) {
1257
                                        if (virt[6] != MA[5] ||
1258
                                            virt[5] != MA[4] ||
1259
                                            virt[4] != MA[3] ||
1260
                                            virt[3] != MA[2] ||
1261
                                            virt[2] != MA[1] ||
1262
                                            virt[1] != MA[0]) {
1263
                                                DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
1264
                                                goto abort_frame ;
1265
                                        }
1266
                                }
1267
                        }
1268
 
1269
                        /*
1270
                         * LLC frame received
1271
                         */
1272
                        DB_RX("LLC - receive",0,0,4) ;
1273
                        mac_drv_rx_complete(smc,rxd,frag_count,len) ;
1274
                }
1275
                else {
1276
                        if (!(mb = smt_get_mbuf(smc))) {
1277
                                smc->hw.fp.err_stats.err_no_buf++ ;
1278
                                DB_RX("No SMbuf; receive terminated",0,0,4) ;
1279
                                goto abort_frame ;
1280
                        }
1281
                        data = smtod(mb,char *) - 1 ;
1282
 
1283
                        /*
1284
                         * copy the frame into a SMT_MBuf
1285
                         */
1286
#ifdef USE_OS_CPY
1287
                        hwm_cpy_rxd2mb(rxd,data,len) ;
1288
#else
1289
                        for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
1290
                                n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;
1291
                                DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
1292
                                memcpy(data,r->rxd_virt,n) ;
1293
                                data += n ;
1294
                        }
1295
                        data = smtod(mb,char *) - 1 ;
1296
#endif
1297
                        fc = *(char *)mb->sm_data = *data ;
1298
                        mb->sm_len = len - 1 ;          /* len - fc */
1299
                        data++ ;
1300
 
1301
                        /*
1302
                         * SMT frame received
1303
                         */
1304
                        switch(fc) {
1305
                        case FC_SMT_INFO :
1306
                                smc->hw.fp.err_stats.err_smt_frame++ ;
1307
                                DB_RX("SMT frame received ",0,0,5) ;
1308
 
1309
                                if (smc->os.hwm.pass_SMT) {
1310
                                        DB_RX("pass SMT frame ",0,0,5) ;
1311
                                        mac_drv_rx_complete(smc, rxd,
1312
                                                frag_count,len) ;
1313
                                }
1314
                                else {
1315
                                        DB_RX("requeue RxD",0,0,5) ;
1316
                                        mac_drv_requeue_rxd(smc,rxd,frag_count);
1317
                                }
1318
 
1319
                                smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
1320
                                break ;
1321
                        case FC_SMT_NSA :
1322
                                smc->hw.fp.err_stats.err_smt_frame++ ;
1323
                                DB_RX("SMT frame received ",0,0,5) ;
1324
 
1325
                                /* if pass_NSA set pass the NSA frame or */
1326
                                /* pass_SMT set and the A-Indicator */
1327
                                /* is not set, pass the NSA frame */
1328
                                if (smc->os.hwm.pass_NSA ||
1329
                                        (smc->os.hwm.pass_SMT &&
1330
                                        !(rfsw & A_INDIC))) {
1331
                                        DB_RX("pass SMT frame ",0,0,5) ;
1332
                                        mac_drv_rx_complete(smc, rxd,
1333
                                                frag_count,len) ;
1334
                                }
1335
                                else {
1336
                                        DB_RX("requeue RxD",0,0,5) ;
1337
                                        mac_drv_requeue_rxd(smc,rxd,frag_count);
1338
                                }
1339
 
1340
                                smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
1341
                                break ;
1342
                        case FC_BEACON :
1343
                                if (smc->os.hwm.pass_DB) {
1344
                                        DB_RX("pass DB frame ",0,0,5) ;
1345
                                        mac_drv_rx_complete(smc, rxd,
1346
                                                frag_count,len) ;
1347
                                }
1348
                                else {
1349
                                        DB_RX("requeue RxD",0,0,5) ;
1350
                                        mac_drv_requeue_rxd(smc,rxd,frag_count);
1351
                                }
1352
                                smt_free_mbuf(smc,mb) ;
1353
                                break ;
1354
                        default :
1355
                                /*
1356
                                 * unknown FC abord the frame
1357
                                 */
1358
                                DB_RX("unknown FC error",0,0,2) ;
1359
                                smt_free_mbuf(smc,mb) ;
1360
                                DB_RX("requeue RxD",0,0,5) ;
1361
                                mac_drv_requeue_rxd(smc,rxd,frag_count) ;
1362
                                if ((fc & 0xf0) == FC_MAC)
1363
                                        smc->hw.fp.err_stats.err_mac_frame++ ;
1364
                                else
1365
                                        smc->hw.fp.err_stats.err_imp_frame++ ;
1366
 
1367
                                break ;
1368
                        }
1369
                }
1370
 
1371
                DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
1372
                NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
1373
 
1374
                continue ;
1375
        /*--------------------------------------------------------------------*/
1376
abort_frame:
1377
                DB_RX("requeue RxD",0,0,5) ;
1378
                mac_drv_requeue_rxd(smc,rxd,frag_count) ;
1379
 
1380
                DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
1381
                NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
1382
        }
1383
rx_end:
1384
#ifdef  ALL_RX_COMPLETE
1385
        mac_drv_all_receives_complete(smc) ;
1386
#endif
1387
        return ;        /* lint bug: needs return detect end of function */
1388
}
1389
 
1390
static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
1391
{
1392
        u_char  fc ;
1393
 
1394
        DB_RX("send a queued frame to the llc layer",0,0,4) ;
1395
        smc->os.hwm.r.len = mb->sm_len ;
1396
        smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
1397
        fc = *smc->os.hwm.r.mb_pos ;
1398
        (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
1399
                smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
1400
        smt_free_mbuf(smc,mb) ;
1401
}
1402
 
1403
/*
1404
 *      BEGIN_MANUAL_ENTRY(hwm_rx_frag)
1405
 *      void hwm_rx_frag(smc,virt,phys,len,frame_status)
1406
 *
1407
 * function     MACRO           (hardware module, hwmtm.h)
1408
 *              This function calls dma_master for preparing the
1409
 *              system hardware for the DMA transfer and initializes
1410
 *              the current RxD with the length and the physical and
1411
 *              virtual address of the fragment. Furthermore, it sets the
1412
 *              STF and EOF bits depending on the frame status byte,
1413
 *              switches the OWN flag of the RxD, so that it is owned by the
1414
 *              adapter and issues an rx_start.
1415
 *
1416
 * para virt    virtual pointer to the fragment
1417
 *      len     the length of the fragment
1418
 *      frame_status    status of the frame, see design description
1419
 *
1420
 * NOTE:        It is possible to call this function with a fragment length
1421
 *              of zero.
1422
 *
1423
 *      END_MANUAL_ENTRY
1424
 */
1425
void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
1426
                 int frame_status)
1427
{
1428
        struct s_smt_fp_rxd volatile *r ;
1429
        u_int   rbctrl ;
1430
 
1431
        NDD_TRACE("RHfB",virt,len,frame_status) ;
1432
        DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
1433
        r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
1434
        r->rxd_virt = virt ;
1435
        r->rxd_rbadr = AIX_REVERSE(phys) ;
1436
        rbctrl = AIX_REVERSE( (((u_long)frame_status &
1437
                (FIRST_FRAG|LAST_FRAG))<<26) |
1438
                (((u_long) frame_status & FIRST_FRAG) << 21) |
1439
                BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
1440
        r->rxd_rbctrl = rbctrl ;
1441
 
1442
        DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1443
        outpd(ADDR(B0_R1_CSR),CSR_START) ;
1444
        smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
1445
        smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
1446
        smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
1447
        NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
1448
}
1449
 
1450
/*
1451
 *      BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
1452
 *
1453
 * void mac_drv_clear_rx_queue(smc)
1454
 * struct s_smc *smc ;
1455
 *
1456
 * function     DOWNCALL        (hardware module, hwmtm.c)
1457
 *              mac_drv_clear_rx_queue is called by the OS-specific module
1458
 *              after it has issued a card_stop.
1459
 *              In this case, the frames in the receive queue are obsolete and
1460
 *              should be removed. For removing mac_drv_clear_rx_queue
1461
 *              calls dma_master for each RxD and mac_drv_clear_rxd for each
1462
 *              receive buffer.
1463
 *
1464
 * NOTE:        calling sequence card_stop:
1465
 *              CLI_FBI(), card_stop(),
1466
 *              mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
1467
 *
1468
 * NOTE:        The caller is responsible that the BMUs are idle
1469
 *              when this function is called.
1470
 *
1471
 *      END_MANUAL_ENTRY
1472
 */
1473
void mac_drv_clear_rx_queue(struct s_smc *smc)
1474
{
1475
        struct s_smt_fp_rxd volatile *r ;
1476
        struct s_smt_fp_rxd volatile *next_rxd ;
1477
        struct s_smt_rx_queue *queue ;
1478
        int frag_count ;
1479
        int i ;
1480
 
1481
        if (smc->hw.hw_state != STOPPED) {
1482
                SK_BREAK() ;
1483
                SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
1484
                return ;
1485
        }
1486
 
1487
        queue = smc->hw.fp.rx[QUEUE_R1] ;
1488
        DB_RX("clear_rx_queue",0,0,5) ;
1489
 
1490
        /*
1491
         * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers
1492
         */
1493
        r = queue->rx_curr_get ;
1494
        while (queue->rx_used) {
1495
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1496
                DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
1497
                r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
1498
                frag_count = 1 ;
1499
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1500
                r = r->rxd_next ;
1501
                DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1502
                while (r != queue->rx_curr_put &&
1503
                        !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
1504
                        DB_RX("Check STF bit in %x",(void *)r,0,5) ;
1505
                        r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
1506
                        DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1507
                        r = r->rxd_next ;
1508
                        DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1509
                        frag_count++ ;
1510
                }
1511
                DB_RX("STF bit found",0,0,5) ;
1512
                next_rxd = r ;
1513
 
1514
                for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
1515
                        DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
1516
                        dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
1517
                }
1518
 
1519
                DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",
1520
                        (void *)queue->rx_curr_get,frag_count,5) ;
1521
                mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
1522
 
1523
                queue->rx_curr_get = next_rxd ;
1524
                queue->rx_used -= frag_count ;
1525
                queue->rx_free += frag_count ;
1526
        }
1527
}
1528
 
1529
 
1530
/*
1531
        -------------------------------------------------------------
1532
        SEND FUNCTIONS:
1533
        -------------------------------------------------------------
1534
*/
1535
 
1536
/*
1537
 *      BEGIN_MANUAL_ENTRY(hwm_tx_init)
1538
 *      int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
1539
 *
1540
 * function     DOWN_CALL       (hardware module, hwmtm.c)
1541
 *              hwm_tx_init checks if the frame can be sent through the
1542
 *              corresponding send queue.
1543
 *
1544
 * para fc      the frame control. To determine through which
1545
 *              send queue the frame should be transmitted.
1546
 *              0x50 - 0x57:    asynchronous LLC frame
1547
 *              0xD0 - 0xD7:    synchronous LLC frame
1548
 *              0x41, 0x4F:     SMT frame to the network
1549
 *              0x42:           SMT frame to the network and to the local SMT
1550
 *              0x43:           SMT frame to the local SMT
1551
 *      frag_count      count of the fragments for this frame
1552
 *      frame_len       length of the frame
1553
 *      frame_status    status of the frame, the send queue bit is already
1554
 *                      specified
1555
 *
1556
 * return               frame_status
1557
 *
1558
 *      END_MANUAL_ENTRY
1559
 */
1560
int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
1561
                int frame_status)
1562
{
1563
        NDD_TRACE("THiB",fc,frag_count,frame_len) ;
1564
        smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
1565
        smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
1566
        smc->os.hwm.tx_len = frame_len ;
1567
        DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;
1568
        if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
1569
                frame_status |= LAN_TX ;
1570
        }
1571
        else {
1572
                switch (fc) {
1573
                case FC_SMT_INFO :
1574
                case FC_SMT_NSA :
1575
                        frame_status |= LAN_TX ;
1576
                        break ;
1577
                case FC_SMT_LOC :
1578
                        frame_status |= LOC_TX ;
1579
                        break ;
1580
                case FC_SMT_LAN_LOC :
1581
                        frame_status |= LAN_TX | LOC_TX ;
1582
                        break ;
1583
                default :
1584
                        SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
1585
                }
1586
        }
1587
        if (!smc->hw.mac_ring_is_up) {
1588
                frame_status &= ~LAN_TX ;
1589
                frame_status |= RING_DOWN ;
1590
                DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
1591
        }
1592
        if (frag_count > smc->os.hwm.tx_p->tx_free) {
1593
#ifndef NDIS_OS2
1594
                mac_drv_clear_txd(smc) ;
1595
                if (frag_count > smc->os.hwm.tx_p->tx_free) {
1596
                        DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
1597
                        frame_status &= ~LAN_TX ;
1598
                        frame_status |= OUT_OF_TXD ;
1599
                }
1600
#else
1601
                DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
1602
                frame_status &= ~LAN_TX ;
1603
                frame_status |= OUT_OF_TXD ;
1604
#endif
1605
        }
1606
        DB_TX("frame_status = %x",frame_status,0,3) ;
1607
        NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
1608
        return(frame_status) ;
1609
}
1610
 
1611
/*
1612
 *      BEGIN_MANUAL_ENTRY(hwm_tx_frag)
1613
 *      void hwm_tx_frag(smc,virt,phys,len,frame_status)
1614
 *
1615
 * function     DOWNCALL        (hardware module, hwmtm.c)
1616
 *              If the frame should be sent to the LAN, this function calls
1617
 *              dma_master, fills the current TxD with the virtual and the
1618
 *              physical address, sets the STF and EOF bits dependent on
1619
 *              the frame status, and requests the BMU to start the
1620
 *              transmit.
1621
 *              If the frame should be sent to the local SMT, an SMT_MBuf
1622
 *              is allocated if the FIRST_FRAG bit is set in the frame_status.
1623
 *              The fragment of the frame is copied into the SMT MBuf.
1624
 *              The function smt_received_pack is called if the LAST_FRAG
1625
 *              bit is set in the frame_status word.
1626
 *
1627
 * para virt    virtual pointer to the fragment
1628
 *      len     the length of the fragment
1629
 *      frame_status    status of the frame, see design description
1630
 *
1631
 * return       nothing returned, no parameter is modified
1632
 *
1633
 * NOTE:        It is possible to invoke this macro with a fragment length
1634
 *              of zero.
1635
 *
1636
 *      END_MANUAL_ENTRY
1637
 */
1638
void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
1639
                 int frame_status)
1640
{
1641
        struct s_smt_fp_txd volatile *t ;
1642
        struct s_smt_tx_queue *queue ;
1643
        u_int   tbctrl ;
1644
 
1645
        queue = smc->os.hwm.tx_p ;
1646
 
1647
        NDD_TRACE("THfB",virt,len,frame_status) ;
1648
        /* Bug fix: AF / May 31 1999 (#missing)
1649
         * snmpinfo problem reported by IBM is caused by invalid
1650
         * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
1651
         * Set: t = queue->tx_curr_put  here !
1652
         */
1653
        t = queue->tx_curr_put ;
1654
 
1655
        DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
1656
        if (frame_status & LAN_TX) {
1657
                /* '*t' is already defined */
1658
                DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
1659
                t->txd_virt = virt ;
1660
                t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ;
1661
                t->txd_tbadr = AIX_REVERSE(phys) ;
1662
                tbctrl = AIX_REVERSE((((u_long)frame_status &
1663
                        (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
1664
                        BMU_OWN|BMU_CHECK |len) ;
1665
                t->txd_tbctrl = tbctrl ;
1666
 
1667
#ifndef AIX
1668
                DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1669
                outpd(queue->tx_bmu_ctl,CSR_START) ;
1670
#else   /* ifndef AIX */
1671
                DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1672
                if (frame_status & QUEUE_A0) {
1673
                        outpd(ADDR(B0_XA_CSR),CSR_START) ;
1674
                }
1675
                else {
1676
                        outpd(ADDR(B0_XS_CSR),CSR_START) ;
1677
                }
1678
#endif
1679
                queue->tx_free-- ;
1680
                queue->tx_used++ ;
1681
                queue->tx_curr_put = t->txd_next ;
1682
                if (frame_status & LAST_FRAG) {
1683
                        smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
1684
                }
1685
        }
1686
        if (frame_status & LOC_TX) {
1687
                DB_TX("LOC_TX: ",0,0,3) ;
1688
                if (frame_status & FIRST_FRAG) {
1689
                        if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
1690
                                smc->hw.fp.err_stats.err_no_buf++ ;
1691
                                DB_TX("No SMbuf; transmit terminated",0,0,4) ;
1692
                        }
1693
                        else {
1694
                                smc->os.hwm.tx_data =
1695
                                        smtod(smc->os.hwm.tx_mb,char *) - 1 ;
1696
#ifdef USE_OS_CPY
1697
#ifdef PASS_1ST_TXD_2_TX_COMP
1698
                                hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
1699
                                        smc->os.hwm.tx_len) ;
1700
#endif
1701
#endif
1702
                        }
1703
                }
1704
                if (smc->os.hwm.tx_mb) {
1705
#ifndef USE_OS_CPY
1706
                        DB_TX("copy fragment into MBuf ",0,0,3) ;
1707
                        memcpy(smc->os.hwm.tx_data,virt,len) ;
1708
                        smc->os.hwm.tx_data += len ;
1709
#endif
1710
                        if (frame_status & LAST_FRAG) {
1711
#ifdef  USE_OS_CPY
1712
#ifndef PASS_1ST_TXD_2_TX_COMP
1713
                                /*
1714
                                 * hwm_cpy_txd2mb(txd,data,len) copies 'len'
1715
                                 * bytes from the virtual pointer in 'rxd'
1716
                                 * to 'data'. The virtual pointer of the
1717
                                 * os-specific tx-buffer should be written
1718
                                 * in the LAST txd.
1719
                                 */
1720
                                hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
1721
                                        smc->os.hwm.tx_len) ;
1722
#endif  /* nPASS_1ST_TXD_2_TX_COMP */
1723
#endif  /* USE_OS_CPY */
1724
                                smc->os.hwm.tx_data =
1725
                                        smtod(smc->os.hwm.tx_mb,char *) - 1 ;
1726
                                *(char *)smc->os.hwm.tx_mb->sm_data =
1727
                                        *smc->os.hwm.tx_data ;
1728
                                smc->os.hwm.tx_data++ ;
1729
                                smc->os.hwm.tx_mb->sm_len =
1730
                                        smc->os.hwm.tx_len - 1 ;
1731
                                DB_TX("pass LLC frame to SMT ",0,0,3) ;
1732
                                smt_received_pack(smc,smc->os.hwm.tx_mb,
1733
                                                RD_FS_LOCAL) ;
1734
                        }
1735
                }
1736
        }
1737
        NDD_TRACE("THfE",t,queue->tx_free,0) ;
1738
}
1739
 
1740
 
1741
/*
1742
 * queues a receive for later send
1743
 */
1744
static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
1745
{
1746
        DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
1747
        smc->os.hwm.queued_rx_frames++ ;
1748
        mb->sm_next = (SMbuf *)NULL ;
1749
        if (smc->os.hwm.llc_rx_pipe == 0) {
1750
                smc->os.hwm.llc_rx_pipe = mb ;
1751
        }
1752
        else {
1753
                smc->os.hwm.llc_rx_tail->sm_next = mb ;
1754
        }
1755
        smc->os.hwm.llc_rx_tail = mb ;
1756
 
1757
        /*
1758
         * force an timer IRQ to receive the data
1759
         */
1760
        if (!smc->os.hwm.isr_flag) {
1761
                smt_force_irq(smc) ;
1762
        }
1763
}
1764
 
1765
/*
1766
 * get a SMbuf from the llc_rx_queue
1767
 */
1768
static SMbuf *get_llc_rx(struct s_smc *smc)
1769
{
1770
        SMbuf   *mb ;
1771
 
1772
        if ((mb = smc->os.hwm.llc_rx_pipe)) {
1773
                smc->os.hwm.queued_rx_frames-- ;
1774
                smc->os.hwm.llc_rx_pipe = mb->sm_next ;
1775
        }
1776
        DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
1777
        return(mb) ;
1778
}
1779
 
1780
/*
1781
 * queues a transmit SMT MBuf during the time were the MBuf is
1782
 * queued the TxD ring
1783
 */
1784
static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
1785
{
1786
        DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
1787
        smc->os.hwm.queued_txd_mb++ ;
1788
        mb->sm_next = (SMbuf *)NULL ;
1789
        if (smc->os.hwm.txd_tx_pipe == 0) {
1790
                smc->os.hwm.txd_tx_pipe = mb ;
1791
        }
1792
        else {
1793
                smc->os.hwm.txd_tx_tail->sm_next = mb ;
1794
        }
1795
        smc->os.hwm.txd_tx_tail = mb ;
1796
}
1797
 
1798
/*
1799
 * get a SMbuf from the txd_tx_queue
1800
 */
1801
static SMbuf *get_txd_mb(struct s_smc *smc)
1802
{
1803
        SMbuf *mb ;
1804
 
1805
        if ((mb = smc->os.hwm.txd_tx_pipe)) {
1806
                smc->os.hwm.queued_txd_mb-- ;
1807
                smc->os.hwm.txd_tx_pipe = mb->sm_next ;
1808
        }
1809
        DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
1810
        return(mb) ;
1811
}
1812
 
1813
/*
1814
 *      SMT Send function
1815
 */
1816
void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
1817
{
1818
        char far *data ;
1819
        int     len ;
1820
        int     n ;
1821
        int     i ;
1822
        int     frag_count ;
1823
        int     frame_status ;
1824
        SK_LOC_DECL(char far,*virt[3]) ;
1825
        int     frag_len[3] ;
1826
        struct s_smt_tx_queue *queue ;
1827
        struct s_smt_fp_txd volatile *t ;
1828
        u_long  phys ;
1829
        u_int   tbctrl ;
1830
 
1831
        NDD_TRACE("THSB",mb,fc,0) ;
1832
        DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
1833
 
1834
        mb->sm_off-- ;  /* set to fc */
1835
        mb->sm_len++ ;  /* + fc */
1836
        data = smtod(mb,char *) ;
1837
        *data = fc ;
1838
        if (fc == FC_SMT_LOC)
1839
                *data = FC_SMT_INFO ;
1840
 
1841
        /*
1842
         * determine the frag count and the virt addresses of the frags
1843
         */
1844
        frag_count = 0 ;
1845
        len = mb->sm_len ;
1846
        while (len) {
1847
                n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;
1848
                if (n >= len) {
1849
                        n = len ;
1850
                }
1851
                DB_TX("frag: virt/len = 0x%x/%d ",(void *)data,n,5) ;
1852
                virt[frag_count] = data ;
1853
                frag_len[frag_count] = n ;
1854
                frag_count++ ;
1855
                len -= n ;
1856
                data += n ;
1857
        }
1858
 
1859
        /*
1860
         * determine the frame status
1861
         */
1862
        queue = smc->hw.fp.tx[QUEUE_A0] ;
1863
        if (fc == FC_BEACON || fc == FC_SMT_LOC) {
1864
                frame_status = LOC_TX ;
1865
        }
1866
        else {
1867
                frame_status = LAN_TX ;
1868
                if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
1869
                   (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
1870
                        frame_status |= LOC_TX ;
1871
        }
1872
 
1873
        if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
1874
                frame_status &= ~LAN_TX;
1875
                if (frame_status) {
1876
                        DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
1877
                }
1878
                else {
1879
                        DB_TX("Ring is down: terminate transmission",0,0,2) ;
1880
                        smt_free_mbuf(smc,mb) ;
1881
                        return ;
1882
                }
1883
        }
1884
        DB_TX("frame_status = 0x%x ",frame_status,0,5) ;
1885
 
1886
        if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
1887
                mb->sm_use_count = 2 ;
1888
        }
1889
 
1890
        if (frame_status & LAN_TX) {
1891
                t = queue->tx_curr_put ;
1892
                frame_status |= FIRST_FRAG ;
1893
                for (i = 0; i < frag_count; i++) {
1894
                        DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
1895
                        if (i == frag_count-1) {
1896
                                frame_status |= LAST_FRAG ;
1897
                                t->txd_txdscr = AIX_REVERSE(TX_DESCRIPTOR |
1898
                                        (((u_long)(mb->sm_len-1)&3) << 27)) ;
1899
                        }
1900
                        t->txd_virt = virt[i] ;
1901
                        phys = dma_master(smc, (void far *)virt[i],
1902
                                frag_len[i], DMA_RD|SMT_BUF) ;
1903
                        t->txd_tbadr = AIX_REVERSE(phys) ;
1904
                        tbctrl = AIX_REVERSE((((u_long) frame_status &
1905
                                (FIRST_FRAG|LAST_FRAG)) << 26) |
1906
                                BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
1907
                        t->txd_tbctrl = tbctrl ;
1908
#ifndef AIX
1909
                        DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1910
                        outpd(queue->tx_bmu_ctl,CSR_START) ;
1911
#else
1912
                        DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1913
                        outpd(ADDR(B0_XA_CSR),CSR_START) ;
1914
#endif
1915
                        frame_status &= ~FIRST_FRAG ;
1916
                        queue->tx_curr_put = t = t->txd_next ;
1917
                        queue->tx_free-- ;
1918
                        queue->tx_used++ ;
1919
                }
1920
                smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
1921
                queue_txd_mb(smc,mb) ;
1922
        }
1923
 
1924
        if (frame_status & LOC_TX) {
1925
                DB_TX("pass Mbuf to LLC queue",0,0,5) ;
1926
                queue_llc_rx(smc,mb) ;
1927
        }
1928
 
1929
        /*
1930
         * We need to unqueue the free SMT_MBUFs here, because it may
1931
         * be that the SMT want's to send more than 1 frame for one down call
1932
         */
1933
        mac_drv_clear_txd(smc) ;
1934
        NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
1935
}
1936
 
1937
/*      BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)
1938
 *      void mac_drv_clear_txd(smc)
1939
 *
1940
 * function     DOWNCALL        (hardware module, hwmtm.c)
1941
 *              mac_drv_clear_txd searches in both send queues for TxD's
1942
 *              which were finished by the adapter. It calls dma_complete
1943
 *              for each TxD. If the last fragment of an LLC frame is
1944
 *              reached, it calls mac_drv_tx_complete to release the
1945
 *              send buffer.
1946
 *
1947
 * return       nothing
1948
 *
1949
 *      END_MANUAL_ENTRY
1950
 */
1951
static void mac_drv_clear_txd(struct s_smc *smc)
1952
{
1953
        struct s_smt_tx_queue *queue ;
1954
        struct s_smt_fp_txd volatile *t1 ;
1955
        struct s_smt_fp_txd volatile *t2 = NULL ;
1956
        SMbuf *mb ;
1957
        u_long  tbctrl ;
1958
        int i ;
1959
        int frag_count ;
1960
        int n ;
1961
 
1962
        NDD_TRACE("THcB",0,0,0) ;
1963
        for (i = QUEUE_S; i <= QUEUE_A0; i++) {
1964
                queue = smc->hw.fp.tx[i] ;
1965
                t1 = queue->tx_curr_get ;
1966
                DB_TX("clear_txd: QUEUE = %d (0=sync/1=async)",i,0,5) ;
1967
 
1968
                for ( ; ; ) {
1969
                        frag_count = 0 ;
1970
 
1971
                        do {
1972
                                DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
1973
                                DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
1974
                                tbctrl = CR_READ(t1->txd_tbctrl) ;
1975
                                tbctrl = AIX_REVERSE(tbctrl) ;
1976
 
1977
                                if (tbctrl & BMU_OWN || !queue->tx_used){
1978
                                        DB_TX("End of TxDs queue %d",i,0,4) ;
1979
                                        goto free_next_queue ;  /* next queue */
1980
                                }
1981
                                t1 = t1->txd_next ;
1982
                                frag_count++ ;
1983
                        } while (!(tbctrl & BMU_EOF)) ;
1984
 
1985
                        t1 = queue->tx_curr_get ;
1986
                        for (n = frag_count; n; n--) {
1987
                                tbctrl = AIX_REVERSE(t1->txd_tbctrl) ;
1988
                                dma_complete(smc,
1989
                                        (union s_fp_descr volatile *) t1,
1990
                                        (int) (DMA_RD |
1991
                                        ((tbctrl & BMU_SMT_TX) >> 18))) ;
1992
                                t2 = t1 ;
1993
                                t1 = t1->txd_next ;
1994
                        }
1995
 
1996
                        if (tbctrl & BMU_SMT_TX) {
1997
                                mb = get_txd_mb(smc) ;
1998
                                smt_free_mbuf(smc,mb) ;
1999
                        }
2000
                        else {
2001
#ifndef PASS_1ST_TXD_2_TX_COMP
2002
                                DB_TX("mac_drv_tx_comp for TxD 0x%x",t2,0,4) ;
2003
                                mac_drv_tx_complete(smc,t2) ;
2004
#else
2005
                                DB_TX("mac_drv_tx_comp for TxD 0x%x",
2006
                                        queue->tx_curr_get,0,4) ;
2007
                                mac_drv_tx_complete(smc,queue->tx_curr_get) ;
2008
#endif
2009
                        }
2010
                        queue->tx_curr_get = t1 ;
2011
                        queue->tx_free += frag_count ;
2012
                        queue->tx_used -= frag_count ;
2013
                }
2014
free_next_queue: ;
2015
        }
2016
        NDD_TRACE("THcE",0,0,0) ;
2017
}
2018
 
2019
/*
2020
 *      BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)
2021
 *
2022
 * void mac_drv_clear_tx_queue(smc)
2023
 * struct s_smc *smc ;
2024
 *
2025
 * function     DOWNCALL        (hardware module, hwmtm.c)
2026
 *              mac_drv_clear_tx_queue is called from the SMT when
2027
 *              the RMT state machine has entered the ISOLATE state.
2028
 *              This function is also called by the os-specific module
2029
 *              after it has called the function card_stop().
2030
 *              In this case, the frames in the send queues are obsolete and
2031
 *              should be removed.
2032
 *
2033
 * note         calling sequence:
2034
 *              CLI_FBI(), card_stop(),
2035
 *              mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
2036
 *
2037
 * NOTE:        The caller is responsible that the BMUs are idle
2038
 *              when this function is called.
2039
 *
2040
 *      END_MANUAL_ENTRY
2041
 */
2042
void mac_drv_clear_tx_queue(struct s_smc *smc)
2043
{
2044
        struct s_smt_fp_txd volatile *t ;
2045
        struct s_smt_tx_queue *queue ;
2046
        int tx_used ;
2047
        int i ;
2048
 
2049
        if (smc->hw.hw_state != STOPPED) {
2050
                SK_BREAK() ;
2051
                SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
2052
                return ;
2053
        }
2054
 
2055
        for (i = QUEUE_S; i <= QUEUE_A0; i++) {
2056
                queue = smc->hw.fp.tx[i] ;
2057
                DB_TX("clear_tx_queue: QUEUE = %d (0=sync/1=async)",i,0,5) ;
2058
 
2059
                /*
2060
                 * switch the OWN bit of all pending frames to the host
2061
                 */
2062
                t = queue->tx_curr_get ;
2063
                tx_used = queue->tx_used ;
2064
                while (tx_used) {
2065
                        DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
2066
                        DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
2067
                        t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
2068
                        DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
2069
                        t = t->txd_next ;
2070
                        tx_used-- ;
2071
                }
2072
        }
2073
 
2074
        /*
2075
         * release all TxD's for both send queues
2076
         */
2077
        mac_drv_clear_txd(smc) ;
2078
 
2079
        for (i = QUEUE_S; i <= QUEUE_A0; i++) {
2080
                queue = smc->hw.fp.tx[i] ;
2081
                t = queue->tx_curr_get ;
2082
 
2083
                /*
2084
                 * write the phys pointer of the NEXT descriptor into the
2085
                 * BMU's current address descriptor pointer and set
2086
                 * tx_curr_get and tx_curr_put to this position
2087
                 */
2088
                if (i == QUEUE_S) {
2089
                        outpd(ADDR(B5_XS_DA),AIX_REVERSE(t->txd_ntdadr)) ;
2090
                }
2091
                else {
2092
                        outpd(ADDR(B5_XA_DA),AIX_REVERSE(t->txd_ntdadr)) ;
2093
                }
2094
 
2095
                queue->tx_curr_put = queue->tx_curr_get->txd_next ;
2096
                queue->tx_curr_get = queue->tx_curr_put ;
2097
        }
2098
}
2099
 
2100
 
2101
/*
2102
        -------------------------------------------------------------
2103
        TEST FUNCTIONS:
2104
        -------------------------------------------------------------
2105
*/
2106
 
2107
#ifdef  DEBUG
2108
/*
2109
 *      BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)
2110
 *      void mac_drv_debug_lev(smc,flag,lev)
2111
 *
2112
 * function     DOWNCALL        (drvsr.c)
2113
 *              To get a special debug info the user can assign a debug level
2114
 *              to any debug flag.
2115
 *
2116
 * para flag    debug flag, possible values are:
2117
 *                      = 0:    reset all debug flags (the defined level is
2118
 *                              ignored)
2119
 *                      = 1:    debug.d_smtf
2120
 *                      = 2:    debug.d_smt
2121
 *                      = 3:    debug.d_ecm
2122
 *                      = 4:    debug.d_rmt
2123
 *                      = 5:    debug.d_cfm
2124
 *                      = 6:    debug.d_pcm
2125
 *
2126
 *                      = 10:   debug.d_os.hwm_rx (hardware module receive path)
2127
 *                      = 11:   debug.d_os.hwm_tx(hardware module transmit path)
2128
 *                      = 12:   debug.d_os.hwm_gen(hardware module general flag)
2129
 *
2130
 *      lev     debug level
2131
 *
2132
 *      END_MANUAL_ENTRY
2133
 */
2134
void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
2135
{
2136
        switch(flag) {
2137
        case (int)NULL:
2138
                DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
2139
                DB_P.d_cfm = 0 ;
2140
                DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
2141
#ifdef  SBA
2142
                DB_P.d_sba = 0 ;
2143
#endif
2144
#ifdef  ESS
2145
                DB_P.d_ess = 0 ;
2146
#endif
2147
                break ;
2148
        case DEBUG_SMTF:
2149
                DB_P.d_smtf = lev ;
2150
                break ;
2151
        case DEBUG_SMT:
2152
                DB_P.d_smt = lev ;
2153
                break ;
2154
        case DEBUG_ECM:
2155
                DB_P.d_ecm = lev ;
2156
                break ;
2157
        case DEBUG_RMT:
2158
                DB_P.d_rmt = lev ;
2159
                break ;
2160
        case DEBUG_CFM:
2161
                DB_P.d_cfm = lev ;
2162
                break ;
2163
        case DEBUG_PCM:
2164
                DB_P.d_pcm = lev ;
2165
                break ;
2166
        case DEBUG_SBA:
2167
#ifdef  SBA
2168
                DB_P.d_sba = lev ;
2169
#endif
2170
                break ;
2171
        case DEBUG_ESS:
2172
#ifdef  ESS
2173
                DB_P.d_ess = lev ;
2174
#endif
2175
                break ;
2176
        case DB_HWM_RX:
2177
                DB_P.d_os.hwm_rx = lev ;
2178
                break ;
2179
        case DB_HWM_TX:
2180
                DB_P.d_os.hwm_tx = lev ;
2181
                break ;
2182
        case DB_HWM_GEN:
2183
                DB_P.d_os.hwm_gen = lev ;
2184
                break ;
2185
        default:
2186
                break ;
2187
        }
2188
}
2189
#endif

powered by: WebSVN 2.1.0

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