12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
233f810b2SJeff Kirsher /******************************************************************************
333f810b2SJeff Kirsher *
433f810b2SJeff Kirsher * (C)Copyright 1998,1999 SysKonnect,
533f810b2SJeff Kirsher * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
633f810b2SJeff Kirsher *
733f810b2SJeff Kirsher * See the file "skfddi.c" for further information.
833f810b2SJeff Kirsher *
933f810b2SJeff Kirsher * The information in this file is provided "AS IS" without warranty.
1033f810b2SJeff Kirsher *
1133f810b2SJeff Kirsher ******************************************************************************/
1233f810b2SJeff Kirsher
1333f810b2SJeff Kirsher #define HWMTM
1433f810b2SJeff Kirsher
1533f810b2SJeff Kirsher #ifndef FDDI
1633f810b2SJeff Kirsher #define FDDI
1733f810b2SJeff Kirsher #endif
1833f810b2SJeff Kirsher
1933f810b2SJeff Kirsher #include "h/types.h"
2033f810b2SJeff Kirsher #include "h/fddi.h"
2133f810b2SJeff Kirsher #include "h/smc.h"
2233f810b2SJeff Kirsher #include "h/supern_2.h"
2333f810b2SJeff Kirsher #include "h/skfbiinc.h"
2433f810b2SJeff Kirsher
2533f810b2SJeff Kirsher /*
2633f810b2SJeff Kirsher -------------------------------------------------------------
2733f810b2SJeff Kirsher DOCUMENTATION
2833f810b2SJeff Kirsher -------------------------------------------------------------
2933f810b2SJeff Kirsher BEGIN_MANUAL_ENTRY(DOCUMENTATION)
3033f810b2SJeff Kirsher
3133f810b2SJeff Kirsher T B D
3233f810b2SJeff Kirsher
3333f810b2SJeff Kirsher END_MANUAL_ENTRY
3433f810b2SJeff Kirsher */
3533f810b2SJeff Kirsher /*
3633f810b2SJeff Kirsher -------------------------------------------------------------
3733f810b2SJeff Kirsher LOCAL VARIABLES:
3833f810b2SJeff Kirsher -------------------------------------------------------------
3933f810b2SJeff Kirsher */
4033f810b2SJeff Kirsher #ifdef COMMON_MB_POOL
41*b4aadd20SWen Zhiwei static SMbuf *mb_start;
42*b4aadd20SWen Zhiwei static SMbuf *mb_free;
4333f810b2SJeff Kirsher static int mb_init = FALSE ;
44*b4aadd20SWen Zhiwei static int call_count;
4533f810b2SJeff Kirsher #endif
4633f810b2SJeff Kirsher
4733f810b2SJeff Kirsher /*
4833f810b2SJeff Kirsher -------------------------------------------------------------
4933f810b2SJeff Kirsher EXTERNE VARIABLES:
5033f810b2SJeff Kirsher -------------------------------------------------------------
5133f810b2SJeff Kirsher */
5233f810b2SJeff Kirsher
5333f810b2SJeff Kirsher #ifdef DEBUG
5433f810b2SJeff Kirsher #ifndef DEBUG_BRD
5533f810b2SJeff Kirsher extern struct smt_debug debug ;
5633f810b2SJeff Kirsher #endif
5733f810b2SJeff Kirsher #endif
5833f810b2SJeff Kirsher
5933f810b2SJeff Kirsher #ifdef NDIS_OS2
6033f810b2SJeff Kirsher extern u_char offDepth ;
6133f810b2SJeff Kirsher extern u_char force_irq_pending ;
6233f810b2SJeff Kirsher #endif
6333f810b2SJeff Kirsher
6433f810b2SJeff Kirsher /*
6533f810b2SJeff Kirsher -------------------------------------------------------------
6633f810b2SJeff Kirsher LOCAL FUNCTIONS:
6733f810b2SJeff Kirsher -------------------------------------------------------------
6833f810b2SJeff Kirsher */
6933f810b2SJeff Kirsher
7033f810b2SJeff Kirsher static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
7133f810b2SJeff Kirsher static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
7233f810b2SJeff Kirsher static void init_txd_ring(struct s_smc *smc);
7333f810b2SJeff Kirsher static void init_rxd_ring(struct s_smc *smc);
7433f810b2SJeff Kirsher static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
7533f810b2SJeff Kirsher static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
7633f810b2SJeff Kirsher int count);
7733f810b2SJeff Kirsher static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
7833f810b2SJeff Kirsher static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
7933f810b2SJeff Kirsher static SMbuf* get_llc_rx(struct s_smc *smc);
8033f810b2SJeff Kirsher static SMbuf* get_txd_mb(struct s_smc *smc);
8133f810b2SJeff Kirsher static void mac_drv_clear_txd(struct s_smc *smc);
8233f810b2SJeff Kirsher
8333f810b2SJeff Kirsher /*
8433f810b2SJeff Kirsher -------------------------------------------------------------
8533f810b2SJeff Kirsher EXTERNAL FUNCTIONS:
8633f810b2SJeff Kirsher -------------------------------------------------------------
8733f810b2SJeff Kirsher */
8833f810b2SJeff Kirsher /* The external SMT functions are listed in cmtdef.h */
8933f810b2SJeff Kirsher
9033f810b2SJeff Kirsher extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
9133f810b2SJeff Kirsher extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
9233f810b2SJeff Kirsher extern void mac_drv_fill_rxd(struct s_smc *smc);
9333f810b2SJeff Kirsher extern void mac_drv_tx_complete(struct s_smc *smc,
9433f810b2SJeff Kirsher volatile struct s_smt_fp_txd *txd);
9533f810b2SJeff Kirsher extern void mac_drv_rx_complete(struct s_smc *smc,
9633f810b2SJeff Kirsher volatile struct s_smt_fp_rxd *rxd,
9733f810b2SJeff Kirsher int frag_count, int len);
9833f810b2SJeff Kirsher extern void mac_drv_requeue_rxd(struct s_smc *smc,
9933f810b2SJeff Kirsher volatile struct s_smt_fp_rxd *rxd,
10033f810b2SJeff Kirsher int frag_count);
10133f810b2SJeff Kirsher extern void mac_drv_clear_rxd(struct s_smc *smc,
10233f810b2SJeff Kirsher volatile struct s_smt_fp_rxd *rxd, int frag_count);
10333f810b2SJeff Kirsher
10433f810b2SJeff Kirsher #ifdef USE_OS_CPY
10533f810b2SJeff Kirsher extern void hwm_cpy_rxd2mb(void);
10633f810b2SJeff Kirsher extern void hwm_cpy_txd2mb(void);
10733f810b2SJeff Kirsher #endif
10833f810b2SJeff Kirsher
10933f810b2SJeff Kirsher #ifdef ALL_RX_COMPLETE
11033f810b2SJeff Kirsher extern void mac_drv_all_receives_complete(void);
11133f810b2SJeff Kirsher #endif
11233f810b2SJeff Kirsher
11333f810b2SJeff Kirsher extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
11433f810b2SJeff Kirsher extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
11533f810b2SJeff Kirsher
11633f810b2SJeff Kirsher #ifdef NDIS_OS2
11733f810b2SJeff Kirsher extern void post_proc(void);
11833f810b2SJeff Kirsher #else
11933f810b2SJeff Kirsher extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
12033f810b2SJeff Kirsher int flag);
12133f810b2SJeff Kirsher #endif
12233f810b2SJeff Kirsher
12333f810b2SJeff Kirsher extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
12433f810b2SJeff Kirsher int la_len);
12533f810b2SJeff Kirsher
12633f810b2SJeff Kirsher /*
12733f810b2SJeff Kirsher -------------------------------------------------------------
12833f810b2SJeff Kirsher PUBLIC FUNCTIONS:
12933f810b2SJeff Kirsher -------------------------------------------------------------
13033f810b2SJeff Kirsher */
13133f810b2SJeff Kirsher void process_receive(struct s_smc *smc);
13233f810b2SJeff Kirsher void fddi_isr(struct s_smc *smc);
13333f810b2SJeff Kirsher void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
13433f810b2SJeff Kirsher void init_driver_fplus(struct s_smc *smc);
13533f810b2SJeff Kirsher void mac_drv_rx_mode(struct s_smc *smc, int mode);
13633f810b2SJeff Kirsher void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
13733f810b2SJeff Kirsher void mac_drv_clear_tx_queue(struct s_smc *smc);
13833f810b2SJeff Kirsher void mac_drv_clear_rx_queue(struct s_smc *smc);
13933f810b2SJeff Kirsher void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
14033f810b2SJeff Kirsher int frame_status);
14133f810b2SJeff Kirsher void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
14233f810b2SJeff Kirsher int frame_status);
14333f810b2SJeff Kirsher
14433f810b2SJeff Kirsher int mac_drv_init(struct s_smc *smc);
14533f810b2SJeff Kirsher int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
14633f810b2SJeff Kirsher int frame_status);
14733f810b2SJeff Kirsher
14833f810b2SJeff Kirsher u_int mac_drv_check_space(void);
14933f810b2SJeff Kirsher
15033f810b2SJeff Kirsher SMbuf* smt_get_mbuf(struct s_smc *smc);
15133f810b2SJeff Kirsher
15233f810b2SJeff Kirsher #ifdef DEBUG
1535671e8c1SJoe Perches void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev);
15433f810b2SJeff Kirsher #endif
15533f810b2SJeff Kirsher
15633f810b2SJeff Kirsher /*
15733f810b2SJeff Kirsher -------------------------------------------------------------
15833f810b2SJeff Kirsher MACROS:
15933f810b2SJeff Kirsher -------------------------------------------------------------
16033f810b2SJeff Kirsher */
16133f810b2SJeff Kirsher #ifndef UNUSED
16233f810b2SJeff Kirsher #ifdef lint
16333f810b2SJeff Kirsher #define UNUSED(x) (x) = (x)
16433f810b2SJeff Kirsher #else
16533f810b2SJeff Kirsher #define UNUSED(x)
16633f810b2SJeff Kirsher #endif
16733f810b2SJeff Kirsher #endif
16833f810b2SJeff Kirsher
16933f810b2SJeff Kirsher #ifdef USE_CAN_ADDR
17033f810b2SJeff Kirsher #define MA smc->hw.fddi_canon_addr.a
17133f810b2SJeff Kirsher #define GROUP_ADDR_BIT 0x01
17233f810b2SJeff Kirsher #else
17333f810b2SJeff Kirsher #define MA smc->hw.fddi_home_addr.a
17433f810b2SJeff Kirsher #define GROUP_ADDR_BIT 0x80
17533f810b2SJeff Kirsher #endif
17633f810b2SJeff Kirsher
17733f810b2SJeff Kirsher #define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
17833f810b2SJeff Kirsher SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
17933f810b2SJeff Kirsher
18033f810b2SJeff Kirsher #ifdef MB_OUTSIDE_SMC
18133f810b2SJeff Kirsher #define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
18233f810b2SJeff Kirsher MAX_MBUF*sizeof(SMbuf))
18333f810b2SJeff Kirsher #define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
18433f810b2SJeff Kirsher #else
18533f810b2SJeff Kirsher #define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
18633f810b2SJeff Kirsher #endif
18733f810b2SJeff Kirsher
18833f810b2SJeff Kirsher /*
18933f810b2SJeff Kirsher * define critical read for 16 Bit drivers
19033f810b2SJeff Kirsher */
19133f810b2SJeff Kirsher #if defined(NDIS_OS2) || defined(ODI2)
19233f810b2SJeff Kirsher #define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))
19333f810b2SJeff Kirsher #else
19433f810b2SJeff Kirsher #define CR_READ(var) (__le32)(var)
19533f810b2SJeff Kirsher #endif
19633f810b2SJeff Kirsher
19733f810b2SJeff Kirsher #define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
19833f810b2SJeff Kirsher IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
19933f810b2SJeff Kirsher IS_R1_C | IS_XA_C | IS_XS_C)
20033f810b2SJeff Kirsher
20133f810b2SJeff Kirsher /*
20233f810b2SJeff Kirsher -------------------------------------------------------------
20333f810b2SJeff Kirsher INIT- AND SMT FUNCTIONS:
20433f810b2SJeff Kirsher -------------------------------------------------------------
20533f810b2SJeff Kirsher */
20633f810b2SJeff Kirsher
20733f810b2SJeff Kirsher
20833f810b2SJeff Kirsher /*
20933f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(mac_drv_check_space)
21033f810b2SJeff Kirsher * u_int mac_drv_check_space()
21133f810b2SJeff Kirsher *
21233f810b2SJeff Kirsher * function DOWNCALL (drvsr.c)
21333f810b2SJeff Kirsher * This function calculates the needed non virtual
21433f810b2SJeff Kirsher * memory for MBufs, RxD and TxD descriptors etc.
21533f810b2SJeff Kirsher * needed by the driver.
21633f810b2SJeff Kirsher *
21733f810b2SJeff Kirsher * return u_int memory in bytes
21833f810b2SJeff Kirsher *
21933f810b2SJeff Kirsher * END_MANUAL_ENTRY
22033f810b2SJeff Kirsher */
mac_drv_check_space(void)22133f810b2SJeff Kirsher u_int mac_drv_check_space(void)
22233f810b2SJeff Kirsher {
22333f810b2SJeff Kirsher #ifdef MB_OUTSIDE_SMC
22433f810b2SJeff Kirsher #ifdef COMMON_MB_POOL
22533f810b2SJeff Kirsher call_count++ ;
22633f810b2SJeff Kirsher if (call_count == 1) {
22733f810b2SJeff Kirsher return EXT_VIRT_MEM;
22833f810b2SJeff Kirsher }
22933f810b2SJeff Kirsher else {
23033f810b2SJeff Kirsher return EXT_VIRT_MEM_2;
23133f810b2SJeff Kirsher }
23233f810b2SJeff Kirsher #else
23333f810b2SJeff Kirsher return EXT_VIRT_MEM;
23433f810b2SJeff Kirsher #endif
23533f810b2SJeff Kirsher #else
23633f810b2SJeff Kirsher return 0;
23733f810b2SJeff Kirsher #endif
23833f810b2SJeff Kirsher }
23933f810b2SJeff Kirsher
24033f810b2SJeff Kirsher /*
24133f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(mac_drv_init)
24233f810b2SJeff Kirsher * void mac_drv_init(smc)
24333f810b2SJeff Kirsher *
24433f810b2SJeff Kirsher * function DOWNCALL (drvsr.c)
24533f810b2SJeff Kirsher * In this function the hardware module allocates it's
24633f810b2SJeff Kirsher * memory.
24733f810b2SJeff Kirsher * The operating system dependent module should call
24833f810b2SJeff Kirsher * mac_drv_init once, after the adatper is detected.
24933f810b2SJeff Kirsher * END_MANUAL_ENTRY
25033f810b2SJeff Kirsher */
mac_drv_init(struct s_smc * smc)25133f810b2SJeff Kirsher int mac_drv_init(struct s_smc *smc)
25233f810b2SJeff Kirsher {
25333f810b2SJeff Kirsher if (sizeof(struct s_smt_fp_rxd) % 16) {
25433f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
25533f810b2SJeff Kirsher }
25633f810b2SJeff Kirsher if (sizeof(struct s_smt_fp_txd) % 16) {
25733f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
25833f810b2SJeff Kirsher }
25933f810b2SJeff Kirsher
26033f810b2SJeff Kirsher /*
26133f810b2SJeff Kirsher * get the required memory for the RxDs and TxDs
26233f810b2SJeff Kirsher */
26333f810b2SJeff Kirsher if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
26433f810b2SJeff Kirsher mac_drv_get_desc_mem(smc,(u_int)
26533f810b2SJeff Kirsher (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
26633f810b2SJeff Kirsher return 1; /* no space the hwm modul can't work */
26733f810b2SJeff Kirsher }
26833f810b2SJeff Kirsher
26933f810b2SJeff Kirsher /*
27033f810b2SJeff Kirsher * get the memory for the SMT MBufs
27133f810b2SJeff Kirsher */
27233f810b2SJeff Kirsher #ifndef MB_OUTSIDE_SMC
27333f810b2SJeff Kirsher smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
27433f810b2SJeff Kirsher #else
27533f810b2SJeff Kirsher #ifndef COMMON_MB_POOL
27633f810b2SJeff Kirsher if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
27733f810b2SJeff Kirsher MAX_MBUF*sizeof(SMbuf)))) {
27833f810b2SJeff Kirsher return 1; /* no space the hwm modul can't work */
27933f810b2SJeff Kirsher }
28033f810b2SJeff Kirsher #else
28133f810b2SJeff Kirsher if (!mb_start) {
28233f810b2SJeff Kirsher if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
28333f810b2SJeff Kirsher MAX_MBUF*sizeof(SMbuf)))) {
28433f810b2SJeff Kirsher return 1; /* no space the hwm modul can't work */
28533f810b2SJeff Kirsher }
28633f810b2SJeff Kirsher }
28733f810b2SJeff Kirsher #endif
28833f810b2SJeff Kirsher #endif
28933f810b2SJeff Kirsher return 0;
29033f810b2SJeff Kirsher }
29133f810b2SJeff Kirsher
29233f810b2SJeff Kirsher /*
29333f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(init_driver_fplus)
29433f810b2SJeff Kirsher * init_driver_fplus(smc)
29533f810b2SJeff Kirsher *
29633f810b2SJeff Kirsher * Sets hardware modul specific values for the mode register 2
29733f810b2SJeff Kirsher * (e.g. the byte alignment for the received frames, the position of the
29833f810b2SJeff Kirsher * least significant byte etc.)
29933f810b2SJeff Kirsher * END_MANUAL_ENTRY
30033f810b2SJeff Kirsher */
init_driver_fplus(struct s_smc * smc)30133f810b2SJeff Kirsher void init_driver_fplus(struct s_smc *smc)
30233f810b2SJeff Kirsher {
30333f810b2SJeff Kirsher smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
30433f810b2SJeff Kirsher
30533f810b2SJeff Kirsher #ifdef PCI
30633f810b2SJeff Kirsher smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
30733f810b2SJeff Kirsher #endif
30833f810b2SJeff Kirsher smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
30933f810b2SJeff Kirsher
31033f810b2SJeff Kirsher #ifdef USE_CAN_ADDR
31133f810b2SJeff Kirsher /* enable address bit swapping */
31233f810b2SJeff Kirsher smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
31333f810b2SJeff Kirsher #endif
31433f810b2SJeff Kirsher }
31533f810b2SJeff Kirsher
init_descr_ring(struct s_smc * smc,union s_fp_descr volatile * start,int count)31633f810b2SJeff Kirsher static u_long init_descr_ring(struct s_smc *smc,
31733f810b2SJeff Kirsher union s_fp_descr volatile *start,
31833f810b2SJeff Kirsher int count)
31933f810b2SJeff Kirsher {
32033f810b2SJeff Kirsher int i ;
32133f810b2SJeff Kirsher union s_fp_descr volatile *d1 ;
32233f810b2SJeff Kirsher union s_fp_descr volatile *d2 ;
32333f810b2SJeff Kirsher u_long phys ;
32433f810b2SJeff Kirsher
3255dbc6530SJoe Perches DB_GEN(3, "descr ring starts at = %p", start);
32633f810b2SJeff Kirsher for (i=count-1, d1=start; i ; i--) {
32733f810b2SJeff Kirsher d2 = d1 ;
32833f810b2SJeff Kirsher d1++ ; /* descr is owned by the host */
32933f810b2SJeff Kirsher d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
33033f810b2SJeff Kirsher d2->r.rxd_next = &d1->r ;
33133f810b2SJeff Kirsher phys = mac_drv_virt2phys(smc,(void *)d1) ;
33233f810b2SJeff Kirsher d2->r.rxd_nrdadr = cpu_to_le32(phys) ;
33333f810b2SJeff Kirsher }
3345dbc6530SJoe Perches DB_GEN(3, "descr ring ends at = %p", d1);
33533f810b2SJeff Kirsher d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
33633f810b2SJeff Kirsher d1->r.rxd_next = &start->r ;
33733f810b2SJeff Kirsher phys = mac_drv_virt2phys(smc,(void *)start) ;
33833f810b2SJeff Kirsher d1->r.rxd_nrdadr = cpu_to_le32(phys) ;
33933f810b2SJeff Kirsher
34033f810b2SJeff Kirsher for (i=count, d1=start; i ; i--) {
34133f810b2SJeff Kirsher DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
34233f810b2SJeff Kirsher d1++;
34333f810b2SJeff Kirsher }
34433f810b2SJeff Kirsher return phys;
34533f810b2SJeff Kirsher }
34633f810b2SJeff Kirsher
init_txd_ring(struct s_smc * smc)34733f810b2SJeff Kirsher static void init_txd_ring(struct s_smc *smc)
34833f810b2SJeff Kirsher {
34933f810b2SJeff Kirsher struct s_smt_fp_txd volatile *ds ;
35033f810b2SJeff Kirsher struct s_smt_tx_queue *queue ;
35133f810b2SJeff Kirsher u_long phys ;
35233f810b2SJeff Kirsher
35333f810b2SJeff Kirsher /*
35433f810b2SJeff Kirsher * initialize the transmit descriptors
35533f810b2SJeff Kirsher */
35633f810b2SJeff Kirsher ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
35733f810b2SJeff Kirsher SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
35833f810b2SJeff Kirsher queue = smc->hw.fp.tx[QUEUE_A0] ;
3595dbc6530SJoe Perches DB_GEN(3, "Init async TxD ring, %d TxDs", HWM_ASYNC_TXD_COUNT);
36033f810b2SJeff Kirsher (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
36133f810b2SJeff Kirsher HWM_ASYNC_TXD_COUNT) ;
36233f810b2SJeff Kirsher phys = le32_to_cpu(ds->txd_ntdadr) ;
36333f810b2SJeff Kirsher ds++ ;
36433f810b2SJeff Kirsher queue->tx_curr_put = queue->tx_curr_get = ds ;
36533f810b2SJeff Kirsher ds-- ;
36633f810b2SJeff Kirsher queue->tx_free = HWM_ASYNC_TXD_COUNT ;
36733f810b2SJeff Kirsher queue->tx_used = 0 ;
36833f810b2SJeff Kirsher outpd(ADDR(B5_XA_DA),phys) ;
36933f810b2SJeff Kirsher
37033f810b2SJeff Kirsher ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
37133f810b2SJeff Kirsher HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
37233f810b2SJeff Kirsher queue = smc->hw.fp.tx[QUEUE_S] ;
3735dbc6530SJoe Perches DB_GEN(3, "Init sync TxD ring, %d TxDs", HWM_SYNC_TXD_COUNT);
37433f810b2SJeff Kirsher (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
37533f810b2SJeff Kirsher HWM_SYNC_TXD_COUNT) ;
37633f810b2SJeff Kirsher phys = le32_to_cpu(ds->txd_ntdadr) ;
37733f810b2SJeff Kirsher ds++ ;
37833f810b2SJeff Kirsher queue->tx_curr_put = queue->tx_curr_get = ds ;
37933f810b2SJeff Kirsher queue->tx_free = HWM_SYNC_TXD_COUNT ;
38033f810b2SJeff Kirsher queue->tx_used = 0 ;
38133f810b2SJeff Kirsher outpd(ADDR(B5_XS_DA),phys) ;
38233f810b2SJeff Kirsher }
38333f810b2SJeff Kirsher
init_rxd_ring(struct s_smc * smc)38433f810b2SJeff Kirsher static void init_rxd_ring(struct s_smc *smc)
38533f810b2SJeff Kirsher {
38633f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *ds ;
38733f810b2SJeff Kirsher struct s_smt_rx_queue *queue ;
38833f810b2SJeff Kirsher u_long phys ;
38933f810b2SJeff Kirsher
39033f810b2SJeff Kirsher /*
39133f810b2SJeff Kirsher * initialize the receive descriptors
39233f810b2SJeff Kirsher */
39333f810b2SJeff Kirsher ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
39433f810b2SJeff Kirsher queue = smc->hw.fp.rx[QUEUE_R1] ;
3955dbc6530SJoe Perches DB_GEN(3, "Init RxD ring, %d RxDs", SMT_R1_RXD_COUNT);
39633f810b2SJeff Kirsher (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
39733f810b2SJeff Kirsher SMT_R1_RXD_COUNT) ;
39833f810b2SJeff Kirsher phys = le32_to_cpu(ds->rxd_nrdadr) ;
39933f810b2SJeff Kirsher ds++ ;
40033f810b2SJeff Kirsher queue->rx_curr_put = queue->rx_curr_get = ds ;
40133f810b2SJeff Kirsher queue->rx_free = SMT_R1_RXD_COUNT ;
40233f810b2SJeff Kirsher queue->rx_used = 0 ;
40333f810b2SJeff Kirsher outpd(ADDR(B4_R1_DA),phys) ;
40433f810b2SJeff Kirsher }
40533f810b2SJeff Kirsher
40633f810b2SJeff Kirsher /*
40733f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(init_fddi_driver)
40833f810b2SJeff Kirsher * void init_fddi_driver(smc,mac_addr)
40933f810b2SJeff Kirsher *
41033f810b2SJeff Kirsher * initializes the driver and it's variables
41133f810b2SJeff Kirsher *
41233f810b2SJeff Kirsher * END_MANUAL_ENTRY
41333f810b2SJeff Kirsher */
init_fddi_driver(struct s_smc * smc,u_char * mac_addr)41433f810b2SJeff Kirsher void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
41533f810b2SJeff Kirsher {
41633f810b2SJeff Kirsher SMbuf *mb ;
41733f810b2SJeff Kirsher int i ;
41833f810b2SJeff Kirsher
41933f810b2SJeff Kirsher init_board(smc,mac_addr) ;
42033f810b2SJeff Kirsher (void)init_fplus(smc) ;
42133f810b2SJeff Kirsher
42233f810b2SJeff Kirsher /*
42333f810b2SJeff Kirsher * initialize the SMbufs for the SMT
42433f810b2SJeff Kirsher */
42533f810b2SJeff Kirsher #ifndef COMMON_MB_POOL
42633f810b2SJeff Kirsher mb = smc->os.hwm.mbuf_pool.mb_start ;
42733f810b2SJeff Kirsher smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
42833f810b2SJeff Kirsher for (i = 0; i < MAX_MBUF; i++) {
42933f810b2SJeff Kirsher mb->sm_use_count = 1 ;
43033f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
43133f810b2SJeff Kirsher mb++ ;
43233f810b2SJeff Kirsher }
43333f810b2SJeff Kirsher #else
43433f810b2SJeff Kirsher mb = mb_start ;
43533f810b2SJeff Kirsher if (!mb_init) {
43633f810b2SJeff Kirsher mb_free = 0 ;
43733f810b2SJeff Kirsher for (i = 0; i < MAX_MBUF; i++) {
43833f810b2SJeff Kirsher mb->sm_use_count = 1 ;
43933f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
44033f810b2SJeff Kirsher mb++ ;
44133f810b2SJeff Kirsher }
44233f810b2SJeff Kirsher mb_init = TRUE ;
44333f810b2SJeff Kirsher }
44433f810b2SJeff Kirsher #endif
44533f810b2SJeff Kirsher
44633f810b2SJeff Kirsher /*
44733f810b2SJeff Kirsher * initialize the other variables
44833f810b2SJeff Kirsher */
44933f810b2SJeff Kirsher smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
45033f810b2SJeff Kirsher smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
45133f810b2SJeff Kirsher smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
45233f810b2SJeff Kirsher smc->os.hwm.pass_llc_promisc = TRUE ;
45333f810b2SJeff Kirsher smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
45433f810b2SJeff Kirsher smc->os.hwm.detec_count = 0 ;
45533f810b2SJeff Kirsher smc->os.hwm.rx_break = 0 ;
45633f810b2SJeff Kirsher smc->os.hwm.rx_len_error = 0 ;
45733f810b2SJeff Kirsher smc->os.hwm.isr_flag = FALSE ;
45833f810b2SJeff Kirsher
45933f810b2SJeff Kirsher /*
46033f810b2SJeff Kirsher * make sure that the start pointer is 16 byte aligned
46133f810b2SJeff Kirsher */
46233f810b2SJeff Kirsher i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;
46333f810b2SJeff Kirsher if (i != 16) {
4645dbc6530SJoe Perches DB_GEN(3, "i = %d", i);
46533f810b2SJeff Kirsher smc->os.hwm.descr_p = (union s_fp_descr volatile *)
46633f810b2SJeff Kirsher ((char *)smc->os.hwm.descr_p+i) ;
46733f810b2SJeff Kirsher }
4685dbc6530SJoe Perches DB_GEN(3, "pt to descr area = %p", smc->os.hwm.descr_p);
46933f810b2SJeff Kirsher
47033f810b2SJeff Kirsher init_txd_ring(smc) ;
47133f810b2SJeff Kirsher init_rxd_ring(smc) ;
47233f810b2SJeff Kirsher mac_drv_fill_rxd(smc) ;
47333f810b2SJeff Kirsher
47433f810b2SJeff Kirsher init_plc(smc) ;
47533f810b2SJeff Kirsher }
47633f810b2SJeff Kirsher
47733f810b2SJeff Kirsher
smt_get_mbuf(struct s_smc * smc)47833f810b2SJeff Kirsher SMbuf *smt_get_mbuf(struct s_smc *smc)
47933f810b2SJeff Kirsher {
48033f810b2SJeff Kirsher register SMbuf *mb ;
48133f810b2SJeff Kirsher
48233f810b2SJeff Kirsher #ifndef COMMON_MB_POOL
48333f810b2SJeff Kirsher mb = smc->os.hwm.mbuf_pool.mb_free ;
48433f810b2SJeff Kirsher #else
48533f810b2SJeff Kirsher mb = mb_free ;
48633f810b2SJeff Kirsher #endif
48733f810b2SJeff Kirsher if (mb) {
48833f810b2SJeff Kirsher #ifndef COMMON_MB_POOL
48933f810b2SJeff Kirsher smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
49033f810b2SJeff Kirsher #else
49133f810b2SJeff Kirsher mb_free = mb->sm_next ;
49233f810b2SJeff Kirsher #endif
49333f810b2SJeff Kirsher mb->sm_off = 8 ;
49433f810b2SJeff Kirsher mb->sm_use_count = 1 ;
49533f810b2SJeff Kirsher }
4965dbc6530SJoe Perches DB_GEN(3, "get SMbuf: mb = %p", mb);
49733f810b2SJeff Kirsher return mb; /* May be NULL */
49833f810b2SJeff Kirsher }
49933f810b2SJeff Kirsher
smt_free_mbuf(struct s_smc * smc,SMbuf * mb)50033f810b2SJeff Kirsher void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
50133f810b2SJeff Kirsher {
50233f810b2SJeff Kirsher
50333f810b2SJeff Kirsher if (mb) {
50433f810b2SJeff Kirsher mb->sm_use_count-- ;
5055dbc6530SJoe Perches DB_GEN(3, "free_mbuf: sm_use_count = %d", mb->sm_use_count);
50633f810b2SJeff Kirsher /*
50733f810b2SJeff Kirsher * If the use_count is != zero the MBuf is queued
50833f810b2SJeff Kirsher * more than once and must not queued into the
50933f810b2SJeff Kirsher * free MBuf queue
51033f810b2SJeff Kirsher */
51133f810b2SJeff Kirsher if (!mb->sm_use_count) {
5125dbc6530SJoe Perches DB_GEN(3, "free SMbuf: mb = %p", mb);
51333f810b2SJeff Kirsher #ifndef COMMON_MB_POOL
51433f810b2SJeff Kirsher mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
51533f810b2SJeff Kirsher smc->os.hwm.mbuf_pool.mb_free = mb ;
51633f810b2SJeff Kirsher #else
51733f810b2SJeff Kirsher mb->sm_next = mb_free ;
51833f810b2SJeff Kirsher mb_free = mb ;
51933f810b2SJeff Kirsher #endif
52033f810b2SJeff Kirsher }
52133f810b2SJeff Kirsher }
52233f810b2SJeff Kirsher else
52333f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
52433f810b2SJeff Kirsher }
52533f810b2SJeff Kirsher
52633f810b2SJeff Kirsher
52733f810b2SJeff Kirsher /*
52833f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)
52933f810b2SJeff Kirsher * void mac_drv_repair_descr(smc)
53033f810b2SJeff Kirsher *
53133f810b2SJeff Kirsher * function called from SMT (HWM / hwmtm.c)
53233f810b2SJeff Kirsher * The BMU is idle when this function is called.
53333f810b2SJeff Kirsher * Mac_drv_repair_descr sets up the physical address
53433f810b2SJeff Kirsher * for all receive and transmit queues where the BMU
53533f810b2SJeff Kirsher * should continue.
53633f810b2SJeff Kirsher * It may be that the BMU was reseted during a fragmented
53733f810b2SJeff Kirsher * transfer. In this case there are some fragments which will
53833f810b2SJeff Kirsher * never completed by the BMU. The OWN bit of this fragments
53933f810b2SJeff Kirsher * must be switched to be owned by the host.
54033f810b2SJeff Kirsher *
54133f810b2SJeff Kirsher * Give a start command to the receive BMU.
54233f810b2SJeff Kirsher * Start the transmit BMUs if transmit frames pending.
54333f810b2SJeff Kirsher *
54433f810b2SJeff Kirsher * END_MANUAL_ENTRY
54533f810b2SJeff Kirsher */
mac_drv_repair_descr(struct s_smc * smc)54633f810b2SJeff Kirsher void mac_drv_repair_descr(struct s_smc *smc)
54733f810b2SJeff Kirsher {
54833f810b2SJeff Kirsher u_long phys ;
54933f810b2SJeff Kirsher
55033f810b2SJeff Kirsher if (smc->hw.hw_state != STOPPED) {
55133f810b2SJeff Kirsher SK_BREAK() ;
55233f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
55333f810b2SJeff Kirsher return ;
55433f810b2SJeff Kirsher }
55533f810b2SJeff Kirsher
55633f810b2SJeff Kirsher /*
55733f810b2SJeff Kirsher * repair tx queues: don't start
55833f810b2SJeff Kirsher */
55933f810b2SJeff Kirsher phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
56033f810b2SJeff Kirsher outpd(ADDR(B5_XA_DA),phys) ;
56133f810b2SJeff Kirsher if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
56233f810b2SJeff Kirsher outpd(ADDR(B0_XA_CSR),CSR_START) ;
56333f810b2SJeff Kirsher }
56433f810b2SJeff Kirsher phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
56533f810b2SJeff Kirsher outpd(ADDR(B5_XS_DA),phys) ;
56633f810b2SJeff Kirsher if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
56733f810b2SJeff Kirsher outpd(ADDR(B0_XS_CSR),CSR_START) ;
56833f810b2SJeff Kirsher }
56933f810b2SJeff Kirsher
57033f810b2SJeff Kirsher /*
57133f810b2SJeff Kirsher * repair rx queues
57233f810b2SJeff Kirsher */
57333f810b2SJeff Kirsher phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
57433f810b2SJeff Kirsher outpd(ADDR(B4_R1_DA),phys) ;
57533f810b2SJeff Kirsher outpd(ADDR(B0_R1_CSR),CSR_START) ;
57633f810b2SJeff Kirsher }
57733f810b2SJeff Kirsher
repair_txd_ring(struct s_smc * smc,struct s_smt_tx_queue * queue)57833f810b2SJeff Kirsher static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
57933f810b2SJeff Kirsher {
58033f810b2SJeff Kirsher int i ;
58133f810b2SJeff Kirsher int tx_used ;
58233f810b2SJeff Kirsher u_long phys ;
58333f810b2SJeff Kirsher u_long tbctrl ;
58433f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t ;
58533f810b2SJeff Kirsher
58633f810b2SJeff Kirsher SK_UNUSED(smc) ;
58733f810b2SJeff Kirsher
58833f810b2SJeff Kirsher t = queue->tx_curr_get ;
58933f810b2SJeff Kirsher tx_used = queue->tx_used ;
59033f810b2SJeff Kirsher for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
59133f810b2SJeff Kirsher t = t->txd_next ;
59233f810b2SJeff Kirsher }
59333f810b2SJeff Kirsher phys = le32_to_cpu(t->txd_ntdadr) ;
59433f810b2SJeff Kirsher
59533f810b2SJeff Kirsher t = queue->tx_curr_get ;
59633f810b2SJeff Kirsher while (tx_used) {
59733f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
59833f810b2SJeff Kirsher tbctrl = le32_to_cpu(t->txd_tbctrl) ;
59933f810b2SJeff Kirsher
60033f810b2SJeff Kirsher if (tbctrl & BMU_OWN) {
60133f810b2SJeff Kirsher if (tbctrl & BMU_STF) {
60233f810b2SJeff Kirsher break ; /* exit the loop */
60333f810b2SJeff Kirsher }
60433f810b2SJeff Kirsher else {
60533f810b2SJeff Kirsher /*
60633f810b2SJeff Kirsher * repair the descriptor
60733f810b2SJeff Kirsher */
60833f810b2SJeff Kirsher t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
60933f810b2SJeff Kirsher }
61033f810b2SJeff Kirsher }
61133f810b2SJeff Kirsher phys = le32_to_cpu(t->txd_ntdadr) ;
61233f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
61333f810b2SJeff Kirsher t = t->txd_next ;
61433f810b2SJeff Kirsher tx_used-- ;
61533f810b2SJeff Kirsher }
61633f810b2SJeff Kirsher return phys;
61733f810b2SJeff Kirsher }
61833f810b2SJeff Kirsher
61933f810b2SJeff Kirsher /*
62033f810b2SJeff Kirsher * Repairs the receive descriptor ring and returns the physical address
62133f810b2SJeff Kirsher * where the BMU should continue working.
62233f810b2SJeff Kirsher *
62333f810b2SJeff Kirsher * o The physical address where the BMU was stopped has to be
62433f810b2SJeff Kirsher * determined. This is the next RxD after rx_curr_get with an OWN
62533f810b2SJeff Kirsher * bit set.
62633f810b2SJeff Kirsher * o The BMU should start working at beginning of the next frame.
62733f810b2SJeff Kirsher * RxDs with an OWN bit set but with a reset STF bit should be
62833f810b2SJeff Kirsher * skipped and owned by the driver (OWN = 0).
62933f810b2SJeff Kirsher */
repair_rxd_ring(struct s_smc * smc,struct s_smt_rx_queue * queue)63033f810b2SJeff Kirsher static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
63133f810b2SJeff Kirsher {
63233f810b2SJeff Kirsher int i ;
63333f810b2SJeff Kirsher int rx_used ;
63433f810b2SJeff Kirsher u_long phys ;
63533f810b2SJeff Kirsher u_long rbctrl ;
63633f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *r ;
63733f810b2SJeff Kirsher
63833f810b2SJeff Kirsher SK_UNUSED(smc) ;
63933f810b2SJeff Kirsher
64033f810b2SJeff Kirsher r = queue->rx_curr_get ;
64133f810b2SJeff Kirsher rx_used = queue->rx_used ;
64233f810b2SJeff Kirsher for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
64333f810b2SJeff Kirsher r = r->rxd_next ;
64433f810b2SJeff Kirsher }
64533f810b2SJeff Kirsher phys = le32_to_cpu(r->rxd_nrdadr) ;
64633f810b2SJeff Kirsher
64733f810b2SJeff Kirsher r = queue->rx_curr_get ;
64833f810b2SJeff Kirsher while (rx_used) {
64933f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
65033f810b2SJeff Kirsher rbctrl = le32_to_cpu(r->rxd_rbctrl) ;
65133f810b2SJeff Kirsher
65233f810b2SJeff Kirsher if (rbctrl & BMU_OWN) {
65333f810b2SJeff Kirsher if (rbctrl & BMU_STF) {
65433f810b2SJeff Kirsher break ; /* exit the loop */
65533f810b2SJeff Kirsher }
65633f810b2SJeff Kirsher else {
65733f810b2SJeff Kirsher /*
65833f810b2SJeff Kirsher * repair the descriptor
65933f810b2SJeff Kirsher */
66033f810b2SJeff Kirsher r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
66133f810b2SJeff Kirsher }
66233f810b2SJeff Kirsher }
66333f810b2SJeff Kirsher phys = le32_to_cpu(r->rxd_nrdadr) ;
66433f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
66533f810b2SJeff Kirsher r = r->rxd_next ;
66633f810b2SJeff Kirsher rx_used-- ;
66733f810b2SJeff Kirsher }
66833f810b2SJeff Kirsher return phys;
66933f810b2SJeff Kirsher }
67033f810b2SJeff Kirsher
67133f810b2SJeff Kirsher
67233f810b2SJeff Kirsher /*
67333f810b2SJeff Kirsher -------------------------------------------------------------
67433f810b2SJeff Kirsher INTERRUPT SERVICE ROUTINE:
67533f810b2SJeff Kirsher -------------------------------------------------------------
67633f810b2SJeff Kirsher */
67733f810b2SJeff Kirsher
67833f810b2SJeff Kirsher /*
67933f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(fddi_isr)
68033f810b2SJeff Kirsher * void fddi_isr(smc)
68133f810b2SJeff Kirsher *
68233f810b2SJeff Kirsher * function DOWNCALL (drvsr.c)
68333f810b2SJeff Kirsher * interrupt service routine, handles the interrupt requests
68433f810b2SJeff Kirsher * generated by the FDDI adapter.
68533f810b2SJeff Kirsher *
68633f810b2SJeff Kirsher * NOTE: The operating system dependent module must guarantee that the
68733f810b2SJeff Kirsher * interrupts of the adapter are disabled when it calls fddi_isr.
68833f810b2SJeff Kirsher *
68933f810b2SJeff Kirsher * About the USE_BREAK_ISR mechanismn:
69033f810b2SJeff Kirsher *
69133f810b2SJeff Kirsher * The main requirement of this mechanismn is to force an timer IRQ when
69233f810b2SJeff Kirsher * leaving process_receive() with leave_isr set. process_receive() may
69333f810b2SJeff Kirsher * be called at any time from anywhere!
69433f810b2SJeff Kirsher * To be sure we don't miss such event we set 'force_irq' per default.
69533f810b2SJeff Kirsher * We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND
69633f810b2SJeff Kirsher * 'force_irq' are set. 'force_irq' may be reset if a receive complete
69733f810b2SJeff Kirsher * IRQ is pending.
69833f810b2SJeff Kirsher *
69933f810b2SJeff Kirsher * END_MANUAL_ENTRY
70033f810b2SJeff Kirsher */
fddi_isr(struct s_smc * smc)70133f810b2SJeff Kirsher void fddi_isr(struct s_smc *smc)
70233f810b2SJeff Kirsher {
70333f810b2SJeff Kirsher u_long is ; /* ISR source */
70433f810b2SJeff Kirsher u_short stu, stl ;
70533f810b2SJeff Kirsher SMbuf *mb ;
70633f810b2SJeff Kirsher
70733f810b2SJeff Kirsher #ifdef USE_BREAK_ISR
70833f810b2SJeff Kirsher int force_irq ;
70933f810b2SJeff Kirsher #endif
71033f810b2SJeff Kirsher
71133f810b2SJeff Kirsher #ifdef ODI2
71233f810b2SJeff Kirsher if (smc->os.hwm.rx_break) {
71333f810b2SJeff Kirsher mac_drv_fill_rxd(smc) ;
71433f810b2SJeff Kirsher if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
71533f810b2SJeff Kirsher smc->os.hwm.rx_break = 0 ;
71633f810b2SJeff Kirsher process_receive(smc) ;
71733f810b2SJeff Kirsher }
71833f810b2SJeff Kirsher else {
71933f810b2SJeff Kirsher smc->os.hwm.detec_count = 0 ;
72033f810b2SJeff Kirsher smt_force_irq(smc) ;
72133f810b2SJeff Kirsher }
72233f810b2SJeff Kirsher }
72333f810b2SJeff Kirsher #endif
72433f810b2SJeff Kirsher smc->os.hwm.isr_flag = TRUE ;
72533f810b2SJeff Kirsher
72633f810b2SJeff Kirsher #ifdef USE_BREAK_ISR
72733f810b2SJeff Kirsher force_irq = TRUE ;
72833f810b2SJeff Kirsher if (smc->os.hwm.leave_isr) {
72933f810b2SJeff Kirsher smc->os.hwm.leave_isr = FALSE ;
73033f810b2SJeff Kirsher process_receive(smc) ;
73133f810b2SJeff Kirsher }
73233f810b2SJeff Kirsher #endif
73333f810b2SJeff Kirsher
73433f810b2SJeff Kirsher while ((is = GET_ISR() & ISR_MASK)) {
73533f810b2SJeff Kirsher NDD_TRACE("CH0B",is,0,0) ;
7365dbc6530SJoe Perches DB_GEN(7, "ISA = 0x%lx", is);
73733f810b2SJeff Kirsher
73833f810b2SJeff Kirsher if (is & IMASK_SLOW) {
73933f810b2SJeff Kirsher NDD_TRACE("CH1b",is,0,0) ;
74033f810b2SJeff Kirsher if (is & IS_PLINT1) { /* PLC1 */
74133f810b2SJeff Kirsher plc1_irq(smc) ;
74233f810b2SJeff Kirsher }
74333f810b2SJeff Kirsher if (is & IS_PLINT2) { /* PLC2 */
74433f810b2SJeff Kirsher plc2_irq(smc) ;
74533f810b2SJeff Kirsher }
74633f810b2SJeff Kirsher if (is & IS_MINTR1) { /* FORMAC+ STU1(U/L) */
74733f810b2SJeff Kirsher stu = inpw(FM_A(FM_ST1U)) ;
74833f810b2SJeff Kirsher stl = inpw(FM_A(FM_ST1L)) ;
7495dbc6530SJoe Perches DB_GEN(6, "Slow transmit complete");
75033f810b2SJeff Kirsher mac1_irq(smc,stu,stl) ;
75133f810b2SJeff Kirsher }
75233f810b2SJeff Kirsher if (is & IS_MINTR2) { /* FORMAC+ STU2(U/L) */
75333f810b2SJeff Kirsher stu= inpw(FM_A(FM_ST2U)) ;
75433f810b2SJeff Kirsher stl= inpw(FM_A(FM_ST2L)) ;
7555dbc6530SJoe Perches DB_GEN(6, "Slow receive complete");
7565dbc6530SJoe Perches DB_GEN(7, "stl = %x : stu = %x", stl, stu);
75733f810b2SJeff Kirsher mac2_irq(smc,stu,stl) ;
75833f810b2SJeff Kirsher }
75933f810b2SJeff Kirsher if (is & IS_MINTR3) { /* FORMAC+ STU3(U/L) */
76033f810b2SJeff Kirsher stu= inpw(FM_A(FM_ST3U)) ;
76133f810b2SJeff Kirsher stl= inpw(FM_A(FM_ST3L)) ;
7625dbc6530SJoe Perches DB_GEN(6, "FORMAC Mode Register 3");
76333f810b2SJeff Kirsher mac3_irq(smc,stu,stl) ;
76433f810b2SJeff Kirsher }
76533f810b2SJeff Kirsher if (is & IS_TIMINT) { /* Timer 82C54-2 */
76633f810b2SJeff Kirsher timer_irq(smc) ;
76733f810b2SJeff Kirsher #ifdef NDIS_OS2
76833f810b2SJeff Kirsher force_irq_pending = 0 ;
76933f810b2SJeff Kirsher #endif
77033f810b2SJeff Kirsher /*
77133f810b2SJeff Kirsher * out of RxD detection
77233f810b2SJeff Kirsher */
77333f810b2SJeff Kirsher if (++smc->os.hwm.detec_count > 4) {
77433f810b2SJeff Kirsher /*
77533f810b2SJeff Kirsher * check out of RxD condition
77633f810b2SJeff Kirsher */
77733f810b2SJeff Kirsher process_receive(smc) ;
77833f810b2SJeff Kirsher }
77933f810b2SJeff Kirsher }
78033f810b2SJeff Kirsher if (is & IS_TOKEN) { /* Restricted Token Monitor */
78133f810b2SJeff Kirsher rtm_irq(smc) ;
78233f810b2SJeff Kirsher }
78333f810b2SJeff Kirsher if (is & IS_R1_P) { /* Parity error rx queue 1 */
78433f810b2SJeff Kirsher /* clear IRQ */
78533f810b2SJeff Kirsher outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
78633f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
78733f810b2SJeff Kirsher }
78833f810b2SJeff Kirsher if (is & IS_R1_C) { /* Encoding error rx queue 1 */
78933f810b2SJeff Kirsher /* clear IRQ */
79033f810b2SJeff Kirsher outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
79133f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
79233f810b2SJeff Kirsher }
79333f810b2SJeff Kirsher if (is & IS_XA_C) { /* Encoding error async tx q */
79433f810b2SJeff Kirsher /* clear IRQ */
79533f810b2SJeff Kirsher outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
79633f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
79733f810b2SJeff Kirsher }
79833f810b2SJeff Kirsher if (is & IS_XS_C) { /* Encoding error sync tx q */
79933f810b2SJeff Kirsher /* clear IRQ */
80033f810b2SJeff Kirsher outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
80133f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
80233f810b2SJeff Kirsher }
80333f810b2SJeff Kirsher }
80433f810b2SJeff Kirsher
80533f810b2SJeff Kirsher /*
80633f810b2SJeff Kirsher * Fast Tx complete Async/Sync Queue (BMU service)
80733f810b2SJeff Kirsher */
80833f810b2SJeff Kirsher if (is & (IS_XS_F|IS_XA_F)) {
8095dbc6530SJoe Perches DB_GEN(6, "Fast tx complete queue");
81033f810b2SJeff Kirsher /*
81133f810b2SJeff Kirsher * clear IRQ, Note: no IRQ is lost, because
81233f810b2SJeff Kirsher * we always service both queues
81333f810b2SJeff Kirsher */
81433f810b2SJeff Kirsher outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
81533f810b2SJeff Kirsher outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
81633f810b2SJeff Kirsher mac_drv_clear_txd(smc) ;
81733f810b2SJeff Kirsher llc_restart_tx(smc) ;
81833f810b2SJeff Kirsher }
81933f810b2SJeff Kirsher
82033f810b2SJeff Kirsher /*
82133f810b2SJeff Kirsher * Fast Rx Complete (BMU service)
82233f810b2SJeff Kirsher */
82333f810b2SJeff Kirsher if (is & IS_R1_F) {
8245dbc6530SJoe Perches DB_GEN(6, "Fast receive complete");
82533f810b2SJeff Kirsher /* clear IRQ */
82633f810b2SJeff Kirsher #ifndef USE_BREAK_ISR
82733f810b2SJeff Kirsher outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
82833f810b2SJeff Kirsher process_receive(smc) ;
82933f810b2SJeff Kirsher #else
83033f810b2SJeff Kirsher process_receive(smc) ;
83133f810b2SJeff Kirsher if (smc->os.hwm.leave_isr) {
83233f810b2SJeff Kirsher force_irq = FALSE ;
83333f810b2SJeff Kirsher } else {
83433f810b2SJeff Kirsher outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
83533f810b2SJeff Kirsher process_receive(smc) ;
83633f810b2SJeff Kirsher }
83733f810b2SJeff Kirsher #endif
83833f810b2SJeff Kirsher }
83933f810b2SJeff Kirsher
84033f810b2SJeff Kirsher #ifndef NDIS_OS2
84133f810b2SJeff Kirsher while ((mb = get_llc_rx(smc))) {
84233f810b2SJeff Kirsher smt_to_llc(smc,mb) ;
84333f810b2SJeff Kirsher }
84433f810b2SJeff Kirsher #else
84533f810b2SJeff Kirsher if (offDepth)
84633f810b2SJeff Kirsher post_proc() ;
84733f810b2SJeff Kirsher
84833f810b2SJeff Kirsher while (!offDepth && (mb = get_llc_rx(smc))) {
84933f810b2SJeff Kirsher smt_to_llc(smc,mb) ;
85033f810b2SJeff Kirsher }
85133f810b2SJeff Kirsher
85233f810b2SJeff Kirsher if (!offDepth && smc->os.hwm.rx_break) {
85333f810b2SJeff Kirsher process_receive(smc) ;
85433f810b2SJeff Kirsher }
85533f810b2SJeff Kirsher #endif
85633f810b2SJeff Kirsher if (smc->q.ev_get != smc->q.ev_put) {
85733f810b2SJeff Kirsher NDD_TRACE("CH2a",0,0,0) ;
85833f810b2SJeff Kirsher ev_dispatcher(smc) ;
85933f810b2SJeff Kirsher }
86033f810b2SJeff Kirsher #ifdef NDIS_OS2
86133f810b2SJeff Kirsher post_proc() ;
86233f810b2SJeff Kirsher if (offDepth) { /* leave fddi_isr because */
86333f810b2SJeff Kirsher break ; /* indications not allowed */
86433f810b2SJeff Kirsher }
86533f810b2SJeff Kirsher #endif
86633f810b2SJeff Kirsher #ifdef USE_BREAK_ISR
86733f810b2SJeff Kirsher if (smc->os.hwm.leave_isr) {
86833f810b2SJeff Kirsher break ; /* leave fddi_isr */
86933f810b2SJeff Kirsher }
87033f810b2SJeff Kirsher #endif
87133f810b2SJeff Kirsher
87233f810b2SJeff Kirsher /* NOTE: when the isr is left, no rx is pending */
87333f810b2SJeff Kirsher } /* end of interrupt source polling loop */
87433f810b2SJeff Kirsher
87533f810b2SJeff Kirsher #ifdef USE_BREAK_ISR
87633f810b2SJeff Kirsher if (smc->os.hwm.leave_isr && force_irq) {
87733f810b2SJeff Kirsher smt_force_irq(smc) ;
87833f810b2SJeff Kirsher }
87933f810b2SJeff Kirsher #endif
88033f810b2SJeff Kirsher smc->os.hwm.isr_flag = FALSE ;
88133f810b2SJeff Kirsher NDD_TRACE("CH0E",0,0,0) ;
88233f810b2SJeff Kirsher }
88333f810b2SJeff Kirsher
88433f810b2SJeff Kirsher
88533f810b2SJeff Kirsher /*
88633f810b2SJeff Kirsher -------------------------------------------------------------
88733f810b2SJeff Kirsher RECEIVE FUNCTIONS:
88833f810b2SJeff Kirsher -------------------------------------------------------------
88933f810b2SJeff Kirsher */
89033f810b2SJeff Kirsher
89133f810b2SJeff Kirsher #ifndef NDIS_OS2
89233f810b2SJeff Kirsher /*
89333f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)
89433f810b2SJeff Kirsher * void mac_drv_rx_mode(smc,mode)
89533f810b2SJeff Kirsher *
89633f810b2SJeff Kirsher * function DOWNCALL (fplus.c)
89733f810b2SJeff Kirsher * Corresponding to the parameter mode, the operating system
89833f810b2SJeff Kirsher * dependent module can activate several receive modes.
89933f810b2SJeff Kirsher *
90033f810b2SJeff Kirsher * para mode = 1: RX_ENABLE_ALLMULTI enable all multicasts
90133f810b2SJeff Kirsher * = 2: RX_DISABLE_ALLMULTI disable "enable all multicasts"
90233f810b2SJeff Kirsher * = 3: RX_ENABLE_PROMISC enable promiscuous
90333f810b2SJeff Kirsher * = 4: RX_DISABLE_PROMISC disable promiscuous
90433f810b2SJeff Kirsher * = 5: RX_ENABLE_NSA enable rec. of all NSA frames
90533f810b2SJeff Kirsher * (disabled after 'driver reset' & 'set station address')
90633f810b2SJeff Kirsher * = 6: RX_DISABLE_NSA disable rec. of all NSA frames
90733f810b2SJeff Kirsher *
90833f810b2SJeff Kirsher * = 21: RX_ENABLE_PASS_SMT ( see description )
90933f810b2SJeff Kirsher * = 22: RX_DISABLE_PASS_SMT ( " " )
91033f810b2SJeff Kirsher * = 23: RX_ENABLE_PASS_NSA ( " " )
91133f810b2SJeff Kirsher * = 24: RX_DISABLE_PASS_NSA ( " " )
91233f810b2SJeff Kirsher * = 25: RX_ENABLE_PASS_DB ( " " )
91333f810b2SJeff Kirsher * = 26: RX_DISABLE_PASS_DB ( " " )
91433f810b2SJeff Kirsher * = 27: RX_DISABLE_PASS_ALL ( " " )
91533f810b2SJeff Kirsher * = 28: RX_DISABLE_LLC_PROMISC ( " " )
91633f810b2SJeff Kirsher * = 29: RX_ENABLE_LLC_PROMISC ( " " )
91733f810b2SJeff Kirsher *
91833f810b2SJeff Kirsher *
91933f810b2SJeff Kirsher * RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT
92033f810b2SJeff Kirsher *
92133f810b2SJeff Kirsher * If the operating system dependent module activates the
92233f810b2SJeff Kirsher * mode RX_ENABLE_PASS_SMT, the hardware module
92333f810b2SJeff Kirsher * duplicates all SMT frames with the frame control
92433f810b2SJeff Kirsher * FC_SMT_INFO and passes them to the LLC receive channel
92533f810b2SJeff Kirsher * by calling mac_drv_rx_init.
92633f810b2SJeff Kirsher * The SMT Frames which are sent by the local SMT and the NSA
92733f810b2SJeff Kirsher * frames whose A- and C-Indicator is not set are also duplicated
92833f810b2SJeff Kirsher * and passed.
92933f810b2SJeff Kirsher * The receive mode RX_DISABLE_PASS_SMT disables the passing
93033f810b2SJeff Kirsher * of SMT frames.
93133f810b2SJeff Kirsher *
93233f810b2SJeff Kirsher * RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA
93333f810b2SJeff Kirsher *
93433f810b2SJeff Kirsher * If the operating system dependent module activates the
93533f810b2SJeff Kirsher * mode RX_ENABLE_PASS_NSA, the hardware module
93633f810b2SJeff Kirsher * duplicates all NSA frames with frame control FC_SMT_NSA
93733f810b2SJeff Kirsher * and a set A-Indicator and passed them to the LLC
93833f810b2SJeff Kirsher * receive channel by calling mac_drv_rx_init.
93933f810b2SJeff Kirsher * All NSA Frames which are sent by the local SMT
94033f810b2SJeff Kirsher * are also duplicated and passed.
94133f810b2SJeff Kirsher * The receive mode RX_DISABLE_PASS_NSA disables the passing
94233f810b2SJeff Kirsher * of NSA frames with the A- or C-Indicator set.
94333f810b2SJeff Kirsher *
94433f810b2SJeff Kirsher * NOTE: For fear that the hardware module receives NSA frames with
94533f810b2SJeff Kirsher * a reset A-Indicator, the operating system dependent module
94633f810b2SJeff Kirsher * has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA
94733f810b2SJeff Kirsher * before activate the RX_ENABLE_PASS_NSA mode and after every
94833f810b2SJeff Kirsher * 'driver reset' and 'set station address'.
94933f810b2SJeff Kirsher *
95033f810b2SJeff Kirsher * RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB
95133f810b2SJeff Kirsher *
95233f810b2SJeff Kirsher * If the operating system dependent module activates the
95333f810b2SJeff Kirsher * mode RX_ENABLE_PASS_DB, direct BEACON frames
95433f810b2SJeff Kirsher * (FC_BEACON frame control) are passed to the LLC receive
95533f810b2SJeff Kirsher * channel by mac_drv_rx_init.
95633f810b2SJeff Kirsher * The receive mode RX_DISABLE_PASS_DB disables the passing
95733f810b2SJeff Kirsher * of direct BEACON frames.
95833f810b2SJeff Kirsher *
95933f810b2SJeff Kirsher * RX_DISABLE_PASS_ALL
96033f810b2SJeff Kirsher *
96133f810b2SJeff Kirsher * Disables all special receives modes. It is equal to
96233f810b2SJeff Kirsher * call mac_drv_set_rx_mode successively with the
96333f810b2SJeff Kirsher * parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,
96433f810b2SJeff Kirsher * RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.
96533f810b2SJeff Kirsher *
96633f810b2SJeff Kirsher * RX_ENABLE_LLC_PROMISC
96733f810b2SJeff Kirsher *
96833f810b2SJeff Kirsher * (default) all received LLC frames and all SMT/NSA/DBEACON
96933f810b2SJeff Kirsher * frames depending on the attitude of the flags
97033f810b2SJeff Kirsher * PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the
97133f810b2SJeff Kirsher * LLC layer
97233f810b2SJeff Kirsher *
97333f810b2SJeff Kirsher * RX_DISABLE_LLC_PROMISC
97433f810b2SJeff Kirsher *
97533f810b2SJeff Kirsher * all received SMT/NSA/DBEACON frames depending on the
97633f810b2SJeff Kirsher * attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON
97733f810b2SJeff Kirsher * will be delivered to the LLC layer.
97833f810b2SJeff Kirsher * all received LLC frames with a directed address, Multicast
97933f810b2SJeff Kirsher * or Broadcast address will be delivered to the LLC
98033f810b2SJeff Kirsher * layer too.
98133f810b2SJeff Kirsher *
98233f810b2SJeff Kirsher * END_MANUAL_ENTRY
98333f810b2SJeff Kirsher */
mac_drv_rx_mode(struct s_smc * smc,int mode)98433f810b2SJeff Kirsher void mac_drv_rx_mode(struct s_smc *smc, int mode)
98533f810b2SJeff Kirsher {
98633f810b2SJeff Kirsher switch(mode) {
98733f810b2SJeff Kirsher case RX_ENABLE_PASS_SMT:
98833f810b2SJeff Kirsher smc->os.hwm.pass_SMT = TRUE ;
98933f810b2SJeff Kirsher break ;
99033f810b2SJeff Kirsher case RX_DISABLE_PASS_SMT:
99133f810b2SJeff Kirsher smc->os.hwm.pass_SMT = FALSE ;
99233f810b2SJeff Kirsher break ;
99333f810b2SJeff Kirsher case RX_ENABLE_PASS_NSA:
99433f810b2SJeff Kirsher smc->os.hwm.pass_NSA = TRUE ;
99533f810b2SJeff Kirsher break ;
99633f810b2SJeff Kirsher case RX_DISABLE_PASS_NSA:
99733f810b2SJeff Kirsher smc->os.hwm.pass_NSA = FALSE ;
99833f810b2SJeff Kirsher break ;
99933f810b2SJeff Kirsher case RX_ENABLE_PASS_DB:
100033f810b2SJeff Kirsher smc->os.hwm.pass_DB = TRUE ;
100133f810b2SJeff Kirsher break ;
100233f810b2SJeff Kirsher case RX_DISABLE_PASS_DB:
100333f810b2SJeff Kirsher smc->os.hwm.pass_DB = FALSE ;
100433f810b2SJeff Kirsher break ;
100533f810b2SJeff Kirsher case RX_DISABLE_PASS_ALL:
100633f810b2SJeff Kirsher smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
100733f810b2SJeff Kirsher smc->os.hwm.pass_DB = FALSE ;
100833f810b2SJeff Kirsher smc->os.hwm.pass_llc_promisc = TRUE ;
100933f810b2SJeff Kirsher mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
101033f810b2SJeff Kirsher break ;
101133f810b2SJeff Kirsher case RX_DISABLE_LLC_PROMISC:
101233f810b2SJeff Kirsher smc->os.hwm.pass_llc_promisc = FALSE ;
101333f810b2SJeff Kirsher break ;
101433f810b2SJeff Kirsher case RX_ENABLE_LLC_PROMISC:
101533f810b2SJeff Kirsher smc->os.hwm.pass_llc_promisc = TRUE ;
101633f810b2SJeff Kirsher break ;
101733f810b2SJeff Kirsher case RX_ENABLE_ALLMULTI:
101833f810b2SJeff Kirsher case RX_DISABLE_ALLMULTI:
101933f810b2SJeff Kirsher case RX_ENABLE_PROMISC:
102033f810b2SJeff Kirsher case RX_DISABLE_PROMISC:
102133f810b2SJeff Kirsher case RX_ENABLE_NSA:
102233f810b2SJeff Kirsher case RX_DISABLE_NSA:
102333f810b2SJeff Kirsher default:
102433f810b2SJeff Kirsher mac_set_rx_mode(smc,mode) ;
102533f810b2SJeff Kirsher break ;
102633f810b2SJeff Kirsher }
102733f810b2SJeff Kirsher }
102833f810b2SJeff Kirsher #endif /* ifndef NDIS_OS2 */
102933f810b2SJeff Kirsher
103033f810b2SJeff Kirsher /*
103133f810b2SJeff Kirsher * process receive queue
103233f810b2SJeff Kirsher */
process_receive(struct s_smc * smc)103333f810b2SJeff Kirsher void process_receive(struct s_smc *smc)
103433f810b2SJeff Kirsher {
103533f810b2SJeff Kirsher int i ;
103633f810b2SJeff Kirsher int n ;
103733f810b2SJeff Kirsher int frag_count ; /* number of RxDs of the curr rx buf */
103833f810b2SJeff Kirsher int used_frags ; /* number of RxDs of the curr frame */
103933f810b2SJeff Kirsher struct s_smt_rx_queue *queue ; /* points to the queue ctl struct */
104033f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *r ; /* rxd pointer */
104133f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *rxd ; /* first rxd of rx frame */
104233f810b2SJeff Kirsher u_long rbctrl ; /* receive buffer control word */
104333f810b2SJeff Kirsher u_long rfsw ; /* receive frame status word */
104433f810b2SJeff Kirsher u_short rx_used ;
104533f810b2SJeff Kirsher u_char far *virt ;
104633f810b2SJeff Kirsher char far *data ;
104733f810b2SJeff Kirsher SMbuf *mb ;
104833f810b2SJeff Kirsher u_char fc ; /* Frame control */
104933f810b2SJeff Kirsher int len ; /* Frame length */
105033f810b2SJeff Kirsher
105133f810b2SJeff Kirsher smc->os.hwm.detec_count = 0 ;
105233f810b2SJeff Kirsher queue = smc->hw.fp.rx[QUEUE_R1] ;
105333f810b2SJeff Kirsher NDD_TRACE("RHxB",0,0,0) ;
105433f810b2SJeff Kirsher for ( ; ; ) {
105533f810b2SJeff Kirsher r = queue->rx_curr_get ;
105633f810b2SJeff Kirsher rx_used = queue->rx_used ;
105733f810b2SJeff Kirsher frag_count = 0 ;
105833f810b2SJeff Kirsher
105933f810b2SJeff Kirsher #ifdef USE_BREAK_ISR
106033f810b2SJeff Kirsher if (smc->os.hwm.leave_isr) {
106133f810b2SJeff Kirsher goto rx_end ;
106233f810b2SJeff Kirsher }
106333f810b2SJeff Kirsher #endif
106433f810b2SJeff Kirsher #ifdef NDIS_OS2
106533f810b2SJeff Kirsher if (offDepth) {
106633f810b2SJeff Kirsher smc->os.hwm.rx_break = 1 ;
106733f810b2SJeff Kirsher goto rx_end ;
106833f810b2SJeff Kirsher }
106933f810b2SJeff Kirsher smc->os.hwm.rx_break = 0 ;
107033f810b2SJeff Kirsher #endif
107133f810b2SJeff Kirsher #ifdef ODI2
107233f810b2SJeff Kirsher if (smc->os.hwm.rx_break) {
107333f810b2SJeff Kirsher goto rx_end ;
107433f810b2SJeff Kirsher }
107533f810b2SJeff Kirsher #endif
107633f810b2SJeff Kirsher n = 0 ;
107733f810b2SJeff Kirsher do {
10785dbc6530SJoe Perches DB_RX(5, "Check RxD %p for OWN and EOF", r);
107933f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
108033f810b2SJeff Kirsher rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));
108133f810b2SJeff Kirsher
108233f810b2SJeff Kirsher if (rbctrl & BMU_OWN) {
108333f810b2SJeff Kirsher NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
10845dbc6530SJoe Perches DB_RX(4, "End of RxDs");
108533f810b2SJeff Kirsher goto rx_end ;
108633f810b2SJeff Kirsher }
108733f810b2SJeff Kirsher /*
108833f810b2SJeff Kirsher * out of RxD detection
108933f810b2SJeff Kirsher */
109033f810b2SJeff Kirsher if (!rx_used) {
109133f810b2SJeff Kirsher SK_BREAK() ;
109233f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
109333f810b2SJeff Kirsher /* Either we don't have an RxD or all
109433f810b2SJeff Kirsher * RxDs are filled. Therefore it's allowed
109533f810b2SJeff Kirsher * for to set the STOPPED flag */
109633f810b2SJeff Kirsher smc->hw.hw_state = STOPPED ;
109733f810b2SJeff Kirsher mac_drv_clear_rx_queue(smc) ;
109833f810b2SJeff Kirsher smc->hw.hw_state = STARTED ;
109933f810b2SJeff Kirsher mac_drv_fill_rxd(smc) ;
110033f810b2SJeff Kirsher smc->os.hwm.detec_count = 0 ;
110133f810b2SJeff Kirsher goto rx_end ;
110233f810b2SJeff Kirsher }
110333f810b2SJeff Kirsher rfsw = le32_to_cpu(r->rxd_rfsw) ;
110433f810b2SJeff Kirsher if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
110533f810b2SJeff Kirsher /*
110633f810b2SJeff Kirsher * The BMU_STF bit is deleted, 1 frame is
110733f810b2SJeff Kirsher * placed into more than 1 rx buffer
110833f810b2SJeff Kirsher *
110933f810b2SJeff Kirsher * skip frame by setting the rx len to 0
111033f810b2SJeff Kirsher *
111133f810b2SJeff Kirsher * if fragment count == 0
111233f810b2SJeff Kirsher * The missing STF bit belongs to the
111333f810b2SJeff Kirsher * current frame, search for the
111433f810b2SJeff Kirsher * EOF bit to complete the frame
111533f810b2SJeff Kirsher * else
111633f810b2SJeff Kirsher * the fragment belongs to the next frame,
111733f810b2SJeff Kirsher * exit the loop and process the frame
111833f810b2SJeff Kirsher */
111933f810b2SJeff Kirsher SK_BREAK() ;
112033f810b2SJeff Kirsher rfsw = 0 ;
112133f810b2SJeff Kirsher if (frag_count) {
112233f810b2SJeff Kirsher break ;
112333f810b2SJeff Kirsher }
112433f810b2SJeff Kirsher }
112533f810b2SJeff Kirsher n += rbctrl & 0xffff ;
112633f810b2SJeff Kirsher r = r->rxd_next ;
112733f810b2SJeff Kirsher frag_count++ ;
112833f810b2SJeff Kirsher rx_used-- ;
112933f810b2SJeff Kirsher } while (!(rbctrl & BMU_EOF)) ;
113033f810b2SJeff Kirsher used_frags = frag_count ;
11315dbc6530SJoe Perches DB_RX(5, "EOF set in RxD, used_frags = %d", used_frags);
113233f810b2SJeff Kirsher
113333f810b2SJeff Kirsher /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
113433f810b2SJeff Kirsher /* BMU_ST_BUF will not be changed by the ASIC */
113533f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
113633f810b2SJeff Kirsher while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
11375dbc6530SJoe Perches DB_RX(5, "Check STF bit in %p", r);
113833f810b2SJeff Kirsher r = r->rxd_next ;
113933f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
114033f810b2SJeff Kirsher frag_count++ ;
114133f810b2SJeff Kirsher rx_used-- ;
114233f810b2SJeff Kirsher }
11435dbc6530SJoe Perches DB_RX(5, "STF bit found");
114433f810b2SJeff Kirsher
114533f810b2SJeff Kirsher /*
114633f810b2SJeff Kirsher * The received frame is finished for the process receive
114733f810b2SJeff Kirsher */
114833f810b2SJeff Kirsher rxd = queue->rx_curr_get ;
114933f810b2SJeff Kirsher queue->rx_curr_get = r ;
115033f810b2SJeff Kirsher queue->rx_free += frag_count ;
115133f810b2SJeff Kirsher queue->rx_used = rx_used ;
115233f810b2SJeff Kirsher
115333f810b2SJeff Kirsher /*
115433f810b2SJeff Kirsher * ASIC Errata no. 7 (STF - Bit Bug)
115533f810b2SJeff Kirsher */
115633f810b2SJeff Kirsher rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;
115733f810b2SJeff Kirsher
115833f810b2SJeff Kirsher for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
11595dbc6530SJoe Perches DB_RX(5, "dma_complete for RxD %p", r);
116033f810b2SJeff Kirsher dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
116133f810b2SJeff Kirsher }
116233f810b2SJeff Kirsher smc->hw.fp.err_stats.err_valid++ ;
116333f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
116433f810b2SJeff Kirsher
116533f810b2SJeff Kirsher /* the length of the data including the FC */
116633f810b2SJeff Kirsher len = (rfsw & RD_LENGTH) - 4 ;
116733f810b2SJeff Kirsher
11685dbc6530SJoe Perches DB_RX(4, "frame length = %d", len);
116933f810b2SJeff Kirsher /*
117033f810b2SJeff Kirsher * check the frame_length and all error flags
117133f810b2SJeff Kirsher */
117233f810b2SJeff Kirsher if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
117333f810b2SJeff Kirsher if (rfsw & RD_S_MSRABT) {
11745dbc6530SJoe Perches DB_RX(2, "Frame aborted by the FORMAC");
117533f810b2SJeff Kirsher smc->hw.fp.err_stats.err_abort++ ;
117633f810b2SJeff Kirsher }
117733f810b2SJeff Kirsher /*
117833f810b2SJeff Kirsher * check frame status
117933f810b2SJeff Kirsher */
118033f810b2SJeff Kirsher if (rfsw & RD_S_SEAC2) {
11815dbc6530SJoe Perches DB_RX(2, "E-Indicator set");
118233f810b2SJeff Kirsher smc->hw.fp.err_stats.err_e_indicator++ ;
118333f810b2SJeff Kirsher }
118433f810b2SJeff Kirsher if (rfsw & RD_S_SFRMERR) {
11855dbc6530SJoe Perches DB_RX(2, "CRC error");
118633f810b2SJeff Kirsher smc->hw.fp.err_stats.err_crc++ ;
118733f810b2SJeff Kirsher }
118833f810b2SJeff Kirsher if (rfsw & RX_FS_IMPL) {
11895dbc6530SJoe Perches DB_RX(2, "Implementer frame");
119033f810b2SJeff Kirsher smc->hw.fp.err_stats.err_imp_frame++ ;
119133f810b2SJeff Kirsher }
119233f810b2SJeff Kirsher goto abort_frame ;
119333f810b2SJeff Kirsher }
119433f810b2SJeff Kirsher if (len > FDDI_RAW_MTU-4) {
11955dbc6530SJoe Perches DB_RX(2, "Frame too long error");
119633f810b2SJeff Kirsher smc->hw.fp.err_stats.err_too_long++ ;
119733f810b2SJeff Kirsher goto abort_frame ;
119833f810b2SJeff Kirsher }
119933f810b2SJeff Kirsher /*
120033f810b2SJeff Kirsher * SUPERNET 3 Bug: FORMAC delivers status words
1201d97c6f68SWeitao Hou * of aborted frames to the BMU
120233f810b2SJeff Kirsher */
120333f810b2SJeff Kirsher if (len <= 4) {
12045dbc6530SJoe Perches DB_RX(2, "Frame length = 0");
120533f810b2SJeff Kirsher goto abort_frame ;
120633f810b2SJeff Kirsher }
120733f810b2SJeff Kirsher
120833f810b2SJeff Kirsher if (len != (n-4)) {
12095dbc6530SJoe Perches DB_RX(4, "BMU: rx len differs: [%d:%d]", len, n);
121033f810b2SJeff Kirsher smc->os.hwm.rx_len_error++ ;
121133f810b2SJeff Kirsher goto abort_frame ;
121233f810b2SJeff Kirsher }
121333f810b2SJeff Kirsher
121433f810b2SJeff Kirsher /*
121533f810b2SJeff Kirsher * Check SA == MA
121633f810b2SJeff Kirsher */
121733f810b2SJeff Kirsher virt = (u_char far *) rxd->rxd_virt ;
12185dbc6530SJoe Perches DB_RX(2, "FC = %x", *virt);
121933f810b2SJeff Kirsher if (virt[12] == MA[5] &&
122033f810b2SJeff Kirsher virt[11] == MA[4] &&
122133f810b2SJeff Kirsher virt[10] == MA[3] &&
122233f810b2SJeff Kirsher virt[9] == MA[2] &&
122333f810b2SJeff Kirsher virt[8] == MA[1] &&
122433f810b2SJeff Kirsher (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
122533f810b2SJeff Kirsher goto abort_frame ;
122633f810b2SJeff Kirsher }
122733f810b2SJeff Kirsher
122833f810b2SJeff Kirsher /*
122933f810b2SJeff Kirsher * test if LLC frame
123033f810b2SJeff Kirsher */
123133f810b2SJeff Kirsher if (rfsw & RX_FS_LLC) {
123233f810b2SJeff Kirsher /*
123333f810b2SJeff Kirsher * if pass_llc_promisc is disable
123433f810b2SJeff Kirsher * if DA != Multicast or Broadcast or DA!=MA
123533f810b2SJeff Kirsher * abort the frame
123633f810b2SJeff Kirsher */
123733f810b2SJeff Kirsher if (!smc->os.hwm.pass_llc_promisc) {
123833f810b2SJeff Kirsher if(!(virt[1] & GROUP_ADDR_BIT)) {
123933f810b2SJeff Kirsher if (virt[6] != MA[5] ||
124033f810b2SJeff Kirsher virt[5] != MA[4] ||
124133f810b2SJeff Kirsher virt[4] != MA[3] ||
124233f810b2SJeff Kirsher virt[3] != MA[2] ||
124333f810b2SJeff Kirsher virt[2] != MA[1] ||
124433f810b2SJeff Kirsher virt[1] != MA[0]) {
12455dbc6530SJoe Perches DB_RX(2, "DA != MA and not multi- or broadcast");
124633f810b2SJeff Kirsher goto abort_frame ;
124733f810b2SJeff Kirsher }
124833f810b2SJeff Kirsher }
124933f810b2SJeff Kirsher }
125033f810b2SJeff Kirsher
125133f810b2SJeff Kirsher /*
125233f810b2SJeff Kirsher * LLC frame received
125333f810b2SJeff Kirsher */
12545dbc6530SJoe Perches DB_RX(4, "LLC - receive");
125533f810b2SJeff Kirsher mac_drv_rx_complete(smc,rxd,frag_count,len) ;
125633f810b2SJeff Kirsher }
125733f810b2SJeff Kirsher else {
125833f810b2SJeff Kirsher if (!(mb = smt_get_mbuf(smc))) {
125933f810b2SJeff Kirsher smc->hw.fp.err_stats.err_no_buf++ ;
12605dbc6530SJoe Perches DB_RX(4, "No SMbuf; receive terminated");
126133f810b2SJeff Kirsher goto abort_frame ;
126233f810b2SJeff Kirsher }
126333f810b2SJeff Kirsher data = smtod(mb,char *) - 1 ;
126433f810b2SJeff Kirsher
126533f810b2SJeff Kirsher /*
126633f810b2SJeff Kirsher * copy the frame into a SMT_MBuf
126733f810b2SJeff Kirsher */
126833f810b2SJeff Kirsher #ifdef USE_OS_CPY
126933f810b2SJeff Kirsher hwm_cpy_rxd2mb(rxd,data,len) ;
127033f810b2SJeff Kirsher #else
127133f810b2SJeff Kirsher for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
127233f810b2SJeff Kirsher n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
12735dbc6530SJoe Perches DB_RX(6, "cp SMT frame to mb: len = %d", n);
127433f810b2SJeff Kirsher memcpy(data,r->rxd_virt,n) ;
127533f810b2SJeff Kirsher data += n ;
127633f810b2SJeff Kirsher }
127733f810b2SJeff Kirsher data = smtod(mb,char *) - 1 ;
127833f810b2SJeff Kirsher #endif
127933f810b2SJeff Kirsher fc = *(char *)mb->sm_data = *data ;
128033f810b2SJeff Kirsher mb->sm_len = len - 1 ; /* len - fc */
128133f810b2SJeff Kirsher data++ ;
128233f810b2SJeff Kirsher
128333f810b2SJeff Kirsher /*
128433f810b2SJeff Kirsher * SMT frame received
128533f810b2SJeff Kirsher */
128633f810b2SJeff Kirsher switch(fc) {
128733f810b2SJeff Kirsher case FC_SMT_INFO :
128833f810b2SJeff Kirsher smc->hw.fp.err_stats.err_smt_frame++ ;
12895dbc6530SJoe Perches DB_RX(5, "SMT frame received");
129033f810b2SJeff Kirsher
129133f810b2SJeff Kirsher if (smc->os.hwm.pass_SMT) {
12925dbc6530SJoe Perches DB_RX(5, "pass SMT frame");
129333f810b2SJeff Kirsher mac_drv_rx_complete(smc, rxd,
129433f810b2SJeff Kirsher frag_count,len) ;
129533f810b2SJeff Kirsher }
129633f810b2SJeff Kirsher else {
12975dbc6530SJoe Perches DB_RX(5, "requeue RxD");
129833f810b2SJeff Kirsher mac_drv_requeue_rxd(smc,rxd,frag_count);
129933f810b2SJeff Kirsher }
130033f810b2SJeff Kirsher
130133f810b2SJeff Kirsher smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
130233f810b2SJeff Kirsher break ;
130333f810b2SJeff Kirsher case FC_SMT_NSA :
130433f810b2SJeff Kirsher smc->hw.fp.err_stats.err_smt_frame++ ;
13055dbc6530SJoe Perches DB_RX(5, "SMT frame received");
130633f810b2SJeff Kirsher
130733f810b2SJeff Kirsher /* if pass_NSA set pass the NSA frame or */
130833f810b2SJeff Kirsher /* pass_SMT set and the A-Indicator */
130933f810b2SJeff Kirsher /* is not set, pass the NSA frame */
131033f810b2SJeff Kirsher if (smc->os.hwm.pass_NSA ||
131133f810b2SJeff Kirsher (smc->os.hwm.pass_SMT &&
131233f810b2SJeff Kirsher !(rfsw & A_INDIC))) {
13135dbc6530SJoe Perches DB_RX(5, "pass SMT frame");
131433f810b2SJeff Kirsher mac_drv_rx_complete(smc, rxd,
131533f810b2SJeff Kirsher frag_count,len) ;
131633f810b2SJeff Kirsher }
131733f810b2SJeff Kirsher else {
13185dbc6530SJoe Perches DB_RX(5, "requeue RxD");
131933f810b2SJeff Kirsher mac_drv_requeue_rxd(smc,rxd,frag_count);
132033f810b2SJeff Kirsher }
132133f810b2SJeff Kirsher
132233f810b2SJeff Kirsher smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
132333f810b2SJeff Kirsher break ;
132433f810b2SJeff Kirsher case FC_BEACON :
132533f810b2SJeff Kirsher if (smc->os.hwm.pass_DB) {
13265dbc6530SJoe Perches DB_RX(5, "pass DB frame");
132733f810b2SJeff Kirsher mac_drv_rx_complete(smc, rxd,
132833f810b2SJeff Kirsher frag_count,len) ;
132933f810b2SJeff Kirsher }
133033f810b2SJeff Kirsher else {
13315dbc6530SJoe Perches DB_RX(5, "requeue RxD");
133233f810b2SJeff Kirsher mac_drv_requeue_rxd(smc,rxd,frag_count);
133333f810b2SJeff Kirsher }
133433f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
133533f810b2SJeff Kirsher break ;
133633f810b2SJeff Kirsher default :
133733f810b2SJeff Kirsher /*
1338d97c6f68SWeitao Hou * unknown FC abort the frame
133933f810b2SJeff Kirsher */
13405dbc6530SJoe Perches DB_RX(2, "unknown FC error");
134133f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
13425dbc6530SJoe Perches DB_RX(5, "requeue RxD");
134333f810b2SJeff Kirsher mac_drv_requeue_rxd(smc,rxd,frag_count) ;
134433f810b2SJeff Kirsher if ((fc & 0xf0) == FC_MAC)
134533f810b2SJeff Kirsher smc->hw.fp.err_stats.err_mac_frame++ ;
134633f810b2SJeff Kirsher else
134733f810b2SJeff Kirsher smc->hw.fp.err_stats.err_imp_frame++ ;
134833f810b2SJeff Kirsher
134933f810b2SJeff Kirsher break ;
135033f810b2SJeff Kirsher }
135133f810b2SJeff Kirsher }
135233f810b2SJeff Kirsher
13535dbc6530SJoe Perches DB_RX(3, "next RxD is %p", queue->rx_curr_get);
135433f810b2SJeff Kirsher NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
135533f810b2SJeff Kirsher
135633f810b2SJeff Kirsher continue ;
135733f810b2SJeff Kirsher /*--------------------------------------------------------------------*/
135833f810b2SJeff Kirsher abort_frame:
13595dbc6530SJoe Perches DB_RX(5, "requeue RxD");
136033f810b2SJeff Kirsher mac_drv_requeue_rxd(smc,rxd,frag_count) ;
136133f810b2SJeff Kirsher
13625dbc6530SJoe Perches DB_RX(3, "next RxD is %p", queue->rx_curr_get);
136333f810b2SJeff Kirsher NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
136433f810b2SJeff Kirsher }
136533f810b2SJeff Kirsher rx_end:
136633f810b2SJeff Kirsher #ifdef ALL_RX_COMPLETE
136733f810b2SJeff Kirsher mac_drv_all_receives_complete(smc) ;
136833f810b2SJeff Kirsher #endif
136933f810b2SJeff Kirsher return ; /* lint bug: needs return detect end of function */
137033f810b2SJeff Kirsher }
137133f810b2SJeff Kirsher
smt_to_llc(struct s_smc * smc,SMbuf * mb)137233f810b2SJeff Kirsher static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
137333f810b2SJeff Kirsher {
137433f810b2SJeff Kirsher u_char fc ;
137533f810b2SJeff Kirsher
13765dbc6530SJoe Perches DB_RX(4, "send a queued frame to the llc layer");
137733f810b2SJeff Kirsher smc->os.hwm.r.len = mb->sm_len ;
137833f810b2SJeff Kirsher smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
137933f810b2SJeff Kirsher fc = *smc->os.hwm.r.mb_pos ;
138033f810b2SJeff Kirsher (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
138133f810b2SJeff Kirsher smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
138233f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
138333f810b2SJeff Kirsher }
138433f810b2SJeff Kirsher
138533f810b2SJeff Kirsher /*
138633f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(hwm_rx_frag)
138733f810b2SJeff Kirsher * void hwm_rx_frag(smc,virt,phys,len,frame_status)
138833f810b2SJeff Kirsher *
138933f810b2SJeff Kirsher * function MACRO (hardware module, hwmtm.h)
139033f810b2SJeff Kirsher * This function calls dma_master for preparing the
139133f810b2SJeff Kirsher * system hardware for the DMA transfer and initializes
139233f810b2SJeff Kirsher * the current RxD with the length and the physical and
139333f810b2SJeff Kirsher * virtual address of the fragment. Furthermore, it sets the
139433f810b2SJeff Kirsher * STF and EOF bits depending on the frame status byte,
139533f810b2SJeff Kirsher * switches the OWN flag of the RxD, so that it is owned by the
139633f810b2SJeff Kirsher * adapter and issues an rx_start.
139733f810b2SJeff Kirsher *
139833f810b2SJeff Kirsher * para virt virtual pointer to the fragment
139933f810b2SJeff Kirsher * len the length of the fragment
140033f810b2SJeff Kirsher * frame_status status of the frame, see design description
140133f810b2SJeff Kirsher *
140233f810b2SJeff Kirsher * NOTE: It is possible to call this function with a fragment length
140333f810b2SJeff Kirsher * of zero.
140433f810b2SJeff Kirsher *
140533f810b2SJeff Kirsher * END_MANUAL_ENTRY
140633f810b2SJeff Kirsher */
hwm_rx_frag(struct s_smc * smc,char far * virt,u_long phys,int len,int frame_status)140733f810b2SJeff Kirsher void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
140833f810b2SJeff Kirsher int frame_status)
140933f810b2SJeff Kirsher {
141033f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *r ;
141133f810b2SJeff Kirsher __le32 rbctrl;
141233f810b2SJeff Kirsher
141333f810b2SJeff Kirsher NDD_TRACE("RHfB",virt,len,frame_status) ;
14145dbc6530SJoe Perches DB_RX(2, "hwm_rx_frag: len = %d, frame_status = %x", len, frame_status);
141533f810b2SJeff Kirsher r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
141633f810b2SJeff Kirsher r->rxd_virt = virt ;
141733f810b2SJeff Kirsher r->rxd_rbadr = cpu_to_le32(phys) ;
141833f810b2SJeff Kirsher rbctrl = cpu_to_le32( (((__u32)frame_status &
141933f810b2SJeff Kirsher (FIRST_FRAG|LAST_FRAG))<<26) |
142033f810b2SJeff Kirsher (((u_long) frame_status & FIRST_FRAG) << 21) |
142133f810b2SJeff Kirsher BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
142233f810b2SJeff Kirsher r->rxd_rbctrl = rbctrl ;
142333f810b2SJeff Kirsher
142433f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
142533f810b2SJeff Kirsher outpd(ADDR(B0_R1_CSR),CSR_START) ;
142633f810b2SJeff Kirsher smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
142733f810b2SJeff Kirsher smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
142833f810b2SJeff Kirsher smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
142933f810b2SJeff Kirsher NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;
143033f810b2SJeff Kirsher }
143133f810b2SJeff Kirsher
143233f810b2SJeff Kirsher /*
143333f810b2SJeff Kirsher * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
143433f810b2SJeff Kirsher *
143533f810b2SJeff Kirsher * void mac_drv_clear_rx_queue(smc)
143633f810b2SJeff Kirsher * struct s_smc *smc ;
143733f810b2SJeff Kirsher *
143833f810b2SJeff Kirsher * function DOWNCALL (hardware module, hwmtm.c)
143933f810b2SJeff Kirsher * mac_drv_clear_rx_queue is called by the OS-specific module
144033f810b2SJeff Kirsher * after it has issued a card_stop.
144133f810b2SJeff Kirsher * In this case, the frames in the receive queue are obsolete and
144233f810b2SJeff Kirsher * should be removed. For removing mac_drv_clear_rx_queue
144333f810b2SJeff Kirsher * calls dma_master for each RxD and mac_drv_clear_rxd for each
144433f810b2SJeff Kirsher * receive buffer.
144533f810b2SJeff Kirsher *
144633f810b2SJeff Kirsher * NOTE: calling sequence card_stop:
144733f810b2SJeff Kirsher * CLI_FBI(), card_stop(),
144833f810b2SJeff Kirsher * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
144933f810b2SJeff Kirsher *
145033f810b2SJeff Kirsher * NOTE: The caller is responsible that the BMUs are idle
145133f810b2SJeff Kirsher * when this function is called.
145233f810b2SJeff Kirsher *
145333f810b2SJeff Kirsher * END_MANUAL_ENTRY
145433f810b2SJeff Kirsher */
mac_drv_clear_rx_queue(struct s_smc * smc)145533f810b2SJeff Kirsher void mac_drv_clear_rx_queue(struct s_smc *smc)
145633f810b2SJeff Kirsher {
145733f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *r ;
145833f810b2SJeff Kirsher struct s_smt_fp_rxd volatile *next_rxd ;
145933f810b2SJeff Kirsher struct s_smt_rx_queue *queue ;
146033f810b2SJeff Kirsher int frag_count ;
146133f810b2SJeff Kirsher int i ;
146233f810b2SJeff Kirsher
146333f810b2SJeff Kirsher if (smc->hw.hw_state != STOPPED) {
146433f810b2SJeff Kirsher SK_BREAK() ;
146533f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
146633f810b2SJeff Kirsher return ;
146733f810b2SJeff Kirsher }
146833f810b2SJeff Kirsher
146933f810b2SJeff Kirsher queue = smc->hw.fp.rx[QUEUE_R1] ;
14705dbc6530SJoe Perches DB_RX(5, "clear_rx_queue");
147133f810b2SJeff Kirsher
147233f810b2SJeff Kirsher /*
147333f810b2SJeff Kirsher * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers
147433f810b2SJeff Kirsher */
147533f810b2SJeff Kirsher r = queue->rx_curr_get ;
147633f810b2SJeff Kirsher while (queue->rx_used) {
147733f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
14785dbc6530SJoe Perches DB_RX(5, "switch OWN bit of RxD 0x%p", r);
147933f810b2SJeff Kirsher r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
148033f810b2SJeff Kirsher frag_count = 1 ;
148133f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
148233f810b2SJeff Kirsher r = r->rxd_next ;
148333f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
148433f810b2SJeff Kirsher while (r != queue->rx_curr_put &&
148533f810b2SJeff Kirsher !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
14865dbc6530SJoe Perches DB_RX(5, "Check STF bit in %p", r);
148733f810b2SJeff Kirsher r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
148833f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
148933f810b2SJeff Kirsher r = r->rxd_next ;
149033f810b2SJeff Kirsher DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
149133f810b2SJeff Kirsher frag_count++ ;
149233f810b2SJeff Kirsher }
14935dbc6530SJoe Perches DB_RX(5, "STF bit found");
149433f810b2SJeff Kirsher next_rxd = r ;
149533f810b2SJeff Kirsher
149633f810b2SJeff Kirsher for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
14975dbc6530SJoe Perches DB_RX(5, "dma_complete for RxD %p", r);
149833f810b2SJeff Kirsher dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
149933f810b2SJeff Kirsher }
150033f810b2SJeff Kirsher
15015dbc6530SJoe Perches DB_RX(5, "mac_drv_clear_rxd: RxD %p frag_count %d",
15025dbc6530SJoe Perches queue->rx_curr_get, frag_count);
150333f810b2SJeff Kirsher mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
150433f810b2SJeff Kirsher
150533f810b2SJeff Kirsher queue->rx_curr_get = next_rxd ;
150633f810b2SJeff Kirsher queue->rx_used -= frag_count ;
150733f810b2SJeff Kirsher queue->rx_free += frag_count ;
150833f810b2SJeff Kirsher }
150933f810b2SJeff Kirsher }
151033f810b2SJeff Kirsher
151133f810b2SJeff Kirsher
151233f810b2SJeff Kirsher /*
151333f810b2SJeff Kirsher -------------------------------------------------------------
151433f810b2SJeff Kirsher SEND FUNCTIONS:
151533f810b2SJeff Kirsher -------------------------------------------------------------
151633f810b2SJeff Kirsher */
151733f810b2SJeff Kirsher
151833f810b2SJeff Kirsher /*
151933f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(hwm_tx_init)
152033f810b2SJeff Kirsher * int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
152133f810b2SJeff Kirsher *
152233f810b2SJeff Kirsher * function DOWN_CALL (hardware module, hwmtm.c)
152333f810b2SJeff Kirsher * hwm_tx_init checks if the frame can be sent through the
152433f810b2SJeff Kirsher * corresponding send queue.
152533f810b2SJeff Kirsher *
152633f810b2SJeff Kirsher * para fc the frame control. To determine through which
152733f810b2SJeff Kirsher * send queue the frame should be transmitted.
152833f810b2SJeff Kirsher * 0x50 - 0x57: asynchronous LLC frame
152933f810b2SJeff Kirsher * 0xD0 - 0xD7: synchronous LLC frame
153033f810b2SJeff Kirsher * 0x41, 0x4F: SMT frame to the network
153133f810b2SJeff Kirsher * 0x42: SMT frame to the network and to the local SMT
153233f810b2SJeff Kirsher * 0x43: SMT frame to the local SMT
153333f810b2SJeff Kirsher * frag_count count of the fragments for this frame
153433f810b2SJeff Kirsher * frame_len length of the frame
153533f810b2SJeff Kirsher * frame_status status of the frame, the send queue bit is already
153633f810b2SJeff Kirsher * specified
153733f810b2SJeff Kirsher *
153833f810b2SJeff Kirsher * return frame_status
153933f810b2SJeff Kirsher *
154033f810b2SJeff Kirsher * END_MANUAL_ENTRY
154133f810b2SJeff Kirsher */
hwm_tx_init(struct s_smc * smc,u_char fc,int frag_count,int frame_len,int frame_status)154233f810b2SJeff Kirsher int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
154333f810b2SJeff Kirsher int frame_status)
154433f810b2SJeff Kirsher {
154533f810b2SJeff Kirsher NDD_TRACE("THiB",fc,frag_count,frame_len) ;
154633f810b2SJeff Kirsher smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
154733f810b2SJeff Kirsher smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
154833f810b2SJeff Kirsher smc->os.hwm.tx_len = frame_len ;
15495dbc6530SJoe Perches DB_TX(3, "hwm_tx_init: fc = %x, len = %d", fc, frame_len);
155033f810b2SJeff Kirsher if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
155133f810b2SJeff Kirsher frame_status |= LAN_TX ;
155233f810b2SJeff Kirsher }
155333f810b2SJeff Kirsher else {
155433f810b2SJeff Kirsher switch (fc) {
155533f810b2SJeff Kirsher case FC_SMT_INFO :
155633f810b2SJeff Kirsher case FC_SMT_NSA :
155733f810b2SJeff Kirsher frame_status |= LAN_TX ;
155833f810b2SJeff Kirsher break ;
155933f810b2SJeff Kirsher case FC_SMT_LOC :
156033f810b2SJeff Kirsher frame_status |= LOC_TX ;
156133f810b2SJeff Kirsher break ;
156233f810b2SJeff Kirsher case FC_SMT_LAN_LOC :
156333f810b2SJeff Kirsher frame_status |= LAN_TX | LOC_TX ;
156433f810b2SJeff Kirsher break ;
156533f810b2SJeff Kirsher default :
156633f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
156733f810b2SJeff Kirsher }
156833f810b2SJeff Kirsher }
156933f810b2SJeff Kirsher if (!smc->hw.mac_ring_is_up) {
157033f810b2SJeff Kirsher frame_status &= ~LAN_TX ;
157133f810b2SJeff Kirsher frame_status |= RING_DOWN ;
15725dbc6530SJoe Perches DB_TX(2, "Ring is down: terminate LAN_TX");
157333f810b2SJeff Kirsher }
157433f810b2SJeff Kirsher if (frag_count > smc->os.hwm.tx_p->tx_free) {
157533f810b2SJeff Kirsher #ifndef NDIS_OS2
157633f810b2SJeff Kirsher mac_drv_clear_txd(smc) ;
157733f810b2SJeff Kirsher if (frag_count > smc->os.hwm.tx_p->tx_free) {
15785dbc6530SJoe Perches DB_TX(2, "Out of TxDs, terminate LAN_TX");
157933f810b2SJeff Kirsher frame_status &= ~LAN_TX ;
158033f810b2SJeff Kirsher frame_status |= OUT_OF_TXD ;
158133f810b2SJeff Kirsher }
158233f810b2SJeff Kirsher #else
15835dbc6530SJoe Perches DB_TX(2, "Out of TxDs, terminate LAN_TX");
158433f810b2SJeff Kirsher frame_status &= ~LAN_TX ;
158533f810b2SJeff Kirsher frame_status |= OUT_OF_TXD ;
158633f810b2SJeff Kirsher #endif
158733f810b2SJeff Kirsher }
15885dbc6530SJoe Perches DB_TX(3, "frame_status = %x", frame_status);
158933f810b2SJeff Kirsher NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
159033f810b2SJeff Kirsher return frame_status;
159133f810b2SJeff Kirsher }
159233f810b2SJeff Kirsher
159333f810b2SJeff Kirsher /*
159433f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(hwm_tx_frag)
159533f810b2SJeff Kirsher * void hwm_tx_frag(smc,virt,phys,len,frame_status)
159633f810b2SJeff Kirsher *
159733f810b2SJeff Kirsher * function DOWNCALL (hardware module, hwmtm.c)
159833f810b2SJeff Kirsher * If the frame should be sent to the LAN, this function calls
159933f810b2SJeff Kirsher * dma_master, fills the current TxD with the virtual and the
160033f810b2SJeff Kirsher * physical address, sets the STF and EOF bits dependent on
160133f810b2SJeff Kirsher * the frame status, and requests the BMU to start the
160233f810b2SJeff Kirsher * transmit.
160333f810b2SJeff Kirsher * If the frame should be sent to the local SMT, an SMT_MBuf
160433f810b2SJeff Kirsher * is allocated if the FIRST_FRAG bit is set in the frame_status.
160533f810b2SJeff Kirsher * The fragment of the frame is copied into the SMT MBuf.
160633f810b2SJeff Kirsher * The function smt_received_pack is called if the LAST_FRAG
160733f810b2SJeff Kirsher * bit is set in the frame_status word.
160833f810b2SJeff Kirsher *
160933f810b2SJeff Kirsher * para virt virtual pointer to the fragment
161033f810b2SJeff Kirsher * len the length of the fragment
161133f810b2SJeff Kirsher * frame_status status of the frame, see design description
161233f810b2SJeff Kirsher *
161333f810b2SJeff Kirsher * return nothing returned, no parameter is modified
161433f810b2SJeff Kirsher *
161533f810b2SJeff Kirsher * NOTE: It is possible to invoke this macro with a fragment length
161633f810b2SJeff Kirsher * of zero.
161733f810b2SJeff Kirsher *
161833f810b2SJeff Kirsher * END_MANUAL_ENTRY
161933f810b2SJeff Kirsher */
hwm_tx_frag(struct s_smc * smc,char far * virt,u_long phys,int len,int frame_status)162033f810b2SJeff Kirsher void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
162133f810b2SJeff Kirsher int frame_status)
162233f810b2SJeff Kirsher {
162333f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t ;
162433f810b2SJeff Kirsher struct s_smt_tx_queue *queue ;
162533f810b2SJeff Kirsher __le32 tbctrl ;
162633f810b2SJeff Kirsher
162733f810b2SJeff Kirsher queue = smc->os.hwm.tx_p ;
162833f810b2SJeff Kirsher
162933f810b2SJeff Kirsher NDD_TRACE("THfB",virt,len,frame_status) ;
163033f810b2SJeff Kirsher /* Bug fix: AF / May 31 1999 (#missing)
163133f810b2SJeff Kirsher * snmpinfo problem reported by IBM is caused by invalid
163233f810b2SJeff Kirsher * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
163333f810b2SJeff Kirsher * Set: t = queue->tx_curr_put here !
163433f810b2SJeff Kirsher */
163533f810b2SJeff Kirsher t = queue->tx_curr_put ;
163633f810b2SJeff Kirsher
16375dbc6530SJoe Perches DB_TX(2, "hwm_tx_frag: len = %d, frame_status = %x", len, frame_status);
163833f810b2SJeff Kirsher if (frame_status & LAN_TX) {
163933f810b2SJeff Kirsher /* '*t' is already defined */
16405dbc6530SJoe Perches DB_TX(3, "LAN_TX: TxD = %p, virt = %p", t, virt);
164133f810b2SJeff Kirsher t->txd_virt = virt ;
164233f810b2SJeff Kirsher t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
164333f810b2SJeff Kirsher t->txd_tbadr = cpu_to_le32(phys) ;
164433f810b2SJeff Kirsher tbctrl = cpu_to_le32((((__u32)frame_status &
164533f810b2SJeff Kirsher (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
164633f810b2SJeff Kirsher BMU_OWN|BMU_CHECK |len) ;
164733f810b2SJeff Kirsher t->txd_tbctrl = tbctrl ;
164833f810b2SJeff Kirsher
164933f810b2SJeff Kirsher #ifndef AIX
165033f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
165133f810b2SJeff Kirsher outpd(queue->tx_bmu_ctl,CSR_START) ;
165233f810b2SJeff Kirsher #else /* ifndef AIX */
165333f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
165433f810b2SJeff Kirsher if (frame_status & QUEUE_A0) {
165533f810b2SJeff Kirsher outpd(ADDR(B0_XA_CSR),CSR_START) ;
165633f810b2SJeff Kirsher }
165733f810b2SJeff Kirsher else {
165833f810b2SJeff Kirsher outpd(ADDR(B0_XS_CSR),CSR_START) ;
165933f810b2SJeff Kirsher }
166033f810b2SJeff Kirsher #endif
166133f810b2SJeff Kirsher queue->tx_free-- ;
166233f810b2SJeff Kirsher queue->tx_used++ ;
166333f810b2SJeff Kirsher queue->tx_curr_put = t->txd_next ;
166433f810b2SJeff Kirsher if (frame_status & LAST_FRAG) {
166533f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
166633f810b2SJeff Kirsher }
166733f810b2SJeff Kirsher }
166833f810b2SJeff Kirsher if (frame_status & LOC_TX) {
16695dbc6530SJoe Perches DB_TX(3, "LOC_TX:");
167033f810b2SJeff Kirsher if (frame_status & FIRST_FRAG) {
167133f810b2SJeff Kirsher if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
167233f810b2SJeff Kirsher smc->hw.fp.err_stats.err_no_buf++ ;
16735dbc6530SJoe Perches DB_TX(4, "No SMbuf; transmit terminated");
167433f810b2SJeff Kirsher }
167533f810b2SJeff Kirsher else {
167633f810b2SJeff Kirsher smc->os.hwm.tx_data =
167733f810b2SJeff Kirsher smtod(smc->os.hwm.tx_mb,char *) - 1 ;
167833f810b2SJeff Kirsher #ifdef USE_OS_CPY
167933f810b2SJeff Kirsher #ifdef PASS_1ST_TXD_2_TX_COMP
168033f810b2SJeff Kirsher hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
168133f810b2SJeff Kirsher smc->os.hwm.tx_len) ;
168233f810b2SJeff Kirsher #endif
168333f810b2SJeff Kirsher #endif
168433f810b2SJeff Kirsher }
168533f810b2SJeff Kirsher }
168633f810b2SJeff Kirsher if (smc->os.hwm.tx_mb) {
168733f810b2SJeff Kirsher #ifndef USE_OS_CPY
16885dbc6530SJoe Perches DB_TX(3, "copy fragment into MBuf");
168933f810b2SJeff Kirsher memcpy(smc->os.hwm.tx_data,virt,len) ;
169033f810b2SJeff Kirsher smc->os.hwm.tx_data += len ;
169133f810b2SJeff Kirsher #endif
169233f810b2SJeff Kirsher if (frame_status & LAST_FRAG) {
169333f810b2SJeff Kirsher #ifdef USE_OS_CPY
169433f810b2SJeff Kirsher #ifndef PASS_1ST_TXD_2_TX_COMP
169533f810b2SJeff Kirsher /*
169633f810b2SJeff Kirsher * hwm_cpy_txd2mb(txd,data,len) copies 'len'
169733f810b2SJeff Kirsher * bytes from the virtual pointer in 'rxd'
169833f810b2SJeff Kirsher * to 'data'. The virtual pointer of the
169933f810b2SJeff Kirsher * os-specific tx-buffer should be written
170033f810b2SJeff Kirsher * in the LAST txd.
170133f810b2SJeff Kirsher */
170233f810b2SJeff Kirsher hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
170333f810b2SJeff Kirsher smc->os.hwm.tx_len) ;
170433f810b2SJeff Kirsher #endif /* nPASS_1ST_TXD_2_TX_COMP */
170533f810b2SJeff Kirsher #endif /* USE_OS_CPY */
170633f810b2SJeff Kirsher smc->os.hwm.tx_data =
170733f810b2SJeff Kirsher smtod(smc->os.hwm.tx_mb,char *) - 1 ;
170833f810b2SJeff Kirsher *(char *)smc->os.hwm.tx_mb->sm_data =
170933f810b2SJeff Kirsher *smc->os.hwm.tx_data ;
171033f810b2SJeff Kirsher smc->os.hwm.tx_data++ ;
171133f810b2SJeff Kirsher smc->os.hwm.tx_mb->sm_len =
171233f810b2SJeff Kirsher smc->os.hwm.tx_len - 1 ;
17135dbc6530SJoe Perches DB_TX(3, "pass LLC frame to SMT");
171433f810b2SJeff Kirsher smt_received_pack(smc,smc->os.hwm.tx_mb,
171533f810b2SJeff Kirsher RD_FS_LOCAL) ;
171633f810b2SJeff Kirsher }
171733f810b2SJeff Kirsher }
171833f810b2SJeff Kirsher }
171933f810b2SJeff Kirsher NDD_TRACE("THfE",t,queue->tx_free,0) ;
172033f810b2SJeff Kirsher }
172133f810b2SJeff Kirsher
172233f810b2SJeff Kirsher
172333f810b2SJeff Kirsher /*
172433f810b2SJeff Kirsher * queues a receive for later send
172533f810b2SJeff Kirsher */
queue_llc_rx(struct s_smc * smc,SMbuf * mb)172633f810b2SJeff Kirsher static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
172733f810b2SJeff Kirsher {
17285dbc6530SJoe Perches DB_GEN(4, "queue_llc_rx: mb = %p", mb);
172933f810b2SJeff Kirsher smc->os.hwm.queued_rx_frames++ ;
173033f810b2SJeff Kirsher mb->sm_next = (SMbuf *)NULL ;
173133f810b2SJeff Kirsher if (smc->os.hwm.llc_rx_pipe == NULL) {
173233f810b2SJeff Kirsher smc->os.hwm.llc_rx_pipe = mb ;
173333f810b2SJeff Kirsher }
173433f810b2SJeff Kirsher else {
173533f810b2SJeff Kirsher smc->os.hwm.llc_rx_tail->sm_next = mb ;
173633f810b2SJeff Kirsher }
173733f810b2SJeff Kirsher smc->os.hwm.llc_rx_tail = mb ;
173833f810b2SJeff Kirsher
173933f810b2SJeff Kirsher /*
174033f810b2SJeff Kirsher * force an timer IRQ to receive the data
174133f810b2SJeff Kirsher */
174233f810b2SJeff Kirsher if (!smc->os.hwm.isr_flag) {
174333f810b2SJeff Kirsher smt_force_irq(smc) ;
174433f810b2SJeff Kirsher }
174533f810b2SJeff Kirsher }
174633f810b2SJeff Kirsher
174733f810b2SJeff Kirsher /*
174833f810b2SJeff Kirsher * get a SMbuf from the llc_rx_queue
174933f810b2SJeff Kirsher */
get_llc_rx(struct s_smc * smc)175033f810b2SJeff Kirsher static SMbuf *get_llc_rx(struct s_smc *smc)
175133f810b2SJeff Kirsher {
175233f810b2SJeff Kirsher SMbuf *mb ;
175333f810b2SJeff Kirsher
175433f810b2SJeff Kirsher if ((mb = smc->os.hwm.llc_rx_pipe)) {
175533f810b2SJeff Kirsher smc->os.hwm.queued_rx_frames-- ;
175633f810b2SJeff Kirsher smc->os.hwm.llc_rx_pipe = mb->sm_next ;
175733f810b2SJeff Kirsher }
17585dbc6530SJoe Perches DB_GEN(4, "get_llc_rx: mb = 0x%p", mb);
175933f810b2SJeff Kirsher return mb;
176033f810b2SJeff Kirsher }
176133f810b2SJeff Kirsher
176233f810b2SJeff Kirsher /*
176333f810b2SJeff Kirsher * queues a transmit SMT MBuf during the time were the MBuf is
176433f810b2SJeff Kirsher * queued the TxD ring
176533f810b2SJeff Kirsher */
queue_txd_mb(struct s_smc * smc,SMbuf * mb)176633f810b2SJeff Kirsher static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
176733f810b2SJeff Kirsher {
17685dbc6530SJoe Perches DB_GEN(4, "_rx: queue_txd_mb = %p", mb);
176933f810b2SJeff Kirsher smc->os.hwm.queued_txd_mb++ ;
177033f810b2SJeff Kirsher mb->sm_next = (SMbuf *)NULL ;
177133f810b2SJeff Kirsher if (smc->os.hwm.txd_tx_pipe == NULL) {
177233f810b2SJeff Kirsher smc->os.hwm.txd_tx_pipe = mb ;
177333f810b2SJeff Kirsher }
177433f810b2SJeff Kirsher else {
177533f810b2SJeff Kirsher smc->os.hwm.txd_tx_tail->sm_next = mb ;
177633f810b2SJeff Kirsher }
177733f810b2SJeff Kirsher smc->os.hwm.txd_tx_tail = mb ;
177833f810b2SJeff Kirsher }
177933f810b2SJeff Kirsher
178033f810b2SJeff Kirsher /*
178133f810b2SJeff Kirsher * get a SMbuf from the txd_tx_queue
178233f810b2SJeff Kirsher */
get_txd_mb(struct s_smc * smc)178333f810b2SJeff Kirsher static SMbuf *get_txd_mb(struct s_smc *smc)
178433f810b2SJeff Kirsher {
178533f810b2SJeff Kirsher SMbuf *mb ;
178633f810b2SJeff Kirsher
178733f810b2SJeff Kirsher if ((mb = smc->os.hwm.txd_tx_pipe)) {
178833f810b2SJeff Kirsher smc->os.hwm.queued_txd_mb-- ;
178933f810b2SJeff Kirsher smc->os.hwm.txd_tx_pipe = mb->sm_next ;
179033f810b2SJeff Kirsher }
17915dbc6530SJoe Perches DB_GEN(4, "get_txd_mb: mb = 0x%p", mb);
179233f810b2SJeff Kirsher return mb;
179333f810b2SJeff Kirsher }
179433f810b2SJeff Kirsher
179533f810b2SJeff Kirsher /*
179633f810b2SJeff Kirsher * SMT Send function
179733f810b2SJeff Kirsher */
smt_send_mbuf(struct s_smc * smc,SMbuf * mb,int fc)179833f810b2SJeff Kirsher void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
179933f810b2SJeff Kirsher {
180033f810b2SJeff Kirsher char far *data ;
180133f810b2SJeff Kirsher int len ;
180233f810b2SJeff Kirsher int n ;
180333f810b2SJeff Kirsher int i ;
180433f810b2SJeff Kirsher int frag_count ;
180533f810b2SJeff Kirsher int frame_status ;
180633f810b2SJeff Kirsher SK_LOC_DECL(char far,*virt[3]) ;
180733f810b2SJeff Kirsher int frag_len[3] ;
180833f810b2SJeff Kirsher struct s_smt_tx_queue *queue ;
180933f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t ;
181033f810b2SJeff Kirsher u_long phys ;
181133f810b2SJeff Kirsher __le32 tbctrl;
181233f810b2SJeff Kirsher
181333f810b2SJeff Kirsher NDD_TRACE("THSB",mb,fc,0) ;
18145dbc6530SJoe Perches DB_TX(4, "smt_send_mbuf: mb = 0x%p, fc = 0x%x", mb, fc);
181533f810b2SJeff Kirsher
181633f810b2SJeff Kirsher mb->sm_off-- ; /* set to fc */
181733f810b2SJeff Kirsher mb->sm_len++ ; /* + fc */
181833f810b2SJeff Kirsher data = smtod(mb,char *) ;
181933f810b2SJeff Kirsher *data = fc ;
182033f810b2SJeff Kirsher if (fc == FC_SMT_LOC)
182133f810b2SJeff Kirsher *data = FC_SMT_INFO ;
182233f810b2SJeff Kirsher
182333f810b2SJeff Kirsher /*
182433f810b2SJeff Kirsher * determine the frag count and the virt addresses of the frags
182533f810b2SJeff Kirsher */
182633f810b2SJeff Kirsher frag_count = 0 ;
182733f810b2SJeff Kirsher len = mb->sm_len ;
182833f810b2SJeff Kirsher while (len) {
182933f810b2SJeff Kirsher n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;
183033f810b2SJeff Kirsher if (n >= len) {
183133f810b2SJeff Kirsher n = len ;
183233f810b2SJeff Kirsher }
18335dbc6530SJoe Perches DB_TX(5, "frag: virt/len = 0x%p/%d", data, n);
183433f810b2SJeff Kirsher virt[frag_count] = data ;
183533f810b2SJeff Kirsher frag_len[frag_count] = n ;
183633f810b2SJeff Kirsher frag_count++ ;
183733f810b2SJeff Kirsher len -= n ;
183833f810b2SJeff Kirsher data += n ;
183933f810b2SJeff Kirsher }
184033f810b2SJeff Kirsher
184133f810b2SJeff Kirsher /*
184233f810b2SJeff Kirsher * determine the frame status
184333f810b2SJeff Kirsher */
184433f810b2SJeff Kirsher queue = smc->hw.fp.tx[QUEUE_A0] ;
184533f810b2SJeff Kirsher if (fc == FC_BEACON || fc == FC_SMT_LOC) {
184633f810b2SJeff Kirsher frame_status = LOC_TX ;
184733f810b2SJeff Kirsher }
184833f810b2SJeff Kirsher else {
184933f810b2SJeff Kirsher frame_status = LAN_TX ;
185033f810b2SJeff Kirsher if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
185133f810b2SJeff Kirsher (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
185233f810b2SJeff Kirsher frame_status |= LOC_TX ;
185333f810b2SJeff Kirsher }
185433f810b2SJeff Kirsher
185533f810b2SJeff Kirsher if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
185633f810b2SJeff Kirsher frame_status &= ~LAN_TX;
185733f810b2SJeff Kirsher if (frame_status) {
18585dbc6530SJoe Perches DB_TX(2, "Ring is down: terminate LAN_TX");
185933f810b2SJeff Kirsher }
186033f810b2SJeff Kirsher else {
18615dbc6530SJoe Perches DB_TX(2, "Ring is down: terminate transmission");
186233f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
186333f810b2SJeff Kirsher return ;
186433f810b2SJeff Kirsher }
186533f810b2SJeff Kirsher }
18665dbc6530SJoe Perches DB_TX(5, "frame_status = 0x%x", frame_status);
186733f810b2SJeff Kirsher
186833f810b2SJeff Kirsher if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
186933f810b2SJeff Kirsher mb->sm_use_count = 2 ;
187033f810b2SJeff Kirsher }
187133f810b2SJeff Kirsher
187233f810b2SJeff Kirsher if (frame_status & LAN_TX) {
187333f810b2SJeff Kirsher t = queue->tx_curr_put ;
187433f810b2SJeff Kirsher frame_status |= FIRST_FRAG ;
187533f810b2SJeff Kirsher for (i = 0; i < frag_count; i++) {
18765dbc6530SJoe Perches DB_TX(5, "init TxD = 0x%p", t);
187733f810b2SJeff Kirsher if (i == frag_count-1) {
187833f810b2SJeff Kirsher frame_status |= LAST_FRAG ;
187933f810b2SJeff Kirsher t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |
188033f810b2SJeff Kirsher (((__u32)(mb->sm_len-1)&3) << 27)) ;
188133f810b2SJeff Kirsher }
188233f810b2SJeff Kirsher t->txd_virt = virt[i] ;
188333f810b2SJeff Kirsher phys = dma_master(smc, (void far *)virt[i],
188433f810b2SJeff Kirsher frag_len[i], DMA_RD|SMT_BUF) ;
188533f810b2SJeff Kirsher t->txd_tbadr = cpu_to_le32(phys) ;
188633f810b2SJeff Kirsher tbctrl = cpu_to_le32((((__u32)frame_status &
188733f810b2SJeff Kirsher (FIRST_FRAG|LAST_FRAG)) << 26) |
188833f810b2SJeff Kirsher BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
188933f810b2SJeff Kirsher t->txd_tbctrl = tbctrl ;
189033f810b2SJeff Kirsher #ifndef AIX
189133f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
189233f810b2SJeff Kirsher outpd(queue->tx_bmu_ctl,CSR_START) ;
189333f810b2SJeff Kirsher #else
189433f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
189533f810b2SJeff Kirsher outpd(ADDR(B0_XA_CSR),CSR_START) ;
189633f810b2SJeff Kirsher #endif
189733f810b2SJeff Kirsher frame_status &= ~FIRST_FRAG ;
189833f810b2SJeff Kirsher queue->tx_curr_put = t = t->txd_next ;
189933f810b2SJeff Kirsher queue->tx_free-- ;
190033f810b2SJeff Kirsher queue->tx_used++ ;
190133f810b2SJeff Kirsher }
190233f810b2SJeff Kirsher smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
190333f810b2SJeff Kirsher queue_txd_mb(smc,mb) ;
190433f810b2SJeff Kirsher }
190533f810b2SJeff Kirsher
190633f810b2SJeff Kirsher if (frame_status & LOC_TX) {
19075dbc6530SJoe Perches DB_TX(5, "pass Mbuf to LLC queue");
190833f810b2SJeff Kirsher queue_llc_rx(smc,mb) ;
190933f810b2SJeff Kirsher }
191033f810b2SJeff Kirsher
191133f810b2SJeff Kirsher /*
191233f810b2SJeff Kirsher * We need to unqueue the free SMT_MBUFs here, because it may
191333f810b2SJeff Kirsher * be that the SMT want's to send more than 1 frame for one down call
191433f810b2SJeff Kirsher */
191533f810b2SJeff Kirsher mac_drv_clear_txd(smc) ;
191633f810b2SJeff Kirsher NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
191733f810b2SJeff Kirsher }
191833f810b2SJeff Kirsher
191933f810b2SJeff Kirsher /* BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)
192033f810b2SJeff Kirsher * void mac_drv_clear_txd(smc)
192133f810b2SJeff Kirsher *
192233f810b2SJeff Kirsher * function DOWNCALL (hardware module, hwmtm.c)
192333f810b2SJeff Kirsher * mac_drv_clear_txd searches in both send queues for TxD's
192433f810b2SJeff Kirsher * which were finished by the adapter. It calls dma_complete
192533f810b2SJeff Kirsher * for each TxD. If the last fragment of an LLC frame is
192633f810b2SJeff Kirsher * reached, it calls mac_drv_tx_complete to release the
192733f810b2SJeff Kirsher * send buffer.
192833f810b2SJeff Kirsher *
192933f810b2SJeff Kirsher * return nothing
193033f810b2SJeff Kirsher *
193133f810b2SJeff Kirsher * END_MANUAL_ENTRY
193233f810b2SJeff Kirsher */
mac_drv_clear_txd(struct s_smc * smc)193333f810b2SJeff Kirsher static void mac_drv_clear_txd(struct s_smc *smc)
193433f810b2SJeff Kirsher {
193533f810b2SJeff Kirsher struct s_smt_tx_queue *queue ;
193633f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t1 ;
193733f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t2 = NULL ;
193833f810b2SJeff Kirsher SMbuf *mb ;
193933f810b2SJeff Kirsher u_long tbctrl ;
194033f810b2SJeff Kirsher int i ;
194133f810b2SJeff Kirsher int frag_count ;
194233f810b2SJeff Kirsher int n ;
194333f810b2SJeff Kirsher
194433f810b2SJeff Kirsher NDD_TRACE("THcB",0,0,0) ;
194533f810b2SJeff Kirsher for (i = QUEUE_S; i <= QUEUE_A0; i++) {
194633f810b2SJeff Kirsher queue = smc->hw.fp.tx[i] ;
194733f810b2SJeff Kirsher t1 = queue->tx_curr_get ;
19485dbc6530SJoe Perches DB_TX(5, "clear_txd: QUEUE = %d (0=sync/1=async)", i);
194933f810b2SJeff Kirsher
195033f810b2SJeff Kirsher for ( ; ; ) {
195133f810b2SJeff Kirsher frag_count = 0 ;
195233f810b2SJeff Kirsher
195333f810b2SJeff Kirsher do {
195433f810b2SJeff Kirsher DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
19555dbc6530SJoe Perches DB_TX(5, "check OWN/EOF bit of TxD 0x%p", t1);
195633f810b2SJeff Kirsher tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));
195733f810b2SJeff Kirsher
195833f810b2SJeff Kirsher if (tbctrl & BMU_OWN || !queue->tx_used){
19595dbc6530SJoe Perches DB_TX(4, "End of TxDs queue %d", i);
196033f810b2SJeff Kirsher goto free_next_queue ; /* next queue */
196133f810b2SJeff Kirsher }
196233f810b2SJeff Kirsher t1 = t1->txd_next ;
196333f810b2SJeff Kirsher frag_count++ ;
196433f810b2SJeff Kirsher } while (!(tbctrl & BMU_EOF)) ;
196533f810b2SJeff Kirsher
196633f810b2SJeff Kirsher t1 = queue->tx_curr_get ;
196733f810b2SJeff Kirsher for (n = frag_count; n; n--) {
196833f810b2SJeff Kirsher tbctrl = le32_to_cpu(t1->txd_tbctrl) ;
196933f810b2SJeff Kirsher dma_complete(smc,
197033f810b2SJeff Kirsher (union s_fp_descr volatile *) t1,
197133f810b2SJeff Kirsher (int) (DMA_RD |
197233f810b2SJeff Kirsher ((tbctrl & BMU_SMT_TX) >> 18))) ;
197333f810b2SJeff Kirsher t2 = t1 ;
197433f810b2SJeff Kirsher t1 = t1->txd_next ;
197533f810b2SJeff Kirsher }
197633f810b2SJeff Kirsher
197733f810b2SJeff Kirsher if (tbctrl & BMU_SMT_TX) {
197833f810b2SJeff Kirsher mb = get_txd_mb(smc) ;
197933f810b2SJeff Kirsher smt_free_mbuf(smc,mb) ;
198033f810b2SJeff Kirsher }
198133f810b2SJeff Kirsher else {
198233f810b2SJeff Kirsher #ifndef PASS_1ST_TXD_2_TX_COMP
19835dbc6530SJoe Perches DB_TX(4, "mac_drv_tx_comp for TxD 0x%p", t2);
198433f810b2SJeff Kirsher mac_drv_tx_complete(smc,t2) ;
198533f810b2SJeff Kirsher #else
19865dbc6530SJoe Perches DB_TX(4, "mac_drv_tx_comp for TxD 0x%x",
19875dbc6530SJoe Perches queue->tx_curr_get);
198833f810b2SJeff Kirsher mac_drv_tx_complete(smc,queue->tx_curr_get) ;
198933f810b2SJeff Kirsher #endif
199033f810b2SJeff Kirsher }
199133f810b2SJeff Kirsher queue->tx_curr_get = t1 ;
199233f810b2SJeff Kirsher queue->tx_free += frag_count ;
199333f810b2SJeff Kirsher queue->tx_used -= frag_count ;
199433f810b2SJeff Kirsher }
199533f810b2SJeff Kirsher free_next_queue: ;
199633f810b2SJeff Kirsher }
199733f810b2SJeff Kirsher NDD_TRACE("THcE",0,0,0) ;
199833f810b2SJeff Kirsher }
199933f810b2SJeff Kirsher
200033f810b2SJeff Kirsher /*
200133f810b2SJeff Kirsher * BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)
200233f810b2SJeff Kirsher *
200333f810b2SJeff Kirsher * void mac_drv_clear_tx_queue(smc)
200433f810b2SJeff Kirsher * struct s_smc *smc ;
200533f810b2SJeff Kirsher *
200633f810b2SJeff Kirsher * function DOWNCALL (hardware module, hwmtm.c)
200733f810b2SJeff Kirsher * mac_drv_clear_tx_queue is called from the SMT when
200833f810b2SJeff Kirsher * the RMT state machine has entered the ISOLATE state.
200933f810b2SJeff Kirsher * This function is also called by the os-specific module
201033f810b2SJeff Kirsher * after it has called the function card_stop().
201133f810b2SJeff Kirsher * In this case, the frames in the send queues are obsolete and
201233f810b2SJeff Kirsher * should be removed.
201333f810b2SJeff Kirsher *
201433f810b2SJeff Kirsher * note calling sequence:
201533f810b2SJeff Kirsher * CLI_FBI(), card_stop(),
201633f810b2SJeff Kirsher * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
201733f810b2SJeff Kirsher *
201833f810b2SJeff Kirsher * NOTE: The caller is responsible that the BMUs are idle
201933f810b2SJeff Kirsher * when this function is called.
202033f810b2SJeff Kirsher *
202133f810b2SJeff Kirsher * END_MANUAL_ENTRY
202233f810b2SJeff Kirsher */
mac_drv_clear_tx_queue(struct s_smc * smc)202333f810b2SJeff Kirsher void mac_drv_clear_tx_queue(struct s_smc *smc)
202433f810b2SJeff Kirsher {
202533f810b2SJeff Kirsher struct s_smt_fp_txd volatile *t ;
202633f810b2SJeff Kirsher struct s_smt_tx_queue *queue ;
202733f810b2SJeff Kirsher int tx_used ;
202833f810b2SJeff Kirsher int i ;
202933f810b2SJeff Kirsher
203033f810b2SJeff Kirsher if (smc->hw.hw_state != STOPPED) {
203133f810b2SJeff Kirsher SK_BREAK() ;
203233f810b2SJeff Kirsher SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
203333f810b2SJeff Kirsher return ;
203433f810b2SJeff Kirsher }
203533f810b2SJeff Kirsher
203633f810b2SJeff Kirsher for (i = QUEUE_S; i <= QUEUE_A0; i++) {
203733f810b2SJeff Kirsher queue = smc->hw.fp.tx[i] ;
20385dbc6530SJoe Perches DB_TX(5, "clear_tx_queue: QUEUE = %d (0=sync/1=async)", i);
203933f810b2SJeff Kirsher
204033f810b2SJeff Kirsher /*
204133f810b2SJeff Kirsher * switch the OWN bit of all pending frames to the host
204233f810b2SJeff Kirsher */
204333f810b2SJeff Kirsher t = queue->tx_curr_get ;
204433f810b2SJeff Kirsher tx_used = queue->tx_used ;
204533f810b2SJeff Kirsher while (tx_used) {
204633f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
20475dbc6530SJoe Perches DB_TX(5, "switch OWN bit of TxD 0x%p", t);
204833f810b2SJeff Kirsher t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
204933f810b2SJeff Kirsher DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
205033f810b2SJeff Kirsher t = t->txd_next ;
205133f810b2SJeff Kirsher tx_used-- ;
205233f810b2SJeff Kirsher }
205333f810b2SJeff Kirsher }
205433f810b2SJeff Kirsher
205533f810b2SJeff Kirsher /*
205633f810b2SJeff Kirsher * release all TxD's for both send queues
205733f810b2SJeff Kirsher */
205833f810b2SJeff Kirsher mac_drv_clear_txd(smc) ;
205933f810b2SJeff Kirsher
206033f810b2SJeff Kirsher for (i = QUEUE_S; i <= QUEUE_A0; i++) {
206133f810b2SJeff Kirsher queue = smc->hw.fp.tx[i] ;
206233f810b2SJeff Kirsher t = queue->tx_curr_get ;
206333f810b2SJeff Kirsher
206433f810b2SJeff Kirsher /*
206533f810b2SJeff Kirsher * write the phys pointer of the NEXT descriptor into the
206633f810b2SJeff Kirsher * BMU's current address descriptor pointer and set
206733f810b2SJeff Kirsher * tx_curr_get and tx_curr_put to this position
206833f810b2SJeff Kirsher */
206933f810b2SJeff Kirsher if (i == QUEUE_S) {
207033f810b2SJeff Kirsher outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;
207133f810b2SJeff Kirsher }
207233f810b2SJeff Kirsher else {
207333f810b2SJeff Kirsher outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;
207433f810b2SJeff Kirsher }
207533f810b2SJeff Kirsher
207633f810b2SJeff Kirsher queue->tx_curr_put = queue->tx_curr_get->txd_next ;
207733f810b2SJeff Kirsher queue->tx_curr_get = queue->tx_curr_put ;
207833f810b2SJeff Kirsher }
207933f810b2SJeff Kirsher }
208033f810b2SJeff Kirsher
208133f810b2SJeff Kirsher
208233f810b2SJeff Kirsher /*
208333f810b2SJeff Kirsher -------------------------------------------------------------
208433f810b2SJeff Kirsher TEST FUNCTIONS:
208533f810b2SJeff Kirsher -------------------------------------------------------------
208633f810b2SJeff Kirsher */
208733f810b2SJeff Kirsher
208833f810b2SJeff Kirsher #ifdef DEBUG
208933f810b2SJeff Kirsher /*
209033f810b2SJeff Kirsher * BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)
209133f810b2SJeff Kirsher * void mac_drv_debug_lev(smc,flag,lev)
209233f810b2SJeff Kirsher *
209333f810b2SJeff Kirsher * function DOWNCALL (drvsr.c)
209433f810b2SJeff Kirsher * To get a special debug info the user can assign a debug level
209533f810b2SJeff Kirsher * to any debug flag.
209633f810b2SJeff Kirsher *
209733f810b2SJeff Kirsher * para flag debug flag, possible values are:
209833f810b2SJeff Kirsher * = 0: reset all debug flags (the defined level is
209933f810b2SJeff Kirsher * ignored)
210033f810b2SJeff Kirsher * = 1: debug.d_smtf
210133f810b2SJeff Kirsher * = 2: debug.d_smt
210233f810b2SJeff Kirsher * = 3: debug.d_ecm
210333f810b2SJeff Kirsher * = 4: debug.d_rmt
210433f810b2SJeff Kirsher * = 5: debug.d_cfm
210533f810b2SJeff Kirsher * = 6: debug.d_pcm
210633f810b2SJeff Kirsher *
210733f810b2SJeff Kirsher * = 10: debug.d_os.hwm_rx (hardware module receive path)
210833f810b2SJeff Kirsher * = 11: debug.d_os.hwm_tx(hardware module transmit path)
210933f810b2SJeff Kirsher * = 12: debug.d_os.hwm_gen(hardware module general flag)
211033f810b2SJeff Kirsher *
211133f810b2SJeff Kirsher * lev debug level
211233f810b2SJeff Kirsher *
211333f810b2SJeff Kirsher * END_MANUAL_ENTRY
211433f810b2SJeff Kirsher */
mac_drv_debug_lev(struct s_smc * smc,int flag,int lev)211533f810b2SJeff Kirsher void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
211633f810b2SJeff Kirsher {
211733f810b2SJeff Kirsher switch(flag) {
211833f810b2SJeff Kirsher case (int)NULL:
211933f810b2SJeff Kirsher DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
212033f810b2SJeff Kirsher DB_P.d_cfm = 0 ;
212133f810b2SJeff Kirsher DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
212233f810b2SJeff Kirsher #ifdef SBA
212333f810b2SJeff Kirsher DB_P.d_sba = 0 ;
212433f810b2SJeff Kirsher #endif
212533f810b2SJeff Kirsher #ifdef ESS
212633f810b2SJeff Kirsher DB_P.d_ess = 0 ;
212733f810b2SJeff Kirsher #endif
212833f810b2SJeff Kirsher break ;
212933f810b2SJeff Kirsher case DEBUG_SMTF:
213033f810b2SJeff Kirsher DB_P.d_smtf = lev ;
213133f810b2SJeff Kirsher break ;
213233f810b2SJeff Kirsher case DEBUG_SMT:
213333f810b2SJeff Kirsher DB_P.d_smt = lev ;
213433f810b2SJeff Kirsher break ;
213533f810b2SJeff Kirsher case DEBUG_ECM:
213633f810b2SJeff Kirsher DB_P.d_ecm = lev ;
213733f810b2SJeff Kirsher break ;
213833f810b2SJeff Kirsher case DEBUG_RMT:
213933f810b2SJeff Kirsher DB_P.d_rmt = lev ;
214033f810b2SJeff Kirsher break ;
214133f810b2SJeff Kirsher case DEBUG_CFM:
214233f810b2SJeff Kirsher DB_P.d_cfm = lev ;
214333f810b2SJeff Kirsher break ;
214433f810b2SJeff Kirsher case DEBUG_PCM:
214533f810b2SJeff Kirsher DB_P.d_pcm = lev ;
214633f810b2SJeff Kirsher break ;
214733f810b2SJeff Kirsher case DEBUG_SBA:
214833f810b2SJeff Kirsher #ifdef SBA
214933f810b2SJeff Kirsher DB_P.d_sba = lev ;
215033f810b2SJeff Kirsher #endif
215133f810b2SJeff Kirsher break ;
215233f810b2SJeff Kirsher case DEBUG_ESS:
215333f810b2SJeff Kirsher #ifdef ESS
215433f810b2SJeff Kirsher DB_P.d_ess = lev ;
215533f810b2SJeff Kirsher #endif
215633f810b2SJeff Kirsher break ;
215733f810b2SJeff Kirsher case DB_HWM_RX:
215833f810b2SJeff Kirsher DB_P.d_os.hwm_rx = lev ;
215933f810b2SJeff Kirsher break ;
216033f810b2SJeff Kirsher case DB_HWM_TX:
216133f810b2SJeff Kirsher DB_P.d_os.hwm_tx = lev ;
216233f810b2SJeff Kirsher break ;
216333f810b2SJeff Kirsher case DB_HWM_GEN:
216433f810b2SJeff Kirsher DB_P.d_os.hwm_gen = lev ;
216533f810b2SJeff Kirsher break ;
216633f810b2SJeff Kirsher default:
216733f810b2SJeff Kirsher break ;
216833f810b2SJeff Kirsher }
216933f810b2SJeff Kirsher }
217033f810b2SJeff Kirsher #endif
2171