## Automatically generated incremental diff ## From: linux-2.4.22-bk25 ## To: linux-2.4.22-bk26 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.4.22-bk25/Documentation/Configure.help linux-2.4.22-bk26/Documentation/Configure.help --- linux-2.4.22-bk25/Documentation/Configure.help 2003-09-29 02:49:35.000000000 -0700 +++ linux-2.4.22-bk26/Documentation/Configure.help 2003-09-29 02:49:40.000000000 -0700 @@ -4006,7 +4006,7 @@ CONFIG_AGP_AMD_8151 This option gives you AGP support for the GLX component of - XFree86 on AMD K8 with an AGP 8151 chipset. + XFree86 on an AMD Opteron/Athlon64 using the on-CPU GART. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. @@ -11646,49 +11646,58 @@ Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter. The following adapters are supported by this driver: - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9521 10/100/1000Base-T Adapter - - DGE-530T Gigabit Ethernet Adapter - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter + - 3Com 3C940 Gigabit LOM Ethernet Adapter + - 3Com 3C941 Gigabit LOM Ethernet Adapter + - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter + - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter + - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter + - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter + - Allied Telesyn AT-2971T Gigabit Ethernet Adapter + - DGE-530T Gigabit Ethernet Adapter + - EG1032 v2 Instant Gigabit Network Adapter + - EG1064 v2 Instant Gigabit Network Adapter + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) + - Marvell RDK-8001 Adapter + - Marvell RDK-8002 Adapter + - Marvell RDK-8003 Adapter + - Marvell RDK-8004 Adapter + - Marvell RDK-8006 Adapter + - Marvell RDK-8007 Adapter + - Marvell RDK-8008 Adapter + - Marvell RDK-8009 Adapter + - Marvell RDK-8010 Adapter + - Marvell RDK-8011 Adapter + - Marvell RDK-8012 Adapter + - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) + - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) + - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) + - SK-9521 10/100/1000Base-T Adapter + - SK-9521 V2.0 10/100/1000Base-T Adapter + - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) + - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter + - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) + - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) + - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter + - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) + - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) + - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) + - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) + - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) + - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) + - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter + - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + - SMC EZ Card 1000 (SMC9452TXV.2) The adapters support Jumbo Frames. The dual link adapters support link-failover and dual port features. @@ -11704,121 +11713,6 @@ say M here and read Documentation/modules.txt. This is recommended. The module will be called sk98lin.o. -Marvell Yukon Chipset -CONFIG_SK98LIN_T1 - This driver supports: - - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -SysKonnect SK98xx Support -CONFIG_SK98LIN_T2 - This driver supports: - - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -SysKonnect SK98xx Support -CONFIG_SK98LIN_T3 - This driver supports: - - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T4 - This driver supports: - - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T5 - This driver supports: - - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9521 10/100/1000Base-T Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T6 - This driver supports: - - - DGE-530T Gigabit Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T7 - This driver supports: - - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T8 - This driver supports: - - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T9 - This driver supports: - - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - Sun GEM support CONFIG_SUNGEM diff -urN linux-2.4.22-bk25/Documentation/cciss.txt linux-2.4.22-bk26/Documentation/cciss.txt --- linux-2.4.22-bk25/Documentation/cciss.txt 2003-09-29 02:49:35.000000000 -0700 +++ linux-2.4.22-bk26/Documentation/cciss.txt 2003-09-29 02:49:40.000000000 -0700 @@ -53,6 +53,56 @@ /dev/cciss/c1d1p2 Controller 1, disk 1, partition 2 /dev/cciss/c1d1p3 Controller 1, disk 1, partition 3 +Support for more than 8 controllers +----------------------------------- +Originally the driver only supports 8 controllers in the system, +and this is due to the major numbers assigned to the driver +(104 thru 111). + +The driver can now support up to 32 controllers in the system. + +For the ninth controller and beyond, the major numbers will be +assigned dynamically by the kernel when it is discovered, +and there is no guarantee what the major number you will get, +but most likely it will start from 254 and goes down from there. + +You can check the assigned major numbers by typing + cat /proc/devices +And look for cciss controllers + +Once you have this, you need to create device nodes in +/dev/cciss directory. The nodes for the first 8 controllers +should already be created by mkdev.cciss script or +/etc/makedev.d/cciss script. You can add the major number(s) +in those scripts, or create the nodes manually by using +the mknod command. + +You can also use mknod_dyn.cciss and rmnod_dyn.cciss scripts +to create or remove nodes easily. These scripts can be found +in the Documentation directory. + +Then you can mount the devices and create partitions +(You also need to make nodes for these partitions). + +As for the minor number, the disk device will have a minor +number divisible by 16 (e.g: 0, 16, 32 etc), and the +partitions on those disk devices will have the minor number +of the disk device plus the partition number (1-15). +For example, disk d2 will have minor number 32, and its +partitions 1 and 2 will have minor numbers 33 and 34. + +Look at the mkdev.cciss script for example. + +Note: + In 2.4 kernel, partition names are hard coded in + /usr/src/linux/fs/partitions/check.c + and only for the first 8 cciss controllers. The rest + will be reported as ccissXX. This should not affect + I/O operation or performance. Please apply the + cciss_2.4_partition_name.patch to address this. This + will not be an issue under 2.5 kernel, since partition + names will be handled by the driver. + SCSI tape drive and medium changer support ------------------------------------------ diff -urN linux-2.4.22-bk25/Documentation/mkdev_dyn.cciss linux-2.4.22-bk26/Documentation/mkdev_dyn.cciss --- linux-2.4.22-bk25/Documentation/mkdev_dyn.cciss 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.4.22-bk26/Documentation/mkdev_dyn.cciss 2003-09-29 02:49:40.000000000 -0700 @@ -0,0 +1,171 @@ +#!/bin/sh +# +# Author: Francis Wiran +# +# Script to create device nodes for SMART Array controllers, idea from +# mkdev.cciss found in Documentation. The argument syntax is different, +# hence, the name change. +# +# Usage: +# mkdev_dyn.cciss [ctlr num] [major num] [num log vol] [num partitions] +# +# With no arguments, the script will check to see if there are any cciss +# nodes already created in the /dev directory. If so, then it will assume +# that the nodes for the first 8 controllers are already created by +# /etc/makedev.d, which is likely. If not, then the script will create +# them, using the major numbers reserved for cciss controllers (104 thru 111). +# +# After that, it will start creating nodes for the controllers which major +# numbers are dynamically allocated by the kernel. It will check +# /proc/devices for any cciss controllers with major numbers other than +# 104 thru 111 and creates the nodes. +# +# Note that it is a good idea to run rmdev_dyn.cciss script if you remove +# those controllers (the ones which major numbers were dynamically allocated) +# This will unclutter /dev, as well as preventing possible problems due to +# referenced devices and major numbers no longer available or taken by +# other non-cciss drivers. +# +# With no arguments, the script assumes 16 logical volumes per controller +# and 16 partitions per volume; +# +# Passing arguments: +# If you know that one of your controllers, say cciss8, has been dynamically +# assigned major number 254, and were planning on no more than 2 logical +# volumes, using a maximum of 4 partitions per volume, you could do: +# +# mkdev_dyn.cciss 8 254 2 4 +# +# Of course, this has no real benefit over "mkdev_dyn.cciss 8 254" except +# that it doesn't create as many device nodes in /dev/cciss. +# + +# Inputs +NR_CTLR=${1-8} +NR_MAJOR=${2-254} +NR_VOL=${3-16} +NR_PART=${4-16} + +echo_usage() +{ + echo "Usage: mkdev_dyn.cciss [ctlr num] [maj] [volumes] [partitions]" + echo "The script assumes that ctlr 0 thru 7 is statically created" + echo "Therefore, if you want to pass arguments make sure that" + echo "ctlr num is equal or greater than 8, and the major number" + echo "is not one that's statically assigned for cciss controller." + echo "Check the correct major number in /proc/devices" + + # Hmm... we don't support volumes and partitions greater than 16 + # either. +} + +echo_create() +{ + echo "created /dev/cciss/c${1}* nodes using major number ${2}" +} + + +# Function: do_mknod() +# Creates devices nodes under /dev/cciss +# Inputs: $1 - ctlr number +# $2 - major number +# $3 - number of devices on controller +# $4 - number of partitions per device +do_mknod() +{ + D=0; + while [ $D -lt $3 ]; do + P=0; + while [ $P -lt $4 ]; do + MIN=`expr $D \* 16 + $P`; + if [ $P -eq 0 ]; then + mknod /dev/cciss/c${1}d${D} b $2 $MIN + else + mknod /dev/cciss/c${1}d${D}p${P} b $2 $MIN + fi + P=`expr $P + 1`; + done + D=`expr $D + 1`; + done +} + +# Function: do_dyn +# Search and create cciss nodes for the controllers which +# major numbers are allocated dynamically by the kernel +# instead of using kernel.org 's value of 104 to 111. +# +# Input: $1 - ctlr num - will create nodes /dev/cciss/c${1} +# $2 - major num - the major number to assign to the nodes +# $3 - volumes - max number of volumes per controller +# $4 - partitions - max number of partitions per volume +# +# Note: Without input, this function will start creating nodes +# for controller c8 and above, making assumption that +# c0 thru c7 are already made, and the name c8 and above +# are not already taken. +do_dyn() +{ + if [ $# -eq 0 ]; then + C=0; + for MAJ in `cat /proc/devices |\ + grep cciss |\ + awk '/cciss[0-9]$/ { sub("cciss", "cciss0") }; {print}' |\ + sort -k 2,2 |\ + awk '{print $1-i}'`; + do + if [ `ls -l /dev/cciss/c* |\ + awk '{print $5-i}' |\ + uniq |\ + grep $MAJ |\ + wc -l` -gt 0 ]; then + : + else + do_mknod $C $MAJ $NR_VOL $NR_PART; + echo_create $C $MAJ; + fi + C=`expr $C + 1`; + done + else + do_mknod $1 $2 $3 $4; + echo_create $1 $2; + fi + + exit +} + +# Start here + +# Check the input values +if [ $NR_CTLR -lt 8 ]; then + echo_usage; + exit +fi + +if [ $NR_CTLR -ge 8 ]; then + if [ \( $NR_MAJOR -ge 104 \) -a \( $NR_MAJOR -le 111 \) ]; then + echo_usage; + exit + fi +fi + +if [ ! -d /dev/cciss ]; then + mkdir -p /dev/cciss +fi + +# Assume that if c0d0p1 node already exist, then all nodes from c0d0p1 +# to c7d15p15 have been created for us. +if [ ! -b /dev/cciss/c0d0p1 ]; then + C=0; + while [ $C -lt 8 ]; do + MAJ=`expr $C + 104`; + do_mknod $C $MAJ $NR_VOL $NR_PART; + echo_create $C $MAJ; + C=`expr $C + 1`; + done +fi + +if [ $# -gt 0 ]; then + do_dyn $NR_CTLR $NR_MAJOR $NR_VOL $NR_PART; +else + do_dyn; +fi diff -urN linux-2.4.22-bk25/Documentation/networking/sk98lin.txt linux-2.4.22-bk26/Documentation/networking/sk98lin.txt --- linux-2.4.22-bk25/Documentation/networking/sk98lin.txt 2003-09-29 02:49:35.000000000 -0700 +++ linux-2.4.22-bk26/Documentation/networking/sk98lin.txt 2003-09-29 02:49:40.000000000 -0700 @@ -2,9 +2,9 @@ All rights reserved =========================================================================== -sk98lin.txt created 26-Aug-2003 +sk98lin.txt created 23-Sep-2003 -Readme File for sk98lin v6.17 +Readme File for sk98lin v6.18 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains diff -urN linux-2.4.22-bk25/Documentation/rmdev_dyn.cciss linux-2.4.22-bk26/Documentation/rmdev_dyn.cciss --- linux-2.4.22-bk25/Documentation/rmdev_dyn.cciss 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.4.22-bk26/Documentation/rmdev_dyn.cciss 2003-09-29 02:49:40.000000000 -0700 @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Author: Francis Wiran +# +# Script to remove device nodes for SMART Array controllers. This will +# be the device nodes with major numbers which are dynamically allocated +# by the kernel. This script will not attempt to remove the device +# nodes with major number 104 thru 111 (c0 thru c7), which are +# the major numbers that's allocated for cciss controllers by kernel.org. +# +# Usage: +# rmdev_dyn.cciss [ctlr num] +# +# With no arguments, the script will check to see if there are any nodes +# under /dev/cciss, whose major number no longer shows in /proc/partitions, +# or to be exact, no longer shows to be owned by cciss driver. +# If there is, then it will be removed. +# +# Note that it is a good idea to run rmdev_dyn.cciss script if you remove +# those controllers (the ones which major numbers were dynamically allocated) +# This will unclutter /dev, as well as preventing possible problems due to +# referenced devices and major numbers no longer available or taken by +# other non-cciss drivers. +# +# Passing arguments: +# If you know that one of your controllers, say cciss8, has been removed +# and the nodes are no longer valid, you could do +# +# rmdev_dyn.cciss 8 +# +# This is the same as doing `rm -f /dev/cciss/c8*` + +# Inputs +NR_CTLR=${1} + +echo_usage() +{ + echo "Usage: rmdev_dyn.cciss [ctlr num]" + echo "The script will not attempt to remove nodes for controllers" + echo "0 thru 7, therefore if you want to pass an argument," + echo "make sure that ctlr num is equal or greater than 8" +} + +rm_nod1() +{ + if [ $1 -lt 8 ]; then + echo_usage; + exit + else + rm -f /dev/cciss/c${1}* + echo "removed /dev/cciss/c${1}*" + fi +} + +rm_nod2() +{ + for X in `ls -l /dev/cciss/c* |\ + awk '{print $5-i}' |\ + uniq`; do + if [ \( $X -ge 104 \) -a \( $X -le 111 \) ]; then + : + elif [ `cat /proc/devices |\ + grep cciss |\ + grep $X |\ + wc -l` -eq 0 ]; then + + Y=`ls -l /dev/cciss/ |\ + awk '{print $5-i ":" $10}'|\ + tr d ':' |\ + grep $X |\ + awk -F: '{print $2}' |\ + uniq` + + Z="/dev/cciss/${Y}*" + + rm -f $Z + echo "removed $Z" + fi + done +} + +# Start here +if [ $# -gt 0 ]; then + rm_nod1 $NR_CTLR; +else + rm_nod2; +fi diff -urN linux-2.4.22-bk25/Documentation/x86_64/boot-options.txt linux-2.4.22-bk26/Documentation/x86_64/boot-options.txt --- linux-2.4.22-bk25/Documentation/x86_64/boot-options.txt 2003-08-25 04:44:39.000000000 -0700 +++ linux-2.4.22-bk26/Documentation/x86_64/boot-options.txt 2003-09-29 02:49:40.000000000 -0700 @@ -65,13 +65,14 @@ 0 don't use an NMI watchdog 1 use the IO-APIC timer for the NMI watchdog 2 use the local APIC for the NMI watchdog using a performance counter. Note - This will use one performance counter. + This will use one performance counter and the local APIC's performance + counter vector. Idle loop idle=poll Don't do power saving in the idle loop using HLT, but poll for rescheduling - event. This will make the CPUs eat a lot more power, but may be useful + events. This will make the CPUs burn a lot more power, but may be useful to get slightly better performance in multiprocessor benchmarks. It also makes some profiling using performance counters more accurate. @@ -145,7 +146,7 @@ off don't use the IOMMU leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) memaper[=order] allocate an own aperture over RAM with size 32MB^order. - noforce don't force IOMMU usage. Should be fastest. - force Force IOMMU and turn on unmap debugging. + noforce don't force IOMMU usage. Default. + force Force IOMMU for all devices. diff -urN linux-2.4.22-bk25/Makefile linux-2.4.22-bk26/Makefile --- linux-2.4.22-bk25/Makefile 2003-09-29 02:49:35.000000000 -0700 +++ linux-2.4.22-bk26/Makefile 2003-09-29 02:49:40.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 22 -EXTRAVERSION = -bk25 +EXTRAVERSION = -bk26 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.4.22-bk25/arch/ppc/8xx_io/Config.in linux-2.4.22-bk26/arch/ppc/8xx_io/Config.in --- linux-2.4.22-bk25/arch/ppc/8xx_io/Config.in 2001-10-15 13:35:26.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/8xx_io/Config.in 2003-09-29 02:49:40.000000000 -0700 @@ -2,8 +2,14 @@ # MPC8xx Communication options # mainmenu_option next_comment -comment 'MPC8xx CPM Options' +comment 'MPC8xx Options' +comment 'Generic MPC8xx Options' +bool 'Copy-Back Data Cache (else Writethrough)' CONFIG_8xx_COPYBACK +bool 'CPU6 Silicon Errata (860 Pre Rev. C)' CONFIG_8xx_CPU6 +bool 'I2C/SPI Microcode Patch' CONFIG_UCODE_PATCH + +comment 'MPC8xx CPM Options' if [ "$CONFIG_NET_ETHERNET" = "y" ]; then bool 'CPM SCC Ethernet' CONFIG_SCC_ENET if [ "$CONFIG_SCC_ENET" = "y" ]; then @@ -12,25 +18,28 @@ SCC2 CONFIG_SCC2_ENET \ SCC3 CONFIG_SCC3_ENET" SCC1 fi - bool '860T FEC Ethernet' CONFIG_FEC_ENET + bool '8xxT FEC Ethernet' CONFIG_FEC_ENET if [ "$CONFIG_FEC_ENET" = "y" ]; then bool 'Use MDIO for PHY configuration' CONFIG_USE_MDIO fi bool 'Use Big CPM Ethernet Buffers' CONFIG_ENET_BIG_BUFFERS fi +if [ "$CONFIG_SCC3_ENET" != "y" ]; then + bool 'Use SMC1 for UART' CONFIG_8xx_SMC1 +fi bool 'Use SMC2 for UART' CONFIG_SMC2_UART if [ "$CONFIG_SMC2_UART" = "y" ]; then bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_ALTSMC2 bool 'Use SMC2 for Console' CONFIG_CONS_SMC2 fi -bool 'Enable SCC2 and SCC3 for UART' CONFIG_USE_SCC_IO - -# This doesn't really belong here, but it is convenient to ask -# 8xx specific questions. - -comment 'Generic MPC8xx Options' -bool 'Copy-Back Data Cache (else Writethrough)' CONFIG_8xx_COPYBACK -bool 'CPU6 Silicon Errata (860 Pre Rev. C)' CONFIG_8xx_CPU6 -bool 'I2C/SPI Microcode Patch' CONFIG_UCODE_PATCH - +if [ "$CONFIG_SCC1_ENET" != "y" ]; then + bool 'Use SCC1 for UART' CONFIG_8xx_SCC1 +fi +if [ "$CONFIG_SCC2_ENET" != "y" ]; then + bool 'Use SCC2 for UART' CONFIG_8xx_SCC2 +fi +if [ "$CONFIG_SCC3_ENET" != "y" ]; then + bool 'Use SCC3 for UART' CONFIG_8xx_SCC3 +fi +bool 'Use SCC4 for UART' CONFIG_8xx_SCC4 endmenu diff -urN linux-2.4.22-bk25/arch/ppc/8xx_io/commproc.c linux-2.4.22-bk26/arch/ppc/8xx_io/commproc.c --- linux-2.4.22-bk25/arch/ppc/8xx_io/commproc.c 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/8xx_io/commproc.c 2003-09-29 02:49:40.000000000 -0700 @@ -54,6 +54,7 @@ static struct cpm_action cpm_vecs[CPMVEC_NR]; static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs); static void cpm_error_interrupt(int irq, void *, struct pt_regs * regs); +static void alloc_host_memory(void); /* Define a table of names to identify CPM interrupt handlers in * /proc/interrupts. @@ -104,7 +105,7 @@ }; void -m8xx_cpm_reset(uint host_page_addr) +m8xx_cpm_reset() { volatile immap_t *imp; volatile cpm8xx_t *commproc; @@ -130,7 +131,7 @@ * this is what we realy want for some applications, but the * manual recommends it. * Bit 25, FAM can also be set to use FEC aggressive mode (860T). - */ + */ imp->im_siu_conf.sc_sdcr = 1; /* Reclaim the DP memory for our use. @@ -138,25 +139,23 @@ dp_alloc_base = CPM_DATAONLY_BASE; dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE; - /* Set the host page for allocation. + /* Tell everyone where the comm processor resides. */ - host_buffer = host_page_addr; /* Host virtual page address */ - host_end = host_page_addr + PAGE_SIZE; + cpmp = (cpm8xx_t *)commproc; +} - /* We need to get this page early, so I have to do it the - * hard way. - */ - if (get_pteptr(&init_mm, host_page_addr, &pte)) { - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, host_buffer); - } - else { - panic("Huh? No CPM host page?"); - } +/* We used to do this earlier, but have to postpone as long as possible + * to ensure the kernel VM is now running. + */ +static void +alloc_host_memory() +{ + uint physaddr; - /* Tell everyone where the comm processor resides. + /* Set the host page for allocation. */ - cpmp = (cpm8xx_t *)commproc; + host_buffer = (uint)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &physaddr); + host_end = host_buffer + PAGE_SIZE; } /* This is called during init_IRQ. We used to do it above, but this @@ -321,6 +320,9 @@ { uint retloc; + if (host_buffer == 0) + alloc_host_memory(); + if ((host_buffer + size) >= host_end) return(0); diff -urN linux-2.4.22-bk25/arch/ppc/8xx_io/enet.c linux-2.4.22-bk26/arch/ppc/8xx_io/enet.c --- linux-2.4.22-bk25/arch/ppc/8xx_io/enet.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/8xx_io/enet.c 2003-09-29 02:49:40.000000000 -0700 @@ -137,6 +137,11 @@ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ scc_t *sccp; + + /* Virtual addresses for the receive buffers because we can't + * do a __va() on them anymore. + */ + unsigned char *rx_vaddr[RX_RING_SIZE]; struct net_device_stats stats; uint tx_free; spinlock_t lock; @@ -498,7 +503,7 @@ skb->dev = dev; skb_put(skb,pkt_len-4); /* Make room */ eth_copy_and_sum(skb, - (unsigned char *)__va(bdp->cbd_bufaddr), + cep->rx_vaddr[bdp - cep->rx_bd_base], pkt_len-4, 0); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); @@ -632,10 +637,9 @@ { struct net_device *dev; struct scc_enet_private *cep; - int i, j; - unsigned char *eap; - unsigned long mem_addr; - pte_t *pte; + int i, j, k; + unsigned char *eap, *ba; + dma_addr_t mem_addr; bd_t *bd; volatile cbd_t *bdp; volatile cpm8xx_t *cp; @@ -826,24 +830,21 @@ bdp->cbd_sc |= BD_SC_WRAP; bdp = cep->rx_bd_base; + k = 0; for (i=0; icbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR; - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = mem_addr; + cep->rx_vaddr[k++] = ba; mem_addr += CPM_ENET_RX_FRSIZE; + ba += CPM_ENET_RX_FRSIZE; bdp++; } } diff -urN linux-2.4.22-bk25/arch/ppc/8xx_io/fec.c linux-2.4.22-bk26/arch/ppc/8xx_io/fec.c --- linux-2.4.22-bk25/arch/ppc/8xx_io/fec.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/8xx_io/fec.c 2003-09-29 02:49:40.000000000 -0700 @@ -161,7 +161,12 @@ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ - scc_t *sccp; + + /* Virtual addresses for the receive buffers because we can't + * do a __va() on them anymore. + */ + unsigned char *rx_vaddr[RX_RING_SIZE]; + struct net_device_stats stats; uint tx_free; spinlock_t lock; @@ -587,7 +592,7 @@ fep->stats.rx_packets++; pkt_len = bdp->cbd_datlen; fep->stats.rx_bytes += pkt_len; - data = (__u8*)__va(bdp->cbd_bufaddr); + data = fep->rx_vaddr[bdp - fep->rx_bd_base]; /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to @@ -602,9 +607,7 @@ } else { skb->dev = dev; skb_put(skb,pkt_len-4); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)__va(bdp->cbd_bufaddr), - pkt_len-4, 0); + eth_copy_and_sum(skb, data, pkt_len-4, 0); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); } @@ -1700,10 +1703,9 @@ { struct net_device *dev; struct fec_enet_private *fep; - int i, j; - unsigned char *eap, *iap; - unsigned long mem_addr; - pte_t *pte; + int i, j, k; + unsigned char *eap, *iap, *ba; + dma_addr_t mem_addr; volatile cbd_t *bdp; cbd_t *cbd_base; volatile immap_t *immap; @@ -1774,14 +1776,7 @@ printk("FEC initialization failed.\n"); return 1; } - mem_addr = __get_free_page(GFP_KERNEL); - cbd_base = (cbd_t *)mem_addr; - - /* Make it uncached. - */ - pte = va_to_pte(mem_addr); - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, mem_addr); + cbd_base = (cbd_t *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr); /* Set receive and transmit descriptor base. */ @@ -1793,24 +1788,21 @@ /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; + k = 0; for (i=0; icbd_sc = BD_ENET_RX_EMPTY; - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = mem_addr; + fep->rx_vaddr[k++] = ba; mem_addr += FEC_ENET_RX_FRSIZE; + ba += FEC_ENET_RX_FRSIZE; bdp++; } } @@ -1974,8 +1966,8 @@ /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = iopa((uint)(fep->rx_bd_base)); + fecp->fec_x_des_start = iopa((uint)(fep->tx_bd_base)); fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->tx_free = TX_RING_SIZE; diff -urN linux-2.4.22-bk25/arch/ppc/8xx_io/uart.c linux-2.4.22-bk26/arch/ppc/8xx_io/uart.c --- linux-2.4.22-bk25/arch/ppc/8xx_io/uart.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/8xx_io/uart.c 2003-09-29 02:49:40.000000000 -0700 @@ -126,10 +126,27 @@ * type of SMC or SCC. * The SMCs do not support any modem control signals. */ -#define smc_scc_num hub6 -#define NUM_IS_SCC ((int)0x00010000) -#define PORT_NUM(P) ((P) & 0x0000ffff) -#define PORT_IS_SCC(P) ((P) & NUM_IS_SCC) +#define smc_scc_num hub6 +#define NUM_IS_SCC ((int)0x000100000) +#define NUM_BRG ((int)0x0000FF00) +#define NUM_BRG_SHIFT 8 +#define NUM ((int)0x000000FF) +#define NUM_SHIFT 0 +#define PORT_NUM(P) ((P) & NUM) +#define PORT_NUM_SET(N) (((N)-1) << NUM_SHIFT) +#define PORT_IS_SCC(P) ((P) & NUM_IS_SCC) +#define PORT_BRG(P) (((P) & NUM_BRG) >> NUM_BRG_SHIFT) +#define PORT_BRG_SET(P,B) (P) = (((P) & ~NUM_BRG) | ((B) << NUM_BRG_SHIFT)) + +/* Short names for the ports +*/ +#define QUICC_CPM_SMC1 (PORT_NUM_SET(1)) +#define QUICC_CPM_SMC2 (PORT_NUM_SET(2)) +#define QUICC_CPM_SCC1 (PORT_NUM_SET(1)|NUM_IS_SCC) +#define QUICC_CPM_SCC2 (PORT_NUM_SET(2)|NUM_IS_SCC) +#define QUICC_CPM_SCC3 (PORT_NUM_SET(3)|NUM_IS_SCC) +#define QUICC_CPM_SCC4 (PORT_NUM_SET(4)|NUM_IS_SCC) +#define QUICC_MAX_BRG 3 /* BRG1..BRG4 */ /* The serial port to use for KGDB. */ #ifdef CONFIG_KGDB_TTYS1 @@ -151,22 +168,24 @@ */ static struct serial_state rs_table[] = { /* UART CLK PORT IRQ FLAGS NUM */ -#ifndef CONFIG_SCC3_ENET /* SMC1 not usable with Ethernet on SCC3 */ - { 0, 0, PROFF_SMC1, CPMVEC_SMC1, 0, 0 }, /* SMC1 ttyS0 */ +#ifdef CONFIG_8xx_SMC1 + { 0, 0, PROFF_SMC1, CPMVEC_SMC1, 0, QUICC_CPM_SMC1 }, /* SMC1 ttySx */ +#endif +#ifdef CONFIG_8xx_SMC2 + { 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, QUICC_CPM_SMC2 }, /* SMC2 ttySx */ +#endif +#ifdef CONFIG_8xx_SCC1 + { 0, 0, PROFF_SCC1, CPMVEC_SCC1, 0, QUICC_CPM_SCC1 }, /* SCC1 ttySx */ +#endif +#ifdef CONFIG_8xx_SCC2 + { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, QUICC_CPM_SCC2 }, /* SCC2 ttySx */ +#endif +#ifdef CONFIG_8xx_SCC3 + { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, QUICC_CPM_SCC3 }, /* SCC3 ttySx */ +#endif +#ifdef CONFIG_8xx_SCC4 + { 0, 0, PROFF_SCC4, CPMVEC_SCC4, 0, QUICC_CPM_SCC4 }, /* SCC4 ttySx */ #endif -#if !defined(CONFIG_USB_MPC8xx) && !defined(CONFIG_USB_CLIENT_MPC8xx) -# ifdef CONFIG_SMC2_UART - { 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, 1 }, /* SMC2 ttyS1 */ -# endif -# ifdef CONFIG_USE_SCC_IO - { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, (NUM_IS_SCC | 1) }, /* SCC2 ttyS2 */ - { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) }, /* SCC3 ttyS3 */ -# endif - #else /* CONFIG_USB_xxx */ -# ifdef CONFIG_USE_SCC_IO - { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) }, /* SCC3 ttyS3 */ -# endif -#endif /* CONFIG_USB_xxx */ }; #define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) @@ -218,6 +237,12 @@ cbd_t *rx_cur; cbd_t *tx_bd_base; cbd_t *tx_cur; + + /* Virtual addresses for the FIFOs because we can't __va() a + * physical address anymore. + */ + unsigned char *rx_va_base; + unsigned char *tx_va_base; } ser_info_t; static struct console sercons = { @@ -394,13 +419,13 @@ /* Get the number of characters and the buffer pointer. */ i = bdp->cbd_datlen; - cp = (unsigned char *)__va(bdp->cbd_bufaddr); + cp = info->rx_va_base + ((bdp - info->rx_bd_base) * RX_BUF_SIZE); status = bdp->cbd_sc; #ifdef CONFIG_KGDB - if (info->state->smc_scc_num == KGDB_SER_IDX) { - if (*cp == 0x03 || *cp == '$') - breakpoint(); + if (info->state->smc_scc_num == KGDB_SER_IDX && + (*cp == 0x03 || *cp == '$')) { + breakpoint(); return; } #endif @@ -420,7 +445,7 @@ icount->rx++; #ifdef SERIAL_DEBUG_INTR - printk("DR%02x:%02x...", ch, status); + printk("DR%02x:%02x...", ch, status); #endif *tty->flip.flag_buf_ptr = 0; if (status & (BD_SC_BR | BD_SC_FR | @@ -1033,7 +1058,7 @@ smcp->smc_smcmr = new_mode; } - m8xx_cpm_setbrg((state - rs_table), baud_rate); + m8xx_cpm_setbrg(PORT_BRG(state->smc_scc_num), baud_rate); restore_flags(flags); } @@ -1042,6 +1067,7 @@ { ser_info_t *info = (ser_info_t *)tty->driver_data; volatile cbd_t *bdp; + unsigned char *cp; if (serial_paranoia_check(info, tty->device, "rs_put_char")) return; @@ -1052,7 +1078,8 @@ bdp = info->tx_cur; while (bdp->cbd_sc & BD_SC_READY); - *((char *)__va(bdp->cbd_bufaddr)) = ch; + cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); + *cp = ch; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -1064,7 +1091,6 @@ bdp++; info->tx_cur = (cbd_t *)bdp; - } static int rs_8xx_write(struct tty_struct * tty, int from_user, @@ -1073,6 +1099,7 @@ int c, ret = 0; ser_info_t *info = (ser_info_t *)tty->driver_data; volatile cbd_t *bdp; + unsigned char *cp; #ifdef CONFIG_KGDB_CONSOLE /* Try to let stub handle output. Returns true if it did. */ @@ -1099,14 +1126,15 @@ break; } + cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); if (from_user) { - if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) { + if (copy_from_user((void *)cp, buf, c)) { if (!ret) ret = -EFAULT; break; } } else { - memcpy(__va(bdp->cbd_bufaddr), buf, c); + memcpy((void *)cp, buf, c); } bdp->cbd_datlen = c; @@ -1181,6 +1209,7 @@ static void rs_8xx_send_xchar(struct tty_struct *tty, char ch) { volatile cbd_t *bdp; + unsigned char *cp; ser_info_t *info = (ser_info_t *)tty->driver_data; @@ -1190,7 +1219,8 @@ bdp = info->tx_cur; while (bdp->cbd_sc & BD_SC_READY); - *((char *)__va(bdp->cbd_bufaddr)) = ch; + cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); + *cp = ch; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -2217,6 +2247,11 @@ #ifdef CONFIG_SERIAL_CONSOLE +/* I need this just so I can store the virtual addresses and have + * common functions for the early console printing. + */ +static ser_info_t consinfo; + /* * Print a string to the serial port trying not to disturb any possible * real use of the port... @@ -2249,6 +2284,8 @@ /* Get the address of the host memory buffer. */ bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; + + info = &consinfo; } /* @@ -2276,7 +2313,7 @@ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR) cp = (u_char *)(bdp->cbd_bufaddr); else - cp = __va(bdp->cbd_bufaddr); + cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); *cp = *s; bdp->cbd_datlen = 1; @@ -2290,7 +2327,18 @@ /* if a LF, also do CR... */ if (*s == 10) { while (bdp->cbd_sc & BD_SC_READY); - cp = __va(bdp->cbd_bufaddr); + /* This 'if' below will never be true, but a few + * people argued with me that it was a "bug by + * inspection" that is was easier to add the code + * than continue the discussion. The only time + * the buffer address is in DPRAM is during early + * use by kgdb/xmon, which format their own packets + * and we never get here. -- Dan + */ + if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR) + cp = (u_char *)(bdp->cbd_bufaddr); + else + cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); *cp = 13; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -2358,10 +2406,13 @@ * If the port has been initialized for general use, we must * use information from the port structure. */ - if ((info = (ser_info_t *)ser->info)) + if ((info = (ser_info_t *)ser->info)) { bdp = info->rx_cur; - else + } + else { bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; + info = &consinfo; + } /* * We need to gracefully shut down the receiver, disable @@ -2383,7 +2434,7 @@ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR) cp = (u_char *)(bdp->cbd_bufaddr); else - cp = __va(bdp->cbd_bufaddr); + cp = info->rx_va_base + ((bdp - info->rx_bd_base) * RX_BUF_SIZE); if (obuf) { i = c = bdp->cbd_datlen; @@ -2522,6 +2573,43 @@ /* * The serial driver boot-time initialization code! */ + +int __init rs_8xx_alloc_brg(int port) +{ + static int brg = 0; + volatile cpm8xx_t *cp = cpmp; + int res = brg; + + /* "Wire" the BRG to the specified port + */ + switch (port) { + case QUICC_CPM_SMC1: + cp->cp_simode = (cp->cp_simode & ~(0x07<<12)) | (brg<<12); + break; + case QUICC_CPM_SMC2: + cp->cp_simode = (cp->cp_simode & ~(0x07<<28)) | (brg<<28); + break; + case QUICC_CPM_SCC1: + cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<0)) | (((brg<<3)|(brg<<0))<<0); + break; + case QUICC_CPM_SCC2: + cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<8)) | (((brg<<3)|(brg<<0))<<8); + break; + case QUICC_CPM_SCC3: + cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<16)) | (((brg<<3)|(brg<<0))<<16); + break; + case QUICC_CPM_SCC4: + cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<24)) | (((brg<<3)|(brg<<0))<<24); + break; + } + /* Consume this BRG - Note: the last BRG will be reused if this + */ + /* function is called too many times! + */ + if (brg < QUICC_MAX_BRG) brg++; + return res; +} + int __init rs_8xx_init(void) { struct serial_state * state; @@ -2668,9 +2756,12 @@ state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n", + PORT_BRG_SET(state->smc_scc_num, rs_8xx_alloc_brg(state->smc_scc_num)); + printk(KERN_INFO "ttyS%d at 0x%04x is on %s%d using BRG%d\n", i, (unsigned int)(state->port), - PORT_IS_SCC(state->smc_scc_num) ? "SCC" : "SMC"); + PORT_IS_SCC(state->smc_scc_num) ? "SCC" : "SMC", + PORT_NUM(state->smc_scc_num)+1, + PORT_BRG(state->smc_scc_num)+1); #ifdef CONFIG_SERIAL_CONSOLE /* If we just printed the message on the console port, and * we are about to initialize it for general use, we have @@ -2704,6 +2795,7 @@ /* Allocate space for FIFOs in the host memory. */ mem_addr = m8xx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); + info->rx_va_base = (unsigned char *)mem_addr; /* Set the physical address of the host memory * buffers in the buffer descriptors, and the @@ -2713,12 +2805,12 @@ info->rx_cur = info->rx_bd_base = (cbd_t *)bdp; for (j=0; j<(RX_NUM_FIFO-1); j++) { - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = iopa(mem_addr); bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += RX_BUF_SIZE; bdp++; } - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = iopa(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; idx = PORT_NUM(info->state->smc_scc_num); @@ -2738,6 +2830,7 @@ /* Allocate space for FIFOs in the host memory. */ mem_addr = m8xx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); + info->tx_va_base = (unsigned char *)mem_addr; /* Set the physical address of the host memory * buffers in the buffer descriptors, and the @@ -2747,12 +2840,12 @@ info->tx_cur = info->tx_bd_base = (cbd_t *)bdp; for (j=0; j<(TX_NUM_FIFO-1); j++) { - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = iopa(mem_addr); bdp->cbd_sc = BD_SC_INTRPT; mem_addr += TX_BUF_SIZE; bdp++; } - bdp->cbd_bufaddr = __pa(mem_addr); + bdp->cbd_bufaddr = iopa(mem_addr); bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT); if (PORT_IS_SCC(info->state->smc_scc_num)) { @@ -2846,12 +2939,14 @@ } #endif /* CONFIG_ALTSMC2 */ +#if 0 /* Connect the baud rate generator to the * SMC based upon index in rs_table. Also * make sure it is connected to NMSI. */ cp->cp_simode &= ~(0xffff << (idx * 16)); cp->cp_simode |= (i << ((idx * 16) + 12)); +#endif up->smc_tbase = dp_addr; @@ -2903,7 +2998,7 @@ /* Set up the baud rate generator. */ - m8xx_cpm_setbrg(i, baud_table[baud_idx]); + m8xx_cpm_setbrg(PORT_BRG(state->smc_scc_num), baud_table[baud_idx]); } } @@ -2959,20 +3054,28 @@ * from dual port ram, and a character buffer area from host mem. */ + /* Allocate space for two FIFOs. We can't allocate from host + * memory yet because vm allocator isn't initialized + * during this early console init. + */ + dp_addr = m8xx_cpm_dpalloc(8); + mem_addr = (uint)(&cpmp->cp_dpmem[dp_addr]); + /* Allocate space for two buffer descriptors in the DP ram. */ dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2); - /* Allocate space for two 2 byte FIFOs in the host memory. - */ - mem_addr = m8xx_cpm_hostalloc(8); - /* Set the physical address of the host memory buffers in * the buffer descriptors. */ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - bdp->cbd_bufaddr = __pa(mem_addr); - (bdp+1)->cbd_bufaddr = __pa(mem_addr+4); + bdp->cbd_bufaddr = iopa(mem_addr); + (bdp+1)->cbd_bufaddr = iopa(mem_addr+4); + + consinfo.rx_va_base = mem_addr; + consinfo.rx_bd_base = bdp; + consinfo.tx_va_base = mem_addr + 4; + consinfo.tx_bd_base = bdp+1; /* For the receive, set empty and wrap. * For transmit, set wrap. diff -urN linux-2.4.22-bk25/arch/ppc/Makefile linux-2.4.22-bk26/arch/ppc/Makefile --- linux-2.4.22-bk25/arch/ppc/Makefile 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/Makefile 2003-09-29 02:49:40.000000000 -0700 @@ -14,7 +14,7 @@ # # Be sure to change PAGE_OFFSET in include/asm-ppc/page.h to match -KERNELLOAD =0xc0000000 +KERNELLOAD =$(CONFIG_KERNEL_START) LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic CPPFLAGS := $(CPPFLAGS) -I$(TOPDIR)/arch/$(ARCH) diff -urN linux-2.4.22-bk25/arch/ppc/boot/simple/embed_config.c linux-2.4.22-bk26/arch/ppc/boot/simple/embed_config.c --- linux-2.4.22-bk25/arch/ppc/boot/simple/embed_config.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/boot/simple/embed_config.c 2003-09-29 02:49:40.000000000 -0700 @@ -753,4 +753,3 @@ timebase_period_ns = 1000000000 / bd->bi_tbfreq; } #endif - diff -urN linux-2.4.22-bk25/arch/ppc/boot/simple/misc-embedded.c linux-2.4.22-bk26/arch/ppc/boot/simple/misc-embedded.c --- linux-2.4.22-bk25/arch/ppc/boot/simple/misc-embedded.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/boot/simple/misc-embedded.c 2003-09-29 02:49:40.000000000 -0700 @@ -79,6 +79,14 @@ extern void gunzip(void *, int, unsigned char *, int *); extern void embed_config(bd_t **bp); +/* Weak function for boards which don't need to build the + * board info struct because they are using PPCBoot/U-Boot. + */ +void __attribute__ ((weak)) +embed_config(bd_t **bdp) +{ +} + unsigned long load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) diff -urN linux-2.4.22-bk25/arch/ppc/config.in linux-2.4.22-bk26/arch/ppc/config.in --- linux-2.4.22-bk25/arch/ppc/config.in 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/config.in 2003-09-29 02:49:40.000000000 -0700 @@ -12,6 +12,7 @@ mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS endmenu mainmenu_option next_comment @@ -80,6 +81,7 @@ RPX-Classic CONFIG_RPXCLASSIC \ BSE-IP CONFIG_BSEIP \ FADS CONFIG_FADS \ + D-Box2 CONFIG_DBOX2 \ TQM823L CONFIG_TQM823L \ TQM850L CONFIG_TQM850L \ TQM855L CONFIG_TQM855L \ @@ -248,8 +250,49 @@ comment 'General setup' bool 'High memory support (experimental)' CONFIG_HIGHMEM +if [ "$CONFIG_ADVANCED_OPTIONS" = "y" ]; then + if [ "$CONFIG_HIGHMEM" = "y" ]; then + bool " Set high memory pool address" CONFIG_HIGHMEM_START_BOOL + if [ "$CONFIG_HIGHMEM_START_BOOL" = "y" ]; then + hex " Virtual start address of high memory pool" CONFIG_HIGHMEM_START 0xfe000000 + fi + fi + bool " Set maximum low memory" CONFIG_LOWMEM_SIZE_BOOL + if [ "$CONFIG_LOWMEM_SIZE_BOOL" = "y" ]; then + hex " Maximum low memory size (in bytes)" CONFIG_LOWMEM_SIZE 0x20000000 + fi + + bool "Set custom kernel base address" CONFIG_KERNEL_START_BOOL + if [ "$CONFIG_KERNEL_START_BOOL" = "y" ]; then + hex " Virtual address of kernel base" CONFIG_KERNEL_START 0xc0000000 + fi + bool "Set custom user task size" CONFIG_TASK_SIZE_BOOL + if [ "$CONFIG_TASK_SIZE_BOOL" = "y" ]; then + hex " Size of user task space" CONFIG_TASK_SIZE 0x80000000 + fi +fi + +if [ "$CONFIG_HIGHMEM_START_BOOL" != "y" ]; then + define_hex CONFIG_HIGHMEM_START 0xfe000000 +fi -define_bool CONFIG_ISA n +if [ "$CONFIG_LOWMEM_SIZE_BOOL" != "y" ]; then + define_hex CONFIG_LOWMEM_SIZE 0x30000000 +fi + +if [ "$CONFIG_KERNEL_START_BOOL" != "y" ]; then + define_hex CONFIG_KERNEL_START 0xc0000000 +fi + +if [ "$CONFIG_TASK_SIZE_BOOL" != "y" ]; then + define_hex CONFIG_TASK_SIZE 0x80000000 +fi + +if [ "$CONFIG_ALL_PPC" = "y" ]; then + bool 'Support for ISA-bus hardware' CONFIG_ISA +else + define_bool CONFIG_ISA n +fi define_bool CONFIG_EISA n define_bool CONFIG_SBUS n diff -urN linux-2.4.22-bk25/arch/ppc/configs/IVMS8_defconfig linux-2.4.22-bk26/arch/ppc/configs/IVMS8_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/IVMS8_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/IVMS8_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -506,14 +506,8 @@ # CONFIG_SOUND is not set # -# MPC8xx CPM Options +# MPC8xx Options # -# CONFIG_SCC_ENET is not set -CONFIG_FEC_ENET=y -CONFIG_USE_MDIO=y -CONFIG_ENET_BIG_BUFFERS=y -# CONFIG_SMC2_UART is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options @@ -523,6 +517,27 @@ # CONFIG_UCODE_PATCH is not set # +# MPC8xx CPM Options +# +# CONFIG_SCC_ENET is not set +CONFIG_FEC_ENET=y +CONFIG_USE_MDIO=y +# CONFIG_FEC_GENERIC_PHY is not set +# CONFIG_FEC_AM79C874 is not set +# CONFIG_FEC_LXT970 is not set +# CONFIG_FEC_QS6612 is not set +# CONFIG_FEC_LXT970 is not set +CONFIG_FEC_DP83843=y +# CONFIG_FEC_DP83846A is not set +CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y +# CONFIG_SMC2_UART is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC2 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set + +# # USB support # # CONFIG_USB is not set diff -urN linux-2.4.22-bk25/arch/ppc/configs/SM850_defconfig linux-2.4.22-bk26/arch/ppc/configs/SM850_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/SM850_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/SM850_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -470,6 +470,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +CONFIG_8xx_CPU6=y +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -481,14 +492,9 @@ CONFIG_SMC2_UART=y CONFIG_ALTSMC2=y CONFIG_CONS_SMC2=y -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -CONFIG_8xx_CPU6=y -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC2 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/SPD823TS_defconfig linux-2.4.22-bk26/arch/ppc/configs/SPD823TS_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/SPD823TS_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/SPD823TS_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -469,6 +469,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -477,17 +488,13 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y CONFIG_ALTSMC2=y # CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/TQM823L_defconfig linux-2.4.22-bk26/arch/ppc/configs/TQM823L_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/TQM823L_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/TQM823L_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -470,6 +470,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -478,17 +489,13 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y CONFIG_ALTSMC2=y # CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/TQM850L_defconfig linux-2.4.22-bk26/arch/ppc/configs/TQM850L_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/TQM850L_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/TQM850L_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -470,6 +470,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y diff -urN linux-2.4.22-bk25/arch/ppc/configs/TQM860L_defconfig linux-2.4.22-bk26/arch/ppc/configs/TQM860L_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/TQM860L_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/TQM860L_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -511,6 +511,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -519,17 +530,13 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y # CONFIG_ALTSMC2 is not set # CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC2 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/bseip_defconfig linux-2.4.22-bk26/arch/ppc/configs/bseip_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/bseip_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/bseip_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -469,6 +469,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -477,17 +488,13 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set # CONFIG_ENET_BIG_BUFFERS is not set +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y # CONFIG_ALTSMC2 is not set # CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/mbx_defconfig linux-2.4.22-bk26/arch/ppc/configs/mbx_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/mbx_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/mbx_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -465,6 +465,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +CONFIG_8xx_CPU6=y +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -473,17 +484,13 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y # CONFIG_ALTSMC2 is not set # CONFIG_CONS_SMC2 is not set -CONFIG_USE_SCC_IO=y - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -CONFIG_8xx_CPU6=y -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC2 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/rpxcllf_defconfig linux-2.4.22-bk26/arch/ppc/configs/rpxcllf_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/rpxcllf_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/rpxcllf_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -504,6 +504,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -513,17 +524,13 @@ CONFIG_FEC_ENET=y # CONFIG_USE_MDIO is not set CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xx_SMC1=y CONFIG_SMC2_UART=y # CONFIG_ALTSMC2 is not set # CONFIG_CONS_SMC2 is not set -CONFIG_USE_SCC_IO=y - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC2 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/configs/rpxlite_defconfig linux-2.4.22-bk26/arch/ppc/configs/rpxlite_defconfig --- linux-2.4.22-bk25/arch/ppc/configs/rpxlite_defconfig 2003-06-13 07:51:31.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/configs/rpxlite_defconfig 2003-09-29 02:49:40.000000000 -0700 @@ -504,6 +504,17 @@ # CONFIG_SOUND is not set # +# MPC8xx Options +# + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +# CONFIG_8xx_CPU6 is not set +# CONFIG_UCODE_PATCH is not set + +# # MPC8xx CPM Options # CONFIG_SCC_ENET=y @@ -512,15 +523,11 @@ # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set # CONFIG_ENET_BIG_BUFFERS is not set +CONFIG_8xx_SMC1=y # CONFIG_SMC2_UART is not set -# CONFIG_USE_SCC_IO is not set - -# -# Generic MPC8xx Options -# -CONFIG_8xx_COPYBACK=y -# CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set +# CONFIG_8xx_SCC1 is not set +# CONFIG_8xx_SCC3 is not set +# CONFIG_8xx_SCC4 is not set # # USB support diff -urN linux-2.4.22-bk25/arch/ppc/kernel/head_8xx.S linux-2.4.22-bk26/arch/ppc/kernel/head_8xx.S --- linux-2.4.22-bk25/arch/ppc/kernel/head_8xx.S 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/kernel/head_8xx.S 2003-09-29 02:49:41.000000000 -0700 @@ -21,9 +21,9 @@ * */ +#include #include #include -#include #include #include #include @@ -817,16 +817,31 @@ * kernel initialization. This maps the first 8 MBytes of memory 1:1 * virtual to physical. Also, set the cache mode since that is defined * by TLB entries and perform any additional mapping (like of the IMMR). + * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel, + * 24 Mbytes of data, and the 8M IMMR space. Anything not covered by + * these mappings is mapped by page tables. */ initial_mmu: tlbia /* Invalidate all TLB entries */ +#ifdef CONFIG_PIN_TLB + lis r8, MI_RSV4I@h + ori r8, r8, 0x1c00 +#else li r8, 0 - mtspr MI_CTR, r8 /* Set instruction control to zero */ - lis r8, MD_RESETVAL@h +#endif + mtspr MI_CTR, r8 /* Set instruction MMU control */ + +#ifdef CONFIG_PIN_TLB + lis r10, (MD_RSV4I | MD_RESETVAL)@h + ori r10, r10, 0x1c00 + mr r8, r10 +#else + lis r10, MD_RESETVAL@h +#endif #ifndef CONFIG_8xx_COPYBACK - oris r8, r8, MD_WTDEF@h + oris r10, r10, MD_WTDEF@h #endif - mtspr MD_CTR, r8 /* Set data TLB control */ + mtspr MD_CTR, r10 /* Set data TLB control */ /* Now map the lower 8 Meg into the TLBs. For this quick hack, * we can load the instruction and data TLB registers with the @@ -850,6 +865,10 @@ /* Map another 8 MByte at the IMMR to get the processor * internal registers (among other things). */ +#ifdef CONFIG_PIN_TLB + addi r10, r10, 0x0100 + mtspr MD_CTR, r10 +#endif mfspr r9, 638 /* Get current IMMR */ andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */ @@ -863,6 +882,30 @@ ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ mtspr MD_RPN, r8 +#ifdef CONFIG_PIN_TLB + /* Map two more 8M kernel data pages. + */ + addi r10, r10, 0x0100 + mtspr MD_CTR, r10 + + lis r8, KERNELBASE@h /* Create vaddr for TLB */ + addis r8, r8, 0x0080 /* Add 8M */ + ori r8, r8, MI_EVALID /* Mark it valid */ + mtspr MD_EPN, r8 + li r9, MI_PS8MEG /* Set 8M byte page */ + ori r9, r9, MI_SVALID /* Make it valid */ + mtspr MD_TWC, r9 + li r11, MI_BOOTINIT /* Create RPN for address 0 */ + addis r11, r11, 0x0080 /* Add 8M */ + mtspr MD_RPN, r8 + + addis r8, r8, 0x0080 /* Add 8M */ + mtspr MD_EPN, r8 + mtspr MD_TWC, r9 + addis r11, r11, 0x0080 /* Add 8M */ + mtspr MD_RPN, r8 +#endif + /* Since the cache is enabled according to the information we * just loaded into the TLB, invalidate and enable the caches here. * We should probably check/set other modes....later. diff -urN linux-2.4.22-bk25/arch/ppc/kernel/indirect_pci.c linux-2.4.22-bk26/arch/ppc/kernel/indirect_pci.c --- linux-2.4.22-bk25/arch/ppc/kernel/indirect_pci.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/kernel/indirect_pci.c 2003-09-29 02:49:41.000000000 -0700 @@ -24,6 +24,12 @@ #define cfg_read(val, addr, type, op) *val = op((type)(addr)) #define cfg_write(val, addr, type, op) op((type *)(addr), (val)) +#ifdef CONFIG_PPC_INDIRECT_PCI_BE +#define PCI_CFG_OUT out_be32 +#else +#define PCI_CFG_OUT out_le32 +#endif + #define INDIRECT_PCI_OP(rw, size, type, op, mask) \ static int \ indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ @@ -39,9 +45,9 @@ if (dev->bus->number != hose->first_busno) \ cfg_type = 1; \ \ - out_be32(hose->cfg_addr, \ - (((offset & 0xfc) | cfg_type) << 24) | (dev->devfn << 16) \ - | ((dev->bus->number - hose->bus_offset) << 8) | 0x80); \ + PCI_CFG_OUT(hose->cfg_addr, \ + (0x80000000 | ((dev->bus->number - hose->bus_offset) << 16) \ + | (dev->devfn << 8) | ((offset & 0xfc) | cfg_type))); \ cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ return PCIBIOS_SUCCESSFUL; \ } diff -urN linux-2.4.22-bk25/arch/ppc/kernel/irq.c linux-2.4.22-bk26/arch/ppc/kernel/irq.c --- linux-2.4.22-bk25/arch/ppc/kernel/irq.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/kernel/irq.c 2003-09-29 02:49:41.000000000 -0700 @@ -429,7 +429,7 @@ int status; struct irqaction *action; int cpu = smp_processor_id(); - irq_desc_t *desc = irq_desc + irq; + irq_desc_t *desc = &irq_desc[irq]; kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); @@ -501,12 +501,25 @@ * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. */ - if (irq_desc[irq].handler) { - if (irq_desc[irq].handler->end) - irq_desc[irq].handler->end(irq); - else if (irq_desc[irq].handler->enable) - irq_desc[irq].handler->enable(irq); + if (desc->handler) { + if (desc->handler->end) + desc->handler->end(irq); + else if (desc->handler->enable) + desc->handler->enable(irq); } + +#ifdef CONFIG_DBOX2 + /* + * Interrupts marked as oneshot are level + * triggered. We disable them here for onboard + * hardware which can not be configured to + * generate edge triggered interrupts due to + * lack of documentation. + */ + if ((action) && (action->flags & SA_ONESHOT)) + disable_irq_nosync(irq); +#endif + spin_unlock(&desc->lock); } diff -urN linux-2.4.22-bk25/arch/ppc/kernel/ppc_ksyms.c linux-2.4.22-bk26/arch/ppc/kernel/ppc_ksyms.c --- linux-2.4.22-bk25/arch/ppc/kernel/ppc_ksyms.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/kernel/ppc_ksyms.c 2003-09-29 02:49:41.000000000 -0700 @@ -162,7 +162,7 @@ EXPORT_SYMBOL(iopa); EXPORT_SYMBOL(mm_ptov); EXPORT_SYMBOL(ioremap); -#ifdef CONFIG_44x +#ifdef CONFIG_PTE_64BIT EXPORT_SYMBOL(ioremap64); #endif EXPORT_SYMBOL(__ioremap); @@ -356,6 +356,7 @@ EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); EXPORT_SYMBOL(m8xx_cpm_hostalloc); +EXPORT_SYMBOL(m8xx_cpm_dpalloc); #endif /* CONFIG_8xx */ /* Those should really be inline */ diff -urN linux-2.4.22-bk25/arch/ppc/mm/pgtable.c linux-2.4.22-bk26/arch/ppc/mm/pgtable.c --- linux-2.4.22-bk25/arch/ppc/mm/pgtable.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/ppc/mm/pgtable.c 2003-09-29 02:49:41.000000000 -0700 @@ -37,10 +37,11 @@ unsigned long ioremap_bot; int io_bat_index; -/* Maximum 768Mb of lowmem. On SMP, this value will be - * trimmed down to whatever can be covered by BATs though. +/* The maximum lowmem defaults to 768Mb, but this can be configured to + * another value. On SMP, this value will be trimmed down to whatever + * can be covered by BATs. */ -#define MAX_LOW_MEM 0x30000000 +#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE #ifndef CONFIG_SMP struct pgtable_cache_struct quicklists; @@ -67,7 +68,7 @@ #define p_mapped_by_bats(x) (0UL) #endif /* HAVE_BATS */ -#ifdef CONFIG_44x +#ifdef CONFIG_PTE_64BIT void * ioremap(phys_addr_t addr, unsigned long size) { @@ -82,14 +83,14 @@ return __ioremap(addr, size, _PAGE_NO_CACHE); } -#else /* CONFIG_44x */ +#else /* !CONFIG_PTE_64BIT */ void * ioremap(phys_addr_t addr, unsigned long size) { return __ioremap(addr, size, _PAGE_NO_CACHE); } -#endif /* CONFIG_44x */ +#endif /* CONFIG_PTE_64BIT */ void * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) diff -urN linux-2.4.22-bk25/arch/ppc/platforms/dbox2.h linux-2.4.22-bk26/arch/ppc/platforms/dbox2.h --- linux-2.4.22-bk25/arch/ppc/platforms/dbox2.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.4.22-bk26/arch/ppc/platforms/dbox2.h 2003-09-29 02:49:41.000000000 -0700 @@ -0,0 +1,24 @@ +/* + * D-BOX2 board specific definitions + * + * Copyright (c) 2001-2002 Florian Schirmer (jolt@tuxbox.org) + */ + +#ifndef __MACH_DBOX2_H +#define __MACH_DBOX2_H + +#include + +#include + +#define DBOX2_IMMR_BASE 0xFF000000 /* phys. addr of IMMR */ +#define DBOX2_IMAP_SIZE (64 * 1024) /* size of mapped area */ + +#define IMAP_ADDR DBOX2_IMMR_BASE /* physical base address of IMMR area */ +#define IMAP_SIZE DBOX2_IMAP_SIZE /* mapped size of IMMR area */ + +/* We don't use the 8259. +*/ +#define NR_8259_INTS 0 + +#endif /* __MACH_DBOX2_H */ diff -urN linux-2.4.22-bk25/arch/x86_64/Makefile linux-2.4.22-bk26/arch/x86_64/Makefile --- linux-2.4.22-bk25/arch/x86_64/Makefile 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/Makefile 2003-09-29 02:49:41.000000000 -0700 @@ -19,7 +19,7 @@ # 20010105 Andi Kleen, add IA32 compiler. # ....and later removed it again.... # -# $Id: Makefile,v 1.33 2003/05/12 14:36:34 ak Exp $ +# $Id: Makefile,v 1.34 2003/09/25 02:50:05 ak Exp $ # # early bootup linking needs 32bit. You can either use real 32bit tools @@ -38,6 +38,8 @@ LDFLAGS=-e stext LINKFLAGS =-T $(TOPDIR)/arch/x86_64/vmlinux.lds $(LDFLAGS) +check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi) + CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel CFLAGS += -pipe @@ -51,9 +53,7 @@ ifneq ($(CONFIG_X86_REMOTE_DEBUG),y) CFLAGS += -fno-asynchronous-unwind-tables endif - -# prevent gcc from keeping the stack 16 byte aligned (FIXME) -#CFLAGS += -mpreferred-stack-boundary=2 +CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff -urN linux-2.4.22-bk25/arch/x86_64/boot/setup.S linux-2.4.22-bk26/arch/x86_64/boot/setup.S --- linux-2.4.22-bk25/arch/x86_64/boot/setup.S 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/boot/setup.S 2003-09-29 02:49:41.000000000 -0700 @@ -524,7 +524,7 @@ cmpw $0, %cs:realmode_swtch jz rmodeswtch_normal - lcall %cs:realmode_swtch + lcall *%cs:realmode_swtch jmp rmodeswtch_end diff -urN linux-2.4.22-bk25/arch/x86_64/config.in linux-2.4.22-bk26/arch/x86_64/config.in --- linux-2.4.22-bk25/arch/x86_64/config.in 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/config.in 2003-09-29 02:49:41.000000000 -0700 @@ -66,7 +66,7 @@ define_bool CONFIG_X86_UP_IOAPIC y else define_bool CONFIG_HAVE_DEC_LOCK y - int 'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32 + int 'Maximum number of CPUs (2-8)' CONFIG_NR_CPUS 4 fi bool 'Machine check support' CONFIG_MCE diff -urN linux-2.4.22-bk25/arch/x86_64/defconfig linux-2.4.22-bk26/arch/x86_64/defconfig --- linux-2.4.22-bk25/arch/x86_64/defconfig 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/defconfig 2003-09-29 02:49:41.000000000 -0700 @@ -40,13 +40,15 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y -# CONFIG_SMP is not set -CONFIG_NR_CPUS=32 +CONFIG_SMP=y CONFIG_HPET_TIMER=y CONFIG_GART_IOMMU=y -CONFIG_X86_UP_IOAPIC=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_NR_CPUS=4 CONFIG_MCE=y -# CONFIG_K8_NUMA is not set +CONFIG_K8_NUMA=y +CONFIG_DISCONTIGMEM=y +CONFIG_NUMA=y # # General setup @@ -89,6 +91,7 @@ # CONFIG_ACPI_ASUS is not set # CONFIG_ACPI_TOSHIBA is not set CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_RELAXED_AML is not set # # Memory Technology Devices (MTD) @@ -109,6 +112,7 @@ # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_CISS_MONITOR_THREAD is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y @@ -307,6 +311,9 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -351,8 +358,9 @@ # # Fusion MPT device support # -# CONFIG_FUSION is not set -# CONFIG_FUSION_BOOT is not set +CONFIG_FUSION=y +CONFIG_FUSION_BOOT=y +CONFIG_FUSION_MAX_SGE=40 # CONFIG_FUSION_ISENSE is not set # CONFIG_FUSION_CTL is not set # CONFIG_FUSION_LAN is not set @@ -517,6 +525,7 @@ # CONFIG_SCx200_GPIO is not set # CONFIG_AMD_RNG is not set # CONFIG_INTEL_RNG is not set +CONFIG_HW_RANDOM=y # CONFIG_AMD_PM768 is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -529,7 +538,7 @@ # # CONFIG_FTAPE is not set CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y +CONFIG_AGP_AMD_K8=y CONFIG_AGP_INTEL=y CONFIG_AGP_I810=y CONFIG_AGP_VIA=y @@ -537,6 +546,12 @@ CONFIG_AGP_SIS=y CONFIG_AGP_ALI=y CONFIG_AGP_SWORKS=y +CONFIG_AGP_NVIDIA=y +# CONFIG_AGP_ATI is not set + +# +# Direct Rendering Manager (XFree86 DRI support) +# # CONFIG_DRM is not set # CONFIG_MWAVE is not set @@ -549,6 +564,7 @@ # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V2 is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set CONFIG_REISERFS_FS=y @@ -558,6 +574,7 @@ # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BEFS_DEBUG is not set # CONFIG_BFS_FS is not set @@ -599,6 +616,7 @@ # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set +# CONFIG_SIMICSFS is not set # # Network File Systems @@ -607,6 +625,7 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_DIRECTIO is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y @@ -704,17 +723,23 @@ # CONFIG_BLUEZ is not set # +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# # Kernel hacking # CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_SLAB=y CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_CHECKING is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_CHECKING=y # CONFIG_INIT_DEBUG is not set -# CONFIG_IOMMU_DEBUG is not set +CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_LEAK=y # CONFIG_DEBUG_STACKOVERFLOW is not set +CONFIG_LOG_BUF_SHIFT=17 # # Library routines diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/ia32_binfmt.c linux-2.4.22-bk26/arch/x86_64/ia32/ia32_binfmt.c --- linux-2.4.22-bk25/arch/x86_64/ia32/ia32_binfmt.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/ia32_binfmt.c 2003-09-29 02:49:41.000000000 -0700 @@ -28,7 +28,6 @@ #define ELF_NAME "elf/i386" -#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000) #define IA32_STACK_TOP IA32_PAGE_OFFSET #define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000) diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.22-bk26/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.4.22-bk25/arch/x86_64/ia32/ia32_ioctl.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/ia32_ioctl.c 2003-09-29 02:49:41.000000000 -0700 @@ -1,4 +1,4 @@ -/* $Id: ia32_ioctl.c,v 1.34 2003/05/08 06:34:01 ak Exp $ +/* $Id: ia32_ioctl.c,v 1.37 2003/08/20 11:00:23 ak Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2472,6 +2472,9 @@ mm_segment_t old_fs; void *karg = &u; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + switch (cmd) { case VG_STATUS: v = kmalloc(sizeof(vg_t), GFP_KERNEL); @@ -3535,6 +3538,7 @@ COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) +COMPATIBLE_IOCTL(FIOQSIZE) /* Big F */ COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) @@ -4416,6 +4420,9 @@ struct ioctl_trans *t; unsigned long hash = ioctl32_hash(cmd); + if (handler == NULL) + handler = (void *)sys_ioctl; + lock_kernel(); for (t = (struct ioctl_trans *)ioctl32_hash_table[hash]; t; @@ -4555,7 +4562,7 @@ "cmd(%08x){%s} arg(%08x) on %s\n", current->comm, current->pid, (int)fd, (unsigned int)cmd, buf, (unsigned int)arg, - IS_ERR(fn) ? "???" : fn); + fn); if (path) free_page((unsigned long)path); } diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/ia32_signal.c linux-2.4.22-bk26/arch/x86_64/ia32/ia32_signal.c --- linux-2.4.22-bk25/arch/x86_64/ia32/ia32_signal.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/ia32_signal.c 2003-09-29 02:49:41.000000000 -0700 @@ -7,7 +7,7 @@ * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen * - * $Id: ia32_signal.c,v 1.31 2003/03/12 08:22:12 ak Exp $ + * $Id: ia32_signal.c,v 1.32 2003/09/06 18:10:44 ak Exp $ */ #include @@ -78,6 +78,10 @@ default: err |= __put_user(from->si_uid, &to->si_uid); break; + case __SI_POLL >> 16: + err |= __put_user(from->si_band, &to->si_band); + err |= __put_user(from->si_fd, &to->si_fd); + break; /* case __SI_RT: This is not generated by the kernel as of now. */ } return err; diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/ia32entry.S linux-2.4.22-bk26/arch/x86_64/ia32/ia32entry.S --- linux-2.4.22-bk25/arch/x86_64/ia32/ia32entry.S 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/ia32entry.S 2003-09-29 02:49:41.000000000 -0700 @@ -3,7 +3,7 @@ * * Copyright 2000,2001 Andi Kleen, SuSE Labs. * - * $Id: ia32entry.S,v 1.40 2003/04/03 09:46:54 ak Exp $ + * $Id: ia32entry.S,v 1.41 2003/09/22 04:25:53 ak Exp $ */ #include @@ -256,10 +256,10 @@ .quad sys32_adjtimex .quad sys32_mprotect /* 125 */ .quad sys32_sigprocmask - .quad sys32_module_warning /* create_module */ - .quad sys32_module_warning /* init_module */ - .quad sys32_module_warning /* delete module */ - .quad sys32_module_warning /* 130 get_kernel_syms */ + .quad sys32_create_module + .quad sys32_init_module + .quad sys32_delete_module + .quad sys32_get_kernel_syms /* 130 */ .quad ni_syscall /* quotactl */ .quad sys_getpgid .quad sys_fchdir @@ -296,7 +296,7 @@ .quad sys_setresuid16 .quad sys_getresuid16 /* 165 */ .quad sys32_vm86_warning /* vm86 */ - .quad quiet_ni_syscall /* query_module */ + .quad sys32_query_module .quad sys_poll .quad sys32_nfsservctl .quad sys_setresgid16 /* 170 */ diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/ipc32.c linux-2.4.22-bk26/arch/x86_64/ia32/ipc32.c --- linux-2.4.22-bk25/arch/x86_64/ia32/ipc32.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/ipc32.c 2003-09-29 02:49:41.000000000 -0700 @@ -16,6 +16,8 @@ #include +extern int sem_ctls[]; + /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * @@ -163,6 +165,7 @@ #define SEMOP 1 #define SEMGET 2 #define SEMCTL 3 +#define SEMTIMEDOP 4 #define MSGSND 11 #define MSGRCV 12 #define MSGGET 13 @@ -638,7 +641,27 @@ switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - return sys_semop(first, (struct sembuf *)AA(ptr), second); + return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL); + case SEMTIMEDOP: { + int err; + mm_segment_t oldfs = get_fs(); + struct timespec32 *ts32 = (struct timespec32 *)AA(fifth); + struct timespec ts; + if ((unsigned)second > sem_ctls[2]) + return -EINVAL; + if (ts32) { + if (get_user(ts.tv_sec, &ts32->tv_sec) || + __get_user(ts.tv_nsec, &ts32->tv_nsec) || + verify_area(VERIFY_READ, (void *)AA(ptr), + second*sizeof(struct sembuf))) + return -EFAULT; + } + set_fs(KERNEL_DS); + err = sys_semtimedop(first, (struct sembuf *)AA(ptr), second, + ts32 ? &ts : NULL); + set_fs(oldfs); + return err; + } case SEMGET: return sys_semget(first, second, third); case SEMCTL: @@ -663,9 +686,7 @@ case SHMCTL: return shmctl32(first, second, (void *)AA(ptr)); - default: - return -EINVAL; } - return -EINVAL; + return -ENOSYS; } diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/socket32.c linux-2.4.22-bk26/arch/x86_64/ia32/socket32.c --- linux-2.4.22-bk25/arch/x86_64/ia32/socket32.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/socket32.c 2003-09-29 02:49:41.000000000 -0700 @@ -503,7 +503,6 @@ __u32 filter; } *fprog32 = (struct sock_fprog32 *)optval; struct sock_fprog kfprog; - unsigned int fsize; mm_segment_t old_fs; __u32 uptr; int ret; diff -urN linux-2.4.22-bk25/arch/x86_64/ia32/sys_ia32.c linux-2.4.22-bk26/arch/x86_64/ia32/sys_ia32.c --- linux-2.4.22-bk25/arch/x86_64/ia32/sys_ia32.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/ia32/sys_ia32.c 2003-09-29 02:49:41.000000000 -0700 @@ -16,7 +16,7 @@ * * This file assumes that there is a hole at the end of user address space. * - * $Id: sys_ia32.c,v 1.58 2003/05/09 17:21:17 ak Exp $ + * $Id: sys_ia32.c,v 1.62 2003/09/22 04:25:53 ak Exp $ */ #include @@ -475,7 +475,13 @@ __put_user (kbuf->f_ffree, &ubuf->f_ffree) || __put_user (kbuf->f_namelen, &ubuf->f_namelen) || __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || - __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1])) + __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || + __put_user (0, &ubuf->f_spare[0]) || + __put_user (0, &ubuf->f_spare[1]) || + __put_user (0, &ubuf->f_spare[2]) || + __put_user (0, &ubuf->f_spare[3]) || + __put_user (0, &ubuf->f_spare[4]) || + __put_user (0, &ubuf->f_spare[5])) return -EFAULT; return 0; } @@ -925,11 +931,6 @@ (struct timeval32 *)A(a.tvp)); } -struct timespec32 { - int tv_sec; - int tv_nsec; -}; - extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); asmlinkage long @@ -1517,10 +1518,30 @@ struct sysinfo s; int ret; mm_segment_t old_fs = get_fs (); + int bitcount = 0; set_fs (KERNEL_DS); ret = sys_sysinfo(&s); set_fs (old_fs); + + /* Check to see if any memory value is too large for 32-bit and scale + * down if needed + */ + if ((s.totalram >> 32) || (s.totalswap >> 32)) { + while (s.mem_unit < PAGE_SIZE) { + s.mem_unit <<= 1; + bitcount++; + } + s.totalram >>= bitcount; + s.freeram >>= bitcount; + s.sharedram >>= bitcount; + s.bufferram >>= bitcount; + s.totalswap >>= bitcount; + s.freeswap >>= bitcount; + s.totalhigh >>= bitcount; + s.freehigh >>= bitcount; + } + if (verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo32)) || __put_user (s.uptime, &info->uptime) || __put_user (s.loads[0], &info->loads[0]) || @@ -2534,17 +2555,422 @@ } #endif -long sys32_module_warning(void) +#ifdef CONFIG_MODULES + +extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size); + +asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size) { - static long warn_time = -(60*HZ); - if (time_before(warn_time + 60*HZ,jiffies) && strcmp(current->comm,"klogd")) { - printk(KERN_INFO "%s: 32bit modutils not supported on 64bit kernel\n", - current->comm); - warn_time = jiffies; + return sys_create_module(name_user, (size_t)size); +} + +extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); + +/* Hey, when you're trying to init module, take time and prepare us a nice 64bit + * module structure, even if from 32bit modutils... Why to pollute kernel... :)) + */ +asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user) +{ + return sys_init_module(name_user, mod_user); +} + +extern asmlinkage int sys_delete_module(const char *name_user); + +asmlinkage int sys32_delete_module(const char *name_user) +{ + return sys_delete_module(name_user); +} + +struct module_info32 { + u32 addr; + u32 size; + u32 flags; + s32 usecount; +}; + +/* Query various bits about modules. */ + +static inline long +get_mod_name(const char *user_name, char **buf) +{ + unsigned long page; + long retval; + + if ((unsigned long)user_name >= TASK_SIZE + && !segment_eq(get_fs (), KERNEL_DS)) + return -EFAULT; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE); + if (retval > 0) { + if (retval < PAGE_SIZE) { + *buf = (char *)page; + return retval; } - return -ENOSYS ; + retval = -ENAMETOOLONG; + } else if (!retval) + retval = -EINVAL; + + free_page(page); + return retval; +} + +static inline void +put_mod_name(char *buf) +{ + free_page((unsigned long)buf); } +static __inline__ struct module *find_module(const char *name) +{ + struct module *mod; + + for (mod = module_list; mod ; mod = mod->next) { + if (mod->flags & MOD_DELETED) + continue; + if (!strcmp(mod->name, name)) + break; + } + + return mod; +} + +static int +qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + struct module *mod; + size_t nmod, space, len; + + nmod = space = 0; + + for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) { + len = strlen(mod->name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, mod->name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(nmod, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((mod = mod->next)->next != NULL) + space += strlen(mod->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t i, space, len; + + if (mod->next == NULL) + return -EINVAL; + if (!MOD_CAN_QUERY(mod)) + return put_user(0, ret); + + space = 0; + for (i = 0; i < mod->ndeps; ++i) { + const char *dep_name = mod->deps[i].dep->name; + + len = strlen(dep_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, dep_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + return put_user(i, ret); + +calc_space_needed: + space += len; + while (++i < mod->ndeps) + space += strlen(mod->deps[i].dep->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t nrefs, space, len; + struct module_ref *ref; + + if (mod->next == NULL) + return -EINVAL; + if (!MOD_CAN_QUERY(mod)) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = 0; + for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { + const char *ref_name = ref->ref->name; + + len = strlen(ref_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, ref_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(nrefs, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((ref = ref->next_ref) != NULL) + space += strlen(ref->ref->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t i, space, len; + struct module_symbol *s; + char *strings; + unsigned *vals; + + if (!MOD_CAN_QUERY(mod)) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = mod->nsyms * 2*sizeof(u32); + + i = len = 0; + s = mod->syms; + + if (space > bufsize) + goto calc_space_needed; + + if (!access_ok(VERIFY_WRITE, buf, space)) + return -EFAULT; + + bufsize -= space; + vals = (unsigned *)buf; + strings = buf+space; + + for (; i < mod->nsyms ; ++i, ++s, vals += 2) { + len = strlen(s->name)+1; + if (len > bufsize) + goto calc_space_needed; + + if (copy_to_user(strings, s->name, len) + || __put_user(s->value, vals+0) + || __put_user(space, vals+1)) + return -EFAULT; + + strings += len; + bufsize -= len; + space += len; + } + + if (put_user(i, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + for (; i < mod->nsyms; ++i, ++s) + space += strlen(s->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + int error = 0; + + if (mod->next == NULL) + return -EINVAL; + + if (sizeof(struct module_info32) <= bufsize) { + struct module_info32 info; + info.addr = (unsigned long)mod; + info.size = mod->size; + info.flags = mod->flags; + info.usecount = + ((mod_member_present(mod, can_unload) + && mod->can_unload) + ? -1 : atomic_read(&mod->uc.usecount)); + + if (copy_to_user(buf, &info, sizeof(struct module_info32))) + return -EFAULT; + } else + error = -ENOSPC; + + if (put_user(sizeof(struct module_info32), ret)) + return -EFAULT; + + return error; +} + +asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret) +{ + struct module *mod; + int err; + + lock_kernel(); + if (name_user == 0) { + /* This finds "kernel_module" which is not exported. */ + for(mod = module_list; mod->next != NULL; mod = mod->next) + ; + } else { + long namelen; + char *name; + + if ((namelen = get_mod_name(name_user, &name)) < 0) { + err = namelen; + goto out; + } + err = -ENOENT; + if (namelen == 0) { + /* This finds "kernel_module" which is not exported. */ + for(mod = module_list; mod->next != NULL; mod = mod->next) + ; + } else if ((mod = find_module(name)) == NULL) { + put_mod_name(name); + goto out; + } + put_mod_name(name); + } + + switch (which) + { + case 0: + err = 0; + break; + case QM_MODULES: + err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret)); + break; + case QM_DEPS: + err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); + break; + case QM_REFS: + err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); + break; + case QM_SYMBOLS: + err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); + break; + case QM_INFO: + err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); + break; + default: + err = -EINVAL; + break; + } +out: + unlock_kernel(); + return err; +} + +struct kernel_sym32 { + u32 value; + char name[60]; +}; + +extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); + +asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) +{ + int len, i; + struct kernel_sym *tbl; + mm_segment_t old_fs; + + len = sys_get_kernel_syms(NULL); + if (!table) return len; + tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); + if (!tbl) return -ENOMEM; + old_fs = get_fs(); + set_fs (KERNEL_DS); + sys_get_kernel_syms(tbl); + set_fs (old_fs); + for (i = 0; i < len; i++, table++) { + if (put_user (tbl[i].value, &table->value) || + copy_to_user (table->name, tbl[i].name, 60)) + break; + } + kfree (tbl); + return i; +} + +#else /* CONFIG_MODULES */ + +asmlinkage unsigned long +sys32_create_module(const char *name_user, size_t size) +{ + return -ENOSYS; +} + +asmlinkage int +sys32_init_module(const char *name_user, struct module *mod_user) +{ + return -ENOSYS; +} + +asmlinkage int +sys32_delete_module(const char *name_user) +{ + return -ENOSYS; +} + +asmlinkage int +sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, + size_t *ret) +{ + /* Let the program know about the new interface. Not that + it'll do them much good. */ + if (which == 0) + return 0; + + return -ENOSYS; +} + +asmlinkage int +sys32_get_kernel_syms(struct kernel_sym *table) +{ + return -ENOSYS; +} + +#endif /* CONFIG_MODULES */ + long sys32_vm86_warning(void) { static long warn_time = -(60*HZ); @@ -2565,7 +2991,7 @@ static int __init ia32_init (void) { - printk("IA32 emulation $Id: sys_ia32.c,v 1.58 2003/05/09 17:21:17 ak Exp $\n"); + printk("IA32 emulation $Id: sys_ia32.c,v 1.62 2003/09/22 04:25:53 ak Exp $\n"); ia32_exec_domain.signal_map = default_exec_domain.signal_map; ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; register_exec_domain(&ia32_exec_domain); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/acpi.c linux-2.4.22-bk26/arch/x86_64/kernel/acpi.c --- linux-2.4.22-bk25/arch/x86_64/kernel/acpi.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/acpi.c 2003-09-29 02:49:41.000000000 -0700 @@ -44,6 +44,7 @@ #include #include +extern int acpi_disabled; #define PREFIX "ACPI: " @@ -352,6 +353,28 @@ #ifdef CONFIG_X86_LOCAL_APIC /* + * ACPI interpreter is required to complete interrupt setup, + * so if it is off, don't enumerate the io-apics with ACPI. + * If MPS is present, it will handle them, + * otherwise the system will stay in PIC mode + */ + if (acpi_disabled) { + return 1; + } + + if (!use_acpi_pci) + return 0; + + /* If "nolocalapic" is specified don't look further */ + extern int apic_disabled; + if (apic_disabled) { + printk(KERN_INFO PREFIX "Skipping Local/IO-APIC probe due to \"nolocalapic\"\n"); + return 0; + } + printk(KERN_INFO PREFIX "Parsing Local APIC info in MADT\n"); + + + /* * MADT * ---- * Parse the Multiple APIC Description Table (MADT), if exists. @@ -412,6 +435,15 @@ #ifdef CONFIG_X86_IO_APIC /* + * if "noapic" boot option, don't look for IO-APICs + */ + if (ioapic_setup_disabled()) { + printk(KERN_INFO PREFIX "Skipping IOAPIC probe " + "due to 'noapic' option.\n"); + return 1; + } + + /* * I/O APIC * -------- */ diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/acpi_wakeup.S linux-2.4.22-bk26/arch/x86_64/kernel/acpi_wakeup.S --- linux-2.4.22-bk25/arch/x86_64/kernel/acpi_wakeup.S 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/acpi_wakeup.S 2003-09-29 02:49:41.000000000 -0700 @@ -209,7 +209,7 @@ movw $0x0e00 + '!', %ds:(0xb801a) movq saved_eip, %rax - jmp %rax + jmp *%rax .code32 diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/bluesmoke.c linux-2.4.22-bk26/arch/x86_64/kernel/bluesmoke.c --- linux-2.4.22-bk25/arch/x86_64/kernel/bluesmoke.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/bluesmoke.c 2003-09-29 02:49:41.000000000 -0700 @@ -186,7 +186,7 @@ [0] = "err cpu1", }; -static void check_k8_nb(void) +static void check_k8_nb(int header) { struct pci_dev *nb; nb = find_k8_nb(); @@ -198,6 +198,9 @@ pci_read_config_dword(nb, 0x4c, &statushigh); if (!(statushigh & (1<<31))) return; + if (header) + printk(KERN_ERR "CPU %d: Silent Northbridge MCE\n", smp_processor_id()); + printk(KERN_ERR "Northbridge status %08x%08x\n", statushigh,statuslow); @@ -257,9 +260,11 @@ rdmsrl(MSR_IA32_MCG_STATUS, status); if ((status & (1<<2)) == 0) { if (!regs) - check_k8_nb(); + check_k8_nb(1); return; } + printk(KERN_EMERG "CPU %d: Machine Check Exception: %016Lx\n", smp_processor_id(), status); + if (status & 1) printk(KERN_EMERG "MCG_STATUS: unrecoverable\n"); @@ -277,7 +282,7 @@ if (nbstatus & (1UL<57)) printk(KERN_EMERG "Unrecoverable condition\n"); - check_k8_nb(); + check_k8_nb(0); if (nbstatus & (1UL<<58)) { u64 adr; @@ -338,7 +343,6 @@ { u64 cap; int i; - struct pci_dev *nb; if (!test_bit(X86_FEATURE_MCE, &c->x86_capability) || !test_bit(X86_FEATURE_MCA, &c->x86_capability)) diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/e820.c linux-2.4.22-bk26/arch/x86_64/kernel/e820.c --- linux-2.4.22-bk25/arch/x86_64/kernel/e820.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/e820.c 2003-09-29 02:49:41.000000000 -0700 @@ -1,7 +1,7 @@ /* * Handle the memory map. * The functions here do the job until bootmem takes over. - * $Id: e820.c,v 1.6 2002/10/15 09:35:16 ak Exp $ + * $Id: e820.c,v 1.10 2003/09/25 03:22:05 ak Exp $ */ #include #include @@ -12,6 +12,7 @@ #include #include #include +#include #include extern unsigned long table_start, table_end; @@ -488,7 +489,6 @@ mem_size = ALT_MEM_K; who = "BIOS-e801"; } - e820.nr_map = 0; add_memory_region(0, LOWMEMSIZE(), E820_RAM); add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); @@ -500,7 +500,6 @@ extern char command_line[], saved_command_line[]; extern int fallback_aper_order; extern int iommu_setup(char *opt); -extern int acpi_disabled; void __init parse_mem_cmdline (char ** cmdline_p) { @@ -541,6 +540,22 @@ #endif else if (!memcmp(from, "acpi=off", 8)) acpi_disabled = 1; + else if (!memcmp(from,"maxcpus=0",9)) { + disable_ioapic_setup(); + apic_disabled = 1; + } + + else if (!memcmp(from, "noapic", 6)) + disable_ioapic_setup(); + else if (!memcmp(from, "nolocalapic", 11) || !memcmp(from,"nolapic",7)) + apic_disabled = 1; + else if (!memcmp(from, "pci=noacpi", 10)) + use_acpi_pci = 0; + else if (!memcmp(from,"apic",4)) { + extern int ioapic_force; + ioapic_force = 1; + skip_ioapic_setup = 0; + } next: c = *(from++); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/head.S linux-2.4.22-bk26/arch/x86_64/kernel/head.S --- linux-2.4.22-bk25/arch/x86_64/kernel/head.S 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/head.S 2003-09-29 02:49:41.000000000 -0700 @@ -6,7 +6,7 @@ * Copyright (C) 2000 Karsten Keil * Copyright (C) 2001,2002 Andi Kleen * - * $Id: head.S,v 1.56 2003/05/12 14:38:43 ak Exp $ + * $Id: head.S,v 1.57 2003/07/11 15:58:46 ak Exp $ */ @@ -312,7 +312,8 @@ ENTRY(level3_physmem_pgt) .quad 0x0000000000105007 /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */ -.org 0xb000 + .org 0xb000 +#ifdef CONFIG_ACPI_SLEEP ENTRY(wakeup_level4_pgt) .quad 0x0000000000102007 /* -> level3_ident_pgt */ .fill 255,8,0 @@ -320,6 +321,7 @@ .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ .quad 0x0000000000103007 /* -> level3_kernel_pgt */ +#endif .data diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/io_apic.c linux-2.4.22-bk26/arch/x86_64/kernel/io_apic.c --- linux-2.4.22-bk25/arch/x86_64/kernel/io_apic.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/io_apic.c 2003-09-29 02:49:41.000000000 -0700 @@ -165,6 +165,14 @@ struct IO_APIC_route_entry entry; unsigned long flags; + /* Check delivery_mode to be sure we're not clearing an SMI pin */ + spin_lock_irqsave(&ioapic_lock, flags); + *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); + *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); + if (entry.delivery_mode == dest_SMI) + return; + /* * Disable it in the IO-APIC irq-routing table: */ @@ -194,9 +202,11 @@ int pirq_entries [MAX_PIRQS]; int pirqs_enabled; int skip_ioapic_setup; +int ioapic_force; static int __init noioapic_setup(char *str) { + ioapic_force = 1; skip_ioapic_setup = 1; return 1; } @@ -205,12 +215,66 @@ static int __init ioapic_setup(char *str) { + ioapic_force = 1; skip_ioapic_setup = 0; return 1; } __setup("apic", ioapic_setup); +#ifndef CONFIG_SMP +#include +#include +#include + +/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC + off. Check for an Nvidia or VIA PCI bridge and turn it off. + Use pci direct infrastructure because this runs before the PCI subsystem. + + Can be overwritten with "apic" */ +void __init check_ioapic(void) +{ + int num,slot,func; + if (ioapic_force) + return; + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u32 vendor; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) + continue; + + vendor = read_pci_config(num, slot, func, + PCI_VENDOR_ID); + vendor &= 0xffff; + switch (vendor) { + case PCI_VENDOR_ID_NVIDIA: + case PCI_VENDOR_ID_VIA: + printk(KERN_INFO + "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", + num,slot,vendor); + skip_ioapic_setup = 1; + return; + } + + /* No multi-function device? */ + u8 type = read_pci_config_byte(num,slot,func, + PCI_HEADER_TYPE); + if (!(type & 0x80)) + break; + } + } + } +} +#endif static int __init ioapic_pirq_setup(char *str) { diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/ioport.c linux-2.4.22-bk26/arch/x86_64/kernel/ioport.c --- linux-2.4.22-bk25/arch/x86_64/kernel/ioport.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/ioport.c 2003-09-29 02:49:41.000000000 -0700 @@ -19,35 +19,13 @@ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) { - unsigned long mask; - unsigned long *bitmap_base = bitmap + base / sizeof(long); - unsigned low_index = base & (BITS_PER_LONG - 1); - int length = low_index + extent; - - if (low_index != 0) { - mask = (~0UL << low_index); - if (length < 64) - mask &= ~(~0UL << length); + int i; if (new_value) - *bitmap_base++ |= mask; + for (i = base; i < base + extent; i++) + __set_bit(i, bitmap); else - *bitmap_base++ &= ~mask; - length -= 64; - } - - mask = (new_value ? ~0UL : 0UL); - while (length >= 64) { - *bitmap_base++ = mask; - length -= 64; - } - - if (length > 0) { - mask = ~(~0UL << length); - if (new_value) - *bitmap_base++ |= mask; - else - *bitmap_base++ &= ~mask; - } + for (i = base; i < base + extent; i++) + clear_bit(i, bitmap); } /* diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/mpparse.c linux-2.4.22-bk26/arch/x86_64/kernel/mpparse.c --- linux-2.4.22-bk25/arch/x86_64/kernel/mpparse.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/mpparse.c 2003-09-29 02:49:41.000000000 -0700 @@ -139,9 +139,12 @@ str[6] = 0; Dprintk("Bus #%d is %s\n", m->mpc_busid, str); - if (m->mpc_busid >= MAX_MP_BUSSES) { +#if MAX_MP_BUSSES < 256 + if ((long)m->mpc_busid >= MAX_MP_BUSSES) { printk(KERN_ERR "MAX_MP_BUSSES ERROR mpc_busid %d, max %d\n", m->mpc_busid, MAX_MP_BUSSES); - } else if (strncmp(str, "ISA", 3) == 0) { + } else +#endif + if (strncmp(str, "ISA", 3) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; } else if (strncmp(str, "EISA", 4) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; @@ -756,7 +759,7 @@ mp_ioapic_routing[idx].irq_end = irq_base + io_apic_get_redir_entries(idx); - printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " + printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].irq_start, @@ -883,8 +886,6 @@ #ifndef CONFIG_ACPI_HT_ONLY -/* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ - extern FADT_DESCRIPTOR acpi_fadt; void __init mp_config_ioapic_for_sci(int irq) @@ -893,6 +894,7 @@ int ioapic_pin; struct acpi_table_madt* madt; struct acpi_table_int_src_ovr *entry = NULL; + acpi_interrupt_flags flags; void *madt_end; acpi_status status; @@ -911,23 +913,42 @@ while ((void *) entry < madt_end) { if (entry->header.type == ACPI_MADT_INT_SRC_OVR && - acpi_fadt.sci_int == entry->global_irq) - return; + acpi_fadt.sci_int == entry->bus_irq) + goto found; entry = (struct acpi_table_int_src_ovr *) ((unsigned long) entry + entry->header.length); } } + /* + * Although the ACPI spec says that the SCI should be level/low + * don't reprogram it unless there is an explicit MADT OVR entry + * instructing us to do so -- otherwise we break Tyan boards which + * have the SCI wired edge/high but no MADT OVR. + */ + return; + +found: + /* + * See the note at the end of ACPI 2.0b section + * 5.2.10.8 for what this is about. + */ + flags = entry->flags; + acpi_fadt.sci_int = entry->global_irq; + irq = entry->global_irq; ioapic = mp_find_ioapic(irq); ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; - io_apic_set_pci_routing(ioapic, ioapic_pin, irq, 1, 1); + io_apic_set_pci_routing(ioapic, ioapic_pin, irq, + (flags.trigger >> 1) , (flags.polarity >> 1)); } #endif /*CONFIG_ACPI_HT_ONLY*/ +int acpi_tolerant; + #ifdef CONFIG_ACPI_PCI void __init mp_parse_prt (void) @@ -961,6 +982,13 @@ } irq = entry->link.index; + + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == irq) { + entry->irq = irq; /*we still need to set entry's irq*/ + continue; + } + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/nmi.c linux-2.4.22-bk26/arch/x86_64/kernel/nmi.c --- linux-2.4.22-bk25/arch/x86_64/kernel/nmi.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/nmi.c 2003-09-29 02:49:41.000000000 -0700 @@ -30,6 +30,7 @@ unsigned int nmi_watchdog = NMI_LOCAL_APIC; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +int panic_on_timeout; int nmi_watchdog_disabled; @@ -121,6 +122,13 @@ { int nmi; + if (!strncmp(str,"panic",5)) { + panic_on_timeout = 1; + str = strchr(str, ','); + if (!str) + return 1; + ++str; + } get_option(&str, &nmi); if (nmi >= NMI_INVALID) @@ -380,6 +388,8 @@ bust_spinlocks(1); printk("NMI Watchdog detected LOCKUP on CPU%d, eip %16lx, registers:\n", cpu, regs->rip); show_registers(regs); + if (panic_on_timeout) + panic("NMI lockup"); printk("console shuts up ...\n"); console_silent(); spin_unlock(&nmi_print_lock); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/pci-gart.c linux-2.4.22-bk26/arch/x86_64/kernel/pci-gart.c --- linux-2.4.22-bk25/arch/x86_64/kernel/pci-gart.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/pci-gart.c 2003-09-29 02:49:41.000000000 -0700 @@ -8,7 +8,7 @@ * See Documentation/DMA-mapping.txt for the interface specification. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: pci-gart.c,v 1.27 2003/08/05 18:25:31 ak Exp $ + * $Id: pci-gart.c,v 1.28 2003/09/19 07:01:58 ak Exp $ */ #include @@ -588,9 +588,12 @@ if (!memcmp(p, "memaper", 7)) { fallback_aper_force = 1; p += 7; - if (*p == '=' && get_option(&p, &arg)) + if (*p == '=') { + ++p; + if (get_option(&p, &arg)) fallback_aper_order = arg; } + } #ifdef CONFIG_IOMMU_LEAK if (!memcmp(p,"leak", 4)) { leak_trace = 1; diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/pci-pc.c linux-2.4.22-bk26/arch/x86_64/kernel/pci-pc.c --- linux-2.4.22-bk25/arch/x86_64/kernel/pci-pc.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/pci-pc.c 2003-09-29 02:49:41.000000000 -0700 @@ -23,9 +23,11 @@ #include #include #include +#include #include "pci-x86_64.h" +int use_acpi_pci = 1; unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2; int pcibios_last_bus = -1; @@ -588,7 +590,7 @@ printk(KERN_INFO "PCI: Probing PCI hardware\n"); #ifdef CONFIG_ACPI_PCI - if (!acpi_pci_irq_init()) + if (!acpi_disabled && use_acpi_pci && !acpi_pci_irq_init()) pci_using_acpi_prt = 1; #endif if (!pci_using_acpi_prt) { @@ -661,7 +663,7 @@ return err; #ifdef CONFIG_ACPI_PCI - if (pci_using_acpi_prt) { + if (use_acpi_pci && pci_using_acpi_prt) { acpi_pci_irq_enable(dev); return 0; } diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/pci-x86_64.c linux-2.4.22-bk26/arch/x86_64/kernel/pci-x86_64.c --- linux-2.4.22-bk25/arch/x86_64/kernel/pci-x86_64.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/pci-x86_64.c 2003-09-29 02:49:41.000000000 -0700 @@ -294,6 +294,17 @@ } } +void __init pcibios_set_cacheline_size(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + pci_cache_line_size = 32 >> 2; + if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) + pci_cache_line_size = 64 >> 2; /* K7 & K8 */ + else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) + pci_cache_line_size = 128 >> 2; /* P4 */ +} + void __init pcibios_resource_survey(void) { DBG("PCI: Allocating resources\n"); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/pci-x86_64.h linux-2.4.22-bk26/arch/x86_64/kernel/pci-x86_64.h --- linux-2.4.22-bk25/arch/x86_64/kernel/pci-x86_64.h 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/pci-x86_64.h 2003-09-29 02:49:41.000000000 -0700 @@ -27,8 +27,10 @@ /* pci-i386.c */ extern unsigned int pcibios_max_latency; +extern u8 pci_cache_line_size; void pcibios_resource_survey(void); +void pcibios_set_cacheline_size(void); int pcibios_enable_resources(struct pci_dev *, int mask); /* pci-pc.c */ diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/process.c linux-2.4.22-bk26/arch/x86_64/kernel/process.c --- linux-2.4.22-bk25/arch/x86_64/kernel/process.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/process.c 2003-09-29 02:49:41.000000000 -0700 @@ -9,7 +9,7 @@ * X86-64 port * Andi Kleen. * - * $Id: process.c,v 1.70 2003/06/09 05:18:21 ak Exp $ + * $Id: process.c,v 1.74 2003/08/13 13:43:16 ak Exp $ */ /* @@ -168,7 +168,7 @@ static int reboot_mode = 0; /* reboot=b[ios] | t[riple] | k[bd] [, [w]arm | [c]old] - bios Use the CPU reboto vector for warm reset + bios Use the CPU reboot vector for warm reset warm Don't set the cold reboot flag cold Set the cold reboto flag triple Force a triple fault (init) @@ -227,7 +227,7 @@ [target] "b" (WARMBOOT_TRAMP)); } -static inline void kb_wait(void) +static void kb_wait(void) { int i; @@ -252,6 +252,7 @@ /* AP calling this. Just halt */ if (cpuid != boot_cpu_id) { + printk("CPU %d SMP halt\n", cpuid); for (;;) asm("hlt"); } diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/setup.c linux-2.4.22-bk26/arch/x86_64/kernel/setup.c --- linux-2.4.22-bk25/arch/x86_64/kernel/setup.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/setup.c 2003-09-29 02:49:41.000000000 -0700 @@ -295,6 +295,11 @@ #endif paging_init(); +#if !defined(CONFIG_SMP) && defined(CONFIG_X86_IO_APIC) + extern void check_ioapic(void); + check_ioapic(); +#endif + #ifdef CONFIG_ACPI_BOOT /* * Parse the ACPI tables for possible boot-time SMP configuration. @@ -377,7 +382,10 @@ c->x86_cache_size=(ecx>>24)+(edx>>24); if (n >= 0x80000006) { printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line/%d way)\n", - ecx_2>>16, ecx_2&0xFF, (ecx_2>>12)&0xf); + ecx_2>>16, ecx_2&0xFF, + /* use bits[15:13] as power of 2 for # of ways */ + 1 << ((ecx>>13) & 0x7) + /* Direct and Full associative L2 are very unlikely */); c->x86_cache_size = ecx_2 >> 16; c->x86_tlbsize = ((ebx>>16)&0xff) + ((ebx_2>>16)&0xfff) + (ebx&0xff) + ((ebx_2)&0xfff); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/setup64.c linux-2.4.22-bk26/arch/x86_64/kernel/setup64.c --- linux-2.4.22-bk25/arch/x86_64/kernel/setup64.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/setup64.c 2003-09-29 02:49:41.000000000 -0700 @@ -3,7 +3,7 @@ * Copyright (C) 1995 Linus Torvalds * Copyright 2001, 2002 SuSE Labs / Andi Kleen. * See setup.c for older changelog. - * $Id: setup64.c,v 1.23 2003/05/16 14:22:27 ak Exp $ + * $Id: setup64.c,v 1.25 2003/07/11 15:58:47 ak Exp $ */ #include #include diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/signal.c linux-2.4.22-bk26/arch/x86_64/kernel/signal.c --- linux-2.4.22-bk25/arch/x86_64/kernel/signal.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/signal.c 2003-09-29 02:49:41.000000000 -0700 @@ -8,7 +8,7 @@ * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-2001 x86-64 support by Andi Kleen * - * $Id: signal.c,v 1.42 2003/02/24 21:06:02 ak Exp $ + * $Id: signal.c,v 1.43 2003/09/06 18:10:44 ak Exp $ */ #include @@ -71,6 +71,10 @@ default: err |= __put_user(from->si_uid, &to->si_uid); break; + case __SI_POLL >> 16: + err |= __put_user(from->si_band, &to->si_band); + err |= __put_user(from->si_fd, &to->si_fd); + break; /* case __SI_RT: This is not generated by the kernel as of now. */ } return err; diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/smpboot.c linux-2.4.22-bk26/arch/x86_64/kernel/smpboot.c --- linux-2.4.22-bk25/arch/x86_64/kernel/smpboot.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/smpboot.c 2003-09-29 02:49:41.000000000 -0700 @@ -50,6 +50,7 @@ #include #include #include +#include /* Setup configured maximum number of CPUs to activate */ static int max_cpus = -1; @@ -863,7 +864,7 @@ * If we couldnt find an SMP configuration at boot time, * get out of here now! */ - if (!smp_found_config) { + if (!smp_found_config && !acpi_lapic) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); io_apic_irqs = 0; cpu_online_map = phys_cpu_present_map = 1; @@ -907,10 +908,8 @@ if (!max_cpus) { smp_found_config = 0; printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); - io_apic_irqs = 0; cpu_online_map = phys_cpu_present_map = 1; smp_num_cpus = 1; - apic_disabled = 1; goto smp_done; } @@ -1012,6 +1011,9 @@ if (cpu_has_tsc && cpucount) synchronize_tsc_bp(); + if (nmi_watchdog != 0) + check_nmi_watchdog(); + smp_done: zap_low_mappings(); time_init_smp(); diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/suspend.c linux-2.4.22-bk26/arch/x86_64/kernel/suspend.c --- linux-2.4.22-bk25/arch/x86_64/kernel/suspend.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/suspend.c 2003-09-29 02:49:41.000000000 -0700 @@ -5,6 +5,9 @@ * * Copyright (c) 2002 Pavel Machek * Copyright (c) 2001 Patrick Mochel + * + * AK currently useless for 24 because the core ACPI code doesn't support S3. + * and most of the infrastructure is missing. */ #include diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/sys_x86_64.c linux-2.4.22-bk26/arch/x86_64/kernel/sys_x86_64.c --- linux-2.4.22-bk25/arch/x86_64/kernel/sys_x86_64.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/sys_x86_64.c 2003-09-29 02:49:41.000000000 -0700 @@ -128,3 +128,17 @@ unsigned long raddr; return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: raddr; } + +asmlinkage long sys_time64(long * tloc) +{ + struct timeval now; + int i; + + do_gettimeofday(&now); + i = now.tv_sec; + if (tloc) { + if (put_user(i,tloc)) + i = -EFAULT; + } + return i; +} diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/traps.c linux-2.4.22-bk26/arch/x86_64/kernel/traps.c --- linux-2.4.22-bk25/arch/x86_64/kernel/traps.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/traps.c 2003-09-29 02:49:41.000000000 -0700 @@ -7,7 +7,7 @@ * Pentium III FXSR, SSE support * Gareth Hughes , May 2000 * - * $Id: traps.c,v 1.66 2003/06/09 05:18:21 ak Exp $ + * $Id: traps.c,v 1.69 2003/09/21 04:54:09 ak Exp $ */ /* @@ -81,7 +81,7 @@ struct notifier_block *die_chain; -int kstack_depth_to_print = 40; +int kstack_depth_to_print = 12; #ifdef CONFIG_KALLSYMS #include @@ -342,18 +342,25 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; int die_owner = -1; -void die(const char * str, struct pt_regs * regs, long err) +void __die(const char * str, struct pt_regs * regs, long err) +{ + printk(KERN_EMERG "%s: %04lx\n", str, err & 0xffff); + notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); + show_registers(regs); + /* Execute summary in case the oops scrolled away */ + printk(KERN_EMERG "RIP "); + printk_address(regs->rip); + printk(" RSP <%016lx>\n", regs->rsp); +} + +void prepare_die(unsigned long *flags) { - unsigned long flags; int cpu; console_verbose(); bust_spinlocks(1); - handle_BUG(regs); - printk(KERN_EMERG "%s: %04lx\n", str, err & 0xffff); - notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); cpu = safe_smp_processor_id(); /* racy, but better than risking deadlock. */ - __save_flags(flags); + __save_flags(*flags); __cli(); if (!spin_trylock(&die_lock)) { if (cpu == die_owner) @@ -362,9 +369,23 @@ spin_lock(&die_lock); } die_owner = cpu; - show_registers(regs); - bust_spinlocks(0); +} + +void exit_die(unsigned long flags) +{ + die_owner = -1; spin_unlock_irqrestore(&die_lock, flags); + __sti(); /* back scroll should work */ + bust_spinlocks(0); +} + +void die(const char * str, struct pt_regs * regs, long err) +{ + unsigned long flags; + prepare_die(&flags); + handle_BUG(regs); + __die(str, regs, err); + exit_die(flags); do_exit(SIGSEGV); } diff -urN linux-2.4.22-bk25/arch/x86_64/kernel/x8664_ksyms.c linux-2.4.22-bk26/arch/x86_64/kernel/x8664_ksyms.c --- linux-2.4.22-bk25/arch/x86_64/kernel/x8664_ksyms.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/kernel/x8664_ksyms.c 2003-09-29 02:49:41.000000000 -0700 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -222,4 +223,6 @@ #endif extern void int_ret_from_sys_call(void); -EXPORT_SYMBOL(int_ret_from_sys_call); +EXPORT_SYMBOL_NOVERS(int_ret_from_sys_call); + +EXPORT_SYMBOL(touch_nmi_watchdog); diff -urN linux-2.4.22-bk25/arch/x86_64/lib/copy_page.S linux-2.4.22-bk26/arch/x86_64/lib/copy_page.S --- linux-2.4.22-bk25/arch/x86_64/lib/copy_page.S 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/lib/copy_page.S 2003-09-29 02:49:41.000000000 -0700 @@ -10,14 +10,8 @@ copy_page: prefetch (%rsi) prefetch 1*64(%rsi) - prefetch 2*64(%rsi) - prefetch 3*64(%rsi) - prefetch 4*64(%rsi) prefetchw (%rdi) prefetchw 1*64(%rdi) - prefetchw 2*64(%rdi) - prefetchw 3*64(%rdi) - prefetchw 4*64(%rdi) subq $3*8,%rsp movq %rbx,(%rsp) diff -urN linux-2.4.22-bk25/arch/x86_64/lib/copy_user.S linux-2.4.22-bk26/arch/x86_64/lib/copy_user.S --- linux-2.4.22-bk25/arch/x86_64/lib/copy_user.S 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/lib/copy_user.S 2003-09-29 02:49:41.000000000 -0700 @@ -4,7 +4,7 @@ * Functions to copy from and to user space. */ -#define FIX_ALIGNMENT 1 +/* #define FIX_ALIGNMENT 1 */ #include #include @@ -59,9 +59,8 @@ .globl copy_user_generic .p2align 4 copy_user_generic: - /* Put the first cacheline into cache. This should handle - the small movements in ioctls etc., but not penalize the bigger - filesystem data copies too much. */ + prefetch (%rsi) + prefetchw (%rdi) pushq %rbx xorl %eax,%eax /*zero for the exception handler */ diff -urN linux-2.4.22-bk25/arch/x86_64/lib/csum-copy.S linux-2.4.22-bk26/arch/x86_64/lib/csum-copy.S --- linux-2.4.22-bk25/arch/x86_64/lib/csum-copy.S 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/lib/csum-copy.S 2003-09-29 02:49:41.000000000 -0700 @@ -56,29 +56,18 @@ .globl csum_partial_copy_generic .p2align 4 csum_partial_copy_generic: - cmpl $3*64,%edx + cmpl $2*64,%edx jle .Lignore ignore - prefetch (%rdi) - ignore prefetch 1*64(%rdi) ignore prefetch 2*64(%rdi) ignore - prefetch 3*64(%rdi) - ignore - prefetch 4*64(%rdi) - ignore prefetchw (%rsi) ignore prefetchw 1*64(%rsi) ignore - prefetchw 2*64(%rsi) - ignore - prefetchw 3*64(%rsi) - ignore - prefetchw 4*64(%rsi) .Lignore: subq $7*8,%rsp @@ -126,9 +115,6 @@ source movq 56(%rdi),%r13 - ignore 2f - prefetch 5*64(%rdi) -2: adcq %rbx,%rax adcq %r8,%rax adcq %r11,%rax @@ -158,10 +144,6 @@ dest movq %r13,56(%rsi) - ignore 3f - prefetchw 5*64(%rsi) -3: - leaq 64(%rdi),%rdi leaq 64(%rsi),%rsi diff -urN linux-2.4.22-bk25/arch/x86_64/lib/usercopy.c linux-2.4.22-bk26/arch/x86_64/lib/usercopy.c --- linux-2.4.22-bk25/arch/x86_64/lib/usercopy.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/lib/usercopy.c 2003-09-29 02:49:41.000000000 -0700 @@ -68,7 +68,7 @@ asm volatile( " testq %[size8],%[size8]\n" " jz 4f\n" - "0: movnti %[zero],(%[dst])\n" + "0: movq %[zero],(%[dst])\n" " addq %[eight],%[dst]\n" " decl %%ecx ; jnz 0b\n" "4: movq %[size1],%%rcx\n" @@ -77,7 +77,7 @@ "1: movb %b[zero],(%[dst])\n" " incq %[dst]\n" " decl %%ecx ; jnz 1b\n" - "2: sfence\n" + "2:\n" ".section .fixup,\"ax\"\n" "3: lea 0(%[size1],%[size8],8),%[size8]\n" " jmp 2b\n" diff -urN linux-2.4.22-bk25/arch/x86_64/mm/fault.c linux-2.4.22-bk26/arch/x86_64/mm/fault.c --- linux-2.4.22-bk25/arch/x86_64/mm/fault.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/mm/fault.c 2003-09-29 02:49:41.000000000 -0700 @@ -94,6 +94,85 @@ printk("BAD\n"); } +/* Sometimes the CPU reports invalid exceptions on prefetch. + Check that here and ignore. + Opcode checker based on code by Richard Brunner */ +static int is_prefetch(struct pt_regs *regs, unsigned long addr) +{ + unsigned char *instr = (unsigned char *)(regs->rip); + int scan_more = 1; + int prefetch = 0; + unsigned char *max_instr = instr + 15; + + /* Avoid recursive faults for this common case */ + if (regs->rip == addr) + return 0; + + if (regs->cs & (1<<2)) + return 0; + + while (scan_more && instr < max_instr) { + unsigned char opcode; + unsigned char instr_hi; + unsigned char instr_lo; + + if (__get_user(opcode, instr)) + break; + + instr_hi = opcode & 0xf0; + instr_lo = opcode & 0x0f; + instr++; + + switch (instr_hi) { + case 0x20: + case 0x30: + /* Values 0x26,0x2E,0x36,0x3E are valid x86 + prefixes. In long mode, the CPU will signal + invalid opcode if some of these prefixes are + present so we will never get here anyway */ + scan_more = ((instr_lo & 7) == 0x6); + break; + + case 0x40: + /* In AMD64 long mode, 0x40 to 0x4F are valid REX prefixes + Need to figure out under what instruction mode the + instruction was issued ... */ + /* Could check the LDT for lm, but for now it's good + enough to assume that long mode only uses well known + segments or kernel. */ + scan_more = ((regs->cs & 3) == 0) || (regs->cs == __USER_CS); + break; + + case 0x60: + /* 0x64 thru 0x67 are valid prefixes in all modes. */ + scan_more = (instr_lo & 0xC) == 0x4; + break; + case 0xF0: + /* 0xF0, 0xF2, and 0xF3 are valid prefixes in all modes. */ + scan_more = !instr_lo || (instr_lo>>1) == 1; + break; + case 0x00: + /* Prefetch instruction is 0x0F0D or 0x0F18 */ + scan_more = 0; + if (__get_user(opcode, instr)) + break; + prefetch = (instr_lo == 0xF) && + (opcode == 0x0D || opcode == 0x18); + break; + default: + scan_more = 0; + break; + } + } + +#if 0 + if (prefetch) + printk("%s: prefetch caused page fault at %lx/%lx\n", current->comm, + regs->rip, addr); +#endif + return prefetch; +} + int page_fault_trace; int exception_trace = 1; @@ -156,7 +235,7 @@ * context, we must not take the fault.. */ if (in_interrupt() || !mm) - goto no_context; + goto bad_area_nosemaphore; again: down_read(&mm->mmap_sem); @@ -226,9 +305,11 @@ up_read(&mm->mmap_sem); bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { + if (is_prefetch(regs, address)) + return; + if (exception_trace && !(tsk->ptrace & PT_PTRACED) && (tsk->sig->action[SIGSEGV-1].sa.sa_handler == SIG_IGN || (tsk->sig->action[SIGSEGV-1].sa.sa_handler == SIG_DFL))) @@ -260,40 +341,27 @@ return; } + if (is_prefetch(regs, address)) + return; + /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - console_verbose(); - bust_spinlocks(1); - - int cpu = safe_smp_processor_id(); unsigned long flags; - extern int die_owner; - extern spinlock_t die_lock; - - __save_flags(flags); - __cli(); - if (!spin_trylock(&die_lock)) { - if (cpu == die_owner) - /* nested oops. should stop eventually */; - else - spin_lock(&die_lock); - } - die_owner = cpu; - + prepare_die(&flags); if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %016lx\n",address); - printk(" printing rip:\n"); - printk("%016lx\n", regs->rip); + printk(KERN_ALERT " at %016lx RIP: ", address); + printk_address(regs->rip); dump_pagetable(address); - die("Oops", regs, error_code); - bust_spinlocks(0); - spin_unlock_irqrestore(&die_lock, flags); + __die("Oops", regs, error_code); + /* Executive summary in case the oops scrolled away */ + printk(KERN_EMERG "CR2: %016lx\n", address); + exit_die(flags); do_exit(SIGKILL); /* @@ -315,10 +383,13 @@ do_sigbus: up_read(&mm->mmap_sem); - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ + /* Kernel mode? Handle exceptions or die */ + if (!(error_code & 4)) + goto no_context; + + if (is_prefetch(regs, address)) + return; + tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -327,10 +398,6 @@ info.si_code = BUS_ADRERR; info.si_addr = (void *)address; force_sig_info(SIGBUS, &info, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!(error_code & 4)) - goto no_context; return; diff -urN linux-2.4.22-bk25/arch/x86_64/mm/ioremap.c linux-2.4.22-bk26/arch/x86_64/mm/ioremap.c --- linux-2.4.22-bk25/arch/x86_64/mm/ioremap.c 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/mm/ioremap.c 2003-09-29 02:49:41.000000000 -0700 @@ -125,12 +125,12 @@ */ if (phys_addr < virt_to_phys(high_memory)) { char *t_addr, *t_end; - struct page *page; t_addr = __va(phys_addr); t_end = t_addr + (size - 1); #ifndef CONFIG_DISCONTIGMEM + struct page *page; for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; diff -urN linux-2.4.22-bk25/arch/x86_64/mm/k8topology.c linux-2.4.22-bk26/arch/x86_64/mm/k8topology.c --- linux-2.4.22-bk25/arch/x86_64/mm/k8topology.c 2003-08-25 04:44:40.000000000 -0700 +++ linux-2.4.22-bk26/arch/x86_64/mm/k8topology.c 2003-09-29 02:49:41.000000000 -0700 @@ -6,7 +6,7 @@ * Instead the northbridge registers are read directly. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: k8topology.c,v 1.7 2003/04/02 21:36:22 ak Exp $ + * $Id: k8topology.c,v 1.11 2003/09/12 01:55:37 ak Exp $ */ #include #include @@ -20,6 +20,8 @@ #include #include +#define Dprintk(x...) + int memnode_shift; u8 memnodemap[NODEMAPSIZE]; @@ -110,6 +112,9 @@ limit = read_pci_config(0, nb, 1, 0x44 + i*8); nodeid = limit & 3; + if ((base & 3) == 0) { + continue; + } if (!limit) { printk(KERN_INFO "Skipping node entry %d (base %lx)\n", i, base); continue; @@ -145,7 +150,7 @@ if (limit == base) continue; if (limit < base) { - printk(KERN_INFO"Node %d bogus settings %lx-%lx. Ignored.\n", + Dprintk(KERN_INFO"Node %d bogus settings %lx-%lx. Ignored.\n", nodeid, base, limit); continue; } diff -urN linux-2.4.22-bk25/drivers/block/cciss.c linux-2.4.22-bk26/drivers/block/cciss.c --- linux-2.4.22-bk25/drivers/block/cciss.c 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/drivers/block/cciss.c 2003-09-29 02:49:41.000000000 -0700 @@ -106,7 +106,15 @@ #define READ_AHEAD 128 #define NR_CMDS 128 /* #commands that can be outstanding */ -#define MAX_CTLR 8 +#define MAX_CTLR 32 + +/* No sense in giving up our preallocated major numbers */ +#if MAX_CTLR < 8 +#error"cciss.c: MAX_CTLR must be 8 or greater" +#endif + +/* Originally cciss driver only supports 8 major number */ +#define MAX_CTLR_ORIG COMPAQ_CISS_MAJOR7 - COMPAQ_CISS_MAJOR + 1 #define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFF /* 64 bit DMA */ @@ -121,7 +129,7 @@ #endif static ctlr_info_t *hba[MAX_CTLR]; - +static int map_major_to_ctlr[MAX_BLKDEV] = {0}; /* gets ctlr num from maj num */ static struct proc_dir_entry *proc_cciss; static void do_cciss_request(request_queue_t *q); @@ -421,7 +429,7 @@ */ static int cciss_open(struct inode *inode, struct file *filep) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -462,7 +470,7 @@ */ static int cciss_release(struct inode *inode, struct file *filep) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -482,7 +490,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -1028,7 +1036,7 @@ int i; target = MINOR(dev) >> NWD_SHIFT; - ctlr = MAJOR(dev) - MAJOR_NR; + ctlr = map_major_to_ctlr[MAJOR(dev)]; gdev = &(hba[ctlr]->gendisk); spin_lock_irqsave(&io_request_lock, flags); @@ -1047,12 +1055,12 @@ for(i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = 1024; + blksize_size[hba[ctlr]->major][minor] = 1024; } /* setup partitions per disk */ grok_partitions(gdev, target, MAX_PART, @@ -1093,7 +1101,7 @@ for (i=max_p-1; i>=0; i--) { int minor = start+i; /* printk("invalidating( %d %d)\n", ctlr, minor); */ - invalidate_device(MKDEV(MAJOR_NR+ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); /* so open will now fail */ h->sizes[minor] = 0; /* so it will no longer appear in /proc/partitions */ @@ -1581,12 +1589,12 @@ for(i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = block_size; + blksize_size[hba[ctlr]->major][minor] = block_size; hba[ctlr]->hardsizes[minor] = block_size; } @@ -1700,12 +1708,12 @@ for (i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = 1024; + blksize_size[hba[ctlr]->major][minor] = block_size; hba[ctlr]->hardsizes[minor] = block_size; } @@ -2269,7 +2277,7 @@ if (creq->nr_segments > MAXSGENTRIES) BUG(); - if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ) { + if( h->ctlr != map_major_to_ctlr[MAJOR(creq->rq_dev)] ) { printk(KERN_WARNING "doreq cmd for %d, %x at %p\n", h->ctlr, creq->rq_dev, creq); blkdev_dequeue_request(creq); @@ -2436,7 +2444,7 @@ /* * See if we can queue up some more IO */ - do_cciss_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr)); + do_cciss_request(BLK_DEFAULT_QUEUE(h->major)); spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -2874,8 +2882,10 @@ return i; } } - printk(KERN_WARNING "cciss: This driver supports a maximum" - " of 8 controllers.\n"); + printk(KERN_WARNING + "cciss: This driver supports a maximum of %d controllers.\n" + "You can change this value in cciss.c and recompile.\n", + MAX_CTLR); return -1; } @@ -3063,6 +3073,7 @@ request_queue_t *q; int i; int j; + int rc; printk(KERN_DEBUG "cciss: Device 0x%x has been found at" " bus %d dev %d func %d\n", @@ -3078,16 +3089,33 @@ } sprintf(hba[i]->devname, "cciss%d", i); hba[i]->ctlr = i; + + /* register with the major number, or get a dynamic major number */ + /* by passing 0 as argument */ + + if (i < MAX_CTLR_ORIG) + hba[i]->major = MAJOR_NR + i; + hba[i]->pdev = pdev; ASSERT_CTLR_ALIVE(hba[i]); - if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops)) { + rc = (register_blkdev(hba[i]->major, hba[i]->devname, &cciss_fops)); + if (rc < 0) { printk(KERN_ERR "cciss: Unable to get major number " - "%d for %s\n", MAJOR_NR+i, hba[i]->devname); + "%d for %s\n", hba[i]->major, hba[i]->devname); release_io_mem(hba[i]); free_hba(i); return -1; + } else { + if (i < MAX_CTLR_ORIG) { + hba[i]->major = MAJOR_NR + i; + map_major_to_ctlr[MAJOR_NR + i] = i; + } else { + hba[i]->major = rc; + map_major_to_ctlr[rc] = i; + } } + /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if (request_irq(hba[i]->intr, do_cciss_intr, @@ -3096,7 +3124,8 @@ printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); - unregister_blkdev( MAJOR_NR+i, hba[i]->devname); + unregister_blkdev( hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; release_io_mem(hba[i]); free_hba(i); return -1; @@ -3125,7 +3154,8 @@ hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); free_irq(hba[i]->intr, hba[i]); - unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + unregister_blkdev(hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; release_io_mem(hba[i]); free_hba(i); printk( KERN_ERR "cciss: out of memory"); @@ -3152,16 +3182,16 @@ cciss_procinit(i); - q = BLK_DEFAULT_QUEUE(MAJOR_NR + i); + q = BLK_DEFAULT_QUEUE(hba[i]->major); q->queuedata = hba[i]; blk_init_queue(q, do_cciss_request); blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); blk_queue_headactive(q, 0); /* fill in the other Kernel structs */ - blksize_size[MAJOR_NR+i] = hba[i]->blocksizes; - hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes; - read_ahead[MAJOR_NR+i] = READ_AHEAD; + blksize_size[hba[i]->major] = hba[i]->blocksizes; + hardsect_size[hba[i]->major] = hba[i]->hardsizes; + read_ahead[hba[i]->major] = READ_AHEAD; /* Set the pointers to queue functions */ q->back_merge_fn = cpq_back_merge_fn; @@ -3170,7 +3200,7 @@ /* Fill in the gendisk data */ - hba[i]->gendisk.major = MAJOR_NR + i; + hba[i]->gendisk.major = hba[i]->major; hba[i]->gendisk.major_name = "cciss"; hba[i]->gendisk.minor_shift = NWD_SHIFT; hba[i]->gendisk.max_p = MAX_PART; @@ -3185,7 +3215,7 @@ cciss_geninit(i); for(j=0; jgendisk), - MKDEV(MAJOR_NR+i, j <<4), + MKDEV(hba[i]->major, j <<4), MAX_PART, &cciss_fops, hba[i]->drv[j].nr_blocks); @@ -3228,7 +3258,8 @@ pci_set_drvdata(pdev, NULL); iounmap((void*)hba[i]->vaddr); cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ - unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + unregister_blkdev(hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; remove_proc_entry(hba[i]->devname, proc_cciss); diff -urN linux-2.4.22-bk25/drivers/block/cciss.h linux-2.4.22-bk26/drivers/block/cciss.h --- linux-2.4.22-bk25/drivers/block/cciss.h 2003-09-29 02:49:36.000000000 -0700 +++ linux-2.4.22-bk26/drivers/block/cciss.h 2003-09-29 02:49:41.000000000 -0700 @@ -40,6 +40,7 @@ struct ctlr_info { int ctlr; + int major; char devname[8]; char *product_name; char firm_ver[4]; // Firmware version diff -urN linux-2.4.22-bk25/drivers/block/cciss_scsi.c linux-2.4.22-bk26/drivers/block/cciss_scsi.c --- linux-2.4.22-bk25/drivers/block/cciss_scsi.c 2003-08-25 04:44:41.000000000 -0700 +++ linux-2.4.22-bk26/drivers/block/cciss_scsi.c 2003-09-29 02:49:41.000000000 -0700 @@ -71,16 +71,7 @@ #endif #endif -static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { - { name: "cciss0", ndevices: 0 }, - { name: "cciss1", ndevices: 0 }, - { name: "cciss2", ndevices: 0 }, - { name: "cciss3", ndevices: 0 }, - { name: "cciss4", ndevices: 0 }, - { name: "cciss5", ndevices: 0 }, - { name: "cciss6", ndevices: 0 }, - { name: "cciss7", ndevices: 0 }, -}; +static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR]; /* We need one Scsi_Host_Template *per controller* instead of the usual one Scsi_Host_Template per controller *type*. This @@ -92,11 +83,7 @@ (that's called from cciss.c:cciss_init_one()) */ static -Scsi_Host_Template driver_template[MAX_CTLR] = -{ - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, -}; +Scsi_Host_Template driver_template[MAX_CTLR]; #pragma pack(1) struct cciss_scsi_cmd_stack_elem_t { @@ -803,13 +790,7 @@ sh->this_id = SELF_SCSI_ID; - /* This is a bit kludgey, using the adapter name to figure out */ - /* which scsi host template we've got, won't scale beyond 9 ctlrs. */ - i = tpnt->name[5] - '0'; - -# if MAX_CTLR > 9 -# error "cciss_scsi.c: MAX_CTLR > 9, code maintenance needed." -# endif + i = simple_strtol((char *)&tpnt->name[5], NULL, 10); if (i<0 || i>=MAX_CTLR || hba[i] == NULL) { /* we didn't find ourself... we shouldn't get here. */ @@ -1528,9 +1509,10 @@ unsigned long flags; CPQ_TAPE_LOCK(ctlr, flags); - driver_template[ctlr].name = ccissscsi[ctlr].name; - driver_template[ctlr].proc_name = ccissscsi[ctlr].name; - driver_template[ctlr].module = THIS_MODULE;; + + sprintf( ccissscsi[ctlr].name, "cciss%d", ctlr ); + + init_driver_template(ctlr); /* Since this is really a block driver, the SCSI core may not be initialized yet, in which case, calling scsi_register_module diff -urN linux-2.4.22-bk25/drivers/block/cciss_scsi.h linux-2.4.22-bk26/drivers/block/cciss_scsi.h --- linux-2.4.22-bk25/drivers/block/cciss_scsi.h 2003-06-13 07:51:32.000000000 -0700 +++ linux-2.4.22-bk26/drivers/block/cciss_scsi.h 2003-09-29 02:49:41.000000000 -0700 @@ -89,7 +89,7 @@ }; struct cciss_scsi_hba_t { - char *name; + char name[32]; int ndevices; #define CCISS_MAX_SCSI_DEVS_PER_HBA 16 struct cciss_scsi_dev_t dev[CCISS_MAX_SCSI_DEVS_PER_HBA]; diff -urN linux-2.4.22-bk25/drivers/char/Config.in linux-2.4.22-bk26/drivers/char/Config.in --- linux-2.4.22-bk25/drivers/char/Config.in 2003-09-29 02:49:37.000000000 -0700 +++ linux-2.4.22-bk26/drivers/char/Config.in 2003-09-29 02:49:41.000000000 -0700 @@ -308,7 +308,7 @@ if [ "$CONFIG_GART_IOMMU" = "y" ]; then bool '/dev/agpgart (AGP Support)' CONFIG_AGP - define_bool CONFIG_AGP_AMD_8151 y + define_bool CONFIG_AGP_AMD_K8 y else tristate '/dev/agpgart (AGP Support)' CONFIG_AGP fi @@ -318,7 +318,7 @@ bool ' VIA chipset support' CONFIG_AGP_VIA bool ' AMD Irongate, 761, and 762 support' CONFIG_AGP_AMD if [ "$CONFIG_GART_IOMMU" != "y" ]; then - bool ' AMD 8151 support' CONFIG_AGP_AMD_8151 + bool ' AMD Opteron/Athlon64 on-CPU GART support' CONFIG_AGP_AMD_K8 fi bool ' Generic SiS support' CONFIG_AGP_SIS bool ' ALI chipset support' CONFIG_AGP_ALI diff -urN linux-2.4.22-bk25/drivers/char/agp/agp.h linux-2.4.22-bk26/drivers/char/agp/agp.h --- linux-2.4.22-bk25/drivers/char/agp/agp.h 2003-09-29 02:49:37.000000000 -0700 +++ linux-2.4.22-bk26/drivers/char/agp/agp.h 2003-09-29 02:49:41.000000000 -0700 @@ -172,6 +172,12 @@ #ifndef PCI_DEVICE_ID_VIA_82C694X_0 #define PCI_DEVICE_ID_VIA_82C694X_0 0x0605 #endif +#ifndef PCI_DEVICE_ID_VIA_8380_0 +#define PCI_DEVICE_ID_VIA_8380_0 0x0204 +#endif +#ifndef PCI_DEVICE_ID_VIA_8385_0 +#define PCI_DEVICE_ID_VIA_8385_0 0x3188 +#endif #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif @@ -511,6 +517,14 @@ #define NVIDIA_3_APBASE 0x50 #define NVIDIA_3_APLIMIT 0x54 +/* NVIDIA x86-64 registers */ +#define NVIDIA_X86_64_0_APBASE 0x10 +#define NVIDIA_X86_64_1_APBASE1 0x50 +#define NVIDIA_X86_64_1_APLIMIT1 0x54 +#define NVIDIA_X86_64_1_APSIZE 0xa8 +#define NVIDIA_X86_64_1_APBASE2 0xd8 +#define NVIDIA_X86_64_1_APLIMIT2 0xdc + /* HP ZX1 IOC registers */ #define HP_ZX1_IBASE 0x300 #define HP_ZX1_IMASK 0x308 diff -urN linux-2.4.22-bk25/drivers/char/agp/agpgart_be.c linux-2.4.22-bk26/drivers/char/agp/agpgart_be.c --- linux-2.4.22-bk25/drivers/char/agp/agpgart_be.c 2003-09-29 02:49:37.000000000 -0700 +++ linux-2.4.22-bk26/drivers/char/agp/agpgart_be.c 2003-09-29 02:49:41.000000000 -0700 @@ -49,9 +49,7 @@ #include #include #include -#ifdef CONFIG_AGP_NVIDIA - #include -#endif +#include #include #include "agp.h" @@ -3403,38 +3401,11 @@ #endif /* CONFIG_AGP_AMD */ -#ifdef CONFIG_AGP_AMD_8151 +#ifdef CONFIG_AGP_AMD_K8 /* Begin AMD-8151 support */ -static u_int64_t pci_read64 (struct pci_dev *dev, int reg) -{ - union { - u64 full; - struct { - u32 high; - u32 low; - } split; - } tmp; - pci_read_config_dword(dev, reg, &tmp.split.high); - pci_read_config_dword(dev, reg+4, &tmp.split.low); - return tmp.full; -} - -static void pci_write64 (struct pci_dev *dev, int reg, u64 value) -{ - union { - u64 full; - struct { - u32 high; - u32 low; - } split; - } tmp; - tmp.full = value; - pci_write_config_dword(dev, reg, tmp.split.high); - pci_write_config_dword(dev, reg+4, tmp.split.low); -} - +/* This is misnamed. It is really a generic AMD K8 Northbridge AMD driver. */ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type) { @@ -3442,7 +3413,6 @@ void *temp; long tmp; u32 pte; - u64 addr; temp = agp_bridge.current_size; @@ -3472,9 +3442,8 @@ } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - addr = agp_bridge.mask_memory(mem->memory[i], mem->type); + tmp = agp_bridge.mask_memory(mem->memory[i], mem->type); - tmp = addr; BUG_ON(tmp & 0xffffff0000000ffc); pte = (tmp & 0x000000ff00000000) >> 28; pte |=(tmp & 0x00000000fffff000); @@ -3612,10 +3581,7 @@ static int amd_8151_configure(void) { - struct pci_dev *dev, *hammer=NULL; - int current_size; - int tmp, tmp2, i; - u64 aperbar; + struct pci_dev *dev; unsigned long gatt_bus = virt_to_phys(agp_bridge.gatt_table_real); /* Configure AGP regs in each x86-64 host bridge. */ @@ -3624,54 +3590,8 @@ PCI_FUNC(dev->devfn)==3 && PCI_SLOT(dev->devfn)>=24 && PCI_SLOT(dev->devfn)<=31) { agp_bridge.gart_bus_addr = amd_x86_64_configure(dev,gatt_bus); - hammer = dev; - - /* - * TODO: Cache pci_dev's of x86-64's in private struct to save us - * having to scan the pci list each time. - */ - } } - - if (hammer == NULL) { - return -ENODEV; } - - /* Shadow x86-64 registers into 8151 registers. */ - - dev = agp_bridge.dev; - if (!dev) - return -ENODEV; - - current_size = amd_x86_64_fetch_size(); - - pci_read_config_dword(dev, AMD_8151_APERTURESIZE, &tmp); - tmp &= ~(0xfff); - - /* translate x86-64 size bits to 8151 size bits*/ - for (i=0 ; i<7; i++) { - if (amd_8151_sizes[i].size == current_size) - tmp |= (amd_8151_sizes[i].size_value) << 3; - } - pci_write_config_dword(dev, AMD_8151_APERTURESIZE, tmp); - - pci_read_config_dword (hammer, AMD_X86_64_GARTAPERTUREBASE, &tmp); - aperbar = pci_read64 (dev, AMD_8151_VMAPERTURE); - aperbar |= (tmp & 0x7fff) <<25; - aperbar &= 0x000000ffffffffff; - aperbar |= 1<<2; /* This address is a 64bit ptr FIXME: Make conditional in 32bit mode */ - pci_write64 (dev, AMD_8151_VMAPERTURE, aperbar); - - pci_read_config_dword(dev, AMD_8151_AGP_CTL , &tmp); - tmp &= ~(AMD_8151_GTLBEN | AMD_8151_APEREN); - - pci_read_config_dword(hammer, AMD_X86_64_GARTAPERTURECTL, &tmp2); - if (tmp2 & AMD_X86_64_GARTEN) - tmp |= AMD_8151_APEREN; - // FIXME: bit 7 of AMD_8151_AGP_CTL (GTLBEN) must be copied if set. - // But where is it set ? - pci_write_config_dword(dev, AMD_8151_AGP_CTL, tmp); - return 0; } @@ -3690,15 +3610,6 @@ tmp &= ~(AMD_X86_64_GARTEN); pci_write_config_dword (dev, AMD_X86_64_GARTAPERTURECTL, tmp); } - - /* Now shadow the disable in the 8151 */ - if (dev->vendor == PCI_VENDOR_ID_AMD && - dev->device == PCI_DEVICE_ID_AMD_8151_0) { - - pci_read_config_dword (dev, AMD_8151_AGP_CTL, &tmp); - tmp &= ~(AMD_8151_APEREN); - pci_write_config_dword (dev, AMD_8151_AGP_CTL, tmp); - } } } @@ -3712,7 +3623,7 @@ static gatt_mask amd_8151_masks[] = { - {0x00000001, 0} + {0, 0} }; @@ -3747,7 +3658,7 @@ printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n", device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn)); } else { - printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch); + printk (KERN_INFO "AGP: Version %x AGP device found.\n", scratch); } } } @@ -3866,7 +3777,165 @@ (void) pdev; /* unused */ } -#endif /* CONFIG_AGP_AMD_8151 */ +/* NVIDIA x86-64 chipset support */ + + +static struct _nvidia_x86_64_private { + struct pci_dev *dev_1; +} nvidia_x86_64_private; + + +static aper_size_info_32 nvidia_x86_64_sizes[5] = +{ + {512, 131072, 7, 0x00000000 }, + {256, 65536, 6, 0x00000008 }, + {128, 32768, 5, 0x0000000C }, + {64, 16384, 4, 0x0000000E }, + {32, 8192, 3, 0x0000000F } +}; + + +static int nvidia_x86_64_configure(void) +{ + struct pci_dev *dev, *hammer=NULL; + int i, current_size; + u32 tmp, apbase, apbar, aplimit; + unsigned long gatt_bus = virt_to_phys(agp_bridge.gatt_table_real); + + if (!agp_bridge.dev) + return -ENODEV; + + /* configure AGP regs in each x86-64 host bridge */ + pci_for_each_dev(dev) { + if (dev->bus->number==0 && + PCI_FUNC(dev->devfn)==3 && + PCI_SLOT(dev->devfn)>=24 && PCI_SLOT(dev->devfn)<=31) { + agp_bridge.gart_bus_addr = amd_x86_64_configure(dev,gatt_bus); + hammer = dev; + } + } + if (hammer == NULL) + return -ENODEV; + + /* translate x86-64 aperture size to NVIDIA aperture size */ + current_size = amd_x86_64_fetch_size(); + for (i = 0 ; i < agp_bridge.num_aperture_sizes; i++) { + if (nvidia_x86_64_sizes[i].size == current_size) + break; + } + /* if x86-64 size does not match any NVIDIA size, exit here */ + if (i == agp_bridge.num_aperture_sizes) + return -ENODEV; + pci_read_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APSIZE, &tmp); + tmp &= ~(0xf); + tmp |= nvidia_x86_64_sizes[i].size_value; + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APSIZE, tmp); + + /* shadow x86-64 registers into NVIDIA registers */ + pci_read_config_dword (hammer, AMD_X86_64_GARTAPERTUREBASE, &apbase); + /* if x86-64 aperture base is beyond 4G, exit here */ + if ( (apbase & 0x7fff) >> (32 - 25) ) + return -ENODEV; + apbase = (apbase & 0x7fff) << 25; + + /* AK: most likely the shadow into the primary device is not needed */ + + pci_read_config_dword(agp_bridge.dev, NVIDIA_X86_64_0_APBASE, &apbar); + apbar &= ~PCI_BASE_ADDRESS_MEM_MASK; + apbar |= apbase; + pci_write_config_dword(agp_bridge.dev, NVIDIA_X86_64_0_APBASE, apbar); + + /* Shadow into secondary device looks dubious, but we keep it for now. + If these two could be dropped then the NForce3 code path could + be just folded into the generic functions above. */ + + aplimit = apbase + (current_size * 1024 * 1024) - 1; + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APBASE1, apbase); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APLIMIT1, aplimit); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APBASE2, apbase); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APLIMIT2, aplimit); + + /* Original driver updated the IORR here, but AMD documentation + explicitely discourages this for something already covered by the GART. */ + + return 0; +} + + +static void nvidia_x86_64_cleanup(void) +{ + struct pci_dev *dev; + u32 tmp; + + pci_for_each_dev(dev) { + /* disable gart translation */ + if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && + (PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) { + + pci_read_config_dword (dev, AMD_X86_64_GARTAPERTURECTL, &tmp); + tmp &= ~(AMD_X86_64_GARTEN); + pci_write_config_dword (dev, AMD_X86_64_GARTAPERTURECTL, tmp); + } + } +} + + +static unsigned long nvidia_x86_64_mask_memory(unsigned long addr, int type) +{ + return addr | agp_bridge.masks[0].mask; +} + + +static gatt_mask nvidia_x86_64_masks[] = +{ + {0x00000001, 0} +}; + + +static int __init nvidia_x86_64_setup (struct pci_dev *pdev) +{ + nvidia_x86_64_private.dev_1 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0)); + + if (nvidia_x86_64_private.dev_1 == NULL) { + printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " + "nForce3 chipset, but could not find " + "the secondary device.\n"); + agp_bridge.type = NOT_SUPPORTED; + return -ENODEV; + } + + agp_bridge.masks = nvidia_x86_64_masks; + agp_bridge.aperture_sizes = (void *) nvidia_x86_64_sizes; + agp_bridge.size_type = U32_APER_SIZE; + agp_bridge.num_aperture_sizes = 5; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = nvidia_x86_64_configure; + agp_bridge.fetch_size = amd_x86_64_fetch_size; + agp_bridge.cleanup = nvidia_x86_64_cleanup; + agp_bridge.tlb_flush = amd_x86_64_tlbflush; + agp_bridge.mask_memory = nvidia_x86_64_mask_memory; + agp_bridge.agp_enable = agp_x86_64_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = x86_64_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +#endif /* CONFIG_AGP_AMD_K8 */ #ifdef CONFIG_AGP_ALI @@ -5938,6 +6007,20 @@ "AMD", "761", amd_irongate_setup }, +#endif +#ifdef CONFIG_AGP_AMD_K8 + { PCI_DEVICE_ID_AMD_8151_0, + PCI_VENDOR_ID_AMD, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, + + /* Note: when adding more PCI-IDs for 8151 compatible bridges + add them to the end of their vendor lists, not here. + This list has to be ordered by vendor. */ +#endif /* CONFIG_AGP_AMD */ +#ifdef CONFIG_AGP_AMD { 0, PCI_VENDOR_ID_AMD, AMD_GENERIC, @@ -5946,15 +6029,6 @@ amd_irongate_setup }, #endif /* CONFIG_AGP_AMD */ -#ifdef CONFIG_AGP_AMD_8151 - { PCI_DEVICE_ID_AMD_8151_0, - PCI_VENDOR_ID_AMD, - AMD_8151, - "AMD", - "8151", - amd_8151_setup }, -#endif /* CONFIG_AGP_AMD */ - #ifdef CONFIG_AGP_INTEL { PCI_DEVICE_ID_INTEL_82443LX_0, PCI_VENDOR_ID_INTEL, @@ -6178,6 +6252,16 @@ "SiS", "550", sis_generic_setup }, +#endif +#ifdef CONFIG_AGP_AMD_K8 + { PCI_DEVICE_ID_SI_755, + PCI_VENDOR_ID_SI, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, +#endif +#ifdef CONFIG_AGP_SIS { 0, PCI_VENDOR_ID_SI, SIS_GENERIC, @@ -6265,6 +6349,24 @@ "Via", "Apollo P4M266", via_generic_setup }, +#endif +#ifdef CONFIG_AGP_AMD_K8 + { PCI_DEVICE_ID_VIA_8380_0, + PCI_VENDOR_ID_VIA, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, + + /* VIA K8T800 */ + { PCI_DEVICE_ID_VIA_8385_0, + PCI_VENDOR_ID_VIA, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, +#endif +#ifdef CONFIG_AGP_VIA { 0, PCI_VENDOR_ID_VIA, VIA_GENERIC, @@ -6286,6 +6388,16 @@ "NVIDIA", "nForce2", nvidia_generic_setup }, +#endif +#ifdef CONFIG_AGP_AMD_K8 + { PCI_DEVICE_ID_NVIDIA_NFORCE3, + PCI_VENDOR_ID_NVIDIA, + NVIDIA_NFORCE3, + "NVIDIA", + "nForce3/K8 On-CPU GART", + nvidia_x86_64_setup }, +#endif +#ifdef CONFIG_AGP_NVIDIA { 0, PCI_VENDOR_ID_NVIDIA, NVIDIA_GENERIC, @@ -6412,7 +6524,11 @@ } printk(KERN_ERR PFX "Unsupported %s chipset (device id: %04x)," +#ifdef MODULE " you might want to try agp_try_unsupported=1.\n", +#else + " you might want to boot with agp=try_unsupported\n", +#endif agp_bridge_info[i].vendor_name, pdev->device); return -ENODEV; } @@ -6435,6 +6551,31 @@ agp_bridge.dev = dev; +#ifdef CONFIG_AGP_AMD_K8 + /* If there is any K8 northbridge in the system always use the K8 driver */ + if (agp_try_unsupported + && pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL) + && !pci_find_device(PCI_VENDOR_ID_NVIDIA, + PCI_DEVICE_ID_NVIDIA_NFORCE3, + NULL)) { + + /* find capndx */ + cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); + if (cap_ptr == 0x00) + return -ENODEV; + agp_bridge.capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + 4, + &agp_bridge.mode); + + printk(KERN_INFO PFX "Detected GART in AMD K8 Northbridge\n"); + agp_bridge.type = AMD_8151; + return amd_8151_setup(dev); + } +#endif + /* Need to test for I810 here */ #ifdef CONFIG_AGP_I810 if (dev->vendor == PCI_VENDOR_ID_INTEL) { @@ -6892,10 +7033,26 @@ &agp_copy_info }; +static int __initdata agp_off = 0; +int __init agp_setup(char *s) +{ + if (!strcmp(s,"off")) + agp_off = 1; + if (!strcmp(s,"try_unsupported")) + agp_try_unsupported = 1; + return 0; +} +__setup("agp=", agp_setup); + int __init agp_init(void) { int ret_val; + if (agp_off) { + printk("AGP disabled\n"); + return -1; + } + printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); diff -urN linux-2.4.22-bk25/drivers/net/Config.in linux-2.4.22-bk26/drivers/net/Config.in --- linux-2.4.22-bk25/drivers/net/Config.in 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/Config.in 2003-09-29 02:49:41.000000000 -0700 @@ -269,17 +269,6 @@ dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate 'Realtek 8169 Gigabit Ethernet support' CONFIG_R8169 $CONFIG_PCI dep_tristate 'Marvell Yukon Chipset / SysKonnect SK-98xx Support' CONFIG_SK98LIN $CONFIG_PCI -if [ "$CONFIG_SK98LIN" != "n" ]; then - bool ' 3Com 3C940/3C941 Gigabit Ethernet Adapter' CONFIG_SK98LIN_T1 - bool ' Allied Telesyn AT-29xx Gigabit Ethernet Adapter' CONFIG_SK98LIN_T3 - bool ' CNet N-Way Gigabit Ethernet Adapter' CONFIG_SK98LIN_T8 - bool ' D-Link DGE-530T Gigabit Ethernet Adapter' CONFIG_SK98LIN_T6 - bool ' Linksys EG10xx Ethernet Server Adapter' CONFIG_SK98LIN_T9 - bool ' Marvell RDK-80xx Adapter' CONFIG_SK98LIN_T4 - bool ' Marvell Yukon Gigabit Ethernet Adapter' CONFIG_SK98LIN_T7 - bool ' SysKonnect SK-98xx Server Gigabit Adapter' CONFIG_SK98LIN_T2 - bool ' SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter' CONFIG_SK98LIN_T5 -fi dep_tristate 'Broadcom Tigon3 support' CONFIG_TIGON3 $CONFIG_PCI if [ "$CONFIG_MOMENCO_OCELOT_C" = "y" -o "$CONFIG_MOMENCO_JAGUAR_ATX" = "y" ]; then diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000.h linux-2.4.22-bk26/drivers/net/e1000/e1000.h --- linux-2.4.22-bk25/drivers/net/e1000/e1000.h 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000.h 2003-09-29 02:49:41.000000000 -0700 @@ -122,7 +122,12 @@ #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 4 +#define E1000_EEPROM_APME 0x0400 + +#ifndef E1000_MASTER_SLAVE +/* Switch to override PHY master/slave setting */ +#define E1000_MASTER_SLAVE e1000_ms_hw_default +#endif /* only works for sizes that are powers of 2 */ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) @@ -180,6 +185,7 @@ spinlock_t stats_lock; atomic_t irq_sem; struct tq_struct tx_timeout_task; + uint8_t fc_autoneg; struct timer_list blink_timer; unsigned long led_status; @@ -194,6 +200,7 @@ uint32_t tx_head_addr; uint32_t tx_fifo_size; atomic_t tx_fifo_stall; + boolean_t pcix_82544; /* RX */ struct e1000_desc_ring rx_ring; diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_ethtool.c linux-2.4.22-bk26/drivers/net/e1000/e1000_ethtool.c --- linux-2.4.22-bk25/drivers/net/e1000/e1000_ethtool.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_ethtool.c 2003-09-29 02:49:41.000000000 -0700 @@ -190,6 +190,55 @@ return 0; } +static int +e1000_ethtool_gpause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + epause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if(hw->fc == e1000_fc_rx_pause) + epause->rx_pause = 1; + else if(hw->fc == e1000_fc_tx_pause) + epause->tx_pause = 1; + else if(hw->fc == e1000_fc_full) { + epause->rx_pause = 1; + epause->tx_pause = 1; + } + + return 0; +} + +static int +e1000_ethtool_spause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + adapter->fc_autoneg = epause->autoneg; + + if(epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_full; + else if(epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_rx_pause; + else if(!epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_tx_pause; + else if(!epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_none; + + hw->original_fc = hw->fc; + + if(netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + + return 0; +} + static void e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, struct ethtool_drvinfo *drvinfo) @@ -197,7 +246,7 @@ strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); - strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); drvinfo->n_stats = E1000_STATS_LEN; drvinfo->testinfo_len = E1000_TEST_LEN; #define E1000_REGS_LEN 32 @@ -504,7 +553,7 @@ return *data; } -static void +static irqreturn_t e1000_test_intr(int irq, void *data, struct pt_regs *regs) @@ -514,7 +563,7 @@ adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); - return; + return IRQ_HANDLED; } static int @@ -958,9 +1007,13 @@ case e1000_82544: case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: return e1000_integrated_phy_loopback(adapter); break; @@ -983,9 +1036,12 @@ { uint32_t rctl; - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { if(adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546) + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3) return e1000_set_phy_loopback(adapter); else { rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1010,9 +1066,12 @@ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); if(adapter->hw.media_type == e1000_media_type_copper || - (adapter->hw.media_type == e1000_media_type_fiber && + ((adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) && (adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546))) { + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3))) { adapter->hw.autoneg = TRUE; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); if(phy_reg & MII_CR_LOOPBACK) { @@ -1114,7 +1173,7 @@ e1000_down(adapter); else e1000_reset(adapter); - + if(e1000_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1162,6 +1221,7 @@ return; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { wol->supported = 0; @@ -1200,6 +1260,7 @@ return wol->wolopts ? -EOPNOTSUPP : 0; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) return wol->wolopts ? -EOPNOTSUPP : 0; @@ -1437,6 +1498,19 @@ addr += offsetof(struct ethtool_eeprom, data); return e1000_ethtool_seeprom(adapter, &eeprom, addr); } + case ETHTOOL_GPAUSEPARAM: { + struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; + e1000_ethtool_gpause(adapter, &epause); + if(copy_to_user(addr, &epause, sizeof(epause))) + return -EFAULT; + return 0; + } + case ETHTOOL_SPAUSEPARAM: { + struct ethtool_pauseparam epause; + if(copy_from_user(&epause, addr, sizeof(epause))) + return -EFAULT; + return e1000_ethtool_spause(adapter, &epause); + } case ETHTOOL_GSTATS: { struct { struct ethtool_stats eth_stats; @@ -1475,6 +1549,107 @@ return -EFAULT; return 0; } + case ETHTOOL_GRXCSUM: { + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + + edata.data = adapter->rx_csum; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_SRXCSUM: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + adapter->rx_csum = edata.data; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + return 0; + } + case ETHTOOL_GTXCSUM: { + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + + edata.data = + (netdev->features & NETIF_F_HW_CSUM) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_STXCSUM: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if(adapter->hw.mac_type < e1000_82543) { + if (edata.data != 0) + return -EINVAL; + return 0; + } + + if (edata.data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + + return 0; + } + case ETHTOOL_GSG: { + struct ethtool_value edata = { ETHTOOL_GSG }; + + edata.data = + (netdev->features & NETIF_F_SG) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSG: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if (edata.data) + netdev->features |= NETIF_F_SG; + else + netdev->features &= ~NETIF_F_SG; + + return 0; + } +#ifdef NETIF_F_TSO + case ETHTOOL_GTSO: { + struct ethtool_value edata = { ETHTOOL_GTSO }; + + edata.data = (netdev->features & NETIF_F_TSO) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_STSO: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if ((adapter->hw.mac_type < e1000_82544) || + (adapter->hw.mac_type == e1000_82547)) { + if (edata.data != 0) + return -EINVAL; + return 0; + } + + if (edata.data) + netdev->features |= NETIF_F_TSO; + else + netdev->features &= ~NETIF_F_TSO; + + return 0; + } +#endif default: return -EOPNOTSUPP; } diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_hw.c linux-2.4.22-bk26/drivers/net/e1000/e1000_hw.c --- linux-2.4.22-bk25/drivers/net/e1000/e1000_hw.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_hw.c 2003-09-29 02:49:41.000000000 -0700 @@ -34,14 +34,15 @@ static int32_t e1000_set_phy_type(struct e1000_hw *hw); static void e1000_phy_init_script(struct e1000_hw *hw); -static int32_t e1000_setup_fiber_link(struct e1000_hw *hw); static int32_t e1000_setup_copper_link(struct e1000_hw *hw); +static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw); +static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw); static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw); -static int32_t e1000_force_mac_fc(struct e1000_hw *hw); static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count); +static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, + uint16_t count); static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset, @@ -52,14 +53,31 @@ static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw); static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count); +static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, + uint16_t count); +static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, + uint16_t phy_data); +static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr, + uint16_t *phy_data); static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); +static int32_t e1000_set_vco_speed(struct e1000_hw *hw); +/* IGP cable length table */ +static const +uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, + 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; /****************************************************************************** * Set the phy type member in the hw struct. @@ -100,50 +118,41 @@ DEBUGFUNC("e1000_phy_init_script"); if(hw->phy_init_script) { - msec_delay(10); + msec_delay(20); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); e1000_write_phy_reg(hw,0x0000,0x0140); msec_delay(5); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F95); - e1000_write_phy_reg(hw,0x0015,0x0001); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F71); - e1000_write_phy_reg(hw,0x0011,0xBD21); + if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) { + e1000_write_phy_reg(hw, 0x1F95, 0x0001); + + e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F79); - e1000_write_phy_reg(hw,0x0019,0x0018); + e1000_write_phy_reg(hw, 0x1F79, 0x0018); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F30); - e1000_write_phy_reg(hw,0x0010,0x1600); + e1000_write_phy_reg(hw, 0x1F30, 0x1600); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F31); - e1000_write_phy_reg(hw,0x0011,0x0014); + e1000_write_phy_reg(hw, 0x1F31, 0x0014); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F32); - e1000_write_phy_reg(hw,0x0012,0x161C); + e1000_write_phy_reg(hw, 0x1F32, 0x161C); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F94); - e1000_write_phy_reg(hw,0x0014,0x0003); + e1000_write_phy_reg(hw, 0x1F94, 0x0003); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F96); - e1000_write_phy_reg(hw,0x0016,0x003F); + e1000_write_phy_reg(hw, 0x1F96, 0x003F); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x2010); - e1000_write_phy_reg(hw,0x0010,0x0008); + e1000_write_phy_reg(hw, 0x2010, 0x0008); + } else { + e1000_write_phy_reg(hw, 0x1F73, 0x0099); + } - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); - e1000_write_phy_reg(hw,0x0000,0x3300); + e1000_write_phy_reg(hw, 0x0000, 0x3300); if(hw->mac_type == e1000_82547) { uint16_t fused, fine, coarse; /* Move to analog registers page */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_ANALOG_REGS_PAGE); - e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { @@ -158,17 +167,14 @@ } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | + fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | + (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); - e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, + e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); } - /* Return to first page of registers */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_IEEE_REGS_PAGE); } } } @@ -218,32 +224,89 @@ case E1000_DEV_ID_82545EM_FIBER: hw->mac_type = e1000_82545; break; + case E1000_DEV_ID_82545GM_COPPER: + case E1000_DEV_ID_82545GM_FIBER: + case E1000_DEV_ID_82545GM_SERDES: + hw->mac_type = e1000_82545_rev_3; + break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_QUAD_COPPER: hw->mac_type = e1000_82546; break; + case E1000_DEV_ID_82546GB_COPPER: + case E1000_DEV_ID_82546GB_FIBER: + case E1000_DEV_ID_82546GB_SERDES: + hw->mac_type = e1000_82546_rev_3; + break; case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82541EI_MOBILE: hw->mac_type = e1000_82541; break; + case E1000_DEV_ID_82541ER: + case E1000_DEV_ID_82541GI: + case E1000_DEV_ID_82541GI_MOBILE: + hw->mac_type = e1000_82541_rev_2; + break; case E1000_DEV_ID_82547EI: hw->mac_type = e1000_82547; break; + case E1000_DEV_ID_82547GI: + hw->mac_type = e1000_82547_rev_2; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } - return E1000_SUCCESS; } + +/***************************************************************************** + * Set media type and TBI compatibility. + * + * hw - Struct containing variables accessed by shared code + * **************************************************************************/ +void +e1000_set_media_type(struct e1000_hw *hw) +{ + uint32_t status; + + DEBUGFUNC("e1000_set_media_type"); + + if(hw->mac_type != e1000_82543) { + /* tbi_compatibility is only valid on 82543 */ + hw->tbi_compatibility_en = FALSE; + } + + switch (hw->device_id) { + case E1000_DEV_ID_82545GM_SERDES: + case E1000_DEV_ID_82546GB_SERDES: + hw->media_type = e1000_media_type_internal_serdes; + break; + default: + if(hw->mac_type >= e1000_82543) { + status = E1000_READ_REG(hw, STATUS); + if(status & E1000_STATUS_TBIMODE) { + hw->media_type = e1000_media_type_fiber; + /* tbi_compatibility not valid on fiber */ + hw->tbi_compatibility_en = FALSE; + } else { + hw->media_type = e1000_media_type_copper; + } + } else { + /* This is an 82542 (fiber only) */ + hw->media_type = e1000_media_type_fiber; + } + } +} + /****************************************************************************** * Reset the transmit and receive units; mask and clear all interrupts. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +int32_t e1000_reset_hw(struct e1000_hw *hw) { uint32_t ctrl; @@ -280,49 +343,75 @@ */ msec_delay(10); - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); /* Must reset the PHY before resetting the MAC */ if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); - msec_delay(5); + msec_delay(5); } + /* Issue a global reset to the MAC. This will reset the chip's + * transmit, receive, DMA, and link units. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + DEBUGOUT("Issuing a global reset to MAC\n"); + switch(hw->mac_type) { case e1000_82544: case e1000_82540: case e1000_82545: case e1000_82546: case e1000_82541: + case e1000_82541_rev_2: /* These controllers can't ack the 64-bit write when issuing the * reset, so use IO-mapping as a workaround to issue the reset */ E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; + case e1000_82545_rev_3: + case e1000_82546_rev_3: + /* Reset is performed on a shadow of the control register */ + E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST)); + break; default: E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; } - /* Force a reload from the EEPROM if necessary */ - if(hw->mac_type < e1000_82540) { - /* Wait for reset to complete */ - udelay(10); - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - /* Wait for EEPROM reload */ - msec_delay(2); - } else { - /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(5); - /* Dissable HW ARPs on ASF enabled adapters */ + /* After MAC reset, force reload of EEPROM to restore power-on settings to + * device. Later controllers reload the EEPROM automatically, so just wait + * for reload to complete. + */ + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: + /* Wait for reset to complete */ + udelay(10); + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + /* Wait for EEPROM reload */ + msec_delay(2); + break; + case e1000_82541: + case e1000_82541_rev_2: + case e1000_82547: + case e1000_82547_rev_2: + /* Wait for EEPROM reload */ + msec_delay(20); + break; + default: + /* Wait for EEPROM reload (it happens automatically) */ + msec_delay(5); + break; + } + + /* Disable HW ARPs on ASF enabled adapters */ + if(hw->mac_type >= e1000_82540) { manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); @@ -350,6 +439,8 @@ if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } + + return E1000_SUCCESS; } /****************************************************************************** @@ -366,7 +457,7 @@ int32_t e1000_init_hw(struct e1000_hw *hw) { - uint32_t ctrl, status; + uint32_t ctrl; uint32_t i; int32_t ret_val; uint16_t pcix_cmd_word; @@ -377,31 +468,13 @@ DEBUGFUNC("e1000_init_hw"); /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if(ret_val < 0) { + if((ret_val = e1000_id_led_init(hw))) { DEBUGOUT("Error Initializing Identification LED\n"); return ret_val; } - /* Set the Media Type and exit with error if it is not valid. */ - if(hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = FALSE; - } - - if(hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; - } else { - hw->media_type = e1000_media_type_copper; - } - } else { - /* This is an 82542 (fiber only) */ - hw->media_type = e1000_media_type_fiber; - } + /* Set the media type and TBI compatibility */ + e1000_set_media_type(hw); /* Disabling VLAN filtering. */ DEBUGOUT("Initializing the IEEE VLAN\n"); @@ -446,21 +519,30 @@ E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } - /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if(hw->bus_type == e1000_bus_type_pcix) { - e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); - e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); - cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> - PCIX_COMMAND_MMRBC_SHIFT; - stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> - PCIX_STATUS_HI_MMRBC_SHIFT; - if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) - stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if(cmd_mmrbc > stat_mmrbc) { - pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; - pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; - e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if(hw->bus_type == e1000_bus_type_pcix) { + e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, + &pcix_stat_hi_word); + cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> + PCIX_COMMAND_MMRBC_SHIFT; + stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> + PCIX_STATUS_HI_MMRBC_SHIFT; + if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) + stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; + if(cmd_mmrbc > stat_mmrbc) { + pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; + pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; + e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, + &pcix_cmd_word); + } } + break; } /* Call a subroutine to configure the link and setup flow control. */ @@ -484,6 +566,46 @@ } /****************************************************************************** + * Adjust SERDES output amplitude based on EEPROM setting. + * + * hw - Struct containing variables accessed by shared code. + *****************************************************************************/ +static int32_t +e1000_adjust_serdes_amplitude(struct e1000_hw *hw) +{ + uint16_t eeprom_data; + int32_t ret_val; + + DEBUGFUNC("e1000_adjust_serdes_amplitude"); + + if(hw->media_type != e1000_media_type_internal_serdes) + return E1000_SUCCESS; + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, + &eeprom_data))) { + return ret_val; + } + + if(eeprom_data != EEPROM_RESERVED_WORD) { + /* Adjust SERDES output amplitude only. */ + eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, + eeprom_data))) + return ret_val; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** * Configures flow control and link settings. * * hw - Struct containing variables accessed by shared code @@ -554,9 +676,9 @@ } /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_fiber) ? - e1000_setup_fiber_link(hw) : - e1000_setup_copper_link(hw); + ret_val = (hw->media_type == e1000_media_type_copper) ? + e1000_setup_copper_link(hw) : + e1000_setup_fiber_serdes_link(hw); /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow @@ -595,7 +717,7 @@ } /****************************************************************************** - * Sets up link for a fiber based adapter + * Sets up link for a fiber based or serdes based adapter * * hw - Struct containing variables accessed by shared code * @@ -604,28 +726,37 @@ * and receiver are not enabled. *****************************************************************************/ static int32_t -e1000_setup_fiber_link(struct e1000_hw *hw) +e1000_setup_fiber_serdes_link(struct e1000_hw *hw) { uint32_t ctrl; uint32_t status; uint32_t txcw = 0; uint32_t i; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; - DEBUGFUNC("e1000_setup_fiber_link"); + DEBUGFUNC("e1000_setup_fiber_serdes_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. + * If we're on serdes media, adjust the output amplitude to value set in + * the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; + + if((ret_val = e1000_adjust_serdes_amplitude(hw))) + return ret_val; /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST); + /* Adjust VCO speed to improve BER performance */ + if((ret_val = e1000_set_vco_speed(hw))) + return ret_val; + e1000_config_collision_dist(hw); /* Check for a software override of the flow control settings, and setup @@ -692,8 +823,10 @@ * indication in the Device Status Register. Time-out if a link isn't * seen in 500 milliseconds seconds (Auto-negotiation should complete in * less than 500 milliseconds even if the other end is doing it in SW). + * For internal serdes, we just assume a signal is present, then poll. */ - if((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { + if(hw->media_type == e1000_media_type_internal_serdes || + (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { DEBUGOUT("Looking for Link\n"); for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { msec_delay(10); @@ -701,19 +834,20 @@ if(status & E1000_STATUS_LU) break; } if(i == (LINK_UP_TIMEOUT / 10)) { - /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the link up if we - * detect a signal. This will allow us to communicate with - * non-autonegotiating link partners. - */ DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; - ret_val = e1000_check_for_link(hw); - if(ret_val < 0) { - DEBUGOUT("Error while checking for link\n"); - return ret_val; + if(hw->media_type == e1000_media_type_fiber) { + /* AutoNeg failed to achieve a link, so we'll call + * e1000_check_for_link. This routine will force the link up if + * we detect a signal. This will allow us to communicate with + * non-autonegotiating link partners. + */ + if((ret_val = e1000_check_for_link(hw))) { + DEBUGOUT("Error while checking for link\n"); + return ret_val; + } + hw->autoneg_failed = 0; } - hw->autoneg_failed = 0; } else { hw->autoneg_failed = 0; DEBUGOUT("Valid Link Found\n"); @@ -721,7 +855,7 @@ } else { DEBUGOUT("No Signal Detected\n"); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -756,233 +890,281 @@ } /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_detect_gig_phy(hw))) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); - if (hw->phy_type == e1000_phy_igp) { - - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + if(hw->mac_type <= e1000_82543 || + hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || + hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) + hw->phy_reset_disable = FALSE; - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + if(!hw->phy_reset_disable) { + if (hw->phy_type == e1000_phy_igp) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - /* Set auto Master/Slave resolution process */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + + /* disable lplu d3 during driver init */ + if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) { + DEBUGOUT("Error Disabling LPLU D3\n"); + return ret_val; } - phy_data &= ~CR_1000T_MS_ENABLE; - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + + /* Configure mdi-mdix settings */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; + + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + hw->dsp_config_state = e1000_dsp_config_disabled; + /* Force MDI for IGP B-0 PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | + IGP01E1000_PSCR_FORCE_MDI_MDIX); + hw->mdix = 1; + + } else { + hw->dsp_config_state = e1000_dsp_config_enabled; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + + switch (hw->mdix) { + case 1: + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 2: + phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 0: + default: + phy_data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } } - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + /* set auto-master slave resolution settings */ + if(hw->autoneg) { + e1000_ms_type phy_ms_setting = hw->master_slave; + + if(hw->ffe_config_state == e1000_ffe_config_active) + hw->ffe_config_state = e1000_ffe_config_enabled; + + if(hw->dsp_config_state == e1000_dsp_config_activated) + hw->dsp_config_state = e1000_dsp_config_enabled; + + /* when autonegotiation advertisment is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. */ + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + /* Set auto Master/Slave resolution process */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; + phy_data &= ~CR_1000T_MS_ENABLE; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } - /* Force MDI for IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; - hw->mdix = 1; + /* load defaults for future use */ + hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? + ((phy_data & CR_1000T_MS_VALUE) ? + e1000_ms_force_master : + e1000_ms_force_slave) : + e1000_ms_auto; + + switch (phy_ms_setting) { + case e1000_ms_force_master: + phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); + break; + case e1000_ms_force_slave: + phy_data |= CR_1000T_MS_ENABLE; + phy_data &= ~(CR_1000T_MS_VALUE); + break; + case e1000_ms_auto: + phy_data &= ~CR_1000T_MS_ENABLE; + default: + break; + } + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } + } else { + /* Enable CRS on TX. This must be set for half-duplex operation. */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - } else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + if((ret_val = e1000_write_phy_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; } - } - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; + /* SW Reset the PHY so all changes take effect */ + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } } - } - /* Options: - * autoneg = 1 (default) - * PHY will advertise value(s) parsed from - * autoneg_advertised and fc - * autoneg = 0 - * PHY will be set to 10H, 10F, 100H, or 100F - * depending on value parsed from forced_speed_duplex. - */ + /* Options: + * autoneg = 1 (default) + * PHY will advertise value(s) parsed from + * autoneg_advertised and fc + * autoneg = 0 + * PHY will be set to 10H, 10F, 100H, or 100F + * depending on value parsed from forced_speed_duplex. + */ + + /* Is autoneg enabled? This is enabled by default or by software + * override. If so, call e1000_phy_setup_autoneg routine to parse the + * autoneg_advertised and fc options. If autoneg is NOT enabled, then + * the user should have provided a speed/duplex override. If so, then + * call e1000_phy_force_speed_duplex to parse and set this up. + */ + if(hw->autoneg) { + /* Perform some bounds checking on the hw->autoneg_advertised + * parameter. If this variable is zero, then set it to the default. + */ + hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* Is autoneg enabled? This is enabled by default or by software override. - * If so, call e1000_phy_setup_autoneg routine to parse the - * autoneg_advertised and fc options. If autoneg is NOT enabled, then the - * user should have provided a speed/duplex override. If so, then call - * e1000_phy_force_speed_duplex to parse and set this up. - */ - if(hw->autoneg) { - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if(hw->autoneg_advertised == 0) + hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if(hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); + if((ret_val = e1000_phy_setup_autoneg(hw))) { + DEBUGOUT("Error Setting up Auto-Negotiation\n"); + return ret_val; + } + DEBUGOUT("Restarting Auto-Neg\n"); - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - DEBUGOUT("Restarting Auto-Neg\n"); + /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if(hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); + /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if(hw->wait_autoneg_complete) { + if((ret_val = e1000_wait_autoneg(hw))) { + DEBUGOUT("Error while waiting for autoneg to complete\n"); + return ret_val; + } + } + hw->get_link_status = TRUE; + } else { + DEBUGOUT("Forcing speed and duplex\n"); + if((ret_val = e1000_phy_force_speed_duplex(hw))) { + DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } } - hw->get_link_status = TRUE; - } else { - DEBUGOUT("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if(ret_val < 0) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } + } /* !hw->phy_reset_disable */ /* Check link status. Wait up to 100 microseconds for link to become * valid. */ for(i = 0; i < 10; i++) { - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if(phy_data & MII_SR_LINK_STATUS) { /* We have link, so we need to finish the config process: * 1) Set up the MAC to the current PHY speed/duplex @@ -995,25 +1177,31 @@ if(hw->mac_type >= e1000_82544) { e1000_config_collision_dist(hw); } else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; - } + } } - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error Configuring Flow Control\n"); return ret_val; } DEBUGOUT("Valid link established!!!\n"); - return 0; + + if(hw->phy_type == e1000_phy_igp) { + if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) { + DEBUGOUT("Error Configuring DSP after link up\n"); + return ret_val; + } + } + DEBUGOUT("Valid link established!!!\n"); + return E1000_SUCCESS; } udelay(10); } DEBUGOUT("Unable to establish link!!!\n"); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1024,22 +1212,20 @@ int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t mii_autoneg_adv_reg; uint16_t mii_1000t_ctrl_reg; DEBUGFUNC("e1000_phy_setup_autoneg"); /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_autoneg_adv_reg))) + return ret_val; /* Read the MII 1000Base-T Control Register (Address 9). */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg))) + return ret_val; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1145,18 +1331,16 @@ return -E1000_ERR_CONFIG; } - if(e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, + mii_autoneg_adv_reg))) + return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - return 0; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg))) + return ret_val; + + return E1000_SUCCESS; } /****************************************************************************** @@ -1192,10 +1376,8 @@ ctrl &= ~E1000_CTRL_ASDE; /* Read the MII Control Register. */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg))) + return ret_val; /* We need to disable autoneg in order to force link and duplex. */ @@ -1241,19 +1423,18 @@ E1000_WRITE_REG(hw, CTRL, ctrl); if (hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed are duplex are forced. */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); /* Need to reset the PHY or these changes will be ignored */ @@ -1262,26 +1443,23 @@ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; } /* Write back the modified PHY MII control register. */ - if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } udelay(1); + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg))) + return ret_val; + /* The wait_autoneg_complete flag may be a little misleading here. * Since we are forcing speed and duplex, Auto-Neg is not enabled. @@ -1300,22 +1478,18 @@ /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + if(mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay(100); } if(i == 0) { /* We didn't get link */ /* Reset the DSP and wait again for link. */ - - ret_val = e1000_phy_reset_dsp(hw); - if(ret_val < 0) { + if((ret_val = e1000_phy_reset_dsp(hw))) { DEBUGOUT("Error Resetting PHY DSP\n"); return ret_val; } @@ -1327,14 +1501,11 @@ /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; } } @@ -1343,30 +1514,29 @@ * Extended PHY Specific Control Register to 25MHz clock. This value * defaults back to a 2.5MHz clock when the PHY is reset. */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; /* In addition, because of the s/w reset above, we need to enable CRS on * TX. This must be set for both full and half duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1406,6 +1576,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) { uint32_t ctrl; + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_config_mac_to_phy"); @@ -1421,10 +1592,10 @@ * registers depending on negotiated values. */ if (hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1440,10 +1611,10 @@ IGP01E1000_PSSR_SPEED_100MBPS) ctrl |= E1000_CTRL_SPD_100; } else { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1459,7 +1630,7 @@ } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1473,7 +1644,7 @@ * by the PHY rather than the MAC. Software must also configure these * bits when link is forced on a fiber connection. *****************************************************************************/ -static int32_t +int32_t e1000_force_mac_fc(struct e1000_hw *hw) { uint32_t ctrl; @@ -1526,7 +1697,7 @@ ctrl &= (~E1000_CTRL_TFCE); E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1557,9 +1728,9 @@ * configuration of the MAC to match the "fc" parameter. */ if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) || + ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) || ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) { - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } @@ -1575,14 +1746,10 @@ * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) { /* The AutoNeg process has completed, so we now need to @@ -1591,14 +1758,12 @@ * Register (Address 5) to determine how flow control was * negotiated. */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg))) + return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base @@ -1704,7 +1869,7 @@ hw->original_fc == e1000_fc_tx_pause) { hw->fc = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); - } else { + } else if(!hw->fc_strict_ieee) { hw->fc = e1000_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); } @@ -1713,7 +1878,10 @@ * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ - e1000_get_speed_and_duplex(hw, &speed, &duplex); + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } if(duplex == HALF_DUPLEX) hw->fc = e1000_fc_none; @@ -1721,16 +1889,15 @@ /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; - } + } } else { DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1747,19 +1914,19 @@ uint32_t ctrl; uint32_t status; uint32_t rctl; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; uint16_t phy_data; uint16_t lp_capability; DEBUGFUNC("e1000_check_for_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. */ - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; ctrl = E1000_READ_REG(hw, CTRL); status = E1000_READ_REG(hw, STATUS); @@ -1777,14 +1944,10 @@ * of the PHY. * Read the register twice since the link bit is sticky. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; @@ -1794,6 +1957,7 @@ } else { /* No link detected */ + e1000_config_dsp_after_link_change(hw, FALSE); return 0; } @@ -1802,6 +1966,9 @@ */ if(!hw->autoneg) return -E1000_ERR_CONFIG; + /* optimize the dsp settings for the igp phy */ + e1000_config_dsp_after_link_change(hw, TRUE); + /* We have a M88E1000 PHY and Auto-Neg is enabled. If we * have Si on board that is 82544 or newer, Auto * Speed Detection takes care of MAC speed/duplex @@ -1813,8 +1980,7 @@ if(hw->mac_type >= e1000_82544) e1000_config_collision_dist(hw); else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } @@ -1824,8 +1990,7 @@ * need to restore the desired flow control settings because we may * have had to re-autoneg with a different link partner. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1840,10 +2005,9 @@ * partner is TBI-based, and we turn on TBI Compatibility. */ if(hw->tbi_compatibility_en) { - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &lp_capability) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, + &lp_capability))) + return ret_val; if(lp_capability & (NWAY_LPAR_10T_HD_CAPS | NWAY_LPAR_10T_FD_CAPS | NWAY_LPAR_100TX_HD_CAPS | @@ -1900,8 +2064,7 @@ E1000_WRITE_REG(hw, CTRL, ctrl); /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1918,7 +2081,7 @@ E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1928,12 +2091,14 @@ * speed - Speed of the connection * duplex - Duplex setting of the connection *****************************************************************************/ -void +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex) { uint32_t status; + int32_t ret_val; + uint16_t phy_data; DEBUGFUNC("e1000_get_speed_and_duplex"); @@ -1962,6 +2127,27 @@ *speed = SPEED_1000; *duplex = FULL_DUPLEX; } + + /* IGP01 PHY may advertise full duplex operation after speed downgrade even + * if it is operating at half duplex. Here we set the duplex settings to + * match the duplex in the link partner's capabilities. + */ + if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) + return ret_val; + + if(!(phy_data & NWAY_ER_LP_NWAY_CAPS)) + *duplex = HALF_DUPLEX; + else { + if((ret_val == e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data))) + return ret_val; + if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || + (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) + *duplex = HALF_DUPLEX; + } + } + + return E1000_SUCCESS; } /****************************************************************************** @@ -1972,6 +2158,7 @@ int32_t e1000_wait_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t i; uint16_t phy_data; @@ -1983,20 +2170,16 @@ /* Read the MII Status Register and wait for Auto-Neg * Complete bit to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_AUTONEG_COMPLETE) { - return 0; + return E1000_SUCCESS; } msec_delay(100); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2010,11 +2193,11 @@ uint32_t *ctrl) { /* Raise the clock input to the Management Data Clock (by setting the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2028,11 +2211,11 @@ uint32_t *ctrl) { /* Lower the clock input to the Management Data Clock (by clearing the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2076,7 +2259,7 @@ E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); e1000_raise_mdi_clk(hw, &ctrl); e1000_lower_mdi_clk(hw, &ctrl); @@ -2138,8 +2321,8 @@ } /***************************************************************************** -* Reads the value from a PHY register -* +* Reads the value from a PHY register, if the value is on a specific non zero +* page, sets the page first. * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to read ******************************************************************************/ @@ -2148,11 +2331,33 @@ uint32_t reg_addr, uint16_t *phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_read_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_read_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t *phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_read_phy_reg"); + DEBUGFUNC("e1000_read_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2172,7 +2377,7 @@ /* Poll the ready bit to see if the MDI read completed */ for(i = 0; i < 64; i++) { - udelay(10); + udelay(50); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2214,7 +2419,7 @@ */ *phy_data = e1000_shift_in_mdi_bits(hw); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2229,11 +2434,33 @@ uint32_t reg_addr, uint16_t phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_write_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_write_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_write_phy_reg"); + DEBUGFUNC("e1000_write_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2254,7 +2481,7 @@ /* Poll the ready bit to see if the MDI read completed */ for(i = 0; i < 64; i++) { - udelay(10); + udelay(50); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2284,7 +2511,7 @@ e1000_shift_out_mdi_bits(hw, mdic, 32); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2329,11 +2556,6 @@ udelay(150); if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return; - } - /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; @@ -2352,24 +2574,26 @@ int32_t e1000_phy_reset(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_reset"); - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= MII_CR_RESET; - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - udelay(1); - if (hw->phy_type == e1000_phy_igp) { + if(hw->mac_type != e1000_82541_rev_2) { + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; + + phy_data |= MII_CR_RESET; + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; + + udelay(1); + } else e1000_phy_hw_reset(hw); + + if(hw->phy_type == e1000_phy_igp) e1000_phy_init_script(hw); - } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -2380,23 +2604,21 @@ int32_t e1000_detect_gig_phy(struct e1000_hw *hw) { + int32_t phy_init_status, ret_val; uint16_t phy_id_high, phy_id_low; boolean_t match = FALSE; - int32_t phy_init_status; DEBUGFUNC("e1000_detect_gig_phy"); /* Read the PHY ID Registers to identify which PHY is onboard. */ - if(e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high))) + return ret_val; + hw->phy_id = (uint32_t) (phy_id_high << 16); udelay(20); - if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low))) + return ret_val; + hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; @@ -2409,11 +2631,15 @@ break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; break; default: @@ -2424,7 +2650,7 @@ if ((match) && (phy_init_status == E1000_SUCCESS)) { DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); - return 0; + return E1000_SUCCESS; } DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id); return -E1000_ERR_PHY; @@ -2438,17 +2664,16 @@ static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw) { - int32_t ret_val = -E1000_ERR_PHY; + int32_t ret_val; DEBUGFUNC("e1000_phy_reset_dsp"); do { - if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x0000) < 0) break; - ret_val = 0; + if((ret_val = e1000_write_phy_reg(hw, 29, 0x001d))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x00c1))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x0000))) break; + ret_val = E1000_SUCCESS; } while(0); - if(ret_val < 0) DEBUGOUT("PHY Write Error\n"); return ret_val; } @@ -2459,8 +2684,10 @@ * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_igp_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity, min_length, max_length, average; DEBUGFUNC("e1000_phy_igp_get_info"); @@ -2476,13 +2703,14 @@ phy_info->polarity_correction = e1000_polarity_reversal_enabled; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> IGP01E1000_PSSR_MDIX_SHIFT; @@ -2490,8 +2718,8 @@ if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { /* Local/Remote Receiver Information are only valid at 1000 Mbps */ - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2499,8 +2727,8 @@ SR_1000T_REMOTE_RX_STATUS_SHIFT; /* Get cable length */ - if(e1000_get_cable_length(hw, &min_length, &max_length) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_get_cable_length(hw, &min_length, &max_length))) + return ret_val; /* transalte to old method */ average = (max_length + min_length) / 2; @@ -2527,8 +2755,10 @@ * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_m88_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity; DEBUGFUNC("e1000_phy_m88_get_info"); @@ -2537,8 +2767,8 @@ * and it stored in the hw->speed_downgraded parameter. */ phy_info->downshift = hw->speed_downgraded; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data))) + return ret_val; phy_info->extended_10bt_distance = (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> @@ -2548,13 +2778,13 @@ M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> M88E1000_PSSR_MDIX_SHIFT; @@ -2566,8 +2796,8 @@ phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2589,6 +2819,7 @@ e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_get_info"); @@ -2607,20 +2838,18 @@ return -E1000_ERR_CONFIG; } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { DEBUGOUT("PHY info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } - if (hw->phy_type == e1000_phy_igp) + if(hw->phy_type == e1000_phy_igp) return e1000_phy_igp_get_info(hw, phy_info); else return e1000_phy_m88_get_info(hw, phy_info); @@ -2636,7 +2865,7 @@ hw->mdix = 1; return -E1000_ERR_CONFIG; } - return 0; + return E1000_SUCCESS; } @@ -2668,7 +2897,9 @@ break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: eeprom->type = e1000_eeprom_microwire; eeprom->opcode_bits = 3; eeprom->delay_usec = 50; @@ -2681,8 +2912,9 @@ } break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: - default: + case e1000_82547_rev_2: if (eecd & E1000_EECD_TYPE) { eeprom->type = e1000_eeprom_spi; eeprom->opcode_bits = 8; @@ -2707,6 +2939,18 @@ } } break; + default: + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + break; } if (eeprom->type == e1000_eeprom_spi) { @@ -2715,28 +2959,28 @@ eeprom_size &= EEPROM_SIZE_MASK; switch (eeprom_size) { - case EEPROM_SIZE_16KB: - eeprom->word_size = 8192; - break; - case EEPROM_SIZE_8KB: - eeprom->word_size = 4096; - break; - case EEPROM_SIZE_4KB: - eeprom->word_size = 2048; - break; - case EEPROM_SIZE_2KB: - eeprom->word_size = 1024; - break; - case EEPROM_SIZE_1KB: - eeprom->word_size = 512; - break; - case EEPROM_SIZE_512B: - eeprom->word_size = 256; - break; - case EEPROM_SIZE_128B: - default: - eeprom->word_size = 64; - break; + case EEPROM_SIZE_16KB: + eeprom->word_size = 8192; + break; + case EEPROM_SIZE_8KB: + eeprom->word_size = 4096; + break; + case EEPROM_SIZE_4KB: + eeprom->word_size = 2048; + break; + case EEPROM_SIZE_2KB: + eeprom->word_size = 1024; + break; + case EEPROM_SIZE_1KB: + eeprom->word_size = 512; + break; + case EEPROM_SIZE_512B: + eeprom->word_size = 256; + break; + case EEPROM_SIZE_128B: + default: + eeprom->word_size = 64; + break; } } } @@ -2841,7 +3085,8 @@ * hw - Struct containing variables accessed by shared code *****************************************************************************/ static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count) +e1000_shift_in_ee_bits(struct e1000_hw *hw, + uint16_t count) { uint32_t eecd; uint32_t i; @@ -3101,13 +3346,17 @@ } /* Prepare the EEPROM for reading */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) + if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; if(eeprom->type == e1000_eeprom_spi) { + uint16_t word_in; uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; + if(e1000_spi_eeprom_ready(hw)) { + e1000_release_eeprom(hw); + return -E1000_ERR_EEPROM; + } e1000_standby_eeprom(hw); @@ -3118,30 +3367,35 @@ /* Send the READ command (opcode + addr) */ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits); - } - else if(eeprom->type == e1000_eeprom_microwire) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, offset, eeprom->address_bits); - } - /* Read the data. The address of the eeprom internally increments with - * each word (microwire) or byte (spi) being read, saving on the overhead - * of eeprom setup and tear-down. The address counter will roll over if - * reading beyond the size of the eeprom, thus allowing the entire memory - * to be read starting from any offset. */ - for (i = 0; i < words; i++) { - uint16_t word_in = e1000_shift_in_ee_bits(hw, 16); - if (eeprom->type == e1000_eeprom_spi) - word_in = (word_in >> 8) | (word_in << 8); - data[i] = word_in; + /* Read the data. The address of the eeprom internally increments with + * each byte (spi) being read, saving on the overhead of eeprom setup + * and tear-down. The address counter will roll over if reading beyond + * the size of the eeprom, thus allowing the entire memory to be read + * starting from any offset. */ + for (i = 0; i < words; i++) { + word_in = e1000_shift_in_ee_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } + } else if(eeprom->type == e1000_eeprom_microwire) { + for (i = 0; i < words; i++) { + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, + eeprom->opcode_bits); + e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i), + eeprom->address_bits); + + /* Read the data. For microwire, each word requires the overhead + * of eeprom setup and tear-down. */ + data[i] = e1000_shift_in_ee_bits(hw, 16); + e1000_standby_eeprom(hw); + } } /* End this read operation */ e1000_release_eeprom(hw); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3169,9 +3423,9 @@ checksum += eeprom_data; } - if(checksum == (uint16_t) EEPROM_SUM) { - return 0; - } else { + if(checksum == (uint16_t) EEPROM_SUM) + return E1000_SUCCESS; + else { DEBUGOUT("EEPROM Checksum Invalid\n"); return -E1000_ERR_EEPROM; } @@ -3205,7 +3459,7 @@ DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3403,7 +3657,7 @@ e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3437,7 +3691,7 @@ /* Save word 1 in lower half of part_num */ *part_num |= eeprom_data; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3463,7 +3717,7 @@ hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } - if((hw->mac_type == e1000_82546) && + if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) && (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { if(hw->perm_mac_addr[5] & 0x01) hw->perm_mac_addr[5] &= ~(0x01); @@ -3472,7 +3726,7 @@ } for(i = 0; i < NODE_ADDRESS_SIZE; i++) hw->mac_addr[i] = hw->perm_mac_addr[i]; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3748,7 +4002,7 @@ if(hw->mac_type < e1000_82540) { /* Nothing to do */ - return 0; + return E1000_SUCCESS; } ledctl = E1000_READ_REG(hw, LEDCTL); @@ -3799,7 +4053,7 @@ break; } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3811,49 +4065,48 @@ e1000_setup_led(struct e1000_hw *hw) { uint32_t ledctl; + int32_t ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No setup necessary */ break; - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); - break; + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn off PHY Smart Power Down (if enabled) */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, + &hw->phy_spd_default))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + (uint16_t)(hw->phy_spd_default & + ~IGP01E1000_GMII_SPD)))) + return ret_val; + /* Fall Through */ default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + ledctl = E1000_READ_REG(hw, LEDCTL); + /* Save current LEDCTL settings */ + hw->ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); + E1000_WRITE_REG(hw, LEDCTL, ledctl); + } else if(hw->media_type == e1000_media_type_copper) + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + break; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3864,39 +4117,33 @@ int32_t e1000_cleanup_led(struct e1000_hw *hw) { + int32_t ret_val = E1000_SUCCESS; + DEBUGFUNC("e1000_cleanup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No cleanup necessary */ break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn on PHY Smart Power Down (if previously enabled) */ + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + hw->phy_spd_default))) + return ret_val; + /* Fall Through */ + default: /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; - default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3907,50 +4154,44 @@ int32_t e1000_led_on(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_on"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Set SW Defineable Pin 0 to turn on the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn on the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -3961,50 +4202,44 @@ int32_t e1000_led_off(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_off"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Clear SW Defineable Pin 0 to turn off the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn off the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -4127,8 +4362,7 @@ DEBUGFUNC("e1000_update_adaptive"); if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > - hw->tx_packet_delta) { + if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { if(hw->tx_packet_delta > MIN_NUM_XMITS) { hw->in_ifs_mode = TRUE; if(hw->current_ifs_val < hw->ifs_max_val) { @@ -4140,8 +4374,7 @@ } } } else { - if((hw->in_ifs_mode == TRUE) && - (hw->tx_packet_delta <= MIN_NUM_XMITS)) { + if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { hw->current_ifs_val = 0; hw->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, AIT, 0); @@ -4324,7 +4557,8 @@ * min_length - The estimated minimum length * max_length - The estimated maximum length * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * This function always returns a ranged length (minimum & maximum). * So for M88 phy's, this function interprets the one value returned from the @@ -4332,9 +4566,11 @@ * For IGP phy's, the function calculates the range by the AGC registers. *****************************************************************************/ int32_t -e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, +e1000_get_cable_length(struct e1000_hw *hw, + uint16_t *min_length, uint16_t *max_length) { + int32_t ret_val; uint16_t agc_value = 0; uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; uint16_t i, phy_data; @@ -4345,8 +4581,9 @@ /* Use old method for Phy older than IGP */ if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; /* Convert the enum value to ranged values */ switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> @@ -4376,19 +4613,16 @@ break; } } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - uint16_t agc_reg_array[IGP01E1000_PHY_AGC_NUM] = {IGP01E1000_PHY_AGC_A, + uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_A, IGP01E1000_PHY_AGC_B, IGP01E1000_PHY_AGC_C, IGP01E1000_PHY_AGC_D}; /* Read the AGC registers for all channels */ - for(i = 0; i < IGP01E1000_PHY_AGC_NUM; i++) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - agc_reg_array[i]) != E1000_SUCCESS) - return -E1000_ERR_PHY; - if(e1000_read_phy_reg(hw, agc_reg_array[i] & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + + if((ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data))) + return ret_val; cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; @@ -4404,20 +4638,15 @@ min_agc = cur_agc; } - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; - /* Remove the minimal AGC result for length < 50m */ - if(agc_value < IGP01E1000_PHY_AGC_NUM * e1000_igp_cable_length_50) { + if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { agc_value -= min_agc; /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_AGC_NUM - 1); + agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); } else { /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_AGC_NUM; + agc_value /= IGP01E1000_PHY_CHANNEL_NUM; } /* Set the range of the calculated length. */ @@ -4439,7 +4668,8 @@ * polarity - output parameter : 0 - Polarity is not reversed * 1 - Polarity is reversed. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function simply reads the polarity bit in the * Phy Status register. For IGP phy's, this bit is valid only if link speed is @@ -4448,22 +4678,26 @@ * IGP01E1000_PHY_PCS_INIT_REG. *****************************************************************************/ int32_t -e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity) +e1000_check_polarity(struct e1000_hw *hw, + uint16_t *polarity) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_polarity"); if(hw->phy_type == e1000_phy_m88) { /* return the Polarity bit in the Status register. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> M88E1000_PSSR_REV_POLARITY_SHIFT; } else if(hw->phy_type == e1000_phy_igp) { /* Read the Status register to check the speed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to * find the polarity status */ @@ -4471,18 +4705,9 @@ IGP01E1000_PSSR_SPEED_1000MBPS) { /* Read the GIG initialization PCS register (0x00B4) */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG) < 0) - return -E1000_ERR_PHY; - - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) < 0) - return -E1000_ERR_PHY; - - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, + &phy_data))) + return ret_val; /* Check the polarity bits */ *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; @@ -4502,7 +4727,8 @@ * downshift - output parameter : 0 - No Downshift ocured. * 1 - Downshift ocured. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function reads the Downshift bit in the Phy * Specific Status register. For IGP phy's, it reads the Downgrade bit in the @@ -4512,25 +4738,287 @@ int32_t e1000_check_downshift(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_downshift"); if(hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; } else if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; + M88E1000_PSSR_DOWNSHIFT_SHIFT; } return E1000_SUCCESS; } +/***************************************************************************** + * + * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a + * gigabit link is achieved to improve link quality. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_config_dsp_after_link_change(struct e1000_hw *hw, + boolean_t link_up) +{ + int32_t ret_val; + uint16_t phy_data, speed, duplex, i; + uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_PARAM_A, + IGP01E1000_PHY_AGC_PARAM_B, + IGP01E1000_PHY_AGC_PARAM_C, + IGP01E1000_PHY_AGC_PARAM_D}; + uint16_t min_length, max_length; + + DEBUGFUNC("e1000_config_dsp_after_link_change"); + + if(hw->phy_type != e1000_phy_igp) + return E1000_SUCCESS; + + if(link_up) { + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } + + if(speed == SPEED_1000) { + + e1000_get_cable_length(hw, &min_length, &max_length); + + if((hw->dsp_config_state == e1000_dsp_config_enabled) && + min_length >= e1000_igp_cable_length_50) { + + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + + if((ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], + phy_data))) + return ret_val; + } + hw->dsp_config_state = e1000_dsp_config_activated; + } + + if((hw->ffe_config_state == e1000_ffe_config_enabled) && + (min_length < e1000_igp_cable_length_50)) { + + uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; + uint32_t idle_errs = 0; + + /* clear previous idle error counts */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + for(i = 0; i < ffe_idle_err_timeout; i++) { + udelay(1000); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); + if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { + hw->ffe_config_state = e1000_ffe_config_active; + + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_CM_CP))) + return ret_val; + break; + } + + if(idle_errs) + ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; + } + } + } + } else { + if(hw->dsp_config_state == e1000_dsp_config_activated) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; + + if((ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], + phy_data))) + return ret_val; + } + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + + hw->dsp_config_state = e1000_dsp_config_enabled; + } + + if(hw->ffe_config_state == e1000_ffe_config_active) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_DEFAULT))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + hw->ffe_config_state = e1000_ffe_config_enabled; + } + } + return E1000_SUCCESS; +} + +/***************************************************************************** + * + * This function sets the lplu state according to the active flag. When + * activating lplu this function also disables smart speed and vise versa. + * lplu will not be activated unless the device autonegotiation advertisment + * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. + * hw: Struct containing variables accessed by shared code + * active - true to enable lplu false to disable lplu. + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_set_d3_lplu_state(struct e1000_hw *hw, + boolean_t active) +{ + int32_t ret_val; + uint16_t phy_data; + DEBUGFUNC("e1000_set_d3_lplu_state"); + + if(!((hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2))) + return E1000_SUCCESS; + + /* During driver activity LPLU should not be used or it will attain link + * from the lowest speeds starting from 10Mbps. The capability is used for + * Dx transitions and states */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data))) + return ret_val; + + if(!active) { + phy_data &= ~IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during + * Dx states where the power conservation is most important. During + * driver activity we should enable SmartSpeed, so performance is + * maintained. */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data |= IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { + + phy_data |= IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* When LPLU is enabled we should disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } + return E1000_SUCCESS; +} + +/****************************************************************************** + * Change VCO speed register to improve Bit Error Rate performance of SERDES. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static int32_t +e1000_set_vco_speed(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t default_page = 0; + uint16_t phy_data; + + DEBUGFUNC("e1000_set_vco_speed"); + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + /* Set PHY register 30, page 5, bit 8 to 0 */ + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + &default_page))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + /* Set PHY register 30, page 4, bit 11 to 1 */ + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data |= M88E1000_PHY_VCO_REG_BIT11; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + default_page))) + return ret_val; + + return E1000_SUCCESS; +} + diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_hw.h linux-2.4.22-bk26/drivers/net/e1000/e1000_hw.h --- linux-2.4.22-bk25/drivers/net/e1000/e1000_hw.h 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_hw.h 2003-09-29 02:49:41.000000000 -0700 @@ -33,9 +33,9 @@ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ - #include "e1000_osdep.h" + /* Forward declarations of structures used by the shared code */ struct e1000_hw; struct e1000_hw_stats; @@ -50,9 +50,13 @@ e1000_82544, e1000_82540, e1000_82545, + e1000_82545_rev_3, e1000_82546, + e1000_82546_rev_3, e1000_82541, + e1000_82541_rev_2, e1000_82547, + e1000_82547_rev_2, e1000_num_macs } e1000_mac_type; @@ -67,6 +71,7 @@ typedef enum { e1000_media_type_copper = 0, e1000_media_type_fiber = 1, + e1000_media_type_internal_serdes = 2, e1000_num_media_types } e1000_media_type; @@ -90,7 +95,8 @@ typedef enum { e1000_bus_type_unknown = 0, e1000_bus_type_pci, - e1000_bus_type_pcix + e1000_bus_type_pcix, + e1000_bus_type_reserved } e1000_bus_type; /* PCI bus speeds */ @@ -108,7 +114,8 @@ typedef enum { e1000_bus_width_unknown = 0, e1000_bus_width_32, - e1000_bus_width_64 + e1000_bus_width_64, + e1000_bus_width_reserved } e1000_bus_width; /* PHY status info structure and supporting enums */ @@ -186,6 +193,26 @@ e1000_phy_undefined = 0xFF } e1000_phy_type; +typedef enum { + e1000_ms_hw_default = 0, + e1000_ms_force_master, + e1000_ms_force_slave, + e1000_ms_auto +} e1000_ms_type; + +typedef enum { + e1000_ffe_config_enabled = 0, + e1000_ffe_config_active, + e1000_ffe_config_blocked +} e1000_ffe_config; + +typedef enum { + e1000_dsp_config_disabled = 0, + e1000_dsp_config_enabled, + e1000_dsp_config_activated, + e1000_dsp_config_undefined = 0xFF +} e1000_dsp_config; + struct e1000_phy_info { e1000_cable_length cable_length; e1000_10bt_ext_dist_enable extended_10bt_distance; @@ -224,9 +251,10 @@ /* Function prototypes */ /* Initialization */ -void e1000_reset_hw(struct e1000_hw *hw); +int32_t e1000_reset_hw(struct e1000_hw *hw); int32_t e1000_init_hw(struct e1000_hw *hw); int32_t e1000_set_mac_type(struct e1000_hw *hw); +void e1000_set_media_type(struct e1000_hw *hw); /* Link Configuration */ int32_t e1000_setup_link(struct e1000_hw *hw); @@ -234,8 +262,9 @@ void e1000_config_collision_dist(struct e1000_hw *hw); int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); int32_t e1000_check_for_link(struct e1000_hw *hw); -void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); int32_t e1000_wait_autoneg(struct e1000_hw *hw); +int32_t e1000_force_mac_fc(struct e1000_hw *hw); /* PHY */ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data); @@ -292,6 +321,8 @@ uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); +int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up); +int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); #define E1000_READ_REG_IO(a, reg) \ e1000_read_reg_io((a), E1000_##reg) @@ -313,13 +344,22 @@ #define E1000_DEV_ID_82540EP_LP 0x101E #define E1000_DEV_ID_82545EM_COPPER 0x100F #define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82545GM_COPPER 0x1026 +#define E1000_DEV_ID_82545GM_FIBER 0x1027 +#define E1000_DEV_ID_82545GM_SERDES 0x1028 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EP 0x1018 +#define E1000_DEV_ID_82541EI_MOBILE 0x1018 +#define E1000_DEV_ID_82541ER 0x1078 +#define E1000_DEV_ID_82547GI 0x1075 +#define E1000_DEV_ID_82541GI 0x1076 +#define E1000_DEV_ID_82541GI_MOBILE 0x1077 +#define E1000_DEV_ID_82546GB_COPPER 0x1079 +#define E1000_DEV_ID_82546GB_FIBER 0x107A +#define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82547EI 0x1019 -#define NUM_DEV_IDS 20 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -385,7 +425,7 @@ E1000_IMS_RXSEQ | \ E1000_IMS_LSC) -/* The number of high/low register pairs in the RAR. The RAR (Receive Address +/* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for * E1000_RAR_ENTRIES - 1 multicast addresses. @@ -539,7 +579,7 @@ volatile uint32_t high; /* receive address high */ }; -/* The number of entries in the Multicast Table Array (MTA). */ +/* Number of entries in the Multicast Table Array (MTA). */ #define E1000_NUM_MTA_REGISTERS 128 /* IPv4 Address Table Entry */ @@ -599,6 +639,7 @@ * A - register array */ #define E1000_CTRL 0x00000 /* Device Control - RW */ +#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ #define E1000_STATUS 0x00008 /* Device Status - RO */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ @@ -934,6 +975,9 @@ e1000_bus_width bus_width; e1000_bus_type bus_type; struct e1000_eeprom_info eeprom; + e1000_ms_type master_slave; + e1000_ms_type original_master_slave; + e1000_ffe_config ffe_config_state; uint32_t io_base; uint32_t phy_id; uint32_t phy_revision; @@ -950,6 +994,8 @@ uint32_t ledctl_default; uint32_t ledctl_mode1; uint32_t ledctl_mode2; + uint16_t phy_spd_default; + uint16_t dsp_reset_counter; uint16_t autoneg_advertised; uint16_t pci_cmd_word; uint16_t fc_high_water; @@ -974,10 +1020,13 @@ uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; boolean_t disable_polarity_correction; boolean_t speed_downgraded; + e1000_dsp_config dsp_config_state; boolean_t get_link_status; boolean_t tbi_compatibility_en; boolean_t tbi_compatibility_on; + boolean_t phy_reset_disable; boolean_t fc_send_xon; + boolean_t fc_strict_ieee; boolean_t report_tx_early; boolean_t adaptive_ifs; boolean_t ifs_params_forced; @@ -1059,7 +1108,7 @@ #define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ #define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ #define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ + * (0-small, 1-large) */ #define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ #ifndef E1000_EEPROM_GRANT_ATTEMPTS #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ @@ -1121,22 +1170,22 @@ #define E1000_MDIC_ERROR 0x40000000 /* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_IVRT 0x00000040 +#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 +#define E1000_LEDCTL_LED1_MODE_SHIFT 8 +#define E1000_LEDCTL_LED1_IVRT 0x00004000 +#define E1000_LEDCTL_LED1_BLINK 0x00008000 +#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 +#define E1000_LEDCTL_LED2_MODE_SHIFT 16 +#define E1000_LEDCTL_LED2_IVRT 0x00400000 +#define E1000_LEDCTL_LED2_BLINK 0x00800000 +#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 +#define E1000_LEDCTL_LED3_MODE_SHIFT 24 +#define E1000_LEDCTL_LED3_IVRT 0x40000000 +#define E1000_LEDCTL_LED3_BLINK 0x80000000 #define E1000_LEDCTL_MODE_LINK_10_1000 0x0 #define E1000_LEDCTL_MODE_LINK_100_1000 0x1 @@ -1159,109 +1208,109 @@ #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ /* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 +#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ +#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ +#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ +#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ +#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ +#define E1000_ICR_RXO 0x00000040 /* rx overrun */ +#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ +#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ +#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ +#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ +#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ +#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ +#define E1000_ICR_TXD_LOW 0x00008000 +#define E1000_ICR_SRPD 0x00010000 /* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_ICS_SRPD E1000_ICR_SRPD /* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD +#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMS_SRPD E1000_ICR_SRPD /* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD +#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMC_SRPD E1000_ICR_SRPD /* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ +#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ +#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ +#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ +#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ +#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ +#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ +#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ +#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ +#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ +#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ +#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ +#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ +#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ +#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ +#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ +#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ @@ -1426,15 +1475,17 @@ #define EEPROM_SIZE_128B 0x0000 #define EEPROM_SIZE_MASK 0x1C00 - /* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F +#define EEPROM_COMPAT 0x0003 +#define EEPROM_ID_LED_SETTINGS 0x0004 +#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define EEPROM_INIT_CONTROL1_REG 0x000A +#define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 +#define EEPROM_CFG 0x0012 +#define EEPROM_FLASH_VERSION 0x0032 +#define EEPROM_CHECKSUM_REG 0x003F /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -1458,6 +1509,9 @@ #define IGP_LED3_MODE 0x07000000 +/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ +#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 @@ -1479,6 +1533,8 @@ #define EEPROM_NODE_ADDRESS_BYTE_0 0 #define EEPROM_PBA_BYTE_1 8 +#define EEPROM_RESERVED_WORD 0xFFFF + /* EEPROM Map Sizes (Byte Counts) */ #define PBA_SIZE 4 @@ -1490,7 +1546,7 @@ #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_COLD_SHIFT 12 -/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 @@ -1557,35 +1613,30 @@ #define PCIX_STATUS_HI_MMRBC_2K 0x2 -/* The number of bits that we need to shift right to move the "pause" - * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field - * in the TXCW register +/* Number of bits required to shift right the "pause" bits from the + * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. */ #define PAUSE_SHIFT 5 -/* The number of bits that we need to shift left to move the "SWDPIO" - * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO" bits from the + * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. */ #define SWDPIO_SHIFT 17 -/* The number of bits that we need to shift left to move the "SWDPIO_EXT" - * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The - * Extended CTRL register. - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO_EXT" bits from the + * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. */ #define SWDPIO__EXT_SHIFT 4 -/* The number of bits that we need to shift left to move the "ILOS" - * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field - * in the CTRL register +/* Number of bits required to shift left the "ILOS" bit from the EEPROM + * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. */ #define ILOS_SHIFT 3 #define RECEIVE_BUFFER_ALIGN_SIZE (256) -/* The number of milliseconds we wait for auto-negotiation to complete */ +/* Number of milliseconds we wait for auto-negotiation to complete */ #define LINK_UP_TIMEOUT 500 #define E1000_TX_BUFFER_SIZE ((uint32_t)1514) @@ -1668,7 +1719,16 @@ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ +#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ +#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ +#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ +#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ +#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ + #define IGP01E1000_IEEE_REGS_PAGE 0x0000 +#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 +#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 + /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ @@ -1684,17 +1744,35 @@ #define IGP01E1000_PHY_AGC_C 0x1472 #define IGP01E1000_PHY_AGC_D 0x1872 -/* Number of AGC registers */ -#define IGP01E1000_PHY_AGC_NUM 4 +/* IGP01E1000 DSP Reset Register */ +#define IGP01E1000_PHY_DSP_RESET 0x1F33 +#define IGP01E1000_PHY_DSP_SET 0x1F71 +#define IGP01E1000_PHY_DSP_FFE 0x1F35 + +#define IGP01E1000_PHY_CHANNEL_NUM 4 +#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 +#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 +#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 +#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 + +#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 +#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 + +#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 +#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 +#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 +#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 +#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A /* IGP01E1000 PCS Initialization register - stores the polarity status when * speed = 1000 Mbps. */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 +#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ - +#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -1808,8 +1886,11 @@ #define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ #define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ #define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 /* Extended Status Register */ #define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ @@ -1901,7 +1982,6 @@ #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 @@ -1952,6 +2032,11 @@ #define IGP01E1000_MSE_CHANNEL_B 0x0F00 #define IGP01E1000_MSE_CHANNEL_A 0xF000 +/* IGP01E1000 DSP reset macros */ +#define DSP_RESET_ENABLE 0x0 +#define DSP_RESET_DISABLE 0x2 +#define E1000_MAX_DSP_RESETS 10 + /* IGP01E1000 AGC Registers */ #define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ @@ -1962,18 +2047,6 @@ /* The precision of the length is +/- 10 meters */ #define IGP01E1000_AGC_RANGE 10 -/* IGP cable length table */ -static const -uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = - { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; - /* IGP01E1000 PCS Initialization register */ /* bits 3:6 in the PCS registers stores the channels polarity */ #define IGP01E1000_PHY_POLARITY_MASK 0x0078 @@ -1982,11 +2055,12 @@ #define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed * on Link-Up */ #define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ + /* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x0011 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x0010 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x001C -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x001E +#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 +#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 +#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC +#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE #define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 #define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 @@ -2032,5 +2106,8 @@ #define ADVERTISE_1000_HALF 0x0010 #define ADVERTISE_1000_FULL 0x0020 #define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ +#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ +#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ + #endif /* _E1000_HW_H_ */ diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_main.c linux-2.4.22-bk26/drivers/net/e1000/e1000_main.c --- linux-2.4.22-bk25/drivers/net/e1000/e1000_main.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_main.c 2003-09-29 02:49:41.000000000 -0700 @@ -30,6 +30,22 @@ /* Change Log * + * 5.2.16 8/8/03 + * o Added support for new controllers: 82545GM, 82546GB, 82541/7_B1 + * o Bug fix: reset h/w before first EEPROM read because we don't know + * who may have been messing with the device before we got there. + * [Dave Johnson (ddj -a-t- cascv.brown.edu)] + * o Bug fix: read the correct work from EEPROM to detect programmed + * WoL settings. + * o Bug fix: TSO would hang if space left in FIFO was being miscalculated + * when mss dropped without a correspoding drop in the DMA buffer size. + * o ASF for Fiber nics isn't supported. + * o Bug fix: Workaround added for potential hang with 82544 running in + * PCI-X if send buffer terminates within an evenly-aligned dword. + * o Feature: Add support for ethtool flow control setting. + * o Feature: Add support for ethtool TSO setting. + * o Feature: Increase default Tx Descriptor count to 1024 for >= 82544. + * * 5.1.13 5/28/03 * o Bug fix: request_irq() failure resulted in freeing resources twice! * [Don Fry (brazilnut@us.ibm.com)] @@ -39,18 +55,11 @@ * o Cleanup: s/int/unsigned int/ for descriptor ring indexes. * * 5.1.11 5/6/03 - * o Feature: Added support for 82546EB (Quad-port) hardware. - * o Feature: Added support for Diagnostics through Ethtool. - * o Cleanup: Removed /proc support. - * o Cleanup: Removed proprietary IDIAG interface. - * o Bug fix: TSO bug fixes. - * - * 5.0.42 3/5/03 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.1.13-k1"; +char e1000_driver_version[] = "5.2.16-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -61,7 +70,7 @@ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id e1000_pci_tbl[] __devinitdata = { +static struct pci_device_id e1000_pci_tbl[] = { {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -71,15 +80,28 @@ {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ {0,} }; @@ -120,7 +142,7 @@ static void e1000_update_stats(struct e1000_adapter *adapter); static inline void e1000_irq_disable(struct e1000_adapter *adapter); static inline void e1000_irq_enable(struct e1000_adapter *adapter); -static void e1000_intr(int irq, void *data, struct pt_regs *regs); +static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs); static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); #ifdef CONFIG_E1000_NAPI static int e1000_clean(struct net_device *netdev, int *budget); @@ -425,6 +447,11 @@ if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + /* before reading the EEPROM, reset the controller to + * put the device in a known good starting state */ + + e1000_reset_hw(&adapter->hw); + /* make sure the EEPROM is good */ if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { @@ -475,12 +502,28 @@ * enable the ACPI Magic Packet filter */ - e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG,1, &eeprom_data); - if((adapter->hw.mac_type >= e1000_82544) && - (eeprom_data & E1000_EEPROM_APME)) + switch(adapter->hw.mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + break; + case e1000_82546: + case e1000_82546_rev_3: + if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) + && (adapter->hw.media_type == e1000_media_type_copper)) { + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + break; + } + /* Fall Through */ + default: + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + break; + } + if(eeprom_data & E1000_EEPROM_APME) adapter->wol |= E1000_WUFC_MAG; - /* reset the hardware with the new settings */ e1000_reset(adapter); @@ -515,7 +558,8 @@ struct e1000_adapter *adapter = netdev->priv; uint32_t manc; - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -583,21 +627,13 @@ hw->fc_pause_time = E1000_FC_PAUSE_TIME; hw->fc_send_xon = 1; - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) + if((hw->mac_type == e1000_82541) || + (hw->mac_type == e1000_82547) || + (hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2)) hw->phy_init_script = 1; - /* Media type - copper or fiber */ - - if(hw->mac_type >= e1000_82543) { - uint32_t status = E1000_READ_REG(hw, STATUS); - - if(status & E1000_STATUS_TBIMODE) - hw->media_type = e1000_media_type_fiber; - else - hw->media_type = e1000_media_type_copper; - } else { - hw->media_type = e1000_media_type_fiber; - } + e1000_set_media_type(hw); if(hw->mac_type < e1000_82543) hw->report_tx_early = 0; @@ -613,6 +649,7 @@ if(hw->media_type == e1000_media_type_copper) { hw->mdix = AUTO_ALL_MODES; hw->disable_polarity_correction = FALSE; + hw->master_slave = E1000_MASTER_SLAVE; } atomic_set(&adapter->irq_sem, 1); @@ -762,7 +799,8 @@ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; default: - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) tipg = DEFAULT_82543_TIPG_IPGT_FIBER; else tipg = DEFAULT_82543_TIPG_IPGT_COPPER; @@ -797,6 +835,12 @@ adapter->txd_cmd |= E1000_TXD_CMD_RS; else adapter->txd_cmd |= E1000_TXD_CMD_RPS; + + /* Cache if we're 82544 running in PCI-X because we'll + * need this to apply a workaround later in the send path. */ + if(adapter->hw.mac_type == e1000_82544 && + adapter->hw.bus_type == e1000_bus_type_pcix) + adapter->pcix_82544 = 1; } /** @@ -1489,11 +1533,18 @@ { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_buffer *buffer_info; - int len = skb->len; + unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int offset = 0, size, count = 0, i; #ifdef NETIF_F_TSO - unsigned int tso = skb_shinfo(skb)->tso_size; + unsigned int mss = skb_shinfo(skb)->tso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ + if(mss) max_per_txd = min(mss << 2, max_per_txd); #endif unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; @@ -1503,13 +1554,20 @@ while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && !nr_frags && size == len && size > 4) + if(mss && !nr_frags && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. Avoid + * terminating buffers within evenly-aligned dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(skb->data + offset + size - 1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_single(adapter->pdev, @@ -1529,22 +1587,30 @@ frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && f == (nr_frags-1) && size == len && size > 4) + if(mss && f == (nr_frags-1) && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. + * Avoid terminating buffers within evenly-aligned + * dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(frag->page+offset+size-1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_page(adapter->pdev, frag->page, - frag->page_offset + offset, + offset, size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; @@ -1555,6 +1621,31 @@ if(++i == tx_ring->count) i = 0; } } + + if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { + + /* There aren't enough descriptors available to queue up + * this send, so undo the mapping and abort the send. + * We could have done the check before we mapped the skb, + * but because of all the workarounds (above), it's too + * difficult to predict how many we're going to need.*/ + i = first; + + while(count--) { + buffer_info = &tx_ring->buffer_info[i]; + if(buffer_info->dma) { + pci_unmap_page(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + if(++i == tx_ring->count) i = 0; + } + + return 0; + } + i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; @@ -1649,29 +1740,19 @@ return 0; } -/* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \ - (((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) -#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \ - MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 - static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; unsigned int first; unsigned int tx_flags = 0; + int count; if(skb->len <= 0) { dev_kfree_skb_any(skb); return 0; } - if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) { - netif_stop_queue(netdev); - return 1; - } - if(adapter->hw.mac_type == e1000_82547) { if(e1000_82547_fifo_workaround(adapter, skb)) { netif_stop_queue(netdev); @@ -1692,7 +1773,12 @@ else if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; - e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags); + if((count = e1000_tx_map(adapter, skb, first))) + e1000_tx_queue(adapter, count, tx_flags); + else { + netif_stop_queue(netdev); + return 1; + } netdev->trans_start = jiffies; @@ -1965,7 +2051,7 @@ * @pt_regs: CPU registers structure **/ -static void +static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; @@ -1976,7 +2062,7 @@ #endif if(!icr) - return; /* Not our interrupt */ + return IRQ_NONE; /* Not our interrupt */ if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { adapter->hw.get_link_status = 1; @@ -2000,6 +2086,8 @@ !e1000_clean_tx_irq(adapter)) break; #endif + + return IRQ_HANDLED; } #ifdef CONFIG_E1000_NAPI @@ -2385,7 +2473,7 @@ uint16_t mii_reg; uint16_t spddplx; - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; switch (cmd) { @@ -2657,7 +2745,7 @@ case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: - pci_for_each_dev(pdev) { + while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { if(pci_dev_driver(pdev) == &e1000_driver) e1000_suspend(pdev, 3); } @@ -2704,7 +2792,8 @@ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; @@ -2724,7 +2813,8 @@ pci_save_state(pdev, adapter->pci_state); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -2762,7 +2852,8 @@ netif_device_attach(netdev); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(&adapter->hw, MANC, manc); diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_osdep.h linux-2.4.22-bk26/drivers/net/e1000/e1000_osdep.h --- linux-2.4.22-bk25/drivers/net/e1000/e1000_osdep.h 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_osdep.h 2003-09-29 02:49:41.000000000 -0700 @@ -55,10 +55,13 @@ #define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE typedef enum { +#undef FALSE FALSE = 0, +#undef TRUE TRUE = 1 } boolean_t; +#undef ASSERT #define ASSERT(x) if(!(x)) BUG() #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) diff -urN linux-2.4.22-bk25/drivers/net/e1000/e1000_param.c linux-2.4.22-bk26/drivers/net/e1000/e1000_param.c --- linux-2.4.22-bk25/drivers/net/e1000/e1000_param.c 2003-06-13 07:51:34.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/e1000/e1000_param.c 2003-09-29 02:49:41.000000000 -0700 @@ -140,7 +140,7 @@ * Valid Range: 0, 1 * - 0 - disables all checksum offload * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 based NICs + * on 82543 and newer -based NICs * * Default Value: 1 */ @@ -458,6 +458,7 @@ switch(adapter->hw.media_type) { case e1000_media_type_fiber: + case e1000_media_type_internal_serdes: e1000_check_fiber_options(adapter); break; case e1000_media_type_copper: @@ -601,7 +602,7 @@ switch (speed + dplx) { case 0: - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET) printk(KERN_INFO "Speed and duplex autonegotiation enabled\n"); @@ -609,14 +610,14 @@ case HALF_DUPLEX: printk(KERN_INFO "Half Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_100_HALF; break; case FULL_DUPLEX: printk(KERN_INFO "Full Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL; @@ -624,38 +625,38 @@ case SPEED_10: printk(KERN_INFO "10 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_10_FULL; break; case SPEED_10 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_10 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_full; adapter->hw.autoneg_advertised = 0; break; case SPEED_100: printk(KERN_INFO "100 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | ADVERTISE_100_FULL; break; case SPEED_100 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_100 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_full; adapter->hw.autoneg_advertised = 0; break; @@ -663,20 +664,20 @@ printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + HALF_DUPLEX: printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + FULL_DUPLEX: printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; default: diff -urN linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_emac.h linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_emac.h --- linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_emac.h 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_emac.h 2003-09-29 02:49:41.000000000 -0700 @@ -85,22 +85,52 @@ #define EMAC_M1_IST 0x01000000 #define EMAC_M1_MF_1000MBPS 0x00800000 /* 0's for 10MBPS */ #define EMAC_M1_MF_100MBPS 0x00400000 +#define EMAC_M1_TR 0x00008000 +#ifdef CONFIG_IBM_EMAC4 +#define EMAC_M1_RFS_16K 0x00280000 /* 000 for 512 byte */ +#define EMAC_M1_RFS_8K 0x00200000 +#define EMAC_M1_RFS_4K 0x00180000 +#define EMAC_M1_RFS_2K 0x00100000 +#define EMAC_M1_RFS_1K 0x00080000 +#define EMAC_M1_TX_FIFO_16K 0x00050000 /* 0's for 512 byte */ +#define EMAC_M1_TX_FIFO_8K 0x00040000 +#define EMAC_M1_TX_FIFO_4K 0x00030000 +#define EMAC_M1_TX_FIFO_2K 0x00020000 +#define EMAC_M1_TX_FIFO_1K 0x00010000 +#define EMAC_M1_TX_MWSW 0x00001000 /* 0 wait for status */ +#define EMAC_M1_JUMBO_ENABLE 0x00000800 /* Upt to 9Kr status */ +#define EMAC_M1_OPB_CLK_66 0x00000010 /* 66Mhz */ +#define EMAC_M1_OPB_CLK_83 0x00000008 /* 83hz */ +#define EMAC_M1_OPB_CLK_100 0x00000018 /* 100Mhz */ +#define EMAC_M1_OPB_CLK_100P 0x00000020 /* 100Mhz+ */ +#else /* CONFIG_IBM_EMAC4 */ #define EMAC_M1_RFS_4K 0x00300000 /* ~4k for 512 byte */ #define EMAC_M1_RFS_2K 0x00200000 #define EMAC_M1_RFS_1K 0x00100000 #define EMAC_M1_TX_FIFO_2K 0x00080000 /* 0's for 512 byte */ #define EMAC_M1_TX_FIFO_1K 0x00040000 #define EMAC_M1_TR0_DEPEND 0x00010000 /* 0'x for single packet */ -#define EMAC_M1_TR0_MULTI 0x00008000 #define EMAC_M1_TR1_DEPEND 0x00004000 #define EMAC_M1_TR1_MULTI 0x00002000 #define EMAC_M1_JUMBO_ENABLE 0x00001000 +#endif /* CONFIG_IBM_EMAC4 */ +#define EMAC_M1_BASE (EMAC_M1_RFS_4K | \ + EMAC_M1_TX_FIFO_2K | \ + EMAC_M1_APP | \ + EMAC_M1_TR) /* Transmit Mode Register 0 */ -#define EMAC_TXM0_GNP0 0x80000000 -#define EMAC_TXM0_GNP1 0x40000000 -#define EMAC_TXM0_GNPD 0x20000000 -#define EMAC_TXM0_FC 0x10000000 +#define EMAC_TMR0_GNP0 0x80000000 +#define EMAC_TMR0_GNP1 0x40000000 +#define EMAC_TMR0_GNPD 0x20000000 +#define EMAC_TMR0_FC 0x10000000 +#define EMAC_TMR0_TFAE_2_32 0x00000001 +#define EMAC_TMR0_TFAE_4_64 0x00000002 +#define EMAC_TMR0_TFAE_8_128 0x00000003 +#define EMAC_TMR0_TFAE_16_256 0x00000004 +#define EMAC_TMR0_TFAE_32_512 0x00000005 +#define EMAC_TMR0_TFAE_64_1024 0x00000006 +#define EMAC_TMR0_TFAE_128_2048 0x00000007 /* Receive Mode Register */ #define EMAC_RMR_SP 0x80000000 @@ -116,6 +146,14 @@ #define EMAC_RMR_MIAE 0x00200000 #define EMAC_RMR_BAE 0x00100000 #define EMAC_RMR_MAE 0x00080000 +#define EMAC_RMR_RFAF_2_32 0x00000001 +#define EMAC_RMR_RFAF_4_64 0x00000002 +#define EMAC_RMR_RFAF_8_128 0x00000003 +#define EMAC_RMR_RFAF_16_256 0x00000004 +#define EMAC_RMR_RFAF_32_512 0x00000005 +#define EMAC_RMR_RFAF_64_1024 0x00000006 +#define EMAC_RMR_RFAF_128_2048 0x00000007 +#define EMAC_RMR_BASE (EMAC_RMR_IAE | EMAC_RMR_BAE) /* Interrupt Status & enable Regs */ #define EMAC_ISR_OVR 0x02000000 @@ -148,11 +186,11 @@ #define EMAC_STACR_CLK_100MHZ 0x00000C00 /* Transmit Request Threshold Register */ -#define EMAC_TRTR_256 0x18000000 /* 0's for 64 Bytes */ +#define EMAC_TRTR_1600 0x18000000 /* 0's for 64 Bytes */ +#define EMAC_TRTR_256 0x03000000 #define EMAC_TRTR_192 0x10000000 #define EMAC_TRTR_128 0x01000000 - #define EMAC_TX_CTRL_GFCS 0x0200 #define EMAC_TX_CTRL_GP 0x0100 #define EMAC_TX_CTRL_ISA 0x0080 @@ -176,8 +214,6 @@ #define EMAC_TX_ST_UR 0x0002 #define EMAC_TX_ST_SQE 0x0001 -#define EMAC_TX_ST_DEFAULT 0x03F3 - /* madmal receive status / Control bits */ #define EMAC_RX_ST_OE 0x0200 #define EMAC_RX_ST_PP 0x0100 @@ -191,5 +227,36 @@ #define EMAC_RX_ST_IRE 0x0001 #define EMAC_BAD_RX_PACKET 0x02ff +/* Revision specific EMAC register defaults */ +#ifdef CONFIG_IBM_EMAC4 +#define EMAC_M1_DEFAULT (EMAC_M1_BASE | \ + EMAC_M1_OPB_CLK_66 | \ + EMAC_M1_TX_MWSW) +#define EMAC_RMR_DEFAULT (EMAC_RMR_BASE | \ + EMAC_RMR_RFAF_128_2048) +#define EMAC_TMR0_XMIT (EMAC_TMR0_GNP0 | \ + EMAC_TMR0_TFAE_128_2048) +#define EMAC_TRTR_DEFAULT EMAC_TRTR_256 +#else /* !CONFIG_IBM_EMAC4 */ +#define EMAC_M1_DEFAULT EMAC_M1_BASE +#define EMAC_RMR_DEFAULT EMAC_RMR_BASE +#define EMAC_TMR0_XMIT EMAC_TMR0_GNP0 +#define EMAC_TRTR_DEFAULT EMAC_TRTR_1600 +#endif /* CONFIG_IBM_EMAC4 */ + +/* SoC implementation specific EMAC register defaults */ +#if defined(CONFIG_440GP) +#define EMAC_RWMR_DEFAULT 0x80009000 +#define EMAC_TMR0_DEFAULT 0x00000000 +#define EMAC_TMR1_DEFAULT 0xf8640000 +#elif defined(CONFIG_440GX) +#define EMAC_RWMR_DEFAULT 0x1000a200 +#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_128_2048 +#define EMAC_TMR1_DEFAULT 0x88810000 +#else +#define EMAC_RWMR_DEFAULT 0x0f002000 +#define EMAC_TMR0_DEFAULT 0x00000000 +#define EMAC_TMR1_DEFAULT 0x380f0000 +#endif /* CONFIG_440GP */ #endif diff -urN linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_ocp_enet.c linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_ocp_enet.c --- linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_ocp_enet.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_ocp_enet.c 2003-09-29 02:49:41.000000000 -0700 @@ -674,7 +674,7 @@ fep->tx_desc[fep->tx_slot].ctrl = ctrl; /* Send the packet out. */ - out_be32(&emacp->em0tmr0, EMAC_TXM0_GNP0); + out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT); if (++fep->tx_slot == NUM_TX_BUFF) fep->tx_slot = 0; @@ -699,10 +699,9 @@ full_duplex = 0; speed = SPEED_10; - /* set receive fifo to 4k and tx fifo to 2k */ - mode_reg = EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K | EMAC_M1_APP | - EMAC_M1_TR0_MULTI; - + /* set mode register 1 defaults */ + mode_reg = EMAC_M1_DEFAULT; + /* Read link mode on PHY */ if (fep->phy_mii.def->ops->read_link(&fep->phy_mii) == 0) { /* If an error occurred, we don't deal with it yet */ @@ -871,26 +870,19 @@ if (netif_carrier_ok(fep->ndev)) emac_adjust_to_link(fep); - /* enable broadcast and individual address */ - out_be32(&emacp->em0rmr, EMAC_RMR_IAE | EMAC_RMR_BAE); + /* enable broadcast/individual address and RX FIFO defaults */ + out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT); + /* set transmit request threshold register */ + out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT); /* Reconfigure multicast */ __emac_set_multicast_list(fep->ndev); - /* set transmit request threshold register */ - out_be32(&emacp->em0trtr, EMAC_TRTR_256); - - - /* set receive low/high water mark register */ -#ifdef CONFIG_440 - /* 440GP has a 64 byte burst length */ - out_be32(&emacp->em0rwmr, 0x80009000); - out_be32(&emacp->em0tmr1, 0xf8640000); -#else - /* 405s have a 16 byte burst length */ - out_be32(&emacp->em0rwmr, 0x0f002000); -#endif /* CONFIG_440 */ + /* Set receiver/transmitter defaults */ + out_be32(&emacp->em0rwmr, EMAC_RWMR_DEFAULT); + out_be32(&emacp->em0tmr0, EMAC_TMR0_DEFAULT); + out_be32(&emacp->em0tmr1, EMAC_TMR1_DEFAULT); /* set frame gap */ out_be32(&emacp->em0ipgvr, CONFIG_IBM_OCP_ENET_GAP); @@ -989,7 +981,8 @@ * latency peaks caused by this code */ emac_reset_configure(fep); - emac_kick(fep); + if (fep->opened) + emac_kick(fep); } else { fep->timer_ticks = 0; netif_carrier_off(fep->ndev); diff -urN linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_ocp_mal.c linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_ocp_mal.c --- linux-2.4.22-bk25/drivers/net/ibm_emac/ibm_ocp_mal.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/ibm_emac/ibm_ocp_mal.c 2003-09-29 02:49:41.000000000 -0700 @@ -103,17 +103,17 @@ case 0: set_mal_dcrn(mal, DCRN_MALRCBS0, size); break; -#ifdef DCRN_RCBS1 +#ifdef DCRN_MALRCBS1 case 1: set_mal_dcrn(mal, DCRN_MALRCBS1, size); break; #endif -#ifdef DCRN_RCBS2 +#ifdef DCRN_MALRCBS2 case 2: set_mal_dcrn(mal, DCRN_MALRCBS2, size); break; #endif -#ifdef DCRN_RCBS3 +#ifdef DCRN_MALRCBS3 case 3: set_mal_dcrn(mal, DCRN_MALRCBS3, size); break; diff -urN linux-2.4.22-bk25/drivers/net/tlan.c linux-2.4.22-bk26/drivers/net/tlan.c --- linux-2.4.22-bk25/drivers/net/tlan.c 2003-08-25 04:44:42.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/tlan.c 2003-09-29 02:49:41.000000000 -0700 @@ -881,7 +881,9 @@ err ); } dev->addr_len = 6; - + + netif_carrier_off(dev); + /* Device methods */ dev->open = &TLan_Open; dev->hard_start_xmit = &TLan_StartTx; @@ -2205,6 +2207,8 @@ priv->tlanFullDuplex = FALSE; priv->phyOnline=0; + netif_carrier_off(dev); + /* 1. Assert reset bit. */ data = inl(dev->base_addr + TLAN_HOST_CMD); @@ -2368,6 +2372,7 @@ } outl( priv->rxListDMA, dev->base_addr + TLAN_CH_PARM ); outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); + netif_carrier_on(dev); } else { printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n", dev->name ); TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET ); diff -urN linux-2.4.22-bk25/drivers/net/wireless/airo.c linux-2.4.22-bk26/drivers/net/wireless/airo.c --- linux-2.4.22-bk25/drivers/net/wireless/airo.c 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/drivers/net/wireless/airo.c 2003-09-29 02:49:41.000000000 -0700 @@ -202,7 +202,7 @@ #ifndef RUN_AT #define RUN_AT(x) (jiffies+(x)) #endif -#if LINUX_VERSION_CODE < 0x020500 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) static inline struct proc_dir_entry *PDE(const struct inode *inode) { return inode->u.generic_ip; diff -urN linux-2.4.22-bk25/include/asm-ppc/commproc.h linux-2.4.22-bk26/include/asm-ppc/commproc.h --- linux-2.4.22-bk25/include/asm-ppc/commproc.h 2003-08-25 04:44:44.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/commproc.h 2003-09-29 02:49:41.000000000 -0700 @@ -466,6 +466,23 @@ #define SICR_ENET_CLKRT ((uint)0x0000003d) #endif /* CONFIG_RPXCLASSIC */ +/*** D-BOX2 ***********************************************/ + +#ifdef CONFIG_DBOX2 + +#define PA_ENET_RXD ((ushort)0x0004) +#define PA_ENET_TXD ((ushort)0x0008) +#define PA_ENET_RCLK ((ushort)0x0200) +#define PA_ENET_TCLK ((ushort)0x0800) + +#define PC_ENET_TENA ((ushort)0x0002) +#define PC_ENET_CLSN ((ushort)0x0040) +#define PC_ENET_RENA ((ushort)0x0080) + +#define SICR_ENET_MASK ((uint)0x0000ff00) +#define SICR_ENET_CLKRT ((uint)0x00003d00) +#endif /* CONFIG_DBOX2 */ + /*** TQM823L, TQM850L ***********************************************/ #if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) diff -urN linux-2.4.22-bk25/include/asm-ppc/highmem.h linux-2.4.22-bk26/include/asm-ppc/highmem.h --- linux-2.4.22-bk25/include/asm-ppc/highmem.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/highmem.h 2003-09-29 02:49:41.000000000 -0700 @@ -41,7 +41,7 @@ * easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#define PKMAP_BASE (0xfe000000UL) +#define PKMAP_BASE CONFIG_HIGHMEM_START #define LAST_PKMAP PTRS_PER_PTE #define LAST_PKMAP_MASK (LAST_PKMAP-1) #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) diff -urN linux-2.4.22-bk25/include/asm-ppc/mpc8xx.h linux-2.4.22-bk26/include/asm-ppc/mpc8xx.h --- linux-2.4.22-bk25/include/asm-ppc/mpc8xx.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/mpc8xx.h 2003-09-29 02:49:41.000000000 -0700 @@ -32,6 +32,10 @@ #include #endif +#ifdef CONFIG_DBOX2 +#include +#endif + #if defined(CONFIG_TQM8xxL) #include #endif diff -urN linux-2.4.22-bk25/include/asm-ppc/page.h linux-2.4.22-bk26/include/asm-ppc/page.h --- linux-2.4.22-bk25/include/asm-ppc/page.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/page.h 2003-09-29 02:49:41.000000000 -0700 @@ -13,8 +13,7 @@ #ifdef __KERNEL__ #include -/* Be sure to change arch/ppc/Makefile to match */ -#define PAGE_OFFSET 0xc0000000 +#define PAGE_OFFSET CONFIG_KERNEL_START #define KERNELBASE PAGE_OFFSET #ifndef __ASSEMBLY__ diff -urN linux-2.4.22-bk25/include/asm-ppc/pgtable.h linux-2.4.22-bk26/include/asm-ppc/pgtable.h --- linux-2.4.22-bk25/include/asm-ppc/pgtable.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/pgtable.h 2003-09-29 02:49:41.000000000 -0700 @@ -279,7 +279,7 @@ #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ /* TODO: Add large page lowmem mapping support */ -#define _PMD_PRESENT 0 +#define _PMD_PRESENT PAGE_MASK #define _PMD_PRESENT_MASK (PAGE_MASK) #define _PMD_BAD (~PAGE_MASK) diff -urN linux-2.4.22-bk25/include/asm-ppc/processor.h linux-2.4.22-bk26/include/asm-ppc/processor.h --- linux-2.4.22-bk25/include/asm-ppc/processor.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/processor.h 2003-09-29 02:49:41.000000000 -0700 @@ -797,7 +797,7 @@ * as soon as I get around to remapping the io areas with the BATs * to match the mac we can raise this. -- Cort */ -#define TASK_SIZE (0x80000000UL) +#define TASK_SIZE CONFIG_TASK_SIZE /* This decides where the kernel will search for a free chunk of vm * space during mmap's. diff -urN linux-2.4.22-bk25/include/asm-ppc/uaccess.h linux-2.4.22-bk26/include/asm-ppc/uaccess.h --- linux-2.4.22-bk25/include/asm-ppc/uaccess.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-ppc/uaccess.h 2003-09-29 02:49:41.000000000 -0700 @@ -77,16 +77,28 @@ * As we use the same address space for kernel and user data on the * PowerPC, we can just do these as direct assignments. (Of course, the * exception handling means that it's no longer "just"...) + * + * The "user64" versions of the user access functions are versions that + * allow access of 64-bit data. The "get_user" functions do not + * properly handle 64-bit data because the value gets down cast to a long. + * The "put_user" functions already handle 64-bit data properly but we add + * "user64" versions for completeness */ #define get_user(x,ptr) \ __get_user_check((x),(ptr),sizeof(*(ptr))) +#define get_user64(x,ptr) \ + __get_user64_check((x),(ptr),sizeof(*(ptr))) #define put_user(x,ptr) \ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define put_user64(x,ptr) put_user(x,ptr) #define __get_user(x,ptr) \ __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user64(x,ptr) \ + __get_user64_nocheck((x),(ptr),sizeof(*(ptr))) #define __put_user(x,ptr) \ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define __put_user64(x,ptr) __put_user(x,ptr) extern long __put_user_bad(void); @@ -166,6 +178,15 @@ __gu_err; \ }) +#define __get_user64_nocheck(x,ptr,size) \ +({ \ + long __gu_err; \ + long long __gu_val; \ + __get_user_size64(__gu_val,(ptr),(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + #define __get_user_check(x,ptr,size) \ ({ \ long __gu_err = -EFAULT, __gu_val = 0; \ @@ -176,6 +197,17 @@ __gu_err; \ }) +#define __get_user64_check(x,ptr,size) \ +({ \ + long __gu_err = -EFAULT; \ + long long __gu_val = 0; \ + const __typeof__(*(ptr)) *__gu_addr = (ptr); \ + if (access_ok(VERIFY_READ,__gu_addr,size)) \ + __get_user_size64(__gu_val,__gu_addr,(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + extern long __get_user_bad(void); #define __get_user_size(x,ptr,size,retval) \ @@ -185,6 +217,17 @@ case 1: __get_user_asm(x,ptr,retval,"lbz"); break; \ case 2: __get_user_asm(x,ptr,retval,"lhz"); break; \ case 4: __get_user_asm(x,ptr,retval,"lwz"); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_size64(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm(x,ptr,retval,"lbz"); break; \ + case 2: __get_user_asm(x,ptr,retval,"lhz"); break; \ + case 4: __get_user_asm(x,ptr,retval,"lwz"); break; \ case 8: __get_user_asm2(x, ptr, retval); break; \ default: (x) = __get_user_bad(); \ } \ diff -urN linux-2.4.22-bk25/include/asm-x86_64/acpi.h linux-2.4.22-bk26/include/asm-x86_64/acpi.h --- linux-2.4.22-bk25/include/asm-x86_64/acpi.h 2003-08-25 04:44:44.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/acpi.h 2003-09-29 02:49:42.000000000 -0700 @@ -115,7 +115,22 @@ #endif #ifdef CONFIG_X86_IO_APIC extern int acpi_ioapic; +extern int skip_ioapic_setup; + +static inline void disable_ioapic_setup(void) +{ + + skip_ioapic_setup = 1; +} + +static inline int ioapic_setup_disabled(void) +{ + return skip_ioapic_setup; +} #else +static inline void disable_ioapic_setup(void) +{ } + #define acpi_ioapic 0 #endif @@ -142,6 +157,8 @@ extern void mp_config_ioapic_for_sci(int irq); +extern int use_acpi_pci; + #endif /*__KERNEL__*/ #endif /*_ASM_ACPI_H*/ diff -urN linux-2.4.22-bk25/include/asm-x86_64/calling.h linux-2.4.22-bk26/include/asm-x86_64/calling.h --- linux-2.4.22-bk25/include/asm-x86_64/calling.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.22-bk26/include/asm-x86_64/calling.h 2003-09-29 02:49:42.000000000 -0700 @@ -8,7 +8,7 @@ #define R14 8 #define R13 16 #define R12 24 -#define RBP 36 +#define RBP 32 #define RBX 40 /* arguments: interrupts/non tracing syscalls only save upto here*/ #define R11 48 diff -urN linux-2.4.22-bk25/include/asm-x86_64/cpufeature.h linux-2.4.22-bk26/include/asm-x86_64/cpufeature.h --- linux-2.4.22-bk25/include/asm-x86_64/cpufeature.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.22-bk26/include/asm-x86_64/cpufeature.h 2003-09-29 02:49:42.000000000 -0700 @@ -63,6 +63,26 @@ #define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ #define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ +#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) +#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) + +#define cpu_has_pge 1 +#define cpu_has_pse 1 +#define cpu_has_pae 1 +#define cpu_has_tsc 1 +#define cpu_has_de 1 +#define cpu_has_vme 1 +#define cpu_has_fxsr 1 +#define cpu_has_xmm 1 +#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) +#define cpu_has_ht 0 +#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) +#define cpu_has_k6_mtrr 0 +#define cpu_has_cyrix_arr 0 +#define cpu_has_centaur_mcr 0 +#define cpu_has_mmx 0 +#define cpu_has_fpu 1 + #endif /* __ASM_X8664_CPUFEATURE_H */ /* diff -urN linux-2.4.22-bk25/include/asm-x86_64/hardirq.h linux-2.4.22-bk26/include/asm-x86_64/hardirq.h --- linux-2.4.22-bk25/include/asm-x86_64/hardirq.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.22-bk26/include/asm-x86_64/hardirq.h 2003-09-29 02:49:42.000000000 -0700 @@ -67,6 +67,8 @@ { ++local_irq_count(cpu); + smp_mb(); + while (test_bit(0,&global_irq_lock)) { cpu_relax(); } diff -urN linux-2.4.22-bk25/include/asm-x86_64/ia32.h linux-2.4.22-bk26/include/asm-x86_64/ia32.h --- linux-2.4.22-bk25/include/asm-x86_64/ia32.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/ia32.h 2003-09-29 02:49:42.000000000 -0700 @@ -234,6 +234,11 @@ int iov_len; }; +struct timespec32 { + int tv_sec; + int tv_nsec; +}; + #endif /* !CONFIG_IA32_SUPPORT */ #endif diff -urN linux-2.4.22-bk25/include/asm-x86_64/kdebug.h linux-2.4.22-bk26/include/asm-x86_64/kdebug.h --- linux-2.4.22-bk25/include/asm-x86_64/kdebug.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/kdebug.h 2003-09-29 02:49:42.000000000 -0700 @@ -39,11 +39,13 @@ return notifier_call_chain(&die_chain, val, &args); } - extern int printk_address(unsigned long address); extern void die(const char *,struct pt_regs *,long); +extern void __die(const char *,struct pt_regs *,long); extern void show_stack(unsigned long* esp); extern void show_registers(struct pt_regs *regs); extern void dump_pagetable(unsigned long); +extern void prepare_die(unsigned long *flags); +extern void exit_die(unsigned long flags); #endif diff -urN linux-2.4.22-bk25/include/asm-x86_64/pgalloc.h linux-2.4.22-bk26/include/asm-x86_64/pgalloc.h --- linux-2.4.22-bk25/include/asm-x86_64/pgalloc.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.22-bk26/include/asm-x86_64/pgalloc.h 2003-09-29 02:49:42.000000000 -0700 @@ -204,7 +204,7 @@ { struct mm_struct *active_mm; int state; -}; +} ____cacheline_aligned; extern struct tlb_state cpu_tlbstate[NR_CPUS]; diff -urN linux-2.4.22-bk25/include/asm-x86_64/processor.h linux-2.4.22-bk26/include/asm-x86_64/processor.h --- linux-2.4.22-bk25/include/asm-x86_64/processor.h 2003-08-25 04:44:44.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/processor.h 2003-09-29 02:49:42.000000000 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include #define TF_MASK 0x00000100 #define IF_MASK 0x00000200 @@ -77,16 +78,6 @@ #define current_cpu_data boot_cpu_data #endif -#define cpu_has_pge 1 -#define cpu_has_pse 1 -#define cpu_has_pae 1 -#define cpu_has_tsc 1 -#define cpu_has_de 1 -#define cpu_has_vme 1 -#define cpu_has_fxsr 1 -#define cpu_has_xmm 1 -#define cpu_has_apic (test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) - extern char ignore_irq13; extern void identify_cpu(struct cpuinfo_x86 *); @@ -258,7 +249,9 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_32 0xa0000000 + +#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000) +#define TASK_UNMAPPED_32 (IA32_PAGE_OFFSET / 3) #define TASK_UNMAPPED_64 (TASK_SIZE/3) #define TASK_UNMAPPED_BASE \ ((current->thread.flags & THREAD_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64) @@ -396,7 +389,7 @@ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ extern inline void rep_nop(void) { - __asm__ __volatile__("rep;nop"); + __asm__ __volatile__("rep;nop":::"memory"); } /* Avoid speculative execution by the CPU */ @@ -406,8 +399,6 @@ asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory"); } -#define cpu_has_fpu 1 - #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW #define ARCH_HAS_SPINLOCK_PREFETCH diff -urN linux-2.4.22-bk25/include/asm-x86_64/proto.h linux-2.4.22-bk26/include/asm-x86_64/proto.h --- linux-2.4.22-bk25/include/asm-x86_64/proto.h 2003-08-25 04:44:44.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/proto.h 2003-09-29 02:49:42.000000000 -0700 @@ -43,6 +43,8 @@ extern void __show_regs(struct pt_regs * regs); extern void show_regs(struct pt_regs * regs); +extern int apic_disabled; +extern int acpi_disabled; #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) #define round_down(x,y) ((x) & ~((y)-1)) diff -urN linux-2.4.22-bk25/include/asm-x86_64/ptrace.h linux-2.4.22-bk26/include/asm-x86_64/ptrace.h --- linux-2.4.22-bk25/include/asm-x86_64/ptrace.h 2002-11-28 15:53:15.000000000 -0800 +++ linux-2.4.22-bk26/include/asm-x86_64/ptrace.h 2003-09-29 02:49:42.000000000 -0700 @@ -6,7 +6,7 @@ #define R14 8 #define R13 16 #define R12 24 -#define RBP 36 +#define RBP 32 #define RBX 40 /* arguments: interrupts/non tracing syscalls only save upto here*/ #define R11 48 @@ -37,10 +37,6 @@ /* options set using PTRACE_SETOPTIONS */ #define PTRACE_O_TRACESYSGOOD 0x00000001 -/* Dummy values for ptrace */ -#define FS 1000 -#define GS 1008 - #ifndef __ASSEMBLY__ struct pt_regs { diff -urN linux-2.4.22-bk25/include/asm-x86_64/system.h linux-2.4.22-bk26/include/asm-x86_64/system.h --- linux-2.4.22-bk25/include/asm-x86_64/system.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/system.h 2003-09-29 02:49:42.000000000 -0700 @@ -284,8 +284,8 @@ #define sti() __global_sti() #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) -#define save_and_cli(x) do { save_flags(x); cli(); } while(0); -#define save_and_sti(x) do { save_flags(x); sti(); } while(0); +#define save_and_cli(x) do { save_flags(x); cli(); } while(0) +#define save_and_sti(x) do { save_flags(x); sti(); } while(0) #else diff -urN linux-2.4.22-bk25/include/asm-x86_64/uaccess.h linux-2.4.22-bk26/include/asm-x86_64/uaccess.h --- linux-2.4.22-bk25/include/asm-x86_64/uaccess.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/uaccess.h 2003-09-29 02:49:42.000000000 -0700 @@ -254,12 +254,12 @@ case 10: __get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16); if (ret) return ret; - __get_user_asm(*(u16*)(8+dst),(u16*)(8+src),ret,"w","w","=r",2); + __get_user_asm(*(u16*)(8+(char*)dst),(u16*)(8+(char*)src),ret,"w","w","=r",2); return ret; case 16: __get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16); if (ret) return ret; - __get_user_asm(*(u64*)(8+dst),(u64*)(8+src),ret,"q","","=r",8); + __get_user_asm(*(u64*)(8+(char*)dst),(u64*)(8+(char*)src),ret,"q","","=r",8); return ret; default: return copy_user_generic(dst,src,size); diff -urN linux-2.4.22-bk25/include/asm-x86_64/unistd.h linux-2.4.22-bk26/include/asm-x86_64/unistd.h --- linux-2.4.22-bk25/include/asm-x86_64/unistd.h 2003-06-13 07:51:38.000000000 -0700 +++ linux-2.4.22-bk26/include/asm-x86_64/unistd.h 2003-09-29 02:49:42.000000000 -0700 @@ -462,7 +462,7 @@ #define __NR_tkill 200 /* 2.5 only */ __SYSCALL(__NR_tkill, sys_ni_syscall) #define __NR_time 201 -__SYSCALL(__NR_time, sys_time) +__SYSCALL(__NR_time, sys_time64) #define __NR_futex 202 /* 2.5 only */ __SYSCALL(__NR_futex, sys_ni_syscall) #define __NR_sched_setaffinity 203 @@ -495,8 +495,12 @@ __SYSCALL(__NR_remap_file_pages, sys_ni_syscall) #define __NR_getdents64 217 __SYSCALL(__NR_getdents64, sys_getdents64) +#define __NR_restart_syscall 219 +__SYSCALL(__NR_restart_syscall, sys_ni_syscall) +#define __NR_semtimedop 220 +__SYSCALL(__NR_semtimedop, sys_semtimedop) -#define __NR_syscall_max __NR_getdents64 +#define __NR_syscall_max __NR_semtimedop #ifndef __NO_STUBS diff -urN linux-2.4.22-bk25/include/linux/agp_backend.h linux-2.4.22-bk26/include/linux/agp_backend.h --- linux-2.4.22-bk25/include/linux/agp_backend.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/linux/agp_backend.h 2003-09-29 02:49:42.000000000 -0700 @@ -92,6 +92,7 @@ SVWRKS_GENERIC, NVIDIA_NFORCE, NVIDIA_NFORCE2, + NVIDIA_NFORCE3, NVIDIA_GENERIC, HP_ZX1, ATI_RS100, diff -urN linux-2.4.22-bk25/include/linux/pci_ids.h linux-2.4.22-bk26/include/linux/pci_ids.h --- linux-2.4.22-bk25/include/linux/pci_ids.h 2003-09-29 02:49:38.000000000 -0700 +++ linux-2.4.22-bk26/include/linux/pci_ids.h 2003-09-29 02:49:42.000000000 -0700 @@ -559,6 +559,7 @@ #define PCI_DEVICE_ID_SI_750 0x0750 #define PCI_DEVICE_ID_SI_751 0x0751 #define PCI_DEVICE_ID_SI_752 0x0752 +#define PCI_DEVICE_ID_SI_755 0x0755 #define PCI_DEVICE_ID_SI_900 0x0900 #define PCI_DEVICE_ID_SI_5107 0x5107 #define PCI_DEVICE_ID_SI_5300 0x5300 @@ -967,6 +968,7 @@ #define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 #define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 @@ -1091,6 +1093,7 @@ #define PCI_DEVICE_ID_VIA_P4X333 0x3168 #define PCI_DEVICE_ID_VIA_8235 0x3177 #define PCI_DEVICE_ID_VIA_8377_0 0x3189 +#define PCI_DEVICE_ID_VIA_K8T400M_0 0x3188 #define PCI_DEVICE_ID_VIA_8237 0x3227 #define PCI_DEVICE_ID_VIA_86C100A 0x6100 #define PCI_DEVICE_ID_VIA_8231 0x8231