📄 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(struct s_smc *smc, SMbuf *mb);static void smt_to_llc(struct s_smc *smc, SMbuf *mb);static void init_txd_ring(struct s_smc *smc);static void init_rxd_ring(struct s_smc *smc);static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start, int count);static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);static SMbuf* get_llc_rx(struct s_smc *smc);static SMbuf* get_txd_mb(struct s_smc *smc);static void mac_drv_clear_txd(struct s_smc *smc);/* ------------------------------------------------------------- EXTERNAL FUNCTIONS: -------------------------------------------------------------*//* The external SMT functions are listed in cmtdef.h */extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);extern void init_board(struct s_smc *smc, u_char *mac_addr);extern void mac_drv_fill_rxd(struct s_smc *smc);extern void plc1_irq(struct s_smc *smc);extern void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);extern void plc2_irq(struct s_smc *smc);extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);extern void timer_irq(struct s_smc *smc);extern void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count, int len);extern void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count);extern void init_plc(struct s_smc *smc);extern void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count);#ifdef USE_OS_CPYextern void hwm_cpy_rxd2mb(void);extern void hwm_cpy_txd2mb(void);#endif#ifdef ALL_RX_COMPLETEextern void mac_drv_all_receives_complete(void);#endifextern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);#ifdef NDIS_OS2extern void post_proc(void);#elseextern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag);#endifextern int init_fplus(struct s_smc *smc);extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, int la_len);/* ------------------------------------------------------------- PUBLIC FUNCTIONS: -------------------------------------------------------------*/void process_receive(struct s_smc *smc);void fddi_isr(struct s_smc *smc);void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);void init_driver_fplus(struct s_smc *smc);void mac_drv_rx_mode(struct s_smc *smc, int mode);void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);void mac_drv_clear_tx_queue(struct s_smc *smc);void mac_drv_clear_rx_queue(struct s_smc *smc);void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, int frame_status);void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, int frame_status);int mac_drv_init(struct s_smc *smc);int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, int frame_status);u_int mac_drv_check_space(void);SMbuf* smt_get_mbuf(struct s_smc *smc);#ifdef DEBUG void mac_drv_debug_lev(void);#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(void){#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(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(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(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(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(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(struct s_smc *smc, u_char *mac_addr){ 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(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(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -