162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * (C)Copyright 1998,1999 SysKonnect, 562306a36Sopenharmony_ci * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * See the file "skfddi.c" for further information. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * The information in this file is provided "AS IS" without warranty. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci ******************************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define HWMTM 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifndef FDDI 1662306a36Sopenharmony_ci#define FDDI 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "h/types.h" 2062306a36Sopenharmony_ci#include "h/fddi.h" 2162306a36Sopenharmony_ci#include "h/smc.h" 2262306a36Sopenharmony_ci#include "h/supern_2.h" 2362306a36Sopenharmony_ci#include "h/skfbiinc.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* 2662306a36Sopenharmony_ci ------------------------------------------------------------- 2762306a36Sopenharmony_ci DOCUMENTATION 2862306a36Sopenharmony_ci ------------------------------------------------------------- 2962306a36Sopenharmony_ci BEGIN_MANUAL_ENTRY(DOCUMENTATION) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci T B D 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci END_MANUAL_ENTRY 3462306a36Sopenharmony_ci*/ 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci ------------------------------------------------------------- 3762306a36Sopenharmony_ci LOCAL VARIABLES: 3862306a36Sopenharmony_ci ------------------------------------------------------------- 3962306a36Sopenharmony_ci*/ 4062306a36Sopenharmony_ci#ifdef COMMON_MB_POOL 4162306a36Sopenharmony_cistatic SMbuf *mb_start; 4262306a36Sopenharmony_cistatic SMbuf *mb_free; 4362306a36Sopenharmony_cistatic int mb_init = FALSE ; 4462306a36Sopenharmony_cistatic int call_count; 4562306a36Sopenharmony_ci#endif 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci ------------------------------------------------------------- 4962306a36Sopenharmony_ci EXTERNE VARIABLES: 5062306a36Sopenharmony_ci ------------------------------------------------------------- 5162306a36Sopenharmony_ci*/ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifdef DEBUG 5462306a36Sopenharmony_ci#ifndef DEBUG_BRD 5562306a36Sopenharmony_ciextern struct smt_debug debug ; 5662306a36Sopenharmony_ci#endif 5762306a36Sopenharmony_ci#endif 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#ifdef NDIS_OS2 6062306a36Sopenharmony_ciextern u_char offDepth ; 6162306a36Sopenharmony_ciextern u_char force_irq_pending ; 6262306a36Sopenharmony_ci#endif 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci ------------------------------------------------------------- 6662306a36Sopenharmony_ci LOCAL FUNCTIONS: 6762306a36Sopenharmony_ci ------------------------------------------------------------- 6862306a36Sopenharmony_ci*/ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic void queue_llc_rx(struct s_smc *smc, SMbuf *mb); 7162306a36Sopenharmony_cistatic void smt_to_llc(struct s_smc *smc, SMbuf *mb); 7262306a36Sopenharmony_cistatic void init_txd_ring(struct s_smc *smc); 7362306a36Sopenharmony_cistatic void init_rxd_ring(struct s_smc *smc); 7462306a36Sopenharmony_cistatic void queue_txd_mb(struct s_smc *smc, SMbuf *mb); 7562306a36Sopenharmony_cistatic u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start, 7662306a36Sopenharmony_ci int count); 7762306a36Sopenharmony_cistatic u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); 7862306a36Sopenharmony_cistatic u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); 7962306a36Sopenharmony_cistatic SMbuf* get_llc_rx(struct s_smc *smc); 8062306a36Sopenharmony_cistatic SMbuf* get_txd_mb(struct s_smc *smc); 8162306a36Sopenharmony_cistatic void mac_drv_clear_txd(struct s_smc *smc); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* 8462306a36Sopenharmony_ci ------------------------------------------------------------- 8562306a36Sopenharmony_ci EXTERNAL FUNCTIONS: 8662306a36Sopenharmony_ci ------------------------------------------------------------- 8762306a36Sopenharmony_ci*/ 8862306a36Sopenharmony_ci/* The external SMT functions are listed in cmtdef.h */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciextern void* mac_drv_get_space(struct s_smc *smc, unsigned int size); 9162306a36Sopenharmony_ciextern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size); 9262306a36Sopenharmony_ciextern void mac_drv_fill_rxd(struct s_smc *smc); 9362306a36Sopenharmony_ciextern void mac_drv_tx_complete(struct s_smc *smc, 9462306a36Sopenharmony_ci volatile struct s_smt_fp_txd *txd); 9562306a36Sopenharmony_ciextern void mac_drv_rx_complete(struct s_smc *smc, 9662306a36Sopenharmony_ci volatile struct s_smt_fp_rxd *rxd, 9762306a36Sopenharmony_ci int frag_count, int len); 9862306a36Sopenharmony_ciextern void mac_drv_requeue_rxd(struct s_smc *smc, 9962306a36Sopenharmony_ci volatile struct s_smt_fp_rxd *rxd, 10062306a36Sopenharmony_ci int frag_count); 10162306a36Sopenharmony_ciextern void mac_drv_clear_rxd(struct s_smc *smc, 10262306a36Sopenharmony_ci volatile struct s_smt_fp_rxd *rxd, int frag_count); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#ifdef USE_OS_CPY 10562306a36Sopenharmony_ciextern void hwm_cpy_rxd2mb(void); 10662306a36Sopenharmony_ciextern void hwm_cpy_txd2mb(void); 10762306a36Sopenharmony_ci#endif 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#ifdef ALL_RX_COMPLETE 11062306a36Sopenharmony_ciextern void mac_drv_all_receives_complete(void); 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciextern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt); 11462306a36Sopenharmony_ciextern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#ifdef NDIS_OS2 11762306a36Sopenharmony_ciextern void post_proc(void); 11862306a36Sopenharmony_ci#else 11962306a36Sopenharmony_ciextern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, 12062306a36Sopenharmony_ci int flag); 12162306a36Sopenharmony_ci#endif 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciextern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, 12462306a36Sopenharmony_ci int la_len); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/* 12762306a36Sopenharmony_ci ------------------------------------------------------------- 12862306a36Sopenharmony_ci PUBLIC FUNCTIONS: 12962306a36Sopenharmony_ci ------------------------------------------------------------- 13062306a36Sopenharmony_ci*/ 13162306a36Sopenharmony_civoid process_receive(struct s_smc *smc); 13262306a36Sopenharmony_civoid fddi_isr(struct s_smc *smc); 13362306a36Sopenharmony_civoid smt_free_mbuf(struct s_smc *smc, SMbuf *mb); 13462306a36Sopenharmony_civoid init_driver_fplus(struct s_smc *smc); 13562306a36Sopenharmony_civoid mac_drv_rx_mode(struct s_smc *smc, int mode); 13662306a36Sopenharmony_civoid init_fddi_driver(struct s_smc *smc, u_char *mac_addr); 13762306a36Sopenharmony_civoid mac_drv_clear_tx_queue(struct s_smc *smc); 13862306a36Sopenharmony_civoid mac_drv_clear_rx_queue(struct s_smc *smc); 13962306a36Sopenharmony_civoid hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, 14062306a36Sopenharmony_ci int frame_status); 14162306a36Sopenharmony_civoid hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, 14262306a36Sopenharmony_ci int frame_status); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciint mac_drv_init(struct s_smc *smc); 14562306a36Sopenharmony_ciint hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, 14662306a36Sopenharmony_ci int frame_status); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciu_int mac_drv_check_space(void); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciSMbuf* smt_get_mbuf(struct s_smc *smc); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#ifdef DEBUG 15362306a36Sopenharmony_ci void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev); 15462306a36Sopenharmony_ci#endif 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* 15762306a36Sopenharmony_ci ------------------------------------------------------------- 15862306a36Sopenharmony_ci MACROS: 15962306a36Sopenharmony_ci ------------------------------------------------------------- 16062306a36Sopenharmony_ci*/ 16162306a36Sopenharmony_ci#ifndef UNUSED 16262306a36Sopenharmony_ci#ifdef lint 16362306a36Sopenharmony_ci#define UNUSED(x) (x) = (x) 16462306a36Sopenharmony_ci#else 16562306a36Sopenharmony_ci#define UNUSED(x) 16662306a36Sopenharmony_ci#endif 16762306a36Sopenharmony_ci#endif 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci#ifdef USE_CAN_ADDR 17062306a36Sopenharmony_ci#define MA smc->hw.fddi_canon_addr.a 17162306a36Sopenharmony_ci#define GROUP_ADDR_BIT 0x01 17262306a36Sopenharmony_ci#else 17362306a36Sopenharmony_ci#define MA smc->hw.fddi_home_addr.a 17462306a36Sopenharmony_ci#define GROUP_ADDR_BIT 0x80 17562306a36Sopenharmony_ci#endif 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci#define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\ 17862306a36Sopenharmony_ci SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#ifdef MB_OUTSIDE_SMC 18162306a36Sopenharmony_ci#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\ 18262306a36Sopenharmony_ci MAX_MBUF*sizeof(SMbuf)) 18362306a36Sopenharmony_ci#define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)) 18462306a36Sopenharmony_ci#else 18562306a36Sopenharmony_ci#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)) 18662306a36Sopenharmony_ci#endif 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* 18962306a36Sopenharmony_ci * define critical read for 16 Bit drivers 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci#if defined(NDIS_OS2) || defined(ODI2) 19262306a36Sopenharmony_ci#define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff)) 19362306a36Sopenharmony_ci#else 19462306a36Sopenharmony_ci#define CR_READ(var) (__le32)(var) 19562306a36Sopenharmony_ci#endif 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \ 19862306a36Sopenharmony_ci IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \ 19962306a36Sopenharmony_ci IS_R1_C | IS_XA_C | IS_XS_C) 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* 20262306a36Sopenharmony_ci ------------------------------------------------------------- 20362306a36Sopenharmony_ci INIT- AND SMT FUNCTIONS: 20462306a36Sopenharmony_ci ------------------------------------------------------------- 20562306a36Sopenharmony_ci*/ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci/* 20962306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(mac_drv_check_space) 21062306a36Sopenharmony_ci * u_int mac_drv_check_space() 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * function DOWNCALL (drvsr.c) 21362306a36Sopenharmony_ci * This function calculates the needed non virtual 21462306a36Sopenharmony_ci * memory for MBufs, RxD and TxD descriptors etc. 21562306a36Sopenharmony_ci * needed by the driver. 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * return u_int memory in bytes 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * END_MANUAL_ENTRY 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ciu_int mac_drv_check_space(void) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci#ifdef MB_OUTSIDE_SMC 22462306a36Sopenharmony_ci#ifdef COMMON_MB_POOL 22562306a36Sopenharmony_ci call_count++ ; 22662306a36Sopenharmony_ci if (call_count == 1) { 22762306a36Sopenharmony_ci return EXT_VIRT_MEM; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci else { 23062306a36Sopenharmony_ci return EXT_VIRT_MEM_2; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci#else 23362306a36Sopenharmony_ci return EXT_VIRT_MEM; 23462306a36Sopenharmony_ci#endif 23562306a36Sopenharmony_ci#else 23662306a36Sopenharmony_ci return 0; 23762306a36Sopenharmony_ci#endif 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* 24162306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(mac_drv_init) 24262306a36Sopenharmony_ci * void mac_drv_init(smc) 24362306a36Sopenharmony_ci * 24462306a36Sopenharmony_ci * function DOWNCALL (drvsr.c) 24562306a36Sopenharmony_ci * In this function the hardware module allocates it's 24662306a36Sopenharmony_ci * memory. 24762306a36Sopenharmony_ci * The operating system dependent module should call 24862306a36Sopenharmony_ci * mac_drv_init once, after the adatper is detected. 24962306a36Sopenharmony_ci * END_MANUAL_ENTRY 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_ciint mac_drv_init(struct s_smc *smc) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci if (sizeof(struct s_smt_fp_rxd) % 16) { 25462306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci if (sizeof(struct s_smt_fp_txd) % 16) { 25762306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* 26162306a36Sopenharmony_ci * get the required memory for the RxDs and TxDs 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *) 26462306a36Sopenharmony_ci mac_drv_get_desc_mem(smc,(u_int) 26562306a36Sopenharmony_ci (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) { 26662306a36Sopenharmony_ci return 1; /* no space the hwm modul can't work */ 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* 27062306a36Sopenharmony_ci * get the memory for the SMT MBufs 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci#ifndef MB_OUTSIDE_SMC 27362306a36Sopenharmony_ci smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ; 27462306a36Sopenharmony_ci#else 27562306a36Sopenharmony_ci#ifndef COMMON_MB_POOL 27662306a36Sopenharmony_ci if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc, 27762306a36Sopenharmony_ci MAX_MBUF*sizeof(SMbuf)))) { 27862306a36Sopenharmony_ci return 1; /* no space the hwm modul can't work */ 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci#else 28162306a36Sopenharmony_ci if (!mb_start) { 28262306a36Sopenharmony_ci if (!(mb_start = (SMbuf *) mac_drv_get_space(smc, 28362306a36Sopenharmony_ci MAX_MBUF*sizeof(SMbuf)))) { 28462306a36Sopenharmony_ci return 1; /* no space the hwm modul can't work */ 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci#endif 28862306a36Sopenharmony_ci#endif 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/* 29362306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(init_driver_fplus) 29462306a36Sopenharmony_ci * init_driver_fplus(smc) 29562306a36Sopenharmony_ci * 29662306a36Sopenharmony_ci * Sets hardware modul specific values for the mode register 2 29762306a36Sopenharmony_ci * (e.g. the byte alignment for the received frames, the position of the 29862306a36Sopenharmony_ci * least significant byte etc.) 29962306a36Sopenharmony_ci * END_MANUAL_ENTRY 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_civoid init_driver_fplus(struct s_smc *smc) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci#ifdef PCI 30662306a36Sopenharmony_ci smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ; 30762306a36Sopenharmony_ci#endif 30862306a36Sopenharmony_ci smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci#ifdef USE_CAN_ADDR 31162306a36Sopenharmony_ci /* enable address bit swapping */ 31262306a36Sopenharmony_ci smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ; 31362306a36Sopenharmony_ci#endif 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic u_long init_descr_ring(struct s_smc *smc, 31762306a36Sopenharmony_ci union s_fp_descr volatile *start, 31862306a36Sopenharmony_ci int count) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci int i ; 32162306a36Sopenharmony_ci union s_fp_descr volatile *d1 ; 32262306a36Sopenharmony_ci union s_fp_descr volatile *d2 ; 32362306a36Sopenharmony_ci u_long phys ; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci DB_GEN(3, "descr ring starts at = %p", start); 32662306a36Sopenharmony_ci for (i=count-1, d1=start; i ; i--) { 32762306a36Sopenharmony_ci d2 = d1 ; 32862306a36Sopenharmony_ci d1++ ; /* descr is owned by the host */ 32962306a36Sopenharmony_ci d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ; 33062306a36Sopenharmony_ci d2->r.rxd_next = &d1->r ; 33162306a36Sopenharmony_ci phys = mac_drv_virt2phys(smc,(void *)d1) ; 33262306a36Sopenharmony_ci d2->r.rxd_nrdadr = cpu_to_le32(phys) ; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci DB_GEN(3, "descr ring ends at = %p", d1); 33562306a36Sopenharmony_ci d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ; 33662306a36Sopenharmony_ci d1->r.rxd_next = &start->r ; 33762306a36Sopenharmony_ci phys = mac_drv_virt2phys(smc,(void *)start) ; 33862306a36Sopenharmony_ci d1->r.rxd_nrdadr = cpu_to_le32(phys) ; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci for (i=count, d1=start; i ; i--) { 34162306a36Sopenharmony_ci DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ; 34262306a36Sopenharmony_ci d1++; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci return phys; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic void init_txd_ring(struct s_smc *smc) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci struct s_smt_fp_txd volatile *ds ; 35062306a36Sopenharmony_ci struct s_smt_tx_queue *queue ; 35162306a36Sopenharmony_ci u_long phys ; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* 35462306a36Sopenharmony_ci * initialize the transmit descriptors 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p + 35762306a36Sopenharmony_ci SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ; 35862306a36Sopenharmony_ci queue = smc->hw.fp.tx[QUEUE_A0] ; 35962306a36Sopenharmony_ci DB_GEN(3, "Init async TxD ring, %d TxDs", HWM_ASYNC_TXD_COUNT); 36062306a36Sopenharmony_ci (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, 36162306a36Sopenharmony_ci HWM_ASYNC_TXD_COUNT) ; 36262306a36Sopenharmony_ci phys = le32_to_cpu(ds->txd_ntdadr) ; 36362306a36Sopenharmony_ci ds++ ; 36462306a36Sopenharmony_ci queue->tx_curr_put = queue->tx_curr_get = ds ; 36562306a36Sopenharmony_ci ds-- ; 36662306a36Sopenharmony_ci queue->tx_free = HWM_ASYNC_TXD_COUNT ; 36762306a36Sopenharmony_ci queue->tx_used = 0 ; 36862306a36Sopenharmony_ci outpd(ADDR(B5_XA_DA),phys) ; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci ds = (struct s_smt_fp_txd volatile *) ((char *)ds + 37162306a36Sopenharmony_ci HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ; 37262306a36Sopenharmony_ci queue = smc->hw.fp.tx[QUEUE_S] ; 37362306a36Sopenharmony_ci DB_GEN(3, "Init sync TxD ring, %d TxDs", HWM_SYNC_TXD_COUNT); 37462306a36Sopenharmony_ci (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, 37562306a36Sopenharmony_ci HWM_SYNC_TXD_COUNT) ; 37662306a36Sopenharmony_ci phys = le32_to_cpu(ds->txd_ntdadr) ; 37762306a36Sopenharmony_ci ds++ ; 37862306a36Sopenharmony_ci queue->tx_curr_put = queue->tx_curr_get = ds ; 37962306a36Sopenharmony_ci queue->tx_free = HWM_SYNC_TXD_COUNT ; 38062306a36Sopenharmony_ci queue->tx_used = 0 ; 38162306a36Sopenharmony_ci outpd(ADDR(B5_XS_DA),phys) ; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void init_rxd_ring(struct s_smc *smc) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *ds ; 38762306a36Sopenharmony_ci struct s_smt_rx_queue *queue ; 38862306a36Sopenharmony_ci u_long phys ; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* 39162306a36Sopenharmony_ci * initialize the receive descriptors 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ; 39462306a36Sopenharmony_ci queue = smc->hw.fp.rx[QUEUE_R1] ; 39562306a36Sopenharmony_ci DB_GEN(3, "Init RxD ring, %d RxDs", SMT_R1_RXD_COUNT); 39662306a36Sopenharmony_ci (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, 39762306a36Sopenharmony_ci SMT_R1_RXD_COUNT) ; 39862306a36Sopenharmony_ci phys = le32_to_cpu(ds->rxd_nrdadr) ; 39962306a36Sopenharmony_ci ds++ ; 40062306a36Sopenharmony_ci queue->rx_curr_put = queue->rx_curr_get = ds ; 40162306a36Sopenharmony_ci queue->rx_free = SMT_R1_RXD_COUNT ; 40262306a36Sopenharmony_ci queue->rx_used = 0 ; 40362306a36Sopenharmony_ci outpd(ADDR(B4_R1_DA),phys) ; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* 40762306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(init_fddi_driver) 40862306a36Sopenharmony_ci * void init_fddi_driver(smc,mac_addr) 40962306a36Sopenharmony_ci * 41062306a36Sopenharmony_ci * initializes the driver and it's variables 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * END_MANUAL_ENTRY 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_civoid init_fddi_driver(struct s_smc *smc, u_char *mac_addr) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci SMbuf *mb ; 41762306a36Sopenharmony_ci int i ; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci init_board(smc,mac_addr) ; 42062306a36Sopenharmony_ci (void)init_fplus(smc) ; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* 42362306a36Sopenharmony_ci * initialize the SMbufs for the SMT 42462306a36Sopenharmony_ci */ 42562306a36Sopenharmony_ci#ifndef COMMON_MB_POOL 42662306a36Sopenharmony_ci mb = smc->os.hwm.mbuf_pool.mb_start ; 42762306a36Sopenharmony_ci smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ; 42862306a36Sopenharmony_ci for (i = 0; i < MAX_MBUF; i++) { 42962306a36Sopenharmony_ci mb->sm_use_count = 1 ; 43062306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 43162306a36Sopenharmony_ci mb++ ; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci#else 43462306a36Sopenharmony_ci mb = mb_start ; 43562306a36Sopenharmony_ci if (!mb_init) { 43662306a36Sopenharmony_ci mb_free = 0 ; 43762306a36Sopenharmony_ci for (i = 0; i < MAX_MBUF; i++) { 43862306a36Sopenharmony_ci mb->sm_use_count = 1 ; 43962306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 44062306a36Sopenharmony_ci mb++ ; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci mb_init = TRUE ; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci#endif 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /* 44762306a36Sopenharmony_ci * initialize the other variables 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_ci smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ; 45062306a36Sopenharmony_ci smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ; 45162306a36Sopenharmony_ci smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ; 45262306a36Sopenharmony_ci smc->os.hwm.pass_llc_promisc = TRUE ; 45362306a36Sopenharmony_ci smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ; 45462306a36Sopenharmony_ci smc->os.hwm.detec_count = 0 ; 45562306a36Sopenharmony_ci smc->os.hwm.rx_break = 0 ; 45662306a36Sopenharmony_ci smc->os.hwm.rx_len_error = 0 ; 45762306a36Sopenharmony_ci smc->os.hwm.isr_flag = FALSE ; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* 46062306a36Sopenharmony_ci * make sure that the start pointer is 16 byte aligned 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ; 46362306a36Sopenharmony_ci if (i != 16) { 46462306a36Sopenharmony_ci DB_GEN(3, "i = %d", i); 46562306a36Sopenharmony_ci smc->os.hwm.descr_p = (union s_fp_descr volatile *) 46662306a36Sopenharmony_ci ((char *)smc->os.hwm.descr_p+i) ; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci DB_GEN(3, "pt to descr area = %p", smc->os.hwm.descr_p); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci init_txd_ring(smc) ; 47162306a36Sopenharmony_ci init_rxd_ring(smc) ; 47262306a36Sopenharmony_ci mac_drv_fill_rxd(smc) ; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci init_plc(smc) ; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ciSMbuf *smt_get_mbuf(struct s_smc *smc) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci register SMbuf *mb ; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci#ifndef COMMON_MB_POOL 48362306a36Sopenharmony_ci mb = smc->os.hwm.mbuf_pool.mb_free ; 48462306a36Sopenharmony_ci#else 48562306a36Sopenharmony_ci mb = mb_free ; 48662306a36Sopenharmony_ci#endif 48762306a36Sopenharmony_ci if (mb) { 48862306a36Sopenharmony_ci#ifndef COMMON_MB_POOL 48962306a36Sopenharmony_ci smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ; 49062306a36Sopenharmony_ci#else 49162306a36Sopenharmony_ci mb_free = mb->sm_next ; 49262306a36Sopenharmony_ci#endif 49362306a36Sopenharmony_ci mb->sm_off = 8 ; 49462306a36Sopenharmony_ci mb->sm_use_count = 1 ; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci DB_GEN(3, "get SMbuf: mb = %p", mb); 49762306a36Sopenharmony_ci return mb; /* May be NULL */ 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_civoid smt_free_mbuf(struct s_smc *smc, SMbuf *mb) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (mb) { 50462306a36Sopenharmony_ci mb->sm_use_count-- ; 50562306a36Sopenharmony_ci DB_GEN(3, "free_mbuf: sm_use_count = %d", mb->sm_use_count); 50662306a36Sopenharmony_ci /* 50762306a36Sopenharmony_ci * If the use_count is != zero the MBuf is queued 50862306a36Sopenharmony_ci * more than once and must not queued into the 50962306a36Sopenharmony_ci * free MBuf queue 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_ci if (!mb->sm_use_count) { 51262306a36Sopenharmony_ci DB_GEN(3, "free SMbuf: mb = %p", mb); 51362306a36Sopenharmony_ci#ifndef COMMON_MB_POOL 51462306a36Sopenharmony_ci mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ; 51562306a36Sopenharmony_ci smc->os.hwm.mbuf_pool.mb_free = mb ; 51662306a36Sopenharmony_ci#else 51762306a36Sopenharmony_ci mb->sm_next = mb_free ; 51862306a36Sopenharmony_ci mb_free = mb ; 51962306a36Sopenharmony_ci#endif 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci else 52362306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci/* 52862306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(mac_drv_repair_descr) 52962306a36Sopenharmony_ci * void mac_drv_repair_descr(smc) 53062306a36Sopenharmony_ci * 53162306a36Sopenharmony_ci * function called from SMT (HWM / hwmtm.c) 53262306a36Sopenharmony_ci * The BMU is idle when this function is called. 53362306a36Sopenharmony_ci * Mac_drv_repair_descr sets up the physical address 53462306a36Sopenharmony_ci * for all receive and transmit queues where the BMU 53562306a36Sopenharmony_ci * should continue. 53662306a36Sopenharmony_ci * It may be that the BMU was reseted during a fragmented 53762306a36Sopenharmony_ci * transfer. In this case there are some fragments which will 53862306a36Sopenharmony_ci * never completed by the BMU. The OWN bit of this fragments 53962306a36Sopenharmony_ci * must be switched to be owned by the host. 54062306a36Sopenharmony_ci * 54162306a36Sopenharmony_ci * Give a start command to the receive BMU. 54262306a36Sopenharmony_ci * Start the transmit BMUs if transmit frames pending. 54362306a36Sopenharmony_ci * 54462306a36Sopenharmony_ci * END_MANUAL_ENTRY 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_civoid mac_drv_repair_descr(struct s_smc *smc) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci u_long phys ; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (smc->hw.hw_state != STOPPED) { 55162306a36Sopenharmony_ci SK_BREAK() ; 55262306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ; 55362306a36Sopenharmony_ci return ; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* 55762306a36Sopenharmony_ci * repair tx queues: don't start 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ci phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ; 56062306a36Sopenharmony_ci outpd(ADDR(B5_XA_DA),phys) ; 56162306a36Sopenharmony_ci if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) { 56262306a36Sopenharmony_ci outpd(ADDR(B0_XA_CSR),CSR_START) ; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ; 56562306a36Sopenharmony_ci outpd(ADDR(B5_XS_DA),phys) ; 56662306a36Sopenharmony_ci if (smc->hw.fp.tx_q[QUEUE_S].tx_used) { 56762306a36Sopenharmony_ci outpd(ADDR(B0_XS_CSR),CSR_START) ; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* 57162306a36Sopenharmony_ci * repair rx queues 57262306a36Sopenharmony_ci */ 57362306a36Sopenharmony_ci phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ; 57462306a36Sopenharmony_ci outpd(ADDR(B4_R1_DA),phys) ; 57562306a36Sopenharmony_ci outpd(ADDR(B0_R1_CSR),CSR_START) ; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci int i ; 58162306a36Sopenharmony_ci int tx_used ; 58262306a36Sopenharmony_ci u_long phys ; 58362306a36Sopenharmony_ci u_long tbctrl ; 58462306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t ; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci SK_UNUSED(smc) ; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci t = queue->tx_curr_get ; 58962306a36Sopenharmony_ci tx_used = queue->tx_used ; 59062306a36Sopenharmony_ci for (i = tx_used+queue->tx_free-1 ; i ; i-- ) { 59162306a36Sopenharmony_ci t = t->txd_next ; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci phys = le32_to_cpu(t->txd_ntdadr) ; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci t = queue->tx_curr_get ; 59662306a36Sopenharmony_ci while (tx_used) { 59762306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ; 59862306a36Sopenharmony_ci tbctrl = le32_to_cpu(t->txd_tbctrl) ; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (tbctrl & BMU_OWN) { 60162306a36Sopenharmony_ci if (tbctrl & BMU_STF) { 60262306a36Sopenharmony_ci break ; /* exit the loop */ 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci else { 60562306a36Sopenharmony_ci /* 60662306a36Sopenharmony_ci * repair the descriptor 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_ci t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci phys = le32_to_cpu(t->txd_ntdadr) ; 61262306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 61362306a36Sopenharmony_ci t = t->txd_next ; 61462306a36Sopenharmony_ci tx_used-- ; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci return phys; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci/* 62062306a36Sopenharmony_ci * Repairs the receive descriptor ring and returns the physical address 62162306a36Sopenharmony_ci * where the BMU should continue working. 62262306a36Sopenharmony_ci * 62362306a36Sopenharmony_ci * o The physical address where the BMU was stopped has to be 62462306a36Sopenharmony_ci * determined. This is the next RxD after rx_curr_get with an OWN 62562306a36Sopenharmony_ci * bit set. 62662306a36Sopenharmony_ci * o The BMU should start working at beginning of the next frame. 62762306a36Sopenharmony_ci * RxDs with an OWN bit set but with a reset STF bit should be 62862306a36Sopenharmony_ci * skipped and owned by the driver (OWN = 0). 62962306a36Sopenharmony_ci */ 63062306a36Sopenharmony_cistatic u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci int i ; 63362306a36Sopenharmony_ci int rx_used ; 63462306a36Sopenharmony_ci u_long phys ; 63562306a36Sopenharmony_ci u_long rbctrl ; 63662306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *r ; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci SK_UNUSED(smc) ; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci r = queue->rx_curr_get ; 64162306a36Sopenharmony_ci rx_used = queue->rx_used ; 64262306a36Sopenharmony_ci for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) { 64362306a36Sopenharmony_ci r = r->rxd_next ; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci phys = le32_to_cpu(r->rxd_nrdadr) ; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci r = queue->rx_curr_get ; 64862306a36Sopenharmony_ci while (rx_used) { 64962306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 65062306a36Sopenharmony_ci rbctrl = le32_to_cpu(r->rxd_rbctrl) ; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (rbctrl & BMU_OWN) { 65362306a36Sopenharmony_ci if (rbctrl & BMU_STF) { 65462306a36Sopenharmony_ci break ; /* exit the loop */ 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci else { 65762306a36Sopenharmony_ci /* 65862306a36Sopenharmony_ci * repair the descriptor 65962306a36Sopenharmony_ci */ 66062306a36Sopenharmony_ci r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci phys = le32_to_cpu(r->rxd_nrdadr) ; 66462306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; 66562306a36Sopenharmony_ci r = r->rxd_next ; 66662306a36Sopenharmony_ci rx_used-- ; 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci return phys; 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/* 67362306a36Sopenharmony_ci ------------------------------------------------------------- 67462306a36Sopenharmony_ci INTERRUPT SERVICE ROUTINE: 67562306a36Sopenharmony_ci ------------------------------------------------------------- 67662306a36Sopenharmony_ci*/ 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci/* 67962306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(fddi_isr) 68062306a36Sopenharmony_ci * void fddi_isr(smc) 68162306a36Sopenharmony_ci * 68262306a36Sopenharmony_ci * function DOWNCALL (drvsr.c) 68362306a36Sopenharmony_ci * interrupt service routine, handles the interrupt requests 68462306a36Sopenharmony_ci * generated by the FDDI adapter. 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * NOTE: The operating system dependent module must guarantee that the 68762306a36Sopenharmony_ci * interrupts of the adapter are disabled when it calls fddi_isr. 68862306a36Sopenharmony_ci * 68962306a36Sopenharmony_ci * About the USE_BREAK_ISR mechanismn: 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * The main requirement of this mechanismn is to force an timer IRQ when 69262306a36Sopenharmony_ci * leaving process_receive() with leave_isr set. process_receive() may 69362306a36Sopenharmony_ci * be called at any time from anywhere! 69462306a36Sopenharmony_ci * To be sure we don't miss such event we set 'force_irq' per default. 69562306a36Sopenharmony_ci * We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND 69662306a36Sopenharmony_ci * 'force_irq' are set. 'force_irq' may be reset if a receive complete 69762306a36Sopenharmony_ci * IRQ is pending. 69862306a36Sopenharmony_ci * 69962306a36Sopenharmony_ci * END_MANUAL_ENTRY 70062306a36Sopenharmony_ci */ 70162306a36Sopenharmony_civoid fddi_isr(struct s_smc *smc) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci u_long is ; /* ISR source */ 70462306a36Sopenharmony_ci u_short stu, stl ; 70562306a36Sopenharmony_ci SMbuf *mb ; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci#ifdef USE_BREAK_ISR 70862306a36Sopenharmony_ci int force_irq ; 70962306a36Sopenharmony_ci#endif 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci#ifdef ODI2 71262306a36Sopenharmony_ci if (smc->os.hwm.rx_break) { 71362306a36Sopenharmony_ci mac_drv_fill_rxd(smc) ; 71462306a36Sopenharmony_ci if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) { 71562306a36Sopenharmony_ci smc->os.hwm.rx_break = 0 ; 71662306a36Sopenharmony_ci process_receive(smc) ; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci else { 71962306a36Sopenharmony_ci smc->os.hwm.detec_count = 0 ; 72062306a36Sopenharmony_ci smt_force_irq(smc) ; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci#endif 72462306a36Sopenharmony_ci smc->os.hwm.isr_flag = TRUE ; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci#ifdef USE_BREAK_ISR 72762306a36Sopenharmony_ci force_irq = TRUE ; 72862306a36Sopenharmony_ci if (smc->os.hwm.leave_isr) { 72962306a36Sopenharmony_ci smc->os.hwm.leave_isr = FALSE ; 73062306a36Sopenharmony_ci process_receive(smc) ; 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci#endif 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci while ((is = GET_ISR() & ISR_MASK)) { 73562306a36Sopenharmony_ci NDD_TRACE("CH0B",is,0,0) ; 73662306a36Sopenharmony_ci DB_GEN(7, "ISA = 0x%lx", is); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci if (is & IMASK_SLOW) { 73962306a36Sopenharmony_ci NDD_TRACE("CH1b",is,0,0) ; 74062306a36Sopenharmony_ci if (is & IS_PLINT1) { /* PLC1 */ 74162306a36Sopenharmony_ci plc1_irq(smc) ; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci if (is & IS_PLINT2) { /* PLC2 */ 74462306a36Sopenharmony_ci plc2_irq(smc) ; 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci if (is & IS_MINTR1) { /* FORMAC+ STU1(U/L) */ 74762306a36Sopenharmony_ci stu = inpw(FM_A(FM_ST1U)) ; 74862306a36Sopenharmony_ci stl = inpw(FM_A(FM_ST1L)) ; 74962306a36Sopenharmony_ci DB_GEN(6, "Slow transmit complete"); 75062306a36Sopenharmony_ci mac1_irq(smc,stu,stl) ; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci if (is & IS_MINTR2) { /* FORMAC+ STU2(U/L) */ 75362306a36Sopenharmony_ci stu= inpw(FM_A(FM_ST2U)) ; 75462306a36Sopenharmony_ci stl= inpw(FM_A(FM_ST2L)) ; 75562306a36Sopenharmony_ci DB_GEN(6, "Slow receive complete"); 75662306a36Sopenharmony_ci DB_GEN(7, "stl = %x : stu = %x", stl, stu); 75762306a36Sopenharmony_ci mac2_irq(smc,stu,stl) ; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci if (is & IS_MINTR3) { /* FORMAC+ STU3(U/L) */ 76062306a36Sopenharmony_ci stu= inpw(FM_A(FM_ST3U)) ; 76162306a36Sopenharmony_ci stl= inpw(FM_A(FM_ST3L)) ; 76262306a36Sopenharmony_ci DB_GEN(6, "FORMAC Mode Register 3"); 76362306a36Sopenharmony_ci mac3_irq(smc,stu,stl) ; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci if (is & IS_TIMINT) { /* Timer 82C54-2 */ 76662306a36Sopenharmony_ci timer_irq(smc) ; 76762306a36Sopenharmony_ci#ifdef NDIS_OS2 76862306a36Sopenharmony_ci force_irq_pending = 0 ; 76962306a36Sopenharmony_ci#endif 77062306a36Sopenharmony_ci /* 77162306a36Sopenharmony_ci * out of RxD detection 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_ci if (++smc->os.hwm.detec_count > 4) { 77462306a36Sopenharmony_ci /* 77562306a36Sopenharmony_ci * check out of RxD condition 77662306a36Sopenharmony_ci */ 77762306a36Sopenharmony_ci process_receive(smc) ; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci if (is & IS_TOKEN) { /* Restricted Token Monitor */ 78162306a36Sopenharmony_ci rtm_irq(smc) ; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci if (is & IS_R1_P) { /* Parity error rx queue 1 */ 78462306a36Sopenharmony_ci /* clear IRQ */ 78562306a36Sopenharmony_ci outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ; 78662306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ; 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci if (is & IS_R1_C) { /* Encoding error rx queue 1 */ 78962306a36Sopenharmony_ci /* clear IRQ */ 79062306a36Sopenharmony_ci outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ; 79162306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci if (is & IS_XA_C) { /* Encoding error async tx q */ 79462306a36Sopenharmony_ci /* clear IRQ */ 79562306a36Sopenharmony_ci outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ; 79662306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci if (is & IS_XS_C) { /* Encoding error sync tx q */ 79962306a36Sopenharmony_ci /* clear IRQ */ 80062306a36Sopenharmony_ci outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ; 80162306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ; 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci /* 80662306a36Sopenharmony_ci * Fast Tx complete Async/Sync Queue (BMU service) 80762306a36Sopenharmony_ci */ 80862306a36Sopenharmony_ci if (is & (IS_XS_F|IS_XA_F)) { 80962306a36Sopenharmony_ci DB_GEN(6, "Fast tx complete queue"); 81062306a36Sopenharmony_ci /* 81162306a36Sopenharmony_ci * clear IRQ, Note: no IRQ is lost, because 81262306a36Sopenharmony_ci * we always service both queues 81362306a36Sopenharmony_ci */ 81462306a36Sopenharmony_ci outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ; 81562306a36Sopenharmony_ci outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ; 81662306a36Sopenharmony_ci mac_drv_clear_txd(smc) ; 81762306a36Sopenharmony_ci llc_restart_tx(smc) ; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci /* 82162306a36Sopenharmony_ci * Fast Rx Complete (BMU service) 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_ci if (is & IS_R1_F) { 82462306a36Sopenharmony_ci DB_GEN(6, "Fast receive complete"); 82562306a36Sopenharmony_ci /* clear IRQ */ 82662306a36Sopenharmony_ci#ifndef USE_BREAK_ISR 82762306a36Sopenharmony_ci outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ; 82862306a36Sopenharmony_ci process_receive(smc) ; 82962306a36Sopenharmony_ci#else 83062306a36Sopenharmony_ci process_receive(smc) ; 83162306a36Sopenharmony_ci if (smc->os.hwm.leave_isr) { 83262306a36Sopenharmony_ci force_irq = FALSE ; 83362306a36Sopenharmony_ci } else { 83462306a36Sopenharmony_ci outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ; 83562306a36Sopenharmony_ci process_receive(smc) ; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci#endif 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci#ifndef NDIS_OS2 84162306a36Sopenharmony_ci while ((mb = get_llc_rx(smc))) { 84262306a36Sopenharmony_ci smt_to_llc(smc,mb) ; 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci#else 84562306a36Sopenharmony_ci if (offDepth) 84662306a36Sopenharmony_ci post_proc() ; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci while (!offDepth && (mb = get_llc_rx(smc))) { 84962306a36Sopenharmony_ci smt_to_llc(smc,mb) ; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci if (!offDepth && smc->os.hwm.rx_break) { 85362306a36Sopenharmony_ci process_receive(smc) ; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci#endif 85662306a36Sopenharmony_ci if (smc->q.ev_get != smc->q.ev_put) { 85762306a36Sopenharmony_ci NDD_TRACE("CH2a",0,0,0) ; 85862306a36Sopenharmony_ci ev_dispatcher(smc) ; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci#ifdef NDIS_OS2 86162306a36Sopenharmony_ci post_proc() ; 86262306a36Sopenharmony_ci if (offDepth) { /* leave fddi_isr because */ 86362306a36Sopenharmony_ci break ; /* indications not allowed */ 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci#endif 86662306a36Sopenharmony_ci#ifdef USE_BREAK_ISR 86762306a36Sopenharmony_ci if (smc->os.hwm.leave_isr) { 86862306a36Sopenharmony_ci break ; /* leave fddi_isr */ 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci#endif 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* NOTE: when the isr is left, no rx is pending */ 87362306a36Sopenharmony_ci } /* end of interrupt source polling loop */ 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci#ifdef USE_BREAK_ISR 87662306a36Sopenharmony_ci if (smc->os.hwm.leave_isr && force_irq) { 87762306a36Sopenharmony_ci smt_force_irq(smc) ; 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci#endif 88062306a36Sopenharmony_ci smc->os.hwm.isr_flag = FALSE ; 88162306a36Sopenharmony_ci NDD_TRACE("CH0E",0,0,0) ; 88262306a36Sopenharmony_ci} 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci/* 88662306a36Sopenharmony_ci ------------------------------------------------------------- 88762306a36Sopenharmony_ci RECEIVE FUNCTIONS: 88862306a36Sopenharmony_ci ------------------------------------------------------------- 88962306a36Sopenharmony_ci*/ 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci#ifndef NDIS_OS2 89262306a36Sopenharmony_ci/* 89362306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(mac_drv_rx_mode) 89462306a36Sopenharmony_ci * void mac_drv_rx_mode(smc,mode) 89562306a36Sopenharmony_ci * 89662306a36Sopenharmony_ci * function DOWNCALL (fplus.c) 89762306a36Sopenharmony_ci * Corresponding to the parameter mode, the operating system 89862306a36Sopenharmony_ci * dependent module can activate several receive modes. 89962306a36Sopenharmony_ci * 90062306a36Sopenharmony_ci * para mode = 1: RX_ENABLE_ALLMULTI enable all multicasts 90162306a36Sopenharmony_ci * = 2: RX_DISABLE_ALLMULTI disable "enable all multicasts" 90262306a36Sopenharmony_ci * = 3: RX_ENABLE_PROMISC enable promiscuous 90362306a36Sopenharmony_ci * = 4: RX_DISABLE_PROMISC disable promiscuous 90462306a36Sopenharmony_ci * = 5: RX_ENABLE_NSA enable rec. of all NSA frames 90562306a36Sopenharmony_ci * (disabled after 'driver reset' & 'set station address') 90662306a36Sopenharmony_ci * = 6: RX_DISABLE_NSA disable rec. of all NSA frames 90762306a36Sopenharmony_ci * 90862306a36Sopenharmony_ci * = 21: RX_ENABLE_PASS_SMT ( see description ) 90962306a36Sopenharmony_ci * = 22: RX_DISABLE_PASS_SMT ( " " ) 91062306a36Sopenharmony_ci * = 23: RX_ENABLE_PASS_NSA ( " " ) 91162306a36Sopenharmony_ci * = 24: RX_DISABLE_PASS_NSA ( " " ) 91262306a36Sopenharmony_ci * = 25: RX_ENABLE_PASS_DB ( " " ) 91362306a36Sopenharmony_ci * = 26: RX_DISABLE_PASS_DB ( " " ) 91462306a36Sopenharmony_ci * = 27: RX_DISABLE_PASS_ALL ( " " ) 91562306a36Sopenharmony_ci * = 28: RX_DISABLE_LLC_PROMISC ( " " ) 91662306a36Sopenharmony_ci * = 29: RX_ENABLE_LLC_PROMISC ( " " ) 91762306a36Sopenharmony_ci * 91862306a36Sopenharmony_ci * 91962306a36Sopenharmony_ci * RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT 92062306a36Sopenharmony_ci * 92162306a36Sopenharmony_ci * If the operating system dependent module activates the 92262306a36Sopenharmony_ci * mode RX_ENABLE_PASS_SMT, the hardware module 92362306a36Sopenharmony_ci * duplicates all SMT frames with the frame control 92462306a36Sopenharmony_ci * FC_SMT_INFO and passes them to the LLC receive channel 92562306a36Sopenharmony_ci * by calling mac_drv_rx_init. 92662306a36Sopenharmony_ci * The SMT Frames which are sent by the local SMT and the NSA 92762306a36Sopenharmony_ci * frames whose A- and C-Indicator is not set are also duplicated 92862306a36Sopenharmony_ci * and passed. 92962306a36Sopenharmony_ci * The receive mode RX_DISABLE_PASS_SMT disables the passing 93062306a36Sopenharmony_ci * of SMT frames. 93162306a36Sopenharmony_ci * 93262306a36Sopenharmony_ci * RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA 93362306a36Sopenharmony_ci * 93462306a36Sopenharmony_ci * If the operating system dependent module activates the 93562306a36Sopenharmony_ci * mode RX_ENABLE_PASS_NSA, the hardware module 93662306a36Sopenharmony_ci * duplicates all NSA frames with frame control FC_SMT_NSA 93762306a36Sopenharmony_ci * and a set A-Indicator and passed them to the LLC 93862306a36Sopenharmony_ci * receive channel by calling mac_drv_rx_init. 93962306a36Sopenharmony_ci * All NSA Frames which are sent by the local SMT 94062306a36Sopenharmony_ci * are also duplicated and passed. 94162306a36Sopenharmony_ci * The receive mode RX_DISABLE_PASS_NSA disables the passing 94262306a36Sopenharmony_ci * of NSA frames with the A- or C-Indicator set. 94362306a36Sopenharmony_ci * 94462306a36Sopenharmony_ci * NOTE: For fear that the hardware module receives NSA frames with 94562306a36Sopenharmony_ci * a reset A-Indicator, the operating system dependent module 94662306a36Sopenharmony_ci * has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA 94762306a36Sopenharmony_ci * before activate the RX_ENABLE_PASS_NSA mode and after every 94862306a36Sopenharmony_ci * 'driver reset' and 'set station address'. 94962306a36Sopenharmony_ci * 95062306a36Sopenharmony_ci * RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB 95162306a36Sopenharmony_ci * 95262306a36Sopenharmony_ci * If the operating system dependent module activates the 95362306a36Sopenharmony_ci * mode RX_ENABLE_PASS_DB, direct BEACON frames 95462306a36Sopenharmony_ci * (FC_BEACON frame control) are passed to the LLC receive 95562306a36Sopenharmony_ci * channel by mac_drv_rx_init. 95662306a36Sopenharmony_ci * The receive mode RX_DISABLE_PASS_DB disables the passing 95762306a36Sopenharmony_ci * of direct BEACON frames. 95862306a36Sopenharmony_ci * 95962306a36Sopenharmony_ci * RX_DISABLE_PASS_ALL 96062306a36Sopenharmony_ci * 96162306a36Sopenharmony_ci * Disables all special receives modes. It is equal to 96262306a36Sopenharmony_ci * call mac_drv_set_rx_mode successively with the 96362306a36Sopenharmony_ci * parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT, 96462306a36Sopenharmony_ci * RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB. 96562306a36Sopenharmony_ci * 96662306a36Sopenharmony_ci * RX_ENABLE_LLC_PROMISC 96762306a36Sopenharmony_ci * 96862306a36Sopenharmony_ci * (default) all received LLC frames and all SMT/NSA/DBEACON 96962306a36Sopenharmony_ci * frames depending on the attitude of the flags 97062306a36Sopenharmony_ci * PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the 97162306a36Sopenharmony_ci * LLC layer 97262306a36Sopenharmony_ci * 97362306a36Sopenharmony_ci * RX_DISABLE_LLC_PROMISC 97462306a36Sopenharmony_ci * 97562306a36Sopenharmony_ci * all received SMT/NSA/DBEACON frames depending on the 97662306a36Sopenharmony_ci * attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON 97762306a36Sopenharmony_ci * will be delivered to the LLC layer. 97862306a36Sopenharmony_ci * all received LLC frames with a directed address, Multicast 97962306a36Sopenharmony_ci * or Broadcast address will be delivered to the LLC 98062306a36Sopenharmony_ci * layer too. 98162306a36Sopenharmony_ci * 98262306a36Sopenharmony_ci * END_MANUAL_ENTRY 98362306a36Sopenharmony_ci */ 98462306a36Sopenharmony_civoid mac_drv_rx_mode(struct s_smc *smc, int mode) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci switch(mode) { 98762306a36Sopenharmony_ci case RX_ENABLE_PASS_SMT: 98862306a36Sopenharmony_ci smc->os.hwm.pass_SMT = TRUE ; 98962306a36Sopenharmony_ci break ; 99062306a36Sopenharmony_ci case RX_DISABLE_PASS_SMT: 99162306a36Sopenharmony_ci smc->os.hwm.pass_SMT = FALSE ; 99262306a36Sopenharmony_ci break ; 99362306a36Sopenharmony_ci case RX_ENABLE_PASS_NSA: 99462306a36Sopenharmony_ci smc->os.hwm.pass_NSA = TRUE ; 99562306a36Sopenharmony_ci break ; 99662306a36Sopenharmony_ci case RX_DISABLE_PASS_NSA: 99762306a36Sopenharmony_ci smc->os.hwm.pass_NSA = FALSE ; 99862306a36Sopenharmony_ci break ; 99962306a36Sopenharmony_ci case RX_ENABLE_PASS_DB: 100062306a36Sopenharmony_ci smc->os.hwm.pass_DB = TRUE ; 100162306a36Sopenharmony_ci break ; 100262306a36Sopenharmony_ci case RX_DISABLE_PASS_DB: 100362306a36Sopenharmony_ci smc->os.hwm.pass_DB = FALSE ; 100462306a36Sopenharmony_ci break ; 100562306a36Sopenharmony_ci case RX_DISABLE_PASS_ALL: 100662306a36Sopenharmony_ci smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ; 100762306a36Sopenharmony_ci smc->os.hwm.pass_DB = FALSE ; 100862306a36Sopenharmony_ci smc->os.hwm.pass_llc_promisc = TRUE ; 100962306a36Sopenharmony_ci mac_set_rx_mode(smc,RX_DISABLE_NSA) ; 101062306a36Sopenharmony_ci break ; 101162306a36Sopenharmony_ci case RX_DISABLE_LLC_PROMISC: 101262306a36Sopenharmony_ci smc->os.hwm.pass_llc_promisc = FALSE ; 101362306a36Sopenharmony_ci break ; 101462306a36Sopenharmony_ci case RX_ENABLE_LLC_PROMISC: 101562306a36Sopenharmony_ci smc->os.hwm.pass_llc_promisc = TRUE ; 101662306a36Sopenharmony_ci break ; 101762306a36Sopenharmony_ci case RX_ENABLE_ALLMULTI: 101862306a36Sopenharmony_ci case RX_DISABLE_ALLMULTI: 101962306a36Sopenharmony_ci case RX_ENABLE_PROMISC: 102062306a36Sopenharmony_ci case RX_DISABLE_PROMISC: 102162306a36Sopenharmony_ci case RX_ENABLE_NSA: 102262306a36Sopenharmony_ci case RX_DISABLE_NSA: 102362306a36Sopenharmony_ci default: 102462306a36Sopenharmony_ci mac_set_rx_mode(smc,mode) ; 102562306a36Sopenharmony_ci break ; 102662306a36Sopenharmony_ci } 102762306a36Sopenharmony_ci} 102862306a36Sopenharmony_ci#endif /* ifndef NDIS_OS2 */ 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci/* 103162306a36Sopenharmony_ci * process receive queue 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_civoid process_receive(struct s_smc *smc) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci int i ; 103662306a36Sopenharmony_ci int n ; 103762306a36Sopenharmony_ci int frag_count ; /* number of RxDs of the curr rx buf */ 103862306a36Sopenharmony_ci int used_frags ; /* number of RxDs of the curr frame */ 103962306a36Sopenharmony_ci struct s_smt_rx_queue *queue ; /* points to the queue ctl struct */ 104062306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *r ; /* rxd pointer */ 104162306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *rxd ; /* first rxd of rx frame */ 104262306a36Sopenharmony_ci u_long rbctrl ; /* receive buffer control word */ 104362306a36Sopenharmony_ci u_long rfsw ; /* receive frame status word */ 104462306a36Sopenharmony_ci u_short rx_used ; 104562306a36Sopenharmony_ci u_char far *virt ; 104662306a36Sopenharmony_ci char far *data ; 104762306a36Sopenharmony_ci SMbuf *mb ; 104862306a36Sopenharmony_ci u_char fc ; /* Frame control */ 104962306a36Sopenharmony_ci int len ; /* Frame length */ 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci smc->os.hwm.detec_count = 0 ; 105262306a36Sopenharmony_ci queue = smc->hw.fp.rx[QUEUE_R1] ; 105362306a36Sopenharmony_ci NDD_TRACE("RHxB",0,0,0) ; 105462306a36Sopenharmony_ci for ( ; ; ) { 105562306a36Sopenharmony_ci r = queue->rx_curr_get ; 105662306a36Sopenharmony_ci rx_used = queue->rx_used ; 105762306a36Sopenharmony_ci frag_count = 0 ; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci#ifdef USE_BREAK_ISR 106062306a36Sopenharmony_ci if (smc->os.hwm.leave_isr) { 106162306a36Sopenharmony_ci goto rx_end ; 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci#endif 106462306a36Sopenharmony_ci#ifdef NDIS_OS2 106562306a36Sopenharmony_ci if (offDepth) { 106662306a36Sopenharmony_ci smc->os.hwm.rx_break = 1 ; 106762306a36Sopenharmony_ci goto rx_end ; 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci smc->os.hwm.rx_break = 0 ; 107062306a36Sopenharmony_ci#endif 107162306a36Sopenharmony_ci#ifdef ODI2 107262306a36Sopenharmony_ci if (smc->os.hwm.rx_break) { 107362306a36Sopenharmony_ci goto rx_end ; 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci#endif 107662306a36Sopenharmony_ci n = 0 ; 107762306a36Sopenharmony_ci do { 107862306a36Sopenharmony_ci DB_RX(5, "Check RxD %p for OWN and EOF", r); 107962306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 108062306a36Sopenharmony_ci rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl)); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci if (rbctrl & BMU_OWN) { 108362306a36Sopenharmony_ci NDD_TRACE("RHxE",r,rfsw,rbctrl) ; 108462306a36Sopenharmony_ci DB_RX(4, "End of RxDs"); 108562306a36Sopenharmony_ci goto rx_end ; 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci /* 108862306a36Sopenharmony_ci * out of RxD detection 108962306a36Sopenharmony_ci */ 109062306a36Sopenharmony_ci if (!rx_used) { 109162306a36Sopenharmony_ci SK_BREAK() ; 109262306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ; 109362306a36Sopenharmony_ci /* Either we don't have an RxD or all 109462306a36Sopenharmony_ci * RxDs are filled. Therefore it's allowed 109562306a36Sopenharmony_ci * for to set the STOPPED flag */ 109662306a36Sopenharmony_ci smc->hw.hw_state = STOPPED ; 109762306a36Sopenharmony_ci mac_drv_clear_rx_queue(smc) ; 109862306a36Sopenharmony_ci smc->hw.hw_state = STARTED ; 109962306a36Sopenharmony_ci mac_drv_fill_rxd(smc) ; 110062306a36Sopenharmony_ci smc->os.hwm.detec_count = 0 ; 110162306a36Sopenharmony_ci goto rx_end ; 110262306a36Sopenharmony_ci } 110362306a36Sopenharmony_ci rfsw = le32_to_cpu(r->rxd_rfsw) ; 110462306a36Sopenharmony_ci if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) { 110562306a36Sopenharmony_ci /* 110662306a36Sopenharmony_ci * The BMU_STF bit is deleted, 1 frame is 110762306a36Sopenharmony_ci * placed into more than 1 rx buffer 110862306a36Sopenharmony_ci * 110962306a36Sopenharmony_ci * skip frame by setting the rx len to 0 111062306a36Sopenharmony_ci * 111162306a36Sopenharmony_ci * if fragment count == 0 111262306a36Sopenharmony_ci * The missing STF bit belongs to the 111362306a36Sopenharmony_ci * current frame, search for the 111462306a36Sopenharmony_ci * EOF bit to complete the frame 111562306a36Sopenharmony_ci * else 111662306a36Sopenharmony_ci * the fragment belongs to the next frame, 111762306a36Sopenharmony_ci * exit the loop and process the frame 111862306a36Sopenharmony_ci */ 111962306a36Sopenharmony_ci SK_BREAK() ; 112062306a36Sopenharmony_ci rfsw = 0 ; 112162306a36Sopenharmony_ci if (frag_count) { 112262306a36Sopenharmony_ci break ; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci n += rbctrl & 0xffff ; 112662306a36Sopenharmony_ci r = r->rxd_next ; 112762306a36Sopenharmony_ci frag_count++ ; 112862306a36Sopenharmony_ci rx_used-- ; 112962306a36Sopenharmony_ci } while (!(rbctrl & BMU_EOF)) ; 113062306a36Sopenharmony_ci used_frags = frag_count ; 113162306a36Sopenharmony_ci DB_RX(5, "EOF set in RxD, used_frags = %d", used_frags); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */ 113462306a36Sopenharmony_ci /* BMU_ST_BUF will not be changed by the ASIC */ 113562306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 113662306a36Sopenharmony_ci while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) { 113762306a36Sopenharmony_ci DB_RX(5, "Check STF bit in %p", r); 113862306a36Sopenharmony_ci r = r->rxd_next ; 113962306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 114062306a36Sopenharmony_ci frag_count++ ; 114162306a36Sopenharmony_ci rx_used-- ; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci DB_RX(5, "STF bit found"); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* 114662306a36Sopenharmony_ci * The received frame is finished for the process receive 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci rxd = queue->rx_curr_get ; 114962306a36Sopenharmony_ci queue->rx_curr_get = r ; 115062306a36Sopenharmony_ci queue->rx_free += frag_count ; 115162306a36Sopenharmony_ci queue->rx_used = rx_used ; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci /* 115462306a36Sopenharmony_ci * ASIC Errata no. 7 (STF - Bit Bug) 115562306a36Sopenharmony_ci */ 115662306a36Sopenharmony_ci rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){ 115962306a36Sopenharmony_ci DB_RX(5, "dma_complete for RxD %p", r); 116062306a36Sopenharmony_ci dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR); 116162306a36Sopenharmony_ci } 116262306a36Sopenharmony_ci smc->hw.fp.err_stats.err_valid++ ; 116362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACCopied_Ct++ ; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci /* the length of the data including the FC */ 116662306a36Sopenharmony_ci len = (rfsw & RD_LENGTH) - 4 ; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci DB_RX(4, "frame length = %d", len); 116962306a36Sopenharmony_ci /* 117062306a36Sopenharmony_ci * check the frame_length and all error flags 117162306a36Sopenharmony_ci */ 117262306a36Sopenharmony_ci if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){ 117362306a36Sopenharmony_ci if (rfsw & RD_S_MSRABT) { 117462306a36Sopenharmony_ci DB_RX(2, "Frame aborted by the FORMAC"); 117562306a36Sopenharmony_ci smc->hw.fp.err_stats.err_abort++ ; 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci /* 117862306a36Sopenharmony_ci * check frame status 117962306a36Sopenharmony_ci */ 118062306a36Sopenharmony_ci if (rfsw & RD_S_SEAC2) { 118162306a36Sopenharmony_ci DB_RX(2, "E-Indicator set"); 118262306a36Sopenharmony_ci smc->hw.fp.err_stats.err_e_indicator++ ; 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci if (rfsw & RD_S_SFRMERR) { 118562306a36Sopenharmony_ci DB_RX(2, "CRC error"); 118662306a36Sopenharmony_ci smc->hw.fp.err_stats.err_crc++ ; 118762306a36Sopenharmony_ci } 118862306a36Sopenharmony_ci if (rfsw & RX_FS_IMPL) { 118962306a36Sopenharmony_ci DB_RX(2, "Implementer frame"); 119062306a36Sopenharmony_ci smc->hw.fp.err_stats.err_imp_frame++ ; 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci goto abort_frame ; 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci if (len > FDDI_RAW_MTU-4) { 119562306a36Sopenharmony_ci DB_RX(2, "Frame too long error"); 119662306a36Sopenharmony_ci smc->hw.fp.err_stats.err_too_long++ ; 119762306a36Sopenharmony_ci goto abort_frame ; 119862306a36Sopenharmony_ci } 119962306a36Sopenharmony_ci /* 120062306a36Sopenharmony_ci * SUPERNET 3 Bug: FORMAC delivers status words 120162306a36Sopenharmony_ci * of aborted frames to the BMU 120262306a36Sopenharmony_ci */ 120362306a36Sopenharmony_ci if (len <= 4) { 120462306a36Sopenharmony_ci DB_RX(2, "Frame length = 0"); 120562306a36Sopenharmony_ci goto abort_frame ; 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci if (len != (n-4)) { 120962306a36Sopenharmony_ci DB_RX(4, "BMU: rx len differs: [%d:%d]", len, n); 121062306a36Sopenharmony_ci smc->os.hwm.rx_len_error++ ; 121162306a36Sopenharmony_ci goto abort_frame ; 121262306a36Sopenharmony_ci } 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* 121562306a36Sopenharmony_ci * Check SA == MA 121662306a36Sopenharmony_ci */ 121762306a36Sopenharmony_ci virt = (u_char far *) rxd->rxd_virt ; 121862306a36Sopenharmony_ci DB_RX(2, "FC = %x", *virt); 121962306a36Sopenharmony_ci if (virt[12] == MA[5] && 122062306a36Sopenharmony_ci virt[11] == MA[4] && 122162306a36Sopenharmony_ci virt[10] == MA[3] && 122262306a36Sopenharmony_ci virt[9] == MA[2] && 122362306a36Sopenharmony_ci virt[8] == MA[1] && 122462306a36Sopenharmony_ci (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) { 122562306a36Sopenharmony_ci goto abort_frame ; 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci /* 122962306a36Sopenharmony_ci * test if LLC frame 123062306a36Sopenharmony_ci */ 123162306a36Sopenharmony_ci if (rfsw & RX_FS_LLC) { 123262306a36Sopenharmony_ci /* 123362306a36Sopenharmony_ci * if pass_llc_promisc is disable 123462306a36Sopenharmony_ci * if DA != Multicast or Broadcast or DA!=MA 123562306a36Sopenharmony_ci * abort the frame 123662306a36Sopenharmony_ci */ 123762306a36Sopenharmony_ci if (!smc->os.hwm.pass_llc_promisc) { 123862306a36Sopenharmony_ci if(!(virt[1] & GROUP_ADDR_BIT)) { 123962306a36Sopenharmony_ci if (virt[6] != MA[5] || 124062306a36Sopenharmony_ci virt[5] != MA[4] || 124162306a36Sopenharmony_ci virt[4] != MA[3] || 124262306a36Sopenharmony_ci virt[3] != MA[2] || 124362306a36Sopenharmony_ci virt[2] != MA[1] || 124462306a36Sopenharmony_ci virt[1] != MA[0]) { 124562306a36Sopenharmony_ci DB_RX(2, "DA != MA and not multi- or broadcast"); 124662306a36Sopenharmony_ci goto abort_frame ; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci /* 125262306a36Sopenharmony_ci * LLC frame received 125362306a36Sopenharmony_ci */ 125462306a36Sopenharmony_ci DB_RX(4, "LLC - receive"); 125562306a36Sopenharmony_ci mac_drv_rx_complete(smc,rxd,frag_count,len) ; 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci else { 125862306a36Sopenharmony_ci if (!(mb = smt_get_mbuf(smc))) { 125962306a36Sopenharmony_ci smc->hw.fp.err_stats.err_no_buf++ ; 126062306a36Sopenharmony_ci DB_RX(4, "No SMbuf; receive terminated"); 126162306a36Sopenharmony_ci goto abort_frame ; 126262306a36Sopenharmony_ci } 126362306a36Sopenharmony_ci data = smtod(mb,char *) - 1 ; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci /* 126662306a36Sopenharmony_ci * copy the frame into a SMT_MBuf 126762306a36Sopenharmony_ci */ 126862306a36Sopenharmony_ci#ifdef USE_OS_CPY 126962306a36Sopenharmony_ci hwm_cpy_rxd2mb(rxd,data,len) ; 127062306a36Sopenharmony_ci#else 127162306a36Sopenharmony_ci for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){ 127262306a36Sopenharmony_ci n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ; 127362306a36Sopenharmony_ci DB_RX(6, "cp SMT frame to mb: len = %d", n); 127462306a36Sopenharmony_ci memcpy(data,r->rxd_virt,n) ; 127562306a36Sopenharmony_ci data += n ; 127662306a36Sopenharmony_ci } 127762306a36Sopenharmony_ci data = smtod(mb,char *) - 1 ; 127862306a36Sopenharmony_ci#endif 127962306a36Sopenharmony_ci fc = *(char *)mb->sm_data = *data ; 128062306a36Sopenharmony_ci mb->sm_len = len - 1 ; /* len - fc */ 128162306a36Sopenharmony_ci data++ ; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* 128462306a36Sopenharmony_ci * SMT frame received 128562306a36Sopenharmony_ci */ 128662306a36Sopenharmony_ci switch(fc) { 128762306a36Sopenharmony_ci case FC_SMT_INFO : 128862306a36Sopenharmony_ci smc->hw.fp.err_stats.err_smt_frame++ ; 128962306a36Sopenharmony_ci DB_RX(5, "SMT frame received"); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci if (smc->os.hwm.pass_SMT) { 129262306a36Sopenharmony_ci DB_RX(5, "pass SMT frame"); 129362306a36Sopenharmony_ci mac_drv_rx_complete(smc, rxd, 129462306a36Sopenharmony_ci frag_count,len) ; 129562306a36Sopenharmony_ci } 129662306a36Sopenharmony_ci else { 129762306a36Sopenharmony_ci DB_RX(5, "requeue RxD"); 129862306a36Sopenharmony_ci mac_drv_requeue_rxd(smc,rxd,frag_count); 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci smt_received_pack(smc,mb,(int)(rfsw>>25)) ; 130262306a36Sopenharmony_ci break ; 130362306a36Sopenharmony_ci case FC_SMT_NSA : 130462306a36Sopenharmony_ci smc->hw.fp.err_stats.err_smt_frame++ ; 130562306a36Sopenharmony_ci DB_RX(5, "SMT frame received"); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci /* if pass_NSA set pass the NSA frame or */ 130862306a36Sopenharmony_ci /* pass_SMT set and the A-Indicator */ 130962306a36Sopenharmony_ci /* is not set, pass the NSA frame */ 131062306a36Sopenharmony_ci if (smc->os.hwm.pass_NSA || 131162306a36Sopenharmony_ci (smc->os.hwm.pass_SMT && 131262306a36Sopenharmony_ci !(rfsw & A_INDIC))) { 131362306a36Sopenharmony_ci DB_RX(5, "pass SMT frame"); 131462306a36Sopenharmony_ci mac_drv_rx_complete(smc, rxd, 131562306a36Sopenharmony_ci frag_count,len) ; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci else { 131862306a36Sopenharmony_ci DB_RX(5, "requeue RxD"); 131962306a36Sopenharmony_ci mac_drv_requeue_rxd(smc,rxd,frag_count); 132062306a36Sopenharmony_ci } 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci smt_received_pack(smc,mb,(int)(rfsw>>25)) ; 132362306a36Sopenharmony_ci break ; 132462306a36Sopenharmony_ci case FC_BEACON : 132562306a36Sopenharmony_ci if (smc->os.hwm.pass_DB) { 132662306a36Sopenharmony_ci DB_RX(5, "pass DB frame"); 132762306a36Sopenharmony_ci mac_drv_rx_complete(smc, rxd, 132862306a36Sopenharmony_ci frag_count,len) ; 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci else { 133162306a36Sopenharmony_ci DB_RX(5, "requeue RxD"); 133262306a36Sopenharmony_ci mac_drv_requeue_rxd(smc,rxd,frag_count); 133362306a36Sopenharmony_ci } 133462306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 133562306a36Sopenharmony_ci break ; 133662306a36Sopenharmony_ci default : 133762306a36Sopenharmony_ci /* 133862306a36Sopenharmony_ci * unknown FC abort the frame 133962306a36Sopenharmony_ci */ 134062306a36Sopenharmony_ci DB_RX(2, "unknown FC error"); 134162306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 134262306a36Sopenharmony_ci DB_RX(5, "requeue RxD"); 134362306a36Sopenharmony_ci mac_drv_requeue_rxd(smc,rxd,frag_count) ; 134462306a36Sopenharmony_ci if ((fc & 0xf0) == FC_MAC) 134562306a36Sopenharmony_ci smc->hw.fp.err_stats.err_mac_frame++ ; 134662306a36Sopenharmony_ci else 134762306a36Sopenharmony_ci smc->hw.fp.err_stats.err_imp_frame++ ; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci break ; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci } 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci DB_RX(3, "next RxD is %p", queue->rx_curr_get); 135462306a36Sopenharmony_ci NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci continue ; 135762306a36Sopenharmony_ci /*--------------------------------------------------------------------*/ 135862306a36Sopenharmony_ciabort_frame: 135962306a36Sopenharmony_ci DB_RX(5, "requeue RxD"); 136062306a36Sopenharmony_ci mac_drv_requeue_rxd(smc,rxd,frag_count) ; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci DB_RX(3, "next RxD is %p", queue->rx_curr_get); 136362306a36Sopenharmony_ci NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_cirx_end: 136662306a36Sopenharmony_ci#ifdef ALL_RX_COMPLETE 136762306a36Sopenharmony_ci mac_drv_all_receives_complete(smc) ; 136862306a36Sopenharmony_ci#endif 136962306a36Sopenharmony_ci return ; /* lint bug: needs return detect end of function */ 137062306a36Sopenharmony_ci} 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_cistatic void smt_to_llc(struct s_smc *smc, SMbuf *mb) 137362306a36Sopenharmony_ci{ 137462306a36Sopenharmony_ci u_char fc ; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci DB_RX(4, "send a queued frame to the llc layer"); 137762306a36Sopenharmony_ci smc->os.hwm.r.len = mb->sm_len ; 137862306a36Sopenharmony_ci smc->os.hwm.r.mb_pos = smtod(mb,char *) ; 137962306a36Sopenharmony_ci fc = *smc->os.hwm.r.mb_pos ; 138062306a36Sopenharmony_ci (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc, 138162306a36Sopenharmony_ci smc->os.hwm.r.mb_pos,(int)mb->sm_len) ; 138262306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 138362306a36Sopenharmony_ci} 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci/* 138662306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(hwm_rx_frag) 138762306a36Sopenharmony_ci * void hwm_rx_frag(smc,virt,phys,len,frame_status) 138862306a36Sopenharmony_ci * 138962306a36Sopenharmony_ci * function MACRO (hardware module, hwmtm.h) 139062306a36Sopenharmony_ci * This function calls dma_master for preparing the 139162306a36Sopenharmony_ci * system hardware for the DMA transfer and initializes 139262306a36Sopenharmony_ci * the current RxD with the length and the physical and 139362306a36Sopenharmony_ci * virtual address of the fragment. Furthermore, it sets the 139462306a36Sopenharmony_ci * STF and EOF bits depending on the frame status byte, 139562306a36Sopenharmony_ci * switches the OWN flag of the RxD, so that it is owned by the 139662306a36Sopenharmony_ci * adapter and issues an rx_start. 139762306a36Sopenharmony_ci * 139862306a36Sopenharmony_ci * para virt virtual pointer to the fragment 139962306a36Sopenharmony_ci * len the length of the fragment 140062306a36Sopenharmony_ci * frame_status status of the frame, see design description 140162306a36Sopenharmony_ci * 140262306a36Sopenharmony_ci * NOTE: It is possible to call this function with a fragment length 140362306a36Sopenharmony_ci * of zero. 140462306a36Sopenharmony_ci * 140562306a36Sopenharmony_ci * END_MANUAL_ENTRY 140662306a36Sopenharmony_ci */ 140762306a36Sopenharmony_civoid hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, 140862306a36Sopenharmony_ci int frame_status) 140962306a36Sopenharmony_ci{ 141062306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *r ; 141162306a36Sopenharmony_ci __le32 rbctrl; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci NDD_TRACE("RHfB",virt,len,frame_status) ; 141462306a36Sopenharmony_ci DB_RX(2, "hwm_rx_frag: len = %d, frame_status = %x", len, frame_status); 141562306a36Sopenharmony_ci r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ; 141662306a36Sopenharmony_ci r->rxd_virt = virt ; 141762306a36Sopenharmony_ci r->rxd_rbadr = cpu_to_le32(phys) ; 141862306a36Sopenharmony_ci rbctrl = cpu_to_le32( (((__u32)frame_status & 141962306a36Sopenharmony_ci (FIRST_FRAG|LAST_FRAG))<<26) | 142062306a36Sopenharmony_ci (((u_long) frame_status & FIRST_FRAG) << 21) | 142162306a36Sopenharmony_ci BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ; 142262306a36Sopenharmony_ci r->rxd_rbctrl = rbctrl ; 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; 142562306a36Sopenharmony_ci outpd(ADDR(B0_R1_CSR),CSR_START) ; 142662306a36Sopenharmony_ci smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ; 142762306a36Sopenharmony_ci smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ; 142862306a36Sopenharmony_ci smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ; 142962306a36Sopenharmony_ci NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ; 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci/* 143362306a36Sopenharmony_ci * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) 143462306a36Sopenharmony_ci * 143562306a36Sopenharmony_ci * void mac_drv_clear_rx_queue(smc) 143662306a36Sopenharmony_ci * struct s_smc *smc ; 143762306a36Sopenharmony_ci * 143862306a36Sopenharmony_ci * function DOWNCALL (hardware module, hwmtm.c) 143962306a36Sopenharmony_ci * mac_drv_clear_rx_queue is called by the OS-specific module 144062306a36Sopenharmony_ci * after it has issued a card_stop. 144162306a36Sopenharmony_ci * In this case, the frames in the receive queue are obsolete and 144262306a36Sopenharmony_ci * should be removed. For removing mac_drv_clear_rx_queue 144362306a36Sopenharmony_ci * calls dma_master for each RxD and mac_drv_clear_rxd for each 144462306a36Sopenharmony_ci * receive buffer. 144562306a36Sopenharmony_ci * 144662306a36Sopenharmony_ci * NOTE: calling sequence card_stop: 144762306a36Sopenharmony_ci * CLI_FBI(), card_stop(), 144862306a36Sopenharmony_ci * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(), 144962306a36Sopenharmony_ci * 145062306a36Sopenharmony_ci * NOTE: The caller is responsible that the BMUs are idle 145162306a36Sopenharmony_ci * when this function is called. 145262306a36Sopenharmony_ci * 145362306a36Sopenharmony_ci * END_MANUAL_ENTRY 145462306a36Sopenharmony_ci */ 145562306a36Sopenharmony_civoid mac_drv_clear_rx_queue(struct s_smc *smc) 145662306a36Sopenharmony_ci{ 145762306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *r ; 145862306a36Sopenharmony_ci struct s_smt_fp_rxd volatile *next_rxd ; 145962306a36Sopenharmony_ci struct s_smt_rx_queue *queue ; 146062306a36Sopenharmony_ci int frag_count ; 146162306a36Sopenharmony_ci int i ; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci if (smc->hw.hw_state != STOPPED) { 146462306a36Sopenharmony_ci SK_BREAK() ; 146562306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ; 146662306a36Sopenharmony_ci return ; 146762306a36Sopenharmony_ci } 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci queue = smc->hw.fp.rx[QUEUE_R1] ; 147062306a36Sopenharmony_ci DB_RX(5, "clear_rx_queue"); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci /* 147362306a36Sopenharmony_ci * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_ci r = queue->rx_curr_get ; 147662306a36Sopenharmony_ci while (queue->rx_used) { 147762306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 147862306a36Sopenharmony_ci DB_RX(5, "switch OWN bit of RxD 0x%p", r); 147962306a36Sopenharmony_ci r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ; 148062306a36Sopenharmony_ci frag_count = 1 ; 148162306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; 148262306a36Sopenharmony_ci r = r->rxd_next ; 148362306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 148462306a36Sopenharmony_ci while (r != queue->rx_curr_put && 148562306a36Sopenharmony_ci !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) { 148662306a36Sopenharmony_ci DB_RX(5, "Check STF bit in %p", r); 148762306a36Sopenharmony_ci r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ; 148862306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; 148962306a36Sopenharmony_ci r = r->rxd_next ; 149062306a36Sopenharmony_ci DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; 149162306a36Sopenharmony_ci frag_count++ ; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci DB_RX(5, "STF bit found"); 149462306a36Sopenharmony_ci next_rxd = r ; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){ 149762306a36Sopenharmony_ci DB_RX(5, "dma_complete for RxD %p", r); 149862306a36Sopenharmony_ci dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR); 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci DB_RX(5, "mac_drv_clear_rxd: RxD %p frag_count %d", 150262306a36Sopenharmony_ci queue->rx_curr_get, frag_count); 150362306a36Sopenharmony_ci mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci queue->rx_curr_get = next_rxd ; 150662306a36Sopenharmony_ci queue->rx_used -= frag_count ; 150762306a36Sopenharmony_ci queue->rx_free += frag_count ; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci} 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci/* 151362306a36Sopenharmony_ci ------------------------------------------------------------- 151462306a36Sopenharmony_ci SEND FUNCTIONS: 151562306a36Sopenharmony_ci ------------------------------------------------------------- 151662306a36Sopenharmony_ci*/ 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci/* 151962306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(hwm_tx_init) 152062306a36Sopenharmony_ci * int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status) 152162306a36Sopenharmony_ci * 152262306a36Sopenharmony_ci * function DOWN_CALL (hardware module, hwmtm.c) 152362306a36Sopenharmony_ci * hwm_tx_init checks if the frame can be sent through the 152462306a36Sopenharmony_ci * corresponding send queue. 152562306a36Sopenharmony_ci * 152662306a36Sopenharmony_ci * para fc the frame control. To determine through which 152762306a36Sopenharmony_ci * send queue the frame should be transmitted. 152862306a36Sopenharmony_ci * 0x50 - 0x57: asynchronous LLC frame 152962306a36Sopenharmony_ci * 0xD0 - 0xD7: synchronous LLC frame 153062306a36Sopenharmony_ci * 0x41, 0x4F: SMT frame to the network 153162306a36Sopenharmony_ci * 0x42: SMT frame to the network and to the local SMT 153262306a36Sopenharmony_ci * 0x43: SMT frame to the local SMT 153362306a36Sopenharmony_ci * frag_count count of the fragments for this frame 153462306a36Sopenharmony_ci * frame_len length of the frame 153562306a36Sopenharmony_ci * frame_status status of the frame, the send queue bit is already 153662306a36Sopenharmony_ci * specified 153762306a36Sopenharmony_ci * 153862306a36Sopenharmony_ci * return frame_status 153962306a36Sopenharmony_ci * 154062306a36Sopenharmony_ci * END_MANUAL_ENTRY 154162306a36Sopenharmony_ci */ 154262306a36Sopenharmony_ciint hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, 154362306a36Sopenharmony_ci int frame_status) 154462306a36Sopenharmony_ci{ 154562306a36Sopenharmony_ci NDD_TRACE("THiB",fc,frag_count,frame_len) ; 154662306a36Sopenharmony_ci smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ; 154762306a36Sopenharmony_ci smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ; 154862306a36Sopenharmony_ci smc->os.hwm.tx_len = frame_len ; 154962306a36Sopenharmony_ci DB_TX(3, "hwm_tx_init: fc = %x, len = %d", fc, frame_len); 155062306a36Sopenharmony_ci if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) { 155162306a36Sopenharmony_ci frame_status |= LAN_TX ; 155262306a36Sopenharmony_ci } 155362306a36Sopenharmony_ci else { 155462306a36Sopenharmony_ci switch (fc) { 155562306a36Sopenharmony_ci case FC_SMT_INFO : 155662306a36Sopenharmony_ci case FC_SMT_NSA : 155762306a36Sopenharmony_ci frame_status |= LAN_TX ; 155862306a36Sopenharmony_ci break ; 155962306a36Sopenharmony_ci case FC_SMT_LOC : 156062306a36Sopenharmony_ci frame_status |= LOC_TX ; 156162306a36Sopenharmony_ci break ; 156262306a36Sopenharmony_ci case FC_SMT_LAN_LOC : 156362306a36Sopenharmony_ci frame_status |= LAN_TX | LOC_TX ; 156462306a36Sopenharmony_ci break ; 156562306a36Sopenharmony_ci default : 156662306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ; 156762306a36Sopenharmony_ci } 156862306a36Sopenharmony_ci } 156962306a36Sopenharmony_ci if (!smc->hw.mac_ring_is_up) { 157062306a36Sopenharmony_ci frame_status &= ~LAN_TX ; 157162306a36Sopenharmony_ci frame_status |= RING_DOWN ; 157262306a36Sopenharmony_ci DB_TX(2, "Ring is down: terminate LAN_TX"); 157362306a36Sopenharmony_ci } 157462306a36Sopenharmony_ci if (frag_count > smc->os.hwm.tx_p->tx_free) { 157562306a36Sopenharmony_ci#ifndef NDIS_OS2 157662306a36Sopenharmony_ci mac_drv_clear_txd(smc) ; 157762306a36Sopenharmony_ci if (frag_count > smc->os.hwm.tx_p->tx_free) { 157862306a36Sopenharmony_ci DB_TX(2, "Out of TxDs, terminate LAN_TX"); 157962306a36Sopenharmony_ci frame_status &= ~LAN_TX ; 158062306a36Sopenharmony_ci frame_status |= OUT_OF_TXD ; 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci#else 158362306a36Sopenharmony_ci DB_TX(2, "Out of TxDs, terminate LAN_TX"); 158462306a36Sopenharmony_ci frame_status &= ~LAN_TX ; 158562306a36Sopenharmony_ci frame_status |= OUT_OF_TXD ; 158662306a36Sopenharmony_ci#endif 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci DB_TX(3, "frame_status = %x", frame_status); 158962306a36Sopenharmony_ci NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ; 159062306a36Sopenharmony_ci return frame_status; 159162306a36Sopenharmony_ci} 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci/* 159462306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(hwm_tx_frag) 159562306a36Sopenharmony_ci * void hwm_tx_frag(smc,virt,phys,len,frame_status) 159662306a36Sopenharmony_ci * 159762306a36Sopenharmony_ci * function DOWNCALL (hardware module, hwmtm.c) 159862306a36Sopenharmony_ci * If the frame should be sent to the LAN, this function calls 159962306a36Sopenharmony_ci * dma_master, fills the current TxD with the virtual and the 160062306a36Sopenharmony_ci * physical address, sets the STF and EOF bits dependent on 160162306a36Sopenharmony_ci * the frame status, and requests the BMU to start the 160262306a36Sopenharmony_ci * transmit. 160362306a36Sopenharmony_ci * If the frame should be sent to the local SMT, an SMT_MBuf 160462306a36Sopenharmony_ci * is allocated if the FIRST_FRAG bit is set in the frame_status. 160562306a36Sopenharmony_ci * The fragment of the frame is copied into the SMT MBuf. 160662306a36Sopenharmony_ci * The function smt_received_pack is called if the LAST_FRAG 160762306a36Sopenharmony_ci * bit is set in the frame_status word. 160862306a36Sopenharmony_ci * 160962306a36Sopenharmony_ci * para virt virtual pointer to the fragment 161062306a36Sopenharmony_ci * len the length of the fragment 161162306a36Sopenharmony_ci * frame_status status of the frame, see design description 161262306a36Sopenharmony_ci * 161362306a36Sopenharmony_ci * return nothing returned, no parameter is modified 161462306a36Sopenharmony_ci * 161562306a36Sopenharmony_ci * NOTE: It is possible to invoke this macro with a fragment length 161662306a36Sopenharmony_ci * of zero. 161762306a36Sopenharmony_ci * 161862306a36Sopenharmony_ci * END_MANUAL_ENTRY 161962306a36Sopenharmony_ci */ 162062306a36Sopenharmony_civoid hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, 162162306a36Sopenharmony_ci int frame_status) 162262306a36Sopenharmony_ci{ 162362306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t ; 162462306a36Sopenharmony_ci struct s_smt_tx_queue *queue ; 162562306a36Sopenharmony_ci __le32 tbctrl ; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci queue = smc->os.hwm.tx_p ; 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci NDD_TRACE("THfB",virt,len,frame_status) ; 163062306a36Sopenharmony_ci /* Bug fix: AF / May 31 1999 (#missing) 163162306a36Sopenharmony_ci * snmpinfo problem reported by IBM is caused by invalid 163262306a36Sopenharmony_ci * t-pointer (txd) if LAN_TX is not set but LOC_TX only. 163362306a36Sopenharmony_ci * Set: t = queue->tx_curr_put here ! 163462306a36Sopenharmony_ci */ 163562306a36Sopenharmony_ci t = queue->tx_curr_put ; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci DB_TX(2, "hwm_tx_frag: len = %d, frame_status = %x", len, frame_status); 163862306a36Sopenharmony_ci if (frame_status & LAN_TX) { 163962306a36Sopenharmony_ci /* '*t' is already defined */ 164062306a36Sopenharmony_ci DB_TX(3, "LAN_TX: TxD = %p, virt = %p", t, virt); 164162306a36Sopenharmony_ci t->txd_virt = virt ; 164262306a36Sopenharmony_ci t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ; 164362306a36Sopenharmony_ci t->txd_tbadr = cpu_to_le32(phys) ; 164462306a36Sopenharmony_ci tbctrl = cpu_to_le32((((__u32)frame_status & 164562306a36Sopenharmony_ci (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) | 164662306a36Sopenharmony_ci BMU_OWN|BMU_CHECK |len) ; 164762306a36Sopenharmony_ci t->txd_tbctrl = tbctrl ; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci#ifndef AIX 165062306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 165162306a36Sopenharmony_ci outpd(queue->tx_bmu_ctl,CSR_START) ; 165262306a36Sopenharmony_ci#else /* ifndef AIX */ 165362306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 165462306a36Sopenharmony_ci if (frame_status & QUEUE_A0) { 165562306a36Sopenharmony_ci outpd(ADDR(B0_XA_CSR),CSR_START) ; 165662306a36Sopenharmony_ci } 165762306a36Sopenharmony_ci else { 165862306a36Sopenharmony_ci outpd(ADDR(B0_XS_CSR),CSR_START) ; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci#endif 166162306a36Sopenharmony_ci queue->tx_free-- ; 166262306a36Sopenharmony_ci queue->tx_used++ ; 166362306a36Sopenharmony_ci queue->tx_curr_put = t->txd_next ; 166462306a36Sopenharmony_ci if (frame_status & LAST_FRAG) { 166562306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACTransmit_Ct++ ; 166662306a36Sopenharmony_ci } 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci if (frame_status & LOC_TX) { 166962306a36Sopenharmony_ci DB_TX(3, "LOC_TX:"); 167062306a36Sopenharmony_ci if (frame_status & FIRST_FRAG) { 167162306a36Sopenharmony_ci if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) { 167262306a36Sopenharmony_ci smc->hw.fp.err_stats.err_no_buf++ ; 167362306a36Sopenharmony_ci DB_TX(4, "No SMbuf; transmit terminated"); 167462306a36Sopenharmony_ci } 167562306a36Sopenharmony_ci else { 167662306a36Sopenharmony_ci smc->os.hwm.tx_data = 167762306a36Sopenharmony_ci smtod(smc->os.hwm.tx_mb,char *) - 1 ; 167862306a36Sopenharmony_ci#ifdef USE_OS_CPY 167962306a36Sopenharmony_ci#ifdef PASS_1ST_TXD_2_TX_COMP 168062306a36Sopenharmony_ci hwm_cpy_txd2mb(t,smc->os.hwm.tx_data, 168162306a36Sopenharmony_ci smc->os.hwm.tx_len) ; 168262306a36Sopenharmony_ci#endif 168362306a36Sopenharmony_ci#endif 168462306a36Sopenharmony_ci } 168562306a36Sopenharmony_ci } 168662306a36Sopenharmony_ci if (smc->os.hwm.tx_mb) { 168762306a36Sopenharmony_ci#ifndef USE_OS_CPY 168862306a36Sopenharmony_ci DB_TX(3, "copy fragment into MBuf"); 168962306a36Sopenharmony_ci memcpy(smc->os.hwm.tx_data,virt,len) ; 169062306a36Sopenharmony_ci smc->os.hwm.tx_data += len ; 169162306a36Sopenharmony_ci#endif 169262306a36Sopenharmony_ci if (frame_status & LAST_FRAG) { 169362306a36Sopenharmony_ci#ifdef USE_OS_CPY 169462306a36Sopenharmony_ci#ifndef PASS_1ST_TXD_2_TX_COMP 169562306a36Sopenharmony_ci /* 169662306a36Sopenharmony_ci * hwm_cpy_txd2mb(txd,data,len) copies 'len' 169762306a36Sopenharmony_ci * bytes from the virtual pointer in 'rxd' 169862306a36Sopenharmony_ci * to 'data'. The virtual pointer of the 169962306a36Sopenharmony_ci * os-specific tx-buffer should be written 170062306a36Sopenharmony_ci * in the LAST txd. 170162306a36Sopenharmony_ci */ 170262306a36Sopenharmony_ci hwm_cpy_txd2mb(t,smc->os.hwm.tx_data, 170362306a36Sopenharmony_ci smc->os.hwm.tx_len) ; 170462306a36Sopenharmony_ci#endif /* nPASS_1ST_TXD_2_TX_COMP */ 170562306a36Sopenharmony_ci#endif /* USE_OS_CPY */ 170662306a36Sopenharmony_ci smc->os.hwm.tx_data = 170762306a36Sopenharmony_ci smtod(smc->os.hwm.tx_mb,char *) - 1 ; 170862306a36Sopenharmony_ci *(char *)smc->os.hwm.tx_mb->sm_data = 170962306a36Sopenharmony_ci *smc->os.hwm.tx_data ; 171062306a36Sopenharmony_ci smc->os.hwm.tx_data++ ; 171162306a36Sopenharmony_ci smc->os.hwm.tx_mb->sm_len = 171262306a36Sopenharmony_ci smc->os.hwm.tx_len - 1 ; 171362306a36Sopenharmony_ci DB_TX(3, "pass LLC frame to SMT"); 171462306a36Sopenharmony_ci smt_received_pack(smc,smc->os.hwm.tx_mb, 171562306a36Sopenharmony_ci RD_FS_LOCAL) ; 171662306a36Sopenharmony_ci } 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci NDD_TRACE("THfE",t,queue->tx_free,0) ; 172062306a36Sopenharmony_ci} 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci/* 172462306a36Sopenharmony_ci * queues a receive for later send 172562306a36Sopenharmony_ci */ 172662306a36Sopenharmony_cistatic void queue_llc_rx(struct s_smc *smc, SMbuf *mb) 172762306a36Sopenharmony_ci{ 172862306a36Sopenharmony_ci DB_GEN(4, "queue_llc_rx: mb = %p", mb); 172962306a36Sopenharmony_ci smc->os.hwm.queued_rx_frames++ ; 173062306a36Sopenharmony_ci mb->sm_next = (SMbuf *)NULL ; 173162306a36Sopenharmony_ci if (smc->os.hwm.llc_rx_pipe == NULL) { 173262306a36Sopenharmony_ci smc->os.hwm.llc_rx_pipe = mb ; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci else { 173562306a36Sopenharmony_ci smc->os.hwm.llc_rx_tail->sm_next = mb ; 173662306a36Sopenharmony_ci } 173762306a36Sopenharmony_ci smc->os.hwm.llc_rx_tail = mb ; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci /* 174062306a36Sopenharmony_ci * force an timer IRQ to receive the data 174162306a36Sopenharmony_ci */ 174262306a36Sopenharmony_ci if (!smc->os.hwm.isr_flag) { 174362306a36Sopenharmony_ci smt_force_irq(smc) ; 174462306a36Sopenharmony_ci } 174562306a36Sopenharmony_ci} 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci/* 174862306a36Sopenharmony_ci * get a SMbuf from the llc_rx_queue 174962306a36Sopenharmony_ci */ 175062306a36Sopenharmony_cistatic SMbuf *get_llc_rx(struct s_smc *smc) 175162306a36Sopenharmony_ci{ 175262306a36Sopenharmony_ci SMbuf *mb ; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci if ((mb = smc->os.hwm.llc_rx_pipe)) { 175562306a36Sopenharmony_ci smc->os.hwm.queued_rx_frames-- ; 175662306a36Sopenharmony_ci smc->os.hwm.llc_rx_pipe = mb->sm_next ; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci DB_GEN(4, "get_llc_rx: mb = 0x%p", mb); 175962306a36Sopenharmony_ci return mb; 176062306a36Sopenharmony_ci} 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci/* 176362306a36Sopenharmony_ci * queues a transmit SMT MBuf during the time were the MBuf is 176462306a36Sopenharmony_ci * queued the TxD ring 176562306a36Sopenharmony_ci */ 176662306a36Sopenharmony_cistatic void queue_txd_mb(struct s_smc *smc, SMbuf *mb) 176762306a36Sopenharmony_ci{ 176862306a36Sopenharmony_ci DB_GEN(4, "_rx: queue_txd_mb = %p", mb); 176962306a36Sopenharmony_ci smc->os.hwm.queued_txd_mb++ ; 177062306a36Sopenharmony_ci mb->sm_next = (SMbuf *)NULL ; 177162306a36Sopenharmony_ci if (smc->os.hwm.txd_tx_pipe == NULL) { 177262306a36Sopenharmony_ci smc->os.hwm.txd_tx_pipe = mb ; 177362306a36Sopenharmony_ci } 177462306a36Sopenharmony_ci else { 177562306a36Sopenharmony_ci smc->os.hwm.txd_tx_tail->sm_next = mb ; 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci smc->os.hwm.txd_tx_tail = mb ; 177862306a36Sopenharmony_ci} 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci/* 178162306a36Sopenharmony_ci * get a SMbuf from the txd_tx_queue 178262306a36Sopenharmony_ci */ 178362306a36Sopenharmony_cistatic SMbuf *get_txd_mb(struct s_smc *smc) 178462306a36Sopenharmony_ci{ 178562306a36Sopenharmony_ci SMbuf *mb ; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci if ((mb = smc->os.hwm.txd_tx_pipe)) { 178862306a36Sopenharmony_ci smc->os.hwm.queued_txd_mb-- ; 178962306a36Sopenharmony_ci smc->os.hwm.txd_tx_pipe = mb->sm_next ; 179062306a36Sopenharmony_ci } 179162306a36Sopenharmony_ci DB_GEN(4, "get_txd_mb: mb = 0x%p", mb); 179262306a36Sopenharmony_ci return mb; 179362306a36Sopenharmony_ci} 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci/* 179662306a36Sopenharmony_ci * SMT Send function 179762306a36Sopenharmony_ci */ 179862306a36Sopenharmony_civoid smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) 179962306a36Sopenharmony_ci{ 180062306a36Sopenharmony_ci char far *data ; 180162306a36Sopenharmony_ci int len ; 180262306a36Sopenharmony_ci int n ; 180362306a36Sopenharmony_ci int i ; 180462306a36Sopenharmony_ci int frag_count ; 180562306a36Sopenharmony_ci int frame_status ; 180662306a36Sopenharmony_ci SK_LOC_DECL(char far,*virt[3]) ; 180762306a36Sopenharmony_ci int frag_len[3] ; 180862306a36Sopenharmony_ci struct s_smt_tx_queue *queue ; 180962306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t ; 181062306a36Sopenharmony_ci u_long phys ; 181162306a36Sopenharmony_ci __le32 tbctrl; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci NDD_TRACE("THSB",mb,fc,0) ; 181462306a36Sopenharmony_ci DB_TX(4, "smt_send_mbuf: mb = 0x%p, fc = 0x%x", mb, fc); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci mb->sm_off-- ; /* set to fc */ 181762306a36Sopenharmony_ci mb->sm_len++ ; /* + fc */ 181862306a36Sopenharmony_ci data = smtod(mb,char *) ; 181962306a36Sopenharmony_ci *data = fc ; 182062306a36Sopenharmony_ci if (fc == FC_SMT_LOC) 182162306a36Sopenharmony_ci *data = FC_SMT_INFO ; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci /* 182462306a36Sopenharmony_ci * determine the frag count and the virt addresses of the frags 182562306a36Sopenharmony_ci */ 182662306a36Sopenharmony_ci frag_count = 0 ; 182762306a36Sopenharmony_ci len = mb->sm_len ; 182862306a36Sopenharmony_ci while (len) { 182962306a36Sopenharmony_ci n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ; 183062306a36Sopenharmony_ci if (n >= len) { 183162306a36Sopenharmony_ci n = len ; 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci DB_TX(5, "frag: virt/len = 0x%p/%d", data, n); 183462306a36Sopenharmony_ci virt[frag_count] = data ; 183562306a36Sopenharmony_ci frag_len[frag_count] = n ; 183662306a36Sopenharmony_ci frag_count++ ; 183762306a36Sopenharmony_ci len -= n ; 183862306a36Sopenharmony_ci data += n ; 183962306a36Sopenharmony_ci } 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci /* 184262306a36Sopenharmony_ci * determine the frame status 184362306a36Sopenharmony_ci */ 184462306a36Sopenharmony_ci queue = smc->hw.fp.tx[QUEUE_A0] ; 184562306a36Sopenharmony_ci if (fc == FC_BEACON || fc == FC_SMT_LOC) { 184662306a36Sopenharmony_ci frame_status = LOC_TX ; 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci else { 184962306a36Sopenharmony_ci frame_status = LAN_TX ; 185062306a36Sopenharmony_ci if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) || 185162306a36Sopenharmony_ci (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO))) 185262306a36Sopenharmony_ci frame_status |= LOC_TX ; 185362306a36Sopenharmony_ci } 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) { 185662306a36Sopenharmony_ci frame_status &= ~LAN_TX; 185762306a36Sopenharmony_ci if (frame_status) { 185862306a36Sopenharmony_ci DB_TX(2, "Ring is down: terminate LAN_TX"); 185962306a36Sopenharmony_ci } 186062306a36Sopenharmony_ci else { 186162306a36Sopenharmony_ci DB_TX(2, "Ring is down: terminate transmission"); 186262306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 186362306a36Sopenharmony_ci return ; 186462306a36Sopenharmony_ci } 186562306a36Sopenharmony_ci } 186662306a36Sopenharmony_ci DB_TX(5, "frame_status = 0x%x", frame_status); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) { 186962306a36Sopenharmony_ci mb->sm_use_count = 2 ; 187062306a36Sopenharmony_ci } 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci if (frame_status & LAN_TX) { 187362306a36Sopenharmony_ci t = queue->tx_curr_put ; 187462306a36Sopenharmony_ci frame_status |= FIRST_FRAG ; 187562306a36Sopenharmony_ci for (i = 0; i < frag_count; i++) { 187662306a36Sopenharmony_ci DB_TX(5, "init TxD = 0x%p", t); 187762306a36Sopenharmony_ci if (i == frag_count-1) { 187862306a36Sopenharmony_ci frame_status |= LAST_FRAG ; 187962306a36Sopenharmony_ci t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR | 188062306a36Sopenharmony_ci (((__u32)(mb->sm_len-1)&3) << 27)) ; 188162306a36Sopenharmony_ci } 188262306a36Sopenharmony_ci t->txd_virt = virt[i] ; 188362306a36Sopenharmony_ci phys = dma_master(smc, (void far *)virt[i], 188462306a36Sopenharmony_ci frag_len[i], DMA_RD|SMT_BUF) ; 188562306a36Sopenharmony_ci t->txd_tbadr = cpu_to_le32(phys) ; 188662306a36Sopenharmony_ci tbctrl = cpu_to_le32((((__u32)frame_status & 188762306a36Sopenharmony_ci (FIRST_FRAG|LAST_FRAG)) << 26) | 188862306a36Sopenharmony_ci BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ; 188962306a36Sopenharmony_ci t->txd_tbctrl = tbctrl ; 189062306a36Sopenharmony_ci#ifndef AIX 189162306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 189262306a36Sopenharmony_ci outpd(queue->tx_bmu_ctl,CSR_START) ; 189362306a36Sopenharmony_ci#else 189462306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 189562306a36Sopenharmony_ci outpd(ADDR(B0_XA_CSR),CSR_START) ; 189662306a36Sopenharmony_ci#endif 189762306a36Sopenharmony_ci frame_status &= ~FIRST_FRAG ; 189862306a36Sopenharmony_ci queue->tx_curr_put = t = t->txd_next ; 189962306a36Sopenharmony_ci queue->tx_free-- ; 190062306a36Sopenharmony_ci queue->tx_used++ ; 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACTransmit_Ct++ ; 190362306a36Sopenharmony_ci queue_txd_mb(smc,mb) ; 190462306a36Sopenharmony_ci } 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci if (frame_status & LOC_TX) { 190762306a36Sopenharmony_ci DB_TX(5, "pass Mbuf to LLC queue"); 190862306a36Sopenharmony_ci queue_llc_rx(smc,mb) ; 190962306a36Sopenharmony_ci } 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci /* 191262306a36Sopenharmony_ci * We need to unqueue the free SMT_MBUFs here, because it may 191362306a36Sopenharmony_ci * be that the SMT want's to send more than 1 frame for one down call 191462306a36Sopenharmony_ci */ 191562306a36Sopenharmony_ci mac_drv_clear_txd(smc) ; 191662306a36Sopenharmony_ci NDD_TRACE("THSE",t,queue->tx_free,frag_count) ; 191762306a36Sopenharmony_ci} 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci/* BEGIN_MANUAL_ENTRY(mac_drv_clear_txd) 192062306a36Sopenharmony_ci * void mac_drv_clear_txd(smc) 192162306a36Sopenharmony_ci * 192262306a36Sopenharmony_ci * function DOWNCALL (hardware module, hwmtm.c) 192362306a36Sopenharmony_ci * mac_drv_clear_txd searches in both send queues for TxD's 192462306a36Sopenharmony_ci * which were finished by the adapter. It calls dma_complete 192562306a36Sopenharmony_ci * for each TxD. If the last fragment of an LLC frame is 192662306a36Sopenharmony_ci * reached, it calls mac_drv_tx_complete to release the 192762306a36Sopenharmony_ci * send buffer. 192862306a36Sopenharmony_ci * 192962306a36Sopenharmony_ci * return nothing 193062306a36Sopenharmony_ci * 193162306a36Sopenharmony_ci * END_MANUAL_ENTRY 193262306a36Sopenharmony_ci */ 193362306a36Sopenharmony_cistatic void mac_drv_clear_txd(struct s_smc *smc) 193462306a36Sopenharmony_ci{ 193562306a36Sopenharmony_ci struct s_smt_tx_queue *queue ; 193662306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t1 ; 193762306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t2 = NULL ; 193862306a36Sopenharmony_ci SMbuf *mb ; 193962306a36Sopenharmony_ci u_long tbctrl ; 194062306a36Sopenharmony_ci int i ; 194162306a36Sopenharmony_ci int frag_count ; 194262306a36Sopenharmony_ci int n ; 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci NDD_TRACE("THcB",0,0,0) ; 194562306a36Sopenharmony_ci for (i = QUEUE_S; i <= QUEUE_A0; i++) { 194662306a36Sopenharmony_ci queue = smc->hw.fp.tx[i] ; 194762306a36Sopenharmony_ci t1 = queue->tx_curr_get ; 194862306a36Sopenharmony_ci DB_TX(5, "clear_txd: QUEUE = %d (0=sync/1=async)", i); 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci for ( ; ; ) { 195162306a36Sopenharmony_ci frag_count = 0 ; 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci do { 195462306a36Sopenharmony_ci DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ; 195562306a36Sopenharmony_ci DB_TX(5, "check OWN/EOF bit of TxD 0x%p", t1); 195662306a36Sopenharmony_ci tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl)); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci if (tbctrl & BMU_OWN || !queue->tx_used){ 195962306a36Sopenharmony_ci DB_TX(4, "End of TxDs queue %d", i); 196062306a36Sopenharmony_ci goto free_next_queue ; /* next queue */ 196162306a36Sopenharmony_ci } 196262306a36Sopenharmony_ci t1 = t1->txd_next ; 196362306a36Sopenharmony_ci frag_count++ ; 196462306a36Sopenharmony_ci } while (!(tbctrl & BMU_EOF)) ; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci t1 = queue->tx_curr_get ; 196762306a36Sopenharmony_ci for (n = frag_count; n; n--) { 196862306a36Sopenharmony_ci tbctrl = le32_to_cpu(t1->txd_tbctrl) ; 196962306a36Sopenharmony_ci dma_complete(smc, 197062306a36Sopenharmony_ci (union s_fp_descr volatile *) t1, 197162306a36Sopenharmony_ci (int) (DMA_RD | 197262306a36Sopenharmony_ci ((tbctrl & BMU_SMT_TX) >> 18))) ; 197362306a36Sopenharmony_ci t2 = t1 ; 197462306a36Sopenharmony_ci t1 = t1->txd_next ; 197562306a36Sopenharmony_ci } 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci if (tbctrl & BMU_SMT_TX) { 197862306a36Sopenharmony_ci mb = get_txd_mb(smc) ; 197962306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 198062306a36Sopenharmony_ci } 198162306a36Sopenharmony_ci else { 198262306a36Sopenharmony_ci#ifndef PASS_1ST_TXD_2_TX_COMP 198362306a36Sopenharmony_ci DB_TX(4, "mac_drv_tx_comp for TxD 0x%p", t2); 198462306a36Sopenharmony_ci mac_drv_tx_complete(smc,t2) ; 198562306a36Sopenharmony_ci#else 198662306a36Sopenharmony_ci DB_TX(4, "mac_drv_tx_comp for TxD 0x%x", 198762306a36Sopenharmony_ci queue->tx_curr_get); 198862306a36Sopenharmony_ci mac_drv_tx_complete(smc,queue->tx_curr_get) ; 198962306a36Sopenharmony_ci#endif 199062306a36Sopenharmony_ci } 199162306a36Sopenharmony_ci queue->tx_curr_get = t1 ; 199262306a36Sopenharmony_ci queue->tx_free += frag_count ; 199362306a36Sopenharmony_ci queue->tx_used -= frag_count ; 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_cifree_next_queue: ; 199662306a36Sopenharmony_ci } 199762306a36Sopenharmony_ci NDD_TRACE("THcE",0,0,0) ; 199862306a36Sopenharmony_ci} 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci/* 200162306a36Sopenharmony_ci * BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue) 200262306a36Sopenharmony_ci * 200362306a36Sopenharmony_ci * void mac_drv_clear_tx_queue(smc) 200462306a36Sopenharmony_ci * struct s_smc *smc ; 200562306a36Sopenharmony_ci * 200662306a36Sopenharmony_ci * function DOWNCALL (hardware module, hwmtm.c) 200762306a36Sopenharmony_ci * mac_drv_clear_tx_queue is called from the SMT when 200862306a36Sopenharmony_ci * the RMT state machine has entered the ISOLATE state. 200962306a36Sopenharmony_ci * This function is also called by the os-specific module 201062306a36Sopenharmony_ci * after it has called the function card_stop(). 201162306a36Sopenharmony_ci * In this case, the frames in the send queues are obsolete and 201262306a36Sopenharmony_ci * should be removed. 201362306a36Sopenharmony_ci * 201462306a36Sopenharmony_ci * note calling sequence: 201562306a36Sopenharmony_ci * CLI_FBI(), card_stop(), 201662306a36Sopenharmony_ci * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(), 201762306a36Sopenharmony_ci * 201862306a36Sopenharmony_ci * NOTE: The caller is responsible that the BMUs are idle 201962306a36Sopenharmony_ci * when this function is called. 202062306a36Sopenharmony_ci * 202162306a36Sopenharmony_ci * END_MANUAL_ENTRY 202262306a36Sopenharmony_ci */ 202362306a36Sopenharmony_civoid mac_drv_clear_tx_queue(struct s_smc *smc) 202462306a36Sopenharmony_ci{ 202562306a36Sopenharmony_ci struct s_smt_fp_txd volatile *t ; 202662306a36Sopenharmony_ci struct s_smt_tx_queue *queue ; 202762306a36Sopenharmony_ci int tx_used ; 202862306a36Sopenharmony_ci int i ; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci if (smc->hw.hw_state != STOPPED) { 203162306a36Sopenharmony_ci SK_BREAK() ; 203262306a36Sopenharmony_ci SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ; 203362306a36Sopenharmony_ci return ; 203462306a36Sopenharmony_ci } 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci for (i = QUEUE_S; i <= QUEUE_A0; i++) { 203762306a36Sopenharmony_ci queue = smc->hw.fp.tx[i] ; 203862306a36Sopenharmony_ci DB_TX(5, "clear_tx_queue: QUEUE = %d (0=sync/1=async)", i); 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci /* 204162306a36Sopenharmony_ci * switch the OWN bit of all pending frames to the host 204262306a36Sopenharmony_ci */ 204362306a36Sopenharmony_ci t = queue->tx_curr_get ; 204462306a36Sopenharmony_ci tx_used = queue->tx_used ; 204562306a36Sopenharmony_ci while (tx_used) { 204662306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ; 204762306a36Sopenharmony_ci DB_TX(5, "switch OWN bit of TxD 0x%p", t); 204862306a36Sopenharmony_ci t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ; 204962306a36Sopenharmony_ci DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; 205062306a36Sopenharmony_ci t = t->txd_next ; 205162306a36Sopenharmony_ci tx_used-- ; 205262306a36Sopenharmony_ci } 205362306a36Sopenharmony_ci } 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci /* 205662306a36Sopenharmony_ci * release all TxD's for both send queues 205762306a36Sopenharmony_ci */ 205862306a36Sopenharmony_ci mac_drv_clear_txd(smc) ; 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci for (i = QUEUE_S; i <= QUEUE_A0; i++) { 206162306a36Sopenharmony_ci queue = smc->hw.fp.tx[i] ; 206262306a36Sopenharmony_ci t = queue->tx_curr_get ; 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci /* 206562306a36Sopenharmony_ci * write the phys pointer of the NEXT descriptor into the 206662306a36Sopenharmony_ci * BMU's current address descriptor pointer and set 206762306a36Sopenharmony_ci * tx_curr_get and tx_curr_put to this position 206862306a36Sopenharmony_ci */ 206962306a36Sopenharmony_ci if (i == QUEUE_S) { 207062306a36Sopenharmony_ci outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ; 207162306a36Sopenharmony_ci } 207262306a36Sopenharmony_ci else { 207362306a36Sopenharmony_ci outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ; 207462306a36Sopenharmony_ci } 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci queue->tx_curr_put = queue->tx_curr_get->txd_next ; 207762306a36Sopenharmony_ci queue->tx_curr_get = queue->tx_curr_put ; 207862306a36Sopenharmony_ci } 207962306a36Sopenharmony_ci} 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci/* 208362306a36Sopenharmony_ci ------------------------------------------------------------- 208462306a36Sopenharmony_ci TEST FUNCTIONS: 208562306a36Sopenharmony_ci ------------------------------------------------------------- 208662306a36Sopenharmony_ci*/ 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_ci#ifdef DEBUG 208962306a36Sopenharmony_ci/* 209062306a36Sopenharmony_ci * BEGIN_MANUAL_ENTRY(mac_drv_debug_lev) 209162306a36Sopenharmony_ci * void mac_drv_debug_lev(smc,flag,lev) 209262306a36Sopenharmony_ci * 209362306a36Sopenharmony_ci * function DOWNCALL (drvsr.c) 209462306a36Sopenharmony_ci * To get a special debug info the user can assign a debug level 209562306a36Sopenharmony_ci * to any debug flag. 209662306a36Sopenharmony_ci * 209762306a36Sopenharmony_ci * para flag debug flag, possible values are: 209862306a36Sopenharmony_ci * = 0: reset all debug flags (the defined level is 209962306a36Sopenharmony_ci * ignored) 210062306a36Sopenharmony_ci * = 1: debug.d_smtf 210162306a36Sopenharmony_ci * = 2: debug.d_smt 210262306a36Sopenharmony_ci * = 3: debug.d_ecm 210362306a36Sopenharmony_ci * = 4: debug.d_rmt 210462306a36Sopenharmony_ci * = 5: debug.d_cfm 210562306a36Sopenharmony_ci * = 6: debug.d_pcm 210662306a36Sopenharmony_ci * 210762306a36Sopenharmony_ci * = 10: debug.d_os.hwm_rx (hardware module receive path) 210862306a36Sopenharmony_ci * = 11: debug.d_os.hwm_tx(hardware module transmit path) 210962306a36Sopenharmony_ci * = 12: debug.d_os.hwm_gen(hardware module general flag) 211062306a36Sopenharmony_ci * 211162306a36Sopenharmony_ci * lev debug level 211262306a36Sopenharmony_ci * 211362306a36Sopenharmony_ci * END_MANUAL_ENTRY 211462306a36Sopenharmony_ci */ 211562306a36Sopenharmony_civoid mac_drv_debug_lev(struct s_smc *smc, int flag, int lev) 211662306a36Sopenharmony_ci{ 211762306a36Sopenharmony_ci switch(flag) { 211862306a36Sopenharmony_ci case (int)NULL: 211962306a36Sopenharmony_ci DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ; 212062306a36Sopenharmony_ci DB_P.d_cfm = 0 ; 212162306a36Sopenharmony_ci DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ; 212262306a36Sopenharmony_ci#ifdef SBA 212362306a36Sopenharmony_ci DB_P.d_sba = 0 ; 212462306a36Sopenharmony_ci#endif 212562306a36Sopenharmony_ci#ifdef ESS 212662306a36Sopenharmony_ci DB_P.d_ess = 0 ; 212762306a36Sopenharmony_ci#endif 212862306a36Sopenharmony_ci break ; 212962306a36Sopenharmony_ci case DEBUG_SMTF: 213062306a36Sopenharmony_ci DB_P.d_smtf = lev ; 213162306a36Sopenharmony_ci break ; 213262306a36Sopenharmony_ci case DEBUG_SMT: 213362306a36Sopenharmony_ci DB_P.d_smt = lev ; 213462306a36Sopenharmony_ci break ; 213562306a36Sopenharmony_ci case DEBUG_ECM: 213662306a36Sopenharmony_ci DB_P.d_ecm = lev ; 213762306a36Sopenharmony_ci break ; 213862306a36Sopenharmony_ci case DEBUG_RMT: 213962306a36Sopenharmony_ci DB_P.d_rmt = lev ; 214062306a36Sopenharmony_ci break ; 214162306a36Sopenharmony_ci case DEBUG_CFM: 214262306a36Sopenharmony_ci DB_P.d_cfm = lev ; 214362306a36Sopenharmony_ci break ; 214462306a36Sopenharmony_ci case DEBUG_PCM: 214562306a36Sopenharmony_ci DB_P.d_pcm = lev ; 214662306a36Sopenharmony_ci break ; 214762306a36Sopenharmony_ci case DEBUG_SBA: 214862306a36Sopenharmony_ci#ifdef SBA 214962306a36Sopenharmony_ci DB_P.d_sba = lev ; 215062306a36Sopenharmony_ci#endif 215162306a36Sopenharmony_ci break ; 215262306a36Sopenharmony_ci case DEBUG_ESS: 215362306a36Sopenharmony_ci#ifdef ESS 215462306a36Sopenharmony_ci DB_P.d_ess = lev ; 215562306a36Sopenharmony_ci#endif 215662306a36Sopenharmony_ci break ; 215762306a36Sopenharmony_ci case DB_HWM_RX: 215862306a36Sopenharmony_ci DB_P.d_os.hwm_rx = lev ; 215962306a36Sopenharmony_ci break ; 216062306a36Sopenharmony_ci case DB_HWM_TX: 216162306a36Sopenharmony_ci DB_P.d_os.hwm_tx = lev ; 216262306a36Sopenharmony_ci break ; 216362306a36Sopenharmony_ci case DB_HWM_GEN: 216462306a36Sopenharmony_ci DB_P.d_os.hwm_gen = lev ; 216562306a36Sopenharmony_ci break ; 216662306a36Sopenharmony_ci default: 216762306a36Sopenharmony_ci break ; 216862306a36Sopenharmony_ci } 216962306a36Sopenharmony_ci} 217062306a36Sopenharmony_ci#endif 2171