📄 smc91113.c
字号:
} return 0;}/*------------------------------------------------------------ . Cleanup when module is removed with rmmod .-------------------------------------------------------------*/void EV44b0_cleanup_module(void){ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ unregister_netdev(&devSMC91113); free_irq(devSMC91113.irq, &devSMC91113); release_region(devSMC91113.base_addr, SMC_IO_EXTENT); if (devSMC91113.priv) kfree(devSMC91113.priv); /* Kernel 2.4 Changes - Pramod */}#ifdef CONFIG_SYSCTL/*------------------------------------------------------------ . Modify a bit in the LAN91C113 register set .-------------------------------------------------------------*/static word smc_modify_regbit(int bank, int ioaddr, int reg, unsigned int bit, int val){ word regval; SMC_SELECT_BANK( bank ); regval = inw( ioaddr+reg ); if (val) regval |= bit; else regval &= ~bit; outw( regval, ioaddr ); return(regval);}/*------------------------------------------------------------ . Retrieve a bit in the LAN91C113 register set .-------------------------------------------------------------*/static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit){ SMC_SELECT_BANK( bank ); if ( inw( ioaddr+reg ) & bit) return(1); else return(0);}/*------------------------------------------------------------ . Modify a LAN91C113 register (word access only) .-------------------------------------------------------------*/static void smc_modify_reg(int bank, int ioaddr, int reg, word val){ SMC_SELECT_BANK( bank ); outw( val, ioaddr+reg );}/*------------------------------------------------------------ . Retrieve a LAN91C113 register (word access only) .-------------------------------------------------------------*/static int smc_get_reg(int bank, int ioaddr, int reg){ SMC_SELECT_BANK( bank ); return(inw( ioaddr+reg ));}static const char smc_info_string[] ="\n""info Provides this information blurb\n""swver Prints the software version information of this driver\n""autoneg Auto-negotiate Mode = 1\n""rspeed Requested Speed, 100=100Mbps, 10=10Mpbs\n""rfduplx Requested Full Duplex Operation\n""aspeed Actual Speed, 100=100Mbps, 10=10Mpbs\n""afduplx Actual Full Duplex Operation\n""lnkfail PHY Link Failure when 1\n""miiop External MII when 1, Internal PHY when 0\n""swfdup Switched Full Duplex Mode (allowed only in MII operation)\n""ephloop EPH Block Loopback\n""forcol Force a collision\n""filtcar Filter leading edge of carrier sense for 12 bit times\n""freemem Free buffer memory in bytes\n""totmem Total buffer memory in bytes\n""leda Output of LED-A (green)\n""ledb Output of LED-B (yellow)\n""chiprev Revision ID of the LAN91C113 chip\n""";/*------------------------------------------------------------ . Sysctl handler for all integer parameters .-------------------------------------------------------------*/static int smc_sysctl_handler(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp){ struct net_device *dev = (struct net_device*)ctl->extra1; struct smc_local *lp = (struct smc_local *)ctl->extra2; int ioaddr = dev->base_addr; int *valp = ctl->data; int val; int ret; // Update parameters from the real registers switch (ctl->ctl_name) { case CTL_SMC_FORCOL: *valp = smc_get_regbit(0, ioaddr, TCR_REG, TCR_FORCOL); break; case CTL_SMC_FREEMEM: *valp = ( (word)smc_get_reg(0, ioaddr, MIR_REG) >> 8 ) * LAN91C113_MEMORY_MULTIPLIER; break; case CTL_SMC_TOTMEM: *valp = ( smc_get_reg(0, ioaddr, MIR_REG) & (word)0x00ff ) * LAN91C113_MEMORY_MULTIPLIER; break; case CTL_SMC_CHIPREV: *valp = smc_get_reg(3, ioaddr, REV_REG); break; case CTL_SMC_AFDUPLX: *valp = (lp->lastPhy18 & PHY_INT_DPLXDET) ? 1 : 0; break; case CTL_SMC_ASPEED: *valp = (lp->lastPhy18 & PHY_INT_SPDDET) ? 100 : 10; break; case CTL_SMC_LNKFAIL: *valp = (lp->lastPhy18 & PHY_INT_LNKFAIL) ? 1 : 0; break; case CTL_SMC_LEDA: *valp = (lp->rpc_cur_mode >> RPC_LSXA_SHFT) & (word)0x0007; break; case CTL_SMC_LEDB: *valp = (lp->rpc_cur_mode >> RPC_LSXB_SHFT) & (word)0x0007; break; case CTL_SMC_MIIOP: *valp = smc_get_regbit(1, ioaddr, CONFIG_REG, CONFIG_EXT_PHY); break;#ifdef SMC_DEBUG case CTL_SMC_REG_BSR: // Bank Select *valp = smc_get_reg(0, ioaddr, BSR_REG); break; case CTL_SMC_REG_TCR: // Transmit Control *valp = smc_get_reg(0, ioaddr, TCR_REG); break; case CTL_SMC_REG_ESR: // EPH Status *valp = smc_get_reg(0, ioaddr, EPH_STATUS_REG); break; case CTL_SMC_REG_RCR: // Receive Control *valp = smc_get_reg(0, ioaddr, RCR_REG); break; case CTL_SMC_REG_CTRR: // Counter *valp = smc_get_reg(0, ioaddr, COUNTER_REG); break; case CTL_SMC_REG_MIR: // Memory Information *valp = smc_get_reg(0, ioaddr, MIR_REG); break; case CTL_SMC_REG_RPCR: // Receive/Phy Control *valp = smc_get_reg(0, ioaddr, RPC_REG); break; case CTL_SMC_REG_CFGR: // Configuration *valp = smc_get_reg(1, ioaddr, CONFIG_REG); break; case CTL_SMC_REG_BAR: // Base Address *valp = smc_get_reg(1, ioaddr, BASE_REG); break; case CTL_SMC_REG_IAR0: // Individual Address *valp = smc_get_reg(1, ioaddr, ADDR0_REG); break; case CTL_SMC_REG_IAR1: // Individual Address *valp = smc_get_reg(1, ioaddr, ADDR1_REG); break; case CTL_SMC_REG_IAR2: // Individual Address *valp = smc_get_reg(1, ioaddr, ADDR2_REG); break; case CTL_SMC_REG_GPR: // General Purpose *valp = smc_get_reg(1, ioaddr, GP_REG); break; case CTL_SMC_REG_CTLR: // Control *valp = smc_get_reg(1, ioaddr, CTL_REG); break; case CTL_SMC_REG_MCR: // MMU Command *valp = smc_get_reg(2, ioaddr, MMU_CMD_REG); break; case CTL_SMC_REG_PNR: // Packet Number *valp = smc_get_reg(2, ioaddr, PN_REG); break; case CTL_SMC_REG_FPR: // Allocation Result/FIFO Ports *valp = smc_get_reg(2, ioaddr, RXFIFO_REG); break; case CTL_SMC_REG_PTR: // Pointer *valp = smc_get_reg(2, ioaddr, PTR_REG); break; case CTL_SMC_REG_DR: // Data *valp = smc_get_reg(2, ioaddr, DATA_REG); break; case CTL_SMC_REG_ISR: // Interrupt Status/Mask *valp = smc_get_reg(2, ioaddr, INT_REG); break; case CTL_SMC_REG_MTR1: // Multicast Table Entry 1 *valp = smc_get_reg(3, ioaddr, MCAST_REG1); break; case CTL_SMC_REG_MTR2: // Multicast Table Entry 2 *valp = smc_get_reg(3, ioaddr, MCAST_REG2); break; case CTL_SMC_REG_MTR3: // Multicast Table Entry 3 *valp = smc_get_reg(3, ioaddr, MCAST_REG3); break; case CTL_SMC_REG_MTR4: // Multicast Table Entry 4 *valp = smc_get_reg(3, ioaddr, MCAST_REG4); break; case CTL_SMC_REG_MIIR: // Management Interface *valp = smc_get_reg(3, ioaddr, MII_REG); break; case CTL_SMC_REG_REVR: // Revision *valp = smc_get_reg(3, ioaddr, REV_REG); break; case CTL_SMC_REG_ERCVR: // Early RCV *valp = smc_get_reg(3, ioaddr, ERCV_REG); break; case CTL_SMC_REG_EXTR: // External *valp = smc_get_reg(7, ioaddr, EXT_REG); break; case CTL_SMC_PHY_CTRL: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_CNTL_REG); break; case CTL_SMC_PHY_STAT: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_STAT_REG); break; case CTL_SMC_PHY_ID1: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_ID1_REG); break; case CTL_SMC_PHY_ID2: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_ID2_REG); break; case CTL_SMC_PHY_ADC: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_AD_REG); break; case CTL_SMC_PHY_REMC: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_RMT_REG); break; case CTL_SMC_PHY_CFG1: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_CFG1_REG); break; case CTL_SMC_PHY_CFG2: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_CFG2_REG); break; case CTL_SMC_PHY_INT: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_INT_REG); break; case CTL_SMC_PHY_MASK: *valp = smc_read_phy_register(ioaddr, lp->phyaddr, PHY_MASK_REG); break;#endif // SMC_DEBUG default: // Just ignore unsupported parameters break; } // Save old state val = *valp; // Perform the generic integer operation if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0) return(ret); // Write changes out to the registers if (write && *valp != val) { val = *valp; switch (ctl->ctl_name) { case CTL_SMC_SWFDUP: if (val) lp->tcr_cur_mode |= TCR_SWFDUP; else lp->tcr_cur_mode &= ~TCR_SWFDUP; smc_modify_regbit(0, ioaddr, TCR_REG, TCR_SWFDUP, val); break; case CTL_SMC_EPHLOOP: if (val) lp->tcr_cur_mode |= TCR_EPH_LOOP; else lp->tcr_cur_mode &= ~TCR_EPH_LOOP; smc_modify_regbit(0, ioaddr, TCR_REG, TCR_EPH_LOOP, val); break; case CTL_SMC_FORCOL: if (val) lp->tcr_cur_mode |= TCR_FORCOL; else lp->tcr_cur_mode &= ~TCR_FORCOL; // Update the EPH block smc_modify_regbit(0, ioaddr, TCR_REG, TCR_FORCOL, val); break; case CTL_SMC_FILTCAR: if (val) lp->rcr_cur_mode |= RCR_FILT_CAR; else lp->rcr_cur_mode &= ~RCR_FILT_CAR; // Update the EPH block smc_modify_regbit(0, ioaddr, RCR_REG, RCR_FILT_CAR, val); break; case CTL_SMC_RFDUPLX: // Disallow changes if in auto-negotiation mode if (lp->ctl_autoneg) break; if (val) { lp->rpc_cur_mode |= RPC_DPLX; } else { lp->rpc_cur_mode &= ~RPC_DPLX; } // Reconfigure the PHY smc_phy_configure(dev); break; case CTL_SMC_RSPEED: // Disallow changes if in auto-negotiation mode if (lp->ctl_autoneg) break; if (val > 10) lp->rpc_cur_mode |= RPC_SPEED; else lp->rpc_cur_mode &= ~RPC_SPEED; // Reconfigure the PHY smc_phy_configure(dev); break; case CTL_SMC_AUTONEG: if (val) lp->rpc_cur_mode |= RPC_ANEG; else lp->rpc_cur_mode &= ~RPC_ANEG; // Reconfigure the PHY smc_phy_configure(dev); break; case CTL_SMC_LEDA: val &= 0x07; // Restrict to 3 ls bits lp->rpc_cur_mode &= ~(word)(0x07<<RPC_LSXA_SHFT); lp->rpc_cur_mode |= (word)(val<<RPC_LSXA_SHFT); // Update the Internal PHY block smc_modify_reg(0, ioaddr, RPC_REG, lp->rpc_cur_mode); break; case CTL_SMC_LEDB: val &= 0x07; // Restrict to 3 ls bits lp->rpc_cur_mode &= ~(word)(0x07<<RPC_LSXB_SHFT); lp->rpc_cur_mode |= (word)(val<<RPC_LSXB_SHFT); // Update the Internal PHY block smc_modify_reg(0, ioaddr, RPC_REG, lp->rpc_cur_mode); break; case CTL_SMC_MIIOP: // Update the Internal PHY block smc_modify_regbit(1, ioaddr, CONFIG_REG, CONFIG_EXT_PHY, val); break;#ifdef SMC_DEBUG case CTL_SMC_REG_BSR: // Bank Select smc_modify_reg(0, ioaddr, BSR_REG, val); break; case CTL_SMC_REG_TCR: // Transmit Control smc_modify_reg(0, ioaddr, TCR_REG, val); break; case CTL_SMC_REG_ESR: // EPH Status smc_modify_reg(0, ioaddr, EPH_STATUS_REG, val); break; case CTL_SMC_REG_RCR: // Receive Control smc_modify_reg(0, ioaddr, RCR_REG, val); break; case CTL_SMC_REG_CTRR: // Counter smc_modify_reg(0, ioaddr, COUNTER_REG, val); break; case CTL_SMC_REG_MIR: // Memory Information smc_modify_reg(0, ioaddr, MIR_REG, val); break; case CTL_SMC_REG_RPCR: // Receive/Phy Control
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -