* [PATCH 0/6] Further changes for 5.15 support
@ 2022-01-07 11:35 Jan Kiszka
2022-01-07 11:35 ` [PATCH 1/6] drivers/net: Remove dead smc91111 driver Jan Kiszka
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
This resolves remaining driver-related issues when building against 5.15
and enables this in CI.
NOTE: This only addresses compilation issues. We still have a bug,
likely in dovetail, see
https://xenomai.org/pipermail/xenomai/2022-January/047048.html.
Jan
Jan Kiszka (6):
drivers/net: Remove dead smc91111 driver
drivers/net: Account for changes to of_get_mac_address in 5.13
drivers/net: fec: Account for changes of get/set_coalesce ethtool
callbacks in 5.15
drivers/serial: rt_imx_uart: Make it DT-only
ci: Add 5.15 kernel
ci: Drop some I-pipe left-overs
.gitlab-ci.yml | 29 +-
kernel/drivers/net/drivers/Kconfig | 5 -
kernel/drivers/net/drivers/Makefile | 4 -
kernel/drivers/net/drivers/at91_ether.c | 7 +
.../drivers/net/drivers/freescale/fec_main.c | 22 +
kernel/drivers/net/drivers/macb.c | 7 +
kernel/drivers/net/drivers/rt_smc91111.h | 566 ---
kernel/drivers/net/drivers/smc91111.c | 3531 -----------------
kernel/drivers/serial/rt_imx_uart.c | 32 +-
9 files changed, 64 insertions(+), 4139 deletions(-)
delete mode 100644 kernel/drivers/net/drivers/rt_smc91111.h
delete mode 100644 kernel/drivers/net/drivers/smc91111.c
--
2.31.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] drivers/net: Remove dead smc91111 driver
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
2022-01-07 11:35 ` [PATCH 2/6] drivers/net: Account for changes to of_get_mac_address in 5.13 Jan Kiszka
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
This was once (2004) added to cater a special x86 platform with ISA
interface. That one is long dead, and now the driver stops building on
5.15, reminding of its old Frankenstein logic. Time to bury it.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
.gitlab-ci.yml | 1 -
kernel/drivers/net/drivers/Kconfig | 5 -
kernel/drivers/net/drivers/Makefile | 4 -
kernel/drivers/net/drivers/rt_smc91111.h | 566 ----
kernel/drivers/net/drivers/smc91111.c | 3531 ----------------------
5 files changed, 4107 deletions(-)
delete mode 100644 kernel/drivers/net/drivers/rt_smc91111.h
delete mode 100644 kernel/drivers/net/drivers/smc91111.c
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e4f35f2c45..859a12b89b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -130,7 +130,6 @@ variables:
- ./scripts/config -m XENO_DRIVERS_NET_DRV_VIA_RHINE
- ./scripts/config -m XENO_DRIVERS_NET_DRV_IGB
- ./scripts/config -m XENO_DRIVERS_NET_DRV_R8169
- - ./scripts/config -m XENO_DRIVERS_NET_DRV_SMC91111
- ./scripts/config -e XENO_DRIVERS_NET_EXP_DRIVERS
- ./scripts/config -m XENO_DRIVERS_NET_DRV_3C59X
- ./scripts/config -m XENO_DRIVERS_NET_DRV_E1000_NEW
diff --git a/kernel/drivers/net/drivers/Kconfig b/kernel/drivers/net/drivers/Kconfig
index 7a9d27e386..3a90dd8abe 100644
--- a/kernel/drivers/net/drivers/Kconfig
+++ b/kernel/drivers/net/drivers/Kconfig
@@ -84,11 +84,6 @@ config XENO_DRIVERS_NET_DRV_LOOPBACK
tristate "Loopback"
default y
-
-config XENO_DRIVERS_NET_DRV_SMC91111
- depends on XENO_DRIVERS_NET
- tristate "SMSC LAN91C111"
-
if ARM
config XENO_DRIVERS_NET_DRV_AT91_ETHER
diff --git a/kernel/drivers/net/drivers/Makefile b/kernel/drivers/net/drivers/Makefile
index 6c715abc00..97cf0c3b12 100644
--- a/kernel/drivers/net/drivers/Makefile
+++ b/kernel/drivers/net/drivers/Makefile
@@ -36,10 +36,6 @@ obj-$(CONFIG_XENO_DRIVERS_NET_DRV_PCNET32) += rt_pcnet32.o
rt_pcnet32-y := pcnet32.o
-obj-$(CONFIG_XENO_DRIVERS_NET_DRV_SMC91111) += rt_smc91111.o
-
-rt_smc91111-y := smc91111.o
-
obj-$(CONFIG_XENO_DRIVERS_NET_DRV_MACB) += rt_macb.o
rt_macb-y := macb.o
diff --git a/kernel/drivers/net/drivers/rt_smc91111.h b/kernel/drivers/net/drivers/rt_smc91111.h
deleted file mode 100644
index da39e17238..0000000000
--- a/kernel/drivers/net/drivers/rt_smc91111.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/*------------------------------------------------------------------------
- . smc91111.h - macros for the LAN91C111 Ethernet Driver
- .
- . Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
- . Developed by Simple Network Magic Corporation (SNMC)
- . Copyright (C) 1996 by Erik Stahlman (ES)
- .
- . 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.
- .
- . This program is distributed in the hope that it will be useful,
- . but WITHOUT ANY WARRANTY; without even the implied warranty of
- . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- . GNU General Public License for more details.
- .
- . You should have received a copy of the GNU General Public License
- . along with this program; if not, write to the Free Software
- . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- .
- . This file contains register information and access macros for
- . the LAN91C111 single chip ethernet controller. It is a modified
- . version of the smc9194.h file.
- .
- . Information contained in this file was obtained from the LAN91C111
- . manual from SMC. To get a copy, if you really want one, you can find
- . information under www.smsc.com.
- .
- . Authors
- . Erik Stahlman ( erik@vt.edu )
- . Daris A Nevil ( dnevil@snmc.com )
- .
- . History
- . 03/16/01 Daris A Nevil Modified for use with LAN91C111 device
- .
- ---------------------------------------------------------------------------*/
-#ifndef _SMC91111_H_
-#define _SMC91111_H_
-
-/* I want some simple types */
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long int dword;
-
-
-/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */
-
-#define SMC_IO_EXTENT 16
-
-
-/*---------------------------------------------------------------
- .
- . A description of the SMSC registers is probably in order here,
- . although for details, the SMC datasheet is invaluable.
- .
- . Basically, the chip has 4 banks of registers ( 0 to 3 ), which
- . are accessed by writing a number into the BANK_SELECT register
- . ( I also use a SMC_SELECT_BANK macro for this ).
- .
- . The banks are configured so that for most purposes, bank 2 is all
- . that is needed for simple run time tasks.
- -----------------------------------------------------------------------*/
-
-/*
- . Bank Select Register:
- .
- . yyyy yyyy 0000 00xx
- . xx = bank number
- . yyyy yyyy = 0x33, for identification purposes.
-*/
-#define BANK_SELECT 14
-
-// Transmit Control Register
-/* BANK 0 */
-#define TCR_REG 0x0000 // transmit control register
-#define TCR_ENABLE 0x0001 // When 1 we can transmit
-#define TCR_LOOP 0x0002 // Controls output pin LBK
-#define TCR_FORCOL 0x0004 // When 1 will force a collision
-#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0
-#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames
-#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier
-#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation
-#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error
-#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback
-#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode
-
-#define TCR_CLEAR 0 /* do NOTHING */
-/* the default settings for the TCR register : */
-/* QUESTION: do I want to enable padding of short packets ? */
-#define TCR_DEFAULT TCR_ENABLE
-
-
-// EPH Status Register
-/* BANK 0 */
-#define EPH_STATUS_REG 0x0002
-#define ES_TX_SUC 0x0001 // Last TX was successful
-#define ES_SNGL_COL 0x0002 // Single collision detected for last tx
-#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx
-#define ES_LTX_MULT 0x0008 // Last tx was a multicast
-#define ES_16COL 0x0010 // 16 Collisions Reached
-#define ES_SQET 0x0020 // Signal Quality Error Test
-#define ES_LTXBRD 0x0040 // Last tx was a broadcast
-#define ES_TXDEFR 0x0080 // Transmit Deferred
-#define ES_LATCOL 0x0200 // Late collision detected on last tx
-#define ES_LOSTCARR 0x0400 // Lost Carrier Sense
-#define ES_EXC_DEF 0x0800 // Excessive Deferral
-#define ES_CTR_ROL 0x1000 // Counter Roll Over indication
-#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin
-#define ES_TXUNRN 0x8000 // Tx Underrun
-
-
-// Receive Control Register
-/* BANK 0 */
-#define RCR_REG 0x0004
-#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted
-#define RCR_PRMS 0x0002 // Enable promiscuous mode
-#define RCR_ALMUL 0x0004 // When set accepts all multicast frames
-#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets
-#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets
-#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision
-#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier
-#define RCR_SOFTRST 0x8000 // resets the chip
-
-/* the normal settings for the RCR register : */
-#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN)
-#define RCR_CLEAR 0x0 // set it to a base state
-
-// Counter Register
-/* BANK 0 */
-#define COUNTER_REG 0x0006
-
-// Memory Information Register
-/* BANK 0 */
-#define MIR_REG 0x0008
-
-// Receive/Phy Control Register
-/* BANK 0 */
-#define RPC_REG 0x000A
-#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
-#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
-#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
-#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
-#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
-#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
-#define RPC_LED_RES (0x01) // LED = Reserved
-#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
-#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
-#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
-#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
-#define RPC_LED_TX (0x06) // LED = TX packet occurred
-#define RPC_LED_RX (0x07) // LED = RX packet occurred
-#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
-
-/* Bank 0 0x000C is reserved */
-
-// Bank Select Register
-/* All Banks */
-#define BSR_REG 0x000E
-
-
-// Configuration Reg
-/* BANK 1 */
-#define CONFIG_REG 0x0000
-#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy
-#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL
-#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus
-#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
-
-// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
-#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN)
-
-
-// Base Address Register
-/* BANK 1 */
-#define BASE_REG 0x0002
-
-
-// Individual Address Registers
-/* BANK 1 */
-#define ADDR0_REG 0x0004
-#define ADDR1_REG 0x0006
-#define ADDR2_REG 0x0008
-
-
-// General Purpose Register
-/* BANK 1 */
-#define GP_REG 0x000A
-
-
-// Control Register
-/* BANK 1 */
-#define CTL_REG 0x000C
-#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received
-#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
-#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt
-#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt
-#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt
-#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
-#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers
-#define CTL_STORE 0x0001 // When set stores registers into EEPROM
-
-
-// MMU Command Register
-/* BANK 2 */
-#define MMU_CMD_REG 0x0000
-#define MC_BUSY 1 // When 1 the last release has not completed
-#define MC_NOP (0<<5) // No Op
-#define MC_ALLOC (1<<5) // OR with number of 256 byte packets
-#define MC_RESET (2<<5) // Reset MMU to initial state
-#define MC_REMOVE (3<<5) // Remove the current rx packet
-#define MC_RELEASE (4<<5) // Remove and release the current rx packet
-#define MC_FREEPKT (5<<5) // Release packet in PNR register
-#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit
-#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs
-
-
-// Packet Number Register
-/* BANK 2 */
-#define PN_REG 0x0002
-
-
-// Allocation Result Register
-/* BANK 2 */
-#define AR_REG 0x0003
-#define AR_FAILED 0x80 // Alocation Failed
-
-
-// RX FIFO Ports Register
-/* BANK 2 */
-#define RXFIFO_REG 0x0004 // Must be read as a word
-#define RXFIFO_REMPTY 0x8000 // RX FIFO Empty
-
-
-// TX FIFO Ports Register
-/* BANK 2 */
-#define TXFIFO_REG RXFIFO_REG // Must be read as a word
-#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty
-
-
-// Pointer Register
-/* BANK 2 */
-#define PTR_REG 0x0006
-#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area
-#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access
-#define PTR_READ 0x2000 // When 1 the operation is a read
-
-
-// Data Register
-/* BANK 2 */
-#define DATA_REG 0x0008
-
-
-// Interrupt Status/Acknowledge Register
-/* BANK 2 */
-#define INT_REG 0x000C
-
-
-// Interrupt Mask Register
-/* BANK 2 */
-#define IM_REG 0x000D
-#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt
-#define IM_ERCV_INT 0x40 // Early Receive Interrupt
-#define IM_EPH_INT 0x20 // Set by Etheret Protocol Handler section
-#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns
-#define IM_ALLOC_INT 0x08 // Set when allocation request is completed
-#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty
-#define IM_TX_INT 0x02 // Transmit Interrrupt
-#define IM_RCV_INT 0x01 // Receive Interrupt
-
-
-// Multicast Table Registers
-/* BANK 3 */
-#define MCAST_REG1 0x0000
-#define MCAST_REG2 0x0002
-#define MCAST_REG3 0x0004
-#define MCAST_REG4 0x0006
-
-
-// Management Interface Register (MII)
-/* BANK 3 */
-#define MII_REG 0x0008
-#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
-#define MII_MDOE 0x0008 // MII Output Enable
-#define MII_MCLK 0x0004 // MII Clock, pin MDCLK
-#define MII_MDI 0x0002 // MII Input, pin MDI
-#define MII_MDO 0x0001 // MII Output, pin MDO
-
-
-// Revision Register
-/* BANK 3 */
-#define REV_REG 0x000A /* ( hi: chip id low: rev # ) */
-
-
-// Early RCV Register
-/* BANK 3 */
-/* this is NOT on SMC9192 */
-#define ERCV_REG 0x000C
-#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received
-#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask
-
-// External Register
-/* BANK 7 */
-#define EXT_REG 0x0000
-
-
-#define CHIP_9192 3
-#define CHIP_9194 4
-#define CHIP_9195 5
-#define CHIP_9196 6
-#define CHIP_91100 7
-#define CHIP_91100FD 8
-#define CHIP_91111FD 9
-
-static const char * chip_ids[ 15 ] = {
- NULL, NULL, NULL,
- /* 3 */ "SMC91C90/91C92",
- /* 4 */ "SMC91C94",
- /* 5 */ "SMC91C95",
- /* 6 */ "SMC91C96",
- /* 7 */ "SMC91C100",
- /* 8 */ "SMC91C100FD",
- /* 9 */ "SMC91C11xFD",
- NULL, NULL,
- NULL, NULL, NULL};
-
-/*
- . Transmit status bits
-*/
-#define TS_SUCCESS 0x0001
-#define TS_LOSTCAR 0x0400
-#define TS_LATCOL 0x0200
-#define TS_16COL 0x0010
-
-/*
- . Receive status bits
-*/
-#define RS_ALGNERR 0x8000
-#define RS_BRODCAST 0x4000
-#define RS_BADCRC 0x2000
-#define RS_ODDFRAME 0x1000 // bug: the LAN91C111 never sets this on receive
-#define RS_TOOLONG 0x0800
-#define RS_TOOSHORT 0x0400
-#define RS_MULTICAST 0x0001
-#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
-
-
-// PHY Types
-enum {
- PHY_LAN83C183 = 1, // LAN91C111 Internal PHY
- PHY_LAN83C180
-};
-
-
-// PHY Register Addresses (LAN91C111 Internal PHY)
-
-// PHY Control Register
-#define PHY_CNTL_REG 0x00
-#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
-#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
-#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
-#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
-#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
-#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
-#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
-#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
-#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
-
-// PHY Status Register
-#define PHY_STAT_REG 0x01
-#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
-#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
-#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
-#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
-#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
-#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
-#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
-#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
-#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
-#define PHY_STAT_LINK 0x0004 // 1=valid link
-#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
-#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
-
-// PHY Identifier Registers
-#define PHY_ID1_REG 0x02 // PHY Identifier 1
-#define PHY_ID2_REG 0x03 // PHY Identifier 2
-
-// PHY Auto-Negotiation Advertisement Register
-#define PHY_AD_REG 0x04
-#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
-#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
-#define PHY_AD_RF 0x2000 // 1=advertise remote fault
-#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
-#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
-#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
-#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
-#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
-#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
-
-// PHY Auto-negotiation Remote End Capability Register
-#define PHY_RMT_REG 0x05
-// Uses same bit definitions as PHY_AD_REG
-
-// PHY Configuration Register 1
-#define PHY_CFG1_REG 0x10
-#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
-#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
-#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
-#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
-#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
-#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
-#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
-#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
-#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
-#define PHY_CFG1_TLVL_MASK 0x003C
-#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
-
-
-// PHY Configuration Register 2
-#define PHY_CFG2_REG 0x11
-#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
-#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
-#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
-#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
-
-// PHY Status Output (and Interrupt status) Register
-#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
-#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
-#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
-#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
-#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
-#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
-#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
-#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
-#define PHY_INT_JAB 0x0100 // 1=Jabber detected
-#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
-#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
-
-// PHY Interrupt/Status Mask Register
-#define PHY_MASK_REG 0x13 // Interrupt Mask
-// Uses the same bit definitions as PHY_INT_REG
-
-
-
-/*-------------------------------------------------------------------------
- . I define some macros to make it easier to do somewhat common
- . or slightly complicated, repeated tasks.
- --------------------------------------------------------------------------*/
-
-/* select a register bank, 0 to 3 */
-
-#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); }
-
-/* this enables an interrupt in the interrupt mask register */
-#define SMC_ENABLE_INT(x) {\
- unsigned char mask;\
- SMC_SELECT_BANK(2);\
- mask = inb( ioaddr + IM_REG );\
- mask |= (x);\
- outb( mask, ioaddr + IM_REG ); \
-}
-
-/* this disables an interrupt from the interrupt mask register */
-
-#define SMC_DISABLE_INT(x) {\
- unsigned char mask;\
- SMC_SELECT_BANK(2);\
- mask = inb( ioaddr + IM_REG );\
- mask &= ~(x);\
- outb( mask, ioaddr + IM_REG ); \
-}
-
-/*----------------------------------------------------------------------
- . Define the interrupts that I want to receive from the card
- .
- . I want:
- . IM_EPH_INT, for nasty errors
- . IM_RCV_INT, for happy received packets
- . IM_RX_OVRN_INT, because I have to kick the receiver
- . IM_MDINT, for PHY Register 18 Status Changes
- --------------------------------------------------------------------------*/
-#define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \
- IM_MDINT)
-
-
-#ifdef CONFIG_SYSCTL
-
-
-/*
- * Declarations for the sysctl interface, which allows users the ability to
- * control the finer aspects of the LAN91C111 chip. Since the smc
- * module currently registers its sysctl table dynamically, the sysctl path
- * for module FOO is /proc/sys/dev/ethX/FOO
- */
-#define CTL_SMC (CTL_BUS+1389) // arbitrary and hopefully unused
-
-enum {
- CTL_SMC_INFO = 1, // Sysctl files information
- CTL_SMC_SWVER, // Driver Software Version Info
- CTL_SMC_SWFDUP, // Switched Full Duplex Mode
- CTL_SMC_EPHLOOP, // EPH Block Internal Loopback
- CTL_SMC_MIIOP, // MII Operation
- CTL_SMC_AUTONEG, // Auto-negotiate Mode
- CTL_SMC_RFDUPLX, // Request Full Duplex Mode
- CTL_SMC_RSPEED, // Request Speed Selection
- CTL_SMC_AFDUPLX, // Actual Full Duplex Mode
- CTL_SMC_ASPEED, // Actual Speed Selection
- CTL_SMC_LNKFAIL, // Link Failed
- CTL_SMC_FORCOL, // Force a Collision
- CTL_SMC_FILTCAR, // Filter Carrier
- CTL_SMC_FREEMEM, // Free Buffer Memory
- CTL_SMC_TOTMEM, // Total Buffer Memory
- CTL_SMC_LEDA, // Output of LED-A
- CTL_SMC_LEDB, // Output of LED-B
- CTL_SMC_CHIPREV, // LAN91C111 Chip Revision ID
-#ifdef SMC_DEBUG
- // Register access for debugging
- CTL_SMC_REG_BSR, // Bank Select
- CTL_SMC_REG_TCR, // Transmit Control
- CTL_SMC_REG_ESR, // EPH Status
- CTL_SMC_REG_RCR, // Receive Control
- CTL_SMC_REG_CTRR, // Counter
- CTL_SMC_REG_MIR, // Memory Information
- CTL_SMC_REG_RPCR, // Receive/Phy Control
- CTL_SMC_REG_CFGR, // Configuration
- CTL_SMC_REG_BAR, // Base Address
- CTL_SMC_REG_IAR0, // Individual Address 0
- CTL_SMC_REG_IAR1, // Individual Address 1
- CTL_SMC_REG_IAR2, // Individual Address 2
- CTL_SMC_REG_GPR, // General Purpose
- CTL_SMC_REG_CTLR, // Control
- CTL_SMC_REG_MCR, // MMU Command
- CTL_SMC_REG_PNR, // Packet Number
- CTL_SMC_REG_FPR, // FIFO Ports
- CTL_SMC_REG_PTR, // Pointer
- CTL_SMC_REG_DR, // Data
- CTL_SMC_REG_ISR, // Interrupt Status
- CTL_SMC_REG_MTR1, // Multicast Table Entry 1
- CTL_SMC_REG_MTR2, // Multicast Table Entry 2
- CTL_SMC_REG_MTR3, // Multicast Table Entry 3
- CTL_SMC_REG_MTR4, // Multicast Table Entry 4
- CTL_SMC_REG_MIIR, // Management Interface
- CTL_SMC_REG_REVR, // Revision
- CTL_SMC_REG_ERCVR, // Early RCV
- CTL_SMC_REG_EXTR, // External
- CTL_SMC_PHY_CTRL, // PHY Control
- CTL_SMC_PHY_STAT, // PHY Status
- CTL_SMC_PHY_ID1, // PHY ID1
- CTL_SMC_PHY_ID2, // PHY ID2
- CTL_SMC_PHY_ADC, // PHY Advertise Capability
- CTL_SMC_PHY_REMC, // PHY Advertise Capability
- CTL_SMC_PHY_CFG1, // PHY Configuration 1
- CTL_SMC_PHY_CFG2, // PHY Configuration 2
- CTL_SMC_PHY_INT, // PHY Interrupt/Status Output
- CTL_SMC_PHY_MASK, // PHY Interrupt/Status Mask
-#endif
- // ---------------------------------------------------
- CTL_SMC_LAST_ENTRY // Add new entries above the line
-};
-
-#endif // CONFIG_SYSCTL
-
-#endif /* _SMC_91111_H_ */
-
-
diff --git a/kernel/drivers/net/drivers/smc91111.c b/kernel/drivers/net/drivers/smc91111.c
deleted file mode 100644
index 07e1596b62..0000000000
--- a/kernel/drivers/net/drivers/smc91111.c
+++ /dev/null
@@ -1,3531 +0,0 @@
-/*------------------------------------------------------------------------
- . smc91111.c
- . This is a driver for SMSC's 91C111 single-chip Ethernet device.
- .
- . Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
- . Developed by Simple Network Magic Corporation (SNMC)
- . Copyright (C) 1996 by Erik Stahlman (ES)
- .
- . 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.
- .
- . This program is distributed in the hope that it will be useful,
- . but WITHOUT ANY WARRANTY; without even the implied warranty of
- . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- . GNU General Public License for more details.
- .
- . You should have received a copy of the GNU General Public License
- . along with this program; if not, write to the Free Software
- . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- .
- . Information contained in this file was obtained from the LAN91C111
- . manual from SMC. To get a copy, if you really want one, you can find
- . information under www.smsc.com.
- .
- .
- . "Features" of the SMC chip:
- . Integrated PHY/MAC for 10/100BaseT Operation
- . Supports internal and external MII
- . Integrated 8K packet memory
- . EEPROM interface for configuration
- .
- . Arguments:
- . io = for the base address
- . irq = for the IRQ
- . nowait = 0 for normal wait states, 1 eliminates additional wait states
- .
- . author:
- . Erik Stahlman ( erik@vt.edu )
- . Daris A Nevil ( dnevil@snmc.com )
- . Pramod B Bhardwaj (pramod.bhardwaj@smsc.com)
- .
- .
- . Hardware multicast code from Peter Cammaert ( pc@denkart.be )
- .
- . Sources:
- . o SMSC LAN91C111 databook (www.smsc.com)
- . o smc9194.c by Erik Stahlman
- . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov )
- .
- . History:
- . 09/24/01 Pramod B Bhardwaj, Added the changes for Kernel 2.4
- . 08/21/01 Pramod B Bhardwaj Added support for RevB of LAN91C111
- . 04/25/01 Daris A Nevil Initial public release through SMSC
- . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111
-
- Ported to RTnet: March 2004, Jan Kiszka <Jan.Kiszka@web.de>
- ----------------------------------------------------------------------------*/
-
-// Use power-down feature of the chip
-#define POWER_DOWN 1
-
-
-static const char version[] =
- "SMSC LAN91C111 Driver (v2.0-rt), RTnet version - Jan Kiszka (jan.kiszka@web.de)\n\n";
-
-#ifdef MODULE
-#include <linux/module.h>
-#include <linux/version.h>
-#endif
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h> //#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-//#include <linux/kcomp.h>
-
-#ifdef DISABLED____CONFIG_SYSCTL
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-#endif
-
-#include <rtnet_port.h>
-
-#include "rt_smc91111.h"
-/*------------------------------------------------------------------------
- .
- . Configuration options, for the experienced user to change.
- .
- -------------------------------------------------------------------------*/
-
-/*
- . Do you want to use 32 bit xfers? This should work on all chips, as
- . the chipset is designed to accommodate them.
-*/
-#define USE_32_BIT 1
-
-
-/*
- .the LAN91C111 can be at any of the following port addresses. To change,
- .for a slightly different card, you can add it to the array. Keep in
- .mind that the array must end in zero.
-*/
-static unsigned int smc_portlist[] __initdata =
- { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
- 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};
-
-
-/*
- . Wait time for memory to be free. This probably shouldn't be
- . tuned that much, as waiting for this means nothing else happens
- . in the system
-*/
-#define MEMORY_WAIT_TIME 16
-
-
-/*
- . Timeout in us for waiting on the completion of a previous MMU command
- . in smc_rcv().
-*/
-#define MMU_CMD_TIMEOUT 5
-
-
-/*
- . DEBUGGING LEVELS
- .
- . 0 for normal operation
- . 1 for slightly more details
- . >2 for various levels of increasingly useless information
- . 2 for interrupt tracking, status flags
- . 3 for packet info
- . 4 for complete packet dumps
-*/
-//#define SMC_DEBUG 3 // Must be defined in makefile
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2)
-#define PRINTK3(args...) rtdm_printk(args)
-#else
-#define PRINTK3(args...)
-#endif
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 1)
-#define PRINTK2(args...) rtdm_printk(args)
-#else
-#define PRINTK2(args...)
-#endif
-
-#ifdef SMC_DEBUG
-#define PRINTK(args...) rtdm_printk(args)
-#else
-#define PRINTK(args...)
-#endif
-
-
-/*------------------------------------------------------------------------
- .
- . The internal workings of the driver. If you are changing anything
- . here with the SMC stuff, you should have the datasheet and know
- . what you are doing.
- .
- -------------------------------------------------------------------------*/
-#define CARDNAME "LAN91C111"
-
-// Memory sizing constant
-#define LAN91C111_MEMORY_MULTIPLIER (1024*2)
-
-/* store this information for the driver.. */
-struct smc_local {
-
-// these are things that the kernel wants me to keep, so users
- // can find out semi-useless statistics of how well the card is
- // performing
- struct net_device_stats stats;
-
- // If I have to wait until memory is available to send
- // a packet, I will store the skbuff here, until I get the
- // desired memory. Then, I'll send it out and free it.
- struct rtskb * saved_skb;
-
- // This keeps track of how many packets that I have
- // sent out. When an TX_EMPTY interrupt comes, I know
- // that all of these have been sent.
- int packets_waiting;
-
- // Set to true during the auto-negotiation sequence
- int autoneg_active;
-
- // Address of our PHY port
- word phyaddr;
-
- // Type of PHY
- word phytype;
-
- // Last contents of PHY Register 18
- word lastPhy18;
-
- // Contains the current active transmission mode
- word tcr_cur_mode;
-
- // Contains the current active receive mode
- word rcr_cur_mode;
-
- // Contains the current active receive/phy mode
- word rpc_cur_mode;
-
- /* => Pramod, Odd Byte issue */
- // Contains the Current ChipID
- unsigned short ChipID;
-
- //Contains the Current ChipRevision
- unsigned short ChipRev;
- /* <= Pramod, Odd Byte issue */
-
-#ifdef DISABLED____CONFIG_SYSCTL
-
- // Root directory /proc/sys/dev
- // Second entry must be null to terminate the table
- ctl_table root_table[2];
-
- // Directory for this device /proc/sys/dev/ethX
- // Again the second entry must be zero to terminate
- ctl_table eth_table[2];
-
- // This is the parameters (file) table
- ctl_table param_table[CTL_SMC_LAST_ENTRY];
-
- // Saves the sysctl header returned by register_sysctl_table()
- // we send this to unregister_sysctl_table()
- struct ctl_table_header *sysctl_header;
-
- // Parameter variables (files) go here
- char ctl_info[1024];
- int ctl_swfdup;
- int ctl_ephloop;
- int ctl_miiop;
- int ctl_autoneg;
- int ctl_rfduplx;
- int ctl_rspeed;
- int ctl_afduplx;
- int ctl_aspeed;
- int ctl_lnkfail;
- int ctl_forcol;
- int ctl_filtcar;
- int ctl_freemem;
- int ctl_totmem;
- int ctl_leda;
- int ctl_ledb;
- int ctl_chiprev;
-#ifdef SMC_DEBUG
- int ctl_reg_bsr;
- int ctl_reg_tcr;
- int ctl_reg_esr;
- int ctl_reg_rcr;
- int ctl_reg_ctrr;
- int ctl_reg_mir;
- int ctl_reg_rpcr;
- int ctl_reg_cfgr;
- int ctl_reg_bar;
- int ctl_reg_iar0;
- int ctl_reg_iar1;
- int ctl_reg_iar2;
- int ctl_reg_gpr;
- int ctl_reg_ctlr;
- int ctl_reg_mcr;
- int ctl_reg_pnr;
- int ctl_reg_fpr;
- int ctl_reg_ptr;
- int ctl_reg_dr;
- int ctl_reg_isr;
- int ctl_reg_mtr1;
- int ctl_reg_mtr2;
- int ctl_reg_mtr3;
- int ctl_reg_mtr4;
- int ctl_reg_miir;
- int ctl_reg_revr;
- int ctl_reg_ercvr;
- int ctl_reg_extr;
- int ctl_phy_ctrl;
- int ctl_phy_stat;
- int ctl_phy_id1;
- int ctl_phy_id2;
- int ctl_phy_adc;
- int ctl_phy_remc;
- int ctl_phy_cfg1;
- int ctl_phy_cfg2;
- int ctl_phy_int;
- int ctl_phy_mask;
-#endif // SMC_DEBUG
-
-#endif // CONFIG_SYSCTL
-
- rtdm_irq_t irq_handle;
-};
-
-
-/*-----------------------------------------------------------------
- .
- . The driver can be entered at any of the following entry points.
- .
- .------------------------------------------------------------------ */
-
-/*
- . This is called by register_netdev(). It is responsible for
- . checking the portlist for the SMC9000 series chipset. If it finds
- . one, then it will initialize the device, find the hardware information,
- . and sets up the appropriate device parameters.
- . NOTE: Interrupts are *OFF* when this procedure is called.
- .
- . NB:This shouldn't be static since it is referred to externally.
-*/
-int smc_init(struct rtnet_device *dev);
-
-/*
- . This is called by unregister_netdev(). It is responsible for
- . cleaning up before the driver is finally unregistered and discarded.
-*/
-//void smc_destructor(struct net_device *dev);
-
-/*
- . The kernel calls this function when someone wants to use the net_device,
- . typically 'ifconfig ethX up'.
-*/
-static int smc_open(struct rtnet_device *dev);
-
-/*
- . This is called by the kernel to send a packet out into the net. it's
- . responsible for doing a best-effort send, but if it's simply not possible
- . to send it, the packet gets dropped.
-*/
-//static void smc_timeout (struct net_device *dev);*/
-/*
- . This is called by the kernel in response to 'ifconfig ethX down'. It
- . is responsible for cleaning up everything that the open routine
- . does, and maybe putting the card into a powerdown state.
-*/
-static int smc_close(struct rtnet_device *dev);
-
-/*
- . This routine allows the proc file system to query the driver's
- . statistics.
-*/
-static struct net_device_stats *smc_query_statistics(struct rtnet_device *rtdev);
-
-/*
- . Finally, a call to set promiscuous mode ( for TCPDUMP and related
- . programs ) and multicast modes.
-*/
-static void smc_set_multicast_list(struct rtnet_device *dev);
-
-/*
- . Configures the PHY through the MII Management interface
-*/
-static void smc_phy_configure(struct rtnet_device* dev);
-
-/*---------------------------------------------------------------
- .
- . Interrupt level calls..
- .
- ----------------------------------------------------------------*/
-
-/*
- . Handles the actual interrupt
-*/
-static int smc_interrupt(rtdm_irq_t *irq_handle);
-/*
- . This is a separate procedure to handle the receipt of a packet, to
- . leave the interrupt code looking slightly cleaner
-*/
-inline static void smc_rcv( struct rtnet_device *dev );
-/*
- . This handles a TX interrupt, which is only called when an error
- . relating to a packet is sent.
-*/
-//inline static void smc_tx( struct net_device * dev );
-
-/*
- . This handles interrupts generated from PHY register 18
-*/
-//static void smc_phy_interrupt(struct net_device* dev);
-
-/*
- ------------------------------------------------------------
- .
- . Internal routines
- .
- ------------------------------------------------------------
-*/
-
-/*
- . Test if a given location contains a chip, trying to cause as
- . little damage as possible if it's not a SMC chip.
-*/
-static int smc_probe(struct rtnet_device *dev, int ioaddr);
-
-/*
- . A rather simple routine to print out a packet for debugging purposes.
-*/
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2)
-static void print_packet( byte *, int );
-#endif
-
-#define tx_done(dev) 1
-
-/* this is called to actually send the packet to the chip */
-static void smc_hardware_send_packet( struct rtnet_device * dev );
-
-/* Since I am not sure if I will have enough room in the chip's ram
- . to store the packet, I call this routine, which either sends it
- . now, or generates an interrupt when the card is ready for the
- . packet */
-static int smc_wait_to_send_packet( struct rtskb * skb, struct rtnet_device *dev );
-
-/* this does a soft reset on the device */
-static void smc_reset( struct rtnet_device* dev );
-
-/* Enable Interrupts, Receive, and Transmit */
-static void smc_enable( struct rtnet_device *dev );
-
-/* this puts the device in an inactive state */
-static void smc_shutdown( int ioaddr );
-
-#ifndef NO_AUTOPROBE
-/* This routine will find the IRQ of the driver if one is not
- . specified in the input to the device. */
-static int smc_findirq( int ioaddr );
-#endif
-
-/* Routines to Read and Write the PHY Registers across the
- MII Management Interface
-*/
-
-static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg);
-static void smc_write_phy_register(int ioaddr, byte phyaddr, byte phyreg, word phydata);
-
-/* Initilizes our device's sysctl proc filesystem */
-
-#ifdef DISABLED____CONFIG_SYSCTL
-static void smc_sysctl_register(struct rtnet_device *);
-static void smc_sysctl_unregister(struct rtnet_device *);
-#endif /* CONFIG_SYSCTL */
-
-/*
- . Function: smc_reset( struct device* dev )
- . Purpose:
- . This sets the SMC91111 chip to its normal state, hopefully from whatever
- . mess that any other DOS driver has put it in.
- .
- . Maybe I should reset more registers to defaults in here? SOFTRST should
- . do that for me.
- .
- . Method:
- . 1. send a SOFT RESET
- . 2. wait for it to finish
- . 3. enable autorelease mode
- . 4. reset the memory management unit
- . 5. clear all interrupts
- .
-*/
-static void smc_reset( struct rtnet_device* dev )
-{
- //struct smc_local *lp = (struct smc_local *)dev->priv;
- int ioaddr = dev->base_addr;
-
- PRINTK2("%s:smc_reset\n", dev->name);
-
- /* This resets the registers mostly to defaults, but doesn't
- affect EEPROM. That seems unnecessary */
- SMC_SELECT_BANK( 0 );
- outw( RCR_SOFTRST, ioaddr + RCR_REG );
-
- /* Setup the Configuration Register */
- /* This is necessary because the CONFIG_REG is not affected */
- /* by a soft reset */
-
- SMC_SELECT_BANK( 1 );
- outw( CONFIG_DEFAULT, ioaddr + CONFIG_REG);
-
- /* Setup for fast accesses if requested */
- /* If the card/system can't handle it then there will */
- /* be no recovery except for a hard reset or power cycle */
-
- if (dev->dma)
- outw( inw( ioaddr + CONFIG_REG ) | CONFIG_NO_WAIT,
- ioaddr + CONFIG_REG );
-
-#ifdef POWER_DOWN
- /* Release from possible power-down state */
- /* Configuration register is not affected by Soft Reset */
- SMC_SELECT_BANK( 1 );
- outw( inw( ioaddr + CONFIG_REG ) | CONFIG_EPH_POWER_EN,
- ioaddr + CONFIG_REG );
-#endif
-
- SMC_SELECT_BANK( 0 );
-
- /* this should pause enough for the chip to be happy */
- mdelay(10);
-
- /* Disable transmit and receive functionality */
- outw( RCR_CLEAR, ioaddr + RCR_REG );
- outw( TCR_CLEAR, ioaddr + TCR_REG );
-
- /* set the control register to automatically
- release successfully transmitted packets, to make the best
- use out of our limited memory */
- SMC_SELECT_BANK( 1 );
- outw( inw( ioaddr + CTL_REG ) | CTL_AUTO_RELEASE , ioaddr + CTL_REG );
-
- /* Reset the MMU */
- SMC_SELECT_BANK( 2 );
- outw( MC_RESET, ioaddr + MMU_CMD_REG );
-
- /* Note: It doesn't seem that waiting for the MMU busy is needed here,
- but this is a place where future chipsets _COULD_ break. Be wary
- of issuing another MMU command right after this */
-
- /* Disable all interrupts */
- outb( 0, ioaddr + IM_REG );
-}
-
-/*
- . Function: smc_enable
- . Purpose: let the chip talk to the outside work
- . Method:
- . 1. Enable the transmitter
- . 2. Enable the receiver
- . 3. Enable interrupts
-*/
-static void smc_enable( struct rtnet_device *dev )
-{
- unsigned short ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
-
- PRINTK2("%s:smc_enable\n", dev->name);
-
- SMC_SELECT_BANK( 0 );
- /* see the header file for options in TCR/RCR DEFAULT*/
- outw( lp->tcr_cur_mode, ioaddr + TCR_REG );
- outw( lp->rcr_cur_mode, ioaddr + RCR_REG );
-
- /* now, enable interrupts */
- SMC_SELECT_BANK( 2 );
- outb( SMC_INTERRUPT_MASK, ioaddr + IM_REG );
-}
-
-/*
- . Function: smc_shutdown
- . Purpose: closes down the SMC91xxx chip.
- . Method:
- . 1. zero the interrupt mask
- . 2. clear the enable receive flag
- . 3. clear the enable xmit flags
- .
- . TODO:
- . (1) maybe utilize power down mode.
- . Why not yet? Because while the chip will go into power down mode,
- . the manual says that it will wake up in response to any I/O requests
- . in the register space. Empirical results do not show this working.
-*/
-static void smc_shutdown( int ioaddr )
-{
- PRINTK2("CARDNAME:smc_shutdown\n");
-
- /* no more interrupts for me */
- SMC_SELECT_BANK( 2 );
- outb( 0, ioaddr + IM_REG );
-
- /* and tell the card to stay away from that nasty outside world */
- SMC_SELECT_BANK( 0 );
- outb( RCR_CLEAR, ioaddr + RCR_REG );
- outb( TCR_CLEAR, ioaddr + TCR_REG );
-
-#ifdef POWER_DOWN
- /* finally, shut the chip down */
- SMC_SELECT_BANK( 1 );
- outw( inw( ioaddr + CONFIG_REG ) & ~CONFIG_EPH_POWER_EN,
- ioaddr + CONFIG_REG );
-#endif
-}
-
-
-/*
- . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * )
- . Purpose:
- . Attempt to allocate memory for a packet, if chip-memory is not
- . available, then tell the card to generate an interrupt when it
- . is available.
- .
- . Algorithm:
- .
- . o if the saved_skb is not currently null, then drop this packet
- . on the floor. This should never happen, because of TBUSY.
- . o if the saved_skb is null, then replace it with the current packet,
- . o See if I can sending it now.
- . o (NO): Enable interrupts and let the interrupt handler deal with it.
- . o (YES):Send it now.
-*/
-static int smc_wait_to_send_packet( struct rtskb * skb, struct rtnet_device * dev )
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- unsigned short ioaddr = dev->base_addr;
- word length;
- unsigned short numPages;
- word time_out;
- word status;
-
- PRINTK3("%s:smc_wait_to_send_packet\n", dev->name);
-
- rtnetif_stop_queue(dev);
-
- if ( lp->saved_skb) {
- /* THIS SHOULD NEVER HAPPEN. */
- lp->stats.tx_aborted_errors++;
- rtdm_printk("%s: Bad Craziness - sent packet while busy.\n",
- dev->name);
- return 1;
- }
- lp->saved_skb = skb;
-
- length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-
-
- /*
- ** The MMU wants the number of pages to be the number of 256 bytes
- ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
- **
- ** The 91C111 ignores the size bits, but the code is left intact
- ** for backwards and future compatibility.
- **
- ** Pkt size for allocating is data length +6 (for additional status
- ** words, length and ctl!)
- **
- ** If odd size then last byte is included in this header.
- */
- numPages = ((length & 0xfffe) + 6);
- numPages >>= 8; // Divide by 256
-
- if (numPages > 7 ) {
- rtdm_printk("%s: Far too big packet error. \n", dev->name);
- /* freeing the packet is a good thing here... but should
- . any packets of this size get down here? */
- kfree_rtskb(skb);
- lp->saved_skb = NULL;
- /* this IS an error, but, i don't want the skb saved */
- rtnetif_wake_queue(dev);
- return 0;
- }
- /* either way, a packet is waiting now */
- lp->packets_waiting++;
-
- /* now, try to allocate the memory */
- SMC_SELECT_BANK( 2 );
- outw( MC_ALLOC | numPages, ioaddr + MMU_CMD_REG );
- /*
- . Performance Hack
- .
- . wait a short amount of time.. if I can send a packet now, I send
- . it now. Otherwise, I enable an interrupt and wait for one to be
- . available.
- .
- . I could have handled this a slightly different way, by checking to
- . see if any memory was available in the FREE MEMORY register. However,
- . either way, I need to generate an allocation, and the allocation works
- . no matter what, so I saw no point in checking free memory.
- */
- time_out = MEMORY_WAIT_TIME;
- do {
- status = inb( ioaddr + INT_REG );
- if ( status & IM_ALLOC_INT ) {
- /* acknowledge the interrupt */
- outb( IM_ALLOC_INT, ioaddr + INT_REG );
- break;
- }
- } while ( -- time_out );
-
- if ( !time_out ) {
- kfree_rtskb(skb);
- lp->saved_skb = NULL;
- rtnetif_wake_queue(dev);
-
- rtdm_printk("%s: ERROR: unable to allocate card memory for "
- "packet transmission.\n", dev->name);
- return 0;
- }
- /* or YES! I can send the packet now.. */
- smc_hardware_send_packet(dev);
- rtnetif_wake_queue(dev);
- return 0;
-}
-
-/*
- . Function: smc_hardware_send_packet(struct device * )
- . Purpose:
- . This sends the actual packet to the SMC9xxx chip.
- .
- . Algorithm:
- . First, see if a saved_skb is available.
- . ( this should NOT be called if there is no 'saved_skb'
- . Now, find the packet number that the chip allocated
- . Point the data pointers at it in memory
- . Set the length word in the chip's memory
- . Dump the packet to chip memory
- . Check if a last byte is needed ( odd length packet )
- . if so, set the control flag right
- . Tell the card to send it
- . Enable the transmit interrupt, so I know if it failed
- . Free the kernel data if I actually sent it.
-*/
-static void smc_hardware_send_packet( struct rtnet_device * dev )
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- byte packet_no;
- struct rtskb * skb = lp->saved_skb;
- word length;
- unsigned short ioaddr;
- void * buf;
- rtdm_lockctx_t context;
-
- PRINTK3("%s:smc_hardware_send_packet\n", dev->name);
-
- ioaddr = dev->base_addr;
-
- if ( !skb ) {
- PRINTK("%s: In XMIT with no packet to send \n", dev->name);
- return;
- }
- length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- buf = skb->data;
-
- /* If I get here, I _know_ there is a packet slot waiting for me */
- packet_no = inb( ioaddr + AR_REG );
- if ( packet_no & AR_FAILED ) {
- /* or isn't there? BAD CHIP! */
- rtdm_printk(KERN_DEBUG "%s: Memory allocation failed. \n",
- dev->name);
- kfree_rtskb(skb);
- lp->saved_skb = NULL;
- rtnetif_wake_queue(dev);
- return;
- }
-
- /* we have a packet address, so tell the card to use it */
- outb( packet_no, ioaddr + PN_REG );
-
- /* point to the beginning of the packet */
- outw( PTR_AUTOINC , ioaddr + PTR_REG );
-
- PRINTK3("%s: Trying to xmit packet of length %x\n",
- dev->name, length);
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2)
- rtdm_printk("Transmitting Packet\n");
- print_packet( buf, length );
-#endif
-
- /* send the packet length ( +6 for status, length and ctl byte )
- and the status word ( set to zeros ) */
-#ifdef USE_32_BIT
- outl( (length +6 ) << 16 , ioaddr + DATA_REG );
-#else
- outw( 0, ioaddr + DATA_REG );
- /* send the packet length ( +6 for status words, length, and ctl*/
- outb( (length+6) & 0xFF,ioaddr + DATA_REG );
- outb( (length+6) >> 8 , ioaddr + DATA_REG );
-#endif
-
- /* send the actual data
- . I _think_ it's faster to send the longs first, and then
- . mop up by sending the last word. It depends heavily
- . on alignment, at least on the 486. Maybe it would be
- . a good idea to check which is optimal? But that could take
- . almost as much time as is saved?
- */
-#ifdef USE_32_BIT
- outsl(ioaddr + DATA_REG, buf, length >> 2 );
- if ( length & 0x2 )
- outw(*((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_REG);
-#else
- outsw(ioaddr + DATA_REG , buf, (length ) >> 1);
-#endif // USE_32_BIT
-
- /* Send the last byte, if there is one. */
- if ( (length & 1) == 0 ) {
- outw( 0, ioaddr + DATA_REG );
- } else {
- outb( ((char *)buf)[length -1 ], ioaddr + DATA_REG );
- outb( 0x20, ioaddr + DATA_REG); // Set odd bit in CONTROL BYTE
- }
-
- rtdm_lock_irqsave(context);
-
- /* get and patch time stamp just before the transmission */
- if (skb->xmit_stamp) {
- nanosecs_abs_t xmit_stamp =
- cpu_to_be64(rtdm_clock_read() + *skb->xmit_stamp);
-
- /* point to the patch address */
- outw(PTR_AUTOINC |
- (4 + (char *)skb->xmit_stamp - (char *)skb->data),
- ioaddr + PTR_REG);
- /* we don't check alignments, we just write bytes */
- outsb(ioaddr + DATA_REG, (char *)&xmit_stamp,
- sizeof(xmit_stamp));
- }
-
- /* enable the interrupts */
- SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
-
- /* and let the chipset deal with it */
- outw( MC_ENQUEUE , ioaddr + MMU_CMD_REG );
-
- rtdm_lock_irqrestore(context);
-
- PRINTK2("%s: Sent packet of length %d \n", dev->name, length);
-
- lp->saved_skb = NULL;
- kfree_rtskb(skb);
-
-// dev->trans_start = jiffies;
-
- /* we can send another packet */
- rtnetif_wake_queue(dev);
-
-
- return;
-}
-
-/*-------------------------------------------------------------------------
- |
- | smc_init( struct device * dev )
- | Input parameters:
- | dev->base_addr == 0, try to find all possible locations
- | dev->base_addr == 1, return failure code
- | dev->base_addr == 2, always allocate space, and return success
- | dev->base_addr == <anything else> this is the address to check
- |
- | Output:
- | 0 --> there is a device
- | anything else, error
- |
- ---------------------------------------------------------------------------
-*/
-int __init smc_init(struct rtnet_device *dev)
-{
- int i;
- int base_addr = dev ? dev->base_addr : 0;
-
- PRINTK2("CARDNAME:smc_init\n");
-
- /* try a specific location */
- if (base_addr > 0x1ff)
- return smc_probe(dev, base_addr);
- else if ( 0 != base_addr )
- return -ENXIO;
-
- /* check every ethernet address */
- for (i = 0; smc_portlist[i]; i++)
- if ( smc_probe(dev,smc_portlist[i]) ==0)
- return 0;
-
- /* couldn't find anything */
- return -ENODEV;
-}
-
-
-#ifndef NO_AUTOPROBE
-/*----------------------------------------------------------------------
- . smc_findirq
- .
- . This routine has a simple purpose -- make the SMC chip generate an
- . interrupt, so an auto-detect routine can detect it, and find the IRQ,
- ------------------------------------------------------------------------
-*/
-int __init smc_findirq( int ioaddr )
-{
- int timeout = 20;
- unsigned long cookie;
-
- PRINTK2("CARDNAME:smc_findirq\n");
-
- /* I have to do a STI() here, because this is called from
- a routine that does an CLI during this process, making it
- rather difficult to get interrupts for auto detection */
- local_irq_enable();
-
- cookie = probe_irq_on();
-
- /*
- * What I try to do here is trigger an ALLOC_INT. This is done
- * by allocating a small chunk of memory, which will give an interrupt
- * when done.
- */
-
-
- SMC_SELECT_BANK(2);
- /* enable ALLOCation interrupts ONLY */
- outb( IM_ALLOC_INT, ioaddr + IM_REG );
-
- /*
- . Allocate 512 bytes of memory. Note that the chip was just
- . reset so all the memory is available
- */
- outw( MC_ALLOC | 1, ioaddr + MMU_CMD_REG );
-
- /*
- . Wait until positive that the interrupt has been generated
- */
- while ( timeout ) {
- byte int_status;
-
- int_status = inb( ioaddr + INT_REG );
-
- if ( int_status & IM_ALLOC_INT )
- break; /* got the interrupt */
- timeout--;
- }
-
- /* there is really nothing that I can do here if timeout fails,
- as autoirq_report will return a 0 anyway, which is what I
- want in this case. Plus, the clean up is needed in both
- cases. */
-
- /* DELAY HERE!
- On a fast machine, the status might change before the interrupt
- is given to the processor. This means that the interrupt was
- never detected, and autoirq_report fails to report anything.
- This should fix autoirq_* problems.
- */
- mdelay(10);
-
- /* and disable all interrupts again */
- outb( 0, ioaddr + IM_REG );
-
- /* clear hardware interrupts again, because that's how it
- was when I was called... */
- local_irq_disable();
-
- /* and return what I found */
- return probe_irq_off(cookie);
-}
-#endif
-
-/*----------------------------------------------------------------------
- . Function: smc_probe( int ioaddr )
- .
- . Purpose:
- . Tests to see if a given ioaddr points to an SMC91111 chip.
- . Returns a 0 on success
- .
- . Algorithm:
- . (1) see if the high byte of BANK_SELECT is 0x33
- . (2) compare the ioaddr with the base register's address
- . (3) see if I recognize the chip ID in the appropriate register
- .
- .---------------------------------------------------------------------
- */
-/*---------------------------------------------------------------
- . Here I do typical initialization tasks.
- .
- . o Initialize the structure if needed
- . o print out my vanity message if not done so already
- . o print out what type of hardware is detected
- . o print out the ethernet address
- . o find the IRQ
- . o set up my private data
- . o configure the dev structure with my subroutines
- . o actually GRAB the irq.
- . o GRAB the region
- .-----------------------------------------------------------------*/
-
-static int __init smc_probe(struct rtnet_device *dev, int ioaddr )
-{
- int i, memory, retval;
- static unsigned version_printed = 0;
- unsigned int bank;
-
- const char *version_string;
-
- /*registers */
- word revision_register;
- word base_address_register;
- word memory_info_register;
- /*=> Pramod */
- struct smc_local *lp;
- /*<= Pramod */
-
- PRINTK2("CARDNAME:smc_probe\n");
-
- /* Grab the region so that no one else tries to probe our ioports. */
- if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) return -EBUSY;
-
- /* First, see if the high byte is 0x33 */
- bank = inw( ioaddr + BANK_SELECT );
- if ( (bank & 0xFF00) != 0x3300 ) return -ENODEV;
-
- /* The above MIGHT indicate a device, but I need to write to further test this. */
- outw( 0x0, ioaddr + BANK_SELECT );
- bank = inw( ioaddr + BANK_SELECT );
- if ( (bank & 0xFF00 ) != 0x3300 )
- {
- retval = -ENODEV;
- goto err_out;
- }
-
- /* well, we've already written once, so hopefully another time won't
- hurt. This time, I need to switch the bank register to bank 1,
- so I can access the base address register */
- SMC_SELECT_BANK(1);
- base_address_register = inw( ioaddr + BASE_REG );
- if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) )
- {
- printk("CARDNAME: IOADDR %x doesn't match configuration (%x)."
- "Probably not a SMC chip\n",
- ioaddr, base_address_register >> 3 & 0x3E0 );
- /* well, the base address register didn't match. Must not have
- been a SMC chip after all. */
- retval = -ENODEV;
- goto err_out;
- }
-
- /* check if the revision register is something that I recognize.
- These might need to be added to later, as future revisions
- could be added. */
- SMC_SELECT_BANK(3);
- revision_register = inw( ioaddr + REV_REG );
- if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] )
- {
- /* I don't recognize this chip, so... */
- printk("CARDNAME: IO %x: Unrecognized revision register:"
- " %x, Contact author. \n",
- ioaddr, revision_register );
- retval = -ENODEV;
- goto err_out;
- }
-
- /* at this point I'll assume that the chip is an SMC9xxx.
- It might be prudent to check a listing of MAC addresses
- against the hardware address, or do some other tests. */
-
- if (version_printed++ == 0)
- printk("%s", version);
-
- /* fill in some of the fields */
- dev->base_addr = ioaddr;
-
- /*
- . Get the MAC address ( bank 1, regs 4 - 9 )
- */
- SMC_SELECT_BANK( 1 );
- for ( i = 0; i < 6; i += 2 )
- {
- word address;
-
- address = inw( ioaddr + ADDR0_REG + i );
- dev->dev_addr[ i + 1] = address >> 8;
- dev->dev_addr[ i ] = address & 0xFF;
- }
-
- /* get the memory information */
-
- SMC_SELECT_BANK( 0 );
- memory_info_register = inw( ioaddr + MIR_REG );
- memory = memory_info_register & (word)0x00ff;
- memory *= LAN91C111_MEMORY_MULTIPLIER;
-
- /*
- Now, I want to find out more about the chip. This is sort of
- redundant, but it's cleaner to have it in both, rather than having
- one VERY long probe procedure.
- */
- SMC_SELECT_BANK(3);
- revision_register = inw( ioaddr + REV_REG );
- version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
- if ( !version_string )
- {
- /* I shouldn't get here because this call was done before.... */
- retval = -ENODEV;
- goto err_out;
- }
-
- /* now, reset the chip, and put it into a known state */
- smc_reset( dev );
-
- /*
- . If dev->irq is 0, then the device has to be banged on to see
- . what the IRQ is.
- .
- . This banging doesn't always detect the IRQ, for unknown reasons.
- . a workaround is to reset the chip and try again.
- .
- . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
- . be what is requested on the command line. I don't do that, mostly
- . because the card that I have uses a non-standard method of accessing
- . the IRQs, and because this _should_ work in most configurations.
- .
- . Specifying an IRQ is done with the assumption that the user knows
- . what (s)he is doing. No checking is done!!!!
- .
- */
- if ( dev->irq < 2 ) {
- int trials;
-
- trials = 3;
- while ( trials-- ) {
- dev->irq = smc_findirq( ioaddr );
- if ( dev->irq )
- break;
- /* kick the card and try again */
- smc_reset( dev );
- }
- }
- if (dev->irq == 0 ) {
- printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
- dev->name);
- retval = -ENODEV;
- goto err_out;
- }
-
- if (dev->irq == 2) {
- /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
- * or don't know which one to set.
- */
- dev->irq = 9;
- }
-
- /* now, print out the card info, in a short format.. */
-
- printk("%s: %s(rev:%d) at %#3x IRQ:%d MEMSIZE:%db NOWAIT:%d ",
- dev->name,
- version_string, revision_register & 0xF, ioaddr, dev->irq,
- memory, dev->dma);
- /*
- . Print the Ethernet address
- */
- printk("ADDR: ");
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i] );
- printk("%2.2x \n", dev->dev_addr[5] );
-
-
- /* Initialize the private structure. */
- /*if (dev->priv == NULL) {
- dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
- if (dev->priv == NULL) {
- retval = -ENOMEM;
- goto err_out;
- }
- }*/
- /* set the private data to zero by default */
- memset(dev->priv, 0, sizeof(struct smc_local));
-
- /* Fill in the fields of the device structure with ethernet values. */
-// ether_setup(dev);
-
- rt_stack_connect(dev, &STACK_manager);
-
- /* Grab the IRQ */
- retval = rtdm_irq_request(&((struct smc_local *)dev->priv)->irq_handle,
- dev->irq, &smc_interrupt, 0,
- "rt_smx91111", dev);
- if (retval) {
- printk("%s: unable to get IRQ %d (irqval=%d).\n",
- dev->name, dev->irq, retval);
- //kfree (dev->priv);
- //dev->priv = NULL;
- goto err_out;
- }
-
- dev->open = smc_open;
- dev->stop = smc_close;
- dev->hard_start_xmit = smc_wait_to_send_packet;
- dev->get_stats = smc_query_statistics;
-// dev->tx_timeout = smc_timeout;
-#ifdef HAVE_MULTICAST
-// dev->set_multicast_list = &smc_set_multicast_list;
-#endif
-
- /* => Store the ChipRevision and ChipID, to be used in resolving the Odd-Byte issue in RevB of LAN91C111; Pramod */
- SMC_SELECT_BANK(3);
- revision_register = inw( ioaddr + REV_REG );
- lp = (struct smc_local *)dev->priv;
- lp->ChipID = (revision_register >> 4) & 0xF;
- lp->ChipRev = revision_register & 0xF;
-
- return 0;
-
-err_out:
- release_region (ioaddr, SMC_IO_EXTENT);
- return retval;
-}
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2)
-static void print_packet( byte * buf, int length )
-{
- int i;
- int remainder;
- int lines;
-
- rtdm_printk("Packet of length %d \n", length );
-
-#if SMC_DEBUG > 3
- lines = length / 16;
- remainder = length % 16;
-
- for ( i = 0; i < lines ; i ++ ) {
- int cur;
-
- for ( cur = 0; cur < 8; cur ++ ) {
- byte a, b;
-
- a = *(buf ++ );
- b = *(buf ++ );
- rtdm_printk("%02x%02x ", a, b );
- }
- rtdm_printk("\n");
- }
- for ( i = 0; i < remainder/2 ; i++ ) {
- byte a, b;
-
- a = *(buf ++ );
- b = *(buf ++ );
- rtdm_printk("%02x%02x ", a, b );
- }
- rtdm_printk("\n");
-#endif
-}
-#endif
-
-
-/*
- * Open and Initialize the board
- *
- * Set up everything, reset the card, etc ..
- *
- */
-static int smc_open(struct rtnet_device *dev)
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- int ioaddr = dev->base_addr;
- int i; /* used to set hw ethernet address */
-
- PRINTK2("%s:smc_open\n", dev->name);
-
- /* clear out all the junk that was put here before... */
- memset(dev->priv, 0, (size_t)&((struct smc_local *)0)->irq_handle);
-
- rtnetif_start_queue(dev);
-
- // Setup the default Register Modes
- lp->tcr_cur_mode = TCR_DEFAULT;
- lp->rcr_cur_mode = RCR_DEFAULT;
- lp->rpc_cur_mode = RPC_DEFAULT;
-
-#ifdef DISABLED____CONFIG_SYSCTL
- // Set default parameters (files)
- lp->ctl_swfdup = 0;
- lp->ctl_ephloop = 0;
- lp->ctl_miiop = 0;
- lp->ctl_autoneg = 1;
- lp->ctl_rfduplx = 1;
- lp->ctl_rspeed = 100;
- lp->ctl_afduplx = 1;
- lp->ctl_aspeed = 100;
- lp->ctl_lnkfail = 1;
- lp->ctl_forcol = 0;
- lp->ctl_filtcar = 0;
-#endif /* CONFIG_SYSCTL */
-
- /* reset the hardware */
-
- smc_reset( dev );
- smc_enable( dev );
-
- /* Configure the PHY */
- smc_phy_configure(dev);
-
- smc_set_multicast_list(dev);
-
- /*
- According to Becker, I have to set the hardware address
- at this point, because the (l)user can set it with an
- ioctl. Easily done...
- */
- SMC_SELECT_BANK( 1 );
- for ( i = 0; i < 6; i += 2 ) {
- word address;
-
- address = dev->dev_addr[ i + 1 ] << 8 ;
- address |= dev->dev_addr[ i ];
- outw( address, ioaddr + ADDR0_REG + i );
- }
-
-#ifdef DISABLED____CONFIG_SYSCTL
- smc_sysctl_register(dev);
-#endif /* CONFIG_SYSCTL */
-
- rtnetif_start_queue(dev);
- return 0;
-}
-
-/*-------------------------------------------------------------
- .
- . smc_rcv - receive a packet from the card
- .
- . There is ( at least ) a packet waiting to be read from
- . chip-memory.
- .
- . o Read the status
- . o If an error, record it
- . o otherwise, read in the packet
- --------------------------------------------------------------
-*/
-static inline void smc_rcv(struct rtnet_device *dev)
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- int ioaddr = dev->base_addr;
- int packet_number;
- word status;
- word packet_length;
- nanosecs_abs_t time_stamp = rtdm_clock_read();
- int timeout;
-
- PRINTK3("%s:smc_rcv\n", dev->name);
-
- /* assume bank 2 */
-
- packet_number = inw( ioaddr + RXFIFO_REG );
-
- if ( packet_number & RXFIFO_REMPTY ) {
-
- /* we got called , but nothing was on the FIFO */
- PRINTK("%s: WARNING: smc_rcv with nothing on FIFO. \n",
- dev->name);
- /* don't need to restore anything */
- return;
- }
-
- /* start reading from the start of the packet */
- outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + PTR_REG );
- inw( ioaddr + MMU_CMD_REG ); /* min delay to avoid errors... */
-
- /* First two words are status and packet_length */
- status = inw( ioaddr + DATA_REG );
- packet_length = inw( ioaddr + DATA_REG );
-
- packet_length &= 0x07ff; /* mask off top bits */
-
- PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length );
-
- if ( !(status & RS_ERRORS ) ){
- /* do stuff to make a new packet */
- struct rtskb * skb;
- void * data;
-
- /* set multicast stats */
- if ( status & RS_MULTICAST )
- lp->stats.multicast++;
-
- // Allocate enough memory for entire receive frame, to be safe
- skb = rtnetdev_alloc_rtskb(dev, packet_length);
-
- /* Adjust for having already read the first two words */
- packet_length -= 4;
-
- if ( skb == NULL ) {
- rtdm_printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
- dev->name);
- lp->stats.rx_dropped++;
- goto done;
- }
-
- /*
- ! This should work without alignment, but it could be
- ! in the worse case
- */
- /* TODO: Should I use 32bit alignment here ? */
- rtskb_reserve( skb, 2 ); /* 16 bit alignment */
-
- /* =>
- ODD-BYTE ISSUE : The odd byte problem has been fixed in the LAN91C111 Rev B.
- So we check if the Chip Revision, stored in smsc_local->ChipRev, is = 1.
- If so then we increment the packet length only if RS_ODDFRAME is set.
- If the Chip's revision is equal to 0, then we blindly increment the packet length
- by 1, thus always assuming that the packet is odd length, leaving the higher layer
- to decide the actual length.
- -- Pramod
- <= */
- if ((9 == lp->ChipID) && (1 == lp->ChipRev))
- {
- if (status & RS_ODDFRAME)
- data = rtskb_put( skb, packet_length + 1 );
- else
- data = rtskb_put( skb, packet_length);
-
- }
- else
- {
- // set odd length for bug in LAN91C111, REV A
- // which never sets RS_ODDFRAME
- data = rtskb_put( skb, packet_length + 1 );
- }
-
-#ifdef USE_32_BIT
- PRINTK3(" Reading %d dwords (and %d bytes) \n",
- packet_length >> 2, packet_length & 3 );
- /* QUESTION: Like in the TX routine, do I want
- to send the DWORDs or the bytes first, or some
- mixture. A mixture might improve already slow PIO
- performance */
- insl(ioaddr + DATA_REG , data, packet_length >> 2 );
- /* read the left over bytes */
- insb( ioaddr + DATA_REG, data + (packet_length & 0xFFFFFC),
- packet_length & 0x3 );
-#else
- PRINTK3(" Reading %d words and %d byte(s) \n",
- (packet_length >> 1 ), packet_length & 1 );
- insw(ioaddr + DATA_REG , data, packet_length >> 1);
-
-#endif // USE_32_BIT
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2)
- rtdm_printk("Receiving Packet\n");
- print_packet( data, packet_length );
-#endif
-
- skb->protocol = rt_eth_type_trans(skb, dev );
- skb->time_stamp = time_stamp;
- rtnetif_rx(skb);
- lp->stats.rx_packets++;
- } else {
- /* error ... */
- lp->stats.rx_errors++;
-
- if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++;
- if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
- lp->stats.rx_length_errors++;
- if ( status & RS_BADCRC) lp->stats.rx_crc_errors++;
- }
-
- timeout = MMU_CMD_TIMEOUT;
- while ( inw( ioaddr + MMU_CMD_REG ) & MC_BUSY ) {
- rtdm_task_busy_sleep(1000); // Wait until not busy
- if (--timeout == 0) {
- rtdm_printk("%s: ERROR: timeout while waiting on MMU.\n",
- dev->name);
- break;
- }
- }
-done:
- /* error or good, tell the card to get rid of this packet */
- outw( MC_RELEASE, ioaddr + MMU_CMD_REG );
-
- return;
-}
-
-/*--------------------------------------------------------------------
- .
- . This is the main routine of the driver, to handle the net_device when
- . it needs some attention.
- .
- . So:
- . first, save state of the chipset
- . branch off into routines to handle each case, and acknowledge
- . each to the interrupt register
- . and finally restore state.
- .
- ---------------------------------------------------------------------*/
-static int smc_interrupt(rtdm_irq_t *irq_handle)
-{
- struct rtnet_device *dev = rtdm_irq_get_arg(irq_handle, struct rtnet_device);
- int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
-
- byte status;
- word card_stats;
- byte mask;
- int timeout;
- /* state registers */
- word saved_bank;
- word saved_pointer;
-
- unsigned int old_packet_cnt = lp->stats.rx_packets;
-
-
-
- PRINTK3("%s: SMC interrupt started \n", dev->name);
-
-/* if (dev == NULL) {
- rtdm_printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- dev->name, irq);
- return;
- }*/
-
-/* will Linux let this happen ?? If not, this costs some speed
- if ( dev->interrupt ) {
- printk(KERN_WARNING "%s: interrupt inside interrupt.\n",
- dev->name);
- return;
- }
-
- dev->interrupt = 1; */
-
- saved_bank = inw( ioaddr + BANK_SELECT );
-
- SMC_SELECT_BANK(2);
- saved_pointer = inw( ioaddr + PTR_REG );
-
- /* read the interrupt status register */
- mask = inb( ioaddr + IM_REG );
-
- /* disable all interrupts */
- outb( 0, ioaddr + IM_REG );
-
- /*
- * The packet reception will take some time (up to several hundred us).
- * Re-enable other irqs now so that no critical deadline will be missed.
- */
- hard_local_irq_enable();
-
- /* set a timeout value, so I don't stay here forever */
- timeout = 4;
-
- PRINTK2(KERN_WARNING "%s: MASK IS %x \n", dev->name, mask);
- do {
- /* read the status flag, and mask it */
- status = inb( ioaddr + INT_REG ) & mask;
- if (!status )
- break;
-
- PRINTK3(KERN_WARNING "%s: Handling interrupt status %x \n",
- dev->name, status);
-
- if (status & IM_RCV_INT) {
- /* Got a packet(s). */
- PRINTK2(KERN_WARNING
- "%s: Receive Interrupt\n", dev->name);
- smc_rcv(dev);
- } else if (status & IM_TX_INT ) {
- rtdm_printk(KERN_ERR "%s: TX ERROR!\n", dev->name);
- //smc_tx(dev);
- // Acknowledge the interrupt
- outb(IM_TX_INT, ioaddr + INT_REG );
- } else if (status & IM_TX_EMPTY_INT ) {
- /* update stats */
- SMC_SELECT_BANK( 0 );
- card_stats = inw( ioaddr + COUNTER_REG );
- /* single collisions */
- lp->stats.collisions += card_stats & 0xF;
- card_stats >>= 4;
- /* multiple collisions */
- lp->stats.collisions += card_stats & 0xF;
-
- /* these are for when linux supports these statistics */
- SMC_SELECT_BANK( 2 );
- PRINTK2(KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
- dev->name);
- // Acknowledge the interrupt
- outb( IM_TX_EMPTY_INT, ioaddr + INT_REG );
- mask &= ~IM_TX_EMPTY_INT;
- lp->stats.tx_packets += lp->packets_waiting;
- lp->packets_waiting = 0;
-
- } else if (status & IM_ALLOC_INT ) {
- PRINTK2(KERN_DEBUG "%s: Allocation interrupt \n",
- dev->name);
- /* clear this interrupt so it doesn't happen again */
- mask &= ~IM_ALLOC_INT;
-
- } else if (status & IM_RX_OVRN_INT ) {
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- // Acknowledge the interrupt
- outb( IM_RX_OVRN_INT, ioaddr + INT_REG );
- } else if (status & IM_EPH_INT ) {
- PRINTK("%s: UNSUPPORTED: EPH INTERRUPT \n",
- dev->name);
- } else if (status & IM_MDINT ) {
- //smc_phy_interrupt(dev);
- PRINTK("%s: UNSUPPORTED: MD INTERRUPT \n",
- dev->name);
- // Acknowledge the interrupt
- outb(IM_MDINT, ioaddr + INT_REG );
- } else if (status & IM_ERCV_INT ) {
- PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n",
- dev->name);
- // Acknowledge the interrupt
- outb( IM_ERCV_INT, ioaddr + INT_REG );
- }
- } while ( timeout -- );
-
-
- /* restore register states */
-
- SMC_SELECT_BANK( 2 );
-
- outb( mask, ioaddr + IM_REG );
-
- PRINTK3( KERN_WARNING "%s: MASK is now %x \n", dev->name, mask);
- outw( saved_pointer, ioaddr + PTR_REG );
-
- SMC_SELECT_BANK( saved_bank );
-
- if (old_packet_cnt != lp->stats.rx_packets)
- rt_mark_stack_mgr(dev);
-
- hard_local_irq_disable();
-
- //dev->interrupt = 0;
- PRINTK3("%s: Interrupt done\n", dev->name);
- return RTDM_IRQ_HANDLED;
-}
-
-
-/*----------------------------------------------------
- . smc_close
- .
- . this makes the board clean up everything that it can
- . and not talk to the outside world. Caused by
- . an 'ifconfig ethX down'
- .
- -----------------------------------------------------*/
-static int smc_close(struct rtnet_device *dev)
-{
- rtnetif_stop_queue(dev);
- //dev->start = 0;
-
- PRINTK2("%s:smc_close\n", dev->name);
-
-#ifdef DISABLED____CONFIG_SYSCTL
- smc_sysctl_unregister(dev);
-#endif /* CONFIG_SYSCTL */
-
- /* clear everything */
- smc_shutdown( dev->base_addr );
-
- /* Update the statistics here. */
-
- return 0;
-}
-
-/*------------------------------------------------------------
- . Get the current statistics.
- . This may be called with the card open or closed.
- .-------------------------------------------------------------*/
-static struct net_device_stats* smc_query_statistics(struct rtnet_device *rtdev)
-{
- struct smc_local *lp = (struct smc_local *)rtdev->priv;
-
- PRINTK2("%s:smc_query_statistics\n", rtdev->name);
-
- return &lp->stats;
-}
-
-/*-----------------------------------------------------------
- . smc_set_multicast_list
- .
- . This routine will, depending on the values passed to it,
- . either make it accept multicast packets, go into
- . promiscuous mode ( for TCPDUMP and cousins ) or accept
- . a select set of multicast packets
-*/
-static void smc_set_multicast_list(struct rtnet_device *dev)
-{
- short ioaddr = dev->base_addr;
-
- PRINTK2("%s:smc_set_multicast_list\n", dev->name);
-
- SMC_SELECT_BANK(0);
- if ( dev->flags & IFF_PROMISC )
- {
- PRINTK2("%s:smc_set_multicast_list:RCR_PRMS\n", dev->name);
- outw( inw(ioaddr + RCR_REG ) | RCR_PRMS, ioaddr + RCR_REG );
- }
-
-/* BUG? I never disable promiscuous mode if multicasting was turned on.
- Now, I turn off promiscuous mode, but I don't do anything to multicasting
- when promiscuous mode is turned on.
-*/
-
- /* Here, I am setting this to accept all multicast packets.
- I don't need to zero the multicast table, because the flag is
- checked before the table is
- */
- else if (dev->flags & IFF_ALLMULTI)
- {
- outw( inw(ioaddr + RCR_REG ) | RCR_ALMUL, ioaddr + RCR_REG );
- PRINTK2("%s:smc_set_multicast_list:RCR_ALMUL\n", dev->name);
- }
-
- else {
- PRINTK2("%s:smc_set_multicast_list:~(RCR_PRMS|RCR_ALMUL)\n",
- dev->name);
- outw( inw( ioaddr + RCR_REG ) & ~(RCR_PRMS | RCR_ALMUL),
- ioaddr + RCR_REG );
-
- /*
- since I'm disabling all multicast entirely, I need to
- clear the multicast list
- */
- SMC_SELECT_BANK( 3 );
- outw( 0, ioaddr + MCAST_REG1 );
- outw( 0, ioaddr + MCAST_REG2 );
- outw( 0, ioaddr + MCAST_REG3 );
- outw( 0, ioaddr + MCAST_REG4 );
- }
-}
-
-#ifdef MODULE
-
-static struct rtnet_device *devSMC91111;
-int io = 0;
-int irq = 0;
-int nowait = 0;
-
-module_param(io, int, 0444);
-module_param(irq, int, 0444);
-module_param(nowait, int, 0444);
-
-/*------------------------------------------------------------
- . Module initialization function
- .-------------------------------------------------------------*/
-int __init init_module(void)
-{
- int result;
-
- PRINTK2("CARDNAME:init_module\n");
- if (io == 0)
- printk(KERN_WARNING
- CARDNAME": You shouldn't use auto-probing with insmod!\n" );
-
- devSMC91111 = rt_alloc_etherdev(sizeof(struct smc_local), 4 * 2 + 1);
- if (devSMC91111 == NULL) {
- printk (KERN_ERR "init_ethernet failed\n");
- return -ENODEV;
- }
- rtdev_alloc_name(devSMC91111, "rteth%d");
- rt_rtdev_connect(devSMC91111, &RTDEV_manager);
- devSMC91111->vers = RTDEV_VERS_2_0;
-
- /* copy the parameters from insmod into the device structure */
- devSMC91111->base_addr = io;
- devSMC91111->irq = irq;
- devSMC91111->dma = nowait; // Use DMA field for nowait
- if ((result = smc_init(devSMC91111)) != 0)
- return result;
-
- if ((result = rt_register_rtnetdev(devSMC91111)) != 0) {
- rt_rtdev_disconnect(devSMC91111);
- release_region(devSMC91111->base_addr, SMC_IO_EXTENT);
-
- rtdm_irq_free(&((struct smc_local *)devSMC91111)->irq_handle);
-
- rtdev_free(devSMC91111);
-
- return result;
- }
-
- return 0;
-}
-
-/*------------------------------------------------------------
- . Cleanup when module is removed with rmmod
- .-------------------------------------------------------------*/
-void __exit cleanup_module(void)
-{
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- rt_unregister_rtnetdev(devSMC91111);
- rt_rtdev_disconnect(devSMC91111);
-
- release_region(devSMC91111->base_addr, SMC_IO_EXTENT);
-
- if (devSMC91111->priv) {
- rtdm_irq_free(&((struct smc_local *)devSMC91111->priv)->irq_handle);
- }
-
- rtdev_free(devSMC91111);
-}
-
-#endif /* MODULE */
-
-
-#ifdef DISABLED____CONFIG_SYSCTL
-
-
-/*------------------------------------------------------------
- . Modify a bit in the LAN91C111 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 LAN91C111 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 LAN91C111 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 LAN91C111 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 LAN91C111 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, loff_t *ppos)
-{
- struct rtnet_device *dev = (struct rtnet_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 )
- * LAN91C111_MEMORY_MULTIPLIER;
- break;
-
-
- case CTL_SMC_TOTMEM:
- *valp = ( smc_get_reg(0, ioaddr, MIR_REG) & (word)0x00ff )
- * LAN91C111_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, ppos)) != 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
- smc_modify_reg(0, ioaddr, RPC_REG, val);
- break;
-
- case CTL_SMC_REG_CFGR: // Configuration
- smc_modify_reg(1, ioaddr, CONFIG_REG, val);
- break;
-
- case CTL_SMC_REG_BAR: // Base Address
- smc_modify_reg(1, ioaddr, BASE_REG, val);
- break;
-
- case CTL_SMC_REG_IAR0: // Individual Address
- smc_modify_reg(1, ioaddr, ADDR0_REG, val);
- break;
-
- case CTL_SMC_REG_IAR1: // Individual Address
- smc_modify_reg(1, ioaddr, ADDR1_REG, val);
- break;
-
- case CTL_SMC_REG_IAR2: // Individual Address
- smc_modify_reg(1, ioaddr, ADDR2_REG, val);
- break;
-
- case CTL_SMC_REG_GPR: // General Purpose
- smc_modify_reg(1, ioaddr, GP_REG, val);
- break;
-
- case CTL_SMC_REG_CTLR: // Control
- smc_modify_reg(1, ioaddr, CTL_REG, val);
- break;
-
- case CTL_SMC_REG_MCR: // MMU Command
- smc_modify_reg(2, ioaddr, MMU_CMD_REG, val);
- break;
-
- case CTL_SMC_REG_PNR: // Packet Number
- smc_modify_reg(2, ioaddr, PN_REG, val);
- break;
-
- case CTL_SMC_REG_FPR: // Allocation Result/FIFO Ports
- smc_modify_reg(2, ioaddr, RXFIFO_REG, val);
- break;
-
- case CTL_SMC_REG_PTR: // Pointer
- smc_modify_reg(2, ioaddr, PTR_REG, val);
- break;
-
- case CTL_SMC_REG_DR: // Data
- smc_modify_reg(2, ioaddr, DATA_REG, val);
- break;
-
- case CTL_SMC_REG_ISR: // Interrupt Status/Mask
- smc_modify_reg(2, ioaddr, INT_REG, val);
- break;
-
- case CTL_SMC_REG_MTR1: // Multicast Table Entry 1
- smc_modify_reg(3, ioaddr, MCAST_REG1, val);
- break;
-
- case CTL_SMC_REG_MTR2: // Multicast Table Entry 2
- smc_modify_reg(3, ioaddr, MCAST_REG2, val);
- break;
-
- case CTL_SMC_REG_MTR3: // Multicast Table Entry 3
- smc_modify_reg(3, ioaddr, MCAST_REG3, val);
- break;
-
- case CTL_SMC_REG_MTR4: // Multicast Table Entry 4
- smc_modify_reg(3, ioaddr, MCAST_REG4, val);
- break;
-
- case CTL_SMC_REG_MIIR: // Management Interface
- smc_modify_reg(3, ioaddr, MII_REG, val);
- break;
-
- case CTL_SMC_REG_REVR: // Revision
- smc_modify_reg(3, ioaddr, REV_REG, val);
- break;
-
- case CTL_SMC_REG_ERCVR: // Early RCV
- smc_modify_reg(3, ioaddr, ERCV_REG, val);
- break;
-
- case CTL_SMC_REG_EXTR: // External
- smc_modify_reg(7, ioaddr, EXT_REG, val);
- break;
-
- case CTL_SMC_PHY_CTRL:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_CNTL_REG, val);
- break;
-
- case CTL_SMC_PHY_STAT:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_STAT_REG, val);
- break;
-
- case CTL_SMC_PHY_ID1:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_ID1_REG, val);
- break;
-
- case CTL_SMC_PHY_ID2:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_ID2_REG, val);
- break;
-
- case CTL_SMC_PHY_ADC:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_AD_REG, val);
- break;
-
- case CTL_SMC_PHY_REMC:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_RMT_REG, val);
- break;
-
- case CTL_SMC_PHY_CFG1:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_CFG1_REG, val);
- break;
-
- case CTL_SMC_PHY_CFG2:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_CFG2_REG, val);
- break;
-
- case CTL_SMC_PHY_INT:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_INT_REG, val);
- break;
-
- case CTL_SMC_PHY_MASK:
- smc_write_phy_register(ioaddr, lp->phyaddr,
- PHY_MASK_REG, val);
- break;
-
-#endif // SMC_DEBUG
-
- default:
- // Just ignore unsupported parameters
- break;
- } // end switch
-
- } // end if
-
- return ret;
-}
-
-/*------------------------------------------------------------
- . Sysctl registration function for all parameters (files)
- .-------------------------------------------------------------*/
-static void smc_sysctl_register(struct rtnet_device *dev)
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- static int ctl_name = CTL_SMC;
- ctl_table* ct;
- int i;
-
- // Make sure the ctl_tables start out as all zeros
- memset(lp->root_table, 0, sizeof lp->root_table);
- memset(lp->eth_table, 0, sizeof lp->eth_table);
- memset(lp->param_table, 0, sizeof lp->param_table);
-
- // Initialize the root table
- ct = lp->root_table;
- ct->ctl_name = CTL_DEV;
- ct->procname = "dev";
- ct->maxlen = 0;
- ct->mode = 0555;
- ct->child = lp->eth_table;
- // remaining fields are zero
-
- // Initialize the ethX table (this device's table)
- ct = lp->eth_table;
- ct->ctl_name = ctl_name++; // Must be unique
- ct->procname = dev->name;
- ct->maxlen = 0;
- ct->mode = 0555;
- ct->child = lp->param_table;
- // remaining fields are zero
-
- // Initialize the parameter (files) table
- // Make sure the last entry remains null
- ct = lp->param_table;
- for (i = 0; i < (CTL_SMC_LAST_ENTRY-1); ++i)
- {
- // Initialize fields common to all table entries
- ct[i].proc_handler = smc_sysctl_handler;
- ct[i].extra1 = (void*)dev; // Save our device pointer
- ct[i].extra2 = (void*)lp; // Save our smc_local data pointer
- }
-
- // INFO - this is our only string parameter
- i = 0;
- ct[i].proc_handler = proc_dostring; // use default handler
- ct[i].ctl_name = CTL_SMC_INFO;
- ct[i].procname = "info";
- ct[i].data = (void*)smc_info_string;
- ct[i].maxlen = sizeof smc_info_string;
- ct[i].mode = 0444; // Read only
-
- // SWVER
- ++i;
- ct[i].proc_handler = proc_dostring; // use default handler
- ct[i].ctl_name = CTL_SMC_SWVER;
- ct[i].procname = "swver";
- ct[i].data = (void*)version;
- ct[i].maxlen = sizeof version;
- ct[i].mode = 0444; // Read only
-
- // SWFDUP
- ++i;
- ct[i].ctl_name = CTL_SMC_SWFDUP;
- ct[i].procname = "swfdup";
- ct[i].data = (void*)&(lp->ctl_swfdup);
- ct[i].maxlen = sizeof lp->ctl_swfdup;
- ct[i].mode = 0644; // Read by all, write by root
-
- // EPHLOOP
- ++i;
- ct[i].ctl_name = CTL_SMC_EPHLOOP;
- ct[i].procname = "ephloop";
- ct[i].data = (void*)&(lp->ctl_ephloop);
- ct[i].maxlen = sizeof lp->ctl_ephloop;
- ct[i].mode = 0644; // Read by all, write by root
-
- // MIIOP
- ++i;
- ct[i].ctl_name = CTL_SMC_MIIOP;
- ct[i].procname = "miiop";
- ct[i].data = (void*)&(lp->ctl_miiop);
- ct[i].maxlen = sizeof lp->ctl_miiop;
- ct[i].mode = 0644; // Read by all, write by root
-
- // AUTONEG
- ++i;
- ct[i].ctl_name = CTL_SMC_AUTONEG;
- ct[i].procname = "autoneg";
- ct[i].data = (void*)&(lp->ctl_autoneg);
- ct[i].maxlen = sizeof lp->ctl_autoneg;
- ct[i].mode = 0644; // Read by all, write by root
-
- // RFDUPLX
- ++i;
- ct[i].ctl_name = CTL_SMC_RFDUPLX;
- ct[i].procname = "rfduplx";
- ct[i].data = (void*)&(lp->ctl_rfduplx);
- ct[i].maxlen = sizeof lp->ctl_rfduplx;
- ct[i].mode = 0644; // Read by all, write by root
-
- // RSPEED
- ++i;
- ct[i].ctl_name = CTL_SMC_RSPEED;
- ct[i].procname = "rspeed";
- ct[i].data = (void*)&(lp->ctl_rspeed);
- ct[i].maxlen = sizeof lp->ctl_rspeed;
- ct[i].mode = 0644; // Read by all, write by root
-
- // AFDUPLX
- ++i;
- ct[i].ctl_name = CTL_SMC_AFDUPLX;
- ct[i].procname = "afduplx";
- ct[i].data = (void*)&(lp->ctl_afduplx);
- ct[i].maxlen = sizeof lp->ctl_afduplx;
- ct[i].mode = 0444; // Read only
-
- // ASPEED
- ++i;
- ct[i].ctl_name = CTL_SMC_ASPEED;
- ct[i].procname = "aspeed";
- ct[i].data = (void*)&(lp->ctl_aspeed);
- ct[i].maxlen = sizeof lp->ctl_aspeed;
- ct[i].mode = 0444; // Read only
-
- // LNKFAIL
- ++i;
- ct[i].ctl_name = CTL_SMC_LNKFAIL;
- ct[i].procname = "lnkfail";
- ct[i].data = (void*)&(lp->ctl_lnkfail);
- ct[i].maxlen = sizeof lp->ctl_lnkfail;
- ct[i].mode = 0444; // Read only
-
- // FORCOL
- ++i;
- ct[i].ctl_name = CTL_SMC_FORCOL;
- ct[i].procname = "forcol";
- ct[i].data = (void*)&(lp->ctl_forcol);
- ct[i].maxlen = sizeof lp->ctl_forcol;
- ct[i].mode = 0644; // Read by all, write by root
-
- // FILTCAR
- ++i;
- ct[i].ctl_name = CTL_SMC_FILTCAR;
- ct[i].procname = "filtcar";
- ct[i].data = (void*)&(lp->ctl_filtcar);
- ct[i].maxlen = sizeof lp->ctl_filtcar;
- ct[i].mode = 0644; // Read by all, write by root
-
- // FREEMEM
- ++i;
- ct[i].ctl_name = CTL_SMC_FREEMEM;
- ct[i].procname = "freemem";
- ct[i].data = (void*)&(lp->ctl_freemem);
- ct[i].maxlen = sizeof lp->ctl_freemem;
- ct[i].mode = 0444; // Read only
-
- // TOTMEM
- ++i;
- ct[i].ctl_name = CTL_SMC_TOTMEM;
- ct[i].procname = "totmem";
- ct[i].data = (void*)&(lp->ctl_totmem);
- ct[i].maxlen = sizeof lp->ctl_totmem;
- ct[i].mode = 0444; // Read only
-
- // LEDA
- ++i;
- ct[i].ctl_name = CTL_SMC_LEDA;
- ct[i].procname = "leda";
- ct[i].data = (void*)&(lp->ctl_leda);
- ct[i].maxlen = sizeof lp->ctl_leda;
- ct[i].mode = 0644; // Read by all, write by root
-
- // LEDB
- ++i;
- ct[i].ctl_name = CTL_SMC_LEDB;
- ct[i].procname = "ledb";
- ct[i].data = (void*)&(lp->ctl_ledb);
- ct[i].maxlen = sizeof lp->ctl_ledb;
- ct[i].mode = 0644; // Read by all, write by root
-
- // CHIPREV
- ++i;
- ct[i].ctl_name = CTL_SMC_CHIPREV;
- ct[i].procname = "chiprev";
- ct[i].data = (void*)&(lp->ctl_chiprev);
- ct[i].maxlen = sizeof lp->ctl_chiprev;
- ct[i].mode = 0444; // Read only
-
-#ifdef SMC_DEBUG
- // REG_BSR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_BSR;
- ct[i].procname = "reg_bsr";
- ct[i].data = (void*)&(lp->ctl_reg_bsr);
- ct[i].maxlen = sizeof lp->ctl_reg_bsr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_TCR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_TCR;
- ct[i].procname = "reg_tcr";
- ct[i].data = (void*)&(lp->ctl_reg_tcr);
- ct[i].maxlen = sizeof lp->ctl_reg_tcr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_ESR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_ESR;
- ct[i].procname = "reg_esr";
- ct[i].data = (void*)&(lp->ctl_reg_esr);
- ct[i].maxlen = sizeof lp->ctl_reg_esr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_RCR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_RCR;
- ct[i].procname = "reg_rcr";
- ct[i].data = (void*)&(lp->ctl_reg_rcr);
- ct[i].maxlen = sizeof lp->ctl_reg_rcr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_CTRR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_CTRR;
- ct[i].procname = "reg_ctrr";
- ct[i].data = (void*)&(lp->ctl_reg_ctrr);
- ct[i].maxlen = sizeof lp->ctl_reg_ctrr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MIR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MIR;
- ct[i].procname = "reg_mir";
- ct[i].data = (void*)&(lp->ctl_reg_mir);
- ct[i].maxlen = sizeof lp->ctl_reg_mir;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_RPCR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_RPCR;
- ct[i].procname = "reg_rpcr";
- ct[i].data = (void*)&(lp->ctl_reg_rpcr);
- ct[i].maxlen = sizeof lp->ctl_reg_rpcr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_CFGR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_CFGR;
- ct[i].procname = "reg_cfgr";
- ct[i].data = (void*)&(lp->ctl_reg_cfgr);
- ct[i].maxlen = sizeof lp->ctl_reg_cfgr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_BAR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_BAR;
- ct[i].procname = "reg_bar";
- ct[i].data = (void*)&(lp->ctl_reg_bar);
- ct[i].maxlen = sizeof lp->ctl_reg_bar;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_IAR0
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_IAR0;
- ct[i].procname = "reg_iar0";
- ct[i].data = (void*)&(lp->ctl_reg_iar0);
- ct[i].maxlen = sizeof lp->ctl_reg_iar0;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_IAR1
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_IAR1;
- ct[i].procname = "reg_iar1";
- ct[i].data = (void*)&(lp->ctl_reg_iar1);
- ct[i].maxlen = sizeof lp->ctl_reg_iar1;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_IAR2
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_IAR2;
- ct[i].procname = "reg_iar2";
- ct[i].data = (void*)&(lp->ctl_reg_iar2);
- ct[i].maxlen = sizeof lp->ctl_reg_iar2;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_GPR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_GPR;
- ct[i].procname = "reg_gpr";
- ct[i].data = (void*)&(lp->ctl_reg_gpr);
- ct[i].maxlen = sizeof lp->ctl_reg_gpr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_CTLR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_CTLR;
- ct[i].procname = "reg_ctlr";
- ct[i].data = (void*)&(lp->ctl_reg_ctlr);
- ct[i].maxlen = sizeof lp->ctl_reg_ctlr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MCR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MCR;
- ct[i].procname = "reg_mcr";
- ct[i].data = (void*)&(lp->ctl_reg_mcr);
- ct[i].maxlen = sizeof lp->ctl_reg_mcr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_PNR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_PNR;
- ct[i].procname = "reg_pnr";
- ct[i].data = (void*)&(lp->ctl_reg_pnr);
- ct[i].maxlen = sizeof lp->ctl_reg_pnr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_FPR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_FPR;
- ct[i].procname = "reg_fpr";
- ct[i].data = (void*)&(lp->ctl_reg_fpr);
- ct[i].maxlen = sizeof lp->ctl_reg_fpr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_PTR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_PTR;
- ct[i].procname = "reg_ptr";
- ct[i].data = (void*)&(lp->ctl_reg_ptr);
- ct[i].maxlen = sizeof lp->ctl_reg_ptr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_DR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_DR;
- ct[i].procname = "reg_dr";
- ct[i].data = (void*)&(lp->ctl_reg_dr);
- ct[i].maxlen = sizeof lp->ctl_reg_dr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_ISR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_ISR;
- ct[i].procname = "reg_isr";
- ct[i].data = (void*)&(lp->ctl_reg_isr);
- ct[i].maxlen = sizeof lp->ctl_reg_isr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MTR1
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MTR1;
- ct[i].procname = "reg_mtr1";
- ct[i].data = (void*)&(lp->ctl_reg_mtr1);
- ct[i].maxlen = sizeof lp->ctl_reg_mtr1;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MTR2
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MTR2;
- ct[i].procname = "reg_mtr2";
- ct[i].data = (void*)&(lp->ctl_reg_mtr2);
- ct[i].maxlen = sizeof lp->ctl_reg_mtr2;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MTR3
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MTR3;
- ct[i].procname = "reg_mtr3";
- ct[i].data = (void*)&(lp->ctl_reg_mtr3);
- ct[i].maxlen = sizeof lp->ctl_reg_mtr3;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MTR4
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MTR4;
- ct[i].procname = "reg_mtr4";
- ct[i].data = (void*)&(lp->ctl_reg_mtr4);
- ct[i].maxlen = sizeof lp->ctl_reg_mtr4;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_MIIR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_MIIR;
- ct[i].procname = "reg_miir";
- ct[i].data = (void*)&(lp->ctl_reg_miir);
- ct[i].maxlen = sizeof lp->ctl_reg_miir;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_REVR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_REVR;
- ct[i].procname = "reg_revr";
- ct[i].data = (void*)&(lp->ctl_reg_revr);
- ct[i].maxlen = sizeof lp->ctl_reg_revr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_ERCVR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_ERCVR;
- ct[i].procname = "reg_ercvr";
- ct[i].data = (void*)&(lp->ctl_reg_ercvr);
- ct[i].maxlen = sizeof lp->ctl_reg_ercvr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // REG_EXTR
- ++i;
- ct[i].ctl_name = CTL_SMC_REG_EXTR;
- ct[i].procname = "reg_extr";
- ct[i].data = (void*)&(lp->ctl_reg_extr);
- ct[i].maxlen = sizeof lp->ctl_reg_extr;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Control
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_CTRL;
- ct[i].procname = "phy_ctrl";
- ct[i].data = (void*)&(lp->ctl_phy_ctrl);
- ct[i].maxlen = sizeof lp->ctl_phy_ctrl;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Status
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_STAT;
- ct[i].procname = "phy_stat";
- ct[i].data = (void*)&(lp->ctl_phy_stat);
- ct[i].maxlen = sizeof lp->ctl_phy_stat;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY ID1
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_ID1;
- ct[i].procname = "phy_id1";
- ct[i].data = (void*)&(lp->ctl_phy_id1);
- ct[i].maxlen = sizeof lp->ctl_phy_id1;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY ID2
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_ID2;
- ct[i].procname = "phy_id2";
- ct[i].data = (void*)&(lp->ctl_phy_id2);
- ct[i].maxlen = sizeof lp->ctl_phy_id2;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Advertise Capabilities
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_ADC;
- ct[i].procname = "phy_adc";
- ct[i].data = (void*)&(lp->ctl_phy_adc);
- ct[i].maxlen = sizeof lp->ctl_phy_adc;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Remote Capabilities
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_REMC;
- ct[i].procname = "phy_remc";
- ct[i].data = (void*)&(lp->ctl_phy_remc);
- ct[i].maxlen = sizeof lp->ctl_phy_remc;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Configuration 1
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_CFG1;
- ct[i].procname = "phy_cfg1";
- ct[i].data = (void*)&(lp->ctl_phy_cfg1);
- ct[i].maxlen = sizeof lp->ctl_phy_cfg1;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Configuration 2
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_CFG2;
- ct[i].procname = "phy_cfg2";
- ct[i].data = (void*)&(lp->ctl_phy_cfg2);
- ct[i].maxlen = sizeof lp->ctl_phy_cfg2;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Interrupt/Status Output
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_INT;
- ct[i].procname = "phy_int";
- ct[i].data = (void*)&(lp->ctl_phy_int);
- ct[i].maxlen = sizeof lp->ctl_phy_int;
- ct[i].mode = 0644; // Read by all, write by root
-
- // PHY Interrupt/Status Mask
- ++i;
- ct[i].ctl_name = CTL_SMC_PHY_MASK;
- ct[i].procname = "phy_mask";
- ct[i].data = (void*)&(lp->ctl_phy_mask);
- ct[i].maxlen = sizeof lp->ctl_phy_mask;
- ct[i].mode = 0644; // Read by all, write by root
-
-#endif // SMC_DEBUG
-
- // Register /proc/sys/dev/ethX
- lp->sysctl_header = register_sysctl_table(lp->root_table, 1);
-}
-
-
-/*------------------------------------------------------------
- . Sysctl unregistration when driver is closed
- .-------------------------------------------------------------*/
-static void smc_sysctl_unregister(struct rtnet_device *dev)
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
-
- unregister_sysctl_table(lp->sysctl_header);
-}
-
-#endif /* endif CONFIG_SYSCTL */
-
-
-//---PHY CONTROL AND CONFIGURATION-----------------------------------------
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2 )
-
-/*------------------------------------------------------------
- . Debugging function for viewing MII Management serial bitstream
- .-------------------------------------------------------------*/
-static void smc_dump_mii_stream(byte* bits, int size)
-{
- int i;
-
- printk("BIT#:");
- for (i = 0; i < size; ++i)
- {
- printk("%d", i%10);
- }
-
- printk("\nMDOE:");
- for (i = 0; i < size; ++i)
- {
- if (bits[i] & MII_MDOE)
- printk("1");
- else
- printk("0");
- }
-
- printk("\nMDO :");
- for (i = 0; i < size; ++i)
- {
- if (bits[i] & MII_MDO)
- printk("1");
- else
- printk("0");
- }
-
- printk("\nMDI :");
- for (i = 0; i < size; ++i)
- {
- if (bits[i] & MII_MDI)
- printk("1");
- else
- printk("0");
- }
-
- printk("\n");
-}
-#endif
-
-/*------------------------------------------------------------
- . Reads a register from the MII Management serial interface
- .-------------------------------------------------------------*/
-static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg)
-{
- int oldBank;
- int i;
- byte mask;
- word mii_reg;
- byte bits[64];
- int clk_idx = 0;
- int input_idx;
- word phydata;
-
- // 32 consecutive ones on MDO to establish sync
- for (i = 0; i < 32; ++i)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
-
- // Start code <01>
- bits[clk_idx++] = MII_MDOE;
- bits[clk_idx++] = MII_MDOE | MII_MDO;
-
- // Read command <10>
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- bits[clk_idx++] = MII_MDOE;
-
- // Output the PHY address, msb first
- mask = (byte)0x10;
- for (i = 0; i < 5; ++i)
- {
- if (phyaddr & mask)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- else
- bits[clk_idx++] = MII_MDOE;
-
- // Shift to next lowest bit
- mask >>= 1;
- }
-
- // Output the phy register number, msb first
- mask = (byte)0x10;
- for (i = 0; i < 5; ++i)
- {
- if (phyreg & mask)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- else
- bits[clk_idx++] = MII_MDOE;
-
- // Shift to next lowest bit
- mask >>= 1;
- }
-
- // Tristate and turnaround (2 bit times)
- bits[clk_idx++] = 0;
- //bits[clk_idx++] = 0;
-
- // Input starts at this bit time
- input_idx = clk_idx;
-
- // Will input 16 bits
- for (i = 0; i < 16; ++i)
- bits[clk_idx++] = 0;
-
- // Final clock bit
- bits[clk_idx++] = 0;
-
- // Save the current bank
- oldBank = inw( ioaddr+BANK_SELECT );
-
- // Select bank 3
- SMC_SELECT_BANK( 3 );
-
- // Get the current MII register value
- mii_reg = inw( ioaddr+MII_REG );
-
- // Turn off all MII Interface bits
- mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-
- // Clock all 64 cycles
- for (i = 0; i < sizeof bits; ++i)
- {
- // Clock Low - output data
- outw( mii_reg | bits[i], ioaddr+MII_REG );
- udelay(50);
-
-
- // Clock Hi - input data
- outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
- udelay(50);
- bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
- }
-
- // Return to idle state
- // Set clock to low, data to low, and output tristated
- outw( mii_reg, ioaddr+MII_REG );
- udelay(50);
-
- // Restore original bank select
- SMC_SELECT_BANK( oldBank );
-
- // Recover input data
- phydata = 0;
- for (i = 0; i < 16; ++i)
- {
- phydata <<= 1;
-
- if (bits[input_idx++] & MII_MDI)
- phydata |= 0x0001;
- }
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2 )
- printk("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
- phyaddr, phyreg, phydata);
- smc_dump_mii_stream(bits, sizeof bits);
-#endif
-
- return(phydata);
-}
-
-
-/*------------------------------------------------------------
- . Writes a register to the MII Management serial interface
- .-------------------------------------------------------------*/
-static void smc_write_phy_register(int ioaddr,
- byte phyaddr, byte phyreg, word phydata)
-{
- int oldBank;
- int i;
- word mask;
- word mii_reg;
- byte bits[65];
- int clk_idx = 0;
-
- // 32 consecutive ones on MDO to establish sync
- for (i = 0; i < 32; ++i)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
-
- // Start code <01>
- bits[clk_idx++] = MII_MDOE;
- bits[clk_idx++] = MII_MDOE | MII_MDO;
-
- // Write command <01>
- bits[clk_idx++] = MII_MDOE;
- bits[clk_idx++] = MII_MDOE | MII_MDO;
-
- // Output the PHY address, msb first
- mask = (byte)0x10;
- for (i = 0; i < 5; ++i)
- {
- if (phyaddr & mask)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- else
- bits[clk_idx++] = MII_MDOE;
-
- // Shift to next lowest bit
- mask >>= 1;
- }
-
- // Output the phy register number, msb first
- mask = (byte)0x10;
- for (i = 0; i < 5; ++i)
- {
- if (phyreg & mask)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- else
- bits[clk_idx++] = MII_MDOE;
-
- // Shift to next lowest bit
- mask >>= 1;
- }
-
- // Tristate and turnaround (2 bit times)
- bits[clk_idx++] = 0;
- bits[clk_idx++] = 0;
-
- // Write out 16 bits of data, msb first
- mask = 0x8000;
- for (i = 0; i < 16; ++i)
- {
- if (phydata & mask)
- bits[clk_idx++] = MII_MDOE | MII_MDO;
- else
- bits[clk_idx++] = MII_MDOE;
-
- // Shift to next lowest bit
- mask >>= 1;
- }
-
- // Final clock bit (tristate)
- bits[clk_idx++] = 0;
-
- // Save the current bank
- oldBank = inw( ioaddr+BANK_SELECT );
-
- // Select bank 3
- SMC_SELECT_BANK( 3 );
-
- // Get the current MII register value
- mii_reg = inw( ioaddr+MII_REG );
-
- // Turn off all MII Interface bits
- mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-
- // Clock all cycles
- for (i = 0; i < sizeof bits; ++i)
- {
- // Clock Low - output data
- outw( mii_reg | bits[i], ioaddr+MII_REG );
- udelay(50);
-
-
- // Clock Hi - input data
- outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
- udelay(50);
- bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
- }
-
- // Return to idle state
- // Set clock to low, data to low, and output tristated
- outw( mii_reg, ioaddr+MII_REG );
- udelay(50);
-
- // Restore original bank select
- SMC_SELECT_BANK( oldBank );
-
-#if defined(SMC_DEBUG) && (SMC_DEBUG > 2 )
- printk("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
- phyaddr, phyreg, phydata);
- smc_dump_mii_stream(bits, sizeof bits);
-#endif
-}
-
-
-/*------------------------------------------------------------
- . Finds and reports the PHY address
- .-------------------------------------------------------------*/
-static int smc_detect_phy(struct rtnet_device* dev)
-{
- struct smc_local *lp = (struct smc_local *)dev->priv;
- int ioaddr = dev->base_addr;
- word phy_id1;
- word phy_id2;
- int phyaddr;
- int found = 0;
-
- PRINTK3("%s:smc_detect_phy()\n", dev->name);
-
- // Scan all 32 PHY addresses if necessary
- for (phyaddr = 0; phyaddr < 32; ++phyaddr)
- {
- // Read the PHY identifiers
- phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
- phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
-
- PRINTK3("%s: phy_id1=%x, phy_id2=%x\n",
- dev->name, phy_id1, phy_id2);
-
- // Make sure it is a valid identifier
- if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
- (phy_id1 > 0x0000) && (phy_id1 < 0xffff))
- {
- if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000))
- {
- // Save the PHY's address
- lp->phyaddr = phyaddr;
- found = 1;
- break;
- }
- }
- }
-
- if (!found)
- {
- PRINTK("%s: No PHY found\n", dev->name);
- return(0);
- }
-
- // Set the PHY type
- if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) )
- {
- lp->phytype = PHY_LAN83C183;
- PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name);
- }
-
- if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) )
- {
- lp->phytype = PHY_LAN83C180;
- PRINTK("%s: PHY=LAN83C180\n", dev->name);
- }
-
- return(1);
-}
-
-/*------------------------------------------------------------
- . Waits the specified number of milliseconds - kernel friendly
- .-------------------------------------------------------------*/
-static void smc_wait_ms(unsigned int ms)
-{
-
- if (!in_interrupt())
- {
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(1 + ms * HZ / 1000);
- }
- else
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1 + ms * HZ / 1000);
- current->state = TASK_RUNNING;
- }
-}
-
-/*------------------------------------------------------------
- . Sets the PHY to a configuration as determined by the user
- .-------------------------------------------------------------*/
-#ifdef DISABLED____CONFIG_SYSCTL
-static int smc_phy_fixed(struct rtnet_device* dev)
-{
- int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
- byte phyaddr = lp->phyaddr;
- word my_fixed_caps;
- word cfg1;
-
- PRINTK3("%s:smc_phy_fixed()\n", dev->name);
-
- // Enter Link Disable state
- cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG);
- cfg1 |= PHY_CFG1_LNKDIS;
- smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1);
-
- // Set our fixed capabilities
- // Disable auto-negotiation
- my_fixed_caps = 0;
-
- if (lp->ctl_rfduplx)
- my_fixed_caps |= PHY_CNTL_DPLX;
-
- if (lp->ctl_rspeed == 100)
- my_fixed_caps |= PHY_CNTL_SPEED;
-
- // Write our capabilities to the phy control register
- smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps);
-
- // Re-Configure the Receive/Phy Control register
- outw( lp->rpc_cur_mode, ioaddr + RPC_REG );
-
- // Success
- return(1);
-}
-#endif // CONFIG_SYSCTL
-
-
-/*------------------------------------------------------------
- . Configures the specified PHY using Autonegotiation. Calls
- . smc_phy_fixed() if the user has requested a certain config.
- .-------------------------------------------------------------*/
-static void smc_phy_configure(struct rtnet_device* dev)
-{
- int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
- int timeout;
- byte phyaddr;
- word my_phy_caps; // My PHY capabilities
- word my_ad_caps; // My Advertised capabilities
- word status;
- int failed = 0;
-
- PRINTK3("%s:smc_program_phy()\n", dev->name);
-
- // Set the blocking flag
- lp->autoneg_active = 1;
-
- // Find the address and type of our phy
- if (!smc_detect_phy(dev))
- {
- goto smc_phy_configure_exit;
- }
-
- // Get the detected phy address
- phyaddr = lp->phyaddr;
-
- // Reset the PHY, setting all other bits to zero
- smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
-
- // Wait for the reset to complete, or time out
- timeout = 6; // Wait up to 3 seconds
- while (timeout--)
- {
- if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
- & PHY_CNTL_RST))
- {
- // reset complete
- break;
- }
-
- smc_wait_ms(500); // wait 500 millisecs
- if (signal_pending(current)) // Exit anyway if signaled
- {
- PRINTK2("%s:PHY reset interrupted by signal\n",
- dev->name);
- timeout = 0;
- break;
- }
- }
-
- if (timeout < 1)
- {
- PRINTK2("%s:PHY reset timed out\n", dev->name);
- goto smc_phy_configure_exit;
- }
-
- // Read PHY Register 18, Status Output
- lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
-
- // Enable PHY Interrupts (for register 18)
- // Interrupts listed here are disabled
- smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
- PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
- PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
- PHY_INT_SPDDET | PHY_INT_DPLXDET);
-
- /* Configure the Receive/Phy Control register */
- SMC_SELECT_BANK( 0 );
- outw( lp->rpc_cur_mode, ioaddr + RPC_REG );
-
- // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
- my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
- my_ad_caps = PHY_AD_CSMA; // I am CSMA capable
-
- if (my_phy_caps & PHY_STAT_CAP_T4)
- my_ad_caps |= PHY_AD_T4;
-
- if (my_phy_caps & PHY_STAT_CAP_TXF)
- my_ad_caps |= PHY_AD_TX_FDX;
-
- if (my_phy_caps & PHY_STAT_CAP_TXH)
- my_ad_caps |= PHY_AD_TX_HDX;
-
- if (my_phy_caps & PHY_STAT_CAP_TF)
- my_ad_caps |= PHY_AD_10_FDX;
-
- if (my_phy_caps & PHY_STAT_CAP_TH)
- my_ad_caps |= PHY_AD_10_HDX;
-
-#ifdef DISABLED____CONFIG_SYSCTL
- // Disable capabilities not selected by our user
- if (lp->ctl_rspeed != 100)
- {
- my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);
- }
-
- if (!lp->ctl_rfduplx)
- {
- my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);
- }
-#endif // CONFIG_SYSCTL
-
- // Update our Auto-Neg Advertisement Register
- smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
-
- PRINTK2("%s:phy caps=%x\n", dev->name, my_phy_caps);
- PRINTK2("%s:phy advertised caps=%x\n", dev->name, my_ad_caps);
-
-#ifdef DISABLED____CONFIG_SYSCTL
- // If the user requested no auto neg, then go set his request
- if (!(lp->ctl_autoneg))
- {
- smc_phy_fixed(dev);
- goto smc_phy_configure_exit;
- }
-#endif // CONFIG_SYSCTL
-
- // Restart auto-negotiation process in order to advertise my caps
- smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
- PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
-
- // Wait for the auto-negotiation to complete. This may take from
- // 2 to 3 seconds.
- // Wait for the reset to complete, or time out
- timeout = 20-1; // Wait up to 10 seconds
- do
- {
- status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
- if (status & PHY_STAT_ANEG_ACK)
- {
- // auto-negotiate complete
- break;
- }
-
- smc_wait_ms(500); // wait 500 millisecs
- if (signal_pending(current)) // Exit anyway if signaled
- {
- printk(KERN_DEBUG
- "%s:PHY auto-negotiate interrupted by signal\n",
- dev->name);
- timeout = 0;
- break;
- }
-
- // Restart auto-negotiation if remote fault
- if (status & PHY_STAT_REM_FLT)
- {
- PRINTK2("%s:PHY remote fault detected\n", dev->name);
-
- // Restart auto-negotiation
- PRINTK2("%s:PHY restarting auto-negotiation\n",
- dev->name);
- smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
- PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
- PHY_CNTL_SPEED | PHY_CNTL_DPLX);
- }
- }
- while (timeout--);
-
- if (timeout < 1)
- {
- printk(KERN_DEBUG "%s:PHY auto-negotiate timed out\n",
- dev->name);
- PRINTK2("%s:PHY auto-negotiate timed out\n", dev->name);
- failed = 1;
- }
-
- // Fail if we detected an auto-negotiate remote fault
- if (status & PHY_STAT_REM_FLT)
- {
- printk(KERN_DEBUG "%s:PHY remote fault detected\n", dev->name);
- PRINTK2("%s:PHY remote fault detected\n", dev->name);
- failed = 1;
- }
-
- // The smc_phy_interrupt() routine will be called to update lastPhy18
-
- // Set our sysctl parameters to match auto-negotiation results
- if ( lp->lastPhy18 & PHY_INT_SPDDET )
- {
- PRINTK2("%s:PHY 100BaseT\n", dev->name);
- lp->rpc_cur_mode |= RPC_SPEED;
- }
- else
- {
- PRINTK2("%s:PHY 10BaseT\n", dev->name);
- lp->rpc_cur_mode &= ~RPC_SPEED;
- }
-
- if ( lp->lastPhy18 & PHY_INT_DPLXDET )
- {
- PRINTK2("%s:PHY Full Duplex\n", dev->name);
- lp->rpc_cur_mode |= RPC_DPLX;
- }
- else
- {
- PRINTK2("%s:PHY Half Duplex\n", dev->name);
- lp->rpc_cur_mode &= ~RPC_DPLX;
- }
-
- // Re-Configure the Receive/Phy Control register
- outw( lp->rpc_cur_mode, ioaddr + RPC_REG );
-
- smc_phy_configure_exit:
-
- // Exit auto-negotiation
- lp->autoneg_active = 0;
-}
-
-
-
-MODULE_LICENSE("GPL");
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] drivers/net: Account for changes to of_get_mac_address in 5.13
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
2022-01-07 11:35 ` [PATCH 1/6] drivers/net: Remove dead smc91111 driver Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
2022-01-07 11:35 ` [PATCH 3/6] drivers/net: fec: Account for changes of get/set_coalesce ethtool callbacks in 5.15 Jan Kiszka
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kernel/drivers/net/drivers/at91_ether.c | 7 +++++++
kernel/drivers/net/drivers/freescale/fec_main.c | 6 ++++++
kernel/drivers/net/drivers/macb.c | 7 +++++++
3 files changed, 20 insertions(+)
diff --git a/kernel/drivers/net/drivers/at91_ether.c b/kernel/drivers/net/drivers/at91_ether.c
index 7a2436c273..f8223b0bc5 100644
--- a/kernel/drivers/net/drivers/at91_ether.c
+++ b/kernel/drivers/net/drivers/at91_ether.c
@@ -303,7 +303,9 @@ static int __init at91ether_probe(struct platform_device *pdev)
struct macb *lp;
int res;
u32 reg;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
const char *mac;
+#endif
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs)
@@ -356,10 +358,15 @@ static int __init at91ether_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0))
+ res = of_get_mac_address(pdev->dev.of_node, lp->dev->dev_addr);
+ if (res)
+#else
mac = of_get_mac_address(pdev->dev.of_node);
if (mac)
memcpy(lp->dev->dev_addr, mac, ETH_ALEN);
else
+#endif
rtmacb_get_hwaddr(lp);
res = of_get_phy_mode(pdev->dev.of_node);
diff --git a/kernel/drivers/net/drivers/freescale/fec_main.c b/kernel/drivers/net/drivers/freescale/fec_main.c
index 38396a08e1..0192a09970 100644
--- a/kernel/drivers/net/drivers/freescale/fec_main.c
+++ b/kernel/drivers/net/drivers/freescale/fec_main.c
@@ -1267,9 +1267,15 @@ static void fec_get_mac(struct net_device *ndev)
if (!is_valid_ether_addr(iap)) {
struct device_node *np = fep->pdev->dev.of_node;
if (np) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
+ int err = of_get_mac_address(np, tmpaddr);
+ if (!err)
+ iap = tmpaddr;
+#else
const char *mac = of_get_mac_address(np);
if (!IS_ERR(mac))
iap = (unsigned char *) mac;
+#endif
}
}
diff --git a/kernel/drivers/net/drivers/macb.c b/kernel/drivers/net/drivers/macb.c
index ccda6aecda..77957d9062 100644
--- a/kernel/drivers/net/drivers/macb.c
+++ b/kernel/drivers/net/drivers/macb.c
@@ -1570,7 +1570,9 @@ static int __init macb_probe(struct platform_device *pdev)
u32 config;
int err = -ENXIO;
struct pinctrl *pinctrl;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)
const char *mac;
+#endif
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
@@ -1688,10 +1690,15 @@ static int __init macb_probe(struct platform_device *pdev)
config |= macb_dbw(bp);
macb_writel(bp, NCFGR, config);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
+ err = of_get_mac_address(pdev->dev.of_node, bp->dev->dev_addr);
+ if (err)
+#else
mac = of_get_mac_address(pdev->dev.of_node);
if (mac)
memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
else
+#endif
rtmacb_get_hwaddr(bp);
err = of_get_phy_mode(pdev->dev.of_node);
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] drivers/net: fec: Account for changes of get/set_coalesce ethtool callbacks in 5.15
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
2022-01-07 11:35 ` [PATCH 1/6] drivers/net: Remove dead smc91111 driver Jan Kiszka
2022-01-07 11:35 ` [PATCH 2/6] drivers/net: Account for changes to of_get_mac_address in 5.13 Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
2022-01-07 11:35 ` [PATCH 4/6] drivers/serial: rt_imx_uart: Make it DT-only Jan Kiszka
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kernel/drivers/net/drivers/freescale/fec_main.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/kernel/drivers/net/drivers/freescale/fec_main.c b/kernel/drivers/net/drivers/freescale/fec_main.c
index 0192a09970..be0ed0c51e 100644
--- a/kernel/drivers/net/drivers/freescale/fec_main.c
+++ b/kernel/drivers/net/drivers/freescale/fec_main.c
@@ -2171,7 +2171,13 @@ static void fec_enet_itr_coal_set(struct net_device *ndev)
}
static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+fec_enet_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
+#else
fec_enet_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
+#endif
{
struct fec_enet_private *fep = netdev_priv(ndev);
@@ -2188,7 +2194,13 @@ fec_enet_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
}
static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec,
+ struct kernel_ethtool_coalesce *kernel_coal,
+ struct netlink_ext_ack *extack)
+#else
fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
+#endif
{
struct fec_enet_private *fep = netdev_priv(ndev);
struct device *dev = &fep->pdev->dev;
@@ -2240,7 +2252,11 @@ static void fec_enet_itr_coal_init(struct net_device *ndev)
ec.tx_coalesce_usecs = FEC_ITR_ICTT_DEFAULT;
ec.tx_max_coalesced_frames = FEC_ITR_ICFT_DEFAULT;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+ fec_enet_set_coalesce(ndev, &ec, NULL, NULL);
+#else
fec_enet_set_coalesce(ndev, &ec);
+#endif
}
static int fec_enet_get_tunable(struct net_device *netdev,
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] drivers/serial: rt_imx_uart: Make it DT-only
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
` (2 preceding siblings ...)
2022-01-07 11:35 ` [PATCH 3/6] drivers/net: fec: Account for changes of get/set_coalesce ethtool callbacks in 5.15 Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
2022-01-07 11:35 ` [PATCH 5/6] ci: Add 5.15 kernel Jan Kiszka
2022-01-07 11:35 ` [PATCH 6/6] ci: Drop some I-pipe left-overs Jan Kiszka
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
Aligns us with upstream and allows to compile against 5.11+.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kernel/drivers/serial/rt_imx_uart.c | 32 +++--------------------------
1 file changed, 3 insertions(+), 29 deletions(-)
diff --git a/kernel/drivers/serial/rt_imx_uart.c b/kernel/drivers/serial/rt_imx_uart.c
index 94efe873a6..00fdd5f363 100644
--- a/kernel/drivers/serial/rt_imx_uart.c
+++ b/kernel/drivers/serial/rt_imx_uart.c
@@ -36,7 +36,6 @@
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/div64.h>
-#include <linux/platform_data/serial-imx.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -1497,11 +1496,9 @@ static struct rtdm_driver imx_uart_driver = {
};
-#ifdef CONFIG_OF
-
/*
- * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
- * could successfully get all information from dt or a negative errno.
+ * This function returns 0 iff it could successfully get all information
+ * from dt or a negative errno.
*/
static int rt_imx_uart_probe_dt(struct rt_imx_uart_port *port,
struct platform_device *pdev)
@@ -1536,27 +1533,6 @@ static int rt_imx_uart_probe_dt(struct rt_imx_uart_port *port,
return 0;
}
-#else
-static inline int rt_imx_uart_probe_dt(struct rt_imx_uart_port *port,
- struct platform_device *pdev)
-{
- return 1;
-}
-#endif
-
-static void rt_imx_uart_probe_pdata(struct rt_imx_uart_port *port,
- struct platform_device *pdev)
-{
- struct imxuart_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
- port->devdata = (struct imx_uart_data *) pdev->id_entry->driver_data;
-
- if (!pdata)
- return;
-
- if (pdata->flags & IMXUART_HAVE_RTSCTS)
- port->have_rtscts = 1;
-}
static int rt_imx_uart_probe(struct platform_device *pdev)
{
@@ -1570,9 +1546,7 @@ static int rt_imx_uart_probe(struct platform_device *pdev)
return -ENOMEM;
ret = rt_imx_uart_probe_dt(port, pdev);
- if (ret > 0)
- rt_imx_uart_probe_pdata(port, pdev);
- else if (ret < 0)
+ if (ret < 0)
return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] ci: Add 5.15 kernel
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
` (3 preceding siblings ...)
2022-01-07 11:35 ` [PATCH 4/6] drivers/serial: rt_imx_uart: Make it DT-only Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
2022-01-07 11:35 ` [PATCH 6/6] ci: Drop some I-pipe left-overs Jan Kiszka
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
.gitlab-ci.yml | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 859a12b89b..8a9a631d41 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -178,6 +178,14 @@ variables:
paths:
- .ccache
+arm-5.15-head:
+ extends: .build
+ variables:
+ ARCH: arm
+ PIPELINE_REV: v5.15.y-dovetail-rebase
+ PIPELINE_KERNEL: ${DOVETAIL_URL}
+ KERNEL_DEFCONFIG: multi_v7_defconfig
+
arm-5.10-head:
extends: .build
variables:
@@ -186,6 +194,14 @@ arm-5.10-head:
PIPELINE_KERNEL: ${DOVETAIL_URL}
KERNEL_DEFCONFIG: multi_v7_defconfig
+arm64-5.15-head:
+ extends: .build
+ variables:
+ ARCH: arm64
+ PIPELINE_REV: v5.15.y-dovetail-rebase
+ PIPELINE_KERNEL: ${DOVETAIL_URL}
+ KERNEL_DEFCONFIG: defconfig
+
arm64-5.10-head:
extends: .build
variables:
@@ -194,6 +210,14 @@ arm64-5.10-head:
PIPELINE_KERNEL: ${DOVETAIL_URL}
KERNEL_DEFCONFIG: defconfig
+x86-5.15-head:
+ extends: .build
+ variables:
+ ARCH: x86
+ PIPELINE_REV: v5.15.y-dovetail-rebase
+ PIPELINE_KERNEL: ${DOVETAIL_URL}
+ KERNEL_DEFCONFIG: x86_64_defconfig
+
x86-5.10-head:
extends: .build
variables:
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] ci: Drop some I-pipe left-overs
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
` (4 preceding siblings ...)
2022-01-07 11:35 ` [PATCH 5/6] ci: Add 5.15 kernel Jan Kiszka
@ 2022-01-07 11:35 ` Jan Kiszka
5 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2022-01-07 11:35 UTC (permalink / raw)
To: xenomai
From: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
.gitlab-ci.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8a9a631d41..ca3c086200 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,7 @@
#
# Xenomai Real-Time System
#
-# Copyright (c) Siemens AG, 2020-2021
+# Copyright (c) Siemens AG, 2020-2022
#
# Authors:
# Quirin Gylstorff <quirin.gylstorff@siemens.com>
@@ -20,7 +20,6 @@ variables:
KDIR: "/tmp/kernel"
USE_CCACHE: "1"
CCACHE_MAXSIZE: "1G"
- IPIPE_URL: "https://source.denx.de/Xenomai"
DOVETAIL_URL: "https://source.denx.de/Xenomai/linux-dovetail.git"
GCC_VERSION: "10"
PACKAGES: "u-boot-tools git make bc bison libelf-dev autotools-dev \
@@ -74,7 +73,6 @@ variables:
# Generic settings
- ./scripts/config -d DEBUG_INFO
# I-pipe and Xenomai settings
- - ./scripts/config -e IPIPE
- ./scripts/config -e DOVETAIL
- ./scripts/config -e XENOMAI
- ./scripts/config -e XENO_OPT_SCHED_CLASSES
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-01-07 11:35 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-07 11:35 [PATCH 0/6] Further changes for 5.15 support Jan Kiszka
2022-01-07 11:35 ` [PATCH 1/6] drivers/net: Remove dead smc91111 driver Jan Kiszka
2022-01-07 11:35 ` [PATCH 2/6] drivers/net: Account for changes to of_get_mac_address in 5.13 Jan Kiszka
2022-01-07 11:35 ` [PATCH 3/6] drivers/net: fec: Account for changes of get/set_coalesce ethtool callbacks in 5.15 Jan Kiszka
2022-01-07 11:35 ` [PATCH 4/6] drivers/serial: rt_imx_uart: Make it DT-only Jan Kiszka
2022-01-07 11:35 ` [PATCH 5/6] ci: Add 5.15 kernel Jan Kiszka
2022-01-07 11:35 ` [PATCH 6/6] ci: Drop some I-pipe left-overs Jan Kiszka
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.