📄 hwmtm.c
字号:
/****************************************************************************** * * (C)Copyright 1998,1999 SysKonnect, * a business unit of Schneider & Koch & Co. Datensysteme GmbH. * * See the file "skfddi.c" for further information. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/#ifndef lintstatic char const ID_sccs[] = "@(#)hwmtm.c 1.40 99/05/31 (C) SK" ;#endif#define HWMTM#ifndef FDDI#define FDDI#endif#include "h/types.h"#include "h/fddi.h"#include "h/smc.h"#include "h/supern_2.h"#include "h/skfbiinc.h"/* ------------------------------------------------------------- DOCUMENTATION ------------------------------------------------------------- BEGIN_MANUAL_ENTRY(DOCUMENTATION) T B D END_MANUAL_ENTRY*//* ------------------------------------------------------------- LOCAL VARIABLES: -------------------------------------------------------------*/#ifdef COMMON_MB_POOLstatic SMbuf *mb_start = 0 ;static SMbuf *mb_free = 0 ;static int mb_init = FALSE ;static int call_count = 0 ;#endif/* ------------------------------------------------------------- EXTERNE VARIABLES: -------------------------------------------------------------*/#ifdef DEBUG#ifndef DEBUG_BRDextern struct smt_debug debug ;#endif#endif#ifdef NDIS_OS2extern u_char offDepth ;extern u_char force_irq_pending ;#endif/* ------------------------------------------------------------- LOCAL FUNCTIONS: -------------------------------------------------------------*/static void queue_llc_rx(), smt_to_llc(), init_txd_ring(), init_rxd_ring(), queue_txd_mb() ;static u_long init_descr_ring(), repair_txd_ring(), repair_rxd_ring() ;static SMbuf *get_llc_rx(), *get_txd_mb() ;/* ------------------------------------------------------------- EXTERNAL FUNCTIONS: -------------------------------------------------------------*//* The external SMT functions are listed in cmtdef.h */extern void *mac_drv_get_space(), *mac_drv_get_desc_mem(), init_board(), mac_drv_fill_rxd(), plc1_irq(), mac_drv_tx_complete(), plc2_irq(), mac1_irq(), mac2_irq(), mac3_irq(), timer_irq(), mac_drv_rx_complete(), mac_drv_requeue_rxd(), init_plc(), mac_drv_clear_rxd(), llc_restart_tx(), ev_dispatcher(), smt_force_irq() ;#ifdef USE_OS_CPYextern void hwm_cpy_rxd2mb(), hwm_cpy_txd2mb() ;#endif#ifdef ALL_RX_COMPLETEextern void mac_drv_all_receives_complete() ;#endifextern u_long mac_drv_virt2phys(), dma_master() ;#ifdef NDIS_OS2extern void post_proc() ;#elseextern void dma_complete() ;#endifextern int init_fplus(), mac_drv_rx_init() ;/* ------------------------------------------------------------- PUBLIC FUNCTIONS: -------------------------------------------------------------*/ void process_receive(), smt_send_mbuf(), fddi_isr(), mac_drv_clear_txd(), smt_free_mbuf(), init_driver_fplus(), mac_drv_rx_mode(), init_fddi_driver(), mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(), hwm_tx_frag(), hwm_rx_frag() ; int mac_drv_rx_frag(), mac_drv_init(), hwm_tx_init() ; u_int mac_drv_check_space() ; SMbuf *smt_get_mbuf() ;#ifdef DEBUG void mac_drv_debug_lev() ;#endif/* ------------------------------------------------------------- MACROS: -------------------------------------------------------------*/#ifndef UNUSED#ifdef lint#define UNUSED(x) (x) = (x)#else#define UNUSED(x)#endif#endif#ifdef USE_CAN_ADDR#define MA smc->hw.fddi_canon_addr.a#define GROUP_ADDR_BIT 0x01#else#define MA smc->hw.fddi_home_addr.a#define GROUP_ADDR_BIT 0x80#endif#define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\ SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)#ifdef MB_OUTSIDE_SMC#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\ MAX_MBUF*sizeof(SMbuf))#define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))#else#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))#endif /* * define critical read for 16 Bit drivers */#if defined(NDIS_OS2) || defined(ODI2)#define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))#else#define CR_READ(var) (u_long)(var)#endif#define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \ IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \ IS_R1_C | IS_XA_C | IS_XS_C)/* ------------------------------------------------------------- INIT- AND SMT FUNCTIONS: -------------------------------------------------------------*//* * BEGIN_MANUAL_ENTRY(mac_drv_check_space) * u_int mac_drv_check_space() * * function DOWNCALL (drvsr.c) * This function calculates the needed non virtual * memory for MBufs, RxD and TxD descriptors etc. * needed by the driver. * * return u_int memory in bytes * * END_MANUAL_ENTRY */u_int mac_drv_check_space(){#ifdef MB_OUTSIDE_SMC#ifdef COMMON_MB_POOL call_count++ ; if (call_count == 1) { return(EXT_VIRT_MEM) ; } else { return(EXT_VIRT_MEM_2) ; }#else return (EXT_VIRT_MEM) ;#endif#else return (0) ;#endif}/* * BEGIN_MANUAL_ENTRY(mac_drv_init) * void mac_drv_init(smc) * * function DOWNCALL (drvsr.c) * In this function the hardware module allocates it's * memory. * The operating system dependent module should call * mac_drv_init once, after the adatper is detected. * END_MANUAL_ENTRY */int mac_drv_init(smc)struct s_smc *smc ;{ if (sizeof(struct s_smt_fp_rxd) % 16) { SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ; } if (sizeof(struct s_smt_fp_txd) % 16) { SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ; } /* * get the required memory for the RxDs and TxDs */ if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *) mac_drv_get_desc_mem(smc,(u_int) (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) { return(1) ; /* no space the hwm modul can't work */ } /* * get the memory for the SMT MBufs */#ifndef MB_OUTSIDE_SMC smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;#else#ifndef COMMON_MB_POOL if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc, MAX_MBUF*sizeof(SMbuf)))) { return(1) ; /* no space the hwm modul can't work */ }#else if (!mb_start) { if (!(mb_start = (SMbuf *) mac_drv_get_space(smc, MAX_MBUF*sizeof(SMbuf)))) { return(1) ; /* no space the hwm modul can't work */ } }#endif#endif return (0) ;}/* * BEGIN_MANUAL_ENTRY(init_driver_fplus) * init_driver_fplus(smc) * * Sets hardware modul specific values for the mode register 2 * (e.g. the byte alignment for the received frames, the position of the * least significant byte etc.) * END_MANUAL_ENTRY */void init_driver_fplus(smc)struct s_smc *smc ;{ smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;#ifdef PCI smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;#endif smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;#ifdef USE_CAN_ADDR /* enable address bit swapping */ smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;#endif}static u_long init_descr_ring(smc,start,count)struct s_smc *smc ;union s_fp_descr volatile *start;int count ;{ int i ; union s_fp_descr volatile *d1 ; union s_fp_descr volatile *d2 ; u_long phys ; DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ; for (i=count-1, d1=start; i ; i--) { d2 = d1 ; d1++ ; /* descr is owned by the host */ d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ; d2->r.rxd_next = &d1->r ; phys = mac_drv_virt2phys(smc,(void *)d1) ; d2->r.rxd_nrdadr = AIX_REVERSE(phys) ; } DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ; d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ; d1->r.rxd_next = &start->r ; phys = mac_drv_virt2phys(smc,(void *)start) ; d1->r.rxd_nrdadr = AIX_REVERSE(phys) ; for (i=count, d1=start; i ; i--) { DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ; d1++; } return(phys) ;}static void init_txd_ring(smc)struct s_smc *smc ;{ struct s_smt_fp_txd volatile *ds ; struct s_smt_tx_queue *queue ; u_long phys ; /* * initialize the transmit descriptors */ ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p + SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ; queue = smc->hw.fp.tx[QUEUE_A0] ; DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ; (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, HWM_ASYNC_TXD_COUNT) ; phys = AIX_REVERSE(ds->txd_ntdadr) ; ds++ ; queue->tx_curr_put = queue->tx_curr_get = ds ; ds-- ; queue->tx_free = HWM_ASYNC_TXD_COUNT ; queue->tx_used = 0 ; outpd(ADDR(B5_XA_DA),phys) ; ds = (struct s_smt_fp_txd volatile *) ((char *)ds + HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ; queue = smc->hw.fp.tx[QUEUE_S] ; DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ; (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, HWM_SYNC_TXD_COUNT) ; phys = AIX_REVERSE(ds->txd_ntdadr) ; ds++ ; queue->tx_curr_put = queue->tx_curr_get = ds ; queue->tx_free = HWM_SYNC_TXD_COUNT ; queue->tx_used = 0 ; outpd(ADDR(B5_XS_DA),phys) ;}static void init_rxd_ring(smc)struct s_smc *smc ;{ struct s_smt_fp_rxd volatile *ds ; struct s_smt_rx_queue *queue ; u_long phys ; /* * initialize the receive descriptors */ ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ; queue = smc->hw.fp.rx[QUEUE_R1] ; DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ; (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds, SMT_R1_RXD_COUNT) ; phys = AIX_REVERSE(ds->rxd_nrdadr) ; ds++ ; queue->rx_curr_put = queue->rx_curr_get = ds ; queue->rx_free = SMT_R1_RXD_COUNT ; queue->rx_used = 0 ; outpd(ADDR(B4_R1_DA),phys) ;}/* * BEGIN_MANUAL_ENTRY(init_fddi_driver) * void init_fddi_driver(smc,mac_addr) * * initializes the driver and it's variables * * END_MANUAL_ENTRY */void init_fddi_driver(smc,mac_addr)struct s_smc *smc ;u_char *mac_addr ; /* canonical address */{ SMbuf *mb ; int i ; init_board(smc,mac_addr) ; (void)init_fplus(smc) ; /* * initialize the SMbufs for the SMT */#ifndef COMMON_MB_POOL mb = smc->os.hwm.mbuf_pool.mb_start ; smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ; for (i = 0; i < MAX_MBUF; i++) { mb->sm_use_count = 1 ; smt_free_mbuf(smc,mb) ; mb++ ; }#else mb = mb_start ; if (!mb_init) { mb_free = 0 ; for (i = 0; i < MAX_MBUF; i++) { mb->sm_use_count = 1 ; smt_free_mbuf(smc,mb) ; mb++ ; } mb_init = TRUE ; }#endif /* * initialize the other variables */ smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ; smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ; smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ; smc->os.hwm.pass_llc_promisc = TRUE ; smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ; smc->os.hwm.detec_count = 0 ; smc->os.hwm.rx_break = 0 ; smc->os.hwm.rx_len_error = 0 ; smc->os.hwm.isr_flag = FALSE ; /* * make sure that the start pointer is 16 byte aligned */ i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ; if (i != 16) { DB_GEN("i = %d",i,0,3) ; smc->os.hwm.descr_p = (union s_fp_descr volatile *) ((char *)smc->os.hwm.descr_p+i) ; } DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ; init_txd_ring(smc) ; init_rxd_ring(smc) ; mac_drv_fill_rxd(smc) ; init_plc(smc) ;}SMbuf *smt_get_mbuf(smc)struct s_smc *smc ;{ register SMbuf *mb ;#ifndef COMMON_MB_POOL mb = smc->os.hwm.mbuf_pool.mb_free ;#else mb = mb_free ;#endif if (mb) {#ifndef COMMON_MB_POOL smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;#else mb_free = mb->sm_next ;#endif mb->sm_off = 8 ; mb->sm_use_count = 1 ; } DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ; return (mb) ; /* May be NULL */}void smt_free_mbuf(smc, mb)struct s_smc *smc ;SMbuf *mb;{ if (mb) { mb->sm_use_count-- ; DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ; /* * If the use_count is != zero the MBuf is queued * more than once and must not queued into the * free MBuf queue */ if (!mb->sm_use_count) { DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;#ifndef COMMON_MB_POOL mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ; smc->os.hwm.mbuf_pool.mb_free = mb ;#else mb->sm_next = mb_free ; mb_free = mb ;#endif } } else SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;}/* * BEGIN_MANUAL_ENTRY(mac_drv_repair_descr) * void mac_drv_repair_descr(smc) * * function called from SMT (HWM / hwmtm.c) * The BMU is idle when this function is called. * Mac_drv_repair_descr sets up the physical address * for all receive and transmit queues where the BMU * should continue. * It may be that the BMU was reseted during a fragmented * transfer. In this case there are some fragments which will * never completed by the BMU. The OWN bit of this fragments * must be switched to be owned by the host. * * Give a start command to the receive BMU. * Start the transmit BMUs if transmit frames pending. * * END_MANUAL_ENTRY */void mac_drv_repair_descr(smc)struct s_smc *smc ;{ u_long phys ; if (smc->hw.hw_state != STOPPED) { SK_BREAK() ; SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ; return ; } /* * repair tx queues: don't start */ phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ; outpd(ADDR(B5_XA_DA),phys) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -